Where does gdb get its lines of code from?
When I compile the program with -g and get a kernel dump, I can use gdb
to read the executable and the main dump to debug the situation the program was running in before it crashed. One of the possibilities gdb
offers the option list
, you can specify the source code that was compiled using an executable file and a core dump. I have used strings -a
with an executable and a core dump and I could not find any statement if
orfor
, while I'm sure there are a lot of them in the code. So where does this code come from? I am compiling the code on one machine and running it on another, so the source code is not available on the machine where the kernel dump is generated and it does not seem to be inside the executable or kernel dump. Any suggestions? I really want to print all the source code from the executable and from the kernel dump, is this possible? I mean without running gdb
, I'm sure it is possible to write a script that uses gdb and that can display all the code, but I am interested in doing it myself without gdb
, because I want to understand from where the source code comes from, how it is formatted, i want to know as much as possible about it.
source to share
The line information is in the .debug_line
DWARF section of the executable:
$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
These sections display the addresses of pointers to pointers to line numbers in the specified file.
To find the contents of a file, you need to find the corresponding source file. If you move / rename the original file, GDB will not be able to print the source code:
mv bla.c bla2.c gdb ./a.out (gdb) break main (gdb) run (gdb) list 1 in bla.c
The .debug_info
DWARF sections have information about the path in which the source file was when it was compiled, which can be used to find the corresponding file:
$ 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
Each DW_TAG_compile_unit
has information about the source file name and the path that is used to find the corresponding source file.
I want to do this myself, you should probably read some relevant parts of the DWARF spec and use a library like libdw (which is part of elfutils ).
source to share