2006-09-10 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / bfd / elf.c
index 30e1efe6bb6adf19d7dbc382f655351d28b66869..e47f2667ffcf9e57df25011a9d2748bf410eaf87 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -206,16 +206,32 @@ bfd_elf_hash (const char *namearg)
   return h & 0xffffffff;
 }
 
+/* DT_GNU_HASH hash function.  Do not change this function; you will
+   cause invalid hash tables to be generated.  */
+
+unsigned long
+bfd_elf_gnu_hash (const char *namearg)
+{
+  const unsigned char *name = (const unsigned char *) namearg;
+  unsigned long h = 5381;
+  unsigned char ch;
+
+  while ((ch = *name++) != '\0')
+    h = (h << 5) + h + ch;
+  return h & 0xffffffff;
+}
+
 bfd_boolean
 bfd_elf_mkobject (bfd *abfd)
 {
-  /* This just does initialization.  */
-  /* coff_mkobject zalloc's space for tdata.coff_obj_data ...  */
-  elf_tdata (abfd) = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
-  if (elf_tdata (abfd) == 0)
-    return FALSE;
-  /* Since everything is done at close time, do we need any
-     initialization?  */
+  if (abfd->tdata.any == NULL)
+    {
+      abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+      if (abfd->tdata.any == NULL)
+       return FALSE;
+    }
+
+  elf_tdata (abfd)->program_header_size = (bfd_size_type) -1;
 
   return TRUE;
 }
@@ -803,7 +819,7 @@ _bfd_elf_make_section_from_shdr (bfd *abfd,
          { "debug",             5  },  /* 'd' */
          { NULL,                0  },  /* 'e' */
          { NULL,                0  },  /* 'f' */
-         { "gnu.linkonce.wi.", 17 },   /* 'g' */
+         { "gnu.linkonce.wi.", 16 },   /* 'g' */
          { NULL,                0  },  /* 'h' */
          { NULL,                0  },  /* 'i' */
          { NULL,                0  },  /* 'j' */
@@ -1239,6 +1255,7 @@ _bfd_elf_print_private_bfd_data (bfd *abfd, void *farg)
            case DT_AUXILIARY: name = "AUXILIARY"; stringp = TRUE; break;
            case DT_USED: name = "USED"; break;
            case DT_FILTER: name = "FILTER"; stringp = TRUE; break;
+           case DT_GNU_HASH: name = "GNU_HASH"; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -1579,6 +1596,7 @@ _bfd_elf_link_hash_table_init
   table->bucketcount = 0;
   table->needed = NULL;
   table->hgot = NULL;
+  table->hplt = NULL;
   table->merge_info = NULL;
   memset (&table->stab_info, 0, sizeof (table->stab_info));
   memset (&table->eh_info, 0, sizeof (table->eh_info));
@@ -1822,6 +1840,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
     case SHT_FINI_ARRAY:       /* .fini_array section.  */
     case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
     case SHT_GNU_LIBLIST:      /* .gnu.liblist section.  */
+    case SHT_GNU_HASH:         /* .gnu.hash section.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
 
     case SHT_DYNAMIC:  /* Dynamic linking information.  */
@@ -2113,13 +2132,11 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
       elf_dynversym (abfd) = shindex;
       elf_tdata (abfd)->dynversym_hdr = *hdr;
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
-      break;
 
     case SHT_GNU_verneed:
       elf_dynverref (abfd) = shindex;
       elf_tdata (abfd)->dynverref_hdr = *hdr;
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
-      break;
 
     case SHT_SHLIB:
       return TRUE;
@@ -2184,11 +2201,20 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
             "`%s' [0x%8x]"),
           abfd, name, hdr->sh_type);
       else if (hdr->sh_type >= SHT_LOOS && hdr->sh_type <= SHT_HIOS)
-       /* FIXME: We should handle this section.  */
-       (*_bfd_error_handler)
-         (_("%B: don't know how to handle OS specific section "
-            "`%s' [0x%8x]"),
-          abfd, name, hdr->sh_type);
+       {
+         /* Unrecognised OS-specific sections.  */
+         if ((hdr->sh_flags & SHF_OS_NONCONFORMING) != 0)
+           /* SHF_OS_NONCONFORMING indicates that special knowledge is
+              required to correctly process the section and the file should 
+              be rejected with an error message.  */
+           (*_bfd_error_handler)
+             (_("%B: don't know how to handle OS specific section "
+                "`%s' [0x%8x]"),
+              abfd, name, hdr->sh_type);
+         else
+           /* Otherwise it should be processed.  */
+           return _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex);
+       }
       else
        /* FIXME: We should handle this section.  */
        (*_bfd_error_handler)
@@ -2296,6 +2322,7 @@ static const struct bfd_elf_special_section special_sections_g[] =
   { ".gnu.version_r", 14,  0, SHT_GNU_verneed, 0 },
   { ".gnu.liblist",   12,  0, SHT_GNU_LIBLIST, SHF_ALLOC },
   { ".gnu.conflict",  13,  0, SHT_RELA,     SHF_ALLOC },
+  { ".gnu.hash",       9,  0, SHT_GNU_HASH, SHF_ALLOC },
   { NULL,              0,  0, 0,            0 }
 };
 
@@ -2487,10 +2514,13 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
   bed = get_elf_backend_data (abfd);
   sec->use_rela_p = bed->default_use_rela_p;
 
-  /* When we read a file, we don't need section type and flags unless
-     it is a linker created section.  They will be overridden in
-     _bfd_elf_make_section_from_shdr anyway.  */
-  if (abfd->direction != read_direction
+  /* When we read a file, we don't need to set ELF section type and
+     flags.  They will be overridden in _bfd_elf_make_section_from_shdr
+     anyway.  We will set ELF section type and flags for all linker
+     created sections.  If user specifies BFD section flags, we will
+     set ELF section type and flags based on BFD section flags in
+     elf_fake_sections.  */
+  if ((!sec->flags && abfd->direction != read_direction)
       || (sec->flags & SEC_LINKER_CREATED) != 0)
     {
       ssect = (*bed->get_sec_type_attr) (abfd, sec);
@@ -2501,7 +2531,7 @@ _bfd_elf_new_section_hook (bfd *abfd, asection *sec)
        }
     }
 
-  return TRUE;
+  return _bfd_generic_new_section_hook (abfd, sec);
 }
 
 /* Create a new bfd section from an ELF program header.
@@ -2735,8 +2765,8 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
       if ((asect->flags & SEC_GROUP) != 0)
        this_hdr->sh_type = SHT_GROUP;
       else if ((asect->flags & SEC_ALLOC) != 0
-         && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
-             || (asect->flags & SEC_NEVER_LOAD) != 0))
+              && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+                  || (asect->flags & SEC_NEVER_LOAD) != 0))
        this_hdr->sh_type = SHT_NOBITS;
       else
        this_hdr->sh_type = SHT_PROGBITS;
@@ -2809,6 +2839,10 @@ elf_fake_sections (bfd *abfd, asection *asect, void *failedptrarg)
     case SHT_GROUP:
       this_hdr->sh_entsize = 4;
       break;
+
+    case SHT_GNU_HASH:
+      this_hdr->sh_entsize = bed->s->arch_size == 64 ? 0 : 4;
+      break;
     }
 
   if ((asect->flags & SEC_ALLOC) != 0)
@@ -3254,6 +3288,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
          break;
 
        case SHT_HASH:
+       case SHT_GNU_HASH:
        case SHT_GNU_versym:
          /* sh_link is the section header index of the symbol table
             this hash table or version table is for.  */
