Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -132,10 +132,12 @@ UnresolvedPolicy UnresolvedSymbols; BuildIdKind BuildId = BuildIdKind::None; ELFKind EKind = ELFNoneKind; + uint64_t CommonPageSize; uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL; uint16_t EMachine = llvm::ELF::EM_NONE; uint64_t EntryAddr = 0; uint64_t ImageBase; + uint64_t MaxPageSize; uint64_t ZStackSize = -1; unsigned LtoJobs; unsigned LtoO; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -264,15 +264,19 @@ return false; } -static Optional -getZOptionValue(opt::InputArgList &Args, StringRef Key) { +static uint64_t +getZOptionValue(opt::InputArgList &Args, StringRef Key, uint64_t Default) { + uint64_t Result = Default; for (auto *Arg : Args.filtered(OPT_z)) { StringRef Value = Arg->getValue(); size_t Pos = Value.find("="); - if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) - return Value.substr(Pos + 1); + if (Pos != StringRef::npos && Key == Value.substr(0, Pos)) { + Value = Value.substr(Pos + 1); + if (Value.getAsInteger(0, Result)) + error("invalid " + Key + ": " + Value); + } } - return None; + return Result; } void LinkerDriver::main(ArrayRef ArgsArr) { @@ -492,9 +496,7 @@ if (!Config->Relocatable) Config->Strip = getStripOption(Args); - if (Optional Value = getZOptionValue(Args, "stack-size")) - if (Value->getAsInteger(0, Config->ZStackSize)) - error("invalid stack size: " + *Value); + Config->ZStackSize = getZOptionValue(Args, "stack-size", -1); // Config->Pic is true if we are generating position-independent code. Config->Pic = Config->Pie || Config->Shared; @@ -657,6 +659,18 @@ Config->ImageBase = Config->Pic ? 0 : Target->DefaultImageBase; } + // Initialize Config->MaxPageSize and Config->CommonPageSize. The default + // value is defined by the target, but it can be overriden using the option. + Config->MaxPageSize = + getZOptionValue(Args, "max-page-size", Target->MaxPageSize); + if ((Config->MaxPageSize & (Config->MaxPageSize - 1)) != 0) + error("max-page-size: value isn't a power of 2"); + uint64_t CommonPageSize = + getZOptionValue(Args, "common-page-size", Target->PageSize); + if ((CommonPageSize & (CommonPageSize - 1)) != 0) + error("common-page-size: value isn't a power of 2"); + Config->CommonPageSize = std::min(CommonPageSize, Config->MaxPageSize); + // Add all files to the symbol table. After this, the symbol table // contains all known names except a few linker-synthesized symbols. for (InputFile *F : Files) Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -1414,9 +1414,9 @@ uint64_t static getConstant(StringRef S) { if (S == "COMMONPAGESIZE") - return Target->PageSize; + return Config->CommonPageSize; if (S == "MAXPAGESIZE") - return Target->MaxPageSize; + return Config->MaxPageSize; error("unknown constant: " + S); return 0; } Index: test/ELF/linkerscript/zcommon-page-size.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/zcommon-page-size.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: symbol = CONSTANT(COMMONPAGESIZE); \ +# RUN: }" > %t.script +# RUN: ld.lld -z common-page-size=0x1000 -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# RUN: not ld.lld -z common-page-size=0x1001 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR1 %s +# ERR1: common-page-size: value isn't a power of 2 + +# RUN: not ld.lld -z common-page-size=-0x1000 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR2 %s +# ERR2: invalid common-page-size: -0x1000 + +# CHECK: 0000000000001000 *ABS* 00000000 symbol + +.global _start +_start: + nop Index: test/ELF/linkerscript/zmax-page-size.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/zmax-page-size.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: symbol = CONSTANT(MAXPAGESIZE); \ +# RUN: }" > %t.script +# RUN: ld.lld -z max-page-size=0x1000 -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# RUN: not ld.lld -z max-page-size=0x1001 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR1 %s +# ERR1: max-page-size: value isn't a power of 2 + +# RUN: not ld.lld -z max-page-size=-0x1000 -o %t1 --script %t.script %t 2>&1 \ +# RUN: | FileCheck -check-prefix=ERR2 %s +# ERR2: invalid max-page-size: -0x1000 + +# CHECK: 0000000000001000 *ABS* 00000000 symbol + +.global _start +_start: + nop