//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.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 "MipsSectionChunks.h" #include "MipsTargetLayout.h" namespace lld { namespace elf { template MipsReginfoSection::MipsReginfoSection( const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_RegInfo ®info) : Section(ctx, ".reginfo", "MipsReginfo"), _reginfo(reginfo), _targetLayout(targetLayout) { this->setOrder(MipsTargetLayout::ORDER_MIPS_REGINFO); this->_entSize = sizeof(Elf_Mips_RegInfo); this->_fsize = sizeof(Elf_Mips_RegInfo); this->_msize = sizeof(Elf_Mips_RegInfo); this->_alignment = 4; this->_type = SHT_MIPS_REGINFO; this->_flags = SHF_ALLOC; } template void MipsReginfoSection::write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) { uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); std::memcpy(dest, &_reginfo, this->_fsize); } template void MipsReginfoSection::finalize() { _reginfo.ri_gp_value = _targetLayout.getGPAddr(); if (this->_outputSection) this->_outputSection->setType(this->_type); } template class MipsReginfoSection; template class MipsReginfoSection; template class MipsReginfoSection; template class MipsReginfoSection; template MipsOptionsSection::MipsOptionsSection( const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_RegInfo ®info) : Section(ctx, ".MIPS.options", "MipsOptions"), _reginfo(reginfo), _targetLayout(targetLayout) { this->setOrder(MipsTargetLayout::ORDER_MIPS_OPTIONS); this->_entSize = 1; this->_alignment = 8; this->_fsize = llvm::RoundUpToAlignment( sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo), this->_alignment); this->_msize = this->_fsize; this->_type = SHT_MIPS_OPTIONS; this->_flags = SHF_ALLOC | SHF_MIPS_NOSTRIP; _header.kind = ODK_REGINFO; _header.size = this->_fsize; _header.section = 0; _header.info = 0; } template void MipsOptionsSection::write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) { uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); std::memset(dest, 0, this->_fsize); std::memcpy(dest, &_header, sizeof(_header)); std::memcpy(dest + sizeof(_header), &_reginfo, sizeof(_reginfo)); } template void MipsOptionsSection::finalize() { _reginfo.ri_gp_value = _targetLayout.getGPAddr(); if (this->_outputSection) this->_outputSection->setType(this->_type); } template class MipsOptionsSection; template class MipsOptionsSection; template class MipsOptionsSection; template class MipsOptionsSection; template MipsAbiFlagsSection::MipsAbiFlagsSection( const ELFLinkingContext &ctx, MipsTargetLayout &targetLayout, const Elf_Mips_ABIFlags &abiFlags) : Section(ctx, ".MIPS.abiflags", "MipsAbiFlags"), _abiFlags(abiFlags), _targetLayout(targetLayout) { this->setOrder(MipsTargetLayout::ORDER_MIPS_ABI_FLAGS); this->_alignment = 8; this->_fsize = llvm::RoundUpToAlignment(sizeof(_abiFlags), this->_alignment); this->_msize = this->_fsize; this->_entSize = this->_fsize; this->_type = SHT_MIPS_ABIFLAGS; this->_flags = SHF_ALLOC; } template void MipsAbiFlagsSection::write(ELFWriter *writer, TargetLayout &layout, llvm::FileOutputBuffer &buffer) { uint8_t *dest = buffer.getBufferStart() + this->fileOffset(); std::memcpy(dest, &_abiFlags, this->_fsize); } template void MipsAbiFlagsSection::finalize() { if (this->_outputSection) this->_outputSection->setType(this->_type); } template class MipsAbiFlagsSection; template class MipsAbiFlagsSection; template class MipsAbiFlagsSection; template class MipsAbiFlagsSection; template MipsGOTSection::MipsGOTSection(const MipsLinkingContext &ctx) : AtomSection(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_, MipsTargetLayout::ORDER_GOT), _hasNonLocal(false), _localCount(0) { this->_flags |= SHF_MIPS_GPREL; this->_alignment = 4; } template bool MipsGOTSection::compare(const Atom *a, const Atom *b) const { auto ia = _posMap.find(a); auto ib = _posMap.find(b); if (ia != _posMap.end() && ib != _posMap.end()) return ia->second < ib->second; return ia == _posMap.end() && ib != _posMap.end(); } template const AtomLayout *MipsGOTSection::appendAtom(const Atom *atom) { const DefinedAtom *da = dyn_cast(atom); if (atom->name() == "_GLOBAL_OFFSET_TABLE_") return AtomSection::appendAtom(atom); for (const auto &r : *da) { if (r->kindNamespace() != Reference::KindNamespace::ELF) continue; assert(r->kindArch() == Reference::KindArch::Mips); switch (r->kindValue()) { case LLD_R_MIPS_GLOBAL_GOT: _hasNonLocal = true; _posMap[r->target()] = _posMap.size(); return AtomSection::appendAtom(atom); case R_MIPS_TLS_TPREL32: case R_MIPS_TLS_DTPREL32: case R_MIPS_TLS_TPREL64: case R_MIPS_TLS_DTPREL64: _hasNonLocal = true; _tlsMap[r->target()] = _tlsMap.size(); return AtomSection::appendAtom(atom); case R_MIPS_TLS_DTPMOD32: case R_MIPS_TLS_DTPMOD64: _hasNonLocal = true; break; } } if (!_hasNonLocal) ++_localCount; return AtomSection::appendAtom(atom); } template class MipsGOTSection; template class MipsGOTSection; template class MipsGOTSection; template class MipsGOTSection; template MipsPLTSection::MipsPLTSection(const MipsLinkingContext &ctx) : AtomSection(ctx, ".plt", DefinedAtom::typeGOT, DefinedAtom::permR_X, MipsTargetLayout::ORDER_PLT) {} template const AtomLayout *MipsPLTSection::findPLTLayout(const Atom *plt) const { auto it = _pltLayoutMap.find(plt); return it != _pltLayoutMap.end() ? it->second : nullptr; } template const AtomLayout *MipsPLTSection::appendAtom(const Atom *atom) { const auto *layout = AtomSection::appendAtom(atom); const DefinedAtom *da = cast(atom); for (const auto &r : *da) { if (r->kindNamespace() != Reference::KindNamespace::ELF) continue; assert(r->kindArch() == Reference::KindArch::Mips); if (r->kindValue() == LLD_R_MIPS_STO_PLT) { _pltLayoutMap[r->target()] = layout; break; } } return layout; } template class MipsPLTSection; template class MipsPLTSection; template class MipsPLTSection; template class MipsPLTSection; template static bool isMips64EL() { return ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little; } template MipsRelocationTable::MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str, int32_t order) : RelocationTable(ctx, str, order) {} template void MipsRelocationTable::writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom, const Reference &ref) { uint32_t rType = ref.kindValue() | (ref.tag() << 8); r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, isMips64EL()); r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); // The addend is used only by relative relocations if (this->_ctx.isRelativeReloc(ref)) r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend(); else r.r_addend = 0; } template void MipsRelocationTable::writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom, const Reference &ref) { uint32_t rType = ref.kindValue() | (ref.tag() << 8); r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, isMips64EL()); r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom(); } template class MipsRelocationTable; template class MipsRelocationTable; template class MipsRelocationTable; template class MipsRelocationTable; } // elf } // lld