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
112 lines
4.0 KiB
C++
112 lines
4.0 KiB
C++
//===- lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp ---------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MipsLinkingContext.h"
|
|
#include "MipsTargetLayout.h"
|
|
|
|
namespace lld {
|
|
namespace elf {
|
|
|
|
template <class ELFT>
|
|
MipsTargetLayout<ELFT>::MipsTargetLayout(MipsLinkingContext &ctx,
|
|
MipsAbiInfoHandler<ELFT> &abi)
|
|
: TargetLayout<ELFT>(ctx), _abiInfo(abi),
|
|
_gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
|
|
_pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
|
|
|
|
template <class ELFT>
|
|
AtomSection<ELFT> *MipsTargetLayout<ELFT>::createSection(
|
|
StringRef name, int32_t type, DefinedAtom::ContentPermissions permissions,
|
|
typename TargetLayout<ELFT>::SectionOrder order) {
|
|
if (type == DefinedAtom::typeGOT && name == ".got")
|
|
return _gotSection;
|
|
if (type == DefinedAtom::typeStub && name == ".plt")
|
|
return _pltSection;
|
|
return TargetLayout<ELFT>::createSection(name, type, permissions, order);
|
|
}
|
|
|
|
template <class ELFT>
|
|
typename TargetLayout<ELFT>::SegmentType
|
|
MipsTargetLayout<ELFT>::getSegmentType(const Section<ELFT> *section) const {
|
|
switch (section->order()) {
|
|
case ORDER_MIPS_REGINFO:
|
|
return _abiInfo.hasMipsAbiSection() ? llvm::ELF::PT_LOAD
|
|
: llvm::ELF::PT_MIPS_REGINFO;
|
|
case ORDER_MIPS_OPTIONS:
|
|
return llvm::ELF::PT_LOAD;
|
|
case ORDER_MIPS_ABI_FLAGS:
|
|
return llvm::ELF::PT_MIPS_ABIFLAGS;
|
|
default:
|
|
return TargetLayout<ELFT>::getSegmentType(section);
|
|
}
|
|
}
|
|
|
|
template <class ELFT> uint64_t MipsTargetLayout<ELFT>::getGPAddr() {
|
|
std::call_once(_gpOnce, [this]() {
|
|
if (AtomLayout *a = this->findAbsoluteAtom("_gp"))
|
|
_gpAddr = a->_virtualAddr;
|
|
});
|
|
return _gpAddr;
|
|
}
|
|
|
|
template <class ELFT>
|
|
typename TargetLayout<ELFT>::SectionOrder
|
|
MipsTargetLayout<ELFT>::getSectionOrder(StringRef name, int32_t contentType,
|
|
int32_t contentPermissions) {
|
|
if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
|
|
return TargetLayout<ELFT>::ORDER_TEXT;
|
|
|
|
return TargetLayout<ELFT>::getSectionOrder(name, contentType,
|
|
contentPermissions);
|
|
}
|
|
|
|
template <class ELFT>
|
|
unique_bump_ptr<RelocationTable<ELFT>>
|
|
MipsTargetLayout<ELFT>::createRelocationTable(StringRef name, int32_t order) {
|
|
return unique_bump_ptr<RelocationTable<ELFT>>(new (
|
|
this->_allocator) MipsRelocationTable<ELFT>(this->_ctx, name, order));
|
|
}
|
|
|
|
template <class ELFT>
|
|
uint64_t MipsTargetLayout<ELFT>::getLookupSectionFlags(
|
|
const OutputSection<ELFT> *os) const {
|
|
uint64_t flags = TargetLayout<ELFT>::getLookupSectionFlags(os);
|
|
return flags & ~llvm::ELF::SHF_MIPS_NOSTRIP;
|
|
}
|
|
|
|
template <class ELFT> void MipsTargetLayout<ELFT>::sortSegments() {
|
|
using namespace llvm::ELF;
|
|
TargetLayout<ELFT>::sortSegments();
|
|
// Move PT_MIPS_ABIFLAGS or PT_MIPS_REGINFO right after PT_INTERP.
|
|
auto abiIt =
|
|
std::find_if(this->_segments.begin(), this->_segments.end(),
|
|
[](const Segment<ELFT> *s) {
|
|
auto typ = s->segmentType();
|
|
return typ == PT_MIPS_ABIFLAGS || typ == PT_MIPS_REGINFO;
|
|
});
|
|
if (abiIt == this->_segments.end())
|
|
return;
|
|
Segment<ELFT> *abiSeg = *abiIt;
|
|
this->_segments.erase(abiIt);
|
|
auto outIt = std::find_if(this->_segments.begin(), this->_segments.end(),
|
|
[](const Segment<ELFT> *s) {
|
|
auto typ = s->segmentType();
|
|
return typ != PT_PHDR && typ != PT_INTERP;
|
|
});
|
|
this->_segments.insert(outIt, abiSeg);
|
|
}
|
|
|
|
template class MipsTargetLayout<ELF32BE>;
|
|
template class MipsTargetLayout<ELF32LE>;
|
|
template class MipsTargetLayout<ELF64BE>;
|
|
template class MipsTargetLayout<ELF64LE>;
|
|
|
|
} // end namespace elf
|
|
} // end namespace lld
|