]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / elf.c
index 9fb5f24c3b604054bda53f11f383ee01c6894939..ae3af35ee2cea7bcdcdd1e6aa18c7439fb939ab2 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1044,61 +1044,6 @@ bfd_elf_generic_reloc (bfd *abfd ATTRIBUTE_UNUSED,
   return bfd_reloc_continue;
 }
 \f
-/* Make sure sec_info_type is cleared if sec_info is cleared too.  */
-
-static void
-merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
-                           asection *sec)
-{
-  BFD_ASSERT (sec->sec_info_type == ELF_INFO_TYPE_MERGE);
-  sec->sec_info_type = ELF_INFO_TYPE_NONE;
-}
-
-/* Finish SHF_MERGE section merging.  */
-
-bfd_boolean
-_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
-{
-  bfd *ibfd;
-  asection *sec;
-
-  if (!is_elf_hash_table (info->hash))
-    return FALSE;
-
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
-    if ((ibfd->flags & DYNAMIC) == 0)
-      for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-       if ((sec->flags & SEC_MERGE) != 0
-           && !bfd_is_abs_section (sec->output_section))
-         {
-           struct bfd_elf_section_data *secdata;
-
-           secdata = elf_section_data (sec);
-           if (! _bfd_add_merge_section (abfd,
-                                         &elf_hash_table (info)->merge_info,
-                                         sec, &secdata->sec_info))
-             return FALSE;
-           else if (secdata->sec_info)
-             sec->sec_info_type = ELF_INFO_TYPE_MERGE;
-         }
-
-  if (elf_hash_table (info)->merge_info != NULL)
-    _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info,
-                        merge_sections_remove_hook);
-  return TRUE;
-}
-
-void
-_bfd_elf_link_just_syms (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->hash))
-    return;
-
-  sec->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
-}
-\f
 /* Copy the program header and other data from one object module to
    another.  */
 
@@ -1419,7 +1364,7 @@ bfd_elf_print_symbol (bfd *abfd,
           we've already printed the size; now print the alignment.
           For other symbols, we have no specified alignment, and
           we've printed the address; now print the size.  */
-       if (bfd_is_com_section (symbol->section))
+       if (symbol->section && bfd_is_com_section (symbol->section))
          val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_value;
        else
          val = ((elf_symbol_type *) symbol)->internal_elf_sym.st_size;
@@ -1496,319 +1441,7 @@ bfd_elf_print_symbol (bfd *abfd,
       break;
     }
 }
