summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp15
-rw-r--r--lld/ELF/Writer.cpp7
-rw-r--r--lld/test/ELF/zstack-size.s20
4 files changed, 41 insertions, 2 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 44902b45853..3f9b776f414 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -121,6 +121,7 @@ struct Configuration {
uint16_t EMachine = llvm::ELF::EM_NONE;
uint64_t EntryAddr = -1;
uint64_t ImageBase;
+ uint64_t ZStackSize = -1;
unsigned LtoJobs;
unsigned LtoO;
unsigned Optimize;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4dbdad7c2bd..a85f30fe7a3 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -256,6 +256,17 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
return false;
}
+static Optional<StringRef>
+getZOptionValue(opt::InputArgList &Args, StringRef Key) {
+ 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);
+ }
+ return None;
+}
+
void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
ELFOptTable Parser;
opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
@@ -395,6 +406,10 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->ZOrigin = hasZOption(Args, "origin");
Config->ZRelro = !hasZOption(Args, "norelro");
+ if (Optional<StringRef> Value = getZOptionValue(Args, "stack-size"))
+ if (Value->getAsInteger(0, Config->ZStackSize))
+ error("invalid stack size: " + *Value);
+
if (Config->Relocatable)
Config->StripAll = false;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e3699818add..ecbbc0a3352 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1005,8 +1005,11 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
// PT_GNU_STACK is a special section to tell the loader to make the
// pages for the stack non-executable.
- if (!Config->ZExecStack)
- AddHdr(PT_GNU_STACK, PF_R | PF_W);
+ if (!Config->ZExecStack) {
+ Phdr &Hdr = *AddHdr(PT_GNU_STACK, PF_R | PF_W);
+ if (Config->ZStackSize != uint64_t(-1))
+ Hdr.H.p_memsz = Config->ZStackSize;
+ }
if (Note.First)
Ret.push_back(std::move(Note));
diff --git a/lld/test/ELF/zstack-size.s b/lld/test/ELF/zstack-size.s
new file mode 100644
index 00000000000..36fbd03766c
--- /dev/null
+++ b/lld/test/ELF/zstack-size.s
@@ -0,0 +1,20 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld -z stack-size=0x1000 %t -o %t1
+# RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+
+.global _start
+_start:
+ nop
+
+# CHECK: Type: PT_GNU_STACK (0x6474E551)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 4096
+# CHECK-NEXT: Flags [ (0x6)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_W (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
OpenPOWER on IntegriCloud