diff --git a/gas/testsuite/gas/aarch64/eh-frame-symbols.d b/gas/testsuite/gas/aarch64/eh-frame-symbols.d new file mode 100644 index 0000000000000000000000000000000000000000..8276648ea1c5ea1ce7cd945ecfdf952cd71a0911 --- /dev/null +++ b/gas/testsuite/gas/aarch64/eh-frame-symbols.d @@ -0,0 +1,24 @@ +# Checking that our relocations against the symbol __EH_FRAME_BEGIN__ are not +# transformed into relocations against the section symbol .eh_frame. +#as: -march=morello+c64 +#objdump: -dr + +.*: file format .* + + +Disassembly of section \.text: + +.* : + *[0-9a-f]+: ........ stp c29, c30, \[csp, #-64\]! + *[0-9a-f]+: ........ adrp c0, 0 + 4: R_MORELLO_ADR_PREL_PG_HI20 __EH_FRAME_BEGIN__ + *[0-9a-f]+: ........ adrp c0, 0 + 8: R_MORELLO_ADR_PREL_PG_HI20 \.eh_frame + *[0-9a-f]+: ........ add c0, c0, #0x0 + c: R_AARCH64_ADD_ABS_LO12_NC __EH_FRAME_BEGIN__ + *[0-9a-f]+: ........ add c0, c0, #0x0 + 10: R_AARCH64_ADD_ABS_LO12_NC \.eh_frame + *[0-9a-f]+: ........ ldp c29, c30, \[csp\], #64 + *[0-9a-f]+: ........ ret c30 + +#... diff --git a/gas/testsuite/gas/aarch64/eh-frame-symbols.s b/gas/testsuite/gas/aarch64/eh-frame-symbols.s new file mode 100644 index 0000000000000000000000000000000000000000..a10b59e034e15d048c5aef4ee1a82da9acd9e69e --- /dev/null +++ b/gas/testsuite/gas/aarch64/eh-frame-symbols.s @@ -0,0 +1,31 @@ +.section .eh_frame,"a" +.type __EH_FRAME_BEGIN__, %object +__EH_FRAME_BEGIN__: + +.text +.type get_eh_frame_begin, %function +get_eh_frame_begin: + .cfi_startproc purecap + stp c29, c30, [csp, -64]! + .cfi_def_cfa_offset 64 + .cfi_offset 227, -64 + .cfi_offset 228, -48 + adrp c0, __EH_FRAME_BEGIN__ + adrp c0, .eh_frame + add c0, c0, :lo12:__EH_FRAME_BEGIN__ + add c0, c0, :lo12:.eh_frame + ldp c29, c30, [csp], 64 + .cfi_restore 228 + .cfi_restore 227 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc + +.global _start +.type _start, %function +_start: + mov x0, #0 + ret + +# .zero 0xff0 - 0x38 - 0x78 +.zero 0xff0 - 0x38 diff --git a/gas/write.c b/gas/write.c index 054f27987d51f1732afdc81bbc9e19a95160c53f..5301bbd465048208c51f9b12fb6479c765c9a5f4 100644 --- a/gas/write.c +++ b/gas/write.c @@ -878,6 +878,28 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED, continue; } + /* Avoid adjusting a relocation against a symbol pointing into a + ".eh_frame" section in an ELF binary. The GNU bfd linker attempts + to de-duplicate CIE/FDE's in *output* .eh_frame sections in ELF + binaries and adjust any relocations pointing at the now removed + duplicate to point to the remaining entry. + Hence a symbol which had been adjusted to a section symbol plus + offset would end up pointing at something completely different. + + We can not robustly match the exact linker-input sections that will + end up in the .eh_frame output section, since users may provide + their own linker scripts. However it does seem useful to avoid + transforming symbols in the sections that are expected to end up in + this linker output section. Rather than add a clause here to match + the current default linker script we use the same check based on + section name as is used in `gas/dw2gencfi.c` to check for .eh_frame + sections. */ + if (IS_ELF + && strncmp (segment_name (symsec), + ".eh_frame", sizeof ".eh_frame" - 1) == 0 + && segment_name (symsec)[9] != '_') + continue; + /* Never adjust a reloc against local symbol in a merge section with non-zero addend. */ if ((symsec->flags & SEC_MERGE) != 0