-\f
-/* Create an entry in an ELF linker hash table.  */
-
-struct bfd_hash_entry *
-_bfd_elf_link_hash_newfunc (struct bfd_hash_entry *entry,
-                           struct bfd_hash_table *table,
-                           const char *string)
-{
-  /* Allocate the structure if it has not already been allocated by a
-     subclass.  */
-  if (entry == NULL)
-    {
-      entry = bfd_hash_allocate (table, sizeof (struct elf_link_hash_entry));
-      if (entry == NULL)
-       return entry;
-    }
-
-  /* Call the allocation method of the superclass.  */
-  entry = _bfd_link_hash_newfunc (entry, table, string);
-  if (entry != NULL)
-    {
-      struct elf_link_hash_entry *ret = (struct elf_link_hash_entry *) entry;
-      struct elf_link_hash_table *htab = (struct elf_link_hash_table *) table;
-
-      /* Set local fields.  */
-      ret->indx = -1;
-      ret->dynindx = -1;
-      ret->got = htab->init_got_refcount;
-      ret->plt = htab->init_plt_refcount;
-      memset (&ret->size, 0, (sizeof (struct elf_link_hash_entry)
-                             - offsetof (struct elf_link_hash_entry, size)));
-      /* Assume that we have been called by a non-ELF symbol reader.
-        This flag is then reset by the code which reads an ELF input
-        file.  This ensures that a symbol created by a non-ELF symbol
-        reader will have the flag set correctly.  */
-      ret->non_elf = 1;
-    }
-
-  return entry;
-}
-
-/* Copy data from an indirect symbol to its direct symbol, hiding the
-   old indirect symbol.  Also used for copying flags to a weakdef.  */
-
-void
-_bfd_elf_link_hash_copy_indirect (struct bfd_link_info *info,
-                                 struct elf_link_hash_entry *dir,
-                                 struct elf_link_hash_entry *ind)
-{
-  struct elf_link_hash_table *htab;
-
-  /* Copy down any references that we may have already seen to the
-     symbol which just became indirect.  */
-
-  dir->ref_dynamic |= ind->ref_dynamic;
-  dir->ref_regular |= ind->ref_regular;
-  dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
-  dir->non_got_ref |= ind->non_got_ref;
-  dir->needs_plt |= ind->needs_plt;
-  dir->pointer_equality_needed |= ind->pointer_equality_needed;
-
-  if (ind->root.type != bfd_link_hash_indirect)
-    return;
-
-  /* Copy over the global and procedure linkage table refcount entries.
-     These may have been already set up by a check_relocs routine.  */
-  htab = elf_hash_table (info);
-  if (ind->got.refcount > htab->init_got_refcount.refcount)
-    {
-      if (dir->got.refcount < 0)
-       dir->got.refcount = 0;
-      dir->got.refcount += ind->got.refcount;
-      ind->got.refcount = htab->init_got_refcount.refcount;
-    }
-
-  if (ind->plt.refcount > htab->init_plt_refcount.refcount)
-    {
-      if (dir->plt.refcount < 0)
-       dir->plt.refcount = 0;
-      dir->plt.refcount += ind->plt.refcount;
-      ind->plt.refcount = htab->init_plt_refcount.refcount;
-    }
-
-  if (ind->dynindx != -1)
-    {
-      if (dir->dynindx != -1)
-       _bfd_elf_strtab_delref (htab->dynstr, dir->dynstr_index);
-      dir->dynindx = ind->dynindx;
-      dir->dynstr_index = ind->dynstr_index;
-      ind->dynindx = -1;
-      ind->dynstr_index = 0;
-    }
-}
-
-void
-_bfd_elf_link_hash_hide_symbol (struct bfd_link_info *info,
-                               struct elf_link_hash_entry *h,
-                               bfd_boolean force_local)
-{
-  h->plt = elf_hash_table (info)->init_plt_offset;
-  h->needs_plt = 0;
-  if (force_local)
-    {
-      h->forced_local = 1;
-      if (h->dynindx != -1)
-       {
-         h->dynindx = -1;
-         _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
-                                 h->dynstr_index);
-       }
-    }
-}
-
-/* Initialize an ELF linker hash table.  */
-
-bfd_boolean
-_bfd_elf_link_hash_table_init
-  (struct elf_link_hash_table *table,
-   bfd *abfd,
-   struct bfd_hash_entry *(*newfunc) (struct bfd_hash_entry *,
-                                     struct bfd_hash_table *,
-                                     const char *),
-   unsigned int entsize)
-{
-  bfd_boolean ret;
-  int can_refcount = get_elf_backend_data (abfd)->can_refcount;
-
-  memset (table, 0, sizeof * table);
-  table->init_got_refcount.refcount = can_refcount - 1;
-  table->init_plt_refcount.refcount = can_refcount - 1;
-  table->init_got_offset.offset = -(bfd_vma) 1;
-  table->init_plt_offset.offset = -(bfd_vma) 1;
-  /* The first dynamic symbol is a dummy.  */
-  table->dynsymcount = 1;
-
-  ret = _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
-  table->root.type = bfd_link_elf_hash_table;
-
-  return ret;
-}
-
-/* Create an ELF linker hash table.  */
-
-struct bfd_link_hash_table *
-_bfd_elf_link_hash_table_create (bfd *abfd)
-{
-  struct elf_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf_link_hash_table);
-
-  ret = bfd_malloc (amt);
-  if (ret == NULL)
-    return NULL;
-
-  if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc,
-                                      sizeof (struct elf_link_hash_entry)))
-    {
-      free (ret);
-      return NULL;
-    }
 
