PR22471, undefined reference to linker-defined symbols
authorAlan Modra <amodra@gmail.com>
Mon, 27 Nov 2017 03:10:43 +0000 (13:40 +1030)
committerAlan Modra <amodra@gmail.com>
Tue, 28 Nov 2017 12:27:00 +0000 (22:57 +1030)
This patch processes linker script assignment statements before ld
opens DT_NEEDED libraries, in order to define symbols like __bss_start
that might also be defined by a library, falsely triggering an error
about "DSO missing from command line".

The initial value won't be correct when assigning a symbol from dot,
and I make no attempt to handle all expressions.  For example, an
assignment like "_start_foo = ADDR (.foo)" isn't valid until sections
are laid out, so won't define _start_foo early.  What's here should be
enough for most common scripts, and hopefully won't perturb fragile
scripts.

bfd/
PR 22471
* elflink.c (_bfd_elf_merge_symbol): Allow weak symbols to override
early passes over linker script symbols.
* linker.c (_bfd_generic_link_add_one_symbol): Allow symbols to
override early passes over linker script symbols.  Clear ldscript_def
on symbol definitions.
ld/
PR 22471
* ldexp.c (struct definedness_hash_entry): Delete "by_script".  Make
"iteration" an 8-bit field, and update mask in all uses.
(definedness_newfunc): Don't init "by_script".
(update_definedness): Test ldscript_def rather than by_script.
(is_sym_value): Likewise.
(fold_name <DEFINED>): Return a result for first phase.  Test
ldscript_def.
(fold_name <NAME>): Return a result for first phase.
* ldlang.c (open_input_bfds): Process all assignments, not just
defsym.
(lang_process): Increment lang_statement_iteration before
open_input_bfds.
* testsuite/ld-mips-elf/tlsdyn-o32-1.d: Adjust for larger .dynsym.
* testsuite/ld-mips-elf/tlsdyn-o32-1.got: Likewise.
* testsuite/ld-mips-elf/tlsdyn-o32-2.d: Likewise.
* testsuite/ld-mips-elf/tlsdyn-o32-2.got: Likewise.
* testsuite/ld-mips-elf/tlsdyn-o32-3.d: Likewise.
* testsuite/ld-mips-elf/tlsdyn-o32-3.got: Likewise.

12 files changed:
bfd/ChangeLog
bfd/elflink.c
bfd/linker.c
ld/ChangeLog
ld/ldexp.c
ld/ldlang.c
ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got

index dc3aa2f..c9c2407 100644 (file)
@@ -1,5 +1,14 @@
 2017-11-28  Alan Modra  <amodra@gmail.com>
 
+       PR 22471
+       * elflink.c (_bfd_elf_merge_symbol): Allow weak symbols to override
+       early passes over linker script symbols.
+       * linker.c (_bfd_generic_link_add_one_symbol): Allow symbols to
+       override early passes over linker script symbols.  Clear ldscript_def
+       on symbol definitions.
+
+2017-11-28  Alan Modra  <amodra@gmail.com>
+
        * elf64-mmix.c (bfd_elf64_bfd_copy_link_hash_symbol_type): Define.
 
 2017-11-28  H.J. Lu  <hongjiu.lu@intel.com>
index ddd088c..fed7caa 100644 (file)
@@ -1471,10 +1471,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
      treated as strong if the new symbol is from a dynamic library.
      This reflects the way glibc's ld.so works.
 
+     Also allow a weak symbol to override a linker script symbol
+     defined by an early pass over the script.  This is done so the
+     linker knows the symbol is defined in an object file, for the
+     DEFINED script function.
+
      Do this before setting *type_change_ok or *size_change_ok so that
      we warn properly when dynamic library symbols are overridden.  */
 
-  if (newdef && !newdyn && olddyn)
+  if (newdef && !newdyn && (olddyn || h->root.ldscript_def))
     newweak = FALSE;
   if (olddef && newdyn)
     oldweak = FALSE;
