<div dir="ltr">Thanks!<div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Sep 21, 2015 at 3:01 PM, Rafael Espindola via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rafael<br>
Date: Mon Sep 21 17:01:00 2015<br>
New Revision: 248215<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=248215&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=248215&view=rev</a><br>
Log:<br>
Make InputSection able to relocate itself.<br>
<br>
This matches the organization used in COFF.<br>
<br>
Modified:<br>
lld/trunk/ELF/Chunks.cpp<br>
lld/trunk/ELF/Chunks.h<br>
lld/trunk/ELF/OutputSections.cpp<br>
lld/trunk/ELF/OutputSections.h<br>
<br>
Modified: lld/trunk/ELF/Chunks.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=248215&r1=248214&r2=248215&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=248215&r1=248214&r2=248215&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Chunks.cpp (original)<br>
+++ lld/trunk/ELF/Chunks.cpp Mon Sep 21 17:01:00 2015<br>
@@ -10,9 +10,13 @@<br>
#include "Chunks.h"<br>
#include "Error.h"<br>
#include "InputFiles.h"<br>
+#include "OutputSections.h"<br>
+<br>
+#include "llvm/Support/raw_ostream.h"<br>
<br>
using namespace llvm;<br>
using namespace llvm::ELF;<br>
+using namespace llvm::object;<br>
<br>
using namespace lld;<br>
using namespace lld::elf2;<br>
@@ -21,12 +25,134 @@ template <class ELFT><br>
InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)<br>
: File(F), Header(Header) {}<br>
<br>
-template <class ELFT> void InputSection<ELFT>::writeTo(uint8_t *Buf) {<br>
+template <class ELFT><br>
+void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,<br>
+ uint32_t Type, uintX_t BaseAddr,<br>
+ uintX_t SymVA) {<br>
+ uintX_t Offset = Rel.r_offset;<br>
+ uint8_t *Location = Buf + Offset;<br>
+ switch (Type) {<br>
+ case R_386_32:<br>
+ support::endian::write32le(Location, SymVA);<br>
+ break;<br>
+ default:<br>
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';<br>
+ break;<br>
+ }<br>
+}<br>
+<br>
+template <class ELFT><br>
+void InputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,<br>
+ uint32_t Type, uintX_t BaseAddr,<br>
+ uintX_t SymVA) {<br>
+ uintX_t Offset = Rel.r_offset;<br>
+ uint8_t *Location = Buf + Offset;<br>
+ switch (Type) {<br>
+ case R_X86_64_PC32:<br>
+ support::endian::write32le(Location,<br>
+ SymVA + (Rel.r_addend - (BaseAddr + Offset)));<br>
+ break;<br>
+ case R_X86_64_64:<br>
+ support::endian::write64le(Location, SymVA + Rel.r_addend);<br>
+ break;<br>
+ case R_X86_64_32: {<br>
+ case R_X86_64_32S:<br>
+ uint64_t VA = SymVA + Rel.r_addend;<br>
+ if (Type == R_X86_64_32 && !isUInt<32>(VA))<br>
+ error("R_X86_64_32 out of range");<br>
+ else if (!isInt<32>(VA))<br>
+ error("R_X86_64_32S out of range");<br>
+<br>
+ support::endian::write32le(Location, VA);<br>
+ break;<br>
+ }<br>
+ default:<br>
+ llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';<br>
+ break;<br>
+ }<br>
+}<br>
+<br>
+template <class ELFT><br>
+template <bool isRela><br>
+void InputSection<ELFT>::relocate(<br>
+ uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,<br>
+ const ObjectFile<ELFT> &File, uintX_t BaseAddr,<br>
+ const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec) {<br>
+ typedef Elf_Rel_Impl<ELFT, isRela> RelType;<br>
+ bool IsMips64EL = File.getObj()->isMips64EL();<br>
+ for (const RelType &RI : Rels) {<br>
+ uint32_t SymIndex = RI.getSymbol(IsMips64EL);<br>
+ uint32_t Type = RI.getType(IsMips64EL);<br>
+ uintX_t SymVA;<br>
+<br>
+ // Handle relocations for local symbols -- they never get<br>
+ // resolved so we don't allocate a SymbolBody.<br>
+ const Elf_Shdr *SymTab = File.getSymbolTable();<br>
+ if (SymIndex < SymTab->sh_info) {<br>
+ const Elf_Sym *Sym = File.getObj()->getRelocationSymbol(&RI, SymTab);<br>
+ if (!Sym)<br>
+ continue;<br>
+ SymVA = getLocalSymVA(Sym, File);<br>
+ } else {<br>
+ const SymbolBody *Body = File.getSymbolBody(SymIndex);<br>
+ if (!Body)<br>
+ continue;<br>
+ switch (Body->kind()) {<br>
+ case SymbolBody::DefinedRegularKind:<br>
+ SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));<br>
+ break;<br>
+ case SymbolBody::DefinedAbsoluteKind:<br>
+ SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;<br>
+ break;<br>
+ case SymbolBody::DefinedCommonKind: {<br>
+ auto *DC = cast<DefinedCommon<ELFT>>(Body);<br>
+ SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;<br>
+ break;<br>
+ }<br>
+ case SymbolBody::SharedKind:<br>
+ if (relocNeedsPLT(Type)) {<br>
+ SymVA = PltSec.getEntryAddr(*Body);<br>
+ Type = R_X86_64_PC32;<br>
+ } else if (relocNeedsGOT(Type)) {<br>
+ SymVA = GotSec.getEntryAddr(*Body);<br>
+ Type = R_X86_64_PC32;<br>
+ } else {<br>
+ continue;<br>
+ }<br>
+ break;<br>
+ case SymbolBody::UndefinedKind:<br>
+ assert(Body->isWeak() && "Undefined symbol reached writer");<br>
+ SymVA = 0;<br>
+ break;<br>
+ case SymbolBody::LazyKind:<br>
+ llvm_unreachable("Lazy symbol reached writer");<br>
+ }<br>
+ }<br>
+<br>
+ relocateOne(Buf, RI, Type, BaseAddr, SymVA);<br>
+ }<br>
+}<br>
+<br>
+template <class ELFT><br>
+void InputSection<ELFT>::writeTo(uint8_t *Buf, const PltSection<ELFT> &PltSec,<br>
+ const GotSection<ELFT> &GotSec) {<br>
if (Header->sh_type == SHT_NOBITS)<br>
return;<br>
// Copy section contents from source object file to output file.<br>
ArrayRef<uint8_t> Data = *File->getObj()->getSectionContents(Header);<br>
memcpy(Buf + OutputSectionOff, Data.data(), Data.size());<br>
+<br>
+ const ObjectFile<ELFT> *File = getFile();<br>
+ ELFFile<ELFT> *EObj = File->getObj();<br>
+ uint8_t *Base = Buf + getOutputSectionOff();<br>
+ uintX_t BaseAddr = Out->getVA() + getOutputSectionOff();<br>
+ // Iterate over all relocation sections that apply to this section.<br>
+ for (const Elf_Shdr *RelSec : RelocSections) {<br>
+ if (RelSec->sh_type == SHT_RELA)<br>
+ relocate(Base, EObj->relas(RelSec), *File, BaseAddr, PltSec, GotSec);<br>
+ else<br>
+ relocate(Base, EObj->rels(RelSec), *File, BaseAddr, PltSec, GotSec);<br>
+ }<br>
}<br>
<br>
template <class ELFT> StringRef InputSection<ELFT>::getSectionName() const {<br>
<br>
Modified: lld/trunk/ELF/Chunks.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=248215&r1=248214&r2=248215&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=248215&r1=248214&r2=248215&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/Chunks.h (original)<br>
+++ lld/trunk/ELF/Chunks.h Mon Sep 21 17:01:00 2015<br>
@@ -18,12 +18,15 @@ namespace elf2 {<br>
<br>
template <class ELFT> class ObjectFile;<br>
template <class ELFT> class OutputSection;<br>
+template <class ELFT> class PltSection;<br>
+template <class ELFT> class GotSection;<br>
<br>
// A chunk corresponding a section of an input file.<br>
template <class ELFT> class InputSection {<br>
typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;<br>
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela;<br>
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;<br>
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;<br>
typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;<br>
<br>
public:<br>
@@ -34,7 +37,8 @@ public:<br>
<br>
// Write this chunk to a mmap'ed file, assuming Buf is pointing to<br>
// beginning of the output section.<br>
- void writeTo(uint8_t *Buf);<br>
+ void writeTo(uint8_t *Buf, const PltSection<ELFT> &PltSec,<br>
+ const GotSection<ELFT> &GotSec);<br>
<br>
StringRef getSectionName() const;<br>
const Elf_Shdr *getSectionHdr() const { return Header; }<br>
@@ -56,6 +60,18 @@ public:<br>
SmallVector<const Elf_Shdr *, 1> RelocSections;<br>
<br>
private:<br>
+ void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,<br>
+ uintX_t BaseAddr, uintX_t SymVA);<br>
+ void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,<br>
+ uintX_t BaseAddr, uintX_t SymVA);<br>
+<br>
+ template <bool isRela><br>
+ void relocate(uint8_t *Buf,<br>
+ llvm::iterator_range<<br>
+ const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels,<br>
+ const ObjectFile<ELFT> &File, uintX_t BaseAddr,<br>
+ const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec);<br>
+<br>
// The offset from beginning of the output sections this chunk was assigned<br>
// to. The writer sets a value.<br>
uint64_t OutputSectionOff = 0;<br>
<br>
Modified: lld/trunk/ELF/OutputSections.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248215&r1=248214&r2=248215&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248215&r1=248214&r2=248215&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.cpp (original)<br>
+++ lld/trunk/ELF/OutputSections.cpp Mon Sep 21 17:01:00 2015<br>
@@ -260,53 +260,6 @@ void OutputSection<ELFT>::addChunk(Input<br>
}<br>
<br>
template <class ELFT><br>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,<br>
- uint32_t Type, uintX_t BaseAddr,<br>
- uintX_t SymVA) {<br>
- uintX_t Offset = Rel.r_offset;<br>
- uint8_t *Location = Buf + Offset;<br>
- switch (Type) {<br>
- case R_386_32:<br>
- support::endian::write32le(Location, SymVA);<br>
- break;<br>
- default:<br>
- llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';<br>
- break;<br>
- }<br>
-}<br>
-<br>
-template <class ELFT><br>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,<br>
- uint32_t Type, uintX_t BaseAddr,<br>
- uintX_t SymVA) {<br>
- uintX_t Offset = Rel.r_offset;<br>
- uint8_t *Location = Buf + Offset;<br>
- switch (Type) {<br>
- case R_X86_64_PC32:<br>
- support::endian::write32le(Location,<br>
- SymVA + (Rel.r_addend - (BaseAddr + Offset)));<br>
- break;<br>
- case R_X86_64_64:<br>
- support::endian::write64le(Location, SymVA + Rel.r_addend);<br>
- break;<br>
- case R_X86_64_32: {<br>
- case R_X86_64_32S:<br>
- uint64_t VA = SymVA + Rel.r_addend;<br>
- if (Type == R_X86_64_32 && !isUInt<32>(VA))<br>
- error("R_X86_64_32 out of range");<br>
- else if (!isInt<32>(VA))<br>
- error("R_X86_64_32S out of range");<br>
-<br>
- support::endian::write32le(Location, VA);<br>
- break;<br>
- }<br>
- default:<br>
- llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';<br>
- break;<br>
- }<br>
-}<br>
-<br>
-template <class ELFT><br>
typename ELFFile<ELFT>::uintX_t<br>
lld::elf2::getSymVA(const DefinedRegular<ELFT> *DR) {<br>
const InputSection<ELFT> *SC = &DR->Section;<br>
@@ -329,81 +282,9 @@ lld::elf2::getLocalSymVA(const typename<br>
return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;<br>
}<br>
<br>
-template <class ELFT><br>
-template <bool isRela><br>
-void OutputSection<ELFT>::relocate(<br>
- uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,<br>
- const ObjectFile<ELFT> &File, uintX_t BaseAddr) {<br>
- typedef Elf_Rel_Impl<ELFT, isRela> RelType;<br>
- bool IsMips64EL = File.getObj()->isMips64EL();<br>
- for (const RelType &RI : Rels) {<br>
- uint32_t SymIndex = RI.getSymbol(IsMips64EL);<br>
- uint32_t Type = RI.getType(IsMips64EL);<br>
- uintX_t SymVA;<br>
-<br>
- // Handle relocations for local symbols -- they never get<br>
- // resolved so we don't allocate a SymbolBody.<br>
- const Elf_Shdr *SymTab = File.getSymbolTable();<br>
- if (SymIndex < SymTab->sh_info) {<br>
- const Elf_Sym *Sym = File.getObj()->getRelocationSymbol(&RI, SymTab);<br>
- if (!Sym)<br>
- continue;<br>
- SymVA = getLocalSymVA(Sym, File);<br>
- } else {<br>
- const SymbolBody *Body = File.getSymbolBody(SymIndex);<br>
- if (!Body)<br>
- continue;<br>
- switch (Body->kind()) {<br>
- case SymbolBody::DefinedRegularKind:<br>
- SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));<br>
- break;<br>
- case SymbolBody::DefinedAbsoluteKind:<br>
- SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;<br>
- break;<br>
- case SymbolBody::DefinedCommonKind: {<br>
- auto *DC = cast<DefinedCommon<ELFT>>(Body);<br>
- SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;<br>
- break;<br>
- }<br>
- case SymbolBody::SharedKind:<br>
- if (relocNeedsPLT(Type)) {<br>
- SymVA = PltSec.getEntryAddr(*Body);<br>
- Type = R_X86_64_PC32;<br>
- } else if (relocNeedsGOT(Type)) {<br>
- SymVA = GotSec.getEntryAddr(*Body);<br>
- Type = R_X86_64_PC32;<br>
- } else {<br>
- continue;<br>
- }<br>
- break;<br>
- case SymbolBody::UndefinedKind:<br>
- assert(Body->isWeak() && "Undefined symbol reached writer");<br>
- SymVA = 0;<br>
- break;<br>
- case SymbolBody::LazyKind:<br>
- llvm_unreachable("Lazy symbol reached writer");<br>
- }<br>
- }<br>
-<br>
- relocateOne(Buf, RI, Type, BaseAddr, SymVA);<br>
- }<br>
-}<br>
-<br>
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {<br>
- for (InputSection<ELFT> *C : Chunks) {<br>
- C->writeTo(Buf);<br>
- const ObjectFile<ELFT> *File = C->getFile();<br>
- ELFFile<ELFT> *EObj = File->getObj();<br>
- uint8_t *Base = Buf + C->getOutputSectionOff();<br>
- uintX_t BaseAddr = this->getVA() + C->getOutputSectionOff();<br>
- // Iterate over all relocation sections that apply to this section.<br>
- for (const Elf_Shdr *RelSec : C->RelocSections) {<br>
- if (RelSec->sh_type == SHT_RELA)<br>
- relocate(Base, EObj->relas(RelSec), *File, BaseAddr);<br>
- else<br>
- relocate(Base, EObj->rels(RelSec), *File, BaseAddr);<br>
- }<br>
- }<br>
+ for (InputSection<ELFT> *C : Chunks)<br>
+ C->writeTo(Buf, PltSec, GotSec);<br>
}<br>
<br>
template <bool Is64Bits><br>
@@ -582,5 +463,21 @@ getSymVA(const DefinedRegular<ELF64LE> *<br>
<br>
template typename ELFFile<ELF64BE>::uintX_t<br>
getSymVA(const DefinedRegular<ELF64BE> *DR);<br>
+<br>
+template typename ELFFile<ELF32LE>::uintX_t<br>
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF32LE>::Elf_Sym *Sym,<br>
+ const ObjectFile<ELF32LE> &File);<br>
+<br>
+template typename ELFFile<ELF32BE>::uintX_t<br>
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF32BE>::Elf_Sym *Sym,<br>
+ const ObjectFile<ELF32BE> &File);<br>
+<br>
+template typename ELFFile<ELF64LE>::uintX_t<br>
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF64LE>::Elf_Sym *Sym,<br>
+ const ObjectFile<ELF64LE> &File);<br>
+<br>
+template typename ELFFile<ELF64BE>::uintX_t<br>
+lld::elf2::getLocalSymVA(const typename ELFFile<ELF64BE>::Elf_Sym *Sym,<br>
+ const ObjectFile<ELF64BE> &File);<br>
}<br>
}<br>
<br>
Modified: lld/trunk/ELF/OutputSections.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=248215&r1=248214&r2=248215&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=248215&r1=248214&r2=248215&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/ELF/OutputSections.h (original)<br>
+++ lld/trunk/ELF/OutputSections.h Mon Sep 21 17:01:00 2015<br>
@@ -245,17 +245,6 @@ public:<br>
void addChunk(InputSection<ELFT> *C);<br>
void writeTo(uint8_t *Buf) override;<br>
<br>
- template <bool isRela><br>
- void relocate(uint8_t *Buf,<br>
- llvm::iterator_range<<br>
- const llvm::object::Elf_Rel_Impl<ELFT, isRela> *> Rels,<br>
- const ObjectFile<ELFT> &File, uintX_t BaseAddr);<br>
-<br>
- void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,<br>
- uintX_t BaseAddr, uintX_t SymVA);<br>
- void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,<br>
- uintX_t BaseAddr, uintX_t SymVA);<br>
-<br>
private:<br>
std::vector<InputSection<ELFT> *> Chunks;<br>
const PltSection<ELFT> &PltSec;<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>