summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
authorShankar Easwaran <shankare@codeaurora.org>2013-06-16 05:06:28 +0000
committerShankar Easwaran <shankare@codeaurora.org>2013-06-16 05:06:28 +0000
commita42a4738935cd56c2426162f3f744dad1efa20da (patch)
treee8f56bed7be2dd8664e4312b096cf131e19b6006 /lld/lib/ReaderWriter
parent089ee1554c74f12bba8dddcf14cb62feeab6a08b (diff)
downloadbcm5719-llvm-a42a4738935cd56c2426162f3f744dad1efa20da.tar.gz
bcm5719-llvm-a42a4738935cd56c2426162f3f744dad1efa20da.zip
[ELF] add NMAGIC/OMAGIC support
llvm-svn: 184055
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/ELF/Chunk.h15
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h29
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp3
-rw-r--r--lld/lib/ReaderWriter/ELF/HeaderChunks.h21
-rw-r--r--lld/lib/ReaderWriter/ELF/Reader.cpp4
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h12
-rw-r--r--lld/lib/ReaderWriter/ELF/SegmentChunks.h78
7 files changed, 144 insertions, 18 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Chunk.h b/lld/lib/ReaderWriter/ELF/Chunk.h
index 667ca045297..811a20092ff 100644
--- a/lld/lib/ReaderWriter/ELF/Chunk.h
+++ b/lld/lib/ReaderWriter/ELF/Chunk.h
@@ -41,10 +41,19 @@ public:
K_AtomSection, ///< A section containing atoms.
K_SectionHeader ///< Section header
};
+ /// \brief the ContentType of the chunk
+ enum ContentType {
+ CT_Unknown,
+ CT_Header,
+ CT_Code,
+ CT_Data,
+ CT_Note,
+ CT_Tls,
+ };
+
Chunk(StringRef name, Kind kind, const ELFTargetInfo &ti)
: _name(name), _kind(kind), _fsize(0), _msize(0), _align2(0), _order(0),
- _ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) {
- }
+ _ordinal(1), _start(0), _fileoffset(0), _targetInfo(ti) {}
virtual ~Chunk() {}
// Does the chunk occupy disk space
virtual bool occupiesNoDiskSpace() const { return false; }
@@ -70,6 +79,8 @@ public:
// Does the chunk occupy memory during execution ?
uint64_t memSize() const { return _msize; }
void setMemSize(uint64_t msize) { _msize = msize; }
+ // Whats the contentType of the chunk ?
+ virtual int getContentType() const = 0;
// Writer the chunk
virtual void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer) = 0;
// Finalize the chunk before assigning offsets/virtual addresses
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index 96479a581d1..5124c0ee022 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -547,8 +547,9 @@ DefaultLayout<ELFT>::mergeSimiliarSections() {
template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
- // TODO: Do we want to give a chance for the targetHandlers
- // to sort segments in an arbitrary order ?
+ ELFTargetInfo::OutputMagic outputMagic = _targetInfo.getOutputMagic();
+ // TODO: Do we want to give a chance for the targetHandlers
+ // to sort segments in an arbitrary order ?
// sort the sections by their order as defined by the layout
std::stable_sort(_sections.begin(), _sections.end(),
[](Chunk<ELFT> *A, Chunk<ELFT> *B) {
@@ -608,6 +609,14 @@ template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
segment->append(section);
}
+ // If the output magic is set to OutputMagic::NMAGIC or
+ // OutputMagic::OMAGIC, Place the data alongside text in one single
+ // segment
+ if (outputMagic == ELFTargetInfo::OutputMagic::NMAGIC ||
+ outputMagic == ELFTargetInfo::OutputMagic::OMAGIC)
+ lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
+ llvm::ELF::SHF_WRITE;
+
// Use the flags of the merged Section for the segment
const SegmentKey key("PT_LOAD", lookupSectionFlag);
const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
@@ -660,6 +669,7 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
return;
uint64_t virtualAddress = _targetInfo.getBaseAddress();
+ ELFTargetInfo::OutputMagic outputMagic = _targetInfo.getOutputMagic();
// HACK: This is a super dirty hack. The elf header and program header are
// not part of a section, but we need them to be loaded at the base address
@@ -690,9 +700,12 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
// Dont assign offsets for non loadable segments
if (si->segmentType() != llvm::ELF::PT_LOAD)
continue;
- // Align the segment to a page boundary
- fileoffset =
- llvm::RoundUpToAlignment(fileoffset, _targetInfo.getPageSize());
+ // Align the segment to a page boundary only if the output mode is
+ // not OutputMagic::NMAGIC/OutputMagic::OMAGIC
+ if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
+ outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
+ fileoffset =
+ llvm::RoundUpToAlignment(fileoffset, _targetInfo.getPageSize());
si->assignOffsets(fileoffset);
fileoffset = si->fileOffset() + si->fileSize();
}
@@ -707,8 +720,10 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
// first segment to the pagesize
(*si)->assignVirtualAddress(address);
(*si)->setMemSize(address - virtualAddress);
- virtualAddress = llvm::RoundUpToAlignment(address,
- _targetInfo.getPageSize());
+ if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
+ outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
+ virtualAddress =
+ llvm::RoundUpToAlignment(address, _targetInfo.getPageSize());
}
_programHeader->resetProgramHeaders();
}
diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
index 8cd6c2dd7c2..c244f292e74 100644
--- a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
@@ -34,7 +34,8 @@ ELFTargetInfo::ELFTargetInfo(llvm::Triple triple,
_mergeCommonStrings(false),
_runLayoutPass(true),
_useShlibUndefines(false),
- _dynamicLinkerArg(false) {}
+ _dynamicLinkerArg(false),
+ _outputMagic(OutputMagic::DEFAULT) {}
bool ELFTargetInfo::is64Bits() const { return getTriple().isArch64Bit(); }
diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
index 95473d8b4ce..7da52c9e9b2 100644
--- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -51,6 +51,10 @@ public:
return c->Kind() == Chunk<ELFT>::K_Header;
}
+ inline int getContentType() const {
+ return Chunk<ELFT>::CT_Header;
+ }
+
void write(ELFWriter *writer, llvm::FileOutputBuffer &buffer);
virtual void doPreFlight() {}
@@ -162,6 +166,10 @@ public:
return _ph.size();
}
+ inline int getContentType() const {
+ return Chunk<ELFT>::CT_Header;
+ }
+
private:
Elf_Phdr *allocateProgramHeader(bool &allocatedNew) {
Elf_Phdr *phdr;
@@ -185,6 +193,7 @@ private:
template <class ELFT>
bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
bool allocatedNew = false;
+ ELFTargetInfo::OutputMagic outputMagic = this->_targetInfo.getOutputMagic();
// For segments that are not a loadable segment, we
// just pick the values directly from the segment as there
// wouldnt be any slices within that
@@ -213,8 +222,12 @@ bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
phdr->p_filesz = slice->fileSize();
phdr->p_memsz = slice->memSize();
phdr->p_flags = segment->flags();
- phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ?
- segment->pageSize() : slice->align2();
+ if (outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
+ outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
+ phdr->p_align = (phdr->p_type == llvm::ELF::PT_LOAD) ? segment->pageSize()
+ : slice->align2();
+ else
+ phdr->p_align = slice->align2();
}
this->_fsize = fileSize();
this->_msize = this->_fsize;
@@ -266,6 +279,10 @@ public:
return sizeof(Elf_Shdr);
}
+ inline int getContentType() const {
+ return Chunk<ELFT>::CT_Header;
+ }
+
inline uint64_t numHeaders() {
return _sectionInfo.size();
}
diff --git a/lld/lib/ReaderWriter/ELF/Reader.cpp b/lld/lib/ReaderWriter/ELF/Reader.cpp
index 73a61f4678a..0acfe5cf3fd 100644
--- a/lld/lib/ReaderWriter/ELF/Reader.cpp
+++ b/lld/lib/ReaderWriter/ELF/Reader.cpp
@@ -103,6 +103,10 @@ public:
break;
}
case llvm::sys::fs::file_magic::elf_shared_object: {
+ // If the link doesnot allow dynamic libraries to be present during the
+ // link, lets not parse the file and just return
+ if (!_elfTargetInfo.allowLinkWithDynamicLibraries())
+ return llvm::make_error_code(llvm::errc::executable_format_error);
auto f = createELF<DynamicFileCreateELFTraits>(
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
if (!f)
diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h
index 765a2795ad7..42c70b89d1b 100644
--- a/lld/lib/ReaderWriter/ELF/SectionChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h
@@ -78,6 +78,18 @@ public:
uint32_t getInfo() const { return _info; }
Layout::SegmentType getSegmentType() const { return _segmentType; }
+ /// \brief Return the type of content that the section contains
+ virtual int getContentType() const {
+ if (_flags & llvm::ELF::SHF_EXECINSTR)
+ return Chunk<ELFT>::CT_Code;
+ else if (_flags & llvm::ELF::SHF_WRITE)
+ return Chunk<ELFT>::CT_Data;
+ else if (_flags & llvm::ELF::SHF_ALLOC)
+ return Chunk<ELFT>::CT_Code;
+ else
+ return Chunk<ELFT>::CT_Unknown;
+ }
+
/// \brief convert the segment type to a String for diagnostics and printing
/// purposes
StringRef segmentKindToStr() const;
diff --git a/lld/lib/ReaderWriter/ELF/SegmentChunks.h b/lld/lib/ReaderWriter/ELF/SegmentChunks.h
index 453f905242a..05da29a06c5 100644
--- a/lld/lib/ReaderWriter/ELF/SegmentChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SegmentChunks.h
@@ -114,6 +114,7 @@ public:
Segment(const ELFTargetInfo &ti, StringRef name,
const Layout::SegmentType type);
+ /// \brief the Order of segments that appear in the output file
enum SegmentOrder {
permUnknown,
permRWX,
@@ -199,8 +200,31 @@ public:
return _sections.size();
}
+ /// \brief, this function returns the type of segment (PT_*)
inline Layout::SegmentType segmentType() { return _segmentType; }
+ /// \brief return the segment type depending on the content,
+ /// If the content corresponds to Code, this will return Segment::Code
+ /// If the content corresponds to Data, this will return Segment::Data
+ /// If the content corresponds to TLS, this will return Segment::TLS
+ virtual int getContentType() const {
+ int64_t fl = flags();
+ switch (_segmentType) {
+ case llvm::ELF::PT_LOAD: {
+ if (fl && llvm::ELF::PF_X)
+ return Chunk<ELFT>::CT_Code;
+ if (fl && llvm::ELF::PF_W)
+ return Chunk<ELFT>::CT_Data;
+ }
+ case llvm::ELF::PT_TLS:
+ return Chunk<ELFT>::CT_Tls;
+ case llvm::ELF::PT_NOTE:
+ return Chunk<ELFT>::CT_Note;
+ default:
+ return Chunk<ELFT>::CT_Unknown;
+ }
+ }
+
inline int pageSize() const { return this->_targetInfo.getPageSize(); }
inline int rawflags() const { return _atomflags; }
@@ -246,6 +270,19 @@ public:
return _segmentSlices.end();
}
+private:
+
+ /// \brief Check if the chunk needs to be aligned
+ bool needAlign(Chunk<ELFT> *chunk) const {
+ if (chunk->getContentType() == Chunk<ELFT>::CT_Data &&
+ _outputMagic == ELFTargetInfo::OutputMagic::NMAGIC)
+ return true;
+ return false;
+ }
+
+ // Cached value of outputMagic
+ ELFTargetInfo::OutputMagic _outputMagic;
+
protected:
/// \brief Section or some other chunk type.
std::vector<Chunk<ELFT> *> _sections;
@@ -294,6 +331,7 @@ Segment<ELFT>::Segment(const ELFTargetInfo &ti, StringRef name,
_flags(0), _atomflags(0) {
this->_align2 = 0;
this->_fsize = 0;
+ _outputMagic = ti.getOutputMagic();
}
// This function actually is used, but not in all instantiations of Segment.
@@ -316,7 +354,7 @@ static DefinedAtom::ContentPermissions toAtomPerms(uint64_t flags) {
template <class ELFT> void Segment<ELFT>::append(Section<ELFT> *section) {
_sections.push_back(section);
if (_flags < section->getFlags())
- _flags = section->getFlags();
+ _flags |= section->getFlags();
if (_atomflags < toAtomPerms(_flags))
_atomflags = toAtomPerms(_flags);
if (this->_align2 < section->align2())
@@ -385,8 +423,16 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
endSectionIter = _sections.end();
startSection = 0;
bool isFirstSection = true;
+ bool isDataPageAlignedForNMagic = false;
for (auto si = _sections.begin(); si != _sections.end(); ++si) {
if (isFirstSection) {
+ // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
+ // to a page boundary
+ if (!isDataPageAlignedForNMagic && needAlign(*si)) {
+ startOffset = llvm::RoundUpToAlignment(startOffset,
+ this->_targetInfo.getPageSize());
+ isDataPageAlignedForNMagic = true;
+ }
// align the startOffset to the section alignment
uint64_t newOffset =
llvm::RoundUpToAlignment(startOffset, (*si)->align2());
@@ -398,12 +444,21 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
isFirstSection = false;
} else {
uint64_t curOffset = curSliceFileOffset + curSliceSize;
- uint64_t newOffset =
- llvm::RoundUpToAlignment(curOffset, (*si)->align2());
+ // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
+ // to a page boundary
+ if (!isDataPageAlignedForNMagic && needAlign(*si)) {
+ curOffset = llvm::RoundUpToAlignment(curOffset,
+ this->_targetInfo.getPageSize());
+ isDataPageAlignedForNMagic = true;
+ }
+ uint64_t newOffset = llvm::RoundUpToAlignment(curOffset, (*si)->align2());
SegmentSlice<ELFT> *slice = nullptr;
// If the newOffset computed is more than a page away, lets create
// a seperate segment, so that memory is not used up while running
- if ((newOffset - curOffset) > this->_targetInfo.getPageSize()) {
+ if (((newOffset - curOffset) > this->_targetInfo.getPageSize()) &&
+ (_outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
+ _outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)) {
+
// TODO: use std::find here
for (auto s : slices()) {
if (s->startSection() == startSection) {
@@ -464,16 +519,27 @@ template <class ELFT> void Segment<ELFT>::assignOffsets(uint64_t startOffset) {
/// \brief Assign virtual addresses to the slices
template <class ELFT> void Segment<ELFT>::assignVirtualAddress(uint64_t &addr) {
bool isTLSSegment = false;
+ bool isDataPageAlignedForNMagic = false;
uint64_t tlsStartAddr = 0;
for (auto slice : slices()) {
- // Align to a page
- addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize());
+ // Align to a page only if the output is not
+ // OutputMagic::NMAGIC/OutputMagic::OMAGIC
+ if (_outputMagic != ELFTargetInfo::OutputMagic::NMAGIC &&
+ _outputMagic != ELFTargetInfo::OutputMagic::OMAGIC)
+ addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize());
+
// Align to the slice alignment
addr = llvm::RoundUpToAlignment(addr, slice->align2());
bool virtualAddressSet = false;
for (auto section : slice->sections()) {
+ // If the linker outputmagic is set to OutputMagic::NMAGIC, align the Data
+ // to a page boundary
+ if (!isDataPageAlignedForNMagic && needAlign(section)) {
+ addr = llvm::RoundUpToAlignment(addr, this->_targetInfo.getPageSize());
+ isDataPageAlignedForNMagic = true;
+ }
// Align the section address
addr = llvm::RoundUpToAlignment(addr, section->align2());
// Check if the segment is of type TLS
OpenPOWER on IntegriCloud