Fixed xgettext invocation in .Sanitize files
[binutils-gdb.git] / bfd / ecoff.c
index f4549d65769ca99997d164e435a496c7f4c988ff..dcedb7b9f71d8f79715a6797b882aabafdad209d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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, 1997 Free Software Foundation, Inc.
    Original version by Per Bothner.
    Full support added by Ian Lance Taylor, ian@cygnus.com.
 
@@ -140,20 +140,11 @@ _bfd_ecoff_new_section_hook (abfd, section)
      bfd *abfd;
      asection *section;
 {
-  /* For the .pdata section, which has a special meaning on the Alpha,
-     we set the alignment 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 +152,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)
@@ -217,6 +209,7 @@ _bfd_ecoff_set_arch_mach_hook (abfd, filehdr)
       break;
 
     case ALPHA_MAGIC:
+    case ALPHA_MAGIC_BSD:
       arch = bfd_arch_alpha;
       mach = 0;
       break;
@@ -237,6 +230,7 @@ static int
 ecoff_get_magic (abfd)
      bfd *abfd;
 {
+  extern const bfd_target bsd_ecoffalpha_little_vec;
   int big, little;
 
   switch (bfd_get_arch (abfd))
@@ -265,7 +259,8 @@ ecoff_get_magic (abfd)
       return bfd_big_endian (abfd) ? big : little;
 
     case bfd_arch_alpha:
-      return ALPHA_MAGIC;
+      return (abfd->xvec == &bsd_ecoffalpha_little_vec
+             ? ALPHA_MAGIC_BSD : ALPHA_MAGIC);
 
     default:
       abort ();
@@ -842,6 +837,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 +900,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;
          }
@@ -1445,11 +1446,11 @@ _bfd_ecoff_get_symbol_info (abfd, symbol, ret)
 
 /*ARGSUSED*/
 boolean
-_bfd_ecoff_bfd_is_local_label (abfd, symbol)
+_bfd_ecoff_bfd_is_local_label_name (abfd, name)
      bfd *abfd;
-     asymbol *symbol;
+     const char *name;
 {
-  return symbol->name[0] == '$';
+  return name[0] == '$';
 }
 
 /* Print information about an ECOFF symbol.  */
@@ -1858,10 +1859,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.  */
@@ -2045,6 +2046,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 +2067,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 +2100,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 +2115,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)
@@ -2550,7 +2570,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
@@ -2921,6 +2941,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++;
@@ -3265,16 +3287,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 +3312,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;
@@ -3295,10 +3328,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