Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -2212,17 +2212,39 @@ // first section after PT_GNU_RELRO have to be page aligned so that the dynamic // linker can set the permissions. template void Writer::fixSectionAlignments() { - auto pageAlign = [](OutputSection *cmd) { - if (cmd && !cmd->addrExpr) - cmd->addrExpr = [=] { - return alignTo(script->getDot(), config->maxPageSize); - }; + const PhdrEntry *last; + auto pageAlign = [&](const PhdrEntry *p) { + OutputSection *cmd = p->firstSec; + if (cmd && !cmd->addrExpr) { + // Advancing to align(dot, maxPageSize) + dot%maxPageSize avoids p_offset + // gaps, which decreases the output size. + // + // When -z separate-code is specified, the PF_X segment should be placed + // in its own pages, not sharable with adjacent segments, so don't use the + // trick. + // + // TODO Enable this trick on x86 (maxPageSize=4096). + if (config->maxPageSize > 4096 && + (!config->zSeparateCode || + (last && (last->p_flags & PF_X) == (p->p_flags & PF_X)))) + cmd->addrExpr = [] { + return alignTo(script->getDot(), config->maxPageSize) + + script->getDot() % config->maxPageSize; + }; + else + cmd->addrExpr = [] { + return alignTo(script->getDot(), config->maxPageSize); + }; + } }; for (Partition &part : partitions) { + last = nullptr; for (const PhdrEntry *p : part.phdrs) - if (p->p_type == PT_LOAD && p->firstSec) - pageAlign(p->firstSec); + if (p->p_type == PT_LOAD && p->firstSec) { + pageAlign(p); + last = p; + } } } @@ -2244,7 +2266,10 @@ OutputSection *first = os->ptLoad->firstSec; if (os == first) { uint64_t alignment = std::max(os->alignment, config->maxPageSize); - return alignTo(off, alignment, os->addr); + uint64_t ret = alignTo(off, alignment, os->addr); + if (ret >= off + alignment) + ret -= alignment; + return ret; } // If two sections share the same PT_LOAD the file offset is calculated Index: test/ELF/ppc64-abs64-dyn.s =================================================================== --- test/ELF/ppc64-abs64-dyn.s +++ test/ELF/ppc64-abs64-dyn.s @@ -12,10 +12,10 @@ ## FIXME the addend for offset 0x20000 should be TOC base+0x8000+1, not 0x80001. # CHECK: .rela.dyn { -# CHECK-NEXT: 0x20000 R_PPC64_RELATIVE - 0x8001 -# CHECK-NEXT: 0x20008 R_PPC64_RELATIVE - 0x20001 -# CHECK-NEXT: 0x20010 R_PPC64_ADDR64 external 0x1 -# CHECK-NEXT: 0x20018 R_PPC64_ADDR64 global 0x1 +# CHECK-NEXT: 0x303b0 R_PPC64_RELATIVE - 0x8001 +# CHECK-NEXT: 0x303b8 R_PPC64_RELATIVE - 0x303b1 +# CHECK-NEXT: 0x303c0 R_PPC64_ADDR64 external 0x1 +# CHECK-NEXT: 0x303c8 R_PPC64_ADDR64 global 0x1 # CHECK-NEXT: } .data Index: test/ELF/ppc64-bsymbolic-toc-restore.s =================================================================== --- test/ELF/ppc64-bsymbolic-toc-restore.s +++ test/ELF/ppc64-bsymbolic-toc-restore.s @@ -63,6 +63,6 @@ # CHECK-EMPTY: # CHECK-NEXT: def: # CHECK-NEXT: addis 2, 12, 2 -# CHECK-NEXT: addi 2, 2, -32616 +# CHECK-NEXT: addi 2, 2, -32456 # CHECK-NEXT: li 3, 55 # CHECK-NEXT: blr Index: test/ELF/ppc64-call-reach.s =================================================================== --- test/ELF/ppc64-call-reach.s +++ test/ELF/ppc64-call-reach.s @@ -2,37 +2,37 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ -# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s +# RUN: -z separate-code %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ -# RUN: %t.o -o %t +# RUN: -z separate-code %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ -# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s +# RUN: -z separate-code %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s # MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x14): improper alignment for relocation R_PPC64_REL24: 0x19 is not aligned to 4 bytes # MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x24): improper alignment for relocation R_PPC64_REL24: 0xB is not aligned to 4 bytes Index: test/ELF/ppc64-dq.s =================================================================== --- test/ELF/ppc64-dq.s +++ test/ELF/ppc64-dq.s @@ -28,5 +28,5 @@ # Verify that we don't overwrite any of the extended opcode bits on a DQ form # instruction. # CHECK-LABEL: test -# CHECK: lxv 3, -32768(3) -# CHECK: stxv 3, -32768(3) +# CHECK: lxv 3, -32752(3) +# CHECK: stxv 3, -32752(3) Index: test/ELF/ppc64-dtprel.s =================================================================== --- test/ELF/ppc64-dtprel.s +++ test/ELF/ppc64-dtprel.s @@ -137,15 +137,15 @@ // OutputRelocs-NEXT: R_PPC64_DTPMOD64 -// The got entry for i is at .got+8*3 = 0x420510 +// The got entry for i is at .got+8*1 = 0x4209e0 // i@dtprel = 1024 - 0x8000 = -31744 = 0xffffffffffff8400 // HEX-LE: section '.got': -// HEX-LE-NEXT: 4204f8 f8844200 00000000 00000000 00000000 -// HEX-LE-NEXT: 420508 00000000 00000000 +// HEX-LE-NEXT: 4209d8 d8894200 00000000 00000000 00000000 +// HEX-LE-NEXT: 4209e8 00000000 00000000 // HEX-BE: section '.got': -// HEX-BE-NEXT: 4204f8 00000000 004284f8 00000000 00000000 -// HEX-BE-NEXT: 420508 00000000 00000000 +// HEX-BE-NEXT: 4209d8 00000000 004289d8 00000000 00000000 +// HEX-BE-NEXT: 4209e8 00000000 00000000 // Dis: test: // Dis: addi 4, 3, -31744 Index: test/ELF/ppc64-dynamic-relocations.s =================================================================== --- test/ELF/ppc64-dynamic-relocations.s +++ test/ELF/ppc64-dynamic-relocations.s @@ -20,16 +20,16 @@ // The dynamic relocation for foo should point to 16 bytes past the start of // the .plt section. // CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x10030010 R_PPC64_JMP_SLOT foo 0x0 +// CHECK-NEXT: 0x10030448 R_PPC64_JMP_SLOT foo 0x0 // There should be 2 reserved doublewords before the first entry. The dynamic // linker will fill those in with the address of the resolver entry point and // the dynamic object identifier. // DIS: Idx Name Size VMA Type -// DIS: .plt 00000018 0000000010030000 BSS +// DIS: .plt 00000018 0000000010030438 BSS // DT_PLTGOT should point to the start of the .plt section. -// DT: 0x0000000000000003 (PLTGOT) 0x10030000 +// DT: 0x0000000000000003 (PLTGOT) 0x10030438 .text .abiversion 2 Index: test/ELF/ppc64-entry-point.s =================================================================== --- test/ELF/ppc64-entry-point.s +++ test/ELF/ppc64-entry-point.s @@ -34,12 +34,12 @@ .Lfunc_end0: .size _start, .Lfunc_end0-.Lfunc_begin0 -# NM-DAG: 0000000010028000 d .TOC. -# NM-DAG: 0000000010010000 T _start +# NM-DAG: 00000000100281f0 d .TOC. +# NM-DAG: 00000000100101d0 T _start -# 0x10010000 = (4097<<16) + 0 -# CHECK: 10010000: lis 4, 4097 -# CHECK-NEXT: 10010004: addi 4, 4, 0 -# .TOC. - _start = (2<<16) - 32768 -# CHECK-NEXT: 10010008: lis 5, 2 -# CHECK-NEXT: 1001000c: addi 5, 5, -32768 +# 0x100101d0 = (4097<<16) + 464 +# CHECK: 100101d0: lis 4, 4097 +# CHECK-NEXT: 100101d4: addi 4, 4, 464 +# .TOC. - _start = (2<<16) - 32736 +# CHECK-NEXT: 100101d8: lis 5, 2 +# CHECK-NEXT: 100101dc: addi 5, 5, -32736 Index: test/ELF/ppc64-error-missaligned-dq.s =================================================================== --- test/ELF/ppc64-error-missaligned-dq.s +++ test/ELF/ppc64-error-missaligned-dq.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s -# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 16 bytes +# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8009 is not aligned to 16 bytes .global test .p2align 4 Index: test/ELF/ppc64-error-missaligned-ds.s =================================================================== --- test/ELF/ppc64-error-missaligned-ds.s +++ test/ELF/ppc64-error-missaligned-ds.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s -# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 4 bytes +# CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8009 is not aligned to 4 bytes .global test .p2align 4