Convert i960 COFF to use COFF backend linker.
[deliverable/binutils-gdb.git] / bfd / ecoff.c
index 5665a993d56a7b6dbd2fbe8ef382ccfcbe79ec55..37af7abb8ef9760244318c7855fbce7d38469685 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic ECOFF (Extended-COFF) routines.
-   Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Original version by Per Bothner.
    Full support added by Ian Lance Taylor, ian@cygnus.com.
 
@@ -17,7 +17,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "libbfd.h"
 #include "aout/ar.h"
 #include "aout/ranlib.h"
+#include "aout/stab_gnu.h"
 
 /* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
    some other stuff which we don't want and which conflicts with stuff
@@ -45,15 +46,18 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* Prototypes for static functions.  */
 
 static int ecoff_get_magic PARAMS ((bfd *abfd));
+static long ecoff_sec_to_styp_flags PARAMS ((const char *name,
+                                            flagword flags));
 static boolean ecoff_slurp_symbolic_header PARAMS ((bfd *abfd));
 static boolean ecoff_set_symbol_info PARAMS ((bfd *abfd, SYMR *ecoff_sym,
                                           asymbol *asym, int ext,
                                           asymbol **indirect_ptr_ptr));
-static void ecoff_emit_aggregate PARAMS ((bfd *abfd, char *string,
+static void ecoff_emit_aggregate PARAMS ((bfd *abfd, FDR *fdr,
+                                         char *string,
                                          RNDXR *rndx, long isym,
-                                         CONST char *which));
-static char *ecoff_type_to_string PARAMS ((bfd *abfd, union aux_ext *aux_ptr,
-                                          unsigned int indx, int bigendian));
+                                         const char *which));
+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));
@@ -72,7 +76,7 @@ static asection bfd_debug_section = { "*DEBUG*" };
 /* Create an ECOFF object.  */
 
 boolean
-ecoff_mkobject (abfd)
+_bfd_ecoff_mkobject (abfd)
      bfd *abfd;
 {
   abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
@@ -90,7 +94,7 @@ ecoff_mkobject (abfd)
    specific information.  */
 
 PTR
-ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
      bfd *abfd;
      PTR filehdr;
      PTR aouthdr;
@@ -98,22 +102,14 @@ ecoff_mkobject_hook (abfd, filehdr, 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)
+  if (_bfd_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;
@@ -127,6 +123,8 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
       ecoff->fprmask = internal_a->fprmask;
       if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
        abfd->flags |= D_PAGED;
+      else
+       abfd->flags &=~ D_PAGED;
     }
 
   /* It turns out that no special action is required by the MIPS or
@@ -142,7 +140,7 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
 
 /*ARGSUSED*/
 asection *
-ecoff_make_section_hook (abfd, name)
+_bfd_ecoff_make_section_hook (abfd, name)
      bfd *abfd;
      char *name;
 {
@@ -152,19 +150,22 @@ ecoff_make_section_hook (abfd, name)
 /* Initialize a new section.  */
 
 boolean
-ecoff_new_section_hook (abfd, section)
+_bfd_ecoff_new_section_hook (abfd, section)
      bfd *abfd;
      asection *section;
 {
   /* For the .pdata section, which has a special meaning on the Alpha,
-     we set the alignment to 8.  We correct this later in
+     we set the alignment power to 3.  We correct this later in
      ecoff_compute_section_file_positions.  We do this hackery because
      we need to know the exact unaligned size of the .pdata section in
-     order to set the lnnoptr field correctly.  */
+     order to set the lnnoptr field correctly.  For every other
+     section we use an alignment power of 4; this could be made target
+     dependent by adding a field to ecoff_backend_data, but 4 appears
+     to be correct for both the MIPS and the Alpha.  */
   if (strcmp (section->name, _PDATA) == 0)
     section->alignment_power = 3;
   else
-    section->alignment_power = abfd->xvec->align_power_min;
+    section->alignment_power = 4;
 
   if (strcmp (section->name, _TEXT) == 0)
     section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
@@ -178,14 +179,10 @@ 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)
+  else if (strcmp (section->name, _LIB) == 0)
     {
-      /* Setting SEC_SHARED_LIBRARY should make the linker leave the
-        section completely alone.  */
-      section->flags |= (SEC_SHARED_LIBRARY
-                        | SEC_HAS_CONTENTS
-                        | SEC_NEVER_LOAD);
-      section->_raw_size = sizeof (struct ecoff_reginfo);
+      /* An Irix 4 shared libary.  */
+      section->flags |= SEC_COFF_SHARED_LIBRARY;
     }
 
   /* Probably any other section name is SEC_NEVER_LOAD, but I'm
@@ -201,7 +198,7 @@ ecoff_new_section_hook (abfd, section)
    for each target, but there aren't all that many ECOFF targets.  */
 
 boolean
-ecoff_set_arch_mach_hook (abfd, filehdr)
+_bfd_ecoff_set_arch_mach_hook (abfd, filehdr)
      bfd *abfd;
      PTR filehdr;
 {
@@ -247,7 +244,7 @@ ecoff_set_arch_mach_hook (abfd, filehdr)
 }
 
 /* Get the magic number to use based on the architecture and machine.
-   This is the inverse of ecoff_set_arch_mach_hook, above.  */
+   This is the inverse of _bfd_ecoff_set_arch_mach_hook, above.  */
 
 static int
 ecoff_get_magic (abfd)
@@ -291,9 +288,9 @@ ecoff_get_magic (abfd)
 
 /* Get the section s_flags to use for a section.  */
 
-long
+static long
 ecoff_sec_to_styp_flags (name, flags)
-     CONST char *name;
+     const char *name;
      flagword flags;
 {
   long styp;
@@ -326,6 +323,8 @@ ecoff_sec_to_styp_flags (name, flags)
     styp = STYP_PDATA;
   else if (strcmp (name, _XDATA) == 0)
     styp = STYP_XDATA;
+  else if (strcmp (name, _LIB) == 0)
+    styp = STYP_ECOFF_LIB;
   else if (flags & SEC_CODE) 
     styp = STYP_TEXT;
   else if (flags & SEC_DATA) 
@@ -347,9 +346,10 @@ ecoff_sec_to_styp_flags (name, flags)
 
 /*ARGSUSED*/
 flagword
-ecoff_styp_to_sec_flags (abfd, hdr)
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
      bfd *abfd;
      PTR hdr;
+     const char *name;
 {
   struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
   long styp_flags = internal_s->s_flags;
@@ -365,7 +365,7 @@ ecoff_styp_to_sec_flags (abfd, hdr)
       || (styp_flags & STYP_ECOFF_FINI))
     {
       if (sec_flags & SEC_NEVER_LOAD)
-       sec_flags |= SEC_CODE | SEC_SHARED_LIBRARY;
+       sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
       else
        sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
     }
@@ -376,7 +376,7 @@ ecoff_styp_to_sec_flags (abfd, hdr)
           || styp_flags == STYP_XDATA)
     {
       if (sec_flags & SEC_NEVER_LOAD)
-       sec_flags |= SEC_DATA | SEC_SHARED_LIBRARY;
+       sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
       else
        sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
       if ((styp_flags & STYP_RDATA)
@@ -398,6 +398,10 @@ ecoff_styp_to_sec_flags (abfd, hdr)
     {
       sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
     }
+  else if (styp_flags & STYP_ECOFF_LIB)
+    {
+      sec_flags |= SEC_COFF_SHARED_LIBRARY;
+    }
   else
     {
       sec_flags |= SEC_ALLOC | SEC_LOAD;
@@ -406,201 +410,6 @@ ecoff_styp_to_sec_flags (abfd, hdr)
   return sec_flags;
 }
 \f
-/* Routines to swap auxiliary information in and out.  I am assuming
-   that the auxiliary information format is always going to be target
-   independent.  */
-
-/* Swap in a type information record.
-   BIGEND says whether AUX symbols are big-endian or little-endian; this
-   info comes from the file header record (fh-fBigendian).  */
-
-void
-ecoff_swap_tir_in (bigend, ext_copy, intern)
-     int bigend;
-     struct tir_ext *ext_copy;
-     TIR *intern;
-{
-  struct tir_ext ext[1];
-
-  *ext = *ext_copy;            /* Make it reasonable to do in-place.  */
-  
-  /* now the fun stuff... */
-  if (bigend) {
-    intern->fBitfield   = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG);
-    intern->continued   = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG);
-    intern->bt          = (ext->t_bits1[0] & TIR_BITS1_BT_BIG)
-                       >>                  TIR_BITS1_BT_SH_BIG;
-    intern->tq4         = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG)
-                       >>                  TIR_BITS_TQ4_SH_BIG;
-    intern->tq5         = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG)
-                       >>                  TIR_BITS_TQ5_SH_BIG;
-    intern->tq0         = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG)
-                       >>                  TIR_BITS_TQ0_SH_BIG;
-    intern->tq1         = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG)
-                       >>                  TIR_BITS_TQ1_SH_BIG;
-    intern->tq2         = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG)
-                       >>                  TIR_BITS_TQ2_SH_BIG;
-    intern->tq3         = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG)
-                       >>                  TIR_BITS_TQ3_SH_BIG;
-  } else {
-    intern->fBitfield   = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE);
-    intern->continued   = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE);
-    intern->bt          = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE)
-                       >>                  TIR_BITS1_BT_SH_LITTLE;
-    intern->tq4         = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE)
-                       >>                  TIR_BITS_TQ4_SH_LITTLE;
-    intern->tq5         = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE)
-                       >>                  TIR_BITS_TQ5_SH_LITTLE;
-    intern->tq0         = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE)
-                       >>                  TIR_BITS_TQ0_SH_LITTLE;
-    intern->tq1         = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE)
-                       >>                  TIR_BITS_TQ1_SH_LITTLE;
-    intern->tq2         = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE)
-                       >>                  TIR_BITS_TQ2_SH_LITTLE;
-    intern->tq3         = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE)
-                       >>                  TIR_BITS_TQ3_SH_LITTLE;
-  }
-
-#ifdef TEST
-  if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
-    abort();
-#endif
-}
-
-/* Swap out a type information record.
-   BIGEND says whether AUX symbols are big-endian or little-endian; this
-   info comes from the file header record (fh-fBigendian).  */
-
-void
-ecoff_swap_tir_out (bigend, intern_copy, ext)
-     int bigend;
-     TIR *intern_copy;
-     struct tir_ext *ext;
-{
-  TIR intern[1];
-
-  *intern = *intern_copy;      /* Make it reasonable to do in-place.  */
-  
-  /* now the fun stuff... */
-  if (bigend) {
-    ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0)
-                      | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0)
-                      | ((intern->bt << TIR_BITS1_BT_SH_BIG)
-                         & TIR_BITS1_BT_BIG));
-    ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG)
-                      & TIR_BITS_TQ4_BIG)
-                     | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG)
-                        & TIR_BITS_TQ5_BIG));
-    ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG)
-                      & TIR_BITS_TQ0_BIG)
-                     | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG)
-                        & TIR_BITS_TQ1_BIG));
-    ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG)
-                      & TIR_BITS_TQ2_BIG)
-                     | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG)
-                        & TIR_BITS_TQ3_BIG));
-  } else {
-    ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0)
-                      | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0)
-                      | ((intern->bt << TIR_BITS1_BT_SH_LITTLE)
-                         & TIR_BITS1_BT_LITTLE));
-    ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE)
-                      & TIR_BITS_TQ4_LITTLE)
-                     | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE)
-                        & TIR_BITS_TQ5_LITTLE));
-    ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE)
-                      & TIR_BITS_TQ0_LITTLE)
-                     | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE)
-                        & TIR_BITS_TQ1_LITTLE));
-    ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE)
-                      & TIR_BITS_TQ2_LITTLE)
-                     | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE)
-                        & TIR_BITS_TQ3_LITTLE));
-  }
-
-#ifdef TEST
-  if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
-    abort();
-#endif
-}
-
-/* Swap in a relative symbol record.  BIGEND says whether it is in
-   big-endian or little-endian format.*/
-
-void
-ecoff_swap_rndx_in (bigend, ext_copy, intern)
-     int bigend;
-     struct rndx_ext *ext_copy;
-     RNDXR *intern;
-{
-  struct rndx_ext ext[1];
-
-  *ext = *ext_copy;            /* Make it reasonable to do in-place.  */
-  
-  /* now the fun stuff... */
-  if (bigend) {
-    intern->rfd   = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG)
-                 | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG)
-                                   >> RNDX_BITS1_RFD_SH_BIG);
-    intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG)
-                                   << RNDX_BITS1_INDEX_SH_LEFT_BIG)
-                 | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG)
-                 | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG);
-  } else {
-    intern->rfd   = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE)
-                 | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE)
-                                   << RNDX_BITS1_RFD_SH_LEFT_LITTLE);
-    intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_LITTLE)
-                                   >> RNDX_BITS1_INDEX_SH_LITTLE)
-                 | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_LITTLE)
-                 | ((unsigned int) ext->r_bits[3]
-                    << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
-  }
-
-#ifdef TEST
-  if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
-    abort();
-#endif
-}
-
-/* Swap out a relative symbol record.  BIGEND says whether it is in
-   big-endian or little-endian format.*/
-
-void
-ecoff_swap_rndx_out (bigend, intern_copy, ext)
-     int bigend;
-     RNDXR *intern_copy;
-     struct rndx_ext *ext;
-{
-  RNDXR intern[1];
-
-  *intern = *intern_copy;      /* Make it reasonable to do in-place.  */
-  
-  /* now the fun stuff... */
-  if (bigend) {
-    ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG;
-    ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG)
-                      & RNDX_BITS1_RFD_BIG)
-                     | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG)
-                        & RNDX_BITS1_INDEX_BIG));
-    ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG;
-    ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG;
-  } else {
-    ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE;
-    ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE)
-                      & RNDX_BITS1_RFD_LITTLE)
-                     | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE)
-                        & RNDX_BITS1_INDEX_LITTLE));
-    ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE;
-    ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE;
-  }
-
-#ifdef TEST
-  if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
-    abort();
-#endif
-}
-\f
 /* Read in the symbolic header for an ECOFF object file.  */
 
 static boolean
