* cofflink.c (coff_link_input_bfd): If r_symndx is -1, don't
authorIan Lance Taylor <ian@airs.com>
Mon, 12 Sep 1994 21:01:19 +0000 (21:01 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 12 Sep 1994 21:01:19 +0000 (21:01 +0000)
change it.
(_bfd_coff_generic_relocate_section): If r_symndx is -1, it is an
absolute reloc.  Don't dump core using r_symndx as an array index.
* cf-m68klynx.c (coff_bfd_link_add_symbols): Define.
(lynx_link_add_symbols): New static function (copy of function in
coff-i386.c).
(coff_m68k_lynxrtype_to_howto): sym argument may be NULL.
* coff-i386.c (coff_i386_rtype_to_howto): Likewise.
* coff-a29k.c (coff_a29k_relocate_section): Handle an r_symndx
value of -1, meaning an absolute reloc.

bfd/ChangeLog
bfd/cf-m68klynx.c
bfd/coff-a29k.c
bfd/cofflink.c

index 9c60291693bba7555667802cb582d434c38193f7..5a431aae8ac11d2ffd94c74569bb4ab74f4b02cf 100644 (file)
@@ -1,5 +1,17 @@
 Mon Sep 12 11:43:08 1994  Ian Lance Taylor  (ian@sanguine.cygnus.com)
 
+       * cofflink.c (coff_link_input_bfd): If r_symndx is -1, don't
+       change it.
+       (_bfd_coff_generic_relocate_section): If r_symndx is -1, it is an
+       absolute reloc.  Don't dump core using r_symndx as an array index.
+       * cf-m68klynx.c (coff_bfd_link_add_symbols): Define.
+       (lynx_link_add_symbols): New static function (copy of function in
+       coff-i386.c).
+       (coff_m68k_lynxrtype_to_howto): sym argument may be NULL.
+       * coff-i386.c (coff_i386_rtype_to_howto): Likewise.
+       * coff-a29k.c (coff_a29k_relocate_section): Handle an r_symndx
+       value of -1, meaning an absolute reloc.
+
        * ctor.c: Remove; obsolete.
        * Makefile.in: Rebuild dependencies.
        (BFD_LIBS): Remove ctor.o.
index 15c9915b888114525d83e872be3599183ccd8cbc..bc6cb293f4ffb9a3a1568507372cb43e86a79c62 100644 (file)
@@ -43,6 +43,7 @@ struct internal_syment;
 
 static bfd_reloc_status_type _bfd_m68klynx_special_fn
   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static boolean lynx_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
 static const struct reloc_howto_struct *coff_m68k_lynx_rtype_to_howto
   PARAMS ((bfd *, asection *, struct internal_reloc *,
           struct coff_link_hash_entry *, struct internal_syment *,
@@ -175,14 +176,44 @@ _bfd_m68klynx_special_fn (abfd, reloc_entry, symbol, data, input_section,
       cache_ptr->addend += asect->vma;                         \
   }
 
+#define coff_bfd_link_add_symbols lynx_link_add_symbols
 #define coff_rtype_to_howto coff_m68k_lynx_rtype_to_howto
 
 #include "coff-m68k.c"
 
+/* On Lynx, we may have a COFF archive which contains a.out elements.
+   This screws up the COFF linker, which expects that any archive it
+   gets contains COFF elements.  We override the add_symbols function
+   to check for this case.  */
+
+static boolean
+lynx_link_add_symbols (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  if (bfd_get_format (abfd) == bfd_archive)
+    {
+      bfd *first;
+
+      first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+      if (first == NULL)
+       return false;
+      if (! bfd_check_format (first, bfd_object))
+       return false;
+      if (bfd_get_flavour (first) != bfd_target_coff_flavour)
+       {
+         /* Treat the archive as though it were actually of the
+            flavour of its first element.  This ought to work,
+            since the archive support is fairly generic.  */
+         return (*first->xvec->_bfd_link_add_symbols) (abfd, info);
+       }
+    }
+
+  return _bfd_coff_link_add_symbols (abfd, info);
+}
+
 /* coff-m68k.c uses the special COFF backend linker.  We need to
-   adjust common symbols.  FIXME: We may able to get rid of
-   CALC_ADDEND and _bfd_m68klynx_special_fn.  However, they may still
-   be used by gas.
+   adjust common symbols.
 
    We can't define this function until after we have included
    coff-m68k.c, because it uses RTYPE2HOWTO.  */
@@ -204,7 +235,7 @@ coff_m68k_lynx_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
 
   howto = relent.howto;
 
-  if (sym->n_scnum == 0 && sym->n_value != 0)
+  if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
     {
       /* This is a common symbol.  The section contents include the
         size (sym->n_value) as an addend.  The relocate_section
index 35e6ea353d7901124a6ac35579128c82aa1a1e54..8e6f11dd32eda73084ea62666543c94814bd109a 100644 (file)
@@ -353,7 +353,10 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
       symndx = rel->r_symndx;
       loc = contents + rel->r_vaddr - input_section->vma;
 
-      h = obj_coff_sym_hashes (input_bfd)[symndx];
+      if (symndx == -1)
+       h = NULL;
+      else
+       h = obj_coff_sym_hashes (input_bfd)[symndx];
 
       sym = NULL;
       sec = NULL;
@@ -366,12 +369,17 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
        {
          if (h == NULL)
            {
-             sym = syms + symndx;
-             sec = sections[symndx];
-             val = (sec->output_section->vma
-                    + sec->output_offset
-                    + sym->n_value
-                    - sec->vma);
+             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);
+               }
            }
          else
            {
@@ -497,7 +505,9 @@ coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
          const char *name;
          char buf[SYMNMLEN + 1];
 
-         if (h != NULL)
+         if (symndx == -1)
+           name = "*ABS*";
+         else if (h != NULL)
            name = h->root.root.string;
          else if (sym == NULL)
            name = "*unknown*";
index 31f2597e45a6b66bc97fa2d89ec3d055b0c823de..87769648c27b08e39066a2eb2000cbf3a1a8e9d9 100644 (file)
@@ -695,15 +695,17 @@ _bfd_coff_final_link (abfd, info)
     {
       unsigned int i;
 
+      /* We use section_count + 1, rather than section_count, because
+         the target_index fields are 1 based.  */
       finfo.section_info = ((struct coff_link_section_info *)
-                           malloc (abfd->section_count
+                           malloc ((abfd->section_count + 1)
                                    * sizeof (struct coff_link_section_info)));
       if (finfo.section_info == NULL)
        {
          bfd_set_error (bfd_error_no_memory);
          goto error_return;
        }
-      for (i = 0; i < abfd->section_count; i++)
+      for (i = 0; i <= abfd->section_count; i++)
        {
          finfo.section_info[i].relocs = NULL;
          finfo.section_info[i].rel_hashes = NULL;
@@ -1122,7 +1124,16 @@ coff_link_input_bfd (finfo, input_bfd)
         the symbol.  */
       isym = *isymp;
 
-      *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
+      if (isym.n_scnum != 0)
+       *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
+      else
+       {
+         if (isym.n_value == 0)
+           *secpp = bfd_und_section_ptr;
+         else
+           *secpp = bfd_com_section_ptr;
+       }
+
       *indexp = -1;
 
       skip = false;
@@ -1647,7 +1658,8 @@ coff_link_input_bfd (finfo, input_bfd)
 
              irel = internal_relocs;
              irelend = irel + o->reloc_count;
-             rel_hash = finfo->section_info[target_index].rel_hashes;
+             rel_hash = (finfo->section_info[target_index].rel_hashes
+                         + o->output_section->reloc_count);
              for (; irel < irelend; irel++, rel_hash++)
                {
                  struct coff_link_hash_entry *h;
@@ -1658,6 +1670,9 @@ coff_link_input_bfd (finfo, input_bfd)
 
                  irel->r_vaddr += offset;
 
+                 if (irel->r_symndx == -1)
+                   continue;
+
                  h = obj_coff_sym_hashes (input_bfd)[irel->r_symndx];
                  if (h != NULL)
                    {
@@ -2004,3 +2019,142 @@ coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
 
   return true;
 }
+
+/* A basic reloc handling routine which may be used by processors with
+   simple relocs.  */
+
+boolean
+_bfd_coff_generic_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;
+
+  rel = relocs;
+  relend = rel + input_section->reloc_count;
+  for (; rel < relend; rel++)
+    {
+      long symndx;
+      struct coff_link_hash_entry *h;
+      struct internal_syment *sym;
+      bfd_vma addend;
+      bfd_vma val;
+      const reloc_howto_type *howto;
+      bfd_reloc_status_type rstat;
+
+      symndx = rel->r_symndx;
+
+      if (symndx == -1)
+       {
+         h = NULL;
+         sym = NULL;
+       }
+      else
+       {    
+         h = obj_coff_sym_hashes (input_bfd)[symndx];
+         sym = syms + symndx;
+       }
+
+      /* COFF treats common symbols in one of two ways.  Either the
+         size of the symbol is included in the section contents, or it
+         is not.  We assume that the size is not included, and force
+         the rtype_to_howto function to adjust the addend as needed.  */
+      if (sym != NULL && sym->n_scnum != 0)
+       addend = - sym->n_value;
+      else
+       addend = 0;
+
+      howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
+                                      sym, &addend);
+      if (howto == NULL)
+       return false;
+
+      val = 0;
+
+      if (h == NULL)
+       {
+         asection *sec;
+
+         if (symndx == -1)
+           {
+             sec = bfd_abs_section_ptr;
+             val = 0;
+           }
+         else
+           {
+             sec = sections[symndx];
+             val = (sec->output_section->vma
+                    + sec->output_offset
+                    + sym->n_value
+                    - sec->vma);
+           }
+       }
+      else
+       {
+         if (h->root.type == bfd_link_hash_defined)
+           {
+             asection *sec;
+
+             sec = h->root.u.def.section;
+             val = (h->root.u.def.value
+                    + sec->output_section->vma
+                    + sec->output_offset);
+           }
+         else if (! info->relocateable)
+           {
+             if (! ((*info->callbacks->undefined_symbol)
+                    (info, h->root.root.string, input_bfd, input_section,
+                     rel->r_vaddr - input_section->vma)))
+               return false;
+           }
+       }
+
+      rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
+                                       contents,
+                                       rel->r_vaddr - input_section->vma,
+                                       val, addend);
+
+      switch (rstat)
+       {
+       default:
+         abort ();
+       case bfd_reloc_ok:
+         break;
+       case bfd_reloc_overflow:
+         {
+           const char *name;
+           char buf[SYMNMLEN + 1];
+
+           if (symndx == -1)
+             name = "*ABS*";
+           else if (h != NULL)
+             name = h->root.root.string;
+           else if (sym->_n._n_n._n_zeroes == 0
+                    && sym->_n._n_n._n_offset != 0)
+             name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
+           else
+             {
+               strncpy (buf, sym->_n._n_name, SYMNMLEN);
+               buf[SYMNMLEN] = '\0';
+               name = buf;
+             }
+
+           if (! ((*info->callbacks->reloc_overflow)
+                  (info, name, howto->name, (bfd_vma) 0, input_bfd,
+                   input_section, rel->r_vaddr - input_section->vma)))
+             return false;
+         }
+       }
+    }
+
+  return true;
+}