1999-08-18 Donn Terry <donn@interix.com>
[deliverable/binutils-gdb.git] / bfd / ecoff.c
index 5c04b1b8d8ff16de10840459c6b3ca5f756b7a46..142cf40cbd424be4e5d3b515b19a2b42970e73ee 100644 (file)
@@ -1,5 +1,6 @@
 /* Generic ECOFF (Extended-COFF) routines.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
    Original version by Per Bothner.
    Full support added by Ian Lance Taylor, ian@cygnus.com.
 
@@ -71,7 +72,12 @@ static unsigned int ecoff_armap_hash PARAMS ((CONST char *s,
 \f
 /* This stuff is somewhat copied from coffcode.h.  */
 
-static asection bfd_debug_section = { "*DEBUG*" };
+static asection bfd_debug_section =
+{
+  "*DEBUG*", 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 0, NULL, NULL,
+   0, 0, 0, 0, NULL, NULL, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL
+};
 
 /* Create an ECOFF object.  */
 
@@ -137,23 +143,14 @@ _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
 
 boolean
 _bfd_ecoff_new_section_hook (abfd, section)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      asection *section;
 {
-  /* For the .pdata section, which has a special meaning on the Alpha,
-     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.  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 = 4;
+  section->alignment_power = 4;
 
-  if (strcmp (section->name, _TEXT) == 0)
+  if (strcmp (section->name, _TEXT) == 0
+      || strcmp (section->name, _INIT) == 0
+      || strcmp (section->name, _FINI) == 0)
     section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
   else if (strcmp (section->name, _DATA) == 0
           || strcmp (section->name, _SDATA) == 0)
@@ -161,7 +158,8 @@ _bfd_ecoff_new_section_hook (abfd, section)
   else if (strcmp (section->name, _RDATA) == 0
           || strcmp (section->name, _LIT8) == 0
           || strcmp (section->name, _LIT4) == 0
-          || strcmp (section->name, _RCONST) == 0)
+          || strcmp (section->name, _RCONST) == 0
+          || strcmp (section->name, _PDATA) == 0)
     section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
   else if (strcmp (section->name, _BSS) == 0
           || strcmp (section->name, _SBSS) == 0)
@@ -262,7 +260,7 @@ ecoff_get_magic (abfd)
          break;
        }
 
-      return abfd->xvec->byteorder_big_p ? big : little;
+      return bfd_big_endian (abfd) ? big : little;
 
     case bfd_arch_alpha:
       return ALPHA_MAGIC;
@@ -357,9 +355,9 @@ ecoff_sec_to_styp_flags (name, flags)
 /*ARGSUSED*/
 flagword
 _bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
-     bfd *abfd;
+     bfd *abfd ATTRIBUTE_UNUSED;
      PTR hdr;
-     const char *name;
+     const char *name ATTRIBUTE_UNUSED;
 {
   struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
   long styp_flags = internal_s->s_flags;
@@ -503,7 +501,7 @@ ecoff_slurp_symbolic_header (abfd)
 boolean
 _bfd_ecoff_slurp_symbolic_info (abfd, ignore, debug)
      bfd *abfd;
-     asection *ignore;
+     asection *ignore ATTRIBUTE_UNUSED;
      struct ecoff_debug_info *debug;
 {
   const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
@@ -842,6 +840,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak)
        case N_SETD:
        case N_SETB:
          {
+           /* This code is no longer needed.  It used to be used to
+              make the linker handle set symbols, but they are now
+              handled in the add_symbols routine instead.  */
+#if 0
            const char *name;
            asection *section;
            arelent_chain *reloc_chain;
@@ -901,6 +903,8 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak)
            section->constructor_chain = reloc_chain;
            section->_raw_size += bitsize / 8;
 
+#endif /* 0 */
+
            /* Mark the symbol as a constructor.  */
            asym->flags |= BSF_CONSTRUCTOR;
          }
@@ -1306,7 +1310,7 @@ ecoff_type_to_string (abfd, fdr, indx)
       break;
 
     default:
-      sprintf (p1, "Unknown basic type %d", (int) basic_type);
+      sprintf (p1, _("Unknown basic type %d"), (int) basic_type);
       break;
     }
 
@@ -1434,7 +1438,7 @@ ecoff_type_to_string (abfd, fdr, indx)
 /*ARGSUSED*/
 void
 _bfd_ecoff_get_symbol_info (abfd, symbol, ret)
