From 5d695627883b32cf33adb529c8fc7271b46dcf55 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 6 Oct 2018 12:24:28 +0930 Subject: [PATCH] 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. --- bfd/ChangeLog | 9 +++++++++ bfd/elf.c | 23 +++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3d6796b094..5276305d80 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2018-10-08 Alan Modra + + * 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 * elf.c (get_program_header_size): Don't count PT_INTERP if diff --git a/bfd/elf.c b/bfd/elf.c index fe43c9ffe7..742a52e7bf 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -5358,16 +5358,16 @@ assign_file_positions_for_load_sections (bfd *abfd, p->p_flags = m->p_flags; if (m->count == 0) - p->p_vaddr = 0; + p->p_vaddr = m->p_vaddr_offset; 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) p->p_paddr = m->p_paddr; else if (m->count == 0) p->p_paddr = 0; 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 && (abfd->flags & D_PAGED) != 0) @@ -6881,6 +6881,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) " at vaddr=%#" PRIx64 ", is this intentional?"), ibfd, (uint64_t) segment->p_vaddr); + map->p_vaddr_offset = segment->p_vaddr; map->count = 0; *pointer_to_map = map; 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 segment. So, we must account for that in the output 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); continue; @@ -7367,12 +7368,14 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd) map->header_size = lowest_section->filepos; } - if (!map->includes_phdrs - && !map->includes_filehdr - && map->p_paddr_valid) - /* There is some other padding before the first section. */ - map->p_vaddr_offset = ((lowest_section ? lowest_section->lma : 0) - - segment->p_paddr); + 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)); map->count = section_count; *pointer_to_map = map; -- 2.34.1