Warn users about mismatched PID namespaces
[deliverable/binutils-gdb.git] / bfd / elf.c
index 075a668c3089c5d09868565c305d2ea5f59dc78f..9c4dcdf452d1ab43c89d38b082214d0f694d3894 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,8 +1,6 @@
 /* ELF executable support for BFD.
 
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1993-2014 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -44,6 +42,7 @@ SECTION
 #include "elf-bfd.h"
 #include "libiberty.h"
 #include "safe-ctype.h"
+#include "elf-linux-psinfo.h"
 
 #ifdef CORE_HEADER
 #include CORE_HEADER
@@ -244,7 +243,14 @@ bfd_elf_allocate_object (bfd *abfd,
     return FALSE;
 
   elf_object_id (abfd) = object_id;
-  elf_program_header_size (abfd) = (bfd_size_type) -1;
+  if (abfd->direction != read_direction)
+    {
+      struct output_elf_obj_tdata *o = bfd_zalloc (abfd, sizeof *o);
+      if (o == NULL)
+       return FALSE;
+      elf_tdata (abfd)->o = o;
+      elf_program_header_size (abfd) = (bfd_size_type) -1;
+    }
   return TRUE;
 }
 
@@ -261,7 +267,10 @@ bfd_boolean
 bfd_elf_mkcorefile (bfd *abfd)
 {
   /* I think this can be done just like an object file.  */
-  return abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd);
+  if (!abfd->xvec->_bfd_set_format[(int) bfd_object] (abfd))
+    return FALSE;
+  elf_tdata (abfd)->core = bfd_zalloc (abfd, sizeof (*elf_tdata (abfd)->core));
+  return elf_tdata (abfd)->core != NULL;
 }
 
 static char *
@@ -545,9 +554,9 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
       shnum = elf_numsections (abfd);
       num_group = 0;
 
-#define IS_VALID_GROUP_SECTION_HEADER(shdr)            \
+#define IS_VALID_GROUP_SECTION_HEADER(shdr, minsize)   \
        (   (shdr)->sh_type == SHT_GROUP                \
-        && (shdr)->sh_size >= (2 * GRP_ENTRY_SIZE)     \
+        && (shdr)->sh_size >= minsize                  \
         && (shdr)->sh_entsize == GRP_ENTRY_SIZE        \
         && ((shdr)->sh_size % GRP_ENTRY_SIZE) == 0)
 
@@ -555,7 +564,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
        {
          Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
 
-         if (IS_VALID_GROUP_SECTION_HEADER (shdr))
+         if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
            num_group += 1;
        }
 
@@ -581,7 +590,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
            {
              Elf_Internal_Shdr *shdr = elf_elfsections (abfd)[i];
 
-             if (IS_VALID_GROUP_SECTION_HEADER (shdr))
+             if (IS_VALID_GROUP_SECTION_HEADER (shdr, 2 * GRP_ENTRY_SIZE))
                {
                  unsigned char *src;
                  Elf_Internal_Group *dest;
@@ -599,9 +608,10 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  if (shdr->contents == NULL)
                    {
                      _bfd_error_handler
-                       (_("%B: Corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+                       (_("%B: corrupt size field in group section header: 0x%lx"), abfd, shdr->sh_size);
                      bfd_set_error (bfd_error_bad_value);
-                     return FALSE;
+                     -- num_group;
+                     continue;
                    }
 
                  memset (shdr->contents, 0, amt);
@@ -609,7 +619,16 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                  if (bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
                      || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
                          != shdr->sh_size))
-                   return FALSE;
+                   {
+                     _bfd_error_handler
+                       (_("%B: invalid size field in group section header: 0x%lx"), abfd, shdr->sh_size);
+                     bfd_set_error (bfd_error_bad_value);
+                     -- num_group;
+                     /* PR 17510: If the group contents are even partially
+                        corrupt, do not allow any of the contents to be used.  */
+                     memset (shdr->contents, 0, amt);
+                     continue;
+                   }
 
                  /* Translate raw contents, a flag word followed by an
                     array of elf section indices all in target byte order,
@@ -642,6 +661,21 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
                    }
                }
            }
+
+         /* PR 17510: Corrupt binaries might contain invalid groups.  */
+         if (num_group != (unsigned) elf_tdata (abfd)->num_group)
+           {
+             elf_tdata (abfd)->num_group = num_group;
+
+             /* If all groups are invalid then fail.  */
+             if (num_group == 0)
+               {
+                 elf_tdata (abfd)->group_sect_ptr = NULL;
+                 elf_tdata (abfd)->num_group = num_group = -1;
+                 (*_bfd_error_handler) (_("%B: no valid group sections found"), abfd);
+                 bfd_set_error (bfd_error_bad_value);
+               }
+           }
        }
     }
 
@@ -707,6 +741,7 @@ setup_group (bfd *abfd, Elf_Internal_Shdr *hdr, asection *newsect)
     {
       (*_bfd_error_handler) (_("%B: no group info for section %A"),
                             abfd, newsect);
+      return FALSE;
     }
   return TRUE;
 }
@@ -880,45 +915,25 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
     {
       /* The debugging sections appear to be recognized only by name,
         not any sort of flag.  Their SEC_ALLOC bits are cleared.  */
-      static const struct
-       {
-         const char *name;
-         int len;
-       } debug_sections [] =
-       {
-         { STRING_COMMA_LEN ("debug") },       /* 'd' */
-         { NULL,                0  },  /* 'e' */
-         { NULL,                0  },  /* 'f' */
-         { STRING_COMMA_LEN ("gnu.linkonce.wi.") },    /* 'g' */
-         { NULL,                0  },  /* 'h' */
-         { NULL,                0  },  /* 'i' */
-         { NULL,                0  },  /* 'j' */
-         { NULL,                0  },  /* 'k' */
-         { STRING_COMMA_LEN ("line") },        /* 'l' */
-         { NULL,                0  },  /* 'm' */
-         { NULL,                0  },  /* 'n' */
-         { NULL,                0  },  /* 'o' */
-         { NULL,                0  },  /* 'p' */
-         { NULL,                0  },  /* 'q' */
-         { NULL,                0  },  /* 'r' */
-         { STRING_COMMA_LEN ("stab") },        /* 's' */
-         { NULL,                0  },  /* 't' */
-         { NULL,                0  },  /* 'u' */
-         { NULL,                0  },  /* 'v' */
-         { NULL,                0  },  /* 'w' */
-         { NULL,                0  },  /* 'x' */
-         { NULL,                0  },  /* 'y' */
-         { STRING_COMMA_LEN ("zdebug") }       /* 'z' */
-       };
-
       if (name [0] == '.')
        {
-         int i = name [1] - 'd';
-         if (i >= 0
-             && i < (int) ARRAY_SIZE (debug_sections)
-             && debug_sections [i].name != NULL
-             && strncmp (&name [1], debug_sections [i].name,
-                         debug_sections [i].len) == 0)
+         const char *p;
+         int n;
+         if (name[1] == 'd')
+           p = ".debug", n = 6;
+         else if (name[1] == 'g' && name[2] == 'n')
+           p = ".gnu.linkonce.wi.", n = 17;
+         else if (name[1] == 'g' && name[2] == 'd')
+           p = ".gdb_index", n = 11; /* yes we really do mean 11.  */
+         else if (name[1] == 'l')
+           p = ".line", n = 5;
+         else if (name[1] == 's')
+           p = ".stab", n = 5;
+         else if (name[1] == 'z')
+           p = ".zdebug", n = 7;
+         else
+           p = NULL, n = 0;
+         if (p != NULL && strncmp (name, p, n) == 0)
            flags |= SEC_DEBUGGING;
        }
     }