@@ -646,10 +455,7 @@ ecoff_slurp_symbolic_header (abfd)
   if (bfd_seek (abfd, ecoff_data (abfd)->sym_filepos, SEEK_SET) == -1
       || (bfd_read (raw, external_hdr_size, 1, abfd)
          != external_hdr_size))
-    {
-      bfd_set_error (bfd_error_system_call);
-      goto error_return;
-    }
+    goto error_return;
   internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
   (*backend->debug_swap.swap_hdr_in) (abfd, raw, internal_symhdr);
 
@@ -673,11 +479,15 @@ ecoff_slurp_symbolic_header (abfd)
 }
 
 /* Read in and swap the important symbolic information for an ECOFF
-   object file.  This is called by gdb.  */
+   object file.  This is called by gdb via the read_debug_info entry
+   point in the backend structure.  */
 
+/*ARGSUSED*/
 boolean
-ecoff_slurp_symbolic_info (abfd)
+_bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)
      bfd *abfd;
+     asection *ignore;
+     struct ecoff_debug_info *debug;
 {
   const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
   HDRR *internal_symhdr;
@@ -691,6 +501,8 @@ ecoff_slurp_symbolic_info (abfd)
   bfd_size_type raw_end;
   bfd_size_type cb_end;
 
+  BFD_ASSERT (debug == &ecoff_data (abfd)->debug_info);
+
   /* Check whether we've already gotten it, and whether there's any to
      get.  */
   if (ecoff_data (abfd)->raw_syments != (PTR) NULL)
@@ -704,7 +516,7 @@ ecoff_slurp_symbolic_info (abfd)
   if (! ecoff_slurp_symbolic_header (abfd))
     return false;
 
-  internal_symhdr = &ecoff_data (abfd)->debug_info.symbolic_header;
+  internal_symhdr = &debug->symbolic_header;
 
   /* Read all the symbolic information at once.  */
   raw_base = (ecoff_data (abfd)->sym_filepos
@@ -755,7 +567,6 @@ ecoff_slurp_symbolic_info (abfd)
                SEEK_SET) != 0
       || bfd_read (raw, raw_size, 1, abfd) != raw_size)
     {
-      bfd_set_error (bfd_error_system_call);
       bfd_release (abfd, raw);
       return false;
     }
@@ -765,11 +576,11 @@ ecoff_slurp_symbolic_info (abfd)
   /* Get pointers for the numeric offsets in the HDRR structure.  */
 #define FIX(off1, off2, type) \
   if (internal_symhdr->off1 == 0) \
-    ecoff_data (abfd)->debug_info.off2 = (type) NULL; \
+    debug->off2 = (type) NULL; \
   else \
-    ecoff_data (abfd)->debug_info.off2 = (type) ((char *) raw \
-                                                + internal_symhdr->off1 \
-                                                - raw_base)
+    debug->off2 = (type) ((char *) raw \
+                         + (internal_symhdr->off1 \
+                            - raw_base))
   FIX (cbLineOffset, line, unsigned char *);
   FIX (cbDnOffset, external_dnr, PTR);
   FIX (cbPdOffset, external_pdr, PTR);
@@ -791,18 +602,17 @@ ecoff_slurp_symbolic_info (abfd)
 
      We need to look at the fdr to deal with a lot of information in
      the symbols, so we swap them here.  */
-  ecoff_data (abfd)->debug_info.fdr =
-    (struct fdr *) bfd_alloc (abfd,
-                             (internal_symhdr->ifdMax *
-                              sizeof (struct fdr)));
-  if (ecoff_data (abfd)->debug_info.fdr == NULL)
+  debug->fdr = (struct fdr *) bfd_alloc (abfd,
+                                        (internal_symhdr->ifdMax *
+                                         sizeof (struct fdr)));
+  if (debug->fdr == NULL)
     {
       bfd_set_error (bfd_error_no_memory);
       return false;
     }
   external_fdr_size = backend->debug_swap.external_fdr_size;
