daily update
[deliverable/binutils-gdb.git] / bfd / elf.c
index 5221f722f43614cc3260836f6cd93bdd27f72062..e3428217e2968a62bdafcbcffd61a24ab9650e90 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1,6 +1,6 @@
 /* ELF executable support for BFD.
-   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-   Free Software Foundation, Inc.
+   Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+   2003 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -19,7 +19,7 @@
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*  SECTION
-    
+
        ELF backends
 
        BFD support for ELF formats is being worked on.
 #include "libiberty.h"
 
 static INLINE struct elf_segment_map *make_mapping
-  PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
-static boolean map_sections_to_segments PARAMS ((bfd *));
-static int elf_sort_sections PARAMS ((const PTR, const PTR));
-static boolean assign_file_positions_for_segments PARAMS ((bfd *));
-static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
-static boolean prep_headers PARAMS ((bfd *));
-static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **, int));
-static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
-static char *elf_read PARAMS ((bfd *, file_ptr, bfd_size_type));
-static boolean setup_group PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
-static void merge_sections_remove_hook PARAMS ((bfd *, asection *));
-static void elf_fake_sections PARAMS ((bfd *, asection *, PTR));
-static void set_group_contents PARAMS ((bfd *, asection *, PTR));
-static boolean assign_section_numbers PARAMS ((bfd *));
-static INLINE int sym_is_global PARAMS ((bfd *, asymbol *));
-static boolean elf_map_symbols PARAMS ((bfd *));
-static bfd_size_type get_program_header_size PARAMS ((bfd *));
-static boolean elfcore_read_notes PARAMS ((bfd *, file_ptr, bfd_size_type));
-static boolean elf_find_function PARAMS ((bfd *, asection *, asymbol **,
-                                         bfd_vma, const char **,
-                                         const char **));
-static int elfcore_make_pid PARAMS ((bfd *));
-static boolean elfcore_maybe_make_sect PARAMS ((bfd *, char *, asection *));
-static boolean elfcore_make_note_pseudosection PARAMS ((bfd *, char *,
-                                                       Elf_Internal_Note *));
-static boolean elfcore_grok_prfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_prxfpreg PARAMS ((bfd *, Elf_Internal_Note *));
-static boolean elfcore_grok_note PARAMS ((bfd *, Elf_Internal_Note *));
-
-static boolean elfcore_netbsd_get_lwpid PARAMS ((Elf_Internal_Note *, int *));
-static boolean elfcore_grok_netbsd_procinfo PARAMS ((bfd *,
-                                                    Elf_Internal_Note *));
-static boolean elfcore_grok_netbsd_note PARAMS ((bfd *, Elf_Internal_Note *));
+  PARAMS ((bfd *, asection **, unsigned int, unsigned int, bfd_boolean));
+static bfd_boolean map_sections_to_segments
+  PARAMS ((bfd *));
+static int elf_sort_sections
+  PARAMS ((const PTR, const PTR));
+static bfd_boolean assign_file_positions_for_segments
+  PARAMS ((bfd *));
+static bfd_boolean assign_file_positions_except_relocs
+  PARAMS ((bfd *));
+static bfd_boolean prep_headers
+  PARAMS ((bfd *));
+static bfd_boolean swap_out_syms
+  PARAMS ((bfd *, struct bfd_strtab_hash **, int));
+static bfd_boolean copy_private_bfd_data
+  PARAMS ((bfd *, bfd *));
+static char *elf_read
+  PARAMS ((bfd *, file_ptr, bfd_size_type));
+static const char *group_signature
+  PARAMS ((bfd *, Elf_Internal_Shdr *));
+static bfd_boolean setup_group
+  PARAMS ((bfd *, Elf_Internal_Shdr *, asection *));
+static void merge_sections_remove_hook
+  PARAMS ((bfd *, asection *));
+static void elf_fake_sections
+  PARAMS ((bfd *, asection *, PTR));
+static bfd_boolean assign_section_numbers
+  PARAMS ((bfd *));
+static INLINE int sym_is_global
+  PARAMS ((bfd *, asymbol *));
+static bfd_boolean elf_map_symbols
+  PARAMS ((bfd *));
+static bfd_size_type get_program_header_size
+  PARAMS ((bfd *));
+static bfd_boolean elfcore_read_notes
+  PARAMS ((bfd *, file_ptr, bfd_size_type));
+static bfd_boolean elf_find_function
+  PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
+          const char **));
+static int elfcore_make_pid
+  PARAMS ((bfd *));
+static bfd_boolean elfcore_maybe_make_sect
+  PARAMS ((bfd *, char *, asection *));
+static bfd_boolean elfcore_make_note_pseudosection
+  PARAMS ((bfd *, char *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prfpreg
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prxfpreg
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_note
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_netbsd_get_lwpid
+  PARAMS ((Elf_Internal_Note *, int *));
+static bfd_boolean elfcore_grok_netbsd_procinfo
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_netbsd_note
+  PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_nto_gregs
+  PARAMS ((bfd *, Elf_Internal_Note *, pid_t));
+static bfd_boolean elfcore_grok_nto_status
+  PARAMS ((bfd *, Elf_Internal_Note *, pid_t *));
+static bfd_boolean elfcore_grok_nto_note
+  PARAMS ((bfd *, Elf_Internal_Note *));
 
 /* Swap version information in and out.  The version information is
    currently size independent.  If that ever changes, this code will
@@ -242,7 +271,7 @@ bfd_elf_hash (namearg)
          h ^= g;
        }
     }
-  return h;
+  return h & 0xffffffff;
 }
 
 /* Read a specified number of bytes at a specified offset in an ELF
@@ -270,7 +299,7 @@ elf_read (abfd, offset, size)
   return buf;
 }
 
-boolean
+bfd_boolean
 bfd_elf_mkobject (abfd)
      bfd *abfd;
 {
@@ -279,14 +308,14 @@ bfd_elf_mkobject (abfd)
   bfd_size_type amt = sizeof (struct elf_obj_tdata);
   elf_tdata (abfd) = (struct elf_obj_tdata *) bfd_zalloc (abfd, amt);
   if (elf_tdata (abfd) == 0)
-    return false;
+    return FALSE;
   /* Since everything is done at close time, do we need any
      initialization?  */
 
-  return true;
+  return TRUE;
 }
 
-boolean
+bfd_boolean
 bfd_elf_mkcorefile (abfd)
      bfd *abfd;
 {
@@ -352,6 +381,124 @@ bfd_elf_string_from_elf_section (abfd, shindex, strindex)
   return ((char *) hdr->contents) + strindex;
 }
 
+/* Read and convert symbols to internal format.
+   SYMCOUNT specifies the number of symbols to read, starting from
+   symbol SYMOFFSET.  If any of INTSYM_BUF, EXTSYM_BUF or EXTSHNDX_BUF
+   are non-NULL, they are used to store the internal symbols, external
+   symbols, and symbol section index extensions, respectively.  */
+
+Elf_Internal_Sym *
+bfd_elf_get_elf_syms (ibfd, symtab_hdr, symcount, symoffset,
+                     intsym_buf, extsym_buf, extshndx_buf)
+     bfd *ibfd;
+     Elf_Internal_Shdr *symtab_hdr;
+     size_t symcount;
+     size_t symoffset;
+     Elf_Internal_Sym *intsym_buf;
+     PTR extsym_buf;
+     Elf_External_Sym_Shndx *extshndx_buf;
+{
+  Elf_Internal_Shdr *shndx_hdr;
+  PTR alloc_ext;
+  const bfd_byte *esym;
+  Elf_External_Sym_Shndx *alloc_extshndx;
+  Elf_External_Sym_Shndx *shndx;
+  Elf_Internal_Sym *isym;
+  Elf_Internal_Sym *isymend;
+  struct elf_backend_data *bed;
+  size_t extsym_size;
+  bfd_size_type amt;
+  file_ptr pos;
+
+  if (symcount == 0)
+    return intsym_buf;
+
+  /* Normal syms might have section extension entries.  */
+  shndx_hdr = NULL;
+  if (symtab_hdr == &elf_tdata (ibfd)->symtab_hdr)
+    shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
+
+  /* Read the symbols.  */
+  alloc_ext = NULL;
+  alloc_extshndx = NULL;
+  bed = get_elf_backend_data (ibfd);
+  extsym_size = bed->s->sizeof_sym;
+  amt = symcount * extsym_size;
+  pos = symtab_hdr->sh_offset + symoffset * extsym_size;
+  if (extsym_buf == NULL)
+    {
+      alloc_ext = bfd_malloc (amt);
+      extsym_buf = alloc_ext;
+    }
+  if (extsym_buf == NULL
+      || bfd_seek (ibfd, pos, SEEK_SET) != 0
+      || bfd_bread (extsym_buf, amt, ibfd) != amt)
+    {
+      intsym_buf = NULL;
+      goto out;
+    }
+
+  if (shndx_hdr == NULL || shndx_hdr->sh_size == 0)
+    extshndx_buf = NULL;
+  else
+    {
+      amt = symcount * sizeof (Elf_External_Sym_Shndx);
+      pos = shndx_hdr->sh_offset + symoffset * sizeof (Elf_External_Sym_Shndx);
+      if (extshndx_buf == NULL)
+       {
+         alloc_extshndx = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+         extshndx_buf = alloc_extshndx;
+       }
+      if (extshndx_buf == NULL
+         || bfd_seek (ibfd, pos, SEEK_SET) != 0
+         || bfd_bread (extshndx_buf, amt, ibfd) != amt)
+       {
+         intsym_buf = NULL;
+         goto out;
+       }
+    }
+
+  if (intsym_buf == NULL)
+    {
+      bfd_size_type amt = symcount * sizeof (Elf_Internal_Sym);
+      intsym_buf = (Elf_Internal_Sym *) bfd_malloc (amt);
+      if (intsym_buf == NULL)
+       goto out;
+    }
+
+  /* Convert the symbols to internal form.  */
+  isymend = intsym_buf + symcount;
+  for (esym = extsym_buf, isym = intsym_buf, shndx = extshndx_buf;
+       isym < isymend;
+       esym += extsym_size, isym++, shndx = shndx != NULL ? shndx + 1 : NULL)
+    (*bed->s->swap_symbol_in) (ibfd, esym, (const PTR) shndx, isym);
+
+ out:
+  if (alloc_ext != NULL)
+    free (alloc_ext);
+  if (alloc_extshndx != NULL)
+    free (alloc_extshndx);
+
+  return intsym_buf;
+}
+
+/* Look up a symbol name.  */
+const char *
+bfd_elf_local_sym_name (abfd, isym)
+     bfd *abfd;
+     Elf_Internal_Sym *isym;
+{
+  unsigned int iname = isym->st_name;
+  unsigned int shindex = elf_tdata (abfd)->symtab_hdr.sh_link;
+  if (iname == 0 && ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+    {
+      iname = elf_elfsections (abfd)[isym->st_shndx]->sh_name;
+      shindex = elf_elfheader (abfd)->e_shstrndx;
+    }
+
+  return bfd_elf_string_from_elf_section (abfd, shindex, iname);
+}
+
 /* Elf_Internal_Shdr->contents is an array of these for SHT_GROUP
    sections.  The first element is the flags, the rest are section
    pointers.  */
@@ -361,9 +508,35 @@ typedef union elf_internal_group {
   unsigned int flags;
 } Elf_Internal_Group;
 
+/* Return the name of the group signature symbol.  Why isn't the
+   signature just a string?  */
+
+static const char *
+group_signature (abfd, ghdr)
+     bfd *abfd;
+     Elf_Internal_Shdr *ghdr;
+{
+  Elf_Internal_Shdr *hdr;
+  unsigned char esym[sizeof (Elf64_External_Sym)];
+  Elf_External_Sym_Shndx eshndx;
+  Elf_Internal_Sym isym;
+
+  /* First we need to ensure the symbol table is available.  */
+  if (! bfd_section_from_shdr (abfd, ghdr->sh_link))
+    return NULL;
+
+  /* Go read the symbol.  */
+  hdr = &elf_tdata (abfd)->symtab_hdr;
+  if (bfd_elf_get_elf_syms (abfd, hdr, 1, ghdr->sh_info,
+                           &isym, esym, &eshndx) == NULL)
+    return NULL;
+
+  return bfd_elf_local_sym_name (abfd, &isym);
+}
+
 /* Set next_in_group list pointer, and group name for NEWSECT.  */
 
-static boolean
+static bfd_boolean
 setup_group (abfd, hdr, newsect)
      bfd *abfd;
      Elf_Internal_Shdr *hdr;
@@ -399,7 +572,7 @@ setup_group (abfd, hdr, newsect)
          bfd_size_type amt = num_group * sizeof (Elf_Internal_Shdr *);
          elf_tdata (abfd)->group_sect_ptr = bfd_alloc (abfd, amt);
          if (elf_tdata (abfd)->group_sect_ptr == NULL)
-           return false;
+           return FALSE;
 
          num_group = 0;
          for (i = 0; i < shnum; i++)
@@ -422,7 +595,7 @@ setup_group (abfd, hdr, newsect)
                      || bfd_seek (abfd, shdr->sh_offset, SEEK_SET) != 0
                      || (bfd_bread (shdr->contents, shdr->sh_size, abfd)
                          != shdr->sh_size))
-                   return false;
+                   return FALSE;
 
                  /* Translate raw contents, a flag word followed by an
                     array of elf section indices all in target byte order,
@@ -440,6 +613,9 @@ setup_group (abfd, hdr, newsect)
                      if (src == shdr->contents)
                        {
                          dest->flags = idx;
+                         if (shdr->bfd_section != NULL && (idx & GRP_COMDAT))
+                           shdr->bfd_section->flags
+                             |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
                          break;
                        }
                      if (idx >= shnum)
@@ -492,32 +668,22 @@ setup_group (abfd, hdr, newsect)
                  }
                else
                  {
-                   struct elf_backend_data *bed;
-                   file_ptr pos;
-                   unsigned char ename[4];
-                   unsigned long iname;
                    const char *gname;
 
-                   /* Humbug.  Get the name from the group signature
-                      symbol.  Why isn't the signature just a string?
-                      Fortunately, the name index is at the same
-                      place in the external symbol for both 32 and 64
-                      bit ELF.  */
-                   bed = get_elf_backend_data (abfd);
-                   pos = elf_tdata (abfd)->symtab_hdr.sh_offset;
-                   pos += shdr->sh_info * bed->s->sizeof_sym;
-                   if (bfd_seek (abfd, pos, SEEK_SET) != 0
-                       || bfd_bread (ename, (bfd_size_type) 4, abfd) != 4)
-                     return false;
-                   iname = H_GET_32 (abfd, ename);
-                   gname = elf_string_from_elf_strtab (abfd, iname);
+                   gname = group_signature (abfd, shdr);
+                   if (gname == NULL)
+                     return FALSE;
                    elf_group_name (newsect) = gname;
 
                    /* Start a circular list with one element.  */
                    elf_next_in_group (newsect) = newsect;
                  }
+
+               /* If the group section has been created, point to the
+                  new member.  */
                if (shdr->bfd_section != NULL)
                  elf_next_in_group (shdr->bfd_section) = newsect;
+
                i = num_group - 1;
                break;
              }
@@ -529,13 +695,32 @@ setup_group (abfd, hdr, newsect)
       (*_bfd_error_handler) (_("%s: no group info for section %s"),
                             bfd_archive_filename (abfd), newsect->name);
     }
-  return true;
+  return TRUE;
+}
+
+bfd_boolean
+bfd_elf_discard_group (abfd, group)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     asection *group;
+{
+  asection *first = elf_next_in_group (group);
+  asection *s = first;
+
+  while (s != NULL)
+    {
+      s->output_section = bfd_abs_section_ptr;
+      s = elf_next_in_group (s);
+      /* These lists are circular.  */
+      if (s == first)
+       break;
+    }
+  return TRUE;
 }
 
 /* Make a BFD section from an ELF section.  We store a pointer to the
    BFD section in the bfd_section field of the header.  */
 
-boolean
+bfd_boolean
 _bfd_elf_make_section_from_shdr (abfd, hdr, name)
      bfd *abfd;
      Elf_Internal_Shdr *hdr;
@@ -549,12 +734,12 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
     {
       BFD_ASSERT (strcmp (name,
                          bfd_get_section_name (abfd, hdr->bfd_section)) == 0);
-      return true;
+      return TRUE;
     }
 
   newsect = bfd_make_section_anyway (abfd, name);
   if (newsect == NULL)
-    return false;
+    return FALSE;
 
   newsect->filepos = hdr->sh_offset;
 
@@ -562,7 +747,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
       || ! bfd_set_section_size (abfd, newsect, hdr->sh_size)
       || ! bfd_set_section_alignment (abfd, newsect,
                                      bfd_log2 ((bfd_vma) hdr->sh_addralign)))
-    return false;
+    return FALSE;
 
   flags = SEC_NO_FLAGS;
   if (hdr->sh_type != SHT_NOBITS)
@@ -590,7 +775,9 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
     }
   if (hdr->sh_flags & SHF_GROUP)
     if (!setup_group (abfd, hdr, newsect))
-      return false;
+      return FALSE;
+  if ((hdr->sh_flags & SHF_TLS) != 0)
+    flags |= SEC_THREAD_LOCAL;
 
   /* The debugging sections appear to be recognized only by name, not
      any sort of flag.  */
@@ -618,16 +805,17 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
      The symbols will be defined as weak, so that multiple definitions
      are permitted.  The GNU linker extension is to actually discard
      all but one of the sections.  */
-  if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0)
+  if (strncmp (name, ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) == 0
+      && elf_next_in_group (newsect) == NULL)
     flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
 
   bed = get_elf_backend_data (abfd);
   if (bed->elf_backend_section_flags)
     if (! bed->elf_backend_section_flags (&flags, hdr))
-      return false;
+      return FALSE;
 
   if (! bfd_set_section_flags (abfd, newsect, flags))
