有时候我们需要知道一个*.so文件或者可执行文件是debug版本的还是release版本的,这时我们有哪些方法呢?
readelf -S filename |grep debug
比如:
g++ thread.cpp -o thread_test_nodebug -lpthread
readelf -S thread_test_nodebug
yanyang@ubuntu:~/MyGit/thread$ readelf -S thread_test_nodebug
There are 30 section headers, starting at offset 0x11e0:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000000030 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002c8 000002c8
0000000000000198 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400460 00000460
00000000000001a8 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000400608 00000608
0000000000000022 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400630 00000630
0000000000000060 0000000000000000 A 6 3 8
[ 9] .rela.dyn RELA 0000000000400690 00000690
0000000000000030 0000000000000018 A 5 0 8
[10] .rela.plt RELA 00000000004006c0 000006c0
0000000000000120 0000000000000018 A 5 12 8
[11] .init PROGBITS 00000000004007e0 000007e0
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400800 00000800
00000000000000d0 0000000000000010 AX 0 0 16
[13] .text PROGBITS 00000000004008d0 000008d0
00000000000002f2 0000000000000000 AX 0 0 16
[14] .fini PROGBITS 0000000000400bc4 00000bc4
0000000000000009 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 0000000000400bd0 00000bd0
0000000000000054 0000000000000000 A 0 0 8
[16] .eh_frame_hdr PROGBITS 0000000000400c24 00000c24
000000000000004c 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000400c70 00000c70
000000000000015c 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000600de8 00000de8
0000000000000010 0000000000000000 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000600df8 00000df8
0000000000000008 0000000000000000 WA 0 0 8
[20] .jcr PROGBITS 0000000000600e00 00000e00
0000000000000008 0000000000000000 WA 0 0 8
[21] .dynamic DYNAMIC 0000000000600e08 00000e08
00000000000001f0 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000601000 00001000
0000000000000078 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000601078 00001078
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 00000000006010a0 00001088
0000000000000118 0000000000000000 WA 0 0 32
[26] .comment PROGBITS 0000000000000000 00001088
000000000000004d 0000000000000001 MS 0 0 1
[27] .shstrtab STRTAB 0000000000000000 000010d5
0000000000000108 0000000000000000 0 0 1
[28] .symtab SYMTAB 0000000000000000 00001960
0000000000000768 0000000000000018 29 48 8
[29] .strtab STRTAB 0000000000000000 000020c8
000000000000041e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
yanyang@ubuntu:~/MyGit/thread$ g++ -g thread.cpp -o thread_test_debug -lpthread
yanyang@ubuntu:~/MyGit/thread$ readelf -S thread_test_debug
There are 35 section headers, starting at offset 0x3b20:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
0000000000000030 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002c8 000002c8
0000000000000198 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400460 00000460
00000000000001a8 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000400608 00000608
0000000000000022 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400630 00000630
0000000000000060 0000000000000000 A 6 3 8
[ 9] .rela.dyn RELA 0000000000400690 00000690
0000000000000030 0000000000000018 A 5 0 8
[10] .rela.plt RELA 00000000004006c0 000006c0
0000000000000120 0000000000000018 A 5 12 8
[11] .init PROGBITS 00000000004007e0 000007e0
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 0000000000400800 00000800
00000000000000d0 0000000000000010 AX 0 0 16
[13] .text PROGBITS 00000000004008d0 000008d0
00000000000002f2 0000000000000000 AX 0 0 16
[14] .fini PROGBITS 0000000000400bc4 00000bc4
0000000000000009 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 0000000000400bd0 00000bd0
0000000000000054 0000000000000000 A 0 0 8
[16] .eh_frame_hdr PROGBITS 0000000000400c24 00000c24
000000000000004c 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000400c70 00000c70
000000000000015c 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000600de8 00000de8
0000000000000010 0000000000000000 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000600df8 00000df8
0000000000000008 0000000000000000 WA 0 0 8
[20] .jcr PROGBITS 0000000000600e00 00000e00
0000000000000008 0000000000000000 WA 0 0 8
[21] .dynamic DYNAMIC 0000000000600e08 00000e08
00000000000001f0 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000601000 00001000
0000000000000078 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000601078 00001078
0000000000000010 0000000000000000 WA 0 0 8
[25] .bss NOBITS 00000000006010a0 00001088
0000000000000118 0000000000000000 WA 0 0 32
[26] .comment PROGBITS 0000000000000000 00001088
000000000000004d 0000000000000001 MS 0 0 1
[27] .debug_aranges PROGBITS 0000000000000000 000010d5
0000000000000030 0000000000000000 0 0 1
[28] .debug_info PROGBITS 0000000000000000 00001105
0000000000001608 0000000000000000 0 0 1
[29] .debug_abbrev PROGBITS 0000000000000000 0000270d
00000000000003ef 0000000000000000 0 0 1
[30] .debug_line PROGBITS 0000000000000000 00002afc
0000000000000269 0000000000000000 0 0 1
[31] .debug_str PROGBITS 0000000000000000 00002d65
0000000000000c72 0000000000000001 MS 0 0 1
[32] .shstrtab STRTAB 0000000000000000 000039d7
0000000000000148 0000000000000000 0 0 1
[33] .symtab SYMTAB 0000000000000000 000043e0
00000000000007e0 0000000000000018 34 53 8
[34] .strtab STRTAB 0000000000000000 00004bc0
000000000000041e 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
当然还有另外一种方法来判断就是
yanyang@ubuntu:~/MyGit/thread$ objdump -g thread_test_debug |grep debug
thread_test_debug: file format elf64-x86-64
Contents of the .debug_aranges section:
Offset into .debug_info: 0x0
Contents of the .debug_info section:
<2f1> DW_AT_name : (indirect string, offset: 0xa07): __debug
<11ca> DW_AT_name : (indirect string, offset: 0x521): __gnu_debug
Contents of the .debug_abbrev section:
Raw dump of debug contents of section .debug_line:
7 /usr/include/c++/4.8/debug
17 7 0 0 debug.h
Contents of the .debug_str section:
0x00000520 005f5f67 6e755f64 65627567 00766677 .__gnu_debug.vfw
0x00000a00 725f7479 7065005f 5f646562 75670074 r_type.__debug.t
yanyang@ubuntu:~/MyGit/thread$ objdump -g thread_test_nodebug |grep debug
thread_test_nodebug: file format elf64-x86-64
但是有人说objdump -g 出来的结果也不一定正确,这个有待确定,也是一种尝试的方法吧。
看网上还有人用:readelf --debug-dump=line
yanyang@ubuntu:~/MyGit/thread$ readelf --debug-dump=line thread_test_debug
Raw dump of debug contents of section .debug_line:
Offset: 0x0
Length: 613
DWARF Version: 2
Prologue Length: 525
Minimum Instruction Length: 1
Initial value of 'is_stmt': 1
Line Base: -5
Line Range: 14
Opcode Base: 13
Opcodes:
Opcode 1 has 0 args
Opcode 2 has 1 args
Opcode 3 has 1 args
Opcode 4 has 1 args
Opcode 5 has 1 args
Opcode 6 has 0 args
Opcode 7 has 0 args
Opcode 8 has 0 args
Opcode 9 has 1 args
Opcode 10 has 0 args
Opcode 11 has 0 args
Opcode 12 has 1 args
The Directory Table (offset 0x1b):
1 /usr/include/c++/4.8
2 /usr/include
3 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
4 /usr/include/c++/4.8/bits
5 /usr/include/x86_64-linux-gnu/c++/4.8/bits
6 /usr/include/c++/4.8/ext
7 /usr/include/c++/4.8/debug
8 /usr/include/x86_64-linux-gnu/bits
The File Name Table (offset 0x104):
Entry Dir Time Size Name
1 0 0 0 thread.cpp
2 1 0 0 iostream
3 0 0 0 <built-in>
4 2 0 0 stdio.h
5 3 0 0 stddef.h
6 2 0 0 wchar.h
7 1 0 0 cwchar
8 4 0 0 char_traits.h
9 5 0 0 c++config.h
10 1 0 0 clocale
11 4 0 0 ios_base.h
12 1 0 0 cwctype
13 1 0 0 iosfwd
14 2 0 0 time.h
15 6 0 0 new_allocator.h
16 6 0 0 numeric_traits.h
17 7 0 0 debug.h
18 2 0 0 locale.h
19 8 0 0 types.h
20 5 0 0 atomic_word.h
21 2 0 0 wctype.h
Line Number Statements:
[0x00000217] Extended opcode 2: set Address to 0x4009bd
[0x00000222] Advance Line by 9 to 10
[0x00000224] Copy
[0x00000225] Special opcode 174: advance Address by 12 to 0x4009c9 and Line by 1 to 11
[0x00000226] Special opcode 132: advance Address by 9 to 0x4009d2 and Line by 1 to 12
[0x00000227] Advance PC by 41 to 0x4009fb
[0x00000229] Special opcode 6: advance Address by 0 to 0x4009fb and Line by 1 to 13
[0x0000022a] Special opcode 36: advance Address by 2 to 0x4009fd and Line by 3 to 16
[0x0000022b] Special opcode 134: advance Address by 9 to 0x400a06 and Line by 3 to 19
[0x0000022c] Special opcode 175: advance Address by 12 to 0x400a12 and Line by 2 to 21
[0x0000022d] Special opcode 174: advance Address by 12 to 0x400a1e and Line by 1 to 22
[0x0000022e] Advance PC by 58 to 0x400a58
[0x00000230] Special opcode 6: advance Address by 0 to 0x400a58 and Line by 1 to 23
[0x00000231] Advance PC by 49 to 0x400a89
[0x00000233] Special opcode 7: advance Address by 0 to 0x400a89 and Line by 2 to 25
[0x00000234] Special opcode 91: advance Address by 6 to 0x400a8f and Line by 2 to 27
[0x00000235] Advance Line by -8 to 19
[0x00000237] Advance PC by 41 to 0x400ab8
[0x00000239] Copy
[0x0000023a] Extended opcode 4: set Discriminator to 1
[0x0000023e] Set is_stmt to 0
[0x0000023f] Special opcode 61: advance Address by 4 to 0x400abc and Line by 0 to 19
[0x00000240] Set is_stmt to 1
[0x00000241] Advance Line by 12 to 31
[0x00000243] Special opcode 145: advance Address by 10 to 0x400ac6 and Line by 0 to 31
[0x00000244] Special opcode 132: advance Address by 9 to 0x400acf and Line by 1 to 32
[0x00000245] Advance PC by constant 17 to 0x400ae0
[0x00000246] Special opcode 88: advance Address by 6 to 0x400ae6 and Line by -1 to 31
[0x00000247] Extended opcode 4: set Discriminator to 1
[0x0000024b] Set is_stmt to 0
[0x0000024c] Special opcode 61: advance Address by 4 to 0x400aea and Line by 0 to 31
[0x0000024d] Set is_stmt to 1
[0x0000024e] Special opcode 92: advance Address by 6 to 0x400af0 and Line by 3 to 34
[0x0000024f] Special opcode 173: advance Address by 12 to 0x400afc and Line by 0 to 34
[0x00000250] Special opcode 201: advance Address by 14 to 0x400b0a and Line by 0 to 34
[0x00000251] Extended opcode 4: set Discriminator to 1
[0x00000255] Set is_stmt to 0
[0x00000256] Special opcode 89: advance Address by 6 to 0x400b10 and Line by 0 to 34
[0x00000257] Set File Name to entry 2 in the File Name Table
[0x00000259] Set is_stmt to 1
[0x0000025a] Advance Line by 40 to 74
[0x0000025c] Special opcode 131: advance Address by 9 to 0x400b19 and Line by 0 to 74
[0x0000025d] Set File Name to entry 1 in the File Name Table
[0x0000025f] Advance Line by -40 to 34
[0x00000261] Advance PC by constant 17 to 0x400b2a
[0x00000262] Special opcode 187: advance Address by 13 to 0x400b37 and Line by 0 to 34
[0x00000263] Special opcode 33: advance Address by 2 to 0x400b39 and Line by 0 to 34
[0x00000264] Special opcode 61: advance Address by 4 to 0x400b3d and Line by 0 to 34
[0x00000265] Advance PC by constant 17 to 0x400b4e
[0x00000266] Extended opcode 1: End of Sequence
yanyang@ubuntu:~/MyGit/thread$ readelf --debug-dump=line thread_test_nodebug
没有输出
objdump和readelf功能相似,都可以从二进制文件中读取相应的信息并显示,它们的区别在readelf.c中有相关的说明:
/* The difference between readelf and objdump:
Both programs are capable of displaying the contents of ELF format files,
so why does the binutils project have two file dumpers ?
The reason is that objdump sees an ELF file through a BFD filter of the
world; if BFD has a bug where, say, it disagrees about a machine constant
in e_flags, then the odds are good that it will remain internally
consistent. The linker sees it the BFD way, objdump sees it the BFD way,
GAS sees it the BFD way. There was need for a tool to go find out what
the file actually says.
This is why the readelf program does not link against the BFD library - it
exists as an independent program to help verify the correct working of BFD.
There is also the case that readelf can provide more information about an
ELF file than is provided by objdump. In particular it can display DWARF
debugging information which (at the moment) objdump cannot. */
第一个区别,objdump使用了bfd库进行文件读取,而readelf则没有,另外写的一套代码,且对一些条件的判断并不是很严格。比如对于没有指定处理方式的CPU类型,BFD库将拒绝往下执行,readelf还是可以显示其内容。
第二个区别,readelf可以显示调试信息,而objdump则没有。但是实际上bfd库支持DWARF的处理,通过简单处理objdump也可以显示调试信息,就如同nm做的那样。
有人说用file命令看有没有stripped来判断是否有调试符号,
但是“ stripped ”只是表示这个可执行文件被 strip 过。没有“ stripped “说明这个可执行文件没有被 strip 过,不意味着它编译时包含了额外的调试信息(-g )
所以这种方法不OK。