summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Arch/SPARCV9.cpp2
-rw-r--r--lld/ELF/Config.h2
-rw-r--r--lld/ELF/Driver.cpp49
-rw-r--r--lld/ELF/LinkerScript.cpp4
-rw-r--r--lld/ELF/Options.td11
-rw-r--r--lld/ELF/ScriptParser.cpp2
-rw-r--r--lld/ELF/Target.h2
-rw-r--r--lld/ELF/Writer.cpp13
-rw-r--r--lld/docs/ld.lld.18
-rw-r--r--lld/test/ELF/common-page.s223
-rw-r--r--lld/test/ELF/linkerscript/nmagic-alignment.test85
-rw-r--r--lld/test/ELF/magic-page-combo-warn.s86
-rw-r--r--lld/test/ELF/relro-omagic.s2
-rw-r--r--lld/test/ELF/segments.s48
14 files changed, 515 insertions, 22 deletions
diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp
index 591810f6c51..9be0696596c 100644
--- a/lld/ELF/Arch/SPARCV9.cpp
+++ b/lld/ELF/Arch/SPARCV9.cpp
@@ -41,7 +41,7 @@ SPARCV9::SPARCV9() {
PltEntrySize = 32;
PltHeaderSize = 4 * PltEntrySize;
- PageSize = 8192;
+ DefaultCommonPageSize = 8192;
DefaultMaxPageSize = 0x100000;
DefaultImageBase = 0x100000;
}
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index b791723dc90..ac23b55f841 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -159,6 +159,7 @@ struct Configuration {
bool LTONewPassManager;
bool MergeArmExidx;
bool MipsN32Abi = false;
+ bool Nmagic;
bool NoinhibitExec;
bool Nostdlib;
bool OFormatBinary;
@@ -219,6 +220,7 @@ struct Configuration {
uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
uint16_t EMachine = llvm::ELF::EM_NONE;
llvm::Optional<uint64_t> ImageBase;
+ uint64_t CommonPageSize;
uint64_t MaxPageSize;
uint64_t MipsGotSize;
uint64_t ZStackSize;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 27f186414d3..0e5f1a72e6e 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -365,7 +365,8 @@ static bool isKnownZFlag(StringRef S) {
S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" ||
S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" ||
S == "rodynamic" || S == "text" || S == "wxneeded" ||
- S.startswith("max-page-size=") || S.startswith("stack-size=");
+ S.startswith("common-page-size") || S.startswith("max-page-size=") ||
+ S.startswith("stack-size=");
}
// Report an error for an unknown -z option.
@@ -829,6 +830,7 @@ static void readConfigs(opt::InputArgList &Args) {
Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0);
Config->MergeArmExidx =
Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
+ Config->Nmagic = Args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec);
Config->Nostdlib = Args.hasArg(OPT_nostdlib);
Config->OFormatBinary = isOutputFormatBinary(Args);
@@ -957,11 +959,10 @@ static void readConfigs(opt::InputArgList &Args) {
if (Args.hasArg(OPT_print_map))
Config->MapFile = "-";
- // --omagic is an option to create old-fashioned executables in which
- // .text segments are writable. Today, the option is still in use to
- // create special-purpose programs such as boot loaders. It doesn't
- // make sense to create PT_GNU_RELRO for such executables.
- if (Config->Omagic)
+ // Page alignment can be disabled by the -n (--nmagic) and -N (--omagic).
+ // As PT_GNU_RELRO relies on Paging, do not create it when we have disabled
+ // it.
+ if (Config->Nmagic || Config->Omagic)
Config->ZRelro = false;
std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args);
@@ -1114,6 +1115,8 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
Config->AsNeeded = false;
break;
case OPT_Bstatic:
+ case OPT_omagic:
+ case OPT_nmagic:
Config->Static = true;
break;
case OPT_Bdynamic:
@@ -1199,6 +1202,29 @@ static uint64_t getMaxPageSize(opt::InputArgList &Args) {
Target->DefaultMaxPageSize);
if (!isPowerOf2_64(Val))
error("max-page-size: value isn't a power of 2");
+ if (Config->Nmagic || Config->Omagic) {
+ if (Val != Target->DefaultMaxPageSize)
+ warn("-z max-page-size set, but paging disabled by omagic or nmagic");
+ return 1;
+ }
+ return Val;
+}
+
+// Parse -z common-page-size=<value>. The default value is defined by
+// each target.
+static uint64_t getCommonPageSize(opt::InputArgList &Args) {
+ uint64_t Val = args::getZOptionValue(Args, OPT_z, "common-page-size",
+ Target->DefaultCommonPageSize);
+ if (!isPowerOf2_64(Val))
+ error("common-page-size: value isn't a power of 2");
+ if (Config->Nmagic || Config->Omagic) {
+ if (Val != Target->DefaultCommonPageSize)
+ warn("-z common-page-size set, but paging disabled by omagic or nmagic");
+ return 1;
+ }
+ // CommonPageSize can't be larger than MaxPageSize.
+ if (Val > Config->MaxPageSize)
+ Val = Config->MaxPageSize;
return Val;
}
@@ -1623,7 +1649,18 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
llvm::erase_if(InputSections, [](InputSectionBase *S) { return S->Debug; });
Config->EFlags = Target->calcEFlags();
+ // MaxPageSize (sometimes called abi page size) is the maximum page size that
+ // the output can be run on. For example if the OS can use 4k or 64k page
+ // sizes then MaxPageSize must be 64 for the output to be useable on both.
+ // All important alignment decisions must use this value.
Config->MaxPageSize = getMaxPageSize(Args);
+ // CommonPageSize is the most common page size that the output will be run on.
+ // For example if an OS can use 4k or 64k page sizes and 4k is more common
+ // than 64k then CommonPageSize is set to 4k. CommonPageSize can be used for
+ // optimizations such as DATA_SEGMENT_ALIGN in linker scripts. LLD's use of it
+ // is limited to writing trap instructions on the last executable segment.
+ Config->CommonPageSize = getCommonPageSize(Args);
+
Config->ImageBase = getImageBase(Args);
if (Config->EMachine == EM_ARM) {
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index e6a253f1f2d..872081f94e5 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -993,8 +993,10 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
llvm::any_of(PhdrsCommands, [](const PhdrsCommand &Cmd) {
return Cmd.HasPhdrs || Cmd.HasFilehdr;
});
+ bool Paged = !Config->Omagic && !Config->Nmagic;
uint64_t HeaderSize = getHeaderSize();
- if (HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) {
+ if ((Paged || HasExplicitHeaders) &&
+ HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) {
Min = alignDown(Min - HeaderSize, Config->MaxPageSize);
Out::ElfHeader->Addr = Min;
Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index e0f3fbec97c..a96bf3cc0a3 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -218,6 +218,9 @@ defm merge_exidx_entries: B<"merge-exidx-entries",
"Enable merging .ARM.exidx entries (default)",
"Disable merging .ARM.exidx entries">;
+def nmagic: F<"nmagic">, MetaVarName<"<magic>">,
+ HelpText<"Do not page align sections, link against static libraries.">;
+
def nostdlib: F<"nostdlib">,
HelpText<"Only search directories specified on the command line">;
@@ -230,8 +233,11 @@ def no_dynamic_linker: F<"no-dynamic-linker">,
def noinhibit_exec: F<"noinhibit-exec">,
HelpText<"Retain the executable output file whenever it is still usable">;
+def no_nmagic: F<"no-nmagic">, MetaVarName<"<magic>">,
+ HelpText<"Page align sections (default)">;
+
def no_omagic: F<"no-omagic">, MetaVarName<"<magic>">,
- HelpText<"Do not set the text data sections to be writable">;
+ HelpText<"Do not set the text data sections to be writable, page align sections (default)">;
def no_rosegment: F<"no-rosegment">,
HelpText<"Do not put read-only non-executable sections in their own segment">;
@@ -246,7 +252,7 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
HelpText<"Specify the binary format for the output object file">;
def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">,
- HelpText<"Set the text and data sections to be readable and writable">;
+ HelpText<"Set the text and data sections to be readable and writable, do not page align sections, link against static libraries">;
defm orphan_handling:
Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;
@@ -414,6 +420,7 @@ def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;
def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;
def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;
def: F<"no-pic-executable">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
+def: Flag<["-"], "n">, Alias<nmagic>, HelpText<"Alias for --nmagic">;
def: Flag<["-"], "N">, Alias<omagic>, HelpText<"Alias for --omagic">;
def: Joined<["--"], "output=">, Alias<o>, HelpText<"Alias for -o">;
def: Separate<["--"], "output">, Alias<o>, HelpText<"Alias for -o">;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 741b32ff031..c4a389a3c88 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1039,7 +1039,7 @@ Expr ScriptParser::getPageSize() {
std::string Location = getCurrentLocation();
return [=]() -> uint64_t {
if (Target)
- return Target->PageSize;
+ return Config->CommonPageSize;
error(Location + ": unable to calculate page size");
return 4096; // Return a dummy value.
};
diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h
index 6eae6c7a298..ca38a455646 100644
--- a/lld/ELF/Target.h
+++ b/lld/ELF/Target.h
@@ -81,7 +81,7 @@ public:
virtual ~TargetInfo();
- unsigned PageSize = 4096;
+ unsigned DefaultCommonPageSize = 4096;
unsigned DefaultMaxPageSize = 4096;
uint64_t getImageBase() const;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1ca359e0443..0678f73a387 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2132,7 +2132,7 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
// segment is the last loadable segment, align the offset of the
// following section to avoid loading non-segments parts of the file.
if (LastRX && LastRX->LastSec == Sec)
- Off = alignTo(Off, Target->PageSize);
+ Off = alignTo(Off, Config->CommonPageSize);
}
SectionHeaderOff = alignTo(Off, Config->Wordsize);
@@ -2184,7 +2184,7 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
// The glibc dynamic loader rounds the size down, so we need to round up
// to protect the last page. This is a no-op on FreeBSD which always
// rounds up.
- P->p_memsz = alignTo(P->p_memsz, Target->PageSize);
+ P->p_memsz = alignTo(P->p_memsz, Config->CommonPageSize);
}
if (P->p_type == PT_TLS && P->p_memsz) {
@@ -2477,10 +2477,10 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
// Fill the last page.
for (PhdrEntry *P : Phdrs)
if (P->p_type == PT_LOAD && (P->p_flags & PF_X))
- fillTrap(Out::BufferStart +
- alignDown(P->p_offset + P->p_filesz, Target->PageSize),
+ fillTrap(Out::BufferStart + alignDown(P->p_offset + P->p_filesz,
+ Config->CommonPageSize),
Out::BufferStart +
- alignTo(P->p_offset + P->p_filesz, Target->PageSize));
+ alignTo(P->p_offset + P->p_filesz, Config->CommonPageSize));
// Round up the file size of the last segment to the page boundary iff it is
// an executable segment to ensure that other tools don't accidentally
@@ -2491,7 +2491,8 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
Last = P;
if (Last && (Last->p_flags & PF_X))
- Last->p_memsz = Last->p_filesz = alignTo(Last->p_filesz, Target->PageSize);
+ Last->p_memsz = Last->p_filesz =
+ alignTo(Last->p_filesz, Config->CommonPageSize);
}
// Write section contents to a mmap'ed file.
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index d18914ca509..24c624b1cdb 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -254,6 +254,8 @@ Set target emulation.
.It Fl -Map Ns = Ns Ar file , Fl M Ar file
Print a link map to
.Ar file .
+.It Fl -nmagic , Fl n
+Do not page align sections, link against static libraries.
.It Fl -no-allow-shlib-undefined
Do not allow unresolved references in shared libraries.
This option is enabled by default when linking an executable.
@@ -277,6 +279,10 @@ Disable garbage collection of unused sections.
Disable STB_GNU_UNIQUE symbol binding.
.It Fl -no-merge-exidx-entries
Disable merging .ARM.exidx entries.
+.It F1 -no-nmagic
+Page align sections.
+.It F1 -no-omagic
+Do not set the text data sections to be writable, page align sections.
.It Fl -no-rosegment
Do not put read-only non-executable sections in their own segment.
.It Fl -no-threads
@@ -325,7 +331,7 @@ is
.Cm binary ,
which produces output with no ELF header.
.It Fl -omagic , Fl N
-Set the text and data sections to be readable and writable.
+Set the text and data sections to be readable and writable, do not page align sections, link against static libraries.
.It Fl -opt-remarks-filename Ar file
Write optimization remarks in YAML format to
.Ar file .
diff --git a/lld/test/ELF/common-page.s b/lld/test/ELF/common-page.s
new file mode 100644
index 00000000000..4734a49a84e
--- /dev/null
+++ b/lld/test/ELF/common-page.s
@@ -0,0 +1,223 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# exits with return code 42 on linux
+.globl _start
+_start:
+ nop
+
+# Increase max-page-size to 64k while using the default x86_64 common page size
+# of 4k. If the last loadable segment is executable then lld aligns the next
+# section using the common page size.
+
+# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x1000 %t -o %t2
+# RUN: llvm-readobj --sections -l %t2 | FileCheck --check-prefix=CHECK-MAX %s
+
+# CHECK-MAX: Sections [
+# CHECK-MAX-NEXT: Section {
+# CHECK-MAX-NEXT: Index: 0
+# CHECK-MAX-NEXT: Name: (0)
+# CHECK-MAX-NEXT: Type: SHT_NULL (0x0)
+# CHECK-MAX-NEXT: Flags [ (0x0)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Address: 0x0
+# CHECK-MAX-NEXT: Offset: 0x0
+# CHECK-MAX-NEXT: Size: 0
+# CHECK-MAX-NEXT: Link: 0
+# CHECK-MAX-NEXT: Info: 0
+# CHECK-MAX-NEXT: AddressAlignment: 0
+# CHECK-MAX-NEXT: EntrySize: 0
+# CHECK-MAX-NEXT: }
+# CHECK-MAX-NEXT: Section {
+# CHECK-MAX-NEXT: Index: 1
+# CHECK-MAX-NEXT: Name: .text (1)
+# CHECK-MAX-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-MAX-NEXT: Flags [ (0x6)
+# CHECK-MAX-NEXT: SHF_ALLOC (0x2)
+# CHECK-MAX-NEXT: SHF_EXECINSTR (0x4)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Address: 0x210000
+# CHECK-MAX-NEXT: Offset: 0x10000
+# CHECK-MAX-NEXT: Size: 1
+# CHECK-MAX-NEXT: Link: 0
+# CHECK-MAX-NEXT: Info: 0
+# CHECK-MAX-NEXT: AddressAlignment: 4
+# CHECK-MAX-NEXT: EntrySize: 0
+# CHECK-MAX-NEXT: }
+# CHECK-MAX-NEXT: Section {
+# CHECK-MAX-NEXT: Index: 2
+# CHECK-MAX-NEXT: Name: .comment (7)
+# CHECK-MAX-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-MAX-NEXT: Flags [ (0x30)
+# CHECK-MAX-NEXT: SHF_MERGE (0x10)
+# CHECK-MAX-NEXT: SHF_STRINGS (0x20)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Address: 0x0
+# CHECK-MAX-NEXT: Offset: 0x11000
+# CHECK-MAX-NEXT: Size: 8
+# CHECK-MAX-NEXT: Link: 0
+# CHECK-MAX-NEXT: Info: 0
+# CHECK-MAX-NEXT: AddressAlignment: 1
+# CHECK-MAX-NEXT: EntrySize: 1
+
+# CHECK-MAX: ProgramHeaders [
+# CHECK-MAX-NEXT: ProgramHeader {
+# CHECK-MAX-NEXT: Type: PT_PHDR (0x6)
+# CHECK-MAX-NEXT: Offset: 0x40
+# CHECK-MAX-NEXT: VirtualAddress: 0x200040
+# CHECK-MAX-NEXT: PhysicalAddress: 0x200040
+# CHECK-MAX-NEXT: FileSize: 224
+# CHECK-MAX-NEXT: MemSize: 224
+# CHECK-MAX-NEXT: Flags [ (0x4)
+# CHECK-MAX-NEXT: PF_R (0x4)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Alignment: 8
+# CHECK-MAX-NEXT: }
+# CHECK-MAX-NEXT: ProgramHeader {
+# CHECK-MAX-NEXT: Type: PT_LOAD (0x1)
+# CHECK-MAX-NEXT: Offset: 0x0
+# CHECK-MAX-NEXT: VirtualAddress: 0x200000
+# CHECK-MAX-NEXT: PhysicalAddress: 0x200000
+# CHECK-MAX-NEXT: FileSize: 288
+# CHECK-MAX-NEXT: MemSize: 288
+# CHECK-MAX-NEXT: Flags [ (0x4)
+# CHECK-MAX-NEXT: PF_R (0x4)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Alignment: 65536
+# CHECK-MAX-NEXT: }
+# CHECK-MAX-NEXT: ProgramHeader {
+# CHECK-MAX-NEXT: Type: PT_LOAD (0x1)
+# CHECK-MAX-NEXT: Offset: 0x10000
+# CHECK-MAX-NEXT: VirtualAddress: 0x210000
+# CHECK-MAX-NEXT: PhysicalAddress: 0x210000
+# CHECK-MAX-NEXT: FileSize: 4096
+# CHECK-MAX-NEXT: MemSize: 4096
+# CHECK-MAX-NEXT: Flags [ (0x5)
+# CHECK-MAX-NEXT: PF_R (0x4)
+# CHECK-MAX-NEXT: PF_X (0x1)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Alignment: 65536
+# CHECK-MAX-NEXT: }
+# CHECK-MAX-NEXT: ProgramHeader {
+# CHECK-MAX-NEXT: Type: PT_GNU_STACK (0x6474E551)
+# CHECK-MAX-NEXT: Offset: 0x0
+# CHECK-MAX-NEXT: VirtualAddress: 0x0
+# CHECK-MAX-NEXT: PhysicalAddress: 0x0
+# CHECK-MAX-NEXT: FileSize: 0
+# CHECK-MAX-NEXT: MemSize: 0
+# CHECK-MAX-NEXT: Flags [ (0x6)
+# CHECK-MAX-NEXT: PF_R (0x4)
+# CHECK-MAX-NEXT: PF_W (0x2)
+# CHECK-MAX-NEXT: ]
+# CHECK-MAX-NEXT: Alignment: 0
+
+# Increase common-page-size to max-page-size. Expect to see a larger offset
+# of the first Section after the executable loadable segment due to the higher
+# alignment requirement.
+
+# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x10000 %t -o %t3
+# RUN: llvm-readobj --sections -l %t3 | FileCheck --check-prefix=CHECK-COMMON %s
+
+# Check that we truncate common-page-size to max-page-size
+
+# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x100000 %t -o %t4
+# RUN: llvm-readobj --sections -l %t4 | FileCheck --check-prefix=CHECK-COMMON %s
+
+# CHECK-COMMON: Sections [
+# CHECK-COMMON-NEXT: Section {
+# CHECK-COMMON-NEXT: Index: 0
+# CHECK-COMMON-NEXT: Name: (0)
+# CHECK-COMMON-NEXT: Type: SHT_NULL (0x0)
+# CHECK-COMMON-NEXT: Flags [ (0x0)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Address: 0x0
+# CHECK-COMMON-NEXT: Offset: 0x0
+# CHECK-COMMON-NEXT: Size: 0
+# CHECK-COMMON-NEXT: Link: 0
+# CHECK-COMMON-NEXT: Info: 0
+# CHECK-COMMON-NEXT: AddressAlignment: 0
+# CHECK-COMMON-NEXT: EntrySize: 0
+# CHECK-COMMON-NEXT: }
+# CHECK-COMMON-NEXT: Section {
+# CHECK-COMMON-NEXT: Index: 1
+# CHECK-COMMON-NEXT: Name: .text (1)
+# CHECK-COMMON-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-COMMON-NEXT: Flags [ (0x6)
+# CHECK-COMMON-NEXT: SHF_ALLOC (0x2)
+# CHECK-COMMON-NEXT: SHF_EXECINSTR (0x4)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Address: 0x210000
+# CHECK-COMMON-NEXT: Offset: 0x10000
+# CHECK-COMMON-NEXT: Size: 1
+# CHECK-COMMON-NEXT: Link: 0
+# CHECK-COMMON-NEXT: Info: 0
+# CHECK-COMMON-NEXT: AddressAlignment: 4
+# CHECK-COMMON-NEXT: EntrySize: 0
+# CHECK-COMMON-NEXT: }
+# CHECK-COMMON-NEXT: Section {
+# CHECK-COMMON-NEXT: Index: 2
+# CHECK-COMMON-NEXT: Name: .comment (7)
+# CHECK-COMMON-NEXT: Type: SHT_PROGBITS (0x1)
+# CHECK-COMMON-NEXT: Flags [ (0x30)
+# CHECK-COMMON-NEXT: SHF_MERGE (0x10)
+# CHECK-COMMON-NEXT: SHF_STRINGS (0x20)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Address: 0x0
+# CHECK-COMMON-NEXT: Offset: 0x20000
+# CHECK-COMMON-NEXT: Size: 8
+# CHECK-COMMON-NEXT: Link: 0
+# CHECK-COMMON-NEXT: Info: 0
+# CHECK-COMMON-NEXT: AddressAlignment: 1
+# CHECK-COMMON-NEXT: EntrySize: 1
+
+# CHECK-COMMON: ProgramHeaders [
+# CHECK-COMMON-NEXT: ProgramHeader {
+# CHECK-COMMON-NEXT: Type: PT_PHDR (0x6)
+# CHECK-COMMON-NEXT: Offset: 0x40
+# CHECK-COMMON-NEXT: VirtualAddress: 0x200040
+# CHECK-COMMON-NEXT: PhysicalAddress: 0x200040
+# CHECK-COMMON-NEXT: FileSize: 224
+# CHECK-COMMON-NEXT: MemSize: 224
+# CHECK-COMMON-NEXT: Flags [ (0x4)
+# CHECK-COMMON-NEXT: PF_R (0x4)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Alignment: 8
+# CHECK-COMMON-NEXT: }
+# CHECK-COMMON-NEXT: ProgramHeader {
+# CHECK-COMMON-NEXT: Type: PT_LOAD (0x1)
+# CHECK-COMMON-NEXT: Offset: 0x0
+# CHECK-COMMON-NEXT: VirtualAddress: 0x200000
+# CHECK-COMMON-NEXT: PhysicalAddress: 0x200000
+# CHECK-COMMON-NEXT: FileSize: 288
+# CHECK-COMMON-NEXT: MemSize: 288
+# CHECK-COMMON-NEXT: Flags [ (0x4)
+# CHECK-COMMON-NEXT: PF_R (0x4)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Alignment: 65536
+# CHECK-COMMON-NEXT: }
+# CHECK-COMMON-NEXT: ProgramHeader {
+# CHECK-COMMON-NEXT: Type: PT_LOAD (0x1)
+# CHECK-COMMON-NEXT: Offset: 0x10000
+# CHECK-COMMON-NEXT: VirtualAddress: 0x210000
+# CHECK-COMMON-NEXT: PhysicalAddress: 0x210000
+# CHECK-COMMON-NEXT: FileSize: 65536
+# CHECK-COMMON-NEXT: MemSize: 65536
+# CHECK-COMMON-NEXT: Flags [ (0x5)
+# CHECK-COMMON-NEXT: PF_R (0x4)
+# CHECK-COMMON-NEXT: PF_X (0x1)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Alignment: 65536
+# CHECK-COMMON-NEXT: }
+# CHECK-COMMON-NEXT: ProgramHeader {
+# CHECK-COMMON-NEXT: Type: PT_GNU_STACK (0x6474E551)
+# CHECK-COMMON-NEXT: Offset: 0x0
+# CHECK-COMMON-NEXT: VirtualAddress: 0x0
+# CHECK-COMMON-NEXT: PhysicalAddress: 0x0
+# CHECK-COMMON-NEXT: FileSize: 0
+# CHECK-COMMON-NEXT: MemSize: 0
+# CHECK-COMMON-NEXT: Flags [ (0x6)
+# CHECK-COMMON-NEXT: PF_R (0x4)
+# CHECK-COMMON-NEXT: PF_W (0x2)
+# CHECK-COMMON-NEXT: ]
+# CHECK-COMMON-NEXT: Alignment: 0
diff --git a/lld/test/ELF/linkerscript/nmagic-alignment.test b/lld/test/ELF/linkerscript/nmagic-alignment.test
new file mode 100644
index 00000000000..9835004e234
--- /dev/null
+++ b/lld/test/ELF/linkerscript/nmagic-alignment.test
@@ -0,0 +1,85 @@
+# REQUIRES: x86
+
+# Test that mimics a use case of -n to produce a kernel mapped shared-object
+# in a non paged context. We specifically want to test:
+# - We can allocate the headers into the first program header (via PHDRS)
+# typically -n does not allocate headers.
+# - The alignment of the .text section is not page aligned.
+
+# RUN: echo ".text; .globl foo; foo: nop" > %t.s
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.s -o %t.o
+# RUN: ld.lld %t.o -o %t.so --shared --hash-style=sysv --script %s
+# RUN: llvm-readobj --program-headers %t.so | FileCheck %s
+# RUN: ld.lld %t.o -o %t2.so --shared --hash-style=sysv -n --script %s
+# RUN: llvm-readobj --program-headers %t2.so | FileCheck %s --check-prefix=CHECK-N
+
+SECTIONS {
+ . = 0x0 + SIZEOF_HEADERS;
+ .hash : { *(.hash) } :text
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4);
+ .text : { *(.text*) }
+ .dynamic : { *(.dynamic) } :text :dynamic
+}
+
+PHDRS {
+ text PT_LOAD FLAGS(5) FILEHDR PHDRS;
+ dynamic PT_DYNAMIC FLAGS(4);
+}
+
+# CHECK: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize:
+# CHECK-NEXT: MemSize:
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_X
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 4096
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_DYNAMIC
+# CHECK-NEXT: Offset: 0x108
+# CHECK-NEXT: VirtualAddress: 0x108
+# CHECK-NEXT: PhysicalAddress: 0x108
+# CHECK-NEXT: FileSize:
+# CHECK-NEXT: MemSize:
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# CHECK-N: ProgramHeaders [
+# CHECK-N-NEXT: ProgramHeader {
+# CHECK-N-NEXT: Type: PT_LOAD
+# CHECK-N-NEXT: Offset: 0x0
+# CHECK-N-NEXT: VirtualAddress: 0x0
+# CHECK-N-NEXT: PhysicalAddress: 0x0
+# CHECK-N-NEXT: FileSize: 360
+# CHECK-N-NEXT: MemSize: 360
+# CHECK-N-NEXT: Flags [
+# CHECK-N-NEXT: PF_R
+# CHECK-N-NEXT: PF_X
+# CHECK-N-NEXT: ]
+# CHECK-N-NEXT: Alignment: 8
+# CHECK-N-NEXT: }
+# CHECK-N-NEXT: ProgramHeader {
+# CHECK-N-NEXT: Type: PT_DYNAMIC
+# CHECK-N-NEXT: Offset: 0x108
+# CHECK-N-NEXT: VirtualAddress: 0x108
+# CHECK-N-NEXT: PhysicalAddress: 0x108
+# CHECK-N-NEXT: FileSize:
+# CHECK-N-NEXT: MemSize:
+# CHECK-N-NEXT: Flags [
+# CHECK-N-NEXT: PF_R
+# CHECK-N-NEXT: ]
+# CHECK-N-NEXT: Alignment: 8
+# CHECK-N-NEXT: }
+# CHECK-N-NEXT: ]
diff --git a/lld/test/ELF/magic-page-combo-warn.s b/lld/test/ELF/magic-page-combo-warn.s
new file mode 100644
index 00000000000..50f328647d9
--- /dev/null
+++ b/lld/test/ELF/magic-page-combo-warn.s
@@ -0,0 +1,86 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# Test that we warn when a page size is set and paging is disabled by -n or -N.
+
+# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 -N %t -o %t2 2>&1 | FileCheck --check-prefix=WARN %s
+# RUN: llvm-readobj --program-headers %t2 | FileCheck --check-prefix=OMAGIC %s
+# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 --omagic %t -o %t2 2>&1 | FileCheck --check-prefix=WARN %s
+# RUN: llvm-readobj --program-headers %t2 | FileCheck --check-prefix=OMAGIC %s
+
+# WARN: ld.lld: warning: -z max-page-size set, but paging disabled by omagic or nmagic
+# WARN-NEXT: ld.lld: warning: -z common-page-size set, but paging disabled by omagic or nmagic
+
+# OMAGIC: ProgramHeader {
+# OMAGIC: Type: PT_LOAD
+# OMAGIC-NEXT: Offset: 0xE8
+# OMAGIC-NEXT: VirtualAddress:
+# OMAGIC-NEXT: PhysicalAddress:
+# OMAGIC-NEXT: FileSize:
+# OMAGIC-NEXT: MemSize:
+# OMAGIC-NEXT: Flags [
+# OMAGIC-NEXT: PF_R
+# OMAGIC-NEXT: PF_W
+# OMAGIC-NEXT: PF_X
+# OMAGIC-NEXT: ]
+# OMAGIC-NEXT: Alignment: 8
+# OMAGIC-NEXT: }
+# OMAGIC-NEXT: ProgramHeader {
+# OMAGIC-NEXT: Type: PT_GNU_STACK
+
+# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 -n %t -o %t3 2>&1 | FileCheck --check-prefix=WARN %s
+# RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=NMAGIC %s
+# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 --nmagic %t -o %t3 2>&1 | FileCheck --check-prefix=WARN %s
+# RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=NMAGIC %s
+
+# NMAGIC: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD
+# NMAGIC-NEXT: Offset: 0x158
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 1
+# NMAGIC-NEXT: MemSize: 1
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 8
+# NMAGIC-NEXT: }
+# NMAGIC-NEXT: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD
+# NMAGIC-NEXT: Offset: 0x15C
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 2
+# NMAGIC-NEXT: MemSize: 2
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: PF_X
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 4
+# NMAGIC-NEXT: }
+# NMAGIC-NEXT: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD (0x1)
+# NMAGIC-NEXT: Offset: 0x15E
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 1
+# NMAGIC-NEXT: MemSize: 1
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: PF_W
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 1
+# NMAGIC-NEXT: }
+
+.global _start
+_start:
+ nop
+
+.section .ro,"a"
+nop
+
+.section .rw,"aw"
+nop
+
+.section .rx,"ax"
+nop
diff --git a/lld/test/ELF/relro-omagic.s b/lld/test/ELF/relro-omagic.s
index 3f6b42557c4..1d4909c85c3 100644
--- a/lld/test/ELF/relro-omagic.s
+++ b/lld/test/ELF/relro-omagic.s
@@ -2,7 +2,7 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so
-# RUN: ld.lld --hash-style=sysv -N %t.o %t2.so -o %t
+# RUN: ld.lld --hash-style=sysv -N %t.o -Bdynamic %t2.so -o %t
# RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s
# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s
diff --git a/lld/test/ELF/segments.s b/lld/test/ELF/segments.s
index 4648ba97a85..65d2f6e7060 100644
--- a/lld/test/ELF/segments.s
+++ b/lld/test/ELF/segments.s
@@ -84,7 +84,7 @@
# OMAGIC: ProgramHeader {
# OMAGIC: Type: PT_LOAD
-# OMAGIC-NEXT: Offset: 0x0
+# OMAGIC-NEXT: Offset: 0xE8
# OMAGIC-NEXT: VirtualAddress:
# OMAGIC-NEXT: PhysicalAddress:
# OMAGIC-NEXT: FileSize:
@@ -94,11 +94,55 @@
# OMAGIC-NEXT: PF_W
# OMAGIC-NEXT: PF_X
# OMAGIC-NEXT: ]
-# OMAGIC-NEXT: Alignment: 4096
+# OMAGIC-NEXT: Alignment: 8
# OMAGIC-NEXT: }
# OMAGIC-NEXT: ProgramHeader {
# OMAGIC-NEXT: Type: PT_GNU_STACK
+# RUN: ld.lld -n %t -o %t4
+# RUN: llvm-readobj --program-headers %t4 | FileCheck --check-prefix=NMAGIC %s
+# RUN: ld.lld --nmagic %t -o %t4
+# RUN: llvm-readobj --program-headers %t4 | FileCheck --check-prefix=NMAGIC %s
+
+# NMAGIC: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD
+# NMAGIC-NEXT: Offset: 0x158
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 1
+# NMAGIC-NEXT: MemSize: 1
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 8
+# NMAGIC-NEXT: }
+# NMAGIC-NEXT: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD
+# NMAGIC-NEXT: Offset: 0x15C
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 2
+# NMAGIC-NEXT: MemSize: 2
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: PF_X
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 4
+# NMAGIC-NEXT: }
+# NMAGIC-NEXT: ProgramHeader {
+# NMAGIC-NEXT: Type: PT_LOAD (0x1)
+# NMAGIC-NEXT: Offset: 0x15E
+# NMAGIC-NEXT: VirtualAddress:
+# NMAGIC-NEXT: PhysicalAddress:
+# NMAGIC-NEXT: FileSize: 1
+# NMAGIC-NEXT: MemSize: 1
+# NMAGIC-NEXT: Flags [
+# NMAGIC-NEXT: PF_R
+# NMAGIC-NEXT: PF_W
+# NMAGIC-NEXT: ]
+# NMAGIC-NEXT: Alignment: 1
+# NMAGIC-NEXT: }
+
.global _start
_start:
nop
OpenPOWER on IntegriCloud