-    return false;
+    return FALSE;
 
   if ((flags & SEC_ALLOC) != 0)
     {
@@ -651,13 +839,13 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
              /* This section is part of this segment if its file
                 offset plus size lies within the segment's memory
                 span and, if the section is loaded, the extent of the
-                loaded data lies within the extent of the segment.  
+                loaded data lies within the extent of the segment.
 
                 Note - we used to check the p_paddr field as well, and
                 refuse to set the LMA if it was 0.  This is wrong
-                though as a perfectly valid, initialised segment can
+                though, as a perfectly valid initialised segment can
                 have a p_paddr of zero.  Some architectures, eg ARM,
-                place special significance one the address 0 and
+                place special significance on the address 0 and
                 executables need to be able to have a segment which
                 covers this address.  */
              if (phdr->p_type == PT_LOAD
@@ -665,19 +853,31 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
                  && (hdr->sh_offset + hdr->sh_size
                      <= phdr->p_offset + phdr->p_memsz)
                  && ((flags & SEC_LOAD) == 0
-                     || (phdr->p_offset + phdr->p_filesz
-                         >= hdr->sh_offset + hdr->sh_size)))
+                     || (hdr->sh_offset + hdr->sh_size
+                         <= phdr->p_offset + phdr->p_filesz)))
                {
-                 /* We used to do a relative adjustment here, but
-                    that doesn't work if the segment is packed with
-                    code from multiple VMAs.  Instead we calculate
-                    the LMA absoultely, based on the LMA of the
-                    segment (it is assumed that the segment will
-                    contain sections with contiguous LMAs, even if
-                    the VMAs are not).  */
-                 newsect->lma = phdr->p_paddr
-                   + hdr->sh_offset - phdr->p_offset;
-                 break;
+                 if ((flags & SEC_LOAD) == 0)
+                   newsect->lma = (phdr->p_paddr
+                                   + hdr->sh_addr - phdr->p_vaddr);
+                 else
+                   /* We used to use the same adjustment for SEC_LOAD
+                      sections, but that doesn't work if the segment
+                      is packed with code from multiple VMAs.
+                      Instead we calculate the section LMA based on
+                      the segment LMA.  It is assumed that the
+                      segment will contain sections with contiguous
+                      LMAs, even if the VMAs are not.  */
+                   newsect->lma = (phdr->p_paddr
+                                   + hdr->sh_offset - phdr->p_offset);
+
+                 /* With contiguous segments, we can't tell from file
+                    offsets whether a section with zero size should
+                    be placed at the end of one segment or the
+                    beginning of the next.  Decide based on vaddr.  */
+                 if (hdr->sh_addr >= phdr->p_vaddr
+                     && (hdr->sh_addr + hdr->sh_size
+                         <= phdr->p_vaddr + phdr->p_memsz))
+                   break;
                }
            }
        }
@@ -686,7 +886,7 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
   hdr->bfd_section = newsect;
   elf_section_data (newsect)->this_hdr = *hdr;
 
-  return true;
+  return TRUE;
 }
 
 /*
@@ -736,7 +936,7 @@ const char *const bfd_elf_section_type_names[] = {
   "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
 };
 
-/* ELF relocs are against symbols.  If we are producing relocateable
+/* ELF relocs are against symbols.  If we are producing relocatable
    output, and the reloc is against an external symbol, and nothing
    has given us any additional addend, the resulting reloc will also
    be against the same symbol.  In such a case, we don't want to
@@ -744,7 +944,7 @@ const char *const bfd_elf_section_type_names[] = {
    all be done at final link time.  Rather than put special case code
    into bfd_perform_relocation, all the reloc types use this howto
    function.  It just short circuits the reloc if producing
-   relocateable output against an external symbol.  */
+   relocatable output against an external symbol.  */
 
 bfd_reloc_status_type
 bfd_elf_generic_reloc (abfd,
@@ -781,39 +981,49 @@ merge_sections_remove_hook (abfd, sec)
      bfd *abfd ATTRIBUTE_UNUSED;
      asection *sec;
 {
-  struct bfd_elf_section_data *sec_data;
-    
-  sec_data = elf_section_data (sec);
-  BFD_ASSERT (sec_data->sec_info_type == ELF_INFO_TYPE_MERGE);
-  sec_data->sec_info_type = ELF_INFO_TYPE_NONE;
+  BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
+  sec->sec_info_type = ELF_INFO_TYPE_NONE;
 }
 
 /* Finish SHF_MERGE section merging.  */
 
-boolean
+bfd_boolean
 _bfd_elf_merge_sections (abfd, info)
      bfd *abfd;
      struct bfd_link_info *info;
 {
   if (!is_elf_hash_table (info))
-    return false;
+    return FALSE;
   if (elf_hash_table (info)->merge_info)
     _bfd_merge_sections (abfd, elf_hash_table (info)->merge_info,
                         merge_sections_remove_hook);
-  return true;
+  return TRUE;
+}
+
+void
+_bfd_elf_link_just_syms (sec, info)
+     asection *sec;
+     struct bfd_link_info *info;
+{
+  sec->output_section = bfd_abs_section_ptr;
+  sec->output_offset = sec->vma;
+  if (!is_elf_hash_table (info))
+    return;
+
+  sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
 }
 \f
 /* Copy the program header and other data from one object module to
    another.  */
 
-boolean
+bfd_boolean
 _bfd_elf_copy_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
      bfd *obfd;
 {
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   BFD_ASSERT (!elf_flags_init (obfd)
              || (elf_elfheader (obfd)->e_flags
@@ -821,13 +1031,13 @@ _bfd_elf_copy_private_bfd_data (ibfd, obfd)
 
   elf_gp (obfd) = elf_gp (ibfd);
   elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
-  elf_flags_init (obfd) = true;
-  return true;
+  elf_flags_init (obfd) = TRUE;
+  return TRUE;
 }
 
 /* Print out the program headers.  */
 
-boolean
+bfd_boolean
 _bfd_elf_print_private_bfd_data (abfd, farg)
      bfd *abfd;
      PTR farg;
@@ -858,7 +1068,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case PT_NOTE: pt = "NOTE"; break;
            case PT_SHLIB: pt = "SHLIB"; break;
            case PT_PHDR: pt = "PHDR"; break;
+           case PT_TLS: pt = "TLS"; break;
            case PT_GNU_EH_FRAME: pt = "EH_FRAME"; break;
+           case PT_GNU_STACK: pt = "STACK"; break;
            default: sprintf (buf, "0x%lx", p->p_type); pt = buf; break;
            }
          fprintf (f, "%8s off    0x", pt);
@@ -915,14 +1127,14 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
          Elf_Internal_Dyn dyn;
          const char *name;
          char ab[20];
-         boolean stringp;
+         bfd_boolean stringp;
 
          (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
 
          if (dyn.d_tag == DT_NULL)
            break;
 
-         stringp = false;
+         stringp = FALSE;
          switch (dyn.d_tag)
            {
            default:
@@ -930,7 +1142,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
              name = ab;
              break;
 
-           case DT_NEEDED: name = "NEEDED"; stringp = true; break;
+           case DT_NEEDED: name = "NEEDED"; stringp = TRUE; break;
            case DT_PLTRELSZ: name = "PLTRELSZ"; break;
            case DT_PLTGOT: name = "PLTGOT"; break;
            case DT_HASH: name = "HASH"; break;
@@ -943,8 +1155,8 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_SYMENT: name = "SYMENT"; break;
            case DT_INIT: name = "INIT"; break;
            case DT_FINI: name = "FINI"; break;
-           case DT_SONAME: name = "SONAME"; stringp = true; break;
-           case DT_RPATH: name = "RPATH"; stringp = true; break;
+           case DT_SONAME: name = "SONAME"; stringp = TRUE; break;
+           case DT_RPATH: name = "RPATH"; stringp = TRUE; break;
            case DT_SYMBOLIC: name = "SYMBOLIC"; break;
            case DT_REL: name = "REL"; break;
            case DT_RELSZ: name = "RELSZ"; break;
@@ -958,7 +1170,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_FINI_ARRAY: name = "FINI_ARRAY"; break;
            case DT_INIT_ARRAYSZ: name = "INIT_ARRAYSZ"; break;
            case DT_FINI_ARRAYSZ: name = "FINI_ARRAYSZ"; break;
-           case DT_RUNPATH: name = "RUNPATH"; stringp = true; break;
+           case DT_RUNPATH: name = "RUNPATH"; stringp = TRUE; break;
            case DT_FLAGS: name = "FLAGS"; break;
            case DT_PREINIT_ARRAY: name = "PREINIT_ARRAY"; break;
            case DT_PREINIT_ARRAYSZ: name = "PREINIT_ARRAYSZ"; break;
@@ -970,9 +1182,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_POSFLAG_1: name = "POSFLAG_1"; break;
            case DT_SYMINSZ: name = "SYMINSZ"; break;
            case DT_SYMINENT: name = "SYMINENT"; break;
-           case DT_CONFIG: name = "CONFIG"; stringp = true; break;
-           case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = true; break;
-           case DT_AUDIT: name = "AUDIT"; stringp = true; break;
+           case DT_CONFIG: name = "CONFIG"; stringp = TRUE; break;
+           case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = TRUE; break;
+           case DT_AUDIT: name = "AUDIT"; stringp = TRUE; break;
            case DT_PLTPAD: name = "PLTPAD"; break;
            case DT_MOVETAB: name = "MOVETAB"; break;
            case DT_SYMINFO: name = "SYMINFO"; break;
@@ -984,9 +1196,9 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_VERDEFNUM: name = "VERDEFNUM"; break;
            case DT_VERNEED: name = "VERNEED"; break;
            case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
-           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+           case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
            case DT_USED: name = "USED"; break;
-           case DT_FILTER: name = "FILTER"; stringp = true; break;
+           case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -1013,7 +1225,7 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
       || (elf_dynverref (abfd) != 0 && elf_tdata (abfd)->verref == NULL))
     {
       if (! _bfd_elf_slurp_version_tables (abfd))
-       return false;
+       return FALSE;
     }
 
   if (elf_dynverdef (abfd) != 0)
@@ -1055,12 +1267,12 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
        }
     }
 
-  return true;
+  return TRUE;
 
  error_return:
   if (dynbuf != NULL)
     free (dynbuf);
-  return false;
+  return FALSE;
 }
 
 /* Display ELF-specific fields of a symbol.  */
@@ -1212,17 +1424,17 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
 
       /* Set local fields.  */
       ret->indx = -1;
-      ret->size = 0;
       ret->dynindx = -1;
       ret->dynstr_index = 0;
+      ret->elf_hash_value = 0;
       ret->weakdef = NULL;
-      ret->got.refcount = htab->init_refcount;
-      ret->plt.refcount = htab->init_refcount;
-      ret->linker_section_pointer = NULL;
       ret->verinfo.verdef = NULL;
-      ret->vtable_entries_used = NULL;
       ret->vtable_entries_size = 0;
+      ret->vtable_entries_used = NULL;
       ret->vtable_parent = NULL;
+      ret->got = htab->init_refcount;
+      ret->plt = htab->init_refcount;
+      ret->size = 0;
       ret->type = STT_NOTYPE;
       ret->other = 0;
       /* Assume that we have been called by a non-ELF symbol reader.
@@ -1239,10 +1451,12 @@ _bfd_elf_link_hash_newfunc (entry, table, string)
    old indirect symbol.  Also used for copying flags to a weakdef.  */
 
 void
-_bfd_elf_link_hash_copy_indirect (dir, ind)
+_bfd_elf_link_hash_copy_indirect (bed, dir, ind)
+     struct elf_backend_data *bed;
      struct elf_link_hash_entry *dir, *ind;
 {
   bfd_signed_vma tmp;
+  bfd_signed_vma lowest_valid = bed->can_refcount;
 
   /* Copy down any references that we may have already seen to the
      symbol which just became indirect.  */
@@ -1260,22 +1474,22 @@ _bfd_elf_link_hash_copy_indirect (dir, ind)
   /* Copy over the global and procedure linkage table refcount entries.
      These may have been already set up by a check_relocs routine.  */
   tmp = dir->got.refcount;
-  if (tmp <= 0)
+  if (tmp < lowest_valid)
     {
       dir->got.refcount = ind->got.refcount;
       ind->got.refcount = tmp;
     }
   else
-    BFD_ASSERT (ind->got.refcount <= 0);
+    BFD_ASSERT (ind->got.refcount < lowest_valid);
 
   tmp = dir->plt.refcount;
-  if (tmp <= 0)
+  if (tmp < lowest_valid)
     {
       dir->plt.refcount = ind->plt.refcount;
       ind->plt.refcount = tmp;
     }
   else
-    BFD_ASSERT (ind->plt.refcount <= 0);
+    BFD_ASSERT (ind->plt.refcount < lowest_valid);
 
   if (dir->dynindx == -1)
     {
@@ -1292,9 +1506,9 @@ void
 _bfd_elf_link_hash_hide_symbol (info, h, force_local)
      struct bfd_link_info *info;
      struct elf_link_hash_entry *h;
-     boolean force_local;
+     bfd_boolean force_local;
 {
-  h->plt.offset = (bfd_vma) -1;
+  h->plt = elf_hash_table (info)->init_offset;
   h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
   if (force_local)
     {
@@ -1310,30 +1524,38 @@ _bfd_elf_link_hash_hide_symbol (info, h, force_local)
 
 /* Initialize an ELF linker hash table.  */
 
-boolean
+bfd_boolean
 _bfd_elf_link_hash_table_init (table, abfd, newfunc)
      struct elf_link_hash_table *table;
      bfd *abfd;
-     struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
-                                               struct bfd_hash_table *,
-                                               const char *));
+     struct bfd_hash_entry *(*newfunc)
+       PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+               const char *));
 {
-  boolean ret;
+  bfd_boolean ret;
 
-  table->dynamic_sections_created = false;
+  table->dynamic_sections_created = FALSE;
   table->dynobj = NULL;
-  table->init_refcount = get_elf_backend_data (abfd)->can_refcount - 1;
+  /* Make sure can_refcount is extended to the width and signedness of
+     init_refcount before we subtract one from it.  */
+  table->init_refcount.refcount = get_elf_backend_data (abfd)->can_refcount;
+  table->init_refcount.refcount -= 1;
+  table->init_offset.offset = -(bfd_vma) 1;
   /* The first dynamic symbol is a dummy.  */
   table->dynsymcount = 1;
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
-  table->runpath = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->merge_info = NULL;
+  memset (&table->eh_info, 0, sizeof (table->eh_info));
   table->dynlocal = NULL;
-  ret = _bfd_link_hash_table_init (& table->root, abfd, newfunc);
+  table->runpath = NULL;
+  table->tls_segment = NULL;
+  table->loaded = NULL;
+
+  ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc);
   table->root.type = bfd_link_elf_hash_table;
 
   return ret;
@@ -1348,13 +1570,13 @@ _bfd_elf_link_hash_table_create (abfd)
   struct elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
-  ret = (struct elf_link_hash_table *) bfd_alloc (abfd, amt);
+  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
   if (ret == (struct elf_link_hash_table *) NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return NULL;
     }
 
@@ -1394,7 +1616,7 @@ bfd_elf_get_needed_list (abfd, info)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (! is_elf_hash_table (info))
     return NULL;
   return elf_hash_table (info)->needed;
 }
@@ -1407,7 +1629,7 @@ bfd_elf_get_runpath_list (abfd, info)
      bfd *abfd ATTRIBUTE_UNUSED;
      struct bfd_link_info *info;
 {
-  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+  if (! is_elf_hash_table (info))
     return NULL;
   return elf_hash_table (info)->runpath;
 }
@@ -1429,7 +1651,7 @@ bfd_elf_get_dt_soname (abfd)
 /* Get the list of DT_NEEDED entries from a BFD.  This is a hook for
    the ELF linker emulation code.  */
 
-boolean
+bfd_boolean
 bfd_elf_get_bfd_needed_list (abfd, pneeded)
      bfd *abfd;
      struct bfd_link_needed_list **pneeded;
@@ -1446,11 +1668,11 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
 
   if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
       || bfd_get_format (abfd) != bfd_object)
-    return true;
+    return TRUE;
 
   s = bfd_get_section_by_name (abfd, ".dynamic");
   if (s == NULL || s->_raw_size == 0)
-    return true;
+    return TRUE;
 
   dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
   if (dynbuf == NULL)
@@ -1505,12 +1727,12 @@ bfd_elf_get_bfd_needed_list (abfd, pneeded)
 
   free (dynbuf);
 
-  return true;
+  return TRUE;
 
  error_return:
   if (dynbuf != NULL)
     free (dynbuf);
-  return false;
+  return FALSE;
 }
 \f
 /* Allocate an ELF string table--force the first byte to be zero.  */