@@ -976,7 +991,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       phdr = elf_tdata (abfd)->phdr;
       for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
        {
-         if (phdr->p_type == PT_LOAD
+         if (((phdr->p_type == PT_LOAD
+               && (hdr->sh_flags & SHF_TLS) == 0)
+              || phdr->p_type == PT_TLS)
              && ELF_SECTION_IN_SEGMENT (hdr, phdr))
            {
              if ((flags & SEC_LOAD) == 0)
@@ -1023,7 +1040,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
       else
        {
          /* Normal section.  Check if we should compress.  */
-         if ((abfd->flags & BFD_COMPRESS))
+         if ((abfd->flags & BFD_COMPRESS) && newsect->size != 0)
            action = compress;
        }
 
@@ -1036,7 +1053,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
          if (!bfd_init_section_compress_status (abfd, newsect))
            {
              (*_bfd_error_handler)
-               (_("%B: unable to initialize commpress status for section %s"),
+               (_("%B: unable to initialize compress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -1056,7 +1073,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
          if (!bfd_init_section_decompress_status (abfd, newsect))
            {
              (*_bfd_error_handler)
-               (_("%B: unable to initialize decommpress status for section %s"),
+               (_("%B: unable to initialize decompress status for section %s"),
                 abfd, name);
              return FALSE;
            }
@@ -1126,13 +1143,17 @@ _bfd_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return TRUE;
 
-  BFD_ASSERT (!elf_flags_init (obfd)
-             || (elf_elfheader (obfd)->e_flags
-                 == elf_elfheader (ibfd)->e_flags));
+  if (!elf_flags_init (obfd))
+    {
+      elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+      elf_flags_init (obfd) = TRUE;
+    }
 
   elf_gp (obfd) = elf_gp (ibfd);
-  elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = TRUE;
+
+  /* Also copy the EI_OSABI field.  */
+  elf_elfheader (obfd)->e_ident[EI_OSABI] =
+    elf_elfheader (ibfd)->e_ident[EI_OSABI];
 
   /* Copy object attributes.  */
   _bfd_elf_copy_obj_attributes (ibfd, obfd);
@@ -1452,9 +1473,9 @@ bfd_elf_print_symbol (bfd *abfd,
        bfd_fprintf_vma (abfd, file, val);
 
        /* If we have version information, print it.  */
-       if (elf_tdata (abfd)->dynversym_section != 0
-           && (elf_tdata (abfd)->dynverdef_section != 0
-               || elf_tdata (abfd)->dynverref_section != 0))
+       if (elf_dynversym (abfd) != 0
+           && (elf_dynverdef (abfd) != 0
+               || elf_dynverref (abfd) != 0))
          {
            unsigned int vernum;
            const char *version_string;
@@ -1557,38 +1578,74 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
   Elf_Internal_Ehdr *ehdr;
   const struct elf_backend_data *bed;
   const char *name;
+  bfd_boolean ret = TRUE;
+  static bfd_boolean * sections_being_created = NULL;
+  static bfd * sections_being_created_abfd = NULL;
+  static unsigned int nesting = 0;
 
   if (shindex >= elf_numsections (abfd))
     return FALSE;
 
+  if (++ nesting > 3)
+    {
+      /* PR17512: A corrupt ELF binary might contain a recursive group of
+        sections, each the string indicies pointing to the next in the
+        loop.  Detect this here, by refusing to load a section that we are
+        already in the process of loading.  We only trigger this test if
+        we have nested at least three sections deep as normal ELF binaries
+        can expect to recurse at least once.
+
+        FIXME: It would be better if this array was attached to the bfd,
+        rather than being held in a static pointer.  */
+
+      if (sections_being_created_abfd != abfd)
+       sections_being_created = NULL;
+      if (sections_being_created == NULL)
+       {
+         /* FIXME: It would be more efficient to attach this array to the bfd somehow.  */
+         sections_being_created = (bfd_boolean *)
+           bfd_zalloc (abfd, elf_numsections (abfd) * sizeof (bfd_boolean));
+         sections_being_created_abfd = abfd;
+       }
+      if (sections_being_created [shindex])
+       {
+         (*_bfd_error_handler)
+           (_("%B: warning: loop in section dependencies detected"), abfd);
+         return FALSE;
+       }
+      sections_being_created [shindex] = TRUE;
+    }
+
   hdr = elf_elfsections (abfd)[shindex];
   ehdr = elf_elfheader (abfd);
   name = bfd_elf_string_from_elf_section (abfd, ehdr->e_shstrndx,
                                          hdr->sh_name);
   if (name == NULL)
-    return FALSE;
+    goto fail;
 
   bed = get_elf_backend_data (abfd);
   switch (hdr->sh_type)
     {
     case SHT_NULL:
       /* Inactive section. Throw it away.  */
-      return TRUE;
+      goto success;
 
-    case SHT_PROGBITS: /* Normal section with contents.  */
-    case SHT_NOBITS:   /* .bss section.  */
-    case SHT_HASH:     /* .hash section.  */
-    case SHT_NOTE:     /* .note section.  */
+    case SHT_PROGBITS:         /* Normal section with contents.  */
+    case SHT_NOBITS:           /* .bss section.  */
+    case SHT_HASH:             /* .hash section.  */
+    case SHT_NOTE:             /* .note section.  */
     case SHT_INIT_ARRAY:       /* .init_array section.  */
     case SHT_FINI_ARRAY:       /* .fini_array section.  */
     case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
     case SHT_GNU_LIBLIST:      /* .gnu.liblist section.  */
     case SHT_GNU_HASH:         /* .gnu.hash section.  */
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
     case SHT_DYNAMIC:  /* Dynamic linking information.  */
       if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
-       return FALSE;
+       goto fail;
+
       if (hdr->sh_link > elf_numsections (abfd))
        {
          /* PR 10478: Accept Solaris binaries with a sh_link
@@ -1602,11 +1659,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                break;
              /* Otherwise fall through.  */
            default:
-             return FALSE;
+             goto fail;
            }
        }
       else if (elf_elfsections (abfd)[hdr->sh_link] == NULL)
-       return FALSE;
+       goto fail;
       else if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
        {
          Elf_Internal_Shdr *dynsymhdr;
@@ -1635,16 +1692,26 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                }
            }
        }
-      break;
+      goto success;
 
-    case SHT_SYMTAB:           /* A symbol table */
+    case SHT_SYMTAB:           /* A symbol table */
       if (elf_onesymtab (abfd) == shindex)
-       return TRUE;
+       goto success;
 
       if (hdr->sh_entsize != bed->s->sizeof_sym)
-       return FALSE;
+       goto fail;
+
       if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
-       return FALSE;
+       {
+         if (hdr->sh_size != 0)
+           goto fail;
+         /* Some assemblers erroneously set sh_info to one with a
+            zero sh_size.  ld sees this as a global symbol count
+            of (unsigned) -1.  Fix it here.  */
+         hdr->sh_info = 0;
+         goto success;
+       }
+
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
       elf_onesymtab (abfd) = shindex;
       elf_tdata (abfd)->symtab_hdr = *hdr;
@@ -1661,7 +1728,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          && (abfd->flags & DYNAMIC) != 0
          && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name,
                                                shindex))
-       return FALSE;
+       goto fail;
 
       /* Go looking for SHT_SYMTAB_SHNDX too, since if there is one we
         can't read symbols without that section loaded as well.  It
@@ -1687,16 +1754,29 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                  break;
              }
          if (i != shindex)
-           return bfd_section_from_shdr (abfd, i);
+           ret = bfd_section_from_shdr (abfd, i);
        }
-      return TRUE;
+      goto success;
 
-    case SHT_DYNSYM:           /* A dynamic symbol table */
+    case SHT_DYNSYM:           /* A dynamic symbol table */
       if (elf_dynsymtab (abfd) == shindex)
-       return TRUE;
+       goto success;
 
       if (hdr->sh_entsize != bed->s->sizeof_sym)
-       return FALSE;
+       goto fail;
+
+      if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+       {
+         if (hdr->sh_size != 0)
+           goto fail;
+
+         /* Some linkers erroneously set sh_info to one with a
+            zero sh_size.  ld sees this as a global symbol count
+            of (unsigned) -1.  Fix it here.  */
+         hdr->sh_info = 0;
+         goto success;
+       }
+
       BFD_ASSERT (elf_dynsymtab (abfd) == 0);
       elf_dynsymtab (abfd) = shindex;
       elf_tdata (abfd)->dynsymtab_hdr = *hdr;
@@ -1705,34 +1785,38 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 
       /* Besides being a symbol table, we also treat this as a regular
         section, so that objcopy can handle it.  */
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
-    case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
+    case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
       if (elf_symtab_shndx (abfd) == shindex)
-       return TRUE;
+       goto success;
 
       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;
-      return TRUE;
+      goto success;
 
-    case SHT_STRTAB:           /* A string table */
+    case SHT_STRTAB:           /* A string table */
       if (hdr->bfd_section != NULL)
-       return TRUE;
+       goto success;
+
       if (ehdr->e_shstrndx == shindex)
        {
          elf_tdata (abfd)->shstrtab_hdr = *hdr;
          elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
-         return TRUE;
+         goto success;
        }
+
       if (elf_elfsections (abfd)[elf_onesymtab (abfd)]->sh_link == shindex)
        {
        symtab_strtab:
          elf_tdata (abfd)->strtab_hdr = *hdr;
          elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->strtab_hdr;
-         return TRUE;
+         goto success;
        }
+
       if (elf_elfsections (abfd)[elf_dynsymtab (abfd)]->sh_link == shindex)
        {
        dynsymtab_strtab:
@@ -1741,8 +1825,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          elf_elfsections (abfd)[shindex] = hdr;
          /* We also treat this as a regular section, so that objcopy
             can handle it.  */
-         return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
-                                                 shindex);
+         ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+                                                shindex);
+         goto success;
        }
 
       /* If the string table isn't one of the above, then treat it as a
@@ -1760,9 +1845,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                {
                  /* Prevent endless recursion on broken objects.  */
                  if (i == shindex)
-                   return FALSE;
+                   goto fail;
                  if (! bfd_section_from_shdr (abfd, i))
-                   return FALSE;
+                   goto fail;
                  if (elf_onesymtab (abfd) == i)
                    goto symtab_strtab;
                  if (elf_dynsymtab (abfd) == i)
@@ -1770,7 +1855,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                }
            }
        }
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
     case SHT_REL:
     case SHT_RELA:
@@ -1785,7 +1871,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        if (hdr->sh_entsize
            != (bfd_size_type) (hdr->sh_type == SHT_REL
                                ? bed->s->sizeof_rel : bed->s->sizeof_rela))
-         return FALSE;
+         goto fail;
 
        /* Check for a bogus link to avoid crashing.  */
        if (hdr->sh_link >= num_sec)
@@ -1793,8 +1879,9 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
            ((*_bfd_error_handler)
             (_("%B: invalid link %lu for reloc section %s (index %u)"),
              abfd, hdr->sh_link, name, shindex));
-           return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
-                                                   shindex);
+           ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+                                                  shindex);
+           goto success;
          }
 
        /* For some incomprehensible reason Oracle distributes
@@ -1835,7 +1922,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        if ((elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
             || elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_DYNSYM)
            && ! bfd_section_from_shdr (abfd, hdr->sh_link))
-         return FALSE;
+         goto fail;
 
        /* If this reloc section does not use the main symbol table we
           don't treat it as a reloc section.  BFD can't adequately
@@ -1850,14 +1937,18 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
            || hdr->sh_info >= num_sec
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_REL
            || elf_elfsections (abfd)[hdr->sh_info]->sh_type == SHT_RELA)
-         return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
-                                                 shindex);
+         {
+           ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+                                                  shindex);
+           goto success;
+         }
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
-         return FALSE;
+         goto fail;
+
        target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
        if (target_sect == NULL)
-         return FALSE;
+         goto fail;
 
        esdt = elf_section_data (target_sect);
        if (hdr->sh_type == SHT_RELA)
@@ -1869,7 +1960,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
        amt = sizeof (*hdr2);
        hdr2 = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
        if (hdr2 == NULL)
-         return FALSE;
+         goto fail;
        *hdr2 = *hdr;
        *p_hdr = hdr2;
        elf_elfsections (abfd)[shindex] = hdr2;
@@ -1885,34 +1976,40 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
              target_sect->use_rela_p = 1;
          }
        abfd->flags |= HAS_RELOC;
-       return TRUE;
+       goto success;
       }
 
     case SHT_GNU_verdef:
       elf_dynverdef (abfd) = shindex;
       elf_tdata (abfd)->dynverdef_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
     case SHT_GNU_versym:
       if (hdr->sh_entsize != sizeof (Elf_External_Versym))
-       return FALSE;
+       goto fail;
+
       elf_dynversym (abfd) = shindex;
       elf_tdata (abfd)->dynversym_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
     case SHT_GNU_verneed:
       elf_dynverref (abfd) = shindex;
       elf_tdata (abfd)->dynverref_hdr = *hdr;
-      return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+      goto success;
 
     case SHT_SHLIB:
-      return TRUE;
+      goto success;
 
     case SHT_GROUP:
-      if (! IS_VALID_GROUP_SECTION_HEADER (hdr))
-       return FALSE;
+      if (! IS_VALID_GROUP_SECTION_HEADER (hdr, GRP_ENTRY_SIZE))
+       goto fail;
+
       if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
-       return FALSE;
+       goto fail;
+
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
@@ -1938,7 +2035,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                }
            }
        }
-      break;
+      goto success;
 
     default:
       /* Possibly an attributes section.  */
@@ -1946,14 +2043,14 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          || hdr->sh_type == bed->obj_attrs_section_type)
        {
          if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
-           return FALSE;
+           goto fail;
          _bfd_elf_parse_attributes (abfd, hdr);
-         return TRUE;
+         goto success;
        }
 
       /* Check for any processor-specific section types.  */
       if (bed->elf_backend_section_from_shdr (abfd, hdr, name, shindex))
-       return TRUE;
+       goto success;
 
       if (hdr->sh_type >= SHT_LOUSER && hdr->sh_type <= SHT_HIUSER)
        {
@@ -1965,9 +2062,12 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                 "specific section `%s' [0x%8x]"),
               abfd, name, hdr->sh_type);
          else
-           /* Allow sections reserved for applications.  */
-           return _bfd_elf_make_section_from_shdr (abfd, hdr, name,
-                                                   shindex);
+           {
+             /* Allow sections reserved for applications.  */
+             ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name,
+                                                    shindex);
+             goto success;
+           }
        }
       else if (hdr->sh_type >= SHT_LOPROC
               && hdr->sh_type <= SHT_HIPROC)
@@ -1988,8 +2088,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
                 "`%s' [0x%8x]"),
               abfd, name, hdr->sh_type);
          else
-           /* Otherwise it should be processed.  */
-           return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+           {
+             /* Otherwise it should be processed.  */
+             ret = _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+             goto success;
+           }
        }
       else
        /* FIXME: We should handle this section.  */
@@ -1997,10 +2100,20 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
          (_("%B: don't know how to handle section `%s' [0x%8x]"),
           abfd, name, hdr->sh_type);
 
-      return FALSE;
+      goto fail;
     }
 
-  return TRUE;
+ fail:
+  ret = FALSE;
+ success:
+  if (sections_being_created && sections_being_created_abfd == abfd)
+    sections_being_created [shindex] = FALSE;
+  if (-- nesting == 0)
+    {
+      sections_being_created = NULL;
+      sections_being_created_abfd = abfd;
+    }
+  return ret;
 }
 
 /* Return the local symbol specified by ABFD, R_SYMNDX.  */
