gdb远程调试

gdb远程调试

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

gdbserver

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

环境依赖

远程机器

只要有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 codeclion两款IDE工具的配置流程。

网络连接

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

编译工具

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

基本流程

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

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

    下面是一个示例:

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

    下面是一个示例

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

    在上面这个示例中,第1行启动gdb。这里在gdb后面加上了你的程序,这里的程序是你在本地机器上保留的副本。注意要和远程机器上跑的程序保持一致,否则可能会出错。其实,这里在gdb后面也可以不加上你的程序,直接gdb就可以启动。不过,不在gdb后面加上你的程序的话,gdb会通过与远程的gdbserver通信将你的程序中包含的符号通过网络传输过来,这可能会增加等待的时间。加上你的程序在本地的副本,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 codeclion为例讲述如何配置IDE来实现远程调试。

vs code

vs code通过launch.json文件来配置远程调试。下面直接以一个实际的例子来讲解launch.json配置文件。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb on remote) 启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/hycan_android29/bin/hycan_front",
            "args": [
                "--flagfile=./dms.flag"
            ],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/build/hycan_android29/bin",
            "environment": [
                {
                    "name": "LD_LIBRARY_PATH",
                    "value": "${workspaceFolder}/build/hycan_android29/lib/"
                }
            ],
            "externalConsole": true,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                },
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "miDebuggerPath": "/home/mini/Downloads/toolchain/android-ndk-r21e/prebuilt/linux-x86_64/bin/gdb",
            "miDebuggerServerAddress": "0.0.0.0:9090"
        }
    ]
}

"program": 配置本地机器上的可执行文件副本

"args": 程序运行时的参数

"cwd": 当前目录

"environment": 配置环境变量,例如LD_LIBRARY_PATH可以在这里配置

"miDebuggerPath": gdb的路径,注意要使用跟远程机器上的环境配套的gdb

"miDebuggerServerAddress": 远程机器的ip和端口号,跟上面命令行使用gdb类似

这些就足够了。在远程机器上启动gdbserver,如上面所说。然后在vs code里面启动调试(F5快捷键或点击界面上的调试按钮)就可以了,打断点、单步调试,等等。

clion

创建一个远程调试

Run菜单下点击Edit Configurations,点击左上角的加号,新建一个Remote Debug.

Remote Debug

Name输入框,输入一个合适的名字

debug输入框选择要使用的gdb,注意要用跟远程机器环境匹配的gdb

"target remote" args输入框输入远程机器的ip和端口号,同上文。

Symbol file选择本地机器上保存的待调试程序的副本,因为在linux上符号跟可执行文件是一起的。

Sysroot设置依赖库的路径,避免gdb从远程机器传输符号。

然后远程机器启动gdbserver,clion界面上点击调试就可以开始调试了。

posted @ 2023-12-15 17:50  leehsiang  阅读(359)  评论(0编辑  收藏  举报