]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Account for LSB on DT_INIT/DT_FINI entries
authorMatthew Malcomson <matthew.malcomson@arm.com>
Thu, 28 Apr 2022 08:50:29 +0000 (09:50 +0100)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Thu, 28 Apr 2022 08:52:42 +0000 (09:52 +0100)
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.

bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/morello-dt-init-fini.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dt-init-fini.s [new file with mode: 0644]

index 766d38c52c31e7f368747c89f2922de189b7c0c8..80abb38c6bf6a7b246d6a7371c5d659cf927098f 100644 (file)
@@ -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);
index 17ba4cfee2aa2214bb3e0c3150862d2aa722a395..a65fff67522c1876da6684ad4b4d733b8c88c165 100644 (file)
@@ -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 (file)
index 0000000..d530a28
--- /dev/null
@@ -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 (file)
index 0000000..71a5b64
--- /dev/null
@@ -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