index a96c6ed..9c19df4 100644 (file)
@@ -1443,9 +1443,14 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
   do
     {
       enum link_action action;
+      int prev;
 
+      prev = h->type;
+      /* Treat symbols defined by early linker script pass as undefined.  */
+      if (h->ldscript_def)
+       prev = bfd_link_hash_undefined;
       cycle = FALSE;
-      action = link_action[(int) row][(int) h->type];
+      action = link_action[(int) row][prev];
       switch (action)
        {
        case FAIL:
@@ -1489,6 +1494,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
            h->u.def.section = section;
            h->u.def.value = value;
            h->linker_def = 0;
+           h->ldscript_def = 0;
 
            /* If we have been asked to, we act like collect2 and
               identify all functions that might be global
@@ -1588,6 +1594,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info,
          else
            h->u.c.p->section = section;
          h->linker_def = 0;
+         h->ldscript_def = 0;
          break;
 
        case REF:
index 058318d..2b20454 100644 (file)
@@ -1,5 +1,27 @@
 2017-11-28  Alan Modra  <amodra@gmail.com>
 
+       PR 22471
+       * ldexp.c (struct definedness_hash_entry): Delete "by_script".  Make
+       "iteration" an 8-bit field, and update mask in all uses.
+       (definedness_newfunc): Don't init "by_script".
+       (update_definedness): Test ldscript_def rather than by_script.
+       (is_sym_value): Likewise.
+       (fold_name <DEFINED>): Return a result for first phase.  Test
+       ldscript_def.
+       (fold_name <NAME>): Return a result for first phase.
+       * ldlang.c (open_input_bfds): Process all assignments, not just
+       defsym.
+       (lang_process): Increment lang_statement_iteration before
+       open_input_bfds.
+       * testsuite/ld-mips-elf/tlsdyn-o32-1.d: Adjust for larger .dynsym.
+       * testsuite/ld-mips-elf/tlsdyn-o32-1.got: Likewise.
+       * testsuite/ld-mips-elf/tlsdyn-o32-2.d: Likewise.
+       * testsuite/ld-mips-elf/tlsdyn-o32-2.got: Likewise.
+       * testsuite/ld-mips-elf/tlsdyn-o32-3.d: Likewise.
+       * testsuite/ld-mips-elf/tlsdyn-o32-3.got: Likewise.
+
+2017-11-28  Alan Modra  <amodra@gmail.com>
+
        * ldexp.h (struct ldexp_control): Add "assign_src".
        * ldexp.c (fold_trinary): Save and restore assign_src around
        condition evaluation.
index 33ca289..1f1420b 100644 (file)
@@ -60,15 +60,12 @@ struct definedness_hash_entry
      section statement, the section we'd like it relative to.  */
   asection *final_sec;
 
+  /* Low bits of iteration count.  Symbols with matching iteration have
+     been defined in this pass over the script.  */
+  unsigned int iteration : 8;
+
   /* Symbol was defined by an object file.  */
   unsigned int by_object : 1;
-
-  /* Symbols was defined by a script.  */
-  unsigned int by_script : 1;
-
-  /* Low bit of iteration count.  Symbols with matching iteration have
-     been defined in this pass over the script.  */
-  unsigned int iteration : 1;
 };
 
 static struct bfd_hash_table definedness_table;
@@ -286,7 +283,6 @@ definedness_newfunc (struct bfd_hash_entry *entry,
     einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
 
   ret->by_object = 0;
-  ret->by_script = 0;
   ret->iteration = 0;
   return &ret->root;
 }
@@ -320,7 +316,7 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
   /* If the symbol was already defined, and not by a script, then it
      must be defined by an object file or by the linker target code.  */
   ret = TRUE;
-  if (!defentry->by_script
+  if (!h->ldscript_def
       && (h->type == bfd_link_hash_defined
          || h->type == bfd_link_hash_defweak
          || h->type == bfd_link_hash_common))
@@ -332,7 +328,6 @@ update_definedness (const char *name, struct bfd_link_hash_entry *h)
        ret = FALSE;
     }
 
-  defentry->by_script = 1;
   defentry->iteration = lang_statement_iteration;
   defentry->final_sec = bfd_abs_section_ptr;
   if (expld.phase == lang_final_phase_enum
@@ -686,6 +681,9 @@ fold_trinary (etree_type *tree)
 static void
 fold_name (etree_type *tree)
 {
+  struct bfd_link_hash_entry *h;
+  struct definedness_hash_entry *def;
+
   memset (&expld.result, 0, sizeof (expld.result));
 
   switch (tree->type.node_code)
@@ -703,23 +701,18 @@ fold_name (etree_type *tree)
       break;
 
     case DEFINED:
-      if (expld.phase != lang_first_phase_enum)
-       {
-         struct bfd_link_hash_entry *h;
-         struct definedness_hash_entry *def;
-
-         h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
-                                           &link_info,
-                                           tree->name.name,
-                                           FALSE, FALSE, TRUE);
-         new_number (h != NULL
-                     && (h->type == bfd_link_hash_defined
-                         || h->type == bfd_link_hash_defweak
-                         || h->type == bfd_link_hash_common)
-                     && ((def = symbol_defined (tree->name.name)) == NULL
-                         || def->by_object
-                         || def->iteration == (lang_statement_iteration & 1)));
-       }
+      h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+                                       &link_info,
+                                       tree->name.name,
+                                       FALSE, FALSE, TRUE);
+      new_number (h != NULL
+                 && (h->type == bfd_link_hash_defined
+                     || h->type == bfd_link_hash_defweak
+                     || h->type == bfd_link_hash_common)
+                 && (!h->ldscript_def
+                     || (def = symbol_defined (tree->name.name)) == NULL
+                     || def->by_object
+                     || def->iteration == (lang_statement_iteration & 255)));
       break;
 
     case NAME:
@@ -728,9 +721,6 @@ fold_name (etree_type *tree)
        {
          /* Self-assignment is only allowed for absolute symbols
             defined in a linker script.  */
-         struct bfd_link_hash_entry *h;
-         struct definedness_hash_entry *def;
-
          h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
                                            &link_info,
                                            tree->name.name,
@@ -740,17 +730,13 @@ fold_name (etree_type *tree)
                    || h->type == bfd_link_hash_defweak)
                && h->u.def.section == bfd_abs_section_ptr
                && (def = symbol_defined (tree->name.name)) != NULL
-               && def->iteration == (lang_statement_iteration & 1)))
+               && def->iteration == (lang_statement_iteration & 255)))
            expld.assign_name = NULL;
        }
