https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104460
Bug ID: 104460 Summary: [RISCV] Incorrect DW_AT_high_pc for assembly source with linker relaxation Product: gcc Version: 11.1.0 URL: https://github.com/riscv-collab/riscv-gnu-toolchain Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: joseph.faulls at imgtec dot com CC: kito.cheng at gmail dot com Target Milestone: --- Target: riscv32-unknown-elf Created attachment 52386 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=52386&action=edit Referenced assembly source When using an assembly source, relocations are not added for DW_AT_high_pc in the DIE, like they are if compiled from a c source. Therefore, there is no fixup for DW_AT_high_pc after linker relaxation, so the value is wrong. In some cases, this causes gdb to be unable to break correctly on code that is placed directly after the code from the assembly source. (I presume) This is because of a mismatch between what the DIE says, and what's actually placed. E.G the DIE says code from the assembly source ranges from 0x0 to 0x60, when in fact it actually goes from 0x0 to 0x30, and the subsequent code from a different source starts at 0x32, causing an overlap/mismatch. This problem can be observed by turning linker relaxation off/on for c/asm sources and looking at the dwarfdump from the resulting elf's. The asm source used in this example is attached and is taken from the newlib crt0.S (just as an example that triggers linker relaxation). The c source here is simply just the asm source wrapped in an __asm__ call. main.c is an empty main function just so something gets placed after. Compilation commands: > riscv32-unknown-elf-gcc myfunc.s -c -o myfunc-asm-no-relax.o -g > -march=rv32imac -mabi=ilp32 -O0 -mno-relax > riscv32-unknown-elf-gcc myfunc.s -c -o myfunc-asm.o -g -march=rv32imac > -mabi=ilp32 -O0 > riscv32-unknown-elf-gcc myfunc.c -c -o myfunc-c-no-relax.o -g -march=rv32imac > -mabi=ilp32 -O0 -mno-relax > riscv32-unknown-elf-gcc myfunc.c -c -o myfunc-c.o -g -march=rv32imac > -mabi=ilp32 -O0 Linking: > riscv32-unknown-elf-gcc myfunc-asm-no-relax.o main.c -o > myfunc-asm-no-relax.elf -march=rv32imac -mabi=ilp32 -nostartfiles -g > riscv32-unknown-elf-gcc myfunc-asm-.o main.c -o myfunc-asm.elf > -march=rv32imac -mabi=ilp32 -nostartfiles -g > riscv32-unknown-elf-gcc myfunc-c-no-relax.o main.c -o myfunc-c-no-relax.elf > -march=rv32imac -mabi=ilp32 -nostartfiles -g > riscv32-unknown-elf-gcc myfunc-c.o main.c -o myfunc-c.elf -march=rv32imac > -mabi=ilp32 -nostartfiles -g Dwarfdumps: (objdump --dwarf) myfunc-c-no-relax.elf > <1a> DW_AT_low_pc : 0x10084 > <1e> DW_AT_high_pc : 0x60 myfunc-c.elf > <1a> DW_AT_low_pc : 0x10084 > <1e> DW_AT_high_pc : 0x3a myfunc-asm-no-relax.elf > <11> DW_AT_low_pc : 0x10084 > <15> DW_AT_high_pc : 82 myfunc-asm.elf > <11> DW_AT_low_pc : 0x10084 > <15> DW_AT_high_pc : 82 I did try and have a crack at fixing this, but got a bit overwhelmed. If anyone can shed some more light on this and give pointers, I could give it another go. LLVM does not have this bug; however, I did notice how it generates the debug information for c/asm sources differently: the .c source uses the AT_high_PC offset with relocations, but the .s source uses an absolute AT_high_PC with a different relocation (I think it was a relocation such that it uses data elsewhere. Maybe the value in .debug_aranges?)