These changes make shared library support work again on 386 COFF
authorIan Lance Taylor <ian@airs.com>
Tue, 6 Apr 1993 00:53:41 +0000 (00:53 +0000)
committerIan Lance Taylor <ian@airs.com>
Tue, 6 Apr 1993 00:53:41 +0000 (00:53 +0000)
systems.

* coffcode.h (styp_to_sec_flags): Set SEC_SHARED_LIBRARY for a
STYP_NOLOAD | STYP_BSS section.  Don't set SEC_NEVER_LOAD for a
STYP_INFO section.
(coff_compute_section_file_positions): Force vma and lma of _LIB
section to be zero.
(coff_set_section_contents): Count number of entries in new lma
field, not in vma.
* coffgen.c (make_a_section_from_file): Force lineno_count of
SEC_SHARED_LIBRARY section to be zero, since it is non-zero on the
SCO 3.2v4 shared library.
* seclet.c (rel): Copy over any section with contents, not just
loadable sections.

* coff-mips.c (ecoff_make_empty_symbol): Zero out newly allocated
symbol.

bfd/ChangeLog
bfd/coff-mips.c
bfd/seclet.c

index 05d2dd0..bd62d19 100644 (file)
@@ -1,5 +1,21 @@
 Mon Apr  5 12:07:12 1993  Ian Lance Taylor  (ian@cygnus.com)
 
+       * coffcode.h (styp_to_sec_flags): Set SEC_SHARED_LIBRARY for a
+       STYP_NOLOAD | STYP_BSS section.  Don't set SEC_NEVER_LOAD for a
+       STYP_INFO section.
+       (coff_compute_section_file_positions): Force vma and lma of _LIB
+       section to be zero.
+       (coff_set_section_contents): Count number of entries in new lma
+       field, not in vma.
+       * coffgen.c (make_a_section_from_file): Force lineno_count of
+       SEC_SHARED_LIBRARY section to be zero, since it is non-zero on the
+       SCO 3.2v4 shared library.
+       * seclet.c (rel): Copy over any section with contents, not just
+       loadable sections.
+
+       * coff-mips.c (ecoff_make_empty_symbol): Zero out newly allocated
+       symbol.
+
        * coff-i386.c (coff_i386_reloc): New function, to generate
        relocateable output correctly.
        (howto_table): Use coff_i386_reloc for all reloc types.
index 595c19b..1148039 100644 (file)
@@ -59,12 +59,6 @@ typedef struct ecoff_symbol_struct
    macro is only ever applied to an asymbol.  */
 #define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
 
-/* This is a hack borrowed from coffcode.h; we need to save the index
-   of a symbol when we write it out so that can set the symbol index
-   correctly when we write out the relocs.  */
-#define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata)
-#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx))
-
 /* The page boundary used to align sections in the executable file.  */
 #define PAGE_SIZE 0x2000
 
@@ -122,6 +116,12 @@ static bfd_reloc_status_type ecoff_refhi_reloc PARAMS ((bfd *abfd,
                                                        PTR data,
                                                        asection *section,
                                                        bfd *output_bfd));