-  fdr_ptr = ecoff_data (abfd)->debug_info.fdr;
-  fraw_src = (char *) ecoff_data (abfd)->debug_info.external_fdr;
+  fdr_ptr = debug->fdr;
+  fraw_src = (char *) debug->external_fdr;
   fraw_end = fraw_src + internal_symhdr->ifdMax * external_fdr_size;
   for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
     (*backend->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
@@ -825,7 +635,7 @@ static asymbol *ecoff_scom_symbol_ptr;
 /* Create an empty symbol.  */
 
 asymbol *
-ecoff_make_empty_symbol (abfd)
+_bfd_ecoff_make_empty_symbol (abfd)
      bfd *abfd;
 {
   ecoff_symbol_type *new;
@@ -858,7 +668,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
   asym->the_bfd = abfd;
   asym->value = ecoff_sym->value;
   asym->section = &bfd_debug_section;
-  asym->udata = NULL;
+  asym->udata.i = 0;
 
   /* An indirect symbol requires two consecutive stabs symbols.  */
   if (*indirect_ptr_ptr != (asymbol *) NULL)
@@ -873,7 +683,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       (*indirect_ptr_ptr)->value = (bfd_vma) asym;
 
       asym->flags = BSF_DEBUGGING;
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       *indirect_ptr_ptr = NULL;
       return true;
     }
@@ -882,7 +692,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       && (ECOFF_UNMARK_STAB (ecoff_sym->index) | N_EXT) == (N_INDR | N_EXT))
     {
       asym->flags = BSF_DEBUGGING | BSF_INDIRECT;
-      asym->section = &bfd_ind_section;
+      asym->section = bfd_ind_section_ptr;
       /* Pass this symbol on to the next call to this function.  */
       *indirect_ptr_ptr = asym;
       return true;
@@ -912,7 +722,19 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
   if (ext)
     asym->flags = BSF_EXPORT | BSF_GLOBAL;
   else
-    asym->flags = BSF_LOCAL;
+    {
+      asym->flags = BSF_LOCAL;
+      /* Normally, a local stProc symbol will have a corresponding
+         external symbol.  We mark the local symbol as a debugging
+         symbol, in order to prevent nm from printing both out.
+         Similarly, we mark stLabel and stabs symbols as debugging
+         symbols.  In both cases, we do want to set the value
+         correctly based on the symbol class.  */
+      if (ecoff_sym->st == stProc
+         || ecoff_sym->st == stLabel
+         || ECOFF_IS_STAB (ecoff_sym))
+       asym->flags |= BSF_DEBUGGING;
+    }
   switch (ecoff_sym->sc)
     {
     case scNil:
@@ -938,10 +760,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       asym->flags = BSF_DEBUGGING;
       break;
     case scAbs:
-      asym->section = &bfd_abs_section;
+      asym->section = bfd_abs_section_ptr;
       break;
     case scUndefined:
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       asym->flags = 0;
       asym->value = 0;
       break;
@@ -971,7 +793,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
     case scCommon:
       if (asym->value > ecoff_data (abfd)->gp_size)
        {
-         asym->section = &bfd_com_section;
+         asym->section = bfd_com_section_ptr;
          asym->flags = 0;
          break;
        }
@@ -998,7 +820,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
       asym->flags = BSF_DEBUGGING;
       break;
     case scSUndefined:
-      asym->section = &bfd_und_section;
+      asym->section = bfd_und_section_ptr;
       asym->flags = 0;
       asym->value = 0;
       break;
@@ -1111,7 +933,7 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, indirect_ptr_ptr)
 /* Read an ECOFF symbol table.  */
 
 boolean
-ecoff_slurp_symbol_table (abfd)
+_bfd_ecoff_slurp_symbol_table (abfd)
      bfd *abfd;
 {
   const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
@@ -1137,7 +959,8 @@ ecoff_slurp_symbol_table (abfd)
     return true;
 
   /* Get the symbolic information.  */
-  if (ecoff_slurp_symbolic_info (abfd) == false)
+  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+                                       &ecoff_data (abfd)->debug_info))
     return false;
   if (bfd_get_symcount (abfd) == 0)
     return true;
@@ -1216,12 +1039,15 @@ ecoff_slurp_symbol_table (abfd)
 
 /* Return the amount of space needed for the canonical symbols.  */
 
-unsigned int
-ecoff_get_symtab_upper_bound (abfd)
+long
+_bfd_ecoff_get_symtab_upper_bound (abfd)
      bfd *abfd;
 {
-  if (ecoff_slurp_symbolic_info (abfd) == false
-      || bfd_get_symcount (abfd) == 0)
+  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+                                       &ecoff_data (abfd)->debug_info))
+    return -1;
+
+  if (bfd_get_symcount (abfd) == 0)
     return 0;
 
   return (bfd_get_symcount (abfd) + 1) * (sizeof (ecoff_symbol_type *));
@@ -1229,8 +1055,8 @@ ecoff_get_symtab_upper_bound (abfd)
 
 /* Get the canonical symbols.  */
 
-unsigned int
-ecoff_get_symtab (abfd, alocation)
+long
+_bfd_ecoff_get_symtab (abfd, alocation)
      bfd *abfd;
      asymbol **alocation;
 {
@@ -1238,8 +1064,9 @@ ecoff_get_symtab (abfd, alocation)
   ecoff_symbol_type *symbase;
   ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
 
-  if (ecoff_slurp_symbol_table (abfd) == false
-      || bfd_get_symcount (abfd) == 0)
+  if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
+    return -1;
+  if (bfd_get_symcount (abfd) == 0)
     return 0;
 
   symbase = ecoff_data (abfd)->canonical_symbols;
@@ -1259,57 +1086,76 @@ ecoff_get_symtab (abfd, alocation)
 /* Write aggregate information to a string.  */
 
 static void
-ecoff_emit_aggregate (abfd, string, rndx, isym, which)
+ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
      bfd *abfd;
+     FDR *fdr;
      char *string;
      RNDXR *rndx;
      long isym;
-     CONST char *which;
+     const char *which;
 {
-  int ifd = rndx->rfd;
-  int indx = rndx->index;
-  int sym_base, ss_base;
-  CONST char *name;
+  const struct ecoff_debug_swap * const debug_swap =
+    &ecoff_backend (abfd)->debug_swap;
+  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
+  unsigned int ifd = rndx->rfd;
+  unsigned int indx = rndx->index;
+  const char *name;
   
   if (ifd == 0xfff)
     ifd = isym;
 
-  sym_base = ecoff_data (abfd)->debug_info.fdr[ifd].isymBase;
-  ss_base  = ecoff_data (abfd)->debug_info.fdr[ifd].issBase;
-  
-  if (indx == indexNil)
-    name = "/* no name */";
+  /* An ifd of -1 is an opaque type.  An escaped index of 0 is a
+     struct return type of a procedure compiled without -g.  */
+  if (ifd == 0xffffffff
+      || (rndx->rfd == 0xfff && indx == 0))
+    name = "<undefined>";
+  else if (indx == indexNil)
+    name = "<no name>";
   else
     {
-      const struct ecoff_debug_swap * const debug_swap
-       = &ecoff_backend (abfd)->debug_swap;
       SYMR sym;
 
-      indx += sym_base;
-      (*debug_swap->swap_sym_in)
-       (abfd,
-        ((char *) ecoff_data (abfd)->debug_info.external_sym
-         + indx * debug_swap->external_sym_size),
-        &sym);
-      name = ecoff_data (abfd)->debug_info.ss + ss_base + sym.iss;
+      if (debug_info->external_rfd == NULL)
+       fdr = debug_info->fdr + ifd;
+      else
+       {
+         RFDT rfd;
+
+         (*debug_swap->swap_rfd_in) (abfd,
+                                     ((char *) debug_info->external_rfd
+                                      + ((fdr->rfdBase + ifd)
+                                         * debug_swap->external_rfd_size)),
+                                     &rfd);
+         fdr = debug_info->fdr + rfd;
+       }
+
+      indx += fdr->isymBase;
+
+      (*debug_swap->swap_sym_in) (abfd,
+                                 ((char *) debug_info->external_sym
+                                  + indx * debug_swap->external_sym_size),
+                                 &sym);
+
+      name = debug_info->ss + fdr->issBase + sym.iss;
     }
 
   sprintf (string,
-          "%s %s { ifd = %d, index = %ld }",
+          "%s %s { ifd = %u, index = %lu }",
           which, name, ifd,
           ((long) indx
-           + ecoff_data (abfd)->debug_info.symbolic_header.iextMax));
+           + debug_info->symbolic_header.iextMax));
 }
 
 /* Convert the type information to string format.  */
 
 static char *
-ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
+ecoff_type_to_string (abfd, fdr, indx)
      bfd *abfd;
-     union aux_ext *aux_ptr;
+     FDR *fdr;
      unsigned int indx;
