complex relocations and mep backend

Alan Modra amodra@bigpond.net.au
Sun Sep 30 14:12:00 GMT 2007


This started off as a patch to speed the linker a little by merging
evaluate_complex_relocation_symbols into the existing loop that checks
for relocs against symbols in discarded sections.  Next, I took a look
at bfd_elf_perform_complex_relocation and decided a better interface
would avoid some code duplication.  From there it turned into a
wholesale review of the complex reloc and mep backend code.

I've interspersed some comments in the ChangeLog entry.

bfd/
	* elflink.c (resolve_symbol): Handle symbols in SEC_MERGE
	sections.  Don't test symbol st_shndx.  Don't bother with

Testing st_shndx isn't needed in any other code calculating a
relocation value for local syms.  See BFD_FAKE_SECTION for why
this is so.  Besides, the test ignored the possibility of >64k
sections.

	bfd_link_hash_common symbols.  Print longs rather than ints

Commons have been converted to normal symbols by this stage.

	in debug messages.
	(eval_symbol): Replace "sym" and "advanced" params with "symp".
	Replace "addr" and "section_offset" params with "dot".  Don't
	cast bfd_vma values to signed, cast them to bfd_signed_vma.
	(bfd_elf_perform_complex_relocation): Delete "output_bfd", "info",
	"local_syms" and "local_sections" params.  Add "relocation".
	Delete code calculating relocation value.

I'm still not at all happy with bfd_elf_perform_complex_relocation,
but perhaps that's because I don't understand what chunksz and wordsz
are supposed to do.  It looks suspicously like get_value and put_value
are broken for big-endian targets.  Some possible values of chunksz
and wordsz will cause get_value to never terminate, some will cause
segfaults, and others will overflow a bfd_vma return value.  Would
someone please add some validity checks?

	(evaluate_complex_relocation_symbols): Delete function.  Fold into..
	(elf_link_input_bfd): ..existing code examining relocs.
	* elf-bfd.h (bfd_elf_perform_complex_relocation): Update prototype.
	* elf32-mep.c (mep_elf_check_relocs): Delete function.

Doesn't do anything.

	(mep_elf_gc_sweep_hook, mep_elf_gc_mark_hook): Likewise.

Doesn't do anything substantially different from the generic function,
and what it does different is plain wrong.

	(mep_elf_object_p): Don't set elf_bad_symtab.

Seems to be necessary only because no one bothered to fix bugs
elsewhere in the complex reloc support.

	(elf_backend_check_relocs): Don't define.
	(elf_backend_gc_mark_hook, elf_backend_gc_sweep_hook): Likewise.
	(elf_backend_can_gc_sections, USE_RELA): Likwise.

I turned off can_gc_sections because no support exists for marking
sections of symbols in complex relocations.  I'm willing to concede
that it could be turned back on so that --gc-sections works just for
"normal" relocations, but it would be much better if someone who cares
about MEP fixed this properly.

	(mep_elf_relocate_section): Move bfd_elf_perform_complex_relocation
	call after we have calculated reloc value.  Delete local sym
	debug code.  Use RELOC_FOR_GLOBAL_SYMBOL.  Delete addend
	adjusting code..
	(elf_backend_rela_normal): ..instead define this.

ld/testsuite/
	* ld-selective/sel-dump.exp: Add am33, m88k, mep to xfails.
	* ld-selective/selective.exp: Don't run for same target list
	we xfail sel-dump.

