GDB&gcc 应用

Linux应用编程基础学习笔记

GCC程序编译

Linux系统下的gcc (GNU C Compiler)是GNU推出的功能强大、性能优越的多平台编译器,是GNU的代表作之一。GCC编译器能将c、c++语言源程序、汇编程序编译、链接成可执行文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件
GCC编译程序时,分为四个阶段:

  1. 预处理(Pre-Processing)
  2. 编译(Comiling)
  3. 汇编(Assembling)
  4. 链接(Linking)
    GCC通过文件后缀来区分输入文件的类型:
    .c:c语言源代码文件
    .a:目标文件构成的库文件
    .cc、.cXX:C++源代码文件
    .i:已经预处理过得c源代码文件
    .ii:已经预处理过得c++源代码文件
    .o:编译后的目标文件
    .s:汇编语言源代码文件
    .S:经过预编译的汇编语言源代码文件

gcc最基本的用法如下
gcc [options] [filenames]
options: 编译器所需要的编译选项(100多个选项)
filenames: 要编译的文件名

编译选项说明举例
aaaaaaaaaaaaaaa调整makrdown表格宽度
-o output_filename确定可执行文件的名称为output_filename,如果不写名称,默认生成可执行文件a.out
-c只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件
-g产生调试工具(GNU的gdb)所必要的符号信息,要想用gdb调试,必须加入这个选项
-O对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样的可执行文件的执行效率可以提高,但是,编译、连接的速度会慢一些
-O2更好的优化编译、链接gcc optimize.c -o optimize root@ubuntu:time ./optimize gcc -O optimize.c -o optimize root@ubuntu:time ./optimize
-ldirname将dirname所指出的目录加入到程序头文件目录列表中gcc foo.c -l /home/include -o foo
-Ldirname将dirname所指出的目录加入到库文件的目录列表中。默认状态,连接程序ld在系统的预设定路径中(如/usr/lib)寻找所需要的库文件,这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后再去指定的路径寻找
-lname在连接时,装载名字为“libname.a”的函数库。例如,-lm表示连接名为“libm.a”的数学函数库gcc foo.c -L /home/lib -lfoo -o foo
-static静态链接库文件(把库文件在源代码应用的地方展开,拷贝过去,相对动态链接,在代码执行时才去调用库函数来说,浪费空间)Linux下进行的连接默认为动态库gcc -static hello.c -o hello
-Wall生成所有告警信息
-w不生成任何警告信息
-DMACRO定义MACRO宏,等效于#define MACROgcc -DMACRO hello.c -o hello
-E查看宏展开后的内容g++ -E .cpp/.h > *.txt

比如代码中:
#ifdef MACRO /定义了,则下面的程序会被执行/

#endif |

GDB 调试

GDB是GNU发布的一款功能强大的程序调试工具。GDB主要完成下面三个方面的功能:

  1. 启动被调试程序
  2. 让被调试的程序在指定的位置停住
  3. 当程序被停住时,可以检查程序状态
    步骤如下:
    A. 编译生成可执行文件:
    gcc -g test.c -o test
    B. 启动GDB
    gdb test
    C. 在函数处设断点
    break main
    D. 运行程序
    run
    E. 单步执行
    next
    GDB常用命令简介:
常用命令缩写命令说明
aaaaaaaaaaaaaaaaaaaaaa调整makrdown表格宽度
listl查看程序
break 函数名b在函数入口处添加断点
break 行号b在指定行添加断点
break 文件名:行号b在指定文件的指定行添加断点
break 行号 if 条件b当条件为真时,指定行号出断点生效,例b 5 if i=10,当i等于10时第5行断点生效
info break查看所有设置的断点
delete 断点编号d删除断点
runr开始运行程序
nextn单步运行程序(不进入子函数)
steps单步运行(进入子函数)
continuec继续运行程序
print 变量名p查看指定的变量值 ,打印指定寄存器print $rsp
watch 变量名对指定变量进行监控
quitq退出gdb
backtracebt产看函数调用信息(堆栈)
disas检查汇编 会给出对应的代码的汇编
info registers查看寄存器内容
x检查寄存器或某个地址 x/4wd $rsp、x $esi
attach 进程id调试某个进程id,例如。假如用ps查看进程qs进程的id为987,用gdb调试这个进程中的函数./gdb attach 987,进入进程后先打断点b,在运行程序c,如果程序执行到断点处,则可以停在断点处,bt查看调用栈
如何用gdb单独调用某个函数假如调用struct l2if * l2if_get(uint32_t ifindex)函数,这个函数在l2进程,先用ps查看l2进程的进程id,然后t调用gdb(./gdb attach 进程id)(gdb) set $pif = l2if_get(0x22105000) (gdb) p /x *$pif
(gdb)p/x p0->data[0]@64查看p0指向的data存储的64个字节

如何格式化输出数据结构?
set print array on
set print array off
show print array
以可读形式打印数组。默认是 off 。

set print array-indexes on
set print array-indexes off
show print array-indexes
打印数组元素的下标。默认是 off 。

set print pretty on
set print pretty off
show print pretty
格式化打印 C 结构体的输出
详细gdb格式参见geb格式输出

gdb调试举例:

(gdb) set $pif = l2if_get(0x22105000)
(gdb) p /x *$pif

 /*调用相关函数 */
call test_l2_mac_add(0x01, 0x00, 0x0c, 0xcd, 0xcd, 0xd2,200,0)

set $trunk_infor = (bcm_trunk_chip_info_t*)malloc(sizeof(bcm_trunk_chip_info_t))
call bcm_trunk_chip_info_get(0, $trunk_infor)

更多用法请查看此篇文章gdb教程

makefile工程管理

Linux程序员必须学习使用GNU make来构建和管理自己的软件工程。GNU的make命令能够使整个软件工程的编译、链接只需一个命令就可以完成。make在执行时,需要一个命名为Makefile的文件(不区分大小写)。Makefile文件描述了整个工程的编译,链接等规则。例:

hello:main.o  func1.o
	gcc main.o func1.o -o hello
main.o:main.c
	gcc -c main.c 
func1.o:func1.c
	gcc -c func1.c
.PHONY:clean
clean:
	rm -f hello main.o func1.o

上面的写法可以进一步优化:

hello:main.o  func1.o
	gcc $^ -o $@
%.o:%.c
	gcc -o $@ -c $<
clean:
	rm -f hello *.o 

规则:用于说明如何生成一个或多个目标文件,格式如下:
targets:prerequisites
(一个tab键位)command
目标 依赖 命令
通过这个规则可以看出,上面的例子有3条规则,并且在Makefile中目标可能有很多,但是第一条规则中的目标将被确立为最终的目标,也就是hello。
问:命令什么时候被执行?
答:1. 目标不存在时(hello程序不存在); 2. 依赖更新时(.c文件更新后)

  1. Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”(phony targets),如上面的clean,敲命令make clean即会执行clean:中的命令
  2. Makefile中可以使用变量,例如:
    obj = main.o func1.o
    hello:$(obj)
    gcc $(obj) -o hello
  3. 在Makefile中存在一些系统默认的自动化变量
  • $^:代表所有的依赖文件
  • $@:代表目标
  • $<:代表第一个依赖文件
    例如:
    hello:main.o func1.o
    gcc main.o func1.o -o hello
    =》
    hello:main.o func1.o
    gcc $^ -o $@
  1. Makefile中“#”字符后的内容被视为注释
  2. 取消回显加@,例如
    hello:helloc.c
    @gcc hello.c -o hello
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值