PR4499, assign file positions assumes segment offsets increasing

This rewrites much of assign_file_positions_for_non_load_sections to
allow objcopy and strip to handle cases like that in PR4499 where
program headers were not in their usual position immediately after the
ELF file header, and PT_LOAD headers were not sorted by paddr.

	PR 4499
include/
	* elf/internal.h (struct elf_segment_map): Delete header_size.
	Add no_sort_lma and idx.
bfd/
	* elf-nacl.c (nacl_modify_segment_map): Set no_sort_lma for all
	PT_LOAD segments.
	* elf32-spu.c (spu_elf_modify_segment_map): Likewise on overlay
	PT_LOAD segments.
	* elf.c (elf_sort_segments): New function.
	(assign_file_positions_except_relocs): Use shortcuts to elfheader
	and elf_tdata.  Seek to e_phoff not sizeof_ehdr to write program
	headers.  Move PT_PHDR check..
	(assign_file_positions_for_non_load_sections): ..and code setting
	PT_PHDR p_vaddr and p_paddr, and code setting __ehdr_start value..
	(assign_file_positions_for_load_sections): ..to here.  Sort
	PT_LOAD headers.  Delete header_pad code.  Use actual number of
	headers rather than allocated in calculating size for program
	headers.  Don't assume program headers follow ELF file header.
	Simplify pt_load_count code.  Only set "off" for PT_LOAD or
	PT_NOTE in cores.
	(rewrite_elf_program_header): Set p_vaddr_offset for segments
	that include file and program headers.
	(copy_elf_program_header): Likewise, replacing header_size code.
This commit is contained in:
Alan Modra 2019-10-23 17:40:51 +10:30
parent c0c121b01c
commit 30fe183248
6 changed files with 299 additions and 239 deletions

View File

@ -1,3 +1,26 @@
2019-10-25 Alan Modra <amodra@gmail.com>
PR 4499
* elf-nacl.c (nacl_modify_segment_map): Set no_sort_lma for all
PT_LOAD segments.
* elf32-spu.c (spu_elf_modify_segment_map): Likewise on overlay
PT_LOAD segments.
* elf.c (elf_sort_segments): New function.
(assign_file_positions_except_relocs): Use shortcuts to elfheader
and elf_tdata. Seek to e_phoff not sizeof_ehdr to write program
headers. Move PT_PHDR check..
(assign_file_positions_for_non_load_sections): ..and code setting
PT_PHDR p_vaddr and p_paddr, and code setting __ehdr_start value..
(assign_file_positions_for_load_sections): ..to here. Sort
PT_LOAD headers. Delete header_pad code. Use actual number of
headers rather than allocated in calculating size for program
headers. Don't assume program headers follow ELF file header.
Simplify pt_load_count code. Only set "off" for PT_LOAD or
PT_NOTE in cores.
(rewrite_elf_program_header): Set p_vaddr_offset for segments
that include file and program headers.
(copy_elf_program_header): Likewise, replacing header_size code.
2019-10-21 Alan Modra <amodra@gmail.com>
PR 452

View File

