gdb远程调试

发布时间 2023-12-15 17:52:44作者: leehsiang

gdb远程调试功能允许你在一台机器上运行你的程序,而在另外一台机器上使用gdb或者使用IDE来进行调试。可以是在移动平台运行程序,在pc上进行调试。甚至是在docker里面运行程序,在主机上调试。配合IDE,你能够像是在本地运行程序一样的去调试。只要你运行程序的机器上有gdbserver,并且能通过网络连接你的调试的机器,你就可以使用这种方式进行远程调试。
为了方便,这里约定后文中把运行你的程序的机器成为远程机器,把你用来调试的机器称为本地机器。

gdb server

让远程调试变为可能的工具就是gdb server。在远程调试中,远程机器上通过gdb server启动被调试程序,本地机器上启动gdb。gdb通过网络连接gdb server,控制gdb server进行调试。

环境依赖

远程机器

只要有gdbserver即可。可以在终端中执行gdbserver --version来检测gdbserver是否存在。一般linux系统都默认安装有gdbserver,如果没有安装,则需要自行安装。您的远程机器是否支持gdbserver以及怎么安装gdbserver需要查找相关文档。

本地机器

本地机器需要有gdb。注意,本地机器要使用的gdb应该是跟远程机器匹配的。例如,你在系统为ubuntu20.04的PC机上远程调试android设备上运行的程序,你需要的gdb是跟android匹配的gdb,而不是调试ubuntu20.04上的程序使用的gdb。通常在交叉编译工具链中你可以找到对应的gdb工具,本文实验使用的gdb在${ANDROID_NDK}/prebuilt/linux-x86_64/bin/gdb下面,其中ANDROID_NDK是安卓交叉编译工具链的路径。
如果你想在IDE中以图形界面的方式调试程序,你需要安装IDE软件。本文会讲述vs code和clion两款IDE工具的配置流程。

网络连接

gdb和gdb server之间是通过网络来通信的,远程机器和本地机器之前需要有网络连接。本文实验环境是通过adb端口映射的方式来实现网络连接的。

编译工具

你需要相应的编译工具来编译你的程序,这里不再赘述。需要强调的是,你应当编译debug版来调试,编译出来的二进制程序需要包含调试信息。

基本流程

  1. 将被调试程序上传到远程机器上,通过gdbserver在远程机器上启动程序。gdbserver的使用方式为gdbserver :port program args,其中port是端口号,program是你的程序,args是需要传给你的程序的参数。如果你的程序需要设置环境变量,你需要在这之前设置号。端口号是用来跟本地机器上的gdb通信的端口号,可以任意指定。

    然后gdb server就会启动,等待本地机器的gdb来连接。

    下面是一个示例:

    export LD_LIBRARY_PATH=$(pwd)/libs
    gdbserver :9090 dms --video='./path/of/video/file.mp4'
    
  2. 本地机器上启动gdb(注意是跟远程机器环境匹配的gdb,前文环境依赖中亦有说明),然后连接远程gdb server,就可以像在本地调试程序一样的调试了。gdb调试程序的方式可以查阅相关文档。

    下面是一个示例

    gdb dms //启动gdb,然后就会进入gdb工具
    target remote ip:9090 //在gdb工具中输入这行命令,连接远程机器上的gdb server
    set sysroot ./path/of/solib //设置本地机器上的动态库的副本的路径
    ... //开启你愉快的调试旅程吧~
    

    在上面这个示例中,第1行启动gdb。这里在gdb后面加上了你的程序,这里的程序是你在本地机器上保留的副本。注意要和远程机器上跑的程序保持一致,否则可能会出错。其实,这里在gdb后面也可以不加上你的程序,直接gdb就可以启动。不过,不在gdb后面加上你的程序的话,gdb会通过与远程的gdb server通信将你的程序中包含的符号通过网络传输过来,这可能会增加等待的时间。加上你的程序在本地的副本,gdb会从本地副本程序中读取符号,这会减少等待。

    第2行是在gdb中输入的命令,它表示通过ip:9090这个地址连接远程的gdbserver。这里的9090是你在第1步启动gdbserver时设置的端口号,ip是远程机器的ip。本文实验中是用adb forward tcp:9090 tcp:9090来将本地机器的9090端口映射到远程机器的9090端口,因此输入的命令是"target remote localhost:9090"。如果你是通过网络连接远程机器,这里的ip填入远程机器的ip即可。

    第3上set sysroot命令设置本第依赖库的副本的路径。跟第1行中类似,你也可以执行这行命令,但这样gdb会将依赖库中的符号从远程通过网络传输过来,这可能会增加你的等待。

    然后你就可以开始使用gdb调试了。具体的怎么使用gdb调试,可以参考gdb的文档。

结合IDE

使用IDE来进行调试,体验会比在命令行中直接使用gdb好得多。接下来将会以vs code和clion为例讲述如何配置IDE来实现远程调试。