-  return &ret->root;
-}
-
-/* This is a hook for the ELF emulation code in the generic linker to
-   tell the backend linker what file name to use for the DT_NEEDED
-   entry for a dynamic object.  */
-
-void
-bfd_elf_set_dt_needed_name (bfd *abfd, const char *name)
-{
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && bfd_get_format (abfd) == bfd_object)
-    elf_dt_name (abfd) = name;
-}
-
-int
-bfd_elf_get_dyn_lib_class (bfd *abfd)
-{
-  int lib_class;
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && bfd_get_format (abfd) == bfd_object)
-    lib_class = elf_dyn_lib_class (abfd);
-  else
-    lib_class = 0;
-  return lib_class;
-}
-
-void
-bfd_elf_set_dyn_lib_class (bfd *abfd, enum dynamic_lib_link_class lib_class)
-{
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && bfd_get_format (abfd) == bfd_object)
-    elf_dyn_lib_class (abfd) = lib_class;
-}
-
-/* Get the list of DT_NEEDED entries for a link.  This is a hook for
-   the linker ELF emulation code.  */
-
-struct bfd_link_needed_list *
-bfd_elf_get_needed_list (bfd *abfd ATTRIBUTE_UNUSED,
-                        struct bfd_link_info *info)
-{
-  if (! is_elf_hash_table (info->hash))
-    return NULL;
-  return elf_hash_table (info)->needed;
-}
-
-/* Get the list of DT_RPATH/DT_RUNPATH entries for a link.  This is a
-   hook for the linker ELF emulation code.  */
-
-struct bfd_link_needed_list *
-bfd_elf_get_runpath_list (bfd *abfd ATTRIBUTE_UNUSED,
-                         struct bfd_link_info *info)
-{
-  if (! is_elf_hash_table (info->hash))
-    return NULL;
-  return elf_hash_table (info)->runpath;
-}
-
-/* Get the name actually used for a dynamic object for a link.  This
-   is the SONAME entry if there is one.  Otherwise, it is the string
-   passed to bfd_elf_set_dt_needed_name, or it is the filename.  */
-
-const char *
-bfd_elf_get_dt_soname (bfd *abfd)
-{
-  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
-      && bfd_get_format (abfd) == bfd_object)
-    return elf_dt_name (abfd);
-  return NULL;
-}
-
-/* Get the list of DT_NEEDED entries from a BFD.  This is a hook for
-   the ELF linker emulation code.  */
-
-bfd_boolean
-bfd_elf_get_bfd_needed_list (bfd *abfd,
-                            struct bfd_link_needed_list **pneeded)
-{
-  asection *s;
-  bfd_byte *dynbuf = NULL;
-  int elfsec;
-  unsigned long shlink;
-  bfd_byte *extdyn, *extdynend;
-  size_t extdynsize;
-  void (*swap_dyn_in) (bfd *, const void *, Elf_Internal_Dyn *);
-
-  *pneeded = NULL;
-
-  if (bfd_get_flavour (abfd) != bfd_target_elf_flavour
-      || bfd_get_format (abfd) != bfd_object)
-    return TRUE;
-
-  s = bfd_get_section_by_name (abfd, ".dynamic");
-  if (s == NULL || s->size == 0)
-    return TRUE;
-
-  if (!bfd_malloc_and_get_section (abfd, s, &dynbuf))
-    goto error_return;
-
-  elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
-  if (elfsec == -1)
-    goto error_return;
-
-  shlink = elf_elfsections (abfd)[elfsec]->sh_link;
-
-  extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
-  swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
-
-  extdyn = dynbuf;
-  extdynend = extdyn + s->size;
-  for (; extdyn < extdynend; extdyn += extdynsize)
-    {
-      Elf_Internal_Dyn dyn;
-
-      (*swap_dyn_in) (abfd, extdyn, &dyn);
-
-      if (dyn.d_tag == DT_NULL)
-       break;
-
-      if (dyn.d_tag == DT_NEEDED)
-       {
-         const char *string;
-         struct bfd_link_needed_list *l;
-         unsigned int tagv = dyn.d_un.d_val;
-         bfd_size_type amt;
-
-         string = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
-         if (string == NULL)
-           goto error_return;
-
-         amt = sizeof *l;
-         l = bfd_alloc (abfd, amt);
-         if (l == NULL)
-           goto error_return;
-
-         l->by = abfd;
-         l->name = string;
-         l->next = *pneeded;
-         *pneeded = l;
-       }
-    }
-
-  free (dynbuf);
-
-  return TRUE;
-
- error_return:
-  if (dynbuf != NULL)
-    free (dynbuf);
-  return FALSE;
-}
-\f
 /* Allocate an ELF string table--force the first byte to be zero.  */
 
 struct bfd_strtab_hash *
@@ -2273,36 +1906,35 @@ bfd_section_from_r_symndx (bfd *abfd,
                           asection *sec,
                           unsigned long r_symndx)
 {
-  Elf_Internal_Shdr *symtab_hdr;
-  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;
+  asection *s;
 
-  if (cache->abfd == abfd && cache->indx[ent] == r_symndx)
-    return cache->sec[ent];
+  if (cache->abfd != abfd || cache->indx[ent] != r_symndx)
+    {
+      Elf_Internal_Shdr *symtab_hdr;
+      unsigned char esym[sizeof (Elf64_External_Sym)];
+      Elf_External_Sym_Shndx eshndx;
+      Elf_Internal_Sym isym;
 
-  symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-  if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
-                           &isym, esym, &eshndx) == NULL)
-    return NULL;
+      symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+      if (bfd_elf_get_elf_syms (abfd, symtab_hdr, 1, r_symndx,
+                               &isym, esym, &eshndx) == NULL)
+       return NULL;
 
-  if (cache->abfd != abfd)
-    {
-      memset (cache->indx, -1, sizeof (cache->indx));
-      cache->abfd = abfd;
-    }
-  cache->indx[ent] = r_symndx;
-  cache->sec[ent] = sec;
-  if ((isym.st_shndx != SHN_UNDEF && isym.st_shndx < SHN_LORESERVE)
-      || isym.st_shndx > SHN_HIRESERVE)
-    {
-      asection *s;
-      s = bfd_section_from_elf_index (abfd, isym.st_shndx);
-      if (s != NULL)
-       cache->sec[ent] = s;
+      if (cache->abfd != abfd)
+       {
+         memset (cache->indx, -1, sizeof (cache->indx));
+         cache->abfd = abfd;
+       }
+      cache->indx[ent] = r_symndx;
+      cache->shndx[ent] = isym.st_shndx;
     }
-  return cache->sec[ent];
+
+  s = bfd_section_from_elf_index (abfd, cache->shndx[ent]);
+  if (s != NULL)
+    return s;
+
+  return sec;
 }
 
 /* Given an ELF section number, retrieve the corresponding BFD
@@ -2591,7 +2223,7 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
    for the single program segment.  The first has the length specified by
    the file size of the segment, and the second has the length specified
    by the difference between the two sizes.  In effect, the segment is split
-   into it's initialized and uninitialized parts.
+   into its initialized and uninitialized parts.
 
  */
 
