Add "arm_any" architecture type to allow -m option to various binutils to match any...
[deliverable/binutils-gdb.git] / bfd / elf.c
index 90319a2702116799567a73444d5b79772005feab..fa4cc4c468e37e1a6e40e30c3d71920d90c1a9a9 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -407,11 +407,17 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
       /* Find an index section that is linked to this symtab section.  */
       for (entry = elf_symtab_shndx_list (ibfd); entry != NULL; entry = entry->next)
-       if (sections[entry->hdr.sh_link] == symtab_hdr)
-         {
-           shndx_hdr = & entry->hdr;
-           break;
-         };
+       {
+         /* PR 20063.  */
+         if (entry->hdr.sh_link >= elf_numsections (ibfd))
+           continue;
+
+         if (sections[entry->hdr.sh_link] == symtab_hdr)
+           {
+             shndx_hdr = & entry->hdr;
+             break;
+           };
+       }
 
       if (shndx_hdr == NULL)
        {
@@ -970,9 +976,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
     {
       flags |= SEC_MERGE;
       newsect->entsize = hdr->sh_entsize;
-      if ((hdr->sh_flags & SHF_STRINGS) != 0)
-       flags |= SEC_STRINGS;
     }
+  if ((hdr->sh_flags & SHF_STRINGS) != 0)
+    flags |= SEC_STRINGS;
   if (hdr->sh_flags & SHF_GROUP)
     if (!setup_group (abfd, hdr, newsect))
       return FALSE;
@@ -1175,7 +1181,8 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
   return TRUE;
 }
 