@@ -1525,7 +1747,7 @@ _bfd_elf_stringtab_init ()
     {
       bfd_size_type loc;
 
-      loc = _bfd_stringtab_add (ret, "", true, false);
+      loc = _bfd_stringtab_add (ret, "", TRUE, FALSE);
       BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
       if (loc == (bfd_size_type) -1)
        {
@@ -1540,7 +1762,7 @@ _bfd_elf_stringtab_init ()
 
 /* Create a new bfd section from an ELF section header.  */
 
-boolean
+bfd_boolean
 bfd_section_from_shdr (abfd, shindex)
      bfd *abfd;
      unsigned int shindex;
@@ -1548,7 +1770,7 @@ bfd_section_from_shdr (abfd, shindex)
   Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
   Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  char *name;
+  const char *name;
 
   name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
 
@@ -1556,10 +1778,9 @@ bfd_section_from_shdr (abfd, shindex)
     {
     case SHT_NULL:
       /* Inactive section. Throw it away.  */
-      return true;
+      return TRUE;
 
     case SHT_PROGBITS: /* Normal section with contents.  */
-    case SHT_DYNAMIC:  /* Dynamic linking information.  */
     case SHT_NOBITS:   /* .bss section.  */
     case SHT_HASH:     /* .hash section.  */
     case SHT_NOTE:     /* .note section.  */
@@ -1568,9 +1789,42 @@ bfd_section_from_shdr (abfd, shindex)
     case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
+    case SHT_DYNAMIC:  /* Dynamic linking information.  */
+      if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+       return FALSE;
+      if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_STRTAB)
+       {
+         Elf_Internal_Shdr *dynsymhdr;
+
+         /* The shared libraries distributed with hpux11 have a bogus
+            sh_link field for the ".dynamic" section.  Find the
+            string table for the ".dynsym" section instead.  */
+         if (elf_dynsymtab (abfd) != 0)
+           {
+             dynsymhdr = elf_elfsections (abfd)[elf_dynsymtab (abfd)];
+             hdr->sh_link = dynsymhdr->sh_link;
+           }
+         else
+           {
+             unsigned int i, num_sec;
+
+             num_sec = elf_numsections (abfd);
+             for (i = 1; i < num_sec; i++)
+               {
+                 dynsymhdr = elf_elfsections (abfd)[i];
+                 if (dynsymhdr->sh_type == SHT_DYNSYM)
+                   {
+                     hdr->sh_link = dynsymhdr->sh_link;
+                     break;
+                   }
+               }
+           }
+       }
+      break;
+
     case SHT_SYMTAB:           /* A symbol table */
       if (elf_onesymtab (abfd) == shindex)
-       return true;
+       return TRUE;
 
       BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
@@ -1583,18 +1837,18 @@ bfd_section_from_shdr (abfd, shindex)
          SHF_ALLOC is set, and this is a shared object, then we also
          treat this section as a BFD section.  We can not base the
          decision purely on SHF_ALLOC, because that flag is sometimes
-         set in a relocateable object file, which would confuse the
+         set in a relocatable object file, which would confuse the
          linker.  */
       if ((hdr->sh_flags & SHF_ALLOC) != 0
          && (abfd->flags & DYNAMIC) != 0
          && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
-       return false;
+       return FALSE;
 
-      return true;
+      return TRUE;
 
     case SHT_DYNSYM:           /* A dynamic symbol table */
       if (elf_dynsymtab (abfd) == shindex)
-       return true;
+       return TRUE;
 
       BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
       BFD_ASSERT (elf_dynsymtab (abfd) == 0);
@@ -1609,26 +1863,26 @@ bfd_section_from_shdr (abfd, shindex)
 
     case SHT_SYMTAB_SHNDX:     /* Symbol section indices when >64k sections */
       if (elf_symtab_shndx (abfd) == shindex)
-       return true;
+       return TRUE;
 
       /* Get the associated symbol table.  */
       if (! bfd_section_from_shdr (abfd, hdr->sh_link)
          || hdr->sh_link != elf_onesymtab (abfd))
-       return false;
+       return FALSE;
 
       elf_symtab_shndx (abfd) = shindex;
       elf_tdata (abfd)->symtab_shndx_hdr = *hdr;
       elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->symtab_shndx_hdr;
-      return true;
+      return TRUE;
 
     case SHT_STRTAB:           /* A string table */
       if (hdr->bfd_section != NULL)
-       return true;
+       return TRUE;
       if (ehdr->e_shstrndx == shindex)
        {
          elf_tdata (abfd)->shstrtab_hdr = *hdr;
          elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
-         return true;
+         return TRUE;
        }
       {
        unsigned int i, num_sec;
@@ -1640,13 +1894,13 @@ bfd_section_from_shdr (abfd, shindex)
            if (hdr2->sh_link == shindex)
              {
                if (! bfd_section_from_shdr (abfd, i))
-                 return false;
+                 return FALSE;
                if (elf_onesymtab (abfd) == i)
                  {
                    elf_tdata (abfd)->strtab_hdr = *hdr;
                    elf_elfsections (abfd)[shindex] =
                      &elf_tdata (abfd)->strtab_hdr;
-                   return true;
+                   return TRUE;
                  }
                if (elf_dynsymtab (abfd) == i)
                  {
@@ -1726,7 +1980,7 @@ bfd_section_from_shdr (abfd, shindex)
        /* Get the symbol table.  */
        if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
            && ! bfd_section_from_shdr (abfd, hdr->sh_link))
-         return false;
+         return FALSE;
 
        /* If this reloc section does not use the main symbol table we
           don't treat it as a reloc section.  BFD can't adequately
@@ -1738,10 +1992,10 @@ bfd_section_from_shdr (abfd, shindex)
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
-         return false;
+         return FALSE;
        target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
        if (target_sect == NULL)
-         return false;
+         return FALSE;
 
        if ((target_sect->flags & SEC_RELOC) == 0
            || target_sect->reloc_count == 0)
@@ -1763,10 +2017,9 @@ bfd_section_from_shdr (abfd, shindex)
        /* In the section to which the relocations apply, mark whether
           its relocations are of the REL or RELA variety.  */
        if (hdr->sh_size != 0)
-         elf_section_data (target_sect)->use_rela_p
-           = (hdr->sh_type == SHT_RELA);
+         target_sect->use_rela_p = hdr->sh_type == SHT_RELA;
        abfd->flags |= HAS_RELOC;
-       return true;
+       return TRUE;
       }
       break;
 
@@ -1789,18 +2042,27 @@ bfd_section_from_shdr (abfd, shindex)
       break;
 
     case SHT_SHLIB:
-      return true;
+      return TRUE;
 
     case SHT_GROUP:
-      /* Make a section for objcopy and relocatable links.  */
+      /* We need a BFD section for objcopy and relocatable linking,
+        and it's handy to have the signature available as the section
+        name.  */
+      name = group_signature (abfd, hdr);
+      if (name == NULL)
+       return FALSE;
       if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name))
-       return false;
+       return FALSE;
       if (hdr->contents != NULL)
        {
          Elf_Internal_Group *idx = (Elf_Internal_Group *) hdr->contents;
          unsigned int n_elt = hdr->sh_size / 4;
          asection *s;
 
+         if (idx->flags & GRP_COMDAT)
+           hdr->bfd_section->flags
+             |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
+
          while (--n_elt != 0)
            if ((s = (++idx)->shdr->bfd_section) != NULL
                && elf_next_in_group (s) != NULL)
@@ -1820,7 +2082,7 @@ bfd_section_from_shdr (abfd, shindex)
       break;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Return the section for the local symbol specified by ABFD, R_SYMNDX.
@@ -1833,50 +2095,19 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
      asection *sec;
      unsigned long r_symndx;
 {
-  unsigned char esym_shndx[4];
-  unsigned int isym_shndx;
   Elf_Internal_Shdr *symtab_hdr;
-  file_ptr pos;
-  bfd_size_type amt;
+  unsigned char esym[sizeof (Elf64_External_Sym)];
+  Elf_External_Sym_Shndx eshndx;
+  Elf_Internal_Sym isym;
   unsigned int ent = r_symndx % LOCAL_SYM_CACHE_SIZE;
 
   if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
     return cache->sec[ent];
 
   symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  pos = symtab_hdr->sh_offset;
-  if (get_elf_backend_data (abfd)->s->sizeof_sym
-      == sizeof (Elf64_External_Sym))
-    {
-      pos += r_symndx * sizeof (Elf64_External_Sym);
-      pos += offsetof (Elf64_External_Sym, st_shndx);
-      amt = sizeof (((Elf64_External_Sym *) 0)->st_shndx);
-    }
-  else
-    {
-      pos += r_symndx * sizeof (Elf32_External_Sym);
-      pos += offsetof (Elf32_External_Sym, st_shndx);
-      amt = sizeof (((Elf32_External_Sym *) 0)->st_shndx);
-    }
-  if (bfd_seek (abfd, pos, SEEK_SET) != 0
-      || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
+  if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
+                           &isym, esym, &eshndx) == NULL)
     return NULL;
-  isym_shndx = H_GET_16 (abfd, esym_shndx);
-
-  if (isym_shndx == SHN_XINDEX)
-    {
-      Elf_Internal_Shdr *shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (shndx_hdr->sh_size != 0)
-       {
-         pos = shndx_hdr->sh_offset;
-         pos += r_symndx * sizeof (Elf_External_Sym_Shndx);
-         amt = sizeof (Elf_External_Sym_Shndx);
-         if (bfd_seek (abfd, pos, SEEK_SET) != 0
-             || bfd_bread ((PTR) esym_shndx, amt, abfd) != amt)
-           return NULL;
-         isym_shndx = H_GET_32 (abfd, esym_shndx);
-       }
-    }
 
   if (cache->abfd != abfd)
     {
@@ -1885,10 +2116,10 @@ bfd_section_from_r_symndx (abfd, cache, sec, r_symndx)
     }
   cache->indx[ent] = r_symndx;
   cache->sec[ent] = sec;
-  if (isym_shndx < SHN_LORESERVE || isym_shndx > SHN_HIRESERVE)
+  if (isym.st_shndx < SHN_LORESERVE || isym.st_shndx > SHN_HIRESERVE)
     {
       asection *s;
-      s = bfd_section_from_elf_index (abfd, isym_shndx);
+      s = bfd_section_from_elf_index (abfd, isym.st_shndx);
       if (s != NULL)
        cache->sec[ent] = s;
     }
@@ -1908,24 +2139,27 @@ bfd_section_from_elf_index (abfd, index)
   return elf_elfsections (abfd)[index]->bfd_section;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_new_section_hook (abfd, sec)
      bfd *abfd;
      asection *sec;
 {
   struct bfd_elf_section_data *sdata;
-  bfd_size_type amt = sizeof (*sdata);
 
-  sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
-  if (!sdata)
-    return false;
-  sec->used_by_bfd = (PTR) sdata;
+  sdata = (struct bfd_elf_section_data *) sec->used_by_bfd;
+  if (sdata == NULL)
+    {
+      bfd_size_type amt = sizeof (*sdata);
+      sdata = (struct bfd_elf_section_data *) bfd_zalloc (abfd, amt);
+      if (sdata == NULL)
+       return FALSE;
+      sec->used_by_bfd = (PTR) sdata;
+    }
 
   /* Indicate whether or not this section should use RELA relocations.  */
-  sdata->use_rela_p
-    = get_elf_backend_data (abfd)->default_use_rela_p;
+  sec->use_rela_p = get_elf_backend_data (abfd)->default_use_rela_p;
 
-  return true;
+  return TRUE;
 }
 
 /* Create a new bfd section from an ELF program header.
@@ -1950,7 +2184,7 @@ _bfd_elf_new_section_hook (abfd, sec)
 
  */
 
-boolean
+bfd_boolean
 _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
      bfd *abfd;
      Elf_Internal_Phdr *hdr;
@@ -1960,19 +2194,21 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
   asection *newsect;
   char *name;
   char namebuf[64];
+  size_t len;
   int split;
 
   split = ((hdr->p_memsz > 0)
            && (hdr->p_filesz > 0)
            && (hdr->p_memsz > hdr->p_filesz));
   sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
-  name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
+  len = strlen (namebuf) + 1;
+  name = bfd_alloc (abfd, (bfd_size_type) len);
   if (!name)
-    return false;
-  strcpy (name, namebuf);
+    return FALSE;
+  memcpy (name, namebuf, len);
   newsect = bfd_make_section (abfd, name);
   if (newsect == NULL)
-    return false;
+    return FALSE;
   newsect->vma = hdr->p_vaddr;
   newsect->lma = hdr->p_paddr;
   newsect->_raw_size = hdr->p_filesz;
@@ -1997,13 +2233,14 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
   if (split)
     {
       sprintf (namebuf, "%s%db", typename, index);
-      name = bfd_alloc (abfd, (bfd_size_type) strlen (namebuf) + 1);
+      len = strlen (namebuf) + 1;
+      name = bfd_alloc (abfd, (bfd_size_type) len);
       if (!name)
-       return false;
-      strcpy (name, namebuf);
+       return FALSE;
+      memcpy (name, namebuf, len);
       newsect = bfd_make_section (abfd, name);
       if (newsect == NULL)
-       return false;
+       return FALSE;
       newsect->vma = hdr->p_vaddr + hdr->p_filesz;
       newsect->lma = hdr->p_paddr + hdr->p_filesz;
       newsect->_raw_size = hdr->p_memsz - hdr->p_filesz;
@@ -2017,10 +2254,10 @@ _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename)
        newsect->flags |= SEC_READONLY;
     }
 
-  return true;
+  return TRUE;
 }
 
-boolean
+bfd_boolean
 bfd_section_from_phdr (abfd, hdr, index)
      bfd *abfd;
      Elf_Internal_Phdr *hdr;
@@ -2044,10 +2281,10 @@ bfd_section_from_phdr (abfd, hdr, index)
 
     case PT_NOTE:
       if (! _bfd_elf_make_section_from_phdr (abfd, hdr, index, "note"))
-       return false;
+       return FALSE;
       if (! elfcore_read_notes (abfd, (file_ptr) hdr->p_offset, hdr->p_filesz))
-       return false;
-      return true;
+       return FALSE;
+      return TRUE;
 
     case PT_SHLIB:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "shlib");
@@ -2055,6 +2292,13 @@ bfd_section_from_phdr (abfd, hdr, index)
     case PT_PHDR:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "phdr");
 
+    case PT_GNU_EH_FRAME:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+                                             "eh_frame_hdr");
+
+    case PT_GNU_STACK:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index, "stack");
+
     default:
       /* Check for any processor-specific program segment types.
          If no handler for them, default to making "segment" sections.  */
@@ -2067,15 +2311,15 @@ bfd_section_from_phdr (abfd, hdr, index)
 }
 
 /* Initialize REL_HDR, the section-header for new section, containing
-   relocations against ASECT.  If USE_RELA_P is true, we use RELA
+   relocations against ASECT.  If USE_RELA_P is TRUE, we use RELA
    relocations; otherwise, we use REL relocations.  */
 
-boolean
+bfd_boolean
 _bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
      bfd *abfd;
      Elf_Internal_Shdr *rel_hdr;
      asection *asect;
-     boolean use_rela_p;
+     bfd_boolean use_rela_p;
 {
   char *name;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
@@ -2083,24 +2327,24 @@ _bfd_elf_init_reloc_shdr (abfd, rel_hdr, asect, use_rela_p)
 
   name = bfd_alloc (abfd, amt);
   if (name == NULL)
-    return false;
+    return FALSE;
   sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
   rel_hdr->sh_name =
     (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd), name,
-                                       false);
+                                       FALSE);
   if (rel_hdr->sh_name == (unsigned int) -1)
-    return false;
+    return FALSE;
   rel_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
   rel_hdr->sh_entsize = (use_rela_p
                         ? bed->s->sizeof_rela
                         : bed->s->sizeof_rel);
-  rel_hdr->sh_addralign = bed->s->file_align;
+  rel_hdr->sh_addralign = 1 << bed->s->log_file_align;
   rel_hdr->sh_flags = 0;
   rel_hdr->sh_addr = 0;
   rel_hdr->sh_size = 0;
   rel_hdr->sh_offset = 0;
 
-  return true;
+  return TRUE;
 }
 
 /* Set up an ELF internal section header for a section.  */
@@ -2112,7 +2356,7 @@ elf_fake_sections (abfd, asect, failedptrarg)
      PTR failedptrarg;
 {
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  boolean *failedptr = (boolean *) failedptrarg;
+  bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
   Elf_Internal_Shdr *this_hdr;
 
   if (*failedptr)
@@ -2124,11 +2368,11 @@ elf_fake_sections (abfd, asect, failedptrarg)
 
   this_hdr = &elf_section_data (asect)->this_hdr;
 
-  this_hdr->sh_name = (unsigned long) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-                                                          asect->name, false);
-  if (this_hdr->sh_name == (unsigned long) -1)
+  this_hdr->sh_name = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
+                                                         asect->name, FALSE);
+  if (this_hdr->sh_name == (unsigned int) -1)
     {
-      *failedptr = true;
+      *failedptr = TRUE;
       return;
     }
 
@@ -2247,13 +2491,28 @@ elf_fake_sections (abfd, asect, failedptrarg)
       if ((asect->flags & SEC_STRINGS) != 0)
        this_hdr->sh_flags |= SHF_STRINGS;
     }
-  if (elf_group_name (asect) != NULL)
+  if ((asect->flags & SEC_GROUP) == 0 && elf_group_name (asect) != NULL)
     this_hdr->sh_flags |= SHF_GROUP;
+  if ((asect->flags & SEC_THREAD_LOCAL) != 0)
+    {
+      this_hdr->sh_flags |= SHF_TLS;
+      if (asect->_raw_size == 0 && (asect->flags & SEC_HAS_CONTENTS) == 0)
+       {
+         struct bfd_link_order *o;
+
+         this_hdr->sh_size = 0;
+         for (o = asect->link_order_head; o != NULL; o = o->next)
+           if (this_hdr->sh_size < o->offset + o->size)
+             this_hdr->sh_size = o->offset + o->size;
+         if (this_hdr->sh_size)
+           this_hdr->sh_type = SHT_NOBITS;
+       }
+    }
 
   /* Check for processor-specific section types.  */
   if (bed->elf_backend_fake_sections
       && !(*bed->elf_backend_fake_sections) (abfd, this_hdr, asect))
-    *failedptr = true;
+    *failedptr = TRUE;
 
   /* If the section has relocs, set up a section header for the
      SHT_REL[A] section.  If two relocation sections are required for
@@ -2263,53 +2522,66 @@ elf_fake_sections (abfd, asect, failedptrarg)
       && !_bfd_elf_init_reloc_shdr (abfd,
                                    &elf_section_data (asect)->rel_hdr,
                                    asect,
-                                   elf_section_data (asect)->use_rela_p))
-    *failedptr = true;
+                                   asect->use_rela_p))
+    *failedptr = TRUE;
 }
 
 /* Fill in the contents of a SHT_GROUP section.  */
 
-static void
-set_group_contents (abfd, sec, failedptrarg)
+void
+bfd_elf_set_group_contents (abfd, sec, failedptrarg)
      bfd *abfd;
      asection *sec;
-     PTR failedptrarg ATTRIBUTE_UNUSED;
+     PTR failedptrarg;
 {
-  boolean *failedptr = (boolean *) failedptrarg;
+  bfd_boolean *failedptr = (bfd_boolean *) failedptrarg;
   unsigned long symindx;
-  asection *elt;
+  asection *elt, *first;
   unsigned char *loc;
   struct bfd_link_order *l;
+  bfd_boolean gas;
 
   if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
       || *failedptr)
     return;
 
-  /* If called from the assembler, swap_out_syms will have set up
-     elf_section_syms;  If called for "ld -r", the symbols won't yet
-     be mapped, so emulate elf_bfd_final_link.  */
-  if (elf_section_syms (abfd) != NULL)
-    symindx = elf_section_syms (abfd)[sec->index]->udata.i;
-  else
-    symindx = elf_section_data (sec)->this_idx;
+  symindx = 0;
+  if (elf_group_id (sec) != NULL)
+    symindx = elf_group_id (sec)->udata.i;
+
+  if (symindx == 0)
+    {
+      /* If called from the assembler, swap_out_syms will have set up
+        elf_section_syms;  If called for "ld -r", use target_index.  */
+      if (elf_section_syms (abfd) != NULL)
+       symindx = elf_section_syms (abfd)[sec->index]->udata.i;
+      else
+       symindx = sec->target_index;
+    }
   elf_section_data (sec)->this_hdr.sh_info = symindx;
 
-  /* Nor will the contents be allocated for "ld -r".  */
+  /* The contents won't be allocated for "ld -r" or objcopy.  */
+  gas = TRUE;
   if (sec->contents == NULL)
     {
+      gas = FALSE;
       sec->contents = bfd_alloc (abfd, sec->_raw_size);
+
+      /* Arrange for the section to be written out.  */
+      elf_section_data (sec)->this_hdr.contents = sec->contents;
       if (sec->contents == NULL)
        {
-         *failedptr = true;
+         *failedptr = TRUE;
          return;
        }
     }
 
   loc = sec->contents + sec->_raw_size;
 
