* bfd.c (enum bfd_error): Define bfd_error_no_armap.
authorIan Lance Taylor <ian@airs.com>
Mon, 3 Jul 1995 22:16:40 +0000 (22:16 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 3 Jul 1995 22:16:40 +0000 (22:16 +0000)
(bfd_errmsgs): Add string for bfd_error_no_armap.
* bfd-in2.h: Rebuild.
* ecoff.c (ecoff_link_add_archive_symbols): If an archive has no
armap, set bfd_error_no_armap rather than bfd_error_no_symbols.
* elfcode.h (elf_link_add_archive_symbols): Likewise.
* linker.c (_bfd_generic_link_add_archive_symbols): Likewise.

bfd/bfd-in2.h
bfd/bfd.c
bfd/ecoff.c
bfd/elfcode.h
bfd/linker.c

index cbe8e8e..b197e42 100644 (file)
@@ -1919,6 +1919,7 @@ typedef enum bfd_error
   bfd_error_invalid_operation,
   bfd_error_no_memory,
   bfd_error_no_symbols,
+  bfd_error_no_armap,
   bfd_error_no_more_archived_files,
   bfd_error_malformed_archive,
   bfd_error_file_not_recognized,
@@ -2120,7 +2121,8 @@ enum bfd_flavour {
   bfd_target_srec_flavour,
   bfd_target_som_flavour,
   bfd_target_os9k_flavour,
-  bfd_target_versados_flavour
+  bfd_target_versados_flavour,
+  bfd_target_msdos_flavour
 };
 
  /* Forward declaration.  */
index b0d0a1d..d58e971 100644 (file)
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -169,6 +169,7 @@ CODE_FRAGMENT
 .      struct lynx_core_struct *lynx_core_data;
 .      struct osf_core_struct *osf_core_data;
 .      struct cisco_core_struct *cisco_core_data;
+.      struct versados_data_struct *versados_data;
 .      PTR any;
 .      } tdata;
 .  
@@ -183,6 +184,13 @@ CODE_FRAGMENT
 
 #include "bfd.h"
 #include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
 #include "bfdlink.h"
 #include "libbfd.h"
 #include "coff/internal.h"
@@ -193,6 +201,16 @@ CODE_FRAGMENT
 #include "libelf.h"
 
 \f
