Replace "link" with "sh_link"
[deliverable/binutils-gdb.git] / bfd / elf.c
index a1f857a900b44c9bf18617db43a9738f9e100dcd..69830ce0b3a2e567dcb052ba19a011d91af67c93 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -42,7 +42,7 @@ SECTION
 #include "elf-bfd.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
-#include "elf-linux-psinfo.h"
+#include "elf-linux-core.h"
 
 #ifdef CORE_HEADER
 #include CORE_HEADER
@@ -970,9 +970,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 +1175,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 +1213,62 @@ 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 (Elf_Internal_Shdr * a, Elf_Internal_Shdr * b)
+{
+  return
+    a->sh_type         == b->sh_type
+    && a->sh_flags     == b->sh_flags
+    && 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 (bfd * obfd, Elf_Internal_Shdr * iheader, 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;
+}
+
 /* 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)
 {
+  Elf_Internal_Shdr ** iheaders = elf_elfsections (ibfd);
+  Elf_Internal_Shdr ** oheaders = elf_elfsections (obfd);
+  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))
@@ -1237,59 +1286,128 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
   /* 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;
 
-  if (iheaders != NULL && oheaders != NULL)
+  /* Possibly copy the sh_info and sh_link fields.  */
+  for (i = 1; i < elf_numsections (obfd); i++)
     {
-      unsigned int i;
-
-      for (i = 0; i < elf_numsections (obfd); i++)
-       {
-         unsigned int j;
-         Elf_Internal_Shdr * oheader = oheaders[i];
+      unsigned int j;
+      Elf_Internal_Shdr * oheader = oheaders[i];
 
-         if (oheader == NULL
-             || oheader->sh_type != SHT_NOBITS
-             || oheader->sh_size == 0
-             || (oheader->sh_info != 0 && oheader->sh_link != 0))
-           continue;
+      if (oheader == NULL
+         || (oheader->sh_type != SHT_NOBITS
+             && oheader->sh_type < SHT_LOOS)
+         || oheader->sh_size == 0
+         || (oheader->sh_info != 0 && oheader->sh_link != 0))
+       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++)
+      /* 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 = 1; j < elf_numsections (ibfd); j++)
+       {
+         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))
            {
-             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))
+             /* PR 19938: Attempt to preserve the sh_link and sh_info fields
+                of OS and Processor specific sections.  We try harder for
+                these sections, because this is not just about matching
+                stripped binaries to their originals.  */
+             if (oheader->sh_type >= SHT_LOOS)
                {
-                 /* Note: Strictly speaking these assignments are wrong.
+                 const struct elf_backend_data *bed = get_elf_backend_data (obfd);
+                 bfd_boolean changed = FALSE;
+                 unsigned int sh_link;
+
+                 /* Allow the target a chance to decide how these fields should
+                    be set.  */
+                 if (bed->elf_backend_set_special_section_info_and_link != NULL
+                     && bed->elf_backend_set_special_section_info_and_link
+                     (ibfd, obfd, iheader, oheader))
+                   break;
+
+                 /* We have iheader which matches oheader, but 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, i);
+                   }
+
+                 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);
+                     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, i);
+                   }
+
+                 if (changed)
+                   break;
+               }
+             else
+               {
+                 /* 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.
+
+                    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.  */
+                    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)
@@ -3099,9 +3217,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)
@@ -3355,6 +3473,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   /* SHT_GROUP sections are in relocatable files only.  */
   if (link_info == NULL || bfd_link_relocatable (link_info))
     {
+      bfd_size_type reloc_count = 0;
+
       /* Put SHT_GROUP sections first.  */
       for (sec = abfd->sections; sec != NULL; sec = sec->next)
        {
@@ -3371,7 +3491,14 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
              else
                d->this_idx = section_number++;
            }
+
+         /* Count relocations.  */
+         reloc_count += sec->reloc_count;
        }
+
+      /* Clear HAS_RELOC if there are no relocations.  */
+      if (reloc_count == 0)
+       abfd->flags &= ~HAS_RELOC;
     }
 
   for (sec = abfd->sections; sec; sec = sec->next)
@@ -3910,7 +4037,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;
@@ -7461,12 +7588,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
        }
       else if (bfd_is_com_section (syms[idx]->section))
        {
-#ifdef USE_STT_COMMON
-         if (type == STT_OBJECT)
-           sym.st_info = ELF_ST_INFO (STB_GLOBAL, STT_COMMON);
-         else
-#endif
-           sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
+         if (type != STT_TLS)
+           {
+             if ((abfd->flags & BFD_CONVERT_ELF_COMMON))
+               type = ((abfd->flags & BFD_USE_ELF_STT_COMMON)
+                       ? STT_COMMON : STT_OBJECT);
+             else
+               type = ((flags & BSF_ELF_COMMON) != 0
+                       ? STT_COMMON : STT_OBJECT);
+           }
+         sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
        }
       else if (bfd_is_und_section (syms[idx]->section))
        sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
@@ -7538,8 +7669,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;
@@ -9287,6 +9417,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
     case NT_SIGINFO:
       return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
                                              note);
+
+    case NT_FREEBSD_THRMISC:
+      if (note->namesz == 8
+         && strcmp (note->namedata, "FreeBSD") == 0)
+       return elfcore_make_note_pseudosection (abfd, ".thrmisc", note);
+      else
+       return TRUE;
     }
 }
 
@@ -9784,9 +9921,7 @@ elfcore_write_linux_prpsinfo32
 {
   struct elf_external_linux_prpsinfo32 data;
 
-  memset (&data, 0, sizeof (data));
-  LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
-
+  swap_linux_prpsinfo32_out (abfd, prpsinfo, &data);
   return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
                             &data, sizeof (data));
 }
@@ -9798,9 +9933,7 @@ elfcore_write_linux_prpsinfo64
 {
   struct elf_external_linux_prpsinfo64 data;
 
-  memset (&data, 0, sizeof (data));
-  LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data);
-
+  swap_linux_prpsinfo64_out (abfd, prpsinfo, &data);
   return elfcore_write_note (abfd, buf, bufsiz,
                             "CORE", NT_PRPSINFO, &data, sizeof (data));
 }
@@ -10448,6 +10581,12 @@ _bfd_elf_rel_local_sym (bfd *abfd,
                                     sym->st_value + addend);
 }
 
+/* Adjust an address within a section.  Given OFFSET within SEC, return
+   the new offset within the section, based upon changes made to the
+   section.  Returns -1 if the offset is now invalid.
+   The offset (in abnd out) is in target sized bytes, however big a
+   byte may be.  */
+
 bfd_vma
 _bfd_elf_section_offset (bfd *abfd,
                         struct bfd_link_info *info,
@@ -10461,12 +10600,17 @@ _bfd_elf_section_offset (bfd *abfd,
                                       offset);
     case SEC_INFO_TYPE_EH_FRAME:
       return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset);
+
     default:
       if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0)
        {
+         /* Reverse the offset.  */
          const struct elf_backend_data *bed = get_elf_backend_data (abfd);
          bfd_size_type address_size = bed->s->arch_size / 8;
-         offset = sec->size - offset - address_size;
+
+         /* address_size and sec->size are in octets.  Convert
+            to bytes before subtracting the original offset.  */
+         offset = (sec->size - address_size) / bfd_octets_per_byte (abfd) - offset;
        }
       return offset;
     }
This page took 0.030621 seconds and 4 git commands to generate.