-  /* Get the pointer to the first section in the group that we
-     squirreled away here.  */
-  elt = elf_next_in_group (sec);
+  /* Get the pointer to the first section in the group that gas
+     squirreled away here.  objcopy arranges for this to be set to the
+     start of the input section group.  */
+  first = elt = elf_next_in_group (sec);
 
   /* First element is a flag word.  Rest of section is elf section
      indices for all the sections of the group.  Write them backwards
@@ -2317,9 +2589,20 @@ set_group_contents (abfd, sec, failedptrarg)
      directives, not that it matters.  */
   while (elt != NULL)
     {
+      asection *s;
+      unsigned int idx;
+
       loc -= 4;
-      H_PUT_32 (abfd, elf_section_data (elt)->this_idx, loc);
+      s = elt;
+      if (!gas)
+       s = s->output_section;
+      idx = 0;
+      if (s != NULL)
+       idx = elf_section_data (s)->this_idx;
+      H_PUT_32 (abfd, idx, loc);
       elt = elf_next_in_group (elt);
+      if (elt == first)
+       break;
     }
 
   /* If this is a relocatable link, then the above did nothing because
@@ -2338,17 +2621,23 @@ set_group_contents (abfd, sec, failedptrarg)
        }
       while (elt != elf_next_in_group (l->u.indirect.section));
 
-  loc -= 4;
-  H_PUT_32 (abfd, 0, loc);
+  /* With ld -r, merging SHT_GROUP sections results in wasted space
+     due to allowing for the flag word on each input.  We may well
+     duplicate entries too.  */
+  while ((loc -= 4) > sec->contents)
+    H_PUT_32 (abfd, 0, loc);
+
+  if (loc != sec->contents)
+    abort ();
 
-  BFD_ASSERT (loc == sec->contents);
+  H_PUT_32 (abfd, sec->flags & SEC_LINK_ONCE ? GRP_COMDAT : 0, loc);
 }
 
 /* Assign all ELF section numbers.  The dummy first section is handled here
    too.  The link/info pointers for the standard section types are filled
    in here too, while we're at it.  */
 
-static boolean
+static bfd_boolean
 assign_section_numbers (abfd)
      bfd *abfd;
 {
@@ -2410,9 +2699,9 @@ assign_section_numbers (abfd)
          t->symtab_shndx_section = section_number++;
          t->symtab_shndx_hdr.sh_name
            = (unsigned int) _bfd_elf_strtab_add (elf_shstrtab (abfd),
-                                                 ".symtab_shndx", false);
+                                                 ".symtab_shndx", FALSE);
          if (t->symtab_shndx_hdr.sh_name == (unsigned int) -1)
-           return false;
+           return FALSE;
        }
       if (section_number == SHN_LORESERVE)
        section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
@@ -2431,18 +2720,17 @@ assign_section_numbers (abfd)
   /* Set up the list of section header pointers, in agreement with the
      indices.  */
   amt = section_number * sizeof (Elf_Internal_Shdr *);
-  i_shdrp = (Elf_Internal_Shdr **) bfd_alloc (abfd, amt);
+  i_shdrp = (Elf_Internal_Shdr **) bfd_zalloc (abfd, amt);
   if (i_shdrp == NULL)
-    return false;
+    return FALSE;
 
   amt = sizeof (Elf_Internal_Shdr);
-  i_shdrp[0] = (Elf_Internal_Shdr *) bfd_alloc (abfd, amt);
+  i_shdrp[0] = (Elf_Internal_Shdr *) bfd_zalloc (abfd, amt);
   if (i_shdrp[0] == NULL)
     {
       bfd_release (abfd, i_shdrp);
-      return false;
+      return FALSE;
     }
-  memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
 
   elf_elfsections (abfd) = i_shdrp;
 
@@ -2523,10 +2811,10 @@ assign_section_numbers (abfd)
              char *alc;
 
              len = strlen (sec->name);
-             alc = (char *) bfd_malloc ((bfd_size_type) len - 2);
+             alc = (char *) bfd_malloc ((bfd_size_type) (len - 2));
              if (alc == NULL)
-               return false;
-             strncpy (alc, sec->name, len - 3);
+               return FALSE;
+             memcpy (alc, sec->name, len - 3);
              alc[len - 3] = '\0';
              s = bfd_get_section_by_name (abfd, alc);
              free (alc);
@@ -2535,8 +2823,9 @@ assign_section_numbers (abfd)
                  elf_section_data (s)->this_hdr.sh_link = d->this_idx;
 
                  /* This is a .stab section.  */
-                 elf_section_data (s)->this_hdr.sh_entsize =
-                   4 + 2 * bfd_get_arch_size (abfd) / 8;
+                 if (elf_section_data (s)->this_hdr.sh_entsize == 0)
+                   elf_section_data (s)->this_hdr.sh_entsize
+                     = 4 + 2 * bfd_get_arch_size (abfd) / 8;
                }
            }
          break;
@@ -2573,7 +2862,7 @@ assign_section_numbers (abfd)
     else
       i_shdrp[secn]->sh_name = _bfd_elf_strtab_offset (elf_shstrtab (abfd),
                                                       i_shdrp[secn]->sh_name);
-  return true;
+  return TRUE;
 }
 
 /* Map symbol from it's internal number to the external number, moving
@@ -2594,7 +2883,7 @@ sym_is_global (abfd, sym)
          || bfd_is_com_section (bfd_get_section (sym)));
 }
 
-static boolean
+static bfd_boolean
 elf_map_symbols (abfd)
      bfd *abfd;
 {
@@ -2626,7 +2915,7 @@ elf_map_symbols (abfd)
   amt = max_index * sizeof (asymbol *);
   sect_syms = (asymbol **) bfd_zalloc (abfd, amt);
   if (sect_syms == NULL)
-    return false;
+    return FALSE;
   elf_section_syms (abfd) = sect_syms;
   elf_num_section_syms (abfd) = max_index;
 
@@ -2701,7 +2990,7 @@ elf_map_symbols (abfd)
   new_syms = (asymbol **) bfd_alloc (abfd, amt);
 
   if (new_syms == NULL)
-    return false;
+    return FALSE;
 
   for (idx = 0; idx < symcount; idx++)
     {
@@ -2736,13 +3025,14 @@ elf_map_symbols (abfd)
 
   elf_num_locals (abfd) = num_locals;
   elf_num_globals (abfd) = num_globals;
-  return true;
+  return TRUE;
 }
 
 /* Align to the maximum file alignment that could be required for any
    ELF data structure.  */
 
-static INLINE file_ptr align_file_position PARAMS ((file_ptr, int));
+static INLINE file_ptr align_file_position
+  PARAMS ((file_ptr, int));
 static INLINE file_ptr
 align_file_position (off, align)
      file_ptr off;
@@ -2758,7 +3048,7 @@ INLINE file_ptr
 _bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
      Elf_Internal_Shdr *i_shdrp;
      file_ptr offset;
-     boolean align;
+     bfd_boolean align;
 {
   if (align)
     {
@@ -2780,37 +3070,37 @@ _bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
    otherwise prepare to begin writing out the ELF file.  If LINK_INFO
    is not NULL, this is being called by the ELF backend linker.  */
 
-boolean
+bfd_boolean
 _bfd_elf_compute_section_file_positions (abfd, link_info)
      bfd *abfd;
      struct bfd_link_info *link_info;
 {
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  boolean failed;
+  bfd_boolean failed;
   struct bfd_strtab_hash *strtab;
   Elf_Internal_Shdr *shstrtab_hdr;
 
   if (abfd->output_has_begun)
-    return true;
+    return TRUE;
 
   /* Do any elf backend specific processing first.  */
   if (bed->elf_backend_begin_write_processing)
     (*bed->elf_backend_begin_write_processing) (abfd, link_info);
 
   if (! prep_headers (abfd))
-    return false;
+    return FALSE;
 
   /* Post process the headers if necessary.  */
   if (bed->elf_backend_post_process_headers)
     (*bed->elf_backend_post_process_headers) (abfd, link_info);
 
-  failed = false;
+  failed = FALSE;
   bfd_map_over_sections (abfd, elf_fake_sections, &failed);
   if (failed)
-    return false;
+    return FALSE;
 
   if (!assign_section_numbers (abfd))
-    return false;
+    return FALSE;
 
   /* The backend linker builds symbol table information itself.  */
   if (link_info == NULL && bfd_get_symcount (abfd) > 0)
@@ -2819,14 +3109,14 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       int relocatable_p = ! (abfd->flags & (EXEC_P | DYNAMIC));
 
       if (! swap_out_syms (abfd, &strtab, relocatable_p))
-       return false;
+       return FALSE;
     }
 
-  if (link_info == NULL || link_info->relocateable)
+  if (link_info == NULL)
     {
-      bfd_map_over_sections (abfd, set_group_contents, &failed);
+      bfd_map_over_sections (abfd, bfd_elf_set_group_contents, &failed);
       if (failed)
-       return false;
+       return FALSE;
     }
 
   shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
@@ -2842,7 +3132,7 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
   shstrtab_hdr->sh_addralign = 1;
 
   if (!assign_file_positions_except_relocs (abfd))
-    return false;
+    return FALSE;
 
   if (link_info == NULL && bfd_get_symcount (abfd) > 0)
     {
@@ -2852,14 +3142,14 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
       off = elf_tdata (abfd)->next_file_pos;
 
       hdr = &elf_tdata (abfd)->symtab_hdr;
-      off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+      off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
       if (hdr->sh_size != 0)
-       off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+       off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       hdr = &elf_tdata (abfd)->strtab_hdr;
-      off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+      off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
       elf_tdata (abfd)->next_file_pos = off;
 
@@ -2867,13 +3157,13 @@ _bfd_elf_compute_section_file_positions (abfd, link_info)
          out.  */
       if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
          || ! _bfd_stringtab_emit (abfd, strtab))
-       return false;
+       return FALSE;
       _bfd_stringtab_free (strtab);
     }
 
-  abfd->output_has_begun = true;
+  abfd->output_has_begun = TRUE;
 
-  return true;
+  return TRUE;
 }
 
 /* Create a mapping from a set of sections to a program segment.  */
@@ -2884,7 +3174,7 @@ make_mapping (abfd, sections, from, to, phdr)
      asection **sections;
      unsigned int from;
      unsigned int to;
-     boolean phdr;
+     bfd_boolean phdr;
 {
   struct elf_segment_map *m;
   unsigned int i;
@@ -2914,7 +3204,7 @@ make_mapping (abfd, sections, from, to, phdr)
 
 /* Set up a mapping from BFD sections to program segments.  */
 
-static boolean
+static bfd_boolean
 map_sections_to_segments (abfd)
      bfd *abfd;
 {
@@ -2929,16 +3219,18 @@ map_sections_to_segments (abfd)
   unsigned int phdr_index;
   bfd_vma maxpagesize;
   asection **hdrpp;
-  boolean phdr_in_segment = true;
-  boolean writable;
+  bfd_boolean phdr_in_segment = TRUE;
+  bfd_boolean writable;
+  int tls_count = 0;
+  asection *first_tls = NULL;
   asection *dynsec, *eh_frame_hdr;
   bfd_size_type amt;
 
   if (elf_tdata (abfd)->segment_map != NULL)
-    return true;
+    return TRUE;
 
   if (bfd_count_sections (abfd) == 0)
-    return true;
+    return TRUE;
 
   /* Select the allocated sections, and sort them.  */
 
@@ -3005,7 +3297,7 @@ map_sections_to_segments (abfd)
   last_hdr = NULL;
   phdr_index = 0;
   maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
-  writable = false;
+  writable = FALSE;
   dynsec = bfd_get_section_by_name (abfd, ".dynamic");
   if (dynsec != NULL
       && (dynsec->flags & SEC_LOAD) == 0)
@@ -3025,13 +3317,13 @@ map_sections_to_segments (abfd)
       if ((abfd->flags & D_PAGED) == 0
          || sections[0]->lma < phdr_size
          || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
-       phdr_in_segment = false;
+       phdr_in_segment = FALSE;
     }
 
   for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
     {
       asection *hdr;
-      boolean new_segment;
+      bfd_boolean new_segment;
 
       hdr = *hdrpp;
 
@@ -3042,40 +3334,41 @@ map_sections_to_segments (abfd)
        {
          /* If we don't have a segment yet, then we don't need a new
             one (we build the last one after this loop).  */
-         new_segment = false;
+         new_segment = FALSE;
        }
       else if (last_hdr->lma - last_hdr->vma != hdr->lma - hdr->vma)
        {
          /* If this section has a different relation between the
              virtual address and the load address, then we need a new
              segment.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
       else if (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
               < BFD_ALIGN (hdr->lma, maxpagesize))
        {
          /* If putting this section in this segment would force us to
              skip a page in the segment, then we need a new segment.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
       else if ((last_hdr->flags & SEC_LOAD) == 0
               && (hdr->flags & SEC_LOAD) != 0)
        {
          /* We don't want to put a loadable section after a
              nonloadable section in the same segment.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
       else if ((abfd->flags & D_PAGED) == 0)
        {
          /* If the file is not demand paged, which means that we
              don't require the sections to be correctly aligned in the
              file, then there is no other reason for a new segment.  */
-         new_segment = false;
+         new_segment = FALSE;
        }
       else if (! writable
               && (hdr->flags & SEC_READONLY) == 0
-              && (BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
-                  == hdr->lma))
+              && (((last_hdr->lma + last_hdr->_raw_size - 1)
+                   & ~(maxpagesize - 1))
+                  != (hdr->lma & ~(maxpagesize - 1))))
        {
          /* We don't want to put a writable section in a read only
              segment, unless they are on the same page in memory
@@ -3084,18 +3377,18 @@ map_sections_to_segments (abfd)
              only case in which the new section is not on the same
              page as the previous section is when the previous section
              ends precisely on a page boundary.  */
-         new_segment = true;
+         new_segment = TRUE;
        }
       else
        {
          /* Otherwise, we can use the same segment.  */
-         new_segment = false;
+         new_segment = FALSE;
        }
 
       if (! new_segment)
        {
          if ((hdr->flags & SEC_READONLY) == 0)
-           writable = true;
+           writable = TRUE;
          last_hdr = hdr;
          continue;
        }
@@ -3111,13 +3404,13 @@ map_sections_to_segments (abfd)
       pm = &m->next;
 
       if ((hdr->flags & SEC_READONLY) == 0)
-       writable = true;
+       writable = TRUE;
       else
-       writable = false;
+       writable = FALSE;
 
       last_hdr = hdr;
       phdr_index = i;
-      phdr_in_segment = false;
+      phdr_in_segment = FALSE;
     }
 
   /* Create a final PT_LOAD program segment.  */
@@ -3169,14 +3462,46 @@ map_sections_to_segments (abfd)
          *pm = m;
          pm = &m->next;
        }
+      if (s->flags & SEC_THREAD_LOCAL)
+       {
+         if (! tls_count)
+           first_tls = s;
+         tls_count++;
+       }
+    }
+
+  /* If there are any SHF_TLS output sections, add PT_TLS segment.  */
+  if (tls_count > 0)
+    {
+      int i;
+
+      amt = sizeof (struct elf_segment_map);
+      amt += (tls_count - 1) * sizeof (asection *);
+      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_TLS;
+      m->count = tls_count;
+      /* Mandated PF_R.  */
+      m->p_flags = PF_R;
+      m->p_flags_valid = 1;
+      for (i = 0; i < tls_count; ++i)
+       {
+         BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
+         m->sections[i] = first_tls;
+         first_tls = first_tls->next;
+       }
+
+      *pm = m;
+      pm = &m->next;
     }
 
   /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
      segment.  */
