From b559959291b5423bbdc51a8d3b84f322f82a1e2b Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sat, 17 Jul 2010 03:10:50 +0000 Subject: [PATCH] * elf.c (_bfd_elf_map_sections_to_segments): Force new segment for sections with overlapping LMAs. (assign_file_positions_for_load_sections): Catch overlap for sections that wrap around the address space. Replace a warning that duplicates ld's --check-sections error with a warning that lma has been adjusted for overlapping sections. --- bfd/ChangeLog | 9 +++++++++ bfd/elf.c | 21 ++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 05d57ce..a6dd0d8 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2010-07-17 Alan Modra + + * elf.c (_bfd_elf_map_sections_to_segments): Force new segment + for sections with overlapping LMAs. + (assign_file_positions_for_load_sections): Catch overlap for + sections that wrap around the address space. Replace a + warning that duplicates ld's --check-sections error with a + warning that lma has been adjusted for overlapping sections. + 2010-07-14 Cary Coutant PR ld/11817 diff --git a/bfd/elf.c b/bfd/elf.c index 0fa75d2..63f0260 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -3736,6 +3736,13 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) segment. */ new_segment = TRUE; } + else if (hdr->lma < last_hdr->lma + last_size + || last_hdr->lma + last_size < last_hdr->lma) + { + /* If this section has a load address that makes it overlap + the previous section, then we need a new segment. */ + new_segment = TRUE; + } /* In the next test we have to be careful when last_hdr->lma is close to the end of the address space. If the aligned address wraps around to the start of the address space, then there are no more @@ -4457,15 +4464,19 @@ assign_file_positions_for_load_sections (bfd *abfd, && ((this_hdr->sh_flags & SHF_TLS) == 0 || p->p_type == PT_TLS)))) { - bfd_vma adjust = sec->lma - (p->p_paddr + p->p_memsz); + bfd_vma p_start = p->p_paddr; + bfd_vma p_end = p_start + p->p_memsz; + bfd_vma s_start = sec->lma; + bfd_vma adjust = s_start - p_end; - if (sec->lma < p->p_paddr + p->p_memsz) + if (s_start < p_end + || p_end < p_start) { (*_bfd_error_handler) - (_("%B: section %A lma 0x%lx overlaps previous sections"), - abfd, sec, (unsigned long) sec->lma); + (_("%B: section %A lma %#lx adjusted to %#lx"), abfd, sec, + (unsigned long) s_start, (unsigned long) p_end); adjust = 0; - sec->lma = p->p_paddr + p->p_memsz; + sec->lma = p_end; } p->p_memsz += adjust; -- 2.7.4