Linux下交叉编译gdb,Linux应用调试

1.gdb和gdbserver调试原理

1.gdb和gdbserver调试原理

陆续编译gdb和gdbserver

由此linux虚拟机里的gdb,来向开发板里的gdbserver发送命令,比如设置断点,运转setp等,然后开发板上的gdbserver收到命令后,便会履行应用程序做相应的动作,来落到实处调试的功效

透过linux虚拟机里的gdb,来向开发板里的gdbserver发送命令,比如设置断点,运转setp等,然后开发板上的gdbserver收到命令后,便会履行应用程序做相应的动作,来兑现调试的功效

1、下载gdb:
下载地址为:
http://ftp.gnu.org/gnu/gdb/

根据一般的想法,最新版本越好,由此下载7.2这一个本子。当然,凡事无相对。
咱俩以gdb-7.2.tar.bz2 那一个文件为例。
2、解压缩:

和事先学的裸板GDB调试无异于,只不过以前学的是在win下的,这次是在linux里的gdb

和前面学的裸板GDB调试一律,只然而此前学的是在win下的,本次是在linux里的gdb

$ tar jxvf gdb-7.2.tar.bz2

1.1一模一样,它们都会须要一个带调试消息的编译文件.

1.1均等,它们都会须要一个带调试信息的编译文件.

注:小技巧:Linux下一般压缩文件后缀为.tar.bz2和.tar.gz,它们解压命令有两七个拔取是一律的:

通过Makefile里的arm-linux-gcc  -g 来的,     -g:表示编译文件里富含gdb调试消息

通过Makefile里的arm-linux-gcc  -g 来的,     -g:表示编译文件里富含gdb调试消息

xf(v),前者再加上j选项,后者再添加z选项。

1.2为啥须要调试音讯的编译文件?

1.2为何要求调试音信的编译文件?

③ 、进入该目录

比如说读开发板的应用程序里的变量a:

例如读开发板的应用程序里的变量a:

$ cd gdb-7.2/

先是gdb通过应用程序的带调试音讯的编译文件,来找出变量a存的地址地方

第②gdb通过应用程序的带调试音讯的编译文件,来找出变量a存的地点地点

4、配置

接下来将地址发送给开发板里的gdbserver,来读出a地址的值

接下来将地址发送给开发板里的gdbserver,来读出a地址的值

$./configure –target=arm-linux –program-prefix=arm-linux-
–prefix=/usr/local/arm-gdb

 

 

:–target=arm-linux趣味是说目的平台是运作于A奔驰G级M种类布局的linux内核;–program-prefix=arm-linux-是指生成的可执行文件的前缀,比如arm-linux-gdb,–prefix是指生成的可执行文件安装在哪些目录,那么些目录须求依照实况作抉择。如果该目录不设有,会自行创制,当然,权限充裕的话。

2.安装gdb和gdbserver

2.安装gdb和gdbserver

5、编译、安装

首先进入官网下载gdb-7.4: http://ftp.gnu.org/gnu/gdb/ 

先是进入官网下载gdb-7.4: http://ftp.gnu.org/gnu/gdb/ 

$  make

$ make install

2.1在虚拟机上设置GDB:  

2.1在虚拟机上设置GDB:  

碰巧的话,会在–prefix钦点的目录下生成多个子目录:bin、lib、share,大家必要的arm-linux-gdb就在内部的bin目录下。
即使你不小心查看它的尺寸的话,会发现它有14MB那么大!天呐!怎么会占这么多空间?没关系,大家可以为它瘦身。没错!就是应用strip命令!

# tar xjf gdb-7.4.tar.bz2                  //解压

# cd gdb-7.4/                              //进入gdb-7.4目录

#./configure --target=arm-linux         
              //GDB需要在pc本机里运行,并调试开发板里的应用程序,所以--target设为arm-linux

#make                                      //编译

#mkdir    tmp                            

#make install prefix=$PWD/tmp              //安装到./tmp目录下

