GDB远程调试技术---基于mini2440

2023-11-13

GDB调试器提供了两种不同的调试代理用于支持远程调试,即gdbserver方式和stub(插桩)方式。
   这两种远程调试方式是有区别的。gdbserver本身的体积很小,能够在具有很少存储容量的目标系统上独立运行,因而非常适合于嵌入式环境;而stub方式则需要通过链接器把调试代理和要调试的程序链接成一个可执行的应用程序文件,如果程序运行在没有操作系统的机器上,那么stub需要提供异常和中断处理序,以及串口驱动程序,如果程序运行在有操作系统的嵌入式平台上,那么stub需要修改串口驱动程序和操作系统异常处理。显然,对于在有嵌入式操作系统支持下的开发而言,gdbserver比stub程序更容易使用。这里使用的是GDB+gdbserver的方式,建立远程调试的环境。
   gdbserver是一个可以独立运行的控制程序,它可以运行在类UNIX操作系统上,当然,也可以运行在Linux的诸多变种。gdbserver允许远程GDB调试器通过target remote命令与运行在目标板上的程序建立连接。
   GDB和gdbserver之间可以通过串口线或TCP/IP网络连接通信,采用的通信协议是标准的GDB远程串行协议( Remote Serial Protocol RSP)。
   使用gdbserver调试方式时,在目标机端需要一份要调试的程序的拷贝,这通常是通过ftp或NFS下载到目标机上的,宿主机端也需要这信一份拷贝。由于gdbserver不处理程序符号表,所以如果有必要,可以用strip工具将要复制到目标机上的程序中的符号表去掉以节省空间。符号表是由运行在主机端的GDB调试器处理的,不能将主机端的程序中的符号表去掉。
    虽然大部分的Linux发行版都已经安装了GDB,但是那都是基于PC的平台的,我们要使用的是在ARM平台上,所以要重新下载gdb的源码,并修改以适应自己的目标平台。可以从http://www.gnu.org/software/gdb/download,获得。这里使用的是GDB的最新的版本7.1。首先将下载到的gdb-7.1.tar.bz2复制到/home/zfz/gdb目录下。在控制台下输入下面的解包命令

#tar -jxvf gdb-7.1.tar.bz2

  解包之后会生成gdb-7.1/目录,所有的源码都在这个目录下,在gdb目录下新建立一个目录arm-linux-gdb,把生成的可执行文件都放在这个目录下,
在gdb-7.1目录下,输入下面的命令,配置GDB源码:

./configure --target=arm-linux --prefix=/home/frank/gdb --program-prefix=arm-linux-

   其中 --target=arm-linux选项,表示针对的目标平台是运行linux内核的ARM体系结构的平台,后面的选项--prefix=/home/frank/gdb 则是指定编译完成后的安装目录,最后一个选项--program-prefix=arm-
linux-用来指定在编译生成的二进制可执行文件名之前加上前缀,这里加上的前缀是arm-linux-。这样就可以和宿主机上的调试文件相区别。

make

把源文件编译成相应的目标文件,并连接成可执行的二进制文件 。然后,再执行下面的命令,

make intall

   执行完该命令后,就会在我们刚才建立的arm-linux-gdb目录下生成bin/,lib/,share/这几个子目录,其中在bin下有三个可执行文件分别为:arm-linux-gdb. arm-linux-run ,arm-linux-gdbui.arm-linux-gdb,就是我们需要的调试器。
   编译完arm-linux-gdb之后,接下来就需要编译在目标板上运行的gdbserver了,在gdb/gdb7.1/gdb下有一个gdbserver的子目录,这个目录包括了编译gdbserver所需要的所有的东西。
首先,进行gdbserver目录

./configure --target=arm-linux --host=arm-linux

此时,如果要直接进行编译的话,会出现错误,

linux-arm-low.c:26:21:sys/reg.h: 没有那个文件 或目录
make:*****[linux-arm-low.0] Error 1


