There is special handling to ensure that symbols which look like they are supposed to point at the start of a section are given a size to span that entire section.
GNU ld has special `start_stop` symbols which are automatically provided by the linker for sections where the output section and input section share a name and that name is representable as a C identifier. (see commit cbd0eecf2)
These special symbols represent the start and end address of the output section. These special symbols are used in much the same way in source code as section-start symbols provided by the linker script. Glibc uses these for the __libc_atexit section containing pointers for functions to run at exit.
This change accounts for these `start_stop` symbols by giving them the size of the "remaining" range of the output section in the same way as linker script defined symbols. This means that the `start` symbols get section-spanning bounds and the `stop` symbols get bounds of zero.
N.b. We will have to also account for these symbols in the `resize_sections` function, but that's not done yet.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index a33aea0eab02ac97cb605cac677d8ac27a475967..9a9bd46f4579d6ad1ec0d2a7c8df3b7d7ba1000a 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -6456,6 +6456,15 @@ c64_symbol_section_adjustment (struct elf_link_hash_entry *h, bfd_vma value, } return C64_SYM_LDSCRIPT_DEF; } + + if (h->start_stop) + { + asection *s = h->u2.start_stop_section->output_section; + BFD_ASSERT (s != NULL); + *ret_sec = s; + return C64_SYM_LDSCRIPT_DEF; + } + return C64_SYM_STANDARD; } diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 49b2e70adca947b61294bf1d589ce366b81da569..f0d2048efc37c2df3f4dfea304c7f93f8fe3a169 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -271,6 +271,7 @@ run_dump_test_lp64 "morello-sec-round-include-relro" run_dump_test_lp64 "morello-pcc-bounds-include-readonly" run_dump_test_lp64 "morello-sec-round-choose-linker-syms" run_dump_test_lp64 "morello-entry-point" +run_dump_test_lp64 "morello-sec-start_stop-round" run_dump_test_lp64 "morello-tlsdesc" run_dump_test_lp64 "morello-tlsdesc-static" run_dump_test_lp64 "morello-tlsdesc-staticpie" diff --git a/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.d b/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.d new file mode 100644 index 0000000000000000000000000000000000000000..3987696e5ab864a4ef1f57016eb9a87f2849f8a2 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.d @@ -0,0 +1,26 @@ +#as: -march=morello+c64 +#ld: -static +#objdump: -d -j .data -j __libc_atexit + +.*: file format .* + + +Disassembly of section .data: + +[0-9a-f]+ <__data_start>: +#record: START_LIBC_ADDR +.*: ([0-9a-f]+) .* +.*: 00000000 .* +.*: 00000008 .* +.*: 02000000 .* + +Disassembly of section __libc_atexit: + +# Use `string tolower` because we know we only have a number so it won't change +# anything. That's needed because the current record/check implementation +# doesn't have a way to define a replacement which is just the existing +# variable. +#check: START_LIBC string tolower $START_LIBC_ADDR +00000000START_LIBC <__start___libc_atexit>: +.*: 0000002a .* +.*: 00000000 .* diff --git a/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.s b/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.s new file mode 100644 index 0000000000000000000000000000000000000000..b89273e82460c05cadfd2e3365be671411558e93 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-sec-start_stop-round.s @@ -0,0 +1,10 @@ +.section __libc_atexit,"aw" + .xword 42 +.data +atexit_location: + .chericap __start___libc_atexit +.text +.globl _start +.type _start STT_FUNC +_start: + add c0, c0, :lo12:atexit_location