@@ -2061,6 +2174,9 @@ static const struct bfd_elf_special_section special_sections_d[] =
 {
   { STRING_COMMA_LEN (".data"),         -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".data1"),         0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+  /* There are more DWARF sections than these, but they needn't be added here
+     unless you have to cope with broken compilers that don't emit section
+     attributes or you want to help the user writing assembler.  */
   { STRING_COMMA_LEN (".debug"),         0, SHT_PROGBITS, 0 },
   { STRING_COMMA_LEN (".debug_line"),    0, SHT_PROGBITS, 0 },
   { STRING_COMMA_LEN (".debug_info"),    0, SHT_PROGBITS, 0 },
@@ -2082,6 +2198,7 @@ static const struct bfd_elf_special_section special_sections_f[] =
 static const struct bfd_elf_special_section special_sections_g[] =
 {
   { STRING_COMMA_LEN (".gnu.linkonce.b"), -2, SHT_NOBITS,      SHF_ALLOC + SHF_WRITE },
+  { STRING_COMMA_LEN (".gnu.lto_"),       -1, SHT_PROGBITS,    SHF_EXCLUDE },
   { STRING_COMMA_LEN (".got"),             0, SHT_PROGBITS,    SHF_ALLOC + SHF_WRITE },
   { STRING_COMMA_LEN (".gnu.version"),     0, SHT_GNU_versym,  0 },
   { STRING_COMMA_LEN (".gnu.version_d"),   0, SHT_GNU_verdef,  0 },
@@ -2163,7 +2280,7 @@ static const struct bfd_elf_special_section special_sections_z[] =
   { NULL,                     0,  0, 0,            0 }
 };
 
-static const struct bfd_elf_special_section *special_sections[] =
+static const struct bfd_elf_special_section * const special_sections[] =
 {
   special_sections_b,          /* 'b' */
   special_sections_c,          /* 'c' */
@@ -2303,12 +2420,19 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
      anyway.  We will set ELF section type and flags for all linker
      created sections.  If user specifies BFD section flags, we will
      set ELF section type and flags based on BFD section flags in
-     elf_fake_sections.  */
-  if ((!sec->flags && abfd->direction != read_direction)
+     elf_fake_sections.  Special handling for .init_array/.fini_array
+     output sections since they may contain .ctors/.dtors input
+     sections.  We don't want _bfd_elf_init_private_section_data to
+     copy ELF section type from .ctors/.dtors input sections.  */
+  if (abfd->direction != read_direction
       || (sec->flags & SEC_LINKER_CREATED) != 0)
     {
       ssect = (*bed->get_sec_type_attr) (abfd, sec);
-      if (ssect != NULL)
+      if (ssect != NULL
+         && (!sec->flags
+             || (sec->flags & SEC_LINKER_CREATED) != 0
+             || ssect->type == SHT_INIT_ARRAY
+             || ssect->type == SHT_FINI_ARRAY))
        {
          elf_section_type (sec) = ssect->type;
          elf_section_flags (sec) = ssect->attr;
@@ -2501,7 +2625,7 @@ _bfd_elf_single_rel_hdr (asection *sec)
    USE_RELA_P is TRUE, we use RELA relocations; otherwise, we use REL
    relocations.  */
 
-bfd_boolean
+static bfd_boolean
 _bfd_elf_init_reloc_shdr (bfd *abfd,
                          struct bfd_elf_section_reloc_data *reldata,
                          asection *asect,
@@ -2517,7 +2641,7 @@ _bfd_elf_init_reloc_shdr (bfd *abfd,
   rel_hdr = bfd_zalloc (abfd, amt);
   reldata->hdr = rel_hdr;
 
-  amt = sizeof ".rela" + strlen (asect->name);      
+  amt = sizeof ".rela" + strlen (asect->name);
   name = (char *) bfd_alloc (abfd, amt);
   if (name == NULL)
     return FALSE;
@@ -2961,9 +3085,9 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
        d->rela.idx = 0;
     }
 
-  t->shstrtab_section = section_number++;
+  elf_shstrtab_sec (abfd) = section_number++;
   _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->shstrtab_hdr.sh_name);
-  elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
+  elf_elfheader (abfd)->e_shstrndx = elf_shstrtab_sec (abfd);
 
   need_symtab = (bfd_get_symcount (abfd) > 0
                || (link_info == NULL
@@ -2971,21 +3095,28 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
                        == HAS_RELOC)));
   if (need_symtab)
     {
-      t->symtab_section = section_number++;
+      elf_onesymtab (abfd) = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->symtab_hdr.sh_name);
       if (section_number > ((SHN_LORESERVE - 2) & 0xFFFF))
        {
-         t->symtab_shndx_section = section_number++;
+         elf_symtab_shndx (abfd) = section_number++;
          t->symtab_shndx_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)
            return FALSE;
        }
-      t->strtab_section = section_number++;
+      elf_strtab_sec (abfd) = section_number++;
       _bfd_elf_strtab_addref (elf_shstrtab (abfd), t->strtab_hdr.sh_name);
     }
 
+  if (section_number >= SHN_LORESERVE)
+    {
+      _bfd_error_handler (_("%B: too many sections: %u"),
+                         abfd, section_number);
+      return FALSE;
+    }
+
   _bfd_elf_strtab_finalize (elf_shstrtab (abfd));
   t->shstrtab_hdr.sh_size = _bfd_elf_strtab_size (elf_shstrtab (abfd));
 
@@ -3009,17 +3140,17 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 
   elf_elfsections (abfd) = i_shdrp;
 
-  i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
+  i_shdrp[elf_shstrtab_sec (abfd)] = &t->shstrtab_hdr;
   if (need_symtab)
     {
-      i_shdrp[t->symtab_section] = &t->symtab_hdr;
+      i_shdrp[elf_onesymtab (abfd)] = &t->symtab_hdr;
       if (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF))
        {
-         i_shdrp[t->symtab_shndx_section] = &t->symtab_shndx_hdr;
-         t->symtab_shndx_hdr.sh_link = t->symtab_section;
+         i_shdrp[elf_symtab_shndx (abfd)] = &t->symtab_shndx_hdr;
+         t->symtab_shndx_hdr.sh_link = elf_onesymtab (abfd);
        }
-      i_shdrp[t->strtab_section] = &t->strtab_hdr;
-      t->symtab_hdr.sh_link = t->strtab_section;
+      i_shdrp[elf_strtab_sec (abfd)] = &t->strtab_hdr;
+      t->symtab_hdr.sh_link = elf_strtab_sec (abfd);
     }
 
   for (sec = abfd->sections; sec; sec = sec->next)
@@ -3042,13 +3173,15 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
         the relocation entries apply.  */
       if (d->rel.idx != 0)
        {
-         d->rel.hdr->sh_link = t->symtab_section;
+         d->rel.hdr->sh_link = elf_onesymtab (abfd);
          d->rel.hdr->sh_info = d->this_idx;
+         d->rel.hdr->sh_flags |= SHF_INFO_LINK;
        }
       if (d->rela.idx != 0)
        {
-         d->rela.hdr->sh_link = t->symtab_section;
+         d->rela.hdr->sh_link = elf_onesymtab (abfd);
          d->rela.hdr->sh_info = d->this_idx;
+         d->rela.hdr->sh_flags |= SHF_INFO_LINK;
        }
 
       /* We need to set up sh_link for SHF_LINK_ORDER.  */
@@ -3061,7 +3194,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
              if (link_info != NULL)
                {
                  /* Check discarded linkonce section.  */
-                 if (elf_discarded_section (s))
+                 if (discarded_section (s))
                    {
                      asection *kept;
                      (*_bfd_error_handler)
@@ -3135,7 +3268,10 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
            name += 5;
          s = bfd_get_section_by_name (abfd, name);
          if (s != NULL)
-           d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+           {
+             d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+             d->this_hdr.sh_flags |= SHF_INFO_LINK;
+           }
          break;
 
        case SHT_STRTAB:
@@ -3202,7 +3338,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
          break;
 
        case SHT_GROUP:
-         d->this_hdr.sh_link = t->symtab_section;
+         d->this_hdr.sh_link = elf_onesymtab (abfd);
        }
     }
 
@@ -3215,9 +3351,6 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
   return TRUE;
 }
 
-/* Map symbol from it's internal number to the external number, moving
-   all local symbols to be at the head of the list.  */
-
 static bfd_boolean
 sym_is_global (bfd *abfd, asymbol *sym)
 {
@@ -3232,19 +3365,31 @@ sym_is_global (bfd *abfd, asymbol *sym)
 }
 
 /* Don't output section symbols for sections that are not going to be
-   output.  */
+   output, that are duplicates or there is no BFD section.  */
 
 static bfd_boolean
 ignore_section_sym (bfd *abfd, asymbol *sym)
 {
-  return ((sym->flags & BSF_SECTION_SYM) != 0
-         && !(sym->section->owner == abfd
+  elf_symbol_type *type_ptr;
+
+  if ((sym->flags & BSF_SECTION_SYM) == 0)
+    return FALSE;
+
+  type_ptr = elf_symbol_from (abfd, sym);
+  return ((type_ptr != NULL
+          && type_ptr->internal_elf_sym.st_shndx != 0
+          && bfd_is_abs_section (sym->section))
+         || !(sym->section->owner == abfd
               || (sym->section->output_section->owner == abfd
-                  && sym->section->output_offset == 0)));
+                  && sym->section->output_offset == 0)
+              || bfd_is_abs_section (sym->section)));
 }
 
+/* Map symbol from it's internal number to the external number, moving
+   all local symbols to be at the head of the list.  */
+
 static bfd_boolean
-elf_map_symbols (bfd *abfd)
+elf_map_symbols (bfd *abfd, unsigned int *pnum_locals)
 {
   unsigned int symcount = bfd_get_symcount (abfd);
   asymbol **syms = bfd_get_outsymbols (abfd);
@@ -3284,7 +3429,8 @@ elf_map_symbols (bfd *abfd)
 
       if ((sym->flags & BSF_SECTION_SYM) != 0
          && sym->value == 0
-         && !ignore_section_sym (abfd, sym))
+         && !ignore_section_sym (abfd, sym)
+         && !bfd_is_abs_section (sym->section))
        {
          asection *sec = sym->section;
 
@@ -3298,12 +3444,10 @@ elf_map_symbols (bfd *abfd)
   /* Classify all of the symbols.  */
   for (idx = 0; idx < symcount; idx++)
     {
-      if (ignore_section_sym (abfd, syms[idx]))
-       continue;
-      if (!sym_is_global (abfd, syms[idx]))
-       num_locals++;
-      else
+      if (sym_is_global (abfd, syms[idx]))
        num_globals++;
+      else if (!ignore_section_sym (abfd, syms[idx]))
+       num_locals++;
     }
 
   /* We will be adding a section symbol for each normal BFD section.  Most
@@ -3333,12 +3477,12 @@ elf_map_symbols (bfd *abfd)
       asymbol *sym = syms[idx];
       unsigned int i;
 
-      if (ignore_section_sym (abfd, sym))
-       continue;
-      if (!sym_is_global (abfd, sym))
+      if (sym_is_global (abfd, sym))
+       i = num_locals + num_globals2++;
+      else if (!ignore_section_sym (abfd, sym))
        i = num_locals2++;
       else
-       i = num_locals + num_globals2++;
+       continue;
       new_syms[i] = sym;
       sym->udata.i = i + 1;
     }
@@ -3361,8 +3505,7 @@ elf_map_symbols (bfd *abfd)
 
   bfd_set_symtab (abfd, new_syms, num_locals + num_globals);
 
-  elf_num_locals (abfd) = num_locals;
-  elf_num_globals (abfd) = num_globals;
+  *pnum_locals = num_locals;
   return TRUE;
 }
 
@@ -3419,8 +3562,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
     return FALSE;
 
   /* Post process the headers if necessary.  */
-  if (bed->elf_backend_post_process_headers)
-    (*bed->elf_backend_post_process_headers) (abfd, link_info);
+  (*bed->elf_backend_post_process_headers) (abfd, link_info);
 
   fsargs.failed = FALSE;
   fsargs.link_info = link_info;
@@ -3473,7 +3615,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
       file_ptr off;
       Elf_Internal_Shdr *hdr;
 
-      off = elf_tdata (abfd)->next_file_pos;
+      off = elf_next_file_pos (abfd);
 
       hdr = &elf_tdata (abfd)->symtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -3485,7 +3627,7 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
       hdr = &elf_tdata (abfd)->strtab_hdr;
       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
-      elf_tdata (abfd)->next_file_pos = off;
+      elf_next_file_pos (abfd) = off;
 
       /* Now that we know where the .strtab section goes, write it
         out.  */
@@ -3536,13 +3678,13 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
       ++segs;
     }
 
-  if (elf_tdata (abfd)->eh_frame_hdr)
+  if (elf_eh_frame_hdr (abfd))
     {
       /* We need a PT_GNU_EH_FRAME segment.  */
       ++segs;
     }
 