@@ -2610,40 +2242,46 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
   split = ((hdr->p_memsz > 0)
            && (hdr->p_filesz > 0)
            && (hdr->p_memsz > hdr->p_filesz));
-  sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
-  len = strlen (namebuf) + 1;
-  name = bfd_alloc (abfd, len);
-  if (!name)
-    return FALSE;
-  memcpy (name, namebuf, len);
-  newsect = bfd_make_section (abfd, name);
-  if (newsect == NULL)
-    return FALSE;
-  newsect->vma = hdr->p_vaddr;
-  newsect->lma = hdr->p_paddr;
-  newsect->size = hdr->p_filesz;
-  newsect->filepos = hdr->p_offset;
-  newsect->flags |= SEC_HAS_CONTENTS;
-  newsect->alignment_power = bfd_log2 (hdr->p_align);
-  if (hdr->p_type == PT_LOAD)
-    {
-      newsect->flags |= SEC_ALLOC;
-      newsect->flags |= SEC_LOAD;
-      if (hdr->p_flags & PF_X)
+
+  if (hdr->p_filesz > 0)
+    {
+      sprintf (namebuf, "%s%d%s", typename, index, split ? "a" : "");
+      len = strlen (namebuf) + 1;
+      name = bfd_alloc (abfd, len);
+      if (!name)
+       return FALSE;
+      memcpy (name, namebuf, len);
+      newsect = bfd_make_section (abfd, name);
+      if (newsect == NULL)
+       return FALSE;
+      newsect->vma = hdr->p_vaddr;
+      newsect->lma = hdr->p_paddr;
+      newsect->size = hdr->p_filesz;
+      newsect->filepos = hdr->p_offset;
+      newsect->flags |= SEC_HAS_CONTENTS;
+      newsect->alignment_power = bfd_log2 (hdr->p_align);
+      if (hdr->p_type == PT_LOAD)
        {
-         /* FIXME: all we known is that it has execute PERMISSION,
-            may be data.  */
-         newsect->flags |= SEC_CODE;
+         newsect->flags |= SEC_ALLOC;
+         newsect->flags |= SEC_LOAD;
+         if (hdr->p_flags & PF_X)
+           {
+             /* FIXME: all we known is that it has execute PERMISSION,
+                may be data.  */
+             newsect->flags |= SEC_CODE;
+           }
+       }
+      if (!(hdr->p_flags & PF_W))
+       {
+         newsect->flags |= SEC_READONLY;
        }
-    }
-  if (!(hdr->p_flags & PF_W))
-    {
-      newsect->flags |= SEC_READONLY;
     }
 
-  if (split)
+  if (hdr->p_memsz > hdr->p_filesz)
     {
-      sprintf (namebuf, "%s%db", typename, index);
+      bfd_vma align;
+
+      sprintf (namebuf, "%s%d%s", typename, index, split ? "b" : "");
       len = strlen (namebuf) + 1;
       name = bfd_alloc (abfd, len);
       if (!name)
@@ -2655,8 +2293,21 @@ _bfd_elf_make_section_from_phdr (bfd *abfd,
       newsect->vma = hdr->p_vaddr + hdr->p_filesz;
       newsect->lma = hdr->p_paddr + hdr->p_filesz;
       newsect->size = hdr->p_memsz - hdr->p_filesz;
+      newsect->filepos = hdr->p_offset + hdr->p_filesz;
+      align = newsect->vma & -newsect->vma;
+      if (align == 0 || align > hdr->p_align)
+       align = hdr->p_align;
+      newsect->alignment_power = bfd_log2 (align);
       if (hdr->p_type == PT_LOAD)
        {
+         /* Hack for gdb.  Segments that have not been modified do
+            not have their contents written to a core file, on the
+            assumption that a debugger can find the contents in the
+            executable.  We flag this case by setting the fake
+            section size to zero.  Note that "real" bss sections will
+            always have their contents dumped to the core file.  */
+         if (bfd_get_format (abfd) == bfd_core)
+           newsect->size = 0;
          newsect->flags |= SEC_ALLOC;
          if (hdr->p_flags & PF_X)
            newsect->flags |= SEC_CODE;
@@ -3697,6 +3348,19 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
        {
          /* We need a PT_NOTE segment.  */
          ++segs;
+         /* Try to create just one PT_NOTE segment
+            for all adjacent loadable .note* sections.
+            gABI requires that within a PT_NOTE segment
+            (and also inside of each SHT_NOTE section)
+            each note is padded to a multiple of 4 size,
+            so we check whether the sections are correctly
+            aligned.  */
+         if (s->alignment_power == 2)
+           while (s->next != NULL
+                  && s->next->alignment_power == 2
+                  && (s->next->flags & SEC_LOAD) != 0
+                  && CONST_STRNEQ (s->next->name, ".note"))
+             s = s->next;
        }
     }
 
@@ -3782,7 +3446,9 @@ _bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
 /* Possibly add or remove segments from the segment map.  */
 
 static bfd_boolean
-elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
+elf_modify_segment_map (bfd *abfd,
+                       struct bfd_link_info *info,
+                       bfd_boolean remove_empty_load)
 {
   struct elf_segment_map **m;
   const struct elf_backend_data *bed;
@@ -3809,7 +3475,7 @@ elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
        }
       (*m)->count = new_count;
 
-      if ((*m)->p_type == PT_LOAD && (*m)->count == 0)
+      if (remove_empty_load && (*m)->p_type == PT_LOAD && (*m)->count == 0)
        *m = (*m)->next;
       else
        m = &(*m)->next;
@@ -3834,9 +3500,10 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
   struct elf_segment_map *m;
   asection **sections = NULL;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  bfd_boolean no_user_phdrs;
 
-  if (elf_tdata (abfd)->segment_map == NULL
-      && bfd_count_sections (abfd) != 0)
+  no_user_phdrs = elf_tdata (abfd)->segment_map == NULL;
+  if (no_user_phdrs && bfd_count_sections (abfd) != 0)
     {
       asection *s;
       unsigned int i;
@@ -4071,25 +3738,47 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
          pm = &m->next;
        }
 
-      /* For each loadable .note section, add a PT_NOTE segment.  We don't
-        use bfd_get_section_by_name, because if we link together
-        nonloadable .note sections and loadable .note sections, we will
-        generate two .note sections in the output file.  FIXME: Using
-        names for section types is bogus anyhow.  */
+      /* For each batch of consecutive loadable .note sections,
+        add a PT_NOTE segment.  We don't use bfd_get_section_by_name,
+        because if we link together nonloadable .note sections and
+        loadable .note sections, we will generate two .note sections
+        in the output file.  FIXME: Using names for section types is
+        bogus anyhow.  */
       for (s = abfd->sections; s != NULL; s = s->next)
        {
          if ((s->flags & SEC_LOAD) != 0
              && CONST_STRNEQ (s->name, ".note"))
            {
+             asection *s2;
+             unsigned count = 1;
              amt = sizeof (struct elf_segment_map);
+             if (s->alignment_power == 2)
+               for (s2 = s; s2->next != NULL; s2 = s2->next)
+                 {
+                   if (s2->next->alignment_power == 2
+                       && (s2->next->flags & SEC_LOAD) != 0
+                       && CONST_STRNEQ (s2->next->name, ".note")
+                       && align_power (s2->vma + s2->size, 2)
+                          == s2->next->vma)
+                     count++;
+                   else
+                     break;
+                 }
+             amt += (count - 1) * sizeof (asection *);
              m = bfd_zalloc (abfd, amt);
              if (m == NULL)
                goto error_return;
              m->next = NULL;
              m->p_type = PT_NOTE;
-             m->count = 1;
-             m->sections[0] = s;
-
+             m->count = count;
+             while (count > 1)
+               {
+                 m->sections[m->count - count--] = s;
+                 BFD_ASSERT ((s->flags & SEC_THREAD_LOCAL) == 0);
+                 s = s->next;
+               }
+             m->sections[m->count - 1] = s;
+             BFD_ASSERT ((s->flags & SEC_THREAD_LOCAL) == 0);
              *pm = m;
              pm = &m->next;
            }
@@ -4183,7 +3872,7 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
       elf_tdata (abfd)->segment_map = mfirst;
     }
 
-  if (!elf_modify_segment_map (abfd, info))
+  if (!elf_modify_segment_map (abfd, info, no_user_phdrs))
     return FALSE;
 
   for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
@@ -4285,6 +3974,32 @@ vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
   return ((vma - off) % maxpagesize);
 }
 
+static void
+print_segment_map (const struct elf_segment_map *m)
+{
+  unsigned int j;
+  const char *pt = get_segment_type (m->p_type);
+  char buf[32];
+
+  if (pt == NULL)
+    {
+      if (m->p_type >= PT_LOPROC && m->p_type <= PT_HIPROC)
+       sprintf (buf, "LOPROC+%7.7x",
+                (unsigned int) (m->p_type - PT_LOPROC));
+      else if (m->p_type >= PT_LOOS && m->p_type <= PT_HIOS)
+       sprintf (buf, "LOOS+%7.7x",
+                (unsigned int) (m->p_type - PT_LOOS));
+      else
+       snprintf (buf, sizeof (buf), "%8.8x",
+                 (unsigned int) m->p_type);
+      pt = buf;
+    }
+  fprintf (stderr, "%s:", pt);
+  for (j = 0; j < m->count; j++)
+    fprintf (stderr, " %s", m->sections [j]->name);
+  putc ('\n',stderr);
+}
+
 /* Assign file positions to the sections based on the mapping from
    sections to segments.  This function also sets up some fields in
    the file header.  */
@@ -4303,7 +4018,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
   unsigned int i, j;
 
   if (link_info == NULL
-      && !elf_modify_segment_map (abfd, link_info))
+      && !elf_modify_segment_map (abfd, link_info, FALSE))
     return FALSE;
 
   alloc = 0;
@@ -4673,6 +4388,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
                (*_bfd_error_handler)
                  (_("%B: section `%A' can't be allocated in segment %d"),
                   abfd, sec, j);
+               print_segment_map (m);
                bfd_set_error (bfd_error_bad_value);
                return FALSE;
              }
