Tue Sep 13 16:04:07 1994 Steve Chamberlain (sac@jonny.cygnus.com)
authorSteve Chamberlain <sac@cygnus>
Wed, 14 Sep 1994 00:10:42 +0000 (00:10 +0000)
committerSteve Chamberlain <sac@cygnus>
Wed, 14 Sep 1994 00:10:42 +0000 (00:10 +0000)
* cofflink.c (coff_link_input_bfd): syment_base is unsigned
so can't compare -ve numbers with it.

Mon Sep 12 20:31:17 1994  Steve Chamberlain  (sac@jonny.cygnus.com)

* configure.in (shcoff_vec): Use cofflink.o now.
* coff-sh.c: Rewritten to use new fast coff backend.

bfd/ChangeLog
bfd/coff-sh.c

index 84d7fa192a756725d623f29fd61b44afdd64be81..7f1320ebda6aa938de8b7a9d05ab9bee891b4bb6 100644 (file)
@@ -1,3 +1,13 @@
+Tue Sep 13 16:04:07 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * cofflink.c (coff_link_input_bfd): syment_base is unsigned
+       so can't compare -ve numbers with it.
+
+Mon Sep 12 20:31:17 1994  Steve Chamberlain  (sac@jonny.cygnus.com)
+
+       * configure.in (shcoff_vec): Use cofflink.o now.
+       * coff-sh.c: Rewritten to use new fast coff backend.
+
 Tue Sep 13 16:23:57 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
 
        * aoutx.h (NAME(aout,final_link)): Don't assume that all the input
index 1964eea27754adc03841aa9e6e755a9c47e459b7..3caaaf7de73838c15b7349ccd0523ad43f0c87bb 100644 (file)
@@ -28,23 +28,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "coff/internal.h"
 #include "libcoff.h"
 
-static reloc_howto_type r_imm32 =
-HOWTO (R_SH_IMM32, 0,2, 32, false, 0,
-       complain_overflow_bitfield, 0, "r_imm32", false, 0x0, 0xffffffff,
-       false);
+static bfd_reloc_status_type sh_reloc();
 
 
+static reloc_howto_type r_imm32 =
+  {R_SH_IMM32,  0, 2, 32, false, 0, 
+     complain_overflow_bitfield, sh_reloc,"r_imm32",    true, 0xffffffff,0xffffffff, false};
 
-/* Turn a howto into a reloc number */
 
-static int 
-coff_SH_select_reloc (howto)
-     reloc_howto_type *howto;
-{
-  return howto->type;
-}
-
-#define SELECT_RELOC(x,howto) x.r_type = coff_SH_select_reloc(howto)
+/*#define SELECT_RELOC(x,y) x->howto = (&r_imm32)*/
 
 
 #define BADMAG(x) SHBADMAG(x)
@@ -53,14 +45,35 @@ coff_SH_select_reloc (howto)
 #define __A_MAGIC_SET__
 
 /* Code to swap in the reloc */
+#if 0
 #define SWAP_IN_RELOC_OFFSET   bfd_h_get_32
 #define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+#endif
 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
   dst->r_stuff[0] = 'S'; \
   dst->r_stuff[1] = 'C';
 
 /* Code to turn a r_type into a howto ptr, uses the above howto table
    */
+static long
+get_symbol_value (symbol)       
+     asymbol *symbol;
+{                                             
+  long relocation = 0;
+
+  if (bfd_is_com_section (symbol->section))
+  {
+    relocation = 0;                           
+  }
+  else 
+  {                                      
+    relocation = symbol->value +
+     symbol->section->output_section->vma +
+      symbol->section->output_offset;
+  }                                           
+
+  return(relocation);
+}
 
 static void
 rtype2howto (internal, dst)
@@ -70,25 +83,218 @@ rtype2howto (internal, dst)
   switch (dst->r_type)
     {
     default:
-      fprintf (stderr, "BAD 0x%x\n", dst->r_type);
+      abort();
     case R_SH_IMM32:
-      internal->howto = &r_imm32;
+
       break;
     }
 }
 
-#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
-
+#define RTYPE2HOWTO(x,y) ((x)->howto = &r_imm32)
 
 /* Perform any necessaru magic to the addend in a reloc entry */
 
