[llvm-commits] [llvm] r139314 - in /llvm/trunk: include/llvm/Object/COFF.h include/llvm/Object/ObjectFile.h lib/Object/COFFObjectFile.cpp lib/Object/ELFObjectFile.cpp lib/Object/MachOObjectFile.cpp

Michael Spencer bigcheesegs at gmail.com
Mon Oct 3 17:02:38 PDT 2011


On Thu, Sep 8, 2011 at 1:52 PM, Benjamin Kramer
<benny.kra at googlemail.com> wrote:
> Author: d0k
> Date: Thu Sep  8 15:52:17 2011
> New Revision: 139314
>
> URL: http://llvm.org/viewvc/llvm-project?rev=139314&view=rev
> Log:
> Add support for relocations to ObjectFile.
>
> Patch by Danil Malyshev!
>
> Modified:
>    llvm/trunk/include/llvm/Object/COFF.h
>    llvm/trunk/include/llvm/Object/ObjectFile.h
>    llvm/trunk/lib/Object/COFFObjectFile.cpp
>    llvm/trunk/lib/Object/ELFObjectFile.cpp
>    llvm/trunk/lib/Object/MachOObjectFile.cpp
>
> Modified: llvm/trunk/include/llvm/Object/COFF.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/COFF.h?rev=139314&r1=139313&r2=139314&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Object/COFF.h (original)
> +++ llvm/trunk/include/llvm/Object/COFF.h Thu Sep  8 15:52:17 2011
> @@ -67,6 +67,12 @@
>   support::ulittle32_t Characteristics;
>  };
>
> +struct coff_relocation {
> +  support::ulittle32_t VirtualAddress;
> +  support::ulittle32_t SymbolTableIndex;
> +  support::ulittle16_t Type;
> +};
> +
>  class COFFObjectFile : public ObjectFile {
>  private:
>   const coff_file_header *Header;
> @@ -81,6 +87,7 @@
>
>   const coff_symbol      *toSymb(DataRefImpl Symb) const;
>   const coff_section     *toSec(DataRefImpl Sec) const;
> +  const coff_relocation  *toRel(DataRefImpl Rel) const;
>
>  protected:
>   virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
> @@ -99,12 +106,24 @@
>   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
>                                            bool &Result) const;
>
> +  virtual error_code getRelocationNext(DataRefImpl Rel,
> +                                       RelocationRef &Res) const;
> +  virtual error_code getRelocationAddress(DataRefImpl Rel,
> +                                          uint64_t &Res) const;
> +  virtual error_code getRelocationSymbol(DataRefImpl Rel,
> +                                         SymbolRef &Res) const;
> +  virtual error_code getRelocationType(DataRefImpl Rel,
> +                                       uint32_t &Res) const;
> +  virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                 int64_t &Res) const;
>  public:
>   COFFObjectFile(MemoryBuffer *Object, error_code &ec);
>   virtual symbol_iterator begin_symbols() const;
>   virtual symbol_iterator end_symbols() const;
>   virtual section_iterator begin_sections() const;
>   virtual section_iterator end_sections() const;
> +  virtual relocation_iterator begin_relocations() const;
> +  virtual relocation_iterator end_relocations() const;
>
>   virtual uint8_t getBytesInAddress() const;
>   virtual StringRef getFileFormatName() const;
>
> Modified: llvm/trunk/include/llvm/Object/ObjectFile.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ObjectFile.h?rev=139314&r1=139313&r2=139314&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Object/ObjectFile.h (original)
> +++ llvm/trunk/include/llvm/Object/ObjectFile.h Thu Sep  8 15:52:17 2011
> @@ -39,22 +39,6 @@
>   return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
>  }
>
> -class RelocationRef {
> -  DataRefImpl RelocationPimpl;
> -  const ObjectFile *OwningObject;
> -
> -public:
> -  RelocationRef() : OwningObject(NULL) {
> -    std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl));
> -  }
> -
> -  RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
> -
> -  bool operator==(const RelocationRef &Other) const;
> -
> -  error_code getNext(RelocationRef &Result);
> -};
> -
>  /// SymbolRef - This is a value type class that represents a single symbol in
>  /// the list of symbols in the object file.
>  class SymbolRef {
> @@ -86,6 +70,29 @@
>   error_code isInternal(bool &Result) const;
>  };
>
> +/// RelocationRef - This is a value type class that represents a single
> +/// relocation in the list of relocations in the object file.
> +class RelocationRef {
> +  DataRefImpl RelocationPimpl;
> +  const ObjectFile *OwningObject;
> +
> +public:
> +  RelocationRef() : OwningObject(NULL) {
> +    std::memset(&RelocationPimpl, 0, sizeof(RelocationPimpl));
> +  }
> +
> +  RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner);
> +
> +  bool operator==(const RelocationRef &Other) const;
> +
> +  error_code getNext(RelocationRef &Result) const;
> +
> +  error_code getAddress(uint64_t &Result) const;
> +  error_code getSymbol(SymbolRef &Result) const;
> +  error_code getType(uint32_t &Result) const;
> +  error_code getAdditionalInfo(int64_t &Result) const;
> +};
> +
>  /// SectionRef - This is a value type class that represents a single section in
>  /// the list of sections in the object file.
>  class SectionRef {
> @@ -160,6 +167,19 @@
>                                            bool &Result) const = 0;
>
>
> +  // Same as above for RelocationRef.
> +  friend class RelocationRef;
> +  virtual error_code getRelocationNext(DataRefImpl Rel,
> +                                       RelocationRef &Res) const = 0;
> +  virtual error_code getRelocationAddress(DataRefImpl Rel,
> +                                          uint64_t &Res) const =0;
> +  virtual error_code getRelocationSymbol(DataRefImpl Rel,
> +                                         SymbolRef &Res) const = 0;
> +  virtual error_code getRelocationType(DataRefImpl Rel,
> +                                       uint32_t &Res) const = 0;
> +  virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                 int64_t &Res) const = 0;
> +
>  public:
>   template<class content_type>
>   class content_iterator {
> @@ -196,6 +216,7 @@
>
>   typedef content_iterator<SymbolRef> symbol_iterator;
>   typedef content_iterator<SectionRef> section_iterator;
> +  typedef content_iterator<RelocationRef> relocation_iterator;
>
>   virtual symbol_iterator begin_symbols() const = 0;
>   virtual symbol_iterator end_symbols() const = 0;
> @@ -203,6 +224,9 @@
>   virtual section_iterator begin_sections() const = 0;
>   virtual section_iterator end_sections() const = 0;
>
> +  virtual relocation_iterator begin_relocations() const = 0;
> +  virtual relocation_iterator end_relocations() const = 0;
> +
>   /// @brief The number of bytes used to represent an address in this object
>   ///        file format.
>   virtual uint8_t getBytesInAddress() const = 0;
> @@ -302,6 +326,37 @@
>                                              Result);
>  }
>
> +
> +/// RelocationRef
> +inline RelocationRef::RelocationRef(DataRefImpl RelocationP,
> +                              const ObjectFile *Owner)
> +  : RelocationPimpl(RelocationP)
> +  , OwningObject(Owner) {}
> +
> +inline bool RelocationRef::operator==(const RelocationRef &Other) const {
> +  return RelocationPimpl == Other.RelocationPimpl;
> +}
> +
> +inline error_code RelocationRef::getNext(RelocationRef &Result) const {
> +  return OwningObject->getRelocationNext(RelocationPimpl, Result);
> +}
> +
> +inline error_code RelocationRef::getAddress(uint64_t &Result) const {
> +  return OwningObject->getRelocationAddress(RelocationPimpl, Result);
> +}
> +
> +inline error_code RelocationRef::getSymbol(SymbolRef &Result) const {
> +  return OwningObject->getRelocationSymbol(RelocationPimpl, Result);
> +}
> +
> +inline error_code RelocationRef::getType(uint32_t &Result) const {
> +  return OwningObject->getRelocationType(RelocationPimpl, Result);
> +}
> +
> +inline error_code RelocationRef::getAdditionalInfo(int64_t &Result) const {
> +  return OwningObject->getRelocationAdditionalInfo(RelocationPimpl, Result);
> +}
> +
>  } // end namespace object
>  } // end namespace llvm
>
>
> Modified: llvm/trunk/lib/Object/COFFObjectFile.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/COFFObjectFile.cpp?rev=139314&r1=139313&r2=139314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Object/COFFObjectFile.cpp (original)
> +++ llvm/trunk/lib/Object/COFFObjectFile.cpp Thu Sep  8 15:52:17 2011
> @@ -327,7 +327,7 @@
>   Header = reinterpret_cast<const coff_file_header *>(base() + HeaderStart);
>   if (!checkAddr(Data, ec, uintptr_t(Header), sizeof(coff_file_header)))
>     return;
> -
> +
>   SectionTable =
>     reinterpret_cast<const coff_section *>( base()
>                                           + HeaderStart
> @@ -360,7 +360,7 @@
>     ec = object_error::parse_failed;
>     return;
>   }
> -
> +
>   ec = object_error::success;
>  }
>
> @@ -445,6 +445,77 @@
>   return object_error::success;
>  }
>
> +const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {
> +  assert(Rel.d.b < Header->NumberOfSections && "Section index out of range!");
> +  const coff_section *Sect;
> +  getSection(Rel.d.b, Sect);
> +  assert(Rel.d.a < Sect->NumberOfRelocations && "Relocation index out of range!");
> +  return
> +    reinterpret_cast<const coff_relocation*>(base() +
> +                                             Sect->PointerToRelocations) +
> +                                             Rel.d.a;
> +}
> +error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel,
> +                                             RelocationRef &Res) const {
> +  const coff_section *Sect = NULL;
> +  if (error_code ec = getSection(Rel.d.b, Sect))
> +    return ec;
> +  if (++Rel.d.a >= Sect->NumberOfRelocations) {
> +    Rel.d.a = 0;
> +    while (++Rel.d.b < Header->NumberOfSections) {
> +      const coff_section *Sect;
> +      getSection(Rel.d.b, Sect);
> +      if (Sect->NumberOfRelocations > 0)
> +        break;
> +    }
> +  }
> +  Res = RelocationRef(Rel, this);
> +  return object_error::success;
> +}
> +error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel,
> +                                                uint64_t &Res) const {
> +  const coff_section *Sect;
> +  if (error_code ec = getSection(Rel.d.b, Sect))
> +    return ec;
> +  const coff_relocation* R = toRel(Rel);
> +  Res = reinterpret_cast<uintptr_t>(base() +
> +                                    Sect->PointerToRawData +
> +                                    R->VirtualAddress);
> +  return object_error::success;
> +}
> +error_code COFFObjectFile::getRelocationSymbol(DataRefImpl Rel,
> +                                               SymbolRef &Res) const {
> +  const coff_relocation* R = toRel(Rel);
> +  DataRefImpl Symb;
> +  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex);
> +  Res = SymbolRef(Symb, this);
> +  return object_error::success;
> +}
> +error_code COFFObjectFile::getRelocationType(DataRefImpl Rel,
> +                                             uint32_t &Res) const {
> +  const coff_relocation* R = toRel(Rel);
> +  Res = R->Type;
> +  return object_error::success;
> +}
> +error_code COFFObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                       int64_t &Res) const {
> +  Res = 0;
> +  return object_error::success;
> +}
> +ObjectFile::relocation_iterator COFFObjectFile::begin_relocations() const {
> +  DataRefImpl ret;
> +  ret.d.a = 0;
> +  ret.d.b = 1;
> +  return relocation_iterator(RelocationRef(ret, this));
> +}
> +ObjectFile::relocation_iterator COFFObjectFile::end_relocations() const {
> +  DataRefImpl ret;
> +  ret.d.a = 0;
> +  ret.d.b = Header->NumberOfSections;
> +  return relocation_iterator(RelocationRef(ret, this));
> +}
> +
> +
>  namespace llvm {
>
>   ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) {
>
> Modified: llvm/trunk/lib/Object/ELFObjectFile.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELFObjectFile.cpp?rev=139314&r1=139313&r2=139314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Object/ELFObjectFile.cpp (original)
> +++ llvm/trunk/lib/Object/ELFObjectFile.cpp Thu Sep  8 15:52:17 2011
> @@ -14,6 +14,7 @@
>  #include "llvm/ADT/SmallVector.h"
>  #include "llvm/ADT/StringSwitch.h"
>  #include "llvm/ADT/Triple.h"
> +#include "llvm/ADT/DenseMap.h"
>  #include "llvm/Object/ObjectFile.h"
>  #include "llvm/Support/ELF.h"
>  #include "llvm/Support/Endian.h"
> @@ -176,12 +177,89 @@
>  }
>
>  namespace {
> +template<support::endianness target_endianness, bool is64Bits, bool isRela>
> +struct Elf_Rel_Base;
> +
> +template<support::endianness target_endianness>
> +struct Elf_Rel_Base<target_endianness, false, false> {
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, false)
> +  Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
> +  Elf_Word      r_info;  // Symbol table index and type of relocation to apply
> +};
> +
> +template<support::endianness target_endianness>
> +struct Elf_Rel_Base<target_endianness, true, false> {
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, true)
> +  Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
> +  Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
> +};
> +
> +template<support::endianness target_endianness>
> +struct Elf_Rel_Base<target_endianness, false, true> {
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, false)
> +  Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
> +  Elf_Word      r_info;   // Symbol table index and type of relocation to apply
> +  Elf_Sword     r_addend; // Compute value for relocatable field by adding this
> +};
> +
> +template<support::endianness target_endianness>
> +struct Elf_Rel_Base<target_endianness, true, true> {
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, true)
> +  Elf_Addr      r_offset; // Location (file byte offset, or program virtual addr)
> +  Elf_Xword     r_info;   // Symbol table index and type of relocation to apply
> +  Elf_Sxword    r_addend; // Compute value for relocatable field by adding this.
> +};
> +
> +template<support::endianness target_endianness, bool is64Bits, bool isRela>
> +struct Elf_Rel_Impl;
> +
> +template<support::endianness target_endianness, bool isRela>
> +struct Elf_Rel_Impl<target_endianness, true, isRela>
> +       : Elf_Rel_Base<target_endianness, true, isRela> {
> +  using Elf_Rel_Base<target_endianness, true, isRela>::r_info;
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, true)
> +
> +  // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE,
> +  // and ELF64_R_INFO macros defined in the ELF specification:
> +  uint64_t getSymbol() const { return (r_info >> 32); }
> +  unsigned char getType() const {
> +    return (unsigned char) (r_info & 0xffffffffL);
> +  }
> +  void setSymbol(uint64_t s) { setSymbolAndType(s, getType()); }
> +  void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
> +  void setSymbolAndType(uint64_t s, unsigned char t) {
> +    r_info = (s << 32) + (t&0xffffffffL);
> +  }
> +};
> +
> +template<support::endianness target_endianness, bool isRela>
> +struct Elf_Rel_Impl<target_endianness, false, isRela>
> +       : Elf_Rel_Base<target_endianness, false, isRela> {
> +  using Elf_Rel_Base<target_endianness, false, isRela>::r_info;
> +  LLVM_ELF_IMPORT_TYPES(target_endianness, false)
> +
> +  // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE,
> +  // and ELF32_R_INFO macros defined in the ELF specification:
> +  uint32_t getSymbol() const { return (r_info >> 8); }
> +  unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); }
> +  void setSymbol(uint32_t s) { setSymbolAndType(s, getType()); }
> +  void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); }
> +  void setSymbolAndType(uint32_t s, unsigned char t) {
> +    r_info = (s << 8) + t;
> +  }
> +};
> +
> +}
> +
> +namespace {
>  template<support::endianness target_endianness, bool is64Bits>
>  class ELFObjectFile : public ObjectFile {
>   LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
>
>   typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
>   typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
> +  typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
> +  typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
>
>   struct Elf_Ehdr {
>     unsigned char e_ident[ELF::EI_NIDENT]; // ELF Identification bytes
> @@ -206,18 +284,26 @@
>     unsigned char getDataEncoding() const { return e_ident[ELF::EI_DATA]; }
>   };
>
> -  typedef SmallVector<const Elf_Shdr*, 1> SymbolTableSections_t;
> +  typedef SmallVector<const Elf_Shdr*, 1> Sections_t;
> +  typedef DenseMap<unsigned, unsigned> IndexMap_t;
>
>   const Elf_Ehdr *Header;
>   const Elf_Shdr *SectionHeaderTable;
>   const Elf_Shdr *dot_shstrtab_sec; // Section header string table.
>   const Elf_Shdr *dot_strtab_sec;   // Symbol header string table.
> -  SymbolTableSections_t SymbolTableSections;
> +  Sections_t SymbolTableSections;
> +  IndexMap_t SymbolTableSectionsIndexMap;
> +  Sections_t RelocationTableSections;
>
>   void            validateSymbol(DataRefImpl Symb) const;
> +  bool            isRelocationHasAddend(DataRefImpl Rel) const;
> +  template<typename T>
> +  const T        *getEntry(DataRefImpl Entry, Sections_t Sections) const;
>   const Elf_Sym  *getSymbol(DataRefImpl Symb) const;
>   const Elf_Shdr *getSection(DataRefImpl index) const;
>   const Elf_Shdr *getSection(uint16_t index) const;
> +  const Elf_Rel  *getRel(DataRefImpl Rel) const;
> +  const Elf_Rela *getRela(DataRefImpl Rela) const;
>   const char     *getString(uint16_t section, uint32_t offset) const;
>   const char     *getString(const Elf_Shdr *section, uint32_t offset) const;
>
> @@ -238,12 +324,25 @@
>   virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
>                                            bool &Result) const;
>
> +  virtual error_code getRelocationNext(DataRefImpl Rel,
> +                                       RelocationRef &Res) const;
> +  virtual error_code getRelocationAddress(DataRefImpl Rel,
> +                                          uint64_t &Res) const;
> +  virtual error_code getRelocationSymbol(DataRefImpl Rel,
> +                                         SymbolRef &Res) const;
> +  virtual error_code getRelocationType(DataRefImpl Rel,
> +                                       uint32_t &Res) const;
> +  virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                 int64_t &Res) const;
> +
>  public:
>   ELFObjectFile(MemoryBuffer *Object, error_code &ec);
>   virtual symbol_iterator begin_symbols() const;
>   virtual symbol_iterator end_symbols() const;
>   virtual section_iterator begin_sections() const;
>   virtual section_iterator end_sections() const;
> +  virtual relocation_iterator begin_relocations() const;
> +  virtual relocation_iterator end_relocations() const;
>
>   virtual uint8_t getBytesInAddress() const;
>   virtual StringRef getFileFormatName() const;
> @@ -416,7 +515,8 @@
>       return ec;
>     Result = StringSwitch<char>(name)
>       .StartsWith(".debug", 'N')
> -      .StartsWith(".note", 'n');
> +      .StartsWith(".note", 'n')
> +      .Default('?');
>     return object_error::success;
>   }
>
> @@ -507,6 +607,121 @@
>   return object_error::success;
>  }
>
> +// Relocations
> +template<support::endianness target_endianness, bool is64Bits>
> +error_code ELFObjectFile<target_endianness, is64Bits>
> +                        ::getRelocationNext(DataRefImpl Rel,
> +                                            RelocationRef &Result) const {
> +  const Elf_Shdr *RelocationTableSection = RelocationTableSections[Rel.d.b];
> +
> +  // Check to see if we are at the end of this relocation table.
> +  if (++Rel.d.a >= RelocationTableSection->getEntityCount()) {
> +    // We are at the end. If there are other relocation tables, jump to them.
> +    Rel.d.a = 0;
> +    // Otherwise return the terminator.
> +    if (++Rel.d.b >= SymbolTableSections.size()) {
> +      Rel.d.a = std::numeric_limits<uint32_t>::max();
> +      Rel.d.b = std::numeric_limits<uint32_t>::max();
> +    }
> +  }
> +
> +  Result = RelocationRef(Rel, this);
> +  return object_error::success;
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +error_code ELFObjectFile<target_endianness, is64Bits>
> +                        ::getRelocationSymbol(DataRefImpl Rel,
> +                                              SymbolRef &Result) const {
> +  uint32_t symbolIdx;
> +  const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
> +  switch (sec->sh_type) {
> +    default :
> +      report_fatal_error("Invalid section type in Rel!");
> +    case ELF::SHT_REL : {
> +      symbolIdx = getRel(Rel)->getSymbol();
> +      break;
> +    }
> +    case ELF::SHT_RELA : {
> +      symbolIdx = getRela(Rel)->getSymbol();
> +      break;
> +    }
> +  }
> +  DataRefImpl SymbolData;
> +  IndexMap_t::const_iterator it = SymbolTableSectionsIndexMap.find(sec->sh_link);
> +  if (it == SymbolTableSectionsIndexMap.end())
> +    report_fatal_error("Relocation symbol table not found!");
> +  SymbolData.d.a = symbolIdx;
> +  SymbolData.d.b = it->second;
> +  Result = SymbolRef(SymbolData, this);
> +  return object_error::success;
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +error_code ELFObjectFile<target_endianness, is64Bits>
> +                        ::getRelocationAddress(DataRefImpl Rel,
> +                                               uint64_t &Result) const {
> +  uint64_t offset;
> +  const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
> +  switch (sec->sh_type) {
> +    default :
> +      report_fatal_error("Invalid section type in Rel!");
> +    case ELF::SHT_REL : {
> +      offset = getRel(Rel)->r_offset;
> +      break;
> +    }
> +    case ELF::SHT_RELA : {
> +      offset = getRela(Rel)->r_offset;
> +      break;
> +    }
> +  }
> +
> +  const Elf_Shdr *secAddr = getSection(sec->sh_info);
> +  Result = offset + reinterpret_cast<uintptr_t>(base() + secAddr->sh_offset);
> +  return object_error::success;
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +error_code ELFObjectFile<target_endianness, is64Bits>
> +                        ::getRelocationType(DataRefImpl Rel,
> +                                            uint32_t &Result) const {
> +  const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
> +  switch (sec->sh_type) {
> +    default :
> +      report_fatal_error("Invalid section type in Rel!");
> +    case ELF::SHT_REL : {
> +      Result = getRel(Rel)->getType();
> +      break;
> +    }
> +    case ELF::SHT_RELA : {
> +      Result = getRela(Rel)->getType();
> +      break;
> +    }
> +  }
> +  return object_error::success;
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +error_code ELFObjectFile<target_endianness, is64Bits>
> +                        ::getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                      int64_t &Result) const {
> +  const Elf_Shdr *sec = RelocationTableSections[Rel.d.b];
> +  switch (sec->sh_type) {
> +    default :
> +      report_fatal_error("Invalid section type in Rel!");
> +    case ELF::SHT_REL : {
> +      Result = 0;
> +      return object_error::success;
> +    }
> +    case ELF::SHT_RELA : {
> +      Result = getRela(Rel)->r_addend;
> +      return object_error::success;
> +    }
> +  }
> +}
> +
> +
> +
>  template<support::endianness target_endianness, bool is64Bits>
>  ELFObjectFile<target_endianness, is64Bits>::ELFObjectFile(MemoryBuffer *Object
>                                                           , error_code &ec)
> @@ -529,13 +744,17 @@
>
>
>   // To find the symbol tables we walk the section table to find SHT_STMTAB.
> -  for (const char *i = reinterpret_cast<const char *>(SectionHeaderTable),
> -                  *e = i + Header->e_shnum * Header->e_shentsize;
> -                   i != e; i += Header->e_shentsize) {
> -    const Elf_Shdr *sh = reinterpret_cast<const Elf_Shdr*>(i);
> +  const Elf_Shdr* sh =
> +                    reinterpret_cast<const Elf_Shdr*>(SectionHeaderTable);
> +  for (unsigned i = 0; i < Header->e_shnum; ++i) {
>     if (sh->sh_type == ELF::SHT_SYMTAB) {
> +      SymbolTableSectionsIndexMap[i] = SymbolTableSections.size();
>       SymbolTableSections.push_back(sh);
>     }
> +    if (sh->sh_type == ELF::SHT_REL || sh->sh_type == ELF::SHT_RELA) {
> +      RelocationTableSections.push_back(sh);
> +    }
> +    ++sh;
>   }
>
>   // Get string table sections.
> @@ -615,6 +834,31 @@
>  }
>
>  template<support::endianness target_endianness, bool is64Bits>
> +ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits>
> +                                         ::begin_relocations() const {
> +  DataRefImpl RelData;
> +  memset(&RelData, 0, sizeof(RelData));
> +  if (RelocationTableSections.size() == 0) {
> +    RelData.d.a = std::numeric_limits<uint32_t>::max();
> +    RelData.d.b = std::numeric_limits<uint32_t>::max();
> +  } else {
> +    RelData.d.a = 0;
> +    RelData.d.b = 0;
> +  }
> +  return relocation_iterator(RelocationRef(RelData, this));
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +ObjectFile::relocation_iterator ELFObjectFile<target_endianness, is64Bits>
> +                                         ::end_relocations() const {
> +  DataRefImpl RelData;
> +  memset(&RelData, 0, sizeof(RelData));
> +  RelData.d.a = std::numeric_limits<uint32_t>::max();
> +  RelData.d.b = std::numeric_limits<uint32_t>::max();
> +  return relocation_iterator(RelocationRef(RelData, this));
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
>  uint8_t ELFObjectFile<target_endianness, is64Bits>::getBytesInAddress() const {
>   return is64Bits ? 8 : 4;
>  }
> @@ -629,6 +873,8 @@
>       return "ELF32-i386";
>     case ELF::EM_X86_64:
>       return "ELF32-x86-64";
> +    case ELF::EM_ARM:
> +      return "ELF32-arm";
>     default:
>       return "ELF32-unknown";
>     }
> @@ -654,19 +900,41 @@
>     return Triple::x86;
>   case ELF::EM_X86_64:
>     return Triple::x86_64;
> +  case ELF::EM_ARM:
> +    return Triple::arm;
>   default:
>     return Triple::UnknownArch;
>   }
>  }
>
>  template<support::endianness target_endianness, bool is64Bits>
> -const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
> -ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
> -  const Elf_Shdr *sec = SymbolTableSections[Symb.d.b];
> -  return reinterpret_cast<const Elf_Sym *>(
> +template<typename T>
> +inline const T *
> +ELFObjectFile<target_endianness, is64Bits>::getEntry(DataRefImpl Entry,
> +                                                     Sections_t Sections) const {
> +  const Elf_Shdr *sec = Sections[Entry.d.b];
> +  return reinterpret_cast<const T *>(
>            base()
>            + sec->sh_offset
> -           + (Symb.d.a * sec->sh_entsize));
> +           + (Entry.d.a * sec->sh_entsize));
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Sym *
> +ELFObjectFile<target_endianness, is64Bits>::getSymbol(DataRefImpl Symb) const {
> +  return getEntry<Elf_Sym>(Symb, SymbolTableSections);
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rel *
> +ELFObjectFile<target_endianness, is64Bits>::getRel(DataRefImpl Rel) const {
> +  return getEntry<Elf_Rel>(Rel, RelocationTableSections);
> +}
> +
> +template<support::endianness target_endianness, bool is64Bits>
> +const typename ELFObjectFile<target_endianness, is64Bits>::Elf_Rela *
> +ELFObjectFile<target_endianness, is64Bits>::getRela(DataRefImpl Rela) const {
> +  return getEntry<Elf_Rela>(Rela, RelocationTableSections);
>  }
>
>  template<support::endianness target_endianness, bool is64Bits>
>
> Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=139314&r1=139313&r2=139314&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
> +++ llvm/trunk/lib/Object/MachOObjectFile.cpp Thu Sep  8 15:52:17 2011
> @@ -18,6 +18,7 @@
>  #include "llvm/Object/ObjectFile.h"
>  #include "llvm/Support/MemoryBuffer.h"
>  #include "llvm/Support/MachO.h"
> +#include "llvm/ADT/SmallVector.h"
>
>  #include <cctype>
>  #include <cstring>
> @@ -32,15 +33,14 @@
>
>  class MachOObjectFile : public ObjectFile {
>  public:
> -  MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec)
> -    : ObjectFile(Binary::isMachO, Object, ec),
> -      MachOObj(MOO),
> -      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {}
> +  MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec);
>
>   virtual symbol_iterator begin_symbols() const;
>   virtual symbol_iterator end_symbols() const;
>   virtual section_iterator begin_sections() const;
>   virtual section_iterator end_sections() const;
> +  virtual relocation_iterator begin_relocations() const;
> +  virtual relocation_iterator end_relocations() const;
>
>   virtual uint8_t getBytesInAddress() const;
>   virtual StringRef getFileFormatName() const;
> @@ -63,9 +63,22 @@
>   virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S,
>                                            bool &Result) const;
>
> +  virtual error_code getRelocationNext(DataRefImpl Rel,
> +                                       RelocationRef &Res) const;
> +  virtual error_code getRelocationAddress(DataRefImpl Rel,
> +                                          uint64_t &Res) const;
> +  virtual error_code getRelocationSymbol(DataRefImpl Rel,
> +                                         SymbolRef &Res) const;
> +  virtual error_code getRelocationType(DataRefImpl Rel,
> +                                       uint32_t &Res) const;
> +  virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                 int64_t &Res) const;
>  private:
>   MachOObject *MachOObj;
>   mutable uint32_t RegisteredStringTable;
> +  typedef SmallVector<DataRefImpl, 1> SectionList;
> +  SectionList Sections;
> +
>
>   void moveToNextSection(DataRefImpl &DRI) const;
>   void getSymbolTableEntry(DataRefImpl DRI,
> @@ -76,8 +89,35 @@
>   void getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const;
>   void getSection64(DataRefImpl DRI,
>                     InMemoryStruct<macho::Section64> &Res) const;
> +  void getRelocation(DataRefImpl Rel,
> +                     InMemoryStruct<macho::RelocationEntry> &Res) const;
>  };
>
> +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO,
> +                                 error_code &ec)
> +    : ObjectFile(Binary::isMachO, Object, ec),
> +      MachOObj(MOO),
> +      RegisteredStringTable(std::numeric_limits<uint32_t>::max()) {
> +  DataRefImpl DRI;
> +  DRI.d.a = DRI.d.b = 0;
> +  moveToNextSection(DRI);
> +  uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands;
> +  while (DRI.d.a < LoadCommandCount) {
> +    Sections.push_back(DRI);
> +    uint64_t Addr;
> +    uint64_t Size;
> +    StringRef Name;
> +    getSectionAddress(DRI, Addr);
> +    getSectionSize(DRI, Size);
> +    getSectionName(DRI, Name);
> +    InMemoryStruct<macho::Section> Sect;
> +    getSection(DRI, Sect);
> +    DRI.d.b++;
> +    moveToNextSection(DRI);
> +  }
> +}
> +
> +
>  ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) {
>   error_code ec;
>   std::string Err;
> @@ -414,6 +454,125 @@
>   return section_iterator(SectionRef(DRI, this));
>  }
>
> +/*===-- Relocations -------------------------------------------------------===*/
> +
> +void MachOObjectFile::
> +getRelocation(DataRefImpl Rel,
> +              InMemoryStruct<macho::RelocationEntry> &Res) const {
> +  uint32_t relOffset;
> +  if (MachOObj->is64Bit()) {
> +    InMemoryStruct<macho::Section64> Sect;
> +    getSection64(Sections[Rel.d.b], Sect);
> +    relOffset = Sect->RelocationTableOffset;
> +  } else {
> +    InMemoryStruct<macho::Section> Sect;
> +    getSection(Sections[Rel.d.b], Sect);
> +    relOffset = Sect->RelocationTableOffset;
> +  }
> +  MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res);
> +}
> +error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel,
> +                                              RelocationRef &Res) const {
> +  ++Rel.d.a;
> +  while (Rel.d.b < Sections.size()) {
> +    unsigned relocationCount;
> +    if (MachOObj->is64Bit()) {
> +      InMemoryStruct<macho::Section64> Sect;
> +      getSection64(Sections[Rel.d.b], Sect);
> +      relocationCount = Sect->NumRelocationTableEntries;
> +    } else {
> +      InMemoryStruct<macho::Section> Sect;
> +      getSection(Sections[Rel.d.b], Sect);
> +      relocationCount = Sect->NumRelocationTableEntries;
> +    }
> +    if (Rel.d.a < relocationCount)
> +      break;
> +
> +    Rel.d.a = 0;
> +    ++Rel.d.b;
> +  }
> +  Res = RelocationRef(Rel, this);
> +  return object_error::success;
> +}
> +error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel,
> +                                                 uint64_t &Res) const {
> +  const uint8_t* sectAddress = base();
> +  if (MachOObj->is64Bit()) {
> +    InMemoryStruct<macho::Section64> Sect;
> +    getSection64(Sections[Rel.d.b], Sect);
> +    sectAddress += Sect->Offset;
> +  } else {
> +    InMemoryStruct<macho::Section> Sect;
> +    getSection(Sections[Rel.d.b], Sect);
> +    sectAddress += Sect->Offset;
> +  }
> +  InMemoryStruct<macho::RelocationEntry> RE;
> +  getRelocation(Rel, RE);
> +  Res = reinterpret_cast<uintptr_t>(sectAddress + RE->Word0);
> +  return object_error::success;
> +}
> +error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel,
> +                                                SymbolRef &Res) const {
> +  InMemoryStruct<macho::RelocationEntry> RE;
> +  getRelocation(Rel, RE);
> +  uint32_t SymbolIdx = RE->Word1 & 0xffffff;
> +  bool isExtern = (RE->Word1 >> 27) & 1;
> +
> +  DataRefImpl Sym;
> +  Sym.d.a = Sym.d.b = 0;
> +  moveToNextSymbol(Sym);
> +  uint32_t NumLoadCommands = MachOObj->getHeader().NumLoadCommands;
> +  if (isExtern) {
> +    for (unsigned i = 0; i < SymbolIdx; i++) {
> +      Sym.d.b++;
> +      moveToNextSymbol(Sym);
> +      assert(Sym.d.a < NumLoadCommands &&
> +             "Relocation symbol index out of range!");
> +    }
> +  }
> +  Res = SymbolRef(Sym, this);
> +  return object_error::success;
> +}
> +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel,
> +                                              uint32_t &Res) const {
> +  InMemoryStruct<macho::RelocationEntry> RE;
> +  getRelocation(Rel, RE);
> +  Res = RE->Word1;
> +  return object_error::success;
> +}
> +error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel,
> +                                                        int64_t &Res) const {
> +  InMemoryStruct<macho::RelocationEntry> RE;
> +  getRelocation(Rel, RE);
> +  bool isExtern = (RE->Word1 >> 27) & 1;
> +  Res = 0;
> +  if (!isExtern) {
> +    const uint8_t* sectAddress = base();
> +    if (MachOObj->is64Bit()) {
> +      InMemoryStruct<macho::Section64> Sect;
> +      getSection64(Sections[Rel.d.b], Sect);
> +      sectAddress += Sect->Offset;
> +    } else {
> +      InMemoryStruct<macho::Section> Sect;
> +      getSection(Sections[Rel.d.b], Sect);
> +      sectAddress += Sect->Offset;
> +    }
> +    Res = reinterpret_cast<uintptr_t>(sectAddress);
> +  }
> +  return object_error::success;
> +}
> +ObjectFile::relocation_iterator MachOObjectFile::begin_relocations() const {
> +  DataRefImpl ret;
> +  ret.d.a = ret.d.b = 0;
> +  return relocation_iterator(RelocationRef(ret, this));
> +}
> +ObjectFile::relocation_iterator MachOObjectFile::end_relocations() const {
> +  DataRefImpl ret;
> +  ret.d.a = 0;
> +  ret.d.b = Sections.size();
> +  return relocation_iterator(RelocationRef(ret, this));
> +}
> +
>  /*===-- Miscellaneous -----------------------------------------------------===*/
>
>  uint8_t MachOObjectFile::getBytesInAddress() const {

Is it alright with you if I change the relocation API to provide
relocations per section instead of per object file? All currently
supported file formats do this internally, and most tools access
relocations in this manner. Also, your implementation of getAddress
returns the memory address the relocation targets on the system as a
uintptr_t, which seems very odd to me.

- Michael Spencer




More information about the llvm-commits mailing list