@@ -5619,7 +5335,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
                  || (bed->want_p_paddr_set_to_zero &&
                      IS_CONTAINED_BY_VMA (output_section, segment)))
                {
-                 if (matching_lma == 0)
+                 if (matching_lma == 0 || output_section->lma < matching_lma)
                    matching_lma = output_section->lma;
 
                  /* We assume that if the section fits within the segment
@@ -5872,6 +5588,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       bfd_size_type amt;
       Elf_Internal_Shdr *this_hdr;
       asection *first_section = NULL;
+      asection *lowest_section = NULL;
 
       /* FIXME: Do we need to copy PT_NULL segment?  */
       if (segment->p_type == PT_NULL)
@@ -5886,7 +5603,9 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
          if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
            {
              if (!first_section)
-               first_section = section;
+               first_section = lowest_section = section;
+             if (section->lma < lowest_section->lma)
+               lowest_section = section;
              section_count++;
            }
        }
@@ -5932,7 +5651,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
 
       if (!map->includes_phdrs && !map->includes_filehdr)
        /* There is some other padding before the first section.  */
-       map->p_vaddr_offset = ((first_section ? first_section->lma : 0)
+       map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0)
                               - segment->p_paddr);
 
       if (section_count != 0)
@@ -8787,7 +8506,7 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   count = relplt->size / hdr->sh_entsize;
   size = count * sizeof (asymbol);
   p = relplt->relocation;