-     int bigendian;
 {
+  union aux_ext *aux_ptr;
+  int bigendian;
   AUXU u;
   struct qual {
     unsigned int  type;
@@ -1317,15 +1163,17 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
     int  high_bound;
     int  stride;
   } qualifiers[7];
-
   unsigned int basic_type;
   int i;
-  static char buffer1[1024];
+  char buffer1[1024];
   static char buffer2[1024];
   char *p1 = buffer1;
   char *p2 = buffer2;
   RNDXR rndx;
 
+  aux_ptr = ecoff_data (abfd)->debug_info.external_aux + fdr->iauxBase;
+  bigendian = fdr->fBigendian;
+
   for (i = 0; i < 7; i++)
     {
       qualifiers[i].low_bound = 0;
@@ -1333,9 +1181,9 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
       qualifiers[i].stride = 0;
     }
 
-  if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == -1)
+  if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == (bfd_vma) -1)
     return "-1 (no type)";
-  ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
+  _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
 
   basic_type = u.ti.bt;
   qualifiers[0].type = u.ti.tq0;
@@ -1404,8 +1252,8 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
         2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
 
     case btStruct:             /* Structure (Record) */
-      ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
-      ecoff_emit_aggregate (abfd, p1, &rndx,
+      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
                            (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
                            "struct");
       indx++;                  /* skip aux words */
@@ -1416,8 +1264,8 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
         2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
 
     case btUnion:              /* Union */
-      ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
-      ecoff_emit_aggregate (abfd, p1, &rndx,
+      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
                            (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
                            "union");
       indx++;                  /* skip aux words */
@@ -1428,8 +1276,8 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
         2nd word is file index if 1st word rfd is ST_RFDESCAPE.  */
 
     case btEnum:               /* Enumeration */
-      ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
-      ecoff_emit_aggregate (abfd, p1, &rndx,
+      _bfd_ecoff_swap_rndx_in (bigendian, &aux_ptr[indx].a_rndx, &rndx);
+      ecoff_emit_aggregate (abfd, fdr, p1, &rndx,
                            (long) AUX_GET_ISYM (bigendian, &aux_ptr[indx+1]),
                            "enum");
       indx++;                  /* skip aux words */
@@ -1611,7 +1459,7 @@ ecoff_type_to_string (abfd, aux_ptr, indx, bigendian)
 
 /*ARGSUSED*/
 void
-ecoff_get_symbol_info (abfd, symbol, ret)
+_bfd_ecoff_get_symbol_info (abfd, symbol, ret)
      bfd *abfd;                        /* Ignored.  */
      asymbol *symbol;
      symbol_info *ret;
@@ -1619,10 +1467,21 @@ ecoff_get_symbol_info (abfd, symbol, ret)
   bfd_symbol_info (symbol, ret);
 }
 
+/* Return whether this is a local label.  */
+
+/*ARGSUSED*/
+boolean
+_bfd_ecoff_bfd_is_local_label (abfd, symbol)
+     bfd *abfd;
+     asymbol *symbol;
+{
+  return symbol->name[0] == '$';
+}
+
 /* Print information about an ECOFF symbol.  */
 
 void
-ecoff_print_symbol (abfd, filep, symbol, how)
+_bfd_ecoff_print_symbol (abfd, filep, symbol, how)
      bfd *abfd;
      PTR filep;
      asymbol *symbol;
@@ -1710,17 +1569,19 @@ ecoff_print_symbol (abfd, filep, symbol, how)
        if (ecoffsymbol (symbol)->fdr != NULL
            && ecoff_ext.asym.index != indexNil)
          {
+           FDR *fdr;
            unsigned int indx;
            int bigendian;
            bfd_size_type sym_base;
            union aux_ext *aux_base;
 
+           fdr = ecoffsymbol (symbol)->fdr;
            indx = ecoff_ext.asym.index;
 
            /* sym_base is used to map the fdr relative indices which
               appear in the file to the position number which we are
               using.  */
-           sym_base = ecoffsymbol (symbol)->fdr->isymBase;
+           sym_base = fdr->isymBase;
            if (ecoffsymbol (symbol)->local)
              sym_base +=
                ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
@@ -1728,11 +1589,11 @@ ecoff_print_symbol (abfd, filep, symbol, how)
            /* aux_base is the start of the aux entries for this file;
               asym.index is an offset from this.  */
            aux_base = (ecoff_data (abfd)->debug_info.external_aux
-                       + ecoffsymbol (symbol)->fdr->iauxBase);
+                       + fdr->iauxBase);
 
            /* The aux entries are stored in host byte order; the
               order is indicated by a bit in the fdr.  */
-           bigendian = ecoffsymbol (symbol)->fdr->fBigendian;
+           bigendian = fdr->fBigendian;
 
            /* This switch is basically from gcc/mips-tdump.c  */
            switch (ecoff_ext.asym.st)
@@ -1754,9 +1615,10 @@ ecoff_print_symbol (abfd, filep, symbol, how)
                           (long) (indx + sym_base));
                else
                  fprintf (file, "\n      First symbol: %ld", 
-                          (long) (AUX_GET_ISYM (bigendian,
-                                                &aux_base[ecoff_ext.asym.index])
-                                  + sym_base));
+                          ((long)
+                           (AUX_GET_ISYM (bigendian,
+                                          &aux_base[ecoff_ext.asym.index])
+                            + sym_base)));
                break;
 
              case stProc:
@@ -1765,11 +1627,11 @@ ecoff_print_symbol (abfd, filep, symbol, how)
                  ;
                else if (ecoffsymbol (symbol)->local)
                  fprintf (file, "\n      End+1 symbol: %-7ld   Type:  %s",
-                          (long) (AUX_GET_ISYM (bigendian,
-                                                &aux_base[ecoff_ext.asym.index])
-                                  + sym_base),
-                          ecoff_type_to_string (abfd, aux_base, indx + 1,
-                                                bigendian));
+                          ((long)
+                           (AUX_GET_ISYM (bigendian,
+                                          &aux_base[ecoff_ext.asym.index])
+                            + sym_base)),
+                          ecoff_type_to_string (abfd, fdr, indx + 1));
                else
                  fprintf (file, "\n      Local symbol: %ld",
                           ((long) indx
@@ -1778,11 +1640,25 @@ ecoff_print_symbol (abfd, filep, symbol, how)
                               ->debug_info.symbolic_header.iextMax)));
                break;
 
+             case stStruct:
+               fprintf (file, "\n      struct; End+1 symbol: %ld",
+                        (long) (indx + sym_base));
+               break;
+
+             case stUnion:
+               fprintf (file, "\n      union; End+1 symbol: %ld",
+                        (long) (indx + sym_base));
+               break;
+
+             case stEnum:
+               fprintf (file, "\n      enum; End+1 symbol: %ld",
+                        (long) (indx + sym_base));
+               break;
+
              default:
                if (! ECOFF_IS_STAB (&ecoff_ext.asym))
                  fprintf (file, "\n      Type: %s",
-                          ecoff_type_to_string (abfd, aux_base, indx,
-                                                bigendian));
+                          ecoff_type_to_string (abfd, fdr, indx));
                break;
              }
          }
@@ -1812,7 +1688,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
       || (section->flags & SEC_CONSTRUCTOR) != 0)
     return true;
 
