]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
elf: Strip unreferenced weak undefined symbols
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 18 Apr 2024 12:28:56 +0000 (05:28 -0700)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 19 Apr 2024 02:17:17 +0000 (19:17 -0700)
Linker will resolve an undefined symbol only if it is referenced by
relocation.  Unreferenced weak undefined symbols serve no purpose.
Weak undefined symbols appear in the dynamic symbol table only when they
are referenced by dynamic relocation.  Mark symbols with relocation and
strip undefined weak symbols if they don't have relocation and aren't
in the dynamic symbol table.

bfd/

PR ld/31652
* elf-bfd.h (elf_link_hash_entry): Add has_reloc.
* elf-vxworks.c (elf_vxworks_emit_relocs): Set has_reloc.
* elflink.c (_bfd_elf_link_output_relocs): Likewise.
(elf_link_output_extsym): Strip undefined weak symbols if they
don't have relocation and aren't in the dynamic symbol table.

ld/

PR ld/31652
* testsuite/ld-elf/elf.exp: Run undefweak tests.
* testsuite/ld-elf/undefweak-1.rd: New file.
* testsuite/ld-elf/undefweak-1a.s: Likewise.
* testsuite/ld-elf/undefweak-1b.s: Likewise.
* testsuite/ld-x86-64/weakundef-1.nd: Likewise.
* testsuite/ld-x86-64/weakundef-1a.s: Likewise.
* testsuite/ld-x86-64/weakundef-1b.s: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run undefweak tests.

bfd/elf-bfd.h
bfd/elf-vxworks.c
bfd/elflink.c
ld/testsuite/ld-elf/elf.exp
ld/testsuite/ld-elf/undefweak-1.rd [new file with mode: 0644]
ld/testsuite/ld-elf/undefweak-1a.s [new file with mode: 0644]
ld/testsuite/ld-elf/undefweak-1b.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/weakundef-1.nd [new file with mode: 0644]
ld/testsuite/ld-x86-64/weakundef-1a.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/weakundef-1b.s [new file with mode: 0644]
ld/testsuite/ld-x86-64/x86-64.exp

index ef5dcb55e72827a95252890fae29aa6d46c61a2e..92a0287d40e14d69531edcb8e3cb6ff666526be1 100644 (file)
@@ -232,6 +232,8 @@ struct elf_link_hash_entry
      a strong defined symbol alias.  U.ALIAS points to a list of aliases,
      the definition having is_weakalias clear.  */
   unsigned int is_weakalias : 1;
+  /* Symbol has a relocation.  */
+  unsigned int has_reloc : 1;
 
   /* String table index in .dynstr if this is a dynamic symbol.  */
   unsigned long dynstr_index;
