+2007-09-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/3281
+ PR binutils/5037
+ * elf-bfd.h (elf_obj_tdata): Remove relro.
+
+ * elf.c (get_program_header_size): Check info->relro instead
+ of elf_tdata (abfd)->relro.
+ (_bfd_elf_map_sections_to_segments): Likewise.
+ (assign_file_positions_for_load_sections): Don't set
+ PT_GNU_RELRO segment alignment here.
+ (assign_file_positions_for_non_load_sections): Properly set up
+ PT_GNU_RELRO segment for copying executable/shared library.
+ (rewrite_elf_program_header): Remove PT_GNU_RELRO segment.
+ (copy_elf_program_header): Set p_size and p_size_valid fields for
+ PT_GNU_RELRO segment.
+
2007-09-17 Nick Clifton <nickc@redhat.com>
* po/fi.po: New Finnish translation.
/* We need a PT_DYNAMIC segment. */
++segs;
- if (elf_tdata (abfd)->relro)
+ if (info->relro)
{
/* We need a PT_GNU_RELRO segment only when there is a
PT_DYNAMIC segment. */
pm = &m->next;
}
- if (dynsec != NULL && elf_tdata (abfd)->relro)
+ if (dynsec != NULL && info->relro)
{
/* We make a PT_GNU_RELRO segment only when there is a
PT_DYNAMIC segment. */
p->p_memsz += this_hdr->sh_size;
}
- if (p->p_type == PT_GNU_RELRO)
- p->p_align = 1;
- else if (align > p->p_align
- && !m->p_align_valid
- && (p->p_type != PT_LOAD
- || (abfd->flags & D_PAGED) == 0))
+ if (align > p->p_align
+ && !m->p_align_valid
+ && (p->p_type != PT_LOAD
+ || (abfd->flags & D_PAGED) == 0))
p->p_align = align;
}
if (m->count != 0)
{
if (p->p_type != PT_LOAD
- && (p->p_type != PT_NOTE || bfd_get_format (abfd) != bfd_core))
+ && (p->p_type != PT_NOTE
+ || bfd_get_format (abfd) != bfd_core))
{
Elf_Internal_Shdr *hdr;
+ asection *sect;
+
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);
+ sect = m->sections[m->count - 1];
+ hdr = &elf_section_data (sect)->this_hdr;
+ p->p_filesz = sect->filepos - m->sections[0]->filepos;
if (hdr->sh_type != SHT_NOBITS)
p->p_filesz += hdr->sh_size;
- p->p_offset = m->sections[0]->filepos;
+ 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;
}
}
else
}
if (segment->p_type != PT_LOAD)
- continue;
+ {
+ /* Remove PT_GNU_RELRO segment. */
+ if (segment->p_type == PT_GNU_RELRO)
+ segment->p_type = PT_NULL;
+ continue;
+ }
/* Determine if this segment overlaps any previous segments. */
for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j++, segment2 ++)
map->p_align_valid = 1;
map->p_vaddr_offset = 0;
+ if (map->p_type == PT_GNU_RELRO
+ && segment->p_filesz == segment->p_memsz)
+ {
+ /* The PT_GNU_RELRO segment may contain the first a few
+ bytes in the .got.plt section even if the whole .got.plt
+ section isn't in the PT_GNU_RELRO segment. We won't
+ change the size of the PT_GNU_RELRO segment. */
+ map->p_size = segment->p_filesz;
+ map->p_size_valid = 1;
+ }
+
/* Determine if this segment contains the ELF file header
and if it contains the program headers themselves. */
map->includes_filehdr = (segment->p_offset == 0
bfd_vma p_vaddr_offset;
/* Program segment alignment. */
bfd_vma p_align;
+ /* Segment size in file and memory */
+ bfd_vma p_size;
/* Whether the p_flags field is valid; if not, the flags are based
on the section flags. */
unsigned int p_flags_valid : 1;
/* Whether the p_align field is valid; if not, PT_LOAD segment
alignment is based on the default maximum page size. */
unsigned int p_align_valid : 1;
+ /* Whether the p_size field is valid; if not, the size are based
+ on the section sizes. */
+ unsigned int p_size_valid : 1;
/* Whether this segment includes the file header. */
unsigned int includes_filehdr : 1;
/* Whether this segment includes the program headers. */
|| segment->p_type == PT_TLS) ? sec_hdr->sh_size : 0)
/* Decide if the given sec_hdr is in the given segment. PT_TLS segment
- contains only SHF_TLS sections. Only PT_LOAD and PT_TLS segments
- can contain SHF_TLS sections. */
+ contains only SHF_TLS sections. Only PT_LOAD, PT_GNU_RELRO and
+ and PT_TLS segments can contain SHF_TLS sections. */
#define ELF_IS_SECTION_IN_SEGMENT(sec_hdr, segment) \
(((((sec_hdr->sh_flags & SHF_TLS) != 0) \
&& (segment->p_type == PT_TLS \
+ || segment->p_type == PT_GNU_RELRO \
|| segment->p_type == PT_LOAD)) \
|| ((sec_hdr->sh_flags & SHF_TLS) == 0 \
&& segment->p_type != PT_TLS)) \