Set BFD_DECOMPRESS to decompress debug sections
[deliverable/binutils-gdb.git] / bfd / elf.c
index f3c90506591b23cd76ba3dff714d36679655a278..74c2f2d33a46057fb1551a5f50190cf001ff1779 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright (C) 1993-2015 Free Software Foundation, Inc.
+   Copyright (C) 1993-2016 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -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
@@ -51,7 +51,7 @@ SECTION
 static int elf_sort_sections (const void *, const void *);
 static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
 static bfd_boolean prep_headers (bfd *);
-static bfd_boolean swap_out_syms (bfd *, struct bfd_strtab_hash **, int) ;
+static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
 static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
 static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
                                    file_ptr offset);
@@ -342,7 +342,7 @@ bfd_elf_string_from_elf_section (bfd *abfd,
                              abfd, shindex);
          return NULL;
        }
-  
+
       if (bfd_elf_get_str_section (abfd, shindex) == NULL)
        return NULL;
     }
@@ -400,8 +400,28 @@ bfd_elf_get_elf_syms (bfd *ibfd,
 
   /* Normal syms might have section extension entries.  */
   shndx_hdr = NULL;
-  if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
-    shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+  if (elf_symtab_shndx_list (ibfd) != NULL)
+    {
+      elf_section_list * entry;
+      Elf_Internal_Shdr **sections = elf_elfsections (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;
+         };
+
+      if (shndx_hdr == NULL)
+       {
+         if (symtab_hdr == & elf_symtab_hdr (ibfd))
+           /* Not really accurate, but this was how the old code used to work.  */
+           shndx_hdr = & elf_symtab_shndx_list (ibfd)->hdr;
+         /* Otherwise we do nothing.  The assumption is that
+            the index table will not be needed.  */
+       }
+    }
 
   /* Read the symbols.  */
   alloc_ext = NULL;
@@ -817,8 +837,21 @@ _bfd_elf_setup_sections (bfd *abfd)
   for (i = 0; i < num_group; i++)
     {
       Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
-      Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
-      unsigned int n_elt = shdr->sh_size / 4;
+      Elf_Internal_Group *idx;
+      unsigned int n_elt;
+
+      /* PR binutils/18758: Beware of corrupt binaries with invalid group data.  */
+      if (shdr == NULL || shdr->bfd_section == NULL || shdr->contents == NULL)
+       {
+         (*_bfd_error_handler)
+           (_("%B: section group entry number %u is corrupt"),
+            abfd, i);
+         result = FALSE;
+         continue;
+       }
+
+      idx = (Elf_Internal_Group *) shdr->contents;
+      n_elt = shdr->sh_size / 4;
 
       while (--n_elt != 0)
        if ((++idx)->shdr->bfd_section)
@@ -855,6 +888,31 @@ bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
   return elf_next_in_group (sec) != NULL;
 }
 
+static char *
+convert_debug_to_zdebug (bfd *abfd, const char *name)
+{
+  unsigned int len = strlen (name);
+  char *new_name = bfd_alloc (abfd, len + 2);
+  if (new_name == NULL)
+    return NULL;
+  new_name[0] = '.';
+  new_name[1] = 'z';
+  memcpy (new_name + 2, name + 1, len);
+  return new_name;
+}
+
+static char *
+convert_zdebug_to_debug (bfd *abfd, const char *name)
+{
+  unsigned int len = strlen (name);
+  char *new_name = bfd_alloc (abfd, len);
+  if (new_name == NULL)
+    return NULL;
+  new_name[0] = '.';
+  memcpy (new_name + 1, name + 2, len - 1);
+  return new_name;
+}
+
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
@@ -1041,27 +1099,38 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
          || (name[1] == 'z' && name[7] == '_')))
     {
       enum { nothing, compress, decompress } action = nothing;
-      char *new_name;
+      int compression_header_size;
+      bfd_size_type uncompressed_size;
+      bfd_boolean compressed
+       = bfd_is_section_compressed_with_header (abfd, newsect,
+                                                &compression_header_size,
+                                                &uncompressed_size);
 
-      if (bfd_is_section_compressed (abfd, newsect))
+      if (compressed)
        {
          /* Compressed section.  Check if we should decompress.  */
          if ((abfd->flags & BFD_DECOMPRESS))
            action = decompress;
        }
-      else
+
+      /* Compress the uncompressed section or convert from/to .zdebug*
+        section.  Check if we should compress.  */
+      if (action == nothing)
        {
-         /* Normal section.  Check if we should compress.  */
-         if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
+         if (newsect->size != 0
+             && (abfd->flags & BFD_COMPRESS)
+             && compression_header_size >= 0
+             && uncompressed_size > 0
+             && (!compressed
+                 || ((compression_header_size > 0)
+                     != ((abfd->flags & BFD_COMPRESS_GABI) != 0))))
            action = compress;
+         else
+           return TRUE;
        }
 
-      new_name = NULL;
-      switch (action)
+      if (action == compress)
        {
-       case nothing:
-         break;
-       case compress:
          if (!bfd_init_section_compress_status (abfd, newsect))
            {
              (*_bfd_error_handler)
@@ -1069,25 +1138,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
                 abfd, name);
              return FALSE;
            }
-         /* PR binutils/18087: Compression does not always make a section
-            smaller.  So only rename the section when compression has
-            actually taken place.  */
-         if (newsect->compress_status == COMPRESS_SECTION_DONE)
-           {
-             if (name[1] != 'z')
-               {
-                 unsigned int len = strlen (name);
-
-                 new_name = bfd_alloc (abfd, len + 2);
-                 if (new_name == NULL)
-                   return FALSE;
-                 new_name[0] = '.';
-                 new_name[1] = 'z';
-                 memcpy (new_name + 2, name + 1, len);
-               }
-           }
-         break;
-       case decompress:
+       }
+      else
+       {
          if (!bfd_init_section_decompress_status (abfd, newsect))
            {
              (*_bfd_error_handler)
@@ -1095,20 +1148,28 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
                 abfd, name);
              return FALSE;
            }
-         if (name[1] == 'z')
-           {
-             unsigned int len = strlen (name);
+       }
 