index 4c172cd411539eb884ce2bbcdb75420009be7306..36e5540f9c045ee7860f0e4a65ef450391946edf 100644 (file)
@@ -172,35 +172,39 @@ elf_vxworks_emit_relocs (bfd *output_bfd,
           irela += bed->s->int_rels_per_ext_rel,
             hash_ptr++)
        {
-         if (*hash_ptr
-             && (*hash_ptr)->def_dynamic
-             && !(*hash_ptr)->def_regular
-             && ((*hash_ptr)->root.type == bfd_link_hash_defined
-                 || (*hash_ptr)->root.type == bfd_link_hash_defweak)
-             && (*hash_ptr)->root.u.def.section->output_section != NULL)
+         if (*hash_ptr)
            {
-             /* This is a relocation from an executable or shared
-                library against a symbol in a different shared
-                library.  We are creating a definition in the output
-                file but it does not come from any of our normal (.o)
-                files. ie. a PLT stub.  Normally this would be a
-                relocation against against SHN_UNDEF with the VMA of
-                the PLT stub.  This upsets the VxWorks loader.
-                Convert it to a section-relative relocation.  This
-                gets some other symbols (for instance .dynbss), but
-                is conservatively correct.  */
-             for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+             (*hash_ptr)->has_reloc = 1;
+             if ((*hash_ptr)->def_dynamic
+                 && !(*hash_ptr)->def_regular
+                 && ((*hash_ptr)->root.type == bfd_link_hash_defined
+                     || (*hash_ptr)->root.type == bfd_link_hash_defweak)
+                 && (*hash_ptr)->root.u.def.section->output_section != NULL)
                {
-                 asection *sec = (*hash_ptr)->root.u.def.section;
-                 int this_idx = sec->output_section->target_index;
-
-                 irela[j].r_info
-                   = ELF32_R_INFO (this_idx, ELF32_R_TYPE (irela[j].r_info));
-                 irela[j].r_addend += (*hash_ptr)->root.u.def.value;
-                 irela[j].r_addend += sec->output_offset;
+                 /* This is a relocation from an executable or shared
+                    library against a symbol in a different shared
+                    library.  We are creating a definition in the output
+                    file but it does not come from any of our normal (.o)
+                    files. ie. a PLT stub.  Normally this would be a
+                    relocation against against SHN_UNDEF with the VMA of
+                    the PLT stub.  This upsets the VxWorks loader.
+                    Convert it to a section-relative relocation.  This
+                    gets some other symbols (for instance .dynbss), but
+                    is conservatively correct.  */
+                 for (j = 0; j < bed->s->int_rels_per_ext_rel; j++)
+                   {
+                     asection *sec = (*hash_ptr)->root.u.def.section;
+                     int this_idx = sec->output_section->target_index;
+
+                     irela[j].r_info
+                       = ELF32_R_INFO (this_idx,
+                                       ELF32_R_TYPE (irela[j].r_info));
+                     irela[j].r_addend += (*hash_ptr)->root.u.def.value;
+                     irela[j].r_addend += sec->output_offset;
+                   }
+                 /* Stop the generic routine adjusting this entry.  */
+                 *hash_ptr = NULL;
                }
-             /* Stop the generic routine adjusting this entry.  */
-             *hash_ptr = NULL;
            }
        }
     }
index 9c53bfcf7d4378404c892c0ca0d67755e0258546..4f72d1b2a90d69410bc4283e3336609b48df7456 100644 (file)
@@ -2942,8 +2942,7 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
                             asection *input_section,
                             Elf_Internal_Shdr *input_rel_hdr,
                             Elf_Internal_Rela *internal_relocs,