sudo cp tmp/bin/arm-linux-gdb  /bin/       //复制到/bin目录下

/bin/arm-linux-gdb  -v                     //-v: 确定一下gdb的版本VID,是否是7.4
# tar xjf gdb-7.4.tar.bz2                  //解压

# cd gdb-7.4/                              //进入gdb-7.4目录

#./configure --target=arm-linux         
              //GDB需要在pc本机里运行,并调试开发板里的应用程序,所以--target设为arm-linux

#make                                      //编译

#mkdir    tmp                            

#make install prefix=$PWD/tmp              //安装到./tmp目录下

sudo cp tmp/bin/arm-linux-gdb  /bin/       //复制到/bin目录下

/bin/arm-linux-gdb  -v                     //-v: 确定一下gdb的版本VID,是否是7.4

$ strip arm-linux-gdb -o arm-linux-gdb-stripped
$ ls -lh 
总计 33M

-rwxr-xr-x 1 latelee root 14M 12-14 16:16 arm-linux-gdb

-rwxr-xr-x 1 latelee root 3.1M 12-14 16:25 arm-linux-gdb-stripped

2.2
在开发板上安装GDBServer:

2.2
在开发板上安装GDBServer:

 

cd gdb/gdbserver/                                   //在gdb-7.4目录下输入

./configure --target=arm-linux --host=arm-linux              //设GDBServer的工作环境

make             //编译
cd gdb/gdbserver/                                   //在gdb-7.4目录下输入

./configure --target=arm-linux --host=arm-linux              //设GDBServer的工作环境

make             //编译

可以见到,strip后的文件大小只有3.1MB,瘦身作用显明!尽管做广告的话,相对有说服力。
本条文件就是我们未来远程调试时在主机上运转的穿插调试器了:在主机上执行,调试的却是另一种连串布局的代码。然则,光有主机的调试器还不够。还亟需在对象板上运营二个叫gdbserver的东东。那几个东东是怎么来的吧?

出现以下错误:

现身以下错误:

一 、在刚刚十三分gdb解压后的目录:gdb-7.2,进入./gdb/gdbserver子目录

图片 1

图片 2

gdbserver

1、cd gdb/gdbserver/