-  if (elf_tdata (abfd)->stack_flags)
+  if (elf_stack_flags (abfd))
     {
       /* We need a PT_GNU_STACK segment.  */
       ++segs;
@@ -3604,8 +3746,7 @@ _bfd_elf_find_segment_containing_section (bfd * abfd, asection * section)
   struct elf_segment_map *m;
   Elf_Internal_Phdr *p;
 
-  for (m = elf_tdata (abfd)->segment_map,
-        p = elf_tdata (abfd)->phdr;
+  for (m = elf_seg_map (abfd), p = elf_tdata (abfd)->phdr;
        m != NULL;
        m = m->next, p++)
     {
@@ -3689,7 +3830,7 @@ elf_modify_segment_map (bfd *abfd,
      sections from the segment map.  We also remove excluded
      sections.  Finally, any PT_LOAD segment without sections is
      removed.  */
-  m = &elf_tdata (abfd)->segment_map;
+  m = &elf_seg_map (abfd);
   while (*m)
     {
       unsigned int i, new_count;
@@ -3733,7 +3874,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   bfd_boolean no_user_phdrs;
 
-  no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
+  no_user_phdrs = elf_seg_map (abfd) == NULL;
+
+  if (info != NULL)
+    info->user_phdrs = !no_user_phdrs;
+
   if (no_user_phdrs && bfd_count_sections (abfd) != 0)
     {
       asection *s;
@@ -3840,10 +3985,11 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
         program headers we will need.  */
       if (count > 0)
        {
-         bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+         bfd_size_type phdr_size = elf_program_header_size (abfd);
 
          if (phdr_size == (bfd_size_type) -1)
            phdr_size = get_program_header_size (abfd, info);
+         phdr_size += bed->s->sizeof_ehdr;
          if ((abfd->flags & D_PAGED) == 0
              || (sections[0]->lma & addr_mask) < phdr_size
              || ((sections[0]->lma & addr_mask) % maxpagesize
@@ -3979,8 +4125,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          phdr_in_segment = FALSE;
        }
 
-      /* Create a final PT_LOAD program segment.  */
-      if (last_hdr != NULL)
+      /* Create a final PT_LOAD program segment, but not if it's just
+        for .tbss.  */
+      if (last_hdr != NULL
+         && (i - phdr_index != 1
+             || ((last_hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+                 != SEC_THREAD_LOCAL)))
        {
          m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
          if (m == NULL)
@@ -4067,11 +4217,31 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          /* Mandated PF_R.  */
          m->p_flags = PF_R;
          m->p_flags_valid = 1;
+         s = first_tls;
          for (i = 0; i < (unsigned int) tls_count; ++i)
            {
-             BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
-             m->sections[i] = first_tls;
-             first_tls = first_tls->next;
+             if ((s->flags & SEC_THREAD_LOCAL) == 0)
+               {
+                 _bfd_error_handler
+                   (_("%B: TLS sections are not adjacent:"), abfd);
+                 s = first_tls;
+                 i = 0;
+                 while (i < (unsigned int) tls_count)
+                   {
+                     if ((s->flags & SEC_THREAD_LOCAL) != 0)
+                       {
+                         _bfd_error_handler (_("           TLS: %A"), s);
+                         i++;
+                       }
+                     else
+                       _bfd_error_handler (_(" non-TLS: %A"), s);
+                     s = s->next;
+                   }
+                 bfd_set_error (bfd_error_bad_value);
+                 goto error_return;
+               }
+             m->sections[i] = s;
+             s = s->next;
            }
 
          *pm = m;
@@ -4080,7 +4250,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
 
       /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
         segment.  */
-      eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
+      eh_frame_hdr = elf_eh_frame_hdr (abfd);
       if (eh_frame_hdr != NULL
          && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
        {
@@ -4097,7 +4267,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          pm = &m->next;
        }
 
-      if (elf_tdata (abfd)->stack_flags)
+      if (elf_stack_flags (abfd))
        {
          amt = sizeof (struct elf_segment_map);
          m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -4105,8 +4275,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
            goto error_return;
          m->next = NULL;
          m->p_type = PT_GNU_STACK;
-         m->p_flags = elf_tdata (abfd)->stack_flags;
+         m->p_flags = elf_stack_flags (abfd);
+         m->p_align = bed->stack_align;
          m->p_flags_valid = 1;
+         m->p_align_valid = m->p_align != 0;
+         if (info->stacksize > 0)
+           {
+             m->p_size = info->stacksize;
+             m->p_size_valid = 1;
+           }
 
          *pm = m;
          pm = &m->next;
@@ -4116,18 +4293,21 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
        {
          for (m = mfirst; m != NULL; m = m->next)
            {
-             if (m->p_type == PT_LOAD)
+             if (m->p_type == PT_LOAD
+                 && m->count != 0
+                 && m->sections[0]->vma >= info->relro_start
+                 && m->sections[0]->vma < info->relro_end)
                {
-                 asection *last = m->sections[m->count - 1];
-                 bfd_vma vaddr = m->sections[0]->vma;
-                 bfd_vma filesz = last->vma - vaddr + last->size;
+                 i = m->count;
+                 while (--i != (unsigned) -1)
+                   if ((m->sections[i]->flags & (SEC_LOAD | SEC_HAS_CONTENTS))
+                       == (SEC_LOAD | SEC_HAS_CONTENTS))
+                     break;
 
-                 if (vaddr < info->relro_end
-                     && vaddr >= info->relro_start
-                     && (vaddr + filesz) >= info->relro_end)
+                 if (i != (unsigned) -1)
                    break;
                }
-             }
+           }
 
          /* Make a PT_GNU_RELRO segment only when it isn't empty.  */
          if (m != NULL)
@@ -4147,15 +4327,15 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
        }
 
       free (sections);
-      elf_tdata (abfd)->segment_map = mfirst;
+      elf_seg_map (abfd) = mfirst;
     }
 
   if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
     return FALSE;
 
-  for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+  for (count = 0, m = elf_seg_map (abfd); m != NULL; m = m->next)
     ++count;
-  elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr;
+  elf_program_header_size (abfd) = count * bed->s->sizeof_phdr;
 
   return TRUE;
 
@@ -4249,6 +4429,9 @@ elf_sort_sections (const void *arg1, const void *arg2)
 static file_ptr
 vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
 {
+  /* PR binutils/16199: Handle an alignment of zero.  */
+  if (maxpagesize == 0)
+    maxpagesize = 1;
   return ((vma - off) % maxpagesize);
 }
 
@@ -4272,10 +4455,12 @@ print_segment_map (const struct elf_segment_map *m)
                  (unsigned int) m->p_type);
       pt = buf;
     }
+  fflush (stdout);
   fprintf (stderr, "%s:", pt);
   for (j = 0; j < m->count; j++)
     fprintf (stderr, " %s", m->sections [j]->name);
   putc ('\n',stderr);
+  fflush (stderr);
 }
 
 static bfd_boolean
@@ -4317,43 +4502,53 @@ assign_file_positions_for_load_sections (bfd *abfd,
     return FALSE;
 
   alloc = 0;
-  for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+  for (m = elf_seg_map (abfd); m != NULL; m = m->next)
     {
       ++alloc;
       if (m->header_size)
        header_pad = m->header_size;
     }
 
-  elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
-  elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+  if (alloc)
+    {
+      elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
+      elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+    }
+  else
+    {
+      /* PR binutils/12467.  */
+      elf_elfheader (abfd)->e_phoff = 0;
+      elf_elfheader (abfd)->e_phentsize = 0;
+    }
+
   elf_elfheader (abfd)->e_phnum = alloc;
 
-  if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
-    elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
+  if (elf_program_header_size (abfd) == (bfd_size_type) -1)
+    elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
   else
-    BFD_ASSERT (elf_tdata (abfd)->program_header_size
+    BFD_ASSERT (elf_program_header_size (abfd)
                >= alloc * bed->s->sizeof_phdr);
 
   if (alloc == 0)
     {
-      elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
+      elf_next_file_pos (abfd) = bed->s->sizeof_ehdr;
       return TRUE;
     }
 
-  /* We're writing the size in elf_tdata (abfd)->program_header_size,
+  /* We're writing the size in elf_program_header_size (abfd),
      see assign_file_positions_except_relocs, so make sure we have
      that amount allocated, with trailing space cleared.
-     The variable alloc contains the computed need, while elf_tdata
-     (abfd)->program_header_size contains the size used for the
+     The variable alloc contains the computed need, while
+     elf_program_header_size (abfd) contains the size used for the
      layout.
      See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
      where the layout is forced to according to a larger size in the
      last iterations for the testcase ld-elf/header.  */
-  BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
+  BFD_ASSERT (elf_program_header_size (abfd) % bed->s->sizeof_phdr
              == 0);
   phdrs = (Elf_Internal_Phdr *)
      bfd_zalloc2 (abfd,
-                  (elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr),
+                  (elf_program_header_size (abfd) / bed->s->sizeof_phdr),
                   sizeof (Elf_Internal_Phdr));
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
@@ -4371,7 +4566,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
     header_pad -= off;
   off += header_pad;
 
-  for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
+  for (m = elf_seg_map (abfd), p = phdrs, j = 0;
        m != NULL;
        m = m->next, p++, j++)
     {
@@ -4520,8 +4715,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
          p->p_memsz = bed->s->sizeof_ehdr;
          if (m->count > 0)
            {
-             BFD_ASSERT (p->p_type == PT_LOAD);
-
              if (p->p_vaddr < (bfd_vma) off)
                {
                  (*_bfd_error_handler)
@@ -4548,7 +4741,6 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
              if (m->count > 0)
                {
-                 BFD_ASSERT (p->p_type == PT_LOAD);
                  p->p_vaddr -= off - p->p_offset;
                  if (!m->p_paddr_valid)
                    p->p_paddr -= off - p->p_offset;
@@ -4664,6 +4856,21 @@ assign_file_positions_for_load_sections (bfd *abfd,
                  if (this_hdr->sh_type != SHT_NOBITS)
                    off += this_hdr->sh_size;
                }
+             else if (this_hdr->sh_type == SHT_NOBITS
+                      && (this_hdr->sh_flags & SHF_TLS) != 0
+                      && this_hdr->sh_offset == 0)
+               {
+                 /* This is a .tbss section that didn't get a PT_LOAD.
+                    (See _bfd_elf_map_sections_to_segments "Create a
+                    final PT_LOAD".)  Set sh_offset to the value it
+                    would have if we had created a zero p_filesz and
+                    p_memsz PT_LOAD header for the section.  This
+                    also makes the PT_TLS header have the same
+                    p_offset value.  */
+                 bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr,
+                                                         off, align);
+                 this_hdr->sh_offset = sec->filepos = off + adjust;
+               }
 
              if (this_hdr->sh_type != SHT_NOBITS)
                {
@@ -4701,6 +4908,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
                p->p_flags |= PF_W;
            }
        }
+
       off -= off_adjust;
 
       /* Check that all sections are in a PT_LOAD segment.
@@ -4728,7 +4936,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
              sec = m->sections[i];
              this_hdr = &(elf_section_data(sec)->this_hdr);
-             if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0))
+             if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)
+                 && !ELF_TBSS_SPECIAL (this_hdr, p))
                {
                  (*_bfd_error_handler)
                    (_("%B: section `%A' can't be allocated in segment %d"),
@@ -4739,7 +4948,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
        }
     }
 
-  elf_tdata (abfd)->next_file_pos = off;
+  elf_next_file_pos (abfd) = off;
   return TRUE;
 }
 
@@ -4755,6 +4964,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
   Elf_Internal_Phdr *phdrs;
   Elf_Internal_Phdr *p;
   struct elf_segment_map *m;
+  struct elf_segment_map *hdrs_segment;
   bfd_vma filehdr_vaddr, filehdr_paddr;
   bfd_vma phdrs_vaddr, phdrs_paddr;
   file_ptr off;
@@ -4764,10 +4974,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
 
   i_shdrpp = elf_elfsections (abfd);
   num_sec = elf_numsections (abfd);
-  off = elf_tdata (abfd)->next_file_pos;
+  off = elf_next_file_pos (abfd);
   for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
     {
-      struct elf_obj_tdata *tdata = elf_tdata (abfd);
       Elf_Internal_Shdr *hdr;
 
       hdr = *hdrpp;
@@ -4778,12 +4987,13 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        BFD_ASSERT (hdr->sh_offset == hdr->bfd_section->filepos);
       else if ((hdr->sh_flags & SHF_ALLOC) != 0)
        {
-         (*_bfd_error_handler)
-           (_("%B: warning: allocated section `%s' not in segment"),
-            abfd,
-            (hdr->bfd_section == NULL
-             ? "*unknown*"
-             : hdr->bfd_section->name));
+         if (hdr->sh_size != 0)
+           (*_bfd_error_handler)
+             (_("%B: warning: allocated section `%s' not in segment"),
+              abfd,
+              (hdr->bfd_section == NULL
+               ? "*unknown*"
+               : hdr->bfd_section->name));
          /* We don't need to page align empty sections.  */
          if ((abfd->flags & D_PAGED) != 0 && hdr->sh_size != 0)
            off += vma_page_aligned_bias (hdr->sh_addr, off,
@@ -4796,9 +5006,9 @@ 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 == i_shdrpp[tdata->symtab_section]
-              || hdr == i_shdrpp[tdata->symtab_shndx_section]
-              || hdr == i_shdrpp[tdata->strtab_section])
+              || hdr == i_shdrpp[elf_onesymtab (abfd)]
+              || hdr == i_shdrpp[elf_symtab_shndx (abfd)]
+              || hdr == i_shdrpp[elf_strtab_sec (abfd)])
        hdr->sh_offset = -1;
       else
        off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
@@ -4811,10 +5021,9 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
   filehdr_paddr = 0;
   phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
   phdrs_paddr = 0;
+  hdrs_segment = NULL;
   phdrs = elf_tdata (abfd)->phdr;
-  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
-       m != NULL;
-       m = m->next, p++)
+  for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
     {
       ++count;
       if (p->p_type != PT_LOAD)
@@ -4831,34 +5040,82 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
          phdrs_paddr = p->p_paddr;
          if (m->includes_filehdr)
            {
+             hdrs_segment = m;
              phdrs_vaddr += bed->s->sizeof_ehdr;
              phdrs_paddr += bed->s->sizeof_ehdr;
            }
        }
     }
 
-  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
-       m != NULL;
-       m = m->next, p++)
+  if (hdrs_segment != NULL && link_info != NULL)
+    {
+      /* There is a segment that contains both the file headers and the
+        program headers, so provide a symbol __ehdr_start pointing there.
+        A program can use this to examine itself robustly.  */
+
+      struct elf_link_hash_entry *hash
+       = elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
+                               FALSE, FALSE, TRUE);
+      /* If the symbol was referenced and not defined, define it.  */
+      if (hash != NULL
+         && (hash->root.type == bfd_link_hash_new
+             || hash->root.type == bfd_link_hash_undefined
+             || hash->root.type == bfd_link_hash_undefweak
+             || hash->root.type == bfd_link_hash_common))
+       {
+         asection *s = NULL;
+         if (hdrs_segment->count != 0)
+           /* The segment contains sections, so use the first one.  */
+           s = hdrs_segment->sections[0];
+         else
+           /* Use the first (i.e. lowest-addressed) section in any segment.  */
+           for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+             if (m->count != 0)
+               {
+                 s = m->sections[0];
+                 break;
+               }
+
+         if (s != NULL)
+           {
+             hash->root.u.def.value = filehdr_vaddr - s->vma;
+             hash->root.u.def.section = s;
+           }
+         else
+           {
+             hash->root.u.def.value = filehdr_vaddr;
+             hash->root.u.def.section = bfd_abs_section_ptr;
+           }
+
+         hash->root.type = bfd_link_hash_defined;
+         hash->def_regular = 1;
+         hash->non_elf = 0;
+       }
+    }
+
+  for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
     {
       if (p->p_type == PT_GNU_RELRO)
        {
          const Elf_Internal_Phdr *lp;
-
-         BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+         struct elf_segment_map *lm;
 
          if (link_info != NULL)
            {
              /* During linking the range of the RELRO segment is passed
                 in link_info.  */
-             for (lp = phdrs; lp < phdrs + count; ++lp)
+             for (lm = elf_seg_map (abfd), lp = phdrs;
+                  lm != NULL;
+                  lm = lm->next, lp++)
                {
                  if (lp->p_type == PT_LOAD
-                     && lp->p_vaddr >= link_info->relro_start
                      && lp->p_vaddr < link_info->relro_end
-                     && lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
+                     && lm->count != 0
+                     && lm->sections[0]->vma >= link_info->relro_start)
                    break;
                }
+
+             BFD_ASSERT (lm != NULL);
            }
          else
            {
@@ -4884,8 +5141,15 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              else
                abort ();
              p->p_memsz = p->p_filesz;
-             p->p_align = 1;
-             p->p_flags = (lp->p_flags & ~PF_W);
+             /* Preserve the alignment and flags if they are valid. The
+                gold linker generates RW/4 for the PT_GNU_RELRO section.
+                It is better for objcopy/strip to honor these attributes
+                otherwise gdb will choke when using separate debug files.
+              */
+             if (!m->p_align_valid)
+               p->p_align = 1;
+             if (!m->p_flags_valid)
+               p->p_flags = (lp->p_flags & ~PF_W);
            }
          else
            {
@@ -4893,23 +5157,32 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              p->p_type = PT_NULL;
            }
        }
+      else if (p->p_type == PT_GNU_STACK)
+       {
+         if (m->p_size_valid)
+           p->p_memsz = m->p_size;
+       }
       else if (m->count != 0)
        {
          if (p->p_type != PT_LOAD
              && (p->p_type != PT_NOTE
                  || bfd_get_format (abfd) != bfd_core))
            {
-             Elf_Internal_Shdr *hdr;
-             asection *sect;
-
              BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
 
-             sect = m->sections[m->count - 1];
-             hdr = &elf_section_data (sect)->this_hdr;
-             p->p_filesz = sect->filepos - m->sections[0]->filepos;
-             if (hdr->sh_type != SHT_NOBITS)
-               p->p_filesz += hdr->sh_size;
+             p->p_filesz = 0;
              p->p_offset = m->sections[0]->filepos;
+             for (i = m->count; i-- != 0;)
+               {
+                 asection *sect = m->sections[i];
+                 Elf_Internal_Shdr *hdr = &elf_section_data (sect)->this_hdr;
+                 if (hdr->sh_type != SHT_NOBITS)
+                   {
+                     p->p_filesz = (sect->filepos - m->sections[0]->filepos
+                                    + hdr->sh_size);
+                     break;
+                   }
+               }
            }
        }
       else if (m->includes_filehdr)
@@ -4926,7 +5199,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        }
     }
 
-  elf_tdata (abfd)->next_file_pos = off;
+  elf_next_file_pos (abfd) = off;
 
   return TRUE;
 }
@@ -4951,7 +5224,6 @@ assign_file_positions_except_relocs (bfd *abfd,
 {
   struct elf_obj_tdata *tdata = elf_tdata (abfd);
   Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
-  file_ptr off;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
@@ -4961,6 +5233,7 @@ assign_file_positions_except_relocs (bfd *abfd,
       unsigned int num_sec = elf_numsections (abfd);
       Elf_Internal_Shdr **hdrpp;
       unsigned int i;
+      file_ptr off;
 
       /* Start after the ELF header.  */
       off = i_ehdrp->e_ehsize;
@@ -4975,15 +5248,17 @@ assign_file_positions_except_relocs (bfd *abfd,
          hdr = *hdrpp;
          if (((hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
               && hdr->bfd_section == NULL)
-             || i == tdata->symtab_section
-             || i == tdata->symtab_shndx_section
-             || i == tdata->strtab_section)
+             || i == elf_onesymtab (abfd)
+             || i == elf_symtab_shndx (abfd)
+             || i == elf_strtab_sec (abfd))
            {
              hdr->sh_offset = -1;
            }
          else
            off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
        }
+
+      elf_next_file_pos (abfd) = off;
     }
   else
     {
@@ -5004,22 +5279,34 @@ assign_file_positions_except_relocs (bfd *abfd,
            return FALSE;
        }
 
+      /* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=.  */
+      if (link_info != NULL
+         && link_info->executable
+         && link_info->shared)
+       {
+         unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
+         Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
+         Elf_Internal_Phdr *end_segment = &segment[num_segments];
+
+         /* Find the lowest p_vaddr in PT_LOAD segments.  */
+         bfd_vma p_vaddr = (bfd_vma) -1;
+         for (; segment < end_segment; segment++)
+           if (segment->p_type == PT_LOAD && p_vaddr > segment->p_vaddr)
+             p_vaddr = segment->p_vaddr;
+
+         /* Set e_type to ET_EXEC if the lowest p_vaddr in PT_LOAD
+            segments is non-zero.  */
+         if (p_vaddr)
+           i_ehdrp->e_type = ET_EXEC;
+       }
+
       /* Write out the program headers.  */
-      alloc = tdata->program_header_size / bed->s->sizeof_phdr;
+      alloc = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
       if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
          || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
        return FALSE;
-
-      off = tdata->next_file_pos;
     }
 
-  /* Place the section headers.  */
-  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;
-
-  tdata->next_file_pos = off;
-
   return TRUE;
 }
 
@@ -5104,7 +5391,7 @@ prep_headers (bfd *abfd)
   elf_tdata (abfd)->shstrtab_hdr.sh_name =
     (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", FALSE);
   if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
-      || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
+      || elf_tdata (abfd)->strtab_hdr.sh_name == (unsigned int) -1
       || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
     return FALSE;
 
@@ -5112,16 +5399,18 @@ prep_headers (bfd *abfd)
 }
 
 /* Assign file positions for all the reloc sections which are not part
-   of the loadable file image.  */
+   of the loadable file image, and the file position of section headers.  */
 
-void
+static void
 _bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
 {
   file_ptr off;
   unsigned int i, num_sec;
   Elf_Internal_Shdr **shdrpp;
+  Elf_Internal_Ehdr *i_ehdrp;
+  const struct elf_backend_data *bed;
 
-  off = elf_tdata (abfd)->next_file_pos;
+  off = elf_next_file_pos (abfd);
 
   num_sec = elf_numsections (abfd);
   for (i = 1, shdrpp = elf_elfsections (abfd) + 1; i < num_sec; i++, shdrpp++)
@@ -5134,7 +5423,13 @@ _bfd_elf_assign_file_positions_for_relocs (bfd *abfd)
        off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
     }
 
-  elf_tdata (abfd)->next_file_pos = off;
+/* 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;
 }
 
 bfd_boolean
@@ -5144,6 +5439,7 @@ _bfd_elf_write_object_contents (bfd *abfd)
   Elf_Internal_Shdr **i_shdrp;
   bfd_boolean failed;
   unsigned int count, num_sec;
+  struct elf_obj_tdata *t;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
@@ -5175,21 +5471,21 @@ _bfd_elf_write_object_contents (bfd *abfd)
     }
 
   /* Write out the section header names.  */
+  t = elf_tdata (abfd);
   if (elf_shstrtab (abfd) != NULL
-      && (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
+      && (bfd_seek (abfd, t->shstrtab_hdr.sh_offset, SEEK_SET) != 0
          || !_bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd))))
     return FALSE;
 
   if (bed->elf_backend_final_write_processing)
-    (*bed->elf_backend_final_write_processing) (abfd,
-                                               elf_tdata (abfd)->linker);
+    (*bed->elf_backend_final_write_processing) (abfd, elf_linker (abfd));
 
   if (!bed->s->write_shdrs_and_ehdr (abfd))
     return FALSE;
 
   /* This is last since write_shdrs_and_ehdr can touch i_shdrp[0].  */
-  if (elf_tdata (abfd)->after_write_object_contents)
-    return (*elf_tdata (abfd)->after_write_object_contents) (abfd);
+  if (t->o->build_id.after_write_object_contents != NULL)
+    return (*t->o->build_id.after_write_object_contents) (abfd);
 
   return TRUE;
 }
@@ -5381,7 +5677,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
        1. It is within the address space of the segment -- we use the LMA
          if that is set for the segment and the VMA otherwise,
        2. It is an allocated section or a NOTE section in a PT_NOTE
-         segment.         
+         segment.
        3. There is an output section associated with it,
        4. The section has not already been allocated to a previous segment.
        5. PT_GNU_STACK segments do not include any sections.
@@ -5898,7 +6194,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                 and carry on looping.  */
              amt = sizeof (struct elf_segment_map);
              amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
-             map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
+             map = (struct elf_segment_map *) bfd_zalloc (obfd, amt);
              if (map == NULL)
                {
                  free (sections);
@@ -5923,7 +6219,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
       free (sections);
     }
 
-  elf_tdata (obfd)->segment_map = map_first;
+  elf_seg_map (obfd) = map_first;
 
   /* If we had to estimate the number of program headers that were
      going to be needed, then check our estimate now and adjust
@@ -6033,12 +6329,15 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       map->p_align_valid = 1;
       map->p_vaddr_offset = 0;
 
-      if (map->p_type == PT_GNU_RELRO)
+      if (map->p_type == PT_GNU_RELRO
+         || map->p_type == PT_GNU_STACK)
        {
          /* The PT_GNU_RELRO segment may contain the first a few
             bytes in the .got.plt section even if the whole .got.plt
             section isn't in the PT_GNU_RELRO segment.  We won't
-            change the size of the PT_GNU_RELRO segment.  */
+            change the size of the PT_GNU_RELRO segment.
+            Similarly, PT_GNU_STACK size is significant on uclinux
+            systems.    */
          map->p_size = segment->p_memsz;
          map->p_size_valid = 1;
        }
@@ -6061,7 +6360,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            phdr_included = TRUE;
        }
 
-      lowest_section = first_section;
+      lowest_section = NULL;
       if (section_count != 0)
        {
          unsigned int isec = 0;
@@ -6074,12 +6373,14 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
              if (ELF_SECTION_IN_SEGMENT (this_hdr, segment))
                {
                  map->sections[isec++] = section->output_section;
-                 if (section->lma < lowest_section->lma)
-                   lowest_section = section;
                  if ((section->flags & SEC_ALLOC) != 0)
                    {
                      bfd_vma seg_off;
 
+                     if (lowest_section == NULL
+                         || section->lma < lowest_section->lma)
+                       lowest_section = section;
+
                      /* Section lmas are set up from PT_LOAD header
                         p_paddr in _bfd_elf_make_section_from_shdr.
                         If this header has a p_paddr that disagrees
@@ -6101,7 +6402,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       if (map->includes_filehdr && lowest_section != NULL)
        /* We need to keep the space used by the headers fixed.  */
        map->header_size = lowest_section->vma - segment->p_vaddr;
-      
+
       if (!map->includes_phdrs
          && !map->includes_filehdr
          && map->p_paddr_valid)
@@ -6114,7 +6415,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       pointer_to_map = &map->next;
     }
 
-  elf_tdata (obfd)->segment_map = map_first;
+  elf_seg_map (obfd) = map_first;
   return TRUE;
 }
 
@@ -6208,6 +6509,26 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd)
     }
 
 rewrite:
