Don't abort for invalid input, print an error message instead.
[deliverable/binutils-gdb.git] / bfd / ecoff.c
index f4549d65769ca99997d164e435a496c7f4c988ff..f22112bd75bdd83c0942f0df8e98e2152524bbe1 100644 (file)
@@ -1,5 +1,6 @@
 /* Generic ECOFF (Extended-COFF) routines.
-   Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+   Free Software Foundation, Inc.
    Original version by Per Bothner.
    Full support added by Ian Lance Taylor, ian@cygnus.com.
 
@@ -71,7 +72,23 @@ 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 =
+{
+  /* name,   index, next, flags, set_vma, reloc_done, linker_mark, gc_mark */
+  "*DEBUG*", 0,     0,    0,     0,       0,          0,           0,
+  /* vma, lma, _cooked_size, _raw_size, output_offset, output_section, */
+  0,      0,   0,            0,         0,             NULL,
+  /* alig, reloc..., orel..., reloc_count, filepos, rel_..., line_... */
+  0,       0,        0,       0,           0,       0,            0,
+  /* userdata, contents, lineno, lineno_count */
+  0,           0,        0,      0,
+  /* comdat_info, moving_line_filepos, target_index, used_by_bfd,  */
+  NULL,           0,                   0,            0,
+  /* cons, owner, symbol */
+  0,       0,     (struct symbol_cache_entry *) NULL,
+  /* symbol_ptr_ptr,                   link_order_head, ..._tail */
+  (struct symbol_cache_entry **) NULL, NULL,            NULL
+};
 
 /* Create an ECOFF object.  */
 
@@ -137,23 +154,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 +169,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)
@@ -335,9 +344,9 @@ ecoff_sec_to_styp_flags (name, flags)
     }
   else if (strcmp (name, _RCONST) == 0)
     styp = STYP_RCONST;
-  else if (flags & SEC_CODE) 
+  else if (flags & SEC_CODE)
     styp = STYP_TEXT;
-  else if (flags & SEC_DATA) 
+  else if (flags & SEC_DATA)
     styp = STYP_DATA;
   else if (flags & SEC_READONLY)
     styp = STYP_RDATA;
@@ -354,12 +363,12 @@ ecoff_sec_to_styp_flags (name, flags)
 
 /* Get the BFD flags to use for a section.  */
 
-/*ARGSUSED*/
 flagword
-_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
-     bfd *abfd;
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name, section)
+     bfd *abfd ATTRIBUTE_UNUSED;
      PTR hdr;
-     const char *name;
+     const char *name ATTRIBUTE_UNUSED;
+     asection *section ATTRIBUTE_UNUSED;
 {
   struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
   long styp_flags = internal_s->s_flags;
@@ -442,7 +451,7 @@ ecoff_slurp_symbolic_header (abfd)
   HDRR *internal_symhdr;
 
   /* See if we've already read it in.  */
-  if (ecoff_data (abfd)->debug_info.symbolic_header.magic == 
+  if (ecoff_data (abfd)->debug_info.symbolic_header.magic ==
       backend->debug_swap.sym_magic)
     return true;
 
@@ -499,11 +508,10 @@ ecoff_slurp_symbolic_header (abfd)
    object file.  This is called by gdb via the read_debug_info entry
    point in the backend structure.  */
 
-/*ARGSUSED*/
 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 +850,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 +913,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;
          }
@@ -1074,7 +1088,7 @@ ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
   unsigned int ifd = rndx->rfd;
   unsigned int indx = rndx->index;
   const char *name;
-  
+
   if (ifd == 0xfff)
     ifd = isym;
 
@@ -1306,7 +1320,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;
     }
 
@@ -1324,7 +1338,6 @@ ecoff_type_to_string (abfd, fdr, indx)
       p1 += strlen (buffer1);
     }
 
-
   /*
    * Deal with any qualifiers.
    */
@@ -1390,7 +1403,7 @@ ecoff_type_to_string (abfd, fdr, indx)
                int j;
 
                /* Print array bounds reversed (ie, in the order the C
-                  programmer writes them).  C is such a fun language.... */
+                  programmer writes them).  C is such a fun language....  */
 
                while (i < 5 && qualifiers[i+1].type == tqArray)
                  i++;
@@ -1431,10 +1444,9 @@ ecoff_type_to_string (abfd, fdr, indx)
 
 /* Return information about ECOFF symbol SYMBOL in RET.  */
 
