diff options
Diffstat (limited to 'contrib/llvm/lib/Object')
-rw-r--r-- | contrib/llvm/lib/Object/Archive.cpp | 450 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Binary.cpp | 118 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/COFFObjectFile.cpp | 938 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/COFFYAML.cpp | 281 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ELF.cpp | 714 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ELFObjectFile.cpp | 73 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ELFYAML.cpp | 338 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Error.cpp | 59 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/MachOObjectFile.cpp | 1605 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/MachOUniversal.cpp | 139 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Object.cpp | 254 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ObjectFile.cpp | 84 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/YAML.cpp | 68 |
13 files changed, 5121 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Object/Archive.cpp b/contrib/llvm/lib/Object/Archive.cpp new file mode 100644 index 000000000000..71efca2b1863 --- /dev/null +++ b/contrib/llvm/lib/Object/Archive.cpp @@ -0,0 +1,450 @@ +//===- Archive.cpp - ar File Format implementation --------------*- 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 the ArchiveObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Archive.h" +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +static const char *const Magic = "!<arch>\n"; + +void Archive::anchor() { } + +StringRef ArchiveMemberHeader::getName() const { + char EndCond; + if (Name[0] == '/' || Name[0] == '#') + EndCond = ' '; + else + EndCond = '/'; + llvm::StringRef::size_type end = + llvm::StringRef(Name, sizeof(Name)).find(EndCond); + if (end == llvm::StringRef::npos) + end = sizeof(Name); + assert(end <= sizeof(Name) && end > 0); + // Don't include the EndCond if there is one. + return llvm::StringRef(Name, end); +} + +uint32_t ArchiveMemberHeader::getSize() const { + uint32_t Ret; + if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("Size is not a decimal number."); + return Ret; +} + +sys::fs::perms ArchiveMemberHeader::getAccessMode() const { + unsigned Ret; + if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(" ").getAsInteger(8, Ret)) + llvm_unreachable("Access mode is not an octal number."); + return static_cast<sys::fs::perms>(Ret); +} + +sys::TimeValue ArchiveMemberHeader::getLastModified() const { + unsigned Seconds; + if (StringRef(LastModified, sizeof(LastModified)).rtrim(" ") + .getAsInteger(10, Seconds)) + llvm_unreachable("Last modified time not a decimal number."); + + sys::TimeValue Ret; + Ret.fromEpochTime(Seconds); + return Ret; +} + +unsigned ArchiveMemberHeader::getUID() const { + unsigned Ret; + if (StringRef(UID, sizeof(UID)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("UID time not a decimal number."); + return Ret; +} + +unsigned ArchiveMemberHeader::getGID() const { + unsigned Ret; + if (StringRef(GID, sizeof(GID)).rtrim(" ").getAsInteger(10, Ret)) + llvm_unreachable("GID time not a decimal number."); + return Ret; +} + +Archive::Child::Child(const Archive *Parent, const char *Start) + : Parent(Parent) { + if (!Start) + return; + + const ArchiveMemberHeader *Header = + reinterpret_cast<const ArchiveMemberHeader *>(Start); + Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize()); + + // Setup StartOfFile and PaddingBytes. + StartOfFile = sizeof(ArchiveMemberHeader); + // Don't include attached name. + StringRef Name = Header->getName(); + if (Name.startswith("#1/")) { + uint64_t NameSize; + if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) + llvm_unreachable("Long name length is not an integer"); + StartOfFile += NameSize; + } +} + +Archive::Child Archive::Child::getNext() const { + size_t SpaceToSkip = Data.size(); + // If it's odd, add 1 to make it even. + if (SpaceToSkip & 1) + ++SpaceToSkip; + + const char *NextLoc = Data.data() + SpaceToSkip; + + // Check to see if this is past the end of the archive. + if (NextLoc >= Parent->Data->getBufferEnd()) + return Child(Parent, NULL); + + return Child(Parent, NextLoc); +} + +error_code Archive::Child::getName(StringRef &Result) 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; + } + // It's a long name. + // Get the offset. + std::size_t offset; + if (name.substr(1).rtrim(" ").getAsInteger(10, offset)) + llvm_unreachable("Long name offset is not an integer"); + const char *addr = Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader) + + offset; + // Verify it. + if (Parent->StringTable == Parent->end_children() + || addr < (Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader)) + || addr > (Parent->StringTable->Data.begin() + + sizeof(ArchiveMemberHeader) + + Parent->StringTable->getSize())) + return object_error::parse_failed; + + // 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 object_error::success; + } 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) + .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; +} + +error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, + bool FullPath) const { + StringRef Name; + if (error_code ec = getName(Name)) + return ec; + SmallString<128> Path; + Result.reset(MemoryBuffer::getMemBuffer( + getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")") + .toStringRef(Path) + : Name, + false)); + return error_code::success(); +} + +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; +} + +Archive::Archive(MemoryBuffer *source, error_code &ec) + : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) { + // Check for sufficient magic. + assert(source); + if (source->getBufferSize() < 8 || + StringRef(source->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(); + + if (i == e) { + ec = object_error::success; + return; + } + + StringRef Name = i->getRawName(); + + // Below is the pattern that is used to figure out the archive format + // GNU archive format + // First member : / (may exist, if it exists, points to the symbol table ) + // Second member : // (may exist, if it exists, points to the string table) + // Note : The string table is used if the filename exceeds 15 characters + // BSD archive format + // First member : __.SYMDEF or "__.SYMDEF SORTED" (the symbol table) + // There is no string table, if the filename exceeds 15 characters or has a + // embedded space, the filename has #1/<size>, The size represents the size + // of the filename that needs to be read after the archive header + // COFF archive format + // First member : / + // Second member : / (provides a directory of symbols) + // Third member : // (may exist, if it exists, contains the string table) + // Note: Microsoft PE/COFF Spec 8.3 says that the third member is present + // even if the string table is empty. However, lib.exe does not in fact + // seem to create the third member if there's no member whose filename + // exceeds 15 characters. So the third member is optional. + + if (Name == "__.SYMDEF") { + Format = K_BSD; + SymbolTable = i; + ++i; + FirstRegular = i; + ec = object_error::success; + return; + } + + 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); + if (ec) + return; + if (Name == "__.SYMDEF SORTED") { + SymbolTable = i; + ++i; + } + FirstRegular = i; + return; + } + + if (Name == "/") { + SymbolTable = i; + + ++i; + if (i == e) { + ec = object_error::parse_failed; + return; + } + Name = i->getRawName(); + } + + if (Name == "//") { + Format = K_GNU; + StringTable = i; + ++i; + FirstRegular = i; + ec = object_error::success; + return; + } + + if (Name[0] != '/') { + Format = K_GNU; + FirstRegular = i; + ec = object_error::success; + return; + } + + if (Name != "/") { + ec = object_error::parse_failed; + return; + } + + Format = K_COFF; + SymbolTable = i; + + ++i; + if (i == e) { + FirstRegular = i; + ec = object_error::success; + return; + } + + Name = i->getRawName(); + + if (Name == "//") { + StringTable = i; + ++i; + } + + FirstRegular = i; + ec = object_error::success; +} + +Archive::child_iterator Archive::begin_children(bool SkipInternal) const { + if (Data->getBufferSize() == 8) // empty archive. + return end_children(); + + if (SkipInternal) + return FirstRegular; + + const char *Loc = Data->getBufferStart() + strlen(Magic); + Child c(this, Loc); + return c; +} + +Archive::child_iterator Archive::end_children() const { + return Child(this, NULL); +} + +error_code Archive::Symbol::getName(StringRef &Result) const { + Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); + return object_error::success; +} + +error_code Archive::Symbol::getMember(child_iterator &Result) const { + const char *Buf = Parent->SymbolTable->getBuffer().begin(); + const char *Offsets = Buf + 4; + uint32_t Offset = 0; + if (Parent->kind() == K_GNU) { + Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) + + SymbolIndex); + } else if (Parent->kind() == K_BSD) { + llvm_unreachable("BSD format is not supported"); + } else { + uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); + + // Skip offsets. + Buf += sizeof(support::ulittle32_t) + + (MemberCount * sizeof(support::ulittle32_t)); + + uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); + + if (SymbolIndex >= SymbolCount) + return object_error::parse_failed; + + // Skip SymbolCount to get to the indices table. + const char *Indices = Buf + sizeof(support::ulittle32_t); + + // Get the index of the offset in the file member offset table for this + // symbol. + uint16_t OffsetIndex = + *(reinterpret_cast<const support::ulittle16_t*>(Indices) + + SymbolIndex); + // Subtract 1 since OffsetIndex is 1 based. + --OffsetIndex; + + if (OffsetIndex >= MemberCount) + return object_error::parse_failed; + + Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets) + + OffsetIndex); + } + + const char *Loc = Parent->getData().begin() + Offset; + Result = Child(Parent, Loc); + + return object_error::success; +} + +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; + ++t.SymbolIndex; + return t; +} + +Archive::symbol_iterator Archive::begin_symbols() const { + if (!hasSymbolTable()) + return symbol_iterator(Symbol(this, 0, 0)); + + const char *buf = SymbolTable->getBuffer().begin(); + if (kind() == K_GNU) { + uint32_t symbol_count = 0; + 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"); + } else { + uint32_t member_count = 0; + uint32_t symbol_count = 0; + member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (symbol_count * 2); // Skip indices. + } + uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin(); + return symbol_iterator(Symbol(this, 0, string_start_offset)); +} + +Archive::symbol_iterator Archive::end_symbols() const { + if (!hasSymbolTable()) + return symbol_iterator(Symbol(this, 0, 0)); + + const char *buf = SymbolTable->getBuffer().begin(); + uint32_t symbol_count = 0; + 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"); + } else { + uint32_t member_count = 0; + member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + } + return symbol_iterator( + Symbol(this, symbol_count, 0)); +} + +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; + for (; bs != es; ++bs) { + if (bs->getName(symname)) + return end_children(); + if (symname == name) { + if (bs->getMember(result)) + return end_children(); + return result; + } + } + return end_children(); +} + +bool Archive::hasSymbolTable() const { + return SymbolTable != end_children(); +} diff --git a/contrib/llvm/lib/Object/Binary.cpp b/contrib/llvm/lib/Object/Binary.cpp new file mode 100644 index 000000000000..de57b4c9a742 --- /dev/null +++ b/contrib/llvm/lib/Object/Binary.cpp @@ -0,0 +1,118 @@ +//===- Binary.cpp - A generic binary file -----------------------*- 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 the Binary class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Binary.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/FileSystem.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(unsigned int Type, MemoryBuffer *Source) + : TypeID(Type) + , Data(Source) {} + +StringRef Binary::getData() const { + return Data->getBuffer(); +} + +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; + } + 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::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: { + 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::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::bitcode: + 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); +} diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp new file mode 100644 index 000000000000..42066c372b43 --- /dev/null +++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp @@ -0,0 +1,938 @@ +//===- COFFObjectFile.cpp - COFF 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. +// +//===----------------------------------------------------------------------===// +// +// This file declares the COFFObjectFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/COFF.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> + +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; + return false; + } + return true; +} + +// 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)) { + uintptr_t Addr = uintptr_t(Ptr); + 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; +} +} + +const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { + const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.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 + + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) + report_fatal_error("Symbol was outside of symbol table."); + + assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) + == 0 && "Symbol did not point to the beginning of a symbol"); +# endif + + return addr; +} + +const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { + const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); + +# ifndef NDEBUG + // Verify that the section points to a valid entry in the section table. + 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 && + "Section did not point to the beginning of a section"); +# endif + + 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; +} + + 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; +} + +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; + + if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + Result = UnknownAddressOrSize; + else if (Section) + Result = Section->VirtualAddress + symb->Value; + else + Result = symb->Value; + return object_error::success; +} + +error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Result) const { + const coff_symbol *symb = toSymb(Symb); + Result = SymbolRef::ST_Other; + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { + Result = SymbolRef::ST_Unknown; + } 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; + } + } + return object_error::success; +} + +error_code COFFObjectFile::getSymbolFlags(DataRefImpl Symb, + uint32_t &Result) const { + const coff_symbol *symb = toSymb(Symb); + Result = SymbolRef::SF_None; + + // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, 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) + Result |= SymbolRef::SF_Global; + + if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + Result |= SymbolRef::SF_Weak; + + if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) + Result |= SymbolRef::SF_Absolute; + + return object_error::success; +} + +error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, + 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; + + if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + Result = UnknownAddressOrSize; + else if (Section) + 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)); + } + return object_error::success; +} + +error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); +} + +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; +} + +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; + return object_error::success; +} + +error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Result) const { + const coff_section *sec = toSec(Sec); + Result = sec->SizeOfRawData; + return object_error::success; +} + +error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Result) const { + const coff_section *sec = toSec(Sec); + ArrayRef<uint8_t> Res; + 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) + return object_error::parse_failed; + 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; + 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; + 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; + return object_error::success; +} + +error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + 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; + return object_error::success; +} + +error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + +error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + 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) + 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_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)); +} + +// Initialize the pointer to the symbol table. +error_code COFFObjectFile::initSymbolTablePtr() { + if (error_code ec = getObject( + SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, + COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) + 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 + // string table is empty, the value of the first four byte would be 4. + const uint8_t *StringTableAddr = + base() + COFFHeader->PointerToSymbolTable + + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); + const ulittle32_t *StringTableSizePtr; + if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr)) + return ec; + StringTableSize = *StringTableSizePtr; + if (error_code ec = + getObject(StringTable, Data, StringTableAddr, StringTableSize)) + return ec; + + // Check that the string table is null terminated if has any in it. + if (StringTableSize < 4 || + (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) + return object_error::parse_failed; + return object_error::success; +} + +// 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); + uint32_t SectionStart = Section->VirtualAddress; + uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; + if (SectionStart <= Rva && Rva < SectionEnd) { + uint32_t Offset = Rva - SectionStart; + Res = uintptr_t(base()) + Section->PointerToRawData + Offset; + return object_error::success; + } + } + return object_error::parse_failed; +} + +// 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 { + uintptr_t IntPtr = 0; + if (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)); + return object_error::success; +} + +// Find the import table. +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; + if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) + return object_error::success; + + // Do nothing if the pointer to import table is NULL. + if (DataEntry->RelativeVirtualAddress == 0) + return object_error::success; + + uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; + NumberOfImportDirectory = DataEntry->Size / + sizeof(import_directory_table_entry); + + // 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; + ImportDirectory = reinterpret_cast< + const import_directory_table_entry *>(IntPtr); + + // It's an error if there's no section containing the Import Table RVA. + return object_error::parse_failed; +} + +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) { + // Check that we at least have enough room for a header. + 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; + + // 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; + 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; + return; + } + CurPtr += 4; // Skip the PE magic bytes. + hasPEHeader = true; + } + + if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) + return; + CurPtr += sizeof(coff_file_header); + + if (hasPEHeader) { + if ((ec = getObject(PE32Header, Data, base() + CurPtr))) + 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; + } + CurPtr += COFFHeader->SizeOfOptionalHeader; + } + + if (!COFFHeader->isImportLibrary()) + 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())) + return; + + // Initialize the pointer to the beginning of the import table. + if ((ec = initImportTablePtr())) + return; + + ec = object_error::success; +} + +symbol_iterator COFFObjectFile::begin_symbols() const { + DataRefImpl ret; + ret.p = reinterpret_cast<uintptr_t>(SymbolTable); + return symbol_iterator(SymbolRef(ret, this)); +} + +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)); +} + +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"); +} + +library_iterator COFFObjectFile::begin_libraries_needed() const { + // TODO: implement + report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); +} + +library_iterator COFFObjectFile::end_libraries_needed() const { + // TODO: implement + report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); +} + +StringRef COFFObjectFile::getLoadName() const { + // COFF does not have this field. + return ""; +} + +import_directory_iterator COFFObjectFile::import_directory_begin() const { + DataRefImpl Imp; + Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory); + return import_directory_iterator(ImportDirectoryEntryRef(Imp, 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)); +} + +section_iterator COFFObjectFile::begin_sections() 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() + ? 0 : COFFHeader->NumberOfSections; + ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections); + return section_iterator(SectionRef(ret, this)); +} + +uint8_t COFFObjectFile::getBytesInAddress() const { + return getArch() == Triple::x86_64 ? 8 : 4; +} + +StringRef COFFObjectFile::getFileFormatName() const { + switch(COFFHeader->Machine) { + case COFF::IMAGE_FILE_MACHINE_I386: + return "COFF-i386"; + case COFF::IMAGE_FILE_MACHINE_AMD64: + return "COFF-x86-64"; + default: + return "COFF-<unknown arch>"; + } +} + +unsigned COFFObjectFile::getArch() const { + switch(COFFHeader->Machine) { + case COFF::IMAGE_FILE_MACHINE_I386: + return Triple::x86; + case COFF::IMAGE_FILE_MACHINE_AMD64: + return Triple::x86_64; + default: + return Triple::UnknownArch; + } +} + +// 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 { + return getCOFFHeader(Res); +} + +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 { + Res = PE32Header; + return object_error::success; +} + +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) + return object_error::parse_failed; + Res = &DataDirectory[index]; + return object_error::success; +} + +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) + // We already verified the section table data, so no need to check again. + Result = SectionTable + (index - 1); + else + return object_error::parse_failed; + return object_error::success; +} + +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) + return object_error::unexpected_eof; + 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; + else + return object_error::parse_failed; + return object_error::success; +} + +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; + return object_error::success; + } + + if (symbol->Name.ShortName[7] == 0) + // Null terminated, let ::strlen figure out the length. + Res = StringRef(symbol->Name.ShortName); + else + // Not null terminated, use all 8 bytes. + 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; + + if ( symbol->NumberOfAuxSymbols > 0 ) { + // AUX data comes immediately after the symbol in COFF + 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 + + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) + report_fatal_error("Aux Symbol data was outside of symbol table."); + + 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)); +} + +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. + Name = Sec->Name; + else + // Not null terminated, use all 8 bytes. + Name = StringRef(Sec->Name, 8); + + // 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; + } + + Res = Name; + return object_error::success; +} + +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. + uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; + uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; + if (ConEnd > uintptr_t(Data->getBufferEnd())) + return object_error::parse_failed; + Res = ArrayRef<uint8_t>(reinterpret_cast<const unsigned char*>(ConStart), + Sec->SizeOfRawData); + return object_error::success; +} + +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 { + 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 { + report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); +} +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)); +} +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_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { + return toSymb(It->getRawDataRefImpl()); +} + +const coff_relocation *COFFObjectFile::getCOFFRelocation( + relocation_iterator &It) const { + return toRel(It->getRawDataRefImpl()); +} + +#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ + case COFF::enum: res = #enum; break; + +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) { + 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); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32NB); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_1); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_2); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_3); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_4); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_REL32_5); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECTION); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SECREL7); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_TOKEN); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SREL32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); + default: + res = "Unknown"; + } + break; + case COFF::IMAGE_FILE_MACHINE_I386: + 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); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR32NB); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SEG12); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECTION); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_TOKEN); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); + LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); + default: + res = "Unknown"; + } + break; + default: + res = "Unknown"; + } + 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()); + return object_error::success; +} + +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 { + report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); +} + +bool ImportDirectoryEntryRef:: +operator==(const ImportDirectoryEntryRef &Other) const { + return ImportDirectoryPimpl == Other.ImportDirectoryPimpl; +} + +static const import_directory_table_entry *toImportEntry(DataRefImpl Imp) { + return reinterpret_cast<const import_directory_table_entry *>(Imp.p); +} + +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); + return object_error::success; +} + +error_code ImportDirectoryEntryRef:: +getImportTableEntry(const import_directory_table_entry *&Result) const { + Result = toImportEntry(ImportDirectoryPimpl); + return object_error::success; +} + +error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { + const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); + 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); + return object_error::success; +} + +error_code ImportDirectoryEntryRef::getImportLookupEntry( + const import_lookup_table_entry32 *&Result) const { + const import_directory_table_entry *Dir = toImportEntry(ImportDirectoryPimpl); + uintptr_t IntPtr = 0; + if (error_code ec = OwningObject->getRvaPtr( + Dir->ImportLookupTableRVA, IntPtr)) + return ec; + Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); + return object_error::success; +} + +namespace llvm { + + ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { + error_code ec; + return new COFFObjectFile(Object, ec); + } + +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/COFFYAML.cpp b/contrib/llvm/lib/Object/COFFYAML.cpp new file mode 100644 index 000000000000..e549b4e9ea25 --- /dev/null +++ b/contrib/llvm/lib/Object/COFFYAML.cpp @@ -0,0 +1,281 @@ +//===- COFFYAML.cpp - COFF YAMLIO implementation --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes for handling the YAML representation of COFF. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/COFFYAML.h" + +#define ECase(X) IO.enumCase(Value, #X, COFF::X); +namespace llvm { + +namespace COFFYAML { +Section::Section() { memset(&Header, 0, sizeof(COFF::section)); } +Symbol::Symbol() { memset(&Header, 0, sizeof(COFF::symbol)); } +Object::Object() { memset(&Header, 0, sizeof(COFF::header)); } +} + +namespace yaml { +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_EBC); + ECase(IMAGE_FILE_MACHINE_I386); + ECase(IMAGE_FILE_MACHINE_IA64); + ECase(IMAGE_FILE_MACHINE_M32R); + ECase(IMAGE_FILE_MACHINE_MIPS16); + ECase(IMAGE_FILE_MACHINE_MIPSFPU); + ECase(IMAGE_FILE_MACHINE_MIPSFPU16); + ECase(IMAGE_FILE_MACHINE_POWERPC); + ECase(IMAGE_FILE_MACHINE_POWERPCFP); + ECase(IMAGE_FILE_MACHINE_R4000); + ECase(IMAGE_FILE_MACHINE_SH3); + ECase(IMAGE_FILE_MACHINE_SH3DSP); + ECase(IMAGE_FILE_MACHINE_SH4); + ECase(IMAGE_FILE_MACHINE_SH5); + ECase(IMAGE_FILE_MACHINE_THUMB); + ECase(IMAGE_FILE_MACHINE_WCEMIPSV2); +} + +void ScalarEnumerationTraits<COFF::SymbolBaseType>::enumeration( + IO &IO, COFF::SymbolBaseType &Value) { + ECase(IMAGE_SYM_TYPE_NULL); + ECase(IMAGE_SYM_TYPE_VOID); + ECase(IMAGE_SYM_TYPE_CHAR); + ECase(IMAGE_SYM_TYPE_SHORT); + ECase(IMAGE_SYM_TYPE_INT); + ECase(IMAGE_SYM_TYPE_LONG); + ECase(IMAGE_SYM_TYPE_FLOAT); + ECase(IMAGE_SYM_TYPE_DOUBLE); + ECase(IMAGE_SYM_TYPE_STRUCT); + ECase(IMAGE_SYM_TYPE_UNION); + ECase(IMAGE_SYM_TYPE_ENUM); + ECase(IMAGE_SYM_TYPE_MOE); + ECase(IMAGE_SYM_TYPE_BYTE); + ECase(IMAGE_SYM_TYPE_WORD); + ECase(IMAGE_SYM_TYPE_UINT); + ECase(IMAGE_SYM_TYPE_DWORD); +} + +void ScalarEnumerationTraits<COFF::SymbolStorageClass>::enumeration( + IO &IO, COFF::SymbolStorageClass &Value) { + ECase(IMAGE_SYM_CLASS_END_OF_FUNCTION); + ECase(IMAGE_SYM_CLASS_NULL); + ECase(IMAGE_SYM_CLASS_AUTOMATIC); + ECase(IMAGE_SYM_CLASS_EXTERNAL); + ECase(IMAGE_SYM_CLASS_STATIC); + ECase(IMAGE_SYM_CLASS_REGISTER); + ECase(IMAGE_SYM_CLASS_EXTERNAL_DEF); + ECase(IMAGE_SYM_CLASS_LABEL); + ECase(IMAGE_SYM_CLASS_UNDEFINED_LABEL); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_ARGUMENT); + ECase(IMAGE_SYM_CLASS_STRUCT_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_UNION); + ECase(IMAGE_SYM_CLASS_UNION_TAG); + ECase(IMAGE_SYM_CLASS_TYPE_DEFINITION); + ECase(IMAGE_SYM_CLASS_UNDEFINED_STATIC); + ECase(IMAGE_SYM_CLASS_ENUM_TAG); + ECase(IMAGE_SYM_CLASS_MEMBER_OF_ENUM); + ECase(IMAGE_SYM_CLASS_REGISTER_PARAM); + ECase(IMAGE_SYM_CLASS_BIT_FIELD); + ECase(IMAGE_SYM_CLASS_BLOCK); + ECase(IMAGE_SYM_CLASS_FUNCTION); + ECase(IMAGE_SYM_CLASS_END_OF_STRUCT); + ECase(IMAGE_SYM_CLASS_FILE); + ECase(IMAGE_SYM_CLASS_SECTION); + ECase(IMAGE_SYM_CLASS_WEAK_EXTERNAL); + ECase(IMAGE_SYM_CLASS_CLR_TOKEN); +} + +void ScalarEnumerationTraits<COFF::SymbolComplexType>::enumeration( + IO &IO, COFF::SymbolComplexType &Value) { + ECase(IMAGE_SYM_DTYPE_NULL); + ECase(IMAGE_SYM_DTYPE_POINTER); + ECase(IMAGE_SYM_DTYPE_FUNCTION); + ECase(IMAGE_SYM_DTYPE_ARRAY); +} + +void ScalarEnumerationTraits<COFF::RelocationTypeX86>::enumeration( + IO &IO, COFF::RelocationTypeX86 &Value) { + ECase(IMAGE_REL_I386_ABSOLUTE); + ECase(IMAGE_REL_I386_DIR16); + ECase(IMAGE_REL_I386_REL16); + ECase(IMAGE_REL_I386_DIR32); + ECase(IMAGE_REL_I386_DIR32NB); + ECase(IMAGE_REL_I386_SEG12); + ECase(IMAGE_REL_I386_SECTION); + ECase(IMAGE_REL_I386_SECREL); + ECase(IMAGE_REL_I386_TOKEN); + ECase(IMAGE_REL_I386_SECREL7); + ECase(IMAGE_REL_I386_REL32); + ECase(IMAGE_REL_AMD64_ABSOLUTE); + ECase(IMAGE_REL_AMD64_ADDR64); + ECase(IMAGE_REL_AMD64_ADDR32); + ECase(IMAGE_REL_AMD64_ADDR32NB); + ECase(IMAGE_REL_AMD64_REL32); + ECase(IMAGE_REL_AMD64_REL32_1); + ECase(IMAGE_REL_AMD64_REL32_2); + ECase(IMAGE_REL_AMD64_REL32_3); + ECase(IMAGE_REL_AMD64_REL32_4); + ECase(IMAGE_REL_AMD64_REL32_5); + ECase(IMAGE_REL_AMD64_SECTION); + ECase(IMAGE_REL_AMD64_SECREL); + ECase(IMAGE_REL_AMD64_SECREL7); + ECase(IMAGE_REL_AMD64_TOKEN); + ECase(IMAGE_REL_AMD64_SREL32); + ECase(IMAGE_REL_AMD64_PAIR); + ECase(IMAGE_REL_AMD64_SSPAN32); +} +#undef ECase + +#define BCase(X) IO.bitSetCase(Value, #X, COFF::X); +void ScalarBitSetTraits<COFF::Characteristics>::bitset( + IO &IO, COFF::Characteristics &Value) { + BCase(IMAGE_FILE_RELOCS_STRIPPED); + BCase(IMAGE_FILE_EXECUTABLE_IMAGE); + BCase(IMAGE_FILE_LINE_NUMS_STRIPPED); + BCase(IMAGE_FILE_LOCAL_SYMS_STRIPPED); + BCase(IMAGE_FILE_AGGRESSIVE_WS_TRIM); + BCase(IMAGE_FILE_LARGE_ADDRESS_AWARE); + BCase(IMAGE_FILE_BYTES_REVERSED_LO); + BCase(IMAGE_FILE_32BIT_MACHINE); + BCase(IMAGE_FILE_DEBUG_STRIPPED); + BCase(IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP); + BCase(IMAGE_FILE_NET_RUN_FROM_SWAP); + BCase(IMAGE_FILE_SYSTEM); + BCase(IMAGE_FILE_DLL); + BCase(IMAGE_FILE_UP_SYSTEM_ONLY); + BCase(IMAGE_FILE_BYTES_REVERSED_HI); +} + +void ScalarBitSetTraits<COFF::SectionCharacteristics>::bitset( + IO &IO, COFF::SectionCharacteristics &Value) { + BCase(IMAGE_SCN_TYPE_NO_PAD); + BCase(IMAGE_SCN_CNT_CODE); + BCase(IMAGE_SCN_CNT_INITIALIZED_DATA); + BCase(IMAGE_SCN_CNT_UNINITIALIZED_DATA); + BCase(IMAGE_SCN_LNK_OTHER); + BCase(IMAGE_SCN_LNK_INFO); + BCase(IMAGE_SCN_LNK_REMOVE); + BCase(IMAGE_SCN_LNK_COMDAT); + BCase(IMAGE_SCN_GPREL); + BCase(IMAGE_SCN_MEM_PURGEABLE); + BCase(IMAGE_SCN_MEM_16BIT); + BCase(IMAGE_SCN_MEM_LOCKED); + BCase(IMAGE_SCN_MEM_PRELOAD); + BCase(IMAGE_SCN_LNK_NRELOC_OVFL); + BCase(IMAGE_SCN_MEM_DISCARDABLE); + BCase(IMAGE_SCN_MEM_NOT_CACHED); + BCase(IMAGE_SCN_MEM_NOT_PAGED); + BCase(IMAGE_SCN_MEM_SHARED); + BCase(IMAGE_SCN_MEM_EXECUTE); + BCase(IMAGE_SCN_MEM_READ); + BCase(IMAGE_SCN_MEM_WRITE); +} +#undef BCase + +namespace { +struct NSectionCharacteristics { + NSectionCharacteristics(IO &) + : Characteristics(COFF::SectionCharacteristics(0)) {} + NSectionCharacteristics(IO &, uint32_t C) + : Characteristics(COFF::SectionCharacteristics(C)) {} + uint32_t denormalize(IO &) { return Characteristics; } + COFF::SectionCharacteristics Characteristics; +}; + +struct NStorageClass { + NStorageClass(IO &) : StorageClass(COFF::SymbolStorageClass(0)) {} + NStorageClass(IO &, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {} + uint8_t denormalize(IO &) { return StorageClass; } + + COFF::SymbolStorageClass StorageClass; +}; + +struct NMachine { + NMachine(IO &) : Machine(COFF::MachineTypes(0)) {} + NMachine(IO &, uint16_t M) : Machine(COFF::MachineTypes(M)) {} + uint16_t denormalize(IO &) { return Machine; } + COFF::MachineTypes Machine; +}; + +struct NHeaderCharacteristics { + NHeaderCharacteristics(IO &) : Characteristics(COFF::Characteristics(0)) {} + NHeaderCharacteristics(IO &, uint16_t C) + : Characteristics(COFF::Characteristics(C)) {} + uint16_t denormalize(IO &) { return Characteristics; } + + COFF::Characteristics Characteristics; +}; + +struct NType { + NType(IO &) : Type(COFF::RelocationTypeX86(0)) {} + NType(IO &, uint16_t T) : Type(COFF::RelocationTypeX86(T)) {} + uint16_t denormalize(IO &) { return Type; } + COFF::RelocationTypeX86 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); +} + +void MappingTraits<COFF::header>::mapping(IO &IO, COFF::header &H) { + MappingNormalization<NMachine, uint16_t> NM(IO, H.Machine); + MappingNormalization<NHeaderCharacteristics, uint16_t> NC(IO, + H.Characteristics); + + IO.mapRequired("Machine", NM->Machine); + IO.mapOptional("Characteristics", NC->Characteristics); +} + +void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { + MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass); + + IO.mapRequired("Name", S.Name); + IO.mapRequired("Value", S.Header.Value); + IO.mapRequired("SectionNumber", S.Header.SectionNumber); + 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()); +} + +void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { + MappingNormalization<NSectionCharacteristics, uint32_t> NC( + IO, Sec.Header.Characteristics); + IO.mapRequired("Name", Sec.Name); + IO.mapRequired("Characteristics", NC->Characteristics); + IO.mapOptional("Alignment", Sec.Alignment); + IO.mapRequired("SectionData", Sec.SectionData); + IO.mapOptional("Relocations", Sec.Relocations); +} + +void MappingTraits<COFFYAML::Object>::mapping(IO &IO, COFFYAML::Object &Obj) { + IO.mapRequired("header", Obj.Header); + IO.mapRequired("sections", Obj.Sections); + IO.mapRequired("symbols", Obj.Symbols); +} + +} +} diff --git a/contrib/llvm/lib/Object/ELF.cpp b/contrib/llvm/lib/Object/ELF.cpp new file mode 100644 index 000000000000..7c80d41942f9 --- /dev/null +++ b/contrib/llvm/lib/Object/ELF.cpp @@ -0,0 +1,714 @@ +//===- ELF.cpp - ELF 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. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ELF.h" + +namespace llvm { +namespace object { + +#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ + case ELF::enum: \ + return #enum; \ + +StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { + switch (Machine) { + case ELF::EM_X86_64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); + default: + break; + } + break; + case ELF::EM_386: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); + default: + break; + } + break; + case ELF::EM_MIPS: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); + 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_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_26_S1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_PC16_S1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_CALL16); + 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_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); + default: + break; + } + break; + case ELF::EM_AARCH64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); + default: + break; + } + break; + case ELF::EM_ARM: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); + default: + break; + } + break; + case ELF::EM_HEXAGON: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); + default: + break; + } + break; + case ELF::EM_PPC: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HA); + default: + break; + } + break; + case ELF::EM_PPC64: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HA); + default: + break; + } + break; + case ELF::EM_S390: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); + default: + break; + } + break; + default: + break; + } + return "Unknown"; +} + +#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME + +} // end namespace object +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp new file mode 100644 index 000000000000..15bc6be0b46e --- /dev/null +++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp @@ -0,0 +1,73 @@ +//===- ELFObjectFile.cpp - ELF 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 ELFObjectFile class implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ELFObjectFile.h" +#include "llvm/Support/MathExtras.h" + +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; + + std::size_t MaxAlignment = + 1ULL << countTrailingZeros(uintptr_t(Object->getBufferStart())); + + 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); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::little, 2, false> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); + 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); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::big, 2, false> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); + 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); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::big, 2, true> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); + 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); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::little, 2, true> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); + } + + report_fatal_error("Buffer is not an ELF object file!"); +} + +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/ELFYAML.cpp b/contrib/llvm/lib/Object/ELFYAML.cpp new file mode 100644 index 000000000000..2f35cf9b1036 --- /dev/null +++ b/contrib/llvm/lib/Object/ELFYAML.cpp @@ -0,0 +1,338 @@ +//===- ELFYAML.cpp - ELF YAMLIO implementation ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes for handling the YAML representation of ELF. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ELFYAML.h" + +namespace llvm { +namespace yaml { + +void +ScalarEnumerationTraits<ELFYAML::ELF_ET>::enumeration(IO &IO, + ELFYAML::ELF_ET &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(ET_NONE) + ECase(ET_REL) + ECase(ET_EXEC) + ECase(ET_DYN) + ECase(ET_CORE) +#undef ECase +} + +void +ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO, + ELFYAML::ELF_EM &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(EM_NONE) + ECase(EM_M32) + ECase(EM_SPARC) + ECase(EM_386) + ECase(EM_68K) + ECase(EM_88K) + ECase(EM_486) + ECase(EM_860) + ECase(EM_MIPS) + ECase(EM_S370) + ECase(EM_MIPS_RS3_LE) + ECase(EM_PARISC) + ECase(EM_VPP500) + ECase(EM_SPARC32PLUS) + ECase(EM_960) + ECase(EM_PPC) + ECase(EM_PPC64) + ECase(EM_S390) + ECase(EM_SPU) + ECase(EM_V800) + ECase(EM_FR20) + ECase(EM_RH32) + ECase(EM_RCE) + ECase(EM_ARM) + ECase(EM_ALPHA) + ECase(EM_SH) + ECase(EM_SPARCV9) + ECase(EM_TRICORE) + ECase(EM_ARC) + ECase(EM_H8_300) + ECase(EM_H8_300H) + ECase(EM_H8S) + ECase(EM_H8_500) + ECase(EM_IA_64) + ECase(EM_MIPS_X) + ECase(EM_COLDFIRE) + ECase(EM_68HC12) + ECase(EM_MMA) + ECase(EM_PCP) + ECase(EM_NCPU) + ECase(EM_NDR1) + ECase(EM_STARCORE) + ECase(EM_ME16) + ECase(EM_ST100) + ECase(EM_TINYJ) + ECase(EM_X86_64) + ECase(EM_PDSP) + ECase(EM_PDP10) + ECase(EM_PDP11) + ECase(EM_FX66) + ECase(EM_ST9PLUS) + ECase(EM_ST7) + ECase(EM_68HC16) + ECase(EM_68HC11) + ECase(EM_68HC08) + ECase(EM_68HC05) + ECase(EM_SVX) + ECase(EM_ST19) + ECase(EM_VAX) + ECase(EM_CRIS) + ECase(EM_JAVELIN) + ECase(EM_FIREPATH) + ECase(EM_ZSP) + ECase(EM_MMIX) + ECase(EM_HUANY) + ECase(EM_PRISM) + ECase(EM_AVR) + ECase(EM_FR30) + ECase(EM_D10V) + ECase(EM_D30V) + ECase(EM_V850) + ECase(EM_M32R) + ECase(EM_MN10300) + ECase(EM_MN10200) + ECase(EM_PJ) + ECase(EM_OPENRISC) + ECase(EM_ARC_COMPACT) + ECase(EM_XTENSA) + ECase(EM_VIDEOCORE) + ECase(EM_TMM_GPP) + ECase(EM_NS32K) + ECase(EM_TPC) + ECase(EM_SNP1K) + ECase(EM_ST200) + ECase(EM_IP2K) + ECase(EM_MAX) + ECase(EM_CR) + ECase(EM_F2MC16) + ECase(EM_MSP430) + ECase(EM_BLACKFIN) + ECase(EM_SE_C33) + ECase(EM_SEP) + ECase(EM_ARCA) + ECase(EM_UNICORE) + ECase(EM_EXCESS) + ECase(EM_DXP) + ECase(EM_ALTERA_NIOS2) + ECase(EM_CRX) + ECase(EM_XGATE) + ECase(EM_C166) + ECase(EM_M16C) + ECase(EM_DSPIC30F) + ECase(EM_CE) + ECase(EM_M32C) + ECase(EM_TSK3000) + ECase(EM_RS08) + ECase(EM_SHARC) + ECase(EM_ECOG2) + ECase(EM_SCORE7) + ECase(EM_DSP24) + ECase(EM_VIDEOCORE3) + ECase(EM_LATTICEMICO32) + ECase(EM_SE_C17) + ECase(EM_TI_C6000) + ECase(EM_TI_C2000) + ECase(EM_TI_C5500) + ECase(EM_MMDSP_PLUS) + ECase(EM_CYPRESS_M8C) + ECase(EM_R32C) + ECase(EM_TRIMEDIA) + ECase(EM_HEXAGON) + ECase(EM_8051) + ECase(EM_STXP7X) + ECase(EM_NDS32) + ECase(EM_ECOG1) + ECase(EM_ECOG1X) + ECase(EM_MAXQ30) + ECase(EM_XIMO16) + ECase(EM_MANIK) + ECase(EM_CRAYNV2) + ECase(EM_RX) + ECase(EM_METAG) + ECase(EM_MCST_ELBRUS) + ECase(EM_ECOG16) + ECase(EM_CR16) + ECase(EM_ETPU) + ECase(EM_SLE9X) + ECase(EM_L10M) + ECase(EM_K10M) + ECase(EM_AARCH64) + ECase(EM_AVR32) + ECase(EM_STM8) + ECase(EM_TILE64) + ECase(EM_TILEPRO) + ECase(EM_CUDA) + ECase(EM_TILEGX) + ECase(EM_CLOUDSHIELD) + ECase(EM_COREA_1ST) + ECase(EM_COREA_2ND) + ECase(EM_ARC_COMPACT2) + ECase(EM_OPEN8) + ECase(EM_RL78) + ECase(EM_VIDEOCORE5) + ECase(EM_78KOR) + ECase(EM_56800EX) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_ELFCLASS>::enumeration( + IO &IO, ELFYAML::ELF_ELFCLASS &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + // Since the semantics of ELFCLASSNONE is "invalid", just don't accept it + // here. + ECase(ELFCLASS32) + ECase(ELFCLASS64) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA>::enumeration( + IO &IO, ELFYAML::ELF_ELFDATA &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + // Since the semantics of ELFDATANONE is "invalid", just don't accept it + // here. + ECase(ELFDATA2LSB) + ECase(ELFDATA2MSB) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( + IO &IO, ELFYAML::ELF_ELFOSABI &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(ELFOSABI_NONE) + ECase(ELFOSABI_HPUX) + ECase(ELFOSABI_NETBSD) + ECase(ELFOSABI_GNU) + ECase(ELFOSABI_GNU) + ECase(ELFOSABI_HURD) + ECase(ELFOSABI_SOLARIS) + ECase(ELFOSABI_AIX) + ECase(ELFOSABI_IRIX) + ECase(ELFOSABI_FREEBSD) + ECase(ELFOSABI_TRU64) + ECase(ELFOSABI_MODESTO) + ECase(ELFOSABI_OPENBSD) + ECase(ELFOSABI_OPENVMS) + ECase(ELFOSABI_NSK) + ECase(ELFOSABI_AROS) + ECase(ELFOSABI_FENIXOS) + ECase(ELFOSABI_C6000_ELFABI) + ECase(ELFOSABI_C6000_LINUX) + ECase(ELFOSABI_ARM) + ECase(ELFOSABI_STANDALONE) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( + IO &IO, ELFYAML::ELF_SHT &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(SHT_NULL) + ECase(SHT_PROGBITS) + // No SHT_SYMTAB. Use the top-level `Symbols` key instead. + // FIXME: Issue a diagnostic with this information. + ECase(SHT_STRTAB) + ECase(SHT_RELA) + ECase(SHT_HASH) + ECase(SHT_DYNAMIC) + ECase(SHT_NOTE) + ECase(SHT_NOBITS) + ECase(SHT_REL) + ECase(SHT_SHLIB) + ECase(SHT_DYNSYM) + ECase(SHT_INIT_ARRAY) + ECase(SHT_FINI_ARRAY) + ECase(SHT_PREINIT_ARRAY) + ECase(SHT_GROUP) + ECase(SHT_SYMTAB_SHNDX) +#undef ECase +} + +void ScalarBitSetTraits<ELFYAML::ELF_SHF>::bitset(IO &IO, + ELFYAML::ELF_SHF &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); + BCase(SHF_WRITE) + BCase(SHF_ALLOC) + BCase(SHF_EXCLUDE) + BCase(SHF_EXECINSTR) + BCase(SHF_MERGE) + BCase(SHF_STRINGS) + BCase(SHF_INFO_LINK) + BCase(SHF_LINK_ORDER) + BCase(SHF_OS_NONCONFORMING) + BCase(SHF_GROUP) + BCase(SHF_TLS) +#undef BCase +} + +void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration( + IO &IO, ELFYAML::ELF_STT &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(STT_NOTYPE) + ECase(STT_OBJECT) + ECase(STT_FUNC) + ECase(STT_SECTION) + ECase(STT_FILE) + ECase(STT_COMMON) + ECase(STT_TLS) + ECase(STT_GNU_IFUNC) +#undef ECase +} + +void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, + ELFYAML::FileHeader &FileHdr) { + IO.mapRequired("Class", FileHdr.Class); + IO.mapRequired("Data", FileHdr.Data); + IO.mapOptional("OSABI", FileHdr.OSABI, ELFYAML::ELF_ELFOSABI(0)); + IO.mapRequired("Type", FileHdr.Type); + IO.mapRequired("Machine", FileHdr.Machine); + IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); +} + +void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { + IO.mapOptional("Name", Symbol.Name, StringRef()); + IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); + IO.mapOptional("Section", Symbol.Section, StringRef()); + IO.mapOptional("Value", Symbol.Value, Hex64(0)); + IO.mapOptional("Size", Symbol.Size, Hex64(0)); +} + +void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping( + IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols) { + IO.mapOptional("Local", Symbols.Local); + IO.mapOptional("Global", Symbols.Global); + IO.mapOptional("Weak", Symbols.Weak); +} + +void MappingTraits<ELFYAML::Section>::mapping(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("AddressAlign", Section.AddressAlign, Hex64(0)); +} + +void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { + IO.mapRequired("FileHeader", Object.Header); + IO.mapOptional("Sections", Object.Sections); + IO.mapOptional("Symbols", Object.Symbols); +} + +} // end namespace yaml +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/Error.cpp b/contrib/llvm/lib/Object/Error.cpp new file mode 100644 index 000000000000..47ce38c88839 --- /dev/null +++ b/contrib/llvm/lib/Object/Error.cpp @@ -0,0 +1,59 @@ +//===- Error.cpp - system_error extensions for Object -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines a new error_category for the Object library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/Error.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; +using namespace object; + +namespace { +class _object_error_category : public _do_message { +public: + virtual const char* name() const; + virtual std::string message(int ev) const; + virtual error_condition default_error_condition(int ev) const; +}; +} + +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); + switch (E) { + case object_error::success: return "Success"; + case object_error::arch_not_found: + return "No object file for requested architecture"; + case object_error::invalid_file_type: + return "The file was not recognized as a valid object file"; + case object_error::parse_failed: + return "Invalid data was encountered while parsing the file"; + case object_error::unexpected_eof: + return "The end of the file was unexpectedly encountered"; + } + llvm_unreachable("An enumerator of object_error does not have a message " + "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() { + static _object_error_category o; + return o; +} diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp new file mode 100644 index 000000000000..d2cb8bde6d24 --- /dev/null +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -0,0 +1,1605 @@ +//===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 the MachOObjectFile class, which binds the MachOObject +// class to the generic ObjectFile wrapper. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MachO.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include <cctype> +#include <cstring> +#include <limits> + +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); +} + +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) { + T Cmd; + memcpy(&Cmd, P, sizeof(T)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + SwapStruct(Cmd); + return Cmd; +} + +static uint32_t +getSegmentLoadCommandNumSections(const MachOObjectFile *O, + const MachOObjectFile::LoadCommandInfo &L) { + if (O->is64Bit()) { + MachO::segment_command_64 S = O->getSegment64LoadCommand(L); + return S.nsects; + } + MachO::segment_command S = O->getSegmentLoadCommand(L); + return S.nsects; +} + +static const char * +getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, + unsigned Sec) { + uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); + + bool Is64 = O->is64Bit(); + unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : + sizeof(MachO::segment_command); + unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : + sizeof(MachO::section); + + uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; + return reinterpret_cast<const char*>(SectionAddr); +} + +static const char *getPtr(const MachOObjectFile *O, size_t Offset) { + return O->getData().substr(Offset, 1).data(); +} + +static nlist_base +getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { + const char *P = reinterpret_cast<const char *>(DRI.p); + return getStruct<nlist_base>(O, P); +} + +static StringRef parseSegmentOrSectionName(const char *P) { + if (P[15] == 0) + // Null terminated. + return P; + // Not null terminated, so this is a 16 char string. + return StringRef(P, 16); +} + +// 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 unsigned getCPUType(const MachOObjectFile *O) { + return O->getHeader().cputype; +} + +static void printRelocationTargetName(const MachOObjectFile *O, + const MachO::any_relocation_info &RE, + raw_string_ostream &fmt) { + bool IsScattered = O->isRelocationScattered(RE); + + // Target of a scattered relocation is an address. In the interest of + // generating pretty output, scan through the symbol table looking for a + // symbol that aligns with that address. If we find one, print it. + // Otherwise, we just print the hex address of the target. + 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()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + // 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()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = O->getPlainRelocationExternal(RE); + uint64_t Val = O->getPlainRelocationSymbolNum(RE); + + if (isExtern) { + symbol_iterator SI = O->begin_symbols(); + advanceTo(SI, Val); + SI->getName(S); + } else { + section_iterator SI = O->begin_sections(); + // Adjust for the fact that sections are 1-indexed. + advanceTo(SI, Val - 1); + SI->getName(S); + } + + fmt << S; +} + +static uint32_t +getPlainRelocationAddress(const MachO::any_relocation_info &RE) { + return RE.r_word0; +} + +static unsigned +getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { + return RE.r_word0 & 0xffffff; +} + +static bool getPlainRelocationPCRel(const MachOObjectFile *O, + const MachO::any_relocation_info &RE) { + if (O->isLittleEndian()) + return (RE.r_word1 >> 24) & 1; + return (RE.r_word1 >> 7) & 1; +} + +static bool +getScatteredRelocationPCRel(const MachOObjectFile *O, + const MachO::any_relocation_info &RE) { + return (RE.r_word0 >> 30) & 1; +} + +static unsigned getPlainRelocationLength(const MachOObjectFile *O, + const MachO::any_relocation_info &RE) { + if (O->isLittleEndian()) + return (RE.r_word1 >> 25) & 3; + return (RE.r_word1 >> 5) & 3; +} + +static unsigned +getScatteredRelocationLength(const MachO::any_relocation_info &RE) { + return (RE.r_word0 >> 28) & 3; +} + +static unsigned getPlainRelocationType(const MachOObjectFile *O, + const MachO::any_relocation_info &RE) { + if (O->isLittleEndian()) + return RE.r_word1 >> 28; + return RE.r_word1 & 0xf; +} + +static unsigned +getScatteredRelocationType(const MachO::any_relocation_info &RE) { + return (RE.r_word0 >> 24) & 0xf; +} + +static uint32_t getSectionFlags(const MachOObjectFile *O, + DataRefImpl Sec) { + if (O->is64Bit()) { + MachO::section_64 Sect = O->getSection64(Sec); + return Sect.flags; + } + MachO::section Sect = O->getSection(Sec); + return Sect.flags; +} + +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, + bool IsLittleEndian, bool Is64bits, + error_code &ec) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), + SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { + uint32_t LoadCommandCount = this->getHeader().ncmds; + MachO::LoadCommandType SegmentLoadType = is64Bit() ? + MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; + + MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); + for (unsigned I = 0; ; ++I) { + if (Load.C.cmd == MachO::LC_SYMTAB) { + assert(!SymtabLoadCmd && "Multiple symbol tables"); + SymtabLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { + assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); + DysymtabLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { + assert(!DataInCodeLoadCmd && "Multiple data in code tables"); + DataInCodeLoadCmd = Load.Ptr; + } else if (Load.C.cmd == SegmentLoadType) { + uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); + for (unsigned J = 0; J < NumSections; ++J) { + const char *Sec = getSectionPtr(this, Load, J); + Sections.push_back(Sec); + } + } + + if (I == LoadCommandCount - 1) + break; + else + Load = getNextLoadCommandInfo(Load); + } +} + +error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Res) 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 { + StringRef StringTable = getStringTableData(); + 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 { + if (is64Bit()) { + MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); + Res = Entry.n_value; + } else { + MachO::nlist Entry = getSymbolTableEntry(Symb); + Res = Entry.n_value; + } + 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; + } + + return object_error::success; +} + +error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { + uint32_t flags; + this->getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) { + nlist_base Entry = getSymbolTableEntryBase(this, DRI); + Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); + } else { + Result = 0; + } + return object_error::success; +} + +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); + uint64_t Value; + getSymbolAddress(DRI, Value); + + BeginOffset = Value; + + SectionIndex = Entry.n_sect; + if (!SectionIndex) { + uint32_t flags = SymbolRef::SF_None; + this->getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Value; + else + Result = UnknownAddressOrSize; + return object_error::success; + } + // 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(); + Entry = getSymbolTableEntryBase(this, DRI); + getSymbolAddress(DRI, Value); + if (Entry.n_sect == SectionIndex && Value > BeginOffset) + if (!EndOffset || Value < EndOffset) + EndOffset = Value; + } + if (!EndOffset) { + uint64_t Size; + DataRefImpl Sec; + Sec.d.a = SectionIndex-1; + getSectionSize(Sec, Size); + getSectionAddress(Sec, EndOffset); + EndOffset += Size; + } + Result = EndOffset - BeginOffset; + return object_error::success; +} + +error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const { + nlist_base Entry = getSymbolTableEntryBase(this, Symb); + uint8_t n_type = Entry.n_type; + + Res = SymbolRef::ST_Other; + + // If this is a STAB debugging symbol, we can do nothing more. + if (n_type & MachO::N_STAB) { + Res = SymbolRef::ST_Debug; + return object_error::success; + } + + switch (n_type & MachO::N_TYPE) { + case MachO::N_UNDF : + Res = SymbolRef::ST_Unknown; + break; + case MachO::N_SECT : + Res = SymbolRef::ST_Function; + break; + } + return object_error::success; +} + +error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, + uint32_t &Result) const { + 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; + + if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) + Result |= SymbolRef::SF_Undefined; + + if (MachOType & MachO::N_STAB) + Result |= SymbolRef::SF_FormatSpecific; + + if (MachOType & MachO::N_EXT) { + Result |= SymbolRef::SF_Global; + if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { + uint64_t Value; + getSymbolAddress(DRI, Value); + if (Value) + Result |= SymbolRef::SF_Common; + } + } + + if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) + Result |= SymbolRef::SF_Weak; + + if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) + Result |= SymbolRef::SF_Absolute; + + return object_error::success; +} + +error_code +MachOObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + nlist_base Entry = getSymbolTableEntryBase(this, Symb); + uint8_t index = Entry.n_sect; + + if (index == 0) { + Res = end_sections(); + } else { + DataRefImpl DRI; + DRI.d.a = index - 1; + Res = section_iterator(SectionRef(DRI, this)); + } + + 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 { + Sec.d.a++; + Res = SectionRef(Sec, this); + return object_error::success; +} + +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 { + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + Res = Sect.addr; + } else { + MachO::section Sect = getSection(Sec); + Res = Sect.addr; + } + return object_error::success; +} + +error_code +MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + Res = Sect.size; + } else { + MachO::section Sect = getSection(Sec); + Res = Sect.size; + } + + return object_error::success; +} + +error_code +MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { + uint32_t Offset; + uint64_t Size; + + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + Offset = Sect.offset; + Size = Sect.size; + } else { + MachO::section Sect = getSection(Sec); + Offset = Sect.offset; + Size = Sect.size; + } + + Res = this->getData().substr(Offset, Size); + return object_error::success; +} + +error_code +MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { + uint32_t Align; + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + Align = Sect.align; + } else { + MachO::section Sect = getSection(Sec); + Align = Sect.align; + } + + Res = uint64_t(1) << Align; + return object_error::success; +} + +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; + return object_error::success; +} + +error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + +error_code +MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { + // FIXME: Unimplemented. + Result = true; + return object_error::success; +} + +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 { + uint32_t Flags = getSectionFlags(this, Sec); + unsigned SectionType = Flags & MachO::SECTION_TYPE; + Res = SectionType == MachO::S_ZEROFILL || + SectionType == MachO::S_GB_ZEROFILL; + return object_error::success; +} + +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. + + // FIXME: Unimplemented. + Result = false; + return object_error::success; +} + +error_code +MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const { + SymbolRef::Type ST; + this->getSymbolType(Symb, ST); + if (ST == SymbolRef::ST_Unknown) { + Result = false; + return object_error::success; + } + + uint64_t SectBegin, SectEnd; + getSectionAddress(Sec, SectBegin); + getSectionSize(Sec, SectEnd); + SectEnd += SectBegin; + + uint64_t SymAddr; + getSymbolAddress(Symb, SymAddr); + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); + + return object_error::success; +} + +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)); + 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); + 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; +} + +error_code +MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { + report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); +} + +error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { + MachO::any_relocation_info RE = getRelocation(Rel); + Res = getAnyRelocationAddress(RE); + return object_error::success; +} + +symbol_iterator +MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { + MachO::any_relocation_info RE = getRelocation(Rel); + uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); + bool isExtern = getPlainRelocationExternal(RE); + if (!isExtern) + return end_symbols(); + + MachO::symtab_command S = getSymtabLoadCommand(); + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(MachO::nlist_64) : + sizeof(MachO::nlist); + uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; + DataRefImpl Sym; + Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); + return symbol_iterator(SymbolRef(Sym, this)); +} + +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 +MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { + StringRef res; + uint64_t RType; + getRelocationType(Rel, RType); + + unsigned Arch = this->getArch(); + + switch (Arch) { + case Triple::x86: { + static const char *const Table[] = { + "GENERIC_RELOC_VANILLA", + "GENERIC_RELOC_PAIR", + "GENERIC_RELOC_SECTDIFF", + "GENERIC_RELOC_PB_LA_PTR", + "GENERIC_RELOC_LOCAL_SECTDIFF", + "GENERIC_RELOC_TLV" }; + + if (RType > 6) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::x86_64: { + static const char *const Table[] = { + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SUBTRACTOR", + "X86_64_RELOC_SIGNED_1", + "X86_64_RELOC_SIGNED_2", + "X86_64_RELOC_SIGNED_4", + "X86_64_RELOC_TLV" }; + + if (RType > 9) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::arm: { + static const char *const Table[] = { + "ARM_RELOC_VANILLA", + "ARM_RELOC_PAIR", + "ARM_RELOC_SECTDIFF", + "ARM_RELOC_LOCAL_SECTDIFF", + "ARM_RELOC_PB_LA_PTR", + "ARM_RELOC_BR24", + "ARM_THUMB_RELOC_BR22", + "ARM_THUMB_32BIT_BRANCH", + "ARM_RELOC_HALF", + "ARM_RELOC_HALF_SECTDIFF" }; + + if (RType > 9) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::ppc: { + static const char *const Table[] = { + "PPC_RELOC_VANILLA", + "PPC_RELOC_PAIR", + "PPC_RELOC_BR14", + "PPC_RELOC_BR24", + "PPC_RELOC_HI16", + "PPC_RELOC_LO16", + "PPC_RELOC_HA16", + "PPC_RELOC_LO14", + "PPC_RELOC_SECTDIFF", + "PPC_RELOC_PB_LA_PTR", + "PPC_RELOC_HI16_SECTDIFF", + "PPC_RELOC_LO16_SECTDIFF", + "PPC_RELOC_HA16_SECTDIFF", + "PPC_RELOC_JBSR", + "PPC_RELOC_LO14_SECTDIFF", + "PPC_RELOC_LOCAL_SECTDIFF" }; + + res = Table[RType]; + break; + } + case Triple::UnknownArch: + res = "Unknown"; + break; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +error_code +MachOObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { + MachO::any_relocation_info RE = getRelocation(Rel); + + unsigned Arch = this->getArch(); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + unsigned Type = this->getAnyRelocationType(RE); + bool IsPCRel = this->getAnyRelocationPCRel(RE); + + // Determine any addends that should be displayed with the relocation. + // These require decoding the relocation type, which is triple-specific. + + // X86_64 has entirely custom relocation types. + if (Arch == Triple::x86_64) { + bool isPCRel = getAnyRelocationPCRel(RE); + + switch (Type) { + case MachO::X86_64_RELOC_GOT_LOAD: + case MachO::X86_64_RELOC_GOT: { + printRelocationTargetName(this, RE, fmt); + fmt << "@GOT"; + if (isPCRel) fmt << "PCREL"; + break; + } + case MachO::X86_64_RELOC_SUBTRACTOR: { + DataRefImpl RelNext = Rel; + RelNext.d.a++; + MachO::any_relocation_info RENext = getRelocation(RelNext); + + // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = getAnyRelocationType(RENext); + if (RType != MachO::X86_64_RELOC_UNSIGNED) + report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol; + // X86_64_RELOC_SUBTRACTOR contains the subtrahend. + printRelocationTargetName(this, RENext, fmt); + fmt << "-"; + printRelocationTargetName(this, RE, fmt); + break; + } + case MachO::X86_64_RELOC_TLV: + printRelocationTargetName(this, RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + case MachO::X86_64_RELOC_SIGNED_1: + printRelocationTargetName(this, RE, fmt); + fmt << "-1"; + break; + case MachO::X86_64_RELOC_SIGNED_2: + printRelocationTargetName(this, RE, fmt); + fmt << "-2"; + break; + case MachO::X86_64_RELOC_SIGNED_4: + printRelocationTargetName(this, RE, fmt); + fmt << "-4"; + break; + default: + printRelocationTargetName(this, RE, fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm || + Arch == Triple::ppc) { + // Generic relocation types... + switch (Type) { + case MachO::GENERIC_RELOC_PAIR: // prints no info + return object_error::success; + case MachO::GENERIC_RELOC_SECTDIFF: { + DataRefImpl RelNext = Rel; + RelNext.d.a++; + MachO::any_relocation_info RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); + + if (RType != MachO::GENERIC_RELOC_PAIR) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(this, RE, fmt); + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + break; + } + } + + if (Arch == Triple::x86 || Arch == Triple::ppc) { + switch (Type) { + case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { + DataRefImpl RelNext = Rel; + RelNext.d.a++; + MachO::any_relocation_info RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); + if (RType != MachO::GENERIC_RELOC_PAIR) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(this, RE, fmt); + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + break; + } + case MachO::GENERIC_RELOC_TLV: { + printRelocationTargetName(this, RE, fmt); + fmt << "@TLV"; + if (IsPCRel) fmt << "P"; + break; + } + default: + printRelocationTargetName(this, RE, fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case MachO::ARM_RELOC_HALF: + case MachO::ARM_RELOC_HALF_SECTDIFF: { + // Half relocations steal a bit from the length field to encode + // whether this is an upper16 or a lower16 relocation. + bool isUpper = getAnyRelocationLength(RE) >> 1; + + if (isUpper) + fmt << ":upper16:("; + else + fmt << ":lower16:("; + printRelocationTargetName(this, RE, fmt); + + DataRefImpl RelNext = Rel; + RelNext.d.a++; + MachO::any_relocation_info RENext = getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); + if (RType != MachO::ARM_RELOC_PAIR) + report_fatal_error("Expected ARM_RELOC_PAIR after " + "ARM_RELOC_HALF"); + + // NOTE: The half of the target virtual address is stashed in the + // address field of the secondary relocation, but we can't reverse + // engineer the constant offset from it without decoding the movw/movt + // instruction to find the other half in its immediate field. + + // ARM_RELOC_HALF_SECTDIFF encodes the second section in the + // symbol/section pointer of the follow-on relocation. + if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + } + + fmt << ")"; + break; + } + default: { + printRelocationTargetName(this, RE, fmt); + } + } + } + } else + printRelocationTargetName(this, RE, fmt); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + return object_error::success; +} + +error_code +MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { + unsigned Arch = getArch(); + uint64_t Type; + getRelocationType(Rel, Type); + + Result = false; + + // On arches that use the generic relocations, GENERIC_RELOC_PAIR + // is always hidden. + if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { + if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; + } else if (Arch == Triple::x86_64) { + // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows + // an X86_64_RELOC_SUBTRACTOR. + if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { + DataRefImpl RelPrev = Rel; + RelPrev.d.a--; + uint64_t PrevType; + getRelocationType(RelPrev, PrevType); + if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) + Result = true; + } + } + + return object_error::success; +} + +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 { + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +symbol_iterator MachOObjectFile::begin_symbols() const { + DataRefImpl DRI; + if (!SymtabLoadCmd) + return symbol_iterator(SymbolRef(DRI, this)); + + MachO::symtab_command Symtab = getSymtabLoadCommand(); + DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); + return symbol_iterator(SymbolRef(DRI, this)); +} + +symbol_iterator MachOObjectFile::end_symbols() const { + DataRefImpl DRI; + if (!SymtabLoadCmd) + return symbol_iterator(SymbolRef(DRI, this)); + + MachO::symtab_command Symtab = getSymtabLoadCommand(); + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(MachO::nlist_64) : + sizeof(MachO::nlist); + unsigned Offset = Symtab.symoff + + Symtab.nsyms * SymbolTableEntrySize; + DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); + return symbol_iterator(SymbolRef(DRI, this)); +} + +symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +symbol_iterator MachOObjectFile::end_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +section_iterator MachOObjectFile::begin_sections() const { + DataRefImpl DRI; + return section_iterator(SectionRef(DRI, this)); +} + +section_iterator MachOObjectFile::end_sections() const { + DataRefImpl DRI; + DRI.d.a = Sections.size(); + return section_iterator(SectionRef(DRI, this)); +} + +library_iterator MachOObjectFile::begin_libraries_needed() const { + // TODO: implement + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +library_iterator MachOObjectFile::end_libraries_needed() const { + // TODO: implement + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +uint8_t MachOObjectFile::getBytesInAddress() const { + return is64Bit() ? 8 : 4; +} + +StringRef MachOObjectFile::getFileFormatName() const { + unsigned CPUType = getCPUType(this); + if (!is64Bit()) { + switch (CPUType) { + case llvm::MachO::CPU_TYPE_I386: + return "Mach-O 32-bit i386"; + case llvm::MachO::CPU_TYPE_ARM: + return "Mach-O arm"; + case llvm::MachO::CPU_TYPE_POWERPC: + return "Mach-O 32-bit ppc"; + default: + assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; + } + } + + // Make sure the cpu type has the correct mask. + assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) + == llvm::MachO::CPU_ARCH_ABI64 && + "32-bit object file when we're 64-bit?"); + + switch (CPUType) { + case llvm::MachO::CPU_TYPE_X86_64: + return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPU_TYPE_POWERPC64: + return "Mach-O 64-bit ppc64"; + default: + return "Mach-O 64-bit unknown"; + } +} + +Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { + switch (CPUType) { + case llvm::MachO::CPU_TYPE_I386: + return Triple::x86; + case llvm::MachO::CPU_TYPE_X86_64: + return Triple::x86_64; + case llvm::MachO::CPU_TYPE_ARM: + return Triple::arm; + case llvm::MachO::CPU_TYPE_POWERPC: + return Triple::ppc; + case llvm::MachO::CPU_TYPE_POWERPC64: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +unsigned MachOObjectFile::getArch() const { + return getArch(getCPUType(this)); +} + +StringRef MachOObjectFile::getLoadName() const { + // TODO: Implement + report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); +} + +relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { + DataRefImpl DRI; + DRI.d.a = Index; + return section_rel_begin(DRI); +} + +relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { + DataRefImpl DRI; + DRI.d.a = Index; + return section_rel_end(DRI); +} + +dice_iterator MachOObjectFile::begin_dices() const { + DataRefImpl DRI; + if (!DataInCodeLoadCmd) + return dice_iterator(DiceRef(DRI, this)); + + MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); + DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); + return dice_iterator(DiceRef(DRI, this)); +} + +dice_iterator MachOObjectFile::end_dices() const { + DataRefImpl DRI; + if (!DataInCodeLoadCmd) + return dice_iterator(DiceRef(DRI, this)); + + MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); + unsigned Offset = DicLC.dataoff + DicLC.datasize; + DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); + return dice_iterator(DiceRef(DRI, this)); +} + +StringRef +MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { + ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); + return parseSegmentOrSectionName(Raw.data()); +} + +ArrayRef<char> +MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { + const section_base *Base = + reinterpret_cast<const section_base *>(Sections[Sec.d.a]); + return ArrayRef<char>(Base->sectname); +} + +ArrayRef<char> +MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const section_base *Base = + reinterpret_cast<const section_base *>(Sections[Sec.d.a]); + return ArrayRef<char>(Base->segname); +} + +bool +MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) + const { + if (getCPUType(this) == MachO::CPU_TYPE_X86_64) + return false; + return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; +} + +unsigned MachOObjectFile::getPlainRelocationSymbolNum( + const MachO::any_relocation_info &RE) const { + if (isLittleEndian()) + return RE.r_word1 & 0xffffff; + return RE.r_word1 >> 8; +} + +bool MachOObjectFile::getPlainRelocationExternal( + const MachO::any_relocation_info &RE) const { + if (isLittleEndian()) + return (RE.r_word1 >> 27) & 1; + return (RE.r_word1 >> 4) & 1; +} + +bool MachOObjectFile::getScatteredRelocationScattered( + const MachO::any_relocation_info &RE) const { + return RE.r_word0 >> 31; +} + +uint32_t MachOObjectFile::getScatteredRelocationValue( + const MachO::any_relocation_info &RE) const { + return RE.r_word1; +} + +unsigned MachOObjectFile::getAnyRelocationAddress( + const MachO::any_relocation_info &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationAddress(RE); + return getPlainRelocationAddress(RE); +} + +unsigned MachOObjectFile::getAnyRelocationPCRel( + const MachO::any_relocation_info &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationPCRel(this, RE); + return getPlainRelocationPCRel(this, RE); +} + +unsigned MachOObjectFile::getAnyRelocationLength( + const MachO::any_relocation_info &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationLength(RE); + return getPlainRelocationLength(this, RE); +} + +unsigned +MachOObjectFile::getAnyRelocationType( + const MachO::any_relocation_info &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationType(RE); + return getPlainRelocationType(this, RE); +} + +SectionRef +MachOObjectFile::getRelocationSection( + const MachO::any_relocation_info &RE) const { + if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) + return *end_sections(); + unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; + DataRefImpl DRI; + DRI.d.a = SecNum; + return SectionRef(DRI, this); +} + +MachOObjectFile::LoadCommandInfo +MachOObjectFile::getFirstLoadCommandInfo() const { + MachOObjectFile::LoadCommandInfo Load; + + unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : + sizeof(MachO::mach_header); + Load.Ptr = getPtr(this, HeaderSize); + Load.C = getStruct<MachO::load_command>(this, Load.Ptr); + return Load; +} + +MachOObjectFile::LoadCommandInfo +MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { + MachOObjectFile::LoadCommandInfo Next; + Next.Ptr = L.Ptr + L.C.cmdsize; + Next.C = getStruct<MachO::load_command>(this, Next.Ptr); + return Next; +} + +MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { + return getStruct<MachO::section>(this, Sections[DRI.d.a]); +} + +MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { + return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); +} + +MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, + unsigned Index) const { + const char *Sec = getSectionPtr(this, L, Index); + return getStruct<MachO::section>(this, Sec); +} + +MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, + unsigned Index) const { + const char *Sec = getSectionPtr(this, L, Index); + return getStruct<MachO::section_64>(this, Sec); +} + +MachO::nlist +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { + const char *P = reinterpret_cast<const char *>(DRI.p); + return getStruct<MachO::nlist>(this, P); +} + +MachO::nlist_64 +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { + const char *P = reinterpret_cast<const char *>(DRI.p); + return getStruct<MachO::nlist_64>(this, P); +} + +MachO::linkedit_data_command +MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::linkedit_data_command>(this, L.Ptr); +} + +MachO::segment_command +MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::segment_command>(this, L.Ptr); +} + +MachO::segment_command_64 +MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::segment_command_64>(this, L.Ptr); +} + +MachO::linker_options_command +MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::linker_options_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); +} + +MachO::data_in_code_entry +MachOObjectFile::getDice(DataRefImpl Rel) const { + const char *P = reinterpret_cast<const char *>(Rel.p); + return getStruct<MachO::data_in_code_entry>(this, P); +} + +MachO::mach_header MachOObjectFile::getHeader() const { + return getStruct<MachO::mach_header>(this, getPtr(this, 0)); +} + +MachO::mach_header_64 MachOObjectFile::getHeader64() const { + return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); +} + +uint32_t MachOObjectFile::getIndirectSymbolTableEntry( + const MachO::dysymtab_command &DLC, + unsigned Index) const { + uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); + return getStruct<uint32_t>(this, getPtr(this, Offset)); +} + +MachO::data_in_code_entry +MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const { + uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); + return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); +} + +MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { + return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); +} + +MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { + return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); +} + +MachO::linkedit_data_command +MachOObjectFile::getDataInCodeLoadCommand() const { + if (DataInCodeLoadCmd) + return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); + + // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. + MachO::linkedit_data_command Cmd; + Cmd.cmd = MachO::LC_DATA_IN_CODE; + Cmd.cmdsize = sizeof(MachO::linkedit_data_command); + Cmd.dataoff = 0; + Cmd.datasize = 0; + return Cmd; +} + +StringRef MachOObjectFile::getStringTableData() const { + MachO::symtab_command S = getSymtabLoadCommand(); + return getData().substr(S.stroff, S.strsize); +} + +bool MachOObjectFile::is64Bit() const { + return getType() == getMachOType(false, true) || + getType() == getMachOType(true, true); +} + +void MachOObjectFile::ReadULEB128s(uint64_t Index, + SmallVectorImpl<uint64_t> &Out) const { + DataExtractor extractor(ObjectFile::getData(), true, 0); + + uint32_t offset = Index; + uint64_t data = 0; + while (uint64_t delta = extractor.getULEB128(&offset)) { + data += delta; + Out.push_back(data); + } +} + +ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + StringRef Magic = Buffer->getBuffer().slice(0, 4); + error_code ec; + OwningPtr<ObjectFile> Ret; + if (Magic == "\xFE\xED\xFA\xCE") + Ret.reset(new MachOObjectFile(Buffer, false, false, ec)); + else if (Magic == "\xCE\xFA\xED\xFE") + Ret.reset(new MachOObjectFile(Buffer, true, false, ec)); + else if (Magic == "\xFE\xED\xFA\xCF") + Ret.reset(new MachOObjectFile(Buffer, false, true, ec)); + else if (Magic == "\xCF\xFA\xED\xFE") + Ret.reset(new MachOObjectFile(Buffer, true, true, ec)); + else { + delete Buffer; + return NULL; + } + + if (ec) + return NULL; + return Ret.take(); +} + +} // end namespace object +} // end namespace llvm diff --git a/contrib/llvm/lib/Object/MachOUniversal.cpp b/contrib/llvm/lib/Object/MachOUniversal.cpp new file mode 100644 index 000000000000..75160af3ad2c --- /dev/null +++ b/contrib/llvm/lib/Object/MachOUniversal.cpp @@ -0,0 +1,139 @@ +//===- MachOUniversal.cpp - Mach-O universal binary -------------*- 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 the MachOUniversalBinary class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MachOUniversal.h" + +#include "llvm/Object/MachO.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBuffer.h" + +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); +} + +template<> +void SwapStruct(MachO::fat_arch &H) { + SwapValue(H.cputype); + SwapValue(H.cpusubtype); + SwapValue(H.offset); + SwapValue(H.size); + SwapValue(H.align); +} + +template<typename T> +static T getUniversalBinaryStruct(const char *Ptr) { + T Res; + memcpy(&Res, Ptr, sizeof(T)); + // Universal binary headers have big-endian byte order. + if (sys::IsLittleEndianHost) + SwapStruct(Res); + return Res; +} + +MachOUniversalBinary::ObjectForArch::ObjectForArch( + const MachOUniversalBinary *Parent, uint32_t Index) + : Parent(Parent), Index(Index) { + if (Parent == 0 || Index > Parent->getNumberOfObjects()) { + clear(); + } else { + // Parse object header. + StringRef ParentData = Parent->getData(); + const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) + + Index * sizeof(MachO::fat_arch); + Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos); + if (ParentData.size() < Header.offset + Header.size) { + clear(); + } + } +} + +error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( + OwningPtr<ObjectFile> &Result) 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; + } + } + 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)) { + ec = object_error::invalid_file_type; + return; + } + // Check for magic value and sufficient header size. + StringRef Buf = getData(); + MachO::fat_header H= getUniversalBinaryStruct<MachO::fat_header>(Buf.begin()); + NumberOfObjects = H.nfat_arch; + uint32_t MinSize = sizeof(MachO::fat_header) + + sizeof(MachO::fat_arch) * NumberOfObjects; + if (H.magic != MachO::FAT_MAGIC || Buf.size() < MinSize) { + ec = object_error::parse_failed; + return; + } + ec = object_error::success; +} + +static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { + switch (Arch) { + case Triple::x86: CTM = MachO::CPU_TYPE_I386; return true; + case Triple::x86_64: CTM = MachO::CPU_TYPE_X86_64; return true; + case Triple::arm: CTM = MachO::CPU_TYPE_ARM; return true; + case Triple::sparc: CTM = MachO::CPU_TYPE_SPARC; return true; + case Triple::ppc: CTM = MachO::CPU_TYPE_POWERPC; return true; + case Triple::ppc64: CTM = MachO::CPU_TYPE_POWERPC64; return true; + default: return false; + } +} + +error_code +MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch, + OwningPtr<ObjectFile> &Result) 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 object_error::arch_not_found; +} diff --git a/contrib/llvm/lib/Object/Object.cpp b/contrib/llvm/lib/Object/Object.cpp new file mode 100644 index 000000000000..6941708dd349 --- /dev/null +++ b/contrib/llvm/lib/Object/Object.cpp @@ -0,0 +1,254 @@ +//===- Object.cpp - C bindings to the object file library--------*- 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 the C bindings to the file-format-independent object +// library. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm-c/Object.h" + +using namespace llvm; +using namespace object; + +inline ObjectFile *unwrap(LLVMObjectFileRef OF) { + return reinterpret_cast<ObjectFile*>(OF); +} + +inline LLVMObjectFileRef wrap(const ObjectFile *OF) { + return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF)); +} + +inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { + return reinterpret_cast<section_iterator*>(SI); +} + +inline LLVMSectionIteratorRef +wrap(const section_iterator *SI) { + return reinterpret_cast<LLVMSectionIteratorRef> + (const_cast<section_iterator*>(SI)); +} + +inline symbol_iterator *unwrap(LLVMSymbolIteratorRef SI) { + return reinterpret_cast<symbol_iterator*>(SI); +} + +inline LLVMSymbolIteratorRef +wrap(const symbol_iterator *SI) { + return reinterpret_cast<LLVMSymbolIteratorRef> + (const_cast<symbol_iterator*>(SI)); +} + +inline relocation_iterator *unwrap(LLVMRelocationIteratorRef SI) { + return reinterpret_cast<relocation_iterator*>(SI); +} + +inline LLVMRelocationIteratorRef +wrap(const relocation_iterator *SI) { + return reinterpret_cast<LLVMRelocationIteratorRef> + (const_cast<relocation_iterator*>(SI)); +} + +// ObjectFile creation +LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { + return wrap(ObjectFile::createObjectFile(unwrap(MemBuf))); +} + +void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { + delete unwrap(ObjectFile); +} + +// ObjectFile Section iterators +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { + section_iterator SI = unwrap(ObjectFile)->begin_sections(); + return wrap(new section_iterator(SI)); +} + +void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { + delete unwrap(SI); +} + +LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSectionIteratorRef SI) { + return (*unwrap(SI) == unwrap(ObjectFile)->end_sections()) ? 1 : 0; +} + +void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { + error_code ec; + unwrap(SI)->increment(ec); + if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message()); +} + +void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, + LLVMSymbolIteratorRef Sym) { + if (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(); + return wrap(new symbol_iterator(SI)); +} + +void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { + delete unwrap(SI); +} + +LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile, + LLVMSymbolIteratorRef SI) { + return (*unwrap(SI) == unwrap(ObjectFile)->end_symbols()) ? 1 : 0; +} + +void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { + error_code ec; + unwrap(SI)->increment(ec); + if (ec) report_fatal_error("LLVMMoveToNextSymbol failed: " + ec.message()); +} + +// SectionRef accessors +const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { + StringRef ret; + if (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)) + report_fatal_error(ec.message()); + return ret; +} + +const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { + StringRef ret; + if (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)) + report_fatal_error(ec.message()); + return ret; +} + +LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, + LLVMSymbolIteratorRef Sym) { + bool ret; + if (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(); + return wrap(new relocation_iterator(SI)); +} + +void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { + delete unwrap(SI); +} + +LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, + LLVMRelocationIteratorRef SI) { + return (*unwrap(SI) == (*unwrap(Section))->end_relocations()) ? 1 : 0; +} + +void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { + error_code ec; + unwrap(SI)->increment(ec); + if (ec) report_fatal_error("LLVMMoveToNextRelocation failed: " + + ec.message()); +} + + +// SymbolRef accessors +const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { + StringRef ret; + if (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)) + report_fatal_error(ec.message()); + return ret; +} + +uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { + uint64_t ret; + if (error_code ec = (*unwrap(SI))->getSize(ret)) + report_fatal_error(ec.message()); + return ret; +} + +// RelocationRef accessors +uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI) { + uint64_t ret; + if (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)) + report_fatal_error(ec.message()); + return ret; +} + +LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { + symbol_iterator ret = (*unwrap(RI))->getSymbol(); + return wrap(new symbol_iterator(ret)); +} + +uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { + uint64_t ret; + if (error_code ec = (*unwrap(RI))->getType(ret)) + report_fatal_error(ec.message()); + return ret; +} + +// NOTE: Caller takes ownership of returned string. +const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { + SmallVector<char, 0> ret; + if (error_code ec = (*unwrap(RI))->getTypeName(ret)) + report_fatal_error(ec.message()); + + char *str = static_cast<char*>(malloc(ret.size())); + std::copy(ret.begin(), ret.end(), str); + return str; +} + +// NOTE: Caller takes ownership of returned string. +const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { + SmallVector<char, 0> ret; + if (error_code ec = (*unwrap(RI))->getValueString(ret)) + report_fatal_error(ec.message()); + + char *str = static_cast<char*>(malloc(ret.size())); + std::copy(ret.begin(), ret.end(), str); + return str; +} + diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp new file mode 100644 index 000000000000..0e626d650fbb --- /dev/null +++ b/contrib/llvm/lib/Object/ObjectFile.cpp @@ -0,0 +1,84 @@ +//===- ObjectFile.cpp - File format independent object file -----*- 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 ObjectFile class. +// +//===----------------------------------------------------------------------===// + +#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" + +using namespace llvm; +using namespace object; + +void ObjectFile::anchor() { } + +ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) + : Binary(Type, source) { +} + +error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { + Result = 0; + return object_error::success; +} + +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; + } + + 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; + 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: + return createELFObjectFile(Object); + 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: + return createMachOObjectFile(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); + } + 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()); +} diff --git a/contrib/llvm/lib/Object/YAML.cpp b/contrib/llvm/lib/Object/YAML.cpp new file mode 100644 index 000000000000..c527bde090e8 --- /dev/null +++ b/contrib/llvm/lib/Object/YAML.cpp @@ -0,0 +1,68 @@ +//===- 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); + } +} |