Added --identify option to dlltool.
[binutils-gdb.git] / bfd / elf.c
index ea44f7246619defe370c09aed684830850bf7079..4525faab3b404623a7241785400caca31cc54d28 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -1608,6 +1608,8 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
 
       if (hdr->sh_entsize != bed->s->sizeof_sym)
        return FALSE;
+      if (hdr->sh_info * hdr->sh_entsize > hdr->sh_size)
+       return FALSE;
       BFD_ASSERT (elf_onesymtab (abfd) == 0);
       elf_onesymtab (abfd) = shindex;
       elf_tdata (abfd)->symtab_hdr = *hdr;
@@ -4156,6 +4158,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
   bfd_size_type maxpagesize;
   unsigned int alloc;
   unsigned int i, j;
+  bfd_vma header_pad = 0;
 
   if (link_info == NULL
       && !_bfd_elf_map_sections_to_segments (abfd, link_info))
@@ -4163,7 +4166,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
   alloc = 0;
   for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-    ++alloc;
+    {
+      ++alloc;
+      if (m->header_size)
+       header_pad = m->header_size;
+    }
 
   elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
   elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
@@ -4181,7 +4188,21 @@ assign_file_positions_for_load_sections (bfd *abfd,
       return TRUE;
     }
 
-  phdrs = bfd_alloc2 (abfd, alloc, sizeof (Elf_Internal_Phdr));
+  /* We're writing the size in elf_tdata (abfd)->program_header_size,
+     see assign_file_positions_except_relocs, so make sure we have
+     that amount allocated, with trailing space cleared.
+     The variable alloc contains the computed need, while elf_tdata
+     (abfd)->program_header_size contains the size used for the
+     layout.
+     See ld/emultempl/elf-generic.em:gld${EMULATION_NAME}_map_segments
+     where the layout is forced to according to a larger size in the
+     last iterations for the testcase ld-elf/header.  */
+  BFD_ASSERT (elf_tdata (abfd)->program_header_size % bed->s->sizeof_phdr
+             == 0);
+  phdrs = bfd_zalloc2 (abfd,
+                      (elf_tdata (abfd)->program_header_size
+                       / bed->s->sizeof_phdr),
+                      sizeof (Elf_Internal_Phdr));
   elf_tdata (abfd)->phdr = phdrs;
   if (phdrs == NULL)
     return FALSE;
@@ -4192,6 +4213,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
   off = bed->s->sizeof_ehdr;
   off += alloc * bed->s->sizeof_phdr;