-      if (expld.phase == lang_first_phase_enum)
-       ;
-      else if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
+      if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
        new_rel_from_abs (expld.dot);
       else
        {
-         struct bfd_link_hash_entry *h;
-
          h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
                                            &link_info,
                                            tree->name.name,
@@ -765,7 +751,7 @@ fold_name (etree_type *tree)
              output_section = h->u.def.section->output_section;
              if (output_section == NULL)
                {
-                 if (expld.phase == lang_mark_phase_enum)
+                 if (expld.phase <= lang_mark_phase_enum)
                    new_rel (h->u.def.value, h->u.def.section);
                  else
                    einfo (_("%X%S: unresolvable symbol `%s'"
@@ -957,12 +943,12 @@ is_sym_value (const etree_type *tree, bfd_vma val)
   return (tree->type.node_class == etree_name
          && tree->type.node_code == NAME
          && (def = symbol_defined (tree->name.name)) != NULL
-         && def->by_script
-         && def->iteration == (lang_statement_iteration & 1)
+         && def->iteration == (lang_statement_iteration & 255)
          && (h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
                                                &link_info,
                                                tree->name.name,
                                                FALSE, FALSE, TRUE)) != NULL
+         && h->ldscript_def
          && h->type == bfd_link_hash_defined
          && h->u.def.section == bfd_abs_section_ptr
          && h->u.def.value == val);
index 674004e..bf1b5d3 100644 (file)
@@ -3359,9 +3359,7 @@ open_input_bfds (lang_statement_union_type *s, enum open_bfd_mode mode)
 #endif
          break;
        case lang_assignment_statement_enum:
-         if (s->assignment_statement.exp->type.node_class != etree_assert
-             && s->assignment_statement.exp->assign.defsym)
-           /* This is from a --defsym on the command line.  */
+         if (s->assignment_statement.exp->type.node_class != etree_assert)
            exp_fold_tree_no_dot (s->assignment_statement.exp);
          break;
        default:
@@ -7167,6 +7165,7 @@ lang_process (void)
 
   /* Create a bfd for each input file.  */
   current_target = default_target;
+  lang_statement_iteration++;
   open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
 
 #ifdef ENABLE_PLUGINS
@@ -7222,6 +7221,7 @@ lang_process (void)
 
          /* Rescan archives in case new undefined symbols have appeared.  */
          files = file_chain;
+         lang_statement_iteration++;
          open_input_bfds (statement_list.head, OPEN_BFD_RESCAN);
          lang_list_remove_tail (&file_chain, &files);
          while (files.head != NULL)
index 011df6c..17e42d0 100644 (file)
@@ -5,7 +5,7 @@ Disassembly of section .text:
 
 .* <__start>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7c30        addiu   gp,gp,31792
+  .*:  279c7b80        addiu   gp,gp,31616
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
@@ -55,7 +55,7 @@ Disassembly of section .text:
 
 .* <other>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7b70        addiu   gp,gp,31600
+  .*:  279c7ac0        addiu   gp,gp,31424
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
index 1dbcab4..508fed2 100644 (file)
@@ -13,6 +13,6 @@ OFFSET   TYPE              VALUE
 
 
 Contents of section .got:
- 10000020 00000000 80000000 0040048c 00000000  .........@......
+ 10000020 00000000 80000000 0040053c 00000000  .........@......
  10000030 00000000 00000000 00000000 00000000  ................
  10000040 00000000 00000001 00000000           ............    
index 011df6c..17e42d0 100644 (file)
@@ -5,7 +5,7 @@ Disassembly of section .text:
 
 .* <__start>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7c30        addiu   gp,gp,31792
+  .*:  279c7b80        addiu   gp,gp,31616
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
@@ -55,7 +55,7 @@ Disassembly of section .text:
 
 .* <other>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7b70        addiu   gp,gp,31600
+  .*:  279c7ac0        addiu   gp,gp,31424
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
index fb50635..4a97099 100644 (file)
@@ -13,6 +13,6 @@ OFFSET   TYPE              VALUE
 
 
 Contents of section .got:
- 10000020 00000000 80000000 0040048c 00000000  .*
+ 10000020 00000000 80000000 0040053c 00000000  .*
  10000030 00000000 00000000 00000000 00000000  .*
  10000040 00000000 00000001 00000000           .*
index 3828aca..fb3750a 100644 (file)
@@ -5,7 +5,7 @@ Disassembly of section .text:
 
 .* <other>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7c30        addiu   gp,gp,31792
+  .*:  279c7b80        addiu   gp,gp,31616
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
@@ -51,7 +51,7 @@ Disassembly of section .text:
 
 .* <__start>:
   .*:  3c1c0fc0        lui     gp,0xfc0
-  .*:  279c7b80        addiu   gp,gp,31616
+  .*:  279c7ad0        addiu   gp,gp,31440
   .*:  0399e021        addu    gp,gp,t9
   .*:  27bdfff0        addiu   sp,sp,-16
   .*:  afbe0008        sw      s8,8\(sp\)
index 4a97099..d96375c 100644 (file)
@@ -13,6 +13,6 @@ OFFSET   TYPE              VALUE
 
 
 Contents of section .got:
- 10000020 00000000 80000000 0040053c 00000000  .*
+ 10000020 00000000 80000000 004005ec 00000000  .*
  10000030 00000000 00000000 00000000 00000000  .*
  10000040 00000000 00000001 00000000           .*