Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -136,6 +136,7 @@ uint16_t EMachine = llvm::ELF::EM_NONE; uint64_t EntryAddr = 0; uint64_t ImageBase; + uint64_t PageSize; uint64_t ZStackSize = -1; unsigned LtoJobs; unsigned LtoO; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -646,12 +646,21 @@ for (auto *Arg : Args.filtered(OPT_trace_symbol)) Symtab.trace(Arg->getValue()); + // Initialize Config->PageSize. The default value is defined by the + // target, but it can be overriden using the -z common-page-size option. + if (Optional Value = getZOptionValue(Args, "common-page-size")) { + if (Value->getAsInteger(0, Config->PageSize)) + error("invalid common page size: " + *Value); + } else { + Config->PageSize = Target->PageSize; + } + // Initialize Config->ImageBase. if (auto *Arg = Args.getLastArg(OPT_image_base)) { StringRef S = Arg->getValue(); if (S.getAsInteger(0, Config->ImageBase)) error(Arg->getSpelling() + ": number expected, but got " + S); - else if ((Config->ImageBase % Target->PageSize) != 0) + else if ((Config->ImageBase % Config->PageSize) != 0) warning(Arg->getSpelling() + ": address isn't multiple of page size"); } else { Config->ImageBase = Config->Pic ? 0 : Target->DefaultImageBase; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -615,7 +615,7 @@ // ELF and Program headers need to be right before the first section in // memory. Set their addresses accordingly. - MinVA = alignDown(MinVA - HeaderSize, Target->PageSize); + MinVA = alignDown(MinVA - HeaderSize, Config->PageSize); Out::ElfHeader->setVA(MinVA); Out::ProgramHeaders->setVA(Out::ElfHeader->getSize() + MinVA); } @@ -1414,7 +1414,7 @@ uint64_t static getConstant(StringRef S) { if (S == "COMMONPAGESIZE") - return Target->PageSize; + return Config->PageSize; if (S == "MAXPAGESIZE") return Target->MaxPageSize; error("unknown constant: " + S); @@ -1526,7 +1526,7 @@ expect(","); readExpr(); expect(")"); - return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); }; + return [](uint64_t Dot) { return alignTo(Dot, Config->PageSize); }; } if (Tok == "SIZEOF") { expect("("); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1154,7 +1154,7 @@ for (OutputSectionBase *Sec : OutputSections) { uintX_t Alignment = Sec->getAlignment(); if (Sec->PageAlign) - Alignment = std::max(Alignment, Target->PageSize); + Alignment = std::max(Alignment, Config->PageSize); auto I = Config->SectionStartMap.find(Sec->getName()); if (I != Config->SectionStartMap.end()) @@ -1182,14 +1182,14 @@ static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) { uintX_t Alignment = Sec->getAlignment(); if (Sec->PageAlign) - Alignment = std::max(Alignment, Target->PageSize); + Alignment = std::max(Alignment, Config->PageSize); Off = alignTo(Off, Alignment); // Relocatable output does not have program headers // and does not need any other offset adjusting. if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC)) return Off; - return alignTo(Off, Target->PageSize, Sec->getVA()); + return alignTo(Off, Config->PageSize, Sec->getVA()); } template @@ -1241,7 +1241,7 @@ H.p_vaddr = First->getVA(); } if (H.p_type == PT_LOAD) - H.p_align = Target->PageSize; + H.p_align = Config->PageSize; else if (H.p_type == PT_GNU_RELRO) H.p_align = 1; Index: test/ELF/linkerscript/zcommon-page-size.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/zcommon-page-size.s @@ -0,0 +1,14 @@ +# 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=0x1234 -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck %s + +# CHECK: 0000000000001234 *ABS* 00000000 symbol + +.global _start +_start: + nop