* libecoff.h (struct ecoff_backend_data): Add adjust_headers
authorIan Lance Taylor <ian@airs.com>
Thu, 5 Oct 1995 17:48:32 +0000 (17:48 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 5 Oct 1995 17:48:32 +0000 (17:48 +0000)
field.
* ecoff.c (ecoff_sec_to_styp_flags): Check for various Alpha
sections, and set styp correctly for them: .got, .hash, .dynamic,
.liblist, .rel.dyn, .conflic, .dynstr, .dynsym, .comment.
(_bfd_ecoff_styp_to_sec_flags): Check for various Alpha section
types.
(ecoff_sort_hdrs): New static function.
(ecoff_compute_section_file_positions): Return boolean, not void.
Sort the sections by VMA before looking through them.  Put the
first non SEC_ALLOC section on a new page.  Put every SEC_ALLOC
section on an appropriate boundary within the page.
(ecoff_compute_reloc_file_positions): Check return value of
ecoff_compute_section_file_positions.
(_bfd_ecoff_set_section_contents): Likewise.
(_bfd_ecoff_write_object_contents): Check for various Alpha
section types when incrementing text_size and data_size.  Call
adjust_headers backend function if it exists.
* coff-alpha.c (alpha_adjust_headers): New static function.
(alpha_ecoff_backend_data): Initialize adjust_headers field.
* coff-mips.c (mips_ecoff_backend_data): Likewise.
PR 8141.

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

index ffede82..d04ff1c 100644 (file)
@@ -1,5 +1,27 @@
 Thu Oct  5 11:45:02 1995  Ian Lance Taylor  <ian@cygnus.com>
 
+       * libecoff.h (struct ecoff_backend_data): Add adjust_headers
+       field.
+       * ecoff.c (ecoff_sec_to_styp_flags): Check for various Alpha
+       sections, and set styp correctly for them: .got, .hash, .dynamic,
+       .liblist, .rel.dyn, .conflic, .dynstr, .dynsym, .comment.
+       (_bfd_ecoff_styp_to_sec_flags): Check for various Alpha section
+       types.
+       (ecoff_sort_hdrs): New static function.
+       (ecoff_compute_section_file_positions): Return boolean, not void.
+       Sort the sections by VMA before looking through them.  Put the
+       first non SEC_ALLOC section on a new page.  Put every SEC_ALLOC
+       section on an appropriate boundary within the page.
+       (ecoff_compute_reloc_file_positions): Check return value of
+       ecoff_compute_section_file_positions.
+       (_bfd_ecoff_set_section_contents): Likewise.
+       (_bfd_ecoff_write_object_contents): Check for various Alpha
+       section types when incrementing text_size and data_size.  Call
+       adjust_headers backend function if it exists.
+       * coff-alpha.c (alpha_adjust_headers): New static function.
+       (alpha_ecoff_backend_data): Initialize adjust_headers field.
+       * coff-mips.c (mips_ecoff_backend_data): Likewise.
+
        * hosts/i386bsd.h: Restore file incorrectly deleted on Sep 6.
 
 Wed Oct  4 18:15:02 1995  Jeff Law  (law@hurl.cygnus.com)
index 8d0b3a5..d914d4d 100644 (file)
@@ -55,6 +55,8 @@ static bfd_vma alpha_convert_external_reloc
 static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
                                               bfd *, asection *,
                                               bfd_byte *, PTR));
+static boolean alpha_adjust_headers
+  PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *));
 \f
 /* ECOFF has COFF sections, but the debugging information is stored in
    a completely different format.  ECOFF targets use some of the
@@ -1935,6 +1937,23 @@ alpha_relocate_section (output_bfd, info, input_bfd, input_section,
   return true;
 }
 \f
+/* Do final adjustments to the filehdr and the aouthdr.  This routine
+   sets the dynamic bits in the file header.  */
+
+/*ARGSUSED*/
+static boolean
+alpha_adjust_headers (abfd, fhdr, ahdr)
+     bfd *abfd;
+     struct internal_filehdr *fhdr;
+     struct internal_aouthdr *ahdr;
+{
+  if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P))
+    fhdr->f_flags |= F_ALPHA_CALL_SHARED;
+  else if ((abfd->flags & DYNAMIC) != 0)
+    fhdr->f_flags |= F_ALPHA_SHARABLE;
+  return true;
+}
+\f
 /* This is the ECOFF backend structure.  The backend field of the
    target vector points to this.  */
 
@@ -1956,8 +1975,7 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
     alpha_ecoff_swap_scnhdr_in, NULL,
     alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
     alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
