链接到 ELF 时,GCC 输出目标文件中的行号未保留
Line numbers in GCC output object file not preserved when linking to ELF
我正在尝试使用符号和关联的行号为 ARM 构建一个基本项目,这样我就可以在 QEMU 运行 中轻松地从 GDB Multiarch 调试该项目。
我有两个文件,一个 C 源文件和一些程序集。在这个例子中,它们非常简单:
cmain.c:
int add_numbers(int a, int b) {
return a + b;
}
int cmain() {
int a = 3;
int b = 4;
int c = add_numbers(a, b);
}
main.s:
.section .init
.global _start
_start:
.extern cmain
mov sp, #0x8000
bl cmain
此外,这是链接器文件,kernel.ld:
SECTIONS {
.init 0x8000 : {
*(.init)
}
.text : {
*(.text)
}
.data : {
*(.data)
*(.bss)
*(.rodata*)
*(.COMMON)
}
/DISCARD/ : {
*(*)
}
}
然后我使用以下 shell 脚本构建带有调试符号的这些项目。简而言之,它将文件组装并编译成目标文件,然后将它们链接到 ELF 中,然后将目标复制到 IMG 中。
rm -r build
mkdir -p build
arm-none-eabi-as -I . main.s -o build/main.o
arm-none-eabi-gcc -ffreestanding -fno-builtin -march=armv7-a -MD -MP -g -c cmain.c -o build/cmain.o
arm-none-eabi-ld build/main.o build/cmain.o -L/usr/lib/gcc/arm-none-eabi/6.3.1/ -lgcc --no-undefined -o build/output.elf -T kernel.ld
arm-none-eabi-objcopy build/output.elf -O binary build/kernel.img --keep-file-symbols
对于 GDB 调试器步进,我需要 ELF 具有 C 源代码的行号。 (请注意,实际项目有更多的 C 文件。)行号存在于 C 目标文件中,但 不是 在 ELF 中。
$ arm-none-eabi-nm build/cmain.o --line-numbers
00000000 T add_numbers /home/aaron/Desktop/arm-mcve/cmain.c:1
00000030 T cmain /home/aaron/Desktop/arm-mcve/cmain.c:5
$ arm-none-eabi-nm build/output.elf --line-numbers
00008008 T add_numbers
00008038 T cmain
00008000 T _start
为什么ELF中没有行号信息,如何添加让GDB单步执行?
您的链接描述文件丢弃了带有调试信息的部分。查看默认链接描述文件 arm-none-eabi-ld --verbose
以获得一些想法。您至少需要一些 DWARF 2 部分:
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
(全部添加应该有效。)
我正在尝试使用符号和关联的行号为 ARM 构建一个基本项目,这样我就可以在 QEMU 运行 中轻松地从 GDB Multiarch 调试该项目。
我有两个文件,一个 C 源文件和一些程序集。在这个例子中,它们非常简单:
cmain.c:
int add_numbers(int a, int b) {
return a + b;
}
int cmain() {
int a = 3;
int b = 4;
int c = add_numbers(a, b);
}
main.s:
.section .init
.global _start
_start:
.extern cmain
mov sp, #0x8000
bl cmain
此外,这是链接器文件,kernel.ld:
SECTIONS {
.init 0x8000 : {
*(.init)
}
.text : {
*(.text)
}
.data : {
*(.data)
*(.bss)
*(.rodata*)
*(.COMMON)
}
/DISCARD/ : {
*(*)
}
}
然后我使用以下 shell 脚本构建带有调试符号的这些项目。简而言之,它将文件组装并编译成目标文件,然后将它们链接到 ELF 中,然后将目标复制到 IMG 中。
rm -r build
mkdir -p build
arm-none-eabi-as -I . main.s -o build/main.o
arm-none-eabi-gcc -ffreestanding -fno-builtin -march=armv7-a -MD -MP -g -c cmain.c -o build/cmain.o
arm-none-eabi-ld build/main.o build/cmain.o -L/usr/lib/gcc/arm-none-eabi/6.3.1/ -lgcc --no-undefined -o build/output.elf -T kernel.ld
arm-none-eabi-objcopy build/output.elf -O binary build/kernel.img --keep-file-symbols
对于 GDB 调试器步进,我需要 ELF 具有 C 源代码的行号。 (请注意,实际项目有更多的 C 文件。)行号存在于 C 目标文件中,但 不是 在 ELF 中。
$ arm-none-eabi-nm build/cmain.o --line-numbers
00000000 T add_numbers /home/aaron/Desktop/arm-mcve/cmain.c:1
00000030 T cmain /home/aaron/Desktop/arm-mcve/cmain.c:5
$ arm-none-eabi-nm build/output.elf --line-numbers
00008008 T add_numbers
00008038 T cmain
00008000 T _start
为什么ELF中没有行号信息,如何添加让GDB单步执行?
您的链接描述文件丢弃了带有调试信息的部分。查看默认链接描述文件 arm-none-eabi-ld --verbose
以获得一些想法。您至少需要一些 DWARF 2 部分:
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
(全部添加应该有效。)