-  eh_frame_hdr = NULL;
-  if (elf_tdata (abfd)->eh_frame_hdr)
-    eh_frame_hdr = bfd_get_section_by_name (abfd, ".eh_frame_hdr");
-  if (eh_frame_hdr != NULL && (eh_frame_hdr->flags & SEC_LOAD))
+  eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
+  if (eh_frame_hdr != NULL
+      && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
     {
       amt = sizeof (struct elf_segment_map);
       m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
@@ -3185,7 +3510,22 @@ map_sections_to_segments (abfd)
       m->next = NULL;
       m->p_type = PT_GNU_EH_FRAME;
       m->count = 1;
-      m->sections[0] = eh_frame_hdr;
+      m->sections[0] = eh_frame_hdr->output_section;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
+  if (elf_tdata (abfd)->stack_flags)
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = (struct elf_segment_map *) bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_GNU_STACK;
+      m->p_flags = elf_tdata (abfd)->stack_flags;
+      m->p_flags_valid = 1;
 
       *pm = m;
       pm = &m->next;
@@ -3195,12 +3535,12 @@ map_sections_to_segments (abfd)
   sections = NULL;
 
   elf_tdata (abfd)->segment_map = mfirst;
-  return true;
+  return TRUE;
 
  error_return:
   if (sections != NULL)
     free (sections);
-  return false;
+  return FALSE;
 }
 
 /* Sort sections by address.  */
@@ -3212,6 +3552,7 @@ elf_sort_sections (arg1, arg2)
 {
   const asection *sec1 = *(const asection **) arg1;
   const asection *sec2 = *(const asection **) arg2;
+  bfd_size_type size1, size2;
 
   /* Sort by LMA first, since this is the address used to
      place the section into a segment.  */
@@ -3229,7 +3570,7 @@ elf_sort_sections (arg1, arg2)
 
   /* Put !SEC_LOAD sections after SEC_LOAD ones.  */
 
-#define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
+#define TOEND(x) (((x)->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0)
 
   if (TOEND (sec1))
     {
@@ -3251,9 +3592,12 @@ elf_sort_sections (arg1, arg2)
   /* Sort by size, to put zero sized sections
      before others at the same address.  */
 
-  if (sec1->_raw_size < sec2->_raw_size)
+  size1 = (sec1->flags & SEC_LOAD) ? sec1->_raw_size : 0;
+  size2 = (sec2->flags & SEC_LOAD) ? sec2->_raw_size : 0;
+
+  if (size1 < size2)
     return -1;
-  if (sec1->_raw_size > sec2->_raw_size)
+  if (size1 > size2)
     return 1;
 
   return sec1->target_index - sec2->target_index;
@@ -3263,7 +3607,7 @@ elf_sort_sections (arg1, arg2)
    sections to segments.  This function also sets up some fields in
    the file header, and writes out the program headers.  */
 
-static boolean
+static bfd_boolean
 assign_file_positions_for_segments (abfd)
      bfd *abfd;
 {
@@ -3281,13 +3625,44 @@ assign_file_positions_for_segments (abfd)
   if (elf_tdata (abfd)->segment_map == NULL)
     {
       if (! map_sections_to_segments (abfd))
-       return false;
+       return FALSE;
+    }
+  else
+    {
+      /* The placement algorithm assumes that non allocated sections are
+        not in PT_LOAD segments.  We ensure this here by removing such
+        sections from the segment map.  */
+      for (m = elf_tdata (abfd)->segment_map;
+          m != NULL;
+          m = m->next)
+       {
+         unsigned int new_count;
+         unsigned int i;
+
+         if (m->p_type != PT_LOAD)
+           continue;
+
+         new_count = 0;
+         for (i = 0; i < m->count; i ++)
+           {
+             if ((m->sections[i]->flags & SEC_ALLOC) != 0)
+               {
+                 if (i != new_count)
+                   m->sections[new_count] = m->sections[i];
+
+                 new_count ++;
+               }
+           }
+
+         if (new_count != m->count)
+           m->count = new_count;
+       }
     }
 
   if (bed->elf_backend_modify_segment_map)
     {
       if (! (*bed->elf_backend_modify_segment_map) (abfd))
-       return false;
+       return FALSE;
     }
 
   count = 0;
@@ -3299,7 +3674,7 @@ assign_file_positions_for_segments (abfd)
   elf_elfheader (abfd)->e_phnum = count;
 
   if (count == 0)
-    return true;
+    return TRUE;
 
   /* If we already counted the number of program segments, make sure
      that we allocated enough space.  This happens when SIZEOF_HEADERS
@@ -3311,7 +3686,7 @@ assign_file_positions_for_segments (abfd)
        (_("%s: Not enough room for program headers (allocated %u, need %u)"),
        bfd_get_filename (abfd), alloc, count));
       bfd_set_error (bfd_error_bad_value);
-      return false;
+      return FALSE;
     }
 
   if (alloc == 0)
@@ -3320,7 +3695,7 @@ assign_file_positions_for_segments (abfd)
   amt = alloc * sizeof (Elf_Internal_Phdr);
   phdrs = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
   if (phdrs == NULL)
-    return false;
+    return FALSE;
 
   off = bed->s->sizeof_ehdr;
   off += alloc * bed->s->sizeof_phdr;
@@ -3338,12 +3713,12 @@ assign_file_positions_for_segments (abfd)
       asection **secpp;
 
       /* If elf_segment_map is not from map_sections_to_segments, the
-         sections may not be correctly ordered.  NOTE: sorting should 
+         sections may not be correctly ordered.  NOTE: sorting should
         not be done to the PT_NOTE section of a corefile, which may
         contain several pseudo-sections artificially created by bfd.
         Sorting these pseudo-sections breaks things badly.  */
-      if (m->count > 1 
-         && !(elf_elfheader (abfd)->e_type == ET_CORE 
+      if (m->count > 1
+         && !(elf_elfheader (abfd)->e_type == ET_CORE
               && m->p_type == PT_NOTE))
        qsort (m->sections, (size_t) m->count, sizeof (asection *),
               elf_sort_sections);
@@ -3391,7 +3766,7 @@ assign_file_positions_for_segments (abfd)
          && (abfd->flags & D_PAGED) != 0)
        p->p_align = bed->maxpagesize;
       else if (m->count == 0)
-       p->p_align = bed->s->file_align;
+       p->p_align = 1 << bed->s->log_file_align;
       else
        p->p_align = 0;
 
@@ -3412,10 +3787,11 @@ assign_file_positions_for_segments (abfd)
 
              if (p->p_vaddr < (bfd_vma) off)
                {
-                 _bfd_error_handler (_("%s: Not enough room for program headers, try linking with -N"),
-                                     bfd_get_filename (abfd));
+                 (*_bfd_error_handler)
+                   (_("%s: Not enough room for program headers, try linking with -N"),
+                    bfd_get_filename (abfd));
                  bfd_set_error (bfd_error_bad_value);
-                 return false;
+                 return FALSE;
                }
 
              p->p_vaddr -= off;
@@ -3502,9 +3878,15 @@ assign_file_positions_for_segments (abfd)
              bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz);
 
              p->p_memsz += adjust;
-             off += adjust;
-             voff += adjust;
-             if ((flags & SEC_LOAD) != 0)
+             if (p->p_type == PT_LOAD
+                 || (p->p_type == PT_NOTE
+                     && bfd_get_format (abfd) == bfd_core))
+               {
+                 off += adjust;
+                 voff += adjust;
+               }
+             if ((flags & SEC_LOAD) != 0
+                 || (flags & SEC_THREAD_LOCAL) != 0)
                p->p_filesz += adjust;
            }
 
@@ -3542,7 +3924,7 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
                                              bfd_section_name (abfd, sec),
                                              sec->lma,
                                              p->p_paddr);
-                     return false;
+                     return FALSE;
                    }
                  p->p_memsz += adjust;
                  off += adjust;
@@ -3561,7 +3943,9 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
                  || (flags & SEC_HAS_CONTENTS) != 0)
                off += sec->_raw_size;
 
-             if ((flags & SEC_ALLOC) != 0)
+             if ((flags & SEC_ALLOC) != 0
+                 && ((flags & SEC_LOAD) != 0
+                     || (flags & SEC_THREAD_LOCAL) == 0))
                voff += sec->_raw_size;
            }
 
@@ -3588,11 +3972,28 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
            }
          else
            {
+             if ((sec->flags & SEC_LOAD) != 0
+                 || (sec->flags & SEC_THREAD_LOCAL) == 0
+                 || p->p_type == PT_TLS)
              p->p_memsz += sec->_raw_size;
 
              if ((flags & SEC_LOAD) != 0)
                p->p_filesz += sec->_raw_size;
 
+             if (p->p_type == PT_TLS
+                 && sec->_raw_size == 0
+                 && (sec->flags & SEC_HAS_CONTENTS) == 0)
+               {
+                 struct bfd_link_order *o;
+                 bfd_vma tbss_size = 0;
+
+                 for (o = sec->link_order_head; o != NULL; o = o->next)
+                   if (tbss_size < o->offset + o->size)
+                     tbss_size = o->offset + o->size;
+
+                 p->p_memsz += tbss_size;
+               }
+
              if (align > p->p_align
                  && (p->p_type != PT_LOAD || (abfd->flags & D_PAGED) == 0))
                p->p_align = align;
@@ -3651,9 +4052,9 @@ Error: First section in segment (%s) starts at 0x%x whereas the segment starts a
   /* Write out the program headers.  */
   if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
       || bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Get the size of the program header.
@@ -3710,13 +4111,18 @@ get_program_header_size (abfd)
       ++segs;
     }
 
-  if (elf_tdata (abfd)->eh_frame_hdr
-      && bfd_get_section_by_name (abfd, ".eh_frame_hdr") != NULL)
+  if (elf_tdata (abfd)->eh_frame_hdr)
     {
       /* We need a PT_GNU_EH_FRAME segment.  */
       ++segs;
     }
 
+  if (elf_tdata (abfd)->stack_flags)
+    {
+      /* We need a PT_GNU_STACK segment.  */
+      ++segs;
+    }
+
   for (s = abfd->sections; s != NULL; s = s->next)
     {
       if ((s->flags & SEC_LOAD) != 0
@@ -3727,6 +4133,16 @@ get_program_header_size (abfd)
        }
     }
 
+  for (s = abfd->sections; s != NULL; s = s->next)
+    {
+      if (s->flags & SEC_THREAD_LOCAL)
+       {
+         /* We need a PT_TLS segment.  */
+         ++segs;
+         break;
+       }
+    }
+
   /* Let the backend count up any program headers it might need.  */
   if (bed->elf_backend_additional_program_headers)
     {
@@ -3753,7 +4169,7 @@ get_program_header_size (abfd)
 
    We also don't set the positions of the .symtab and .strtab here.  */
 
-static boolean
+static bfd_boolean
 assign_file_positions_except_relocs (abfd)
      bfd *abfd;
 {
@@ -3790,7 +4206,7 @@ assign_file_positions_except_relocs (abfd)
              hdr->sh_offset = -1;
            }
          else
-           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
          if (i == SHN_LORESERVE - 1)
            {
@@ -3807,7 +4223,7 @@ assign_file_positions_except_relocs (abfd)
       /* Assign file positions for the loaded sections based on the
          assignment of sections to segments.  */
       if (! assign_file_positions_for_segments (abfd))
-       return false;
+       return FALSE;
 
       /* Assign file positions for the other sections.  */
 
@@ -3833,7 +4249,7 @@ assign_file_positions_except_relocs (abfd)
              else
                off += (hdr->sh_addr - off) % hdr->sh_addralign;
              off = _bfd_elf_assign_file_position_for_section (hdr, off,
-                                                              false);
+                                                              FALSE);
            }
          else if (hdr->sh_type == SHT_REL
                   || hdr->sh_type == SHT_RELA
@@ -3842,7 +4258,7 @@ assign_file_positions_except_relocs (abfd)
                   || hdr == i_shdrpp[tdata->strtab_section])
            hdr->sh_offset = -1;
          else
-           off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+           off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
 
          if (i == SHN_LORESERVE - 1)
            {
@@ -3853,23 +4269,22 @@ assign_file_positions_except_relocs (abfd)
     }
 
   /* Place the section headers.  */
-  off = align_file_position (off, bed->s->file_align);
+  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_tdata (abfd)->next_file_pos = off;
 
-  return true;
+  return TRUE;
 }
 
-static boolean
+static bfd_boolean
 prep_headers (abfd)
      bfd *abfd;
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
   Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
-  int count;
   struct elf_strtab_hash *shstrtab;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
@@ -3878,7 +4293,7 @@ prep_headers (abfd)
 
   shstrtab = _bfd_elf_strtab_init ();
   if (shstrtab == NULL)
-    return false;
+    return FALSE;
 
   elf_shstrtab (abfd) = shstrtab;
 
@@ -3892,12 +4307,6 @@ prep_headers (abfd)
     bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
   i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
 
-  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NONE;
-  i_ehdrp->e_ident[EI_ABIVERSION] = 0;
-
-  for (count = EI_PAD; count < EI_NIDENT; count++)
-    i_ehdrp->e_ident[count] = 0;
-
   if ((abfd->flags & DYNAMIC) != 0)
     i_ehdrp->e_type = ET_DYN;
   else if ((abfd->flags & EXEC_P) != 0)
@@ -3962,17 +4371,17 @@ prep_headers (abfd)
     }
 
   elf_tdata (abfd)->symtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".symtab", FALSE);
   elf_tdata (abfd)->strtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", false);
+    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".strtab", FALSE);
   elf_tdata (abfd)->shstrtab_hdr.sh_name =
-    (unsigned int) _bfd_elf_strtab_add (shstrtab, ".shstrtab", false);
+    (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)->shstrtab_hdr.sh_name == (unsigned int) -1)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 /* Assign file positions for all the reloc sections which are not part
@@ -3996,34 +4405,34 @@ _bfd_elf_assign_file_positions_for_relocs (abfd)
       shdrp = *shdrpp;
       if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
          && shdrp->sh_offset == -1)
-       off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+       off = _bfd_elf_assign_file_position_for_section (shdrp, off, TRUE);
     }
 
   elf_tdata (abfd)->next_file_pos = off;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_write_object_contents (abfd)
      bfd *abfd;
 {
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
   Elf_Internal_Ehdr *i_ehdrp;
   Elf_Internal_Shdr **i_shdrp;
-  boolean failed;
+  bfd_boolean failed;
   unsigned int count, num_sec;
 
   if (! abfd->output_has_begun
       && ! _bfd_elf_compute_section_file_positions
              (abfd, (struct bfd_link_info *) NULL))
-    return false;
+    return FALSE;
 
   i_shdrp = elf_elfsections (abfd);
   i_ehdrp = elf_elfheader (abfd);
 
-  failed = false;
+  failed = FALSE;
   bfd_map_over_sections (abfd, bed->s->write_relocs, &failed);
   if (failed)
-    return false;
+    return FALSE;
 
   _bfd_elf_assign_file_positions_for_relocs (abfd);
 
@@ -4039,7 +4448,7 @@ _bfd_elf_write_object_contents (abfd)
 
          if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
              || bfd_bwrite (i_shdrp[count]->contents, amt, abfd) != amt)
-           return false;
+           return FALSE;
        }
       if (count == SHN_LORESERVE - 1)
        count += SHN_HIRESERVE + 1 - SHN_LORESERVE;
@@ -4048,7 +4457,7 @@ _bfd_elf_write_object_contents (abfd)
   /* Write out the section header names.  */
   if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
       || ! _bfd_elf_strtab_emit (abfd, elf_shstrtab (abfd)))
-    return false;
+    return FALSE;
 
   if (bed->elf_backend_final_write_processing)
     (*bed->elf_backend_final_write_processing) (abfd,
@@ -4057,7 +4466,7 @@ _bfd_elf_write_object_contents (abfd)
   return bed->s->write_shdrs_and_ehdr (abfd);
 }
 
-boolean
+bfd_boolean
 _bfd_elf_write_corefile_contents (abfd)
      bfd *abfd;
 {
@@ -4175,31 +4584,33 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
 
 /* Copy private BFD data.  This copies any program header information.  */
 
-static boolean
+static bfd_boolean
 copy_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
      bfd *obfd;
 {
-  Elf_Internal_Ehdr *       iehdr;
-  struct elf_segment_map *  map;
-  struct elf_segment_map *  map_first;
-  struct elf_segment_map ** pointer_to_map;
-  Elf_Internal_Phdr *       segment;
-  asection *                section;
-  unsigned int              i;
-  unsigned int              num_segments;
-  boolean                   phdr_included = false;
-  bfd_vma                   maxpagesize;
-  struct elf_segment_map *  phdr_adjust_seg = NULL;
-  unsigned int              phdr_adjust_num = 0;
+  Elf_Internal_Ehdr *iehdr;
+  struct elf_segment_map *map;
+  struct elf_segment_map *map_first;
+  struct elf_segment_map **pointer_to_map;
+  Elf_Internal_Phdr *segment;
+  asection *section;
+  unsigned int i;
+  unsigned int num_segments;
+  bfd_boolean phdr_included = FALSE;
+  bfd_vma maxpagesize;
+  struct elf_segment_map *phdr_adjust_seg = NULL;
+  unsigned int phdr_adjust_num = 0;
+  struct elf_backend_data *bed;
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   if (elf_tdata (ibfd)->phdr == NULL)
-    return true;
+    return TRUE;
 
+  bed = get_elf_backend_data (ibfd);
   iehdr = elf_elfheader (ibfd);
 
   map_first = NULL;
@@ -4209,44 +4620,51 @@ copy_private_bfd_data (ibfd, obfd)
   maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
 
   /* Returns the end address of the segment + 1.  */
-#define SEGMENT_END(segment, start)                    \
-  (start + (segment->p_memsz > segment->p_filesz       \
-   ? segment->p_memsz : segment->p_filesz))
+#define SEGMENT_END(segment, start)                                    \
+  (start + (segment->p_memsz > segment->p_filesz                       \
+           ? segment->p_memsz : segment->p_filesz))
 
-  /* Returns true if the given section is contained within
+#define SECTION_SIZE(section, segment)                                 \
+  (((section->flags & (SEC_HAS_CONTENTS | SEC_THREAD_LOCAL))           \
+    != SEC_THREAD_LOCAL || segment->p_type == PT_TLS)                  \
+   ? section->_raw_size : 0)
+
+  /* Returns TRUE if the given section is contained within
      the given segment.  VMA addresses are compared.  */
-#define IS_CONTAINED_BY_VMA(section, segment)          \
-  (section->vma >= segment->p_vaddr                    \
-   && (section->vma + section->_raw_size)              \
-   <= (SEGMENT_END (segment, segment->p_vaddr)))
+#define IS_CONTAINED_BY_VMA(section, segment)                          \
+  (section->vma >= segment->p_vaddr                                    \
+   && (section->vma + SECTION_SIZE (section, segment)                  \
+       <= (SEGMENT_END (segment, segment->p_vaddr))))
 
-  /* Returns true if the given section is contained within
+  /* Returns TRUE if the given section is contained within
      the given segment.  LMA addresses are compared.  */
-#define IS_CONTAINED_BY_LMA(section, segment, base)    \
-    (section->lma >= base                              \
-     && (section->lma + section->_raw_size)            \
-     <= SEGMENT_END (segment, base))
+#define IS_CONTAINED_BY_LMA(section, segment, base)                    \
+  (section->lma >= base                                                        \
+   && (section->lma + SECTION_SIZE (section, segment)                  \
+       <= SEGMENT_END (segment, base)))
 
   /* Special case: corefile "NOTE" section containing regs, prpsinfo etc.  */
-#define IS_COREFILE_NOTE(p, s)                          \
-           (p->p_type == PT_NOTE                       \
-            && bfd_get_format (ibfd) == bfd_core       \
-            && s->vma == 0 && s->lma == 0              \
-            && (bfd_vma) s->filepos >= p->p_offset     \
-            && (bfd_vma) s->filepos + s->_raw_size     \
-            <= p->p_offset + p->p_filesz)
+#define IS_COREFILE_NOTE(p, s)                                         \
+  (p->p_type == PT_NOTE                                                        \
+   && bfd_get_format (ibfd) == bfd_core                                        \
+   && s->vma == 0 && s->lma == 0                                       \
+   && (bfd_vma) s->filepos >= p->p_offset                              \
+   && ((bfd_vma) s->filepos + s->_raw_size                             \
+       <= p->p_offset + p->p_filesz))
 
   /* The complicated case when p_vaddr is 0 is to handle the Solaris
      linker, which generates a PT_INTERP section with p_vaddr and
      p_memsz set to 0.  */
-#define IS_SOLARIS_PT_INTERP(p, s)                     \
-           (   p->p_vaddr == 0                         \
-            && p->p_filesz > 0                         \
-            && (s->flags & SEC_HAS_CONTENTS) != 0      \
-            && s->_raw_size > 0                        \
-            && (bfd_vma) s->filepos >= p->p_offset     \
-            && ((bfd_vma) s->filepos + s->_raw_size    \
-                    <= p->p_offset + p->p_filesz))
+#define IS_SOLARIS_PT_INTERP(p, s)                                     \
+  (p->p_vaddr == 0                                                     \
+   && p->p_paddr == 0                                                  \
+   && p->p_memsz == 0                                                  \
+   && p->p_filesz > 0                                                  \
+   && (s->flags & SEC_HAS_CONTENTS) != 0                               \
+   && s->_raw_size > 0                                                 \
+   && (bfd_vma) s->filepos >= p->p_offset                              \
+   && ((bfd_vma) s->filepos + s->_raw_size                             \
+       <= p->p_offset + p->p_filesz))
 
   /* Decide if the given section should be included in the given segment.
      A section will be included if:
@@ -4254,33 +4672,47 @@ copy_private_bfd_data (ibfd, obfd)
           if that is set for the segment and the VMA otherwise,
        2. It is an allocated segment,
        3. There is an output section associated with it,
-       4. The section has not already been allocated to a previous segment.  */
-#define INCLUDE_SECTION_IN_SEGMENT(section, segment)                   \
-  (((((segment->p_paddr                                                        \
-       ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)      \
-       : IS_CONTAINED_BY_VMA (section, segment))                       \
-      || IS_SOLARIS_PT_INTERP (segment, section))                      \
+       4. The section has not already been allocated to a previous segment.
+       5. PT_TLS segment includes only SHF_TLS sections.
+       6. SHF_TLS sections are only in PT_TLS or PT_LOAD segments.  */
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment, bed)              \
+  ((((segment->p_paddr                                                 \
+      ? IS_CONTAINED_BY_LMA (section, segment, segment->p_paddr)       \
+      : IS_CONTAINED_BY_VMA (section, segment))                                \
      && (section->flags & SEC_ALLOC) != 0)                             \
     || IS_COREFILE_NOTE (segment, section))                            \
    && section->output_section != NULL                                  \
-   && section->segment_mark == false)
-
-  /* Returns true iff seg1 starts after the end of seg2.  */
-#define SEGMENT_AFTER_SEGMENT(seg1, seg2)              \
-    (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr))
-
-  /* Returns true iff seg1 and seg2 overlap.  */
-#define SEGMENT_OVERLAPS(seg1, seg2)                   \
-  (!(SEGMENT_AFTER_SEGMENT (seg1, seg2) || SEGMENT_AFTER_SEGMENT (seg2, seg1)))
+   && (segment->p_type != PT_TLS                                       \
+       || (section->flags & SEC_THREAD_LOCAL))                         \
+   && (segment->p_type == PT_LOAD                                      \
+       || segment->p_type == PT_TLS                                    \
+       || (section->flags & SEC_THREAD_LOCAL) == 0)                    \
+   && ! section->segment_mark)
+
+  /* Returns TRUE iff seg1 starts after the end of seg2.  */
+#define SEGMENT_AFTER_SEGMENT(seg1, seg2, field)                       \
+  (seg1->field >= SEGMENT_END (seg2, seg2->field))
+
+  /* Returns TRUE iff seg1 and seg2 overlap. Segments overlap iff both
+     their VMA address ranges and their LMA address ranges overlap.
+     It is possible to have overlapping VMA ranges without overlapping LMA
+     ranges.  RedBoot images for example can have both .data and .bss mapped
+     to the same VMA range, but with the .data section mapped to a different
+     LMA.  */
+#define SEGMENT_OVERLAPS(seg1, seg2)                                   \
+  (   !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_vaddr)                    \
+        || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_vaddr))                \
+   && !(SEGMENT_AFTER_SEGMENT (seg1, seg2, p_paddr)                    \
+        || SEGMENT_AFTER_SEGMENT (seg2, seg1, p_paddr)))
 
   /* Initialise the segment mark field.  */
   for (section = ibfd->sections; section != NULL; section = section->next)
