]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - bfd/elf.c
bfd/
[thirdparty/binutils-gdb.git] / bfd / elf.c
index 4bc5a78ff4e07a90bfe3ea54a36ae391e8ba7eb9..ae3af35ee2cea7bcdcdd1e6aa18c7439fb939ab2 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2223,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.
 
  */
 
@@ -2242,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)
@@ -2287,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;
@@ -3427,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;
@@ -3454,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;
@@ -3479,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;
@@ -3850,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)
@@ -3952,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.  */
@@ -3970,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;
@@ -4340,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;
              }