Use p_vaddr_offset to set p_vaddr on segments without sections

p_vaddr is currently set from the first section vma if a segment has
sections, and to zero if a segment has no sections.  This means we
lose p_vaddr when objcopy'ing executables if a segment without
sections has a non-zero p_vaddr.

This patch saves p_vaddr to p_vaddr_offset, and to make the use of
p_vaddr_offset consistent, inverts the sign.  (It's now added to
section vma to get segment vaddr, and added to zero when there are no
sections.)

	* elf.c (assign_file_positions_for_load_sections): Set p_vaddr
	from m->p_vaddr_offset for segments without sections.  Invert
	sign of p_vaddr_offset.
	(rewrite_elf_program_header, copy_elf_program_header): Save
	old segment p_vaddr to p_vaddr_offset.  Invert sign of
	p_vaddr_offset.
This commit is contained in:
Alan Modra 2018-10-06 12:24:28 +09:30
parent 1b9e270b09
commit 5d69562788
2 changed files with 22 additions and 10 deletions

View file

@ -1,3 +1,12 @@
2018-10-08 Alan Modra <amodra@gmail.com>
* elf.c (assign_file_positions_for_load_sections): Set p_vaddr
from m->p_vaddr_offset for segments without sections. Invert
sign of p_vaddr_offset.
(rewrite_elf_program_header, copy_elf_program_header): Save
old segment p_vaddr to p_vaddr_offset. Invert sign of
p_vaddr_offset.
2018-10-08 Alan Modra <amodra@gmail.com> 2018-10-08 Alan Modra <amodra@gmail.com>
* elf.c (get_program_header_size): Don't count PT_INTERP if * elf.c (get_program_header_size): Don't count PT_INTERP if

View file

@ -5358,16 +5358,16 @@ assign_file_positions_for_load_sections (bfd *abfd,
p->p_flags = m->p_flags; p->p_flags = m->p_flags;
if (m->count == 0) if (m->count == 0)
p->p_vaddr = 0; p->p_vaddr = m->p_vaddr_offset;
else else
p->p_vaddr = m->sections[0]->vma - m->p_vaddr_offset; p->p_vaddr = m->sections[0]->vma + m->p_vaddr_offset;
if (m->p_paddr_valid) if (m->p_paddr_valid)
p->p_paddr = m->p_paddr; p->p_paddr = m->p_paddr;
else if (m->count == 0) else if (m->count == 0)
p->p_paddr = 0; p->p_paddr = 0;
else else
p->p_paddr = m->sections[0]->lma - m->p_vaddr_offset; p->p_paddr = m->sections[0]->lma + m->p_vaddr_offset;
if (p->p_type == PT_LOAD if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0) && (abfd->flags & D_PAGED) != 0)
@ -6881,6 +6881,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
" at vaddr=%#" PRIx64 ", is this intentional?"), " at vaddr=%#" PRIx64 ", is this intentional?"),
ibfd, (uint64_t) segment->p_vaddr); ibfd, (uint64_t) segment->p_vaddr);
map->p_vaddr_offset = segment->p_vaddr;
map->count = 0; map->count = 0;
*pointer_to_map = map; *pointer_to_map = map;
pointer_to_map = &map->next; pointer_to_map = &map->next;
@ -7005,7 +7006,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
/* There is some padding before the first section in the /* There is some padding before the first section in the
segment. So, we must account for that in the output segment. So, we must account for that in the output
segment's vma. */ segment's vma. */
map->p_vaddr_offset = matching_lma->lma - map->p_paddr; map->p_vaddr_offset = map->p_paddr - matching_lma->lma;
free (sections); free (sections);
continue; continue;
@ -7367,12 +7368,14 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
map->header_size = lowest_section->filepos; map->header_size = lowest_section->filepos;
} }
if (!map->includes_phdrs if (section_count == 0)
&& !map->includes_filehdr map->p_vaddr_offset = segment->p_vaddr;
&& map->p_paddr_valid) else if (!map->includes_phdrs
/* There is some other padding before the first section. */ && !map->includes_filehdr
map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0) && map->p_paddr_valid)
- segment->p_paddr); /* Account for padding before the first section. */
map->p_vaddr_offset = (segment->p_paddr
- (lowest_section ? lowest_section->lma : 0));
map->count = section_count; map->count = section_count;
*pointer_to_map = map; *pointer_to_map = map;