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]

mapping of stripped section syms


FDPR sometimes gets confused due to GNU ld's stripping of empty output
sections.  A recent case involved libstdc++.so and an empty
.tm_clone_table where the section symbol happened to be converted to
the .tbss section symbol.  I think it's better that we convert -q
output reloc section symbols the same way fix_syms maps other symbols
in deleted sections.

I'll also be committing another patch that disables stripping of
output sections when -q is in effect, which of course makes this patch
irrelevant.  However, I still think it's worth committing this change
to remove these uses of text_index_section and data_index_section,
sections that have more to do with dynamic relocs than these relocs.

	* linker.c (_bfd_nearby_section): New function, split out from..
	(fix_syms): ..here.
	* bfd-in.h (_bfd_nearby_section): Declare.
	* bfd-in2.h: Regenerate.
	* elflink.c (elf_link_input_bfd): Don't use text_index_section or
	data_index_section with ld -q or ld -r output relocs against
	stripped output sections.  Instead use _bfd_nearby_section.

Index: bfd/linker.c
===================================================================
RCS file: /cvs/src/src/bfd/linker.c,v
retrieving revision 1.92
diff -u -p -r1.92 linker.c
--- bfd/linker.c	13 Feb 2012 18:08:50 -0000	1.92
+++ bfd/linker.c	23 Mar 2012 04:32:15 -0000
@@ -3130,6 +3130,81 @@ _bfd_generic_section_already_linked (bfd
   return FALSE;
 }
 