这里的sys/reg.h是指/usr/include/sys/reg.h,在该文件中定义的寄存器都是针对x86平台的,对于运行
在ARM平台上的gdbserver显然是不对的,在configure后,将会生成一个config.h文件,在这个文件中定
义了相应的宏,在config.h中我们可以看到这样一个C语言的宏定义,


#define HAVE_SYS_REG_H 1
在linux-arm-low.c文件中出错的代码行:
#ifdef HAVE_SYS_REG_H 
#include <sys/reg.h>
#endif

这里我们只需要把conifg.h文件中的#define HAVE_SYS_REG_H 1注释掉就OK了。由于gdbserver是运行在ARM-linux平台上的,因此需要使用交叉编译器arm-linux-gcc,这可以通过给make加上CC参数来实现这里我使用的是默认的,你也可以使用一个绝对的路径来指定一个arm-linux-gcc.
   所有的工作都已经完成了,只要把生成的gdbserver下载到目标板上,或者是通过NFS挂载到目标板上就可能进行远程的调试了,如果就是足够幸运的话,编译中没有出现什么错误的话,这样完全可以了,不过在我的系统上却不是那么幸运。我一直使用的是友善之臂的arm-linux-gcc-4.3.2交叉编译器,这个版本的编译器中,已经自带了arm-linux-gdb.
在终端中输入arm-linux-gdb -v 可以看到下面的信息

#make CC = arm-linux-gcc


GNU gdb (Sourcery G++ Lite 2008q3-72) 6.8.50.20080821-cvs

Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi".
For bug reporting instructions, please see:
<https:

   这里可以看出arm-linux-gcc-4.3.2自带的arm-linux-gdb的版本是6.8版的,而我们一直编译的是7.1版本的。一开始我并没有注意arm-linux-gdb的版本信息,不过在使用过程中,我把用生成的gdbserver的7.1版本用NFS加载到目标板上,而在宿主机上用的arm-linux-gcc 6.8版本,一直出现下面的错误:
先在目标机上运行下面的gdbserver,注意这里的IP地址是宿主机上的IP地址。

[root@Frankzfz]$gdbserver 10.27.10.48:9000 ./test_seg_fault 
Process ./test_seg_fault created; pid = 760 
Listening on port 9000 
Remote debugging from host 10.27.10.48

然后在宿主机上运行

arm-linux-gdb/bin$ arm-linux-gdb
GNU gdb (Sourcery G++ Lite 2008q3-72) 6.8.50.20080821-cvs
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi".
For bug reporting instructions, please see:
<https://support.codesourcery.com/GNUToolchain/>.

(gdb) target remote 10.27.10.23:9000
Remote debugging using 10.27.10.23:9000
Malformed packet(b) (missing colon): ore:0;
Packet: 'T050b:00000000;0d:804ebdbe;0f:b0070040;thread:2f8;core:0;'

(gdb) symbol-file test_seg_fault
Reading symbols from /home/zfz/kernel/fs/arm-linux-gdb/bin/test_seg_fault...done.
(gdb) break main
Breakpoint 1 at 0x84a8: file test_seg_fault.c, line 7.
(gdb) info main
Undefined info command: "main". Try "help info".
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x000084a8 in main at test_seg_fault.c:7
(gdb) c
The program is not being run.
(gdb)

输入c命令时说是程序没有运行,可是程序已经在目标板上运行了,不用输入run命令,当输入  target remote 10.27.10.23:9000结束后,在minicom中可以看到目标板上的输出信息有了变化.

[root@Frankzfz]$gdbserver 10.27.10.48:9000 ./test_seg_fault 
Process ./test_seg_fault created; pid = 760 
Listening on port 9000 
Remote debugging from host 10.27.10.48 
readchar: Got EOF 
Remote side has terminated connection. GDBserver will reopen the connection. 
Listening on port 9000

   在这里捣鼓了一整天没有弄明白错误在那里,看到了arm-linux-gdb 和gdbserver的版本不匹配,所以就变换arm-linux-gdb,这里要把arm-linux-gdb加入到.profile文件中,或者environment文件中,

PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/lib/jvm/j
dk1.6.0_17/bin:/home/zfz/kernel/fs/arm-linux-gdb/bin:/home/zfz/linux-
tool/usr/local/arm/4.3.2/bin"

   当时一直在,arm-linux-gdb/bin目录下执行,其实执行的也都是arm-linux-gcc-4.3.2中的arm-linux-gdb,如果这样你看到的版本信息还是6.8版本的话,也可以直接在arm-linux-gcc-4.3.2中把arm-linux-gdb文件删除掉。
   这样再一次查看arm-linux-gdb的信息。

GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

   使用GDB进行调试,首先,我的宿主机的IP 10.27.10.48,开发板上的IP 10.27.10.23在开发板上运行gdbserver 10.27.10.48:9000 test,这里是通过NFS,把要调试的程序加载到目标版上面的。这样就可从在宿主机上运行。

zfz@zfz:~/kernel/fs/arm-linux-gdb/bin$ ./arm-linux-gdb test
./arm-linux-gdb: Symbol `acs_map' has different size in shared object, consider re-linking
GNU gdb (GDB) 7.1
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/zfz/kernel/fs/arm-linux-gdb/bin/test...done.
(gdb) target remote 10.27.10.23:9000
Remote debugging using 10.27.10.23:9000
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
0x400007b0 in ?? ()
(gdb) l
Cannot access memory at address 0x0
1    #include <stdio.h>
2    int main( void )
3    {
4     int i=2;
5     int x, y;
6     
7     x=(++i);
8     printf(" %d %d\n", i,x);
9     x+=(++i);
10     printf(" %d %d\n", i,x);
(gdb) l
11     x+=(++i);
12     printf(" %d %d\n", i,x);
13     i=2;
14     y=(i++)+(i++)+(i++);
15     printf(" %d %d\n", i,y);
16     
17     return 0;
18    }
19     
(gdb) break 9
Breakpoint 1 at 0x83b8: file test.c, line 9.
(gdb) c
Continuing.
Error while mapping shared library sections:
`/lib/libc.so.6'
: not in executable format: File format not recognized
Error while mapping shared library sections:
/lib/ld-linux.so.3: No such file or directory.

Breakpoint 1, main () at test.c:9
9     x+=(++i);
(gdb) step
10     printf(" %d %d\n", i,x);
(gdb) next
11     x+=(++i);
(gdb) next
12     printf(" %d %d\n", i,x);
(gdb) next
13     i=2;
(gdb) next
14     y=(i++)+(i++)+(i++);
(gdb) next
15     printf(" %d %d\n", i,y);
(gdb) next
17     return 0;
(gdb) next
18    }
(gdb) next

在目标板上的输出:

[root@Frankzfz]$gdbserver 10.27.10.48:9000 ./test 
Process ./test created; pid = 746 
Listening on port 9000 
Remote debugging from host 10.27.10.48 
 3 3 
 4 7 
 5 12 
 5 6

补充:前面还有库文件错误的问题,这里可以通过下面这样的方法的来解决。需要说明的是,远程调试,可能程序动态库,我们可以这样设置:

set solib-absolute-prefix /nfsroot/rootfs
set solib-search-path /nfsroot/rootfs/lib

调试找不到源代码,如下设置:

directory xfer-1.0.0/src/

下面是调试的情况:

(gdb) set solib-absolute-prefix /home/kernel/fs/root_nfs
(gdb) set solib-search-path /home/kernel/fs/root_nfs/lib
(gdb) target remote 10.27.10.23:9000
Remote debugging using 10.27.10.23:9000
Reading symbols from /home/kernel/fs/root_nfs/lib/ld-linux.so.3...(no debugging symbols 

found)...done.
Loaded symbols for /home/kernel/fs/root_nfs/lib/ld-linux.so.3
0x400007b0 in ?? () from /home/kernel/fs/root_nfs/lib/ld-linux.so.3
(gdb) l
3    {
4     int i=2;
5     int x, y;
6     
7     x=(++i);
8     printf(" %d %d\n", i,x);
9     x+=(++i);
10     printf(" %d %d\n", i,x);
11     x+=(++i);
12     printf(" %d %d\n", i,x);
(gdb) l
13     i=2;
14     y=(i++)+(i++)+(i++);
15     printf(" %d %d\n", i,y);
16     
17     return 0;
18    }
19     
(gdb) b 8
Note: breakpoint 1 also set at pc 0x83a8.
Breakpoint 2 at 0x83a8: file test.c, line 8.
(gdb) c
Continuing.

Breakpoint 1, main () at test.c:8
8     printf(" %d %d\n", i,x);
(gdb) n
9     x+=(++i);
(gdb) b 12
Breakpoint 3 at 0x8400: file test.c, line 12.
(gdb) n
10     printf(" %d %d\n", i,x);
(gdb) n
11     x+=(++i);
(gdb) n

Breakpoint 3, main () at test.c:12
12     printf(" %d %d\n", i,x);
(gdb) n
13     i=2;
(gdb) n
14     y=(i++)+(i++)+(i++);
(gdb) n
15     printf(" %d %d\n", i,y);
(gdb) n
17     return 0;
(gdb) n
18    }
(gdb) n
0x4003b004 in __libc_start_main ()
   from /home/kernel/fs/root_nfs/lib/libc.so.6