-     bfd *abfd;                        /* Ignored.  */
+     bfd *abfd ATTRIBUTE_UNUSED;
      asymbol *symbol;
      symbol_info *ret;
 {
@@ -1445,11 +1449,11 @@ _bfd_ecoff_get_symbol_info (abfd, symbol, ret)
 
 /*ARGSUSED*/
 boolean
-_bfd_ecoff_bfd_is_local_label (abfd, symbol)
-     bfd *abfd;
-     asymbol *symbol;
+_bfd_ecoff_bfd_is_local_label_name (abfd, name)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     const char *name;
 {
-  return symbol->name[0] == '$';
+  return name[0] == '$';
 }
 
 /* Print information about an ECOFF symbol.  */
@@ -1578,17 +1582,17 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how)
 
              case stFile:
              case stBlock:
-               fprintf (file, "\n      End+1 symbol: %ld",
+               fprintf (file, _("\n      End+1 symbol: %ld"),
                         (long) (indx + sym_base));
                break;
 
              case stEnd:
                if (ecoff_ext.asym.sc == scText
                    || ecoff_ext.asym.sc == scInfo)
-                 fprintf (file, "\n      First symbol: %ld",
+                 fprintf (file, _("\n      First symbol: %ld"),
                           (long) (indx + sym_base));
                else
-                 fprintf (file, "\n      First symbol: %ld"
+                 fprintf (file, _("\n      First symbol: %ld")
                           ((long)
                            (AUX_GET_ISYM (bigendian,
                                           &aux_base[ecoff_ext.asym.index])
@@ -1600,14 +1604,14 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how)
                if (ECOFF_IS_STAB (&ecoff_ext.asym))
                  ;
                else if (ecoffsymbol (symbol)->local)
-                 fprintf (file, "\n      End+1 symbol: %-7ld   Type:  %s",
+                 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, fdr, indx + 1));
                else
-                 fprintf (file, "\n      Local symbol: %ld",
+                 fprintf (file, _("\n      Local symbol: %ld"),
                           ((long) indx
                            + (long) sym_base
                            + (ecoff_data (abfd)
@@ -1615,23 +1619,23 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how)
                break;
 
              case stStruct:
-               fprintf (file, "\n      struct; End+1 symbol: %ld",
+               fprintf (file, _("\n      struct; End+1 symbol: %ld"),
                         (long) (indx + sym_base));
                break;
 
              case stUnion:
-               fprintf (file, "\n      union; End+1 symbol: %ld",
+               fprintf (file, _("\n      union; End+1 symbol: %ld"),
                         (long) (indx + sym_base));
                break;
 
              case stEnum:
-               fprintf (file, "\n      enum; End+1 symbol: %ld",
+               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",
+                 fprintf (file, _("\n      Type: %s"),
                           ecoff_type_to_string (abfd, fdr, indx));
                break;
              }
@@ -1802,7 +1806,7 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
                              filename_ptr, functionname_ptr, retline_ptr)
      bfd *abfd;
      asection *section;
-     asymbol **ignore_symbols;
+     asymbol **ignore_symbols ATTRIBUTE_UNUSED;
      bfd_vma offset;
      CONST char **filename_ptr;
      CONST char **functionname_ptr;
@@ -1813,12 +1817,6 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
   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.  */
-  if (strcmp (section->name, _TEXT) != 0
-      || offset >= bfd_section_size (abfd, section))
-    return false;
-
   /* Make sure we have the FDR's.  */
   if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
       || bfd_get_symcount (abfd) == 0)
@@ -1828,12 +1826,9 @@ _bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
     {
       ecoff_data (abfd)->find_line_info =
        ((struct ecoff_find_line *)
-        bfd_alloc (abfd, sizeof (struct ecoff_find_line)));
+        bfd_zalloc (abfd, sizeof (struct ecoff_find_line)));
       if (ecoff_data (abfd)->find_line_info == NULL)
        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;
 
@@ -1867,10 +1862,10 @@ _bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
   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
+  /* We only want to copy information over if both BFD's use ECOFF
      format.  */
-  if (bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
+  if (bfd_get_flavour (ibfd) != bfd_target_ecoff_flavour
+      || bfd_get_flavour (obfd) != bfd_target_ecoff_flavour)
     return true;
 
   /* Copy the GP value and the register masks.  */
@@ -1981,7 +1976,7 @@ _bfd_ecoff_set_arch_mach (abfd, arch, machine)
 int
 _bfd_ecoff_sizeof_headers (abfd, reloc)
      bfd *abfd;
-     boolean reloc;
+     boolean reloc ATTRIBUTE_UNUSED;
 {
   asection *current;
   int c;
@@ -2049,15 +2044,17 @@ static boolean
 ecoff_compute_section_file_positions (abfd)
      bfd *abfd;
 {
-  file_ptr sofar;
+  file_ptr sofar, file_sofar;
   asection **sorted_hdrs;
   asection *current;
   unsigned int i;
   file_ptr old_sofar;
+  boolean rdata_in_text;
   boolean first_data, first_nonalloc;
   const bfd_vma round = ecoff_backend (abfd)->round;
 
   sofar = _bfd_ecoff_sizeof_headers (abfd, false);
+  file_sofar = sofar;
 
   /* Sort the sections by VMA.  */
   sorted_hdrs = (asection **) bfd_malloc (abfd->section_count
@@ -2073,6 +2070,27 @@ ecoff_compute_section_file_positions (abfd)
   qsort (sorted_hdrs, abfd->section_count, sizeof (asection *),
         ecoff_sort_hdrs);
 
+  /* Some versions of the OSF linker put the .rdata section in the
+     text segment, and some do not.  */
+  rdata_in_text = ecoff_backend (abfd)->rdata_in_text;
+  if (rdata_in_text)
+    {
+      for (i = 0; i < abfd->section_count; i++)
+       {
+         current = sorted_hdrs[i];
+         if (strcmp (current->name, _RDATA) == 0)
+           break;
+         if ((current->flags & SEC_CODE) == 0
+             && strcmp (current->name, _PDATA) != 0
+             && strcmp (current->name, _RCONST) != 0)
+           {
+             rdata_in_text = false;
+             break;
+           }
+       }
+    }
+  ecoff_data (abfd)->rdata_in_text = rdata_in_text;
+
   first_data = true;
   first_nonalloc = true;
   for (i = 0; i < abfd->section_count; i++)
@@ -2081,21 +2099,14 @@ ecoff_compute_section_file_positions (abfd)
 
       current = sorted_hdrs[i];
 
-      /* Only deal with sections which have contents */
-      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) == 0)
-       continue;
-
       /* For the Alpha ECOFF .pdata section the lnnoptr field is
         supposed to indicate the number of .pdata entries that are
         really in the section.  Each entry is 8 bytes.  We store this
         away in line_filepos before increasing the section size.  */
-      if (strcmp (current->name, _PDATA) != 0)
-       alignment_power = current->alignment_power;
-      else
-       {
-         current->line_filepos = current->_raw_size / 8;
-         alignment_power = 4;
-       }
+      if (strcmp (current->name, _PDATA) == 0)
+       current->line_filepos = current->_raw_size / 8;
+
+      alignment_power = current->alignment_power;
 
       /* On Ultrix, the data sections in an executable file must be
         aligned to a page boundary within the file.  This does not
@@ -2107,12 +2118,13 @@ ecoff_compute_section_file_positions (abfd)
          && (abfd->flags & D_PAGED) != 0
          && ! first_data
          && (current->flags & SEC_CODE) == 0
-         && (! ecoff_backend (abfd)->rdata_in_text
+         && (! rdata_in_text
              || strcmp (current->name, _RDATA) != 0)
          && strcmp (current->name, _PDATA) != 0
          && strcmp (current->name, _RCONST) != 0)
        {
          sofar = (sofar + round - 1) &~ (round - 1);
+         file_sofar = (file_sofar + round - 1) &~ (round - 1);
          first_data = false;
        }
       else if (strcmp (current->name, _LIB) == 0)
@@ -2122,6 +2134,7 @@ ecoff_compute_section_file_positions (abfd)
             page boundary.  */
 
          sofar = (sofar + round - 1) &~ (round - 1);
+         file_sofar = (file_sofar + round - 1) &~ (round - 1);
        }
       else if (first_nonalloc
               && (current->flags & SEC_ALLOC) == 0
@@ -2132,31 +2145,42 @@ ecoff_compute_section_file_positions (abfd)
              for the .bss section.  */
          first_nonalloc = false;
          sofar = (sofar + round - 1) &~ (round - 1);
+         file_sofar = (file_sofar + round - 1) &~ (round - 1);
        }
 
       /* Align the sections in the file to the same boundary on
         which they are aligned in virtual memory.  */
-      old_sofar = sofar;
       sofar = BFD_ALIGN (sofar, 1 << alignment_power);
+      if ((current->flags & SEC_HAS_CONTENTS) != 0)
+       file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power);
 
       if ((abfd->flags & D_PAGED) != 0
          && (current->flags & SEC_ALLOC) != 0)
-       sofar += (current->vma - sofar) % round;
+       {
+         sofar += (current->vma - sofar) % round;
+         if ((current->flags & SEC_HAS_CONTENTS) != 0)
+           file_sofar += (current->vma - file_sofar) % round;
+       }
 
-      current->filepos = sofar;
+      if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) != 0)
+       current->filepos = file_sofar;
 
       sofar += current->_raw_size;
+      if ((current->flags & SEC_HAS_CONTENTS) != 0)
+       file_sofar += current->_raw_size;
 
       /* make sure that this section is of the right size too */
       old_sofar = sofar;
       sofar = BFD_ALIGN (sofar, 1 << alignment_power);
+      if ((current->flags & SEC_HAS_CONTENTS) != 0)
+       file_sofar = BFD_ALIGN (file_sofar, 1 << alignment_power);
       current->_raw_size += sofar - old_sofar;
     }
 
   free (sorted_hdrs);
   sorted_hdrs = NULL;
 
-  ecoff_data (abfd)->reloc_filepos = sofar;
+  ecoff_data (abfd)->reloc_filepos = file_sofar;
 
   return true;
 }
@@ -2236,11 +2260,22 @@ _bfd_ecoff_set_section_contents (abfd, section, location, offset, count)
        return false;
     }
 
-  /* If this is a .lib section, bump the vma address so that it winds
-     up being the number of .lib sections output.  This is right for
-     Irix 4.  Ian Taylor <ian@cygnus.com>.  */
+  /* Handle the .lib section specially so that Irix 4 shared libraries
+     work out.  See coff_set_section_contents in coffcode.h.  */
   if (strcmp (section->name, _LIB) == 0)
-    ++section->vma;
+    {
+      bfd_byte *rec, *recend;
+
+      rec = (bfd_byte *) location;
+      recend = rec + count;
+      while (rec < recend)
+       {
+         ++section->lma;
+         rec += bfd_get_32 (abfd, rec) * 4;
+       }
+
+      BFD_ASSERT (rec == recend);
+    }
 
   if (count == 0)
     return true;
@@ -2499,7 +2534,7 @@ _bfd_ecoff_write_object_contents (abfd)
       else
        section.s_vaddr = vma;
 
-      section.s_paddr = vma;
+      section.s_paddr = current->lma;
       section.s_size = bfd_get_section_size_before_reloc (current);
 
       /* If this section is unloadable then the scnptr will be 0.  */
@@ -2538,7 +2573,7 @@ _bfd_ecoff_write_object_contents (abfd)
 
       if ((section.s_flags & STYP_TEXT) != 0
          || ((section.s_flags & STYP_RDATA) != 0
-             && backend->rdata_in_text)
+             && ecoff_data (abfd)->rdata_in_text)
          || section.s_flags == STYP_PDATA
          || (section.s_flags & STYP_DYNAMIC) != 0
          || (section.s_flags & STYP_LIBLIST) != 0
@@ -2619,7 +2654,7 @@ _bfd_ecoff_write_object_contents (abfd)
   if (abfd->flags & EXEC_P)
     internal_f.f_flags |= F_EXEC;
 
-  if (! abfd->xvec->byteorder_big_p)
+  if (bfd_little_endian (abfd))
     internal_f.f_flags |= F_AR32WR;
   else
     internal_f.f_flags |= F_AR32W;
@@ -2909,6 +2944,8 @@ ecoff_armap_hash (s, rehash, size, hlog)
 {
   unsigned int hash;
 
+  if (hlog == 0)
+    return 0;
   hash = *s++;
   while (*s != '\0')
     hash = ((hash >> 27) | (hash << 5)) + *s++;
@@ -2970,9 +3007,9 @@ _bfd_ecoff_slurp_armap (abfd)
 
   /* Make sure we have the right byte ordering.  */
   if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
-       ^ (abfd->xvec->header_byteorder_big_p != false))
+       ^ (bfd_header_big_endian (abfd)))
       || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
-         ^ (abfd->xvec->byteorder_big_p != false)))
+         ^ (bfd_big_endian (abfd))))
     {
       bfd_set_error (bfd_error_wrong_format);
       return false;
@@ -3110,7 +3147,7 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
 
   /* Ultrix appears to use as a hash table size the least power of two
      greater than twice the number of entries.  */
-  for (hashlog = 0; (1 << hashlog) <= 2 * orl_count; hashlog++)
+  for (hashlog = 0; ((unsigned int) 1 << hashlog) <= 2 * orl_count; hashlog++)
     ;
   hashsize = 1 << hashlog;
 
@@ -3129,12 +3166,12 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
   strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start);
   hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER;
   hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] =
