Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -99,6 +99,7 @@ uint64_t EntryAddr = -1; unsigned LtoJobs; unsigned LtoO; + unsigned ZMaxPageSize; unsigned Optimize; }; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -228,6 +228,27 @@ return false; } +static unsigned getZOptionValue(opt::InputArgList &Args, StringRef Key) { + for (auto *Arg : Args.filtered(OPT_z)) { + StringRef ZExpr = Arg->getValue(); + if (!ZExpr.startswith(Key)) + continue; + + ZExpr = ZExpr.drop_front(Key.size()); + if (ZExpr.empty() || !ZExpr.startswith("=")) { + error("invalid format for -z " + Key + ": " + ZExpr); + return -1U; + } + + StringRef Val = ZExpr.drop_front(1); + unsigned Ret = -1; + if (Val.getAsInteger(0, Ret)) + error("-z " + Key + ": number expected, but got " + Val); + return Ret; + } + return -1U; +} + static void logCommandline(ArrayRef Args) { if (std::error_code EC = sys::fs::create_directories( Config->Reproduce, /*IgnoreExisting=*/false)) { @@ -356,6 +377,7 @@ Config->ZNow = hasZOption(Args, "now"); Config->ZOrigin = hasZOption(Args, "origin"); Config->ZRelro = !hasZOption(Args, "norelro"); + Config->ZMaxPageSize = getZOptionValue(Args, "max-page-size"); if (Config->Relocatable) Config->StripAll = false; @@ -478,6 +500,14 @@ Config->EntrySym = Symtab.addUndefined(S)->Backref; } + // Target page size can be changed by -z max-page-size. + if (Config->ZMaxPageSize != -1U) { + if (Config->ZMaxPageSize < Target->PageSize || + (Config->ZMaxPageSize % Target->PageSize != 0)) + error("wrong page size specified: " + Twine(Config->ZMaxPageSize)); + Target->PageSize = Config->ZMaxPageSize; + } + for (std::unique_ptr &F : Files) Symtab.addFile(std::move(F)); if (HasError) Index: test/ELF/max-page-size.s =================================================================== --- test/ELF/max-page-size.s +++ test/ELF/max-page-size.s @@ -0,0 +1,110 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: ld.lld -z max-page-size=0x20000 %t -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s +# CHECK: ProgramHeaders [ +# CHECK: ProgramHeader { +# CHECK: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: VirtualAddress: 0x10000 +# CHECK-NEXT: PhysicalAddress: 0x10000 +# CHECK-NEXT: FileSize: 344 +# CHECK-NEXT: MemSize: 344 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 131072 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x20000 +# CHECK-NEXT: VirtualAddress: 0x20000 +# CHECK-NEXT: PhysicalAddress: 0x20000 +# CHECK-NEXT: FileSize: 1 +# CHECK-NEXT: MemSize: 1 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 131072 +# CHECK-NEXT: } +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD +# CHECK-NEXT: Offset: 0x40000 +# CHECK-NEXT: VirtualAddress: 0x40000 +# CHECK-NEXT: PhysicalAddress: 0x40000 +# CHECK-NEXT: FileSize: 8 +# CHECK-NEXT: MemSize: 8 +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_W +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 131072 +# CHECK-NEXT: } + +# RUN: ld.lld -z max-page-size=0x1000 %t -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck -check-prefix STANDART %s +# STANDART: ProgramHeaders [ +# STANDART: ProgramHeader { +# STANDART: Type: PT_LOAD +# STANDART-NEXT: Offset: 0x0 +# STANDART-NEXT: VirtualAddress: 0x10000 +# STANDART-NEXT: PhysicalAddress: 0x10000 +# STANDART-NEXT: FileSize: 344 +# STANDART-NEXT: MemSize: 344 +# STANDART-NEXT: Flags [ +# STANDART-NEXT: PF_R +# STANDART-NEXT: ] +# STANDART-NEXT: Alignment: 4096 +# STANDART-NEXT: } +# STANDART-NEXT: ProgramHeader { +# STANDART-NEXT: Type: PT_LOAD +# STANDART-NEXT: Offset: 0x1000 +# STANDART-NEXT: VirtualAddress: 0x11000 +# STANDART-NEXT: PhysicalAddress: 0x11000 +# STANDART-NEXT: FileSize: 1 +# STANDART-NEXT: MemSize: 1 +# STANDART-NEXT: Flags [ +# STANDART-NEXT: PF_R +# STANDART-NEXT: PF_X +# STANDART-NEXT: ] +# STANDART-NEXT: Alignment: 4096 +# STANDART-NEXT: } +# STANDART-NEXT: ProgramHeader { +# STANDART-NEXT: Type: PT_LOAD +# STANDART-NEXT: Offset: 0x2000 +# STANDART-NEXT: VirtualAddress: 0x12000 +# STANDART-NEXT: PhysicalAddress: 0x12000 +# STANDART-NEXT: FileSize: 8 +# STANDART-NEXT: MemSize: 8 +# STANDART-NEXT: Flags [ +# STANDART-NEXT: PF_R +# STANDART-NEXT: PF_W +# STANDART-NEXT: ] +# STANDART-NEXT: Alignment: 4096 +# STANDART-NEXT: } + +# RUN: not ld.lld -z max-page-sizeX %t -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=INVALID1 %s +# INVALID1: invalid format for -z max-page-size + +# RUN: not ld.lld -z max-page-size=X %t -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=INVALID2 %s +# INVALID2: -z max-page-size: number expected, but got X + +# RUN: not ld.lld -z max-page-size=0x1 %t -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=INVALID3 %s +# INVALID3: wrong page size specified: 1 + +# RUN: not ld.lld -z max-page-size=0x1000001 %t -o %t2 2>&1 | \ +# RUN: FileCheck --check-prefix=INVALID4 %s +# INVALID4: wrong page size specified: 16777217 + +.globl _start +_start: + nop + +.section .a, "aw" +.quad 0