summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h4
-rw-r--r--lld/ELF/Driver.cpp16
-rw-r--r--lld/ELF/Writer.cpp18
-rw-r--r--lld/docs/ld.lld.15
-rw-r--r--lld/test/ELF/gnustack.s5
5 files changed, 40 insertions, 8 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 43d23ef3029..af27f8b13c7 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -64,6 +64,9 @@ enum class ARMVFPArgKind { Default, Base, VFP, ToolChain };
// For -z noseparate-code, -z separate-code and -z separate-loadable-segments.
enum class SeparateSegmentKind { None, Code, Loadable };
+// For -z *stack
+enum class GnuStackKind { None, Exec, NoExec };
+
struct SymbolVersion {
llvm::StringRef name;
bool isExternCpp;
@@ -216,6 +219,7 @@ struct Configuration {
bool zRetpolineplt;
bool zWxneeded;
DiscardPolicy discard;
+ GnuStackKind zGnustack;
ICFLevel icf;
OrphanHandlingPolicy orphanHandling;
SortSectionPolicy sortSection;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index e6c700dcb76..5999fc21533 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -394,6 +394,20 @@ static SeparateSegmentKind getZSeparate(opt::InputArgList &args) {
return SeparateSegmentKind::None;
}
+static GnuStackKind getZGnuStack(opt::InputArgList &args) {
+ for (auto *arg : args.filtered_reverse(OPT_z)) {
+ if (StringRef("execstack") == arg->getValue())
+ return GnuStackKind::Exec;
+ if (StringRef("noexecstack") == arg->getValue())
+ return GnuStackKind::NoExec;
+ if (StringRef("nognustack") == arg->getValue())
+ return GnuStackKind::None;
+ }
+
+ // default
+ return GnuStackKind::NoExec;
+}
+
static bool isKnownZFlag(StringRef s) {
return s == "combreloc" || s == "copyreloc" || s == "defs" ||
s == "execstack" || s == "global" || s == "hazardplt" ||
@@ -402,6 +416,7 @@ static bool isKnownZFlag(StringRef s) {
s == "separate-code" || s == "separate-loadable-segments" ||
s == "nocombreloc" || s == "nocopyreloc" || s == "nodefaultlib" ||
s == "nodelete" || s == "nodlopen" || s == "noexecstack" ||
+ s == "nognustack" ||
s == "nokeep-text-section-prefix" || s == "norelro" ||
s == "noseparate-code" || s == "notext" || s == "now" ||
s == "origin" || s == "relro" || s == "retpolineplt" ||
@@ -951,6 +966,7 @@ static void readConfigs(opt::InputArgList &args) {
config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
config->zExecstack = getZFlag(args, "execstack", "noexecstack", false);
config->zGlobal = hasZOption(args, "global");
+ config->zGnustack = getZGnuStack(args);
config->zHazardplt = hasZOption(args, "hazardplt");
config->zIfuncNoplt = hasZOption(args, "ifunc-noplt");
config->zInitfirst = hasZOption(args, "initfirst");
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 86fdc35fc06..8e253577385 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -2172,14 +2172,16 @@ std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) {
if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))
addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd);
- // PT_GNU_STACK is a special section to tell the loader to make the
- // pages for the stack non-executable. If you really want an executable
- // stack, you can pass -z execstack, but that's not recommended for
- // security reasons.
- unsigned perm = PF_R | PF_W;
- if (config->zExecstack)
- perm |= PF_X;
- addHdr(PT_GNU_STACK, perm)->p_memsz = config->zStackSize;
+ if (config->zGnustack != GnuStackKind::None) {
+ // PT_GNU_STACK is a special section to tell the loader to make the
+ // pages for the stack non-executable. If you really want an executable
+ // stack, you can pass -z execstack, but that's not recommended for
+ // security reasons.
+ unsigned perm = PF_R | PF_W;
+ if (config->zGnustack == GnuStackKind::Exec)
+ perm |= PF_X;
+ addHdr(PT_GNU_STACK, perm)->p_memsz = config->zStackSize;
+ }
// PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
// is expected to perform W^X violations, such as calling mprotect(2) or
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 1746ae9f5fd..5c558a4bcc7 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -655,6 +655,11 @@ Set the
flag to indicate that the object may not be opened by
.Xr dlopen 3 .
.Pp
+.It Cm nognustack
+Do not emit the
+.Dv PT_GNU_STACK
+segment.
+.Pp
.It Cm norelro
Do not indicate that portions of the object shold be mapped read-only
after initial relocation processing.
diff --git a/lld/test/ELF/gnustack.s b/lld/test/ELF/gnustack.s
index 43dde48af3f..828e09328c8 100644
--- a/lld/test/ELF/gnustack.s
+++ b/lld/test/ELF/gnustack.s
@@ -10,6 +10,9 @@
# RUN: ld.lld %t1 -o %t -z noexecstack
# RUN: llvm-readobj --program-headers -S %t | FileCheck --check-prefix=RW %s
+# RUN: ld.lld %t1 -o %t -z nognustack
+# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=NOGNUSTACK %s
+
# RW: Type: PT_GNU_STACK
# RW-NEXT: Offset: 0x0
# RW-NEXT: VirtualAddress: 0x0
@@ -35,5 +38,7 @@
# RWX-NEXT: ]
# RWX-NEXT: Alignment: 0
+# NOGNUSTACK-NOT: Type: PT_GNU_STACK
+
.globl _start
_start:
OpenPOWER on IntegriCloud