-    (abfd->xvec->header_byteorder_big_p
+    (bfd_header_big_endian (abfd)
      ? ARMAP_BIG_ENDIAN
      : ARMAP_LITTLE_ENDIAN);
   hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER;
   hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] =
-    abfd->xvec->byteorder_big_p ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN;
+    bfd_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN;
   memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1);
 
   /* Write the timestamp of the archive header to be just a little bit
@@ -3149,7 +3186,14 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
      armap.  */
   hdr.ar_uid[0] = '0';
   hdr.ar_gid[0] = '0';
+#if 0
   hdr.ar_mode[0] = '0';
+#else
+  /* Building gcc ends up extracting the armap as a file - twice. */
+  hdr.ar_mode[0] = '6';
+  hdr.ar_mode[1] = '4';
+  hdr.ar_mode[2] = '4';
+#endif
 
   sprintf (hdr.ar_size, "%-10d", (int) mapsize);
 
@@ -3253,16 +3297,24 @@ const bfd_target *
 _bfd_ecoff_archive_p (abfd)
      bfd *abfd;
 {
+  struct artdata *tdata_hold;
   char armag[SARMAG + 1];
 
-  if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
-      || strncmp (armag, ARMAG, SARMAG) != 0)
+  tdata_hold = abfd->tdata.aout_ar_data;
+
+  if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG)
     {
       if (bfd_get_error () != bfd_error_system_call)
        bfd_set_error (bfd_error_wrong_format);
       return (const bfd_target *) NULL;
     }
 