@ -197,6 +197,7 @@ nacl_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
included the file header and phdrs. */
seg->includes_filehdr = 0;
seg->includes_phdrs = 0;
seg->no_sort_lma = 1;
/* Also strip out empty segments. */
if (seg->count == 0)
{

498
bfd/elf.c
View File

@ -5296,6 +5296,48 @@ elf_sort_sections (const void *arg1, const void *arg2)
return sec1->target_index - sec2->target_index;
}
/* This qsort comparison functions sorts PT_LOAD segments first and
by p_paddr, for assign_file_positions_for_load_sections. */
static int
elf_sort_segments (const void *arg1, const void *arg2)
{
const struct elf_segment_map *m1 = *(const struct elf_segment_map **) arg1;
const struct elf_segment_map *m2 = *(const struct elf_segment_map **) arg2;
if (m1->p_type != m2->p_type)
{
if (m1->p_type == PT_NULL)
return 1;
if (m2->p_type == PT_NULL)
return -1;
return m1->p_type < m2->p_type ? -1 : 1;
}
if (m1->includes_filehdr != m2->includes_filehdr)
return m1->includes_filehdr ? -1 : 1;
if (m1->no_sort_lma != m2->no_sort_lma)
return m1->no_sort_lma ? -1 : 1;
if (m1->p_type == PT_LOAD && !m1->no_sort_lma)
{
bfd_vma lma1, lma2;
lma1 = 0;
if (m1->p_paddr_valid)
lma1 = m1->p_paddr;
else if (m1->count != 0)
lma1 = m1->sections[0]->lma + m1->p_vaddr_offset;
lma2 = 0;
if (m2->p_paddr_valid)
lma2 = m2->p_paddr;
else if (m2->count != 0)
lma2 = m2->sections[0]->lma + m2->p_vaddr_offset;
if (lma1 != lma2)
return lma1 < lma2 ? -1 : 1;
}
if (m1->idx != m2->idx)
return m1->idx < m2->idx ? -1 : 1;
return 0;
}
/* Ian Lance Taylor writes:
We shouldn't be using % with a negative signed number. That's just
@ -5382,14 +5424,14 @@ assign_file_positions_for_load_sections (bfd *abfd,
{
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
struct elf_segment_map *m;
struct elf_segment_map *phdr_load_seg;
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
file_ptr off;
bfd_size_type maxpagesize;
unsigned int pt_load_count = 0;
unsigned int alloc;
unsigned int alloc, actual;
unsigned int i, j;
bfd_vma header_pad = 0;
struct elf_segment_map **sorted_seg_map;
if (link_info == NULL
&& !_bfd_elf_map_sections_to_segments (abfd, link_info))
@ -5397,11 +5439,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
alloc = 0;
for (m = elf_seg_map (abfd); m != NULL; m = m->next)
{
++alloc;
if (m->header_size)
header_pad = m->header_size;
}
m->idx = alloc++;
if (alloc)
{
@ -5418,10 +5456,17 @@ assign_file_positions_for_load_sections (bfd *abfd,
elf_elfheader (abfd)->e_phnum = alloc;
if (elf_program_header_size (abfd) == (bfd_size_type) -1)
elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
{
actual = alloc;
elf_program_header_size (abfd) = alloc * bed->s->sizeof_phdr;
}
else
BFD_ASSERT (elf_program_header_size (abfd)
>= alloc * bed->s->sizeof_phdr);
{
actual = elf_program_header_size (abfd) / bed->s->sizeof_phdr;
BFD_ASSERT (elf_program_header_size (abfd)
== actual * bed->s->sizeof_phdr);
BFD_ASSERT (actual >= alloc);
}
if (alloc == 0)
{
@ -5438,36 +5483,16 @@ assign_file_positions_for_load_sections (bfd *abfd,
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_program_header_size (abfd) % bed->s->sizeof_phdr
== 0);
phdrs = (Elf_Internal_Phdr *)
bfd_zalloc2 (abfd,
(elf_program_header_size (abfd) / bed->s->sizeof_phdr),
sizeof (Elf_Internal_Phdr));
phdrs = bfd_zalloc (abfd, (actual * sizeof (*phdrs)
+ alloc * sizeof (*sorted_seg_map)));
sorted_seg_map = (struct elf_segment_map **) (phdrs + actual);
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;
if (header_pad < (bfd_vma) off)
header_pad = 0;
else
header_pad -= off;
off += header_pad;
for (m = elf_seg_map (abfd), p = phdrs, j = 0;
m != NULL;
m = m->next, p++, j++)
for (m = elf_seg_map (abfd), j = 0; m != NULL; m = m->next, j++)
{
asection **secpp;
bfd_vma off_adjust;
bfd_boolean no_contents;
sorted_seg_map[j] = m;
/* If elf_segment_map is not from map_sections_to_segments, the
sections may not be correctly ordered. NOTE: sorting should
not be done to the PT_NOTE section of a corefile, which may
@ -5482,12 +5507,48 @@ assign_file_positions_for_load_sections (bfd *abfd,
qsort (m->sections, (size_t) m->count, sizeof (asection *),
elf_sort_sections);
}
}
if (alloc > 1)
qsort (sorted_seg_map, alloc, sizeof (*sorted_seg_map),
elf_sort_segments);
maxpagesize = 1;
if ((abfd->flags & D_PAGED) != 0)
maxpagesize = bed->maxpagesize;
/* Sections must map to file offsets past the ELF file header. */
off = bed->s->sizeof_ehdr;
/* And if one of the PT_LOAD headers doesn't include the program
headers then we'll be mapping program headers in the usual
position after the ELF file header. */
phdr_load_seg = NULL;
for (j = 0; j < alloc; j++)
{
m = sorted_seg_map[j];
if (m->p_type != PT_LOAD)
break;
if (m->includes_phdrs)
{
phdr_load_seg = m;
break;
}
}
if (phdr_load_seg == NULL)
off += actual * bed->s->sizeof_phdr;
for (j = 0; j < alloc; j++)
{
asection **secpp;
bfd_vma off_adjust;
bfd_boolean no_contents;
/* An ELF segment (described by Elf_Internal_Phdr) may contain a
number of sections with contents contributing to both p_filesz
and p_memsz, followed by a number of sections with no contents
that just contribute to p_memsz. In this loop, OFF tracks next
available file offset for PT_LOAD and PT_NOTE segments. */
m = sorted_seg_map[j];
p = phdrs + m->idx;
p->p_type = m->p_type;
p->p_flags = m->p_flags;
@ -5518,14 +5579,18 @@ assign_file_positions_for_load_sections (bfd *abfd,
maxpagesize = m->p_align;
p->p_align = maxpagesize;
pt_load_count += 1;
}
else if (m->p_align_valid)
p->p_align = m->p_align;
else if (m->count == 0)
p->p_align = 1 << bed->s->log_file_align;
else
p->p_align = 0;
if (m == phdr_load_seg)
{
if (!m->includes_filehdr)
p->p_offset = off;
off += actual * bed->s->sizeof_phdr;
}
no_contents = FALSE;
off_adjust = 0;
@ -5574,7 +5639,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
/* Broken hardware and/or kernel require that files do not
map the same page with different permissions on some hppa
processors. */
if (pt_load_count > 1
if (j != 0
&& (abfd->flags & D_PAGED) != 0
&& bed->no_page_alias
&& (off & (maxpagesize - 1)) != 0
&& (off & -maxpagesize) == ((off + off_adjust) & -maxpagesize))
@ -5612,33 +5678,38 @@ assign_file_positions_for_load_sections (bfd *abfd,
for (i = 0; i < m->count; i++)
elf_section_type (m->sections[i]) = SHT_NOTE;
p->p_offset = 0;
p->p_filesz = 0;
p->p_memsz = 0;
if (m->includes_filehdr)
{
if (!m->p_flags_valid)
p->p_flags |= PF_R;
p->p_filesz = bed->s->sizeof_ehdr;
p->p_memsz = bed->s->sizeof_ehdr;
if (m->count > 0)
if (p->p_type == PT_LOAD)
{
if (p->p_vaddr < (bfd_vma) off
|| (!m->p_paddr_valid
&& p->p_paddr < (bfd_vma) off))
if (m->count > 0)
{
_bfd_error_handler
(_("%pB: not enough room for program headers,"
" try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
if (p->p_vaddr < (bfd_vma) off
|| (!m->p_paddr_valid
&& p->p_paddr < (bfd_vma) off))
{
_bfd_error_handler
(_("%pB: not enough room for program headers,"
" try linking with -N"),
abfd);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
p->p_vaddr -= off;
if (!m->p_paddr_valid)
p->p_paddr -= off;
}
p->p_vaddr -= off;
}
else if (sorted_seg_map[0]->includes_filehdr)
{
Elf_Internal_Phdr *filehdr = phdrs + sorted_seg_map[0]->idx;
p->p_vaddr = filehdr->p_vaddr;
if (!m->p_paddr_valid)
p->p_paddr -= off;
p->p_paddr = filehdr->p_paddr;
}
}
@ -5646,25 +5717,33 @@ assign_file_positions_for_load_sections (bfd *abfd,
{
if (!m->p_flags_valid)
p->p_flags |= PF_R;
p->p_filesz += actual * bed->s->sizeof_phdr;
p->p_memsz += actual * bed->s->sizeof_phdr;
if (!m->includes_filehdr)
{
p->p_offset = bed->s->sizeof_ehdr;
if (m->count > 0)
if (p->p_type == PT_LOAD)
{
p->p_vaddr -= off - p->p_offset;
if (!m->p_paddr_valid)
p->p_paddr -= off - p->p_offset;
elf_elfheader (abfd)->e_phoff = p->p_offset;
if (m->count > 0)
{
p->p_vaddr -= off - p->p_offset;
if (!m->p_paddr_valid)
p->p_paddr -= off - p->p_offset;
}
}
}
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;
else if (phdr_load_seg != NULL)
{
Elf_Internal_Phdr *phdr = phdrs + phdr_load_seg->idx;
bfd_vma phdr_off = 0;
if (phdr_load_seg->includes_filehdr)
phdr_off = bed->s->sizeof_ehdr;
p->p_vaddr = phdr->p_vaddr + phdr_off;
if (!m->p_paddr_valid)
p->p_paddr = phdr->p_paddr + phdr_off;
p->p_offset = phdr->p_offset + phdr_off;
}
else
p->p_offset = bed->s->sizeof_ehdr;
}
}
@ -5726,16 +5805,19 @@ assign_file_positions_for_load_sections (bfd *abfd,
if (this_hdr->sh_type != SHT_NOBITS)
{
if (p->p_filesz + adjust < p->p_memsz)
if (p->p_type == PT_LOAD)
{
/* We have a PROGBITS section following NOBITS ones.
Allocate file space for the NOBITS section(s) and
zero it. */
adjust = p->p_memsz - p->p_filesz;
if (!write_zeros (abfd, off, adjust))
return FALSE;
if (p->p_filesz + adjust < p->p_memsz)
{
/* We have a PROGBITS section following NOBITS ones.
Allocate file space for the NOBITS section(s) and
zero it. */
adjust = p->p_memsz - p->p_filesz;
if (!write_zeros (abfd, off, adjust))
return FALSE;
}
off += adjust;
}
off += adjust;
p->p_filesz += adjust;
}
}
@ -5824,6 +5906,22 @@ assign_file_positions_for_load_sections (bfd *abfd,
off -= off_adjust;
/* PR ld/20815 - Check that the program header segment, if
present, will be loaded into memory. */
if (p->p_type == PT_PHDR
&& phdr_load_seg == NULL
&& !(bed->elf_backend_allow_non_load_phdr != NULL
&& bed->elf_backend_allow_non_load_phdr (abfd, phdrs, alloc)))
{
/* The fix for this error is usually to edit the linker script being
used and set up the program headers manually. Either that or
leave room for the headers at the start of the SECTIONS. */
_bfd_error_handler (_("%pB: error: PHDR segment not covered"
" by LOAD segment"),
abfd);
return FALSE;
}
/* Check that all sections are in a PT_LOAD segment.
Don't check funky gdb generated core files. */
if (p->p_type == PT_LOAD && bfd_get_format (abfd) != bfd_core)
@ -5863,6 +5961,57 @@ assign_file_positions_for_load_sections (bfd *abfd,
}
elf_next_file_pos (abfd) = off;
if (link_info != NULL
&& phdr_load_seg != NULL
&& phdr_load_seg->includes_filehdr)
{
/* There is a segment that contains both the file headers and the
program headers, so provide a symbol __ehdr_start pointing there.
A program can use this to examine itself robustly. */
struct elf_link_hash_entry *hash
= elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
FALSE, FALSE, TRUE);
/* If the symbol was referenced and not defined, define it. */
if (hash != NULL
&& (hash->root.type == bfd_link_hash_new
|| hash->root.type == bfd_link_hash_undefined
|| hash->root.type == bfd_link_hash_undefweak
|| hash->root.type == bfd_link_hash_common))
{
asection *s = NULL;
bfd_vma filehdr_vaddr = phdrs[phdr_load_seg->idx].p_vaddr;
if (phdr_load_seg->count != 0)
/* The segment contains sections, so use the first one. */
s = phdr_load_seg->sections[0];
else
/* Use the first (i.e. lowest-addressed) section in any segment. */
for (m = elf_seg_map (abfd); m != NULL; m = m->next)
if (m->p_type == PT_LOAD && m->count != 0)
{
s = m->sections[0];
break;
}
if (s != NULL)
{
hash->root.u.def.value = filehdr_vaddr - s->vma;
hash->root.u.def.section = s;
}
else
{
hash->root.u.def.value = filehdr_vaddr;
hash->root.u.def.section = bfd_abs_section_ptr;
}
hash->root.type = bfd_link_hash_defined;
hash->def_regular = 1;
hash->non_elf = 0;
}
}
return TRUE;
}
@ -5908,11 +6057,7 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
Elf_Internal_Phdr *phdrs;
Elf_Internal_Phdr *p;
struct elf_segment_map *m;
struct elf_segment_map *hdrs_segment;
bfd_vma filehdr_vaddr, filehdr_paddr;
bfd_vma phdrs_vaddr, phdrs_paddr;
file_ptr off;
unsigned int count;
i_shdrpp = elf_elfsections (abfd);
end_hdrpp = i_shdrpp + elf_numsections (abfd);
@ -5970,86 +6115,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
else
off = _bfd_elf_assign_file_position_for_section (hdr, off, TRUE);
}
elf_next_file_pos (abfd) = off;
/* 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;
hdrs_segment = NULL;
phdrs = elf_tdata (abfd)->phdr;
for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
{
++count;
if (p->p_type != PT_LOAD)
continue;
if (m->includes_filehdr)
{
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)
{
hdrs_segment = m;
phdrs_vaddr += bed->s->sizeof_ehdr;
phdrs_paddr += bed->s->sizeof_ehdr;
}
}
}
if (hdrs_segment != NULL && link_info != NULL)
{
/* There is a segment that contains both the file headers and the
program headers, so provide a symbol __ehdr_start pointing there.
A program can use this to examine itself robustly. */
struct elf_link_hash_entry *hash
= elf_link_hash_lookup (elf_hash_table (link_info), "__ehdr_start",
FALSE, FALSE, TRUE);
/* If the symbol was referenced and not defined, define it. */
if (hash != NULL
&& (hash->root.type == bfd_link_hash_new
|| hash->root.type == bfd_link_hash_undefined
|| hash->root.type == bfd_link_hash_undefweak
|| hash->root.type == bfd_link_hash_common))
{
asection *s = NULL;
if (hdrs_segment->count != 0)
/* The segment contains sections, so use the first one. */
s = hdrs_segment->sections[0];
else
/* Use the first (i.e. lowest-addressed) section in any segment. */
for (m = elf_seg_map (abfd); m != NULL; m = m->next)
if (m->count != 0)
{
s = m->sections[0];
break;
}
if (s != NULL)
{
hash->root.u.def.value = filehdr_vaddr - s->vma;
hash->root.u.def.section = s;
}
else
{
hash->root.u.def.value = filehdr_vaddr;
hash->root.u.def.section = bfd_abs_section_ptr;
}
hash->root.type = bfd_link_hash_defined;
hash->def_regular = 1;
hash->non_elf = 0;
}
}
for (m = elf_seg_map (abfd), p = phdrs; m != NULL; m = m->next, p++)
{
if (p->p_type == PT_GNU_RELRO)
@ -6195,22 +6265,8 @@ assign_file_positions_for_non_load_sections (bfd *abfd,
}
}
}
else 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;
}
}
elf_next_file_pos (abfd) = off;
return TRUE;
}
@ -6310,8 +6366,8 @@ assign_file_positions_except_relocs (bfd *abfd,
/* Set e_type in ELF header to ET_EXEC for -pie -Ttext-segment=. */
if (link_info != NULL && bfd_link_pie (link_info))
{
unsigned int num_segments = elf_elfheader (abfd)->e_phnum;
Elf_Internal_Phdr *segment = elf_tdata (abfd)->phdr;
unsigned int num_segments = i_ehdrp->e_phnum;
Elf_Internal_Phdr *segment = tdata->phdr;
Elf_Internal_Phdr *end_segment = &segment[num_segments];
/* Find the lowest p_vaddr in PT_LOAD segments. */
@ -6326,42 +6382,16 @@ assign_file_positions_except_relocs (bfd *abfd,
i_ehdrp->e_type = ET_EXEC;
}
/* Write out the program headers. */
alloc = elf_elfheader (abfd)->e_phnum;
if (alloc == 0)
return TRUE;
/* PR ld/20815 - Check that the program header segment, if present, will
be loaded into memory. FIXME: The check below is not sufficient as
really all PT_LOAD segments should be checked before issuing an error
message. Plus the PHDR segment does not have to be the first segment
in the program header table. But this version of the check should
catch all real world use cases.
/* Write out the program headers.
FIXME: We used to have code here to sort the PT_LOAD segments into
ascending order, as per the ELF spec. But this breaks some programs,
including the Linux kernel. But really either the spec should be
changed or the programs updated. */
if (alloc > 1
&& tdata->phdr[0].p_type == PT_PHDR
&& (bed->elf_backend_allow_non_load_phdr == NULL
|| !bed->elf_backend_allow_non_load_phdr (abfd, tdata->phdr,
alloc))
&& tdata->phdr[1].p_type == PT_LOAD
&& (tdata->phdr[1].p_vaddr > tdata->phdr[0].p_vaddr
|| (tdata->phdr[1].p_vaddr + tdata->phdr[1].p_memsz
< tdata->phdr[0].p_vaddr + tdata->phdr[0].p_memsz)))
{
/* The fix for this error is usually to edit the linker script being
used and set up the program headers manually. Either that or
leave room for the headers at the start of the SECTIONS. */
_bfd_error_handler (_("%pB: error: PHDR segment not covered"
" by LOAD segment"),
abfd);
return FALSE;
}
alloc = i_ehdrp->e_phnum;
if (alloc == 0)
return TRUE;
if (bfd_seek (abfd, (bfd_signed_vma) bed->s->sizeof_ehdr, SEEK_SET) != 0
if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0
|| bed->s->write_out_phdrs (abfd, tdata->phdr, alloc) != 0)
return FALSE;
}
@ -7185,14 +7215,18 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
pointer_to_map = &map->next;
if (p_paddr_valid
&& !bed->want_p_paddr_set_to_zero
&& matching_lma->lma != map->p_paddr
&& !map->includes_filehdr
&& !map->includes_phdrs)
/* There is some padding before the first section in the
segment. So, we must account for that in the output
segment's vma. */
map->p_vaddr_offset = map->p_paddr - matching_lma->lma;
&& !bed->want_p_paddr_set_to_zero)
{
bfd_vma hdr_size = 0;
if (map->includes_filehdr)
hdr_size = iehdr->e_ehsize;
if (map->includes_phdrs)
hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
/* Account for padding before the first section in the
segment. */
map->p_vaddr_offset = map->p_paddr + hdr_size - matching_lma->lma;
}
free (sections);
continue;
@ -7441,7 +7475,6 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
Elf_Internal_Shdr *this_hdr;
asection *first_section = NULL;
asection *lowest_section;
bfd_boolean no_contents = TRUE;
/* Compute how many sections are in this segment. */
for (section = ibfd->sections, section_count = 0;
@ -7453,8 +7486,6 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
{
if (first_section == NULL)
first_section = section;
if (elf_section_type (section) != SHT_NOBITS)
no_contents = FALSE;
section_count++;
}
}
@ -7549,27 +7580,20 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
}
}
if (map->includes_filehdr && lowest_section != NULL)
{
/* Try to keep the space used by the headers plus any
padding fixed. If there are sections with file contents
in this segment then the lowest sh_offset is the best
guess. Otherwise the segment only has file contents for
the headers, and p_filesz is the best guess. */
if (no_contents)
map->header_size = segment->p_filesz;
else
map->header_size = lowest_section->filepos;
}
if (section_count == 0)
map->p_vaddr_offset = segment->p_vaddr;
else if (!map->includes_phdrs
&& !map->includes_filehdr
&& map->p_paddr_valid)
/* Account for padding before the first section. */
map->p_vaddr_offset = (segment->p_paddr
- (lowest_section ? lowest_section->lma : 0));
else if (map->p_paddr_valid)
{
/* Account for padding before the first section in the segment. */
bfd_vma hdr_size = 0;
if (map->includes_filehdr)
hdr_size = iehdr->e_ehsize;
if (map->includes_phdrs)
hdr_size += iehdr->e_phnum * iehdr->e_phentsize;
map->p_vaddr_offset = (map->p_paddr + hdr_size
- (lowest_section ? lowest_section->lma : 0));
}
map->count = section_count;
*pointer_to_map = map;