-
+#if 0
 #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
  cache_ptr->addend =  ext_reloc.r_offset;
 
-
+#endif
+
+
+/* Compute the addend of a reloc.  If the reloc is to a common symbol,
+   the object file contains the value of the common symbol.  By the
+   time this is called, the linker may be using a different symbol
+   from a different object file with a different value.  Therefore, we
+   hack wildly to locate the original symbol from this file so that we
+   can make the correct adjustment.  This macro sets coffsym to the
+   symbol from the original file, and uses it to set the addend value
+   correctly.  If this is not a common symbol, the usual addend
+   calculation is done, except that an additional tweak is needed for
+   PC relative relocs.
+   FIXME: This macro refers to symbols and asect; these are from the
+   calling function, not the macro arguments.  */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)               \
+  {                                                            \
+    coff_symbol_type *coffsym = (coff_symbol_type *) NULL;     \
+    if (ptr && bfd_asymbol_bfd (ptr) != abfd)                  \
+      coffsym = (obj_symbols (abfd)                            \
+                + (cache_ptr->sym_ptr_ptr - symbols));         \
+    else if (ptr)                                              \
+      coffsym = coff_symbol_from (abfd, ptr);                  \
+    if (coffsym != (coff_symbol_type *) NULL                   \
+       && coffsym->native->u.syment.n_scnum == 0)              \
+      cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+    else if (ptr && bfd_asymbol_bfd (ptr) == abfd              \
+            && ptr->section != (asection *) NULL)              \
+      cache_ptr->addend = - (ptr->section->vma + ptr->value);  \
+    else                                                       \
+      cache_ptr->addend = 0;                                   \
+  }
+
+#if 0
 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
  reloc_processing(relent, reloc, symbols, abfd, section)
+#endif
+
+/* this function is in charge of performing all the 29k relocations */
+
+static bfd_reloc_status_type
+sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+           error_message)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol_in;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+     char **error_message;
+{
+  /* the consth relocation comes in two parts, we have to remember
+     the state between calls, in these variables */
+  unsigned long insn;
+  unsigned long sym_value;
+  unsigned short r_type;
+
+  unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
+  bfd_byte  *hit_data =addr + (bfd_byte *)(data);
+       
+  r_type = reloc_entry->howto->type;
+
+  if (output_bfd) {
+    /* Partial linking - do nothing */
+    reloc_entry->address += input_section->output_offset;
+    return bfd_reloc_ok;
+  }
+
+  if (symbol_in != NULL
+      && bfd_is_und_section (symbol_in->section))
+    {
+      /* Keep the state machine happy in case we're called again */
+      return (bfd_reloc_undefined);
+    }
+
+
+  sym_value = get_symbol_value(symbol_in);
+
+  switch (r_type) 
+    {
+    case R_SH_IMM32:
+      /* We ignore the previous contents ! */
+      insn = sym_value + reloc_entry->addend;  
+      bfd_put_32(abfd, insn, hit_data);
+      break;
+    default:
+      *error_message = "Unrecognized reloc";
+      return (bfd_reloc_dangerous);
+    }
+
+
+  return(bfd_reloc_ok);        
+}
+
+/* The reloc processing routine for the optimized COFF linker.  */
+
+static boolean
+coff_sh_relocate_section (output_bfd, info, input_bfd, input_section,
+                           contents, relocs, syms, sections)
+     bfd *output_bfd;
+     struct bfd_link_info *info;
+     bfd *input_bfd;
+     asection *input_section;
+     bfd_byte *contents;
+     struct internal_reloc *relocs;
+     struct internal_syment *syms;
+     asection **sections;
+{
+  struct internal_reloc *rel;
+  struct internal_reloc *relend;
+
+  /* If we are performing a relocateable link, we don't need to do a
+     thing.  The caller will take care of adjusting the reloc
+     addresses and symbol indices.  */
+  if (info->relocateable)
+    return true;
+
+
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      bfd_byte *loc;
+      struct coff_link_hash_entry *h;
+      struct internal_syment *sym;
+      asection *sec;
+      bfd_vma val;
+      bfd_reloc_status_type rstat;
+
+      symndx = rel->r_symndx;
+      loc = contents + rel->r_vaddr - input_section->vma;
+
+      if (symndx == -1)
+       h = NULL;
+      else
+       h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+      sym = NULL;
+      sec = NULL;
+      val = 0;
+
+
+      if (h == NULL)
+       {
+         if (symndx == -1)
+           sec = bfd_abs_section_ptr;
+         else
+           {
+             sym = syms + symndx;
+             sec = sections[symndx];
+             val = (sec->output_section->vma
+                    + sec->output_offset
+                    + sym->n_value
+                    - sec->vma 
+                    - sec->vma);
+           }
+       }
+      else
+       {
+         if (h->root.type == bfd_link_hash_defined)
+           {
+             sec = h->root.u.def.section;
+             val = (h->root.u.def.value
+                    + sec->output_section->vma
+                    + sec->output_offset);
+           }
+         else
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd, input_section,
+                     rel->r_vaddr - input_section->vma)))
+               return false;
+           }
+       }
+
+      switch (rel->r_type)
+       {
+       default:
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+
+       case R_SH_IMM32:
+         {
+           long x = bfd_get_32 (input_bfd, loc);
+           x += val;
+           bfd_put_32 (input_bfd, x, loc);
+
+         }
+
+         break;
+       }
+    }     
+
+  return true;
+}
 
 static void 
 reloc_processing (relent, reloc, symbols, abfd, section)