-             new_name = bfd_alloc (abfd, len);
+      if (abfd->is_linker_input)
+       {
+         if (name[1] == 'z'
+             && (action == decompress
+                 || (action == compress
+                     && (abfd->flags & BFD_COMPRESS_GABI) != 0)))
+           {
+             /* Convert section name from .zdebug_* to .debug_* so
+                that linker will consider this section as a debug
+                section.  */
+             char *new_name = convert_zdebug_to_debug (abfd, name);
              if (new_name == NULL)
                return FALSE;
-             new_name[0] = '.';
-             memcpy (new_name + 1, name + 2, len - 1);
+             bfd_rename_section (abfd, newsect, new_name);
            }
-         break;
        }
-      if (new_name != NULL)
-       bfd_rename_section (abfd, newsect, new_name);
+      else
+       /* For objdump, don't rename the section.  For objcopy, delay
+          section rename to elf_fake_sections.  */
+       newsect->flags |= SEC_ELF_RENAME;
     }
 
   return TRUE;
@@ -1175,6 +1236,70 @@ _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)
+    {
+      unsigned int i;
+
+      for (i = 0; i < elf_numsections (obfd); 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;
+
+         /* 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++)
+           {
+             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;
+               }
+           }
+       }
+    }
+
   return TRUE;
 }
 
@@ -1582,29 +1707,6 @@ bfd_elf_print_symbol (bfd *abfd,
       break;
     }
 }
-
-/* Allocate an ELF string table--force the first byte to be zero.  */
-
-struct bfd_strtab_hash *
-_bfd_elf_stringtab_init (void)
-{
-  struct bfd_strtab_hash *ret;
-
-  ret = _bfd_stringtab_init ();
-  if (ret != NULL)
-    {
-      bfd_size_type loc;
-
-      loc = _bfd_stringtab_add (ret, "", TRUE, FALSE);
-      BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
-      if (loc == (bfd_size_type) -1)
-       {
-         _bfd_stringtab_free (ret);
-         ret = NULL;
-       }
-    }
-  return ret;
-}
 \f
 /* ELF .o/exec file reading */
 
@@ -1751,10 +1853,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          goto success;
        }
 
-      BFD_ASSERT (elf_onesymtab (abfd) == 0);
+      /* PR 18854: A binary might contain more than one symbol table.
+        Unusual, but possible.  Warn, but continue.  */
+      if (elf_onesymtab (abfd) != 0)
+       {
+         (*_bfd_error_handler)
+           (_("%B: warning: multiple symbol tables detected - ignoring the table in section %u"),
+            abfd, shindex);
+         goto success;
+       }
       elf_onesymtab (abfd) = shindex;
-      elf_tdata (abfd)->symtab_hdr = *hdr;
-      elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
+      elf_symtab_hdr (abfd) = *hdr;
+      elf_elfsections (abfd)[shindex] = hdr = & elf_symtab_hdr (abfd);
       abfd->flags |= HAS_SYMS;
 
       /* Sometimes a shared object will map in the symbol table.  If
@@ -1772,30 +1882,39 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
         can't read symbols without that section loaded as well.  It
         is most likely specified by the next section header.  */
-      if (elf_elfsections (abfd)[elf_symtab_shndx (abfd)]->sh_link != shindex)
-       {
-         unsigned int i, num_sec;
+      {
+       elf_section_list * entry;
+       unsigned int i, num_sec;
 
-         num_sec = elf_numsections (abfd);
-         for (i = shindex + 1; i < num_sec; i++)
+       for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+         if (entry->hdr.sh_link == shindex)
+           goto success;
+
+       num_sec = elf_numsections (abfd);
+       for (i = shindex + 1; i < num_sec; i++)
+         {
+           Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
+           if (hdr2->sh_type == SHT_SYMTAB_SHNDX
+               && hdr2->sh_link == shindex)
+             break;
+         }
+
+       if (i == num_sec)
+         for (i = 1; i < shindex; i++)
            {
              Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+
              if (hdr2->sh_type == SHT_SYMTAB_SHNDX
                  && hdr2->sh_link == shindex)
                break;
            }
-         if (i == num_sec)
-           for (i = 1; i < shindex; i++)
-             {
-               Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
-               if (hdr2->sh_type == SHT_SYMTAB_SHNDX
-                   && hdr2->sh_link == shindex)
-                 break;
-             }
-         if (i != shindex)
-           ret = bfd_section_from_shdr (abfd, i);
-       }
-      goto success;
+
+       if (i != shindex)
+         ret = bfd_section_from_shdr (abfd, i);
+       /* else FIXME: we have failed to find the symbol table - should we issue an error ? */
+       goto success;
+      }
 
     case SHT_DYNSYM:           /* A dynamic symbol table.  */
       if (elf_dynsymtab (abfd) == shindex)
@@ -1816,7 +1935,15 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          goto success;
        }
 
-      BFD_ASSERT (elf_dynsymtab (abfd) == 0);
+      /* PR 18854: A binary might contain more than one dynamic symbol table.
+        Unusual, but possible.  Warn, but continue.  */
+      if (elf_dynsymtab (abfd) != 0)
+       {
+         (*_bfd_error_handler)
+           (_("%B: warning: multiple dynamic symbol tables detected - ignoring the table in section %u"),
+            abfd, shindex);
+         goto success;
+       }
       elf_dynsymtab (abfd) = shindex;
       elf_tdata (abfd)->dynsymtab_hdr = *hdr;
       elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr;
@@ -1828,14 +1955,23 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       goto success;
 
     case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections.  */
-      if (elf_symtab_shndx (abfd) == shindex)
-       goto success;
+      {
+       elf_section_list * entry;
 
-      BFD_ASSERT (elf_symtab_shndx (abfd) == 0);
-      elf_symtab_shndx (abfd) = shindex;
-      elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
-      elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
-      goto success;
+       for (entry = elf_symtab_shndx_list (abfd); entry != NULL; entry = entry->next)
+         if (entry->ndx == shindex)
+           goto success;
+       
+       entry = bfd_alloc (abfd, sizeof * entry);
+       if (entry == NULL)
+         goto fail;
+       entry->ndx = shindex;
+       entry->hdr = * hdr;
+       entry->next = elf_symtab_shndx_list (abfd);
+       elf_symtab_shndx_list (abfd) = entry;
+       elf_elfsections (abfd)[shindex] = & entry->hdr;
+       goto success;
+      }
 
     case SHT_STRTAB:           /* A string table.  */
       if (hdr->bfd_section != NULL)