+/* provide storage for subsystem, stack and heap data which may have been
+   passed in on the command line.  Ld puts this data into a bfd_link_info
+   struct which ultimately gets passed in to the bfd.  When it arrives, copy
+   it to the following struct so that the data will be available in coffcode.h
+   where it is needed.  The typedef's used are defined in bfd.h */
+
+enum bfd_link_subsystem NT_subsystem;
+
+bfd_link_stack_heap NT_stack_heap;
+\f
 /*
 SECTION
        Error reporting
@@ -224,6 +242,7 @@ CODE_FRAGMENT
 .  bfd_error_invalid_operation,
 .  bfd_error_no_memory,
 .  bfd_error_no_symbols,
+.  bfd_error_no_armap,
 .  bfd_error_no_more_archived_files,
 .  bfd_error_malformed_archive,
 .  bfd_error_file_not_recognized,
@@ -233,6 +252,7 @@ CODE_FRAGMENT
 .  bfd_error_no_debug_section,
 .  bfd_error_bad_value,
 .  bfd_error_file_truncated,
+.  bfd_error_file_too_big,
 .  bfd_error_invalid_error_code
 .} bfd_error_type;
 .
@@ -251,6 +271,7 @@ CONST char *CONST bfd_errmsgs[] = {
                         "Invalid operation",
                         "Memory exhausted",
                         "No symbols",
+                       "Archive has no index; run ranlib to add one",
                         "No more archived files",
                         "Malformed archive",
                         "File format not recognized",
@@ -260,6 +281,7 @@ CONST char *CONST bfd_errmsgs[] = {
                        "Symbol needs debug section which does not exist",
                        "Bad value",
                        "File truncated",
+                       "File too big",
                         "#<Invalid error code>"
                        };
 
@@ -356,6 +378,126 @@ bfd_perror (message)
   }
 }
 
+/*
+SUBSECTION
+       BFD error handler
+
+       Some BFD functions want to print messages describing the
+       problem.  They call a BFD error handler function.  This
+       function may be overriden by the program.
+
+       The BFD error handler acts like printf.
+
+CODE_FRAGMENT
+.
+.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+.
+*/
+
+/* The program name used when printing BFD error messages.  */
+
+static const char *_bfd_error_program_name;
+
+/* This is the default routine to handle BFD error messages.  */
+
+#ifdef ANSI_PROTOTYPES
+
+static void _bfd_default_error_handler PARAMS ((const char *s, ...));
+
+static void
+_bfd_default_error_handler (const char *s, ...)
+{
+  va_list p;
+
+  if (_bfd_error_program_name != NULL)
+    fprintf (stderr, "%s: ", _bfd_error_program_name);
+
+  va_start (p, s);
+
+  vfprintf (stderr, s, p);
+
+  va_end (p);
+
+  fprintf (stderr, "\n");
+}
+
+#else /* ! defined (ANSI_PROTOTYPES) */
+
+static void _bfd_default_error_handler ();
+
+static void
+_bfd_default_error_handler (va_alist)
+     va_dcl
+{
+  va_list p;
+  const char *s;
+
+  if (_bfd_error_program_name != NULL)
+    fprintf (stderr, "%s: ", _bfd_error_program_name);
+
+  va_start (p);
+
+  s = va_arg (p, const char *);
+  vfprintf (stderr, s, p);
+
+  va_end (p);
+
+  fprintf (stderr, "\n");
+}
+
+#endif /* ! defined (ANSI_PROTOTYPES) */
+
+/* This is a function pointer to the routine which should handle BFD
+   error messages.  It is called when a BFD routine encounters an
+   error for which it wants to print a message.  Going through a
+   function pointer permits a program linked against BFD to intercept
+   the messages and deal with them itself.  */
+
+bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler;
+
+/*
+FUNCTION
+       bfd_set_error_handler
+
+SYNOPSIS
+       bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
+
+DESCRIPTION
+       Set the BFD error handler function.  Returns the previous
+       function.
+*/
+
+bfd_error_handler_type
+bfd_set_error_handler (pnew)
+     bfd_error_handler_type pnew;
+{
+  bfd_error_handler_type pold;
+
+  pold = _bfd_error_handler;
+  _bfd_error_handler = pnew;
+  return pold;
+}
+
+/*
+FUNCTION
+       bfd_set_error_program_name
+
+SYNOPSIS
+       void bfd_set_error_program_name (const char *);
+
+DESCRIPTION
+       Set the program name to use when printing a BFD error.  This
+       is printed before the error message followed by a colon and
+       space.  The string must not be changed after it is passed to
+       this function.
+*/
+
+void
+bfd_set_error_program_name (name)
+     const char *name;
+{
+  _bfd_error_program_name = name;
+}
 \f
 /*
 SECTION
@@ -696,7 +838,7 @@ bfd_scan_vma (string, end, base)
 
   /* Let the host do it if possible.  */
   if (sizeof(bfd_vma) <= sizeof(unsigned long))
-    return (bfd_vma) strtoul (string, end, base);
+    return (bfd_vma) strtoul (string, (char **) end, base);
 
   /* A negative base makes no sense, and we only need to go as high as hex.  */
   if ((base < 0) || (base > 16))
