For PR 4865.
authorIan Lance Taylor <ian@airs.com>
Tue, 14 Jun 1994 17:06:08 +0000 (17:06 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 14 Jun 1994 17:06:08 +0000 (17:06 +0000)
* libecoff.h (struct ecoff_link_hash_entry): Change type of
written from boolean to char.  Add new field small.
* ecoff.c (ecoff_link_hash_newfunc): Initialize written to 0
rather than false.  Initialize small to 0.
(ecoff_link_add_externals): If ECOFF type is scSUndefined, set
small.  If small is set, and hash table type is common, force the
symbol into a section named SCOMMON and change the ECOFF type from
scCommon to scSCommon.
(ecoff_link_write_external): Set written to 1 rather than true.
* coff-mips.c (mips_relocate_section): Correct JMPADDR reloc
overflow check to consider section VMA of input file.

bfd/ChangeLog
bfd/coff-mips.c
bfd/ecoff.c
bfd/libecoff.h

index f43cfe8c67461e842517cc3f0265811fa9fab135..8e7fc5a1731c7d2063a2983d0b849b8620b2d8d3 100644 (file)
@@ -1,3 +1,17 @@
+Tue Jun 14 13:00:04 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * libecoff.h (struct ecoff_link_hash_entry): Change type of
+       written from boolean to char.  Add new field small.
+       * ecoff.c (ecoff_link_hash_newfunc): Initialize written to 0
+       rather than false.  Initialize small to 0.
+       (ecoff_link_add_externals): If ECOFF type is scSUndefined, set
+       small.  If small is set, and hash table type is common, force the
+       symbol into a section named SCOMMON and change the ECOFF type from
+       scCommon to scSCommon.
+       (ecoff_link_write_external): Set written to 1 rather than true.
+       * coff-mips.c (mips_relocate_section): Correct JMPADDR reloc
+       overflow check to consider section VMA of input file.
+
 Mon Jun 13 14:20:07 1994  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        * aoutf1.h (aout_32_sunos4_write_object_contents): Handle a
index 3ad2f0a1b67f44c2cf0ce48f1ce6d584a2e68352..d013bc192adb7d059d64f152a9163a8abdef8bd8 100644 (file)
@@ -1444,6 +1444,43 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
+      /* If we are relaxing, and this is a reloc against the .text
+        segment, we may need to adjust it if some branches have been
+        expanded.  The reloc types which are likely to occur in the
+        .text section are handled efficiently by mips_relax_section,
+        and thus do not need to be handled here.  */
+      if (ecoff_data (input_bfd)->debug_info.adjust != NULL
+         && ! int_rel.r_extern
+         && int_rel.r_symndx == RELOC_SECTION_TEXT
+         && (strcmp (bfd_get_section_name (input_bfd, input_section),
+                     ".text") != 0
+             || (int_rel.r_type != MIPS_R_PCREL16
+                 && int_rel.r_type != MIPS_R_SWITCH
+                 && int_rel.r_type != MIPS_R_RELHI
+                 && int_rel.r_type != MIPS_R_RELLO)))
+       {
+         bfd_vma adr;
+         struct ecoff_value_adjust *a;
+
+         /* We need to get the addend so that we know whether we need
+            to adjust the address.  */
+         BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
+
+         adr = bfd_get_32 (input_bfd,
+                           (contents
+                            + adjust
+                            + int_rel.r_vaddr
+                            - input_section->vma));
+
+         for (a = ecoff_data (input_bfd)->debug_info.adjust;
+              a != (struct ecoff_value_adjust *) NULL;
+              a = a->next)
+           {
+             if (adr >= a->start && adr < a->end)
+               addend += a->adjust;
+           }
+       }
+
       if (info->relocateable)
        {
          /* We are generating relocateable output, and must convert
@@ -1587,6 +1624,7 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
            }
 
          relocation += addend;
+         addend = 0;
 
          /* Adjust a PC relative relocation by removing the reference
             to the original address in the section and including the
@@ -1697,6 +1735,23 @@ mips_relocate_section (output_bfd, info, input_bfd, input_section,
            }
        }
 
+      /* MIPS_R_JMPADDR requires peculiar overflow detection.  The
+        instruction provides a 28 bit address (the two lower bits are
+        implicit zeroes) which is combined with the upper four bits
+        of the instruction address.  */
+      if (r == bfd_reloc_ok
+         && int_rel.r_type == MIPS_R_JMPADDR
+         && (((relocation
+               + addend
+               + (int_rel.r_extern ? 0 : s->vma))
+              & 0xf0000000)
+             != ((input_section->output_section->vma
+                  + input_section->output_offset
+                  + (int_rel.r_vaddr - input_section->vma)
+                  + adjust)
+                 & 0xf0000000)))
+       r = bfd_reloc_overflow;
+
       if (r != bfd_reloc_ok)
        {
          switch (r)
index 2555c0cbd920d1da6b11e84936c39633788c1e5c..bd2c742cdb260e9d1fcb06fdf3bd0b1112ba816e 100644 (file)
@@ -3575,6 +3575,8 @@ ecoff_link_hash_newfunc (entry, table, string)
       /* Set local fields.  */
       ret->indx = -1;
       ret->abfd = NULL;
+      ret->written = 0;
+      ret->small = 0;
     }
   memset ((PTR) &ret->esym, 0, sizeof ret->esym);
 
@@ -4171,6 +4173,25 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
              h->abfd = abfd;
              h->esym = esym;
            }
+
+         /* Remember whether this symbol was small undefined.  */
+         if (esym.asym.sc == scSUndefined)
+           h->small = 1;
+
+         /* If this symbol was ever small undefined, it needs to wind
+            up in a GP relative section.  We can't control the
+            section of a defined symbol, but we can control the
+            section of a common symbol.  This case is actually needed
+            on Ultrix 4.2 to handle the symbol cred in -lckrb.  */
+         if (h->small
+             && h->root.type == bfd_link_hash_common
+             && strcmp (h->root.u.c.section->name, SCOMMON) != 0)
+           {
+             h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON);
+             h->root.u.c.section->flags = SEC_ALLOC;
+             if (h->esym.asym.sc == scCommon)
+               h->esym.asym.sc = scSCommon;
+           }
        }
     }
 
@@ -4506,7 +4527,7 @@ ecoff_link_write_external (h, data)
 
   /* FIXME: We should check if this symbol is being stripped.  */
 
-  if (h->root.written)
+  if (h->written)
     return true;
 
   if (h->abfd == (bfd *) NULL)
@@ -4607,7 +4628,7 @@ ecoff_link_write_external (h, data)
   /* bfd_ecoff_debug_one_external uses iextMax to keep track of the
      symbol number.  */
   h->indx = ecoff_data (output_bfd)->debug_info.symbolic_header.iextMax;
-  h->root.written = true;
+  h->written = 1;
 
   return (bfd_ecoff_debug_one_external
          (output_bfd, &ecoff_data (output_bfd)->debug_info,
index 0d20c4ba746f5502954f747cc4f2f70c223f6f5b..d4d503d2c3ff6aeaa94833c5a4fc8942464023d1 100644 (file)
@@ -206,6 +206,10 @@ struct ecoff_link_hash_entry
   bfd *abfd;
   /* ECOFF external symbol information.  */
   EXTR esym;
+  /* Nonzero if this symbol has been written out.  */
+  char written;
+  /* Nonzero if this symbol was referred to as small undefined.  */
+  char small;
 };
 
 /* ECOFF linker hash table.  */