-                            struct elf_link_hash_entry **rel_hash
-                              ATTRIBUTE_UNUSED)
+                            struct elf_link_hash_entry **rel_hash)
 {
   Elf_Internal_Rela *irela;
   Elf_Internal_Rela *irelaend;
@@ -2986,9 +2985,12 @@ _bfd_elf_link_output_relocs (bfd *output_bfd,
                      * bed->s->int_rels_per_ext_rel);
   while (irela < irelaend)
     {
+      if (*rel_hash)
+       (*rel_hash)->has_reloc = 1;
       (*swap_out) (output_bfd, irela, erel);
       irela += bed->s->int_rels_per_ext_rel;
       erel += input_rel_hdr->sh_entsize;
+      rel_hash++;
     }
 
   /* Bump the counter, so that we know where to add the next set of
@@ -10769,6 +10771,13 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
           && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0)
     strip = true;
 
+  /* Remember if this symbol should be stripped.  */
+  bool should_strip = strip;
+
+  /* Strip undefined weak symbols link if they don't have relocation.  */
+  if (!strip)
+    strip = !h->has_reloc && h->root.type == bfd_link_hash_undefweak;
+
   type = h->type;
 
   /* If we're stripping it, and it's not a dynamic symbol, there's
@@ -10917,6 +10926,10 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
          eoinfo->failed = true;
          return false;
        }
+      /* If a symbol is in the dynamic symbol table and isn't a
+        should-strip symbol, also keep it in the symbol table.  */
+      if (!should_strip)
+       strip = false;
     }
 
   /* If we are marking the symbol as undefined, and there are no
index 685b87588e776514cb7e5ae578abf5667ba86dd3..874ba662d2b6ac93dc22fe69f46a7596589009e5 100644 (file)
@@ -171,6 +171,21 @@ run_ld_link_tests [list \
        "implib" ] \
 ] \[uses_genelf\]
 
+run_ld_link_tests [list \
+    [list "Generate undefweak-1.a" \
+       "" "" \
+       $hpux \
+       {undefweak-1a.s} \
+       {} \
+       "undefweak-1.a" ] \
+    [list "Generate undefweak-1.o" \
+       "-r" "tmpdir/undefweak-1.a" \
+       $hpux \
+       {undefweak-1b.s} \
+       {{readelf {-rsW} undefweak-1.rd}} \
+       "undefweak-1.o" ] \
+] \[uses_genelf\]
+
 #v850 gas complains about .tbss.var section attributes.
 if { [check_gc_sections_available] && ![istarget "v850-*-*"] } {
     run_ld_link_tests {
diff --git a/ld/testsuite/ld-elf/undefweak-1.rd b/ld/testsuite/ld-elf/undefweak-1.rd
new file mode 100644 (file)
index 0000000..5b48c13
--- /dev/null
@@ -0,0 +1,10 @@
+#source: undefweak-1a.s
+#source: undefweak-1b.s
+#as:
+#ld: -r
+#readelf: -sW
+
+#failif
+#...
+.*: 0+ +0 +FUNC +WEAK +DEFAULT +UND +bar
+#pass
diff --git a/ld/testsuite/ld-elf/undefweak-1a.s b/ld/testsuite/ld-elf/undefweak-1a.s
new file mode 100644 (file)
index 0000000..1d885fb
--- /dev/null
@@ -0,0 +1,14 @@
+       .section .text.foobar,"axG",%progbits,foo,comdat
+       .weak foo
+       .type foo,%function
+foo:
+       .nop
+       .size foo, . - foo
+       .weak bar
+       .set bar, foo
+       .text
+       .global baz
+       .type baz,%function
+baz:
+       .dc.a foo
+       .size baz, . - baz
diff --git a/ld/testsuite/ld-elf/undefweak-1b.s b/ld/testsuite/ld-elf/undefweak-1b.s
new file mode 100644 (file)
index 0000000..8ba34ea
--- /dev/null
@@ -0,0 +1,10 @@
+       .section .text.foobar,"axG",%progbits,foo,comdat
+       .weak foo
+       .type foo,%function
+foo:
+       .nop
+       .size foo, . - foo
+       .text
+       .global _start
+       .set _start,foo
+       .dc.a baz
diff --git a/ld/testsuite/ld-x86-64/weakundef-1.nd b/ld/testsuite/ld-x86-64/weakundef-1.nd
new file mode 100644 (file)
index 0000000..c4c89bf
--- /dev/null
@@ -0,0 +1,6 @@
+#nm: -n
+#target: x86_64-*-*
+
+#...
+ +w +bar
+#pass
diff --git a/ld/testsuite/ld-x86-64/weakundef-1a.s b/ld/testsuite/ld-x86-64/weakundef-1a.s
new file mode 100644 (file)
index 0000000..b6eea32
--- /dev/null
@@ -0,0 +1,6 @@
+       .text
+       .global foo
+       .type foo,%function
+foo:
+       .nop
+       .size foo, . - foo
diff --git a/ld/testsuite/ld-x86-64/weakundef-1b.s b/ld/testsuite/ld-x86-64/weakundef-1b.s
new file mode 100644 (file)
index 0000000..3d2da7d
--- /dev/null
@@ -0,0 +1,8 @@
+       .weak bar
+       .text
+       .global _start
+       .type _start,%function
+_start:
+       mov     bar@GOTPCREL(%rip), %rax
+       mov     foo@GOTPCREL(%rip), %rax
+       .size _start, . - _start
index e370f393a7a53194ec60c5a3334e6750f9e7ac25..6546fff4efc49d1691e4790222a4d5358edfbe9e 100644 (file)
@@ -264,6 +264,24 @@ run_ld_link_tests [list \
         {objdump -drj.plt tlsdesc.pd}} \
         "libtlsdesc.so" \
     ] \
+    [list \
+       "Generate x86-64-weakundef-1.so" \
+       "-shared -melf_x86_64" \
+       "" \
+       "--64" \
+       {weakundef-1a.s} \
+       {} \
+       "x86-64-weakundef-1.so" \
+    ] \
+    [list \
+       "Generate x86-64-weakundef-1" \
+       "-melf_x86_64" \
+       "tmpdir/x86-64-weakundef-1.so" \
+       "--64" \
+       {weakundef-1b.s} \
+       {{nm -n weakundef-1.nd}} \
+       "x86-64-weakundef-1" \
+    ] \
 ]
 
 set test_name "Mixed x86_64 and i386 input test 1"