* ecoff.c (ecoff_mkobject): Check bfd_make_section return value.
authorIan Lance Taylor <ian@airs.com>
Mon, 11 Oct 1993 21:38:38 +0000 (21:38 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 11 Oct 1993 21:38:38 +0000 (21:38 +0000)
(ecoff_mkobject_hook): New function.
(ecoff_new_section_hook, ecoff_sizeof_headers,
ecoff_compute_section_file_positions, ecoff_set_section_contents,
ecoff_write_object_contents): Handle dummy REGINFO section.
(ecoff_get_section_contents): New function to handle reading
REGINFO section.
* libecoff.h (ecoff_get_section_contents): Change from macro
definition to function prototype.
(ecoff_mkobject_hook): New prototype.
* coff-alpha.c (alpha_ecoff_mkobject_hook): Removed.
(alpha_ecoff_backend_data): Use ecoff_mkobject_hook.
* coff-mips.c (mips_ecoff_mkobject_hook): Removed.
(mips_ecoff_backend_data): Use ecoff_mkobject_hook.

bfd/ChangeLog
bfd/ecoff.c

index f924da6ab1b823a429a49a89d8c4a8239078673f..effc8daea2c91af0092544dba2d4c2aa1366f4da 100644 (file)
@@ -1,3 +1,20 @@
+Mon Oct 11 17:25:18 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       * ecoff.c (ecoff_mkobject): Check bfd_make_section return value.
+       (ecoff_mkobject_hook): New function.
+       (ecoff_new_section_hook, ecoff_sizeof_headers,
+       ecoff_compute_section_file_positions, ecoff_set_section_contents,
+       ecoff_write_object_contents): Handle dummy REGINFO section.
+       (ecoff_get_section_contents): New function to handle reading
+       REGINFO section.
+       * libecoff.h (ecoff_get_section_contents): Change from macro
+       definition to function prototype.
+       (ecoff_mkobject_hook): New prototype.
+       * coff-alpha.c (alpha_ecoff_mkobject_hook): Removed.
+       (alpha_ecoff_backend_data): Use ecoff_mkobject_hook.
+       * coff-mips.c (mips_ecoff_mkobject_hook): Removed.
+       (mips_ecoff_backend_data): Use ecoff_mkobject_hook.
+
 Fri Oct  8 15:25:33 1993  Peter Schauer  (pes@regent.e-technik.tu-muenchen.de)
 
        * libbfd.c (bfd_get*32, bfd_get*64):  Prevent ANSI sign extension
index 68fe010fcc58f93ef3897cdff90c00b31a0d00b4..4accb5cde3ca94011f7abc925da502a9ceb80565 100644 (file)
@@ -44,6 +44,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 \f
 /* Prototypes for static functions.  */
 
+static int ecoff_get_magic PARAMS ((bfd *abfd));
 static void ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
                                           asymbol *asym, int ext,
                                           asymbol **indirect_ptr_ptr));
@@ -93,11 +94,64 @@ ecoff_mkobject (abfd)
 
   /* Always create a .scommon section for every BFD.  This is a hack so
      that the linker has something to attach scSCommon symbols to.  */
-  bfd_make_section (abfd, SCOMMON);
+  if (bfd_make_section (abfd, SCOMMON) == NULL)
+    return false;
 
   return true;
 }
 
+/* This is a hook called by coff_real_object_p to create any backend
+   specific information.  */
+
+PTR
+ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+     bfd *abfd;
+     PTR filehdr;
+     PTR aouthdr;
+{
+  struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+  struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
+  ecoff_data_type *ecoff;
+  asection *regsec;
+
+  if (ecoff_mkobject (abfd) == false)
+    return NULL;
+
+  ecoff = ecoff_data (abfd);
+  ecoff->gp_size = 8;
+  ecoff->sym_filepos = internal_f->f_symptr;
+
+  /* Create the .reginfo section to give programs outside BFD a way to
+     see the information stored in the a.out header.  See the comment
+     in coff/ecoff.h.  */
+  regsec = bfd_make_section (abfd, REGINFO);
+  if (regsec == NULL)
+    return NULL;
+
+  if (internal_a != (struct internal_aouthdr *) NULL)
+    {
+      int i;
+
+      ecoff->text_start = internal_a->text_start;
+      ecoff->text_end = internal_a->text_start + internal_a->tsize;
+      ecoff->gp = internal_a->gp_value;
+      ecoff->gprmask = internal_a->gprmask;
+      for (i = 0; i < 4; i++)
+       ecoff->cprmask[i] = internal_a->cprmask[i];
+      ecoff->fprmask = internal_a->fprmask;
+      if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
+       abfd->flags |= D_PAGED;
+    }
+
+  /* It turns out that no special action is required by the MIPS or
+     Alpha ECOFF backends.  They have different information in the
+     a.out header, but we just copy it all (e.g., gprmask, cprmask and
+     fprmask) and let the swapping routines ensure that only relevant
+     information is written out.  */
+
+  return (PTR) ecoff;
+}
+
 /* This is a hook needed by SCO COFF, but we have nothing to do.  */
 
 asection *