+  if (ibfd->xvec == obfd->xvec)
+    {
+      /* When rewriting program header, set the output maxpagesize to
+        the maximum alignment of input PT_LOAD segments.  */
+      Elf_Internal_Phdr *segment;
+      unsigned int i;
+      unsigned int num_segments = elf_elfheader (ibfd)->e_phnum;
+      bfd_vma maxpagesize = 0;
+
+      for (i = 0, segment = elf_tdata (ibfd)->phdr;
+          i < num_segments;
+          i++, segment++)
+       if (segment->p_type == PT_LOAD
+           && maxpagesize < segment->p_align)
+         maxpagesize = segment->p_align;
+
+      if (maxpagesize != get_elf_backend_data (obfd)->maxpagesize)
+       bfd_emul_set_maxpagesize (bfd_get_target (obfd), maxpagesize);
+    }
+
   return rewrite_elf_program_header (ibfd, obfd);
 }
 
@@ -6228,6 +6549,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
       || obfd->xvec->flavour != bfd_target_elf_flavour)
     return TRUE;
 
+  BFD_ASSERT (elf_section_data (osec) != NULL);
+
   /* For objcopy and relocatable link, don't copy the output ELF
      section type from input if the output BFD section flags have been
      set to something different.  For a final link allow some flags
@@ -6383,7 +6706,7 @@ _bfd_elf_copy_private_header_data (bfd *ibfd, bfd *obfd)
      entry point, because the latter is called after the section
      contents have been set, which means that the program headers have
      already been worked out.  */