@@ -2664,6 +2800,27 @@ _bfd_elf_single_rel_hdr (asection *sec)
     return elf_section_data (sec)->rela.hdr;
 }
 
+static bfd_boolean
+_bfd_elf_set_reloc_sh_name (bfd *abfd,
+                           Elf_Internal_Shdr *rel_hdr,
+                           const char *sec_name,
+                           bfd_boolean use_rela_p)
+{
+  char *name = (char *) bfd_alloc (abfd,
+                                  sizeof ".rela" + strlen (sec_name));
+  if (name == NULL)
+    return FALSE;
+
+  sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", sec_name);
+  rel_hdr->sh_name =
+    (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
+                                       FALSE);
+  if (rel_hdr->sh_name == (unsigned int) -1)
+    return FALSE;
+
+  return TRUE;
+}
+
 /* Allocate and initialize a section-header for a new reloc section,
    containing relocations against ASECT.  It is stored in RELDATA.  If
    USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL
@@ -2672,11 +2829,11 @@ _bfd_elf_single_rel_hdr (asection *sec)
 static bfd_boolean
 _bfd_elf_init_reloc_shdr (bfd *abfd,
                          struct bfd_elf_section_reloc_data *reldata,
-                         asection *asect,
-                         bfd_boolean use_rela_p)
+                         const char *sec_name,
+                         bfd_boolean use_rela_p,
+                         bfd_boolean delay_st_name_p)
 {
   Elf_Internal_Shdr *rel_hdr;
-  char *name;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_size_type amt;
 
@@ -2685,15 +2842,10 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
   rel_hdr = bfd_zalloc (abfd, amt);
   reldata->hdr = rel_hdr;
 
-  amt = sizeof ".rela" + strlen (asect->name);
-  name = (char *) bfd_alloc (abfd, amt);
-  if (name == NULL)
-    return FALSE;
-  sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
-  rel_hdr->sh_name =
-    (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
-                                       FALSE);
-  if (rel_hdr->sh_name == (unsigned int) -1)
+  if (delay_st_name_p)
+    rel_hdr->sh_name = (unsigned int) -1;
+  else if (!_bfd_elf_set_reloc_sh_name (abfd, rel_hdr, sec_name,
+                                       use_rela_p))
     return FALSE;
   rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
   rel_hdr->sh_entsize = (use_rela_p
@@ -2735,6 +2887,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
   struct bfd_elf_section_data *esd = elf_section_data (asect);
   Elf_Internal_Shdr *this_hdr;
   unsigned int sh_type;
+  const char *name = asect->name;
+  bfd_boolean delay_st_name_p = FALSE;
 
   if (arg->failed)
     {
@@ -2745,12 +2899,72 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
 
   this_hdr = &esd->this_hdr;
 
-  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-                                                         asect->name, FALSE);
-  if (this_hdr->sh_name == (unsigned int) -1)
+  if (arg->link_info)
     {
-      arg->failed = TRUE;
-      return;
+      /* ld: compress DWARF debug sections with names: .debug_*.  */
+      if ((arg->link_info->compress_debug & COMPRESS_DEBUG)
+         && (asect->flags & SEC_DEBUGGING)
+         && name[1] == 'd'
+         && name[6] == '_')
+       {
+         /* Set SEC_ELF_COMPRESS to indicate this section should be
+            compressed.  */
+         asect->flags |= SEC_ELF_COMPRESS;
+
+         /* If this section will be compressed, delay adding setion
+            name to section name section after it is compressed in
+            _bfd_elf_assign_file_positions_for_non_load.  */
+         delay_st_name_p = TRUE;
+       }
+    }
+  else if ((asect->flags & SEC_ELF_RENAME))
+    {
+      /* objcopy: rename output DWARF debug section.  */
+      if ((abfd->flags & (BFD_DECOMPRESS | BFD_COMPRESS_GABI)))
+       {
+         /* When we decompress or compress with SHF_COMPRESSED,
+            convert section name from .zdebug_* to .debug_* if
+            needed.  */
+         if (name[1] == 'z')
+           {
+             char *new_name = convert_zdebug_to_debug (abfd, name);
+             if (new_name == NULL)
+               {
+                 arg->failed = TRUE;
+                 return;
+               }
+             name = new_name;
+           }
+       }
+      else if (asect->compress_status == COMPRESS_SECTION_DONE)
+       {
+         /* PR binutils/18087: Compression does not always make a
+            section smaller.  So only rename the section when
+            compression has actually taken place.  If input section
+            name is .zdebug_*, we should never compress it again.  */
+         char *new_name = convert_debug_to_zdebug (abfd, name);
+         if (new_name == NULL)
+           {
+             arg->failed = TRUE;
+             return;
+           }
+         BFD_ASSERT (name[1] != 'z');
+         name = new_name;
+       }
+    }
+
+  if (delay_st_name_p)
+    this_hdr->sh_name = (unsigned int) -1;
+  else
+    {
+      this_hdr->sh_name
+       = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                             name, FALSE);
+      if (this_hdr->sh_name == (unsigned int) -1)
+       {
+         arg->failed = TRUE;
+         return;
+       }
     }
 
   /* Don't clear sh_flags. Assembler may set additional bits.  */
@@ -2921,16 +3135,19 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
       if (arg->link_info
          /* Do the normal setup if we wouldn't create any sections here.  */
          && esd->rel.count + esd->rela.count > 0
-         && (arg->link_info->relocatable || arg->link_info->emitrelocations))
+         && (bfd_link_relocatable (arg->link_info)
+             || arg->link_info->emitrelocations))
        {
          if (esd->rel.count && esd->rel.hdr == NULL
-             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, asect, FALSE))
+             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rel, name, FALSE,
+                                           delay_st_name_p))
            {
              arg->failed = TRUE;
              return;
            }
          if (esd->rela.count && esd->rela.hdr == NULL
-             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, asect, TRUE))
+             && !_bfd_elf_init_reloc_shdr (abfd, &esd->rela, name, TRUE,
+                                           delay_st_name_p))
            {
              arg->failed = TRUE;
              return;
@@ -2939,8 +3156,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
       else if (!_bfd_elf_init_reloc_shdr (abfd,
                                          (asect->use_rela_p
                                           ? &esd->rela : &esd->rel),
-                                         asect,
-                                         asect->use_rela_p))
+                                         name,
+                                         asect->use_rela_p,
+                                         delay_st_name_p))
          arg->failed = TRUE;
     }
 
