Debugging Tools Intro - DWARF, ELF, GDB:Binutils, Build-Id
Debugging Tools Intro - DWARF, ELF, GDB:Binutils, Build-Id
Agenda
Section 1
Memory debugging tools
valgrind db-attach=yes
--suppressions=/usr/share/doc/python-*/valgrind-python.supp
--num-callers=50
gcc -fstack-protector -O
defaults: rpmbuild yes, gcc no
void f (int i) {
void *p = alloca (i);
memset (p, 0, 0x50); }
int main (void) { f (1); return 0; }
LD PRELOAD=/usr/lib64/libefence.so
ElectricFence
int main (void) {
char *s = malloc (0x10);
s[0x10] = 0;
gcc -lmcheck
enabled system-wide by Fedora debugmode.rpm
char *s = malloc (0x10);
s[0x10] = 0;
free (s);
*******
mudflap violation 1 (check/write): time=1297291147.545274 ptr=0x155bb11 s
pc=0x7ffd94c8ab21 location=`mudflaptest.c:4:8 (f)'
/usr/lib64/libmudflap.so.0(__mf_check+0x41) [0x7ffd94c8ab21]
./mudflaptest(f+0x8a) [0x40095e]
./mudflaptest(main+0xe) [0x40097e]
Nearby object 1: checked region begins 1B after and ends 1B after
mudflap object 0x155bb60: name=`alloca region'
bounds=[0x155bb10,0x155bb10] size=1 area=heap check=0r/0w liveness=0
alloc time=1297291147.545162 pc=0x7ffd94c89ef1
[...]
gdb record
.gdbinit: set record insn-number-max 200000
(gdb) record
(gdb) continue
Continuing.
0x0000000000000000 in ?? ()
(gdb) backtrace
#0 0x0000000000000000 in ?? ()
#1 0x000000000040049b in main () at jumpzero.c:6
(gdb) reverse-stepi
first (secondptr=0) at jumpzero.c:3
3
(*secondptr) ();
(gdb) backtrace
#0 first (secondptr=0) at jumpzero.c:3
#1 0x000000000040049b in main () at jumpzero.c:6
(gdb) _
Section 2
DWARF debug info
ELF
described by /usr/include/elf.h
magic: 00000000
7F 45 4C 46 [...] .ELF[...]
overview: readelf -a binary, objdump -x binary
elfutils: eu-readelf -a binary
ELF sample
readelf -a binary
ELF Header:
Class:
ELF64
Type:
EXEC (Executable file)
Machine:
Advanced Micro Devices X86-64
Entry point address: 0x41aef0
Section Headers:
[Nr] Name
Type
Address
Off
Size
ES Flg
[ 1] .interp
PROGBITS 0000000000400238 000238 00001c 00
A
[13] .plt
PROGBITS 000000000041a280 01a280 000c70 10 AX
[14] .text
PROGBITS 000000000041aef0 01aef0 086268 00 AX
[29] .debug_info PROGBITS 0000000000000000 00c63f 088c33 00
Dynamic section at offset 0xd46d8 contains 26 entries:
Tag
Type
Name/Value
0x0000000000000001 (NEEDED) Shared library: [libtinfo.so.5]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
subprogram
name
decl_file
decl_line
type
low_pc
high_pc
frame_base
sibling
variable
[...]
(strp) "have_minimal_symbols"
(data1) 1
(data2) 997
(ref4) [ 11917]
(addr) 0x486997 <have_minimal_symbols>
(addr) 0x4869da <qsort_cmp>
(block1) [
0] call_frame_cfa
(ref4) [ 1ada7]
DWARF
specification: http://dwarfstd.org
displayed by readelf -w binary
ELF sections .debug_* (like .debug_info)
DWARF versions in use are 2, 3 and 4
gcc debug info level 3 provides macro information
gcc -g2 or -g3 specify debug info level, not DWARF version
rpmbuild uses -g, that is like -g2 (level 2)
OS
file format
GNU/Linux
GNU/Linux
Apple OSX
MS-Windows
MinGW32
ELF
ELF
Mach-O
PE32
PE32
DWARF
STABS
DWARF
PDB
DWARF
STABS
DWARF parsing
elfutils-libs
libdwarf
gdb dwarf2read.c
readelf -w / eu-readelf -w
no runtime overhead
(only .dynsym has runtime overhead)
neither separate (/usr/lib/debug/) nor in-file debug info
debug info is never mapped to memory
debug info sections are not covered by segments at all
DWARF sections
Section 3
Unwinding using .eh frame
push
mov
%rbp
%rsp,%rbp
leaveq
retq
push
mov
%rbp
%rsp,%rbp
leaveq
retq
retq
.eh frame
0000000000000000 <functionname>:
0:
48 83 ec 18
sub $24,%rsp
4:
c7 44 24 0c 00 00 00 00 movl $0,0xc(%rsp)
Section 4
Unique binaries identification by build-id
build-id
uniquely generated for each linked executable / shared library
eu-readelf -n file
Owner
Data size Type
GNU
20 GNU_BUILD_ID
Build ID: d48a....c8d1
/usr/lib/debug/.build-id/d4/8a....c8d1
../../../../../bin/bash = /bin/bash
/usr/lib/debug/.build-id/d4/8a....c8d1.debug
../../bin/bash.debug = /usr/lib/debug/bin/bash.debug
both symlinks are only in *-debuginfo-*.rpm
The end.
Thanks for listening.