-    _bfd_ecoff_make_section_hook, _bfd_ecoff_set_alignment_hook,
-    _bfd_ecoff_slurp_symbol_table,
+    _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL
   },
   /* Supported architecture.  */
@@ -2023,7 +2041,9 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
   alpha_adjust_reloc_in,
   alpha_adjust_reloc_out,
   /* Relocate section contents while linking.  */
-  alpha_relocate_section
+  alpha_relocate_section,
+  /* Do final adjustments to filehdr and aouthdr.  */
+  alpha_adjust_headers
 };
 
 /* Looking up a reloc type is Alpha specific.  */
index c8cb744..e1a269f 100644 (file)
@@ -2441,8 +2441,7 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
     mips_ecoff_swap_scnhdr_in, NULL,
     mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
     _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
-    _bfd_ecoff_make_section_hook, _bfd_ecoff_set_alignment_hook,
-    _bfd_ecoff_slurp_symbol_table,
+    _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL
   },
   /* Supported architecture.  */
@@ -2508,7 +2507,9 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
   mips_adjust_reloc_in,
   mips_adjust_reloc_out,
   /* Relocate section contents while linking.  */
-  mips_relocate_section
+  mips_relocate_section,
+  /* Do final adjustments to filehdr and aouthdr.  */
+  NULL
 };
 
 /* Looking up a reloc type is MIPS specific.  */
index 1fe4f75..8b40eb5 100644 (file)
@@ -59,7 +59,8 @@ static char *ecoff_type_to_string PARAMS ((bfd *abfd, FDR *fdr,
                                           unsigned int indx));
 static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
                                                asymbol **symbols));
-static void ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
+static int ecoff_sort_hdrs PARAMS ((const PTR, const PTR));
+static boolean ecoff_compute_section_file_positions PARAMS ((bfd *abfd));
 static bfd_size_type ecoff_compute_reloc_file_positions PARAMS ((bfd *abfd));
 static boolean ecoff_get_extr PARAMS ((asymbol *, EXTR *));
 static void ecoff_set_index PARAMS ((asymbol *, bfd_size_type));
@@ -135,17 +136,6 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
   return (PTR) ecoff;
 }
 
-/* This is a hook needed by SCO COFF, but we have nothing to do.  */
-
-/*ARGSUSED*/
-asection *
-_bfd_ecoff_make_section_hook (abfd, name)
-     bfd *abfd;
-     char *name;
-{
-  return (asection *) NULL;
-}
-
 /* Initialize a new section.  */
 
 boolean
@@ -324,6 +314,27 @@ ecoff_sec_to_styp_flags (name, flags)
     styp = STYP_XDATA;
   else if (strcmp (name, _LIB) == 0)
     styp = STYP_ECOFF_LIB;
+  else if (strcmp (name, _GOT) == 0)
+    styp = STYP_GOT;
+  else if (strcmp (name, _HASH) == 0)
+    styp = STYP_HASH;
+  else if (strcmp (name, _DYNAMIC) == 0)
+    styp = STYP_DYNAMIC;
+  else if (strcmp (name, _LIBLIST) == 0)
+    styp = STYP_LIBLIST;
+  else if (strcmp (name, _RELDYN) == 0)
+    styp = STYP_RELDYN;
+  else if (strcmp (name, _CONFLIC) == 0)
+    styp = STYP_CONFLIC;
+  else if (strcmp (name, _DYNSTR) == 0)
+    styp = STYP_DYNSTR;
+  else if (strcmp (name, _DYNSYM) == 0)
+    styp = STYP_DYNSYM;
+  else if (strcmp (name, _COMMENT) == 0)
+    {
+      styp = STYP_COMMENT;
+      flags &=~ SEC_NEVER_LOAD;
+    }
   else if (flags & SEC_CODE) 
     styp = STYP_TEXT;
   else if (flags & SEC_DATA) 
@@ -361,7 +372,14 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
      actually a shared library section.  */
   if ((styp_flags & STYP_TEXT)
       || (styp_flags & STYP_ECOFF_INIT)
-      || (styp_flags & STYP_ECOFF_FINI))
+      || (styp_flags & STYP_ECOFF_FINI)
+      || (styp_flags & STYP_DYNAMIC)
+      || (styp_flags & STYP_LIBLIST)
+      || (styp_flags & STYP_RELDYN)
+      || styp_flags == STYP_CONFLIC
+      || (styp_flags & STYP_DYNSTR)
+      || (styp_flags & STYP_DYNSYM)
+      || (styp_flags & STYP_HASH))
     {
       if (sec_flags & SEC_NEVER_LOAD)
        sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
@@ -372,7 +390,8 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
           || (styp_flags & STYP_RDATA)
           || (styp_flags & STYP_SDATA)
           || styp_flags == STYP_PDATA
-          || styp_flags == STYP_XDATA)
+          || styp_flags == STYP_XDATA
+          || (styp_flags & STYP_GOT))
     {
       if (sec_flags & SEC_NEVER_LOAD)
        sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
@@ -2011,27 +2030,77 @@ _bfd_ecoff_get_section_contents (abfd, section, location, offset, count)
                                            offset, count);
 }
 