@@ -129,6 +183,11 @@ ecoff_new_section_hook (abfd, section)
   else if (strcmp (section->name, _BSS) == 0
           || strcmp (section->name, _SBSS) == 0)
     section->flags |= SEC_ALLOC;
+  else if (strcmp (section->name, REGINFO) == 0)
+    {
+      section->flags |= SEC_HAS_CONTENTS | SEC_NEVER_LOAD;
+      section->_raw_size = sizeof (struct ecoff_reginfo);
+    }
 
   /* Probably any other section name is SEC_NEVER_LOAD, but I'm
      uncertain about .init on some systems and I don't know how shared
@@ -137,7 +196,10 @@ ecoff_new_section_hook (abfd, section)
   return true;
 }
 
-/* Determine the machine architecture and type.  */
+/* Determine the machine architecture and type.  This is called from
+   the generic COFF routines.  It is the inverse of ecoff_get_magic,
+   below.  This could be an ECOFF backend routine, with one version
+   for each target, but there aren't all that many ECOFF targets.  */
 
 boolean
 ecoff_set_arch_mach_hook (abfd, filehdr)
@@ -146,6 +208,7 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
 {
   struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
   enum bfd_architecture arch;
+  unsigned long mach;
 
   switch (internal_f->f_magic)
     {
@@ -153,20 +216,78 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
     case MIPS_MAGIC_LITTLE:
     case MIPS_MAGIC_BIG:
       arch = bfd_arch_mips;
+      mach = 3000;
+      break;
+
+    case MIPS_MAGIC_LITTLE2:
+    case MIPS_MAGIC_BIG2:
+      /* MIPS ISA level 2: the r6000 */
+      arch = bfd_arch_mips;
+      mach = 6000;
+      break;
+
+    case MIPS_MAGIC_LITTLE3:
+    case MIPS_MAGIC_BIG3:
+      /* MIPS ISA level 3: the r4000 */
+      arch = bfd_arch_mips;
+      mach = 4000;
       break;
 
     case ALPHA_MAGIC:
       arch = bfd_arch_alpha;
+      mach = 0;
       break;
 
     default:
       arch = bfd_arch_obscure;
+      mach = 0;
       break;
     }
 
-  bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
+  return bfd_default_set_arch_mach (abfd, arch, mach);
+}
 
-  return true;
+/* Get the magic number to use based on the architecture and machine.
+   This is the inverse of ecoff_set_arch_mach_hook, above.  */
+
+static int
+ecoff_get_magic (abfd)
+     bfd *abfd;
+{
+  int big, little;
+
+  switch (bfd_get_arch (abfd))
+    {
+    case bfd_arch_mips:
+      switch (bfd_get_mach (abfd))
+       {
+       default:
+       case 0:
+       case 3000:
+         big = MIPS_MAGIC_BIG;
+         little = MIPS_MAGIC_LITTLE;
+         break;
+
+       case 6000:
+         big = MIPS_MAGIC_BIG2;
+         little = MIPS_MAGIC_LITTLE2;
+         break;
+
+       case 4000:
+         big = MIPS_MAGIC_BIG3;
+         little = MIPS_MAGIC_LITTLE3;
+         break;
+       }
+
+      return abfd->xvec->byteorder_big_p ? big : little;
+
+    case bfd_arch_alpha:
+      return ALPHA_MAGIC;
+
+    default:
+      abort ();
+      return 0;
+    }
 }
 
 /* Get the section s_flags to use for a section.  */
@@ -198,6 +319,8 @@ ecoff_sec_to_styp_flags (name, flags)
     styp = STYP_SBSS;
   else if (strcmp (name, _INIT) == 0)
     styp = STYP_ECOFF_INIT;
+  else if (strcmp (name, _FINI) == 0)
+    styp = STYP_ECOFF_FINI;
   else if (flags & SEC_CODE) 
     styp = STYP_TEXT;
   else if (flags & SEC_DATA) 
