diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 17:02:24 +0000 | 
| commit | 91bc56ed825ba56b3cc264aa5c95ab84f86832ab (patch) | |
| tree | 4df130b28021d86e13bf4565ef58c1c5a5e093b4 /contrib/llvm/lib/Object | |
| parent | 9efc7e72bb1daf5d6019871d9c93a1c488a11229 (diff) | |
| parent | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (diff) | |
Notes
Diffstat (limited to 'contrib/llvm/lib/Object')
| -rw-r--r-- | contrib/llvm/lib/Object/Archive.cpp | 214 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/Binary.cpp | 85 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/COFFObjectFile.cpp | 1039 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/COFFYAML.cpp | 138 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/ELF.cpp | 12 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/ELFObjectFile.cpp | 51 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/ELFYAML.cpp | 427 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/Error.cpp | 19 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/IRObjectFile.cpp | 279 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/MachOObjectFile.cpp | 966 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/MachOUniversal.cpp | 84 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/Object.cpp | 68 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/ObjectFile.cpp | 47 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/RecordStreamer.cpp | 100 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/RecordStreamer.h | 42 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/SymbolicFile.cpp | 65 | ||||
| -rw-r--r-- | contrib/llvm/lib/Object/YAML.cpp | 68 | 
17 files changed, 2515 insertions, 1189 deletions
diff --git a/contrib/llvm/lib/Object/Archive.cpp b/contrib/llvm/lib/Object/Archive.cpp index 71efca2b1863..e32bdd5c5bec 100644 --- a/contrib/llvm/lib/Object/Archive.cpp +++ b/contrib/llvm/lib/Object/Archive.cpp @@ -110,23 +110,19 @@ Archive::Child Archive::Child::getNext() const {    // Check to see if this is past the end of the archive.    if (NextLoc >= Parent->Data->getBufferEnd()) -    return Child(Parent, NULL); +    return Child(Parent, nullptr);    return Child(Parent, NextLoc);  } -error_code Archive::Child::getName(StringRef &Result) const { +ErrorOr<StringRef> Archive::Child::getName() const {    StringRef name = getRawName();    // Check if it's a special name.    if (name[0] == '/') { -    if (name.size() == 1) { // Linker member. -      Result = name; -      return object_error::success; -    } -    if (name.size() == 2 && name[1] == '/') { // String table. -      Result = name; -      return object_error::success; -    } +    if (name.size() == 1) // Linker member. +      return name; +    if (name.size() == 2 && name[1] == '/') // String table. +      return name;      // It's a long name.      // Get the offset.      std::size_t offset; @@ -136,7 +132,7 @@ error_code Archive::Child::getName(StringRef &Result) const {                         + sizeof(ArchiveMemberHeader)                         + offset;      // Verify it. -    if (Parent->StringTable == Parent->end_children() +    if (Parent->StringTable == Parent->child_end()          || addr < (Parent->StringTable->Data.begin()                     + sizeof(ArchiveMemberHeader))          || addr > (Parent->StringTable->Data.begin() @@ -147,65 +143,67 @@ error_code Archive::Child::getName(StringRef &Result) const {      // GNU long file names end with a /.      if (Parent->kind() == K_GNU) {        StringRef::size_type End = StringRef(addr).find('/'); -      Result = StringRef(addr, End); -    } else { -      Result = addr; +      return StringRef(addr, End);      } -    return object_error::success; +    return StringRef(addr);    } else if (name.startswith("#1/")) {      uint64_t name_size;      if (name.substr(3).rtrim(" ").getAsInteger(10, name_size))        llvm_unreachable("Long name length is not an ingeter"); -    Result = Data.substr(sizeof(ArchiveMemberHeader), name_size) +    return Data.substr(sizeof(ArchiveMemberHeader), name_size)          .rtrim(StringRef("\0", 1)); -    return object_error::success;    }    // It's a simple name.    if (name[name.size() - 1] == '/') -    Result = name.substr(0, name.size() - 1); -  else -    Result = name; -  return object_error::success; +    return name.substr(0, name.size() - 1); +  return name;  } -error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, -                                           bool FullPath) const { -  StringRef Name; -  if (error_code ec = getName(Name)) -    return ec; +ErrorOr<std::unique_ptr<MemoryBuffer>> +Archive::Child::getMemoryBuffer(bool FullPath) const { +  ErrorOr<StringRef> NameOrErr = getName(); +  if (std::error_code EC = NameOrErr.getError()) +    return EC; +  StringRef Name = NameOrErr.get();    SmallString<128> Path; -  Result.reset(MemoryBuffer::getMemBuffer( -      getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")") -                                  .toStringRef(Path) -                            : Name, +  std::unique_ptr<MemoryBuffer> Ret(MemoryBuffer::getMemBuffer( +      getBuffer(), +      FullPath +          ? (Twine(Parent->getFileName()) + "(" + Name + ")").toStringRef(Path) +          : Name,        false)); -  return error_code::success(); +  return std::move(Ret); +} + +ErrorOr<std::unique_ptr<Binary>> +Archive::Child::getAsBinary(LLVMContext *Context) const { +  ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = getMemoryBuffer(); +  if (std::error_code EC = BuffOrErr.getError()) +    return EC; + +  return createBinary(std::move(*BuffOrErr), Context);  } -error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const { -  OwningPtr<Binary> ret; -  OwningPtr<MemoryBuffer> Buff; -  if (error_code ec = getMemoryBuffer(Buff)) -    return ec; -  if (error_code ec = createBinary(Buff.take(), ret)) -    return ec; -  Result.swap(ret); -  return object_error::success; +ErrorOr<Archive *> Archive::create(std::unique_ptr<MemoryBuffer> Source) { +  std::error_code EC; +  std::unique_ptr<Archive> Ret(new Archive(std::move(Source), EC)); +  if (EC) +    return EC; +  return Ret.release();  } -Archive::Archive(MemoryBuffer *source, error_code &ec) -  : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) { +Archive::Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &ec) +    : Binary(Binary::ID_Archive, std::move(Source)), SymbolTable(child_end()) {    // Check for sufficient magic. -  assert(source); -  if (source->getBufferSize() < 8 || -      StringRef(source->getBufferStart(), 8) != Magic) { +  if (Data->getBufferSize() < 8 || +      StringRef(Data->getBufferStart(), 8) != Magic) {      ec = object_error::invalid_file_type;      return;    }    // Get the special members. -  child_iterator i = begin_children(false); -  child_iterator e = end_children(); +  child_iterator i = child_begin(false); +  child_iterator e = child_end();    if (i == e) {      ec = object_error::success; @@ -245,9 +243,11 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)    if (Name.startswith("#1/")) {      Format = K_BSD;      // We know this is BSD, so getName will work since there is no string table. -    ec = i->getName(Name); +    ErrorOr<StringRef> NameOrErr = i->getName(); +    ec = NameOrErr.getError();      if (ec)        return; +    Name = NameOrErr.get();      if (Name == "__.SYMDEF SORTED") {        SymbolTable = i;        ++i; @@ -309,9 +309,9 @@ Archive::Archive(MemoryBuffer *source, error_code &ec)    ec = object_error::success;  } -Archive::child_iterator Archive::begin_children(bool SkipInternal) const { +Archive::child_iterator Archive::child_begin(bool SkipInternal) const {    if (Data->getBufferSize() == 8) // empty archive. -    return end_children(); +    return child_end();    if (SkipInternal)      return FirstRegular; @@ -321,16 +321,15 @@ Archive::child_iterator Archive::begin_children(bool SkipInternal) const {    return c;  } -Archive::child_iterator Archive::end_children() const { -  return Child(this, NULL); +Archive::child_iterator Archive::child_end() const { +  return Child(this, nullptr);  } -error_code Archive::Symbol::getName(StringRef &Result) const { -  Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); -  return object_error::success; +StringRef Archive::Symbol::getName() const { +  return Parent->SymbolTable->getBuffer().begin() + StringIndex;  } -error_code Archive::Symbol::getMember(child_iterator &Result) const { +ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {    const char *Buf = Parent->SymbolTable->getBuffer().begin();    const char *Offsets = Buf + 4;    uint32_t Offset = 0; @@ -338,7 +337,14 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const {      Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets)                 + SymbolIndex);    } else if (Parent->kind() == K_BSD) { -    llvm_unreachable("BSD format is not supported"); +    // The SymbolIndex is an index into the ranlib structs that start at +    // Offsets (the first uint32_t is the number of bytes of the ranlib +    // structs).  The ranlib structs are a pair of uint32_t's the first +    // being a string table offset and the second being the offset into +    // the archive of the member that defines the symbol.  Which is what +    // is needed here. +    Offset = *(reinterpret_cast<const support::ulittle32_t *>(Offsets) + +               (SymbolIndex * 2) + 1);    } else {      uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); @@ -370,21 +376,54 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const {    }    const char *Loc = Parent->getData().begin() + Offset; -  Result = Child(Parent, Loc); - -  return object_error::success; +  child_iterator Iter(Child(Parent, Loc)); +  return Iter;  }  Archive::Symbol Archive::Symbol::getNext() const {    Symbol t(*this); -  // Go to one past next null. -  t.StringIndex = -      Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; +  if (Parent->kind() == K_BSD) { +    // t.StringIndex is an offset from the start of the __.SYMDEF or +    // "__.SYMDEF SORTED" member into the string table for the ranlib +    // struct indexed by t.SymbolIndex .  To change t.StringIndex to the +    // offset in the string table for t.SymbolIndex+1 we subtract the +    // its offset from the start of the string table for t.SymbolIndex +    // and add the offset of the string table for t.SymbolIndex+1. + +    // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t +    // which is the number of bytes of ranlib structs that follow.  The ranlib +    // structs are a pair of uint32_t's the first being a string table offset +    // and the second being the offset into the archive of the member that +    // define the symbol. After that the next uint32_t is the byte count of +    // the string table followed by the string table. +    const char *Buf = Parent->SymbolTable->getBuffer().begin(); +    uint32_t RanlibCount = 0; +    RanlibCount = (*reinterpret_cast<const support::ulittle32_t *>(Buf)) / +                  (sizeof(uint32_t) * 2); +    // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount) +    // don't change the t.StringIndex as we don't want to reference a ranlib +    // past RanlibCount. +    if (t.SymbolIndex + 1 < RanlibCount) { +      const char *Ranlibs = Buf + 4; +      uint32_t CurRanStrx = 0; +      uint32_t NextRanStrx = 0; +      CurRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + +                     (t.SymbolIndex * 2)); +      NextRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + +                      ((t.SymbolIndex + 1) * 2)); +      t.StringIndex -= CurRanStrx; +      t.StringIndex += NextRanStrx; +    } +  } else { +    // Go to one past next null. +    t.StringIndex = +        Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; +  }    ++t.SymbolIndex;    return t;  } -Archive::symbol_iterator Archive::begin_symbols() const { +Archive::symbol_iterator Archive::symbol_begin() const {    if (!hasSymbolTable())      return symbol_iterator(Symbol(this, 0, 0)); @@ -394,7 +433,22 @@ Archive::symbol_iterator Archive::begin_symbols() const {      symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);      buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t)));    } else if (kind() == K_BSD) { -    llvm_unreachable("BSD archive format is not supported"); +    // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t +    // which is the number of bytes of ranlib structs that follow.  The ranlib +    // structs are a pair of uint32_t's the first being a string table offset +    // and the second being the offset into the archive of the member that +    // define the symbol. After that the next uint32_t is the byte count of +    // the string table followed by the string table. +    uint32_t ranlib_count = 0; +    ranlib_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / +                   (sizeof(uint32_t) * 2); +    const char *ranlibs = buf + 4; +    uint32_t ran_strx = 0; +    ran_strx = *(reinterpret_cast<const support::ulittle32_t *>(ranlibs)); +    buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); +    // Skip the byte count of the string table. +    buf += sizeof(uint32_t); +    buf += ran_strx;    } else {      uint32_t member_count = 0;      uint32_t symbol_count = 0; @@ -407,7 +461,7 @@ Archive::symbol_iterator Archive::begin_symbols() const {    return symbol_iterator(Symbol(this, 0, string_start_offset));  } -Archive::symbol_iterator Archive::end_symbols() const { +Archive::symbol_iterator Archive::symbol_end() const {    if (!hasSymbolTable())      return symbol_iterator(Symbol(this, 0, 0)); @@ -416,7 +470,8 @@ Archive::symbol_iterator Archive::end_symbols() const {    if (kind() == K_GNU) {      symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf);    } else if (kind() == K_BSD) { -    llvm_unreachable("BSD archive format is not supported"); +    symbol_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / +                   (sizeof(uint32_t) * 2);    } else {      uint32_t member_count = 0;      member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); @@ -428,23 +483,22 @@ Archive::symbol_iterator Archive::end_symbols() const {  }  Archive::child_iterator Archive::findSym(StringRef name) const { -  Archive::symbol_iterator bs = begin_symbols(); -  Archive::symbol_iterator es = end_symbols(); -  Archive::child_iterator result; -   -  StringRef symname; +  Archive::symbol_iterator bs = symbol_begin(); +  Archive::symbol_iterator es = symbol_end(); +    for (; bs != es; ++bs) { -    if (bs->getName(symname)) -        return end_children(); -    if (symname == name) { -      if (bs->getMember(result)) -        return end_children(); -      return result; +    StringRef SymName = bs->getName(); +    if (SymName == name) { +      ErrorOr<Archive::child_iterator> ResultOrErr = bs->getMember(); +      // FIXME: Should we really eat the error? +      if (ResultOrErr.getError()) +        return child_end(); +      return ResultOrErr.get();      }    } -  return end_children(); +  return child_end();  }  bool Archive::hasSymbolTable() const { -  return SymbolTable != end_children(); +  return SymbolTable != child_end();  } diff --git a/contrib/llvm/lib/Object/Binary.cpp b/contrib/llvm/lib/Object/Binary.cpp index de57b4c9a742..552d5db89c54 100644 --- a/contrib/llvm/lib/Object/Binary.cpp +++ b/contrib/llvm/lib/Object/Binary.cpp @@ -13,26 +13,22 @@  #include "llvm/Object/Binary.h"  #include "llvm/ADT/StringRef.h" -#include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/Path.h"  // Include headers for createBinary.  #include "llvm/Object/Archive.h" -#include "llvm/Object/COFF.h"  #include "llvm/Object/MachOUniversal.h"  #include "llvm/Object/ObjectFile.h"  using namespace llvm;  using namespace object; -Binary::~Binary() { -  delete Data; -} +Binary::~Binary() {} -Binary::Binary(unsigned int Type, MemoryBuffer *Source) -  : TypeID(Type) -  , Data(Source) {} +Binary::Binary(unsigned int Type, std::unique_ptr<MemoryBuffer> Source) +    : TypeID(Type), Data(std::move(Source)) {}  StringRef Binary::getData() const {    return Data->getBuffer(); @@ -42,31 +38,17 @@ StringRef Binary::getFileName() const {    return Data->getBufferIdentifier();  } -error_code object::createBinary(MemoryBuffer *Source, -                                OwningPtr<Binary> &Result) { -  OwningPtr<MemoryBuffer> scopedSource(Source); -  if (!Source) -    return make_error_code(errc::invalid_argument); -  sys::fs::file_magic type = sys::fs::identify_magic(Source->getBuffer()); -  error_code ec; -  switch (type) { -    case sys::fs::file_magic::archive: { -      OwningPtr<Binary> ret(new Archive(scopedSource.take(), ec)); -      if (ec) return ec; -      Result.swap(ret); -      return object_error::success; -    } +ErrorOr<Binary *> object::createBinary(std::unique_ptr<MemoryBuffer> Buffer, +                                       LLVMContext *Context) { +  sys::fs::file_magic Type = sys::fs::identify_magic(Buffer->getBuffer()); + +  switch (Type) { +    case sys::fs::file_magic::archive: +      return Archive::create(std::move(Buffer));      case sys::fs::file_magic::elf_relocatable:      case sys::fs::file_magic::elf_executable:      case sys::fs::file_magic::elf_shared_object: -    case sys::fs::file_magic::elf_core: { -      OwningPtr<Binary> ret( -        ObjectFile::createELFObjectFile(scopedSource.take())); -      if (!ret) -        return object_error::invalid_file_type; -      Result.swap(ret); -      return object_error::success; -    } +    case sys::fs::file_magic::elf_core:      case sys::fs::file_magic::macho_object:      case sys::fs::file_magic::macho_executable:      case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: @@ -76,43 +58,26 @@ error_code object::createBinary(MemoryBuffer *Source,      case sys::fs::file_magic::macho_dynamic_linker:      case sys::fs::file_magic::macho_bundle:      case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: -    case sys::fs::file_magic::macho_dsym_companion: { -      OwningPtr<Binary> ret( -        ObjectFile::createMachOObjectFile(scopedSource.take())); -      if (!ret) -        return object_error::invalid_file_type; -      Result.swap(ret); -      return object_error::success; -    } -    case sys::fs::file_magic::macho_universal_binary: { -      OwningPtr<Binary> ret(new MachOUniversalBinary(scopedSource.take(), ec)); -      if (ec) return ec; -      Result.swap(ret); -      return object_error::success; -    } +    case sys::fs::file_magic::macho_dsym_companion:      case sys::fs::file_magic::coff_object:      case sys::fs::file_magic::coff_import_library: -    case sys::fs::file_magic::pecoff_executable: { -      OwningPtr<Binary> ret( -          ObjectFile::createCOFFObjectFile(scopedSource.take())); -      if (!ret) -        return object_error::invalid_file_type; -      Result.swap(ret); -      return object_error::success; -    } -    case sys::fs::file_magic::unknown: +    case sys::fs::file_magic::pecoff_executable:      case sys::fs::file_magic::bitcode: -    case sys::fs::file_magic::windows_resource: { +      return ObjectFile::createSymbolicFile(Buffer, Type, Context); +    case sys::fs::file_magic::macho_universal_binary: +      return MachOUniversalBinary::create(std::move(Buffer)); +    case sys::fs::file_magic::unknown: +    case sys::fs::file_magic::windows_resource:        // Unrecognized object file format.        return object_error::invalid_file_type; -    }    }    llvm_unreachable("Unexpected Binary File Type");  } -error_code object::createBinary(StringRef Path, OwningPtr<Binary> &Result) { -  OwningPtr<MemoryBuffer> File; -  if (error_code ec = MemoryBuffer::getFileOrSTDIN(Path, File)) -    return ec; -  return createBinary(File.take(), Result); +ErrorOr<Binary *> object::createBinary(StringRef Path) { +  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = +      MemoryBuffer::getFileOrSTDIN(Path); +  if (std::error_code EC = FileOrErr.getError()) +    return EC; +  return createBinary(std::move(*FileOrErr));  } diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp index 42066c372b43..46ef87d15680 100644 --- a/contrib/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp @@ -16,25 +16,25 @@  #include "llvm/ADT/SmallString.h"  #include "llvm/ADT/StringSwitch.h"  #include "llvm/ADT/Triple.h" +#include "llvm/Support/COFF.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/raw_ostream.h"  #include <cctype> +#include <limits>  using namespace llvm;  using namespace object; -namespace {  using support::ulittle8_t;  using support::ulittle16_t;  using support::ulittle32_t;  using support::little16_t; -} -namespace {  // Returns false if size is greater than the buffer size. And sets ec. -bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { -  if (m->getBufferSize() < size) { -    ec = object_error::unexpected_eof; +static bool checkSize(const MemoryBuffer &M, std::error_code &EC, +                      uint64_t Size) { +  if (M.getBufferSize() < Size) { +    EC = object_error::unexpected_eof;      return false;    }    return true; @@ -42,332 +42,364 @@ bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) {  // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m.  // Returns unexpected_eof if error. -template<typename T> -error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, -                     const size_t Size = sizeof(T)) { +template <typename T> +static std::error_code getObject(const T *&Obj, const MemoryBuffer &M, +                                 const uint8_t *Ptr, +                                 const size_t Size = sizeof(T)) {    uintptr_t Addr = uintptr_t(Ptr); -  if (Addr + Size < Addr || -      Addr + Size < Size || -      Addr + Size > uintptr_t(M->getBufferEnd())) { +  if (Addr + Size < Addr || Addr + Size < Size || +      Addr + Size > uintptr_t(M.getBufferEnd())) {      return object_error::unexpected_eof;    }    Obj = reinterpret_cast<const T *>(Addr);    return object_error::success;  } + +// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without +// prefixed slashes. +static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { +  assert(Str.size() <= 6 && "String too long, possible overflow."); +  if (Str.size() > 6) +    return true; + +  uint64_t Value = 0; +  while (!Str.empty()) { +    unsigned CharVal; +    if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 +      CharVal = Str[0] - 'A'; +    else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 +      CharVal = Str[0] - 'a' + 26; +    else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 +      CharVal = Str[0] - '0' + 52; +    else if (Str[0] == '+') // 62 +      CharVal = 62; +    else if (Str[0] == '/') // 63 +      CharVal = 63; +    else +      return true; + +    Value = (Value * 64) + CharVal; +    Str = Str.substr(1); +  } + +  if (Value > std::numeric_limits<uint32_t>::max()) +    return true; + +  Result = static_cast<uint32_t>(Value); +  return false;  } -const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { -  const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); +const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const { +  const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p);  # ifndef NDEBUG    // Verify that the symbol points to a valid entry in the symbol table. -  uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); -  if (offset < COFFHeader->PointerToSymbolTable -      || offset >= COFFHeader->PointerToSymbolTable +  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); +  if (Offset < COFFHeader->PointerToSymbolTable +      || Offset >= COFFHeader->PointerToSymbolTable           + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))      report_fatal_error("Symbol was outside of symbol table."); -  assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) +  assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)           == 0 && "Symbol did not point to the beginning of a symbol");  # endif -  return addr; +  return Addr;  } -const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { -  const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); +const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { +  const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p);  # ifndef NDEBUG    // Verify that the section points to a valid entry in the section table. -  if (addr < SectionTable -      || addr >= (SectionTable + COFFHeader->NumberOfSections)) +  if (Addr < SectionTable +      || Addr >= (SectionTable + COFFHeader->NumberOfSections))      report_fatal_error("Section was outside of section table."); -  uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); -  assert(offset % sizeof(coff_section) == 0 && +  uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); +  assert(Offset % sizeof(coff_section) == 0 &&           "Section did not point to the beginning of a section");  # endif -  return addr; +  return Addr;  } -error_code COFFObjectFile::getSymbolNext(DataRefImpl Symb, -                                         SymbolRef &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  symb += 1 + symb->NumberOfAuxSymbols; -  Symb.p = reinterpret_cast<uintptr_t>(symb); -  Result = SymbolRef(Symb, this); -  return object_error::success; +void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { +  const coff_symbol *Symb = toSymb(Ref); +  Symb += 1 + Symb->NumberOfAuxSymbols; +  Ref.p = reinterpret_cast<uintptr_t>(Symb);  } - error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, -                                          StringRef &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  return getSymbolName(symb, Result); -} - -error_code COFFObjectFile::getSymbolFileOffset(DataRefImpl Symb, -                                            uint64_t &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  const coff_section *Section = NULL; -  if (error_code ec = getSection(symb->SectionNumber, Section)) -    return ec; - -  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) -    Result = UnknownAddressOrSize; -  else if (Section) -    Result = Section->PointerToRawData + symb->Value; -  else -    Result = symb->Value; -  return object_error::success; +std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, +                                              StringRef &Result) const { +  const coff_symbol *Symb = toSymb(Ref); +  return getSymbolName(Symb, Result);  } -error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, -                                            uint64_t &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  const coff_section *Section = NULL; -  if (error_code ec = getSection(symb->SectionNumber, Section)) -    return ec; +std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, +                                                 uint64_t &Result) const { +  const coff_symbol *Symb = toSymb(Ref); +  const coff_section *Section = nullptr; +  if (std::error_code EC = getSection(Symb->SectionNumber, Section)) +    return EC; -  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) +  if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)      Result = UnknownAddressOrSize;    else if (Section) -    Result = Section->VirtualAddress + symb->Value; +    Result = Section->VirtualAddress + Symb->Value;    else -    Result = symb->Value; +    Result = Symb->Value;    return object_error::success;  } -error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, -                                         SymbolRef::Type &Result) const { -  const coff_symbol *symb = toSymb(Symb); +std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, +                                              SymbolRef::Type &Result) const { +  const coff_symbol *Symb = toSymb(Ref);    Result = SymbolRef::ST_Other; -  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && -      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { +  if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && +      Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) {      Result = SymbolRef::ST_Unknown; +  } else if (Symb->isFunctionDefinition()) { +    Result = SymbolRef::ST_Function;    } else { -    if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { -      Result = SymbolRef::ST_Function; -    } else { -      uint32_t Characteristics = 0; -      if (symb->SectionNumber > 0) { -        const coff_section *Section = NULL; -        if (error_code ec = getSection(symb->SectionNumber, Section)) -          return ec; -        Characteristics = Section->Characteristics; -      } -      if (Characteristics & COFF::IMAGE_SCN_MEM_READ && -          ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. -        Result = SymbolRef::ST_Data; +    uint32_t Characteristics = 0; +    if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { +      const coff_section *Section = nullptr; +      if (std::error_code EC = getSection(Symb->SectionNumber, Section)) +        return EC; +      Characteristics = Section->Characteristics;      } +    if (Characteristics & COFF::IMAGE_SCN_MEM_READ && +        ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. +      Result = SymbolRef::ST_Data;    }    return object_error::success;  } -error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, -                                          uint32_t &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  Result = SymbolRef::SF_None; +uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { +  const coff_symbol *Symb = toSymb(Ref); +  uint32_t Result = SymbolRef::SF_None; + +  // TODO: Correctly set SF_FormatSpecific, SF_Common -  // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common +  if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { +    if (Symb->Value == 0) +      Result |= SymbolRef::SF_Undefined; +    else +      Result |= SymbolRef::SF_Common; +  } -  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && -      symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) -    Result |= SymbolRef::SF_Undefined;    // TODO: This are certainly too restrictive. -  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) +  if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL)      Result |= SymbolRef::SF_Global; -  if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) +  if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL)      Result |= SymbolRef::SF_Weak; -  if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) +  if (Symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE)      Result |= SymbolRef::SF_Absolute; -  return object_error::success; +  return Result;  } -error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, -                                         uint64_t &Result) const { +std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, +                                              uint64_t &Result) const {    // FIXME: Return the correct size. This requires looking at all the symbols    //        in the same section as this symbol, and looking for either the next    //        symbol, or the end of the section. -  const coff_symbol *symb = toSymb(Symb); -  const coff_section *Section = NULL; -  if (error_code ec = getSection(symb->SectionNumber, Section)) -    return ec; +  const coff_symbol *Symb = toSymb(Ref); +  const coff_section *Section = nullptr; +  if (std::error_code EC = getSection(Symb->SectionNumber, Section)) +    return EC; -  if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) +  if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED)      Result = UnknownAddressOrSize;    else if (Section) -    Result = Section->SizeOfRawData - symb->Value; +    Result = Section->SizeOfRawData - Symb->Value;    else      Result = 0;    return object_error::success;  } -error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, -                                            section_iterator &Result) const { -  const coff_symbol *symb = toSymb(Symb); -  if (symb->SectionNumber <= COFF::IMAGE_SYM_UNDEFINED) -    Result = end_sections(); -  else { -    const coff_section *sec = 0; -    if (error_code ec = getSection(symb->SectionNumber, sec)) return ec; -    DataRefImpl Sec; -    Sec.p = reinterpret_cast<uintptr_t>(sec); -    Result = section_iterator(SectionRef(Sec, this)); +std::error_code +COFFObjectFile::getSymbolSection(DataRefImpl Ref, +                                 section_iterator &Result) const { +  const coff_symbol *Symb = toSymb(Ref); +  if (COFF::isReservedSectionNumber(Symb->SectionNumber)) { +    Result = section_end(); +  } else { +    const coff_section *Sec = nullptr; +    if (std::error_code EC = getSection(Symb->SectionNumber, Sec)) +      return EC; +    DataRefImpl Ref; +    Ref.p = reinterpret_cast<uintptr_t>(Sec); +    Result = section_iterator(SectionRef(Ref, this));    }    return object_error::success;  } -error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, -                                          uint64_t &Val) const { -  report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); +void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { +  const coff_section *Sec = toSec(Ref); +  Sec += 1; +  Ref.p = reinterpret_cast<uintptr_t>(Sec);  } -error_code COFFObjectFile::getSectionNext(DataRefImpl Sec, -                                          SectionRef &Result) const { -  const coff_section *sec = toSec(Sec); -  sec += 1; -  Sec.p = reinterpret_cast<uintptr_t>(sec); -  Result = SectionRef(Sec, this); -  return object_error::success; +std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, +                                               StringRef &Result) const { +  const coff_section *Sec = toSec(Ref); +  return getSectionName(Sec, Result);  } -error_code COFFObjectFile::getSectionName(DataRefImpl Sec, -                                          StringRef &Result) const { -  const coff_section *sec = toSec(Sec); -  return getSectionName(sec, Result); -} - -error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, -                                             uint64_t &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->VirtualAddress; +std::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, +                                                  uint64_t &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->VirtualAddress;    return object_error::success;  } -error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, -                                          uint64_t &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->SizeOfRawData; +std::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, +                                               uint64_t &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->SizeOfRawData;    return object_error::success;  } -error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, -                                              StringRef &Result) const { -  const coff_section *sec = toSec(Sec); +std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, +                                                   StringRef &Result) const { +  const coff_section *Sec = toSec(Ref);    ArrayRef<uint8_t> Res; -  error_code EC = getSectionContents(sec, Res); +  std::error_code EC = getSectionContents(Sec, Res);    Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size());    return EC;  } -error_code COFFObjectFile::getSectionAlignment(DataRefImpl Sec, -                                               uint64_t &Res) const { -  const coff_section *sec = toSec(Sec); -  if (!sec) +std::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, +                                                    uint64_t &Res) const { +  const coff_section *Sec = toSec(Ref); +  if (!Sec)      return object_error::parse_failed; -  Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); +  Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1);    return object_error::success;  } -error_code COFFObjectFile::isSectionText(DataRefImpl Sec, -                                         bool &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; +std::error_code COFFObjectFile::isSectionText(DataRefImpl Ref, +                                              bool &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE;    return object_error::success;  } -error_code COFFObjectFile::isSectionData(DataRefImpl Sec, -                                         bool &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; +std::error_code COFFObjectFile::isSectionData(DataRefImpl Ref, +                                              bool &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;    return object_error::success;  } -error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, -                                        bool &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; +std::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, +                                             bool &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;    return object_error::success;  } -error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, -                                                         bool &Result) const { +std::error_code +COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, +                                              bool &Result) const {    // FIXME: Unimplemented    Result = true;    return object_error::success;  } -error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, -                                           bool &Result) const { -  const coff_section *sec = toSec(Sec); -  Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; +std::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, +                                                 bool &Result) const { +  const coff_section *Sec = toSec(Ref); +  Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;    return object_error::success;  } -error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, -                                             bool &Result) const { +std::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, +                                                  bool &Result) const {    // FIXME: Unimplemented.    Result = false;    return object_error::success;  } -error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, -                                                bool &Result) const { +std::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, +                                                      bool &Result) const {    // FIXME: Unimplemented.    Result = false;    return object_error::success;  } -error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, -                                                 DataRefImpl Symb, -                                                 bool &Result) const { -  const coff_section *sec = toSec(Sec); -  const coff_symbol *symb = toSymb(Symb); -  const coff_section *symb_sec = 0; -  if (error_code ec = getSection(symb->SectionNumber, symb_sec)) return ec; -  if (symb_sec == sec) +std::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, +                                                      DataRefImpl SymbRef, +                                                      bool &Result) const { +  const coff_section *Sec = toSec(SecRef); +  const coff_symbol *Symb = toSymb(SymbRef); +  const coff_section *SymbSec = nullptr; +  if (std::error_code EC = getSection(Symb->SectionNumber, SymbSec)) +    return EC; +  if (SymbSec == Sec)      Result = true;    else      Result = false;    return object_error::success;  } -relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const { -  const coff_section *sec = toSec(Sec); -  DataRefImpl ret; -  if (sec->NumberOfRelocations == 0) -    ret.p = 0; -  else -    ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); - -  return relocation_iterator(RelocationRef(ret, this)); +relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { +  const coff_section *Sec = toSec(Ref); +  DataRefImpl Ret; +  if (Sec->NumberOfRelocations == 0) { +    Ret.p = 0; +  } else { +    auto begin = reinterpret_cast<const coff_relocation*>( +        base() + Sec->PointerToRelocations); +    if (Sec->hasExtendedRelocations()) { +      // Skip the first relocation entry repurposed to store the number of +      // relocations. +      begin++; +    } +    Ret.p = reinterpret_cast<uintptr_t>(begin); +  } +  return relocation_iterator(RelocationRef(Ret, this)); +} + +static uint32_t getNumberOfRelocations(const coff_section *Sec, +                                       const uint8_t *base) { +  // The field for the number of relocations in COFF section table is only +  // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to +  // NumberOfRelocations field, and the actual relocation count is stored in the +  // VirtualAddress field in the first relocation entry. +  if (Sec->hasExtendedRelocations()) { +    auto *FirstReloc = reinterpret_cast<const coff_relocation*>( +        base + Sec->PointerToRelocations); +    return FirstReloc->VirtualAddress; +  } +  return Sec->NumberOfRelocations;  } -relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Sec) const { -  const coff_section *sec = toSec(Sec); -  DataRefImpl ret; -  if (sec->NumberOfRelocations == 0) -    ret.p = 0; -  else -    ret.p = reinterpret_cast<uintptr_t>( -              reinterpret_cast<const coff_relocation*>( -                base() + sec->PointerToRelocations) -              + sec->NumberOfRelocations); - -  return relocation_iterator(RelocationRef(ret, this)); +relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { +  const coff_section *Sec = toSec(Ref); +  DataRefImpl Ret; +  if (Sec->NumberOfRelocations == 0) { +    Ret.p = 0; +  } else { +    auto begin = reinterpret_cast<const coff_relocation*>( +        base() + Sec->PointerToRelocations); +    uint32_t NumReloc = getNumberOfRelocations(Sec, base()); +    Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); +  } +  return relocation_iterator(RelocationRef(Ret, this));  }  // Initialize the pointer to the symbol table. -error_code COFFObjectFile::initSymbolTablePtr() { -  if (error_code ec = getObject( -          SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, +std::error_code COFFObjectFile::initSymbolTablePtr() { +  if (std::error_code EC = getObject( +          SymbolTable, *Data, base() + COFFHeader->PointerToSymbolTable,            COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) -    return ec; +    return EC;    // Find string table. The first four byte of the string table contains the    // total size of the string table, including the size field itself. If the @@ -376,32 +408,42 @@ error_code COFFObjectFile::initSymbolTablePtr() {        base() + COFFHeader->PointerToSymbolTable +        COFFHeader->NumberOfSymbols * sizeof(coff_symbol);    const ulittle32_t *StringTableSizePtr; -  if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr)) -    return ec; +  if (std::error_code EC = +          getObject(StringTableSizePtr, *Data, StringTableAddr)) +    return EC;    StringTableSize = *StringTableSizePtr; -  if (error_code ec = -      getObject(StringTable, Data, StringTableAddr, StringTableSize)) -    return ec; +  if (std::error_code EC = +          getObject(StringTable, *Data, StringTableAddr, StringTableSize)) +    return EC; + +  // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some +  // tools like cvtres write a size of 0 for an empty table instead of 4. +  if (StringTableSize < 4) +      StringTableSize = 4;    // Check that the string table is null terminated if has any in it. -  if (StringTableSize < 4 || -      (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) +  if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)      return  object_error::parse_failed;    return object_error::success;  } +// Returns the file offset for the given VA. +std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { +  uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase +                                  : (uint64_t)PE32PlusHeader->ImageBase; +  uint64_t Rva = Addr - ImageBase; +  assert(Rva <= UINT32_MAX); +  return getRvaPtr((uint32_t)Rva, Res); +} +  // Returns the file offset for the given RVA. -error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const { -  error_code ec; -  for (section_iterator i = begin_sections(), e = end_sections(); i != e; -       i.increment(ec)) { -    if (ec) -      return ec; -    const coff_section *Section = getCOFFSection(i); +std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { +  for (const SectionRef &S : sections()) { +    const coff_section *Section = getCOFFSection(S);      uint32_t SectionStart = Section->VirtualAddress;      uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; -    if (SectionStart <= Rva && Rva < SectionEnd) { -      uint32_t Offset = Rva - SectionStart; +    if (SectionStart <= Addr && Addr < SectionEnd) { +      uint32_t Offset = Addr - SectionStart;        Res = uintptr_t(base()) + Section->PointerToRawData + Offset;        return object_error::success;      } @@ -411,11 +453,11 @@ error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const {  // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name  // table entry. -error_code COFFObjectFile:: -getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { +std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, +                                            StringRef &Name) const {    uintptr_t IntPtr = 0; -  if (error_code ec = getRvaPtr(Rva, IntPtr)) -    return ec; +  if (std::error_code EC = getRvaPtr(Rva, IntPtr)) +    return EC;    const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr);    Hint = *reinterpret_cast<const ulittle16_t *>(Ptr);    Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); @@ -423,7 +465,7 @@ getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const {  }  // Find the import table. -error_code COFFObjectFile::initImportTablePtr() { +std::error_code COFFObjectFile::initImportTablePtr() {    // First, we get the RVA of the import table. If the file lacks a pointer to    // the import table, do nothing.    const data_directory *DataEntry; @@ -441,118 +483,139 @@ error_code COFFObjectFile::initImportTablePtr() {    // Find the section that contains the RVA. This is needed because the RVA is    // the import table's memory address which is different from its file offset.    uintptr_t IntPtr = 0; -  if (error_code ec = getRvaPtr(ImportTableRva, IntPtr)) -    return ec; +  if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) +    return EC;    ImportDirectory = reinterpret_cast<        const import_directory_table_entry *>(IntPtr); +  return object_error::success; +} -  // It's an error if there's no section containing the Import Table RVA. -  return object_error::parse_failed; +// Find the export table. +std::error_code COFFObjectFile::initExportTablePtr() { +  // First, we get the RVA of the export table. If the file lacks a pointer to +  // the export table, do nothing. +  const data_directory *DataEntry; +  if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) +    return object_error::success; + +  // Do nothing if the pointer to export table is NULL. +  if (DataEntry->RelativeVirtualAddress == 0) +    return object_error::success; + +  uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; +  uintptr_t IntPtr = 0; +  if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) +    return EC; +  ExportDirectory = +      reinterpret_cast<const export_directory_table_entry *>(IntPtr); +  return object_error::success;  } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) -  : ObjectFile(Binary::ID_COFF, Object) -  , COFFHeader(0) -  , PE32Header(0) -  , DataDirectory(0) -  , SectionTable(0) -  , SymbolTable(0) -  , StringTable(0) -  , StringTableSize(0) -  , ImportDirectory(0) -  , NumberOfImportDirectory(0) { +COFFObjectFile::COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, +                               std::error_code &EC) +    : ObjectFile(Binary::ID_COFF, std::move(Object)), COFFHeader(nullptr), +      PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), +      SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr), +      StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0), +      ExportDirectory(nullptr) {    // Check that we at least have enough room for a header. -  if (!checkSize(Data, ec, sizeof(coff_file_header))) return; +  if (!checkSize(*Data, EC, sizeof(coff_file_header))) +    return;    // The current location in the file where we are looking at.    uint64_t CurPtr = 0;    // PE header is optional and is present only in executables. If it exists,    // it is placed right after COFF header. -  bool hasPEHeader = false; +  bool HasPEHeader = false;    // Check if this is a PE/COFF file.    if (base()[0] == 0x4d && base()[1] == 0x5a) {      // PE/COFF, seek through MS-DOS compatibility stub and 4-byte      // PE signature to find 'normal' COFF header. -    if (!checkSize(Data, ec, 0x3c + 8)) return; +    if (!checkSize(*Data, EC, 0x3c + 8)) +      return;      CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c);      // Check the PE magic bytes. ("PE\0\0")      if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { -      ec = object_error::parse_failed; +      EC = object_error::parse_failed;        return;      }      CurPtr += 4; // Skip the PE magic bytes. -    hasPEHeader = true; +    HasPEHeader = true;    } -  if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) +  if ((EC = getObject(COFFHeader, *Data, base() + CurPtr)))      return;    CurPtr += sizeof(coff_file_header); -  if (hasPEHeader) { -    if ((ec = getObject(PE32Header, Data, base() + CurPtr))) +  if (HasPEHeader) { +    const pe32_header *Header; +    if ((EC = getObject(Header, *Data, base() + CurPtr))) +      return; + +    const uint8_t *DataDirAddr; +    uint64_t DataDirSize; +    if (Header->Magic == 0x10b) { +      PE32Header = Header; +      DataDirAddr = base() + CurPtr + sizeof(pe32_header); +      DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; +    } else if (Header->Magic == 0x20b) { +      PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); +      DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); +      DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; +    } else { +      // It's neither PE32 nor PE32+. +      EC = object_error::parse_failed;        return; -    if (PE32Header->Magic != 0x10b) { -      // We only support PE32. If this is PE32 (not PE32+), the magic byte -      // should be 0x10b. If this is not PE32, continue as if there's no PE -      // header in this file. -      PE32Header = 0; -    } else if (PE32Header->NumberOfRvaAndSize > 0) { -      const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); -      uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; -      if ((ec = getObject(DataDirectory, Data, addr, size))) -        return;      } +    if ((EC = getObject(DataDirectory, *Data, DataDirAddr, DataDirSize))) +      return;      CurPtr += COFFHeader->SizeOfOptionalHeader;    } -  if (!COFFHeader->isImportLibrary()) -    if ((ec = getObject(SectionTable, Data, base() + CurPtr, -                        COFFHeader->NumberOfSections * sizeof(coff_section)))) -      return; +  if (COFFHeader->isImportLibrary()) +    return; + +  if ((EC = getObject(SectionTable, *Data, base() + CurPtr, +                      COFFHeader->NumberOfSections * sizeof(coff_section)))) +    return;    // Initialize the pointer to the symbol table.    if (COFFHeader->PointerToSymbolTable != 0) -    if ((ec = initSymbolTablePtr())) +    if ((EC = initSymbolTablePtr()))        return;    // Initialize the pointer to the beginning of the import table. -  if ((ec = initImportTablePtr())) +  if ((EC = initImportTablePtr()))      return; -  ec = object_error::success; -} +  // Initialize the pointer to the export table. +  if ((EC = initExportTablePtr())) +    return; -symbol_iterator COFFObjectFile::begin_symbols() const { -  DataRefImpl ret; -  ret.p = reinterpret_cast<uintptr_t>(SymbolTable); -  return symbol_iterator(SymbolRef(ret, this)); +  EC = object_error::success;  } -symbol_iterator COFFObjectFile::end_symbols() const { -  // The symbol table ends where the string table begins. -  DataRefImpl ret; -  ret.p = reinterpret_cast<uintptr_t>(StringTable); -  return symbol_iterator(SymbolRef(ret, this)); +basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { +  DataRefImpl Ret; +  Ret.p = reinterpret_cast<uintptr_t>(SymbolTable); +  return basic_symbol_iterator(SymbolRef(Ret, this));  } -symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { -  // TODO: implement -  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); -} - -symbol_iterator COFFObjectFile::end_dynamic_symbols() const { -  // TODO: implement -  report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); +basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { +  // The symbol table ends where the string table begins. +  DataRefImpl Ret; +  Ret.p = reinterpret_cast<uintptr_t>(StringTable); +  return basic_symbol_iterator(SymbolRef(Ret, this));  } -library_iterator COFFObjectFile::begin_libraries_needed() const { +library_iterator COFFObjectFile::needed_library_begin() const {    // TODO: implement    report_fatal_error("Libraries needed unimplemented in COFFObjectFile");  } -library_iterator COFFObjectFile::end_libraries_needed() const { +library_iterator COFFObjectFile::needed_library_end() const {    // TODO: implement    report_fatal_error("Libraries needed unimplemented in COFFObjectFile");  } @@ -563,34 +626,40 @@ StringRef COFFObjectFile::getLoadName() const {  }  import_directory_iterator COFFObjectFile::import_directory_begin() const { -  DataRefImpl Imp; -  Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory); -  return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); +  return import_directory_iterator( +      ImportDirectoryEntryRef(ImportDirectory, 0, this));  }  import_directory_iterator COFFObjectFile::import_directory_end() const { -  DataRefImpl Imp; -  if (ImportDirectory) { -    Imp.p = reinterpret_cast<uintptr_t>( -        ImportDirectory + (NumberOfImportDirectory - 1)); -  } else { -    Imp.p = 0; -  } -  return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); +  return import_directory_iterator( +      ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); +} + +export_directory_iterator COFFObjectFile::export_directory_begin() const { +  return export_directory_iterator( +      ExportDirectoryEntryRef(ExportDirectory, 0, this)); +} + +export_directory_iterator COFFObjectFile::export_directory_end() const { +  if (!ExportDirectory) +    return export_directory_iterator(ExportDirectoryEntryRef(nullptr, 0, this)); +  ExportDirectoryEntryRef Ref(ExportDirectory, +                              ExportDirectory->AddressTableEntries, this); +  return export_directory_iterator(Ref);  } -section_iterator COFFObjectFile::begin_sections() const { -  DataRefImpl ret; -  ret.p = reinterpret_cast<uintptr_t>(SectionTable); -  return section_iterator(SectionRef(ret, this)); +section_iterator COFFObjectFile::section_begin() const { +  DataRefImpl Ret; +  Ret.p = reinterpret_cast<uintptr_t>(SectionTable); +  return section_iterator(SectionRef(Ret, this));  } -section_iterator COFFObjectFile::end_sections() const { -  DataRefImpl ret; -  int numSections = COFFHeader->isImportLibrary() +section_iterator COFFObjectFile::section_end() const { +  DataRefImpl Ret; +  int NumSections = COFFHeader->isImportLibrary()        ? 0 : COFFHeader->NumberOfSections; -  ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections); -  return section_iterator(SectionRef(ret, this)); +  Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); +  return section_iterator(SectionRef(Ret, this));  }  uint8_t COFFObjectFile::getBytesInAddress() const { @@ -603,6 +672,8 @@ StringRef COFFObjectFile::getFileFormatName() const {      return "COFF-i386";    case COFF::IMAGE_FILE_MACHINE_AMD64:      return "COFF-x86-64"; +  case COFF::IMAGE_FILE_MACHINE_ARMNT: +    return "COFF-ARM";    default:      return "COFF-<unknown arch>";    } @@ -614,6 +685,8 @@ unsigned COFFObjectFile::getArch() const {      return Triple::x86;    case COFF::IMAGE_FILE_MACHINE_AMD64:      return Triple::x86_64; +  case COFF::IMAGE_FILE_MACHINE_ARMNT: +    return Triple::thumb;    default:      return Triple::UnknownArch;    } @@ -621,107 +694,119 @@ unsigned COFFObjectFile::getArch() const {  // This method is kept here because lld uses this. As soon as we make  // lld to use getCOFFHeader, this method will be removed. -error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { +std::error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const {    return getCOFFHeader(Res);  } -error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { +std::error_code +COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const {    Res = COFFHeader;    return object_error::success;  } -error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { +std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const {    Res = PE32Header;    return object_error::success;  } -error_code COFFObjectFile::getDataDirectory(uint32_t index, -                                            const data_directory *&Res) const { +std::error_code +COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { +  Res = PE32PlusHeader; +  return object_error::success; +} + +std::error_code +COFFObjectFile::getDataDirectory(uint32_t Index, +                                 const data_directory *&Res) const {    // Error if if there's no data directory or the index is out of range. -  if (!DataDirectory || index > PE32Header->NumberOfRvaAndSize) +  if (!DataDirectory)      return object_error::parse_failed; -  Res = &DataDirectory[index]; +  assert(PE32Header || PE32PlusHeader); +  uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize +                               : PE32PlusHeader->NumberOfRvaAndSize; +  if (Index > NumEnt) +    return object_error::parse_failed; +  Res = &DataDirectory[Index];    return object_error::success;  } -error_code COFFObjectFile::getSection(int32_t index, -                                      const coff_section *&Result) const { +std::error_code COFFObjectFile::getSection(int32_t Index, +                                           const coff_section *&Result) const {    // Check for special index values. -  if (index == COFF::IMAGE_SYM_UNDEFINED || -      index == COFF::IMAGE_SYM_ABSOLUTE || -      index == COFF::IMAGE_SYM_DEBUG) -    Result = NULL; -  else if (index > 0 && index <= COFFHeader->NumberOfSections) +  if (COFF::isReservedSectionNumber(Index)) +    Result = nullptr; +  else if (Index > 0 && Index <= COFFHeader->NumberOfSections)      // We already verified the section table data, so no need to check again. -    Result = SectionTable + (index - 1); +    Result = SectionTable + (Index - 1);    else      return object_error::parse_failed;    return object_error::success;  } -error_code COFFObjectFile::getString(uint32_t offset, -                                     StringRef &Result) const { +std::error_code COFFObjectFile::getString(uint32_t Offset, +                                          StringRef &Result) const {    if (StringTableSize <= 4)      // Tried to get a string from an empty string table.      return object_error::parse_failed; -  if (offset >= StringTableSize) +  if (Offset >= StringTableSize)      return object_error::unexpected_eof; -  Result = StringRef(StringTable + offset); +  Result = StringRef(StringTable + Offset);    return object_error::success;  } -error_code COFFObjectFile::getSymbol(uint32_t index, -                                     const coff_symbol *&Result) const { -  if (index < COFFHeader->NumberOfSymbols) -    Result = SymbolTable + index; +std::error_code COFFObjectFile::getSymbol(uint32_t Index, +                                          const coff_symbol *&Result) const { +  if (Index < COFFHeader->NumberOfSymbols) +    Result = SymbolTable + Index;    else      return object_error::parse_failed;    return object_error::success;  } -error_code COFFObjectFile::getSymbolName(const coff_symbol *symbol, -                                         StringRef &Res) const { +std::error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, +                                              StringRef &Res) const {    // Check for string table entry. First 4 bytes are 0. -  if (symbol->Name.Offset.Zeroes == 0) { -    uint32_t Offset = symbol->Name.Offset.Offset; -    if (error_code ec = getString(Offset, Res)) -      return ec; +  if (Symbol->Name.Offset.Zeroes == 0) { +    uint32_t Offset = Symbol->Name.Offset.Offset; +    if (std::error_code EC = getString(Offset, Res)) +      return EC;      return object_error::success;    } -  if (symbol->Name.ShortName[7] == 0) +  if (Symbol->Name.ShortName[7] == 0)      // Null terminated, let ::strlen figure out the length. -    Res = StringRef(symbol->Name.ShortName); +    Res = StringRef(Symbol->Name.ShortName);    else      // Not null terminated, use all 8 bytes. -    Res = StringRef(symbol->Name.ShortName, 8); +    Res = StringRef(Symbol->Name.ShortName, 8);    return object_error::success;  }  ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( -                                  const coff_symbol *symbol) const { -  const uint8_t *aux = NULL; +                                  const coff_symbol *Symbol) const { +  const uint8_t *Aux = nullptr; -  if ( symbol->NumberOfAuxSymbols > 0 ) { +  if (Symbol->NumberOfAuxSymbols > 0) {    // AUX data comes immediately after the symbol in COFF -    aux = reinterpret_cast<const uint8_t *>(symbol + 1); +    Aux = reinterpret_cast<const uint8_t *>(Symbol + 1);  # ifndef NDEBUG -    // Verify that the aux symbol points to a valid entry in the symbol table. -    uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); -    if (offset < COFFHeader->PointerToSymbolTable -        || offset >= COFFHeader->PointerToSymbolTable +    // Verify that the Aux symbol points to a valid entry in the symbol table. +    uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); +    if (Offset < COFFHeader->PointerToSymbolTable +        || Offset >= COFFHeader->PointerToSymbolTable             + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol)))        report_fatal_error("Aux Symbol data was outside of symbol table."); -    assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) +    assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol)           == 0 && "Aux Symbol data did not point to the beginning of a symbol");  # endif    } -  return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); +  return ArrayRef<uint8_t>(Aux, +                           Symbol->NumberOfAuxSymbols * sizeof(coff_symbol));  } -error_code COFFObjectFile::getSectionName(const coff_section *Sec, -                                          StringRef &Res) const { +std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, +                                               StringRef &Res) const {    StringRef Name;    if (Sec->Name[7] == 0)      // Null terminated, let ::strlen figure out the length. @@ -733,18 +818,24 @@ error_code COFFObjectFile::getSectionName(const coff_section *Sec,    // Check for string table entry. First byte is '/'.    if (Name[0] == '/') {      uint32_t Offset; -    if (Name.substr(1).getAsInteger(10, Offset)) -      return object_error::parse_failed; -    if (error_code ec = getString(Offset, Name)) -      return ec; +    if (Name[1] == '/') { +      if (decodeBase64StringEntry(Name.substr(2), Offset)) +        return object_error::parse_failed; +    } else { +      if (Name.substr(1).getAsInteger(10, Offset)) +        return object_error::parse_failed; +    } +    if (std::error_code EC = getString(Offset, Name)) +      return EC;    }    Res = Name;    return object_error::success;  } -error_code COFFObjectFile::getSectionContents(const coff_section *Sec, -                                              ArrayRef<uint8_t> &Res) const { +std::error_code +COFFObjectFile::getSectionContents(const coff_section *Sec, +                                   ArrayRef<uint8_t> &Res) const {    // The only thing that we need to verify is that the contents is contained    // within the file bounds. We don't need to make sure it doesn't cover other    // data, as there's nothing that says that is not allowed. @@ -760,58 +851,65 @@ error_code COFFObjectFile::getSectionContents(const coff_section *Sec,  const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const {    return reinterpret_cast<const coff_relocation*>(Rel.p);  } -error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, -                                             RelocationRef &Res) const { + +void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const {    Rel.p = reinterpret_cast<uintptr_t>(              reinterpret_cast<const coff_relocation*>(Rel.p) + 1); -  Res = RelocationRef(Rel, this); -  return object_error::success;  } -error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, -                                                uint64_t &Res) const { + +std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, +                                                     uint64_t &Res) const {    report_fatal_error("getRelocationAddress not implemented in COFFObjectFile");  } -error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, -                                               uint64_t &Res) const { + +std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, +                                                    uint64_t &Res) const {    Res = toRel(Rel)->VirtualAddress;    return object_error::success;  } +  symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const {    const coff_relocation* R = toRel(Rel); -  DataRefImpl Symb; -  Symb.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); -  return symbol_iterator(SymbolRef(Symb, this)); +  DataRefImpl Ref; +  Ref.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); +  return symbol_iterator(SymbolRef(Ref, this));  } -error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, -                                             uint64_t &Res) const { + +std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, +                                                  uint64_t &Res) const {    const coff_relocation* R = toRel(Rel);    Res = R->Type;    return object_error::success;  } -const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { -  return toSec(It->getRawDataRefImpl()); +const coff_section * +COFFObjectFile::getCOFFSection(const SectionRef &Section) const { +  return toSec(Section.getRawDataRefImpl());  } -const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { -  return toSymb(It->getRawDataRefImpl()); +const coff_symbol * +COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { +  return toSymb(Symbol.getRawDataRefImpl());  } -const coff_relocation *COFFObjectFile::getCOFFRelocation( -                                             relocation_iterator &It) const { -  return toRel(It->getRawDataRefImpl()); +const coff_relocation * +COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { +  return toRel(Reloc.getRawDataRefImpl());  } -#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ -  case COFF::enum: res = #enum; break; +#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type)                           \ +  case COFF::reloc_type:                                                       \ +    Res = #reloc_type;                                                         \ +    break; -error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, -                                          SmallVectorImpl<char> &Result) const { -  const coff_relocation *reloc = toRel(Rel); -  StringRef res; +std::error_code +COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, +                                      SmallVectorImpl<char> &Result) const { +  const coff_relocation *Reloc = toRel(Rel); +  StringRef Res;    switch (COFFHeader->Machine) {    case COFF::IMAGE_FILE_MACHINE_AMD64: -    switch (reloc->Type) { +    switch (Reloc->Type) {      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); @@ -830,11 +928,32 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32);      default: -      res = "Unknown"; +      Res = "Unknown"; +    } +    break; +  case COFF::IMAGE_FILE_MACHINE_ARMNT: +    switch (Reloc->Type) { +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ABSOLUTE); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_ADDR32NB); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH11); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_TOKEN); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX24); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX11); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECTION); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_SECREL); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32A); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_MOV32T); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH20T); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BRANCH24T); +    LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_ARM_BLX23T); +    default: +      Res = "Unknown";      }      break;    case COFF::IMAGE_FILE_MACHINE_I386: -    switch (reloc->Type) { +    switch (Reloc->Type) {      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); @@ -847,92 +966,158 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel,      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7);      LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32);      default: -      res = "Unknown"; +      Res = "Unknown";      }      break;    default: -    res = "Unknown"; +    Res = "Unknown";    } -  Result.append(res.begin(), res.end()); +  Result.append(Res.begin(), Res.end());    return object_error::success;  }  #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME -error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, -                                          SmallVectorImpl<char> &Result) const { -  const coff_relocation *reloc = toRel(Rel); -  const coff_symbol *symb = 0; -  if (error_code ec = getSymbol(reloc->SymbolTableIndex, symb)) return ec; -  DataRefImpl sym; -  sym.p = reinterpret_cast<uintptr_t>(symb); -  StringRef symname; -  if (error_code ec = getSymbolName(sym, symname)) return ec; -  Result.append(symname.begin(), symname.end()); +std::error_code +COFFObjectFile::getRelocationValueString(DataRefImpl Rel, +                                         SmallVectorImpl<char> &Result) const { +  const coff_relocation *Reloc = toRel(Rel); +  const coff_symbol *Symb = nullptr; +  if (std::error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb)) +    return EC; +  DataRefImpl Sym; +  Sym.p = reinterpret_cast<uintptr_t>(Symb); +  StringRef SymName; +  if (std::error_code EC = getSymbolName(Sym, SymName)) +    return EC; +  Result.append(SymName.begin(), SymName.end());    return object_error::success;  } -error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, -                                          LibraryRef &Result) const { +std::error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, +                                               LibraryRef &Result) const {    report_fatal_error("getLibraryNext not implemented in COFFObjectFile");  } -error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, -                                          StringRef &Result) const { +std::error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, +                                               StringRef &Result) const {    report_fatal_error("getLibraryPath not implemented in COFFObjectFile");  }  bool ImportDirectoryEntryRef::  operator==(const ImportDirectoryEntryRef &Other) const { -  return ImportDirectoryPimpl == Other.ImportDirectoryPimpl; +  return ImportTable == Other.ImportTable && Index == Other.Index;  } -static const import_directory_table_entry *toImportEntry(DataRefImpl Imp) { -  return reinterpret_cast<const import_directory_table_entry *>(Imp.p); +void ImportDirectoryEntryRef::moveNext() { +  ++Index;  } -error_code -ImportDirectoryEntryRef::getNext(ImportDirectoryEntryRef &Result) const { -  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); -  Dir += 1; -  DataRefImpl Next; -  Next.p = reinterpret_cast<uintptr_t>(Dir); -  Result = ImportDirectoryEntryRef(Next, OwningObject); +std::error_code ImportDirectoryEntryRef::getImportTableEntry( +    const import_directory_table_entry *&Result) const { +  Result = ImportTable;    return object_error::success;  } -error_code ImportDirectoryEntryRef:: -getImportTableEntry(const import_directory_table_entry *&Result) const { -  Result = toImportEntry(ImportDirectoryPimpl); +std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { +  uintptr_t IntPtr = 0; +  if (std::error_code EC = +          OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) +    return EC; +  Result = StringRef(reinterpret_cast<const char *>(IntPtr));    return object_error::success;  } -error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { -  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); +std::error_code ImportDirectoryEntryRef::getImportLookupEntry( +    const import_lookup_table_entry32 *&Result) const {    uintptr_t IntPtr = 0; -  if (error_code ec = OwningObject->getRvaPtr(Dir->NameRVA, IntPtr)) -    return ec; -  const char *Ptr = reinterpret_cast<const char *>(IntPtr); -  Result = StringRef(Ptr); +  if (std::error_code EC = +          OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) +    return EC; +  Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr);    return object_error::success;  } -error_code ImportDirectoryEntryRef::getImportLookupEntry( -    const import_lookup_table_entry32 *&Result) const { -  const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); +bool ExportDirectoryEntryRef:: +operator==(const ExportDirectoryEntryRef &Other) const { +  return ExportTable == Other.ExportTable && Index == Other.Index; +} + +void ExportDirectoryEntryRef::moveNext() { +  ++Index; +} + +// Returns the name of the current export symbol. If the symbol is exported only +// by ordinal, the empty string is set as a result. +std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const {    uintptr_t IntPtr = 0; -  if (error_code ec = OwningObject->getRvaPtr( -          Dir->ImportLookupTableRVA, IntPtr)) -    return ec; -  Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); +  if (std::error_code EC = +          OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) +    return EC; +  Result = StringRef(reinterpret_cast<const char *>(IntPtr));    return object_error::success;  } -namespace llvm { +// Returns the starting ordinal number. +std::error_code +ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { +  Result = ExportTable->OrdinalBase; +  return object_error::success; +} + +// Returns the export ordinal of the current export symbol. +std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { +  Result = ExportTable->OrdinalBase + Index; +  return object_error::success; +} + +// Returns the address of the current export symbol. +std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { +  uintptr_t IntPtr = 0; +  if (std::error_code EC = +          OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) +    return EC; +  const export_address_table_entry *entry = +      reinterpret_cast<const export_address_table_entry *>(IntPtr); +  Result = entry[Index].ExportRVA; +  return object_error::success; +} -  ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { -    error_code ec; -    return new COFFObjectFile(Object, ec); +// Returns the name of the current export symbol. If the symbol is exported only +// by ordinal, the empty string is set as a result. +std::error_code +ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { +  uintptr_t IntPtr = 0; +  if (std::error_code EC = +          OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) +    return EC; +  const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); + +  uint32_t NumEntries = ExportTable->NumberOfNamePointers; +  int Offset = 0; +  for (const ulittle16_t *I = Start, *E = Start + NumEntries; +       I < E; ++I, ++Offset) { +    if (*I != Index) +      continue; +    if (std::error_code EC = +            OwningObject->getRvaPtr(ExportTable->NamePointerRVA, IntPtr)) +      return EC; +    const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); +    if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) +      return EC; +    Result = StringRef(reinterpret_cast<const char *>(IntPtr)); +    return object_error::success;    } +  Result = ""; +  return object_error::success; +} -} // end namespace llvm +ErrorOr<ObjectFile *> +ObjectFile::createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object) { +  std::error_code EC; +  std::unique_ptr<COFFObjectFile> Ret( +      new COFFObjectFile(std::move(Object), EC)); +  if (EC) +    return EC; +  return Ret.release(); +} diff --git a/contrib/llvm/lib/Object/COFFYAML.cpp b/contrib/llvm/lib/Object/COFFYAML.cpp index e549b4e9ea25..49c5ddaee0a7 100644 --- a/contrib/llvm/lib/Object/COFFYAML.cpp +++ b/contrib/llvm/lib/Object/COFFYAML.cpp @@ -23,13 +23,39 @@ Object::Object() { memset(&Header, 0, sizeof(COFF::header)); }  }  namespace yaml { +void ScalarEnumerationTraits<COFFYAML::COMDATType>::enumeration( +    IO &IO, COFFYAML::COMDATType &Value) { +  IO.enumCase(Value, "0", 0); +  ECase(IMAGE_COMDAT_SELECT_NODUPLICATES); +  ECase(IMAGE_COMDAT_SELECT_ANY); +  ECase(IMAGE_COMDAT_SELECT_SAME_SIZE); +  ECase(IMAGE_COMDAT_SELECT_EXACT_MATCH); +  ECase(IMAGE_COMDAT_SELECT_ASSOCIATIVE); +  ECase(IMAGE_COMDAT_SELECT_LARGEST); +  ECase(IMAGE_COMDAT_SELECT_NEWEST); +} + +void +ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics>::enumeration( +    IO &IO, COFFYAML::WeakExternalCharacteristics &Value) { +  IO.enumCase(Value, "0", 0); +  ECase(IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); +  ECase(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY); +  ECase(IMAGE_WEAK_EXTERN_SEARCH_ALIAS); +} + +void ScalarEnumerationTraits<COFFYAML::AuxSymbolType>::enumeration( +    IO &IO, COFFYAML::AuxSymbolType &Value) { +  ECase(IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF); +} +  void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration(      IO &IO, COFF::MachineTypes &Value) {    ECase(IMAGE_FILE_MACHINE_UNKNOWN);    ECase(IMAGE_FILE_MACHINE_AM33);    ECase(IMAGE_FILE_MACHINE_AMD64);    ECase(IMAGE_FILE_MACHINE_ARM); -  ECase(IMAGE_FILE_MACHINE_ARMV7); +  ECase(IMAGE_FILE_MACHINE_ARMNT);    ECase(IMAGE_FILE_MACHINE_EBC);    ECase(IMAGE_FILE_MACHINE_I386);    ECase(IMAGE_FILE_MACHINE_IA64); @@ -107,8 +133,8 @@ void ScalarEnumerationTraits<COFF::SymbolComplexType>::enumeration(    ECase(IMAGE_SYM_DTYPE_ARRAY);  } -void ScalarEnumerationTraits<COFF::RelocationTypeX86>::enumeration( -    IO &IO, COFF::RelocationTypeX86 &Value) { +void ScalarEnumerationTraits<COFF::RelocationTypeI386>::enumeration( +    IO &IO, COFF::RelocationTypeI386 &Value) {    ECase(IMAGE_REL_I386_ABSOLUTE);    ECase(IMAGE_REL_I386_DIR16);    ECase(IMAGE_REL_I386_REL16); @@ -120,6 +146,10 @@ void ScalarEnumerationTraits<COFF::RelocationTypeX86>::enumeration(    ECase(IMAGE_REL_I386_TOKEN);    ECase(IMAGE_REL_I386_SECREL7);    ECase(IMAGE_REL_I386_REL32); +} + +void ScalarEnumerationTraits<COFF::RelocationTypeAMD64>::enumeration( +    IO &IO, COFF::RelocationTypeAMD64 &Value) {    ECase(IMAGE_REL_AMD64_ABSOLUTE);    ECase(IMAGE_REL_AMD64_ADDR64);    ECase(IMAGE_REL_AMD64_ADDR32); @@ -187,6 +217,24 @@ void ScalarBitSetTraits<COFF::SectionCharacteristics>::bitset(  #undef BCase  namespace { +struct NSectionSelectionType { +  NSectionSelectionType(IO &) +      : SelectionType(COFFYAML::COMDATType(0)) {} +  NSectionSelectionType(IO &, uint8_t C) +      : SelectionType(COFFYAML::COMDATType(C)) {} +  uint8_t denormalize(IO &) { return SelectionType; } +  COFFYAML::COMDATType SelectionType; +}; + +struct NWeakExternalCharacteristics { +  NWeakExternalCharacteristics(IO &) +      : Characteristics(COFFYAML::WeakExternalCharacteristics(0)) {} +  NWeakExternalCharacteristics(IO &, uint32_t C) +      : Characteristics(COFFYAML::WeakExternalCharacteristics(C)) {} +  uint32_t denormalize(IO &) { return Characteristics; } +  COFFYAML::WeakExternalCharacteristics Characteristics; +}; +  struct NSectionCharacteristics {    NSectionCharacteristics(IO &)        : Characteristics(COFF::SectionCharacteristics(0)) {} @@ -196,6 +244,15 @@ struct NSectionCharacteristics {    COFF::SectionCharacteristics Characteristics;  }; +struct NAuxTokenType { +  NAuxTokenType(IO &) +      : AuxType(COFFYAML::AuxSymbolType(0)) {} +  NAuxTokenType(IO &, uint8_t C) +      : AuxType(COFFYAML::AuxSymbolType(C)) {} +  uint32_t denormalize(IO &) { return AuxType; } +  COFFYAML::AuxSymbolType AuxType; +}; +  struct NStorageClass {    NStorageClass(IO &) : StorageClass(COFF::SymbolStorageClass(0)) {}    NStorageClass(IO &, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {} @@ -220,22 +277,33 @@ struct NHeaderCharacteristics {    COFF::Characteristics Characteristics;  }; +template <typename RelocType>  struct NType { -  NType(IO &) : Type(COFF::RelocationTypeX86(0)) {} -  NType(IO &, uint16_t T) : Type(COFF::RelocationTypeX86(T)) {} +  NType(IO &) : Type(RelocType(0)) {} +  NType(IO &, uint16_t T) : Type(RelocType(T)) {}    uint16_t denormalize(IO &) { return Type; } -  COFF::RelocationTypeX86 Type; +  RelocType Type;  };  }  void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO,                                                    COFFYAML::Relocation &Rel) { -  MappingNormalization<NType, uint16_t> NT(IO, Rel.Type); -    IO.mapRequired("VirtualAddress", Rel.VirtualAddress);    IO.mapRequired("SymbolName", Rel.SymbolName); -  IO.mapRequired("Type", NT->Type); + +  COFF::header &H = *static_cast<COFF::header *>(IO.getContext()); +  if (H.Machine == COFF::IMAGE_FILE_MACHINE_I386) { +    MappingNormalization<NType<COFF::RelocationTypeI386>, uint16_t> NT( +        IO, Rel.Type); +    IO.mapRequired("Type", NT->Type); +  } else if (H.Machine == COFF::IMAGE_FILE_MACHINE_AMD64) { +    MappingNormalization<NType<COFF::RelocationTypeAMD64>, uint16_t> NT( +        IO, Rel.Type); +    IO.mapRequired("Type", NT->Type); +  } else { +    IO.mapRequired("Type", Rel.Type); +  }  }  void MappingTraits<COFF::header>::mapping(IO &IO, COFF::header &H) { @@ -245,6 +313,49 @@ void MappingTraits<COFF::header>::mapping(IO &IO, COFF::header &H) {    IO.mapRequired("Machine", NM->Machine);    IO.mapOptional("Characteristics", NC->Characteristics); +  IO.setContext(static_cast<void *>(&H)); +} + +void MappingTraits<COFF::AuxiliaryFunctionDefinition>::mapping( +    IO &IO, COFF::AuxiliaryFunctionDefinition &AFD) { +  IO.mapRequired("TagIndex", AFD.TagIndex); +  IO.mapRequired("TotalSize", AFD.TotalSize); +  IO.mapRequired("PointerToLinenumber", AFD.PointerToLinenumber); +  IO.mapRequired("PointerToNextFunction", AFD.PointerToNextFunction); +} + +void MappingTraits<COFF::AuxiliarybfAndefSymbol>::mapping( +    IO &IO, COFF::AuxiliarybfAndefSymbol &AAS) { +  IO.mapRequired("Linenumber", AAS.Linenumber); +  IO.mapRequired("PointerToNextFunction", AAS.PointerToNextFunction); +} + +void MappingTraits<COFF::AuxiliaryWeakExternal>::mapping( +    IO &IO, COFF::AuxiliaryWeakExternal &AWE) { +  MappingNormalization<NWeakExternalCharacteristics, uint32_t> NWEC( +      IO, AWE.Characteristics); +  IO.mapRequired("TagIndex", AWE.TagIndex); +  IO.mapRequired("Characteristics", NWEC->Characteristics); +} + +void MappingTraits<COFF::AuxiliarySectionDefinition>::mapping( +    IO &IO, COFF::AuxiliarySectionDefinition &ASD) { +  MappingNormalization<NSectionSelectionType, uint8_t> NSST( +      IO, ASD.Selection); + +  IO.mapRequired("Length", ASD.Length); +  IO.mapRequired("NumberOfRelocations", ASD.NumberOfRelocations); +  IO.mapRequired("NumberOfLinenumbers", ASD.NumberOfLinenumbers); +  IO.mapRequired("CheckSum", ASD.CheckSum); +  IO.mapRequired("Number", ASD.Number); +  IO.mapOptional("Selection", NSST->SelectionType, COFFYAML::COMDATType(0)); +} + +void MappingTraits<COFF::AuxiliaryCLRToken>::mapping( +    IO &IO, COFF::AuxiliaryCLRToken &ACT) { +  MappingNormalization<NAuxTokenType, uint8_t> NATT(IO, ACT.AuxType); +  IO.mapRequired("AuxType", NATT->AuxType); +  IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex);  }  void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { @@ -256,9 +367,12 @@ void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) {    IO.mapRequired("SimpleType", S.SimpleType);    IO.mapRequired("ComplexType", S.ComplexType);    IO.mapRequired("StorageClass", NS->StorageClass); -  IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols, -                 (uint8_t) 0); -  IO.mapOptional("AuxiliaryData", S.AuxiliaryData, object::yaml::BinaryRef()); +  IO.mapOptional("FunctionDefinition", S.FunctionDefinition); +  IO.mapOptional("bfAndefSymbol", S.bfAndefSymbol); +  IO.mapOptional("WeakExternal", S.WeakExternal); +  IO.mapOptional("File", S.File, StringRef()); +  IO.mapOptional("SectionDefinition", S.SectionDefinition); +  IO.mapOptional("CLRToken", S.CLRToken);  }  void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { diff --git a/contrib/llvm/lib/Object/ELF.cpp b/contrib/llvm/lib/Object/ELF.cpp index 41d05197c23d..d999106ba982 100644 --- a/contrib/llvm/lib/Object/ELF.cpp +++ b/contrib/llvm/lib/Object/ELF.cpp @@ -159,6 +159,15 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC21_S2); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC26_S2); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC18_S3); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC19_S2); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PCHI16); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PCLO16); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_GOT16); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_HI16); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_LO16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_26_S1); @@ -170,11 +179,14 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_DISP);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_PAGE);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_OFST); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_GD); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_LDM);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_HI16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_LO16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_TPREL_HI16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_TPREL_LO16);        LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); +      LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC32);      default:        break;      } diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp index 15bc6be0b46e..4f0f60b62428 100644 --- a/contrib/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp @@ -17,57 +17,70 @@  namespace llvm {  using namespace object; -// Creates an in-memory object-file by default: createELFObjectFile(Buffer) -ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { -  std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); -  error_code ec; - +ErrorOr<ObjectFile *> +ObjectFile::createELFObjectFile(std::unique_ptr<MemoryBuffer> &Obj) { +  std::pair<unsigned char, unsigned char> Ident = +      getElfArchType(Obj->getBuffer());    std::size_t MaxAlignment = -    1ULL << countTrailingZeros(uintptr_t(Object->getBufferStart())); +    1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart())); +  std::error_code EC; +  std::unique_ptr<ObjectFile> R;    if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)  #if !LLVM_IS_UNALIGNED_ACCESS_FAST      if (MaxAlignment >= 4) -      return new ELFObjectFile<ELFType<support::little, 4, false> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::little, 4, false>>( +          std::move(Obj), EC));      else  #endif      if (MaxAlignment >= 2) -      return new ELFObjectFile<ELFType<support::little, 2, false> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::little, 2, false>>( +          std::move(Obj), EC));      else -      llvm_unreachable("Invalid alignment for ELF file!"); +      return object_error::parse_failed;    else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)  #if !LLVM_IS_UNALIGNED_ACCESS_FAST      if (MaxAlignment >= 4) -      return new ELFObjectFile<ELFType<support::big, 4, false> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::big, 4, false>>(std::move(Obj), +                                                                 EC));      else  #endif      if (MaxAlignment >= 2) -      return new ELFObjectFile<ELFType<support::big, 2, false> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::big, 2, false>>(std::move(Obj), +                                                                 EC));      else -      llvm_unreachable("Invalid alignment for ELF file!"); +      return object_error::parse_failed;    else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)  #if !LLVM_IS_UNALIGNED_ACCESS_FAST      if (MaxAlignment >= 8) -      return new ELFObjectFile<ELFType<support::big, 8, true> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::big, 8, true>>(std::move(Obj), +                                                                EC));      else  #endif      if (MaxAlignment >= 2) -      return new ELFObjectFile<ELFType<support::big, 2, true> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::big, 2, true>>(std::move(Obj), +                                                                EC));      else -      llvm_unreachable("Invalid alignment for ELF file!"); +      return object_error::parse_failed;    else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {  #if !LLVM_IS_UNALIGNED_ACCESS_FAST      if (MaxAlignment >= 8) -      return new ELFObjectFile<ELFType<support::little, 8, true> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::little, 8, true>>( +          std::move(Obj), EC));      else  #endif      if (MaxAlignment >= 2) -      return new ELFObjectFile<ELFType<support::little, 2, true> >(Object, ec); +      R.reset(new ELFObjectFile<ELFType<support::little, 2, true>>( +          std::move(Obj), EC));      else -      llvm_unreachable("Invalid alignment for ELF file!"); +      return object_error::parse_failed;    } +  else +    llvm_unreachable("Buffer is not an ELF object file!"); -  report_fatal_error("Buffer is not an ELF object file!"); +  if (EC) +    return EC; +  return R.release();  }  } // end namespace llvm diff --git a/contrib/llvm/lib/Object/ELFYAML.cpp b/contrib/llvm/lib/Object/ELFYAML.cpp index 2f35cf9b1036..6340841e5ee6 100644 --- a/contrib/llvm/lib/Object/ELFYAML.cpp +++ b/contrib/llvm/lib/Object/ELFYAML.cpp @@ -12,8 +12,12 @@  //===----------------------------------------------------------------------===//  #include "llvm/Object/ELFYAML.h" +#include "llvm/Support/Casting.h"  namespace llvm { + +ELFYAML::Section::~Section() {} +  namespace yaml {  void @@ -237,8 +241,65 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration(  #undef ECase  } +void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, +                                                 ELFYAML::ELF_EF &Value) { +  const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); +  assert(Object && "The IO context is not initialized"); +#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); +#define BCaseMask(X, M) IO.maskedBitSetCase(Value, #X, ELF::X, ELF::M); +  switch (Object->Header.Machine) { +  case ELF::EM_ARM: +    BCase(EF_ARM_SOFT_FLOAT) +    BCase(EF_ARM_VFP_FLOAT) +    BCaseMask(EF_ARM_EABI_UNKNOWN, EF_ARM_EABIMASK) +    BCaseMask(EF_ARM_EABI_VER1, EF_ARM_EABIMASK) +    BCaseMask(EF_ARM_EABI_VER2, EF_ARM_EABIMASK) +    BCaseMask(EF_ARM_EABI_VER3, EF_ARM_EABIMASK) +    BCaseMask(EF_ARM_EABI_VER4, EF_ARM_EABIMASK) +    BCaseMask(EF_ARM_EABI_VER5, EF_ARM_EABIMASK) +    break; +  case ELF::EM_MIPS: +    BCase(EF_MIPS_NOREORDER) +    BCase(EF_MIPS_PIC) +    BCase(EF_MIPS_CPIC) +    BCase(EF_MIPS_ABI2) +    BCase(EF_MIPS_32BITMODE) +    BCase(EF_MIPS_ABI_O32) +    BCase(EF_MIPS_MICROMIPS) +    BCase(EF_MIPS_ARCH_ASE_M16) +    BCaseMask(EF_MIPS_ARCH_1, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_2, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_3, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_4, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_5, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_32, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_64, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_32R2, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_64R2, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_32R6, EF_MIPS_ARCH) +    BCaseMask(EF_MIPS_ARCH_64R6, EF_MIPS_ARCH) +    break; +  case ELF::EM_HEXAGON: +    BCase(EF_HEXAGON_MACH_V2) +    BCase(EF_HEXAGON_MACH_V3) +    BCase(EF_HEXAGON_MACH_V4) +    BCase(EF_HEXAGON_MACH_V5) +    BCase(EF_HEXAGON_ISA_V2) +    BCase(EF_HEXAGON_ISA_V3) +    BCase(EF_HEXAGON_ISA_V4) +    BCase(EF_HEXAGON_ISA_V5) +    break; +  default: +    llvm_unreachable("Unsupported architecture"); +  } +#undef BCase +#undef BCaseMask +} +  void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(      IO &IO, ELFYAML::ELF_SHT &Value) { +  const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); +  assert(Object && "The IO context is not initialized");  #define ECase(X) IO.enumCase(Value, #X, ELF::X);    ECase(SHT_NULL)    ECase(SHT_PROGBITS) @@ -258,6 +319,37 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(    ECase(SHT_PREINIT_ARRAY)    ECase(SHT_GROUP)    ECase(SHT_SYMTAB_SHNDX) +  ECase(SHT_LOOS) +  ECase(SHT_GNU_ATTRIBUTES) +  ECase(SHT_GNU_HASH) +  ECase(SHT_GNU_verdef) +  ECase(SHT_GNU_verneed) +  ECase(SHT_GNU_versym) +  ECase(SHT_HIOS) +  ECase(SHT_LOPROC) +  switch (Object->Header.Machine) { +  case ELF::EM_ARM: +    ECase(SHT_ARM_EXIDX) +    ECase(SHT_ARM_PREEMPTMAP) +    ECase(SHT_ARM_ATTRIBUTES) +    ECase(SHT_ARM_DEBUGOVERLAY) +    ECase(SHT_ARM_OVERLAYSECTION) +    break; +  case ELF::EM_HEXAGON: +    ECase(SHT_HEX_ORDERED) +    break; +  case ELF::EM_X86_64: +    ECase(SHT_X86_64_UNWIND) +    break; +  case ELF::EM_MIPS: +    ECase(SHT_MIPS_REGINFO) +    ECase(SHT_MIPS_OPTIONS) +    ECase(SHT_MIPS_ABIFLAGS) +    break; +  default: +    // Nothing to do. +    break; +  }  #undef ECase  } @@ -292,6 +384,280 @@ void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration(  #undef ECase  } +void ScalarEnumerationTraits<ELFYAML::ELF_STV>::enumeration( +    IO &IO, ELFYAML::ELF_STV &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); +  ECase(STV_DEFAULT) +  ECase(STV_INTERNAL) +  ECase(STV_HIDDEN) +  ECase(STV_PROTECTED) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( +    IO &IO, ELFYAML::ELF_REL &Value) { +  const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); +  assert(Object && "The IO context is not initialized"); +#define ECase(X) IO.enumCase(Value, #X, ELF::X); +  switch (Object->Header.Machine) { +  case ELF::EM_X86_64: +    ECase(R_X86_64_NONE) +    ECase(R_X86_64_64) +    ECase(R_X86_64_PC32) +    ECase(R_X86_64_GOT32) +    ECase(R_X86_64_PLT32) +    ECase(R_X86_64_COPY) +    ECase(R_X86_64_GLOB_DAT) +    ECase(R_X86_64_JUMP_SLOT) +    ECase(R_X86_64_RELATIVE) +    ECase(R_X86_64_GOTPCREL) +    ECase(R_X86_64_32) +    ECase(R_X86_64_32S) +    ECase(R_X86_64_16) +    ECase(R_X86_64_PC16) +    ECase(R_X86_64_8) +    ECase(R_X86_64_PC8) +    ECase(R_X86_64_DTPMOD64) +    ECase(R_X86_64_DTPOFF64) +    ECase(R_X86_64_TPOFF64) +    ECase(R_X86_64_TLSGD) +    ECase(R_X86_64_TLSLD) +    ECase(R_X86_64_DTPOFF32) +    ECase(R_X86_64_GOTTPOFF) +    ECase(R_X86_64_TPOFF32) +    ECase(R_X86_64_PC64) +    ECase(R_X86_64_GOTOFF64) +    ECase(R_X86_64_GOTPC32) +    ECase(R_X86_64_GOT64) +    ECase(R_X86_64_GOTPCREL64) +    ECase(R_X86_64_GOTPC64) +    ECase(R_X86_64_GOTPLT64) +    ECase(R_X86_64_PLTOFF64) +    ECase(R_X86_64_SIZE32) +    ECase(R_X86_64_SIZE64) +    ECase(R_X86_64_GOTPC32_TLSDESC) +    ECase(R_X86_64_TLSDESC_CALL) +    ECase(R_X86_64_TLSDESC) +    ECase(R_X86_64_IRELATIVE) +    break; +  case ELF::EM_MIPS: +    ECase(R_MIPS_NONE) +    ECase(R_MIPS_16) +    ECase(R_MIPS_32) +    ECase(R_MIPS_REL32) +    ECase(R_MIPS_26) +    ECase(R_MIPS_HI16) +    ECase(R_MIPS_LO16) +    ECase(R_MIPS_GPREL16) +    ECase(R_MIPS_LITERAL) +    ECase(R_MIPS_GOT16) +    ECase(R_MIPS_PC16) +    ECase(R_MIPS_CALL16) +    ECase(R_MIPS_GPREL32) +    ECase(R_MIPS_UNUSED1) +    ECase(R_MIPS_UNUSED2) +    ECase(R_MIPS_SHIFT5) +    ECase(R_MIPS_SHIFT6) +    ECase(R_MIPS_64) +    ECase(R_MIPS_GOT_DISP) +    ECase(R_MIPS_GOT_PAGE) +    ECase(R_MIPS_GOT_OFST) +    ECase(R_MIPS_GOT_HI16) +    ECase(R_MIPS_GOT_LO16) +    ECase(R_MIPS_SUB) +    ECase(R_MIPS_INSERT_A) +    ECase(R_MIPS_INSERT_B) +    ECase(R_MIPS_DELETE) +    ECase(R_MIPS_HIGHER) +    ECase(R_MIPS_HIGHEST) +    ECase(R_MIPS_CALL_HI16) +    ECase(R_MIPS_CALL_LO16) +    ECase(R_MIPS_SCN_DISP) +    ECase(R_MIPS_REL16) +    ECase(R_MIPS_ADD_IMMEDIATE) +    ECase(R_MIPS_PJUMP) +    ECase(R_MIPS_RELGOT) +    ECase(R_MIPS_JALR) +    ECase(R_MIPS_TLS_DTPMOD32) +    ECase(R_MIPS_TLS_DTPREL32) +    ECase(R_MIPS_TLS_DTPMOD64) +    ECase(R_MIPS_TLS_DTPREL64) +    ECase(R_MIPS_TLS_GD) +    ECase(R_MIPS_TLS_LDM) +    ECase(R_MIPS_TLS_DTPREL_HI16) +    ECase(R_MIPS_TLS_DTPREL_LO16) +    ECase(R_MIPS_TLS_GOTTPREL) +    ECase(R_MIPS_TLS_TPREL32) +    ECase(R_MIPS_TLS_TPREL64) +    ECase(R_MIPS_TLS_TPREL_HI16) +    ECase(R_MIPS_TLS_TPREL_LO16) +    ECase(R_MIPS_GLOB_DAT) +    ECase(R_MIPS_PC21_S2) +    ECase(R_MIPS_PC26_S2) +    ECase(R_MIPS_PC18_S3) +    ECase(R_MIPS_PC19_S2) +    ECase(R_MIPS_PCHI16) +    ECase(R_MIPS_PCLO16) +    ECase(R_MIPS16_GOT16) +    ECase(R_MIPS16_HI16) +    ECase(R_MIPS16_LO16) +    ECase(R_MIPS_COPY) +    ECase(R_MIPS_JUMP_SLOT) +    ECase(R_MICROMIPS_26_S1) +    ECase(R_MICROMIPS_HI16) +    ECase(R_MICROMIPS_LO16) +    ECase(R_MICROMIPS_GOT16) +    ECase(R_MICROMIPS_PC16_S1) +    ECase(R_MICROMIPS_CALL16) +    ECase(R_MICROMIPS_GOT_DISP) +    ECase(R_MICROMIPS_GOT_PAGE) +    ECase(R_MICROMIPS_GOT_OFST) +    ECase(R_MICROMIPS_TLS_GD) +    ECase(R_MICROMIPS_TLS_LDM) +    ECase(R_MICROMIPS_TLS_DTPREL_HI16) +    ECase(R_MICROMIPS_TLS_DTPREL_LO16) +    ECase(R_MICROMIPS_TLS_TPREL_HI16) +    ECase(R_MICROMIPS_TLS_TPREL_LO16) +    ECase(R_MIPS_NUM) +    ECase(R_MIPS_PC32) +    break; +  case ELF::EM_HEXAGON: +    ECase(R_HEX_NONE) +    ECase(R_HEX_B22_PCREL) +    ECase(R_HEX_B15_PCREL) +    ECase(R_HEX_B7_PCREL) +    ECase(R_HEX_LO16) +    ECase(R_HEX_HI16) +    ECase(R_HEX_32) +    ECase(R_HEX_16) +    ECase(R_HEX_8) +    ECase(R_HEX_GPREL16_0) +    ECase(R_HEX_GPREL16_1) +    ECase(R_HEX_GPREL16_2) +    ECase(R_HEX_GPREL16_3) +    ECase(R_HEX_HL16) +    ECase(R_HEX_B13_PCREL) +    ECase(R_HEX_B9_PCREL) +    ECase(R_HEX_B32_PCREL_X) +    ECase(R_HEX_32_6_X) +    ECase(R_HEX_B22_PCREL_X) +    ECase(R_HEX_B15_PCREL_X) +    ECase(R_HEX_B13_PCREL_X) +    ECase(R_HEX_B9_PCREL_X) +    ECase(R_HEX_B7_PCREL_X) +    ECase(R_HEX_16_X) +    ECase(R_HEX_12_X) +    ECase(R_HEX_11_X) +    ECase(R_HEX_10_X) +    ECase(R_HEX_9_X) +    ECase(R_HEX_8_X) +    ECase(R_HEX_7_X) +    ECase(R_HEX_6_X) +    ECase(R_HEX_32_PCREL) +    ECase(R_HEX_COPY) +    ECase(R_HEX_GLOB_DAT) +    ECase(R_HEX_JMP_SLOT) +    ECase(R_HEX_RELATIVE) +    ECase(R_HEX_PLT_B22_PCREL) +    ECase(R_HEX_GOTREL_LO16) +    ECase(R_HEX_GOTREL_HI16) +    ECase(R_HEX_GOTREL_32) +    ECase(R_HEX_GOT_LO16) +    ECase(R_HEX_GOT_HI16) +    ECase(R_HEX_GOT_32) +    ECase(R_HEX_GOT_16) +    ECase(R_HEX_DTPMOD_32) +    ECase(R_HEX_DTPREL_LO16) +    ECase(R_HEX_DTPREL_HI16) +    ECase(R_HEX_DTPREL_32) +    ECase(R_HEX_DTPREL_16) +    ECase(R_HEX_GD_PLT_B22_PCREL) +    ECase(R_HEX_GD_GOT_LO16) +    ECase(R_HEX_GD_GOT_HI16) +    ECase(R_HEX_GD_GOT_32) +    ECase(R_HEX_GD_GOT_16) +    ECase(R_HEX_IE_LO16) +    ECase(R_HEX_IE_HI16) +    ECase(R_HEX_IE_32) +    ECase(R_HEX_IE_GOT_LO16) +    ECase(R_HEX_IE_GOT_HI16) +    ECase(R_HEX_IE_GOT_32) +    ECase(R_HEX_IE_GOT_16) +    ECase(R_HEX_TPREL_LO16) +    ECase(R_HEX_TPREL_HI16) +    ECase(R_HEX_TPREL_32) +    ECase(R_HEX_TPREL_16) +    ECase(R_HEX_6_PCREL_X) +    ECase(R_HEX_GOTREL_32_6_X) +    ECase(R_HEX_GOTREL_16_X) +    ECase(R_HEX_GOTREL_11_X) +    ECase(R_HEX_GOT_32_6_X) +    ECase(R_HEX_GOT_16_X) +    ECase(R_HEX_GOT_11_X) +    ECase(R_HEX_DTPREL_32_6_X) +    ECase(R_HEX_DTPREL_16_X) +    ECase(R_HEX_DTPREL_11_X) +    ECase(R_HEX_GD_GOT_32_6_X) +    ECase(R_HEX_GD_GOT_16_X) +    ECase(R_HEX_GD_GOT_11_X) +    ECase(R_HEX_IE_32_6_X) +    ECase(R_HEX_IE_16_X) +    ECase(R_HEX_IE_GOT_32_6_X) +    ECase(R_HEX_IE_GOT_16_X) +    ECase(R_HEX_IE_GOT_11_X) +    ECase(R_HEX_TPREL_32_6_X) +    ECase(R_HEX_TPREL_16_X) +    ECase(R_HEX_TPREL_11_X) +    break; +  case ELF::EM_386: +    ECase(R_386_NONE) +    ECase(R_386_32) +    ECase(R_386_PC32) +    ECase(R_386_GOT32) +    ECase(R_386_PLT32) +    ECase(R_386_COPY) +    ECase(R_386_GLOB_DAT) +    ECase(R_386_JUMP_SLOT) +    ECase(R_386_RELATIVE) +    ECase(R_386_GOTOFF) +    ECase(R_386_GOTPC) +    ECase(R_386_32PLT) +    ECase(R_386_TLS_TPOFF) +    ECase(R_386_TLS_IE) +    ECase(R_386_TLS_GOTIE) +    ECase(R_386_TLS_LE) +    ECase(R_386_TLS_GD) +    ECase(R_386_TLS_LDM) +    ECase(R_386_16) +    ECase(R_386_PC16) +    ECase(R_386_8) +    ECase(R_386_PC8) +    ECase(R_386_TLS_GD_32) +    ECase(R_386_TLS_GD_PUSH) +    ECase(R_386_TLS_GD_CALL) +    ECase(R_386_TLS_GD_POP) +    ECase(R_386_TLS_LDM_32) +    ECase(R_386_TLS_LDM_PUSH) +    ECase(R_386_TLS_LDM_CALL) +    ECase(R_386_TLS_LDM_POP) +    ECase(R_386_TLS_LDO_32) +    ECase(R_386_TLS_IE_32) +    ECase(R_386_TLS_LE_32) +    ECase(R_386_TLS_DTPMOD32) +    ECase(R_386_TLS_DTPOFF32) +    ECase(R_386_TLS_TPOFF32) +    ECase(R_386_TLS_GOTDESC) +    ECase(R_386_TLS_DESC_CALL) +    ECase(R_386_TLS_DESC) +    ECase(R_386_IRELATIVE) +    ECase(R_386_NUM) +    break; +  default: +    llvm_unreachable("Unsupported architecture"); +  } +#undef ECase +} +  void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,                                                   ELFYAML::FileHeader &FileHdr) {    IO.mapRequired("Class", FileHdr.Class); @@ -299,6 +665,7 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO,    IO.mapOptional("OSABI", FileHdr.OSABI, ELFYAML::ELF_ELFOSABI(0));    IO.mapRequired("Type", FileHdr.Type);    IO.mapRequired("Machine", FileHdr.Machine); +  IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0));    IO.mapOptional("Entry", FileHdr.Entry, Hex64(0));  } @@ -308,6 +675,7 @@ void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) {    IO.mapOptional("Section", Symbol.Section, StringRef());    IO.mapOptional("Value", Symbol.Value, Hex64(0));    IO.mapOptional("Size", Symbol.Size, Hex64(0)); +  IO.mapOptional("Visibility", Symbol.Visibility, ELFYAML::ELF_STV(0));  }  void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping( @@ -317,21 +685,72 @@ void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping(    IO.mapOptional("Weak", Symbols.Weak);  } -void MappingTraits<ELFYAML::Section>::mapping(IO &IO, -                                              ELFYAML::Section &Section) { +static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) {    IO.mapOptional("Name", Section.Name, StringRef());    IO.mapRequired("Type", Section.Type);    IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0));    IO.mapOptional("Address", Section.Address, Hex64(0)); -  IO.mapOptional("Content", Section.Content); -  IO.mapOptional("Link", Section.Link); +  IO.mapOptional("Link", Section.Link, StringRef());    IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0));  } +static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { +  commonSectionMapping(IO, Section); +  IO.mapOptional("Content", Section.Content); +  IO.mapOptional("Size", Section.Size, Hex64(Section.Content.binary_size())); +} + +static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { +  commonSectionMapping(IO, Section); +  IO.mapOptional("Info", Section.Info, StringRef()); +  IO.mapOptional("Relocations", Section.Relocations); +} + +void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( +    IO &IO, std::unique_ptr<ELFYAML::Section> &Section) { +  ELFYAML::ELF_SHT sectionType; +  if (IO.outputting()) +    sectionType = Section->Type; +  else +    IO.mapRequired("Type", sectionType); + +  switch (sectionType) { +  case ELF::SHT_REL: +  case ELF::SHT_RELA: +    if (!IO.outputting()) +      Section.reset(new ELFYAML::RelocationSection()); +    sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get())); +    break; +  default: +    if (!IO.outputting()) +      Section.reset(new ELFYAML::RawContentSection()); +    sectionMapping(IO, *cast<ELFYAML::RawContentSection>(Section.get())); +  } +} + +StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( +    IO &io, std::unique_ptr<ELFYAML::Section> &Section) { +  const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(Section.get()); +  if (!RawSection || RawSection->Size >= RawSection->Content.binary_size()) +    return StringRef(); +  return "Section size must be greater or equal to the content size"; +} + +void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, +                                                 ELFYAML::Relocation &Rel) { +  IO.mapRequired("Offset", Rel.Offset); +  IO.mapRequired("Symbol", Rel.Symbol); +  IO.mapRequired("Type", Rel.Type); +  IO.mapOptional("Addend", Rel.Addend); +} +  void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { +  assert(!IO.getContext() && "The IO context is initialized already"); +  IO.setContext(&Object);    IO.mapRequired("FileHeader", Object.Header);    IO.mapOptional("Sections", Object.Sections);    IO.mapOptional("Symbols", Object.Symbols); +  IO.setContext(nullptr);  }  } // end namespace yaml diff --git a/contrib/llvm/lib/Object/Error.cpp b/contrib/llvm/lib/Object/Error.cpp index 47ce38c88839..9d252697ae52 100644 --- a/contrib/llvm/lib/Object/Error.cpp +++ b/contrib/llvm/lib/Object/Error.cpp @@ -18,11 +18,10 @@ using namespace llvm;  using namespace object;  namespace { -class _object_error_category : public _do_message { +class _object_error_category : public std::error_category {  public: -  virtual const char* name() const; -  virtual std::string message(int ev) const; -  virtual error_condition default_error_condition(int ev) const; +  const char* name() const LLVM_NOEXCEPT override; +  std::string message(int ev) const override;  };  } @@ -30,8 +29,8 @@ const char *_object_error_category::name() const {    return "llvm.object";  } -std::string _object_error_category::message(int ev) const { -  object_error::Impl E = static_cast<object_error::Impl>(ev); +std::string _object_error_category::message(int EV) const { +  object_error E = static_cast<object_error>(EV);    switch (E) {    case object_error::success: return "Success";    case object_error::arch_not_found: @@ -47,13 +46,7 @@ std::string _object_error_category::message(int ev) const {                     "defined.");  } -error_condition _object_error_category::default_error_condition(int ev) const { -  if (ev == object_error::success) -    return errc::success; -  return errc::invalid_argument; -} - -const error_category &object::object_category() { +const std::error_category &object::object_category() {    static _object_error_category o;    return o;  } diff --git a/contrib/llvm/lib/Object/IRObjectFile.cpp b/contrib/llvm/lib/Object/IRObjectFile.cpp new file mode 100644 index 000000000000..5323d9277eee --- /dev/null +++ b/contrib/llvm/lib/Object/IRObjectFile.cpp @@ -0,0 +1,279 @@ +//===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Part of the IRObjectFile class implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/IRObjectFile.h" +#include "RecordStreamer.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/GVMaterializer.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace object; + +IRObjectFile::IRObjectFile(std::unique_ptr<MemoryBuffer> Object, +                           std::unique_ptr<Module> Mod) +    : SymbolicFile(Binary::ID_IR, std::move(Object)), M(std::move(Mod)) { +  // If we have a DataLayout, setup a mangler. +  const DataLayout *DL = M->getDataLayout(); +  if (!DL) +    return; + +  Mang.reset(new Mangler(DL)); + +  const std::string &InlineAsm = M->getModuleInlineAsm(); +  if (InlineAsm.empty()) +    return; + +  StringRef Triple = M->getTargetTriple(); +  std::string Err; +  const Target *T = TargetRegistry::lookupTarget(Triple, Err); +  if (!T) +    return; + +  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); +  if (!MRI) +    return; + +  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); +  if (!MAI) +    return; + +  std::unique_ptr<MCSubtargetInfo> STI( +      T->createMCSubtargetInfo(Triple, "", "")); +  if (!STI) +    return; + +  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); +  if (!MCII) +    return; + +  MCObjectFileInfo MOFI; +  MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); +  MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); +  std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); + +  std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); +  SourceMgr SrcMgr; +  SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); +  std::unique_ptr<MCAsmParser> Parser( +      createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); + +  MCTargetOptions MCOptions; +  std::unique_ptr<MCTargetAsmParser> TAP( +      T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); +  if (!TAP) +    return; + +  Parser->setTargetParser(*TAP); +  if (Parser->Run(false)) +    return; + +  for (auto &KV : *Streamer) { +    StringRef Key = KV.first(); +    RecordStreamer::State Value = KV.second; +    uint32_t Res = BasicSymbolRef::SF_None; +    switch (Value) { +    case RecordStreamer::NeverSeen: +      llvm_unreachable("foo"); +    case RecordStreamer::DefinedGlobal: +      Res |= BasicSymbolRef::SF_Global; +      break; +    case RecordStreamer::Defined: +      break; +    case RecordStreamer::Global: +    case RecordStreamer::Used: +      Res |= BasicSymbolRef::SF_Undefined; +      Res |= BasicSymbolRef::SF_Global; +      break; +    } +    AsmSymbols.push_back( +        std::make_pair<std::string, uint32_t>(Key, std::move(Res))); +  } +} + +IRObjectFile::~IRObjectFile() { +  GVMaterializer *GVM =  M->getMaterializer(); +  if (GVM) +    GVM->releaseBuffer(); + } + +static const GlobalValue *getGV(DataRefImpl &Symb) { +  if ((Symb.p & 3) == 3) +    return nullptr; + +  return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); +} + +static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { +  if (I == M.alias_end()) +    return 3; +  const GlobalValue *GV = &*I; +  return reinterpret_cast<uintptr_t>(GV) | 2; +} + +static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { +  if (I == M.global_end()) +    return skipEmpty(M.alias_begin(), M); +  const GlobalValue *GV = &*I; +  return reinterpret_cast<uintptr_t>(GV) | 1; +} + +static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { +  if (I == M.end()) +    return skipEmpty(M.global_begin(), M); +  const GlobalValue *GV = &*I; +  return reinterpret_cast<uintptr_t>(GV) | 0; +} + +static unsigned getAsmSymIndex(DataRefImpl Symb) { +  assert((Symb.p & uintptr_t(3)) == 3); +  uintptr_t Index = Symb.p & ~uintptr_t(3); +  Index >>= 2; +  return Index; +} + +void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { +  const GlobalValue *GV = getGV(Symb); +  uintptr_t Res; + +  switch (Symb.p & 3) { +  case 0: { +    Module::const_iterator Iter(static_cast<const Function*>(GV)); +    ++Iter; +    Res = skipEmpty(Iter, *M); +    break; +  } +  case 1: { +    Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); +    ++Iter; +    Res = skipEmpty(Iter, *M); +    break; +  } +  case 2: { +    Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); +    ++Iter; +    Res = skipEmpty(Iter, *M); +    break; +  } +  case 3: { +    unsigned Index = getAsmSymIndex(Symb); +    assert(Index < AsmSymbols.size()); +    ++Index; +    Res = (Index << 2) | 3; +    break; +  } +  } + +  Symb.p = Res; +} + +std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, +                                              DataRefImpl Symb) const { +  const GlobalValue *GV = getGV(Symb); +  if (!GV) { +    unsigned Index = getAsmSymIndex(Symb); +    assert(Index <= AsmSymbols.size()); +    OS << AsmSymbols[Index].first; +    return object_error::success;; +  } + +  if (Mang) +    Mang->getNameWithPrefix(OS, GV, false); +  else +    OS << GV->getName(); + +  return object_error::success; +} + +static bool isDeclaration(const GlobalValue &V) { +  if (V.hasAvailableExternallyLinkage()) +    return true; + +  if (V.isMaterializable()) +    return false; + +  return V.isDeclaration(); +} + +uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { +  const GlobalValue *GV = getGV(Symb); + +  if (!GV) { +    unsigned Index = getAsmSymIndex(Symb); +    assert(Index <= AsmSymbols.size()); +    return AsmSymbols[Index].second; +  } + +  uint32_t Res = BasicSymbolRef::SF_None; +  if (isDeclaration(*GV)) +    Res |= BasicSymbolRef::SF_Undefined; +  if (GV->hasPrivateLinkage()) +    Res |= BasicSymbolRef::SF_FormatSpecific; +  if (!GV->hasLocalLinkage()) +    Res |= BasicSymbolRef::SF_Global; +  if (GV->hasCommonLinkage()) +    Res |= BasicSymbolRef::SF_Common; +  if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) +    Res |= BasicSymbolRef::SF_Weak; + +  if (GV->getName().startswith("llvm.")) +    Res |= BasicSymbolRef::SF_FormatSpecific; +  else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { +    if (Var->getSection() == StringRef("llvm.metadata")) +      Res |= BasicSymbolRef::SF_FormatSpecific; +  } + +  return Res; +} + +const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { +  const GlobalValue *GV = getGV(Symb); +  return GV; +} + +basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { +  Module::const_iterator I = M->begin(); +  DataRefImpl Ret; +  Ret.p = skipEmpty(I, *M); +  return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +basic_symbol_iterator IRObjectFile::symbol_end_impl() const { +  DataRefImpl Ret; +  uint64_t NumAsm = AsmSymbols.size(); +  NumAsm <<= 2; +  Ret.p = 3 | NumAsm; +  return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +ErrorOr<IRObjectFile *> llvm::object::IRObjectFile::createIRObjectFile( +    std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) { +  ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Object.get(), Context); +  if (std::error_code EC = MOrErr.getError()) +    return EC; + +  std::unique_ptr<Module> M(MOrErr.get()); +  return new IRObjectFile(std::move(Object), std::move(M)); +} diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp index d2cb8bde6d24..51c4c332c182 100644 --- a/contrib/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -13,6 +13,7 @@  //===----------------------------------------------------------------------===//  #include "llvm/Object/MachO.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/Triple.h"  #include "llvm/Support/DataExtractor.h"  #include "llvm/Support/Format.h" @@ -26,206 +27,19 @@  using namespace llvm;  using namespace object; -namespace llvm { -namespace object { - -struct nlist_base { -  uint32_t n_strx; -  uint8_t n_type; -  uint8_t n_sect; -  uint16_t n_desc; -}; - -struct section_base { -  char sectname[16]; -  char segname[16]; -}; - -template<typename T> -static void SwapValue(T &Value) { -  Value = sys::SwapByteOrder(Value); +namespace { +  struct section_base { +    char sectname[16]; +    char segname[16]; +  };  }  template<typename T> -static void SwapStruct(T &Value); - -template<> -void SwapStruct(MachO::any_relocation_info &H) { -  SwapValue(H.r_word0); -  SwapValue(H.r_word1); -} - -template<> -void SwapStruct(MachO::load_command &L) { -  SwapValue(L.cmd); -  SwapValue(L.cmdsize); -} - -template<> -void SwapStruct(nlist_base &S) { -  SwapValue(S.n_strx); -  SwapValue(S.n_desc); -} - -template<> -void SwapStruct(MachO::section &S) { -  SwapValue(S.addr); -  SwapValue(S.size); -  SwapValue(S.offset); -  SwapValue(S.align); -  SwapValue(S.reloff); -  SwapValue(S.nreloc); -  SwapValue(S.flags); -  SwapValue(S.reserved1); -  SwapValue(S.reserved2); -} - -template<> -void SwapStruct(MachO::section_64 &S) { -  SwapValue(S.addr); -  SwapValue(S.size); -  SwapValue(S.offset); -  SwapValue(S.align); -  SwapValue(S.reloff); -  SwapValue(S.nreloc); -  SwapValue(S.flags); -  SwapValue(S.reserved1); -  SwapValue(S.reserved2); -  SwapValue(S.reserved3); -} - -template<> -void SwapStruct(MachO::nlist &S) { -  SwapValue(S.n_strx); -  SwapValue(S.n_desc); -  SwapValue(S.n_value); -} - -template<> -void SwapStruct(MachO::nlist_64 &S) { -  SwapValue(S.n_strx); -  SwapValue(S.n_desc); -  SwapValue(S.n_value); -} - -template<> -void SwapStruct(MachO::mach_header &H) { -  SwapValue(H.magic); -  SwapValue(H.cputype); -  SwapValue(H.cpusubtype); -  SwapValue(H.filetype); -  SwapValue(H.ncmds); -  SwapValue(H.sizeofcmds); -  SwapValue(H.flags); -} - -template<> -void SwapStruct(MachO::mach_header_64 &H) { -  SwapValue(H.magic); -  SwapValue(H.cputype); -  SwapValue(H.cpusubtype); -  SwapValue(H.filetype); -  SwapValue(H.ncmds); -  SwapValue(H.sizeofcmds); -  SwapValue(H.flags); -  SwapValue(H.reserved); -} - -template<> -void SwapStruct(MachO::symtab_command &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.symoff); -  SwapValue(C.nsyms); -  SwapValue(C.stroff); -  SwapValue(C.strsize); -} - -template<> -void SwapStruct(MachO::dysymtab_command &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.ilocalsym); -  SwapValue(C.nlocalsym); -  SwapValue(C.iextdefsym); -  SwapValue(C.nextdefsym); -  SwapValue(C.iundefsym); -  SwapValue(C.nundefsym); -  SwapValue(C.tocoff); -  SwapValue(C.ntoc); -  SwapValue(C.modtaboff); -  SwapValue(C.nmodtab); -  SwapValue(C.extrefsymoff); -  SwapValue(C.nextrefsyms); -  SwapValue(C.indirectsymoff); -  SwapValue(C.nindirectsyms); -  SwapValue(C.extreloff); -  SwapValue(C.nextrel); -  SwapValue(C.locreloff); -  SwapValue(C.nlocrel); -} - -template<> -void SwapStruct(MachO::linkedit_data_command &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.dataoff); -  SwapValue(C.datasize); -} - -template<> -void SwapStruct(MachO::segment_command &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.vmaddr); -  SwapValue(C.vmsize); -  SwapValue(C.fileoff); -  SwapValue(C.filesize); -  SwapValue(C.maxprot); -  SwapValue(C.initprot); -  SwapValue(C.nsects); -  SwapValue(C.flags); -} - -template<> -void SwapStruct(MachO::segment_command_64 &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.vmaddr); -  SwapValue(C.vmsize); -  SwapValue(C.fileoff); -  SwapValue(C.filesize); -  SwapValue(C.maxprot); -  SwapValue(C.initprot); -  SwapValue(C.nsects); -  SwapValue(C.flags); -} - -template<> -void SwapStruct(uint32_t &C) { -  SwapValue(C); -} - -template<> -void SwapStruct(MachO::linker_options_command &C) { -  SwapValue(C.cmd); -  SwapValue(C.cmdsize); -  SwapValue(C.count); -} - -template<> -void SwapStruct(MachO::data_in_code_entry &C) { -  SwapValue(C.offset); -  SwapValue(C.length); -  SwapValue(C.kind); -} - -template<typename T> -T getStruct(const MachOObjectFile *O, const char *P) { +static T getStruct(const MachOObjectFile *O, const char *P) {    T Cmd;    memcpy(&Cmd, P, sizeof(T));    if (O->isLittleEndian() != sys::IsLittleEndianHost) -    SwapStruct(Cmd); +    MachO::swapStruct(Cmd);    return Cmd;  } @@ -259,10 +73,10 @@ static const char *getPtr(const MachOObjectFile *O, size_t Offset) {    return O->getData().substr(Offset, 1).data();  } -static nlist_base +static MachO::nlist_base  getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) {    const char *P = reinterpret_cast<const char *>(DRI.p); -  return getStruct<nlist_base>(O, P); +  return getStruct<MachO::nlist_base>(O, P);  }  static StringRef parseSegmentOrSectionName(const char *P) { @@ -275,18 +89,9 @@ static StringRef parseSegmentOrSectionName(const char *P) {  // Helper to advance a section or symbol iterator multiple increments at a time.  template<class T> -static error_code advance(T &it, size_t Val) { -  error_code ec; -  while (Val--) { -    it.increment(ec); -  } -  return ec; -} - -template<class T> -static void advanceTo(T &it, size_t Val) { -  if (error_code ec = advance(it, Val)) -    report_fatal_error(ec.message()); +static void advance(T &it, size_t Val) { +  while (Val--) +    ++it;  }  static unsigned getCPUType(const MachOObjectFile *O) { @@ -305,18 +110,16 @@ static void printRelocationTargetName(const MachOObjectFile *O,    if (IsScattered) {      uint32_t Val = O->getPlainRelocationSymbolNum(RE); -    error_code ec; -    for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols(); -         SI != SE; SI.increment(ec)) { -      if (ec) report_fatal_error(ec.message()); - +    for (const SymbolRef &Symbol : O->symbols()) { +      std::error_code ec;        uint64_t Addr;        StringRef Name; -      if ((ec = SI->getAddress(Addr))) +      if ((ec = Symbol.getAddress(Addr)))          report_fatal_error(ec.message()); -      if (Addr != Val) continue; -      if ((ec = SI->getName(Name))) +      if (Addr != Val) +        continue; +      if ((ec = Symbol.getName(Name)))          report_fatal_error(ec.message());        fmt << Name;        return; @@ -324,17 +127,16 @@ static void printRelocationTargetName(const MachOObjectFile *O,      // If we couldn't find a symbol that this relocation refers to, try      // to find a section beginning instead. -    for (section_iterator SI = O->begin_sections(), SE = O->end_sections(); -         SI != SE; SI.increment(ec)) { -      if (ec) report_fatal_error(ec.message()); - +    for (const SectionRef &Section : O->sections()) { +      std::error_code ec;        uint64_t Addr;        StringRef Name; -      if ((ec = SI->getAddress(Addr))) +      if ((ec = Section.getAddress(Addr)))          report_fatal_error(ec.message()); -      if (Addr != Val) continue; -      if ((ec = SI->getName(Name))) +      if (Addr != Val) +        continue; +      if ((ec = Section.getName(Name)))          report_fatal_error(ec.message());        fmt << Name;        return; @@ -349,13 +151,13 @@ static void printRelocationTargetName(const MachOObjectFile *O,    uint64_t Val = O->getPlainRelocationSymbolNum(RE);    if (isExtern) { -    symbol_iterator SI = O->begin_symbols(); -    advanceTo(SI, Val); +    symbol_iterator SI = O->symbol_begin(); +    advance(SI, Val);      SI->getName(S);    } else { -    section_iterator SI = O->begin_sections(); +    section_iterator SI = O->section_begin();      // Adjust for the fact that sections are 1-indexed. -    advanceTo(SI, Val - 1); +    advance(SI, Val - 1);      SI->getName(S);    } @@ -419,11 +221,12 @@ static uint32_t getSectionFlags(const MachOObjectFile *O,    return Sect.flags;  } -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, +MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object,                                   bool IsLittleEndian, bool Is64bits, -                                 error_code &ec) -    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), -      SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { +                                 std::error_code &EC) +    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), +      SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), +      DataInCodeLoadCmd(nullptr) {    uint32_t LoadCommandCount = this->getHeader().ncmds;    MachO::LoadCommandType SegmentLoadType = is64Bit() ?      MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; @@ -445,6 +248,12 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,          const char *Sec = getSectionPtr(this, Load, J);          Sections.push_back(Sec);        } +    } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || +               Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || +               Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || +               Load.C.cmd == MachO::LC_REEXPORT_DYLIB || +               Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { +      Libraries.push_back(Load.Ptr);      }      if (I == LoadCommandCount - 1) @@ -454,66 +263,71 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object,    }  } -error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, -                                          SymbolRef &Res) const { +void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {    unsigned SymbolTableEntrySize = is64Bit() ?      sizeof(MachO::nlist_64) :      sizeof(MachO::nlist);    Symb.p += SymbolTableEntrySize; -  Res = SymbolRef(Symb, this); -  return object_error::success;  } -error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, -                                          StringRef &Res) const { +std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, +                                               StringRef &Res) const {    StringRef StringTable = getStringTableData(); -  nlist_base Entry = getSymbolTableEntryBase(this, Symb); +  MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);    const char *Start = &StringTable.data()[Entry.n_strx];    Res = StringRef(Start);    return object_error::success;  } -error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, -                                             uint64_t &Res) const { +// getIndirectName() returns the name of the alias'ed symbol who's string table +// index is in the n_value field. +std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, +                                                 StringRef &Res) const { +  StringRef StringTable = getStringTableData(); +  uint64_t NValue;    if (is64Bit()) {      MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); -    Res = Entry.n_value; +    NValue = Entry.n_value; +    if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) +      return object_error::parse_failed;    } else {      MachO::nlist Entry = getSymbolTableEntry(Symb); -    Res = Entry.n_value; +    NValue = Entry.n_value; +    if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) +      return object_error::parse_failed;    } +  if (NValue >= StringTable.size()) +    return object_error::parse_failed; +  const char *Start = &StringTable.data()[NValue]; +  Res = StringRef(Start);    return object_error::success;  } -error_code -MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, -                                     uint64_t &Res) const { -  nlist_base Entry = getSymbolTableEntryBase(this, Symb); -  getSymbolAddress(Symb, Res); -  if (Entry.n_sect) { -    uint64_t Delta; -    DataRefImpl SecRel; -    SecRel.d.a = Entry.n_sect-1; -    if (is64Bit()) { -      MachO::section_64 Sec = getSection64(SecRel); -      Delta = Sec.offset - Sec.addr; -    } else { -      MachO::section Sec = getSection(SecRel); -      Delta = Sec.offset - Sec.addr; -    } - -    Res += Delta; +std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, +                                                  uint64_t &Res) const { +  if (is64Bit()) { +    MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); +    if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && +        Entry.n_value == 0) +      Res = UnknownAddressOrSize; +    else +      Res = Entry.n_value; +  } else { +    MachO::nlist Entry = getSymbolTableEntry(Symb); +    if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && +        Entry.n_value == 0) +      Res = UnknownAddressOrSize; +    else +      Res = Entry.n_value;    } -    return object_error::success;  } -error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, -                                               uint32_t &Result) const { -  uint32_t flags; -  this->getSymbolFlags(DRI, flags); +std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, +                                                    uint32_t &Result) const { +  uint32_t flags = getSymbolFlags(DRI);    if (flags & SymbolRef::SF_Common) { -    nlist_base Entry = getSymbolTableEntryBase(this, DRI); +    MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);      Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);    } else {      Result = 0; @@ -521,22 +335,25 @@ error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI,    return object_error::success;  } -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, -                                          uint64_t &Result) const { +std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, +                                               uint64_t &Result) const {    uint64_t BeginOffset;    uint64_t EndOffset = 0;    uint8_t SectionIndex; -  nlist_base Entry = getSymbolTableEntryBase(this, DRI); +  MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);    uint64_t Value;    getSymbolAddress(DRI, Value); +  if (Value == UnknownAddressOrSize) { +    Result = UnknownAddressOrSize; +    return object_error::success; +  }    BeginOffset = Value;    SectionIndex = Entry.n_sect;    if (!SectionIndex) { -    uint32_t flags = SymbolRef::SF_None; -    this->getSymbolFlags(DRI, flags); +    uint32_t flags = getSymbolFlags(DRI);      if (flags & SymbolRef::SF_Common)        Result = Value;      else @@ -545,12 +362,12 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,    }    // Unfortunately symbols are unsorted so we need to touch all    // symbols from load command -  error_code ec; -  for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E; -       I.increment(ec)) { -    DataRefImpl DRI = I->getRawDataRefImpl(); +  for (const SymbolRef &Symbol : symbols()) { +    DataRefImpl DRI = Symbol.getRawDataRefImpl();      Entry = getSymbolTableEntryBase(this, DRI);      getSymbolAddress(DRI, Value); +    if (Value == UnknownAddressOrSize) +      continue;      if (Entry.n_sect == SectionIndex && Value > BeginOffset)        if (!EndOffset || Value < EndOffset)          EndOffset = Value; @@ -567,9 +384,9 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI,    return object_error::success;  } -error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, -                                          SymbolRef::Type &Res) const { -  nlist_base Entry = getSymbolTableEntryBase(this, Symb); +std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, +                                               SymbolRef::Type &Res) const { +  MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);    uint8_t n_type = Entry.n_type;    Res = SymbolRef::ST_Other; @@ -591,19 +408,20 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb,    return object_error::success;  } -error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, -                                           uint32_t &Result) const { -  nlist_base Entry = getSymbolTableEntryBase(this, DRI); +uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { +  MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI);    uint8_t MachOType = Entry.n_type;    uint16_t MachOFlags = Entry.n_desc; -  // TODO: Correctly set SF_ThreadLocal -  Result = SymbolRef::SF_None; +  uint32_t Result = SymbolRef::SF_None;    if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF)      Result |= SymbolRef::SF_Undefined; +  if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) +    Result |= SymbolRef::SF_Indirect; +    if (MachOType & MachO::N_STAB)      Result |= SymbolRef::SF_FormatSpecific; @@ -612,7 +430,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,      if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {        uint64_t Value;        getSymbolAddress(DRI, Value); -      if (Value) +      if (Value && Value != UnknownAddressOrSize)          Result |= SymbolRef::SF_Common;      }    } @@ -623,17 +441,16 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI,    if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)      Result |= SymbolRef::SF_Absolute; -  return object_error::success; +  return Result;  } -error_code -MachOObjectFile::getSymbolSection(DataRefImpl Symb, -                                  section_iterator &Res) const { -  nlist_base Entry = getSymbolTableEntryBase(this, Symb); +std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, +                                                  section_iterator &Res) const { +  MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb);    uint8_t index = Entry.n_sect;    if (index == 0) { -    Res = end_sections(); +    Res = section_end();    } else {      DataRefImpl DRI;      DRI.d.a = index - 1; @@ -643,27 +460,19 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb,    return object_error::success;  } -error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, -                                           uint64_t &Val) const { -  report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); -} - -error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, -                                           SectionRef &Res) const { +void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {    Sec.d.a++; -  Res = SectionRef(Sec, this); -  return object_error::success;  } -error_code -MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { +std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, +                                                StringRef &Result) const {    ArrayRef<char> Raw = getSectionRawName(Sec);    Result = parseSegmentOrSectionName(Raw.data());    return object_error::success;  } -error_code -MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, +                                                   uint64_t &Res) const {    if (is64Bit()) {      MachO::section_64 Sect = getSection64(Sec);      Res = Sect.addr; @@ -674,8 +483,8 @@ MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const {    return object_error::success;  } -error_code -MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, +                                                uint64_t &Res) const {    if (is64Bit()) {      MachO::section_64 Sect = getSection64(Sec);      Res = Sect.size; @@ -687,8 +496,8 @@ MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const {    return object_error::success;  } -error_code -MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { +std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, +                                                    StringRef &Res) const {    uint32_t Offset;    uint64_t Size; @@ -706,8 +515,8 @@ MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const {    return object_error::success;  } -error_code -MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, +                                                     uint64_t &Res) const {    uint32_t Align;    if (is64Bit()) {      MachO::section_64 Sect = getSection64(Sec); @@ -721,26 +530,34 @@ MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const {    return object_error::success;  } -error_code -MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { +std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, +                                               bool &Res) const {    uint32_t Flags = getSectionFlags(this, Sec);    Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;    return object_error::success;  } -error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { -  // FIXME: Unimplemented. -  Result = false; +std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, +                                               bool &Result) const { +  uint32_t Flags = getSectionFlags(this, Sec); +  unsigned SectionType = Flags & MachO::SECTION_TYPE; +  Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && +           !(SectionType == MachO::S_ZEROFILL || +             SectionType == MachO::S_GB_ZEROFILL);    return object_error::success;  } -error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { -  // FIXME: Unimplemented. -  Result = false; +std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, +                                              bool &Result) const { +  uint32_t Flags = getSectionFlags(this, Sec); +  unsigned SectionType = Flags & MachO::SECTION_TYPE; +  Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && +           (SectionType == MachO::S_ZEROFILL || +            SectionType == MachO::S_GB_ZEROFILL);    return object_error::success;  } -error_code +std::error_code  MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,                                                 bool &Result) const {    // FIXME: Unimplemented. @@ -748,15 +565,15 @@ MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec,    return object_error::success;  } -error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, -                                             bool &Result) const { +std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, +                                                  bool &Result) const {    // FIXME: Unimplemented.    Result = false;    return object_error::success;  } -error_code -MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { +std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, +                                                   bool &Res) const {    uint32_t Flags = getSectionFlags(this, Sec);    unsigned SectionType = Flags & MachO::SECTION_TYPE;    Res = SectionType == MachO::S_ZEROFILL || @@ -764,8 +581,8 @@ MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const {    return object_error::success;  } -error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, -                                                  bool &Result) const { +std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, +                                                       bool &Result) const {    // Consider using the code from isSectionText to look for __const sections.    // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS    // to use section attributes to distinguish code from data. @@ -775,9 +592,9 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec,    return object_error::success;  } -error_code -MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, -                                       bool &Result) const { +std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, +                                                       DataRefImpl Symb, +                                                       bool &Result) const {    SymbolRef::Type ST;    this->getSymbolType(Symb, ST);    if (ST == SymbolRef::ST_Unknown) { @@ -798,58 +615,50 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,  }  relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { -  uint32_t Offset; -  if (is64Bit()) { -    MachO::section_64 Sect = getSection64(Sec); -    Offset = Sect.reloff; -  } else { -    MachO::section Sect = getSection(Sec); -    Offset = Sect.reloff; -  } -    DataRefImpl Ret; -  Ret.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); +  Ret.d.a = Sec.d.a; +  Ret.d.b = 0;    return relocation_iterator(RelocationRef(Ret, this));  }  relocation_iterator  MachOObjectFile::section_rel_end(DataRefImpl Sec) const { -  uint32_t Offset;    uint32_t Num;    if (is64Bit()) {      MachO::section_64 Sect = getSection64(Sec); -    Offset = Sect.reloff;      Num = Sect.nreloc;    } else {      MachO::section Sect = getSection(Sec); -    Offset = Sect.reloff;      Num = Sect.nreloc;    } -  const MachO::any_relocation_info *P = -    reinterpret_cast<const MachO::any_relocation_info *>(getPtr(this, Offset)); -    DataRefImpl Ret; -  Ret.p = reinterpret_cast<uintptr_t>(P + Num); +  Ret.d.a = Sec.d.a; +  Ret.d.b = Num;    return relocation_iterator(RelocationRef(Ret, this));  } -error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, -                                              RelocationRef &Res) const { -  const MachO::any_relocation_info *P = -    reinterpret_cast<const MachO::any_relocation_info *>(Rel.p); -  Rel.p = reinterpret_cast<uintptr_t>(P + 1); -  Res = RelocationRef(Rel, this); -  return object_error::success; +void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { +  ++Rel.d.b;  } -error_code -MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { -  report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); +std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, +                                                      uint64_t &Res) const { +  uint64_t Offset; +  getRelocationOffset(Rel, Offset); + +  DataRefImpl Sec; +  Sec.d.a = Rel.d.a; +  uint64_t SecAddress; +  getSectionAddress(Sec, SecAddress); +  Res = SecAddress + Offset; +  return object_error::success;  } -error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, -                                                uint64_t &Res) const { +std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, +                                                     uint64_t &Res) const { +  assert(getHeader().filetype == MachO::MH_OBJECT && +         "Only implemented for MH_OBJECT");    MachO::any_relocation_info RE = getRelocation(Rel);    Res = getAnyRelocationAddress(RE);    return object_error::success; @@ -858,10 +667,13 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel,  symbol_iterator  MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {    MachO::any_relocation_info RE = getRelocation(Rel); +  if (isRelocationScattered(RE)) +    return symbol_end(); +    uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);    bool isExtern = getPlainRelocationExternal(RE);    if (!isExtern) -    return end_symbols(); +    return symbol_end();    MachO::symtab_command S = getSymtabLoadCommand();    unsigned SymbolTableEntrySize = is64Bit() ? @@ -873,14 +685,14 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {    return symbol_iterator(SymbolRef(Sym, this));  } -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, -                                              uint64_t &Res) const { +std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, +                                                   uint64_t &Res) const {    MachO::any_relocation_info RE = getRelocation(Rel);    Res = getAnyRelocationType(RE);    return object_error::success;  } -error_code +std::error_code  MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,                                         SmallVectorImpl<char> &Result) const {    StringRef res; @@ -899,7 +711,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,          "GENERIC_RELOC_LOCAL_SECTDIFF",          "GENERIC_RELOC_TLV" }; -      if (RType > 6) +      if (RType > 5)          res = "Unknown";        else          res = Table[RType]; @@ -943,6 +755,23 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,          res = Table[RType];        break;      } +    case Triple::arm64: +    case Triple::aarch64: { +      static const char *const Table[] = { +        "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR", +        "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21", +        "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21", +        "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", +        "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", +        "ARM64_RELOC_ADDEND" +      }; + +      if (RType >= array_lengthof(Table)) +        res = "Unknown"; +      else +        res = Table[RType]; +      break; +    }      case Triple::ppc: {        static const char *const Table[] =  {          "PPC_RELOC_VANILLA", @@ -962,7 +791,10 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,          "PPC_RELOC_LO14_SECTDIFF",          "PPC_RELOC_LOCAL_SECTDIFF" }; -      res = Table[RType]; +      if (RType > 15) +        res = "Unknown"; +      else +        res = Table[RType];        break;      }      case Triple::UnknownArch: @@ -973,7 +805,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel,    return object_error::success;  } -error_code +std::error_code  MachOObjectFile::getRelocationValueString(DataRefImpl Rel,                                            SmallVectorImpl<char> &Result) const {    MachO::any_relocation_info RE = getRelocation(Rel); @@ -1002,7 +834,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,        }        case MachO::X86_64_RELOC_SUBTRACTOR: {          DataRefImpl RelNext = Rel; -        RelNext.d.a++; +        moveRelocationNext(RelNext);          MachO::any_relocation_info RENext = getRelocation(RelNext);          // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type @@ -1050,7 +882,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,          return object_error::success;        case MachO::GENERIC_RELOC_SECTDIFF: {          DataRefImpl RelNext = Rel; -        RelNext.d.a++; +        moveRelocationNext(RelNext);          MachO::any_relocation_info RENext = getRelocation(RelNext);          // X86 sect diff's must be followed by a relocation of type @@ -1072,7 +904,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,        switch (Type) {          case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: {            DataRefImpl RelNext = Rel; -          RelNext.d.a++; +          moveRelocationNext(RelNext);            MachO::any_relocation_info RENext = getRelocation(RelNext);            // X86 sect diff's must be followed by a relocation of type @@ -1111,7 +943,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,            printRelocationTargetName(this, RE, fmt);            DataRefImpl RelNext = Rel; -          RelNext.d.a++; +          moveRelocationNext(RelNext);            MachO::any_relocation_info RENext = getRelocation(RelNext);            // ARM half relocs must be followed by a relocation of type @@ -1149,8 +981,8 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel,    return object_error::success;  } -error_code -MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { +std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, +                                                     bool &Result) const {    unsigned Arch = getArch();    uint64_t Type;    getRelocationType(Rel, Type); @@ -1177,30 +1009,207 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const {    return object_error::success;  } -error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, -                                           LibraryRef &Res) const { +std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, +                                                LibraryRef &Res) const {    report_fatal_error("Needed libraries unimplemented in MachOObjectFile");  } -error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, -                                           StringRef &Res) const { +std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, +                                                StringRef &Res) const {    report_fatal_error("Needed libraries unimplemented in MachOObjectFile");  } -symbol_iterator MachOObjectFile::begin_symbols() const { -  DataRefImpl DRI; -  if (!SymtabLoadCmd) -    return symbol_iterator(SymbolRef(DRI, this)); +// +// guessLibraryShortName() is passed a name of a dynamic library and returns a +// guess on what the short name is.  Then name is returned as a substring of the +// StringRef Name passed in.  The name of the dynamic library is recognized as +// a framework if it has one of the two following forms: +//      Foo.framework/Versions/A/Foo +//      Foo.framework/Foo +// Where A and Foo can be any string.  And may contain a trailing suffix +// starting with an underbar.  If the Name is recognized as a framework then +// isFramework is set to true else it is set to false.  If the Name has a +// suffix then Suffix is set to the substring in Name that contains the suffix +// else it is set to a NULL StringRef. +// +// The Name of the dynamic library is recognized as a library name if it has +// one of the two following forms: +//      libFoo.A.dylib +//      libFoo.dylib +// The library may have a suffix trailing the name Foo of the form: +//      libFoo_profile.A.dylib +//      libFoo_profile.dylib +// +// The Name of the dynamic library is also recognized as a library name if it +// has the following form: +//      Foo.qtx +// +// If the Name of the dynamic library is none of the forms above then a NULL +// StringRef is returned. +// +StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, +                                                 bool &isFramework, +                                                 StringRef &Suffix) { +  StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; +  size_t a, b, c, d, Idx; + +  isFramework = false; +  Suffix = StringRef(); + +  // Pull off the last component and make Foo point to it +  a = Name.rfind('/'); +  if (a == Name.npos || a == 0) +    goto guess_library; +  Foo = Name.slice(a+1, Name.npos); + +  // Look for a suffix starting with a '_' +  Idx = Foo.rfind('_'); +  if (Idx != Foo.npos && Foo.size() >= 2) { +    Suffix = Foo.slice(Idx, Foo.npos); +    Foo = Foo.slice(0, Idx); +  } -  MachO::symtab_command Symtab = getSymtabLoadCommand(); -  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); -  return symbol_iterator(SymbolRef(DRI, this)); +  // First look for the form Foo.framework/Foo +  b = Name.rfind('/', a); +  if (b == Name.npos) +    Idx = 0; +  else +    Idx = b+1; +  F = Name.slice(Idx, Idx + Foo.size()); +  DotFramework = Name.slice(Idx + Foo.size(), +                            Idx + Foo.size() + sizeof(".framework/")-1); +  if (F == Foo && DotFramework == ".framework/") { +    isFramework = true; +    return Foo; +  } + +  // Next look for the form Foo.framework/Versions/A/Foo +  if (b == Name.npos) +    goto guess_library; +  c =  Name.rfind('/', b); +  if (c == Name.npos || c == 0) +    goto guess_library; +  V = Name.slice(c+1, Name.npos); +  if (!V.startswith("Versions/")) +    goto guess_library; +  d =  Name.rfind('/', c); +  if (d == Name.npos) +    Idx = 0; +  else +    Idx = d+1; +  F = Name.slice(Idx, Idx + Foo.size()); +  DotFramework = Name.slice(Idx + Foo.size(), +                            Idx + Foo.size() + sizeof(".framework/")-1); +  if (F == Foo && DotFramework == ".framework/") { +    isFramework = true; +    return Foo; +  } + +guess_library: +  // pull off the suffix after the "." and make a point to it +  a = Name.rfind('.'); +  if (a == Name.npos || a == 0) +    return StringRef(); +  Dylib = Name.slice(a, Name.npos); +  if (Dylib != ".dylib") +    goto guess_qtx; + +  // First pull off the version letter for the form Foo.A.dylib if any. +  if (a >= 3) { +    Dot = Name.slice(a-2, a-1); +    if (Dot == ".") +      a = a - 2; +  } + +  b = Name.rfind('/', a); +  if (b == Name.npos) +    b = 0; +  else +    b = b+1; +  // ignore any suffix after an underbar like Foo_profile.A.dylib +  Idx = Name.find('_', b); +  if (Idx != Name.npos && Idx != b) { +    Lib = Name.slice(b, Idx); +    Suffix = Name.slice(Idx, a); +  } +  else +    Lib = Name.slice(b, a); +  // There are incorrect library names of the form: +  // libATS.A_profile.dylib so check for these. +  if (Lib.size() >= 3) { +    Dot = Lib.slice(Lib.size()-2, Lib.size()-1); +    if (Dot == ".") +      Lib = Lib.slice(0, Lib.size()-2); +  } +  return Lib; + +guess_qtx: +  Qtx = Name.slice(a, Name.npos); +  if (Qtx != ".qtx") +    return StringRef(); +  b = Name.rfind('/', a); +  if (b == Name.npos) +    Lib = Name.slice(0, a); +  else +    Lib = Name.slice(b+1, a); +  // There are library names of the form: QT.A.qtx so check for these. +  if (Lib.size() >= 3) { +    Dot = Lib.slice(Lib.size()-2, Lib.size()-1); +    if (Dot == ".") +      Lib = Lib.slice(0, Lib.size()-2); +  } +  return Lib; +} + +// getLibraryShortNameByIndex() is used to get the short name of the library +// for an undefined symbol in a linked Mach-O binary that was linked with the +// normal two-level namespace default (that is MH_TWOLEVEL in the header). +// It is passed the index (0 - based) of the library as translated from +// GET_LIBRARY_ORDINAL (1 - based). +std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, +                                                            StringRef &Res) { +  if (Index >= Libraries.size()) +    return object_error::parse_failed; + +  MachO::dylib_command D = +    getStruct<MachO::dylib_command>(this, Libraries[Index]); +  if (D.dylib.name >= D.cmdsize) +    return object_error::parse_failed; + +  // If the cache of LibrariesShortNames is not built up do that first for +  // all the Libraries. +  if (LibrariesShortNames.size() == 0) { +    for (unsigned i = 0; i < Libraries.size(); i++) { +      MachO::dylib_command D = +        getStruct<MachO::dylib_command>(this, Libraries[i]); +      if (D.dylib.name >= D.cmdsize) { +        LibrariesShortNames.push_back(StringRef()); +        continue; +      } +      const char *P = (const char *)(Libraries[i]) + D.dylib.name; +      StringRef Name = StringRef(P); +      StringRef Suffix; +      bool isFramework; +      StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); +      if (shortName == StringRef()) +        LibrariesShortNames.push_back(Name); +      else +        LibrariesShortNames.push_back(shortName); +    } +  } + +  Res = LibrariesShortNames[Index]; +  return object_error::success;  } -symbol_iterator MachOObjectFile::end_symbols() const { +basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { +  return getSymbolByIndex(0); +} + +basic_symbol_iterator MachOObjectFile::symbol_end_impl() const {    DataRefImpl DRI;    if (!SymtabLoadCmd) -    return symbol_iterator(SymbolRef(DRI, this)); +    return basic_symbol_iterator(SymbolRef(DRI, this));    MachO::symtab_command Symtab = getSymtabLoadCommand();    unsigned SymbolTableEntrySize = is64Bit() ? @@ -1209,36 +1218,40 @@ symbol_iterator MachOObjectFile::end_symbols() const {    unsigned Offset = Symtab.symoff +      Symtab.nsyms * SymbolTableEntrySize;    DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); -  return symbol_iterator(SymbolRef(DRI, this)); +  return basic_symbol_iterator(SymbolRef(DRI, this));  } -symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { -  // TODO: implement -  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); -} +basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { +  DataRefImpl DRI; +  if (!SymtabLoadCmd) +    return basic_symbol_iterator(SymbolRef(DRI, this)); -symbol_iterator MachOObjectFile::end_dynamic_symbols() const { -  // TODO: implement -  report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +  MachO::symtab_command Symtab = getSymtabLoadCommand(); +  assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); +  unsigned SymbolTableEntrySize = +    is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); +  DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); +  DRI.p += Index * SymbolTableEntrySize; +  return basic_symbol_iterator(SymbolRef(DRI, this));  } -section_iterator MachOObjectFile::begin_sections() const { +section_iterator MachOObjectFile::section_begin() const {    DataRefImpl DRI;    return section_iterator(SectionRef(DRI, this));  } -section_iterator MachOObjectFile::end_sections() const { +section_iterator MachOObjectFile::section_end() const {    DataRefImpl DRI;    DRI.d.a = Sections.size();    return section_iterator(SectionRef(DRI, this));  } -library_iterator MachOObjectFile::begin_libraries_needed() const { +library_iterator MachOObjectFile::needed_library_begin() const {    // TODO: implement    report_fatal_error("Needed libraries unimplemented in MachOObjectFile");  } -library_iterator MachOObjectFile::end_libraries_needed() const { +library_iterator MachOObjectFile::needed_library_end() const {    // TODO: implement    report_fatal_error("Needed libraries unimplemented in MachOObjectFile");  } @@ -1272,6 +1285,8 @@ StringRef MachOObjectFile::getFileFormatName() const {    switch (CPUType) {    case llvm::MachO::CPU_TYPE_X86_64:      return "Mach-O 64-bit x86-64"; +  case llvm::MachO::CPU_TYPE_ARM64: +    return "Mach-O arm64";    case llvm::MachO::CPU_TYPE_POWERPC64:      return "Mach-O 64-bit ppc64";    default: @@ -1287,6 +1302,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {      return Triple::x86_64;    case llvm::MachO::CPU_TYPE_ARM:      return Triple::arm; +  case llvm::MachO::CPU_TYPE_ARM64: +    return Triple::arm64;    case llvm::MachO::CPU_TYPE_POWERPC:      return Triple::ppc;    case llvm::MachO::CPU_TYPE_POWERPC64: @@ -1296,6 +1313,108 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {    }  } +Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { +  switch (CPUType) { +  case MachO::CPU_TYPE_I386: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_I386_ALL: +      return Triple("i386-apple-darwin"); +    default: +      return Triple(); +    } +  case MachO::CPU_TYPE_X86_64: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_X86_64_ALL: +      return Triple("x86_64-apple-darwin"); +    case MachO::CPU_SUBTYPE_X86_64_H: +      return Triple("x86_64h-apple-darwin"); +    default: +      return Triple(); +    } +  case MachO::CPU_TYPE_ARM: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_ARM_V4T: +      return Triple("armv4t-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V5TEJ: +      return Triple("armv5e-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V6: +      return Triple("armv6-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V6M: +      return Triple("armv6m-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V7EM: +      return Triple("armv7em-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V7K: +      return Triple("armv7k-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V7M: +      return Triple("armv7m-apple-darwin"); +    case MachO::CPU_SUBTYPE_ARM_V7S: +      return Triple("armv7s-apple-darwin"); +    default: +      return Triple(); +    } +  case MachO::CPU_TYPE_ARM64: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_ARM64_ALL: +      return Triple("arm64-apple-darwin"); +    default: +      return Triple(); +    } +  case MachO::CPU_TYPE_POWERPC: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_POWERPC_ALL: +      return Triple("ppc-apple-darwin"); +    default: +      return Triple(); +    } +  case MachO::CPU_TYPE_POWERPC64: +    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { +    case MachO::CPU_SUBTYPE_POWERPC_ALL: +      return Triple("ppc64-apple-darwin"); +    default: +      return Triple(); +    } +  default: +    return Triple(); +  } +} + +Triple MachOObjectFile::getHostArch() { +  return Triple(sys::getDefaultTargetTriple()); +} + +Triple MachOObjectFile::getArch(StringRef ArchFlag) { +  if (ArchFlag == "i386") +    return Triple("i386-apple-darwin"); +  else if (ArchFlag == "x86_64") +    return Triple("x86_64-apple-darwin"); +  else if (ArchFlag == "x86_64h") +    return Triple("x86_64h-apple-darwin"); +  else if (ArchFlag == "armv4t" || ArchFlag == "arm") +    return Triple("armv4t-apple-darwin"); +  else if (ArchFlag == "armv5e") +    return Triple("armv5e-apple-darwin"); +  else if (ArchFlag == "armv6") +    return Triple("armv6-apple-darwin"); +  else if (ArchFlag == "armv6m") +    return Triple("armv6m-apple-darwin"); +  else if (ArchFlag == "armv7em") +    return Triple("armv7em-apple-darwin"); +  else if (ArchFlag == "armv7k") +    return Triple("armv7k-apple-darwin"); +  else if (ArchFlag == "armv7k") +    return Triple("armv7m-apple-darwin"); +  else if (ArchFlag == "armv7s") +    return Triple("armv7s-apple-darwin"); +  else if (ArchFlag == "arm64") +    return Triple("arm64-apple-darwin"); +  else if (ArchFlag == "ppc") +    return Triple("ppc-apple-darwin"); +  else if (ArchFlag == "ppc64") +    return Triple("ppc64-apple-darwin"); +  else +    return Triple(); +} +  unsigned MachOObjectFile::getArch() const {    return getArch(getCPUType(this));  } @@ -1423,7 +1542,7 @@ SectionRef  MachOObjectFile::getRelocationSection(                                     const MachO::any_relocation_info &RE) const {    if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) -    return *end_sections(); +    return *section_end();    unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1;    DataRefImpl DRI;    DRI.d.a = SecNum; @@ -1501,10 +1620,34 @@ MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const {    return getStruct<MachO::linker_options_command>(this, L.Ptr);  } +MachO::version_min_command +MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { +  return getStruct<MachO::version_min_command>(this, L.Ptr); +} + +MachO::dylib_command +MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { +  return getStruct<MachO::dylib_command>(this, L.Ptr); +} + +  MachO::any_relocation_info  MachOObjectFile::getRelocation(DataRefImpl Rel) const { -  const char *P = reinterpret_cast<const char *>(Rel.p); -  return getStruct<MachO::any_relocation_info>(this, P); +  DataRefImpl Sec; +  Sec.d.a = Rel.d.a; +  uint32_t Offset; +  if (is64Bit()) { +    MachO::section_64 Sect = getSection64(Sec); +    Offset = Sect.reloff; +  } else { +    MachO::section Sect = getSection(Sec); +    Offset = Sect.reloff; +  } + +  auto P = reinterpret_cast<const MachO::any_relocation_info *>( +      getPtr(this, Offset)) + Rel.d.b; +  return getStruct<MachO::any_relocation_info>( +      this, reinterpret_cast<const char *>(P));  }  MachO::data_in_code_entry @@ -1579,27 +1722,24 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index,    }  } -ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { +ErrorOr<ObjectFile *> +ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) {    StringRef Magic = Buffer->getBuffer().slice(0, 4); -  error_code ec; -  OwningPtr<ObjectFile> Ret; +  std::error_code EC; +  std::unique_ptr<MachOObjectFile> Ret;    if (Magic == "\xFE\xED\xFA\xCE") -    Ret.reset(new MachOObjectFile(Buffer, false, false, ec)); +    Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC));    else if (Magic == "\xCE\xFA\xED\xFE") -    Ret.reset(new MachOObjectFile(Buffer, true, false, ec)); +    Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC));    else if (Magic == "\xFE\xED\xFA\xCF") -    Ret.reset(new MachOObjectFile(Buffer, false, true, ec)); +    Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC));    else if (Magic == "\xCF\xFA\xED\xFE") -    Ret.reset(new MachOObjectFile(Buffer, true, true, ec)); -  else { -    delete Buffer; -    return NULL; -  } +    Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); +  else +    return object_error::parse_failed; -  if (ec) -    return NULL; -  return Ret.take(); +  if (EC) +    return EC; +  return Ret.release();  } -} // end namespace object -} // end namespace llvm diff --git a/contrib/llvm/lib/Object/MachOUniversal.cpp b/contrib/llvm/lib/Object/MachOUniversal.cpp index 75160af3ad2c..4ba5d9686497 100644 --- a/contrib/llvm/lib/Object/MachOUniversal.cpp +++ b/contrib/llvm/lib/Object/MachOUniversal.cpp @@ -12,9 +12,9 @@  //===----------------------------------------------------------------------===//  #include "llvm/Object/MachOUniversal.h" -  #include "llvm/Object/MachO.h"  #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Archive.h"  #include "llvm/Support/Casting.h"  #include "llvm/Support/Host.h"  #include "llvm/Support/MemoryBuffer.h" @@ -23,26 +23,21 @@ using namespace llvm;  using namespace object;  template<typename T> -static void SwapValue(T &Value) { -  Value = sys::SwapByteOrder(Value); -} - -template<typename T>  static void SwapStruct(T &Value);  template<>  void SwapStruct(MachO::fat_header &H) { -  SwapValue(H.magic); -  SwapValue(H.nfat_arch); +  sys::swapByteOrder(H.magic); +  sys::swapByteOrder(H.nfat_arch);  }  template<>  void SwapStruct(MachO::fat_arch &H) { -  SwapValue(H.cputype); -  SwapValue(H.cpusubtype); -  SwapValue(H.offset); -  SwapValue(H.size); -  SwapValue(H.align); +  sys::swapByteOrder(H.cputype); +  sys::swapByteOrder(H.cpusubtype); +  sys::swapByteOrder(H.offset); +  sys::swapByteOrder(H.size); +  sys::swapByteOrder(H.align);  }  template<typename T> @@ -58,7 +53,7 @@ static T getUniversalBinaryStruct(const char *Ptr) {  MachOUniversalBinary::ObjectForArch::ObjectForArch(      const MachOUniversalBinary *Parent, uint32_t Index)      : Parent(Parent), Index(Index) { -  if (Parent == 0 || Index > Parent->getNumberOfObjects()) { +  if (!Parent || Index >= Parent->getNumberOfObjects()) {      clear();    } else {      // Parse object header. @@ -72,31 +67,53 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch(    }  } -error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( -    OwningPtr<ObjectFile> &Result) const { +ErrorOr<std::unique_ptr<ObjectFile>> +MachOUniversalBinary::ObjectForArch::getAsObjectFile() const {    if (Parent) {      StringRef ParentData = Parent->getData();      StringRef ObjectData = ParentData.substr(Header.offset, Header.size); -    std::string ObjectName = -        Parent->getFileName().str() + ":" + -        Triple::getArchTypeName(MachOObjectFile::getArch(Header.cputype)); -    MemoryBuffer *ObjBuffer = MemoryBuffer::getMemBuffer( -        ObjectData, ObjectName, false); -    if (ObjectFile *Obj = ObjectFile::createMachOObjectFile(ObjBuffer)) { -      Result.reset(Obj); -      return object_error::success; -    } +    std::string ObjectName = Parent->getFileName().str(); +    std::unique_ptr<MemoryBuffer> ObjBuffer( +        MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); +    return ObjectFile::createMachOObjectFile(ObjBuffer); +  } +  return object_error::parse_failed; +} + +std::error_code MachOUniversalBinary::ObjectForArch::getAsArchive( +    std::unique_ptr<Archive> &Result) const { +  if (Parent) { +    StringRef ParentData = Parent->getData(); +    StringRef ObjectData = ParentData.substr(Header.offset, Header.size); +    std::string ObjectName = Parent->getFileName().str(); +    std::unique_ptr<MemoryBuffer> ObjBuffer( +        MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); +    ErrorOr<Archive *> Obj = Archive::create(std::move(ObjBuffer)); +    if (std::error_code EC = Obj.getError()) +      return EC; +    Result.reset(Obj.get()); +    return object_error::success;    }    return object_error::parse_failed;  }  void MachOUniversalBinary::anchor() { } -MachOUniversalBinary::MachOUniversalBinary(MemoryBuffer *Source, -                                           error_code &ec) -  : Binary(Binary::ID_MachOUniversalBinary, Source), -    NumberOfObjects(0) { -  if (Source->getBufferSize() < sizeof(MachO::fat_header)) { +ErrorOr<MachOUniversalBinary *> +MachOUniversalBinary::create(std::unique_ptr<MemoryBuffer> Source) { +  std::error_code EC; +  std::unique_ptr<MachOUniversalBinary> Ret( +      new MachOUniversalBinary(std::move(Source), EC)); +  if (EC) +    return EC; +  return Ret.release(); +} + +MachOUniversalBinary::MachOUniversalBinary(std::unique_ptr<MemoryBuffer> Source, +                                           std::error_code &ec) +    : Binary(Binary::ID_MachOUniversalBinary, std::move(Source)), +      NumberOfObjects(0) { +  if (Data->getBufferSize() < sizeof(MachO::fat_header)) {      ec = object_error::invalid_file_type;      return;    } @@ -125,15 +142,14 @@ static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) {    }  } -error_code -MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch, -                                       OwningPtr<ObjectFile> &Result) const { +ErrorOr<std::unique_ptr<ObjectFile>> +MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch) const {    MachO::CPUType CTM;    if (!getCTMForArch(Arch, CTM))      return object_error::arch_not_found;    for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) {      if (I->getCPUType() == static_cast<uint32_t>(CTM)) -      return I->getAsObjectFile(Result); +      return I->getAsObjectFile();    }    return object_error::arch_not_found;  } diff --git a/contrib/llvm/lib/Object/Object.cpp b/contrib/llvm/lib/Object/Object.cpp index 6941708dd349..567d87f7a0e5 100644 --- a/contrib/llvm/lib/Object/Object.cpp +++ b/contrib/llvm/lib/Object/Object.cpp @@ -13,8 +13,8 @@  //===----------------------------------------------------------------------===//  #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/ObjectFile.h"  #include "llvm-c/Object.h" +#include "llvm/Object/ObjectFile.h"  using namespace llvm;  using namespace object; @@ -59,7 +59,11 @@ wrap(const relocation_iterator *SI) {  // ObjectFile creation  LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { -  return wrap(ObjectFile::createObjectFile(unwrap(MemBuf))); +  std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf)); +  ErrorOr<ObjectFile *> ObjOrErr(ObjectFile::createObjectFile(Buf)); +  Buf.release(); +  ObjectFile *Obj = ObjOrErr ? ObjOrErr.get() : nullptr; +  return wrap(Obj);  }  void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { @@ -68,7 +72,7 @@ void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) {  // ObjectFile Section iterators  LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { -  section_iterator SI = unwrap(ObjectFile)->begin_sections(); +  section_iterator SI = unwrap(ObjectFile)->section_begin();    return wrap(new section_iterator(SI));  } @@ -78,24 +82,22 @@ void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) {  LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile,                                  LLVMSectionIteratorRef SI) { -  return (*unwrap(SI) == unwrap(ObjectFile)->end_sections()) ? 1 : 0; +  return (*unwrap(SI) == unwrap(ObjectFile)->section_end()) ? 1 : 0;  }  void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { -  error_code ec; -  unwrap(SI)->increment(ec); -  if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message()); +  ++(*unwrap(SI));  }  void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect,                                   LLVMSymbolIteratorRef Sym) { -  if (error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect))) +  if (std::error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect)))      report_fatal_error(ec.message());  }  // ObjectFile Symbol iterators  LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile) { -  symbol_iterator SI = unwrap(ObjectFile)->begin_symbols(); +  symbol_iterator SI = unwrap(ObjectFile)->symbol_begin();    return wrap(new symbol_iterator(SI));  } @@ -105,40 +107,38 @@ void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) {  LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile,                                  LLVMSymbolIteratorRef SI) { -  return (*unwrap(SI) == unwrap(ObjectFile)->end_symbols()) ? 1 : 0; +  return (*unwrap(SI) == unwrap(ObjectFile)->symbol_end()) ? 1 : 0;  }  void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { -  error_code ec; -  unwrap(SI)->increment(ec); -  if (ec) report_fatal_error("LLVMMoveToNextSymbol failed: " + ec.message()); +  ++(*unwrap(SI));  }  // SectionRef accessors  const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) {    StringRef ret; -  if (error_code ec = (*unwrap(SI))->getName(ret)) +  if (std::error_code ec = (*unwrap(SI))->getName(ret))     report_fatal_error(ec.message());    return ret.data();  }  uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) {    uint64_t ret; -  if (error_code ec = (*unwrap(SI))->getSize(ret)) +  if (std::error_code ec = (*unwrap(SI))->getSize(ret))      report_fatal_error(ec.message());    return ret;  }  const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) {    StringRef ret; -  if (error_code ec = (*unwrap(SI))->getContents(ret)) +  if (std::error_code ec = (*unwrap(SI))->getContents(ret))      report_fatal_error(ec.message());    return ret.data();  }  uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {    uint64_t ret; -  if (error_code ec = (*unwrap(SI))->getAddress(ret)) +  if (std::error_code ec = (*unwrap(SI))->getAddress(ret))      report_fatal_error(ec.message());    return ret;  } @@ -146,14 +146,14 @@ uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) {  LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI,                                   LLVMSymbolIteratorRef Sym) {    bool ret; -  if (error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret)) +  if (std::error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret))      report_fatal_error(ec.message());    return ret;  }  // Section Relocation iterators  LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { -  relocation_iterator SI = (*unwrap(Section))->begin_relocations(); +  relocation_iterator SI = (*unwrap(Section))->relocation_begin();    return wrap(new relocation_iterator(SI));  } @@ -163,42 +163,32 @@ void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) {  LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section,                                         LLVMRelocationIteratorRef SI) { -  return (*unwrap(SI) == (*unwrap(Section))->end_relocations()) ? 1 : 0; +  return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0;  }  void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { -  error_code ec; -  unwrap(SI)->increment(ec); -  if (ec) report_fatal_error("LLVMMoveToNextRelocation failed: " + -                             ec.message()); +  ++(*unwrap(SI));  }  // SymbolRef accessors  const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) {    StringRef ret; -  if (error_code ec = (*unwrap(SI))->getName(ret)) +  if (std::error_code ec = (*unwrap(SI))->getName(ret))      report_fatal_error(ec.message());    return ret.data();  }  uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) {    uint64_t ret; -  if (error_code ec = (*unwrap(SI))->getAddress(ret)) -    report_fatal_error(ec.message()); -  return ret; -} - -uint64_t LLVMGetSymbolFileOffset(LLVMSymbolIteratorRef SI) { -  uint64_t ret; -  if (error_code ec = (*unwrap(SI))->getFileOffset(ret)) +  if (std::error_code ec = (*unwrap(SI))->getAddress(ret))      report_fatal_error(ec.message());    return ret;  }  uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {    uint64_t ret; -  if (error_code ec = (*unwrap(SI))->getSize(ret)) +  if (std::error_code ec = (*unwrap(SI))->getSize(ret))      report_fatal_error(ec.message());    return ret;  } @@ -206,14 +196,14 @@ uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) {  // RelocationRef accessors  uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI) {    uint64_t ret; -  if (error_code ec = (*unwrap(RI))->getAddress(ret)) +  if (std::error_code ec = (*unwrap(RI))->getAddress(ret))      report_fatal_error(ec.message());    return ret;  }  uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) {    uint64_t ret; -  if (error_code ec = (*unwrap(RI))->getOffset(ret)) +  if (std::error_code ec = (*unwrap(RI))->getOffset(ret))      report_fatal_error(ec.message());    return ret;  } @@ -225,7 +215,7 @@ LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) {  uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {    uint64_t ret; -  if (error_code ec = (*unwrap(RI))->getType(ret)) +  if (std::error_code ec = (*unwrap(RI))->getType(ret))      report_fatal_error(ec.message());    return ret;  } @@ -233,7 +223,7 @@ uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) {  // NOTE: Caller takes ownership of returned string.  const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {    SmallVector<char, 0> ret; -  if (error_code ec = (*unwrap(RI))->getTypeName(ret)) +  if (std::error_code ec = (*unwrap(RI))->getTypeName(ret))      report_fatal_error(ec.message());    char *str = static_cast<char*>(malloc(ret.size())); @@ -244,7 +234,7 @@ const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) {  // NOTE: Caller takes ownership of returned string.  const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) {    SmallVector<char, 0> ret; -  if (error_code ec = (*unwrap(RI))->getValueString(ret)) +  if (std::error_code ec = (*unwrap(RI))->getValueString(ret))      report_fatal_error(ec.message());    char *str = static_cast<char*>(malloc(ret.size())); diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp index 0e626d650fbb..f5488c6d52db 100644 --- a/contrib/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm/lib/Object/ObjectFile.cpp @@ -12,23 +12,31 @@  //===----------------------------------------------------------------------===//  #include "llvm/Object/ObjectFile.h" -#include "llvm/ADT/OwningPtr.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/system_error.h" +#include "llvm/Support/raw_ostream.h" +#include <system_error>  using namespace llvm;  using namespace object;  void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) -  : Binary(Type, source) { +ObjectFile::ObjectFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source) +    : SymbolicFile(Type, std::move(Source)) {} + +std::error_code ObjectFile::printSymbolName(raw_ostream &OS, +                                            DataRefImpl Symb) const { +  StringRef Name; +  if (std::error_code EC = getSymbolName(Symb, Name)) +    return EC; +  OS << Name; +  return object_error::success;  } -error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, -                                          uint32_t &Result) const { +std::error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, +                                               uint32_t &Result) const {    Result = 0;    return object_error::success;  } @@ -37,21 +45,19 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const {    return section_iterator(SectionRef(Sec, this));  } -ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { -  if (Object->getBufferSize() < 64) { -    delete Object; -    return 0; -  } +ErrorOr<ObjectFile *> +ObjectFile::createObjectFile(std::unique_ptr<MemoryBuffer> &Object, +                             sys::fs::file_magic Type) { +  if (Type == sys::fs::file_magic::unknown) +    Type = sys::fs::identify_magic(Object->getBuffer()); -  sys::fs::file_magic Type = sys::fs::identify_magic(Object->getBuffer());    switch (Type) {    case sys::fs::file_magic::unknown:    case sys::fs::file_magic::bitcode:    case sys::fs::file_magic::archive:    case sys::fs::file_magic::macho_universal_binary:    case sys::fs::file_magic::windows_resource: -    delete Object; -    return 0; +    return object_error::invalid_file_type;    case sys::fs::file_magic::elf_relocatable:    case sys::fs::file_magic::elf_executable:    case sys::fs::file_magic::elf_shared_object: @@ -71,14 +77,15 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) {    case sys::fs::file_magic::coff_object:    case sys::fs::file_magic::coff_import_library:    case sys::fs::file_magic::pecoff_executable: -    return createCOFFObjectFile(Object); +    return createCOFFObjectFile(std::move(Object));    }    llvm_unreachable("Unexpected Object File Type");  } -ObjectFile *ObjectFile::createObjectFile(StringRef ObjectPath) { -  OwningPtr<MemoryBuffer> File; -  if (MemoryBuffer::getFile(ObjectPath, File)) -    return NULL; -  return createObjectFile(File.take()); +ErrorOr<ObjectFile *> ObjectFile::createObjectFile(StringRef ObjectPath) { +  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = +      MemoryBuffer::getFile(ObjectPath); +  if (std::error_code EC = FileOrErr.getError()) +    return EC; +  return createObjectFile(FileOrErr.get());  } diff --git a/contrib/llvm/lib/Object/RecordStreamer.cpp b/contrib/llvm/lib/Object/RecordStreamer.cpp new file mode 100644 index 000000000000..081faddc214c --- /dev/null +++ b/contrib/llvm/lib/Object/RecordStreamer.cpp @@ -0,0 +1,100 @@ +//===-- RecordStreamer.cpp - Record asm definde and used symbols ----------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RecordStreamer.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +void RecordStreamer::markDefined(const MCSymbol &Symbol) { +  State &S = Symbols[Symbol.getName()]; +  switch (S) { +  case DefinedGlobal: +  case Global: +    S = DefinedGlobal; +    break; +  case NeverSeen: +  case Defined: +  case Used: +    S = Defined; +    break; +  } +} + +void RecordStreamer::markGlobal(const MCSymbol &Symbol) { +  State &S = Symbols[Symbol.getName()]; +  switch (S) { +  case DefinedGlobal: +  case Defined: +    S = DefinedGlobal; +    break; + +  case NeverSeen: +  case Global: +  case Used: +    S = Global; +    break; +  } +} + +void RecordStreamer::markUsed(const MCSymbol &Symbol) { +  State &S = Symbols[Symbol.getName()]; +  switch (S) { +  case DefinedGlobal: +  case Defined: +  case Global: +    break; + +  case NeverSeen: +  case Used: +    S = Used; +    break; +  } +} + +void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } + +RecordStreamer::const_iterator RecordStreamer::begin() { +  return Symbols.begin(); +} + +RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } + +RecordStreamer::RecordStreamer(MCContext &Context) : MCStreamer(Context) {} + +void RecordStreamer::EmitInstruction(const MCInst &Inst, +                                     const MCSubtargetInfo &STI) { +  MCStreamer::EmitInstruction(Inst, STI); +} + +void RecordStreamer::EmitLabel(MCSymbol *Symbol) { +  MCStreamer::EmitLabel(Symbol); +  markDefined(*Symbol); +} + +void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { +  markDefined(*Symbol); +  MCStreamer::EmitAssignment(Symbol, Value); +} + +bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, +                                         MCSymbolAttr Attribute) { +  if (Attribute == MCSA_Global) +    markGlobal(*Symbol); +  return true; +} + +void RecordStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, +                                  uint64_t Size, unsigned ByteAlignment) { +  markDefined(*Symbol); +} + +void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, +                                      unsigned ByteAlignment) { +  markDefined(*Symbol); +} diff --git a/contrib/llvm/lib/Object/RecordStreamer.h b/contrib/llvm/lib/Object/RecordStreamer.h new file mode 100644 index 000000000000..10e70ef16e22 --- /dev/null +++ b/contrib/llvm/lib/Object/RecordStreamer.h @@ -0,0 +1,42 @@ +//===-- RecordStreamer.h - Record asm defined and used symbols ---*- C++ -*===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RECORD_STREAMER +#define LLVM_OBJECT_RECORD_STREAMER + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class RecordStreamer : public MCStreamer { +public: +  enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; + +private: +  StringMap<State> Symbols; +  void markDefined(const MCSymbol &Symbol); +  void markGlobal(const MCSymbol &Symbol); +  void markUsed(const MCSymbol &Symbol); +  void visitUsedSymbol(const MCSymbol &Sym) override; + +public: +  typedef StringMap<State>::const_iterator const_iterator; +  const_iterator begin(); +  const_iterator end(); +  RecordStreamer(MCContext &Context); +  void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; +  void EmitLabel(MCSymbol *Symbol) override; +  void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; +  bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; +  void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, +                    unsigned ByteAlignment) override; +  void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, +                        unsigned ByteAlignment) override; +}; +} +#endif diff --git a/contrib/llvm/lib/Object/SymbolicFile.cpp b/contrib/llvm/lib/Object/SymbolicFile.cpp new file mode 100644 index 000000000000..30cf1a03f415 --- /dev/null +++ b/contrib/llvm/lib/Object/SymbolicFile.cpp @@ -0,0 +1,65 @@ +//===- SymbolicFile.cpp - Interface that only provides symbols --*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a file format independent SymbolicFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +SymbolicFile::SymbolicFile(unsigned int Type, +                           std::unique_ptr<MemoryBuffer> Source) +    : Binary(Type, std::move(Source)) {} + +SymbolicFile::~SymbolicFile() {} + +ErrorOr<SymbolicFile *> +SymbolicFile::createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object, +                                 sys::fs::file_magic Type, +                                 LLVMContext *Context) { +  if (Type == sys::fs::file_magic::unknown) +    Type = sys::fs::identify_magic(Object->getBuffer()); + +  switch (Type) { +  case sys::fs::file_magic::bitcode: +    if (Context) +      return IRObjectFile::createIRObjectFile(std::move(Object), *Context); +  // Fallthrough +  case sys::fs::file_magic::unknown: +  case sys::fs::file_magic::archive: +  case sys::fs::file_magic::macho_universal_binary: +  case sys::fs::file_magic::windows_resource: +    return object_error::invalid_file_type; +  case sys::fs::file_magic::elf_relocatable: +  case sys::fs::file_magic::elf_executable: +  case sys::fs::file_magic::elf_shared_object: +  case sys::fs::file_magic::elf_core: +  case sys::fs::file_magic::macho_object: +  case sys::fs::file_magic::macho_executable: +  case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: +  case sys::fs::file_magic::macho_core: +  case sys::fs::file_magic::macho_preload_executable: +  case sys::fs::file_magic::macho_dynamically_linked_shared_lib: +  case sys::fs::file_magic::macho_dynamic_linker: +  case sys::fs::file_magic::macho_bundle: +  case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: +  case sys::fs::file_magic::macho_dsym_companion: +  case sys::fs::file_magic::coff_object: +  case sys::fs::file_magic::coff_import_library: +  case sys::fs::file_magic::pecoff_executable: +    return ObjectFile::createObjectFile(Object, Type); +  } +  llvm_unreachable("Unexpected Binary File Type"); +} diff --git a/contrib/llvm/lib/Object/YAML.cpp b/contrib/llvm/lib/Object/YAML.cpp deleted file mode 100644 index c527bde090e8..000000000000 --- a/contrib/llvm/lib/Object/YAML.cpp +++ /dev/null @@ -1,68 +0,0 @@ -//===- YAML.cpp - YAMLIO utilities for object files -----------------------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/YAML.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> - -using namespace llvm; -using namespace object::yaml; - -void yaml::ScalarTraits<object::yaml::BinaryRef>::output( -    const object::yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) { -  Val.writeAsHex(Out); -} - -StringRef yaml::ScalarTraits<object::yaml::BinaryRef>::input( -    StringRef Scalar, void *, object::yaml::BinaryRef &Val) { -  if (Scalar.size() % 2 != 0) -    return "BinaryRef hex string must contain an even number of nybbles."; -  // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? -  // (e.g. a caret pointing to the offending character). -  for (unsigned I = 0, N = Scalar.size(); I != N; ++I) -    if (!isxdigit(Scalar[I])) -      return "BinaryRef hex string must contain only hex digits."; -  Val = object::yaml::BinaryRef(Scalar); -  return StringRef(); -} - -void BinaryRef::writeAsBinary(raw_ostream &OS) const { -  if (!DataIsHexString) { -    OS.write((const char *)Data.data(), Data.size()); -    return; -  } -  for (unsigned I = 0, N = Data.size(); I != N; I += 2) { -    uint8_t Byte; -    StringRef((const char *)&Data[I],  2).getAsInteger(16, Byte); -    OS.write(Byte); -  } -} - -void BinaryRef::writeAsHex(raw_ostream &OS) const { -  if (binary_size() == 0) { -    OS << "\"\""; -    return; -  } -  if (DataIsHexString) { -    OS.write((const char *)Data.data(), Data.size()); -    return; -  } -  for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; -       ++I) { -    uint8_t Byte = *I; -    OS << hexdigit(Byte >> 4); -    OS << hexdigit(Byte & 0xf); -  } -}  | 
