GNU 工具链调试信息分离和加载:支持 GDB 调试 RELEASE 版本程序
一般地,release版本的程序都不带调试信息,无法使用gdb调试。
GNU 编译工具链和二进制工具链做法如下:
- gcc/g++ 使用 -g 编译得到目标程序:gcc hello.c -g
- objcopy 复制目标程序中的调试信息:objcopy --only-keep-debug a.out a.debug
- strip/objcopy 去除目标程序中的调试信息: strip --strip-unneeded --strip-debug a.out 或者 objcopy --strip-debug a.out
- gdb 调试目标程序时加载分离的调试信息:gdb -s a.debug -e a.out 或着 objcopy --add-gnu-debuglink=a.debug a.out 再 gdb a.out
通过上面图片可以看到,gdb是从 a.debug 中读取的符号信息。
另外,通过 readlef 读取 a.out 和 a.debug 各个段信息如下:
a.out 的段信息:
There are 31 section headers, starting at offset 0x3908:
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 0000000000000318 00000318
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.gnu.propert NOTE 0000000000000338 00000338
0000000000000020 0000000000000000 A 0 0 8
[ 3] .note.gnu.build-i NOTE 0000000000000358 00000358
0000000000000024 0000000000000000 A 0 0 4
[ 4] .note.ABI-tag NOTE 000000000000037c 0000037c
0000000000000020 0000000000000000 A 0 0 4
[ 5] .gnu.hash GNU_HASH 00000000000003a0 000003a0
0000000000000024 0000000000000000 A 6 0 8
[ 6] .dynsym DYNSYM 00000000000003c8 000003c8
00000000000000a8 0000000000000018 A 7 1 8
[ 7] .dynstr STRTAB 0000000000000470 00000470
0000000000000084 0000000000000000 A 0 0 1
[ 8] .gnu.version VERSYM 00000000000004f4 000004f4
000000000000000e 0000000000000002 A 6 0 2
[ 9] .gnu.version_r VERNEED 0000000000000508 00000508
0000000000000020 0000000000000000 A 7 1 8
[10] .rela.dyn RELA 0000000000000528 00000528
00000000000000c0 0000000000000018 A 6 0 8
[11] .rela.plt RELA 00000000000005e8 000005e8
0000000000000018 0000000000000018 AI 6 24 8
[12] .init PROGBITS 0000000000001000 00001000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt PROGBITS 0000000000001020 00001020
0000000000000020 0000000000000010 AX 0 0 16
[14] .plt.got PROGBITS 0000000000001040 00001040
0000000000000010 0000000000000010 AX 0 0 16
[15] .plt.sec PROGBITS 0000000000001050 00001050
0000000000000010 0000000000000010 AX 0 0 16
[16] .text PROGBITS 0000000000001060 00001060
0000000000000225 0000000000000000 AX 0 0 16
[17] .fini PROGBITS 0000000000001288 00001288
000000000000000d 0000000000000000 AX 0 0 4
[18] .rodata PROGBITS 0000000000002000 00002000
0000000000000018 0000000000000000 A 0 0 8
[19] .eh_frame_hdr PROGBITS 0000000000002018 00002018
0000000000000044 0000000000000000 A 0 0 4
[20] .eh_frame PROGBITS 0000000000002060 00002060
0000000000000108 0000000000000000 A 0 0 8
[21] .init_array INIT_ARRAY 0000000000003db8 00002db8
0000000000000008 0000000000000008 WA 0 0 8
[22] .fini_array FINI_ARRAY 0000000000003dc0 00002dc0
0000000000000008 0000000000000008 WA 0 0 8
[23] .dynamic DYNAMIC 0000000000003dc8 00002dc8
00000000000001f0 0000000000000010 WA 7 0 8
[24] .got PROGBITS 0000000000003fb8 00002fb8
0000000000000048 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000004000 00003000
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000004010 00003010
0000000000000008 0000000000000000 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 00003010
000000000000002b 0000000000000001 MS 0 0 1
[28] .symtab SYMTAB 0000000000000000 00003040
00000000000005b8 0000000000000018 29 42 8
[29] .strtab STRTAB 0000000000000000 000035f8
00000000000001f2 0000000000000000 0 0 1
[30] .shstrtab STRTAB 0000000000000000 000037ea
000000000000011a 0000000000000000 0 0 1
a.debug 的段信息:
There are 36 section headers, starting at offset 0x1668:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp NOBITS 0000000000000318 00000318
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.gnu.propert NOTE 0000000000000338 00000338
0000000000000020 0000000000000000 A 0 0 8
[ 3] .note.gnu.build-i NOTE 0000000000000358 00000358
0000000000000024 0000000000000000 A 0 0 4
[ 4] .note.ABI-tag NOTE 000000000000037c 0000037c
0000000000000020 0000000000000000 A 0 0 4
[ 5] .gnu.hash NOBITS 00000000000003a0 0000039c
0000000000000024 0000000000000000 A 6 0 8
[ 6] .dynsym NOBITS 00000000000003c8 0000039c
00000000000000a8 0000000000000018 A 7 1 8
[ 7] .dynstr NOBITS 0000000000000470 0000039c
0000000000000084 0000000000000000 A 0 0 1
[ 8] .gnu.version NOBITS 00000000000004f4 0000039c
000000000000000e 0000000000000002 A 6 0 2
[ 9] .gnu.version_r NOBITS 0000000000000508 0000039c
0000000000000020 0000000000000000 A 7 1 8
[10] .rela.dyn NOBITS 0000000000000528 0000039c
00000000000000c0 0000000000000018 A 6 0 8
[11] .rela.plt NOBITS 00000000000005e8 0000039c
0000000000000018 0000000000000018 A 6 24 8
[12] .init NOBITS 0000000000001000 00001000
000000000000001b 0000000000000000 AX 0 0 4
[13] .plt NOBITS 0000000000001020 00001000
0000000000000020 0000000000000010 AX 0 0 16
[14] .plt.got NOBITS 0000000000001040 00001000
0000000000000010 0000000000000010 AX 0 0 16
[15] .plt.sec NOBITS 0000000000001050 00001000
0000000000000010 0000000000000010 AX 0 0 16
[16] .text NOBITS 0000000000001060 00001000
0000000000000225 0000000000000000 AX 0 0 16
[17] .fini NOBITS 0000000000001288 00001000
000000000000000d 0000000000000000 AX 0 0 4
[18] .rodata NOBITS 0000000000002000 00001000
0000000000000018 0000000000000000 A 0 0 8
[19] .eh_frame_hdr NOBITS 0000000000002018 00001000
0000000000000044 0000000000000000 A 0 0 4
[20] .eh_frame NOBITS 0000000000002060 00001000
0000000000000108 0000000000000000 A 0 0 8
[21] .init_array NOBITS 0000000000003db8 00000db8
0000000000000008 0000000000000008 WA 0 0 8
[22] .fini_array NOBITS 0000000000003dc0 00000db8
0000000000000008 0000000000000008 WA 0 0 8
[23] .dynamic NOBITS 0000000000003dc8 00000db8
00000000000001f0 0000000000000010 WA 7 0 8
[24] .got NOBITS 0000000000003fb8 00000db8
0000000000000048 0000000000000008 WA 0 0 8
[25] .data NOBITS 0000000000004000 00000db8
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000004010 00000db8
0000000000000008 0000000000000000 WA 0 0 1
[27] .comment PROGBITS 0000000000000000 0000039c
000000000000002b 0000000000000001 MS 0 0 1
[28] .debug_aranges PROGBITS 0000000000000000 000003c7
0000000000000030 0000000000000000 0 0 1
[29] .debug_info PROGBITS 0000000000000000 000003f7
000000000000038a 0000000000000000 0 0 1
[30] .debug_abbrev PROGBITS 0000000000000000 00000781
00000000000000e8 0000000000000000 0 0 1
[31] .debug_line PROGBITS 0000000000000000 00000869
0000000000000162 0000000000000000 0 0 1
[32] .debug_str PROGBITS 0000000000000000 000009cb
00000000000002a8 0000000000000001 MS 0 0 1
[33] .symtab SYMTAB 0000000000000000 00000c78
0000000000000690 0000000000000018 34 51 8
[34] .strtab STRTAB 0000000000000000 00001308
0000000000000205 0000000000000000 0 0 1
[35] .shstrtab STRTAB 0000000000000000 0000150d
000000000000015a 0000000000000000 0 0 1
根据二者段信息看见:
- a.out 中不包含调试信息
- a.debug 包含调试信息,并且其他段的属性都为 NOBITS,即没有内容。
这种方式可以借鉴用来版本发布,编译时候带上调试信息,发布的版本去除调试信息,调试时候加载分离式的调试信息。其他芯片公司也可以参考GNU的做法设计编译工具链和二进制工具。
|