-    section->segment_mark = false;
+    section->segment_mark = FALSE;
 
   /* Scan through the segments specified in the program header
      of the input BFD.  For this first scan we look for overlaps
      in the loadable segments.  These can be created by weird
-     parameters to objcopy.  */
+     parameters to objcopy.  Also, fix some solaris weirdness.  */
   for (i = 0, segment = elf_tdata (ibfd)->phdr;
        i < num_segments;
        i++, segment++)
@@ -4288,6 +4720,16 @@ copy_private_bfd_data (ibfd, obfd)
       unsigned int j;
       Elf_Internal_Phdr *segment2;
 
+      if (segment->p_type == PT_INTERP)
+       for (section = ibfd->sections; section; section = section->next)
+         if (IS_SOLARIS_PT_INTERP (segment, section))
+           {
+             /* Mininal change so that the normal section to segment
+                assigment code will work.  */
+             segment->p_vaddr = section->vma;
+             break;
+           }
+
       if (segment->p_type != PT_LOAD)
        continue;
 
@@ -4359,18 +4801,19 @@ copy_private_bfd_data (ibfd, obfd)
        continue;
 
       /* Compute how many sections might be placed into this segment.  */
-      section_count = 0;
-      for (section = ibfd->sections; section != NULL; section = section->next)
-       if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
+      for (section = ibfd->sections, section_count = 0;
+          section != NULL;
+          section = section->next)
+       if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
          ++section_count;
 
-      /* Allocate a segment map big enough to contain all of the
-        sections we have selected.  */
+      /* Allocate a segment map big enough to contain
+        all of the sections we have selected.  */
       amt = sizeof (struct elf_segment_map);
       amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
       map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
       if (map == NULL)
-       return false;
+       return FALSE;
 
       /* Initialise the fields of the segment map.  Default to
         using the physical address of the segment in the input BFD.  */
@@ -4397,18 +4840,19 @@ copy_private_bfd_data (ibfd, obfd)
                     + iehdr->e_phnum * iehdr->e_phentsize)));
 
          if (segment->p_type == PT_LOAD && map->includes_phdrs)
-           phdr_included = true;
+           phdr_included = TRUE;
        }
 
       if (section_count == 0)
        {
          /* Special segments, such as the PT_PHDR segment, may contain
             no sections, but ordinary, loadable segments should contain
-            something.  */
+            something.  They are allowed by the ELF spec however, so only
+            a warning is produced.  */
          if (segment->p_type == PT_LOAD)
-             _bfd_error_handler
-               (_("%s: warning: Empty loadable segment detected\n"),
-                bfd_archive_filename (ibfd));
+           (*_bfd_error_handler)
+             (_("%s: warning: Empty loadable segment detected, is this intentional ?\n"),
+              bfd_archive_filename (ibfd));
 
          map->count = 0;
          *pointer_to_map = map;
@@ -4436,7 +4880,7 @@ copy_private_bfd_data (ibfd, obfd)
            and possibly its LMA changed, and a new segment or segments will
            have to be created to contain the other sections.
 
-        4. The sections have been moved, but not be the same amount.
+        4. The sections have been moved, but not by the same amount.
            In this case we can change the segment's LMA to match the LMA
            of the first section and we will have to create a new segment
            or segments to contain the other sections.
@@ -4445,10 +4889,12 @@ copy_private_bfd_data (ibfd, obfd)
         pointers that we are interested in.  As these sections get assigned
         to a segment, they are removed from this array.  */
 
-      amt = (bfd_size_type) section_count * sizeof (asection *);
+      /* Gcc 2.96 miscompiles this code on mips. Don't do casting here
+        to work around this long long bug.  */
+      amt = section_count * sizeof (asection *);
       sections = (asection **) bfd_malloc (amt);
       if (sections == NULL)
-       return false;
+       return FALSE;
 
       /* Step One: Scan for segment vs section LMA conflicts.
         Also add the sections to the section array allocated above.
@@ -4464,7 +4910,7 @@ copy_private_bfd_data (ibfd, obfd)
           section != NULL;
           section = section->next)
        {
-         if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
+         if (INCLUDE_SECTION_IN_SEGMENT (section, segment, bed))
            {
              output_section = section->output_section;
 
@@ -4472,9 +4918,11 @@ copy_private_bfd_data (ibfd, obfd)
 
              /* The Solaris native linker always sets p_paddr to 0.
                 We try to catch that case here, and set it to the
-                correct value.  */
+                correct value.  Note - some backends require that
+                p_paddr be left as zero.  */
              if (segment->p_paddr == 0
                  && segment->p_vaddr != 0
+                 && (! bed->want_p_paddr_set_to_zero)
                  && isec == 0
                  && output_section->lma != 0
                  && (output_section->vma == (segment->p_vaddr
@@ -4490,7 +4938,10 @@ copy_private_bfd_data (ibfd, obfd)
              /* Match up the physical address of the segment with the
                 LMA address of the output section.  */
              if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
-                 || IS_COREFILE_NOTE (segment, section))
+                 || IS_COREFILE_NOTE (segment, section)
+                 || (bed->want_p_paddr_set_to_zero &&
+                     IS_CONTAINED_BY_VMA (output_section, segment))
+                )
                {
                  if (matching_lma == 0)
                    matching_lma = output_section->lma;
@@ -4559,7 +5010,7 @@ copy_private_bfd_data (ibfd, obfd)
        }
 
       /* Step Three: Loop over the sections again, this time assigning
-        those that fit to the current segment and remvoing them from the
+        those that fit to the current segment and removing them from the
         sections array; but making sure not to leave large gaps.  Once all
         possible sections have been assigned to the current segment it is
         added to the list of built segments and if sections still remain
@@ -4610,7 +5061,7 @@ copy_private_bfd_data (ibfd, obfd)
                         maxpagesize then we need to start a new segment.  */
                      if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size,
                                      maxpagesize)
-                         < BFD_ALIGN (output_section->lma, maxpagesize))
+                          < BFD_ALIGN (output_section->lma, maxpagesize))
                          || ((prev_sec->lma + prev_sec->_raw_size)
                              > output_section->lma))
                        {
@@ -4624,7 +5075,7 @@ copy_private_bfd_data (ibfd, obfd)
                  map->sections[map->count++] = output_section;
                  ++isec;
                  sections[j] = NULL;
-                 section->segment_mark = true;
+                 section->segment_mark = TRUE;
                }
              else if (suggested_lma == 0)
                suggested_lma = output_section->lma;
@@ -4645,7 +5096,10 @@ copy_private_bfd_data (ibfd, obfd)
              amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
              map = (struct elf_segment_map *) bfd_alloc (obfd, amt);
              if (map == NULL)
-               return false;
+               {
+                 free (sections);
+                 return FALSE;
+               }
 
              /* Initialise the fields of the segment map.  Set the physical
                 physical address to the LMA of the first section that has
@@ -4673,10 +5127,8 @@ copy_private_bfd_data (ibfd, obfd)
     if (map->p_paddr != 0)
       break;
   if (map == NULL)
-    {
-      for (map = map_first; map != NULL; map = map->next)
-       map->p_paddr_valid = 0;
-    }
+    for (map = map_first; map != NULL; map = map->next)
+      map->p_paddr_valid = 0;
 
   elf_tdata (obfd)->segment_map = map_first;
 
@@ -4721,6 +5173,7 @@ copy_private_bfd_data (ibfd, obfd)
 #endif
 
 #undef SEGMENT_END
+#undef SECTION_SIZE
 #undef IS_CONTAINED_BY_VMA
 #undef IS_CONTAINED_BY_LMA
 #undef IS_COREFILE_NOTE
@@ -4728,13 +5181,13 @@ copy_private_bfd_data (ibfd, obfd)
 #undef INCLUDE_SECTION_IN_SEGMENT
 #undef SEGMENT_AFTER_SEGMENT
 #undef SEGMENT_OVERLAPS
-  return true;
+  return TRUE;
 }
 
 /* Copy private section information.  This copies over the entsize
    field, and sometimes the info field.  */
 
-boolean
+bfd_boolean
 _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
      bfd *ibfd;
      asection *isec;
@@ -4745,30 +5198,24 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
 
   if (ibfd->xvec->flavour != bfd_target_elf_flavour
       || obfd->xvec->flavour != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
-  /* Copy over private BFD data if it has not already been copied.
-     This must be done here, rather than in the copy_private_bfd_data
-     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_tdata (obfd)->segment_map == NULL && elf_tdata (ibfd)->phdr != NULL)
     {
-      asection *s;
+       asection *s;
 
-      /* Only set up the segments if there are no more SEC_ALLOC
-         sections.  FIXME: This won't do the right thing if objcopy is
-         used to remove the last SEC_ALLOC section, since objcopy
-         won't call this routine in that case.  */
-      for (s = isec->next; s != NULL; s = s->next)
-       if ((s->flags & SEC_ALLOC) != 0)
-         break;
-      if (s == NULL)
-       {
-         if (! copy_private_bfd_data (ibfd, obfd))
-           return false;
-       }
+       /* Only set up the segments if there are no more SEC_ALLOC
+          sections.  FIXME: This won't do the right thing if objcopy is
+          used to remove the last SEC_ALLOC section, since objcopy
+          won't call this routine in that case.  */
+       for (s = isec->next; s != NULL; s = s->next)
+         if ((s->flags & SEC_ALLOC) != 0)
+           break;
+       if (s == NULL)
+         {
+           if (! copy_private_bfd_data (ibfd, obfd))
+             return FALSE;
+         }
     }
 
   ihdr = &elf_section_data (isec)->this_hdr;
@@ -4782,10 +5229,15 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
       || ihdr->sh_type == SHT_GNU_verdef)
     ohdr->sh_info = ihdr->sh_info;
 
-  elf_section_data (osec)->use_rela_p
-    = elf_section_data (isec)->use_rela_p;
+  /* Set things up for objcopy.  The output SHT_GROUP section will
+     have its elf_next_in_group pointing back to the input group
+     members.  */
+  elf_next_in_group (osec) = elf_next_in_group (isec);
+  elf_group_name (osec) = elf_group_name (isec);
+
+  osec->use_rela_p = isec->use_rela_p;
 
-  return true;
+  return TRUE;
 }
 
 /* Copy private symbol information.  If this symbol is in a section
@@ -4800,7 +5252,7 @@ _bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
 #define MAP_SHSTRTAB  (SHN_HIOS + 4)
 #define MAP_SYM_SHNDX (SHN_HIOS + 5)
 
-boolean
+bfd_boolean
 _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
      bfd *ibfd;
      asymbol *isymarg;
@@ -4811,7 +5263,7 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
 
   if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
-    return true;
+    return TRUE;
 
   isym = elf_symbol_from (ibfd, isymarg);
   osym = elf_symbol_from (obfd, osymarg);
@@ -4836,12 +5288,12 @@ _bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
       osym->internal_elf_sym.st_shndx = shndx;
     }
 
-  return true;
+  return TRUE;
 }
 
 /* Swap out the symbols.  */
 
-static boolean
+static bfd_boolean
 swap_out_syms (abfd, sttp, relocatable_p)
      bfd *abfd;
      struct bfd_strtab_hash **sttp;
@@ -4860,12 +5312,12 @@ swap_out_syms (abfd, sttp, relocatable_p)
   bfd_size_type amt;
 
   if (!elf_map_symbols (abfd))
-    return false;
+    return FALSE;
 
   /* Dump out the symtabs.  */
   stt = _bfd_elf_stringtab_init ();
   if (stt == NULL)
-    return false;
+    return FALSE;
 
   bed = get_elf_backend_data (abfd);
   symcount = bfd_get_symcount (abfd);
@@ -4874,7 +5326,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
   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_addralign = bed->s->file_align;
+  symtab_hdr->sh_addralign = 1 << bed->s->log_file_align;
 
   symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
   symstrtab_hdr->sh_type = SHT_STRTAB;
@@ -4882,7 +5334,10 @@ swap_out_syms (abfd, sttp, relocatable_p)
   amt = (bfd_size_type) (1 + symcount) * bed->s->sizeof_sym;
   outbound_syms = bfd_alloc (abfd, amt);
   if (outbound_syms == NULL)
-    return false;
+    {
+      _bfd_stringtab_free (stt);
+      return FALSE;
+    }
   symtab_hdr->contents = (PTR) outbound_syms;
 
   outbound_shndx = NULL;
@@ -4890,10 +5345,13 @@ swap_out_syms (abfd, sttp, relocatable_p)
   if (symtab_shndx_hdr->sh_name != 0)
     {
       amt = (bfd_size_type) (1 + symcount) * sizeof (Elf_External_Sym_Shndx);
-      outbound_shndx = bfd_alloc (abfd, amt);
+      outbound_shndx = bfd_zalloc (abfd, amt);
       if (outbound_shndx == NULL)
-       return false;
-      memset (outbound_shndx, 0, (unsigned long) amt);
+       {
+         _bfd_stringtab_free (stt);
+         return FALSE;
+       }
+
       symtab_shndx_hdr->contents = outbound_shndx;
       symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
       symtab_shndx_hdr->sh_size = amt;
@@ -4901,7 +5359,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
       symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
     }
 
-  /* now generate the data (for "contents") */
+  /* Now generate the data (for "contents").  */
   {
     /* Fill in zeroth symbol and swap it out.  */
     Elf_Internal_Sym sym;
@@ -4935,9 +5393,12 @@ swap_out_syms (abfd, sttp, relocatable_p)
        {
          sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
                                                            syms[idx]->name,
-                                                           true, false);
+                                                           TRUE, FALSE);
          if (sym.st_name == (unsigned long) -1)
-           return false;
+           {
+             _bfd_stringtab_free (stt);
+             return FALSE;
+           }
        }
 
       type_ptr = elf_symbol_from (abfd, syms[idx]);
@@ -4967,6 +5428,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
              value += sec->output_offset;
              sec = sec->output_section;
            }
+
          /* Don't add in the section vma for relocatable output.  */
          if (! relocatable_p)
            value += sec->vma;
@@ -5018,7 +5480,17 @@ swap_out_syms (abfd, sttp, relocatable_p)
                     section of a symbol to be a section that is
                     actually in the output file.  */
                  sec2 = bfd_get_section_by_name (abfd, sec->name);
-                 BFD_ASSERT (sec2 != 0);
+                 if (sec2 == NULL)
+                   {
+                     _bfd_error_handler (_("\
+Unable to find equivalent output section for symbol '%s' from section '%s'"),
+                                         syms[idx]->name ? syms[idx]->name : "<Local sym>",
+                                         sec->name);
+                     bfd_set_error (bfd_error_invalid_operation);
+                     _bfd_stringtab_free (stt);
+                     return FALSE;
+                   }
+
                  shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
                  BFD_ASSERT (shndx != -1);
                }
@@ -5027,14 +5499,19 @@ swap_out_syms (abfd, sttp, relocatable_p)
          sym.st_shndx = shndx;
        }
 
-      if ((flags & BSF_FUNCTION) != 0)
+      if ((flags & BSF_THREAD_LOCAL) != 0)
+       type = STT_TLS;
+      else if ((flags & BSF_FUNCTION) != 0)
        type = STT_FUNC;
       else if ((flags & BSF_OBJECT) != 0)
        type = STT_OBJECT;
       else
        type = STT_NOTYPE;
 