-  for (i = 0; i < count; i++, s++, p++)
+  for (i = 0; i < count; i++, p++)
     size += strlen ((*p->sym_ptr_ptr)->name) + sizeof ("@plt");
 
   s = *ret = bfd_malloc (size);
@@ -8825,365 +8544,11 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd,
   return n;
 }
 
-struct elf_symbuf_symbol
-{
-  unsigned long st_name;       /* Symbol name, index in string tbl */
-  unsigned char st_info;       /* Type and binding attributes */
-  unsigned char st_other;      /* Visibilty, and target specific */
-};
-
-struct elf_symbuf_head
-{
-  struct elf_symbuf_symbol *ssym;
-  bfd_size_type count;
-  unsigned int st_shndx;
-};
-
-struct elf_symbol
-{
-  union
-    {
-      Elf_Internal_Sym *isym;
-      struct elf_symbuf_symbol *ssym;
-    } u;
-  const char *name;
-};
-
-/* Sort references to symbols by ascending section number.  */
-
-static int
-elf_sort_elf_symbol (const void *arg1, const void *arg2)
-{
-  const Elf_Internal_Sym *s1 = *(const Elf_Internal_Sym **) arg1;
-  const Elf_Internal_Sym *s2 = *(const Elf_Internal_Sym **) arg2;
-
-  return s1->st_shndx - s2->st_shndx;
-}
-
-static int
-elf_sym_name_compare (const void *arg1, const void *arg2)
-{
-  const struct elf_symbol *s1 = (const struct elf_symbol *) arg1;
-  const struct elf_symbol *s2 = (const struct elf_symbol *) arg2;
-  return strcmp (s1->name, s2->name);
-}
-
-static struct elf_symbuf_head *
-elf_create_symbuf (bfd_size_type symcount, Elf_Internal_Sym *isymbuf)
-{
-  Elf_Internal_Sym **ind, **indbufend, **indbuf
-    = bfd_malloc2 (symcount, sizeof (*indbuf));
-  struct elf_symbuf_symbol *ssym;
-  struct elf_symbuf_head *ssymbuf, *ssymhead;
-  bfd_size_type i, shndx_count;
-
-  if (indbuf == NULL)
-    return NULL;
-
-  for (ind = indbuf, i = 0; i < symcount; i++)
-    if (isymbuf[i].st_shndx != SHN_UNDEF)
-      *ind++ = &isymbuf[i];
-  indbufend = ind;
-
-  qsort (indbuf, indbufend - indbuf, sizeof (Elf_Internal_Sym *),
-        elf_sort_elf_symbol);
-
-  shndx_count = 0;
-  if (indbufend > indbuf)
-    for (ind = indbuf, shndx_count++; ind < indbufend - 1; ind++)
-      if (ind[0]->st_shndx != ind[1]->st_shndx)
-       shndx_count++;
-
-  ssymbuf = bfd_malloc ((shndx_count + 1) * sizeof (*ssymbuf)
-                       + (indbufend - indbuf) * sizeof (*ssymbuf));
-  if (ssymbuf == NULL)
-    {
-      free (indbuf);
-      return NULL;
-    }
-
-  ssym = (struct elf_symbuf_symbol *) (ssymbuf + shndx_count);
-  ssymbuf->ssym = NULL;
-  ssymbuf->count = shndx_count;
-  ssymbuf->st_shndx = 0;
-  for (ssymhead = ssymbuf, ind = indbuf; ind < indbufend; ssym++, ind++)
-    {
-      if (ind == indbuf || ssymhead->st_shndx != (*ind)->st_shndx)
-       {
-         ssymhead++;
-         ssymhead->ssym = ssym;
-         ssymhead->count = 0;
-         ssymhead->st_shndx = (*ind)->st_shndx;
-       }
-      ssym->st_name = (*ind)->st_name;
-      ssym->st_info = (*ind)->st_info;
-      ssym->st_other = (*ind)->st_other;
-      ssymhead->count++;
-    }
-  BFD_ASSERT ((bfd_size_type) (ssymhead - ssymbuf) == shndx_count);
-
-  free (indbuf);
-  return ssymbuf;
-}
-
-/* Check if 2 sections define the same set of local and global
-   symbols.  */
-
-bfd_boolean
-bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2,
-                                  struct bfd_link_info *info)
-{
-  bfd *bfd1, *bfd2;
-  const struct elf_backend_data *bed1, *bed2;
-  Elf_Internal_Shdr *hdr1, *hdr2;
-  bfd_size_type symcount1, symcount2;
-  Elf_Internal_Sym *isymbuf1, *isymbuf2;
-  struct elf_symbuf_head *ssymbuf1, *ssymbuf2;
-  Elf_Internal_Sym *isym, *isymend;
-  struct elf_symbol *symtable1 = NULL, *symtable2 = NULL;
-  bfd_size_type count1, count2, i;
-  int shndx1, shndx2;
-  bfd_boolean result;
-
-  bfd1 = sec1->owner;
-  bfd2 = sec2->owner;
-
-  /* If both are .gnu.linkonce sections, they have to have the same
-     section name.  */
-  if (CONST_STRNEQ (sec1->name, ".gnu.linkonce")
-      && CONST_STRNEQ (sec2->name, ".gnu.linkonce"))
-    return strcmp (sec1->name + sizeof ".gnu.linkonce",
-                  sec2->name + sizeof ".gnu.linkonce") == 0;
-
-  /* Both sections have to be in ELF.  */
-  if (bfd_get_flavour (bfd1) != bfd_target_elf_flavour
-      || bfd_get_flavour (bfd2) != bfd_target_elf_flavour)
-    return FALSE;
-
-  if (elf_section_type (sec1) != elf_section_type (sec2))
-    return FALSE;
-
-  if ((elf_section_flags (sec1) & SHF_GROUP) != 0
-      && (elf_section_flags (sec2) & SHF_GROUP) != 0)
-    {
-      /* If both are members of section groups, they have to have the
-        same group name.  */
-      if (strcmp (elf_group_name (sec1), elf_group_name (sec2)) != 0)
-       return FALSE;
-    }
-
-  shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
-  shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
-  if (shndx1 == -1 || shndx2 == -1)
-    return FALSE;
-
-  bed1 = get_elf_backend_data (bfd1);
-  bed2 = get_elf_backend_data (bfd2);
-  hdr1 = &elf_tdata (bfd1)->symtab_hdr;
-  symcount1 = hdr1->sh_size / bed1->s->sizeof_sym;
-  hdr2 = &elf_tdata (bfd2)->symtab_hdr;
-  symcount2 = hdr2->sh_size / bed2->s->sizeof_sym;
-
-  if (symcount1 == 0 || symcount2 == 0)
-    return FALSE;
-
-  result = FALSE;
-  isymbuf1 = NULL;
-  isymbuf2 = NULL;
-  ssymbuf1 = elf_tdata (bfd1)->symbuf;
-  ssymbuf2 = elf_tdata (bfd2)->symbuf;
-
-  if (ssymbuf1 == NULL)
-    {
-      isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, symcount1, 0,
-                                      NULL, NULL, NULL);
-      if (isymbuf1 == NULL)
-       goto done;
-
-      if (!info->reduce_memory_overheads)
-       elf_tdata (bfd1)->symbuf = ssymbuf1
-         = elf_create_symbuf (symcount1, isymbuf1);
-    }
-
-  if (ssymbuf1 == NULL || ssymbuf2 == NULL)
-    {
-      isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, symcount2, 0,
-                                      NULL, NULL, NULL);
-      if (isymbuf2 == NULL)
-       goto done;
-
-      if (ssymbuf1 != NULL && !info->reduce_memory_overheads)
-       elf_tdata (bfd2)->symbuf = ssymbuf2
-         = elf_create_symbuf (symcount2, isymbuf2);
-    }
-
-  if (ssymbuf1 != NULL && ssymbuf2 != NULL)
-    {
-      /* Optimized faster version.  */
-      bfd_size_type lo, hi, mid;
-      struct elf_symbol *symp;
-      struct elf_symbuf_symbol *ssym, *ssymend;
-
-      lo = 0;
-      hi = ssymbuf1->count;
-      ssymbuf1++;
-      count1 = 0;
-      while (lo < hi)
-       {
-         mid = (lo + hi) / 2;
-         if ((unsigned int) shndx1 < ssymbuf1[mid].st_shndx)
-           hi = mid;
-         else if ((unsigned int) shndx1 > ssymbuf1[mid].st_shndx)
-           lo = mid + 1;
-         else
-           {
-             count1 = ssymbuf1[mid].count;
-             ssymbuf1 += mid;
-             break;
-           }
-       }
-
-      lo = 0;
-      hi = ssymbuf2->count;
-      ssymbuf2++;
-      count2 = 0;
-      while (lo < hi)
-       {
-         mid = (lo + hi) / 2;
-         if ((unsigned int) shndx2 < ssymbuf2[mid].st_shndx)
-           hi = mid;
-         else if ((unsigned int) shndx2 > ssymbuf2[mid].st_shndx)
-           lo = mid + 1;
-         else
-           {
-             count2 = ssymbuf2[mid].count;
-             ssymbuf2 += mid;
-             break;
-           }
-       }
-
-      if (count1 == 0 || count2 == 0 || count1 != count2)
-       goto done;
-
-      symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
-      symtable2 = bfd_malloc (count2 * sizeof (struct elf_symbol));
-      if (symtable1 == NULL || symtable2 == NULL)
-       goto done;
-
-      symp = symtable1;
-      for (ssym = ssymbuf1->ssym, ssymend = ssym + count1;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd1,
-                                                       hdr1->sh_link,
-                                                       ssym->st_name);
-       }
-
-      symp = symtable2;
-      for (ssym = ssymbuf2->ssym, ssymend = ssym + count2;
-          ssym < ssymend; ssym++, symp++)
-       {
-         symp->u.ssym = ssym;
-         symp->name = bfd_elf_string_from_elf_section (bfd2,
-                                                       hdr2->sh_link,
-                                                       ssym->st_name);
-       }
-
-      /* Sort symbol by name.  */
-      qsort (symtable1, count1, sizeof (struct elf_symbol),
-            elf_sym_name_compare);
-      qsort (symtable2, count1, sizeof (struct elf_symbol),
-            elf_sym_name_compare);
-
-      for (i = 0; i < count1; i++)
-       /* Two symbols must have the same binding, type and name.  */
-       if (symtable1 [i].u.ssym->st_info != symtable2 [i].u.ssym->st_info
-           || symtable1 [i].u.ssym->st_other != symtable2 [i].u.ssym->st_other
-           || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
-         goto done;
-
-      result = TRUE;
-      goto done;
-    }
-
-  symtable1 = bfd_malloc (symcount1 * sizeof (struct elf_symbol));
-  symtable2 = bfd_malloc (symcount2 * sizeof (struct elf_symbol));
-  if (symtable1 == NULL || symtable2 == NULL)
-    goto done;
-
-  /* Count definitions in the section.  */
-  count1 = 0;
-  for (isym = isymbuf1, isymend = isym + symcount1; isym < isymend; isym++)
-    if (isym->st_shndx == (unsigned int) shndx1)
-      symtable1[count1++].u.isym = isym;
-
-  count2 = 0;
-  for (isym = isymbuf2, isymend = isym + symcount2; isym < isymend; isym++)
-    if (isym->st_shndx == (unsigned int) shndx2)
-      symtable2[count2++].u.isym = isym;
-
-  if (count1 == 0 || count2 == 0 || count1 != count2)
-    goto done;
-
-  for (i = 0; i < count1; i++)
-    symtable1[i].name
-      = bfd_elf_string_from_elf_section (bfd1, hdr1->sh_link,
-                                        symtable1[i].u.isym->st_name);
-
-  for (i = 0; i < count2; i++)
-    symtable2[i].name
-      = bfd_elf_string_from_elf_section (bfd2, hdr2->sh_link,
-                                        symtable2[i].u.isym->st_name);
-
-  /* Sort symbol by name.  */
-  qsort (symtable1, count1, sizeof (struct elf_symbol),
-        elf_sym_name_compare);
-  qsort (symtable2, count1, sizeof (struct elf_symbol),
-        elf_sym_name_compare);
-
-  for (i = 0; i < count1; i++)
-    /* Two symbols must have the same binding, type and name.  */
-    if (symtable1 [i].u.isym->st_info != symtable2 [i].u.isym->st_info
-       || symtable1 [i].u.isym->st_other != symtable2 [i].u.isym->st_other
-       || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
-      goto done;
-
-  result = TRUE;
-
-done:
-  if (symtable1)
-    free (symtable1);
-  if (symtable2)
-    free (symtable2);
-  if (isymbuf1)
-    free (isymbuf1);
-  if (isymbuf2)
-    free (isymbuf2);
-
-  return result;
-}
-
 /* It is only used by x86-64 so far.  */
 asection _bfd_elf_large_com_section
   = BFD_FAKE_SECTION (_bfd_elf_large_com_section,
                      SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
 
-/* Return TRUE if 2 section types are compatible.  */
-
-bfd_boolean
-_bfd_elf_match_sections_by_type (bfd *abfd, const asection *asec,
-                                bfd *bbfd, const asection *bsec)
-{
-  if (asec == NULL
-      || bsec == NULL
-      || abfd->xvec->flavour != bfd_target_elf_flavour
-      || bbfd->xvec->flavour != bfd_target_elf_flavour)
-    return TRUE;
-
-  return elf_section_type (asec) == elf_section_type (bsec);
-}
-
 void
 _bfd_elf_set_osabi (bfd * abfd,
                    struct bfd_link_info * link_info ATTRIBUTE_UNUSED)