llvm-project/lld/ELF/InputSection.cpp
Rui Ueyama 15ef5e174b ELF2: Make singleton output sections globally accessible.
Previously, output sections that are handled specially by the linker
(e.g. PLT or GOT) were created by Writer and passed to other classes
that need them. The problem was that because these special sections
are required by so many classes, the plumbing work became too much
burden.

This patch is to simply make them accessible from anywhere in the
linker to eliminate the plumbing work once and for all.

http://reviews.llvm.org/D13486

llvm-svn: 249590
2015-10-07 19:18:16 +00:00

105 lines
3.4 KiB
C++

//===- InputSection.cpp ---------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "InputSection.h"
#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
#include "OutputSections.h"
#include "Target.h"
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
using namespace lld;
using namespace lld::elf2;
template <class ELFT>
InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
: File(F), Header(Header) {}
template <class ELFT>
template <bool isRela>
void InputSection<ELFT>::relocate(
uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,
const ObjectFile<ELFT> &File, uintX_t BaseAddr) {
typedef Elf_Rel_Impl<ELFT, isRela> RelType;
bool IsMips64EL = File.getObj().isMips64EL();
for (const RelType &RI : Rels) {
uint32_t SymIndex = RI.getSymbol(IsMips64EL);
uint32_t Type = RI.getType(IsMips64EL);
uintX_t GotVA = Out<ELFT>::Got->getVA();
uintX_t SymVA;
// Handle relocations for local symbols -- they never get
// resolved so we don't allocate a SymbolBody.
const Elf_Shdr *SymTab = File.getSymbolTable();
if (SymIndex < SymTab->sh_info) {
const Elf_Sym *Sym = File.getObj().getRelocationSymbol(&RI, SymTab);
if (!Sym)
continue;
SymVA = getLocalSymVA(Sym, File);
} else {
SymbolBody &Body = *File.getSymbolBody(SymIndex);
SymVA = getSymVA<ELFT>(Body);
if (Target->relocNeedsPlt(Type, Body)) {
SymVA = Out<ELFT>::Plt->getEntryAddr(Body);
Type = Target->getPCRelReloc();
} else if (Target->relocNeedsGot(Type, Body)) {
SymVA = Out<ELFT>::Got->getEntryAddr(Body);
Type = Target->getGotRefReloc();
} else if (Target->relocPointsToGot(Type)) {
SymVA = GotVA;
Type = Target->getPCRelReloc();
} else if (isa<SharedSymbol<ELFT>>(Body)) {
continue;
}
}
Target->relocateOne(Buf, reinterpret_cast<const void *>(&RI), Type,
BaseAddr, SymVA, GotVA);
}
}
template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
if (Header->sh_type == SHT_NOBITS)
return;
// Copy section contents from source object file to output file.
ArrayRef<uint8_t> Data = *File->getObj().getSectionContents(Header);
memcpy(Buf + OutputSectionOff, Data.data(), Data.size());
ObjectFile<ELFT> *File = getFile();
ELFFile<ELFT> &EObj = File->getObj();
uint8_t *Base = Buf + getOutputSectionOff();
uintX_t BaseAddr = OutSec->getVA() + getOutputSectionOff();
// Iterate over all relocation sections that apply to this section.
for (const Elf_Shdr *RelSec : RelocSections) {
if (RelSec->sh_type == SHT_RELA)
relocate(Base, EObj.relas(RelSec), *File, BaseAddr);
else
relocate(Base, EObj.rels(RelSec), *File, BaseAddr);
}
}
template <class ELFT> StringRef InputSection<ELFT>::getSectionName() const {
ErrorOr<StringRef> Name = File->getObj().getSectionName(Header);
error(Name);
return *Name;
}
namespace lld {
namespace elf2 {
template class InputSection<object::ELF32LE>;
template class InputSection<object::ELF32BE>;
template class InputSection<object::ELF64LE>;
template class InputSection<object::ELF64BE>;
}
}