bfd/ 2012-06-11 H.J. Lu PR bfd/14207 * elf.c (_bfd_elf_map_sections_to_segments): Properly compute file size for PT_GNU_RELRO segment. (assign_file_positions_for_non_load_sections): Abort if PT_GNU_RELRO segment doesn't fit in PT_LOAD segment. ld/testsuite/ 2012-06-11 H.J. Lu PR ld/14207 * ld-x86-64/x86-64.exp: Run pr14207. * ld-x86-64/pr14207.d: New file. * ld-x86-64/pr14207.s: Likewise. diff --git a/bfd/elf.c b/bfd/elf.c index d97da9f..8b7e764 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -4154,9 +4154,31 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) { if (m->p_type == PT_LOAD) { - asection *last = m->sections[m->count - 1]; bfd_vma vaddr = m->sections[0]->vma; - bfd_vma filesz = last->vma - vaddr + last->size; + bfd_vma filesz = 0, memsz = 0; + asection **secpp; + + for (i = 0, secpp = m->sections; + i < m->count; + i++, secpp++) + { + asection *sec = *secpp; + if ((sec->flags + & (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD)) + == (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD)) + { + if (filesz < memsz) + filesz += memsz - filesz; + filesz += sec->size; + memsz += sec->size; + } + /* .tbss is special. It doesn't contribute to + memory size of normal segments. */ + else if ((sec->flags + & (SEC_THREAD_LOCAL | SEC_ALLOC | SEC_LOAD)) + == (SEC_ALLOC | SEC_LOAD)) + memsz += sec->size; + } if (vaddr < info->relro_end && vaddr >= info->relro_start @@ -4924,6 +4946,11 @@ assign_file_positions_for_non_load_sections (bfd *abfd, && lp->p_vaddr + lp->p_filesz >= link_info->relro_end) break; } + + /* PR ld/14207. If the RELRO segment doesn't fit in the + LOAD segment, it should be removed. */ + if (lp == (phdrs + count) && link_info->relro) + abort (); } else { diff --git a/ld/testsuite/ld-x86-64/pr14207.d b/ld/testsuite/ld-x86-64/pr14207.d new file mode 100644 index 0000000..2362e88 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr14207.d @@ -0,0 +1,9 @@ +#name: PR ld/14207 +#as: --64 +#ld: -melf_x86_64 -shared -z relro -z now +#readelf: -l --wide + +#failif +#... + NULL +.* +#... diff --git a/ld/testsuite/ld-x86-64/pr14207.s b/ld/testsuite/ld-x86-64/pr14207.s new file mode 100644 index 0000000..496e67e --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr14207.s @@ -0,0 +1,24 @@ + + .section .ctors, "aw" + .space 0x10, 1 + + .section .dtors, "aw" + .space 0x10, 2 + + .section .jcr, "aw" + .space 0x8, 3 + + .section .data.rel.ro + .p2align 4 + .space 0x20, 3 + + .section .dynamic + .space 0xb0, 2 + + .section .got + .space 0x2a8, 4 + + .bss + .zero 0x840 + + diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index b9af8de..1eb1b1c 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -209,6 +209,7 @@ run_dump_test "pr13947" run_dump_test "pr12570a" run_dump_test "pr12570b" run_dump_test "pr14215" +run_dump_test "pr14207" if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} { return