gdb server简单探索

前言

gdb server运行于嵌入式设备,比如arm或arm64体系结构,体积小,占用资源少,相当于一个前端。gdb server可以attach到一个strip的进程。
gdb运行于性能更高的主机,如x86设备上,需要有带符号表的相应进程。
以下分别以aarch64和x86来指带被调试进程运行设备(也就gdbserver运行设备)和gdb运行的设备。

关于gdb编译参数–target

我是使用ubuntu docker编译的gdb和gdb server,之前去简单看了下gdb的官方文档,不过也没咋看明白,之前在automake中文手册中提到过–target=target选项,我一直以为这个只有在交叉编译编译器的时候才会用到,但编译gdb时也用到了。
首先确认一下,需要编译的至少有两个进程,gdb与gdbserver,分别运行于x86和arm平台,gdbserver运行于进程真正运行的设备上,毫无疑问,指定–host=aarch64就可以了。
而gdb需要怎么编译呢?若指定–host=aarch64,则变成了arm平台的程序,但是若不指定host,那么变成了x86平台的普通gdb了,经过亲身实践,不带参数指定编译完的gdb在远程连接gdbserver后是不能正常调试的。
但是当使用同一源码编译gdb时携带–target=aarch64,则可以正常调试。
这里引用一句话:

target:表示需要处理的目标平台名称,若无指定使用 host 相同名称,gcc、binutils, gdb
等与平台指令相关的软件都有此参数,多数软件此参数无用处。

因此之前对target参数的理解可能偏狭隘,target参数不只是给编译器用的,指明编译出的编译器编译出的程序运行的平台,而是编译出的程序需要处理的目标的平台。
还有一个有意思的地方是这两种参数编译出来的产物也不同,如果指定了host(交叉编译),那么产物是gcore gdb gdb-add-index gdbserver run,而指定target,产物是gdb gdb-add-index run,少了gcore和gdbserver。

编译

具体编译过程可参照Building GDB and GDBserver for cross debugging
编译过程还好,可能问题都是由于我这个ubuntu是被简化过的,过程中有不报不支持c++11,实际上是g++没安。
一个编译gdb常见的问题可能是缺少libtermcap库,实际这个库很老了,之前编译也不好编,只能编出静态库,而且指定了也不好用,可以去下载ncurses源码,交叉编译使用之。
还有就是报缺少gmp,我当时用apt在装,可能是脑子不清醒了,实际交叉编译缺库,安装自己平台的库是没用的,因此去下载了gmp源码交叉编译,指定-I和-L就可以了。
最后把编译好的gdbserver拷贝到arm设备就可以了。
如果只编译嵌入式设备的gdbserver的话应该不需要额外的库,看编译完的依赖:

Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libdl.so.2]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libpthread.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-aarch64.so.1]

很明显是不需要 额外库的。看了本节开头的链接后,编译gdbserver只需要:

 ../configure --host=aarch64-linux-gnu --prefix=/opt/linkcopy/ CPPFLAGS="-Wno-error"
make -j4 all-gdbserver

跟本不需要去交叉编译那些库。
使用源码包版本记录,全部下载于http://ftp.gnu.org
gdb-12.1.tar.gz
gmp-6.2.1.tar.xz
ncurses-6.4.tar.gz

连接

arm设备:
先编个程序:

pi@link:~/project$ cat test.cpp
#include<iostream>
using namespace std;
int main()
{
	cout<<"hello world!"<<std::endl;
}
pi@link:~/project$g++ -g  -O2 test.cpp

然后做个strip的版本,把原版拷贝到x86设备,然后运行

gdbserver link.local:6000 a_strip.out

x86设备:

 /opt/bentutucopy/bin/aarch64-linux-gnu-gdb a.out

之后在gdb里执行:

(gdb) target remote link.local:6000

然后这两个就连上了,可以开始使用了。

使用

1)远程获取/上传/删除文件

remote get/put/delete命令
get
这样在测试的时候,在嵌入式设备上编译的带符号表版本的进程可以直接下载到本地设备。

2)运行进程

  1. 用gdbserver attach已经运行的进程
  2. 运行时命令行指定要调试的进程,然后用gdb连接后运行continue(不让运行run)。
  3. 不指定任何进程启动gdbserver:$ gdbserver --multi localhost:6000,然后在gdb指定要调试的进程,但客户端必须要用target extended-remote命令连接。连接后使用set remote exec-file a.out指定要调试进程的名字,然后就可以运行run了。需要注意的是以–multi启动的gdbserver不会主动退出,需要在gdb端连接后使用monitor exit显式退出,除非一种情况,在启动gdbserver时还指定了–onece。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GDB Server是一个用于远程调试的工具。它允许将调试会话从一个机器转移到另一个机器上。具体来说,当我们需要在虚拟机A上调试代码时,我们需要在A上安装gdbserver,并在虚拟机B上安装gdb。确保gdbserver的版本和gdb的版本尽可能保持一致,以避免可能出现的符号表不能装载等问题。安装步骤可以根据实际情况进行操作。 当代码很大时,我们可能无法在虚拟机或板子上装载完整的、带符号表的代码。为了减小代码的大小,我们可能会使用strip命令去除可执行文件的调试信息。然而,如果代码发生问题,我们将无法使用gdb进行调试。这时候就需要使用gdbserver来进行远程调试。 具体操作如下: 1. 首先,在虚拟机A上去除代码的调试信息,可以使用file命令来检查。确保没有调试信息后,可以将代码复制到虚拟机A上。 2. 在虚拟机A上使用命令"gdbserver ip:端口 可执行文件名"来启动程序。其中,ip是当前虚拟机的IP地址,端口可以自行选择,只要没有被占用即可。 3. 在虚拟机B上使用gcc -g命令生成一个带有调试信息的可执行文件。例如,如果代码文件名是demo.c,可以使用gcc -g demo.c来生成a.out文件。 4. 然后,在虚拟机B上使用gdb命令连接到虚拟机A上的gdbserver,可以使用命令"target remote ip:端口"进行连接。 通过以上步骤,我们可以在虚拟机B上使用gdb来远程调试虚拟机A上的代码。这使得我们能够在较小的设备上进行调试,同时保留了完整的调试信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值