Search code examples
cgccarmgdbdebug-symbols

Line numbers in GCC output object file not preserved when linking to ELF


I am trying to build a basic project for ARM with symbols and associated line numbers, so that I can easily debug the project from GDB Multiarch while it is running in QEMU.

I have two files, a C source file and some assembly. In this example, they are very simple:

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

Additionally, here's the linker file, kernel.ld:

SECTIONS {
    .init 0x8000 : {
        *(.init)
    }

    .text : {
        *(.text)
    }

    .data : {
        *(.data)
        *(.bss)
        *(.rodata*)
        *(.COMMON)
    }

    /DISCARD/ : {
        *(*)
    }
}

I then build these projects with debugging symbols using the following shell script. In brief, it assembles and compiles the files into object files, then links them into an ELF and objcopies into an 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

For GDB debugger stepping, I need the ELF to have line numbers for the C source. (Note that the actual project has many more C files.) The lines numbers are present in C object file, but not in the 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

Why is there no line number information in the ELF, and how can I add it so that GDB can step through it?


Solution

  • Your linker script discards the sections with debugging information. Look at the default linker script arm-none-eabi-ld --verbose for some ideas. You will at least need some of the DWARF 2 sections:

      .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) }
    

    (Adding all of them should work.)