@@ -232,7 +355,8 @@ ecoff_styp_to_sec_flags (abfd, hdr)
   /* For 386 COFF, at least, an unloadable text or data section is
      actually a shared library section.  */
   if ((styp_flags & STYP_TEXT)
-      || (styp_flags & STYP_ECOFF_INIT))
+      || (styp_flags & STYP_ECOFF_INIT)
+      || (styp_flags & STYP_ECOFF_FINI))
     {
       if (sec_flags & SEC_NEVER_LOAD)
        sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
@@ -483,6 +607,8 @@ ecoff_slurp_symbolic_info (abfd)
   char *fraw_src;
   char *fraw_end;
   struct fdr *fdr_ptr;
+  bfd_size_type raw_end;
+  bfd_size_type cb_end;
 
   /* Check whether we've already gotten it, and whether there's any to
      get.  */
@@ -530,30 +656,34 @@ ecoff_slurp_symbolic_info (abfd)
   /* Read all the symbolic information at once.  */
   raw_base = ecoff_data (abfd)->sym_filepos + external_hdr_size;
 
-  if (internal_symhdr->cbExtOffset != 0)
-    raw_size = (internal_symhdr->cbExtOffset
-               - raw_base
-               + internal_symhdr->iextMax * backend->external_ext_size);
-  else
-    {
-      long cbline, issmax, issextmax;
-
-      cbline = (internal_symhdr->cbLine + 3) &~ 3;
-      issmax = (internal_symhdr->issMax + 3) &~ 3;
-      issextmax = (internal_symhdr->issExtMax + 3) &~ 3;
-      raw_size = (cbline * sizeof (unsigned char)
-                 + internal_symhdr->idnMax * backend->external_dnr_size
-                 + internal_symhdr->ipdMax * backend->external_pdr_size
-                 + internal_symhdr->isymMax * backend->external_sym_size
-                 + internal_symhdr->ioptMax * backend->external_opt_size
-                 + internal_symhdr->iauxMax * sizeof (union aux_ext)
-                 + issmax * sizeof (char)
-                 + issextmax * sizeof (char)
-                 + internal_symhdr->ifdMax * backend->external_fdr_size
-                 + internal_symhdr->crfd * backend->external_rfd_size
-                 + internal_symhdr->iextMax * backend->external_ext_size);
-    }
-
+  /* Alpha ecoff makes the determination of raw_size difficult. It has
+     an undocumented debug data section between the symhdr and the first
+     documented section. And the ordering of the sections varies between
+     statically and dynamically linked executables.
+     If bfd supports SEEK_END someday, this code could be simplified.  */
+
+  raw_end = 0;
+
+#define UPDATE_RAW_END(start, count, size) \
+  cb_end = internal_symhdr->start + internal_symhdr->count * (size); \
+  if (cb_end > raw_end) \
+    raw_end = cb_end
+
+  UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));
+  UPDATE_RAW_END (cbDnOffset, idnMax, backend->external_dnr_size);
+  UPDATE_RAW_END (cbPdOffset, ipdMax, backend->external_pdr_size);
+  UPDATE_RAW_END (cbSymOffset, isymMax, backend->external_sym_size);
+  UPDATE_RAW_END (cbOptOffset, ioptMax, backend->external_opt_size);
+  UPDATE_RAW_END (cbAuxOffset, iauxMax, sizeof (union aux_ext));
+  UPDATE_RAW_END (cbSsOffset, issMax, sizeof (char));
+  UPDATE_RAW_END (cbSsExtOffset, issExtMax, sizeof (char));
+  UPDATE_RAW_END (cbFdOffset, ifdMax, backend->external_fdr_size);
+  UPDATE_RAW_END (cbRfdOffset, crfd, backend->external_rfd_size);
+  UPDATE_RAW_END (cbExtOffset, iextMax, backend->external_ext_size);
+
+#undef UPDATE_RAW_END
+
+  raw_size = raw_end - raw_base;
   if (raw_size == 0)
     {
       ecoff_data (abfd)->sym_filepos = 0;
@@ -2821,16 +2951,63 @@ ecoff_set_arch_mach (abfd, arch, machine)
 }
 
 /* Get the size of the section headers.  We do not output the .scommon
-   section which we created in ecoff_mkobject.  */
+   section which we created in ecoff_mkobject, nor do we output any
+   .reginfo section.  */
 
 int
 ecoff_sizeof_headers (abfd, reloc)
      bfd *abfd;
      boolean reloc;
 {
+  asection *current;
+  int c;
+
+  c = 0;
+  for (current = abfd->sections;
+       current != (asection *)NULL; 
+       current = current->next) 
+    if (strcmp (current->name, SCOMMON) != 0
+       && strcmp (current->name, REGINFO) != 0)
+      ++c;
+
   return (bfd_coff_filhsz (abfd)
          + bfd_coff_aoutsz (abfd)
-         + (abfd->section_count - 1) * bfd_coff_scnhsz (abfd));
+         + c * bfd_coff_scnhsz (abfd));
+}
+
+
+/* Get the contents of a section.  This is where we handle reading the
+   .reginfo section, which implicitly holds the contents of an
+   ecoff_reginfo structure.  */
+
+boolean
+ecoff_get_section_contents (abfd, section, location, offset, count)
+     bfd *abfd;
+     asection *section;
+     PTR location;
+     file_ptr offset;
+     bfd_size_type count;
+{
+  ecoff_data_type *tdata = ecoff_data (abfd);
+  struct ecoff_reginfo s;
+  int i;
+
+  if (strcmp (section->name, REGINFO) != 0)
+    return bfd_generic_get_section_contents (abfd, section, location,
+                                            offset, count);
+
+  s.gp_value = tdata->gp;
+  s.gprmask = tdata->gprmask;
+  for (i = 0; i < 4; i++)
+    s.cprmask[i] = tdata->cprmask[i];
+  s.fprmask = tdata->fprmask;
+
+  /* bfd_get_section_contents has already checked that the offset and
+     size is reasonable.  We don't have to worry about swapping or any
+     such thing; the .reginfo section is defined such that the
+     contents are an ecoff_reginfo structure as seen on the host.  */
+  memcpy (location, ((char *) &s) + offset, count);
+  return true;
 }
 
 /* Calculate the file position for each section, and set
@@ -2857,7 +3034,8 @@ ecoff_compute_section_file_positions (abfd)
     {
       /* Only deal with sections which have contents */
       if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