@@ -3102,7 +3320,15 @@ _bfd_elf_get_reloc_section (asection *reloc_sec)
   abfd = reloc_sec->owner;
   if (get_elf_backend_data (abfd)->want_got_plt
       && strcmp (name, ".plt") == 0)
-    name = ".got.plt";
+    {
+      /* .got.plt is a linker created input section.  It may be mapped
+        to some other output section.  Try two likely sections.  */
+      name = ".got.plt";
+      reloc_sec = bfd_get_section_by_name (abfd, name);
+      if (reloc_sec != NULL)
+       return reloc_sec;
+      name = ".got";
+    }
 
   reloc_sec = bfd_get_section_by_name (abfd, name);
   return reloc_sec;
@@ -3117,7 +3343,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 {
   struct elf_obj_tdata *t = elf_tdata (abfd);
   asection *sec;
-  unsigned int section_number, secn;
+  unsigned int section_number;
   Elf_Internal_Shdr **i_shdrp;
   struct bfd_elf_section_data *d;
   bfd_boolean need_symtab;
@@ -3127,7 +3353,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   _bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
 
   /* SHT_GROUP sections are in relocatable files only.  */
-  if (link_info == NULL || link_info->relocatable)
+  if (link_info == NULL || bfd_link_relocatable (link_info))
     {
       /* Put SHT_GROUP sections first.  */
       for (sec = abfd->sections; sec != NULL; sec = sec->next)
@@ -3154,11 +3380,13 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 
       if (d->this_hdr.sh_type != SHT_GROUP)
        d->this_idx = section_number++;
-      _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
+      if (d->this_hdr.sh_name != (unsigned int) -1)
+       _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->this_hdr.sh_name);
       if (d->rel.hdr)
        {
          d->rel.idx = section_number++;
-         _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name);
+         if (d->rel.hdr->sh_name != (unsigned int) -1)
+           _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rel.hdr->sh_name);
        }
       else
        d->rel.idx = 0;
@@ -3166,7 +3394,8 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       if (d->rela.hdr)
        {
          d->rela.idx = section_number++;
-         _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name);
+         if (d->rela.hdr->sh_name != (unsigned int) -1)
+           _bfd_elf_strtab_addref (elf_shstrtab (abfd), d->rela.hdr->sh_name);
        }
       else
        d->rela.idx = 0;
@@ -3186,11 +3415,17 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
       if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
        {
-         elf_symtab_shndx (abfd) = section_number++;
-         t->symtab_shndx_hdr.sh_name
+         elf_section_list * entry;
+
+         BFD_ASSERT (elf_symtab_shndx_list (abfd) == NULL);
+
+         entry = bfd_zalloc (abfd, sizeof * entry);
+         entry->ndx = section_number++;
+         elf_symtab_shndx_list (abfd) = entry;
+         entry->hdr.sh_name
            = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
                                                  ".symtab_shndx", FALSE);
-         if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
+         if (entry->hdr.sh_name == (unsigned int) -1)
            return FALSE;
        }
       elf_strtab_sec (abfd) = section_number++;
@@ -3204,9 +3439,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       return FALSE;
     }
 
-  _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
-  t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
-
   elf_numsections (abfd) = section_number;
   elf_elfheader (abfd)->e_shnum = section_number;
 
@@ -3233,8 +3465,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
       i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr;
       if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
        {
-         i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr;
-         t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd);
+         elf_section_list * entry = elf_symtab_shndx_list (abfd);
+         BFD_ASSERT (entry != NULL);
+         i_shdrp[entry->ndx] = & entry->hdr;
+         entry->hdr.sh_link = elf_onesymtab (abfd);
        }
       i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr;
       t->symtab_hdr.sh_link = elf_strtab_sec (abfd);
@@ -3422,12 +3656,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
        }
     }
 
-  for (secn = 1; secn < section_number; ++secn)
-    if (i_shdrp[secn] == NULL)
-      i_shdrp[secn] = i_shdrp[0];
-    else
-      i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
-                                                      i_shdrp[secn]->sh_name);
+  /* Delay setting sh_name to _bfd_elf_write_object_contents so that
+     _bfd_elf_assign_file_positions_for_non_load can convert DWARF
+     debug section name from .debug_* to .zdebug_* if needed.  */
+
   return TRUE;
 }
 
@@ -3478,7 +3710,7 @@ elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
   unsigned int num_globals = 0;
   unsigned int num_locals2 = 0;
   unsigned int num_globals2 = 0;
-  int max_index = 0;
+  unsigned int max_index = 0;
   unsigned int idx;
   asection *asect;
   asymbol **new_syms;
@@ -3627,7 +3859,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct fake_section_arg fsargs;
   bfd_boolean failed;
-  struct bfd_strtab_hash *strtab = NULL;
+  struct elf_strtab_hash *strtab = NULL;
   Elf_Internal_Shdr *shstrtab_hdr;
   bfd_boolean need_symtab;
 
@@ -3680,11 +3912,11 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   shstrtab_hdr->sh_type = SHT_STRTAB;
   shstrtab_hdr->sh_flags = 0;
   shstrtab_hdr->sh_addr = 0;
-  shstrtab_hdr->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
+  /* sh_size is set in _bfd_elf_assign_file_positions_for_non_load.  */
   shstrtab_hdr->sh_entsize = 0;
   shstrtab_hdr->sh_link = 0;
   shstrtab_hdr->sh_info = 0;
-  /* sh_offset is set in assign_file_positions_except_relocs.  */
+  /* sh_offset is set in _bfd_elf_assign_file_positions_for_non_load.  */
   shstrtab_hdr->sh_addralign = 1;
 
   if (!assign_file_positions_except_relocs (abfd, link_info))
@@ -3697,12 +3929,16 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
 
       off = elf_next_file_pos (abfd);
 
-      hdr = &elf_tdata (abfd)->symtab_hdr;
+      hdr = & elf_symtab_hdr (abfd);
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
-      hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (hdr->sh_size != 0)
-       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+      if (elf_symtab_shndx_list (abfd) != NULL)
+       {
+         hdr = & elf_symtab_shndx_list (abfd)->hdr;
+         if (hdr->sh_size != 0)
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
+         /* FIXME: What about other symtab_shndx sections in the list ?  */
+       }
 
       hdr = &elf_tdata (abfd)->strtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -3712,9 +3948,9 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
       /* Now that we know where the .strtab section goes, write it
         out.  */
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
-         || ! _bfd_stringtab_emit (abfd, strtab))
+         || ! _bfd_elf_strtab_emit (abfd, strtab))
        return FALSE;
