如何用GDB调试手动通过动态加载器启动的进程?
问题:手动通过ld.so启动进程后GDB附加缺失栈信息
场景复现
测试程序代码
#include <iostream> #include <thread> #include <chrono> int main() { while (true) { std::cout << "Hello World\n"; std::this_thread::sleep_for(std::chrono::seconds(1)); } }
编译命令
g++ -Wall helloworld.cc -o helloworld -g
手动通过ld.so启动程序
/lib64/ld-linux-x86-64.so.2 ./helloworld
GDB附加后的异常栈信息
假设进程PID为12345,执行附加命令:
sudo gdb -p 12345
输出内容:
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1 Copyright (C) 2022 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 "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". Attaching to process 83860 Reading symbols from /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/61/ef896a699bb1c2e4e231642b2e1688b2f1a61e.debug... Reading symbols from /lib/x86_64-linux-gnu/libstdc++.so.6... (No debugging symbols found in /lib/x86_64-linux-gnu/libstdc++.so.6) Reading symbols from /lib/x86_64-linux-gnu/libc.so.6... Reading symbols from /usr/lib/debug/.build-id/69/389d485a9793dbe873f0ea2c93e02efaa9aa3d.debug... Reading symbols from /lib/x86_64-linux-gnu/libm.so.6... Reading symbols from /usr/lib/debug/.build-id/27/e82301dba6c3f644404d504e1bb1c97894b433.debug... Reading symbols from /lib64/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/61/ef896a699bb1c2e4e231642b2e1688b2f1a61e.debug... Reading symbols from /lib/x86_64-linux-gnu/libgcc_s.so.1... (No debugging symbols found in /lib/x86_64-linux-gnu/libgcc_s.so.1) [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 0x00007f2b474e57fa in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffc1ea7ff20, rem=0x7ffc1ea7ff20) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78 78 ../sysdeps/unix/sysv/linux/clock_nanosleep.c: No such file or directory. (gdb) bt #0 0x00007f2b474e57fa in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffc1ea7ff20, rem=0x7ffc1ea7ff20) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78 #1 0x00007f2b474ea6e7 in __GI___nanosleep (req=<optimized out>, rem=<optimized out>) at ../sysdeps/unix/sysv/linux/nanosleep.c:25 #2 0x00007f2b47b0a54f in ?? () #3 0x00007f2b47b0d040 in ?? () # <=== 缺失栈信息 #4 0x00007ffc1ea7ff60 in ?? () #5 0x0000000000000001 in ?? () #6 0x0000000000000000 in ?? () (gdb)
正常启动后的完整栈信息
直接运行./helloworld后附加GDB:
sudo gdb -p 12345
输出内容:
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04) 12.1 Copyright (C) 2022 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 "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". Attaching to process 83928 Reading symbols from /tmp/helloworld... Reading symbols from /lib/x86_64-linux-gnu/libstdc++.so.6... (No debugging symbols found in /lib/x86_64-linux-gnu/libstdc++.so.6) Reading symbols from /lib/x86_64-linux-gnu/libc.so.6... Reading symbols from /usr/lib/debug/.build-id/69/389d485a9793dbe873f0ea2c93e02efaa9aa3d.debug... Reading symbols from /lib/x86_64-linux-gnu/libm.so.6... Reading symbols from /usr/lib/debug/.build-id/27/e82301dba6c3f644404d504e1bb1c97894b433.debug... Reading symbols from /lib64/ld-linux-x86-64.so.2... Reading symbols from /usr/lib/debug/.build-id/61/ef896a699bb1c2e4e231642b2e1688b2f1a61e.debug... Reading symbols from /lib/x86_64-linux-gnu/libgcc_s.so.1... (No debugging symbols found in /lib/x86_64-linux-gnu/libgcc_s.so.1) [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". 0x00007f543c2e57fa in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffdf8c83640, rem=0x7ffdf8c83640) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78 78 ../sysdeps/unix/sysv/linux/clock_nanosleep.c: No such file or directory. (gdb) bt #0 0x00007f543c2e57fa in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffdf8c83640, rem=0x7ffdf8c83640) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78 #1 0x00007f543c2ea6e7 in __GI___nanosleep (req=<optimized out>, rem=<optimized out>) at ../sysdeps/unix/sysv/linux/nanosleep.c:25 #2 0x000056445831054f in std::this_thread::sleep_for<long, std::ratio<1l, 1l> > (__rtime=...) at /usr/include/c++/11/bits/this_thread_sleep.h:82 #3 0x0000564458310243 in main () at helloworld.cc:8 (gdb)
运行环境:Ubuntu22.04,gcc 11.3.0,gdb 12.1
原因分析
手动调用/lib64/ld-linux-x86-64.so.2启动程序时,进程的入口点是动态链接器本身,而非你的helloworld程序的main函数。GDB附加时,默认会将动态链接器识别为主程序,仅加载它的调试符号,没有自动关联到helloworld可执行文件的符号信息。这就导致栈回溯时,无法解析属于你的程序代码的栈帧,出现??的缺失信息。
而直接运行./helloworld时,内核会自动启动动态链接器,并将你的程序作为主程序加载。GDB附加时能正确识别helloworld是目标程序,加载对应的调试符号,因此栈信息完整。
解决方法
方法1:附加后手动加载程序符号
在GDB命令行中执行:
add-symbol-file ./helloworld <加载基址>
其中<加载基址>可以通过查看进程的内存映射获取:
cat /proc/<PID>/maps | grep helloworld
输出中类似555555554000-555555555000 r-xp ... ./helloworld的起始地址就是加载基址(示例中的0x555555554000)。
方法2:用GDB直接启动动态链接器和程序
直接通过GDB指定启动命令,让它自动识别目标程序:
gdb --args /lib64/ld-linux-x86-64.so.2 ./helloworld
启动后可以正常设置断点、调试,栈回溯信息完整。
方法3:附加时指定程序文件
附加进程的同时,告诉GDB目标程序的路径:
sudo gdb -p <PID> ./helloworld
这样GDB会同时加载进程和指定程序的调试符号,栈回溯即可正常解析。
内容的提问来源于stack exchange,提问作者walkerlala
相关产品推荐
相关产品推荐