@@ -762,6 +904,48 @@ DESCRIPTION
 
 /*
 FUNCTION
+       bfd_merge_private_bfd_data
+
+SYNOPSIS
+       boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+       Merge private BFD information from the BFD @var{ibfd} to the 
+       the output file BFD @var{obfd} when linking.  Return <<true>>
+       on success, <<false>> on error.  Possible error returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_merge_private_bfd_data(ibfd, obfd) \
+.     BFD_SEND (ibfd, _bfd_merge_private_bfd_data, \
+.              (ibfd, obfd))
+
+*/
+
+/*
+FUNCTION
+       bfd_set_private_flags
+
+SYNOPSIS
+       boolean bfd_set_private_flags(bfd *abfd, flagword flags);
+
+DESCRIPTION
+       Set private BFD flag information in the BFD @var{abfd}.
+       Return <<true>> on success, <<false>> on error.  Possible error
+       returns are:
+
+       o <<bfd_error_no_memory>> -
+       Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_set_private_flags(abfd, flags) \
+.     BFD_SEND (abfd, _bfd_set_private_flags, \
+.              (abfd, flags))
+
+*/
+
+/*
+FUNCTION
        stuff
 
 DESCRIPTION
@@ -793,10 +977,6 @@ DESCRIPTION
 .#define bfd_set_arch_mach(abfd, arch, mach)\
 .        BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
 .
-.#define bfd_get_relocated_section_contents(abfd, link_info, link_order, data, relocateable, symbols) \
-.      BFD_SEND (abfd, _bfd_get_relocated_section_contents, \
-.                 (abfd, link_info, link_order, data, relocateable, symbols))
-. 
 .#define bfd_relax_section(abfd, section, link_info, again) \
 .       BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again))
 .
@@ -824,5 +1004,38 @@ DESCRIPTION
 .#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \
 .      BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms))
 .
+.extern bfd_byte *bfd_get_relocated_section_contents
+.      PARAMS ((bfd *, struct bfd_link_info *,
+.                struct bfd_link_order *, bfd_byte *,
+.                boolean, asymbol **));
+.
 
 */
+
+bfd_byte *
+bfd_get_relocated_section_contents (abfd, link_info, link_order, data,
+                                   relocateable, symbols)
+     bfd *abfd;
+     struct bfd_link_info *link_info;
+     struct bfd_link_order *link_order;
+     bfd_byte *data;
+     boolean relocateable;
+     asymbol **symbols;
+{
+  bfd *abfd2;
+  bfd_byte *(*fn) PARAMS ((bfd *, struct bfd_link_info *,
+                          struct bfd_link_order *, bfd_byte *, boolean,
+                          asymbol **));
+
+  if (link_order->type == bfd_indirect_link_order)
+    {
+      abfd2 = link_order->u.indirect.section->owner;
+      if (abfd2 == 0)
+       abfd2 = abfd;
+    }
+  else
+    abfd2 = abfd;
+  fn = abfd2->xvec->_bfd_get_relocated_section_contents;
+
+  return (*fn) (abfd, link_info, link_order, data, relocateable, symbols);
+}
index f5461ae..8d67697 100644 (file)
@@ -123,6 +123,8 @@ _bfd_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
@@ -408,201 +410,6 @@ _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
   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
-_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern)
-     int bigend;
-     const 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
-_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext)
-     int bigend;
-     const 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
-_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern)
-     int bigend;
-     const 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
-_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext)
-     int bigend;
-     const 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
@@ -2002,164 +1809,6 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
   return section->reloc_count;
 }
 \f