Index: bfd/elflink.c
===================================================================
RCS file: /cvs/src/src/bfd/elflink.c,v
retrieving revision 1.279
diff -u -p -r1.279 elflink.c
--- bfd/elflink.c	26 Sep 2007 12:29:41 -0000	1.279
+++ bfd/elflink.c	29 Sep 2007 13:15:52 -0000
@@ -7281,7 +7281,6 @@ resolve_symbol (const char *            
   struct bfd_link_hash_entry *  global_entry;
   const char *                  candidate = NULL;
   Elf_Internal_Shdr *           symtab_hdr;
-  asection *                    sec = NULL;
   size_t                        i;
   
   symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
@@ -7289,7 +7288,6 @@ resolve_symbol (const char *            
   for (i = 0; i < locsymcount; ++ i)
     {
       sym = isymbuf + i;
-      sec = finfo->sections [i];
 
       if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
 	continue;
@@ -7298,26 +7296,18 @@ resolve_symbol (const char *            
 						   symtab_hdr->sh_link,
 						   sym->st_name);
 #ifdef DEBUG
-      printf ("Comparing string: '%s' vs. '%s' = 0x%x\n", 
-	      name, candidate, (unsigned int)sym->st_value);
+      printf ("Comparing string: '%s' vs. '%s' = 0x%lx\n",
+	      name, candidate, (unsigned long) sym->st_value);
 #endif
       if (candidate && strcmp (candidate, name) == 0)
 	{
-	  * result = sym->st_value;
+	  asection *sec = finfo->sections [i];
 
-	  if (sym->st_shndx > SHN_UNDEF && 
-	      sym->st_shndx < SHN_LORESERVE)
-	    {
-#ifdef DEBUG
-	      printf ("adjusting for sec '%s' @ 0x%x + 0x%x\n",
-		      sec->output_section->name, 
-		      (unsigned int)sec->output_section->vma, 
-		      (unsigned int)sec->output_offset);
-#endif
-	      * result += sec->output_offset + sec->output_section->vma;
-	    }
+	  *result = _bfd_elf_rel_local_sym (input_bfd, sym, &sec, 0);
+	  *result += sec->output_offset + sec->output_section->vma;
 #ifdef DEBUG
-	  printf ("Found symbol with effective value %8.8x\n", (unsigned int)* result);
+	  printf ("Found symbol with value %8.8lx\n",
+		  (unsigned long) *result);
 #endif
 	  return TRUE;
 	}
@@ -7335,24 +7325,12 @@ resolve_symbol (const char *            
 	+ global_entry->u.def.section->output_section->vma 
 	+ global_entry->u.def.section->output_offset;
 #ifdef DEBUG
-      printf ("Found GLOBAL symbol '%s' with value %8.8x\n",
-	      global_entry->root.string, (unsigned int)*result);
+      printf ("Found GLOBAL symbol '%s' with value %8.8lx\n",
+	      global_entry->root.string, (unsigned long) *result);
 #endif
       return TRUE;
     } 
 
-  if (global_entry->type == bfd_link_hash_common)
-    {
-      *result = global_entry->u.def.value +
-	bfd_com_section_ptr->output_section->vma +
-	bfd_com_section_ptr->output_offset;
-#ifdef DEBUG
-      printf ("Found COMMON symbol '%s' with value %8.8x\n",
-	      global_entry->root.string, (unsigned int)*result);
-#endif
-      return TRUE;
-    }
-  
   return FALSE;
 }
 
@@ -7402,12 +7380,10 @@ undefined_reference (const char *  refty
 
 static bfd_boolean
 eval_symbol (bfd_vma *                     result,
-	     char *                        sym,
-	     char **                       advanced,
+	     const char **                 symp,
 	     bfd *                         input_bfd,
 	     struct elf_final_link_info *  finfo,
-	     bfd_vma                       addr,
-	     bfd_vma                       section_offset,
+	     bfd_vma                       dot,
 	     Elf_Internal_Sym *            isymbuf,
 	     size_t                        locsymcount,
 	     int                           signed_p)
@@ -7418,6 +7394,7 @@ eval_symbol (bfd_vma *                  
   bfd_vma       b;
   const int     bufsz = 4096;
   char          symbuf [bufsz];
+  const char *sym = *symp;
   const char *  symend;
   bfd_boolean   symbol_is_section = FALSE;
 
@@ -7433,21 +7410,21 @@ eval_symbol (bfd_vma *                  
   switch (* sym)
     {
     case '.':
-      * result = addr + section_offset;
-      * advanced = sym + 1;
+      *result = dot;
+      *symp = sym + 1;
       return TRUE;
 
     case '#':
-      ++ sym;
-      * result = strtoul (sym, advanced, 16);
+      ++sym;
+      *result = strtoul (sym, (char **) symp, 16);
       return TRUE;
 
     case 'S':
       symbol_is_section = TRUE;
     case 's':      
-      ++ sym;
-      symlen = strtol (sym, &sym, 10);
-      ++ sym; /* Skip the trailing ':'.  */
+      ++sym;
+      symlen = strtol (sym, (char **) symp, 10);
+      sym = *symp + 1; /* Skip the trailing ':'.  */
 
       if ((symend < sym) || ((symlen + 1) > bufsz))
 	{
@@ -7457,7 +7434,7 @@ eval_symbol (bfd_vma *                  
 
       memcpy (symbuf, sym, symlen);
       symbuf [symlen] = '\0';
-      * advanced = sym + symlen;
+      *symp = sym + symlen;
       
       /* Is it always possible, with complex symbols, that gas "mis-guessed" 
 	 the symbol as a section, or vice-versa. so we're pretty liberal in our
@@ -7496,15 +7473,14 @@ eval_symbol (bfd_vma *                  
       sym += strlen (#op);					\
       if (* sym == ':')						\
         ++ sym;							\
-      if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr,	\
-			section_offset, isymbuf, locsymcount,	\
-			signed_p))				\
+      *symp = sym;						\
+      if (!eval_symbol (&a, symp, input_bfd, finfo, dot,	\
+			isymbuf, locsymcount, signed_p))	\
         return FALSE;						\
       if (signed_p)                                             \
-        * result = op ((signed)a);         			\
+	*result = op ((bfd_signed_vma) a);			\
       else                                                      \
         * result = op a;                                        \
-      * advanced = sym; 					\
       return TRUE;						\
     }
 
@@ -7514,20 +7490,18 @@ eval_symbol (bfd_vma *                  
       sym += strlen (#op);					\
       if (* sym == ':')						\
         ++ sym;							\
-      if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr,	\
-			section_offset, isymbuf, locsymcount,	\
-			signed_p))				\
+      *symp = sym;						\
+      if (!eval_symbol (&a, symp, input_bfd, finfo, dot,	\
+			isymbuf, locsymcount, signed_p))	\
         return FALSE;						\
-      ++ sym;							\
-      if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr,	\
-			section_offset, isymbuf, locsymcount,	\
-			signed_p))				\
+      ++*symp;							\
+      if (!eval_symbol (&b, symp, input_bfd, finfo, dot,	\
+			isymbuf, locsymcount, signed_p))	\
         return FALSE;						\
       if (signed_p)                                             \
-        * result = ((signed) a) op ((signed) b);	        \
+	*result = ((bfd_signed_vma) a) op ((bfd_signed_vma) b);	\
       else                                                      \
         * result = a op b;                                      \
-      * advanced = sym;						\
       return TRUE;						\
     }
 
@@ -7561,141 +7535,6 @@ eval_symbol (bfd_vma *                  
     }
 }
 
-/* Entry point to evaluator, called from elf_link_input_bfd.  */
-
-static bfd_boolean
-evaluate_complex_relocation_symbols (bfd *input_bfd,
-				     struct elf_final_link_info *finfo,
-				     Elf_Internal_Sym *isymbuf,
-				     size_t locsymcount)
-{
-  const struct elf_backend_data * bed;
-  Elf_Internal_Shdr *             symtab_hdr;
-  struct elf_link_hash_entry **   sym_hashes;
-  asection *                      reloc_sec;
-  bfd_boolean                     result = TRUE;
-
-  /* For each section, we're going to check and see if it has any
-     complex relocations, and we're going to evaluate any of them
-     we can.  */
-
-  if (finfo->info->relocatable)
-    return TRUE;
-
-  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
-  sym_hashes = elf_sym_hashes (input_bfd);
-  bed = get_elf_backend_data (input_bfd);
-
-  for (reloc_sec = input_bfd->sections; reloc_sec; reloc_sec = reloc_sec->next)
-    {
-      Elf_Internal_Rela * internal_relocs;
-      unsigned long i;
-
-      /* This section was omitted from the link.  */
-      if (! reloc_sec->linker_mark)
-	continue;
-
-      /* Only process sections containing relocs.  */
-      if ((reloc_sec->flags & SEC_RELOC) == 0)
-	continue;
-
-      if (reloc_sec->reloc_count == 0)
-	continue;
-
-      /* Read in the relocs for this section.  */
-      internal_relocs
-	= _bfd_elf_link_read_relocs (input_bfd, reloc_sec, NULL,
-				     (Elf_Internal_Rela *) NULL,
-				     FALSE);
-      if (internal_relocs == NULL)
-	continue;
-
-      for (i = reloc_sec->reloc_count; i--;)
-	{
-	  Elf_Internal_Rela * rel;
-	  char * sym_name;
-	  bfd_vma index;
-	  Elf_Internal_Sym * sym;
-	  bfd_vma result;
-	  bfd_vma section_offset;
-	  bfd_vma addr;
-	  int signed_p = 0;
-
-	  rel = internal_relocs + i;
-	  section_offset = reloc_sec->output_section->vma
-	    + reloc_sec->output_offset;
-	  addr = rel->r_offset;
-
-	  index = ELF32_R_SYM (rel->r_info);
-	  if (bed->s->arch_size == 64)
-	    index >>= 24;
-
-	  if (index == STN_UNDEF)
-	    continue;
-
-	  if (index < locsymcount)
-	    {
-	      /* The symbol is local.  */
-	      sym = isymbuf + index;
-
-	      /* We're only processing STT_RELC or STT_SRELC type symbols.  */
-	      if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
-		  (ELF_ST_TYPE (sym->st_info) != STT_SRELC))
-		continue;
-
-	      sym_name = bfd_elf_string_from_elf_section
-		(input_bfd, symtab_hdr->sh_link, sym->st_name);
-
-	      signed_p = (ELF_ST_TYPE (sym->st_info) == STT_SRELC);
-	    }
-	  else
-	    {
-	      /* The symbol is global.  */
-	      struct elf_link_hash_entry * h;
-
-	      if (elf_bad_symtab (input_bfd))
-		continue;
-
-	      h = sym_hashes [index - locsymcount];
-	      while (   h->root.type == bfd_link_hash_indirect
-		     || h->root.type == bfd_link_hash_warning)
-		h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-	      if (h->type != STT_RELC && h->type != STT_SRELC)
-		continue;
-
-	      signed_p = (h->type == STT_SRELC);
-	      sym_name = (char *) h->root.root.string;
-	    }
-#ifdef DEBUG
-	  printf ("Encountered a complex symbol!");
-	  printf (" (input_bfd %s, section %s, reloc %ld\n",
-		  input_bfd->filename, reloc_sec->name, i);
-	  printf (" symbol: idx  %8.8lx, name %s\n",
-		  index, sym_name);
-	  printf (" reloc : info %8.8lx, addr %8.8lx\n",
-		  rel->r_info, addr);
-	  printf (" Evaluating '%s' ...\n ", sym_name);
-#endif
-	  if (eval_symbol (& result, sym_name, & sym_name, input_bfd, 
-			   finfo, addr, section_offset, isymbuf, locsymcount,
-			   signed_p))
-	    /* Symbol evaluated OK.  Update to absolute value.  */
-	    set_symbol_value (input_bfd, isymbuf, locsymcount, index, result);
-
-	  else
-	    result = FALSE;
-	}
-
-      if (internal_relocs != elf_section_data (reloc_sec)->relocs)
-	free (internal_relocs);
-    }
-
-  /* If nothing went wrong, then we adjusted 
-     everything we wanted to adjust.  */
-  return result;
-}
-
 static void
 put_value (bfd_vma        size,
 	   unsigned long  chunksz,
@@ -7791,84 +7630,20 @@ decode_complex_addend
 }
 
 void
-bfd_elf_perform_complex_relocation
-    (bfd *                   output_bfd ATTRIBUTE_UNUSED,
-     struct bfd_link_info *  info,
-     bfd *                   input_bfd,
-     asection *              input_section,
-     bfd_byte *              contents,
-     Elf_Internal_Rela *     rel,
-     Elf_Internal_Sym *      local_syms,
-     asection **             local_sections)
-{
-  const struct elf_backend_data * bed;
-  Elf_Internal_Shdr * symtab_hdr;
-  asection * sec;
-  bfd_vma relocation = 0, shift, x;
-  bfd_vma r_symndx;
-  bfd_vma mask;
-  unsigned long start, oplen, len, wordsz, 
-    chunksz, lsb0_p, signed_p, trunc_p;
+bfd_elf_perform_complex_relocation (bfd *input_bfd,
+				    asection *input_section,
+				    bfd_byte *contents,
+				    Elf_Internal_Rela *rel,
+				    bfd_vma relocation)
+{
+  bfd_vma shift, x, mask;
+  unsigned long start, oplen, len, wordsz, chunksz, lsb0_p, signed_p, trunc_p;
 
   /*  Perform this reloc, since it is complex.
       (this is not to say that it necessarily refers to a complex
       symbol; merely that it is a self-describing CGEN based reloc.
       i.e. the addend has the complete reloc information (bit start, end,
       word size, etc) encoded within it.).  */ 
-  r_symndx = ELF32_R_SYM (rel->r_info);
-  bed = get_elf_backend_data (input_bfd);
-  if (bed->s->arch_size == 64)
-    r_symndx >>= 24;
-
-#ifdef DEBUG
-  printf ("Performing complex relocation %ld...\n", r_symndx);
-#endif
-
-  symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
-  if (r_symndx < symtab_hdr->sh_info)
-    {
-      /* The symbol is local.  */
-      Elf_Internal_Sym * sym;
-
-      sym = local_syms + r_symndx;
-      sec = local_sections [r_symndx];
-      relocation = sym->st_value;
-      if (sym->st_shndx > SHN_UNDEF && 
-	  sym->st_shndx < SHN_LORESERVE)
-	relocation += (sec->output_offset +
-		       sec->output_section->vma);
-    }
-  else
-    {
-      /* The symbol is global.  */
-      struct elf_link_hash_entry **sym_hashes;
-      struct elf_link_hash_entry * h;
-
-      sym_hashes = elf_sym_hashes (input_bfd);
-      h = sym_hashes [r_symndx];
-
-      while (h->root.type == bfd_link_hash_indirect
-	     || h->root.type == bfd_link_hash_warning)
-	h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-      if (h->root.type == bfd_link_hash_defined
-	  || h->root.type == bfd_link_hash_defweak)
-	{
-	  sec = h->root.u.def.section;
-	  relocation = h->root.u.def.value;
-
-	  if (! bfd_is_abs_section (sec))
-	    relocation += (sec->output_section->vma 
-			   + sec->output_offset); 
-	}
-      if (h->root.type == bfd_link_hash_undefined
-	  && !((*info->callbacks->undefined_symbol)
-	       (info, h->root.root.string, input_bfd,
-		input_section, rel->r_offset,
-		info->unresolved_syms_in_objects == RM_GENERATE_ERROR
-		|| ELF_ST_VISIBILITY (h->other))))
-	return;
-    }
 
   decode_complex_addend (& start, & oplen, & len, & wordsz, 
 			 & chunksz, & lsb0_p, & signed_p, 
@@ -9213,10 +8988,6 @@ elf_link_input_bfd (struct elf_final_lin
 	return FALSE;
     }
 
-  if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf,
-					     locsymcount))
-    return FALSE;
-
   /* Relocate the contents of each section.  */
   sym_hashes = elf_sym_hashes (input_bfd);
   for (o = input_bfd->sections; o != NULL; o = o->next)
@@ -9258,8 +9029,10 @@ elf_link_input_bfd (struct elf_final_lin
       if ((o->flags & SEC_RELOC) != 0)
 	{
 	  Elf_Internal_Rela *internal_relocs;
+	  Elf_Internal_Rela *rel, *relend;
 	  bfd_vma r_type_mask;
 	  int r_sym_shift;
+	  int action_discarded;
 	  int ret;
 
 	  /* Get the swapped relocs.  */
@@ -9281,76 +9054,107 @@ elf_link_input_bfd (struct elf_final_lin
 	      r_sym_shift = 32;
 	    }
 
-	  /* Run through the relocs looking for any against symbols
-	     from discarded sections and section symbols from
-	     removed link-once sections.  Complain about relocs
-	     against discarded sections.  Zero relocs against removed
-	     link-once sections.  */
+	  action_discarded = -1;
 	  if (!elf_section_ignore_discarded_relocs (o))
-	    {
-	      Elf_Internal_Rela *rel, *relend;
-	      unsigned int action = (*bed->action_discarded) (o);
+	    action_discarded = (*bed->action_discarded) (o);
 
-	      rel = internal_relocs;
-	      relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
-	      for ( ; rel < relend; rel++)
-		{
-		  unsigned long r_symndx = rel->r_info >> r_sym_shift;
-		  asection **ps, *sec;
-		  struct elf_link_hash_entry *h = NULL;
-		  const char *sym_name;
+	  /* Run through the relocs evaluating complex reloc symbols and
+	     looking for relocs against symbols from discarded sections
+	     or section symbols from removed link-once sections.
+	     Complain about relocs against discarded sections.  Zero
+	     relocs against removed link-once sections.  */
+
+	  rel = internal_relocs;
+	  relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
+	  for ( ; rel < relend; rel++)
+	    {
+	      unsigned long r_symndx = rel->r_info >> r_sym_shift;
+	      unsigned int s_type;
+	      asection **ps, *sec;
+	      struct elf_link_hash_entry *h = NULL;
+	      const char *sym_name;
 
-		  if (r_symndx == STN_UNDEF)
-		    continue;
+	      if (r_symndx == STN_UNDEF)
+		continue;
 
-		  if (r_symndx >= locsymcount
-		      || (elf_bad_symtab (input_bfd)
-			  && finfo->sections[r_symndx] == NULL))
+	      if (r_symndx >= locsymcount
+		  || (elf_bad_symtab (input_bfd)
+		      && finfo->sections[r_symndx] == NULL))
+		{
+		  h = sym_hashes[r_symndx - extsymoff];
+
+		  /* Badly formatted input files can contain relocs that
+		     reference non-existant symbols.  Check here so that
+		     we do not seg fault.  */
+		  if (h == NULL)
 		    {
-		      h = sym_hashes[r_symndx - extsymoff];
+		      char buffer [32];
 
-		      /* Badly formatted input files can contain relocs that
-			 reference non-existant symbols.  Check here so that
-			 we do not seg fault.  */
-		      if (h == NULL)
-			{
-			  char buffer [32];
+		      sprintf_vma (buffer, rel->r_info);
+		      (*_bfd_error_handler)
+			(_("error: %B contains a reloc (0x%s) for section %A "
+			   "that references a non-existent global symbol"),
+			 input_bfd, o, buffer);
+		      bfd_set_error (bfd_error_bad_value);
+		      return FALSE;
+		    }
 
-			  sprintf_vma (buffer, rel->r_info);
-			  (*_bfd_error_handler)
-			    (_("error: %B contains a reloc (0x%s) for section %A "
-			       "that references a non-existent global symbol"),
-			     input_bfd, o, buffer);
-			  bfd_set_error (bfd_error_bad_value);
-			  return FALSE;
-			}
+		  while (h->root.type == bfd_link_hash_indirect
+			 || h->root.type == bfd_link_hash_warning)
+		    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+		  s_type = h->type;
+
+		  ps = NULL;
+		  if (h->root.type == bfd_link_hash_defined
+		      || h->root.type == bfd_link_hash_defweak)
+		    ps = &h->root.u.def.section;
 
-		      while (h->root.type == bfd_link_hash_indirect
-			     || h->root.type == bfd_link_hash_warning)
-			h = (struct elf_link_hash_entry *) h->root.u.i.link;
-
-		      if (h->root.type != bfd_link_hash_defined
-			  && h->root.type != bfd_link_hash_defweak)
-			continue;
+		  sym_name = h->root.root.string;
+		}
+	      else
+		{
+		  Elf_Internal_Sym *sym = isymbuf + r_symndx;
 
-		      ps = &h->root.u.def.section;
-		      sym_name = h->root.root.string;
-		    }
-		  else
-		    {
-		      Elf_Internal_Sym *sym = isymbuf + r_symndx;
-		      ps = &finfo->sections[r_symndx];
-		      sym_name = bfd_elf_sym_name (input_bfd,
-						   symtab_hdr,
-						   sym, *ps);
-		    }
+		  s_type = ELF_ST_TYPE (sym->st_info);
+		  ps = &finfo->sections[r_symndx];
+		  sym_name = bfd_elf_sym_name (input_bfd, symtab_hdr,
+					       sym, *ps);
+		}
 
+	      if (s_type == STT_RELC || s_type == STT_SRELC)
+		{
+		  bfd_vma val;
+		  bfd_vma dot = (rel->r_offset
+				 + o->output_offset + o->output_section->vma);
+#ifdef DEBUG
+		  printf ("Encountered a complex symbol!");
+		  printf (" (input_bfd %s, section %s, reloc %ld\n",
+			  input_bfd->filename, o->name, rel - internal_relocs);
+		  printf (" symbol: idx  %8.8lx, name %s\n",
+			  r_symndx, sym_name);
+		  printf (" reloc : info %8.8lx, addr %8.8lx\n",
+			  (unsigned long) rel->r_info,
+			  (unsigned long) rel->r_offset);
+#endif
+		  if (!eval_symbol (&val, &sym_name, input_bfd, finfo, dot,
+				    isymbuf, locsymcount, s_type == STT_SRELC))
+		    return FALSE;
+
+		  /* Symbol evaluated OK.  Update to absolute value.  */
+		  set_symbol_value (input_bfd, isymbuf, locsymcount,
+				    r_symndx, val);
+		  continue;
+		}
+
+	      if (action_discarded != -1 && ps != NULL)
+		{
 		  /* Complain if the definition comes from a
 		     discarded section.  */
 		  if ((sec = *ps) != NULL && elf_discarded_section (sec))
 		    {
 		      BFD_ASSERT (r_symndx != 0);
-		      if (action & COMPLAIN)
+		      if (action_discarded & COMPLAIN)
 			(*finfo->info->callbacks->einfo)
 			  (_("%X`%s' referenced in section `%A' of %B: "
 			     "defined in discarded section `%A' of %B\n"),
@@ -9362,7 +9166,7 @@ elf_link_input_bfd (struct elf_final_lin
 			 FIXME: This is quite broken.  Modifying the
 			 symbol here means we will be changing all later
 			 uses of the symbol, not just in this section.  */
-		      if (action & PRETEND)
+		      if (action_discarded & PRETEND)
 			{
 			  asection *kept;
 
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.242
diff -u -p -r1.242 elf-bfd.h
--- bfd/elf-bfd.h	18 Sep 2007 00:25:07 -0000	1.242
+++ bfd/elf-bfd.h	29 Sep 2007 13:15:52 -0000
@@ -1814,14 +1814,7 @@ extern bfd_boolean bfd_elf_match_symbols
   (asection *, asection *, struct bfd_link_info *);
 
 extern void bfd_elf_perform_complex_relocation
-  (bfd *                   output_bfd ATTRIBUTE_UNUSED,
-   struct bfd_link_info *  info,
-   bfd *                   input_bfd,
-   asection *              input_section,
-   bfd_byte *              contents,
-   Elf_Internal_Rela *     rel,
-   Elf_Internal_Sym *      local_syms,
-   asection **             local_sections);
+  (bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma);
 
 extern bfd_boolean _bfd_elf_setup_sections
   (bfd *);
Index: bfd/elf32-mep.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-mep.c,v
retrieving revision 1.7
diff -u -p -r1.7 elf32-mep.c
--- bfd/elf32-mep.c	4 Jul 2007 14:23:22 -0000	1.7
+++ bfd/elf32-mep.c	29 Sep 2007 13:15:52 -0000
@@ -402,48 +402,6 @@ mep_info_to_howto_rela
   r_type = ELF32_R_TYPE (dst->r_info);
   cache_ptr->howto = & mep_elf_howto_table [r_type];
 }
-
-/* Look through the relocs for a section during the first phase.
-   Since we don't do .gots or .plts, we just need to consider the
-   virtual table relocs for gc.  */
-
-static bfd_boolean
-mep_elf_check_relocs
-    (bfd *                     abfd,
-     struct bfd_link_info *    info,
-     asection *                sec,
-     const Elf_Internal_Rela * relocs)
-{
-  Elf_Internal_Shdr *           symtab_hdr;
-  struct elf_link_hash_entry ** sym_hashes;
-  struct elf_link_hash_entry ** sym_hashes_end;
-  const Elf_Internal_Rela *     rel;
-  const Elf_Internal_Rela *     rel_end;
-
-  if (info->relocatable)
-    return TRUE;
-
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  sym_hashes = elf_sym_hashes (abfd);
-  sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
-  if (!elf_bad_symtab (abfd))
-    sym_hashes_end -= symtab_hdr->sh_info;
-
-  rel_end = relocs + sec->reloc_count;
-  for (rel = relocs; rel < rel_end; rel++)
-    {
-      struct elf_link_hash_entry *h;
-      unsigned long r_symndx;
-
-      r_symndx = ELF32_R_SYM (rel->r_info);
-      if (r_symndx < symtab_hdr->sh_info)
-        h = NULL;
-      else
-        h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-    }
-  return TRUE;
-}
-
 
 /* Relocate a MEP ELF section.
    There is some attempt to make this function usable for many architectures,
@@ -513,18 +471,7 @@ mep_elf_relocate_section
       int                          r_type;
 
       r_type = ELF32_R_TYPE (rel->r_info);
-
       r_symndx = ELF32_R_SYM (rel->r_info);
-
-      /* Is this a complex relocation?  */
-      if (!info->relocatable && ELF32_R_TYPE (rel->r_info) == R_RELC)
-	{
-	  bfd_elf_perform_complex_relocation (output_bfd, info,
-					      input_bfd, input_section, contents,
-					      rel, local_syms, local_sections);
-	  continue;
-	}
-
       howto  = mep_elf_howto_table + ELF32_R_TYPE (rel->r_info);
       h      = NULL;
       sym    = NULL;
@@ -539,56 +486,17 @@ mep_elf_relocate_section
 	  name = bfd_elf_string_from_elf_section
 	    (input_bfd, symtab_hdr->sh_link, sym->st_name);
 	  name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name;
-#if 0
-	  fprintf (stderr, "local: sec: %s, sym: %s (%d), value: %x + %x + %x addend %x\n",
-		   sec->name, name, sym->st_name,
-		   sec->output_section->vma, sec->output_offset,
-		   sym->st_value, rel->r_addend);
-#endif
 	}
       else
 	{
-	  relocation = 0;
-	  h = sym_hashes [r_symndx];
+	  bfd_boolean warned, unresolved_reloc;
 
-	  while (h->root.type == bfd_link_hash_indirect
-		 || h->root.type == bfd_link_hash_warning)
-	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+	  RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel,
+				  r_symndx, symtab_hdr, sym_hashes,
+				  h, sec, relocation,
+				  unresolved_reloc, warned);
 
 	  name = h->root.root.string;
-
-	  if (h->root.type == bfd_link_hash_defined
-	      || h->root.type == bfd_link_hash_defweak)
-	    {
-	      sec = h->root.u.def.section;
-	      relocation = (h->root.u.def.value
-			    + sec->output_section->vma
-			    + sec->output_offset);
-#if 0
-	      fprintf (stderr,
-		       "defined: sec: %s, name: %s, value: %x + %x + %x gives: %x\n",
-		       sec->name, name, h->root.u.def.value,
-		       sec->output_section->vma, sec->output_offset, relocation);
-#endif
-	    }
-	  else if (h->root.type == bfd_link_hash_undefweak)
-	    {
-#if 0
-	      fprintf (stderr, "undefined: sec: %s, name: %s\n",
-		       sec->name, name);
-#endif
-	    }
-	  else if (!info->relocatable)
-	    {
-	      if (! ((*info->callbacks->undefined_symbol)
-		     (info, h->root.root.string, input_bfd,
-		      input_section, rel->r_offset,
-		      (!info->shared && info->unresolved_syms_in_objects == RM_GENERATE_ERROR))))
-		return FALSE;
-#if 0
-	      fprintf (stderr, "unknown: name: %s\n", name);
-#endif
-	    }
 	}
 
       if (sec != NULL && elf_discarded_section (sec))
@@ -603,18 +511,15 @@ mep_elf_relocate_section
 	}
 
       if (info->relocatable)
-	{
-	  /* This is a relocatable link.  We don't have to change
-             anything, unless the reloc is against a section symbol,
-             in which case we have to adjust according to where the
-             section symbol winds up in the output section.  */
-	  if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-	    rel->r_addend += sec->output_offset;
-	  continue;
-	}
+	continue;
 
       switch (r_type)
 	{
+	case R_RELC:
+	  bfd_elf_perform_complex_relocation (input_bfd, input_section,
+					      contents, rel, relocation);
+	  continue;
+
 	default:
 	  r = mep_final_link_relocate (howto, input_bfd, input_section,
 					 contents, rel, relocation);
@@ -676,63 +581,6 @@ mep_elf_relocate_section
   return TRUE;
 }
 
-
-/* Update the got entry reference counts for the section being
-   removed.  */
-
-static bfd_boolean
-mep_elf_gc_sweep_hook
-    (bfd *                     abfd ATTRIBUTE_UNUSED,
-     struct bfd_link_info *    info ATTRIBUTE_UNUSED,
-     asection *                sec ATTRIBUTE_UNUSED,
-     const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
-{
-  return TRUE;
-}
-
-/* Return the section that should be marked against GC for a given
-   relocation.  */
-
-static asection *
-mep_elf_gc_mark_hook
-    (asection *                   sec,
-     struct bfd_link_info *       info ATTRIBUTE_UNUSED,
-     Elf_Internal_Rela *          rel,
-     struct elf_link_hash_entry * h,
-     Elf_Internal_Sym *           sym)
-{
-  if (h != NULL)
-    {
-      switch (ELF32_R_TYPE (rel->r_info))
-	{
-	default:
-	  switch (h->root.type)
-	    {
-	    case bfd_link_hash_defined:
-	    case bfd_link_hash_defweak:
-	      return h->root.u.def.section;
-
-	    case bfd_link_hash_common:
-	      return h->root.u.c.p->section;
-
-	    default:
-	      break;
-	    }
-	}
-    }
-  else
-    {
-      if (!(elf_bad_symtab (sec->owner)
-	    && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
-	  && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
-		&& sym->st_shndx != SHN_COMMON))
-	return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
-    }
-
-  return NULL;
-}
-
-
 /* Function to set the ELF flag bits.  */
 
 static bfd_boolean
@@ -899,11 +747,6 @@ elf32_mep_machine (bfd * abfd)
 static bfd_boolean
 mep_elf_object_p (bfd * abfd)
 {
-  /* Irix 5 and 6 is broken.  Object file symbol tables are not always
-     sorted correctly such that local symbols preceed global symbols,
-     and the sh_info field in the symbol table is not always right.  */
-  /* This is needed for the RELC support code.  */
-  elf_bad_symtab (abfd) = TRUE;
   bfd_default_set_arch_mach (abfd, bfd_arch_mep, elf32_mep_machine (abfd));
   return TRUE;
 }
@@ -940,23 +783,17 @@ mep_elf_fake_sections (bfd *            
 #define elf_info_to_howto_rel			NULL
 #define elf_info_to_howto			mep_info_to_howto_rela
 #define elf_backend_relocate_section		mep_elf_relocate_section
-#define elf_backend_gc_mark_hook		mep_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook		mep_elf_gc_sweep_hook
-#define elf_backend_check_relocs                mep_elf_check_relocs
 #define elf_backend_object_p		        mep_elf_object_p
 #define elf_backend_section_flags		mep_elf_section_flags
 #define elf_backend_fake_sections		mep_elf_fake_sections
 
-#define elf_backend_can_gc_sections		1
-
 #define bfd_elf32_bfd_reloc_type_lookup		mep_reloc_type_lookup
-#define bfd_elf32_bfd_reloc_name_lookup	mep_reloc_name_lookup
+#define bfd_elf32_bfd_reloc_name_lookup		mep_reloc_name_lookup
 #define bfd_elf32_bfd_set_private_flags		mep_elf_set_private_flags
 #define bfd_elf32_bfd_copy_private_bfd_data	mep_elf_copy_private_bfd_data
 #define bfd_elf32_bfd_merge_private_bfd_data	mep_elf_merge_private_bfd_data
 #define bfd_elf32_bfd_print_private_bfd_data	mep_elf_print_private_bfd_data
 
-/* We use only the RELA entries.  */
-#define USE_RELA
+#define elf_backend_rela_normal			1
 
 #include "elf32-target.h"
Index: ld/testsuite/ld-selective/sel-dump.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-selective/sel-dump.exp,v
retrieving revision 1.9
diff -u -p -r1.9 sel-dump.exp
--- ld/testsuite/ld-selective/sel-dump.exp	6 Jul 2007 14:09:45 -0000	1.9
+++ ld/testsuite/ld-selective/sel-dump.exp	28 Sep 2007 07:16:22 -0000
@@ -28,8 +28,8 @@ set test_list [lsort [glob -nocomplain $
 for { set i 0 } { $i < [llength $test_list] } { incr i } {
     # We need to strip the ".d", but can leave the dirname.
     verbose [file rootname [lindex $test_list $i]]
-    setup_xfail "alpha*-*" "arc*-*" "d30v*-*" "dlx*-*" "hppa64-*-*"
-    setup_xfail "i370*-*" "i860*-*" "i960*-*" "ia64*-*" "mn10200-*"
-    setup_xfail  "or32-*" "pj-*"
+    setup_xfail "alpha*-*" "am33*-*" "arc*-*" "d30v*-*" "dlx*-*"
+    setup_xfail "hppa*64-*-*" "i370*-*" "i860*-*" "i960*-*" "ia64*-*"
+    setup_xfail "m88*-*" "mn10200-*" "mep-*" "or32-*" "pj-*"
     run_dump_test [file rootname [lindex $test_list $i]]
 }
Index: ld/testsuite/ld-selective/selective.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-selective/selective.exp,v
retrieving revision 1.38
diff -u -p -r1.38 selective.exp
--- ld/testsuite/ld-selective/selective.exp	28 Aug 2007 13:21:58 -0000	1.38
+++ ld/testsuite/ld-selective/selective.exp	28 Sep 2007 07:16:22 -0000
@@ -27,8 +27,15 @@ if ![is_elf_format] {
     return
 }
 
-# Alpha and IA64 do not support selective linking
-if {[istarget "alpha*-*-*"] || [istarget "ia64-*-*"]} {
+# These targets do not support selective linking
+if {[istarget "alpha*-*-*"] || [istarget "am33*-*-*"] ||
+    [istarget "arc-*-*"] || [istarget "d30v-*-*"] ||
+    [istarget "dlx-*-*"] || [istarget "hppa*64*-*-*"] ||
+    [istarget "i370-*-*"] || [istarget "i860-*-*"] ||
+    [istarget "i960-*-*"] || [istarget "ia64-*-*"] ||
+    [istarget "m88*-*-*"] || [istarget "mn10200-*-*"] ||
+    [istarget "mep-*-*"] || [istarget "or32-*-*"] ||
+    [istarget "pj*-*-*"]} {
     return
 }
 

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list