gdb从哪里获取代码行?

7
当我使用-g编译程序并得到核心转储时,我可以使用gdb读取可执行文件和核心转储以调试程序在崩溃之前运行到的情况。其中gdb提供的一个功能是列表选项,可以列出使用可执行文件和核心转储编译的源代码。我使用strings -a命令与可执行文件和核心转储一起使用,但是我找不到任何if或for语句,虽然我确定代码有很多这些语句。那么代码从哪里来?我在一台计算机上编译代码,然后在不同的计算机上运行它,因此源代码不可用于生成核心转储的计算机,并且似乎也不在可执行文件或核心转储中。有什么建议吗?我真的想从可执行文件和核心转储中打印所有源代码,这可能吗?我的意思是不使用gdb,我确定可以编写一个使用gdb并可以列出整个代码的脚本,但我想自己做而不使用gdb,因为我想了解源代码来自何处以及如何格式化它,我希望尽可能多地了解它。

有许多不同的调试信息格式;您如何直接访问它将取决于使用哪种格式。 - Scott Hunter
1个回答

7
该行信息位于可执行文件的.debug_line DWARF部分中:
$readelf -wL ./a.out 
Decoded dump of debug contents of section .debug_line:

CU: bla.c:
File name                            Line number    Starting address
bla.c                                          2            0x4004b6
bla.c                                          3            0x4004ba
bla.c                                          4            0x4004bf

这个部分将指令指针地址映射到给定文件中的行号。
为了找到文件的内容,您需要能够找到相关的源文件。如果您移动/重命名源文件,GDB 将无法打印源代码:
mv bla.c bla2.c
gdb ./a.out
(gdb) break main
(gdb) run
(gdb) list
1       in bla.c
.debug_info DWARF 部分包含有关编译源文件时源文件所在路径的一些信息,可以用于查找相关文件。
$ objdump -Wi -wa ./a.out
./a.out: 文件格式为 elf64-x86-64 ./a.out
.debug_info 部分的内容:
编译单元 @ 偏移量 0x0: 长度:0x4e(32 位) 版本:4 缩写偏移量:0x0 指针大小:8 : 缩写编号:1(DW_TAG_compile_unit) DW_AT_producer : (间接字符串,偏移量:0x0):GNU C 4.9.1 -mtune=generic -march=x86-64 -g DW_AT_language : 1(ANSI C) DW_AT_name : (间接字符串,偏移量:0x59):bla.c DW_AT_comp_dir : (间接字符串,偏移量:0x31):/home/myself/temp/bla DW_AT_low_pc : 0x4004b6 DW_AT_high_pc : 0xb DW_AT_stmt_list : 0x0 : 缩写编号:2(DW_TAG_subprogram) DW_AT_external : 1 DW_AT_name : (间接字符串,偏移量:0x2c):main DW_AT_decl_file : 1 DW_AT_decl_line : 2 DW_AT_type : DW_AT_low_pc : 0x4004b6 DW_AT_high_pc : 0xb DW_AT_frame_base : 1 字节块:9c (DW_OP_call_frame_cfa) DW_AT_GNU_all_call_sites: 1 : 缩写编号:3(DW_TAG_base_type) DW_AT_byte_size : 4 DW_AT_encoding : 5 (有符号) DW_AT_name : int : 缩写编号:0
每个DW_TAG_compile_unit都包含有关源文件名称和路径的信息,用于查找相关的源文件。
如果您想自己完成所有工作,您应该阅读一些相关部分的DWARF规范,并使用诸如libdw(它是elfutils的一部分)之类的库。

非常感谢,您刚刚为我节省了几天的循环运行时间。@ysdx,新年快乐! - e271p314

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接