-
-static int
-cmp_fdrtab_entry (leftp, rightp)
-     const void *leftp, *rightp;
-{
-  const struct ecoff_fdrtab_entry *lp = leftp;
-  const struct ecoff_fdrtab_entry *rp = rightp;
-
-  if (lp->base_addr < rp->base_addr)
-    return -1;
-  if (lp->base_addr > rp->base_addr)
-    return  1;
-  return 0;
-}
-
-/* Each file descriptor (FDR) has a memory address, to simplify
-   looking up an FDR by address, we build a table covering all FDRs
-   that have a least one procedure descriptor in them.  The final
-   table will be sorted by address so we can look it up via binary
-   search.  */
-static boolean
-mk_fdrtab (abfd)
-     bfd *abfd;
-{
-  struct ecoff_debug_info * const debug_info = &ecoff_data (abfd)->debug_info;
-  const struct ecoff_debug_swap * const debug_swap
-    = &ecoff_backend (abfd)->debug_swap;
-  struct ecoff_fdrtab_entry *tab;
-  FDR *fdr_ptr;
-  FDR *fdr_start;
-  FDR *fdr_end;
-  boolean stabs;
-  long len;
-
-  /* Make sure we have the FDR's.  */
-  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
-      || bfd_get_symcount (abfd) == 0)
-    return false;
-
-  fdr_start = debug_info->fdr;
-  fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
-
-  /* First, let's see how long the table needs to be: */
-  for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
-    {
-      if (fdr_ptr->cpd == 0)   /* skip FDRs that have no PDRs */
-       continue;
-      ++len;
-    }
-
-  /* Now, create and fill in the table: */
-
-  ecoff_data (abfd)->fdrtab = (struct ecoff_fdrtab_entry*)
-    bfd_zalloc (abfd,len * sizeof (struct ecoff_fdrtab_entry));
-  if (ecoff_data (abfd)->fdrtab == NULL)
-    {
-      bfd_set_error (bfd_error_no_memory);
-      return false;
-    }
-  ecoff_data (abfd)->fdrtab_len = len;
-
-  tab = ecoff_data (abfd)->fdrtab;
-  for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
-    {
-      if (fdr_ptr->cpd == 0)
-       continue;
-
-      /* Check whether this file has stabs debugging information.  In
-        a file with stabs debugging information, the second local
-        symbol is named @stabs.  */
-      stabs = false;
-      if (fdr_ptr->csym >= 2)
-       {
-         char *sym_ptr;
-         SYMR sym;
-
-         sym_ptr = ((char *) debug_info->external_sym
-                    + (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size);
-         (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
-         if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
-                     STABS_SYMBOL) == 0)
-           stabs = true;
-       }
-
-      if (!stabs)
-       {
-         bfd_size_type external_pdr_size;
-         char *pdr_ptr;
-         PDR pdr;
-
-         external_pdr_size = debug_swap->external_pdr_size;
-
-         pdr_ptr = ((char *) debug_info->external_pdr
-                    + fdr_ptr->ipdFirst * external_pdr_size);
-         (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-         /* The address of the first PDR is the offset of that
-            procedure relative to the beginning of file FDR.  */
-         tab->base_addr = fdr_ptr->adr - pdr.adr;
-       }
-      else
-       {
-         /* XXX I don't know about stabs, so this is a guess
-            (davidm@cs.arizona.edu): */
-         tab->base_addr = fdr_ptr->adr;
-       }
-      tab->fdr = fdr_ptr;
-      ++tab;
-    }
-  /* Finally, the table is sorted in increasing memory-address order.
-     The table is mostly sorted already, but there are cases (e.g.,
-     static functions in include files), where this does not hold.
-     Use "odump -PFv" to verify...  */
-  qsort((char*) ecoff_data (abfd)->fdrtab, len,
-       sizeof(struct ecoff_fdrtab_entry), cmp_fdrtab_entry);
-
-  return true;
-}
-
-/* Return index of first FDR that covers to OFFSET.  */
-static long
-lookup (abfd, offset)
-     bfd *abfd;
-     bfd_vma offset;
-{
-  long low, high, len;
-  long mid = -1;
-  struct ecoff_fdrtab_entry *tab;
-
-  len = ecoff_data(abfd)->fdrtab_len;
-  if (!len)
-    return -1;
-
-  tab = ecoff_data(abfd)->fdrtab;
-  for (low = 0, high = len - 1 ; low != high ;)
-    {
-      mid = (high + low) / 2;
-      if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr)
-       goto find_min;
-
-      if (tab[mid].base_addr > offset)
-       high = mid;
-      else
-       low = mid + 1;
-    }
-  ++mid;
-
-  /* last entry is catch-all for all higher addresses: */
-  if (offset < tab[mid].base_addr)
-    return -1;
-
- find_min:
-
-  while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr)
-    --mid;
-
-  return mid;
-}
-
 /* Provided a BFD, a section and an offset into the section, calculate
    and return the name of the source file and the line nearest to the
    wanted location.  */