@@ -3279,7 +3314,7 @@ assign_section_numbers (bfd *abfd, struct bfd_link_info *link_info)
 /* Map symbol from it's internal number to the external number, moving
    all local symbols to be at the head of the list.  */
 
-static int
+static bfd_boolean
 sym_is_global (bfd *abfd, asymbol *sym)
 {
   /* If the backend has a special mapping, use it.  */
@@ -3292,6 +3327,20 @@ sym_is_global (bfd *abfd, asymbol *sym)
          || bfd_is_com_section (bfd_get_section (sym)));
 }
 
+/* Don't output section symbols for sections that are not going to be
+   output.  Also, don't output section symbols for reloc and other
+   special sections.  */
+
+static bfd_boolean
+ignore_section_sym (bfd *abfd, asymbol *sym)
+{
+  return ((sym->flags & BSF_SECTION_SYM) != 0
+         && (sym->value != 0
+             || (sym->section->owner != abfd
+                 && (sym->section->output_section->owner != abfd
+                     || sym->section->output_offset != 0))));
+}
+
 static bfd_boolean
 elf_map_symbols (bfd *abfd)
 {
@@ -3332,51 +3381,29 @@ elf_map_symbols (bfd *abfd)
       asymbol *sym = syms[idx];
 
       if ((sym->flags & BSF_SECTION_SYM) != 0
-         && sym->value == 0)
+         && !ignore_section_sym (abfd, sym))
        {
-         asection *sec;
+         asection *sec = sym->section;
 
-         sec = sym->section;
+         if (sec->owner != abfd)
+           sec = sec->output_section;
 
-         if (sec->owner != NULL)
-           {
-             if (sec->owner != abfd)
-               {
-                 if (sec->output_offset != 0)
-                   continue;
-
-                 sec = sec->output_section;
-
-                 /* Empty sections in the input files may have had a
-                    section symbol created for them.  (See the comment
-                    near the end of _bfd_generic_link_output_symbols in
-                    linker.c).  If the linker script discards such
-                    sections then we will reach this point.  Since we know
-                    that we cannot avoid this case, we detect it and skip
-                    the abort and the assignment to the sect_syms array.
-                    To reproduce this particular case try running the
-                    linker testsuite test ld-scripts/weak.exp for an ELF
-                    port that uses the generic linker.  */
-                 if (sec->owner == NULL)
-                   continue;
-
-                 BFD_ASSERT (sec->owner == abfd);
-               }
-             sect_syms[sec->index] = syms[idx];
-           }
+         sect_syms[sec->index] = syms[idx];
        }
     }
 
   /* Classify all of the symbols.  */
   for (idx = 0; idx < symcount; idx++)
     {
+      if (ignore_section_sym (abfd, syms[idx]))
+       continue;
       if (!sym_is_global (abfd, syms[idx]))
        num_locals++;
       else
        num_globals++;
     }
 
-  /* We will be adding a section symbol for each BFD section.  Most normal
+  /* We will be adding a section symbol for each normal BFD section.  Most
      sections will already have a section symbol in outsymbols, but
      eg. SHT_GROUP sections will not, and we need the section symbol mapped
      at least in that case.  */
@@ -3402,6 +3429,8 @@ elf_map_symbols (bfd *abfd)
       asymbol *sym = syms[idx];
       unsigned int i;
 
+      if (ignore_section_sym (abfd, sym))
+       continue;
       if (!sym_is_global (abfd, sym))
        i = num_locals2++;
       else
@@ -3565,6 +3594,90 @@ _bfd_elf_compute_section_file_positions (bfd *abfd,
   return TRUE;
 }
 
+/* Make an initial estimate of the size of the program header.  If we
+   get the number wrong here, we'll redo section placement.  */
+
+static bfd_size_type
+get_program_header_size (bfd *abfd, struct bfd_link_info *info)
+{
+  size_t segs;
+  asection *s;
+  const struct elf_backend_data *bed;
+
+  /* Assume we will need exactly two PT_LOAD segments: one for text
+     and one for data.  */
+  segs = 2;
+
+  s = bfd_get_section_by_name (abfd, ".interp");
+  if (s != NULL && (s->flags & SEC_LOAD) != 0)
+    {
+      /* If we have a loadable interpreter section, we need a
+        PT_INTERP segment.  In this case, assume we also need a
+        PT_PHDR segment, although that may not be true for all
+        targets.  */
+      segs += 2;
+    }
+
+  if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
+    {
+      /* We need a PT_DYNAMIC segment.  */
+      ++segs;
+      
+      if (elf_tdata (abfd)->relro)
+       {
+         /* We need a PT_GNU_RELRO segment only when there is a
+            PT_DYNAMIC segment.  */
+         ++segs;
+       }
+    }
+
+  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
+         && strncmp (s->name, ".note", 5) == 0)
+       {
+         /* We need a PT_NOTE segment.  */
+         ++segs;
+       }
+    }
+
+  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.  */
+  bed = get_elf_backend_data (abfd);
+  if (bed->elf_backend_additional_program_headers)
+    {
+      int a;
+
+      a = (*bed->elf_backend_additional_program_headers) (abfd, info);
+      if (a == -1)
+       abort ();
+      segs += a;
+    }
+
+  return segs * bed->s->sizeof_phdr;
+}
+
 /* Create a mapping from a set of sections to a program segment.  */
 
 static struct elf_segment_map *
@@ -3619,359 +3732,413 @@ _bfd_elf_make_dynamic_segment (bfd *abfd, asection *dynsec)
   return m;
 }
 
-/* Set up a mapping from BFD sections to program segments.  */
+/* Possibly add or remove segments from the segment map.  */
 
 static bfd_boolean
-map_sections_to_segments (bfd *abfd)
+elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
 {
-  asection **sections = NULL;
-  asection *s;
-  unsigned int i;
-  unsigned int count;
-  struct elf_segment_map *mfirst;
-  struct elf_segment_map **pm;
-  struct elf_segment_map *m;
-  asection *last_hdr;
-  bfd_vma last_size;
-  unsigned int phdr_index;
-  bfd_vma maxpagesize;
-  asection **hdrpp;
-  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;
+  struct elf_segment_map **m;
+  const struct elf_backend_data *bed;
 
-  if (bfd_count_sections (abfd) == 0)
-    return TRUE;
+  /* 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.  We also remove excluded
+     sections.  Finally, any PT_LOAD segment without sections is
+     removed.  */
+  m = &elf_tdata (abfd)->segment_map;
+  while (*m)
+    {
+      unsigned int i, new_count;
 
-  /* Select the allocated sections, and sort them.  */
+      for (new_count = 0, i = 0; i < (*m)->count; i++)
+       {
+         if (((*m)->sections[i]->flags & SEC_EXCLUDE) == 0
+             && (((*m)->sections[i]->flags & SEC_ALLOC) != 0
+                 || (*m)->p_type != PT_LOAD))
+           {
+             (*m)->sections[new_count] = (*m)->sections[i];
+             new_count++;
+           }
+       }
+      (*m)->count = new_count;
 
-  sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
-  if (sections == NULL)
-    goto error_return;
+      if ((*m)->p_type == PT_LOAD && (*m)->count == 0)
+       *m = (*m)->next;
+      else
+       m = &(*m)->next;
+    }
 
-  i = 0;
-  for (s = abfd->sections; s != NULL; s = s->next)
+  bed = get_elf_backend_data (abfd);
+  if (bed->elf_backend_modify_segment_map != NULL)
     {
-      if ((s->flags & SEC_ALLOC) != 0)
-       {
-         sections[i] = s;
-         ++i;
-       }
+      if (!(*bed->elf_backend_modify_segment_map) (abfd, info))
+       return FALSE;
     }
-  BFD_ASSERT (i <= bfd_count_sections (abfd));
-  count = i;
 
-  qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
+  return TRUE;
+}
 