+  if (strncmp (armag, ARMAG, SARMAG) != 0)
+    {
+      bfd_set_error (bfd_error_wrong_format);
+      return NULL;
+    }
+
   /* We are setting bfd_ardata(abfd) here, but since bfd_ardata
      involves a cast, we can't do it as the left operand of
      assignment.  */
@@ -3270,7 +3322,10 @@ _bfd_ecoff_archive_p (abfd)
     (struct artdata *) bfd_zalloc (abfd, sizeof (struct artdata));
 
   if (bfd_ardata (abfd) == (struct artdata *) NULL)
-    return (const bfd_target *) NULL;
+    {
+      abfd->tdata.aout_ar_data = tdata_hold;
+      return (const bfd_target *) NULL;
+    }
 
   bfd_ardata (abfd)->first_file_filepos = SARMAG;
   bfd_ardata (abfd)->cache = NULL;
@@ -3283,10 +3338,43 @@ _bfd_ecoff_archive_p (abfd)
       || _bfd_ecoff_slurp_extended_name_table (abfd) == false)
     {
       bfd_release (abfd, bfd_ardata (abfd));
-      abfd->tdata.aout_ar_data = (struct artdata *) NULL;
+      abfd->tdata.aout_ar_data = tdata_hold;
       return (const bfd_target *) NULL;
     }
   
