diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elf.c | 159 |
2 files changed, 84 insertions, 86 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 6f6a89a..d8b3773 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2018-05-12 Alan Modra <amodra@gmail.com> + + PR 20659 + * elf.c (rewrite_elf_program_header): Use segment_mark only for + PT_LOAD headers. Delete first_matching_lma and first_suggested_lma. + Instead make matching_lma and suggested_lma pointers to the + sections. Align section vma and lma calculated from segment. + Don't clear includes_phdrs or includes_filehdr based on p_paddr + test. Try to handle alignment padding before first section by + adjusting new segment lma down. Adjust PT_PHDR map p_paddr. + 2018-05-09 Dimitar Dimitrov <dimitar@dinux.eu> * elf32-pru.c (pru_elf32_do_ldi32_relocate): Make LDI32 relocation @@ -6641,7 +6641,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) : segment->p_vaddr != section->vma) \ || (strcmp (bfd_get_section_name (ibfd, section), ".dynamic") \ == 0)) \ - && !section->segment_mark) + && (segment->p_type != PT_LOAD || !section->segment_mark)) /* If the output section of a section in the input segment is NULL, it is removed from the corresponding output segment. */ @@ -6769,13 +6769,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) asection **sections; asection *output_section; unsigned int isec; - bfd_vma matching_lma; - bfd_vma suggested_lma; + asection *matching_lma; + asection *suggested_lma; unsigned int j; bfd_size_type amt; asection *first_section; - bfd_boolean first_matching_lma; - bfd_boolean first_suggested_lma; if (segment->p_type == PT_NULL) continue; @@ -6902,10 +6900,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) we have completely filled the segment, and there is nothing more to do. */ isec = 0; - matching_lma = 0; - suggested_lma = 0; - first_matching_lma = TRUE; - first_suggested_lma = TRUE; + matching_lma = NULL; + suggested_lma = NULL; for (section = first_section, j = 0; section != NULL; @@ -6926,14 +6922,14 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) && !bed->want_p_paddr_set_to_zero && isec == 0 && output_section->lma != 0 - && output_section->vma == (segment->p_vaddr - + (map->includes_filehdr - ? iehdr->e_ehsize - : 0) - + (map->includes_phdrs - ? (iehdr->e_phnum - * iehdr->e_phentsize) - : 0))) + && (align_power (segment->p_vaddr + + (map->includes_filehdr + ? iehdr->e_ehsize : 0) + + (map->includes_phdrs + ? iehdr->e_phnum * iehdr->e_phentsize + : 0), + output_section->alignment_power) + == output_section->vma)) map->p_paddr = segment->p_vaddr; /* Match up the physical address of the segment with the @@ -6943,22 +6939,17 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) || (bed->want_p_paddr_set_to_zero && IS_CONTAINED_BY_VMA (output_section, segment))) { - if (first_matching_lma || output_section->lma < matching_lma) - { - matching_lma = output_section->lma; - first_matching_lma = FALSE; - } + if (matching_lma == NULL + || output_section->lma < matching_lma->lma) + matching_lma = output_section; /* We assume that if the section fits within the segment then it does not overlap any other section within that segment. */ map->sections[isec++] = output_section; } - else if (first_suggested_lma) - { - suggested_lma = output_section->lma; - first_suggested_lma = FALSE; - } + else if (suggested_lma == NULL) + suggested_lma = output_section; if (j == section_count) break; @@ -6981,63 +6972,54 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) if (p_paddr_valid && !bed->want_p_paddr_set_to_zero - && matching_lma != map->p_paddr + && 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 = matching_lma - map->p_paddr; + map->p_vaddr_offset = matching_lma->lma - map->p_paddr; free (sections); continue; } else { - if (!first_matching_lma) - { - /* At least one section fits inside the current segment. - Keep it, but modify its physical address to match the - LMA of the first section that fitted. */ - map->p_paddr = matching_lma; - } - else - { - /* None of the sections fitted inside the current segment. - Change the current segment's physical address to match - the LMA of the first section. */ - map->p_paddr = suggested_lma; - } + /* Change the current segment's physical address to match + the LMA of the first section that fitted, or if no + section fitted, the first section. */ + if (matching_lma == NULL) + matching_lma = suggested_lma; + + map->p_paddr = matching_lma->lma; /* Offset the segment physical address from the lma to allow for space taken up by elf headers. */ - if (map->includes_filehdr) + if (map->includes_phdrs) { - if (map->p_paddr >= iehdr->e_ehsize) - map->p_paddr -= iehdr->e_ehsize; - else - { - map->includes_filehdr = FALSE; - map->includes_phdrs = FALSE; - } + map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize; + + /* iehdr->e_phnum is just an estimate of the number + of program headers that we will need. Make a note + here of the number we used and the segment we chose + to hold these headers, so that we can adjust the + offset when we know the correct value. */ + phdr_adjust_num = iehdr->e_phnum; + phdr_adjust_seg = map; } - if (map->includes_phdrs) + if (map->includes_filehdr) { - if (map->p_paddr >= iehdr->e_phnum * iehdr->e_phentsize) - { - map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize; - - /* iehdr->e_phnum is just an estimate of the number - of program headers that we will need. Make a note - here of the number we used and the segment we chose - to hold these headers, so that we can adjust the - offset when we know the correct value. */ - phdr_adjust_num = iehdr->e_phnum; - phdr_adjust_seg = map; - } - else - map->includes_phdrs = FALSE; + bfd_vma align = (bfd_vma) 1 << matching_lma->alignment_power; + map->p_paddr -= iehdr->e_ehsize; + /* We've subtracted off the size of headers from the + first section lma, but there may have been some + alignment padding before that section too. Try to + account for that by adjusting the segment lma down to + the same alignment. */ + if (segment->p_align != 0 && segment->p_align < align) + align = segment->p_align; + map->p_paddr &= -align; } } @@ -7052,8 +7034,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) do { map->count = 0; - suggested_lma = 0; - first_suggested_lma = TRUE; + suggested_lma = NULL; /* Fill the current segment with sections that fit. */ for (j = 0; j < section_count; j++) @@ -7075,12 +7056,14 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) /* If the first section in a segment does not start at the beginning of the segment, then something is wrong. */ - if (output_section->lma - != (map->p_paddr - + (map->includes_filehdr ? iehdr->e_ehsize : 0) - + (map->includes_phdrs - ? iehdr->e_phnum * iehdr->e_phentsize - : 0))) + if (align_power (map->p_paddr + + (map->includes_filehdr + ? iehdr->e_ehsize : 0) + + (map->includes_phdrs + ? iehdr->e_phnum * iehdr->e_phentsize + : 0), + output_section->alignment_power) + != output_section->lma) abort (); } else @@ -7098,11 +7081,8 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) || (prev_sec->lma + prev_sec->size > output_section->lma)) { - if (first_suggested_lma) - { - suggested_lma = output_section->lma; - first_suggested_lma = FALSE; - } + if (suggested_lma == NULL) + suggested_lma = output_section; continue; } @@ -7111,13 +7091,11 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) map->sections[map->count++] = output_section; ++isec; sections[j] = NULL; - section->segment_mark = TRUE; - } - else if (first_suggested_lma) - { - suggested_lma = output_section->lma; - first_suggested_lma = FALSE; + if (segment->p_type == PT_LOAD) + section->segment_mark = TRUE; } + else if (suggested_lma == NULL) + suggested_lma = output_section; } BFD_ASSERT (map->count > 0); @@ -7147,7 +7125,7 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) map->p_type = segment->p_type; map->p_flags = segment->p_flags; map->p_flags_valid = 1; - map->p_paddr = suggested_lma; + map->p_paddr = suggested_lma->lma; map->p_paddr_valid = p_paddr_valid; map->includes_filehdr = 0; map->includes_phdrs = 0; @@ -7173,6 +7151,15 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd) if (count > phdr_adjust_num) phdr_adjust_seg->p_paddr -= (count - phdr_adjust_num) * iehdr->e_phentsize; + + for (map = map_first; map != NULL; map = map->next) + if (map->p_type == PT_PHDR) + { + bfd_vma adjust + = phdr_adjust_seg->includes_filehdr ? iehdr->e_ehsize : 0; + map->p_paddr = phdr_adjust_seg->p_paddr + adjust; + break; + } } #undef SEGMENT_END |