Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

From where does gdb take the code lines?

When I compile a program with -g and get a core dump I can use gdb to read the executable and the core dump to debug the situation the program run into before it crashed. One of the features gdb offers is the list option, it is possible to list the source code which was compiled using the executable and the core dump. I used strings -a with the executable and the core dump and I couldn't find even one if or for statements while I'm sure the code has plenty of them. So where does the code is coming from? I compile the code on one computer and run it on different one, so the source code is not available on the computer where the core dump is generated, and it doesn't seem to be inside the executable or the core dump. Any suggestions? I really want to print all the source code from the executable and from the core dump, is it possible? I mean without running gdb, I'm sure it is possible to write a script which uses gdb and that can list the entire code but I'm interested in doing it myself without gdb because I want to understand from where the source code is taken how it is formatted, I want o know as much as possible about it.

like image 332
e271p314 Avatar asked Dec 31 '14 14:12

e271p314


People also ask

How does GDB work?

GDB allows you to do things like run the program up to a certain point then stop and print out the values of certain variables at that point, or step through the program one line at a time and print out the values of each variable after executing each line. GDB uses a simple command line interface.

How do I run a GDB code?

Run the code by typing “run or r”. If you haven't set any breakpoints, run command will simply execute the full program. 11. To see the value of variable, type “print variable_name or p variable_name“.


1 Answers

The line information is located in the .debug_line DWARF sections 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

This sections maps instruction pointer addresses to line numbers in a given file.

In order to find the content of the file, you need to be able to finds the relevant source file. If you move/rename the source 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 has some information on the path where the source file was when it was compiled which may be used to find the relevant 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 path which is used to find the relevant source file.

I you want to do it all by yourself, you should probably read some relevant parts of the DWARF specifications and use a library such as libdw (which is a part of elfutils).

like image 141
ysdx Avatar answered Sep 30 '22 17:09

ysdx