+/* Choose a neighbouring section to S in OBFD that will be output, or
+   the absolute section if ADDR is out of bounds of the neighbours.  */
+
+asection *
+_bfd_nearby_section (bfd *obfd, asection *s, bfd_vma addr)
+{
+  asection *next, *prev, *best;
+
+  /* Find preceding kept section.  */
+  for (prev = s->prev; prev != NULL; prev = prev->prev)
+    if ((prev->flags & SEC_EXCLUDE) == 0
+	&& !bfd_section_removed_from_list (obfd, prev))
+      break;
+
+  /* Find following kept section.  Start at prev->next because
+     other sections may have been added after S was removed.  */
+  if (s->prev != NULL)
+    next = s->prev->next;
+  else
+    next = s->owner->sections;
+  for (; next != NULL; next = next->next)
+    if ((next->flags & SEC_EXCLUDE) == 0
+	&& !bfd_section_removed_from_list (obfd, next))
+      break;
+
+  /* Choose better of two sections, based on flags.  The idea
+     is to choose a section that will be in the same segment
+     as S would have been if it was kept.  */
+  best = next;
+  if (prev == NULL)
+    {
+      if (next == NULL)
+	best = bfd_abs_section_ptr;
+    }
+  else if (next == NULL)
+    best = prev;
+  else if (((prev->flags ^ next->flags)
+	    & (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_LOAD)) != 0)
+    {
+      if (((next->flags ^ s->flags)
+	   & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0
+	  /* We prefer to choose a loaded section.  Section S
+	     doesn't have SEC_LOAD set (it being excluded, that
+	     part of the flag processing didn't happen) so we
+	     can't compare that flag to those of NEXT and PREV.  */
+	  || ((prev->flags & SEC_LOAD) != 0
+	      && (next->flags & SEC_LOAD) == 0))
+	best = prev;
+    }
+  else if (((prev->flags ^ next->flags) & SEC_READONLY) != 0)
+    {
+      if (((next->flags ^ s->flags) & SEC_READONLY) != 0)
+	best = prev;
+    }
+  else if (((prev->flags ^ next->flags) & SEC_CODE) != 0)
+    {
+      if (((next->flags ^ s->flags) & SEC_CODE) != 0)
+	best = prev;
+    }
+  else
+    {
+      /* Flags we care about are the same.  Prefer the following
+	 section if that will result in a positive valued sym.  */
+      if (addr < next->vma)
+	best = prev;
+    }
+
+  /* Refuse to choose a section for which we are out of bounds.  */
+  /* ??? This may make most of the above moot.  */
+  if (addr < best->vma || addr > best->vma + best->size)
+    best = bfd_abs_section_ptr;
+
+  return best;
+}
+
 /* Convert symbols in excluded output sections to use a kept section.  */
 
 static bfd_boolean
@@ -3146,74 +3221,10 @@ fix_syms (struct bfd_link_hash_entry *h,
 	  && (s->output_section->flags & SEC_EXCLUDE) != 0
 	  && bfd_section_removed_from_list (obfd, s->output_section))
 	{
-	  asection *op, *op1;
+	  asection *op;
 
 	  h->u.def.value += s->output_offset + s->output_section->vma;
-
-	  /* Find preceding kept section.  */
-	  for (op1 = s->output_section->prev; op1 != NULL; op1 = op1->prev)
-	    if ((op1->flags & SEC_EXCLUDE) == 0
-		&& !bfd_section_removed_from_list (obfd, op1))
-	      break;
-
-	  /* Find following kept section.  Start at prev->next because
-	     other sections may have been added after S was removed.  */
-	  if (s->output_section->prev != NULL)
-	    op = s->output_section->prev->next;
-	  else
-	    op = s->output_section->owner->sections;
-	  for (; op != NULL; op = op->next)
-	    if ((op->flags & SEC_EXCLUDE) == 0
-		&& !bfd_section_removed_from_list (obfd, op))
-	      break;
-
-	  /* Choose better of two sections, based on flags.  The idea
-	     is to choose a section that will be in the same segment
-	     as S would have been if it was kept.  */
-	  if (op1 == NULL)
-	    {
-	      if (op == NULL)
-		op = bfd_abs_section_ptr;
-	    }
-	  else if (op == NULL)
-	    op = op1;
-	  else if (((op1->flags ^ op->flags)
-		    & (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_LOAD)) != 0)
-	    {
-	      if (((op->flags ^ s->flags)
-		   & (SEC_ALLOC | SEC_THREAD_LOCAL)) != 0
-		  /* We prefer to choose a loaded section.  Section S
-		     doesn't have SEC_LOAD set (it being excluded, that
-		     part of the flag processing didn't happen) so we
-		     can't compare that flag to those of OP and OP1.  */
-		  || ((op1->flags & SEC_LOAD) != 0
-		      && (op->flags & SEC_LOAD) == 0))
-		op = op1;
-	    }
-	  else if (((op1->flags ^ op->flags) & SEC_READONLY) != 0)
-	    {
-	      if (((op->flags ^ s->flags) & SEC_READONLY) != 0)
-		op = op1;
-	    }
-	  else if (((op1->flags ^ op->flags) & SEC_CODE) != 0)
-	    {
-	      if (((op->flags ^ s->flags) & SEC_CODE) != 0)
-		op = op1;
-	    }
-	  else
-	    {
-	      /* Flags we care about are the same.  Prefer the following
-		 section if that will result in a positive valued sym.  */
-	      if (h->u.def.value < op->vma)
-		op = op1;
-	    }
-
-	  /* Refuse to choose a section for which we are out of bounds.  */
-	  /* ??? This may make most of the above moot.  */
-	  if (h->u.def.value < op->vma
-	      || h->u.def.value > op->vma + op->size)
-	    op = bfd_abs_section_ptr;
-
+	  op = _bfd_nearby_section (obfd, s->output_section, h->u.def.value);
 	  h->u.def.value -= op->vma;
 	  h->u.def.section = op;
 	}
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.159
diff -u -p -r1.159 bfd-in.h
--- bfd/bfd-in.h	24 Oct 2011 11:23:40 -0000	1.159
+++ bfd/bfd-in.h	23 Mar 2012 04:32:00 -0000
@@ -705,6 +705,9 @@ extern int bfd_get_sign_extend_vma
 extern struct bfd_section *_bfd_elf_tls_setup
   (bfd *, struct bfd_link_info *);
 
+extern struct bfd_section *
+_bfd_nearby_section (bfd *, struct bfd_section *, bfd_vma);
+
 extern void _bfd_fix_excluded_sec_syms
   (bfd *, struct bfd_link_info *);
 
Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.433
diff -u -p -r1.433 elflink.c
--- bfd/elflink.c	8 Feb 2012 10:12:20 -0000	1.433
+++ bfd/elflink.c	23 Mar 2012 04:32:11 -0000
@@ -9747,23 +9747,12 @@ elf_link_input_bfd (struct elf_final_lin
 			      r_symndx = osec->target_index;
 			      if (r_symndx == STN_UNDEF)
 				{
-				  struct elf_link_hash_table *htab;
-				  asection *oi;
-
-				  htab = elf_hash_table (finfo->info);
-				  oi = htab->text_index_section;
-				  if ((osec->flags & SEC_READONLY) == 0
-				      && htab->data_index_section != NULL)
-				    oi = htab->data_index_section;
-
-				  if (oi != NULL)
-				    {
-				      irela->r_addend += osec->vma - oi->vma;
-				      r_symndx = oi->target_index;
-				    }
+				  irela->r_addend += osec->vma;
+				  osec = _bfd_nearby_section (output_bfd, osec,
+							      osec->vma);
+				  irela->r_addend -= osec->vma;
+				  r_symndx = osec->target_index;
 				}
-
-			      BFD_ASSERT (r_symndx != STN_UNDEF);
 			    }
 			}
 

-- 
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]