-      _bfd_stringtab_free (strtab);
+      _bfd_elf_strtab_free (strtab);
     }
 
   abfd->output_has_begun = TRUE;
@@ -4128,11 +4364,18 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
              new_segment = TRUE;
            }
          else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
-                  && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+                  && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0
+                  && ((abfd->flags & D_PAGED) == 0
+                      || (((last_hdr->lma + last_size - 1) & -maxpagesize)
+                          != (hdr->lma & -maxpagesize))))
            {
-             /* We don't want to put a loadable section after a
-                nonloadable section in the same segment.
-                Consider .tbss sections as loadable for this purpose.  */
+             /* We don't want to put a loaded section after a
+                nonloaded (ie. bss style) section in the same segment
+                as that will force the non-loaded section to be loaded.
+                Consider .tbss sections as loaded for this purpose.
+                However, like the writable/non-writable case below,
+                if they are on the same page then they must be put
+                in the same segment.  */
              new_segment = TRUE;
            }
          else if ((abfd->flags & D_PAGED) == 0)
@@ -4403,9 +4646,6 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
                goto error_return;
              m->next = NULL;
              m->p_type = PT_GNU_RELRO;
-             m->p_flags = PF_R;
-             m->p_flags_valid = 1;
-
              *pm = m;
              pm = &m->next;
            }
@@ -5045,7 +5285,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   Elf_Internal_Shdr **i_shdrpp;
-  Elf_Internal_Shdr **hdrpp;
+  Elf_Internal_Shdr **hdrpp, **end_hdrpp;
   Elf_Internal_Phdr *phdrs;
   Elf_Internal_Phdr *p;
   struct elf_segment_map *m;
@@ -5053,14 +5293,12 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
   bfd_vma filehdr_vaddr, filehdr_paddr;
   bfd_vma phdrs_vaddr, phdrs_paddr;
   file_ptr off;
-  unsigned int num_sec;
-  unsigned int i;
   unsigned int count;
 
   i_shdrpp = elf_elfsections (abfd);
-  num_sec = elf_numsections (abfd);
+  end_hdrpp = i_shdrpp + elf_numsections (abfd);
   off = elf_next_file_pos (abfd);
-  for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
+  for (hdrpp = i_shdrpp + 1; hdrpp < end_hdrpp; hdrpp++)
     {
       Elf_Internal_Shdr *hdr;
 
@@ -5091,9 +5329,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        }
       else if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
                && hdr->bfd_section == NULL)
+              || (hdr->bfd_section != NULL
+                  && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
+                  /* Compress DWARF debug sections.  */
               || hdr == i_shdrpp[elf_onesymtab (abfd)]
-              || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
-              || hdr == i_shdrpp[elf_strtab_sec (abfd)])
+              || (elf_symtab_shndx_list (abfd) != NULL
+                  && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
+              || hdr == i_shdrpp[elf_strtab_sec (abfd)]
+              || hdr == i_shdrpp[elf_shstrtab_sec (abfd)])
        hdr->sh_offset = -1;
       else
        off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -5234,7 +5477,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              if (!m->p_align_valid)
                p->p_align = 1;
              if (!m->p_flags_valid)
-               p->p_flags = (lp->p_flags & ~PF_W);
+               p->p_flags = PF_R;
            }
          else
            {
@@ -5249,13 +5492,14 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        }
       else if (m->count != 0)
        {
+         unsigned int i;
          if (p->p_type != PT_LOAD
              && (p->p_type != PT_NOTE
                  || bfd_get_format (abfd) != bfd_core))
            {
              if (m->includes_filehdr || m->includes_phdrs)
                {
-                 /* PR 17512: file: 2195325e.  */ 
+                 /* PR 17512: file: 2195325e.  */
                  (*_bfd_error_handler)
                    (_("%B: warning: non-load segment includes file header and/or program header"),
                     abfd);
@@ -5296,6 +5540,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
   return TRUE;
 }
 
+static elf_section_list *
+find_section_in_list (unsigned int i, elf_section_list * list)
+{
+  for (;list != NULL; list = list->next)
+    if (list->ndx == i)
+      break;
+  return list;
+}
+
 /* Work out the file positions of all the sections.  This is called by
    _bfd_elf_compute_section_file_positions.  All the section sizes and
    VMAs must be known before this is called.
@@ -5340,9 +5593,14 @@ assign_file_positions_except_relocs (bfd *abfd,
          hdr = *hdrpp;
          if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
               && hdr->bfd_section == NULL)
+             || (hdr->bfd_section != NULL
+                 && (hdr->bfd_section->flags & SEC_ELF_COMPRESS))
+                 /* Compress DWARF debug sections.  */
              || i == elf_onesymtab (abfd)
-             || i == elf_symtab_shndx (abfd)
-             || i == elf_strtab_sec (abfd))
+             || (elf_symtab_shndx_list (abfd) != NULL
+                 && hdr == i_shdrpp[elf_symtab_shndx_list (abfd)->ndx])
+             || i == elf_strtab_sec (abfd)
+             || i == elf_shstrtab_sec (abfd))
            {
              hdr->sh_offset = -1;
            }
@@ -5372,9 +5630,7 @@ assign_file_positions_except_relocs (bfd *abfd,
        }
 
       /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=.  */
