summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShankar Easwaran <shankarke@gmail.com>2014-09-08 04:05:52 +0000
committerShankar Easwaran <shankarke@gmail.com>2014-09-08 04:05:52 +0000
commit595e056dcee01f1cb9ccd32ae7a48d515ecde67d (patch)
treec75a11e444d82e1fccb211389787a7e75c80c06e
parent24511fc426d1ed62156f51f1c3e0afcd2fe3f2d4 (diff)
downloadbcm5719-llvm-595e056dcee01f1cb9ccd32ae7a48d515ecde67d.tar.gz
bcm5719-llvm-595e056dcee01f1cb9ccd32ae7a48d515ecde67d.zip
[ELF] Implement --rosegment
By default linker would not create a separate segment to hold read only data. This option overrides that behavior by creating the a separate read only segment for read only data. llvm-svn: 217358
-rw-r--r--lld/include/lld/ReaderWriter/ELFLinkingContext.h8
-rw-r--r--lld/lib/Driver/GnuLdDriver.cpp4
-rw-r--r--lld/lib/Driver/GnuLdOptions.td3
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp4
-rw-r--r--lld/test/elf/Inputs/rodata.c4
-rw-r--r--lld/test/elf/Inputs/rodata.obin0 -> 1568 bytes
-rw-r--r--lld/test/elf/rosegment.test26
8 files changed, 49 insertions, 3 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h
index f551a3cbfb8..32f7a7b7ab4 100644
--- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h
@@ -251,6 +251,13 @@ public:
return true;
}
+ // By default, the linker would merge sections that are read only with
+ // segments that have read and execute permissions. When the user specifies a
+ // flag --rosegment, a separate segment needs to be created.
+ bool mergeRODataToTextSegment() const { return _mergeRODataToTextSegment; }
+
+ void setCreateSeparateROSegment() { _mergeRODataToTextSegment = false; }
+
private:
ELFLinkingContext() LLVM_DELETED_FUNCTION;
@@ -273,6 +280,7 @@ protected:
bool _useShlibUndefines;
bool _dynamicLinkerArg;
bool _noAllowDynamicLibraries;
+ bool _mergeRODataToTextSegment;
OutputMagic _outputMagic;
StringRefVector _inputSearchPaths;
std::unique_ptr<Writer> _writer;
diff --git a/lld/lib/Driver/GnuLdDriver.cpp b/lld/lib/Driver/GnuLdDriver.cpp
index 623a74f8af2..c6dda412921 100644
--- a/lld/lib/Driver/GnuLdDriver.cpp
+++ b/lld/lib/Driver/GnuLdDriver.cpp
@@ -537,6 +537,10 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
ctx->setSharedObjectName(inputArg->getValue());
break;
+ case OPT_rosegment:
+ ctx->setCreateSeparateROSegment();
+ break;
+
default:
break;
} // end switch on option ID
diff --git a/lld/lib/Driver/GnuLdOptions.td b/lld/lib/Driver/GnuLdOptions.td
index d062181bd3c..08adcc4b6ab 100644
--- a/lld/lib/Driver/GnuLdOptions.td
+++ b/lld/lib/Driver/GnuLdOptions.td
@@ -201,6 +201,9 @@ def defsym : Joined<["--"], "defsym=">,
//===----------------------------------------------------------------------===//
def grp_customopts : OptionGroup<"opts">,
HelpText<"CUSTOM OPTIONS">;
+def rosegment: Flag<["--"], "rosegment">,
+ HelpText<"Put read-only non-executable sections in their own segment">,
+ Group<grp_customopts>;
def z : Separate<["-"], "z">,
HelpText<"Linker Option extensions">,
Group<grp_customopts>;
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index beef4a45ea5..4030526b10a 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -634,7 +634,8 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
StringRef segmentName = section->segmentKindToStr();
int64_t lookupSectionFlag = msi->flags();
- if (!(lookupSectionFlag & llvm::ELF::SHF_WRITE))
+ if ((!(lookupSectionFlag & llvm::ELF::SHF_WRITE)) &&
+ (_context.mergeRODataToTextSegment()))
lookupSectionFlag &= ~llvm::ELF::SHF_EXECINSTR;
// Merge string sections into Data segment itself
diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index dbcee258a25..60237928920 100644
--- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -59,8 +59,8 @@ ELFLinkingContext::ELFLinkingContext(
_isStaticExecutable(false), _noInhibitExec(false),
_mergeCommonStrings(false), _runLayoutPass(true),
_useShlibUndefines(true), _dynamicLinkerArg(false),
- _noAllowDynamicLibraries(false), _outputMagic(OutputMagic::DEFAULT),
- _sysrootPath("") {}
+ _noAllowDynamicLibraries(false), _mergeRODataToTextSegment(true),
+ _outputMagic(OutputMagic::DEFAULT), _sysrootPath("") {}
bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); }
diff --git a/lld/test/elf/Inputs/rodata.c b/lld/test/elf/Inputs/rodata.c
new file mode 100644
index 00000000000..b43c9c94589
--- /dev/null
+++ b/lld/test/elf/Inputs/rodata.c
@@ -0,0 +1,4 @@
+const unsigned char *str = "llvm";
+int foo() {
+ return str[0];
+}
diff --git a/lld/test/elf/Inputs/rodata.o b/lld/test/elf/Inputs/rodata.o
new file mode 100644
index 00000000000..f13ddc9bba9
--- /dev/null
+++ b/lld/test/elf/Inputs/rodata.o
Binary files differ
diff --git a/lld/test/elf/rosegment.test b/lld/test/elf/rosegment.test
new file mode 100644
index 00000000000..eab2a904ee7
--- /dev/null
+++ b/lld/test/elf/rosegment.test
@@ -0,0 +1,26 @@
+# Tests that the option --rosegment produces an output file with a separate
+# segment created for read only data.
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/rodata.o -o %t1.elf \
+RUN: --noinhibit-exec
+RUN: lld -flavor gnu -target x86_64 %p/Inputs/rodata.o --rosegment -o %t2.elf \
+RUN: --noinhibit-exec
+RUN: llvm-readobj -program-headers %t1.elf | FileCheck %s -check-prefix=NORO-SEGMENT
+RUN: llvm-readobj -program-headers %t2.elf | FileCheck %s -check-prefix=RO-SEGMENT
+
+#NORO-SEGMENT: Type: PT_PHDR
+#NORO-SEGMENT: Type: PT_INTERP
+#NORO-SEGMENT: Type: PT_LOAD
+#NORO-SEGMENT: Type: PT_LOAD
+#NORO-SEGMENT: Type: PT_GNU_EH_FRAME
+#NORO-SEGMENT: Type: PT_DYNAMIC
+
+#RO-SEGMENT: Type: PT_PHDR
+#RO-SEGMENT: Type: PT_INTERP
+#RO-SEGMENT: Type: PT_LOAD
+#RO-SEGMENT: Type: PT_LOAD
+#RO-SEGMENT: Flags [
+#RO-SEGMENT: PF_R (0x4)
+#RO-SEGMENT: ]
+#RO-SEGMENT: Type: PT_LOAD
+#RO-SEGMENT: Type: PT_GNU_EH_FRAME
+#RO-SEGMENT: Type: PT_DYNAMIC
OpenPOWER on IntegriCloud