+  if (header_pad < (bfd_vma) off)
+    header_pad = 0;
+  else
+    header_pad -= off;
+  off += header_pad;
 
   for (m = elf_tdata (abfd)->segment_map, p = phdrs, j = 0;
        m != NULL;
@@ -4379,6 +4405,11 @@ assign_file_positions_for_load_sections (bfd *abfd,
 
          p->p_filesz += alloc * bed->s->sizeof_phdr;
          p->p_memsz += alloc * bed->s->sizeof_phdr;
+         if (m->count)
+           {
+             p->p_filesz += header_pad;
+             p->p_memsz += header_pad;
+           }
        }
 
       if (p->p_type == PT_LOAD
@@ -4631,7 +4662,61 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
        m != NULL;
        m = m->next, p++)
     {
-      if (m->count != 0)
+      if (p->p_type == PT_GNU_RELRO)
+       {
+         const Elf_Internal_Phdr *lp;
+
+         BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs);
+
+         if (link_info != NULL)
+           {
+             /* During linking the range of the RELRO segment is passed
+                in link_info.  */
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_vaddr >= link_info->relro_start
+                     && lp->p_vaddr < link_info->relro_end
+                     && lp->p_vaddr + lp->p_filesz >= link_info->relro_end)
+                   break;
+               }
+           }
+         else
+           {
+             /* Otherwise we are copying an executable or shared
+                library, but we need to use the same linker logic.  */
+             for (lp = phdrs; lp < phdrs + count; ++lp)
+               {
+                 if (lp->p_type == PT_LOAD
+                     && lp->p_paddr == p->p_paddr)
+                   break;
+               }
+           }
+
+         if (lp < phdrs + count)
+           {
+             p->p_vaddr = lp->p_vaddr;
+             p->p_paddr = lp->p_paddr;
+             p->p_offset = lp->p_offset;
+             if (link_info != NULL)
+               p->p_filesz = link_info->relro_end - lp->p_vaddr;
+             else if (m->p_size_valid)
+               p->p_filesz = m->p_size;
+             else
+               abort ();
+             p->p_memsz = p->p_filesz;
+             p->p_align = 1;
+             p->p_flags = (lp->p_flags & ~PF_W);
+           }
+         else if (link_info != NULL)
+           {
+             memset (p, 0, sizeof *p);
+             p->p_type = PT_NULL;
+           }
+         else
+           abort ();
+       }
+      else if (m->count != 0)
        {
          if (p->p_type != PT_LOAD
              && (p->p_type != PT_NOTE
@@ -4647,87 +4732,20 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
              p->p_filesz = sect->filepos - m->sections[0]->filepos;
              if (hdr->sh_type != SHT_NOBITS)
                p->p_filesz += hdr->sh_size;
-
-             if (p->p_type == PT_GNU_RELRO)
-               {
-                 /* When we get here, we are copying executable
-                    or shared library. But we need to use the same
-                    linker logic.  */
-                 Elf_Internal_Phdr *lp;
-
-                 for (lp = phdrs; lp < phdrs + count; ++lp)
-                   {
-                     if (lp->p_type == PT_LOAD
-                         && lp->p_paddr == p->p_paddr)
-                       break;
-                   }
-         
-                 if (lp < phdrs + count)
-                   {
-                     /* We should use p_size if it is valid since it
-                        may contain the first few bytes of the next
-                        SEC_ALLOC section.  */
-                     if (m->p_size_valid)
-                       p->p_filesz = m->p_size;
-                     else
-                       abort ();
-                     p->p_vaddr = lp->p_vaddr;
-                     p->p_offset = lp->p_offset;
-                     p->p_memsz = p->p_filesz;
-                     p->p_align = 1;
-                   }
-                 else
-                   abort ();
-               }
-             else
-               p->p_offset = m->sections[0]->filepos;
+             p->p_offset = m->sections[0]->filepos;
            }
        }
-      else
+      else if (m->includes_filehdr)
        {
-         if (m->includes_filehdr)
-           {
-             p->p_vaddr = filehdr_vaddr;
-             if (! m->p_paddr_valid)
-               p->p_paddr = filehdr_paddr;
-           }
-         else if (m->includes_phdrs)
-           {
-             p->p_vaddr = phdrs_vaddr;
-             if (! m->p_paddr_valid)
-               p->p_paddr = phdrs_paddr;
-           }
-         else if (p->p_type == PT_GNU_RELRO)
-           {
-             Elf_Internal_Phdr *lp;
-
-             for (lp = phdrs; lp < phdrs + count; ++lp)
-               {
-                 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))
-                   break;
-               }
-
-             if (lp < phdrs + count
-                 && link_info->relro_end > lp->p_vaddr)
-               {
-                 p->p_vaddr = lp->p_vaddr;
-                 p->p_paddr = lp->p_paddr;
-                 p->p_offset = lp->p_offset;
-                 p->p_filesz = link_info->relro_end - lp->p_vaddr;
-                 p->p_memsz = p->p_filesz;
-                 p->p_align = 1;
-                 p->p_flags = (lp->p_flags & ~PF_W);
-               }
-             else
-               {
-                 memset (p, 0, sizeof *p);
-                 p->p_type = PT_NULL;
-               }
-           }
+         p->p_vaddr = filehdr_vaddr;
+         if (! m->p_paddr_valid)
+           p->p_paddr = filehdr_paddr;
+       }
+      else if (m->includes_phdrs)
+       {
+         p->p_vaddr = phdrs_vaddr;
+         if (! m->p_paddr_valid)
+           p->p_paddr = phdrs_paddr;
        }
     }
 
@@ -5874,6 +5892,10 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
            phdr_included = TRUE;
        }
 
+      if (map->includes_filehdr && first_section)
+       /* We need to keep the space used by the headers fixed.  */
+       map->header_size = first_section->vma - segment->p_vaddr;
+      
       if (!map->includes_phdrs
          && !map->includes_filehdr
          && map->p_paddr_valid)