-      if (link_info != NULL
-         && link_info->executable
-         && link_info->shared)
+      if (link_info != NULL && bfd_link_pie (link_info))
        {
          unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
          Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
@@ -5493,35 +5749,99 @@ prep_headers (bfd *abfd)
 /* Assign file positions for all the reloc sections which are not part
    of the loadable file image, and the file position of section headers.  */
 
-static void
-_bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
+static bfd_boolean
+_bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
 {
   file_ptr off;
-  unsigned int i, num_sec;
-  Elf_Internal_Shdr **shdrpp;
+  Elf_Internal_Shdr **shdrpp, **end_shdrpp;
+  Elf_Internal_Shdr *shdrp;
   Elf_Internal_Ehdr *i_ehdrp;
   const struct elf_backend_data *bed;
 
   off = elf_next_file_pos (abfd);
 
-  num_sec = elf_numsections (abfd);
-  for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
+  shdrpp = elf_elfsections (abfd);
+  end_shdrpp = shdrpp + elf_numsections (abfd);
+  for (shdrpp++; shdrpp < end_shdrpp; shdrpp++)
     {
-      Elf_Internal_Shdr *shdrp;
-
       shdrp = *shdrpp;
-      if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
-         && shdrp->sh_offset == -1)
-       off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
+      if (shdrp->sh_offset == -1)
+       {
+         asection *sec = shdrp->bfd_section;
+         bfd_boolean is_rel = (shdrp->sh_type == SHT_REL
+                               || shdrp->sh_type == SHT_RELA);
+         if (is_rel
+             || (sec != NULL && (sec->flags & SEC_ELF_COMPRESS)))
+           {
+             if (!is_rel)
+               {
+                 const char *name = sec->name;
+                 struct bfd_elf_section_data *d;
+
+                 /* Compress DWARF debug sections.  */
+                 if (!bfd_compress_section (abfd, sec,
+                                            shdrp->contents))
+                   return FALSE;
+
+                 if (sec->compress_status == COMPRESS_SECTION_DONE
+                     && (abfd->flags & BFD_COMPRESS_GABI) == 0)
+                   {
+                     /* If section is compressed with zlib-gnu, convert
+                        section name from .debug_* to .zdebug_*.  */
+                     char *new_name
+                       = convert_debug_to_zdebug (abfd, name);
+                     if (new_name == NULL)
+                       return FALSE;
+                     name = new_name;
+                   }
+                 /* Add setion name to section name section.  */
+                 if (shdrp->sh_name != (unsigned int) -1)
+                   abort ();
+                 shdrp->sh_name
+                   = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                                         name, FALSE);
+                 d = elf_section_data (sec);
+
+                 /* Add reloc setion name to section name section.  */
+                 if (d->rel.hdr
+                     && !_bfd_elf_set_reloc_sh_name (abfd,
+                                                     d->rel.hdr,
+                                                     name, FALSE))
+                   return FALSE;
+                 if (d->rela.hdr
+                     && !_bfd_elf_set_reloc_sh_name (abfd,
+                                                     d->rela.hdr,
+                                                     name, TRUE))
+                   return FALSE;
+
+                 /* Update section size and contents.  */
+                 shdrp->sh_size = sec->size;
+                 shdrp->contents = sec->contents;
+                 shdrp->bfd_section->contents = NULL;
+               }
+             off = _bfd_elf_assign_file_position_for_section (shdrp,
+                                                              off,
+                                                              TRUE);
+           }
+       }
     }
 
-/* Place the section headers.  */
+  /* Place section name section after DWARF debug sections have been
+     compressed.  */
+  _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
+  shdrp = &elf_tdata (abfd)->shstrtab_hdr;
+  shdrp->sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
+  off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
+
+  /* Place the section headers.  */
   i_ehdrp = elf_elfheader (abfd);
   bed = get_elf_backend_data (abfd);
   off = align_file_position (off, 1 << bed->s->log_file_align);
   i_ehdrp->e_shoff = off;
   off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
   elf_next_file_pos (abfd) = off;
+
+  return TRUE;
 }
 
 bfd_boolean
@@ -5544,12 +5864,16 @@ _bfd_elf_write_object_contents (bfd *abfd)
   if (failed)
     return FALSE;
 