-  if (ecoff_slurp_symbol_table (abfd) == false)
+  if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
     return false;
   
   internal_relocs = (arelent *) bfd_alloc (abfd,
@@ -1831,10 +1707,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
     return false;
   if (bfd_read (external_relocs, 1, external_relocs_size, abfd)
       != external_relocs_size)
-    {
-      bfd_set_error (bfd_error_system_call);
-      return false;
-    }
+    return false;
 
   for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
     {
@@ -1857,7 +1730,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
       else if (intern.r_symndx == RELOC_SECTION_NONE
               || intern.r_symndx == RELOC_SECTION_ABS)
        {
-         rptr->sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+         rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
          rptr->addend = 0;
        }
       else
@@ -1908,8 +1781,8 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
 
 /* Get a canonical list of relocs.  */
 
-unsigned int
-ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
+long
+_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
      bfd *abfd;
      asection *section;
      arelent **relptr;
@@ -1934,11 +1807,9 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
       arelent *tblptr;
 
       if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
-       return 0;
+       return -1;
 
       tblptr = section->relocation;
-      if (tblptr == (arelent *) NULL)
-       return 0;
 
       for (count = 0; count < section->reloc_count; count++)
        *relptr++ = tblptr++;
@@ -1955,13 +1826,8 @@ ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
 
 /*ARGSUSED*/
 boolean
-ecoff_find_nearest_line (abfd,
-                        section,
-                        ignore_symbols,
-                        offset,
-                        filename_ptr,
-                        functionname_ptr,
-                        retline_ptr)
+_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
+                             filename_ptr, functionname_ptr, retline_ptr)
      bfd *abfd;
      asection *section;
      asymbol **ignore_symbols;
@@ -1972,17 +1838,8 @@ ecoff_find_nearest_line (abfd,
 {
   const struct ecoff_debug_swap * const debug_swap
     = &ecoff_backend (abfd)->debug_swap;
-  FDR *fdr_ptr;
-  FDR *fdr_start;
-  FDR *fdr_end;
-  FDR *fdr_hold;
-  bfd_size_type external_pdr_size;
-  char *pdr_ptr;
-  char *pdr_end;
-  PDR pdr;
-  unsigned char *line_ptr;
-  unsigned char *line_end;
-  int lineno;
+  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
+  struct ecoff_find_line *line_info;
 
   /* If we're not in the .text section, we don't have any line
      numbers.  */
@@ -1992,134 +1849,147 @@ ecoff_find_nearest_line (abfd,
     return false;
 
   /* Make sure we have the FDR's.  */
-  if (ecoff_slurp_symbolic_info (abfd) == false
+  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
       || bfd_get_symcount (abfd) == 0)
     return false;
 
-  /* Each file descriptor (FDR) has a memory address.  Here we track
-     down which FDR we want.  The FDR's are stored in increasing
-     memory order.  If speed is ever important, this can become a
-     binary search.  We must ignore FDR's with no PDR entries; they
-     will have the adr of the FDR before or after them.  */
-  fdr_start = ecoff_data (abfd)->debug_info.fdr;
-  fdr_end = fdr_start + ecoff_data (abfd)->debug_info.symbolic_header.ifdMax;
-  fdr_hold = (FDR *) NULL;
-  for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
+  if (ecoff_data (abfd)->find_line_info == NULL)
     {
-      if (fdr_ptr->cpd == 0)
-       continue;
-      if (offset < fdr_ptr->adr)
-       break;
-      fdr_hold = fdr_ptr;
-    }
-  if (fdr_hold == (FDR *) NULL)
-    return false;
-  fdr_ptr = fdr_hold;
-
-  /* Each FDR has a list of procedure descriptors (PDR).  PDR's also
-     have an address, which is relative to the FDR address, and are
-     also stored in increasing memory order.  */
-  offset -= fdr_ptr->adr;
-  external_pdr_size = debug_swap->external_pdr_size;
-  pdr_ptr = ((char *) ecoff_data (abfd)->debug_info.external_pdr
-            + fdr_ptr->ipdFirst * external_pdr_size);
-  pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
-  (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
-  /* The address of the first PDR is an offset which applies to the
-     addresses of all the PDR's.  */
-  offset += pdr.adr;
-
-  for (pdr_ptr += external_pdr_size;
-       pdr_ptr < pdr_end;
-       pdr_ptr += external_pdr_size)
-    {
-      (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-      if (offset < pdr.adr)
-       break;
+      ecoff_data (abfd)->find_line_info =
+       ((struct ecoff_find_line *)
+        bfd_alloc (abfd, sizeof (struct ecoff_find_line)));
+      if (ecoff_data (abfd)->find_line_info == NULL)
+       {
+         bfd_set_error (bfd_error_no_memory);
+         return false;
+       }
+      ecoff_data (abfd)->find_line_info->find_buffer = NULL;
+      ecoff_data (abfd)->find_line_info->fdrtab_len = 0;
+      ecoff_data (abfd)->find_line_info->fdrtab = NULL;
     }
+  line_info = ecoff_data (abfd)->find_line_info;
 
-  /* Now we can look for the actual line number.  The line numbers are
-     stored in a very funky format, which I won't try to describe.
-     Note that right here pdr_ptr and pdr hold the PDR *after* the one
-     we want; we need this to compute line_end.  */
-  line_end = ecoff_data (abfd)->debug_info.line;
-  if (pdr_ptr == pdr_end)
-    line_end += fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
-  else
-    line_end += fdr_ptr->cbLineOffset + pdr.cbLineOffset;
-
-  /* Now change pdr and pdr_ptr to the one we want.  */
-  pdr_ptr -= external_pdr_size;
-  (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-
-  offset -= pdr.adr;
-  lineno = pdr.lnLow;
-  line_ptr = (ecoff_data (abfd)->debug_info.line
-             + fdr_ptr->cbLineOffset
-             + pdr.cbLineOffset);
-  while (line_ptr < line_end)
+  return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
+                                debug_swap, line_info, filename_ptr,
+                                functionname_ptr, retline_ptr);
+}
+\f
+/* Copy private BFD data.  This is called by objcopy and strip.  We
+   use it to copy the ECOFF debugging information from one BFD to the
+   other.  It would be theoretically possible to represent the ECOFF
+   debugging information in the symbol table.  However, it would be a
+   lot of work, and there would be little gain (gas, gdb, and ld
+   already access the ECOFF debugging information via the
+   ecoff_debug_info structure, and that structure would have to be
+   retained in order to support ECOFF debugging in MIPS ELF).
+
+   The debugging information for the ECOFF external symbols comes from
+   the symbol table, so this function only handles the other debugging
+   information.  */
+
+boolean
+_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
+     bfd *ibfd;
+     bfd *obfd;
+{
+  struct ecoff_debug_info *iinfo = &ecoff_data (ibfd)->debug_info;
+  struct ecoff_debug_info *oinfo = &ecoff_data (obfd)->debug_info;
+  register int i;
+  asymbol **sym_ptr_ptr;
+  size_t c;
+  boolean local;
+
+  /* This function is selected based on the input vector.  We only
+     want to copy information over if the output BFD also uses ECOFF
+     format.  */
+  if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
+    return true;
+
+  /* Copy the GP value and the register masks.  */
+  ecoff_data (obfd)->gp = ecoff_data (ibfd)->gp;
+  ecoff_data (obfd)->gprmask = ecoff_data (ibfd)->gprmask;
+  ecoff_data (obfd)->fprmask = ecoff_data (ibfd)->fprmask;
+  for (i = 0; i < 3; i++)
+    ecoff_data (obfd)->cprmask[i] = ecoff_data (ibfd)->cprmask[i];
+
+  /* Copy the version stamp.  */
+  oinfo->symbolic_header.vstamp = iinfo->symbolic_header.vstamp;
+
+  /* If there are no symbols, don't copy any debugging information.  */
+  c = bfd_get_symcount (obfd);
+  sym_ptr_ptr = bfd_get_outsymbols (obfd);
+  if (c == 0 || sym_ptr_ptr == (asymbol **) NULL)
+    return true;
+
+  /* See if there are any local symbols.  */
+  local = false;
+  for (; c > 0; c--, sym_ptr_ptr++)
     {
-      int delta;
-      int count;
-
-      delta = *line_ptr >> 4;
-      if (delta >= 0x8)
-       delta -= 0x10;
-      count = (*line_ptr & 0xf) + 1;
-      ++line_ptr;
-      if (delta == -8)
+      if (ecoffsymbol (*sym_ptr_ptr)->local)
        {
-         delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
-         if (delta >= 0x8000)
-           delta -= 0x10000;
-         line_ptr += 2;
+         local = true;
+         break;
        }
-      lineno += delta;
-      if (offset < count * 4)
-       break;
-      offset -= count * 4;
     }
 
-  /* If fdr_ptr->rss is -1, then this file does not have full symbols,
-     at least according to gdb/mipsread.c.  */
-  if (fdr_ptr->rss == -1)
+  if (local)
     {
-      *filename_ptr = NULL;
-      if (pdr.isym == -1)
-       *functionname_ptr = NULL;
-      else
-       {
-         EXTR proc_ext;
-
-         (*debug_swap->swap_ext_in)
-           (abfd,
-            ((char *) ecoff_data (abfd)->debug_info.external_ext
-             + pdr.isym * debug_swap->external_ext_size),
-            &proc_ext);
-         *functionname_ptr = (ecoff_data (abfd)->debug_info.ssext
-                              + proc_ext.asym.iss);
-       }
+      /* There are some local symbols.  We just bring over all the
+        debugging information.  FIXME: This is not quite the right
+        thing to do.  If the user has asked us to discard all
+        debugging information, then we are probably going to wind up
+        keeping it because there will probably be some local symbol
+        which objcopy did not discard.  We should actually break
+        apart the debugging information and only keep that which
+        applies to the symbols we want to keep.  */
+      oinfo->symbolic_header.ilineMax = iinfo->symbolic_header.ilineMax;
+      oinfo->symbolic_header.cbLine = iinfo->symbolic_header.cbLine;
+      oinfo->line = iinfo->line;
+
+      oinfo->symbolic_header.idnMax = iinfo->symbolic_header.idnMax;
+      oinfo->external_dnr = iinfo->external_dnr;
+
+      oinfo->symbolic_header.ipdMax = iinfo->symbolic_header.ipdMax;
+      oinfo->external_pdr = iinfo->external_pdr;
+
+      oinfo->symbolic_header.isymMax = iinfo->symbolic_header.isymMax;
+      oinfo->external_sym = iinfo->external_sym;
+
+      oinfo->symbolic_header.ioptMax = iinfo->symbolic_header.ioptMax;
+      oinfo->external_opt = iinfo->external_opt;
+
+      oinfo->symbolic_header.iauxMax = iinfo->symbolic_header.iauxMax;
+      oinfo->external_aux = iinfo->external_aux;
+
+      oinfo->symbolic_header.issMax = iinfo->symbolic_header.issMax;
+      oinfo->ss = iinfo->ss;
+
+      oinfo->symbolic_header.ifdMax = iinfo->symbolic_header.ifdMax;
+      oinfo->external_fdr = iinfo->external_fdr;
+
+      oinfo->symbolic_header.crfd = iinfo->symbolic_header.crfd;
+      oinfo->external_rfd = iinfo->external_rfd;
     }
   else
     {
-      SYMR proc_sym;
-
-      *filename_ptr = (ecoff_data (abfd)->debug_info.ss
-                      + fdr_ptr->issBase
-                      + fdr_ptr->rss);
-      (*debug_swap->swap_sym_in)
-       (abfd,
-        ((char *) ecoff_data (abfd)->debug_info.external_sym
-         + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
-        &proc_sym);
-      *functionname_ptr = (ecoff_data (abfd)->debug_info.ss
-                          + fdr_ptr->issBase
-                          + proc_sym.iss);
+      /* We are discarding all the local symbol information.  Look
+        through the external symbols and remove all references to FDR
+        or aux information.  */
+      c = bfd_get_symcount (obfd);
+      sym_ptr_ptr = bfd_get_outsymbols (obfd);
+      for (; c > 0; c--, sym_ptr_ptr++)
+       {
+         EXTR esym;
+
+         (*(ecoff_backend (obfd)->debug_swap.swap_ext_in))
+           (obfd, ecoffsymbol (*sym_ptr_ptr)->native, &esym);
+         esym.ifd = ifdNil;
+         esym.asym.index = indexNil;
+         (*(ecoff_backend (obfd)->debug_swap.swap_ext_out))
+           (obfd, &esym, ecoffsymbol (*sym_ptr_ptr)->native);
+       }
     }
-  if (lineno == ilineNil)
-    lineno = 0;
-  *retline_ptr = lineno;
+
   return true;
 }
 \f
@@ -2128,7 +1998,7 @@ ecoff_find_nearest_line (abfd,
    callers ignore the return value.  */
 
 boolean
-ecoff_set_arch_mach (abfd, arch, machine)
+_bfd_ecoff_set_arch_mach (abfd, arch, machine)
      bfd *abfd;
      enum bfd_architecture arch;
      unsigned long machine;
@@ -2137,12 +2007,11 @@ ecoff_set_arch_mach (abfd, arch, machine)
   return arch == ecoff_backend (abfd)->arch;
 }
 
-/* Get the size of the section headers.  We do not output the .reginfo
-   section.  */
+/* Get the size of the section headers.  */
 
 /*ARGSUSED*/
 int
-ecoff_sizeof_headers (abfd, reloc)
+_bfd_ecoff_sizeof_headers (abfd, reloc)
      bfd *abfd;
      boolean reloc;
 {
@@ -2154,8 +2023,7 @@ ecoff_sizeof_headers (abfd, reloc)
   for (current = abfd->sections;
        current != (asection *)NULL; 
        current = current->next) 
-    if (strcmp (current->name, REGINFO) != 0)
-      ++c;
+    ++c;
 
   ret = (bfd_coff_filhsz (abfd)
         + bfd_coff_aoutsz (abfd)
@@ -2163,38 +2031,18 @@ ecoff_sizeof_headers (abfd, reloc)
   return BFD_ALIGN (ret, 16);
 }
 
-/* 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.  */
+/* Get the contents of a section.  */
 
 boolean
-ecoff_get_section_contents (abfd, section, location, offset, count)
+_bfd_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, (size_t) count);
-  return true;
+  return _bfd_generic_get_section_contents (abfd, section, location,
+                                           offset, count);
 }
 
 /* Calculate the file position for each section, and set
@@ -2209,7 +2057,7 @@ ecoff_compute_section_file_positions (abfd)
   file_ptr old_sofar;
   boolean first_data;
 
-  sofar = ecoff_sizeof_headers (abfd, false);
+  sofar = _bfd_ecoff_sizeof_headers (abfd, false);
 
   first_data = true;
   for (current = abfd->sections;
@@ -2219,8 +2067,7 @@ ecoff_compute_section_file_positions (abfd)
       unsigned int alignment_power;
 
       /* Only deal with sections which have contents */
-      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0
-         || strcmp (current->name, REGINFO) == 0)
+      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
        continue;
 
       /* For the Alpha ECOFF .pdata section the lnnoptr field is
@@ -2254,6 +2101,15 @@ ecoff_compute_section_file_positions (abfd)
          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);
+       }
 
       /* Align the sections in the file to the same boundary on
         which they are aligned in virtual memory.  */
@@ -2301,8 +2157,6 @@ ecoff_compute_reloc_file_positions (abfd)
        current != (asection *)NULL; 
        current = current->next) 
     {
-      if (strcmp (current->name, REGINFO) == 0)
-       continue;
       if (current->reloc_count == 0)
        current->rel_filepos = 0;
       else
@@ -2331,12 +2185,10 @@ ecoff_compute_reloc_file_positions (abfd)
   return reloc_size;
 }
 
-/* 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.  */
+/* Set the contents of a section.  */
 
 boolean
-ecoff_set_section_contents (abfd, section, location, offset, count)
+_bfd_ecoff_set_section_contents (abfd, section, location, offset, count)
      bfd *abfd;
      asection *section;
      PTR location;
@@ -2348,45 +2200,88 @@ ecoff_set_section_contents (abfd, section, location, offset, count)
   if (abfd->output_has_begun == false)
     ecoff_compute_section_file_positions (abfd);
 
+  /* 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
+     Irix 4.  Ian Taylor <ian@cygnus.com>.  */
+  if (strcmp (section->name, _LIB) == 0)
+    ++section->vma;
+
   if (count == 0)
     return true;
 
-  if (strcmp (section->name, REGINFO) == 0)
+  if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+      || bfd_write (location, 1, count, abfd) != count)
+    return false;
+
+  return true;
+}
+
+/* Get the GP value for an ECOFF file.  This is a hook used by
+   nlmconv.  */
+
+bfd_vma
+bfd_ecoff_get_gp_value (abfd)
+     bfd *abfd;
+{
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
     {
-      ecoff_data_type *tdata = ecoff_data (abfd);
-      struct ecoff_reginfo s;
-      int i;
+      bfd_set_error (bfd_error_invalid_operation);
+      return 0;
+    }
+  
+  return ecoff_data (abfd)->gp;
+}
 
-      /* 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;
-       }
+/* Set the GP value for an ECOFF file.  This is a hook used by the
+   assembler.  */
 
-      /* 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, (size_t) count);
+boolean
+bfd_ecoff_set_gp_value (abfd, gp_value)
+     bfd *abfd;
+     bfd_vma gp_value;
+{
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
+    }
 
-      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;
+  ecoff_data (abfd)->gp = gp_value;
 
-      return true;
+  return true;
+}
+
+/* Set the register masks for an ECOFF file.  This is a hook used by
+   the assembler.  */
+
+boolean
+bfd_ecoff_set_regmasks (abfd, gprmask, fprmask, cprmask)
+     bfd *abfd;
+     unsigned long gprmask;
+     unsigned long fprmask;
+     unsigned long *cprmask;
+{
+  ecoff_data_type *tdata;
+
+  if (bfd_get_flavour (abfd) != bfd_target_ecoff_flavour
+      || bfd_get_format (abfd) != bfd_object)
+    {
+      bfd_set_error (bfd_error_invalid_operation);
+      return false;
     }
 
-  if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
-      || bfd_write (location, 1, count, abfd) != count)
-    return false;
+  tdata = ecoff_data (abfd);
+  tdata->gprmask = gprmask;
+  tdata->fprmask = fprmask;
+  if (cprmask != (unsigned long *) NULL)
+    {
+      register int i;
+
+      for (i = 0; i < 3; i++)
+       tdata->cprmask[i] = cprmask[i];
+    }
 
   return true;
 }