2、配置: ./configure
–target=arm-hismall-linux
–host=arm-hismall-linux **
–prefix=/mnt/hgfs/vmshare/gdbserver7.41/**

(同样,target 和 host
为你的穿插编译器, prefix为设置的目录)

  

3、编译: make CC=**make
CC=arm-hismall-linux-gcc**

并发谬误:

linux-arm-low.c: In function
`arm_stopped_by_watchpoint’:

linux-arm-low.c:642: error:
`PTRACE_GETSIGINFO’ undeclared (first use in this
function)

linux-arm-low.c:642: error: (Each
undeclared identifier is reported only once

linux-arm-low.c:642: error: for
each function it appears in.)

 

style=”font-size: medium;”>焚薮而田办法:那里提醒没有PTRACE_GETSIGINFO那几个东西,那里寻找PTRACE_GETSIGINFO的路子为-I钦点的头文件以及交叉
编译工

 

style=”font-size: medium;”>具链,大家不妨到交叉编译工具链里面去搜寻一下:

cd /usr/local/arm/3.4.5/

grep “PTRACE_GETSIGINFO” *
-nR

找到如下新闻:

style=”font-size: medium;”>arm-linux/sys-include/linux/ptrace.h:27:#define
PTRACE_GETSIGINFO       0x4202

style=”font-size: medium;”>arm-linux/include/linux/ptrace.h:27:#define
PTRACE_GETSIGINFO   0x4202

style=”font-size: medium;”>distributed/arm-linux/sys-include/linux/ptrace.h:27:#define
PTRACE_GETSIGINFO  0x4202

style=”font-size: medium;”>distributed/arm-linux/include/linux/ptrace.h:27:#define
PTRACE_GETSIGINFO       0x4202

style=”font-size: medium;”>说明PTRACE_GETSIGINFO是在陆续编译工具链:linux/ptrace.h文件里定义的,那么或然是头文件没有包括好呢!

style=”font-size: medium;”>咱俩到gdbserver下的linux-arm-low.c里面一看,可不是嘛,只有:#include
<sys/ptrace.h>而没有:#include 

 

<linux/ptrace.h>,于是 > style=”color: #ff0000;”>在** > style=”color: #ff0000;”>linux-arm-low.c文件中 > style=”color: #ff0000;”>加上: > style=”color: #ed1c24;”>#include
<linux/ptrace.h>,再一次编译:make
CC=/usr/local/arm/3.4.5/bin/arm-linux-gcc**

成功!

指在linux-arm-low.c里,没有找到PTRACE_GETSIGINFO 定义

指在linux-arm-low.c里,没有找到PTRACE_GETSIGINFO 定义

三九个人,A瑞虎M平台,动态链接,未strip。
平等,大家也减小它的体量:

2.3
解决:

2.3
解决:

 

1) 

1) 

     # arm-hismall-linux-strip gdbserver

#echo $PATH     //来查看PATH环境变量
#echo $PATH     //来查看PATH环境变量

 

找到编译器gcc位于/work/tools/gcc-3.4.5-glibc-2.3.6/bin

找到编译器gcc位于/work/tools/gcc-3.4.5-glibc-2.3.6/bin

[root@localhost gdbserver]# ls
gdbserver -l

2)

2)

-rwxrwxrwx 1 root root 498279 2012-12-30 06:21 gdbserver

#cd /work/tools/gcc-3.4.5-glibc-2.3.6/    
# grep "PTRACE_GETSIGINFO"  *  -nR
#cd /work/tools/gcc-3.4.5-glibc-2.3.6/    
# grep "PTRACE_GETSIGINFO"  *  -nR

 

在gcc根目录下,搜索到在linux/ptrace.h中定义:

在gcc根目录下,搜索到在linux/ptrace.h中定义:

[root@localhost gdbserver]# ls gdbserver -l

 图片 3

 图片 4

-rwxrwxrwx 1 root root 209048 2012-12-30 06:53 gdbserver

3)

3)

瘦身效果一样那么明白!
专注,那里不可不利用strip的接力版本,相当于您交叉编译器带的strip工具,作者的是arm-hismall-linux-strip

#vi linux-arm-low.c
#vi linux-arm-low.c

 

添加: #define PTRACE_GETSIGINFO 0x4202

添加: #define PTRACE_GETSIGINFO 0x4202

[root@localhost gdbserver]# file gdbserver

gdbserver: ELF 32-bit LSB
executable, ARM, version 1, dynamically linked (uses shared libs),
stripped

4)最终再度make,生成gdbserver命令文件

4)最后再一次make,生成gdbserver命令文件

到此,大家转移了多少个轻重级其他文件:arm-linux-gdbgdbserver。它们的版本是相同的,那点至极主要。大家必要将gdbserver下载到开发板中,——可以透过各样各个的手法,包括但不避免NFS。调试时需求在开发板中运维这一个顺序。同时在主机中执行arm-linux-gdb调试器。

下一场将gdbserver命令文件,放入大家开发板的根目录/bin中,便能利用了

接下来将gdbserver命令文件,放入大家开发板的根目录/bin中,便能动用了

 

cp  gdbserver  /nfs_root/bin/          //nfs_root:开发板的nfs系统根目录
cp  gdbserver  /nfs_root/bin/          //nfs_root:开发板的nfs系统根目录

 

3.测试程序如下(test_debug.c)

3.测试程序如下(test_debug.c)

GDB+GDBServer的使用

#include <stdio.h>

void  C(int *p)
{
   *p = 0x12;
}

void  B(int *p)
{
  C(p);
}

void  A(int *p)
{
  B(p);
}

void  A2(int *p)
{
  C(p);
}

int  main(int argc, char **argv)
{
  int a;
  int *p = NULL;
  A2(&a);  // A2 > C
  printf("a = 0x%x\n", a);
  A(p);    // A > B > C
  return 0;
}
#include <stdio.h>

void  C(int *p)
{
   *p = 0x12;
}

void  B(int *p)
{
  C(p);
}

void  A(int *p)
{
  B(p);
}

void  A2(int *p)
{
  C(p);
}

int  main(int argc, char **argv)
{
  int a;
  int *p = NULL;
  A2(&a);  // A2 > C
  printf("a = 0x%x\n", a);
  A(p);    // A > B > C
  return 0;
}

在对象序列上运维gdbserver,其实就是在一流终端下恐怕minicom下运维gdbserver。那里将gdbserver放在宿主机的NFS设置的共享目录下/home/zzl,该目录挂载在目标板/work下。宿主机的ip为192.168.1.1,目标板的ip为192.168.1.33

其中A2(&a)会调用A2()->C(),然后将a赋值为0x12.

其中A2(&a)会调用A2()->C(),然后将a赋值为0x12.

超级终端或许minicom下

A(p)会调用A()->B()->C(),由于p是个空指针,那里将会出错.

A(p)会调用A()->B()->C(),由于p是个空指针,那里将会出错.

[root@localhost]cd /work

接下去,大家便以那一个应用程序为例.

接下去,大家便以这些应用程序为例.

[root@localhost]./gdbserver
192.168.1.1:1234 hello

4.编译

4.编译

并发提醒:
Process /work/hello
created: pid=69
Listening on port 1234

#arm-linux-gcc -g -o test_debug test_debug.c   //-g:附带调试信息
#arm-linux-gcc -g -o test_debug test_debug.c   //-g:附带调试信息

此时切换来宿主机的控制台,运营

5.调试test_debug.c

5.调试test_debug.c

[root@localhost]
arm-softfloat-linux-gnu-gdb hello

在开发板上:

在开发板上:

(gdb) target remote
192.168.2.33:1234

率先,须要让gdbserver建立地点服务器,以及要测试的哪些文件:

首先,需求让gdbserver建立地点服务器,以及要测试的哪个文件:

并发提醒:
Remote debugging using 192.168.1.33:1234
[New thread 80]
[Switching to thread 80]
0x40002a90 in ??()
同时在minicom下提示:
Remote debugging from host 192.168.2.100
(gdb)
总是成功,那时候就能够输入各类gdb命令如list、continue、next、step、break等展开程序调试了。

#gdbserver 192.168.2.107:2345 ./test_debug
//192.168.2.107:本地IP地址
//2345:端口号,用来让gdb来连接用的
//./test_debug:要测试的哪个文件
#gdbserver 192.168.2.107:2345 ./test_debug
//192.168.2.107:本地IP地址
//2345:端口号,用来让gdb来连接用的
//./test_debug:要测试的哪个文件

 

在虚拟机上:

在虚拟机上:

     使用GDB调试core文件

#/bin/arm-linux-gdb   ./test_debug    // 启动gdb,指定调试文件为test_debug

#target remote  192.168.2.107:2345    //与gdbserver建立连接
#/bin/arm-linux-gdb   ./test_debug    // 启动gdb,指定调试文件为test_debug

#target remote  192.168.2.107:2345    //与gdbserver建立连接

$ gdb –core=core.9128 
GNU gdb Asianux (6.0post-0.20040223.17.1AX) 
Copyright 2004 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-asianux-linux-gnu”. 
Core was generated by `./a.out’. 
Program terminated with signal 11, Segmentation fault. 
#0 0x08048373 in ?? () 
(gdb) bt 
#0 0x08048373 in ?? () 
#1 0xbfffd8f8 in ?? () 
#2 0x0804839e in ?? () 
#3 0xb74cc6b3 in ?? () 
#4 0x00000000 in ?? () 

5.1老是成功,便利用gdb命令来调节

5.1接连成功,便采纳gdb命令来调节

此刻用bt看不到backtrace,约等于调用堆栈,原来GDB还不驾驭符号新闻在哪儿。大家告诉它刹那间: 

常用命令如下所示(参考http://blog.sciencenet.cn/blog-619295-813770.html):

常用命令如下所示(参考http://blog.sciencenet.cn/blog-619295-813770.html):

(gdb) file ./a.out 
Reading symbols from ./a.out…done. 
Using host libthread_db library “/lib/tls/libthread_db.so.1”. 
(gdb) bt 
#0 0x08048373 in sub () at foo.c:17 
#1 0x08048359 in main () at foo.c:8 

l

l

此时backtrace出来了。 

列出具有源代码

列出装有源代码

(gdb) l 
8        sub(); 
9        return 0; 
10    } 
11 
12    static void sub(void) 
13    { 
14        int *p = NULL; 
15 
16         
17        printf(“%d”, *p); 
(gdb) 

break
[file]:[row]

break
[file]:[row]

 

打断点,比如:

打断点,比如:

 

break test_debug.c:21     //在test_debug.c文件的第21行处打断点
break test_debug.c:21     //在test_debug.c文件的第21行处打断点

对于GDBServer出现的题材

info
br

info
br

1.  GDBServer调试时现身packet error 难点。

查阅断点

查看断点

紧即使虚拟机与目标机的网络连接要通过windows,数据包简单丢失。换来Linux系统下则苏醒不奇怪。

 

 

info file

info file

 

 

列出当下的公文,共享库。

列出近期的文本,共享库。

 

 

delete
<num>

delete
<num>

剔除第多少个断点,如下图所示:

除去第多少个断点,如下图所示:

 图片 5

 图片 6

c

c

开行程序运维 

起步程序运转 

step

step

单步执行

单步执行

next  

next  

单步执行,和step不一致的是,比如:当前行里有函数调用时,next直接实施下一句,step会进入函数

单步执行,和step区其余是,比如:当前行里有函数调用时,next直接执行下一句,step会进入函数

print a

print a

打印a变量的值

打印a变量的值

quit

quit

退出gdb

退出gdb

 

 

6.也得以透过gdb+coredump来调节test_debug.c

6.也可以通过gdb+coredump来调节test_debug.c

当程序运营出错时,便会生成core文件,并将顺序里的运行景况存到core中,相当于coredump,须求gdb来调节

当程序运维出错时,便会生成core文件,并将次第里的运转意况存到core中,相当于coredump,必要gdb来调节

6.1首先,通过ulimit来查看coredump的财富大小**     **

6.1先是,通过ulimit来查看coredump的财富大小**     **

ulimit命令**(user
limit),首要用来限制用户的逐条进程资源.

ulimit命令**(user
limit),主要用来界定用户的次第进程能源.

在开发板里,输入

在开发板里,输入

 图片 7

 图片 8

如上图所示,可以看看coredump的能源大小为0,也等于说,当程序运行出错时,不会生成core文件

如上图所示,可以看出coredump的财富大小为0,也等于说,当程序运营出错时,不会生成core文件

6.2设置core文件

6.2设置core文件

设置core文件的能源大小为无界定,输入:

安装core文件的财富大小为无界定,输入:

ulimit -c unlimited
 //-c:对应coredump
ulimit -c unlimited
 //-c:对应coredump

6.3生成core文件

6.3生成core文件

执行:

执行:

#./test_debug
#./test_debug

并发段错误,并生成core文件,如下图所示:

出现段错误,并生成core文件,如下图所示:

 图片 9

 图片 10

6.4
进入虚拟机

6.4
进入虚拟机

将core拷贝过来,然后实施:

将core拷贝过来,然后实施:

#/bin/arm-linux-gdb ./test_debug ./core
#/bin/arm-linux-gdb ./test_debug ./core

然后输入bt,便可查阅调用关系:

下一场输入bt,便可查看调用关系:

 图片 11

 图片 12

 

 

相关文章