-const char *const bfd_elf_section_type_names[] = {
+const char *const bfd_elf_section_type_names[] =
+{
   "SHT_NULL", "SHT_PROGBITS", "SHT_SYMTAB", "SHT_STRTAB",
   "SHT_RELA", "SHT_HASH", "SHT_DYNAMIC", "SHT_NOTE",
   "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
@@ -1212,14 +1219,160 @@ bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   return bfd_reloc_continue;
 }
 \f
+/* Returns TRUE if section A matches section B.
+   Names, addresses and links may be different, but everything else
+   should be the same.  */
+
+static bfd_boolean
+section_match (const Elf_Internal_Shdr * a,
+              const Elf_Internal_Shdr * b)
+{
+  return
+    a->sh_type         == b->sh_type
+    && (a->sh_flags & ~ SHF_INFO_LINK)
+    == (b->sh_flags & ~ SHF_INFO_LINK)
+    && a->sh_addralign == b->sh_addralign
+    && a->sh_size      == b->sh_size
+    && a->sh_entsize   == b->sh_entsize
+    /* FIXME: Check sh_addr ?  */
+    ;
+}
+
+/* Find a section in OBFD that has the same characteristics
+   as IHEADER.  Return the index of this section or SHN_UNDEF if
+   none can be found.  Check's section HINT first, as this is likely
+   to be the correct section.  */
+
+static unsigned int
+find_link (const bfd * obfd, const Elf_Internal_Shdr * iheader, const unsigned int hint)
+{
+  Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
+  unsigned int i;
+
+  if (section_match (oheaders[hint], iheader))
+    return hint;
+
+  for (i = 1; i < elf_numsections (obfd); i++)
+    {
+      Elf_Internal_Shdr * oheader = oheaders[i];
+
+      if (section_match (oheader, iheader))
+       /* FIXME: Do we care if there is a potential for
+          multiple matches ?  */
+       return i;
+    }
+
+  return SHN_UNDEF;
+}
+
+/* PR 19938: Attempt to set the ELF section header fields of an OS or
+   Processor specific section, based upon a matching input section.
+   Returns TRUE upon success, FALSE otherwise.  */
+   
+static bfd_boolean
+copy_special_section_fields (const bfd *ibfd,
+                            bfd *obfd,
+                            const Elf_Internal_Shdr *iheader,
+                            Elf_Internal_Shdr *oheader,
+                            const unsigned int secnum)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (obfd);
+  const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd);
+  bfd_boolean changed = FALSE;
+  unsigned int sh_link;
+
+  if (oheader->sh_type == SHT_NOBITS)
+    {
+      /* This is a feature for objcopy --only-keep-debug:
+        When a section's type is changed to NOBITS, we preserve
+        the sh_link and sh_info fields so that they can be
+        matched up with the original.
+
+        Note: Strictly speaking these assignments are wrong.
+        The sh_link and sh_info fields should point to the
+        relevent sections in the output BFD, which may not be in
+        the same location as they were in the input BFD.  But
+        the whole point of this action is to preserve the
+        original values of the sh_link and sh_info fields, so
+        that they can be matched up with the section headers in
+        the original file.  So strictly speaking we may be
+        creating an invalid ELF file, but it is only for a file
+        that just contains debug info and only for sections
+        without any contents.  */
+      if (oheader->sh_link == 0)
+       oheader->sh_link = iheader->sh_link;
+      if (oheader->sh_info == 0)
+       oheader->sh_info = iheader->sh_info;
+      return TRUE;
+    }
+
+  /* Allow the target a chance to decide how these fields should be set.  */
+  if (bed->elf_backend_copy_special_section_fields != NULL
+      && bed->elf_backend_copy_special_section_fields
+      (ibfd, obfd, iheader, oheader))
+    return TRUE;
+
+  /* We have an iheader which might match oheader, and which has non-zero
+     sh_info and/or sh_link fields.  Attempt to follow those links and find
+     the section in the output bfd which corresponds to the linked section
+     in the input bfd.  */
+  if (iheader->sh_link != SHN_UNDEF)
+    {
+      sh_link = find_link (obfd, iheaders[iheader->sh_link], iheader->sh_link);
+      if (sh_link != SHN_UNDEF)
+       {
+         oheader->sh_link = sh_link;
+         changed = TRUE;
+       }
+      else
+       /* FIXME: Should we install iheader->sh_link
+          if we could not find a match ?  */
+       (* _bfd_error_handler)
+         (_("%B: Failed to find link section for section %d"), obfd, secnum);
+    }
+
+  if (iheader->sh_info)
+    {
+      /* The sh_info field can hold arbitrary information, but if the
+        SHF_LINK_INFO flag is set then it should be interpreted as a
+        section index.  */
+      if (iheader->sh_flags & SHF_INFO_LINK)
+       {
+         sh_link = find_link (obfd, iheaders[iheader->sh_info],
+                              iheader->sh_info);
+         if (sh_link != SHN_UNDEF)
+           oheader->sh_flags |= SHF_INFO_LINK;
+       }
+      else
+       /* No idea what it means - just copy it.  */
+       sh_link = iheader->sh_info;
+
+      if (sh_link != SHN_UNDEF)
+       {
+         oheader->sh_info = sh_link;
+         changed = TRUE;
+       }
+      else
+       (* _bfd_error_handler)
+         (_("%B: Failed to find info section for section %d"), obfd, secnum);
+    }
+
+  return changed;
+}
+  
 /* Copy the program header and other data from one object module to
    another.  */
 
 bfd_boolean
 _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 {
+  const Elf_Internal_Shdr **iheaders = (const Elf_Internal_Shdr **) elf_elfsections (ibfd);
+  Elf_Internal_Shdr **oheaders = elf_elfsections (obfd);
+  const struct elf_backend_data *bed;
+  unsigned int i;
+
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
-      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+    || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
   if (!elf_flags_init (obfd))
@@ -1234,70 +1387,103 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
   elf_elfheader (obfd)->e_ident[EI_OSABI] =
     elf_elfheader (ibfd)->e_ident[EI_OSABI];
 
+  /* If set, copy the EI_ABIVERSION field.  */
+  if (elf_elfheader (ibfd)->e_ident[EI_ABIVERSION])
+    elf_elfheader (obfd)->e_ident[EI_ABIVERSION]
+      = elf_elfheader (ibfd)->e_ident[EI_ABIVERSION];
+  
   /* Copy object attributes.  */
   _bfd_elf_copy_obj_attributes (ibfd, obfd);
 
-  /* This is an feature for objcopy --only-keep-debug:  When a section's type
-     is changed to NOBITS, we preserve the sh_link and sh_info fields so that
-     they can be matched up with the original.  */
-  Elf_Internal_Shdr ** iheaders = elf_elfsections (ibfd);
-  Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
+  if (iheaders == NULL || oheaders == NULL)
+    return TRUE;
+
+  bed = get_elf_backend_data (obfd);
 
-  if (iheaders != NULL && oheaders != NULL)
+  /* Possibly copy other fields in the section header.  */
+  for (i = 1; i < elf_numsections (obfd); i++)
     {
-      unsigned int i;
+      unsigned int j;
+      Elf_Internal_Shdr * oheader = oheaders[i];
+
+      /* Ignore ordinary sections.  SHT_NOBITS sections are considered however
+        because of a special case need for generating separate debug info
+        files.  See below for more details.  */
+      if (oheader == NULL
+         || (oheader->sh_type != SHT_NOBITS
+             && oheader->sh_type < SHT_LOOS))
+       continue;
 
-      for (i = 0; i < elf_numsections (obfd); i++)
+      /* Ignore empty sections, and sections whose
+        fields have already been initialised.  */
+      if (oheader->sh_size == 0
+         || (oheader->sh_info != 0 && oheader->sh_link != 0))
+       continue;
+
+      /* Scan for the matching section in the input bfd.
+        First we try for a direct mapping between the input and output sections.  */
+      for (j = 1; j < elf_numsections (ibfd); j++)
        {
-         unsigned int j;
-         Elf_Internal_Shdr * oheader = oheaders[i];
+         const Elf_Internal_Shdr * iheader = iheaders[j];
 
-         if (oheader == NULL
-             || oheader->sh_type != SHT_NOBITS
-             || oheader->sh_size == 0
-             || (oheader->sh_info != 0 && oheader->sh_link != 0))
+         if (iheader == NULL)
            continue;
 
-         /* Scan for the matching section in the input bfd.
-            FIXME: We could use something better than a linear scan here.
-            Unfortunately we cannot compare names as the output string table
-            is empty, so instead we check size, address and type.  */
-         for (j = 0; j < elf_numsections (ibfd); j++)
+         if (oheader->bfd_section != NULL
+             && iheader->bfd_section != NULL
+             && iheader->bfd_section->output_section != NULL
+             && iheader->bfd_section->output_section == oheader->bfd_section)
            {
-             Elf_Internal_Shdr * iheader = iheaders[j];
-
-             /* Since --only-keep-debug turns all non-debug sections
-                into SHT_NOBITS sections, the output SHT_NOBITS type
-                matches any input type.  */
-             if ((oheader->sh_type == SHT_NOBITS
-                  || iheader->sh_type == oheader->sh_type)
-                 && iheader->sh_flags == oheader->sh_flags
-                 && iheader->sh_addralign == oheader->sh_addralign
-                 && iheader->sh_entsize == oheader->sh_entsize
-                 && iheader->sh_size == oheader->sh_size
-                 && iheader->sh_addr == oheader->sh_addr
-                 && (iheader->sh_info != oheader->sh_info
-                     || iheader->sh_link != oheader->sh_link))
-               {
-                 /* Note: Strictly speaking these assignments are wrong.
-                    The sh_link and sh_info fields should point to the
-                    relevent sections in the output BFD, which may not be in
-                    the same location as they were in the input BFD.  But the
-                    whole point of this action is to preserve the original
-                    values of the sh_link and sh_info fields, so that they
-                    can be matched up with the section headers in the
-                    original file.  So strictly speaking we may be creating
-                    an invalid ELF file, but it is only for a file that just
-                    contains debug info and only for sections without any
-                    contents.  */
-                 if (oheader->sh_link == 0)
-                   oheader->sh_link = iheader->sh_link;
-                 if (oheader->sh_info == 0)
-                   oheader->sh_info = iheader->sh_info;
-                 break;
-               }
+             /* We have found a connection from the input section to the
+                output section.  Attempt to copy the header fields.  If
+                this fails then do not try any further sections - there
+                should only be a one-to-one mapping between input and output. */
+             if (! copy_special_section_fields (ibfd, obfd, iheader, oheader, i))
+               j = elf_numsections (ibfd);
+             break;
            }
        }
+
+      if (j < elf_numsections (ibfd))
+       continue;
+
+      /* That failed.  So try to deduce the corresponding input section.
+        Unfortunately we cannot compare names as the output string table
+        is empty, so instead we check size, address and type.  */
+      for (j = 1; j < elf_numsections (ibfd); j++)
+       {
+         const Elf_Internal_Shdr * iheader = iheaders[j];
+
+         if (iheader == NULL)
+           continue;
+
+         /* Try matching fields in the input section's header.
+            Since --only-keep-debug turns all non-debug sections into
+            SHT_NOBITS sections, the output SHT_NOBITS type matches any
+            input type.  */
+         if ((oheader->sh_type == SHT_NOBITS
+              || iheader->sh_type == oheader->sh_type)
+             && (iheader->sh_flags & ~ SHF_INFO_LINK)
+             == (oheader->sh_flags & ~ SHF_INFO_LINK)
+             && iheader->sh_addralign == oheader->sh_addralign
+             && iheader->sh_entsize == oheader->sh_entsize
+             && iheader->sh_size == oheader->sh_size
+             && iheader->sh_addr == oheader->sh_addr
+             && (iheader->sh_info != oheader->sh_info
+                 || iheader->sh_link != oheader->sh_link))
+           {
+             if (copy_special_section_fields (ibfd, obfd, iheader, oheader, i))
+               break;
+           }
+       }
+
+      if (j == elf_numsections (ibfd) && oheader->sh_type >= SHT_LOOS)
+       {
+         /* Final attempt.  Call the backend copy function
+            with a NULL input section.  */
+         if (bed->elf_backend_copy_special_section_fields != NULL)
+           bed->elf_backend_copy_special_section_fields (ibfd, obfd, NULL, oheader);
+       }
     }
 
   return TRUE;
@@ -3022,14 +3208,17 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
       break;
 
     case SHT_STRTAB:
-    case SHT_INIT_ARRAY:
-    case SHT_FINI_ARRAY:
-    case SHT_PREINIT_ARRAY:
     case SHT_NOTE:
     case SHT_NOBITS:
     case SHT_PROGBITS:
       break;
 
+    case SHT_INIT_ARRAY:
+    case SHT_FINI_ARRAY:
+    case SHT_PREINIT_ARRAY:
+      this_hdr->sh_entsize = bed->s->arch_size / 8;
+      break;
+
     case SHT_HASH:
       this_hdr->sh_entsize = bed->s->sizeof_hash_entry;
       break;
@@ -3099,9 +3288,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
     {
       this_hdr->sh_flags |= SHF_MERGE;
       this_hdr->sh_entsize = asect->entsize;
-      if ((asect->flags & SEC_STRINGS) != 0)
-       this_hdr->sh_flags |= SHF_STRINGS;
     }
+  if ((asect->flags & SEC_STRINGS) != 0)
+    this_hdr->sh_flags |= SHF_STRINGS;
   if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
     this_hdr->sh_flags |= SHF_GROUP;
   if ((asect->flags & SEC_THREAD_LOCAL) != 0)
@@ -3919,7 +4108,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
   /* sh_name was set in prep_headers.  */
   shstrtab_hdr->sh_type = SHT_STRTAB;
-  shstrtab_hdr->sh_flags = 0;
+  shstrtab_hdr->sh_flags = bed->elf_strtab_flags;
   shstrtab_hdr->sh_addr = 0;
   /* sh_size is set in _bfd_elf_assign_file_positions_for_non_load.  */
   shstrtab_hdr->sh_entsize = 0;
@@ -7551,8 +7740,7 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
   *sttp = stt;
   symstrtab_hdr->sh_size = _bfd_elf_strtab_size (stt);
   symstrtab_hdr->sh_type = SHT_STRTAB;
-
-  symstrtab_hdr->sh_flags = 0;
+  symstrtab_hdr->sh_flags = bed->elf_strtab_flags;
   symstrtab_hdr->sh_addr = 0;
   symstrtab_hdr->sh_entsize = 0;
   symstrtab_hdr->sh_link = 0;
This page took 0.029232 seconds and 4 git commands to generate.