-      /* Processor-specific types */
+      if (syms[idx]->section->flags & SEC_THREAD_LOCAL)
+       type = STT_TLS;
+
+      /* Processor-specific types.  */
       if (type_ptr != NULL
          && bed->elf_backend_get_symbol_type)
        type = ((*bed->elf_backend_get_symbol_type)
@@ -5092,7 +5569,7 @@ swap_out_syms (abfd, sttp, relocatable_p)
   symstrtab_hdr->sh_info = 0;
   symstrtab_hdr->sh_addralign = 1;
 
-  return true;
+  return TRUE;
 }
 
 /* Return the number of bytes required to hold the symtab vector.
@@ -5110,7 +5587,9 @@ _bfd_elf_get_symtab_upper_bound (abfd)
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
-  symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+  symtab_size = (symcount + 1) * (sizeof (asymbol *));
+  if (symcount > 0)
+    symtab_size -= sizeof (asymbol *);
 
   return symtab_size;
 }
@@ -5130,7 +5609,9 @@ _bfd_elf_get_dynamic_symtab_upper_bound (abfd)
     }
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
-  symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+  symtab_size = (symcount + 1) * (sizeof (asymbol *));
+  if (symcount > 0)
+    symtab_size -= sizeof (asymbol *);
 
   return symtab_size;
 }
@@ -5156,7 +5637,7 @@ _bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
   unsigned int i;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-  if (! bed->s->slurp_reloc_table (abfd, section, symbols, false))
+  if (! bed->s->slurp_reloc_table (abfd, section, symbols, FALSE))
     return -1;
 
   tblptr = section->relocation;
@@ -5174,7 +5655,7 @@ _bfd_elf_get_symtab (abfd, alocation)
      asymbol **alocation;
 {
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  long symcount = bed->s->slurp_symbol_table (abfd, alocation, false);
+  long symcount = bed->s->slurp_symbol_table (abfd, alocation, FALSE);
 
   if (symcount >= 0)
     bfd_get_symcount (abfd) = symcount;
@@ -5187,7 +5668,11 @@ _bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
      asymbol **alocation;
 {
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  return bed->s->slurp_symbol_table (abfd, alocation, true);
+  long symcount = bed->s->slurp_symbol_table (abfd, alocation, TRUE);
+
+  if (symcount >= 0)
+    bfd_get_dynamic_symcount (abfd) = symcount;
+  return symcount;
 }
 
 /* Return the size required for the dynamic reloc entries.  Any
@@ -5234,7 +5719,8 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
      arelent **storage;
      asymbol **syms;
 {
-  boolean (*slurp_relocs) PARAMS ((bfd *, asection *, asymbol **, boolean));
+  bfd_boolean (*slurp_relocs)
+    PARAMS ((bfd *, asection *, asymbol **, bfd_boolean));
   asection *s;
   long ret;
 
@@ -5255,7 +5741,7 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
          arelent *p;
          long count, i;
 
-         if (! (*slurp_relocs) (abfd, s, syms, true))
+         if (! (*slurp_relocs) (abfd, s, syms, TRUE))
            return -1;
          count = s->_raw_size / elf_section_data (s)->this_hdr.sh_entsize;
          p = s->relocation;
@@ -5272,7 +5758,7 @@ _bfd_elf_canonicalize_dynamic_reloc (abfd, storage, syms)
 \f
 /* Read in the version information.  */
 
-boolean
+bfd_boolean
 _bfd_elf_slurp_version_tables (abfd)
      bfd *abfd;
 {
@@ -5459,12 +5945,12 @@ _bfd_elf_slurp_version_tables (abfd)
       contents = NULL;
     }
 
-  return true;
+  return TRUE;
 
  error_return:
-  if (contents == NULL)
+  if (contents != NULL)
     free (contents);
-  return false;
+  return FALSE;
 }
 \f
 asymbol *
@@ -5497,19 +5983,19 @@ _bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
    use this function for the is_local_label_name entry point, but some
    override it.  */
 
-boolean
+bfd_boolean
 _bfd_elf_is_local_label_name (abfd, name)
      bfd *abfd ATTRIBUTE_UNUSED;
      const char *name;
 {
   /* Normal local symbols start with ``.L''.  */
   if (name[0] == '.' && name[1] == 'L')
-    return true;
+    return TRUE;
 
   /* At least some SVR4 compilers (e.g., UnixWare 2.1 cc) generate
      DWARF debugging symbols starting with ``..''.  */
   if (name[0] == '.' && name[1] == '.')
-    return true;
+    return TRUE;
 
   /* gcc will sometimes generate symbols beginning with ``_.L_'' when
      emitting DWARF debugging output.  I suspect this is actually a
@@ -5518,9 +6004,9 @@ _bfd_elf_is_local_label_name (abfd, name)
      underscore to be emitted on some ELF targets).  For ease of use,
      we treat such symbols as local.  */
   if (name[0] == '_' && name[1] == '.' && name[2] == 'L' && name[3] == '_')
-    return true;
+    return TRUE;
 
-  return false;
+  return FALSE;
 }
 
 alent *
@@ -5532,7 +6018,7 @@ _bfd_elf_get_lineno (ignore_abfd, symbol)
   return NULL;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_set_arch_mach (abfd, arch, machine)
      bfd *abfd;
      enum bfd_architecture arch;
@@ -5543,7 +6029,7 @@ _bfd_elf_set_arch_mach (abfd, arch, machine)
   if (arch != get_elf_backend_data (abfd)->arch
       && arch != bfd_arch_unknown
       && get_elf_backend_data (abfd)->arch != bfd_arch_unknown)
-    return false;
+    return FALSE;
 
   return bfd_default_set_arch_mach (abfd, arch, machine);
 }
@@ -5551,7 +6037,7 @@ _bfd_elf_set_arch_mach (abfd, arch, machine)
 /* Find the function to a particular section and offset,
    for error reporting.  */
 
-static boolean
+static bfd_boolean
 elf_find_function (abfd, section, symbols, offset,
                   filename_ptr, functionname_ptr)
      bfd *abfd ATTRIBUTE_UNUSED;
@@ -5600,20 +6086,20 @@ elf_find_function (abfd, section, symbols, offset,
     }
 
   if (func == NULL)
-    return false;
+    return FALSE;
 
   if (filename_ptr)
     *filename_ptr = filename;
   if (functionname_ptr)
     *functionname_ptr = bfd_asymbol_name (func);
 
-  return true;
+  return TRUE;
 }
 
 /* Find the nearest line to a particular section and offset,
    for error reporting.  */
 
-boolean
+bfd_boolean
 _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                            filename_ptr, functionname_ptr, line_ptr)
      bfd *abfd;
@@ -5624,7 +6110,7 @@ _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
      const char **functionname_ptr;
      unsigned int *line_ptr;
 {
-  boolean found;
+  bfd_boolean found;
 
   if (_bfd_dwarf1_find_nearest_line (abfd, section, symbols, offset,
                                     filename_ptr, functionname_ptr,
@@ -5635,7 +6121,7 @@ _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
-      return true;
+      return TRUE;
     }
 
   if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset,
@@ -5648,32 +6134,32 @@ _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
                           *filename_ptr ? NULL : filename_ptr,
                           functionname_ptr);
 
-      return true;
+      return TRUE;
     }
 
   if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
                                             &found, filename_ptr,
                                             functionname_ptr, line_ptr,
                                             &elf_tdata (abfd)->line_info))
-    return false;
-  if (found)
-    return true;
+    return FALSE;
+  if (found && (*functionname_ptr || *line_ptr))
+    return TRUE;
 
   if (symbols == NULL)
-    return false;
+    return FALSE;
 
   if (! elf_find_function (abfd, section, symbols, offset,
                           filename_ptr, functionname_ptr))
-    return false;
+    return FALSE;
 
   *line_ptr = 0;
-  return true;
+  return TRUE;
 }
 
 int
 _bfd_elf_sizeof_headers (abfd, reloc)
      bfd *abfd;
-     boolean reloc;
+     bfd_boolean reloc;
 {
   int ret;
 
@@ -5683,7 +6169,7 @@ _bfd_elf_sizeof_headers (abfd, reloc)
   return ret;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_set_section_contents (abfd, section, location, offset, count)
      bfd *abfd;
      sec_ptr section;
@@ -5695,17 +6181,17 @@ _bfd_elf_set_section_contents (abfd, section, location, offset, count)
   bfd_signed_vma pos;
 
   if (! abfd->output_has_begun
-      && ! _bfd_elf_compute_section_file_positions
-      (abfd, (struct bfd_link_info *) NULL))
-    return false;
+      && ! (_bfd_elf_compute_section_file_positions
+           (abfd, (struct bfd_link_info *) NULL)))
+    return FALSE;
 
   hdr = &elf_section_data (section)->this_hdr;
   pos = hdr->sh_offset + offset;
   if (bfd_seek (abfd, pos, SEEK_SET) != 0
       || bfd_bwrite (location, count, abfd) != count)
-    return false;
+    return FALSE;
 
-  return true;
+  return TRUE;
 }
 
 void
@@ -5717,20 +6203,9 @@ _bfd_elf_no_info_to_howto (abfd, cache_ptr, dst)
   abort ();
 }
 
-#if 0
-void
-_bfd_elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
-     bfd *abfd;
-     arelent *cache_ptr;
-     Elf_Internal_Rel *dst;
-{
-  abort ();
-}
-#endif
-
 /* Try to convert a non-ELF reloc into an ELF one.  */
 
-boolean
+bfd_boolean
 _bfd_elf_validate_reloc (abfd, areloc)
      bfd *abfd;
      arelent *areloc;
@@ -5816,17 +6291,17 @@ _bfd_elf_validate_reloc (abfd, areloc)
        goto fail;
     }
 
-  return true;
+  return TRUE;
 
  fail:
   (*_bfd_error_handler)
     (_("%s: unsupported relocation type %s"),
      bfd_archive_filename (abfd), areloc->howto->name);
   bfd_set_error (bfd_error_bad_value);
-  return false;
+  return FALSE;
 }
 
-boolean
+bfd_boolean
 _bfd_elf_close_and_cleanup (abfd)
      bfd *abfd;
 {
@@ -5881,7 +6356,7 @@ elfcore_make_pid (abfd)
    reference to NAME, so you shouldn't deallocate or
    overwrite it.  */
 
-static boolean
+static bfd_boolean
 elfcore_maybe_make_sect (abfd, name, sect)
      bfd *abfd;
      char *name;
@@ -5890,17 +6365,17 @@ elfcore_maybe_make_sect (abfd, name, sect)
   asection *sect2;
 
   if (bfd_get_section_by_name (abfd, name) != NULL)
-    return true;
+    return TRUE;
 
   sect2 = bfd_make_section (abfd, name);
   if (sect2 == NULL)
-    return false;
+    return FALSE;
 
   sect2->_raw_size = sect->_raw_size;
   sect2->filepos = sect->filepos;
   sect2->flags = sect->flags;
   sect2->alignment_power = sect->alignment_power;
-  return true;
+  return TRUE;
 }
 
 /* Create a pseudosection containing SIZE bytes at FILEPOS.  This
@@ -5910,7 +6385,7 @@ elfcore_maybe_make_sect (abfd, name, sect)
    - For the multi-threaded case, a section named "NAME/PID", where
      PID is elfcore_make_pid (abfd).
    Both pseudosections have identical contents. */
-boolean
+bfd_boolean
 _bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
      bfd *abfd;
      char *name;
@@ -5919,19 +6394,21 @@ _bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
 {
   char buf[100];
   char *threaded_name;
+  size_t len;
   asection *sect;
 
   /* Build the section name.  */
 
   sprintf (buf, "%s/%d", name, elfcore_make_pid (abfd));
-  threaded_name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+  len = strlen (buf) + 1;
+  threaded_name = bfd_alloc (abfd, (bfd_size_type) len);
   if (threaded_name == NULL)
-    return false;
-  strcpy (threaded_name, buf);
+    return FALSE;
+  memcpy (threaded_name, buf, len);
 
   sect = bfd_make_section (abfd, threaded_name);
   if (sect == NULL)
-    return false;
+    return FALSE;
   sect->_raw_size = size;
   sect->filepos = filepos;
   sect->flags = SEC_HAS_CONTENTS;
@@ -5947,9 +6424,10 @@ _bfd_elfcore_make_pseudosection (abfd, name, size, filepos)
 */
 
 #if defined (HAVE_PRSTATUS_T)
-static boolean elfcore_grok_prstatus PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_prstatus
+  PARAMS ((bfd *, Elf_Internal_Note *));
 
-static boolean
+static bfd_boolean
 elfcore_grok_prstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6012,7 +6490,7 @@ elfcore_grok_prstatus (abfd, note)
     {
       /* Fail - we don't know how to handle any other
         note size (ie. data object type).  */
-      return true;
+      return TRUE;
     }
 
   /* Make a ".reg/999" section and a ".reg" section.  */
@@ -6022,7 +6500,7 @@ elfcore_grok_prstatus (abfd, note)
 #endif /* defined (HAVE_PRSTATUS_T) */
 
 /* Create a pseudosection containing the exact contents of NOTE.  */
-static boolean
+static bfd_boolean
 elfcore_make_note_pseudosection (abfd, name, note)
      bfd *abfd;
      char *name;
@@ -6036,7 +6514,7 @@ elfcore_make_note_pseudosection (abfd, name, note)
    but it doesn't matter, because we don't have to pick this
    data structure apart.  */
 
-static boolean
+static bfd_boolean
 elfcore_grok_prfpreg (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6048,7 +6526,7 @@ elfcore_grok_prfpreg (abfd, note)
    type of 5 (NT_PRXFPREG).  Just include the whole note's contents
    literally.  */
 
-static boolean
+static bfd_boolean
 elfcore_grok_prxfpreg (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6100,9 +6578,10 @@ _bfd_elfcore_strndup (abfd, start, max)
 }
 
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
-static boolean elfcore_grok_psinfo PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_psinfo
+  PARAMS ((bfd *, Elf_Internal_Note *));
 
-static boolean
+static bfd_boolean
 elfcore_grok_psinfo (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6143,7 +6622,7 @@ elfcore_grok_psinfo (abfd, note)
     {
       /* Fail - we don't know how to handle any other
         note size (ie. data object type).  */
-      return true;
+      return TRUE;
     }
 
   /* Note that for some reason, a spurious space is tacked
@@ -6158,14 +6637,15 @@ elfcore_grok_psinfo (abfd, note)
       command[n - 1] = '\0';
   }
 
-  return true;
+  return TRUE;
 }
 #endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
 
 #if defined (HAVE_PSTATUS_T)
-static boolean elfcore_grok_pstatus PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_pstatus
+  PARAMS ((bfd *, Elf_Internal_Note *));
 
-static boolean
+static bfd_boolean
 elfcore_grok_pstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6197,14 +6677,15 @@ elfcore_grok_pstatus (abfd, note)
      lwpstatus_t in pstat.pr_lwp, but we'll catch it all in an
      NT_LWPSTATUS note, presumably.  */
 
-  return true;
+  return TRUE;
 }
 #endif /* defined (HAVE_PSTATUS_T) */
 
 #if defined (HAVE_LWPSTATUS_T)
-static boolean elfcore_grok_lwpstatus PARAMS ((bfd *, Elf_Internal_Note *));
+static bfd_boolean elfcore_grok_lwpstatus
+  PARAMS ((bfd *, Elf_Internal_Note *));
 
-static boolean
+static bfd_boolean
 elfcore_grok_lwpstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6212,6 +6693,7 @@ elfcore_grok_lwpstatus (abfd, note)
   lwpstatus_t lwpstat;
   char buf[100];
   char *name;
+  size_t len;
   asection *sect;
 
   if (note->descsz != sizeof (lwpstat)
@@ -6219,7 +6701,7 @@ elfcore_grok_lwpstatus (abfd, note)
       && note->descsz != sizeof (lwpxstatus_t)
 #endif
       )
-    return true;
+    return TRUE;
 
   memcpy (&lwpstat, note->descdata, sizeof (lwpstat));
 
@@ -6229,14 +6711,15 @@ elfcore_grok_lwpstatus (abfd, note)
   /* Make a ".reg/999" section.  */
 
   sprintf (buf, ".reg/%d", elfcore_make_pid (abfd));
-  name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+  len = strlen (buf) + 1;
+  name = bfd_alloc (abfd, (bfd_size_type) len);
   if (name == NULL)
-    return false;
-  strcpy (name, buf);
+    return FALSE;
+  memcpy (name, buf, len);
 
   sect = bfd_make_section (abfd, name);
   if (sect == NULL)
-    return false;
+    return FALSE;
 
 #if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
   sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.gregs);
@@ -6253,19 +6736,20 @@ elfcore_grok_lwpstatus (abfd, note)
   sect->alignment_power = 2;
 
   if (!elfcore_maybe_make_sect (abfd, ".reg", sect))
-    return false;
+    return FALSE;
 
   /* Make a ".reg2/999" section */
 
   sprintf (buf, ".reg2/%d", elfcore_make_pid (abfd));
-  name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+  len = strlen (buf) + 1;
+  name = bfd_alloc (abfd, (bfd_size_type) len);
   if (name == NULL)
-    return false;
-  strcpy (name, buf);
+    return FALSE;
+  memcpy (name, buf, len);
 
   sect = bfd_make_section (abfd, name);
   if (sect == NULL)
-    return false;
+    return FALSE;
 
 #if defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
   sect->_raw_size = sizeof (lwpstat.pr_context.uc_mcontext.fpregs);
@@ -6286,18 +6770,19 @@ elfcore_grok_lwpstatus (abfd, note)
 #endif /* defined (HAVE_LWPSTATUS_T) */
 
 #if defined (HAVE_WIN32_PSTATUS_T)
-static boolean
+static bfd_boolean
 elfcore_grok_win32pstatus (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
 {
   char buf[30];
   char *name;
+  size_t len;
   asection *sect;
   win32_pstatus_t pstatus;
 
   if (note->descsz < sizeof (pstatus))
-    return true;
+    return TRUE;
 
   memcpy (&pstatus, note->descdata, sizeof (pstatus));
 
@@ -6313,15 +6798,16 @@ elfcore_grok_win32pstatus (abfd, note)
       /* Make a ".reg/999" section.  */
       sprintf (buf, ".reg/%d", pstatus.data.thread_info.tid);
 
-      name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+      len = strlen (buf) + 1;
+      name = bfd_alloc (abfd, (bfd_size_type) len);
       if (name == NULL)
-       return false;
+       return FALSE;
 
-      strcpy (name, buf);
+      memcpy (name, buf, len);
 
       sect = bfd_make_section (abfd, name);
       if (sect == NULL)
-       return false;
+       return FALSE;
 
       sect->_raw_size = sizeof (pstatus.data.thread_info.thread_context);
       sect->filepos = (note->descpos
@@ -6332,23 +6818,24 @@ elfcore_grok_win32pstatus (abfd, note)
 
       if (pstatus.data.thread_info.is_active_thread)
        if (! elfcore_maybe_make_sect (abfd, ".reg", sect))
-         return false;
+         return FALSE;
       break;
 
     case NOTE_INFO_MODULE:
       /* Make a ".module/xxxxxxxx" section.  */
       sprintf (buf, ".module/%08x", pstatus.data.module_info.base_address);
 
-      name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+      len = strlen (buf) + 1;
+      name = bfd_alloc (abfd, (bfd_size_type) len);
       if (name == NULL)
-       return false;
+       return FALSE;
 
-      strcpy (name, buf);
+      memcpy (name, buf, len);
 
       sect = bfd_make_section (abfd, name);
 
       if (sect == NULL)
-       return false;
+       return FALSE;
 
       sect->_raw_size = note->descsz;
       sect->filepos = note->descpos;
@@ -6357,14 +6844,14 @@ elfcore_grok_win32pstatus (abfd, note)
       break;
 
     default:
-      return true;
+      return TRUE;
     }
 
-  return true;
+  return TRUE;
 }
 #endif /* HAVE_WIN32_PSTATUS_T */
 
-static boolean
+static bfd_boolean
 elfcore_grok_note (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6374,16 +6861,16 @@ elfcore_grok_note (abfd, note)
   switch (note->type)
     {
     default:
-      return true;
+      return TRUE;
 
     case NT_PRSTATUS:
       if (bed->elf_backend_grok_prstatus)
        if ((*bed->elf_backend_grok_prstatus) (abfd, note))
-         return true;
+         return TRUE;
 #if defined (HAVE_PRSTATUS_T)
       return elfcore_grok_prstatus (abfd, note);
 #else
-      return true;
+      return TRUE;
 #endif
 
 #if defined (HAVE_PSTATUS_T)
@@ -6405,26 +6892,40 @@ elfcore_grok_note (abfd, note)
 #endif
 
     case NT_PRXFPREG:          /* Linux SSE extension */
-      if (note->namesz == 5
-         && ! strcmp (note->namedata, "LINUX"))
+      if (note->namesz == 6
+         && strcmp (note->namedata, "LINUX") == 0)
        return elfcore_grok_prxfpreg (abfd, note);
       else
-       return true;
+       return TRUE;
 
     case NT_PRPSINFO:
     case NT_PSINFO:
       if (bed->elf_backend_grok_psinfo)
        if ((*bed->elf_backend_grok_psinfo) (abfd, note))
-         return true;
+         return TRUE;
 #if defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T)
       return elfcore_grok_psinfo (abfd, note);
 #else
-      return true;
+      return TRUE;
 #endif
+
+    case NT_AUXV:
+      {
+       asection *sect = bfd_make_section (abfd, ".auxv");
+
+       if (sect == NULL)
+         return FALSE;
+       sect->_raw_size = note->descsz;
+       sect->filepos = note->descpos;
+       sect->flags = SEC_HAS_CONTENTS;
+       sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
+
+       return TRUE;
+      }
     }
 }
 
-static boolean
+static bfd_boolean
 elfcore_netbsd_get_lwpid (note, lwpidp)
      Elf_Internal_Note *note;
      int *lwpidp;
@@ -6434,13 +6935,13 @@ elfcore_netbsd_get_lwpid (note, lwpidp)
   cp = strchr (note->namedata, '@');
   if (cp != NULL)
     {
-      *lwpidp = atoi(cp);
-      return true;
+      *lwpidp = atoi(cp + 1);
+      return TRUE;
     }
-  return false;
+  return FALSE;
 }
 
-static boolean
+static bfd_boolean
 elfcore_grok_netbsd_procinfo (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6458,10 +6959,10 @@ elfcore_grok_netbsd_procinfo (abfd, note)
   elf_tdata (abfd)->core_command
     = _bfd_elfcore_strndup (abfd, note->descdata + 0x7c, 31);
 
-  return true;
+  return TRUE;
 }
 
-static boolean
+static bfd_boolean
 elfcore_grok_netbsd_note (abfd, note)
      bfd *abfd;
      Elf_Internal_Note *note;
@@ -6477,7 +6978,7 @@ elfcore_grok_netbsd_note (abfd, note)
          find this note before any of the others, which is fine,
          since the kernel writes this note out first when it
          creates a core file.  */
-      
+
       return elfcore_grok_netbsd_procinfo (abfd, note);
     }
 