-  if (elf_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
+  if (elf_seg_map (obfd) == NULL && elf_tdata (ibfd)->phdr != NULL)
     {
       if (! copy_private_bfd_data (ibfd, obfd))
        return FALSE;
@@ -6431,11 +6754,11 @@ _bfd_elf_copy_private_symbol_data (bfd *ibfd,
        shndx = MAP_ONESYMTAB;
       else if (shndx == elf_dynsymtab (ibfd))
        shndx = MAP_DYNSYMTAB;
-      else if (shndx == elf_tdata (ibfd)->strtab_section)
+      else if (shndx == elf_strtab_sec (ibfd))
        shndx = MAP_STRTAB;
-      else if (shndx == elf_tdata (ibfd)->shstrtab_section)
+      else if (shndx == elf_shstrtab_sec (ibfd))
        shndx = MAP_SHSTRTAB;
-      else if (shndx == elf_tdata (ibfd)->symtab_shndx_section)
+      else if (shndx == elf_symtab_shndx (ibfd))
        shndx = MAP_SYM_SHNDX;
       osym->internal_elf_sym.st_shndx = shndx;
     }
@@ -6460,10 +6783,11 @@ swap_out_syms (bfd *abfd,
   bfd_byte *outbound_syms;
   bfd_byte *outbound_shndx;
   int idx;
+  unsigned int num_locals;
   bfd_size_type amt;
   bfd_boolean name_local_sections;
 
-  if (!elf_map_symbols (abfd))
+  if (!elf_map_symbols (abfd, &num_locals))
     return FALSE;
 
   /* Dump out the symtabs.  */
@@ -6477,7 +6801,7 @@ swap_out_syms (bfd *abfd,
   symtab_hdr->sh_type = SHT_SYMTAB;
   symtab_hdr->sh_entsize = bed->s->sizeof_sym;
   symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
-  symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
+  symtab_hdr->sh_info = num_locals + 1;
   symtab_hdr->sh_addralign = (bfd_vma) 1 << bed->s->log_file_align;
 
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
@@ -6522,6 +6846,7 @@ swap_out_syms (bfd *abfd,
     sym.st_info = 0;
     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;
     if (outbound_shndx != NULL)
@@ -6610,15 +6935,16 @@ swap_out_syms (bfd *abfd,
                  shndx = elf_dynsymtab (abfd);
                  break;
                case MAP_STRTAB:
-                 shndx = elf_tdata (abfd)->strtab_section;
+                 shndx = elf_strtab_sec (abfd);
                  break;
                case MAP_SHSTRTAB:
-                 shndx = elf_tdata (abfd)->shstrtab_section;
+                 shndx = elf_shstrtab_sec (abfd);
                  break;
                case MAP_SYM_SHNDX:
-                 shndx = elf_tdata (abfd)->symtab_shndx_section;
+                 shndx = elf_symtab_shndx (abfd);
                  break;
                default:
+                 shndx = SHN_ABS;
                  break;
                }
            }
@@ -6721,9 +7047,16 @@ Unable to find equivalent output section for symbol '%s' from section '%s'"),
        }
 
       if (type_ptr != NULL)
-       sym.st_other = type_ptr->internal_elf_sym.st_other;
+       {
+         sym.st_other = type_ptr->internal_elf_sym.st_other;
+         sym.st_target_internal
+           = type_ptr->internal_elf_sym.st_target_internal;
+       }
       else
-       sym.st_other = 0;
+       {
+         sym.st_other = 0;
+         sym.st_target_internal = 0;
+       }
 
       bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
       outbound_syms += bed->s->sizeof_sym;
@@ -7204,7 +7537,7 @@ error_return_verdef:
       Elf_Internal_Verdef *iverdef;
       Elf_Internal_Verdaux *iverdaux;
 
-      iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];;
+      iverdef = &elf_tdata (abfd)->verdef[freeidx - 1];
 
       iverdef->vd_version = VER_DEF_CURRENT;
       iverdef->vd_flags = 0;
@@ -7316,77 +7649,100 @@ _bfd_elf_set_arch_mach (bfd *abfd,
 
 static bfd_boolean
 elf_find_function (bfd *abfd,
-                  asection *section,
                   asymbol **symbols,
+                  asection *section,
                   bfd_vma offset,
                   const char **filename_ptr,
                   const char **functionname_ptr)
 {
-  const char *filename;
-  asymbol *func, *file;
-  bfd_vma low_func;
-  asymbol **p;
-  /* ??? Given multiple file symbols, it is impossible to reliably
-     choose the right file name for global symbols.  File symbols are
-     local symbols, and thus all file symbols must sort before any
-     global symbols.  The ELF spec may be interpreted to say that a
-     file symbol must sort before other local symbols, but currently
-     ld -r doesn't do this.  So, for ld -r output, it is possible to
-     make a better choice of file name for local symbols by ignoring
-     file symbols appearing after a given local symbol.  */
-  enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  struct elf_find_function_cache
+  {
+    asection *last_section;
+    asymbol *func;
+    const char *filename;
+    bfd_size_type func_size;
+  } *cache;
 
-  filename = NULL;
-  func = NULL;
-  file = NULL;
-  low_func = 0;
-  state = nothing_seen;
+  if (symbols == NULL)
+    return FALSE;
 
-  for (p = symbols; *p != NULL; p++)
+  cache = elf_tdata (abfd)->elf_find_function_cache;
+  if (cache == NULL)
     {
-      elf_symbol_type *q;
-      unsigned int type;
-
-      q = (elf_symbol_type *) *p;
+      cache = bfd_zalloc (abfd, sizeof (*cache));
+      elf_tdata (abfd)->elf_find_function_cache = cache;
+      if (cache == NULL)
+       return FALSE;
+    }
+  if (cache->last_section != section
+      || cache->func == NULL
+      || offset < cache->func->value
+      || offset >= cache->func->value + cache->func_size)
+    {
+      asymbol *file;
+      bfd_vma low_func;
+      asymbol **p;
+      /* ??? Given multiple file symbols, it is impossible to reliably
+        choose the right file name for global symbols.  File symbols are
+        local symbols, and thus all file symbols must sort before any
+        global symbols.  The ELF spec may be interpreted to say that a
+        file symbol must sort before other local symbols, but currently
+        ld -r doesn't do this.  So, for ld -r output, it is possible to
+        make a better choice of file name for local symbols by ignoring
+        file symbols appearing after a given local symbol.  */
+      enum { nothing_seen, symbol_seen, file_after_symbol_seen } state;
+      const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+      file = NULL;
+      low_func = 0;
+      state = nothing_seen;
+      cache->filename = NULL;
+      cache->func = NULL;
+      cache->func_size = 0;
+      cache->last_section = section;
+
+      for (p = symbols; *p != NULL; p++)
+       {
+         asymbol *sym = *p;
+         bfd_vma code_off;
+         bfd_size_type size;
+
+         if ((sym->flags & BSF_FILE) != 0)
+           {
+             file = sym;
+             if (state == symbol_seen)
+               state = file_after_symbol_seen;
+             continue;
+           }
 
-      type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
-      switch (type)
-       {
-       case STT_FILE:
-         file = &q->symbol;
-         if (state == symbol_seen)
-           state = file_after_symbol_seen;
-         continue;
-       default:
-         if (!bed->is_function_type (type))
-           break;
-       case STT_NOTYPE:
-         if (bfd_get_section (&q->symbol) == section
-             && q->symbol.value >= low_func
-             && q->symbol.value <= offset)
+         size = bed->maybe_function_sym (sym, section, &code_off);
+         if (size != 0
+             && code_off <= offset
+             && (code_off > low_func
+                 || (code_off == low_func
+                     && size > cache->func_size)))
            {
-             func = (asymbol *) q;
-             low_func = q->symbol.value;
-             filename = NULL;
+             cache->func = sym;
+             cache->func_size = size;
+             cache->filename = NULL;
+             low_func = code_off;
              if (file != NULL
-                 && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
+                 && ((sym->flags & BSF_LOCAL) != 0
                      || state != file_after_symbol_seen))
-               filename = bfd_asymbol_name (file);
+               cache->filename = bfd_asymbol_name (file);
            }
-         break;
+         if (state == nothing_seen)
+           state = symbol_seen;
        }
-      if (state == nothing_seen)
-       state = symbol_seen;
     }
 
-  if (func == NULL)
+  if (cache->func == NULL)
     return FALSE;
 
   if (filename_ptr)
-    *filename_ptr = filename;
+    *filename_ptr = cache->filename;
   if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (func);
+    *functionname_ptr = bfd_asymbol_name (cache->func);
 
   return TRUE;
 }
@@ -7396,34 +7752,35 @@ elf_find_function (bfd *abfd,
 
 bfd_boolean
 _bfd_elf_find_nearest_line (bfd *abfd,
-                           asection *section,
                            asymbol **symbols,
+                           asection *section,
                            bfd_vma offset,
                            const char **filename_ptr,
                            const char **functionname_ptr,
-                           unsigned int *line_ptr)
+                           unsigned int *line_ptr,
+                           unsigned int *discriminator_ptr)
 {
   bfd_boolean found;
 
-  if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr))
+                                    line_ptr, discriminator_ptr,
+                                    dwarf_debug_sections, 0,
+                                    &elf_tdata (abfd)->dwarf2_find_line_info))
     {
       if (!*functionname_ptr)
-       elf_find_function (abfd, section, symbols, offset,
+       elf_find_function (abfd, symbols, section, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
       return TRUE;
     }
 
-  if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
-                                    filename_ptr, functionname_ptr,
-                                    line_ptr, 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
+  if (_bfd_dwarf1_find_nearest_line (abfd, symbols, section, offset,
+                                    filename_ptr, functionname_ptr, line_ptr))
     {
       if (!*functionname_ptr)
-       elf_find_function (abfd, section, symbols, offset,
+       elf_find_function (abfd, symbols, section, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
@@ -7441,7 +7798,7 @@ _bfd_elf_find_nearest_line (bfd *abfd,
   if (symbols == NULL)
     return FALSE;
 
-  if (! elf_find_function (abfd, section, symbols, offset,
+  if (! elf_find_function (abfd, symbols, section, offset,
                           filename_ptr, functionname_ptr))
     return FALSE;
 
@@ -7455,9 +7812,10 @@ bfd_boolean
 _bfd_elf_find_line (bfd *abfd, asymbol **symbols, asymbol *symbol,
                    const char **filename_ptr, unsigned int *line_ptr)
 {
-  return _bfd_dwarf2_find_line (abfd, symbols, symbol,
-                               filename_ptr, line_ptr, 0,
-                               &elf_tdata (abfd)->dwarf2_find_line_info);
+  return _bfd_dwarf2_find_nearest_line (abfd, symbols, symbol, NULL, 0,
+                                       filename_ptr, NULL, line_ptr, NULL,
+                                       dwarf_debug_sections, 0,
+                                       &elf_tdata (abfd)->dwarf2_find_line_info);
 }
 
 /* After a call to bfd_find_nearest_line, successive calls to
@@ -7487,21 +7845,21 @@ _bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 
   if (!info->relocatable)
     {
-      bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+      bfd_size_type phdr_size = elf_program_header_size (abfd);
 
       if (phdr_size == (bfd_size_type) -1)
        {
          struct elf_segment_map *m;
 
          phdr_size = 0;
-         for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+         for (m = elf_seg_map (abfd); m != NULL; m = m->next)
            phdr_size += bed->s->sizeof_phdr;
 
          if (phdr_size == 0)
            phdr_size = get_program_header_size (abfd, info);
        }
 
-      elf_tdata (abfd)->program_header_size = phdr_size;
+      elf_program_header_size (abfd) = phdr_size;
       ret += phdr_size;
     }
 
@@ -7516,7 +7874,7 @@ _bfd_elf_set_section_contents (bfd *abfd,
                               bfd_size_type count)
 {
   Elf_Internal_Shdr *hdr;
-  bfd_signed_vma pos;
+  file_ptr pos;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions (abfd, NULL))
@@ -7638,11 +7996,12 @@ _bfd_elf_validate_reloc (bfd *abfd, arelent *areloc)
 bfd_boolean
 _bfd_elf_close_and_cleanup (bfd *abfd)
 {
-  if (bfd_get_format (abfd) == bfd_object)
+  struct elf_obj_tdata *tdata = elf_tdata (abfd);
+  if (bfd_get_format (abfd) == bfd_object && tdata != NULL)
     {
-      if (elf_tdata (abfd) != NULL && elf_shstrtab (abfd) != NULL)
+      if (elf_tdata (abfd)->o != NULL && elf_shstrtab (abfd) != NULL)
        _bfd_elf_strtab_free (elf_shstrtab (abfd));
-      _bfd_dwarf2_cleanup_debug_info (abfd);
+      _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info);
     }
 
   return _bfd_generic_close_and_cleanup (abfd);
@@ -7682,9 +8041,9 @@ elfcore_make_pid (bfd *abfd)
 {
   int pid;
 
-  pid = elf_tdata (abfd)->core_lwpid;
+  pid = elf_tdata (abfd)->core->lwpid;
   if (pid == 0)
-    pid = elf_tdata (abfd)->core_pid;
+    pid = elf_tdata (abfd)->core->pid;
 
   return pid;
 }
@@ -7774,10 +8133,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
       /* Do not overwrite the core signal if it
         has already been set by another thread.  */
-      if (elf_tdata (abfd)->core_signal == 0)
-       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
-      if (elf_tdata (abfd)->core_pid == 0)
-       elf_tdata (abfd)->core_pid = prstat.pr_pid;
+      if (elf_tdata (abfd)->core->signal == 0)
+       elf_tdata (abfd)->core->signal = prstat.pr_cursig;
+      if (elf_tdata (abfd)->core->pid == 0)
+       elf_tdata (abfd)->core->pid = prstat.pr_pid;
 
       /* pr_who exists on:
         solaris 2.5+
@@ -7786,9 +8145,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
         linux 2.[01]
         */
 #if defined (HAVE_PRSTATUS_T_PR_WHO)
-      elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+      elf_tdata (abfd)->core->lwpid = prstat.pr_who;
 #else
-      elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
+      elf_tdata (abfd)->core->lwpid = prstat.pr_pid;
 #endif
     }
 #if defined (HAVE_PRSTATUS32_T)
@@ -7803,10 +8162,10 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
 
       /* Do not overwrite the core signal if it
         has already been set by another thread.  */
-      if (elf_tdata (abfd)->core_signal == 0)
-       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
-      if (elf_tdata (abfd)->core_pid == 0)
-       elf_tdata (abfd)->core_pid = prstat.pr_pid;
+      if (elf_tdata (abfd)->core->signal == 0)
+       elf_tdata (abfd)->core->signal = prstat.pr_cursig;
+      if (elf_tdata (abfd)->core->pid == 0)
+       elf_tdata (abfd)->core->pid = prstat.pr_pid;
 
       /* pr_who exists on:
         solaris 2.5+
@@ -7815,9 +8174,9 @@ elfcore_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
         linux 2.[01]
         */
 #if defined (HAVE_PRSTATUS32_T_PR_WHO)
-      elf_tdata (abfd)->core_lwpid = prstat.pr_who;
+      elf_tdata (abfd)->core->lwpid = prstat.pr_who;
 #else
-      elf_tdata (abfd)->core_lwpid = prstat.pr_pid;
+      elf_tdata (abfd)->core->lwpid = prstat.pr_pid;
 #endif
     }
 #endif /* HAVE_PRSTATUS32_T */
@@ -7922,6 +8281,48 @@ elfcore_grok_s390_prefix (bfd *abfd, Elf_Internal_Note *note)
   return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note);
 }
 
+static bfd_boolean
+elfcore_grok_s390_last_break (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-last-break", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note);
+}
+
+static bfd_boolean
+elfcore_grok_s390_tdb (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-s390-tdb", note);
+}
+
+static bfd_boolean
+elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_tls (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-aarch-tls", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_hw_break (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-break", note);
+}
+
+static bfd_boolean
+elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note)
+{
+  return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", note);
+}
+
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
 #if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
@@ -7972,11 +8373,14 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
-      elf_tdata (abfd)->core_program
+#if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID)
+      elf_tdata (abfd)->core->pid = psinfo.pr_pid;
+#endif
+      elf_tdata (abfd)->core->program
        = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
                                sizeof (psinfo.pr_fname));
 
-      elf_tdata (abfd)->core_command
+      elf_tdata (abfd)->core->command
        = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
                                sizeof (psinfo.pr_psargs));
     }