@@ -2179,395 +1828,37 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
   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;
-  struct ecoff_fdrtab_entry *tab;
-  boolean stabs;
-  FDR *fdr_ptr;
-  int i;
+  struct ecoff_find_line *line_info;
 
-  offset += section->vma;
   /* If we're not in the .text section, we don't have any line
      numbers.  */
   if (strcmp (section->name, _TEXT) != 0
       || offset < ecoff_data (abfd)->text_start
       || offset >= ecoff_data (abfd)->text_end)
     return false;
-  /* Build FDR table (sorted by object file's base-address) if we
-     don't have it already.  */
-  if (!ecoff_data (abfd)->fdrtab && !mk_fdrtab (abfd))
-    return false;
-  tab = ecoff_data (abfd)->fdrtab;
-
-  i = lookup(abfd, offset);    /* find first FDR for address OFFSET */
-  if (i < 0)
-    return false;              /* no FDR, no fun... */
-  fdr_ptr = tab[i].fdr;
-
-  /* Check whether this file has stabs debugging information.  In a
-     file with stabs debugging information, the second local symbol is
-     named @stabs.  */
-  stabs = false;
-  if (fdr_ptr->csym >= 2)
-    {
-      char *sym_ptr;
-      SYMR sym;
-
-      sym_ptr = ((char *) debug_info->external_sym
-                + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size);
-      (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
-      if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
-                 STABS_SYMBOL) == 0)
-       stabs = true;
-    }
 