+/* Sort sections by VMA, but put SEC_ALLOC sections first.  This is
+   called via qsort.  */
+
+static int
+ecoff_sort_hdrs (arg1, arg2)
+     const PTR arg1;
+     const PTR arg2;
+{
+  const asection *hdr1 = *(const asection **) arg1;
+  const asection *hdr2 = *(const asection **) arg2;
+
+  if ((hdr1->flags & SEC_ALLOC) != 0)
+    {
+      if ((hdr2->flags & SEC_ALLOC) == 0)
+       return -1;
+    }
+  else
+    {
+      if ((hdr2->flags & SEC_ALLOC) != 0)
+       return 1;
+    }
+  if (hdr1->vma < hdr2->vma)
+    return -1;
+  else if (hdr1->vma > hdr2->vma)
+    return 1;
+  else
+    return 0;
+}
+
 /* Calculate the file position for each section, and set
    reloc_filepos.  */
 
-static void
+static boolean
 ecoff_compute_section_file_positions (abfd)
      bfd *abfd;
 {
-  asection *current;
   file_ptr sofar;
+  asection **sorted_hdrs;
+  asection *current;
+  unsigned int i;
   file_ptr old_sofar;
-  boolean first_data;
+  boolean first_data, first_nonalloc;
+  const bfd_vma round = ecoff_backend (abfd)->round;
 
   sofar = _bfd_ecoff_sizeof_headers (abfd, false);
 
+  /* Sort the sections by VMA.  */
+  sorted_hdrs = (asection **) malloc (abfd->section_count
+                                     * sizeof (asection *));
+  if (sorted_hdrs == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return false;
+    }
+  for (current = abfd->sections, i = 0;
+       current != NULL;
+       current = current->next, i++)
+    sorted_hdrs[i] = current;
+  BFD_ASSERT (i == abfd->section_count);
+
+  qsort (sorted_hdrs, abfd->section_count, sizeof (asection *),
+        ecoff_sort_hdrs);
+
   first_data = true;
-  for (current = abfd->sections;
-       current != (asection *) NULL;
-       current = current->next)
+  first_nonalloc = true;
+  for (i = 0; i < abfd->section_count; i++)
     {
       unsigned int alignment_power;
 
+      current = sorted_hdrs[i];
+
       /* Only deal with sections which have contents */
       if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
        continue;
@@ -2062,26 +2131,37 @@ ecoff_compute_section_file_positions (abfd)
              || strcmp (current->name, _RDATA) != 0)
          && strcmp (current->name, _PDATA) != 0)
        {
-         const bfd_vma round = ecoff_backend (abfd)->round;
-
          sofar = (sofar + round - 1) &~ (round - 1);
          first_data = false;
        }
       else if (strcmp (current->name, _LIB) == 0)
        {
-         const bfd_vma round = ecoff_backend (abfd)->round;
          /* On Irix 4, the location of contents of the .lib section
             from a shared library section is also rounded up to a
             page boundary.  */
 
          sofar = (sofar + round - 1) &~ (round - 1);
        }
+      else if (first_nonalloc
+              && (current->flags & SEC_ALLOC) == 0
+              && (abfd->flags & D_PAGED) != 0)
+       {
+         /* Skip up to the next page for an unallocated section, such
+             as the .comment section on the Alpha.  This leaves room
+             for the .bss section.  */
+         first_nonalloc = false;
+         sofar = (sofar + round - 1) &~ (round - 1);
+       }
 
       /* Align the sections in the file to the same boundary on
         which they are aligned in virtual memory.  */
       old_sofar = sofar;
       sofar = BFD_ALIGN (sofar, 1 << alignment_power);
 
+      if ((abfd->flags & D_PAGED) != 0
+         && (current->flags & SEC_ALLOC) != 0)
+       sofar += (current->vma - sofar) % round;
+
       current->filepos = sofar;
 
       sofar += current->_raw_size;
@@ -2092,7 +2172,12 @@ ecoff_compute_section_file_positions (abfd)
       current->_raw_size += sofar - old_sofar;
     }
 
+  free (sorted_hdrs);
+  sorted_hdrs = NULL;
+
   ecoff_data (abfd)->reloc_filepos = sofar;