@@ -7988,11 +8392,14 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
-      elf_tdata (abfd)->core_program
+#if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID)
+      elf_tdata (abfd)->core->pid = psinfo.pr_pid;
+#endif
+      elf_tdata (abfd)->core->program
        = _bfd_elfcore_strndup (abfd, psinfo.pr_fname,
                                sizeof (psinfo.pr_fname));
 
-      elf_tdata (abfd)->core_command
+      elf_tdata (abfd)->core->command
        = _bfd_elfcore_strndup (abfd, psinfo.pr_psargs,
                                sizeof (psinfo.pr_psargs));
     }
@@ -8010,7 +8417,7 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
      implementations, so strip it off if it exists.  */
 
   {
-    char *command = elf_tdata (abfd)->core_command;
+    char *command = elf_tdata (abfd)->core->command;
     int n = strlen (command);
 
     if (0 < n && command[n - 1] == ' ')
@@ -8035,7 +8442,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&pstat, note->descdata, sizeof (pstat));
 
-      elf_tdata (abfd)->core_pid = pstat.pr_pid;
+      elf_tdata (abfd)->core->pid = pstat.pr_pid;
     }
 #if defined (HAVE_PSTATUS32_T)
   else if (note->descsz == sizeof (pstatus32_t))
@@ -8045,7 +8452,7 @@ elfcore_grok_pstatus (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (&pstat, note->descdata, sizeof (pstat));
 
-      elf_tdata (abfd)->core_pid = pstat.pr_pid;
+      elf_tdata (abfd)->core->pid = pstat.pr_pid;
     }
 #endif
   /* Could grab some more details from the "representative"
@@ -8075,11 +8482,11 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
 
   memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
 
-  elf_tdata (abfd)->core_lwpid = lwpstat.pr_lwpid;
+  elf_tdata (abfd)->core->lwpid = lwpstat.pr_lwpid;
   /* Do not overwrite the core signal if it has already been set by
      another thread.  */
-  if (elf_tdata (abfd)->core_signal == 0)
-    elf_tdata (abfd)->core_signal = lwpstat.pr_cursig;
+  if (elf_tdata (abfd)->core->signal == 0)
+    elf_tdata (abfd)->core->signal = lwpstat.pr_cursig;
 
   /* Make a ".reg/999" section.  */
 
@@ -8162,11 +8569,11 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
   switch (type)
     {
     case 1 /* NOTE_INFO_PROCESS */:
-      /* FIXME: need to add ->core_command.  */
+      /* FIXME: need to add ->core->command.  */
       /* process_info.pid */
-      elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 8);
+      elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 8);
       /* process_info.signal */
-      elf_tdata (abfd)->core_signal = bfd_get_32 (abfd, note->descdata + 12);
+      elf_tdata (abfd)->core->signal = bfd_get_32 (abfd, note->descdata + 12);
       break;
 
     case 2 /* NOTE_INFO_THREAD */:
@@ -8335,6 +8742,55 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
       else
         return TRUE;
 
+    case NT_S390_LAST_BREAK:
+      if (note->namesz == 6
+          && strcmp (note->namedata, "LINUX") == 0)
+        return elfcore_grok_s390_last_break (abfd, note);
+      else
+        return TRUE;
+
+    case NT_S390_SYSTEM_CALL:
+      if (note->namesz == 6
+          && strcmp (note->namedata, "LINUX") == 0)
+        return elfcore_grok_s390_system_call (abfd, note);
+      else
+        return TRUE;
+
+    case NT_S390_TDB:
+      if (note->namesz == 6
+          && strcmp (note->namedata, "LINUX") == 0)
+        return elfcore_grok_s390_tdb (abfd, note);
+      else
+        return TRUE;
+
+    case NT_ARM_VFP:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_arm_vfp (abfd, note);
+      else
+       return TRUE;
+
+    case NT_ARM_TLS:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_aarch_tls (abfd, note);
+      else
+       return TRUE;
+
+    case NT_ARM_HW_BREAK:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_aarch_hw_break (abfd, note);
+      else
+       return TRUE;
+
+    case NT_ARM_HW_WATCH:
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
+       return elfcore_grok_aarch_hw_watch (abfd, note);
+      else
+       return TRUE;
+
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
@@ -8359,18 +8815,32 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 
        return TRUE;
       }
+
+    case NT_FILE:
+      return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.file",
+                                             note);
+
+    case NT_SIGINFO:
+      return elfcore_make_note_pseudosection (abfd, ".note.linuxcore.siginfo",
+                                             note);
     }
 }
 
 static bfd_boolean
 elfobj_grok_gnu_build_id (bfd *abfd, Elf_Internal_Note *note)
 {
-  elf_tdata (abfd)->build_id_size = note->descsz;
-  elf_tdata (abfd)->build_id = (bfd_byte *) bfd_alloc (abfd, note->descsz);
-  if (elf_tdata (abfd)->build_id == NULL)
+  struct elf_obj_tdata *t;
+
+  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)
     return FALSE;
 
-  memcpy (elf_tdata (abfd)->build_id, note->descdata, note->descsz);
+  t->build_id->size = note->descsz;
+  memcpy (t->build_id->data, note->descdata, note->descsz);
 
   return TRUE;
 }
@@ -8388,6 +8858,35 @@ elfobj_grok_gnu_note (bfd *abfd, Elf_Internal_Note *note)
     }
 }
 
+static bfd_boolean
+elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note)
+{
+  struct sdt_note *cur =
+    (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note)
+                                  + note->descsz);
+
+  cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head;
+  cur->size = (bfd_size_type) note->descsz;
+  memcpy (cur->data, note->descdata, note->descsz);
+
+  elf_tdata (abfd)->sdt_note_head = cur;
+
+  return TRUE;
+}
+
+static bfd_boolean
+elfobj_grok_stapsdt_note (bfd *abfd, Elf_Internal_Note *note)
+{
+  switch (note->type)
+    {
+    case NT_STAPSDT:
+      return elfobj_grok_stapsdt_note_1 (abfd, note);
+
+    default:
+      return TRUE;
+    }
+}
+
 static bfd_boolean
 elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp)
 {
@@ -8406,15 +8905,15 @@ static bfd_boolean
 elfcore_grok_netbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   /* Signal number at offset 0x08. */
-  elf_tdata (abfd)->core_signal
+  elf_tdata (abfd)->core->signal
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
 
   /* Process ID at offset 0x50. */
-  elf_tdata (abfd)->core_pid
+  elf_tdata (abfd)->core->pid
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x50);
 
   /* Command name at 0x7c (max 32 bytes, including nul). */
