diff options
| author | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-07-23 10:34:30 +0000 |
|---|---|---|
| committer | Denis Protivensky <dprotivensky@accesssoftek.com> | 2015-07-23 10:34:30 +0000 |
| commit | cdc1246750163de49a4357444f47aaef9ffc6323 (patch) | |
| tree | 072be3fc08e77a80c1b86af434201405880ef7d7 /lld/lib/ReaderWriter/ELF/SegmentChunks.cpp | |
| parent | ffcc7663a20499497d4650cf0367c836c2bb3b15 (diff) | |
| download | bcm5719-llvm-cdc1246750163de49a4357444f47aaef9ffc6323.tar.gz bcm5719-llvm-cdc1246750163de49a4357444f47aaef9ffc6323.zip | |
[ELF] Apply segments from linker scripts
Put sections to segments according to linker scripts if available.
Rework the code of TargetLayout::assignSectionsToSegments so it operates
on the given list of segments, which can be either read from linker scripts
or constructed as before.
Handle NONE segments defined in linker scripts by putting corresponding sections
to PT_NULL segment.
Consider flags set for segments through linker scripts.
Differential Revision: http://reviews.llvm.org/D10918
llvm-svn: 243002
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/SegmentChunks.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/SegmentChunks.cpp | 36 |
1 files changed, 33 insertions, 3 deletions
diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp b/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp index 60a0b164042..cc6998d7ae4 100644 --- a/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp +++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp @@ -23,7 +23,7 @@ template <class ELFT> Segment<ELFT>::Segment(const ELFLinkingContext &ctx, StringRef name, const typename TargetLayout<ELFT>::SegmentType type) : Chunk<ELFT>(name, Chunk<ELFT>::Kind::ELFSegment, ctx), _segmentType(type), - _flags(0), _atomflags(0) { + _flags(0), _atomflags(0), _segmentFlags(false) { this->_alignment = 1; this->_fsize = 0; _outputMagic = ctx.getOutputMagic(); @@ -46,17 +46,37 @@ static DefinedAtom::ContentPermissions toAtomPerms(uint64_t flags) { } } +// This function actually is used, but not in all instantiations of Segment. +LLVM_ATTRIBUTE_UNUSED +static DefinedAtom::ContentPermissions toAtomPermsSegment(uint64_t flags) { + switch (flags & (llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X)) { + case llvm::ELF::PF_R | llvm::ELF::PF_W | llvm::ELF::PF_X: + return DefinedAtom::permRWX; + case llvm::ELF::PF_R | llvm::ELF::PF_X: + return DefinedAtom::permR_X; + case llvm::ELF::PF_R: + return DefinedAtom::permR__; + case llvm::ELF::PF_R | llvm::ELF::PF_W: + return DefinedAtom::permRW_; + default: + return DefinedAtom::permUnknown; + } +} + template <class ELFT> void Segment<ELFT>::append(Chunk<ELFT> *chunk) { _sections.push_back(chunk); Section<ELFT> *section = dyn_cast<Section<ELFT>>(chunk); if (!section) return; + if (this->_alignment < section->alignment()) + this->_alignment = section->alignment(); + + if (_segmentFlags) + return; if (_flags < section->getFlags()) _flags |= section->getFlags(); if (_atomflags < toAtomPerms(_flags)) _atomflags = toAtomPerms(_flags); - if (this->_alignment < section->alignment()) - this->_alignment = section->alignment(); } template <class ELFT> @@ -389,6 +409,9 @@ void Segment<ELFT>::write(ELFWriter *writer, TargetLayout<ELFT> &layout, } template <class ELFT> int64_t Segment<ELFT>::flags() const { + if (_segmentFlags) + return (int64_t)_flags; + int64_t fl = 0; if (_flags & llvm::ELF::SHF_ALLOC) fl |= llvm::ELF::PF_R; @@ -399,6 +422,13 @@ template <class ELFT> int64_t Segment<ELFT>::flags() const { return fl; } +template <class ELFT> void Segment<ELFT>::setSegmentFlags(uint64_t flags) { + assert(!_segmentFlags && !_flags && "Flags has already been set"); + _segmentFlags = true; + _flags = flags; + _atomflags = toAtomPermsSegment(flags); +} + template <class ELFT> void Segment<ELFT>::finalize() { // We want to finalize the segment values for now only for non loadable // segments, since those values are not set in the Layout |