(gdb) 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GDB远程调试技术---基于mini2440 的相关文章

  • 检查 python 调试器中的复杂变量,例如 pudb

    如何使用 python 调试器检查复杂变量 列表 字典 对象 值 我是 python 新手 我尝试了 pudb 看起来当变量类型为复杂类型时 调试器仅显示变量的类型 而不显示变量的类型价值 是否可以使用 pudb 检查值 或者有其他 pyt
  • 在 OSX 上通过 dlopen 打开库时调试崩溃

    我开发的 C 应用程序有问题 该应用程序使用 dlopen 加载用户开发的库 在过去的几年里 这个应用程序已经被很多人在各种 Linux 发行版和 OSX 版本上使用 所以我假设我对 dlopen 的使用是好的 依赖它的代码也是如此 是的
  • ndk-build DUMP_APP_ABI 在 Windows 上返回 2 行

    我无法在 Windows 上调试 android ndk 应用程序 它seems https stackoverflow com questions 20047348 unknown application abi while debug
  • 如何在 gdb 上进行 grep 打印

    有没有办法在 gdb 中 grep 打印命令的输出 就我而言 我正在使用 gdb 调试核心转储 并且我正在调试的对象包含大量元素 我发现很难寻找匹配的属性 即 gdb print this grep
  • VS 2008 Addon 暂时禁用/删除所有 catch 块

    是否有任何插件可以暂时禁用所有 catch 块 我正在维护一个应用程序 我需要找出它到底在哪里抛出异常 有人已经完成了错误处理 所有层都完成了 这使我的工作变得艰难 我不知道如何禁用 catch 块 但您想要实现的目标可以通过异常对话框中的
  • 禁用 Google 应用测量调试日志记录

    在 Xcode 7 2 上 如何禁用这些调试 应用程序测量紧急显示 2016 01 07 11 52 53 085 MyApp 1457
  • 调试 Ruby 段错误

    如何确定段错误是否是由于库不一致或我正在使用的某些 gem 中的错误造成的 uname a Linux redacted 3 2 0 24 generic 39 Ubuntu SMP Mon May 21 16 52 17 UTC 2012
  • 无法使用 RVM、Ruby 1.9.2 和 Rails 3 运行 RubyMine 调试器

    我已经设置了全新的 Ubuntu 安装并遵循本指南 http ryanbigg com 2010 12 ubuntu ruby rvm rails and you安装 RVM Ruby 1 9 2 和 Rails 3 然后我安装了RubyM
  • 如何在远程计算机上调试 war 文件?

    如果我有一个 jboss 服务器在另一台机器上运行 并且我将我的 war 文件 scp 到该机器 我该如何调试 war 我会使用什么命令 如何在我的终端中执行此操作 在远程计算机上使用调试参数运行 jboss Xdebug Xrunjdwp
  • 使用 Google Breakpad 的小型转储无法显示应用程序崩溃的行号

    我在崩溃时获得了应用程序的小型转储文件 但它没有给我诸如函数名称和行号之类的详细信息 输出如下 Operating system Linux 0 0 0 Linux 3 3 8 2 2 1 SMP Thu May 12 13 30 26 U
  • 尝试更改冻结标题:有 FB 开发人员吗?

    在过去的几年里 这个问题已经被问过几次了 但正如 Facebook 告诉我的那样 Facebook 工程师积极参与 StackOverflow 所以我希望在这里能得到一些快乐 我们已将视频上传到 YouTube 进行了转发并确保我们对此感到
  • Objective-C 有没有办法捕获发送到 nil 的消息?

    我刚刚被一种烦人的东西咬了bug https stackoverflow com questions 913627 uiviewcontroller viewdidload not being calledObjective C 中的 向
  • 当线程无法访问所有已用堆时查找 Java 内存泄漏

    我正在研究基于 Java 的大型系统中潜在的内存泄漏 或至少是内存浪费 JVM 运行时的最大堆大小为 5 GB 2 3GB 堆使用量是应用程序的预期基准 可能会有更高的峰值 在我正在调查的过载场景中 堆被填满 使用 Eclipse Memo
  • 检查仪器中的内存分配

    我已经使用泄漏工具清除了应用程序的泄漏 但我仍然注意到当我切换视图时 objectalloc 工具分配的对象数量和占用空间会增加 我特别看到大量 GeneralBlock 16 主要由基金会负责调用者 NSLogv and GeneralB
  • 哪个信号被传递到信号处理程序中死锁的进程

    我有一个来自调用信号处理程序后死锁的进程的核心转储 如何确定传送了哪个信号以及是谁发送的 GDB 为接收信号的线程生成的回溯如下 信号处理程序在第 15 帧中被调用 gdb bt 0 0x00007fa9c204654b in sys fu
  • 编写 LESS 时,chrome 调试器中出现红点?

    我正在将 css 文件转换为 LESS 文件 我的 LESS 只有一部分运行良好 我在 chrome 调试器中看到那些有问题的行有一条奇怪的红点线 知道它们是什么意思吗 http codemirror net doc releases ht
  • 生成转储并导致非托管代码崩溃?

    当我的应用程序突然崩溃时 有没有办法获得完整的故障转储 问题是 我怀疑这是由于非托管代码杀死了 net 框架本身 因此 除非在崩溃时应用程序附加了调试器 否则应用程序甚至没有机会处理崩溃 我无法附加调试器并等待 因为崩溃是随机发生的 而且我
  • 使用 Julia 的 Debugger.jl - 如何进入类似于 Python 的 pdb.set_trace() 或 ipdb.set_trace() 的调试模式?

    Julia 的新 Debugger jl 很棒 但有时要达到我想要达到的代码中的确切位置有点痛苦 有没有办法可以进入交互式调试模式 类似于 Python 在 pdb set trace 或 ipdb set trace 中的模式 例如 我希
  • 如何使用 PDB 文件

    我听说使用 PDB 文件可以帮助诊断崩溃发生的位置 My basic理解是你给 Visual Studio 源文件 pdb 文件和崩溃信息 来自 Dr Watson 有人可以解释一下这一切是如何运作的 涉及什么吗 谢谢你 PDB 文件将程序
  • wpf 调试错误输出 System.WIndows.Data 错误 25

    我有一个自定义样式的组合框 效果很好 它被放置在用户控件内并绑定到数据结构 我使用 DisplayMemberPath 仅显示组合框文本框中的一个元素 ComboBox 样式取自 MSDN 并被多次使用 所以这里就不显示了

随机推荐