summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Driver.cpp')
-rw-r--r--lld/ELF/Driver.cpp49
1 files changed, 43 insertions, 6 deletions
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) {
OpenPOWER on IntegriCloud