@@ -2402,15 +2297,15 @@ ecoff_get_extr (sym, esym)
   ecoff_symbol_type *ecoff_sym_ptr;
   bfd *input_bfd;
 
-  /* Don't include debugging, local or section symbols.  */
-  if ((sym->flags & BSF_DEBUGGING) != 0
-      || (sym->flags & BSF_LOCAL) != 0
-      || (sym->flags & BSF_SECTION_SYM) != 0)
-    return false;
-
   if (bfd_asymbol_flavour (sym) != bfd_target_ecoff_flavour
       || ecoffsymbol (sym)->native == NULL)
     {
+      /* Don't include debugging, local, or section symbols.  */
+      if ((sym->flags & BSF_DEBUGGING) != 0
+         || (sym->flags & BSF_LOCAL) != 0
+         || (sym->flags & BSF_SECTION_SYM) != 0)
+       return false;
+
       esym->jmptbl = 0;
       esym->cobol_main = 0;
       esym->weakext = 0;
@@ -2427,7 +2322,7 @@ ecoff_get_extr (sym, esym)
   ecoff_sym_ptr = ecoffsymbol (sym);
 
   if (ecoff_sym_ptr->local)
-    abort ();
+    return false;
 
   input_bfd = bfd_asymbol_bfd (sym);
   (*(ecoff_backend (input_bfd)->debug_swap.swap_ext_in))
@@ -2438,7 +2333,7 @@ ecoff_get_extr (sym, esym)
      symbol.  */
   if ((esym->asym.sc == scUndefined
        || esym->asym.sc == scSUndefined)
-      && bfd_get_section (sym) != &bfd_und_section)
+      && ! bfd_is_und_section (bfd_get_section (sym)))
     esym->asym.sc = scAbs;
 
   /* Adjust the FDR index for the symbol by that used for the input
@@ -2470,7 +2365,7 @@ ecoff_set_index (sym, indx)
 /* Write out an ECOFF file.  */
 
 boolean