-  _bfd_elf_assign_file_positions_for_relocs (abfd);
+  if (!_bfd_elf_assign_file_positions_for_non_load (abfd))
+    return FALSE;
 
   /* After writing the headers, we need to write the sections too...  */
   num_sec = elf_numsections (abfd);
   for (count = 1; count < num_sec; count++)
     {
+      i_shdrp[count]->sh_name
+       = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
+                                 i_shdrp[count]->sh_name);
       if (bed->elf_backend_section_processing)
        (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
       if (i_shdrp[count]->contents)
@@ -6056,13 +6380,9 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       first_matching_lma = TRUE;
       first_suggested_lma = TRUE;
 
-      for (section = ibfd->sections;
+      for (section = first_section, j = 0;
           section != NULL;
           section = section->next)
-       if (section == first_section)
-         break;
-
-      for (j = 0; section != NULL; section = section->next)
        {
          if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
            {
@@ -6643,7 +6963,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
 
 {
   Elf_Internal_Shdr *ihdr, *ohdr;
-  bfd_boolean final_link = link_info != NULL && !link_info->relocatable;
+  bfd_boolean final_link = (link_info != NULL
+                           && !bfd_link_relocatable (link_info));
 
   if (ibfd->xvec->flavour != bfd_target_elf_flavour
       || obfd->xvec->flavour != bfd_target_elf_flavour)
@@ -6680,6 +7001,11 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
          elf_next_in_group (osec) = elf_next_in_group (isec);
          elf_section_data (osec)->group = elf_section_data (isec)->group;
        }
+
+      /* If not decompress, preserve SHF_COMPRESSED.  */
+      if ((ibfd->flags & BFD_DECOMPRESS) == 0)
+       elf_section_flags (osec) |= (elf_section_flags (isec)
+                                    & SHF_COMPRESSED);
     }
 
   ihdr = &elf_section_data (isec)->this_hdr;
@@ -6858,7 +7184,7 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
        shndx = MAP_STRTAB;
       else if (shndx == elf_shstrtab_sec (ibfd))
        shndx = MAP_SHSTRTAB;
-      else if (shndx == elf_symtab_shndx (ibfd))
+      else if (find_section_in_list (shndx, elf_symtab_shndx_list (ibfd)))
        shndx = MAP_SYM_SHNDX;
       osym->internal_elf_sym.st_shndx = shndx;
     }
@@ -6870,18 +7196,21 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
 
 static bfd_boolean
 swap_out_syms (bfd *abfd,
-              struct bfd_strtab_hash **sttp,
+              struct elf_strtab_hash **sttp,
               int relocatable_p)
 {
   const struct elf_backend_data *bed;
   int symcount;
   asymbol **syms;
-  struct bfd_strtab_hash *stt;
+  struct elf_strtab_hash *stt;
   Elf_Internal_Shdr *symtab_hdr;
   Elf_Internal_Shdr *symtab_shndx_hdr;
   Elf_Internal_Shdr *symstrtab_hdr;
+  struct elf_sym_strtab *symstrtab;
   bfd_byte *outbound_syms;
   bfd_byte *outbound_shndx;
+  unsigned long outbound_syms_index;
+  unsigned long outbound_shndx_index;
   int idx;
   unsigned int num_locals;
   bfd_size_type amt;
@@ -6891,7 +7220,7 @@ swap_out_syms (bfd *abfd,
     return FALSE;
 
   /* Dump out the symtabs.  */
-  stt = _bfd_elf_stringtab_init ();
+  stt = _bfd_elf_strtab_init ();
   if (stt == NULL)
     return FALSE;
 
@@ -6907,33 +7236,48 @@ swap_out_syms (bfd *abfd,
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
   symstrtab_hdr->sh_type = SHT_STRTAB;
 
+  /* Allocate buffer to swap out the .strtab section.  */
+  symstrtab = (struct elf_sym_strtab *) bfd_malloc ((symcount + 1)
+                                                   * sizeof (*symstrtab));
+  if (symstrtab == NULL)
+    {
+      _bfd_elf_strtab_free (stt);
+      return FALSE;
+    }
+
   outbound_syms = (bfd_byte *) bfd_alloc2 (abfd, 1 + symcount,
                                            bed->s->sizeof_sym);
   if (outbound_syms == NULL)
     {
-      _bfd_stringtab_free (stt);
+error_return:
+      _bfd_elf_strtab_free (stt);
+      free (symstrtab);
       return FALSE;
     }
   symtab_hdr->contents = outbound_syms;
+  outbound_syms_index = 0;
 
   outbound_shndx = NULL;
-  symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-  if (symtab_shndx_hdr->sh_name != 0)
+  outbound_shndx_index = 0;
+
+  if (elf_symtab_shndx_list (abfd))
     {
-      amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
-      outbound_shndx =  (bfd_byte *)
-          bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
-      if (outbound_shndx == NULL)
+      symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      if (symtab_shndx_hdr->sh_name != 0)
        {
-         _bfd_stringtab_free (stt);
-         return FALSE;
-       }
+         amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
+         outbound_shndx =  (bfd_byte *)
+           bfd_zalloc2 (abfd, 1 + symcount, sizeof (Elf_External_Sym_Shndx));
+         if (outbound_shndx == NULL)
+           goto error_return;
 
-      symtab_shndx_hdr->contents = outbound_shndx;
-      symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
-      symtab_shndx_hdr->sh_size = amt;
-      symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
-      symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+         symtab_shndx_hdr->contents = outbound_shndx;
+         symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
+         symtab_shndx_hdr->sh_size = amt;
+         symtab_shndx_hdr->sh_addralign = sizeof (Elf_External_Sym_Shndx);
+         symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
+       }
+      /* FIXME: What about any other headers in the list ?  */
     }
 
   /* Now generate the data (for "contents").  */
@@ -6947,10 +7291,12 @@ swap_out_syms (bfd *abfd,
     sym.st_other = 0;
     sym.st_shndx = SHN_UNDEF;
     sym.st_target_internal = 0;
-    bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
-    outbound_syms += bed->s->sizeof_sym;
+    symstrtab[0].sym = sym;
+    symstrtab[0].dest_index = outbound_syms_index;
+    symstrtab[0].destshndx_index = outbound_shndx_index;
+    outbound_syms_index++;
     if (outbound_shndx != NULL)
-      outbound_shndx += sizeof (Elf_External_Sym_Shndx);
+      outbound_shndx_index++;
   }
 
   name_local_sections
@@ -6958,7 +7304,7 @@ swap_out_syms (bfd *abfd,
        && bed->elf_backend_name_local_section_symbols (abfd));
 
   syms = bfd_get_outsymbols (abfd);
-  for (idx = 0; idx < symcount; idx++)
+  for (idx = 0; idx < symcount;)
     {
       Elf_Internal_Sym sym;
       bfd_vma value = syms[idx]->value;
@@ -6970,18 +7316,17 @@ swap_out_syms (bfd *abfd,
          && (flags & (BSF_SECTION_SYM | BSF_GLOBAL)) == BSF_SECTION_SYM)
        {
          /* Local section symbols have no name.  */
-         sym.st_name = 0;
+         sym.st_name = (unsigned long) -1;
        }
       else
        {
-         sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
-                                                           syms[idx]->name,
-                                                           TRUE, FALSE);
+         /* Call _bfd_elf_strtab_offset after _bfd_elf_strtab_finalize
+            to get the final offset for st_name.  */
+         sym.st_name
+           = (unsigned long) _bfd_elf_strtab_add (stt, syms[idx]->name,
+                                                  FALSE);
          if (sym.st_name == (unsigned long) -1)
-           {
-             _bfd_stringtab_free (stt);
-             return FALSE;
-           }
+           goto error_return;
        }
 
       type_ptr = elf_symbol_from (abfd, syms[idx]);
@@ -7041,7 +7386,8 @@ swap_out_syms (bfd *abfd,
                  shndx = elf_shstrtab_sec (abfd);
                  break;
                case MAP_SYM_SHNDX:
-                 shndx = elf_symtab_shndx (abfd);
+                 if (elf_symtab_shndx_list (abfd))
+                   shndx = elf_symtab_shndx_list (abfd)->ndx;
                  break;
                default:
                  shndx = SHN_ABS;
@@ -7071,8 +7417,7 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
                                          syms[idx]->name ? syms[idx]->name : "<Local sym>",
                                          sec->name);
                      bfd_set_error (bfd_error_invalid_operation);
-                     _bfd_stringtab_free (stt);
-                     return FALSE;
+                     goto error_return;
                    }
 
                  shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
@@ -7158,14 +7503,40 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
          sym.st_target_internal = 0;
        }
 
-      bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
-      outbound_syms += bed->s->sizeof_sym;
+      idx++;
+      symstrtab[idx].sym = sym;
+      symstrtab[idx].dest_index = outbound_syms_index;
+      symstrtab[idx].destshndx_index = outbound_shndx_index;
+
+      outbound_syms_index++;
       if (outbound_shndx != NULL)
-       outbound_shndx += sizeof (Elf_External_Sym_Shndx);
+       outbound_shndx_index++;
     }
 
+  /* Finalize the .strtab section.  */
+  _bfd_elf_strtab_finalize (stt);
+
+  /* Swap out the .strtab section.  */
+  for (idx = 0; idx <= symcount; idx++)
+    {
+      struct elf_sym_strtab *elfsym = &symstrtab[idx];
+      if (elfsym->sym.st_name == (unsigned long) -1)
+       elfsym->sym.st_name = 0;
+      else
+       elfsym->sym.st_name = _bfd_elf_strtab_offset (stt,
+                                                     elfsym->sym.st_name);
+      bed->s->swap_symbol_out (abfd, &elfsym->sym,
+                              (outbound_syms
+                               + (elfsym->dest_index
+                                  * bed->s->sizeof_sym)),
+                              (outbound_shndx
+                               + (elfsym->destshndx_index
+                                  * sizeof (Elf_External_Sym_Shndx))));
+    }
+  free (symstrtab);
+
   *sttp = stt;
-  symstrtab_hdr->sh_size = _bfd_stringtab_size (stt);
+  symstrtab_hdr->sh_size = _bfd_elf_strtab_size (stt);
   symstrtab_hdr->sh_type = SHT_STRTAB;
 
   symstrtab_hdr->sh_flags = 0;
@@ -7576,7 +7947,7 @@ error_return_verref:
            goto error_return_bad_verdef;
 
          iverdef = &iverdefarr[(iverdefmem.vd_ndx & VERSYM_VERSION) - 1];
-         memcpy (iverdef, &iverdefmem, sizeof (Elf_Internal_Verdef));
+         memcpy (iverdef, &iverdefmem, offsetof (Elf_Internal_Verdef, vd_bfd));
 
          iverdef->vd_bfd = abfd;
 
@@ -7625,6 +7996,7 @@ error_return_verref:
                          ((bfd_byte *) everdaux + iverdaux->vda_next));
            }
 
