首先:
Gcc的编译流程分为了四个步骤:1.预处理,生成预编译文件(.文件):
Gcc –E hello.c –o hello.i
2.编译,生成汇编代码(.s文件):(如果要加入gdb的话,在这一步加入-g即可)
Gcc –S hello.i –o hello.s
3.汇编,生成目标文件(.o文件):
Gcc –c hello.s –o hello.o
4.链接,生成可执行文件:
Gcc hello.o –o hello
1.不管是生成完.i .s .o文件,都可以直接执行第四部生成可执行文件
2.如果是多个文件的话,那么123步骤是单独做的,最后生成的.o 要一起链接成可执行文件,因为他们要找函数的具体实现。
知识储备
- 一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:
-
> cc -g hello . c -o hello
-
> g ++ -g hello . cpp -o hello
- 如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址
gcc -g main.c //在目标文件加入源代码的信息
gdb a.out
(备注:回车代表上个命令继续执行)
(gdb) start //开始调试
(gdb) n //一条一条执行
(gdb) step/s //执行下一条,如果函数进入函数
(gdb) backtrace/bt //查看函数调用栈帧
(gdb) print/p //打印变量的值(gdb) finish //运行到当前函数返回
(gdb) set var sum=0 //修改变量值
(gdb) list/l 行号或函数名 //列出源码
(gdb) display var //每次停下显示变量的值
(gdb) info display //显示自动显示的列表
(gdb)undisplay 序号 //取消某个自动显示
(gdb) break/b 行号或函数名 //设置断点(gdb) continue/c //连续运行
(gdb) info/i breakpoints //查看已经设置的断点
(gdb) delete breakpoints 2 //删除某个断点
(gdb) disable/enable breakpoints 3 //禁用/启用某个断点
(gdb) break 9 if sum != 0 //满足条件才激活断点
(gdb) run/r //重新从程序开头连续执行
(gdb) watch input[4] //设置观察点,硬件观察,只有在变量发生变化才会打印
(gdb) info/i watchpoints //查看设置的观察点
(gdb) x/7b input //打印内存内容,b--每个字节一组,7--7组,input是地址
(gdb) disassemble func //反汇编当前函数或指定函数
(gdb) si // 一条指令一条指令调试 而 s 是一行一行代码
(gdb) info registers // 显示所有寄存器的当前值
(gdb) x/20 $esp //查看内存中开始的20个数