+static bfd_reloc_status_type ecoff_reflo_reloc PARAMS ((bfd *abfd,
+                                                       arelent *reloc,
+                                                       asymbol *symbol,
+                                                       PTR data,
+                                                       asection *section,
+                                                       bfd *output_bfd));
 static bfd_reloc_status_type ecoff_gprel_reloc PARAMS ((bfd *abfd,
                                                        arelent *reloc,
                                                        asymbol *symbol,
@@ -264,7 +264,7 @@ ecoff_mkobject (abfd)
      bfd *abfd;
 {
   abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
-                               bfd_zalloc (abfd, sizeof(ecoff_data_type)));
+                               bfd_zalloc (abfd, sizeof (ecoff_data_type)));
   if (abfd->tdata.ecoff_obj_data == NULL)
     {
       bfd_error = no_memory;
@@ -294,6 +294,7 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
     return NULL;
 
   ecoff = ecoff_data (abfd);
+  ecoff->gp_size = 8;
   ecoff->sym_filepos = internal_f->f_symptr;
 
   if (internal_a != (struct internal_aouthdr *) NULL)
@@ -618,6 +619,7 @@ ecoff_make_empty_symbol (abfd)
       bfd_error = no_memory;
       return (asymbol *) NULL;
     }
+  memset (new, 0, sizeof *new);
   new->symbol.section = (asection *) NULL;
   new->fdr = (FDR *) NULL;
   new->local = false;
@@ -648,7 +650,13 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
     case stLabel:
     case stProc:
     case stStaticProc:
+      break;
     case stNil:
+      if (MIPS_IS_STAB (ecoff_sym))
+       {
+         asym->flags = BSF_DEBUGGING;
+         return;
+       }
       break;
     default:
       asym->flags = BSF_DEBUGGING;
@@ -724,14 +732,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
       asym->flags = BSF_DEBUGGING;
       break;
     case scCommon:
-      /* FIXME: We should take a -G argument, which gives the maximum
-        size of objects to be put in the small common section.  Until
-        we do, we put objects of sizes up to 8 in the small common
-        section.  The assembler should do this for us, but the native
-        assembler seems to get confused.  */
-      if (asym->value > 8)
+      if (asym->value > ecoff_data (abfd)->gp_size)
        {
          asym->section = &bfd_com_section;
+         asym->flags = 0;
          break;
        }
       /* Fall through.  */
@@ -1491,10 +1495,11 @@ ecoff_swap_reloc_out (abfd, src, dst)
 
 /* ECOFF relocs are either against external symbols, or against
    sections.  If we are producing relocateable output, and the reloc
-   is against an external symbol, the resulting reloc will also be
-   against the same symbol.  In such a case, we don't want to change
-   anything about the way the reloc is handled, since it will all be
-   done at final link time.  Rather than put special case code into
+   is against an external symbol, and nothing has given us any
+   additional addend, the resulting reloc will also be against the
+   same symbol.  In such a case, we don't want to change anything
+   about the way the reloc is handled, since it will all be done at
+   final link time.  Rather than put special case code into
    bfd_perform_relocation, all the reloc types use this howto
    function.  It just short circuits the reloc if producing
    relocateable output against an external symbol.  */
@@ -1514,7 +1519,8 @@ ecoff_generic_reloc (abfd,
      bfd *output_bfd;
 {
   if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) == 0)
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && reloc_entry->addend == 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1523,9 +1529,14 @@ ecoff_generic_reloc (abfd,
   return bfd_reloc_continue;
 }
 
-/* Do a REFHI relocation.  The next reloc must be the corresponding
-   REFLO.  This has to be done in a function so that carry is handled
-   correctly.  */
+/* Do a REFHI relocation.  This has to be done in combination with a
+   REFLO reloc, because there is a carry from the REFLO to the REFHI.
+   Here we just save the information we need; we do the actual
+   relocation when we see the REFLO.  ECOFF requires that the REFLO
+   immediately follow the REFHI, so this ought to work.  */
+
+static bfd_byte *ecoff_refhi_addr;
+static bfd_vma ecoff_refhi_addend;
 
 static bfd_reloc_status_type
 ecoff_refhi_reloc (abfd,
@@ -1542,16 +1553,13 @@ ecoff_refhi_reloc (abfd,
      bfd *output_bfd;
 {
   bfd_reloc_status_type ret;
-  arelent *rello;
   bfd_vma relocation;
-  unsigned long insn;
-  unsigned long val;
-  unsigned long vallo;
 
   /* If we're relocating, and this an external symbol, we don't want
      to change anything.  */
   if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) == 0)
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && reloc_entry->addend == 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1562,10 +1570,6 @@ ecoff_refhi_reloc (abfd,
       && output_bfd == (bfd *) NULL)
     ret = bfd_reloc_undefined;
 
-  rello = reloc_entry + 1;
-  BFD_ASSERT (rello->howto->type == ECOFF_R_REFLO
-             && *rello->sym_ptr_ptr == *reloc_entry->sym_ptr_ptr);
-
   if (bfd_is_com_section (symbol->section))
     relocation = 0;
   else
@@ -1578,30 +1582,71 @@ ecoff_refhi_reloc (abfd,
   if (reloc_entry->address > input_section->_cooked_size)
     return bfd_reloc_outofrange;
 
-  insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
-  vallo = bfd_get_32 (abfd, (bfd_byte *) data + rello->address) & 0xffff;
-  val = ((insn & 0xffff) << 16) + vallo;
-  val += relocation;
-
-  /* The low order 16 bits are always treated as a signed value.
-     Therefore, a negative value in the low order bits requires an
-     adjustment in the high order bits.  We need to make this
-     adjustment in two ways: once for the bits we took from the data,
-     and once for the bits we are putting back in to the data.  */
-  if ((vallo & 0x8000) != 0)
-    val -= 0x10000;
-  if ((val & 0x8000) != 0)
-    val += 0x10000;
-
-  insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
-  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+  /* Save the information, and let REFLO do the actual relocation.  */
+  ecoff_refhi_addr = (bfd_byte *) data + reloc_entry->address;
+  ecoff_refhi_addend = relocation;
 
-  if (output_bfd != (bfd *) NULL) 
+  if (output_bfd != (bfd *) NULL)
     reloc_entry->address += input_section->output_offset;
 
   return ret;
 }
 
+/* Do a REFLO relocation.  This is a straightforward 16 bit inplace
+   relocation; this function exists in order to do the REFHI
+   relocation described above.  */
+
+static bfd_reloc_status_type
+ecoff_reflo_reloc (abfd,
+                  reloc_entry,
+                  symbol,
+                  data,
+                  input_section,
+                  output_bfd)
+     bfd *abfd;
+     arelent *reloc_entry;
+     asymbol *symbol;
+     PTR data;
+     asection *input_section;
+     bfd *output_bfd;
+{
+  if (ecoff_refhi_addr != (bfd_byte *) NULL)
+    {
+      unsigned long insn;
+      unsigned long val;
+      unsigned long vallo;
+
+      /* Do the REFHI relocation.  Note that we actually don't need to
+        know anything about the REFLO itself, except where to find
+        the low 16 bits of the addend needed by the REFHI.  */
+      insn = bfd_get_32 (abfd, ecoff_refhi_addr);
+      vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
+              & 0xffff);
+      val = ((insn & 0xffff) << 16) + vallo;
+      val += ecoff_refhi_addend;
+
+      /* The low order 16 bits are always treated as a signed value.
+        Therefore, a negative value in the low order bits requires an
+        adjustment in the high order bits.  We need to make this
+        adjustment in two ways: once for the bits we took from the
+        data, and once for the bits we are putting back in to the
+        data.  */
+      if ((vallo & 0x8000) != 0)
+       val -= 0x10000;
+      if ((val & 0x8000) != 0)
+       val += 0x10000;
+
+      insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
+      bfd_put_32 (abfd, insn, ecoff_refhi_addr);
+
+      ecoff_refhi_addr = (bfd_byte *) NULL;
+    }
+
+  /* Now do the REFLO reloc in the usual way.  */
+  return ecoff_generic_reloc (abfd, reloc_entry, symbol, data,
+                             input_section, output_bfd);
+}
+
 /* Do a GPREL relocation.  This is a 16 bit value which must become
    the offset from the gp register.  */
 
@@ -1624,10 +1669,13 @@ ecoff_gprel_reloc (abfd,
   unsigned long val;
   unsigned long insn;
 
-  /* If we're relocating, and this an external symbol, we don't want
-     to change anything.  */
+  /* If we're relocating, and this is an external symbol with no
+     addend, we don't want to change anything.  We will only have an
+     addend if this is a newly created reloc, not read from an ECOFF
+     file.  */
   if (output_bfd != (bfd *) NULL
-      && (symbol->flags & BSF_SECTION_SYM) == 0)
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && reloc_entry->addend == 0)
     {
       reloc_entry->address += input_section->output_offset;
       return bfd_reloc_ok;
@@ -1648,8 +1696,11 @@ ecoff_gprel_reloc (abfd,
   /* We have to figure out the gp value, so that we can adjust the
      symbol value correctly.  We look up the symbol _gp in the output
      BFD.  If we can't find it, we're stuck.  We cache it in the ECOFF
-     target data.  */
-  if (ecoff_data (output_bfd)->gp == 0)
+     target data.  We don't need to adjust the symbol value for an
+     external symbol if we are producing relocateable output.  */
+  if (ecoff_data (output_bfd)->gp == 0
+      && (relocateable == false
+         || (symbol->flags & BSF_SECTION_SYM) != 0))
     {
       if (relocateable != false)
        {
@@ -1703,15 +1754,17 @@ ecoff_gprel_reloc (abfd,
 
   insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
 
-  /* Set val to the offset into the section (if we are relocating
-     against an external symbol, insn & 0xffff will be zero and so
-     will reloc_entry->addend).  */
+  /* Set val to the offset into the section or symbol.  */
   val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
   if (val & 0x8000)
     val -= 0x10000;
 
-  /* Adjust val for the final section location and GP value.  */
-  val += (relocation - ecoff_data (output_bfd)->gp);
+  /* Adjust val for the final section location and GP value.  If we
+     are producing relocateable output, we don't want to do this for
+     an external symbol.  */
+  if (relocateable == false
+      || (symbol->flags & BSF_SECTION_SYM) != 0)
+    val += relocation - ecoff_data (output_bfd)->gp;
 
   insn = (insn &~ 0xffff) | (val & 0xffff);
   bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
@@ -1822,7 +1875,7 @@ static reloc_howto_type ecoff_howto_table[] =
         0,                     /* bitpos */
         false,                 /* absolute (obsolete) */
         true,                  /* complain_on_overflow */
-        ecoff_generic_reloc,   /* special_function */
+        ecoff_reflo_reloc,     /* special_function */
         "REFLO",               /* name */
         true,                  /* partial_inplace */
         0xffff,                /* src_mask */
@@ -2041,6 +2094,9 @@ ecoff_bfd_reloc_type_lookup (abfd, code)
     case BFD_RELOC_LO16:
       ecoff_type = ECOFF_R_REFLO;
       break;
+    case BFD_RELOC_MIPS_GPREL:
+      ecoff_type = ECOFF_R_GPREL;
+      break;
     default:
       return (CONST struct reloc_howto_struct *) NULL;
     }
index 5b4d764..5dcc59a 100644 (file)
@@ -79,10 +79,7 @@ DEFUN(rel,(abfd, seclet, output_section, data, relocateable),
       PTR data AND
       boolean relocateable)
 {
-
-  if (output_section->flags & SEC_HAS_CONTENTS 
-      && !(output_section->flags & SEC_NEVER_LOAD)
-      && (output_section->flags & SEC_LOAD)
+  if ((output_section->flags & SEC_HAS_CONTENTS) != 0
       && seclet->size)
   {
     data = (PTR) bfd_get_relocated_section_contents(abfd, seclet, data,