-/*ARGSUSED*/
 void
 _bfd_ecoff_get_symbol_info (abfd, symbol, ret)
-     bfd *abfd;                        /* Ignored.  */
+     bfd *abfd ATTRIBUTE_UNUSED;
      asymbol *symbol;
      symbol_info *ret;
 {
@@ -1443,13 +1455,12 @@ _bfd_ecoff_get_symbol_info (abfd, symbol, ret)
 
 /* Return whether this is a local label.  */
 
-/*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.  */
@@ -1474,7 +1485,7 @@ _bfd_ecoff_print_symbol (abfd, filep, symbol, how)
       if (ecoffsymbol (symbol)->local)
        {
          SYMR ecoff_sym;
-       
+
          (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
                                      &ecoff_sym);
          fprintf (file, "ecoff local ");
@@ -1578,17 +1589,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 +1611,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 +1626,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;
              }
@@ -1664,7 +1675,7 @@ ecoff_slurp_reloc_table (abfd, section, symbols)
 
   if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
     return false;
-  
+
   internal_relocs = (arelent *) bfd_alloc (abfd,
                                           (sizeof (arelent)
                                            * section->reloc_count));
@@ -1762,7 +1773,7 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
 {
   unsigned int count;
 
-  if (section->flags & SEC_CONSTRUCTOR) 
+  if (section->flags & SEC_CONSTRUCTOR)
     {
       arelent_chain *chain;
 
@@ -1775,7 +1786,7 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
        *relptr++ = &chain->relent;
     }
   else
-    { 
+    {
       arelent *tblptr;
 
       if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
@@ -1796,13 +1807,12 @@ _bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
    and return the name of the source file and the line nearest to the
    wanted location.  */
 
-/*ARGSUSED*/
 boolean
 _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;
@@ -1858,10 +1868,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.  */
@@ -1968,11 +1978,10 @@ _bfd_ecoff_set_arch_mach (abfd, arch, machine)
 
 /* Get the size of the section headers.  */
 
-/*ARGSUSED*/
 int
 _bfd_ecoff_sizeof_headers (abfd, reloc)
      bfd *abfd;
-     boolean reloc;
+     boolean reloc ATTRIBUTE_UNUSED;
 {
   asection *current;
   int c;
@@ -1980,8 +1989,8 @@ _bfd_ecoff_sizeof_headers (abfd, reloc)
 
   c = 0;
   for (current = abfd->sections;
-       current != (asection *)NULL; 
-       current = current->next) 
+       current != (asection *)NULL;
+       current = current->next)
     ++c;
 
   ret = (bfd_coff_filhsz (abfd)
@@ -2045,6 +2054,7 @@ ecoff_compute_section_file_positions (abfd)
   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;
 
@@ -2065,6 +2075,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++)
@@ -2077,13 +2108,10 @@ ecoff_compute_section_file_positions (abfd)
         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
@@ -2095,7 +2123,7 @@ 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)
@@ -2183,13 +2211,13 @@ ecoff_compute_reloc_file_positions (abfd)
        abort ();
       abfd->output_has_begun = true;
     }
-  
+
   reloc_base = ecoff_data (abfd)->reloc_filepos;
 
   reloc_size = 0;
   for (current = abfd->sections;
-       current != (asection *)NULL; 
-       current = current->next) 
+       current != (asection *)NULL;
+       current = current->next)
     {
       if (current->reloc_count == 0)
        current->rel_filepos = 0;
@@ -2277,7 +2305,7 @@ bfd_ecoff_get_gp_value (abfd)
       bfd_set_error (bfd_error_invalid_operation);
       return 0;
     }
-  
+
   return ecoff_data (abfd)->gp;
 }
 
@@ -2456,8 +2484,8 @@ _bfd_ecoff_write_object_contents (abfd)
 
   count = 1;
   for (current = abfd->sections;
-       current != (asection *)NULL; 
-       current = current->next) 
+       current != (asection *)NULL;
+       current = current->next)
     {
       current->target_index = count;
       ++count;
@@ -2550,7 +2578,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
@@ -2595,7 +2623,7 @@ _bfd_ecoff_write_object_contents (abfd)
        /* Do nothing */ ;
       else
        abort ();
-    }  
+    }
 
   /* Set up the file header.  */
 