@@ -6485,9 +6986,9 @@ elfcore_grok_netbsd_note (abfd, note)
      defined for NetBSD core files.  If the note type is less
      than the start of the machine-dependent note types, we don't
      understand it.  */
-  
+
   if (note->type < NT_NETBSDCORE_FIRSTMACH)
-    return true;
+    return TRUE;
 
 
   switch (bfd_get_arch (abfd))
@@ -6506,7 +7007,7 @@ elfcore_grok_netbsd_note (abfd, note)
           return elfcore_make_note_pseudosection (abfd, ".reg2", note);
 
         default:
-          return true;
+          return TRUE;
         }
 
     /* On all other arch's, PT_GETREGS == mach+1 and
@@ -6522,15 +7023,129 @@ elfcore_grok_netbsd_note (abfd, note)
           return elfcore_make_note_pseudosection (abfd, ".reg2", note);
 
         default:
-          return true;
+          return TRUE;
         }
     }
     /* NOTREACHED */
 }
 
+static bfd_boolean
+elfcore_grok_nto_status (abfd, note, tid)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+     pid_t *tid;
+{
+  void *ddata = note->descdata;
+  char buf[100];
+  char *name;
+  asection *sect;
+  short sig;
+  unsigned flags;
+
+  /* nto_procfs_status 'pid' field is at offset 0.  */
+  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);
+
+  /* nto_procfs_status 'flags' field is at offset 8.  */
+  flags = bfd_get_32 (abfd, (bfd_byte *) ddata + 8);
+
+  /* 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;
+    }
+
+  /* _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;
+
+  /* Make a ".qnx_core_status/%d" section.  */
+  sprintf (buf, ".qnx_core_status/%d", *tid);
+
+  name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+  if (name == NULL)
+    return FALSE;
+  strcpy (name, buf);
+
+  sect = bfd_make_section (abfd, name);
+  if (sect == NULL)
+    return FALSE;
+
+  sect->_raw_size       = note->descsz;
+  sect->filepos         = note->descpos;
+  sect->flags           = SEC_HAS_CONTENTS;
+  sect->alignment_power = 2;
+
+  return (elfcore_maybe_make_sect (abfd, ".qnx_core_status", sect));
+}
+
+static bfd_boolean
+elfcore_grok_nto_gregs (abfd, note, tid)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+     pid_t tid;
+{
+  char buf[100];
+  char *name;
+  asection *sect;
+
+  /* Make a ".reg/%d" section.  */
+  sprintf (buf, ".reg/%d", tid);
+
+  name = bfd_alloc (abfd, (bfd_size_type) strlen (buf) + 1);
+  if (name == NULL)
+    return FALSE;
+  strcpy (name, buf);
+
+  sect = bfd_make_section (abfd, name);
+  if (sect == NULL)
+    return FALSE;
+
+  sect->_raw_size       = note->descsz;
+  sect->filepos         = note->descpos;
+  sect->flags           = SEC_HAS_CONTENTS;
+  sect->alignment_power = 2;
+
+  /* This is the current thread.  */
+  if (elf_tdata (abfd)->core_lwpid == tid)
+    return elfcore_maybe_make_sect (abfd, ".reg", sect);
+
+  return TRUE;
+}
+
+#define BFD_QNT_CORE_INFO      7
+#define BFD_QNT_CORE_STATUS    8
+#define BFD_QNT_CORE_GREG      9
+#define BFD_QNT_CORE_FPREG     10
+
+static bfd_boolean
+elfcore_grok_nto_note (abfd, note)
+     bfd *abfd;
+     Elf_Internal_Note *note;
+{
+  /* Every GREG section has a STATUS section before it.  Store the
+     tid from the previous call to pass down to the next gregs
+     function.  */
+  static pid_t tid = 1;
+
+  switch (note->type)
+    {
+    case BFD_QNT_CORE_INFO:   return elfcore_make_note_pseudosection (abfd, ".qnx_core_info", note);
+    case BFD_QNT_CORE_STATUS: return elfcore_grok_nto_status (abfd, note, &tid);
+    case BFD_QNT_CORE_GREG:   return elfcore_grok_nto_gregs (abfd, note, tid);
+    case BFD_QNT_CORE_FPREG:  return elfcore_grok_prfpreg (abfd, note);
+    default:                  return TRUE;
+    }
+}
+
 /* Function: elfcore_write_note
 
-   Inputs: 
+   Inputs:
      buffer to hold note
      name of note
      type of note
@@ -6545,16 +7160,30 @@ elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
      bfd  *abfd;
      char *buf;
      int  *bufsiz;
-     char *name;
+     const char *name;
      int  type;
-     void *input;
+     const PTR input;
      int  size;
 {
   Elf_External_Note *xnp;
-  int namesz = strlen (name);
-  int newspace = BFD_ALIGN (sizeof (Elf_External_Note) + size + namesz - 1, 4);
+  size_t namesz;
+  size_t pad;
+  size_t newspace;
   char *p, *dest;
 
+  namesz = 0;
+  pad = 0;
+  if (name != NULL)
+    {
+      struct elf_backend_data *bed;
+
+      namesz = strlen (name) + 1;
+      bed = get_elf_backend_data (abfd);
+      pad = -namesz & ((1 << bed->s->log_file_align) - 1);
+    }
+
+  newspace = sizeof (Elf_External_Note) - 1 + namesz + pad + size;
+
   p = realloc (buf, *bufsiz + newspace);
   dest = p + *bufsiz;
   *bufsiz += newspace;
@@ -6562,8 +7191,18 @@ elfcore_write_note (abfd, buf, bufsiz, name, type, input, size)
   H_PUT_32 (abfd, namesz, xnp->namesz);
   H_PUT_32 (abfd, size, xnp->descsz);
   H_PUT_32 (abfd, type, xnp->type);
-  strcpy (xnp->name, name);
-  memcpy (xnp->name + BFD_ALIGN (namesz, 4), input, size);
+  dest = xnp->name;
+  if (name != NULL)
+    {
+      memcpy (dest, name, namesz);
+      dest += namesz;
+      while (pad != 0)
+       {
+         *dest++ = '\0';
+         --pad;
+       }
+    }
+  memcpy (dest, input, size);
   return p;
 }
 
@@ -6573,8 +7212,8 @@ elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs)
      bfd  *abfd;
      char *buf;
      int  *bufsiz;
-     char *fname; 
-     char *psargs;
+     const char *fname;
+     const char *psargs;
 {
   int note_type;
   char *note_name = "CORE";
@@ -6590,7 +7229,7 @@ elfcore_write_prpsinfo (abfd, buf, bufsiz, fname, psargs)
   memset (&data, 0, sizeof (data));
   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, 
+  return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, note_type, &data, sizeof (data));
 }
 #endif /* PSINFO_T or PRPSINFO_T */
@@ -6603,7 +7242,7 @@ elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
      int *bufsiz;
      long pid;
      int cursig;
-     void *gregs;
+     const PTR gregs;
 {
   prstatus_t prstat;
   char *note_name = "CORE";
@@ -6612,7 +7251,7 @@ elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
   prstat.pr_pid = pid;
   prstat.pr_cursig = cursig;
   memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg));
-  return elfcore_write_note (abfd, buf, bufsiz, 
+  return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, NT_PRSTATUS, &prstat, sizeof (prstat));
 }
 #endif /* HAVE_PRSTATUS_T */
@@ -6625,7 +7264,7 @@ elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
      int *bufsiz;
      long pid;
      int cursig;
-     void *gregs;
+     const PTR gregs;
 {
   lwpstatus_t lwpstat;
   char *note_name = "CORE";
@@ -6644,7 +7283,7 @@ elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
          gregs, sizeof (lwpstat.pr_context.uc_mcontext.__gregs));
 #endif
 #endif
-  return elfcore_write_note (abfd, buf, bufsiz, note_name, 
+  return elfcore_write_note (abfd, buf, bufsiz, note_name,
                             NT_LWPSTATUS, &lwpstat, sizeof (lwpstat));
 }
 #endif /* HAVE_LWPSTATUS_T */
@@ -6657,14 +7296,14 @@ elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
      int *bufsiz;
      long pid;
      int cursig;
-     void *gregs;
+     const PTR gregs;
 {
   pstatus_t pstat;
   char *note_name = "CORE";
 
   memset (&pstat, 0, sizeof (pstat));
   pstat.pr_pid = pid & 0xffff;
-  buf = elfcore_write_note (abfd, buf, bufsiz, note_name, 
+  buf = elfcore_write_note (abfd, buf, bufsiz, note_name,
                            NT_PSTATUS, &pstat, sizeof (pstat));
   return buf;
 }
@@ -6675,11 +7314,11 @@ elfcore_write_prfpreg (abfd, buf, bufsiz, fpregs, size)
      bfd  *abfd;
      char *buf;
      int  *bufsiz;
-     void *fpregs;
+     const PTR fpregs;
      int size;
 {
   char *note_name = "CORE";
-  return elfcore_write_note (abfd, buf, bufsiz, 
+  return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, NT_FPREGSET, fpregs, size);
 }
 
@@ -6688,15 +7327,15 @@ elfcore_write_prxfpreg (abfd, buf, bufsiz, xfpregs, size)
      bfd  *abfd;
      char *buf;
      int  *bufsiz;
-     void *xfpregs;
+     const PTR xfpregs;
      int size;
 {
   char *note_name = "LINUX";
-  return elfcore_write_note (abfd, buf, bufsiz, 
+  return elfcore_write_note (abfd, buf, bufsiz,
                             note_name, NT_PRXFPREG, xfpregs, size);
 }
 
-static boolean
+static bfd_boolean
 elfcore_read_notes (abfd, offset, size)
      bfd *abfd;
      file_ptr offset;
@@ -6706,20 +7345,20 @@ elfcore_read_notes (abfd, offset, size)
   char *p;
 
   if (size <= 0)
-    return true;
+    return TRUE;
 
   if (bfd_seek (abfd, offset, SEEK_SET) != 0)
-    return false;
+    return FALSE;
 
   buf = bfd_malloc (size);
   if (buf == NULL)
-    return false;
+    return FALSE;
 
   if (bfd_bread (buf, size, abfd) != size)
     {
     error:
       free (buf);
-      return false;
+      return FALSE;
     }
 
   p = buf;
@@ -6743,6 +7382,11 @@ elfcore_read_notes (abfd, offset, size)
           if (! elfcore_grok_netbsd_note (abfd, &in))
             goto error;
         }
+      else if (strncmp (in.namedata, "QNX", 3) == 0)
+       {
+         if (! elfcore_grok_nto_note (abfd, &in))
+           goto error;
+       }
       else
         {
           if (! elfcore_grok_note (abfd, &in))
@@ -6753,7 +7397,7 @@ elfcore_read_notes (abfd, offset, size)
     }
 
   free (buf);
-  return true;
+  return TRUE;
 }
 \f
 /* Providing external access to the ELF program header table.  */
@@ -6873,7 +7517,7 @@ _bfd_elf_reloc_type_class (rela)
   return reloc_class_normal;
 }
 
-/* For RELA architectures, return what the relocation value for
+/* For RELA architectures, return the relocation value for a
    relocation against a local symbol.  */
 
 bfd_vma
@@ -6890,7 +7534,7 @@ _bfd_elf_rela_local_sym (abfd, sym, sec, rel)
                + sym->st_value);
   if ((sec->flags & SEC_MERGE)
       && ELF_ST_TYPE (sym->st_info) == STT_SECTION
-      && elf_section_data (sec)->sec_info_type == ELF_INFO_TYPE_MERGE)
+      && sec->sec_info_type == ELF_INFO_TYPE_MERGE)
     {
       asection *msec;
 
@@ -6912,10 +7556,10 @@ _bfd_elf_rel_local_sym (abfd, sym, psec, addend)
      Elf_Internal_Sym *sym;
      asection **psec;
      bfd_vma addend;
-{     
+{
   asection *sec = *psec;
 
-  if (elf_section_data (sec)->sec_info_type != ELF_INFO_TYPE_MERGE)
+  if (sec->sec_info_type != ELF_INFO_TYPE_MERGE)
     return sym->st_value + addend;
 
   return _bfd_merged_section_offset (abfd, psec,
@@ -6933,15 +7577,39 @@ _bfd_elf_section_offset (abfd, info, sec, offset)
   struct bfd_elf_section_data *sec_data;
 
   sec_data = elf_section_data (sec);
-  switch (sec_data->sec_info_type)
+  switch (sec->sec_info_type)
     {
     case ELF_INFO_TYPE_STABS:
-      return _bfd_stab_section_offset
-       (abfd, &elf_hash_table (info)->merge_info, sec, &sec_data->sec_info,
-        offset);
+      return _bfd_stab_section_offset (abfd,
+                                      &elf_hash_table (info)->merge_info,
+                                      sec, &sec_data->sec_info, offset);
     case ELF_INFO_TYPE_EH_FRAME:
       return _bfd_elf_eh_frame_section_offset (abfd, sec, offset);
     default:
       return offset;
     }
 }
+\f
+/* Create a new BFD as if by bfd_openr.  Rather than opening a file,
+   reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the VMAs from which the segments were read, and the VMAs the
+   file headers (and hence BFD's idea of each section's VMA) put them at.
+
+   The function TARGET_READ_MEMORY is called to copy LEN bytes from the
+   remote memory at target address VMA into the local buffer at MYADDR; it
+   should return zero on success or an `errno' code on failure.  TEMPL must
+   be a BFD for an ELF target with the word size and byte order found in
+   the remote memory.  */
+
+bfd *
+bfd_elf_bfd_from_remote_memory (templ, ehdr_vma, loadbasep, target_read_memory)
+     bfd *templ;
+     bfd_vma ehdr_vma;
+     bfd_vma *loadbasep;
+     int (*target_read_memory) PARAMS ((bfd_vma vma, char *myaddr, int len));
+{
+  return (*get_elf_backend_data (templ)->elf_backend_bfd_from_remote_memory)
+    (templ, ehdr_vma, loadbasep, target_read_memory);
+}
This page took 0.082515 seconds and 4 git commands to generate.