-  elf_tdata (abfd)->core_command
+  elf_tdata (abfd)->core->command
     = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
 
   return elfcore_make_note_pseudosection (abfd, ".note.netbsdcore.procinfo",
@@ -8427,7 +8926,7 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
   int lwp;
 
   if (elfcore_netbsd_get_lwpid (note, &lwp))
-    elf_tdata (abfd)->core_lwpid = lwp;
+    elf_tdata (abfd)->core->lwpid = lwp;
 
   if (note->type == NT_NETBSDCORE_PROCINFO)
     {
@@ -8490,15 +8989,15 @@ static bfd_boolean
 elfcore_grok_openbsd_procinfo (bfd *abfd, Elf_Internal_Note *note)
 {
   /* Signal number at offset 0x08. */
-  elf_tdata (abfd)->core_signal
+  elf_tdata (abfd)->core->signal
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x08);
 
   /* Process ID at offset 0x20. */
-  elf_tdata (abfd)->core_pid
+  elf_tdata (abfd)->core->pid
     = bfd_h_get_32 (abfd, (bfd_byte *) note->descdata + 0x20);
 
   /* Command name at 0x48 (max 32 bytes, including nul). */
-  elf_tdata (abfd)->core_command
+  elf_tdata (abfd)->core->command
     = _bfd_elfcore_strndup (abfd, note->descdata + 0x48, 31);
 
   return TRUE;
@@ -8561,7 +9060,7 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
   unsigned flags;
 
   /* nto_procfs_status 'pid' field is at offset 0.  */
-  elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
+  elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, (bfd_byte *) ddata);
 
   /* nto_procfs_status 'tid' field is at offset 4.  Pass it back.  */
   *tid = bfd_get_32 (abfd, (bfd_byte *) ddata + 4);
@@ -8572,15 +9071,15 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
   /* nto_procfs_status 'what' field is at offset 14.  */
   if ((sig = bfd_get_16 (abfd, (bfd_byte *) ddata + 14)) > 0)
     {
-      elf_tdata (abfd)->core_signal = sig;
-      elf_tdata (abfd)->core_lwpid = *tid;
+      elf_tdata (abfd)->core->signal = sig;
+      elf_tdata (abfd)->core->lwpid = *tid;
     }
 
   /* _DEBUG_FLAG_CURTID (current thread) is 0x80.  Some cores
      do not come from signals so we make sure we set the current
      thread just in case.  */
   if (flags & 0x00000080)
-    elf_tdata (abfd)->core_lwpid = *tid;
+    elf_tdata (abfd)->core->lwpid = *tid;
 
   /* Make a ".qnx_core_status/%d" section.  */
   sprintf (buf, ".qnx_core_status/%ld", *tid);
@@ -8628,7 +9127,7 @@ elfcore_grok_nto_regs (bfd *abfd,
   sect->alignment_power = 2;
 
   /* This is the current thread.  */
-  if (elf_tdata (abfd)->core_lwpid == tid)
+  if (elf_tdata (abfd)->core->lwpid == tid)
     return elfcore_maybe_make_sect (abfd, base, sect);
 
   return TRUE;
@@ -8755,7 +9254,6 @@ elfcore_write_note (bfd *abfd,
   return buf;
 }
 
-#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 char *
 elfcore_write_prpsinfo (bfd  *abfd,
                        char *buf,
@@ -8763,7 +9261,6 @@ elfcore_write_prpsinfo (bfd  *abfd,
                        const char *fname,
                        const char *psargs)
 {
-  const char *note_name = "CORE";
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (bed->elf_backend_write_core_note != NULL)
@@ -8775,6 +9272,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
        return ret;
     }
 
+#if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
 #if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
   if (bed->s->elfclass == ELFCLASS32)
     {
@@ -8790,7 +9288,7 @@ elfcore_write_prpsinfo (bfd  *abfd,
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
       strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
       return elfcore_write_note (abfd, buf, bufsiz,
-                                note_name, note_type, &data, sizeof (data));
+                                "CORE", note_type, &data, sizeof (data));
     }
   else
 #endif
@@ -8807,12 +9305,42 @@ elfcore_write_prpsinfo (bfd  *abfd,
       strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
       strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
       return elfcore_write_note (abfd, buf, bufsiz,
-                                note_name, note_type, &data, sizeof (data));
+                                "CORE", note_type, &data, sizeof (data));
     }
-}
 #endif /* PSINFO_T or PRPSINFO_T */
 
-#if defined (HAVE_PRSTATUS_T)
+  free (buf);
+  return NULL;
+}
+
+char *
+elfcore_write_linux_prpsinfo32
+  (bfd *abfd, char *buf, int *bufsiz,
+   const struct elf_internal_linux_prpsinfo *prpsinfo)
+{
+  struct elf_external_linux_prpsinfo32 data;
+
+  memset (&data, 0, sizeof (data));
+  LINUX_PRPSINFO32_SWAP_FIELDS (abfd, prpsinfo, data);
+
+  return elfcore_write_note (abfd, buf, bufsiz, "CORE", NT_PRPSINFO,
+                            &data, sizeof (data));
+}
+
+char *
+elfcore_write_linux_prpsinfo64
+  (bfd *abfd, char *buf, int *bufsiz,
+   const struct elf_internal_linux_prpsinfo *prpsinfo)
+{
+  struct elf_external_linux_prpsinfo64 data;
+
+  memset (&data, 0, sizeof (data));
+  LINUX_PRPSINFO64_SWAP_FIELDS (abfd, prpsinfo, data);
+
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            "CORE", NT_PRPSINFO, &data, sizeof (data));
+}
+
 char *
 elfcore_write_prstatus (bfd *abfd,
                        char *buf,
@@ -8821,7 +9349,6 @@ elfcore_write_prstatus (bfd *abfd,
                        int cursig,
                        const void *gregs)
 {
-  const char *note_name = "CORE";
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   if (bed->elf_backend_write_core_note != NULL)
@@ -8834,6 +9361,7 @@ elfcore_write_prstatus (bfd *abfd,
        return ret;
     }
 
+#if defined (HAVE_PRSTATUS_T)
 #if defined (HAVE_PRSTATUS32_T)
   if (bed->s->elfclass == ELFCLASS32)
     {
@@ -8843,7 +9371,7 @@ elfcore_write_prstatus (bfd *abfd,
       prstat.pr_pid = pid;
       prstat.pr_cursig = cursig;
       memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
-      return elfcore_write_note (abfd, buf, bufsiz, note_name,
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
                                 NT_PRSTATUS, &prstat, sizeof (prstat));
     }
   else
@@ -8855,12 +9383,15 @@ elfcore_write_prstatus (bfd *abfd,
       prstat.pr_pid = pid;
       prstat.pr_cursig = cursig;
       memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
-      return elfcore_write_note (abfd, buf, bufsiz, note_name,
+      return elfcore_write_note (abfd, buf, bufsiz, "CORE",
                                 NT_PRSTATUS, &prstat, sizeof (prstat));
     }
-}
 #endif /* HAVE_PRSTATUS_T */
 
+  free (buf);
+  return NULL;
+}
+
 #if defined (HAVE_LWPSTATUS_T)
 char *
 elfcore_write_lwpstatus (bfd *abfd,
@@ -8877,7 +9408,7 @@ elfcore_write_lwpstatus (bfd *abfd,
   lwpstat.pr_lwpid  = pid >> 16;
   lwpstat.pr_cursig = cursig;
 #if defined (HAVE_LWPSTATUS_T_PR_REG)
-  memcpy (lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
+  memcpy (&lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
 #elif defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
 #if !defined(gregs)
   memcpy (lwpstat.pr_context.uc_mcontext.gregs,
@@ -9059,6 +9590,92 @@ elfcore_write_s390_prefix (bfd *abfd,
                              note_name, NT_S390_PREFIX, s390_prefix, size);
 }
 
+char *
+elfcore_write_s390_last_break (bfd *abfd,
+                              char *buf,
+                              int *bufsiz,
+                              const void *s390_last_break,
+                              int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                             note_name, NT_S390_LAST_BREAK,
+                            s390_last_break, size);
+}
+
+char *
+elfcore_write_s390_system_call (bfd *abfd,
+                               char *buf,
+                               int *bufsiz,
+                               const void *s390_system_call,
+                               int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                             note_name, NT_S390_SYSTEM_CALL,
+                            s390_system_call, size);
+}
+
+char *
+elfcore_write_s390_tdb (bfd *abfd,
+                       char *buf,
+                       int *bufsiz,
+                       const void *s390_tdb,
+                       int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                             note_name, NT_S390_TDB, s390_tdb, size);
+}
+
+char *
+elfcore_write_arm_vfp (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      const void *arm_vfp,
+                      int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_VFP, arm_vfp, size);
+}
+
+char *
+elfcore_write_aarch_tls (bfd *abfd,
+                      char *buf,
+                      int *bufsiz,
+                      const void *aarch_tls,
+                      int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_TLS, aarch_tls, size);
+}
+
+char *
+elfcore_write_aarch_hw_break (bfd *abfd,
+                           char *buf,
+                           int *bufsiz,
+                           const void *aarch_hw_break,
+                           int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_HW_BREAK, aarch_hw_break, size);
+}
+
+char *
+elfcore_write_aarch_hw_watch (bfd *abfd,
+                           char *buf,
+                           int *bufsiz,
+                           const void *aarch_hw_watch,
+                           int size)
+{
+  char *note_name = "LINUX";
+  return elfcore_write_note (abfd, buf, bufsiz,
+                            note_name, NT_ARM_HW_WATCH, aarch_hw_watch, size);
+}
+
 char *
 elfcore_write_register_note (bfd *abfd,
                             char *buf,
@@ -9089,6 +9706,20 @@ elfcore_write_register_note (bfd *abfd,
     return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size);
   if (strcmp (section, ".reg-s390-prefix") == 0)
     return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-last-break") == 0)
+    return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-system-call") == 0)
+    return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-s390-tdb") == 0)
+    return elfcore_write_s390_tdb (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-arm-vfp") == 0)
+    return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-aarch-tls") == 0)
+    return elfcore_write_aarch_tls (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-aarch-hw-break") == 0)
+    return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size);
+  if (strcmp (section, ".reg-aarch-hw-watch") == 0)
+    return elfcore_write_aarch_hw_watch (abfd, buf, bufsiz, data, size);
   return NULL;
 }
 
@@ -9161,6 +9792,12 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
              if (! elfobj_grok_gnu_note (abfd, &in))
                return FALSE;
            }
+         else if (in.namesz == sizeof "stapsdt"
+                  && strcmp (in.namedata, "stapsdt") == 0)
+           {
+             if (! elfobj_grok_stapsdt_note (abfd, &in))
+               return FALSE;
+           }
          break;
        }
 
@@ -9241,7 +9878,9 @@ bfd_get_elf_phdrs (bfd *abfd, void *phdrs)
 }
 
 enum elf_reloc_type_class
-_bfd_elf_reloc_type_class (const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
+_bfd_elf_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
+                          const asection *rel_sec ATTRIBUTE_UNUSED,
+                          const Elf_Internal_Rela *rela ATTRIBUTE_UNUSED)
 {
   return reloc_class_normal;
 }
@@ -9263,7 +9902,7 @@ _bfd_elf_rela_local_sym (bfd *abfd,
                + sym->st_value);
   if ((sec->flags & SEC_MERGE)
       && ELF_ST_TYPE (sym->st_info) == STT_SECTION
-      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
+      && sec->sec_info_type == SEC_INFO_TYPE_MERGE)
     {
       rel->r_addend =
        _bfd_merged_section_offset (abfd, psec,
@@ -9294,7 +9933,7 @@ _bfd_elf_rel_local_sym (bfd *abfd,
 {
   asection *sec = *psec;
 
-  if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
+  if (sec->sec_info_type != SEC_INFO_TYPE_MERGE)
     return sym->st_value + addend;
 
   return _bfd_merged_section_offset (abfd, psec,
@@ -9310,12 +9949,18 @@ _bfd_elf_section_offset (bfd *abfd,
 {
   switch (sec->sec_info_type)
     {
-    case ELF_INFO_TYPE_STABS:
+    case SEC_INFO_TYPE_STABS:
       return _bfd_stab_section_offset (sec, elf_section_data (sec)->sec_info,
                                       offset);
-    case ELF_INFO_TYPE_EH_FRAME:
+    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)
+       {
+         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;
+       }
       return offset;
     }
 }
@@ -9337,11 +9982,12 @@ bfd *
 bfd_elf_bfd_from_remote_memory
   (bfd *templ,
    bfd_vma ehdr_vma,
+   bfd_size_type size,
    bfd_vma *loadbasep,
-   int (*target_read_memory) (bfd_vma, bfd_byte *, int))
+   int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
 {
   return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
-    (templ, ehdr_vma, loadbasep, target_read_memory);
+    (templ, ehdr_vma, size, loadbasep, target_read_memory);
 }
 \f
 long
@@ -9443,7 +10089,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
       if (p->addend != 0)
        {
          char buf[30], *a;
-         
+
          memcpy (names, "+0x", sizeof ("+0x") - 1);
          names += sizeof ("+0x") - 1;
          bfd_sprintf_vma (abfd, buf, p->addend);
@@ -9467,8 +10113,8 @@ asection _bfd_elf_large_com_section
                      SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
 
 void
-_bfd_elf_set_osabi (bfd * abfd,
-                   struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
+_bfd_elf_post_process_headers (bfd * abfd,
+                              struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
 {
   Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form.  */
 
@@ -9477,11 +10123,11 @@ _bfd_elf_set_osabi (bfd * abfd,
   i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
 
   /* To make things simpler for the loader on Linux systems we set the
-     osabi field to ELFOSABI_LINUX if the binary contains symbols of
-     the STT_GNU_IFUNC type.  */
+     osabi field to ELFOSABI_GNU if the binary contains symbols of
+     the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding.  */
   if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE
-      && elf_tdata (abfd)->has_ifunc_symbols)
-    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
+      && elf_tdata (abfd)->has_gnu_symbols)
+    i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU;
 }
 
 
@@ -9495,3 +10141,27 @@ _bfd_elf_is_function_type (unsigned int type)
   return (type == STT_FUNC
          || type == STT_GNU_IFUNC);
 }
+
+/* If the ELF symbol SYM might be a function in SEC, return the
+   function size and set *CODE_OFF to the function's entry point,
+   otherwise return zero.  */
+
+bfd_size_type
+_bfd_elf_maybe_function_sym (const asymbol *sym, asection *sec,
+                            bfd_vma *code_off)
+{
+  bfd_size_type size;
+
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+                    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+      || sym->section != sec)
+    return 0;
+
+  *code_off = sym->value;
+  size = 0;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+  if (size == 0)
+    size = 1;
+  return size;
+}
This page took 0.068968 seconds and 4 git commands to generate.