summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Driver.cpp
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@linaro.org>2019-05-13 16:01:26 +0000
committerPeter Smith <peter.smith@linaro.org>2019-05-13 16:01:26 +0000
commit4e21c770ec328bf03fac6f729602a744b7ef4bca (patch)
treeaecd2d104a296a3c5856cec4dc2a681db7e13a46 /lld/ELF/Driver.cpp
parentd3cedee3c609270335f82400999b4fa6ffb2e441 (diff)
downloadbcm5719-llvm-4e21c770ec328bf03fac6f729602a744b7ef4bca.tar.gz
bcm5719-llvm-4e21c770ec328bf03fac6f729602a744b7ef4bca.zip
[ELF] Full support for -n (--nmagic) and -N (--omagic) via common page
The -n (--nmagic) disables page alignment, and acts as a -Bstatic The -N (--omagic) does what -n does but also marks the executable segment as writeable. As page alignment is disabled headers are not allocated unless explicit in the linker script. To disable page alignment in LLD we choose to set the page sizes to 1 so that any alignment based on the page size does nothing. To set the Target->PageSize to 1 we implement -z common-page-size, which has the side effect of allowing the user to set the value as well. Setting the page alignments to 1 does mean that any use of CONSTANT(MAXPAGESIZE) or CONSTANT(COMMONPAGESIZE) in a linker script will return 1, unlike in ld.bfd. However given that -n and -N disable paging these probably shouldn't be used in a linker script where -n or -N is in use. Differential Revision: https://reviews.llvm.org/D61688 llvm-svn: 360593
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