This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] ELF: Don't check DT_NEEDED for linker script defined symbols


On Mon, Nov 27, 2017 at 02:55:55PM +1030, Alan Modra wrote:
> On Mon, Nov 27, 2017 at 07:12:59AM +1030, Alan Modra wrote:
> > We already process some assignments in open_input_bfds to have
> > --defsym symbols defined early, so (3) shouldn't be too hard.
> 
> I'm testing the following.

Well, that failed badly on mmix use of DEFINED.  I'd missed the need
to increment lang_statement_iteration before open_input_bfds, and with
DEFINED not returning values on the first pass ld could trash symbols
defined in object files.  It's also possible for update_definedness to
be missed on one pass, hence the need to track more than one bit of
lang_statement_iteration.


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.

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 99f867d..e0ed135 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -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;
diff --git a/bfd/linker.c b/bfd/linker.c
index a96c6ed..9c19df4 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -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:
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 33ca289..1f1420b 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -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);
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 674004e..bf1b5d3 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
index 011df6c..17e42d0 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
index 1dbcab4..508fed2 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-1.got
@@ -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           ............    
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
index 011df6c..17e42d0 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
index fb50635..4a97099 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-2.got
@@ -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           .*
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
index 3828aca..fb3750a 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.d
@@ -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\)
diff --git a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
index 4a97099..d96375c 100644
--- a/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
+++ b/ld/testsuite/ld-mips-elf/tlsdyn-o32-3.got
@@ -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           .*


-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]