-  if (!stabs)
-    {
-      bfd_size_type external_pdr_size;
-      char *pdr_ptr;
-      char *best_pdr = NULL;
-      FDR *best_fdr;
-      bfd_vma best_dist = ~0;
-      PDR pdr;
-      unsigned char *line_ptr;
-      unsigned char *line_end;
-      int lineno;
-      /* This file uses ECOFF debugging information.  Each FDR has a
-         list of procedure descriptors (PDR).  The address in the FDR
-         is the absolute address of the first procedure.  The address
-         in the first PDR gives the offset of that procedure relative
-         to the object file's base-address.  The addresses in
-         subsequent PDRs specify each procedure's address relative to
-         the object file's base-address.  To make things more juicy,
-         whenever the PROF bit in the PDR is set, the real entry point
-         of the procedure may be 16 bytes below what would normally be
-         the procedure's entry point.  Instead, DEC came up with a
-         wicked scheme to create profiled libraries "on the fly":
-         instead of shipping a regular and a profiled version of each
-         library, they insert 16 bytes of unused space in front of
-         each procedure and set the "prof" bit in the PDR to indicate
-         that there is a gap there (this is done automagically by "as"
-         when option "-pg" is specified).  Thus, normally, you link
-         against such a library and, except for lots of 16 byte gaps
-         between functions, things will behave as usual.  However,
-         when invoking "ld" with option "-pg", it will fill those gaps
-         with code that calls mcount().  It then moves the function's
-         entry point down by 16 bytes, and out pops a binary that has
-         all functions profiled.
-
-         NOTE: Neither FDRs nor PDRs are strictly sorted in memory
-               order.  For example, when including header-files that
-               define functions, the FDRs follow behind the including
-               file, even though their code may have been generated at
-               a lower address.  File coff-alpha.c from libbfd
-               illustrates this (use "odump -PFv" to look at a file's
-               FDR/PDR).  Similarly, PDRs are sometimes out of order
-               as well.  An example of this is OSF/1 v3.0 libc's
-               malloc.c.  I'm not sure why this happens, but it could
-               be due to optimizations that reorder a function's
-               position within an object-file.
-        
-         Strategy:
-         
-         On the first call to this function, we build a table of FDRs
-         that is sorted by the base-address of the object-file the FDR
-         is referring to.  Notice that each object-file may contain
-         code from multiple source files (e.g., due to code defined in
-         include files).  Thus, for any given base-address, there may
-         be multiple FDRs (but this case is, fortunately, uncommon).
-         lookup(addr) guarantees to return the first FDR that applies
-         to address ADDR.  Thus, after invoking lookup(), we have a
-         list of FDRs that may contain the PDR for ADDR.  Next, we
-         walk through the PDRs of these FDRs and locate the one that
-         is closest to ADDR (i.e., for which the difference between
-         ADDR and the PDR's entry point is positive and minimal).
-         Once, the right FDR and PDR are located, we simply walk
-         through the line-number table to lookup the line-number that
-         best matches ADDR.  Obviously, things could be sped up by
-         keeping a sorted list of PDRs instead of a sorted list of
-         FDRs.  However, this would increase space requirements
-         considerably, which is undesirable.  */
-      external_pdr_size = debug_swap->external_pdr_size;
-
-      /* Make offset relative to object file's start-address: */
-      offset -= tab[i].base_addr;
-      /* Search FDR list starting at tab[i] for the PDR that best matches
-         OFFSET.  Normally, the FDR list is only one entry long.  */
-      best_fdr = NULL;
-      do
-       {
-         bfd_vma dist, min_dist = 0;
-         char *pdr_hold;
-         char *pdr_end;
-         
-         fdr_ptr = tab[i].fdr;
-         
-         pdr_ptr = ((char *) 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);
-         /* Find PDR that is closest to OFFSET.  If pdr.prof is set,
-            the procedure entry-point *may* be 0x10 below pdr.adr.  We
-            simply pretend that pdr.prof *implies* a lower entry-point.
-            This is safe because it just means that may identify 4 NOPs
-            in front of the function as belonging to the function.  */
-         for (pdr_hold = NULL;
-              pdr_ptr < pdr_end;
-              (pdr_ptr += external_pdr_size,
-               (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr)))
-           {
-             if (offset >= (pdr.adr - 0x10 * pdr.prof))
-               {
-                 dist = offset - (pdr.adr - 0x10 * pdr.prof);
-                 if (!pdr_hold || dist < min_dist)
-                   {
-                     min_dist = dist;
-                     pdr_hold = pdr_ptr;
-                   }
-               }
-           }
-         
-         if (!best_pdr || min_dist < best_dist)
-           {
-             best_dist = min_dist;
-             best_fdr = fdr_ptr;
-             best_pdr = pdr_hold;
-           }
-         /* continue looping until base_addr of next entry is different: */
-       }
-      while (++i < ecoff_data (abfd)->fdrtab_len
-            && tab[i].base_addr == tab[i - 1].base_addr);
-
-      if (!best_fdr || !best_pdr)
-       return false;                   /* shouldn't happen... */
-
-      /* phew, finally we got something that we can hold onto: */
-      fdr_ptr = best_fdr;
-      pdr_ptr = best_pdr;
-      (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
-      /* 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.  The search is bounded by the end of the FDRs line
-         number entries.  */
-      line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
-
-      /* Make offset relative to procedure entry: */
-      offset -= pdr.adr - 0x10 * pdr.prof;
-      lineno = pdr.lnLow;
-      line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset;
-      while (line_ptr < line_end)
-       {
-         int delta;
-         int count;
-
-         delta = *line_ptr >> 4;
-         if (delta >= 0x8)
-           delta -= 0x10;
-         count = (*line_ptr & 0xf) + 1;
-         ++line_ptr;
-         if (delta == -8)
-           {
-             delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
-             if (delta >= 0x8000)
-               delta -= 0x10000;
-             line_ptr += 2;
-           }
-         lineno += delta;
-         if (offset < count * 4)
-           break;
-         offset -= count * 4;
-       }
+  /* Make sure we have the FDR's.  */
+  if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
+      || bfd_get_symcount (abfd) == 0)
+    return false;
 
-      /* 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)
-       {
-         *filename_ptr = NULL;
-         if (pdr.isym == -1)
-           *functionname_ptr = NULL;
-         else
-           {
-             EXTR proc_ext;
-
-             (*debug_swap->swap_ext_in)
-               (abfd,
-                ((char *) debug_info->external_ext
-                 + pdr.isym * debug_swap->external_ext_size),
-                &proc_ext);
-             *functionname_ptr = debug_info->ssext + proc_ext.asym.iss;
-           }
-       }
-      else
-       {
-         SYMR proc_sym;
-
-         *filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss;
-         (*debug_swap->swap_sym_in)
-           (abfd,
-            ((char *) debug_info->external_sym
-             + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
-            &proc_sym);
-         *functionname_ptr = debug_info->ss + fdr_ptr->issBase + proc_sym.iss;
-       }
-      if (lineno == ilineNil)
-       lineno = 0;
-      *retline_ptr = lineno;
-    }
-  else
+  if (ecoff_data (abfd)->find_line_info == NULL)
     {
-      bfd_size_type external_sym_size;
-      const char *directory_name;
-      const char *main_file_name;
-      const char *current_file_name;
-      const char *function_name;
-      const char *line_file_name;
-      bfd_vma low_func_vma;
-      bfd_vma low_line_vma;
-      char *sym_ptr, *sym_ptr_end;
-      size_t len, funclen;
-      char *buffer = NULL;
-
-      /* This file uses stabs debugging information.  */
-
-      *filename_ptr = NULL;
-      *functionname_ptr = NULL;
-      *retline_ptr = 0;
-
-      directory_name = NULL;
-      main_file_name = NULL;
-      current_file_name = NULL;
-      function_name = NULL;
-      line_file_name = NULL;
-      low_func_vma = 0;
-      low_line_vma = 0;
-
-      external_sym_size = debug_swap->external_sym_size;
-
-      sym_ptr = ((char *) debug_info->external_sym
-                + (fdr_ptr->isymBase + 2) * external_sym_size);
-      sym_ptr_end = sym_ptr + fdr_ptr->csym * external_sym_size;
-      for (; sym_ptr < sym_ptr_end; sym_ptr += external_sym_size)
-       {
-         SYMR sym;
-
-         (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
-
-         if (ECOFF_IS_STAB (&sym))
-           {
-             switch (ECOFF_UNMARK_STAB (sym.index))
-               {
-               case N_SO:
-                 main_file_name = current_file_name =
-                   debug_info->ss + fdr_ptr->issBase + sym.iss;
-
-                 /* Check the next symbol to see if it is also an
-                     N_SO symbol.  */
-                 if (sym_ptr + external_sym_size < sym_ptr_end)
-                   {
-                     SYMR nextsym;
-
-                     (*debug_swap->swap_sym_in) (abfd,
-                                                 sym_ptr + external_sym_size,
-                                                 &nextsym);
-                     if (ECOFF_IS_STAB (&nextsym)
-                         && ECOFF_UNMARK_STAB (nextsym.index) == N_SO)
-                       {
-                         directory_name = current_file_name;
-                         main_file_name = current_file_name =
-                           debug_info->ss + fdr_ptr->issBase + sym.iss;
-                         sym_ptr += external_sym_size;
-                       }
-                   }
-                 break;
-
-               case N_SOL:
-                 current_file_name =
-                   debug_info->ss + fdr_ptr->issBase + sym.iss;
-                 break;
-
-               case N_FUN:
-                 if (sym.value >= low_func_vma
-                     && sym.value <= offset + section->vma)
-                   {
-                     low_func_vma = sym.value;
-                     function_name =
-                       debug_info->ss + fdr_ptr->issBase + sym.iss;
-                   }
-                 break;
-               }
-           }
-         else if (sym.st == stLabel && sym.index != indexNil)
-           {
-             if (sym.value > offset + section->vma)
-               {
-                 /* We have passed the location in the file we are
-                    looking for, so we can get out of the loop.  */
-                 break;
-               }
-
-             if (sym.value >= low_line_vma)
-               {
-                 low_line_vma = sym.value;
-                 line_file_name = current_file_name;
-                 *retline_ptr = sym.index;
-               }
-           }
-       }
-
-      if (*retline_ptr != 0)
-       main_file_name = line_file_name;
-
-      /* We need to remove the stuff after the colon in the function
-         name.  We also need to put the directory name and the file
-         name together.  */
-      if (function_name == NULL)
-       len = funclen = 0;
-      else
-       len = funclen = strlen (function_name) + 1;
-
-      if (main_file_name != NULL
-         && directory_name != NULL
-         && main_file_name[0] != '/')
-       len += strlen (directory_name) + strlen (main_file_name) + 1;
-
-      if (len != 0)
-       {
-         if (ecoff_data (abfd)->find_buffer != NULL)
-           free (ecoff_data (abfd)->find_buffer);
-         buffer = (char *) malloc (len);
-         if (buffer == NULL)
-           {
-             bfd_set_error (bfd_error_no_memory);
-             return false;
-           }
-         ecoff_data (abfd)->find_buffer = buffer;
-       }
-
-      if (function_name != NULL)
+      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)
        {
-         char *colon;
-
-         strcpy (buffer, function_name);
-         colon = strchr (buffer, ':');
-         if (colon != NULL)
-           *colon = '\0';
-         *functionname_ptr = buffer;
-       }
-
-      if (main_file_name != NULL)
-       {
-         if (directory_name == NULL || main_file_name[0] == '/')
-           *filename_ptr = main_file_name;
-         else
-           {
-             sprintf (buffer + funclen, "%s%s", directory_name,
-                      main_file_name);
-             *filename_ptr = buffer + funclen;
-           }
+         bfd_set_error (bfd_error_no_memory);
+         return false;
        }
     }