-ecoff_write_object_contents (abfd)
+_bfd_ecoff_write_object_contents (abfd)
      bfd *abfd;
 {
   const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
@@ -2496,8 +2391,10 @@ ecoff_write_object_contents (abfd)
   bfd_size_type reloc_size;
   bfd_size_type text_size;
   bfd_vma text_start;
+  boolean set_text_start;
   bfd_size_type data_size;
   bfd_vma data_start;
+  boolean set_data_start;
   bfd_size_type bss_size;
   PTR buff = NULL;
   PTR reloc_buff = NULL;
@@ -2505,8 +2402,6 @@ ecoff_write_object_contents (abfd)
   struct internal_aouthdr internal_a;
   int i;
 
-  bfd_set_error (bfd_error_system_call);
-
   /* Determine where the sections and relocs will go in the output
      file.  */
   reloc_size = ecoff_compute_reloc_file_positions (abfd);
@@ -2516,19 +2411,19 @@ ecoff_write_object_contents (abfd)
        current != (asection *)NULL; 
        current = current->next) 
     {
-      if (strcmp (current->name, REGINFO) == 0)
-       continue;
       current->target_index = count;
       ++count;
     }
 
   if ((abfd->flags & D_PAGED) != 0)
-    text_size = ecoff_sizeof_headers (abfd, false);
+    text_size = _bfd_ecoff_sizeof_headers (abfd, false);
   else
     text_size = 0;
   text_start = 0;
+  set_text_start = false;
   data_size = 0;
   data_start = 0;
+  set_data_start = false;
   bss_size = 0;
 
   /* Write section headers to the file.  */
@@ -2542,7 +2437,7 @@ ecoff_write_object_contents (abfd)
       siz = filhsz;
     if (siz < aoutsz)
       siz = aoutsz;
-    buff = (PTR) malloc (siz);
+    buff = (PTR) malloc ((size_t) siz);
     if (buff == NULL)
       {
        bfd_set_error (bfd_error_no_memory);
@@ -2560,18 +2455,11 @@ ecoff_write_object_contents (abfd)
       struct internal_scnhdr section;
       bfd_vma vma;
 
-      if (strcmp (current->name, REGINFO) == 0)
-       {
-         BFD_ASSERT (current->reloc_count == 0);
-         continue;
-       }
-
       ++internal_f.f_nscns;
 
       strncpy (section.s_name, current->name, sizeof section.s_name);
 
-      /* FIXME: is this correct for shared libraries?  I think it is
-        but I have no platform to check.  Ian Lance Taylor.  */
+      /* This seems to be correct for Irix 4 shared libraries.  */
       vma = bfd_get_section_vma (abfd, current);
       if (strcmp (current->name, _LIB) == 0)
        section.s_vaddr = 0;
@@ -2611,8 +2499,8 @@ ecoff_write_object_contents (abfd)
       section.s_flags = ecoff_sec_to_styp_flags (current->name,
                                                 current->flags);
 
-      bfd_coff_swap_scnhdr_out (abfd, (PTR) &section, buff);
-      if (bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
+      if (bfd_coff_swap_scnhdr_out (abfd, (PTR) &section, buff) == 0
+         || bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
        goto error_return;
 
       if ((section.s_flags & STYP_TEXT) != 0
@@ -2621,8 +2509,11 @@ ecoff_write_object_contents (abfd)
          || strcmp (current->name, _PDATA) == 0)
        {
          text_size += bfd_get_section_size_before_reloc (current);
-         if (text_start == 0 || text_start > vma)
-           text_start = vma;
+         if (! set_text_start || text_start > vma)
+           {
+             text_start = vma;
+             set_text_start = true;
+           }
        }
       else if ((section.s_flags & STYP_RDATA) != 0
               || (section.s_flags & STYP_DATA) != 0
@@ -2633,12 +2524,17 @@ ecoff_write_object_contents (abfd)
               || strcmp (current->name, _XDATA) == 0)
        {
          data_size += bfd_get_section_size_before_reloc (current);
-         if (data_start == 0 || data_start > vma)
-           data_start = vma;
+         if (! set_data_start || data_start > vma)
+           {
+             data_start = vma;
+             set_data_start = true;
+           }
        }
       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)
+       /* Do nothing */ ;
       else
        abort ();
     }  
@@ -2743,11 +2639,10 @@ ecoff_write_object_contents (abfd)
     goto error_return;
 
   /* Build the external symbol information.  This must be done before
-     writing out the relocs so that we know the symbol indices.  The
-     condition checks makes sure this object was not created by
-     ecoff_bfd_final_link, since if it was we do not want to tamper
-     with the external symbols.  */
-  if (bfd_get_outsymbols (abfd) != (asymbol **) NULL)
+     writing out the relocs so that we know the symbol indices.  We
+     don't do this if this BFD was created by the backend linker,
+     since it will have already handled the symbols and relocs.  */
+  if (! ecoff_data (abfd)->linker)
     {
       symhdr->iextMax = 0;
       symhdr->issExtMax = 0;
@@ -2973,7 +2868,7 @@ ecoff_armap_hash (s, rehash, size, hlog)
 /* Read in the armap.  */
 
 boolean
-ecoff_slurp_armap (abfd)
+_bfd_ecoff_slurp_armap (abfd)
      bfd *abfd;
 {
   char nextname[17];
@@ -2994,7 +2889,8 @@ ecoff_slurp_armap (abfd)
   if (i != 16)
       return false;
 
-  bfd_seek (abfd, (file_ptr) -16, SEEK_CUR);
+  if (bfd_seek (abfd, (file_ptr) -16, SEEK_CUR) != 0)
+    return false;
 
   /* Irix 4.0.5F apparently can use either an ECOFF armap or a
      standard COFF armap.  We could move the ECOFF armap stuff into
@@ -3047,7 +2943,8 @@ ecoff_slurp_armap (abfd)
     
   if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
     {
-      bfd_set_error (bfd_error_malformed_archive);
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_malformed_archive);
       bfd_release (abfd, (PTR) raw_armap);
       return false;
     }
@@ -3144,7 +3041,7 @@ ecoff_slurp_armap (abfd)
 /* Write out an armap.  */
 
 boolean
-ecoff_write_armap (abfd, elength, map, orl_count, stridx)
+_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
      bfd *abfd;
      unsigned int elength;
      struct orl *map;
@@ -3309,8 +3206,8 @@ ecoff_write_armap (abfd, elength, map, orl_count, stridx)
 /* See whether this BFD is an archive.  If it is, read in the armap
    and the extended name table.  */
 
-bfd_target *
-ecoff_archive_p (abfd)
+const bfd_target *
+_bfd_ecoff_archive_p (abfd)
      bfd *abfd;
 {
   char armag[SARMAG + 1];
@@ -3318,8 +3215,9 @@ ecoff_archive_p (abfd)
   if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
       || strncmp (armag, ARMAG, SARMAG) != 0)
     {
-      bfd_set_error (bfd_error_wrong_format);
-      return (bfd_target *) NULL;
+      if (bfd_get_error () != bfd_error_system_call)
+       bfd_set_error (bfd_error_wrong_format);
+      return (const bfd_target *) NULL;
     }
 
   /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
@@ -3331,7 +3229,7 @@ ecoff_archive_p (abfd)
   if (bfd_ardata (abfd) == (struct artdata *) NULL)
     {
       bfd_set_error (bfd_error_no_memory);
-      return (bfd_target *) NULL;
+      return (const bfd_target *) NULL;
     }
 
   bfd_ardata (abfd)->first_file_filepos = SARMAG;
@@ -3341,12 +3239,12 @@ ecoff_archive_p (abfd)
   bfd_ardata (abfd)->extended_names = NULL;
   bfd_ardata (abfd)->tdata = NULL;
   
-  if (ecoff_slurp_armap (abfd) == false
-      || ecoff_slurp_extended_name_table (abfd) == false)
+  if (_bfd_ecoff_slurp_armap (abfd) == false
+      || _bfd_ecoff_slurp_extended_name_table (abfd) == false)
     {
       bfd_release (abfd, bfd_ardata (abfd));
       abfd->tdata.aout_ar_data = (struct artdata *) NULL;
-      return (bfd_target *) NULL;
+      return (const bfd_target *) NULL;
     }
   
   return abfd->xvec;
@@ -3398,6 +3296,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);
 
@@ -3407,18 +3307,18 @@ ecoff_link_hash_newfunc (entry, table, string)
 /* Create an ECOFF link hash table.  */
 
 struct bfd_link_hash_table *
-ecoff_bfd_link_hash_table_create (abfd)
+_bfd_ecoff_bfd_link_hash_table_create (abfd)
      bfd *abfd;
 {
   struct ecoff_link_hash_table *ret;
 
   ret = ((struct ecoff_link_hash_table *)
-        malloc (sizeof (struct ecoff_link_hash_table)));
-  if (!ret)
-      {
-       bfd_set_error (bfd_error_no_memory);
-       return NULL;
-      }
+        bfd_alloc (abfd, sizeof (struct ecoff_link_hash_table)));
+  if (ret == NULL)
+    {
+      bfd_set_error (bfd_error_no_memory);
+      return NULL;
+    }
   if (! _bfd_link_hash_table_init (&ret->root, abfd,
                                   ecoff_link_hash_newfunc))
     {
@@ -3451,7 +3351,7 @@ ecoff_bfd_link_hash_table_create (abfd)
    appropriate.  */
 
 boolean
-ecoff_bfd_link_add_symbols (abfd, info)
+_bfd_ecoff_bfd_link_add_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
@@ -3489,7 +3389,10 @@ ecoff_link_add_archive_symbols (abfd, info)
 
   if (! bfd_has_map (abfd))
     {
-      bfd_set_error (bfd_error_no_symbols);
+      /* An empty archive is a special case.  */
+      if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
+       return true;
+      bfd_set_error (bfd_error_no_armap);
       return false;
     }
 
@@ -3671,7 +3574,8 @@ ecoff_link_check_archive_element (abfd, info, pneeded)
     }
 
   if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
-      || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax)
+      || (bfd_read (ssext, 1, symhdr->issExtMax, abfd) !=
+         (bfd_size_type) symhdr->issExtMax))
     goto error_return;
 
   /* Look through the external symbols to see if they define some
@@ -3795,7 +3699,8 @@ ecoff_link_add_object_symbols (abfd, info)
     }
 
   if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
-      || bfd_read (ssext, 1, symhdr->issExtMax, abfd) != symhdr->issExtMax)
+      || (bfd_read (ssext, 1, symhdr->issExtMax, abfd)
+         != (bfd_size_type) symhdr->issExtMax))
     goto error_return;
 
   result = ecoff_link_add_externals (abfd, info, external_ext, ssext);
@@ -3915,10 +3820,10 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
          value -= section->vma;
          break;
        case scAbs:
-         section = &bfd_abs_section;
+         section = bfd_abs_section_ptr;
          break;
        case scUndefined:
-         section = &bfd_und_section;
+         section = bfd_und_section_ptr;
          break;
        case scSData:
          section = bfd_make_section_old_way (abfd, ".sdata");
@@ -3935,7 +3840,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
        case scCommon:
          if (value > ecoff_data (abfd)->gp_size)
            {
-             section = &bfd_com_section;
+             section = bfd_com_section_ptr;
              break;
            }
          /* Fall through.  */
