From: Matthew Malcomson Date: Thu, 28 Apr 2022 08:50:29 +0000 (+0100) Subject: Account for LSB on DT_INIT/DT_FINI entries X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fbinutils-gdb.git;a=commitdiff_plain;h=b2cb8a193229c81cd4a1248e011351cb8ecc6ea8 Account for LSB on DT_INIT/DT_FINI entries When DT_INIT and/or DT_FINI point to C64 functions they should have their LSB set. I.e. these entries should contain the address of the relevant functions and not a slight variation on them. This is already done by Morello clang, and we want GNU ld updated to match. Here we account for these LSB's for Morello in the same way as the Arm backend accounts for the Thumb LSB. This is done in the finish_dynamic_sections hook by checking the two dynamic section entries, looking up the relevant functions, and adding that LSB onto the entry value. In our testcase we simply check that the INIT and FINI section entries have the same address as the _init and _fini symbols. --- diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 766d38c52c3..80abb38c6bf 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -11241,6 +11241,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, if (htab->root.dynamic_sections_created) { + const char *name; ElfNN_External_Dyn *dyncon, *dynconend; if (sdyn == NULL || htab->root.sgot == NULL) @@ -11287,6 +11288,27 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, dyn.d_un.d_ptr = s->output_section->vma + s->output_offset + htab->root.tlsdesc_got; break; + + /* Set the bottom bit of DT_INIT/FINI if the + corresponding function is C64. */ + case DT_INIT: + name = info->init_function; + goto get_sym; + case DT_FINI: + name = info->fini_function; +get_sym: + /* If it wasn't set by elf_bfd_final_link + then there is nothing to adjust. */ + if (dyn.d_un.d_val != 0) + { + struct elf_link_hash_entry * eh; + + eh = elf_link_hash_lookup (elf_hash_table (info), name, + FALSE, FALSE, TRUE); + if (eh != NULL) + dyn.d_un.d_val |= eh->target_internal; + } + break; } bfd_elfNN_swap_dyn_out (output_bfd, &dyn, dyncon); diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 17ba4cfee2a..a65fff67522 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -274,6 +274,7 @@ run_dump_test_lp64 "morello-sizeless-got-syms" run_dump_test_lp64 "morello-disallow-merged-binaries" run_dump_test_lp64 "c64-ehdr-sized-reloc" +run_dump_test_lp64 "morello-dt-init-fini" run_dump_test_lp64 "morello-capinit" run_dump_test_lp64 "morello-stubs" run_dump_test_lp64 "morello-stubs-static" diff --git a/ld/testsuite/ld-aarch64/morello-dt-init-fini.d b/ld/testsuite/ld-aarch64/morello-dt-init-fini.d new file mode 100644 index 00000000000..d530a288b66 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-dt-init-fini.d @@ -0,0 +1,23 @@ +# Checking that the DT_INIT and DT_FINI entries in the dynamic section include +# the LSB when referring to functions which include the LSB. +#as: -march=morello+c64 +#ld: -shared +#readelf: --symbols --dynamic --wide + +Dynamic section at offset .* + Tag Type Name/Value +#record: INIT_LOC +#... + 0x000000000000000c \(INIT\) 0x([0-9a-f]+) +#record: FINI_LOC +#... + 0x000000000000000d \(FINI\) 0x([0-9a-f]+) +#... +Symbol table '.symtab' contains 18 entries: + Num: Value Size Type Bind Vis Ndx Name +#check: INIT_ADDR string tolower $INIT_LOC +#check: FINI_ADDR string tolower $FINI_LOC +#... +.*: 0+INIT_ADDR 0 FUNC LOCAL DEFAULT .* _init +.*: 0+FINI_ADDR 0 FUNC LOCAL DEFAULT .* _fini +#pass diff --git a/ld/testsuite/ld-aarch64/morello-dt-init-fini.s b/ld/testsuite/ld-aarch64/morello-dt-init-fini.s new file mode 100644 index 00000000000..71a5b645b91 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-dt-init-fini.s @@ -0,0 +1,13 @@ + .section .init,"ax",%progbits + .global _init + .hidden _init + .type _init, %function +_init: + ret + + .section .fini,"ax",%progbits + .global _fini + .hidden _fini + .type _fini, %function +_fini: + ret