diff options
author | Shankar Easwaran <shankarke@gmail.com> | 2014-09-08 04:05:52 +0000 |
---|---|---|
committer | Shankar Easwaran <shankarke@gmail.com> | 2014-09-08 04:05:52 +0000 |
commit | 595e056dcee01f1cb9ccd32ae7a48d515ecde67d (patch) | |
tree | c75a11e444d82e1fccb211389787a7e75c80c06e | |
parent | 24511fc426d1ed62156f51f1c3e0afcd2fe3f2d4 (diff) | |
download | bcm5719-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.h | 8 | ||||
-rw-r--r-- | lld/lib/Driver/GnuLdDriver.cpp | 4 | ||||
-rw-r--r-- | lld/lib/Driver/GnuLdOptions.td | 3 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/DefaultLayout.h | 3 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp | 4 | ||||
-rw-r--r-- | lld/test/elf/Inputs/rodata.c | 4 | ||||
-rw-r--r-- | lld/test/elf/Inputs/rodata.o | bin | 0 -> 1568 bytes | |||
-rw-r--r-- | lld/test/elf/rosegment.test | 26 |
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 Binary files differnew file mode 100644 index 00000000000..f13ddc9bba9 --- /dev/null +++ b/lld/test/elf/Inputs/rodata.o 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 |