@@ -3956,7 +3861,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
          section = &ecoff_scom_section;
          break;
        case scSUndefined:
-         section = &bfd_und_section;
+         section = bfd_und_section_ptr;
          break;
        case scInit:
          section = bfd_make_section_old_way (abfd, ".init");
@@ -3973,6 +3878,7 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
 
       name = ssext + esym.asym.iss;
 
+      h = NULL;
       if (! (_bfd_generic_link_add_one_symbol
             (info, abfd, name, BSF_GLOBAL, section, value,
              (const char *) NULL, true, true,
@@ -3986,13 +3892,34 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
       if (info->hash->creator->flavour == bfd_get_flavour (abfd))
        {
          if (h->abfd == (bfd *) NULL
-             || (section != &bfd_und_section
+             || (! bfd_is_und_section (section)
                  && (! bfd_is_com_section (section)
-                     || h->root.type != bfd_link_hash_defined)))
+                     || (h->root.type != bfd_link_hash_defined
+                         && h->root.type != bfd_link_hash_defweak))))
            {
              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.p->section->name, SCOMMON) != 0)
+           {
+             h->root.u.c.p->section = bfd_make_section_old_way (abfd,
+                                                                SCOMMON);
+             h->root.u.c.p->section->flags = SEC_ALLOC;
+             if (h->esym.asym.sc == scCommon)
+               h->esym.asym.sc = scSCommon;
+           }
        }
     }
 
@@ -4019,7 +3946,7 @@ static boolean ecoff_reloc_link_order
    close and reopen some input BFDs; I'll see how bad this is.  */
 
 boolean
-ecoff_bfd_final_link (abfd, info)
+_bfd_ecoff_bfd_final_link (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
@@ -4182,11 +4109,6 @@ ecoff_bfd_final_link (abfd, info)
 
   for (o = abfd->sections; o != (asection *) NULL; o = o->next)
     {
-      /* Ignore any link_orders for the .reginfo section, which does
-        not really exist.  */
-      if (strcmp (o->name, REGINFO) == 0)
-       continue;
-      
       for (p = o->link_order_head;
           p != (struct bfd_link_order *) NULL;
           p = p->next)
@@ -4214,6 +4136,8 @@ ecoff_bfd_final_link (abfd, info)
 
   bfd_get_symcount (abfd) = symhdr->iextMax + symhdr->isymMax;
 
+  ecoff_data (abfd)->linker = true;
+
   return true;
 }
 
@@ -4239,7 +4163,7 @@ ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle)
     debug->ptr = NULL;                                                 \
   else                                                                 \
     {                                                                  \
-      debug->ptr = (type) malloc (size * symhdr->count);               \
+      debug->ptr = (type) malloc ((size_t) (size * symhdr->count));    \
       if (debug->ptr == NULL)                                          \
        {                                                               \
           bfd_set_error (bfd_error_no_memory);                         \
@@ -4257,7 +4181,7 @@ ecoff_final_link_debug_accumulate (output_bfd, input_bfd, info, handle)
     }
 
   /* If raw_syments is not NULL, then the data was already by read by
-     ecoff_slurp_symbolic_info.  */
+     _bfd_ecoff_slurp_symbolic_info.  */
   if (ecoff_data (input_bfd)->raw_syments == NULL)
     {
       READ (line, cbLineOffset, cbLine, sizeof (unsigned char),
@@ -4331,7 +4255,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)
@@ -4344,7 +4268,8 @@ ecoff_link_write_external (h, data)
       h->esym.asym.value = 0;
       h->esym.asym.st = stGlobal;
 
-      if (h->root.type != bfd_link_hash_defined)
+      if (h->root.type != bfd_link_hash_defined
+         && h->root.type != bfd_link_hash_defweak)
        h->esym.asym.sc = scAbs;
       else
        {
@@ -4399,12 +4324,13 @@ ecoff_link_write_external (h, data)
     case bfd_link_hash_new:
       abort ();
     case bfd_link_hash_undefined:
-    case bfd_link_hash_weak:
+    case bfd_link_hash_undefweak:
       if (h->esym.asym.sc != scUndefined
          && h->esym.asym.sc != scSUndefined)
        h->esym.asym.sc = scUndefined;
       break;
     case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
       if (h->esym.asym.sc == scUndefined
          || h->esym.asym.sc == scSUndefined)
        h->esym.asym.sc = scAbs;
@@ -4432,7 +4358,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,
@@ -4480,8 +4406,8 @@ ecoff_indirect_link_order (output_bfd, info, output_section, link_order)
   /* Get the section contents.  We allocate memory for the larger of
      the size before relocating and the size after relocating.  */
   contents = (bfd_byte *) malloc (raw_size >= cooked_size
-                                 ? raw_size
-                                 : cooked_size);
+                                 ? (size_t) raw_size
+                                 : (size_t) cooked_size);
   if (contents == NULL && raw_size != 0)
     {
       bfd_set_error (bfd_error_no_memory);
@@ -4493,7 +4419,7 @@ ecoff_indirect_link_order (output_bfd, info, output_section, link_order)
      simply reuse the old buffer in case cooked_size > raw_size.  */
   if (section_tdata != (struct ecoff_section_tdata *) NULL
       && section_tdata->contents != (bfd_byte *) NULL)
-    memcpy (contents, section_tdata->contents, raw_size);
+    memcpy (contents, section_tdata->contents, (size_t) raw_size);
   else
     {
       if (! bfd_get_section_contents (input_bfd, input_section,
@@ -4511,7 +4437,7 @@ ecoff_indirect_link_order (output_bfd, info, output_section, link_order)
     external_relocs = section_tdata->external_relocs;
   else
     {
-      external_relocs = (PTR) malloc (external_relocs_size);
+      external_relocs = (PTR) malloc ((size_t) external_relocs_size);
       if (external_relocs == NULL && external_relocs_size != 0)
        {
          bfd_set_error (bfd_error_no_memory);
@@ -4591,7 +4517,7 @@ ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
   rel.address = link_order->offset;
 
   rel.howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
-  if (rel.howto == (const reloc_howto_type *) NULL)
+  if (rel.howto == 0)
     {
       bfd_set_error (bfd_error_bad_value);
       return false;
@@ -4727,7 +4653,7 @@ ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
 
   /* Get some memory and swap out the reloc.  */
   external_reloc_size = ecoff_backend (output_bfd)->external_reloc_size;
-  rbuf = (bfd_byte *) malloc (external_reloc_size);
+  rbuf = (bfd_byte *) malloc ((size_t) external_reloc_size);
   if (rbuf == (bfd_byte *) NULL)
     {
       bfd_set_error (bfd_error_no_memory);
This page took 0.053635 seconds and 4 git commands to generate.