+  if (bfd_has_map (abfd))
+    {
+      bfd *first;
+
+      /* This archive has a map, so we may presume that the contents
+        are object files.  Make sure that if the first file in the
+        archive can be recognized as an object file, it is for this
+        target.  If not, assume that this is the wrong format.  If
+        the first file is not an object file, somebody is doing
+        something weird, and we permit it so that ar -t will work.  */
+
+      first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+      if (first != NULL)
+       {
+         boolean fail;
+
+         first->target_defaulted = false;
+         fail = false;
+         if (bfd_check_format (first, bfd_object)
+             && first->xvec != abfd->xvec)
+           {
+             (void) bfd_close (first);
+             bfd_release (abfd, bfd_ardata (abfd));
+             abfd->tdata.aout_ar_data = tdata_hold;
+             bfd_set_error (bfd_error_wrong_format);
+             return NULL;
+           }
+
+         /* We ought to close first here, but we can't, because we
+             have no way to remove it from the archive cache.  FIXME.  */
+       }
+    }
+
   return abfd->xvec;
 }
 \f
@@ -3413,6 +3501,7 @@ ecoff_link_add_archive_symbols (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
+  const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
   const bfd_byte *raw_armap;
   struct bfd_link_hash_entry **pundef;
   unsigned int armap_count;
@@ -3534,7 +3623,7 @@ ecoff_link_add_archive_symbols (abfd, info)
          hash = srch;
        }
 