+         iverdef->vd_nodename = NULL;
          if (iverdef->vd_cnt)
            iverdef->vd_nodename = iverdef->vd_auxptr->vda_nodename;
 
@@ -7738,6 +8110,47 @@ _bfd_elf_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
   if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
     return TRUE;
 
+  /* Treat assembler generated fake symbols, dollar local labels and
+     forward-backward labels (aka local labels) as locals.
+     These labels have the form:
+
+       L0^A.*                                  (fake symbols)
+
+       [.]?L[0123456789]+{^A|^B}[0123456789]*  (local labels)
+
+     Versions which start with .L will have already been matched above,
+     so we only need to match the rest.  */
+  if (name[0] == 'L' && ISDIGIT (name[1]))
+    {
+      bfd_boolean ret = FALSE;
+      const char * p;
+      char c;
+
+      for (p = name + 2; (c = *p); p++)
+       {
+         if (c == 1 || c == 2)
+           {
+             if (c == 1 && p == name + 2)
+               /* A fake symbol.  */
+               return TRUE;
+
+             /* FIXME: We are being paranoid here and treating symbols like
+                L0^Bfoo as if there were non-local, on the grounds that the
+                assembler will never generate them.  But can any symbol
+                containing an ASCII value in the range 1-31 ever be anything
+                other than some kind of local ?  */
+             ret = TRUE;
+           }
+
+         if (! ISDIGIT (c))
+           {
+             ret = FALSE;
+             break;
+           }
+       }
+      return ret;
+    }
+
   return FALSE;
 }
 
@@ -7851,7 +8264,7 @@ _bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   int ret = bed->s->sizeof_ehdr;
 
-  if (!info->relocatable)
+  if (!bfd_link_relocatable (info))
     {
       bfd_size_type phdr_size = elf_program_header_size (abfd);
 
@@ -7888,7 +8301,21 @@ _bfd_elf_set_section_contents (bfd *abfd,
       && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
     return FALSE;
 
+  if (!count)
+    return TRUE;
+
   hdr = &elf_section_data (section)->this_hdr;
+  if (hdr->sh_offset == (file_ptr) -1)
+    {
+      /* We must compress this section.  Write output to the buffer.  */
+      unsigned char *contents = hdr->contents;
+      if ((offset + count) > hdr->sh_size
+         || (section->flags & SEC_ELF_COMPRESS) == 0
+         || contents == NULL)
+       abort ();
+      memcpy (contents + offset, location, count);
+      return TRUE;
+    }
   pos = hdr->sh_offset + offset;
   if (bfd_seek (abfd, pos, SEEK_SET) != 0
       || bfd_bwrite (location, count, abfd) != count)
@@ -8703,6 +9130,9 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       if (note->namesz == 6
          && strcmp (note->namedata, "LINUX") == 0)
        return elfcore_grok_xstatereg (abfd, note);
+      else if (note->namesz == 8
+         && strcmp (note->namedata, "FreeBSD") == 0)
+       return elfcore_grok_xstatereg (abfd, note);
       else
        return TRUE;
 
@@ -8857,24 +9287,31 @@ 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;
     }
 }
 
 static bfd_boolean
 elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
 {
-  struct elf_obj_tdata *t;
+  struct bfd_build_id* build_id;
 
   if (note->descsz == 0)
     return FALSE;
 
-  t = elf_tdata (abfd);
-  t->build_id = bfd_alloc (abfd, sizeof (*t->build_id) - 1 + note->descsz);
-  if (t->build_id == NULL)
+  build_id = bfd_alloc (abfd, sizeof (struct bfd_build_id) - 1 + note->descsz);
+  if (build_id == NULL)
     return FALSE;
 
-  t->build_id->size = note->descsz;
-  memcpy (t->build_id->data, note->descdata, note->descsz);
+  build_id->size = note->descsz;
+  memcpy (build_id->data, note->descdata, note->descsz);
+  abfd->build_id = build_id;
 
   return TRUE;
 }
@@ -9354,9 +9791,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));
 }
@@ -9368,9 +9803,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));
 }
@@ -9522,7 +9955,11 @@ char *
 elfcore_write_xstatereg (bfd *abfd, char *buf, int *bufsiz,
                         const void *xfpregs, int size)
 {
-  char *note_name = "LINUX";
+  char *note_name;
+  if (get_elf_backend_data (abfd)->elf_osabi == ELFOSABI_FREEBSD)
+    note_name = "FreeBSD";
+  else
+    note_name = "LINUX";
   return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, NT_X86_XSTATE, xfpregs, size);
 }
This page took 0.04729 seconds and 4 git commands to generate.