[lld] r248215 - Make InputSection able to relocate itself.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 18:03:44 PDT 2015


Thanks!


On Mon, Sep 21, 2015 at 3:01 PM, Rafael Espindola via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> 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;
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150923/4b8daba4/attachment-0001.html>


More information about the llvm-commits mailing list