-      element = _bfd_get_elt_at_filepos (abfd, file_offset);
+      element = (*backend->get_elt_at_filepos) (abfd, file_offset);
       if (element == (bfd *) NULL)
        return false;
 
@@ -3965,6 +4054,14 @@ static boolean ecoff_reloc_link_order
   PARAMS ((bfd *, struct bfd_link_info *, asection *,
           struct bfd_link_order *));
 
+/* Structure used to pass information to ecoff_link_write_external.  */
+
+struct extsym_info
+{
+  bfd *abfd;
+  struct bfd_link_info *info;
+};
+
 /* ECOFF final link routine.  This looks through all the input BFDs
    and gathers together all the debugging information, and then
    processes all the link order information.  This may cause it to
@@ -3982,6 +4079,7 @@ _bfd_ecoff_bfd_final_link (abfd, info)
   register bfd *input_bfd;
   asection *o;
   struct bfd_link_order *p;
+  struct extsym_info einfo;
 
   /* We accumulate the debugging information counts in the symbolic
      header.  */
@@ -4052,9 +4150,11 @@ _bfd_ecoff_bfd_final_link (abfd, info)
     }
 
   /* Write out the external symbols.  */
+  einfo.abfd = abfd;
+  einfo.info = info;
   ecoff_link_hash_traverse (ecoff_hash_table (info),
                            ecoff_link_write_external,
-                           (PTR) abfd);
+                           (PTR) &einfo);
 
   if (info->relocateable)
     {
@@ -4275,11 +4375,24 @@ ecoff_link_write_external (h, data)
      struct ecoff_link_hash_entry *h;
      PTR data;
 {
-  bfd *output_bfd = (bfd *) data;
-
-  /* FIXME: We should check if this symbol is being stripped.  */
+  struct extsym_info *einfo = (struct extsym_info *) data;
+  bfd *output_bfd = einfo->abfd;
+  boolean strip;
+
+  /* We need to check if this symbol is being stripped. */
+  if (h->root.type == bfd_link_hash_undefined
+      || h->root.type == bfd_link_hash_undefweak)
+    strip = false;
+  else if (einfo->info->strip == strip_all
+          || (einfo->info->strip == strip_some
+              && bfd_hash_lookup (einfo->info->keep_hash,
+                                  h->root.root.string,
+                                  false, false) == NULL))
+    strip = true;
+  else
+    strip = false;
 
-  if (h->written)
+  if (strip || h->written)
     return true;
 
   if (h->abfd == (bfd *) NULL)
@@ -4562,8 +4675,9 @@ ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
 
       /* Treat a reloc against a defined symbol as though it were
          actually against the section.  */
-      h = bfd_link_hash_lookup (info->hash, link_order->u.reloc.p->u.name,
-                               false, false, false);
+      h = bfd_wrapped_link_hash_lookup (output_bfd, info,
+                                       link_order->u.reloc.p->u.name,
+                                       false, false, false);
       if (h != NULL
          && (h->type == bfd_link_hash_defined
              || h->type == bfd_link_hash_defweak))
@@ -4639,9 +4753,10 @@ ecoff_reloc_link_order (output_bfd, info, output_section, link_order)
     {
       struct ecoff_link_hash_entry *h;
 
-      h = ecoff_link_hash_lookup (ecoff_hash_table (info),
-                                 link_order->u.reloc.p->u.name,
-                                 false, false, true);
+      h = ((struct ecoff_link_hash_entry *)
+          bfd_wrapped_link_hash_lookup (output_bfd, info,
+                                        link_order->u.reloc.p->u.name,
+                                        false, false, true));
       if (h != (struct ecoff_link_hash_entry *) NULL
          && h->indx != -1)
        in.r_symndx = h->indx;
This page took 0.037418 seconds and 4 git commands to generate.