summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
diff options
context:
space:
mode:
authorDenis Protivensky <dprotivensky@accesssoftek.com>2015-07-23 10:34:30 +0000
committerDenis Protivensky <dprotivensky@accesssoftek.com>2015-07-23 10:34:30 +0000
commitcdc1246750163de49a4357444f47aaef9ffc6323 (patch)
tree072be3fc08e77a80c1b86af434201405880ef7d7 /lld/lib/ReaderWriter/ELF/SegmentChunks.cpp
parentffcc7663a20499497d4650cf0367c836c2bb3b15 (diff)
downloadbcm5719-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.cpp36
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
OpenPOWER on IntegriCloud