@@ -98,61 +304,34 @@ reloc_processing (relent, reloc, symbols, abfd, section)
      bfd * abfd;
      asection * section;
 {
+  asymbol *ptr;
   relent->address = reloc->r_vaddr;
-  rtype2howto (relent, reloc);
+  relent->howto = &r_imm32;
 
-  if (reloc->r_symndx > 0)
-    {
-      relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
-    }
-  else
-    {
-      relent->sym_ptr_ptr = &(bfd_abs_symbol);
-    }
 
+  relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx];
 
-  relent->addend = reloc->r_offset;
-  relent->address -= section->vma;
-}
+  ptr = *(relent->sym_ptr_ptr);
 
-static void
-extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
-     bfd *in_abfd;
-     struct bfd_link_info *link_info;
-     struct bfd_link_order *link_order;
-     arelent *reloc;
-     bfd_byte *data;
-     unsigned int *src_ptr;
-     unsigned int *dst_ptr;
-{
-  switch (reloc->howto->type)
-    {
-    case R_SH_IMM32:
-      {
-       int v = bfd_coff_reloc16_get_value(reloc, link_info,
-                                          link_order->u.indirect.section);
-       bfd_put_32 (in_abfd, v, data  + *dst_ptr);
-       (*dst_ptr) +=4;
-       (*src_ptr)+=4;;
-      }
-      break;
+  if (ptr 
+      && bfd_asymbol_bfd(ptr) == abfd          
+
+      && ((ptr->flags & BSF_OLD_COMMON)== 0))  
+    {                                          
+      relent->addend = 0;
+    }                                          
+  else
+    {                                  
+      relent->addend = 0;                      
+    }                  
+  relent->address-= section->vma;
 
-    default:
-      abort ();
-    }
 }
 
-#define coff_reloc16_extra_cases extra_case
+#define coff_relocate_section coff_sh_relocate_section
 
 #include "coffcode.h"
 
-
-#undef  coff_bfd_get_relocated_section_contents
-#undef coff_bfd_relax_section
-#define coff_bfd_get_relocated_section_contents \
-  bfd_coff_reloc16_get_relocated_section_contents
-#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
-
 const bfd_target shcoff_vec =
 {
   "coff-sh",                   /* name */
@@ -169,10 +348,10 @@ const bfd_target shcoff_vec =
   '/',                         /* ar_pad_char */
   15,                          /* ar_max_namelen */
   2,                           /* minimum section alignment */
-bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
-bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+     bfd_getb64, bfd_getb_signed_64, bfd_putb64,
      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
 
@@ -195,3 +374,4 @@ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
 
     COFF_SWAP_TABLE,
 };
+