@@ -2747,7 +2775,7 @@ _bfd_ecoff_write_object_contents (abfd)
              arelent *reloc;
              asymbol *sym;
              struct internal_reloc in;
-         
+
              memset ((PTR) &in, 0, sizeof in);
 
              reloc = *reloc_ptr_ptr;
@@ -2921,6 +2949,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++;
@@ -2945,7 +2975,7 @@ _bfd_ecoff_slurp_armap (abfd)
   char *raw_ptr;
   struct symdef *symdef_ptr;
   char *stringbase;
-  
+
   /* Get the name of the first element.  */
   i = bfd_read ((PTR) nextname, 1, 16, abfd);
   if (i == 0)
@@ -2997,11 +3027,11 @@ _bfd_ecoff_slurp_armap (abfd)
     return false;
   parsed_size = mapdata->parsed_size;
   bfd_release (abfd, (PTR) mapdata);
-    
+
   raw_armap = (char *) bfd_alloc (abfd, parsed_size);
   if (raw_armap == (char *) NULL)
     return false;
-    
+
   if (bfd_read ((PTR) raw_armap, 1, parsed_size, abfd) != parsed_size)
     {
       if (bfd_get_error () != bfd_error_system_call)
@@ -3009,7 +3039,7 @@ _bfd_ecoff_slurp_armap (abfd)
       bfd_release (abfd, (PTR) raw_armap);
       return false;
     }
-    
+
   ardata->tdata = (PTR) raw_armap;
 
   count = bfd_h_get_32 (abfd, (PTR) raw_armap);
@@ -3038,7 +3068,7 @@ _bfd_ecoff_slurp_armap (abfd)
       {
        unsigned int name_offset, file_offset;
        unsigned int hash, rehash, srch;
-      
+
        name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
        file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
        if (file_offset == 0)
@@ -3122,7 +3152,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;
 
@@ -3130,7 +3160,7 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
   padit = stridx % 2;
   stringsize = stridx + padit;
 
-  /* Include 8 bytes to store symdefsize and stringsize in output. */
+  /* Include 8 bytes to store symdefsize and stringsize in output.  */
   mapsize = symdefsize + stringsize + 8;
 
   firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
@@ -3161,7 +3191,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);
 
@@ -3170,8 +3207,8 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
 
   /* Turn all null bytes in the header into spaces.  */
   for (i = 0; i < sizeof (struct ar_hdr); i++)
-   if (((char *)(&hdr))[i] == '\0')
-     (((char *)(&hdr))[i]) = ' ';
+   if (((char *) (&hdr))[i] == '\0')
+     (((char *) (&hdr))[i]) = ' ';
 
   if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
       != sizeof (struct ar_hdr))
@@ -3180,7 +3217,7 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
   bfd_h_put_32 (abfd, (bfd_vma) hashsize, temp);
   if (bfd_write ((PTR) temp, 1, 4, abfd) != 4)
     return false;
-  
+
   hashtable = (bfd_byte *) bfd_zalloc (abfd, symdefsize);
   if (!hashtable)
     return false;
@@ -3222,7 +3259,7 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
 
          hash = srch;
        }
-       
+
       bfd_h_put_32 (abfd, (bfd_vma) map[i].namidx,
                    (PTR) (hashtable + hash * 8));
       bfd_h_put_32 (abfd, (bfd_vma) firstreal,
@@ -3265,16 +3302,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.  */
@@ -3282,7 +3327,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;
@@ -3290,15 +3338,48 @@ _bfd_ecoff_archive_p (abfd)
   bfd_ardata (abfd)->symdefs = NULL;
   bfd_ardata (abfd)->extended_names = NULL;
   bfd_ardata (abfd)->tdata = NULL;
-  
+
   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;
+      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
@@ -4303,7 +4384,7 @@ ecoff_link_write_external (h, data)
   bfd *output_bfd = einfo->abfd;
   boolean strip;
 
-  /* We need to check if this symbol is being stripped. */
+  /* 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;
@@ -4339,7 +4420,7 @@ ecoff_link_write_external (h, data)
 
          output_section = h->root.u.def.section->output_section;
          name = bfd_section_name (output_section->owner, output_section);
-       
+
          if (strcmp (name, _TEXT) == 0)
            h->esym.asym.sc = scText;
          else if (strcmp (name, _DATA) == 0)
This page took 0.035046 seconds and 4 git commands to generate.