View File

@ -5302,6 +5302,7 @@ spu_elf_modify_segment_map (bfd *abfd, struct bfd_link_info *info)
&& spu_elf_section_data ((*p)->sections[0])->u.o.ovl_index != 0)
{
m = *p;
m->no_sort_lma = 1;
*p = m->next;
*p_overlay = m;
p_overlay = &m->next;

View File

@ -1,3 +1,9 @@
2019-10-25 Alan Modra <amodra@gmail.com>
PR 4499
* elf/internal.h (struct elf_segment_map): Delete header_size.
Add no_sort_lma and idx.
2019-10-16 Alan Modra <amodra@gmail.com>
PR 13616

View File

@ -273,8 +273,6 @@ struct elf_segment_map
bfd_vma p_align;
/* Segment size in file and memory */
bfd_vma p_size;
/* Required size of filehdr + phdrs, if non-zero */
bfd_vma header_size;
/* Whether the p_flags field is valid; if not, the flags are based
on the section flags. */
unsigned int p_flags_valid : 1;
@ -291,6 +289,13 @@ struct elf_segment_map
unsigned int includes_filehdr : 1;
/* Whether this segment includes the program headers. */
unsigned int includes_phdrs : 1;
/* Assume this PT_LOAD header has an lma of zero when sorting
headers before assigning file offsets. PT_LOAD headers with this
flag set are placed after one with includes_filehdr set, and
before PT_LOAD headers without this flag set. */
unsigned int no_sort_lma : 1;
/* Index holding original order before sorting segments. */
unsigned int idx;
/* Number of sections (may be 0). */
unsigned int count;
/* Sections. Actual number of elements is in count field. */