-         || strcmp (current->name, SCOMMON) == 0)
+         || strcmp (current->name, SCOMMON) == 0
+         || strcmp (current->name, REGINFO) == 0)
        continue;
 
       /* On Ultrix, the data sections in an executable file must be
@@ -2893,7 +3071,9 @@ ecoff_compute_section_file_positions (abfd)
   ecoff_data (abfd)->reloc_filepos = sofar;
 }
 
-/* Set the contents of a section.  */
+/* Set the contents of a section.  This is where we handle setting the
+   contents of the .reginfo section, which implicitly holds a
+   ecoff_reginfo structure.  */
 
 boolean
 ecoff_set_section_contents (abfd, section, location, offset, count)
@@ -2906,6 +3086,40 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
   if (abfd->output_has_begun == false)
     ecoff_compute_section_file_positions (abfd);
 
+  if (strcmp (section->name, REGINFO) == 0)
+    {
+      ecoff_data_type *tdata = ecoff_data (abfd);
+      struct ecoff_reginfo s;
+      int i;
+
+      /* If the caller is only changing part of the structure, we must
+        retrieve the current information before the memcpy.  */
+      if (offset != 0 || count != sizeof (struct ecoff_reginfo))
+       {
+         s.gp_value = tdata->gp;
+         s.gprmask = tdata->gprmask;
+         for (i = 0; i < 4; i++)
+           s.cprmask[i] = tdata->cprmask[i];
+         s.fprmask = tdata->fprmask;
+       }
+
+      /* bfd_set_section_contents has already checked that the offset
+        and size is reasonable.  We don't have to worry about
+        swapping or any such thing; the .reginfo section is defined
+        such that the contents are an ecoff_reginfo structure as seen
+        on the host.  */
+      memcpy (((char *) &s) + offset, location, count);
+
+      tdata->gp = s.gp_value;
+      tdata->gprmask = s.gprmask;
+      for (i = 0; i < 4; i++)
+       tdata->cprmask[i] = s.cprmask[i];
+      tdata->fprmask = s.fprmask;
+
+      return true;
+
+    }
+
   bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET);
 
   if (count != 0)
@@ -2964,7 +3178,8 @@ ecoff_write_object_contents (abfd)
        current != (asection *)NULL; 
        current = current->next) 
     {
-      if (strcmp (current->name, SCOMMON) == 0)
+      if (strcmp (current->name, SCOMMON) == 0
+         || strcmp (current->name, REGINFO) == 0)
        continue;
       current->target_index = count;
       ++count;
@@ -3020,6 +3235,13 @@ ecoff_write_object_contents (abfd)
                      && current->reloc_count == 0);
          continue;
        }
+      if (strcmp (current->name, REGINFO) == 0)
+       {
+         BFD_ASSERT ((bfd_get_section_size_before_reloc (current)
+                      == sizeof (struct ecoff_reginfo))
+                     && current->reloc_count == 0);
+         continue;
+       }
 
       ++internal_f.f_nscns;
 
@@ -3084,10 +3306,7 @@ ecoff_write_object_contents (abfd)
 
   /* Set up the file header.  */
 
-  if (abfd->xvec->header_byteorder_big_p != false)
-    internal_f.f_magic = backend->big_magic;
-  else
-    internal_f.f_magic = backend->little_magic;
+  internal_f.f_magic = ecoff_get_magic (abfd);
 
   /* We will NOT put a fucking timestamp in the header here. Every
      time you put it back, I will come in and take it out again.  I'm