[lld] r248215 - Make InputSection able to relocate itself.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 15:01:01 PDT 2015
Author: rafael
Date: Mon Sep 21 17:01:00 2015
New Revision: 248215
URL: http://llvm.org/viewvc/llvm-project?rev=248215&view=rev
Log:
Make InputSection able to relocate itself.
This matches the organization used in COFF.
Modified:
lld/trunk/ELF/Chunks.cpp
lld/trunk/ELF/Chunks.h
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/OutputSections.h
Modified: lld/trunk/ELF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=248215&r1=248214&r2=248215&view=diff
==============================================================================
--- lld/trunk/ELF/Chunks.cpp (original)
+++ lld/trunk/ELF/Chunks.cpp Mon Sep 21 17:01:00 2015
@@ -10,9 +10,13 @@
#include "Chunks.h"
#include "Error.h"
#include "InputFiles.h"
+#include "OutputSections.h"
+
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::ELF;
+using namespace llvm::object;
using namespace lld;
using namespace lld::elf2;
@@ -21,12 +25,134 @@ template <class ELFT>
InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
: File(F), Header(Header) {}
-template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {
+template <class ELFT>
+void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
+ uint32_t Type, uintX_t BaseAddr,
+ uintX_t SymVA) {
+ uintX_t Offset = Rel.r_offset;
+ uint8_t *Location = Buf + Offset;
+ switch (Type) {
+ case R_386_32:
+ support::endian::write32le(Location, SymVA);
+ break;
+ default:
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
+ break;
+ }
+}
+
+template <class ELFT>
+void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,
+ uint32_t Type, uintX_t BaseAddr,
+ uintX_t SymVA) {
+ uintX_t Offset = Rel.r_offset;
+ uint8_t *Location = Buf + Offset;
+ switch (Type) {
+ case R_X86_64_PC32:
+ support::endian::write32le(Location,
+ SymVA + (Rel.r_addend - (BaseAddr + Offset)));
+ break;
+ case R_X86_64_64:
+ support::endian::write64le(Location, SymVA + Rel.r_addend);
+ break;
+ case R_X86_64_32: {
+ case R_X86_64_32S:
+ uint64_t VA = SymVA + Rel.r_addend;
+ if (Type == R_X86_64_32 && !isUInt<32>(VA))
+ error("R_X86_64_32 out of range");
+ else if (!isInt<32>(VA))
+ error("R_X86_64_32S out of range");
+
+ support::endian::write32le(Location, VA);
+ break;
+ }
+ default:
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
+ break;
+ }
+}
+
+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,
+ const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec) {
+ 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 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 {
+ const SymbolBody *Body = File.getSymbolBody(SymIndex);
+ if (!Body)
+ continue;
+ switch (Body->kind()) {
+ case SymbolBody::DefinedRegularKind:
+ SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
+ break;
+ case SymbolBody::DefinedAbsoluteKind:
+ SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;
+ break;
+ case SymbolBody::DefinedCommonKind: {
+ auto *DC = cast<DefinedCommon<ELFT>>(Body);
+ SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;
+ break;
+ }
+ case SymbolBody::SharedKind:
+ if (relocNeedsPLT(Type)) {
+ SymVA = PltSec.getEntryAddr(*Body);
+ Type = R_X86_64_PC32;
+ } else if (relocNeedsGOT(Type)) {
+ SymVA = GotSec.getEntryAddr(*Body);
+ Type = R_X86_64_PC32;
+ } else {
+ continue;
+ }
+ break;
+ case SymbolBody::UndefinedKind:
+ assert(Body->isWeak() && "Undefined symbol reached writer");
+ SymVA = 0;
+ break;
+ case SymbolBody::LazyKind:
+ llvm_unreachable("Lazy symbol reached writer");
+ }
+ }
+
+ relocateOne(Buf, RI, Type, BaseAddr, SymVA);
+ }
+}
+
+template <class ELFT>
+void InputSection<ELFT>::writeTo(uint8_t *Buf, const PltSection<ELFT> &PltSec,
+ const GotSection<ELFT> &GotSec) {
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());
+
+ const ObjectFile<ELFT> *File = getFile();
+ ELFFile<ELFT> *EObj = File->getObj();
+ uint8_t *Base = Buf + getOutputSectionOff();
+ uintX_t BaseAddr = Out->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, PltSec, GotSec);
+ else
+ relocate(Base, EObj->rels(RelSec), *File, BaseAddr, PltSec, GotSec);
+ }
}
template <class ELFT> StringRef InputSection<ELFT>::getSectionName() const {
Modified: lld/trunk/ELF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=248215&r1=248214&r2=248215&view=diff
==============================================================================
--- lld/trunk/ELF/Chunks.h (original)
+++ lld/trunk/ELF/Chunks.h Mon Sep 21 17:01:00 2015
@@ -18,12 +18,15 @@ namespace elf2 {
template <class ELFT> class ObjectFile;
template <class ELFT> class OutputSection;
+template <class ELFT> class PltSection;
+template <class ELFT> class GotSection;
// A chunk corresponding a section of an input file.
template <class ELFT> class InputSection {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
public:
@@ -34,7 +37,8 @@ public:
// Write this chunk to a mmap'ed file, assuming Buf is pointing to
// beginning of the output section.
- void writeTo(uint8_t *Buf);
+ void writeTo(uint8_t *Buf, const PltSection<ELFT> &PltSec,
+ const GotSection<ELFT> &GotSec);
StringRef getSectionName() const;
const Elf_Shdr *getSectionHdr() const { return Header; }
@@ -56,6 +60,18 @@ public:
SmallVector<const Elf_Shdr *, 1> RelocSections;
private:
+ void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
+ uintX_t BaseAddr, uintX_t SymVA);
+ void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
+ uintX_t BaseAddr, uintX_t SymVA);
+
+ template <bool isRela>
+ void relocate(uint8_t *Buf,
+ llvm::iterator_range<
+ const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels,
+ const ObjectFile<ELFT> &File, uintX_t BaseAddr,
+ const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec);
+
// The offset from beginning of the output sections this chunk was assigned
// to. The writer sets a value.
uint64_t OutputSectionOff = 0;
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248215&r1=248214&r2=248215&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Mon Sep 21 17:01:00 2015
@@ -260,53 +260,6 @@ void OutputSection<ELFT>::addChunk(Input
}
template <class ELFT>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
- uint32_t Type, uintX_t BaseAddr,
- uintX_t SymVA) {
- uintX_t Offset = Rel.r_offset;
- uint8_t *Location = Buf + Offset;
- switch (Type) {
- case R_386_32:
- support::endian::write32le(Location, SymVA);
- break;
- default:
- llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
- break;
- }
-}
-
-template <class ELFT>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,
- uint32_t Type, uintX_t BaseAddr,
- uintX_t SymVA) {
- uintX_t Offset = Rel.r_offset;
- uint8_t *Location = Buf + Offset;
- switch (Type) {
- case R_X86_64_PC32:
- support::endian::write32le(Location,
- SymVA + (Rel.r_addend - (BaseAddr + Offset)));
- break;
- case R_X86_64_64:
- support::endian::write64le(Location, SymVA + Rel.r_addend);
- break;
- case R_X86_64_32: {
- case R_X86_64_32S:
- uint64_t VA = SymVA + Rel.r_addend;
- if (Type == R_X86_64_32 && !isUInt<32>(VA))
- error("R_X86_64_32 out of range");
- else if (!isInt<32>(VA))
- error("R_X86_64_32S out of range");
-
- support::endian::write32le(Location, VA);
- break;
- }
- default:
- llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
- break;
- }
-}
-
-template <class ELFT>
typename ELFFile<ELFT>::uintX_t
lld::elf2::getSymVA(const DefinedRegular<ELFT> *DR) {
const InputSection<ELFT> *SC = &DR->Section;
@@ -329,81 +282,9 @@ lld::elf2::getLocalSymVA(const typename
return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
}
-template <class ELFT>
-template <bool isRela>
-void OutputSection<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 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 {
- const SymbolBody *Body = File.getSymbolBody(SymIndex);
- if (!Body)
- continue;
- switch (Body->kind()) {
- case SymbolBody::DefinedRegularKind:
- SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
- break;
- case SymbolBody::DefinedAbsoluteKind:
- SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;
- break;
- case SymbolBody::DefinedCommonKind: {
- auto *DC = cast<DefinedCommon<ELFT>>(Body);
- SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;
- break;
- }
- case SymbolBody::SharedKind:
- if (relocNeedsPLT(Type)) {
- SymVA = PltSec.getEntryAddr(*Body);
- Type = R_X86_64_PC32;
- } else if (relocNeedsGOT(Type)) {
- SymVA = GotSec.getEntryAddr(*Body);
- Type = R_X86_64_PC32;
- } else {
- continue;
- }
- break;
- case SymbolBody::UndefinedKind:
- assert(Body->isWeak() && "Undefined symbol reached writer");
- SymVA = 0;
- break;
- case SymbolBody::LazyKind:
- llvm_unreachable("Lazy symbol reached writer");
- }
- }
-
- relocateOne(Buf, RI, Type, BaseAddr, SymVA);
- }
-}
-
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
- for (InputSection<ELFT> *C : Chunks) {
- C->writeTo(Buf);
- const ObjectFile<ELFT> *File = C->getFile();
- ELFFile<ELFT> *EObj = File->getObj();
- uint8_t *Base = Buf + C->getOutputSectionOff();
- uintX_t BaseAddr = this->getVA() + C->getOutputSectionOff();
- // Iterate over all relocation sections that apply to this section.
- for (const Elf_Shdr *RelSec : C->RelocSections) {
- if (RelSec->sh_type == SHT_RELA)
- relocate(Base, EObj->relas(RelSec), *File, BaseAddr);
- else
- relocate(Base, EObj->rels(RelSec), *File, BaseAddr);
- }
- }
+ for (InputSection<ELFT> *C : Chunks)
+ C->writeTo(Buf, PltSec, GotSec);
}
template <bool Is64Bits>
@@ -582,5 +463,21 @@ getSymVA(const DefinedRegular<ELF64LE> *
template typename ELFFile<ELF64BE>::uintX_t
getSymVA(const DefinedRegular<ELF64BE> *DR);
+
+template typename ELFFile<ELF32LE>::uintX_t
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF32LE>::Elf_Sym *Sym,
+ const ObjectFile<ELF32LE> &File);
+
+template typename ELFFile<ELF32BE>::uintX_t
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF32BE>::Elf_Sym *Sym,
+ const ObjectFile<ELF32BE> &File);
+
+template typename ELFFile<ELF64LE>::uintX_t
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF64LE>::Elf_Sym *Sym,
+ const ObjectFile<ELF64LE> &File);
+
+template typename ELFFile<ELF64BE>::uintX_t
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF64BE>::Elf_Sym *Sym,
+ const ObjectFile<ELF64BE> &File);
}
}
Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=248215&r1=248214&r2=248215&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Mon Sep 21 17:01:00 2015
@@ -245,17 +245,6 @@ public:
void addChunk(InputSection<ELFT> *C);
void writeTo(uint8_t *Buf) override;
- template <bool isRela>
- void relocate(uint8_t *Buf,
- llvm::iterator_range<
- const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels,
- const ObjectFile<ELFT> &File, uintX_t BaseAddr);
-
- void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
- uintX_t BaseAddr, uintX_t SymVA);
- void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
- uintX_t BaseAddr, uintX_t SymVA);
-
private:
std::vector<InputSection<ELFT> *> Chunks;
const PltSection<ELFT> &PltSec;
More information about the llvm-commits
mailing list