Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

extract debug symbol info from elf binary

Tags:

gcc

debugging

gdb

Let's have a look to this basic c program:

#include <stdio.h>

int myadd(int a, int b);

int myadd(int a, int b)
{
    return a+b;
}

int main(int argc, char *argv[])
{
    int res = myadd(argc,3);
    printf("%d\n",res);
    return 0;
}

What i want is to understand how debug symbol files work.

If i compile this way:

gcc test.c 

I can see debug symbols in gdb:

gdb ./a.out
(gdb) disassemble myadd
Dump of assembler code for function myadd:
   0x00000000000006b0 <+0>: push   %rbp

That's fine !

Now, if i run:

gcc -s test.c 

Here what i get in gdb:

(gdb) disassemble myadd
No symbol table is loaded.  Use the "file" command.

That's fine too, because i have stripped symbols with -s gcc option.

Now, i want to "split" my elf executable in 2 files: - A stripped elf executable - an external debug symbol files.

Here what i read in some tutorials:

gcc test.c
objcopy --only-keep-debug a.out a.dbg
strip ./a.out 

But, now, if i want to run gdb, i say to gdb to look inside ./a.dbg for debug symbols

gdb -s ./a.dbg a.out

And gdb cannot resolve myadd function:

(gdb) disassemble myadd
No symbol table is loaded.  Use the "file" command.

And this is what i do not understand: Why gdb does not resolv myadd function?

Thanks

like image 771
Bob5421 Avatar asked Aug 13 '17 09:08

Bob5421


1 Answers

If i compile this way: gcc test.c I can see debug symbols in gdb

You do not see debug symbols here, only the symbol table (which is distinct from debug symbols).

To see debug symbols, compile with gcc -g test.c.

gdb -s a.dbg a.out

The problem here is that when GDB sees "unadorned" a.out, it throws away previously specified symbol file (a.dbg) and replaces it with (fully stripped) a.out. You want:

gdb -s a.dbg -e a.out

Update:

What does mean a "stripped" file: Does it mean this is a file without symbol table or without debuging informations?

On ELF platforms, the state of the file with respect to "strip"-ness is not binary: you can remove individual sections of the file, and depending on exactly what you stripped, your debugging experience will be affected to varying degree.

This command: strip -g a.out removes all .debug_* sections, leaving you without instruction address to source file and line mapping, and without stack address to local variables mapping. However, the symbol table remains in the binary, and can be used to provide instruction address to function name mapping.

This command: strip a.out removes all .debug_* sections, as well as .symtab and .strtab (which together form the symbol table). Such binary is often called "fully stripped".

One could also use obcopy to remove individual sections. It is possible to remove source file/line info (.debug_line section) without removing variable info, and vice versa.

I have tried eu-unstrip ./a.out ./a.dbg but ./a.out result file does not contains debug informations.

You may be hitting a bug in eu-unstrip, perhaps this one.

like image 143
Employed Russian Avatar answered Nov 16 '22 20:11

Employed Russian