GDB调试

调试前准备

获取进程的内核转储(core dump)

why:最大好处是,其保存了问题发生时的状态。记录进程当前状态。

步入正题:

启动内核转储,查看当前内核转储功能是否有效,结果为0表示内核转储无效

$ ulimit -c

那么,则需要开启内核转储,该命令不限制转储文件大小。亦可设置为有限上限1G,ulimit -c 1073741842。

$ ulimit -c  unlimited

$ ./a.out    生成转储文件

查看生成的转储文件

$ file core*

GDB启动,使用转储文件

$ gdb -c core.xxx   ./a.out

 

一、GDB调试前问题汇总

1.编译出现undefined reference to 'pthread_create'

编译加上参数   -lpthread

2.apue.h找不到

导入src.3e.tar.gz 中apue/include/apue.h  到 /usr/include

3.err_sys未定义

关于err_sys未定义错误解决方法

二、GDB例子(切入)

一个调试示例

——————

源程序:tst.c

#include

int func(int n){

int sum = 0,i;

for(i=0; i<7;i++){

sum += i; } return sum;}

main(){

int i;

long result = 0;

for(i=1;i<=100;i++){

result += i;}

printf("result[1-100]= %d/n",result);

printf("result[1-250]= %d/n",func(250));

}

编译生成执行文件:(Linux下)

hchen/test> cc -g tst.c -o tst

使用GDB调试:

hchen/test> gdb tst  <---------- 启动GDB

GNU gdb 5.1.1

Copyright 2002 Free Software Foundation, Inc.

GDB is free software, covered by the GNU General Public License, and you are

welcome to change it and/or distribute copies of it under certain conditions.

Type "show copying" to see the conditions.

There is absolutely no warranty for GDB.  Type "show warranty" for details.

This GDB was configured as "i386-suse-linux"...

(gdb) l     <-------------------- l命令相当于list,从第一行开始例出原码。

1        #include

2

3        int func(int n)