-  /* Build the mapping.  */
+/* Set up a mapping from BFD sections to program segments.  */
 
-  mfirst = NULL;
-  pm = &mfirst;
+bfd_boolean
+_bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info)
+{
+  unsigned int count;
+  struct elf_segment_map *m;
+  asection **sections = NULL;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
-  /* If we have a .interp section, then create a PT_PHDR segment for
-     the program headers and a PT_INTERP segment for the .interp
-     section.  */
-  s = bfd_get_section_by_name (abfd, ".interp");
-  if (s != NULL && (s->flags & SEC_LOAD) != 0)
+  if (elf_tdata (abfd)->segment_map == NULL
+      && bfd_count_sections (abfd) != 0)
     {
-      amt = sizeof (struct elf_segment_map);
-      m = bfd_zalloc (abfd, amt);
-      if (m == NULL)
-       goto error_return;
-      m->next = NULL;
-      m->p_type = PT_PHDR;
-      /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not.  */
-      m->p_flags = PF_R | PF_X;
-      m->p_flags_valid = 1;
-      m->includes_phdrs = 1;
+      asection *s;
+      unsigned int i;
+      struct elf_segment_map *mfirst;
+      struct elf_segment_map **pm;
+      asection *last_hdr;
+      bfd_vma last_size;
+      unsigned int phdr_index;
+      bfd_vma maxpagesize;
+      asection **hdrpp;
+      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;
 
-      *pm = m;
-      pm = &m->next;
+      /* Select the allocated sections, and sort them.  */
 
-      amt = sizeof (struct elf_segment_map);
-      m = bfd_zalloc (abfd, amt);
-      if (m == NULL)
+      sections = bfd_malloc2 (bfd_count_sections (abfd), sizeof (asection *));
+      if (sections == NULL)
        goto error_return;
-      m->next = NULL;
-      m->p_type = PT_INTERP;
-      m->count = 1;
-      m->sections[0] = s;
-
-      *pm = m;
-      pm = &m->next;
-    }
-
-  /* Look through the sections.  We put sections in the same program
-     segment when the start of the second section can be placed within
-     a few bytes of the end of the first section.  */
-  last_hdr = NULL;
-  last_size = 0;
-  phdr_index = 0;
-  maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
-  writable = FALSE;
-  dynsec = bfd_get_section_by_name (abfd, ".dynamic");
-  if (dynsec != NULL
-      && (dynsec->flags & SEC_LOAD) == 0)
-    dynsec = NULL;
-
-  /* Deal with -Ttext or something similar such that the first section
-     is not adjacent to the program headers.  This is an
-     approximation, since at this point we don't know exactly how many
-     program headers we will need.  */
-  if (count > 0)
-    {
-      bfd_size_type phdr_size;
-
-      phdr_size = elf_tdata (abfd)->program_header_size;
-      if (phdr_size == 0)
-       phdr_size = get_elf_backend_data (abfd)->s->sizeof_phdr;
-      if ((abfd->flags & D_PAGED) == 0
-         || sections[0]->lma < phdr_size
-         || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
-       phdr_in_segment = FALSE;
-    }
-
-  for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
-    {
-      asection *hdr;
-      bfd_boolean new_segment;
-
-      hdr = *hdrpp;
-
-      /* See if this section and the last one will fit in the same
-         segment.  */
-
-      if (last_hdr == NULL)
-       {
-         /* 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;
-       }
-      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;
-       }
-      else if (BFD_ALIGN (last_hdr->lma + last_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;
-       }
-      else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
-              && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
-       {
-         /* We don't want to put a loadable section after a
-             nonloadable section in the same segment.
-             Consider .tbss sections as loadable for this purpose.  */
-         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;
-       }
-      else if (! writable
-              && (hdr->flags & SEC_READONLY) == 0
-              && (((last_hdr->lma + last_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
-             anyhow.  We already know that the last section does not
-             bring us past the current section on the page, so the
-             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;
-       }
-      else
-       {
-         /* Otherwise, we can use the same segment.  */
-         new_segment = FALSE;
-       }
 
-      if (! new_segment)
+      i = 0;
+      for (s = abfd->sections; s != NULL; s = s->next)
        {
-         if ((hdr->flags & SEC_READONLY) == 0)
-           writable = TRUE;
-         last_hdr = hdr;
-         /* .tbss sections effectively have zero size.  */
-         if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
-           last_size = hdr->size;
-         else
-           last_size = 0;
-         continue;
+         if ((s->flags & SEC_ALLOC) != 0)
+           {
+             sections[i] = s;
+             ++i;
+           }
        }
+      BFD_ASSERT (i <= bfd_count_sections (abfd));
+      count = i;
 
-      /* We need a new program segment.  We must create a new program
-         header holding all the sections from phdr_index until hdr.  */
-
-      m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
-      if (m == NULL)
-       goto error_return;
-
-      *pm = m;
-      pm = &m->next;
-
-      if ((hdr->flags & SEC_READONLY) == 0)
-       writable = TRUE;
-      else
-       writable = FALSE;
+      qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
 
-      last_hdr = hdr;
-      /* .tbss sections effectively have zero size.  */
-      if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
-       last_size = hdr->size;
-      else
-       last_size = 0;
-      phdr_index = i;
-      phdr_in_segment = FALSE;
-    }
+      /* Build the mapping.  */
 
-  /* Create a final PT_LOAD program segment.  */
-  if (last_hdr != NULL)
-    {
-      m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
-      if (m == NULL)
-       goto error_return;
+      mfirst = NULL;
+      pm = &mfirst;
 
-      *pm = m;
-      pm = &m->next;
-    }
+      /* If we have a .interp section, then create a PT_PHDR segment for
+        the program headers and a PT_INTERP segment for the .interp
+        section.  */
+      s = bfd_get_section_by_name (abfd, ".interp");
+      if (s != NULL && (s->flags & SEC_LOAD) != 0)
+       {
+         amt = sizeof (struct elf_segment_map);
+         m = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           goto error_return;
+         m->next = NULL;
+         m->p_type = PT_PHDR;
+         /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not.  */
+         m->p_flags = PF_R | PF_X;
+         m->p_flags_valid = 1;
+         m->includes_phdrs = 1;
 
-  /* If there is a .dynamic section, throw in a PT_DYNAMIC segment.  */
-  if (dynsec != NULL)
-    {
-      m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
-      if (m == NULL)
-       goto error_return;
-      *pm = m;
-      pm = &m->next;
-    }
+         *pm = m;
+         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 (s = abfd->sections; s != NULL; s = s->next)
-    {
-      if ((s->flags & SEC_LOAD) != 0
-         && strncmp (s->name, ".note", 5) == 0)
-       {
          amt = sizeof (struct elf_segment_map);
          m = bfd_zalloc (abfd, amt);
          if (m == NULL)
            goto error_return;
          m->next = NULL;
-         m->p_type = PT_NOTE;
+         m->p_type = PT_INTERP;
          m->count = 1;
          m->sections[0] = s;
 
          *pm = m;
          pm = &m->next;
        }
-      if (s->flags & SEC_THREAD_LOCAL)
+
+      /* Look through the sections.  We put sections in the same program
+        segment when the start of the second section can be placed within
+        a few bytes of the end of the first section.  */
+      last_hdr = NULL;
+      last_size = 0;
+      phdr_index = 0;
+      maxpagesize = bed->maxpagesize;
+      writable = FALSE;
+      dynsec = bfd_get_section_by_name (abfd, ".dynamic");
+      if (dynsec != NULL
+         && (dynsec->flags & SEC_LOAD) == 0)
+       dynsec = NULL;
+
+      /* Deal with -Ttext or something similar such that the first section
+        is not adjacent to the program headers.  This is an
+        approximation, since at this point we don't know exactly how many
+        program headers we will need.  */
+      if (count > 0)
        {
-         if (! tls_count)
-           first_tls = s;
-         tls_count++;
+         bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+
+         if (phdr_size == (bfd_size_type) -1)
+           phdr_size = get_program_header_size (abfd, info);
+         if ((abfd->flags & D_PAGED) == 0
+             || sections[0]->lma < phdr_size
+             || sections[0]->lma % maxpagesize < phdr_size % maxpagesize)
+           phdr_in_segment = FALSE;
        }
-    }
-
-  /* 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 = 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)
+      for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
        {
-         BFD_ASSERT (first_tls->flags & SEC_THREAD_LOCAL);
-         m->sections[i] = first_tls;
-         first_tls = first_tls->next;
-       }
+         asection *hdr;
+         bfd_boolean new_segment;
 
-      *pm = m;
-      pm = &m->next;
-    }
+         hdr = *hdrpp;
 
-  /* If there is a .eh_frame_hdr section, throw in a PT_GNU_EH_FRAME
-     segment.  */
-  eh_frame_hdr = elf_tdata (abfd)->eh_frame_hdr;
-  if (eh_frame_hdr != NULL
-      && (eh_frame_hdr->output_section->flags & SEC_LOAD) != 0)
-    {
-      amt = sizeof (struct elf_segment_map);
-      m = bfd_zalloc (abfd, amt);
-      if (m == NULL)
-       goto error_return;
-      m->next = NULL;
-      m->p_type = PT_GNU_EH_FRAME;
-      m->count = 1;
-      m->sections[0] = eh_frame_hdr->output_section;
+         /* See if this section and the last one will fit in the same
+            segment.  */
 
-      *pm = m;
-      pm = &m->next;
-    }
+         if (last_hdr == NULL)
+           {
+             /* 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;
+           }
+         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;
+           }
+         else if (BFD_ALIGN (last_hdr->lma + last_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;
+           }
+         else if ((last_hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) == 0
+                  && (hdr->flags & (SEC_LOAD | SEC_THREAD_LOCAL)) != 0)
+           {
+             /* We don't want to put a loadable section after a
+                nonloadable section in the same segment.
+                Consider .tbss sections as loadable for this purpose.  */
+             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;
+           }
+         else if (! writable
+                  && (hdr->flags & SEC_READONLY) == 0
+                  && (((last_hdr->lma + last_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
+                anyhow.  We already know that the last section does not
+                bring us past the current section on the page, so the
+                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;
+           }
+         else
+           {
+             /* Otherwise, we can use the same segment.  */
+             new_segment = FALSE;
+           }
 
-  if (elf_tdata (abfd)->stack_flags)
-    {
-      amt = sizeof (struct elf_segment_map);
-      m = 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;
+         if (! new_segment)
+           {
+             if ((hdr->flags & SEC_READONLY) == 0)
+               writable = TRUE;
+             last_hdr = hdr;
+             /* .tbss sections effectively have zero size.  */
+             if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
+                 != SEC_THREAD_LOCAL)
+               last_size = hdr->size;
+             else
+               last_size = 0;
+             continue;
+           }
 
-      *pm = m;
-      pm = &m->next;
-    }
+         /* We need a new program segment.  We must create a new program
+            header holding all the sections from phdr_index until hdr.  */
 
-  if (elf_tdata (abfd)->relro)
-    {
-      amt = sizeof (struct elf_segment_map);
-      m = bfd_zalloc (abfd, amt);
-      if (m == NULL)
-       goto error_return;
-      m->next = NULL;
-      m->p_type = PT_GNU_RELRO;
-      m->p_flags = PF_R;
-      m->p_flags_valid = 1;
+         m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+         if (m == NULL)
+           goto error_return;
+
+         *pm = m;
+         pm = &m->next;
+
+         if ((hdr->flags & SEC_READONLY) == 0)
+           writable = TRUE;
+         else
+           writable = FALSE;
+
+         last_hdr = hdr;
+         /* .tbss sections effectively have zero size.  */
+         if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
+           last_size = hdr->size;
+         else
+           last_size = 0;
+         phdr_index = i;
+         phdr_in_segment = FALSE;
+       }
+
+      /* Create a final PT_LOAD program segment.  */
+      if (last_hdr != NULL)
+       {
+         m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment);
+         if (m == NULL)
+           goto error_return;
+
+         *pm = m;
+         pm = &m->next;
+       }
+
+      /* If there is a .dynamic section, throw in a PT_DYNAMIC segment.  */
+      if (dynsec != NULL)
+       {
+         m = _bfd_elf_make_dynamic_segment (abfd, dynsec);
+         if (m == NULL)
+           goto error_return;
+         *pm = m;
+         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 (s = abfd->sections; s != NULL; s = s->next)
+       {
+         if ((s->flags & SEC_LOAD) != 0
+             && strncmp (s->name, ".note", 5) == 0)
+           {
+             amt = sizeof (struct elf_segment_map);
+             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;
+
+             *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 = 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 = 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 = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           goto error_return;
+         m->next = NULL;
+         m->p_type = PT_GNU_EH_FRAME;
+         m->count = 1;
+         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 = 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;
+       }
+
+      if (dynsec != NULL && elf_tdata (abfd)->relro)
+       {
+         /* We make a PT_GNU_RELRO segment only when there is a
+            PT_DYNAMIC segment.  */
+         amt = sizeof (struct elf_segment_map);
+         m = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           goto error_return;
+         m->next = NULL;
+         m->p_type = PT_GNU_RELRO;
+         m->p_flags = PF_R;
+         m->p_flags_valid = 1;
+
+         *pm = m;
+         pm = &m->next;
+       }
 
-      *pm = m;
-      pm = &m->next;
+      free (sections);
+      elf_tdata (abfd)->segment_map = mfirst;
     }
 
-  free (sections);
-  sections = NULL;
+  if (!elf_modify_segment_map (abfd, info))
+    return FALSE;
+
+  for (count = 0, m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+    ++count;
+  elf_tdata (abfd)->program_header_size = count * bed->s->sizeof_phdr;
 
-  elf_tdata (abfd)->segment_map = mfirst;
   return TRUE;
 
  error_return:
@@ -4067,148 +4234,59 @@ vma_page_aligned_bias (bfd_vma vma, ufile_ptr off, bfd_vma maxpagesize)
   return ((vma - off) % maxpagesize);
 }
 
-static void
-print_segment_map (bfd *abfd)
-{
-  struct elf_segment_map *m;
-  unsigned int i, j;
-
-  fprintf (stderr, _(" Section to Segment mapping:\n"));
-  fprintf (stderr, _("  Segment              Sections...\n"));
-
-  for (i= 0, m = elf_tdata (abfd)->segment_map;
-       m != NULL;
-       i++, m = m->next)
-    {
-      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, "  %2.2d: %14.14s:  ", i, 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, and writes out the program headers.  */
+   the file header.  */
 
 static bfd_boolean
-assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
+assign_file_positions_for_load_sections (bfd *abfd,
+                                        struct bfd_link_info *link_info)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-  unsigned int count;
   struct elf_segment_map *m;
-  unsigned int alloc;
   Elf_Internal_Phdr *phdrs;
-  file_ptr off, voff;
-  bfd_vma filehdr_vaddr, filehdr_paddr;
-  bfd_vma phdrs_vaddr, phdrs_paddr;
   Elf_Internal_Phdr *p;
-  Elf_Internal_Shdr **i_shdrpp;
-  Elf_Internal_Shdr **hdrpp;
+  file_ptr off, voff;
+  bfd_size_type maxpagesize;
+  unsigned int alloc;
   unsigned int i;
-  unsigned int num_sec;
 
-  if (elf_tdata (abfd)->segment_map == NULL)
-    {
-      if (! map_sections_to_segments (abfd))
-       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.  We also remove excluded
-        sections.  */
-      for (m = elf_tdata (abfd)->segment_map;
-          m != NULL;
-          m = m->next)
-       {
-         unsigned int new_count;
-
-         new_count = 0;
-         for (i = 0; i < m->count; i ++)
-           {
-             if ((m->sections[i]->flags & SEC_EXCLUDE) == 0
-                 && ((m->sections[i]->flags & SEC_ALLOC) != 0
-                     || m->p_type != PT_LOAD))
-               {
-                 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, link_info))
-       return FALSE;
-    }
+  if (link_info == NULL
+      && !elf_modify_segment_map (abfd, link_info))
+    return FALSE;
 
-  count = 0;
+  alloc = 0;
   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-    ++count;
+    ++alloc;
 
   elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
   elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
-  elf_elfheader (abfd)->e_phnum = count;
+  elf_elfheader (abfd)->e_phnum = alloc;
+
+  if (elf_tdata (abfd)->program_header_size == (bfd_size_type) -1)
+    elf_tdata (abfd)->program_header_size = alloc * bed->s->sizeof_phdr;
+  else
+    BFD_ASSERT (elf_tdata (abfd)->program_header_size
+               == alloc * bed->s->sizeof_phdr);
 
-  if (count == 0)
+  if (alloc == 0)
     {
       elf_tdata (abfd)->next_file_pos = bed->s->sizeof_ehdr;
       return TRUE;
     }
 
-  /* If we already counted the number of program segments, make sure
-     that we allocated enough space.  This happens when SIZEOF_HEADERS
-     is used in a linker script.  */
-  alloc = elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr;
-  if (alloc != 0 && count > alloc)
-    {
-      ((*_bfd_error_handler)
-       (_("%B: Not enough room for program headers (allocated %u, need %u)"),
-       abfd, alloc, count));
-      print_segment_map (abfd);
-      bfd_set_error (bfd_error_bad_value);
-      return FALSE;
-    }
-
-  if (alloc == 0)
-    alloc = count;
-
   phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
+  elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
 
+  maxpagesize = 1;
+  if ((abfd->flags & D_PAGED) != 0)
+    maxpagesize = bed->maxpagesize;
+
   off = bed->s->sizeof_ehdr;
   off += alloc * bed->s->sizeof_phdr;
 
-  filehdr_vaddr = 0;
-  filehdr_paddr = 0;
-  phdrs_vaddr = 0;
-  phdrs_paddr = 0;
-
   for (m = elf_tdata (abfd)->segment_map, p = phdrs;
        m != NULL;
        m = m->next, p++)
@@ -4237,6 +4315,39 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
       p->p_type = m->p_type;
       p->p_flags = m->p_flags;
 
+      if (m->count == 0)
+       p->p_vaddr = 0;
+      else
+       p->p_vaddr = m->sections[0]->vma;
+
+      if (m->p_paddr_valid)
+       p->p_paddr = m->p_paddr;
+      else if (m->count == 0)
+       p->p_paddr = 0;
+      else
+       p->p_paddr = m->sections[0]->lma;
+
+      if (p->p_type == PT_LOAD
+         && (abfd->flags & D_PAGED) != 0)
+       {
+         /* p_align in demand paged PT_LOAD segments effectively stores
+            the maximum page size.  When copying an executable with
+            objcopy, we set m->p_align from the input file.  Use this
+            value for maxpagesize rather than bed->maxpagesize, which
+            may be different.  Note that we use maxpagesize for PT_TLS
+            segment alignment later in this function, so we are relying
+            on at least one PT_LOAD segment appearing before a PT_TLS
+            segment.  */
+         if (m->p_align_valid)
+           maxpagesize = m->p_align;
+
+         p->p_align = maxpagesize;
+       }
+      else if (m->count == 0)
+       p->p_align = 1 << bed->s->log_file_align;
+      else
+       p->p_align = 0;
+
       if (p->p_type == PT_LOAD
          && m->count > 0)
        {
@@ -4254,8 +4365,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
            }
          align = (bfd_size_type) 1 << align_power;
 
-         if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align)
-           align = bed->maxpagesize;
+         if (align < maxpagesize)
+           align = maxpagesize;
 
          adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
          off += adjust;
@@ -4271,7 +4382,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                 .tbss, we need to look at the next section to decide
                 whether the segment has any loadable sections.  */
              i = 0;
-             while ((m->sections[i]->flags & SEC_LOAD) == 0)
+             while ((m->sections[i]->flags & SEC_LOAD) == 0
+                    && (m->sections[i]->flags & SEC_HAS_CONTENTS) == 0)
                {
                  if ((m->sections[i]->flags & SEC_THREAD_LOCAL) == 0
                      || ++i >= m->count)
@@ -4296,26 +4408,6 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
          return FALSE;
        }
 
-      if (m->count == 0)
-       p->p_vaddr = 0;
-      else
-       p->p_vaddr = m->sections[0]->vma;
-
-      if (m->p_paddr_valid)
-       p->p_paddr = m->p_paddr;
-      else if (m->count == 0)
-       p->p_paddr = 0;
-      else
-       p->p_paddr = m->sections[0]->lma;
-
-      if (p->p_type == PT_LOAD
-         && (abfd->flags & D_PAGED) != 0)
-       p->p_align = bed->maxpagesize;
-      else if (m->count == 0)
-       p->p_align = 1 << bed->s->log_file_align;
-      else
-       p->p_align = 0;
-
       p->p_offset = 0;
       p->p_filesz = 0;
       p->p_memsz = 0;
@@ -4344,11 +4436,6 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
              if (! m->p_paddr_valid)
                p->p_paddr -= off;
            }
-         if (p->p_type == PT_LOAD)
-           {
-             filehdr_vaddr = p->p_vaddr;
-             filehdr_paddr = p->p_paddr;
-           }
        }
 
       if (m->includes_phdrs)
@@ -4356,15 +4443,7 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
          if (! m->p_flags_valid)
            p->p_flags |= PF_R;
 
-         if (m->includes_filehdr)
-           {
-             if (p->p_type == PT_LOAD)
-               {
-                 phdrs_vaddr = p->p_vaddr + bed->s->sizeof_ehdr;
-                 phdrs_paddr = p->p_paddr + bed->s->sizeof_ehdr;
-               }
-           }
-         else
+         if (!m->includes_filehdr)
            {
              p->p_offset = bed->s->sizeof_ehdr;
 
@@ -4375,14 +4454,6 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                  if (! m->p_paddr_valid)
                    p->p_paddr -= off - p->p_offset;
                }
-
-             if (p->p_type == PT_LOAD)
-               {
-                 phdrs_vaddr = p->p_vaddr;
-                 phdrs_paddr = p->p_paddr;
-               }
-             else
-               phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
            }
 
          p->p_filesz += alloc * bed->s->sizeof_phdr;
@@ -4404,6 +4475,11 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
            }
        }
 
+      /* Set up p_filesz, p_memsz, p_align and p_flags from the section
+        maps.  Set filepos for sections in PT_LOAD segments, and in
+        core files, for sections in PT_NOTE segments.
+        assign_file_positions_for_non_load_sections will set filepos
+        for other sections and update p_filesz for other segments.  */
       for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
        {
          asection *sec;
@@ -4412,7 +4488,7 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
 
          sec = *secpp;
          flags = sec->flags;
-         align = 1 << bfd_get_section_alignment (abfd, sec);
+         align = (bfd_size_type) 1 << bfd_get_section_alignment (abfd, sec);
 
          if (p->p_type == PT_LOAD
              || p->p_type == PT_TLS)
@@ -4435,14 +4511,15 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                }
              /* .tbss is special.  It doesn't contribute to p_memsz of
                 normal segments.  */
-             else if ((flags & SEC_THREAD_LOCAL) == 0
-                      || p->p_type == PT_TLS)
+             else if ((flags & SEC_ALLOC) != 0
+                      && ((flags & SEC_THREAD_LOCAL) == 0
+                          || p->p_type == PT_TLS))
                {
                  /* The section VMA must equal the file position
                     modulo the page size.  */
                  bfd_size_type page = align;
-                 if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > page)
-                   page = bed->maxpagesize;
+                 if (page < maxpagesize)
+                   page = maxpagesize;
                  adjust = vma_page_aligned_bias (sec->vma,
                                                  p->p_vaddr + p->p_memsz,
                                                  page);
@@ -4475,7 +4552,7 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
            {
              if (p->p_type == PT_LOAD)
                {
-                 sec->filepos = off;
+                 sec->filepos = off + voff;
                  /* FIXME: The SEC_HAS_CONTENTS test here dates back to
                     1997, and the exact reason for it isn't clear.  One
                     plausible explanation is that it is to work around
@@ -4500,16 +4577,12 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                  p->p_filesz += sec->size;
                  p->p_memsz += sec->size;
                }
-             /* PR ld/594:  Sections in note segments which are not loaded
-                contribute to the file size but not the in-memory size.  */
-             else if (p->p_type == PT_NOTE
-                 && (flags & SEC_HAS_CONTENTS) != 0)
-               p->p_filesz += sec->size;
 
              /* .tbss is special.  It doesn't contribute to p_memsz of
                 normal segments.  */
-             else if ((flags & SEC_THREAD_LOCAL) == 0
-                      || p->p_type == PT_TLS)
+             else if ((flags & SEC_ALLOC) != 0
+                      && ((flags & SEC_THREAD_LOCAL) == 0
+                          || p->p_type == PT_TLS))
                p->p_memsz += sec->size;
 
              if (p->p_type == PT_TLS
@@ -4521,8 +4594,11 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                    p->p_memsz += o->offset + o->size;
                }
 
-             if (align > p->p_align
-                 && (p->p_type != PT_LOAD || (abfd->flags & D_PAGED) == 0))
+             if (p->p_type == PT_GNU_RELRO)
+               p->p_align = 1;
+             else if (align > p->p_align
+                      && (p->p_type != PT_LOAD
+                          || (abfd->flags & D_PAGED) == 0))
                p->p_align = align;
            }
 
@@ -4537,9 +4613,32 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
        }
     }
 
-  /* Assign file positions for the other sections.  */
+  elf_tdata (abfd)->next_file_pos = off;
+  return TRUE;
+}
+
+/* Assign file positions for the other sections.  */
+
+static bfd_boolean
+assign_file_positions_for_non_load_sections (bfd *abfd,
+                                            struct bfd_link_info *link_info)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  Elf_Internal_Shdr **i_shdrpp;
+  Elf_Internal_Shdr **hdrpp;
+  Elf_Internal_Phdr *phdrs;
+  Elf_Internal_Phdr *p;
+  struct elf_segment_map *m;
+  bfd_vma filehdr_vaddr, filehdr_paddr;
+  bfd_vma phdrs_vaddr, phdrs_paddr;
+  file_ptr off;
+  unsigned int num_sec;
+  unsigned int i;
+  unsigned int count;
+
   i_shdrpp = elf_elfsections (abfd);
   num_sec = elf_numsections (abfd);
+  off = elf_tdata (abfd)->next_file_pos;
   for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
     {
       struct elf_obj_tdata *tdata = elf_tdata (abfd);
@@ -4547,7 +4646,9 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
 
       hdr = *hdrpp;
       if (hdr->bfd_section != NULL
-         && hdr->bfd_section->filepos != 0)
+         && (hdr->bfd_section->filepos != 0
+             || (hdr->sh_type == SHT_NOBITS
+                 && hdr->contents == NULL)))
        hdr->sh_offset = hdr->bfd_section->filepos;
       else if ((hdr->sh_flags & SHF_ALLOC) != 0)
        {
@@ -4584,31 +4685,59 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
 
   /* Now that we have set the section file positions, we can set up
      the file positions for the non PT_LOAD segments.  */
+  count = 0;
+  filehdr_vaddr = 0;
+  filehdr_paddr = 0;
+  phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
+  phdrs_paddr = 0;
+  phdrs = elf_tdata (abfd)->phdr;
   for (m = elf_tdata (abfd)->segment_map, p = phdrs;
        m != NULL;
        m = m->next, p++)
     {
-      if (p->p_type != PT_LOAD && m->count > 0)
+      ++count;
+      if (p->p_type != PT_LOAD)
+       continue;
+
+      if (m->includes_filehdr)
        {
-         BFD_ASSERT (! m->includes_filehdr && ! m->includes_phdrs);
-         /* If the section has not yet been assigned a file position,
-            do so now.  The ARM BPABI requires that .dynamic section
-            not be marked SEC_ALLOC because it is not part of any
-            PT_LOAD segment, so it will not be processed above.  */
-         if (p->p_type == PT_DYNAMIC && m->sections[0]->filepos == 0)
+         filehdr_vaddr = p->p_vaddr;
+         filehdr_paddr = p->p_paddr;
+       }
+      if (m->includes_phdrs)
+       {
+         phdrs_vaddr = p->p_vaddr;
+         phdrs_paddr = p->p_paddr;
+         if (m->includes_filehdr)
            {
-             Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
-
-             i = 1;
-             while (i_shdrpp[i]->bfd_section != m->sections[0])
-               ++i;
-             off = (_bfd_elf_assign_file_position_for_section 
-                    (i_shdrpp[i], off, TRUE));
-             p->p_filesz = m->sections[0]->size;
+             phdrs_vaddr += bed->s->sizeof_ehdr;
+             phdrs_paddr += bed->s->sizeof_ehdr;
            }
-         p->p_offset = m->sections[0]->filepos;
        }
-      if (m->count == 0)
+    }
+
+  for (m = elf_tdata (abfd)->segment_map, p = phdrs;
+       m != NULL;
+       m = m->next, p++)
+    {
+      if (m->count != 0)
+       {
+         if (p->p_type != PT_LOAD
+             && (p->p_type != PT_NOTE || bfd_get_format (abfd) != bfd_core))
+           {
+             Elf_Internal_Shdr *hdr;
+             BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+
+             hdr = &elf_section_data (m->sections[m->count - 1])->this_hdr;
+             p->p_filesz = (m->sections[m->count - 1]->filepos
+                            - m->sections[0]->filepos);
+             if (hdr->sh_type != SHT_NOBITS)
+               p->p_filesz += hdr->sh_size;
+
+             p->p_offset = m->sections[0]->filepos;
+           }
+       }
+      else
        {
          if (m->includes_filehdr)
            {
@@ -4631,8 +4760,8 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
                  if (lp->p_type == PT_LOAD
                      && lp->p_vaddr <= link_info->relro_end
                      && lp->p_vaddr >= link_info->relro_start
-                     && lp->p_vaddr + lp->p_filesz
-                        >= link_info->relro_end)
+                     && (lp->p_vaddr + lp->p_filesz
+                         >= link_info->relro_end))
                    break;
                }
 
@@ -4656,131 +4785,11 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
        }
     }
 
-  /* Clear out any program headers we allocated but did not use.  */
-  for (; count < alloc; count++, p++)
-    {
-      memset (p, 0, sizeof *p);
-      p->p_type = PT_NULL;
-    }
-
-  elf_tdata (abfd)->phdr = phdrs;
-
   elf_tdata (abfd)->next_file_pos = off;
 
-  /* 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 TRUE;
 }
 
-/* Get the size of the program header.
-
-   If this is called by the linker before any of the section VMA's are set, it
-   can't calculate the correct value for a strange memory layout.  This only
-   happens when SIZEOF_HEADERS is used in a linker script.  In this case,
-   SORTED_HDRS is NULL and we assume the normal scenario of one text and one
-   data segment (exclusive of .interp and .dynamic).
-
-   ??? User written scripts must either not use SIZEOF_HEADERS, or assume there
-   will be two segments.  */
-
-static bfd_size_type
-get_program_header_size (bfd *abfd)
-{
-  size_t segs;
-  asection *s;
-  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
-  /* We can't return a different result each time we're called.  */
-  if (elf_tdata (abfd)->program_header_size != 0)
-    return elf_tdata (abfd)->program_header_size;
-
-  if (elf_tdata (abfd)->segment_map != NULL)
-    {
-      struct elf_segment_map *m;
-
-      segs = 0;
-      for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-       ++segs;
-      elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
-      return elf_tdata (abfd)->program_header_size;
-    }
-
-  /* Assume we will need exactly two PT_LOAD segments: one for text
-     and one for data.  */
-  segs = 2;
-
-  s = bfd_get_section_by_name (abfd, ".interp");
-  if (s != NULL && (s->flags & SEC_LOAD) != 0)
-    {
-      /* If we have a loadable interpreter section, we need a
-        PT_INTERP segment.  In this case, assume we also need a
-        PT_PHDR segment, although that may not be true for all
-        targets.  */
-      segs += 2;
-    }
-
-  if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
-    {
-      /* We need a PT_DYNAMIC segment.  */
-      ++segs;
-    }
-
-  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;
-    }
-
-  if (elf_tdata (abfd)->relro)
-    {
-      /* We need a PT_GNU_RELRO segment.  */
-      ++segs;
-    }
-
-  for (s = abfd->sections; s != NULL; s = s->next)
-    {
-      if ((s->flags & SEC_LOAD) != 0
-         && strncmp (s->name, ".note", 5) == 0)
-       {
-         /* We need a PT_NOTE segment.  */
-         ++segs;
-       }
-    }
-
-  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)
-    {
-      int a;
-
-      a = (*bed->elf_backend_additional_program_headers) (abfd);
-      if (a == -1)
-       abort ();
-      segs += a;
-    }
-
-  elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
-  return elf_tdata (abfd)->program_header_size;
-}
-
 /* Work out the file positions of all the sections.  This is called by
    _bfd_elf_compute_section_file_positions.  All the section sizes and
    VMAs must be known before this is called.
@@ -4843,9 +4852,27 @@ assign_file_positions_except_relocs (bfd *abfd,
     }
   else
     {
+      unsigned int alloc;
+
       /* Assign file positions for the loaded sections based on the
          assignment of sections to segments.  */
-      if (! assign_file_positions_for_segments (abfd, link_info))
+      if (!assign_file_positions_for_load_sections (abfd, link_info))
+       return FALSE;
+
+      /* And for non-load sections.  */
+      if (!assign_file_positions_for_non_load_sections (abfd, link_info))
+       return FALSE;
+
+      if (bed->elf_backend_modify_program_headers != NULL)
+       {
+         if (!(*bed->elf_backend_modify_program_headers) (abfd, link_info))
+           return FALSE;
+       }
+
+      /* Write out the program headers.  */
+      alloc = tdata->program_header_size / bed->s->sizeof_phdr;
+      if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
+         || bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
        return FALSE;
 
       off = tdata->next_file_pos;
@@ -5095,13 +5122,14 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
       && (flags & BSF_SECTION_SYM)
       && asym_ptr->section)
     {
+      asection *sec;
       int indx;
 
-      if (asym_ptr->section->output_section != NULL)
-       indx = asym_ptr->section->output_section->index;
-      else
-       indx = asym_ptr->section->index;
-      if (indx < elf_num_section_syms (abfd)
+      sec = asym_ptr->section;
+      if (sec->owner != abfd && sec->output_section != NULL)
+       sec = sec->output_section;
+      if (sec->owner == abfd
+         && (indx = sec->index) < elf_num_section_syms (abfd)
          && elf_section_syms (abfd)[indx] != NULL)
        asym_ptr->udata.i = elf_section_syms (abfd)[indx]->udata.i;
     }
@@ -5770,6 +5798,8 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
       map->p_flags_valid = 1;
       map->p_paddr = segment->p_paddr;
       map->p_paddr_valid = 1;
+      map->p_align = segment->p_align;
+      map->p_align_valid = 1;
 
       /* Determine if this segment contains the ELF file header
         and if it contains the program headers themselves.  */
@@ -5906,16 +5936,18 @@ _bfd_elf_init_private_section_data (bfd *ibfd,
       || obfd->xvec->flavour != bfd_target_elf_flavour)
     return TRUE;
 
-  /* FIXME: What if the output ELF section type has been set to
-     something different?  */
-  if (elf_section_type (osec) == SHT_NULL)
+  /* Don't copy the output ELF section type from input if the
+     output BFD section flags have been set to something different.
+     elf_fake_sections will set ELF section type based on BFD
+     section flags.  */
+  if (osec->flags == isec->flags
+      || (osec->flags == 0 && elf_section_type (osec) == SHT_NULL))
     elf_section_type (osec) = elf_section_type (isec);
 
   /* Set things up for objcopy and relocatable link.  The output
      SHT_GROUP section will have its elf_next_in_group pointing back
      to the input group members.  Ignore linker created group section.
      See elfNN_ia64_object_p in elfxx-ia64.c.  */
-
   if (need_group)
     {
       if (elf_sec_group (isec) == NULL
@@ -7065,13 +7097,31 @@ _bfd_elf_find_inliner_info (bfd *abfd,
 }
 
 int
-_bfd_elf_sizeof_headers (bfd *abfd, bfd_boolean reloc)
+_bfd_elf_sizeof_headers (bfd *abfd, struct bfd_link_info *info)
 {
-  int ret;
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+  int ret = bed->s->sizeof_ehdr;
+
+  if (!info->relocatable)
+    {
+      bfd_size_type phdr_size = elf_tdata (abfd)->program_header_size;
+
+      if (phdr_size == (bfd_size_type) -1)
+       {
+         struct elf_segment_map *m;
+
+         phdr_size = 0;
+         for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+           phdr_size += bed->s->sizeof_phdr;
+
+         if (phdr_size == 0)
+           phdr_size = get_program_header_size (abfd, info);
+       }
+
+      elf_tdata (abfd)->program_header_size = phdr_size;
+      ret += phdr_size;
+    }
 
-  ret = get_elf_backend_data (abfd)->s->sizeof_ehdr;
-  if (! reloc)
-    ret += get_program_header_size (abfd);
   return ret;
 }
 
@@ -7207,7 +7257,7 @@ _bfd_elf_close_and_cleanup (bfd *abfd)
 {
   if (bfd_get_format (abfd) == bfd_object)
     {
-      if (elf_shstrtab (abfd) != NULL)
+      if (elf_tdata (abfd) != NULL && elf_shstrtab (abfd) != NULL)
        _bfd_elf_strtab_free (elf_shstrtab (abfd));
       _bfd_dwarf2_cleanup_debug_info (abfd);
     }
@@ -7261,13 +7311,12 @@ elfcore_maybe_make_sect (bfd *abfd, char *name, asection *sect)
   if (bfd_get_section_by_name (abfd, name) != NULL)
     return TRUE;
 
-  sect2 = bfd_make_section (abfd, name);
+  sect2 = bfd_make_section_with_flags (abfd, name, sect->flags);
   if (sect2 == NULL)
     return FALSE;
 
   sect2->size = sect->size;
   sect2->filepos = sect->filepos;
-  sect2->flags = sect->flags;
   sect2->alignment_power = sect->alignment_power;
   return TRUE;
 }
@@ -7299,12 +7348,12 @@ _bfd_elfcore_make_pseudosection (bfd *abfd,
     return FALSE;
   memcpy (threaded_name, buf, len);
 
-  sect = bfd_make_section_anyway (abfd, threaded_name);
+  sect = bfd_make_section_anyway_with_flags (abfd, threaded_name,
+                                            SEC_HAS_CONTENTS);
   if (sect == NULL)
     return FALSE;
   sect->size = size;
   sect->filepos = filepos;
-  sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
   return elfcore_maybe_make_sect (abfd, name, sect);
@@ -7583,7 +7632,7 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
     return FALSE;
   memcpy (name, buf, len);
 
-  sect = bfd_make_section_anyway (abfd, name);
+  sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
   if (sect == NULL)
     return FALSE;
 
@@ -7598,7 +7647,6 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
   sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_reg);
 #endif
 
-  sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
   if (!elfcore_maybe_make_sect (abfd, ".reg", sect))
@@ -7613,7 +7661,7 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
     return FALSE;
   memcpy (name, buf, len);
 
-  sect = bfd_make_section_anyway (abfd, name);
+  sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
   if (sect == NULL)
     return FALSE;
 
@@ -7628,7 +7676,6 @@ elfcore_grok_lwpstatus (bfd *abfd, Elf_Internal_Note *note)
   sect->filepos = note->descpos + offsetof (lwpstatus_t, pr_fpreg);
 #endif
 
-  sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
   return elfcore_maybe_make_sect (abfd, ".reg2", sect);
@@ -7669,7 +7716,7 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (name, buf, len);
 
-      sect = bfd_make_section_anyway (abfd, name);
+      sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
       if (sect == NULL)
        return FALSE;
 
@@ -7677,7 +7724,6 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
       sect->filepos = (note->descpos
                       + offsetof (struct win32_pstatus,
                                   data.thread_info.thread_context));
-      sect->flags = SEC_HAS_CONTENTS;
       sect->alignment_power = 2;
 
       if (pstatus.data.thread_info.is_active_thread)
@@ -7697,14 +7743,13 @@ elfcore_grok_win32pstatus (bfd *abfd, Elf_Internal_Note *note)
 
       memcpy (name, buf, len);
 
-      sect = bfd_make_section_anyway (abfd, name);
+      sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
 
       if (sect == NULL)
        return FALSE;
 
       sect->size = note->descsz;
       sect->filepos = note->descpos;
-      sect->flags = SEC_HAS_CONTENTS;
       sect->alignment_power = 2;
       break;
 
@@ -7774,13 +7819,13 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
 
     case NT_AUXV:
       {
-       asection *sect = bfd_make_section_anyway (abfd, ".auxv");
+       asection *sect = bfd_make_section_anyway_with_flags (abfd, ".auxv",
+                                                            SEC_HAS_CONTENTS);
 
        if (sect == NULL)
          return FALSE;
        sect->size = note->descsz;
        sect->filepos = note->descpos;
-       sect->flags = SEC_HAS_CONTENTS;
        sect->alignment_power = 1 + bfd_get_arch_size (abfd) / 32;
 
        return TRUE;
@@ -7888,7 +7933,7 @@ elfcore_grok_netbsd_note (bfd *abfd, Elf_Internal_Note *note)
 }
 
 static bfd_boolean
-elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
+elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, long *tid)
 {
   void *ddata = note->descdata;
   char buf[100];
@@ -7920,20 +7965,19 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
     elf_tdata (abfd)->core_lwpid = *tid;
 
   /* Make a ".qnx_core_status/%d" section.  */
-  sprintf (buf, ".qnx_core_status/%ld", (long) *tid);
+  sprintf (buf, ".qnx_core_status/%ld", *tid);
 
   name = bfd_alloc (abfd, strlen (buf) + 1);
   if (name == NULL)
     return FALSE;
   strcpy (name, buf);
 
-  sect = bfd_make_section_anyway (abfd, name);
+  sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
   if (sect == NULL)
     return FALSE;
 
   sect->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));
@@ -7942,7 +7986,7 @@ elfcore_grok_nto_status (bfd *abfd, Elf_Internal_Note *note, pid_t *tid)
 static bfd_boolean
 elfcore_grok_nto_regs (bfd *abfd,
                       Elf_Internal_Note *note,
-                      pid_t tid,
+                      long tid,
                       char *base)
 {
   char buf[100];
@@ -7950,20 +7994,19 @@ elfcore_grok_nto_regs (bfd *abfd,
   asection *sect;
 
   /* Make a "(base)/%d" section.  */
-  sprintf (buf, "%s/%ld", base, (long) tid);
+  sprintf (buf, "%s/%ld", base, tid);
 
   name = bfd_alloc (abfd, strlen (buf) + 1);
   if (name == NULL)
     return FALSE;
   strcpy (name, buf);
 
-  sect = bfd_make_section_anyway (abfd, name);
+  sect = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS);
   if (sect == NULL)
     return FALSE;
 
   sect->size            = note->descsz;
   sect->filepos         = note->descpos;
-  sect->flags           = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
 
   /* This is the current thread.  */
@@ -7984,7 +8027,7 @@ elfcore_grok_nto_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;
+  static long tid = 1;
 
   switch (note->type)
     {
@@ -8757,8 +8800,7 @@ done:
 /* 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, NULL, "LARGE_COMMON",
-                     0);
+                     SEC_IS_COMMON, NULL, "LARGE_COMMON", 0);
 
 /* Return TRUE if 2 section types are compatible.  */
 
This page took 0.067288 seconds and 4 git commands to generate.