必须加-g选项,否则gdb无法获取变量名、行号、函数名等调试信息,只能进行汇编级调试。可通过file或readelf验证调试符号是否存在,无符号时应优先重编译,或借助debuginfo包、反汇编和寄存器分析辅助定位问题。

不能直接调试——除非编译时加了 -g。没带调试信息的可执行文件,GDB 只能看汇编、寄存器和内存,看不到变量名、行号、函数名,基本等于“盲调”。
确认程序是否含调试信息
这是最关键的一步,很多人跳过就硬试,结果 list 没输出、break main 报错、bt 显示 ??。用 file 或 readelf 快速验证:
-
file ./a.out—— 如果输出里有with debug_info,说明有调试符号 -
readelf -S ./a.out | grep debug—— 看到类似.debug_info、.debug_line的节才真正有效 - 如果什么都没输出,或提示
no debugging information,那 GDB 对你这个二进制是“睁眼瞎”
没有 -g 怎么办:补救路径有限但真实存在
重编译永远是最优解;但如果源码丢失、环境不可控、或只是临时分析第三方程序(比如系统工具崩溃),可以尝试以下方式:
- 检查是否安装了
debuginfo包(仅限发行版预编译包):dnf debuginfo-install coreutils(Fedora/RHEL)或apt install coreutils-dbgsym(Ubuntu) - 用
objdump -d ./a.out | head -20看反汇编,配合info registers和x/10x $rsp手动查栈,适合定位段错误地址 - 若程序崩溃生成了
core文件,且你知道大概出错位置(比如Segmentation fault (core dumped)后的地址),可用gdb ./a.out core+info registers+bt(可能显示 ??,但至少能看到崩溃时的 RIP 和 RSP)
gdb ./a.out 启动后立刻能做的三件事
哪怕没 -g,GDB 仍能提供底层运行时状态。启动后别急着 run,先做这几步:
-
info files—— 确认加载的段、入口地址、是否 stripped(stripped 表示符号已删,基本放弃源码级调试) -
disassemble main—— 查看main函数汇编,找关键 call 或 cmp 指令位置 -
break *0x401126—— 在反汇编中看到的某条指令地址下断点(注意加*),然后run,再用x/4x $rax查寄存器值
真没调试信息时,GDB 不是“不能用”,而是从“源码调试器”退化为“内存+寄存器观察器”。所有依赖符号名的操作(print var、break func、list)都会失效,这时候与其硬扛,不如先确认:这程序是不是你可控的?如果是,立刻加 -g 重编;如果不是,就接受它只能帮你定位到汇编层级的事实。