4        {

5                int sum=0,i;

6                for(i=0; i

7                {

8                        sum+=i;

9                }

10               return sum;

(gdb)       <-------------------- 直接回车表示,重复上一次命令

11       }

12

13

14       main()

15       {

16               int i;

17               long result = 0;

18               for(i=1; i<=100; i++)

19               {

20                       result += i;

(gdb) break 16    <-------------------- 设置断点,在源程序第16行处。

Breakpoint 1 at 0x8048496: file tst.c, line 16.

(gdb) break func  <-------------------- 设置断点,在函数func()入口处。

Breakpoint 2 at 0x8048456: file tst.c, line 5.

(gdb) info break  <-------------------- 查看断点信息。

Num Type           Disp Enb Address    What

1   breakpoint     keep y   0x08048496 in main at tst.c:16

2   breakpoint     keep y   0x08048456 in func at tst.c:5

(gdb) r           <--------------------- 运行程序,run命令简写

Starting program: /home/hchen/test/tst

Breakpoint 1, main () at tst.c:17    <---------- 在断点处停住。

17               long result = 0;

(gdb) n          <--------------------- 单条语句执行,next命令简写。

18               for(i=1; i<=100; i++)

(gdb) n

20                       result += i;

(gdb) n

18               for(i=1; i<=100; i++)

(gdb) n

20                       result += i;

(gdb) c          <--------------------- 继续运行程序,continue命令简写。

Continuing.

result[1-100] = 5050       <----------程序输出。

Breakpoint 2, func (n=250) at tst.c:5

5                int sum=0,i;

(gdb) n

6                for(i=1; i<=n; i++)

(gdb) p i        <--------------------- 打印变量i的值,print命令简写。

$1 = 134513808

(gdb) n

8                        sum+=i;

(gdb) n

6                for(i=1; i<=n; i++)

(gdb) p sum

$2 = 1

(gdb) n

8                        sum+=i;

(gdb) p i

$3 = 2

(gdb) n

6                for(i=1; i<=n; i++)

(gdb) p sum

$4 = 3

(gdb) bt        <--------------------- 查看函数堆栈。

#0  func (n=250) at tst.c:5

#1  0x080484e4 in main () at tst.c:24

#2  0x400409ed in __libc_start_main () from /lib/libc.so.6

(gdb) finish    <--------------------- 退出函数。

Run till exit from #0  func (n=250) at tst.c:5

0x080484e4 in main () at tst.c:24

24              printf("result[1-250] = %d /n", func(250) );

Value returned is $6 = 31375

(gdb) c     <--------------------- 继续运行。

Continuing.

result[1-250] = 31375    <----------程序输出。

Program exited with code 027. <--------程序退出,调试结束。

(gdb) q     <--------------------- 退出gdb。

hchen/test>

好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。

三、adb + GDB用法

3.1 静态调试

(1)通过命令ulimit -c unlimited设置系统生成Core

 Dump文件

gdb+ 带符号表的可执行文件+Core Dump文件

该方式可以直接定位到错误发生的地方。

(2)直接gdb+ 带符号表的可执行文件

该方式需要启动之后运行run命令才能执行调试。

3.2 动态调试

就是用attach的方式连接到正在运行中的进程上面去,进行调试,下面是利用PC机动态调试手机上面的进程的操作步骤。

編譯小程序:

arm-none-linux-gnueabi-gcc -static HelloWorld.c -o HelloWorld

在android運行軟件-小程序

<1>adb shell ps -elf                                                  查看所需要调试程序的进程号

<2>adb shell gdbserver :5039 --attach PID          attach到对应进程号上面

<3>打开另一个终端,adb forward tcp:5039 tcp:5039

<4>運行arm-eabi-gdb

路径:

/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8/bin/arm-eabi-gdb

<5>set solib-absolute-prefix + 符号表文件路径

<6>set  solib-search-path + 带符号表可执行文件路径:动态共享库文件路径:....

<7>鏈接遠端程序target  remote:5039  進行調試 

四、GDB 命令(一)

gcc -g main.c  -o  xxxxx   //在目标文件加入源代码的信息

gdb a.out     

(gdb) start                        //开始调试

(gdb) n                            //一条一条执行

(gdb) step/s                        //执行下一条,如果函数进入函数

(gdb) backtrace/bt                  //查看函数调用栈帧

(gdb) info/i locals                //查看当前栈帧局部变量

(gdb) frame/f                      //选择栈帧,再查看局部变量

(gdb) print/p                      //打印变量的值

(gdb) finish                        //运行到当前函数返回

(gdb) set var sum=0                //修改变量值

(gdb) list/l 行号或函数名            //列出源码

(gdb) display/undisplay sum        //每次停下显示变量的值/取消跟踪

(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组

(gdb) disassemble                  //反汇编当前函数或指定函数

(gdb) si                                  // 一条指令一条指令调试 而 s 是一行一行代码

(gdb) info registers                // 显示所有寄存器的当前值

(gdb) x/20 $esp                    //查看内存中开始的20个数

(gdb) i   threads                      //查看threads

(gdb) t    x                             //切换至x线程下调试

(gdb) i     r                              //查看寄存器状态

(gdb) i proc m                      //(info proc mappings 的简写)核查Mapped address

(gdb) i  signals                    //查看所有信号量的设置情况。

(gdb) p $eax                        //查看eax寄存器的内容。

(gdb) generate-core-file        //生成转储文件

(gdb) i  p                                //info proc  查看进程信息

(未完待续)

四、GDB 命令(二)

attach 到进程

调试守护进程等已经启动的进程,或是调试陷入死循环而无法返回的进程时使用。

attach pid

以sleep命令为举例:

ps aux| grep sleep  查看sleep进程ID  若为17606

(gdb) attach 17606



五、GDB原理及调试实例参考

GDB原理及调试实例(推荐)

你可能感兴趣的:(GDB调试)