当我使用-g编译程序并获得核心转储时,我可以使用gdb
来读取可执行文件和核心转储,以调试程序在崩溃之前遇到的情况。 gdb
提供的功能之一是list
选项,可以列出使用可执行文件和核心转储编译的源代码。我将strings -a
与可执行文件和核心转储一起使用,我甚至找不到一个if
或for
语句,而我确信代码中有很多这些语句。那么代码来自哪里?我在一台计算机上编译代码并在不同的计算机上运行它,因此源代码在生成核心转储的计算机上不可用,并且它似乎不在可执行文件或核心转储中。有什么建议?我真的想从可执行文件和核心转储中打印所有源代码,是否可能?我的意思是在没有运行gdb
的情况下,我确信可以编写一个使用gdb的脚本,并且可以列出整个代码,但我有兴趣在没有gdb
的情况下自行完成因为我想了解源代码在何处被格式化,我希望尽可能多地了解它。
答案 0 :(得分:3)
行信息位于可执行文件的.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: file format elf64-x86-64 ./a.out Contents of the .debug_info section: Compilation Unit @ offset 0x0: Length: 0x4e (32-bit) Version: 4 Abbrev Offset: 0x0 Pointer Size: 8 : Abbrev Number: 1 (DW_TAG_compile_unit) DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.9.1 -mtune=generic -march=x86-64 -g DW_AT_language : 1 (ANSI C) DW_AT_name : (indirect string, offset: 0x59): bla.c DW_AT_comp_dir : (indirect string, offset: 0x31): /home/myself/temp/bla DW_AT_low_pc : 0x4004b6 DW_AT_high_pc : 0xb DW_AT_stmt_list : 0x0 : Abbrev Number: 2 (DW_TAG_subprogram) DW_AT_external : 1 DW_AT_name : (indirect string, offset: 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 byte block: 9c (DW_OP_call_frame_cfa) DW_AT_GNU_all_call_sites: 1 : Abbrev Number: 3 (DW_TAG_base_type) DW_AT_byte_size : 4 DW_AT_encoding : 5 (signed) DW_AT_name : int : Abbrev Number: 0
每个DW_TAG_compile_unit
都有关于源文件名和路径的信息,用于查找相关的源文件。
我想你自己做这一切,你应该阅读DWARF specifications的一些相关部分,并使用libdw这个库(elfutils的一部分)。