+  line_info = ecoff_data (abfd)->find_line_info;
 
-  return true;
+  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
@@ -3194,8 +2485,8 @@ _bfd_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
@@ -4087,7 +3378,7 @@ ecoff_link_add_archive_symbols (abfd, info)
       /* 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_symbols);
+      bfd_set_error (bfd_error_no_armap);
       return false;
     }
 
@@ -4605,10 +3896,11 @@ ecoff_link_add_externals (abfd, info, external_ext, ssext)
             on Ultrix 4.2 to handle the symbol cred in -lckrb.  */
          if (h->small
              && h->root.type == bfd_link_hash_common
-             && strcmp (h->root.u.c.section->name, SCOMMON) != 0)
+             && strcmp (h->root.u.c.p->section->name, SCOMMON) != 0)
            {
-             h->root.u.c.section = bfd_make_section_old_way (abfd, SCOMMON);
-             h->root.u.c.section->flags = SEC_ALLOC;
+             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;
            }
index 4c73825..2ce8bed 100644 (file)
@@ -4035,7 +4035,7 @@ elf_link_add_archive_symbols (abfd, info)
       /* 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_symbols);
+      bfd_set_error (bfd_error_no_armap);
       return false;
     }
 
index 0d7e47a..4ce41e9 100644 (file)
@@ -867,7 +867,7 @@ _bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
       /* 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_symbols);
+      bfd_set_error (bfd_error_no_armap);
       return false;
     }