+
+  return true;
 }
 
 /* Determine the location of the relocs for all the sections in the
@@ -2112,7 +2197,8 @@ ecoff_compute_reloc_file_positions (abfd)
 
   if (! abfd->output_has_begun)
     {
-      ecoff_compute_section_file_positions (abfd);
+      if (! ecoff_compute_section_file_positions (abfd))
+       abort ();
       abfd->output_has_begun = true;
     }
   
@@ -2164,7 +2250,10 @@ _bfd_ecoff_set_section_contents (abfd, section, location, offset, count)
   /* This must be done first, because bfd_set_section_contents is
      going to set output_has_begun to true.  */
   if (abfd->output_has_begun == false)
-    ecoff_compute_section_file_positions (abfd);
+    {
+      if (! ecoff_compute_section_file_positions (abfd))
+       return false;
+    }
 
   /* If this is a .lib section, bump the vma address so that it winds
      up being the number of .lib sections output.  This is right for
@@ -2472,7 +2561,16 @@ _bfd_ecoff_write_object_contents (abfd)
       if ((section.s_flags & STYP_TEXT) != 0
          || ((section.s_flags & STYP_RDATA) != 0
              && backend->rdata_in_text)
-         || strcmp (current->name, _PDATA) == 0)
+         || section.s_flags == STYP_PDATA
+         || (section.s_flags & STYP_DYNAMIC) != 0
+         || (section.s_flags & STYP_LIBLIST) != 0
+         || (section.s_flags & STYP_RELDYN) != 0
+         || section.s_flags == STYP_CONFLIC
+         || (section.s_flags & STYP_DYNSTR) != 0
+         || (section.s_flags & STYP_DYNSYM) != 0
+         || (section.s_flags & STYP_HASH) != 0
+         || (section.s_flags & STYP_ECOFF_INIT) != 0
+         || (section.s_flags & STYP_ECOFF_FINI) != 0)
        {
          text_size += bfd_get_section_size_before_reloc (current);
          if (! set_text_start || text_start > vma)
@@ -2487,7 +2585,8 @@ _bfd_ecoff_write_object_contents (abfd)
               || (section.s_flags & STYP_LIT8) != 0
               || (section.s_flags & STYP_LIT4) != 0
               || (section.s_flags & STYP_SDATA) != 0
-              || strcmp (current->name, _XDATA) == 0)
+              || section.s_flags == STYP_XDATA
+              || (section.s_flags & STYP_GOT) != 0)
        {
          data_size += bfd_get_section_size_before_reloc (current);
          if (! set_data_start || data_start > vma)
@@ -2499,7 +2598,9 @@ _bfd_ecoff_write_object_contents (abfd)
       else if ((section.s_flags & STYP_BSS) != 0
               || (section.s_flags & STYP_SBSS) != 0)
        bss_size += bfd_get_section_size_before_reloc (current);
-      else if ((section.s_flags & STYP_ECOFF_LIB) != 0)
+      else if (section.s_flags == 0
+              || (section.s_flags & STYP_ECOFF_LIB) != 0
+              || section.s_flags == STYP_COMMENT)
        /* Do nothing */ ;
       else
        abort ();
@@ -2591,6 +2692,13 @@ _bfd_ecoff_write_object_contents (abfd)
   for (i = 0; i < 4; i++)
     internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i];
 
+  /* Let the backend adjust the headers if necessary.  */
+  if (backend->adjust_headers)
+    {
+      if (! (*backend->adjust_headers) (abfd, &internal_f, &internal_a))
+       goto error_return;
+    }
+
   /* Write out the file header and the optional header.  */
 
   if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
index d16e3fa..e8af957 100644 (file)
@@ -68,6 +68,9 @@ struct ecoff_backend_data
                                       bfd *input_bfd, asection *input_section,
                                       bfd_byte *contents,
                                       PTR external_relocs));
+  /* Do final adjustments to filehdr and aouthdr.  */
+  boolean (*adjust_headers) PARAMS ((bfd *, struct internal_filehdr *,
+                                    struct internal_aouthdr *));
 };
 
 /* This is the target specific information kept for ECOFF files.  */
@@ -312,7 +315,6 @@ extern boolean _bfd_ecoff_bfd_final_link
 /* Hook functions for the generic COFF section reading code.  */
 
 extern PTR _bfd_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));
-extern asection *_bfd_ecoff_make_section_hook PARAMS ((bfd *abfd, char *name));
 #define _bfd_ecoff_set_alignment_hook \
   ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
 extern boolean _bfd_ecoff_set_arch_mach_hook PARAMS ((bfd *abfd, PTR filehdr));