diff options
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Android.mk | 6 | ||||
-rw-r--r-- | lib/Object/Archive.cpp | 71 | ||||
-rw-r--r-- | lib/Object/Binary.cpp | 85 | ||||
-rw-r--r-- | lib/Object/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 885 | ||||
-rw-r--r-- | lib/Object/COFFYAML.cpp | 105 | ||||
-rw-r--r-- | lib/Object/ELF.cpp | 94 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 44 | ||||
-rw-r--r-- | lib/Object/ELFYAML.cpp | 43 | ||||
-rw-r--r-- | lib/Object/Error.cpp | 8 | ||||
-rw-r--r-- | lib/Object/IRObjectFile.cpp | 151 | ||||
-rw-r--r-- | lib/Object/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 232 | ||||
-rw-r--r-- | lib/Object/MachOUniversal.cpp | 27 | ||||
-rw-r--r-- | lib/Object/Object.cpp | 31 | ||||
-rw-r--r-- | lib/Object/ObjectFile.cpp | 47 | ||||
-rw-r--r-- | lib/Object/SymbolicFile.cpp | 67 | ||||
-rw-r--r-- | lib/Object/YAML.cpp | 4 |
18 files changed, 1255 insertions, 649 deletions
diff --git a/lib/Object/Android.mk b/lib/Object/Android.mk index 93b5434..7dfa44f 100644 --- a/lib/Object/Android.mk +++ b/lib/Object/Android.mk @@ -7,10 +7,12 @@ object_SRC_FILES := \ ELF.cpp \ ELFObjectFile.cpp \ Error.cpp \ + IRObjectFile.cpp \ MachOObjectFile.cpp \ MachOUniversal.cpp \ Object.cpp \ - ObjectFile.cpp + ObjectFile.cpp \ + SymbolicFile.cpp # For the host @@ -29,6 +31,7 @@ include $(BUILD_HOST_STATIC_LIBRARY) # For the device only # ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) include $(CLEAR_VARS) LOCAL_MODULE:= libLLVMObject @@ -39,3 +42,4 @@ LOCAL_SRC_FILES := $(object_SRC_FILES) include $(LLVM_DEVICE_BUILD_MK) include $(LLVM_GEN_INTRINSICS_MK) include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 71efca2..999bf28 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/Archive.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Endian.h" @@ -136,7 +137,7 @@ error_code Archive::Child::getName(StringRef &Result) const { + sizeof(ArchiveMemberHeader) + offset; // Verify it. - if (Parent->StringTable == Parent->end_children() + if (Parent->StringTable == Parent->child_end() || addr < (Parent->StringTable->Data.begin() + sizeof(ArchiveMemberHeader)) || addr > (Parent->StringTable->Data.begin() @@ -168,7 +169,7 @@ error_code Archive::Child::getName(StringRef &Result) const { return object_error::success; } -error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, +error_code Archive::Child::getMemoryBuffer(std::unique_ptr<MemoryBuffer> &Result, bool FullPath) const { StringRef Name; if (error_code ec = getName(Name)) @@ -182,19 +183,45 @@ error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, return error_code::success(); } -error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const { - OwningPtr<Binary> ret; - OwningPtr<MemoryBuffer> Buff; +error_code Archive::Child::getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, + bool FullPath) const { + std::unique_ptr<MemoryBuffer> MB; + error_code ec = getMemoryBuffer(MB, FullPath); + Result = std::move(MB); + return ec; +} + +error_code Archive::Child::getAsBinary(std::unique_ptr<Binary> &Result, + LLVMContext *Context) const { + std::unique_ptr<Binary> ret; + std::unique_ptr<MemoryBuffer> Buff; if (error_code ec = getMemoryBuffer(Buff)) return ec; - if (error_code ec = createBinary(Buff.take(), ret)) - return ec; - Result.swap(ret); + ErrorOr<Binary *> BinaryOrErr = createBinary(Buff.release(), Context); + if (error_code EC = BinaryOrErr.getError()) + return EC; + Result.reset(BinaryOrErr.get()); return object_error::success; } +error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result, + LLVMContext *Context) const { + std::unique_ptr<Binary> B; + error_code ec = getAsBinary(B, Context); + Result = std::move(B); + return ec; +} + +ErrorOr<Archive*> Archive::create(MemoryBuffer *Source) { + error_code EC; + std::unique_ptr<Archive> Ret(new Archive(Source, EC)); + if (EC) + return EC; + return Ret.release(); +} + Archive::Archive(MemoryBuffer *source, error_code &ec) - : Binary(Binary::ID_Archive, source), SymbolTable(end_children()) { + : Binary(Binary::ID_Archive, source), SymbolTable(child_end()) { // Check for sufficient magic. assert(source); if (source->getBufferSize() < 8 || @@ -204,8 +231,8 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) } // Get the special members. - child_iterator i = begin_children(false); - child_iterator e = end_children(); + child_iterator i = child_begin(false); + child_iterator e = child_end(); if (i == e) { ec = object_error::success; @@ -309,9 +336,9 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) ec = object_error::success; } -Archive::child_iterator Archive::begin_children(bool SkipInternal) const { +Archive::child_iterator Archive::child_begin(bool SkipInternal) const { if (Data->getBufferSize() == 8) // empty archive. - return end_children(); + return child_end(); if (SkipInternal) return FirstRegular; @@ -321,7 +348,7 @@ Archive::child_iterator Archive::begin_children(bool SkipInternal) const { return c; } -Archive::child_iterator Archive::end_children() const { +Archive::child_iterator Archive::child_end() const { return Child(this, NULL); } @@ -384,7 +411,7 @@ Archive::Symbol Archive::Symbol::getNext() const { return t; } -Archive::symbol_iterator Archive::begin_symbols() const { +Archive::symbol_iterator Archive::symbol_begin() const { if (!hasSymbolTable()) return symbol_iterator(Symbol(this, 0, 0)); @@ -407,7 +434,7 @@ Archive::symbol_iterator Archive::begin_symbols() const { return symbol_iterator(Symbol(this, 0, string_start_offset)); } -Archive::symbol_iterator Archive::end_symbols() const { +Archive::symbol_iterator Archive::symbol_end() const { if (!hasSymbolTable()) return symbol_iterator(Symbol(this, 0, 0)); @@ -428,23 +455,23 @@ Archive::symbol_iterator Archive::end_symbols() const { } Archive::child_iterator Archive::findSym(StringRef name) const { - Archive::symbol_iterator bs = begin_symbols(); - Archive::symbol_iterator es = end_symbols(); + Archive::symbol_iterator bs = symbol_begin(); + Archive::symbol_iterator es = symbol_end(); Archive::child_iterator result; StringRef symname; for (; bs != es; ++bs) { if (bs->getName(symname)) - return end_children(); + return child_end(); if (symname == name) { if (bs->getMember(result)) - return end_children(); + return child_end(); return result; } } - return end_children(); + return child_end(); } bool Archive::hasSymbolTable() const { - return SymbolTable != end_children(); + return SymbolTable != child_end(); } diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index de57b4c..63fd3ed 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -13,13 +13,12 @@ #include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" // Include headers for createBinary. #include "llvm/Object/Archive.h" -#include "llvm/Object/COFF.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" @@ -27,12 +26,12 @@ using namespace llvm; using namespace object; Binary::~Binary() { - delete Data; + if (BufferOwned) + delete Data; } -Binary::Binary(unsigned int Type, MemoryBuffer *Source) - : TypeID(Type) - , Data(Source) {} +Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned) + : TypeID(Type), BufferOwned(BufferOwned), Data(Source) {} StringRef Binary::getData() const { return Data->getBuffer(); @@ -42,31 +41,18 @@ StringRef Binary::getFileName() const { return Data->getBufferIdentifier(); } -error_code object::createBinary(MemoryBuffer *Source, - OwningPtr<Binary> &Result) { - OwningPtr<MemoryBuffer> scopedSource(Source); - if (!Source) - return make_error_code(errc::invalid_argument); - sys::fs::file_magic type = sys::fs::identify_magic(Source->getBuffer()); - error_code ec; - switch (type) { - case sys::fs::file_magic::archive: { - OwningPtr<Binary> ret(new Archive(scopedSource.take(), ec)); - if (ec) return ec; - Result.swap(ret); - return object_error::success; - } +ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source, + LLVMContext *Context) { + std::unique_ptr<MemoryBuffer> scopedSource(Source); + sys::fs::file_magic Type = sys::fs::identify_magic(Source->getBuffer()); + + switch (Type) { + case sys::fs::file_magic::archive: + return Archive::create(scopedSource.release()); case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: { - OwningPtr<Binary> ret( - ObjectFile::createELFObjectFile(scopedSource.take())); - if (!ret) - return object_error::invalid_file_type; - Result.swap(ret); - return object_error::success; - } + case sys::fs::file_magic::elf_core: case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: @@ -76,43 +62,26 @@ error_code object::createBinary(MemoryBuffer *Source, case sys::fs::file_magic::macho_dynamic_linker: case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: { - OwningPtr<Binary> ret( - ObjectFile::createMachOObjectFile(scopedSource.take())); - if (!ret) - return object_error::invalid_file_type; - Result.swap(ret); - return object_error::success; - } - case sys::fs::file_magic::macho_universal_binary: { - OwningPtr<Binary> ret(new MachOUniversalBinary(scopedSource.take(), ec)); - if (ec) return ec; - Result.swap(ret); - return object_error::success; - } + case sys::fs::file_magic::macho_dsym_companion: case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: { - OwningPtr<Binary> ret( - ObjectFile::createCOFFObjectFile(scopedSource.take())); - if (!ret) - return object_error::invalid_file_type; - Result.swap(ret); - return object_error::success; - } - case sys::fs::file_magic::unknown: + case sys::fs::file_magic::pecoff_executable: case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::windows_resource: { + return ObjectFile::createSymbolicFile(scopedSource.release(), true, Type, + Context); + case sys::fs::file_magic::macho_universal_binary: + return MachOUniversalBinary::create(scopedSource.release()); + case sys::fs::file_magic::unknown: + case sys::fs::file_magic::windows_resource: // Unrecognized object file format. return object_error::invalid_file_type; - } } llvm_unreachable("Unexpected Binary File Type"); } -error_code object::createBinary(StringRef Path, OwningPtr<Binary> &Result) { - OwningPtr<MemoryBuffer> File; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(Path, File)) - return ec; - return createBinary(File.take(), Result); +ErrorOr<Binary *> object::createBinary(StringRef Path) { + std::unique_ptr<MemoryBuffer> File; + if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, File)) + return EC; + return createBinary(File.release()); } diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 1f07cbb..dc18296 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -7,9 +7,11 @@ add_llvm_library(LLVMObject ELFObjectFile.cpp ELFYAML.cpp Error.cpp + IRObjectFile.cpp MachOObjectFile.cpp MachOUniversal.cpp Object.cpp ObjectFile.cpp + SymbolicFile.cpp YAML.cpp ) diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 3434e70..a75ebbf 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -16,27 +16,24 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" +#include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include <cctype> - -#include <ctype.h> +#include <limits> using namespace llvm; using namespace object; -namespace { using support::ulittle8_t; using support::ulittle16_t; using support::ulittle32_t; using support::little16_t; -} -namespace { // Returns false if size is greater than the buffer size. And sets ec. -bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { - if (m->getBufferSize() < size) { - ec = object_error::unexpected_eof; +static bool checkSize(const MemoryBuffer *M, error_code &EC, uint64_t Size) { + if (M->getBufferSize() < Size) { + EC = object_error::unexpected_eof; return false; } return true; @@ -45,8 +42,8 @@ bool checkSize(const MemoryBuffer *m, error_code &ec, uint64_t size) { // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. // Returns unexpected_eof if error. template<typename T> -error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, - const size_t Size = sizeof(T)) { +static 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 || @@ -56,320 +53,353 @@ error_code getObject(const T *&Obj, const MemoryBuffer *M, const uint8_t *Ptr, Obj = reinterpret_cast<const T *>(Addr); return object_error::success; } + +// Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without +// prefixed slashes. +static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { + assert(Str.size() <= 6 && "String too long, possible overflow."); + if (Str.size() > 6) + return true; + + uint64_t Value = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= 'A' && Str[0] <= 'Z') // 0..25 + CharVal = Str[0] - 'A'; + else if (Str[0] >= 'a' && Str[0] <= 'z') // 26..51 + CharVal = Str[0] - 'a' + 26; + else if (Str[0] >= '0' && Str[0] <= '9') // 52..61 + CharVal = Str[0] - '0' + 52; + else if (Str[0] == '+') // 62 + CharVal = 62; + else if (Str[0] == '/') // 63 + CharVal = 63; + else + return true; + + Value = (Value * 64) + CharVal; + Str = Str.substr(1); + } + + if (Value > std::numeric_limits<uint32_t>::max()) + return true; + + Result = static_cast<uint32_t>(Value); + return false; } -const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Symb) const { - const coff_symbol *addr = reinterpret_cast<const coff_symbol*>(Symb.p); +const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const { + const coff_symbol *Addr = reinterpret_cast<const coff_symbol*>(Ref.p); # ifndef NDEBUG // Verify that the symbol points to a valid entry in the symbol table. - uintptr_t offset = uintptr_t(addr) - uintptr_t(base()); - if (offset < COFFHeader->PointerToSymbolTable - || offset >= COFFHeader->PointerToSymbolTable + uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); + if (Offset < COFFHeader->PointerToSymbolTable + || Offset >= COFFHeader->PointerToSymbolTable + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) report_fatal_error("Symbol was outside of symbol table."); - assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) + assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) == 0 && "Symbol did not point to the beginning of a symbol"); # endif - return addr; + return Addr; } -const coff_section *COFFObjectFile::toSec(DataRefImpl Sec) const { - const coff_section *addr = reinterpret_cast<const coff_section*>(Sec.p); +const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { + const coff_section *Addr = reinterpret_cast<const coff_section*>(Ref.p); # ifndef NDEBUG // Verify that the section points to a valid entry in the section table. - if (addr < SectionTable - || addr >= (SectionTable + COFFHeader->NumberOfSections)) + if (Addr < SectionTable + || Addr >= (SectionTable + COFFHeader->NumberOfSections)) report_fatal_error("Section was outside of section table."); - uintptr_t offset = uintptr_t(addr) - uintptr_t(SectionTable); - assert(offset % sizeof(coff_section) == 0 && + uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); + assert(Offset % sizeof(coff_section) == 0 && "Section did not point to the beginning of a section"); # endif - return addr; -} - -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; + return Addr; } - error_code COFFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - const coff_symbol *symb = toSymb(Symb); - return getSymbolName(symb, Result); +void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { + const coff_symbol *Symb = toSymb(Ref); + Symb += 1 + Symb->NumberOfAuxSymbols; + Ref.p = reinterpret_cast<uintptr_t>(Symb); } -error_code COFFObjectFile::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::getSymbolName(DataRefImpl Ref, + StringRef &Result) const { + const coff_symbol *Symb = toSymb(Ref); + return getSymbolName(Symb, Result); } -error_code COFFObjectFile::getSymbolAddress(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, uint64_t &Result) const { - const coff_symbol *symb = toSymb(Symb); + const coff_symbol *Symb = toSymb(Ref); const coff_section *Section = NULL; - if (error_code ec = getSection(symb->SectionNumber, Section)) - return ec; + if (error_code EC = getSection(Symb->SectionNumber, Section)) + return EC; - if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) Result = UnknownAddressOrSize; else if (Section) - Result = Section->VirtualAddress + symb->Value; + Result = Section->VirtualAddress + Symb->Value; else - Result = symb->Value; + Result = Symb->Value; return object_error::success; } -error_code COFFObjectFile::getSymbolType(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, SymbolRef::Type &Result) const { - const coff_symbol *symb = toSymb(Symb); + const coff_symbol *Symb = toSymb(Ref); Result = SymbolRef::ST_Other; - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { + if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && + Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { Result = SymbolRef::ST_Unknown; + } else if (Symb->isFunctionDefinition()) { + Result = SymbolRef::ST_Function; } else { - if (symb->getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) { - Result = SymbolRef::ST_Function; - } else { - uint32_t Characteristics = 0; - if (symb->SectionNumber > 0) { - const coff_section *Section = NULL; - if (error_code ec = getSection(symb->SectionNumber, Section)) - return ec; - Characteristics = Section->Characteristics; - } - if (Characteristics & COFF::IMAGE_SCN_MEM_READ && - ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. - Result = SymbolRef::ST_Data; + uint32_t Characteristics = 0; + if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { + const coff_section *Section = 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; +uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { + const coff_symbol *Symb = toSymb(Ref); + uint32_t Result = SymbolRef::SF_None; - // TODO: Correctly set SF_FormatSpecific, SF_ThreadLocal, SF_Common + // TODO: Correctly set SF_FormatSpecific, SF_Common + + if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { + if (Symb->Value == 0) + Result |= SymbolRef::SF_Undefined; + else + Result |= SymbolRef::SF_Common; + } - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) - Result |= SymbolRef::SF_Undefined; // TODO: This are certainly too restrictive. - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) + if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) Result |= SymbolRef::SF_Global; - if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) Result |= SymbolRef::SF_Weak; - if (symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) + if (Symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) Result |= SymbolRef::SF_Absolute; - return object_error::success; + return Result; } -error_code COFFObjectFile::getSymbolSize(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, uint64_t &Result) const { // FIXME: Return the correct size. This requires looking at all the symbols // in the same section as this symbol, and looking for either the next // symbol, or the end of the section. - const coff_symbol *symb = toSymb(Symb); + const coff_symbol *Symb = toSymb(Ref); const coff_section *Section = NULL; - if (error_code ec = getSection(symb->SectionNumber, Section)) - return ec; + if (error_code EC = getSection(Symb->SectionNumber, Section)) + return EC; - if (symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) Result = UnknownAddressOrSize; else if (Section) - Result = Section->SizeOfRawData - symb->Value; + Result = Section->SizeOfRawData - Symb->Value; else Result = 0; return object_error::success; } -error_code COFFObjectFile::getSymbolSection(DataRefImpl Symb, +error_code COFFObjectFile::getSymbolSection(DataRefImpl Ref, 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)); + const coff_symbol *Symb = toSymb(Ref); + if (COFF::isReservedSectionNumber(Symb->SectionNumber)) { + Result = section_end(); + } else { + const coff_section *Sec = 0; + if (error_code EC = getSection(Symb->SectionNumber, Sec)) return EC; + DataRefImpl Ref; + Ref.p = reinterpret_cast<uintptr_t>(Sec); + Result = section_iterator(SectionRef(Ref, this)); } return object_error::success; } -error_code COFFObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - report_fatal_error("getSymbolValue unimplemented in COFFObjectFile"); -} - -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; +void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { + const coff_section *Sec = toSec(Ref); + Sec += 1; + Ref.p = reinterpret_cast<uintptr_t>(Sec); } -error_code COFFObjectFile::getSectionName(DataRefImpl Sec, +error_code COFFObjectFile::getSectionName(DataRefImpl Ref, StringRef &Result) const { - const coff_section *sec = toSec(Sec); - return getSectionName(sec, Result); + const coff_section *Sec = toSec(Ref); + return getSectionName(Sec, Result); } -error_code COFFObjectFile::getSectionAddress(DataRefImpl Sec, +error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, uint64_t &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->VirtualAddress; + const coff_section *Sec = toSec(Ref); + Result = Sec->VirtualAddress; return object_error::success; } -error_code COFFObjectFile::getSectionSize(DataRefImpl Sec, +error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, uint64_t &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->SizeOfRawData; + const coff_section *Sec = toSec(Ref); + Result = Sec->SizeOfRawData; return object_error::success; } -error_code COFFObjectFile::getSectionContents(DataRefImpl Sec, +error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, StringRef &Result) const { - const coff_section *sec = toSec(Sec); + const coff_section *Sec = toSec(Ref); ArrayRef<uint8_t> Res; - error_code EC = getSectionContents(sec, 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, +error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, uint64_t &Res) const { - const coff_section *sec = toSec(Sec); - if (!sec) + const coff_section *Sec = toSec(Ref); + if (!Sec) return object_error::parse_failed; - Res = uint64_t(1) << (((sec->Characteristics & 0x00F00000) >> 20) - 1); + Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); return object_error::success; } -error_code COFFObjectFile::isSectionText(DataRefImpl Sec, +error_code COFFObjectFile::isSectionText(DataRefImpl Ref, bool &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; + const coff_section *Sec = toSec(Ref); + Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; return object_error::success; } -error_code COFFObjectFile::isSectionData(DataRefImpl Sec, +error_code COFFObjectFile::isSectionData(DataRefImpl Ref, bool &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; + const coff_section *Sec = toSec(Ref); + Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionBSS(DataRefImpl Sec, +error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, bool &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + const coff_section *Sec = toSec(Ref); + Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, +error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, bool &Result) const { // FIXME: Unimplemented Result = true; return object_error::success; } -error_code COFFObjectFile::isSectionVirtual(DataRefImpl Sec, +error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, bool &Result) const { - const coff_section *sec = toSec(Sec); - Result = sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + const coff_section *Sec = toSec(Ref); + Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Sec, +error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, +error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, +error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, + DataRefImpl SymbRef, 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) + const coff_section *Sec = toSec(SecRef); + const coff_symbol *Symb = toSymb(SymbRef); + const coff_section *SymbSec = 0; + if (error_code EC = getSection(Symb->SectionNumber, SymbSec)) return EC; + if (SymbSec == Sec) Result = true; else Result = false; return object_error::success; } -relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Sec) const { - const coff_section *sec = toSec(Sec); - DataRefImpl ret; - if (sec->NumberOfRelocations == 0) - ret.p = 0; - else - ret.p = reinterpret_cast<uintptr_t>(base() + sec->PointerToRelocations); - - return relocation_iterator(RelocationRef(ret, this)); +relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { + const coff_section *Sec = toSec(Ref); + DataRefImpl Ret; + if (Sec->NumberOfRelocations == 0) { + Ret.p = 0; + } else { + auto begin = reinterpret_cast<const coff_relocation*>( + base() + Sec->PointerToRelocations); + if (Sec->hasExtendedRelocations()) { + // Skip the first relocation entry repurposed to store the number of + // relocations. + begin++; + } + Ret.p = reinterpret_cast<uintptr_t>(begin); + } + return relocation_iterator(RelocationRef(Ret, this)); +} + +static uint32_t getNumberOfRelocations(const coff_section *Sec, + const uint8_t *base) { + // The field for the number of relocations in COFF section table is only + // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to + // NumberOfRelocations field, and the actual relocation count is stored in the + // VirtualAddress field in the first relocation entry. + if (Sec->hasExtendedRelocations()) { + auto *FirstReloc = reinterpret_cast<const coff_relocation*>( + base + Sec->PointerToRelocations); + return FirstReloc->VirtualAddress; + } + return Sec->NumberOfRelocations; } -relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Sec) const { - const coff_section *sec = toSec(Sec); - DataRefImpl ret; - if (sec->NumberOfRelocations == 0) - ret.p = 0; - else - ret.p = reinterpret_cast<uintptr_t>( - reinterpret_cast<const coff_relocation*>( - base() + sec->PointerToRelocations) - + sec->NumberOfRelocations); +relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { + const coff_section *Sec = toSec(Ref); + DataRefImpl Ret; + if (Sec->NumberOfRelocations == 0) { + Ret.p = 0; + } else { + auto begin = reinterpret_cast<const coff_relocation*>( + base() + Sec->PointerToRelocations); + uint32_t NumReloc = getNumberOfRelocations(Sec, base()); + Ret.p = reinterpret_cast<uintptr_t>(begin + NumReloc); + } + return relocation_iterator(RelocationRef(Ret, this)); +} - return relocation_iterator(RelocationRef(ret, this)); +bool COFFObjectFile::section_rel_empty(DataRefImpl Ref) const { + const coff_section *Sec = toSec(Ref); + return Sec->NumberOfRelocations == 0; } // Initialize the pointer to the symbol table. error_code COFFObjectFile::initSymbolTablePtr() { - if (error_code ec = getObject( + if (error_code EC = getObject( SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) - return ec; + return EC; // Find string table. The first four byte of the string table contains the // total size of the string table, including the size field itself. If the @@ -378,32 +408,41 @@ error_code COFFObjectFile::initSymbolTablePtr() { base() + COFFHeader->PointerToSymbolTable + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); const ulittle32_t *StringTableSizePtr; - if (error_code ec = getObject(StringTableSizePtr, Data, StringTableAddr)) - return ec; + if (error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) + return EC; StringTableSize = *StringTableSizePtr; - if (error_code ec = + if (error_code EC = getObject(StringTable, Data, StringTableAddr, StringTableSize)) - return ec; + return EC; + + // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some + // tools like cvtres write a size of 0 for an empty table instead of 4. + if (StringTableSize < 4) + StringTableSize = 4; // Check that the string table is null terminated if has any in it. - if (StringTableSize < 4 || - (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0)) + if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) return object_error::parse_failed; return object_error::success; } +// Returns the file offset for the given VA. +error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { + uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase + : (uint64_t)PE32PlusHeader->ImageBase; + uint64_t Rva = Addr - ImageBase; + assert(Rva <= UINT32_MAX); + return getRvaPtr((uint32_t)Rva, Res); +} + // Returns the file offset for the given RVA. -error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const { - error_code ec; - for (section_iterator i = begin_sections(), e = end_sections(); i != e; - i.increment(ec)) { - if (ec) - return ec; - const coff_section *Section = getCOFFSection(i); +error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { + for (const SectionRef &S : sections()) { + const coff_section *Section = getCOFFSection(S); uint32_t SectionStart = Section->VirtualAddress; uint32_t SectionEnd = Section->VirtualAddress + Section->VirtualSize; - if (SectionStart <= Rva && Rva < SectionEnd) { - uint32_t Offset = Rva - SectionStart; + if (SectionStart <= Addr && Addr < SectionEnd) { + uint32_t Offset = Addr - SectionStart; Res = uintptr_t(base()) + Section->PointerToRawData + Offset; return object_error::success; } @@ -416,8 +455,8 @@ error_code COFFObjectFile::getRvaPtr(uint32_t Rva, uintptr_t &Res) const { error_code COFFObjectFile:: getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { uintptr_t IntPtr = 0; - if (error_code ec = getRvaPtr(Rva, IntPtr)) - return ec; + if (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)); @@ -443,118 +482,136 @@ error_code COFFObjectFile::initImportTablePtr() { // Find the section that contains the RVA. This is needed because the RVA is // the import table's memory address which is different from its file offset. uintptr_t IntPtr = 0; - if (error_code ec = getRvaPtr(ImportTableRva, IntPtr)) - return ec; + if (error_code EC = getRvaPtr(ImportTableRva, IntPtr)) + return EC; ImportDirectory = reinterpret_cast< const import_directory_table_entry *>(IntPtr); + return object_error::success; +} - // It's an error if there's no section containing the Import Table RVA. - return object_error::parse_failed; +// Find the export table. +error_code COFFObjectFile::initExportTablePtr() { + // First, we get the RVA of the export table. If the file lacks a pointer to + // the export table, do nothing. + const data_directory *DataEntry; + if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) + return object_error::success; + + // Do nothing if the pointer to export table is NULL. + if (DataEntry->RelativeVirtualAddress == 0) + return object_error::success; + + uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; + uintptr_t IntPtr = 0; + if (error_code EC = getRvaPtr(ExportTableRva, IntPtr)) + return EC; + ExportDirectory = + reinterpret_cast<const export_directory_table_entry *>(IntPtr); + return object_error::success; } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(Binary::ID_COFF, Object) - , COFFHeader(0) - , PE32Header(0) - , DataDirectory(0) - , SectionTable(0) - , SymbolTable(0) - , StringTable(0) - , StringTableSize(0) - , ImportDirectory(0) - , NumberOfImportDirectory(0) { +COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, + bool BufferOwned) + : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(0), + PE32Header(0), PE32PlusHeader(0), DataDirectory(0), SectionTable(0), + SymbolTable(0), StringTable(0), StringTableSize(0), ImportDirectory(0), + NumberOfImportDirectory(0), ExportDirectory(0) { // Check that we at least have enough room for a header. - if (!checkSize(Data, ec, sizeof(coff_file_header))) return; + if (!checkSize(Data, EC, sizeof(coff_file_header))) return; // The current location in the file where we are looking at. uint64_t CurPtr = 0; // PE header is optional and is present only in executables. If it exists, // it is placed right after COFF header. - bool hasPEHeader = false; + bool HasPEHeader = false; // Check if this is a PE/COFF file. if (base()[0] == 0x4d && base()[1] == 0x5a) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - if (!checkSize(Data, ec, 0x3c + 8)) return; + if (!checkSize(Data, EC, 0x3c + 8)) return; CurPtr = *reinterpret_cast<const ulittle16_t *>(base() + 0x3c); // Check the PE magic bytes. ("PE\0\0") if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { - ec = object_error::parse_failed; + EC = object_error::parse_failed; return; } CurPtr += 4; // Skip the PE magic bytes. - hasPEHeader = true; + HasPEHeader = true; } - if ((ec = getObject(COFFHeader, Data, base() + CurPtr))) + if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) return; CurPtr += sizeof(coff_file_header); - if (hasPEHeader) { - if ((ec = getObject(PE32Header, Data, base() + CurPtr))) + if (HasPEHeader) { + const pe32_header *Header; + if ((EC = getObject(Header, Data, base() + CurPtr))) + return; + + const uint8_t *DataDirAddr; + uint64_t DataDirSize; + if (Header->Magic == 0x10b) { + PE32Header = Header; + DataDirAddr = base() + CurPtr + sizeof(pe32_header); + DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; + } else if (Header->Magic == 0x20b) { + PE32PlusHeader = reinterpret_cast<const pe32plus_header *>(Header); + DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); + DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; + } else { + // It's neither PE32 nor PE32+. + EC = object_error::parse_failed; return; - if (PE32Header->Magic != 0x10b) { - // We only support PE32. If this is PE32 (not PE32+), the magic byte - // should be 0x10b. If this is not PE32, continue as if there's no PE - // header in this file. - PE32Header = 0; - } else if (PE32Header->NumberOfRvaAndSize > 0) { - const uint8_t *addr = base() + CurPtr + sizeof(pe32_header); - uint64_t size = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; - if ((ec = getObject(DataDirectory, Data, addr, size))) - return; } + if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) + return; CurPtr += COFFHeader->SizeOfOptionalHeader; } - if (!COFFHeader->isImportLibrary()) - if ((ec = getObject(SectionTable, Data, base() + CurPtr, - COFFHeader->NumberOfSections * sizeof(coff_section)))) - return; + if (COFFHeader->isImportLibrary()) + return; + + if ((EC = getObject(SectionTable, Data, base() + CurPtr, + COFFHeader->NumberOfSections * sizeof(coff_section)))) + return; // Initialize the pointer to the symbol table. if (COFFHeader->PointerToSymbolTable != 0) - if ((ec = initSymbolTablePtr())) + if ((EC = initSymbolTablePtr())) return; // Initialize the pointer to the beginning of the import table. - if ((ec = initImportTablePtr())) + if ((EC = initImportTablePtr())) return; - ec = object_error::success; -} - -symbol_iterator COFFObjectFile::begin_symbols() const { - DataRefImpl ret; - ret.p = reinterpret_cast<uintptr_t>(SymbolTable); - return symbol_iterator(SymbolRef(ret, this)); -} + // Initialize the pointer to the export table. + if ((EC = initExportTablePtr())) + return; -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)); + EC = object_error::success; } -symbol_iterator COFFObjectFile::begin_dynamic_symbols() const { - // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); +basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { + DataRefImpl Ret; + Ret.p = reinterpret_cast<uintptr_t>(SymbolTable); + return basic_symbol_iterator(SymbolRef(Ret, this)); } -symbol_iterator COFFObjectFile::end_dynamic_symbols() const { - // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in COFFObjectFile"); +basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { + // The symbol table ends where the string table begins. + DataRefImpl Ret; + Ret.p = reinterpret_cast<uintptr_t>(StringTable); + return basic_symbol_iterator(SymbolRef(Ret, this)); } -library_iterator COFFObjectFile::begin_libraries_needed() const { +library_iterator COFFObjectFile::needed_library_begin() const { // TODO: implement report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); } -library_iterator COFFObjectFile::end_libraries_needed() const { +library_iterator COFFObjectFile::needed_library_end() const { // TODO: implement report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); } @@ -565,34 +622,40 @@ StringRef COFFObjectFile::getLoadName() const { } import_directory_iterator COFFObjectFile::import_directory_begin() const { - DataRefImpl Imp; - Imp.p = reinterpret_cast<uintptr_t>(ImportDirectory); - return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); + return import_directory_iterator( + ImportDirectoryEntryRef(ImportDirectory, 0, this)); } import_directory_iterator COFFObjectFile::import_directory_end() const { - DataRefImpl Imp; - if (ImportDirectory) { - Imp.p = reinterpret_cast<uintptr_t>( - ImportDirectory + (NumberOfImportDirectory - 1)); - } else { - Imp.p = 0; - } - return import_directory_iterator(ImportDirectoryEntryRef(Imp, this)); + return import_directory_iterator( + ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); +} + +export_directory_iterator COFFObjectFile::export_directory_begin() const { + return export_directory_iterator( + ExportDirectoryEntryRef(ExportDirectory, 0, this)); +} + +export_directory_iterator COFFObjectFile::export_directory_end() const { + if (ExportDirectory == 0) + return export_directory_iterator(ExportDirectoryEntryRef(0, 0, this)); + ExportDirectoryEntryRef Ref(ExportDirectory, + ExportDirectory->AddressTableEntries, this); + return export_directory_iterator(Ref); } -section_iterator COFFObjectFile::begin_sections() const { - DataRefImpl ret; - ret.p = reinterpret_cast<uintptr_t>(SectionTable); - return section_iterator(SectionRef(ret, this)); +section_iterator COFFObjectFile::section_begin() const { + DataRefImpl Ret; + Ret.p = reinterpret_cast<uintptr_t>(SectionTable); + return section_iterator(SectionRef(Ret, this)); } -section_iterator COFFObjectFile::end_sections() const { - DataRefImpl ret; - int numSections = COFFHeader->isImportLibrary() +section_iterator COFFObjectFile::section_end() const { + DataRefImpl Ret; + int NumSections = COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; - ret.p = reinterpret_cast<uintptr_t>(SectionTable + numSections); - return section_iterator(SectionRef(ret, this)); + Ret.p = reinterpret_cast<uintptr_t>(SectionTable + NumSections); + return section_iterator(SectionRef(Ret, this)); } uint8_t COFFObjectFile::getBytesInAddress() const { @@ -605,6 +668,8 @@ StringRef COFFObjectFile::getFileFormatName() const { return "COFF-i386"; case COFF::IMAGE_FILE_MACHINE_AMD64: return "COFF-x86-64"; + case COFF::IMAGE_FILE_MACHINE_ARMNT: + return "COFF-ARM"; default: return "COFF-<unknown arch>"; } @@ -616,6 +681,8 @@ unsigned COFFObjectFile::getArch() const { return Triple::x86; case COFF::IMAGE_FILE_MACHINE_AMD64: return Triple::x86_64; + case COFF::IMAGE_FILE_MACHINE_ARMNT: + return Triple::thumb; default: return Triple::UnknownArch; } @@ -637,89 +704,99 @@ error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { return object_error::success; } -error_code COFFObjectFile::getDataDirectory(uint32_t index, +error_code +COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { + Res = PE32PlusHeader; + 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) + if (!DataDirectory) + return object_error::parse_failed; + assert(PE32Header || PE32PlusHeader); + uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize + : PE32PlusHeader->NumberOfRvaAndSize; + if (Index > NumEnt) return object_error::parse_failed; - Res = &DataDirectory[index]; + Res = &DataDirectory[Index]; return object_error::success; } -error_code COFFObjectFile::getSection(int32_t index, +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) + if (COFF::isReservedSectionNumber(Index)) Result = NULL; - else if (index > 0 && index <= COFFHeader->NumberOfSections) + else if (Index > 0 && Index <= COFFHeader->NumberOfSections) // We already verified the section table data, so no need to check again. - Result = SectionTable + (index - 1); + Result = SectionTable + (Index - 1); else return object_error::parse_failed; return object_error::success; } -error_code COFFObjectFile::getString(uint32_t offset, +error_code COFFObjectFile::getString(uint32_t Offset, StringRef &Result) const { if (StringTableSize <= 4) // Tried to get a string from an empty string table. return object_error::parse_failed; - if (offset >= StringTableSize) + if (Offset >= StringTableSize) return object_error::unexpected_eof; - Result = StringRef(StringTable + offset); + Result = StringRef(StringTable + Offset); return object_error::success; } -error_code COFFObjectFile::getSymbol(uint32_t index, +error_code COFFObjectFile::getSymbol(uint32_t Index, const coff_symbol *&Result) const { - if (index < COFFHeader->NumberOfSymbols) - Result = SymbolTable + index; + 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, +error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, StringRef &Res) const { // Check for string table entry. First 4 bytes are 0. - if (symbol->Name.Offset.Zeroes == 0) { - uint32_t Offset = symbol->Name.Offset.Offset; - if (error_code ec = getString(Offset, Res)) - return ec; + if (Symbol->Name.Offset.Zeroes == 0) { + uint32_t Offset = Symbol->Name.Offset.Offset; + if (error_code EC = getString(Offset, Res)) + return EC; return object_error::success; } - if (symbol->Name.ShortName[7] == 0) + if (Symbol->Name.ShortName[7] == 0) // Null terminated, let ::strlen figure out the length. - Res = StringRef(symbol->Name.ShortName); + Res = StringRef(Symbol->Name.ShortName); else // Not null terminated, use all 8 bytes. - Res = StringRef(symbol->Name.ShortName, 8); + Res = StringRef(Symbol->Name.ShortName, 8); return object_error::success; } ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( - const coff_symbol *symbol) const { - const uint8_t *aux = NULL; + const coff_symbol *Symbol) const { + const uint8_t *Aux = NULL; - if ( symbol->NumberOfAuxSymbols > 0 ) { + if (Symbol->NumberOfAuxSymbols > 0) { // AUX data comes immediately after the symbol in COFF - aux = reinterpret_cast<const uint8_t *>(symbol + 1); + Aux = reinterpret_cast<const uint8_t *>(Symbol + 1); # ifndef NDEBUG - // Verify that the aux symbol points to a valid entry in the symbol table. - uintptr_t offset = uintptr_t(aux) - uintptr_t(base()); - if (offset < COFFHeader->PointerToSymbolTable - || offset >= COFFHeader->PointerToSymbolTable + // Verify that the Aux symbol points to a valid entry in the symbol table. + uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); + if (Offset < COFFHeader->PointerToSymbolTable + || Offset >= COFFHeader->PointerToSymbolTable + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) report_fatal_error("Aux Symbol data was outside of symbol table."); - assert((offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) + assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) == 0 && "Aux Symbol data did not point to the beginning of a symbol"); # endif } - return ArrayRef<uint8_t>(aux, symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); + return ArrayRef<uint8_t>(Aux, + Symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); } error_code COFFObjectFile::getSectionName(const coff_section *Sec, @@ -735,10 +812,15 @@ error_code COFFObjectFile::getSectionName(const coff_section *Sec, // Check for string table entry. First byte is '/'. if (Name[0] == '/') { uint32_t Offset; - if (Name.substr(1).getAsInteger(10, Offset)) - return object_error::parse_failed; - if (error_code ec = getString(Offset, Name)) - return ec; + if (Name[1] == '/') { + if (decodeBase64StringEntry(Name.substr(2), Offset)) + return object_error::parse_failed; + } else { + if (Name.substr(1).getAsInteger(10, Offset)) + return object_error::parse_failed; + } + if (error_code EC = getString(Offset, Name)) + return EC; } Res = Name; @@ -762,28 +844,30 @@ error_code COFFObjectFile::getSectionContents(const coff_section *Sec, const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { return reinterpret_cast<const coff_relocation*>(Rel.p); } -error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { + +void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.p = reinterpret_cast<uintptr_t>( reinterpret_cast<const coff_relocation*>(Rel.p) + 1); - Res = RelocationRef(Rel, this); - return object_error::success; } + error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { 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)); + DataRefImpl Ref; + Ref.p = reinterpret_cast<uintptr_t>(SymbolTable + R->SymbolTableIndex); + return symbol_iterator(SymbolRef(Ref, this)); } + error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const coff_relocation* R = toRel(Rel); @@ -791,29 +875,33 @@ error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, return object_error::success; } -const coff_section *COFFObjectFile::getCOFFSection(section_iterator &It) const { - return toSec(It->getRawDataRefImpl()); +const coff_section * +COFFObjectFile::getCOFFSection(const SectionRef &Section) const { + return toSec(Section.getRawDataRefImpl()); } -const coff_symbol *COFFObjectFile::getCOFFSymbol(symbol_iterator &It) const { - return toSymb(It->getRawDataRefImpl()); +const coff_symbol * +COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { + return toSymb(Symbol.getRawDataRefImpl()); } -const coff_relocation *COFFObjectFile::getCOFFRelocation( - relocation_iterator &It) const { - return toRel(It->getRawDataRefImpl()); +const coff_relocation * +COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { + return toRel(Reloc.getRawDataRefImpl()); } -#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(enum) \ - case COFF::enum: res = #enum; break; +#define LLVM_COFF_SWITCH_RELOC_TYPE_NAME(reloc_type) \ + case COFF::reloc_type: \ + Res = #reloc_type; \ + break; error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { - const coff_relocation *reloc = toRel(Rel); - StringRef res; + const coff_relocation *Reloc = toRel(Rel); + StringRef Res; switch (COFFHeader->Machine) { case COFF::IMAGE_FILE_MACHINE_AMD64: - switch (reloc->Type) { + switch (Reloc->Type) { LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR64); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ADDR32); @@ -832,11 +920,11 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_PAIR); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_SSPAN32); default: - res = "Unknown"; + Res = "Unknown"; } break; case COFF::IMAGE_FILE_MACHINE_I386: - switch (reloc->Type) { + switch (Reloc->Type) { LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_ABSOLUTE); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_DIR16); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL16); @@ -849,13 +937,13 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_SECREL7); LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_I386_REL32); default: - res = "Unknown"; + Res = "Unknown"; } break; default: - res = "Unknown"; + Res = "Unknown"; } - Result.append(res.begin(), res.end()); + Result.append(Res.begin(), Res.end()); return object_error::success; } @@ -863,14 +951,14 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, 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()); + 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; } @@ -886,55 +974,114 @@ error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, bool ImportDirectoryEntryRef:: operator==(const ImportDirectoryEntryRef &Other) const { - return ImportDirectoryPimpl == Other.ImportDirectoryPimpl; + return ImportTable == Other.ImportTable && Index == Other.Index; } -static const import_directory_table_entry *toImportEntry(DataRefImpl Imp) { - return reinterpret_cast<const import_directory_table_entry *>(Imp.p); -} - -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; +void ImportDirectoryEntryRef::moveNext() { + ++Index; } error_code ImportDirectoryEntryRef:: getImportTableEntry(const import_directory_table_entry *&Result) const { - Result = toImportEntry(ImportDirectoryPimpl); + Result = ImportTable; 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); + if (error_code EC = OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) + return EC; + Result = StringRef(reinterpret_cast<const char *>(IntPtr)); 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; + if (error_code EC = + OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) + return EC; Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); return object_error::success; } -namespace llvm { +bool ExportDirectoryEntryRef:: +operator==(const ExportDirectoryEntryRef &Other) const { + return ExportTable == Other.ExportTable && Index == Other.Index; +} + +void ExportDirectoryEntryRef::moveNext() { + ++Index; +} - ObjectFile *ObjectFile::createCOFFObjectFile(MemoryBuffer *Object) { - error_code ec; - return new COFFObjectFile(Object, ec); +// Returns the name of the current export symbol. If the symbol is exported only +// by ordinal, the empty string is set as a result. +error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { + uintptr_t IntPtr = 0; + if (error_code EC = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) + return EC; + Result = StringRef(reinterpret_cast<const char *>(IntPtr)); + return object_error::success; +} + +// Returns the starting ordinal number. +error_code ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { + Result = ExportTable->OrdinalBase; + return object_error::success; +} + +// Returns the export ordinal of the current export symbol. +error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { + Result = ExportTable->OrdinalBase + Index; + return object_error::success; +} + +// Returns the address of the current export symbol. +error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { + uintptr_t IntPtr = 0; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->ExportAddressTableRVA, IntPtr)) + return EC; + const export_address_table_entry *entry = + reinterpret_cast<const export_address_table_entry *>(IntPtr); + Result = entry[Index].ExportRVA; + return object_error::success; +} + +// Returns the name of the current export symbol. If the symbol is exported only +// by ordinal, the empty string is set as a result. +error_code ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { + uintptr_t IntPtr = 0; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->OrdinalTableRVA, IntPtr)) + return EC; + const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); + + uint32_t NumEntries = ExportTable->NumberOfNamePointers; + int Offset = 0; + for (const ulittle16_t *I = Start, *E = Start + NumEntries; + I < E; ++I, ++Offset) { + if (*I != Index) + continue; + if (error_code EC = OwningObject->getRvaPtr( + ExportTable->NamePointerRVA, IntPtr)) + return EC; + const ulittle32_t *NamePtr = reinterpret_cast<const ulittle32_t *>(IntPtr); + if (error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) + return EC; + Result = StringRef(reinterpret_cast<const char *>(IntPtr)); + return object_error::success; } + Result = ""; + return object_error::success; +} -} // end namespace llvm +ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object, + bool BufferOwned) { + error_code EC; + std::unique_ptr<COFFObjectFile> Ret( + new COFFObjectFile(Object, EC, BufferOwned)); + if (EC) + return EC; + return Ret.release(); +} diff --git a/lib/Object/COFFYAML.cpp b/lib/Object/COFFYAML.cpp index e549b4e..94b72ff 100644 --- a/lib/Object/COFFYAML.cpp +++ b/lib/Object/COFFYAML.cpp @@ -23,13 +23,38 @@ Object::Object() { memset(&Header, 0, sizeof(COFF::header)); } } namespace yaml { +void ScalarEnumerationTraits<COFFYAML::COMDATType>::enumeration( + IO &IO, COFFYAML::COMDATType &Value) { + IO.enumCase(Value, "0", 0); + ECase(IMAGE_COMDAT_SELECT_NODUPLICATES); + ECase(IMAGE_COMDAT_SELECT_ANY); + ECase(IMAGE_COMDAT_SELECT_SAME_SIZE); + ECase(IMAGE_COMDAT_SELECT_EXACT_MATCH); + ECase(IMAGE_COMDAT_SELECT_ASSOCIATIVE); + ECase(IMAGE_COMDAT_SELECT_LARGEST); + ECase(IMAGE_COMDAT_SELECT_NEWEST); +} + +void +ScalarEnumerationTraits<COFFYAML::WeakExternalCharacteristics>::enumeration( + IO &IO, COFFYAML::WeakExternalCharacteristics &Value) { + ECase(IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY); + ECase(IMAGE_WEAK_EXTERN_SEARCH_LIBRARY); + ECase(IMAGE_WEAK_EXTERN_SEARCH_ALIAS); +} + +void ScalarEnumerationTraits<COFFYAML::AuxSymbolType>::enumeration( + IO &IO, COFFYAML::AuxSymbolType &Value) { + ECase(IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF); +} + void ScalarEnumerationTraits<COFF::MachineTypes>::enumeration( IO &IO, COFF::MachineTypes &Value) { ECase(IMAGE_FILE_MACHINE_UNKNOWN); ECase(IMAGE_FILE_MACHINE_AM33); ECase(IMAGE_FILE_MACHINE_AMD64); ECase(IMAGE_FILE_MACHINE_ARM); - ECase(IMAGE_FILE_MACHINE_ARMV7); + ECase(IMAGE_FILE_MACHINE_ARMNT); ECase(IMAGE_FILE_MACHINE_EBC); ECase(IMAGE_FILE_MACHINE_I386); ECase(IMAGE_FILE_MACHINE_IA64); @@ -187,6 +212,24 @@ void ScalarBitSetTraits<COFF::SectionCharacteristics>::bitset( #undef BCase namespace { +struct NSectionSelectionType { + NSectionSelectionType(IO &) + : SelectionType(COFFYAML::COMDATType(0)) {} + NSectionSelectionType(IO &, uint8_t C) + : SelectionType(COFFYAML::COMDATType(C)) {} + uint8_t denormalize(IO &) { return SelectionType; } + COFFYAML::COMDATType SelectionType; +}; + +struct NWeakExternalCharacteristics { + NWeakExternalCharacteristics(IO &) + : Characteristics(COFFYAML::WeakExternalCharacteristics(0)) {} + NWeakExternalCharacteristics(IO &, uint32_t C) + : Characteristics(COFFYAML::WeakExternalCharacteristics(C)) {} + uint32_t denormalize(IO &) { return Characteristics; } + COFFYAML::WeakExternalCharacteristics Characteristics; +}; + struct NSectionCharacteristics { NSectionCharacteristics(IO &) : Characteristics(COFF::SectionCharacteristics(0)) {} @@ -196,6 +239,15 @@ struct NSectionCharacteristics { COFF::SectionCharacteristics Characteristics; }; +struct NAuxTokenType { + NAuxTokenType(IO &) + : AuxType(COFFYAML::AuxSymbolType(0)) {} + NAuxTokenType(IO &, uint8_t C) + : AuxType(COFFYAML::AuxSymbolType(C)) {} + uint32_t denormalize(IO &) { return AuxType; } + COFFYAML::AuxSymbolType AuxType; +}; + struct NStorageClass { NStorageClass(IO &) : StorageClass(COFF::SymbolStorageClass(0)) {} NStorageClass(IO &, uint8_t S) : StorageClass(COFF::SymbolStorageClass(S)) {} @@ -247,6 +299,48 @@ void MappingTraits<COFF::header>::mapping(IO &IO, COFF::header &H) { IO.mapOptional("Characteristics", NC->Characteristics); } +void MappingTraits<COFF::AuxiliaryFunctionDefinition>::mapping( + IO &IO, COFF::AuxiliaryFunctionDefinition &AFD) { + IO.mapRequired("TagIndex", AFD.TagIndex); + IO.mapRequired("TotalSize", AFD.TotalSize); + IO.mapRequired("PointerToLinenumber", AFD.PointerToLinenumber); + IO.mapRequired("PointerToNextFunction", AFD.PointerToNextFunction); +} + +void MappingTraits<COFF::AuxiliarybfAndefSymbol>::mapping( + IO &IO, COFF::AuxiliarybfAndefSymbol &AAS) { + IO.mapRequired("Linenumber", AAS.Linenumber); + IO.mapRequired("PointerToNextFunction", AAS.PointerToNextFunction); +} + +void MappingTraits<COFF::AuxiliaryWeakExternal>::mapping( + IO &IO, COFF::AuxiliaryWeakExternal &AWE) { + MappingNormalization<NWeakExternalCharacteristics, uint32_t> NWEC( + IO, AWE.Characteristics); + IO.mapRequired("TagIndex", AWE.TagIndex); + IO.mapRequired("Characteristics", NWEC->Characteristics); +} + +void MappingTraits<COFF::AuxiliarySectionDefinition>::mapping( + IO &IO, COFF::AuxiliarySectionDefinition &ASD) { + MappingNormalization<NSectionSelectionType, uint8_t> NSST( + IO, ASD.Selection); + + IO.mapRequired("Length", ASD.Length); + IO.mapRequired("NumberOfRelocations", ASD.NumberOfRelocations); + IO.mapRequired("NumberOfLinenumbers", ASD.NumberOfLinenumbers); + IO.mapRequired("CheckSum", ASD.CheckSum); + IO.mapRequired("Number", ASD.Number); + IO.mapOptional("Selection", NSST->SelectionType, COFFYAML::COMDATType(0)); +} + +void MappingTraits<COFF::AuxiliaryCLRToken>::mapping( + IO &IO, COFF::AuxiliaryCLRToken &ACT) { + MappingNormalization<NAuxTokenType, uint8_t> NATT(IO, ACT.AuxType); + IO.mapRequired("AuxType", NATT->AuxType); + IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); +} + void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass); @@ -256,9 +350,12 @@ void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) { IO.mapRequired("SimpleType", S.SimpleType); IO.mapRequired("ComplexType", S.ComplexType); IO.mapRequired("StorageClass", NS->StorageClass); - IO.mapOptional("NumberOfAuxSymbols", S.Header.NumberOfAuxSymbols, - (uint8_t) 0); - IO.mapOptional("AuxiliaryData", S.AuxiliaryData, object::yaml::BinaryRef()); + IO.mapOptional("FunctionDefinition", S.FunctionDefinition); + IO.mapOptional("bfAndefSymbol", S.bfAndefSymbol); + IO.mapOptional("WeakExternal", S.WeakExternal); + IO.mapOptional("File", S.File, StringRef()); + IO.mapOptional("SectionDefinition", S.SectionDefinition); + IO.mapOptional("CLRToken", S.CLRToken); } void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) { diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index 7c80d41..e9a88bf 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -170,6 +170,8 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_DISP); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_PAGE); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_OFST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_GD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_LDM); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_HI16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_LO16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_TPREL_HI16); @@ -702,6 +704,98 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { break; } break; + case ELF::EM_SPARC: + case ELF::EM_SPARC32PLUS: + case ELF::EM_SPARCV9: + switch (Type) { + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_NONE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP8); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP30); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HI22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_13); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LO10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT13); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WPLT30); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_COPY); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GLOB_DAT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_RELATIVE); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIPLT22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOPLT10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_11); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_OLO10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HH22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HM10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LM22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HH22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HM10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_LM22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP19); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_7); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_5); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_6); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOX10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_H44); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_M44); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_L44); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_REGISTER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_HI22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_LO10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_ADD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_HI22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_LO10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_ADD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_CALL); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_HIX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_LOX10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_ADD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_HI22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LO10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LDX); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_ADD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_HIX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_LOX10); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_HIX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_LOX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_HIX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_LOX22); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP); + default: + break; + } + break; default: break; } diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 20b7307..a2c4df2 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -14,62 +14,72 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/MathExtras.h" -#include <ctype.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; - +ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj, + bool BufferOwned) { + std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj); std::size_t MaxAlignment = - 1ULL << countTrailingZeros(uintptr_t(Object->getBufferStart())); + 1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart())); + error_code EC; + std::unique_ptr<ObjectFile> R; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - return new ELFObjectFile<ELFType<support::little, 4, false> >(Object, ec); + R.reset(new ELFObjectFile<ELFType<support::little, 4, false> >( + Obj, EC, BufferOwned)); else #endif if (MaxAlignment >= 2) - return new ELFObjectFile<ELFType<support::little, 2, false> >(Object, ec); + R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >( + Obj, EC, BufferOwned)); 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); + R.reset(new ELFObjectFile<ELFType<support::big, 4, false> >(Obj, EC, + BufferOwned)); else #endif if (MaxAlignment >= 2) - return new ELFObjectFile<ELFType<support::big, 2, false> >(Object, ec); + R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC, + BufferOwned)); 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); + R.reset(new ELFObjectFile<ELFType<support::big, 8, true> >(Obj, EC, + BufferOwned)); else #endif if (MaxAlignment >= 2) - return new ELFObjectFile<ELFType<support::big, 2, true> >(Object, ec); + R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC, + BufferOwned)); 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); + R.reset(new ELFObjectFile<ELFType<support::little, 8, true> >( + Obj, EC, BufferOwned)); else #endif if (MaxAlignment >= 2) - return new ELFObjectFile<ELFType<support::little, 2, true> >(Object, ec); + R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >( + Obj, EC, BufferOwned)); else llvm_unreachable("Invalid alignment for ELF file!"); } + else + report_fatal_error("Buffer is not an ELF object file!"); - report_fatal_error("Buffer is not an ELF object file!"); + if (EC) + return EC; + return R.release(); } } // end namespace llvm diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index 2f35cf9..d513670 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -237,6 +237,48 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( #undef ECase } +void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, + ELFYAML::ELF_EF &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); + BCase(EF_ARM_SOFT_FLOAT) + BCase(EF_ARM_VFP_FLOAT) + BCase(EF_ARM_EABI_UNKNOWN) + BCase(EF_ARM_EABI_VER1) + BCase(EF_ARM_EABI_VER2) + BCase(EF_ARM_EABI_VER3) + BCase(EF_ARM_EABI_VER4) + BCase(EF_ARM_EABI_VER5) + BCase(EF_ARM_EABIMASK) + BCase(EF_MIPS_NOREORDER) + BCase(EF_MIPS_PIC) + BCase(EF_MIPS_CPIC) + BCase(EF_MIPS_ABI2) + BCase(EF_MIPS_32BITMODE) + BCase(EF_MIPS_ABI_O32) + BCase(EF_MIPS_MICROMIPS) + BCase(EF_MIPS_ARCH_ASE_M16) + BCase(EF_MIPS_ARCH_1) + BCase(EF_MIPS_ARCH_2) + BCase(EF_MIPS_ARCH_3) + BCase(EF_MIPS_ARCH_4) + BCase(EF_MIPS_ARCH_5) + BCase(EF_MIPS_ARCH_32) + BCase(EF_MIPS_ARCH_64) + BCase(EF_MIPS_ARCH_32R2) + BCase(EF_MIPS_ARCH_64R2) + BCase(EF_MIPS_ARCH) + BCase(EF_HEXAGON_MACH_V2) + BCase(EF_HEXAGON_MACH_V3) + BCase(EF_HEXAGON_MACH_V4) + BCase(EF_HEXAGON_MACH_V5) + BCase(EF_HEXAGON_ISA_MACH) + BCase(EF_HEXAGON_ISA_V2) + BCase(EF_HEXAGON_ISA_V3) + BCase(EF_HEXAGON_ISA_V4) + BCase(EF_HEXAGON_ISA_V5) +#undef BCase +} + void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration( IO &IO, ELFYAML::ELF_SHT &Value) { #define ECase(X) IO.enumCase(Value, #X, ELF::X); @@ -299,6 +341,7 @@ void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, IO.mapOptional("OSABI", FileHdr.OSABI, ELFYAML::ELF_ELFOSABI(0)); IO.mapRequired("Type", FileHdr.Type); IO.mapRequired("Machine", FileHdr.Machine); + IO.mapOptional("Flags", FileHdr.Flags, ELFYAML::ELF_EF(0)); IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); } diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp index 47ce38c..8e50869 100644 --- a/lib/Object/Error.cpp +++ b/lib/Object/Error.cpp @@ -18,11 +18,11 @@ using namespace llvm; using namespace object; namespace { -class _object_error_category : public _do_message { +class _object_error_category : public error_category { public: - virtual const char* name() const; - virtual std::string message(int ev) const; - virtual error_condition default_error_condition(int ev) const; + const char* name() const override; + std::string message(int ev) const override; + error_condition default_error_condition(int ev) const override; }; } diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp new file mode 100644 index 0000000..a8aba26 --- /dev/null +++ b/lib/Object/IRObjectFile.cpp @@ -0,0 +1,151 @@ +//===- IRObjectFile.cpp - IR object file implementation ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Part of the IRObjectFile class implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace object; + +IRObjectFile::IRObjectFile(MemoryBuffer *Object, error_code &EC, + LLVMContext &Context, bool BufferOwned) + : SymbolicFile(Binary::ID_IR, Object, BufferOwned) { + ErrorOr<Module*> MOrErr = parseBitcodeFile(Object, Context); + if ((EC = MOrErr.getError())) + return; + + M.reset(MOrErr.get()); + + // If we have a DataLayout, setup a mangler. + const DataLayout *DL = M->getDataLayout(); + if (!DL) + return; + + Mang.reset(new Mangler(DL)); +} + +static const GlobalValue &getGV(DataRefImpl &Symb) { + return *reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); +} + +static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { + if (I == M.alias_end()) + return 3; + const GlobalValue *GV = &*I; + return reinterpret_cast<uintptr_t>(GV) | 2; +} + +static uintptr_t skipEmpty(Module::const_global_iterator I, const Module &M) { + if (I == M.global_end()) + return skipEmpty(M.alias_begin(), M); + const GlobalValue *GV = &*I; + return reinterpret_cast<uintptr_t>(GV) | 1; +} + +static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { + if (I == M.end()) + return skipEmpty(M.global_begin(), M); + const GlobalValue *GV = &*I; + return reinterpret_cast<uintptr_t>(GV) | 0; +} + +void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { + const GlobalValue *GV = &getGV(Symb); + const Module &M = *GV->getParent(); + uintptr_t Res; + switch (Symb.p & 3) { + case 0: { + Module::const_iterator Iter(static_cast<const Function*>(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 1: { + Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 2: { + Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); + ++Iter; + Res = skipEmpty(Iter, M); + break; + } + case 3: + llvm_unreachable("Invalid symbol reference"); + } + + Symb.p = Res; +} + +error_code IRObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + const GlobalValue &GV = getGV(Symb); + + if (Mang) + Mang->getNameWithPrefix(OS, &GV, false); + else + OS << GV.getName(); + + return object_error::success; +} + +uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { + const GlobalValue &GV = getGV(Symb); + + uint32_t Res = BasicSymbolRef::SF_None; + if (GV.isDeclaration() || GV.hasAvailableExternallyLinkage()) + Res |= BasicSymbolRef::SF_Undefined; + if (GV.hasPrivateLinkage()) + Res |= BasicSymbolRef::SF_FormatSpecific; + if (!GV.hasLocalLinkage()) + Res |= BasicSymbolRef::SF_Global; + if (GV.hasCommonLinkage()) + Res |= BasicSymbolRef::SF_Common; + if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage()) + Res |= BasicSymbolRef::SF_Weak; + + return Res; +} + +const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const { + const GlobalValue &GV = getGV(Symb); + return GV; +} + +basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { + Module::const_iterator I = M->begin(); + DataRefImpl Ret; + Ret.p = skipEmpty(I, *M); + return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +basic_symbol_iterator IRObjectFile::symbol_end_impl() const { + DataRefImpl Ret; + Ret.p = 3; + return basic_symbol_iterator(BasicSymbolRef(Ret, this)); +} + +ErrorOr<SymbolicFile *> llvm::object::SymbolicFile::createIRObjectFile( + MemoryBuffer *Object, LLVMContext &Context, bool BufferOwned) { + error_code EC; + std::unique_ptr<IRObjectFile> Ret( + new IRObjectFile(Object, EC, Context, BufferOwned)); + if (EC) + return EC; + return Ret.release(); +} diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt index 69610f9..a87da6e 100644 --- a/lib/Object/LLVMBuild.txt +++ b/lib/Object/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Object parent = Libraries -required_libraries = Support +required_libraries = Support BitReader diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index d2cb8bd..12132a4 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/MachO.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" @@ -214,6 +215,14 @@ void SwapStruct(MachO::linker_options_command &C) { } template<> +void SwapStruct(MachO::version_min_command&C) { + SwapValue(C.cmd); + SwapValue(C.cmdsize); + SwapValue(C.version); + SwapValue(C.reserved); +} + +template<> void SwapStruct(MachO::data_in_code_entry &C) { SwapValue(C.offset); SwapValue(C.length); @@ -275,18 +284,9 @@ static StringRef parseSegmentOrSectionName(const char *P) { // Helper to advance a section or symbol iterator multiple increments at a time. template<class T> -static error_code advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template<class T> -static void advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); +static void advance(T &it, size_t Val) { + while (Val--) + ++it; } static unsigned getCPUType(const MachOObjectFile *O) { @@ -305,18 +305,16 @@ static void printRelocationTargetName(const MachOObjectFile *O, if (IsScattered) { uint32_t Val = O->getPlainRelocationSymbolNum(RE); - error_code ec; - for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols(); - SI != SE; SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - + for (const SymbolRef &Symbol : O->symbols()) { + error_code ec; uint64_t Addr; StringRef Name; - if ((ec = SI->getAddress(Addr))) + if ((ec = Symbol.getAddress(Addr))) report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) + if (Addr != Val) + continue; + if ((ec = Symbol.getName(Name))) report_fatal_error(ec.message()); fmt << Name; return; @@ -324,17 +322,16 @@ static void printRelocationTargetName(const MachOObjectFile *O, // If we couldn't find a symbol that this relocation refers to, try // to find a section beginning instead. - for (section_iterator SI = O->begin_sections(), SE = O->end_sections(); - SI != SE; SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - + for (const SectionRef &Section : O->sections()) { + error_code ec; uint64_t Addr; StringRef Name; - if ((ec = SI->getAddress(Addr))) + if ((ec = Section.getAddress(Addr))) report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) + if (Addr != Val) + continue; + if ((ec = Section.getName(Name))) report_fatal_error(ec.message()); fmt << Name; return; @@ -349,13 +346,13 @@ static void printRelocationTargetName(const MachOObjectFile *O, uint64_t Val = O->getPlainRelocationSymbolNum(RE); if (isExtern) { - symbol_iterator SI = O->begin_symbols(); - advanceTo(SI, Val); + symbol_iterator SI = O->symbol_begin(); + advance(SI, Val); SI->getName(S); } else { - section_iterator SI = O->begin_sections(); + section_iterator SI = O->section_begin(); // Adjust for the fact that sections are 1-indexed. - advanceTo(SI, Val - 1); + advance(SI, Val - 1); SI->getName(S); } @@ -419,10 +416,10 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, - bool IsLittleEndian, bool Is64bits, - error_code &ec) - : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, + bool Is64bits, error_code &EC, + bool BufferOwned) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned), SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL), DataInCodeLoadCmd(NULL) { uint32_t LoadCommandCount = this->getHeader().ncmds; MachO::LoadCommandType SegmentLoadType = is64Bit() ? @@ -454,14 +451,11 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, } } -error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, - SymbolRef &Res) const { +void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); Symb.p += SymbolTableEntrySize; - Res = SymbolRef(Symb, this); - return object_error::success; } error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, @@ -485,33 +479,9 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 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); + uint32_t flags = getSymbolFlags(DRI); if (flags & SymbolRef::SF_Common) { nlist_base Entry = getSymbolTableEntryBase(this, DRI); Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); @@ -535,8 +505,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, SectionIndex = Entry.n_sect; if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - this->getSymbolFlags(DRI, flags); + uint32_t flags = getSymbolFlags(DRI); if (flags & SymbolRef::SF_Common) Result = Value; else @@ -545,10 +514,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, } // Unfortunately symbols are unsorted so we need to touch all // symbols from load command - error_code ec; - for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E; - I.increment(ec)) { - DataRefImpl DRI = I->getRawDataRefImpl(); + for (const SymbolRef &Symbol : symbols()) { + DataRefImpl DRI = Symbol.getRawDataRefImpl(); Entry = getSymbolTableEntryBase(this, DRI); getSymbolAddress(DRI, Value); if (Entry.n_sect == SectionIndex && Value > BeginOffset) @@ -591,15 +558,13 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { +uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) 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; + uint32_t Result = SymbolRef::SF_None; if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) Result |= SymbolRef::SF_Undefined; @@ -623,7 +588,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) Result |= SymbolRef::SF_Absolute; - return object_error::success; + return Result; } error_code @@ -633,7 +598,7 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb, uint8_t index = Entry.n_sect; if (index == 0) { - Res = end_sections(); + Res = section_end(); } else { DataRefImpl DRI; DRI.d.a = index - 1; @@ -643,16 +608,8 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); -} - -error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, - SectionRef &Res) const { +void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; - Res = SectionRef(Sec, this); - return object_error::success; } error_code @@ -834,13 +791,20 @@ MachOObjectFile::section_rel_end(DataRefImpl Sec) const { return relocation_iterator(RelocationRef(Ret, this)); } -error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { +bool MachOObjectFile::section_rel_empty(DataRefImpl Sec) const { + if (is64Bit()) { + MachO::section_64 Sect = getSection64(Sec); + return Sect.nreloc == 0; + } else { + MachO::section Sect = getSection(Sec); + return Sect.nreloc == 0; + } +} + +void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) 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 @@ -861,7 +825,7 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); bool isExtern = getPlainRelocationExternal(RE); if (!isExtern) - return end_symbols(); + return symbol_end(); MachO::symtab_command S = getSymtabLoadCommand(); unsigned SymbolTableEntrySize = is64Bit() ? @@ -899,7 +863,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, "GENERIC_RELOC_LOCAL_SECTDIFF", "GENERIC_RELOC_TLV" }; - if (RType > 6) + if (RType > 5) res = "Unknown"; else res = Table[RType]; @@ -943,6 +907,23 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, res = Table[RType]; break; } + case Triple::arm64: + case Triple::aarch64: { + static const char *const Table[] = { + "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", + "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", + "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", + "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", + "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", + "ARM64_RELOC_ADDEND" + }; + + if (RType >= array_lengthof(Table)) + res = "Unknown"; + else + res = Table[RType]; + break; + } case Triple::ppc: { static const char *const Table[] = { "PPC_RELOC_VANILLA", @@ -962,7 +943,10 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, "PPC_RELOC_LO14_SECTDIFF", "PPC_RELOC_LOCAL_SECTDIFF" }; - res = Table[RType]; + if (RType > 15) + res = "Unknown"; + else + res = Table[RType]; break; } case Triple::UnknownArch: @@ -1187,20 +1171,20 @@ error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } -symbol_iterator MachOObjectFile::begin_symbols() const { +basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { DataRefImpl DRI; if (!SymtabLoadCmd) - return symbol_iterator(SymbolRef(DRI, this)); + return basic_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)); + return basic_symbol_iterator(SymbolRef(DRI, this)); } -symbol_iterator MachOObjectFile::end_symbols() const { +basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { DataRefImpl DRI; if (!SymtabLoadCmd) - return symbol_iterator(SymbolRef(DRI, this)); + return basic_symbol_iterator(SymbolRef(DRI, this)); MachO::symtab_command Symtab = getSymtabLoadCommand(); unsigned SymbolTableEntrySize = is64Bit() ? @@ -1209,36 +1193,26 @@ symbol_iterator MachOObjectFile::end_symbols() const { unsigned Offset = Symtab.symoff + Symtab.nsyms * SymbolTableEntrySize; DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); - return symbol_iterator(SymbolRef(DRI, this)); -} - -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"); + return basic_symbol_iterator(SymbolRef(DRI, this)); } -section_iterator MachOObjectFile::begin_sections() const { +section_iterator MachOObjectFile::section_begin() const { DataRefImpl DRI; return section_iterator(SectionRef(DRI, this)); } -section_iterator MachOObjectFile::end_sections() const { +section_iterator MachOObjectFile::section_end() const { DataRefImpl DRI; DRI.d.a = Sections.size(); return section_iterator(SectionRef(DRI, this)); } -library_iterator MachOObjectFile::begin_libraries_needed() const { +library_iterator MachOObjectFile::needed_library_begin() const { // TODO: implement report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } -library_iterator MachOObjectFile::end_libraries_needed() const { +library_iterator MachOObjectFile::needed_library_end() const { // TODO: implement report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } @@ -1272,6 +1246,8 @@ StringRef MachOObjectFile::getFileFormatName() const { switch (CPUType) { case llvm::MachO::CPU_TYPE_X86_64: return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPU_TYPE_ARM64: + return "Mach-O arm64"; case llvm::MachO::CPU_TYPE_POWERPC64: return "Mach-O 64-bit ppc64"; default: @@ -1287,6 +1263,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { return Triple::x86_64; case llvm::MachO::CPU_TYPE_ARM: return Triple::arm; + case llvm::MachO::CPU_TYPE_ARM64: + return Triple::arm64; case llvm::MachO::CPU_TYPE_POWERPC: return Triple::ppc; case llvm::MachO::CPU_TYPE_POWERPC64: @@ -1423,7 +1401,7 @@ SectionRef MachOObjectFile::getRelocationSection( const MachO::any_relocation_info &RE) const { if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) - return *end_sections(); + return *section_end(); unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; DataRefImpl DRI; DRI.d.a = SecNum; @@ -1501,6 +1479,11 @@ MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { return getStruct<MachO::linker_options_command>(this, L.Ptr); } +MachO::version_min_command +MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::version_min_command>(this, L.Ptr); +} + MachO::any_relocation_info MachOObjectFile::getRelocation(DataRefImpl Rel) const { const char *P = reinterpret_cast<const char *>(Rel.p); @@ -1579,26 +1562,27 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { +ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer, + bool BufferOwned) { StringRef Magic = Buffer->getBuffer().slice(0, 4); - error_code ec; - OwningPtr<ObjectFile> Ret; + error_code EC; + std::unique_ptr<MachOObjectFile> Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(Buffer, false, false, ec)); + Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned)); else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, false, ec)); + Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned)); else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(Buffer, false, true, ec)); + Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned)); else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, true, ec)); + Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned)); else { delete Buffer; - return NULL; + return object_error::parse_failed; } - if (ec) - return NULL; - return Ret.take(); + if (EC) + return EC; + return Ret.release(); } } // end namespace object diff --git a/lib/Object/MachOUniversal.cpp b/lib/Object/MachOUniversal.cpp index 75160af..70baa9f 100644 --- a/lib/Object/MachOUniversal.cpp +++ b/lib/Object/MachOUniversal.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/MachOUniversal.h" - #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" @@ -73,7 +72,7 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch( } error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( - OwningPtr<ObjectFile> &Result) const { + std::unique_ptr<ObjectFile> &Result) const { if (Parent) { StringRef ParentData = Parent->getData(); StringRef ObjectData = ParentData.substr(Header.offset, Header.size); @@ -82,16 +81,27 @@ error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( 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; - } + ErrorOr<ObjectFile *> Obj = ObjectFile::createMachOObjectFile(ObjBuffer); + if (error_code EC = Obj.getError()) + return EC; + Result.reset(Obj.get()); + return object_error::success; } return object_error::parse_failed; } void MachOUniversalBinary::anchor() { } +ErrorOr<MachOUniversalBinary *> +MachOUniversalBinary::create(MemoryBuffer *Source) { + error_code EC; + std::unique_ptr<MachOUniversalBinary> Ret( + new MachOUniversalBinary(Source, EC)); + if (EC) + return EC; + return Ret.release(); +} + MachOUniversalBinary::MachOUniversalBinary(MemoryBuffer *Source, error_code &ec) : Binary(Binary::ID_MachOUniversalBinary, Source), @@ -125,9 +135,8 @@ static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { } } -error_code -MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch, - OwningPtr<ObjectFile> &Result) const { +error_code MachOUniversalBinary::getObjectForArch( + Triple::ArchType Arch, std::unique_ptr<ObjectFile> &Result) const { MachO::CPUType CTM; if (!getCTMForArch(Arch, CTM)) return object_error::arch_not_found; diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 6941708..243bd44 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallVector.h" -#include "llvm/Object/ObjectFile.h" #include "llvm-c/Object.h" +#include "llvm/Object/ObjectFile.h" using namespace llvm; using namespace object; @@ -59,7 +59,9 @@ wrap(const relocation_iterator *SI) { // ObjectFile creation LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { - return wrap(ObjectFile::createObjectFile(unwrap(MemBuf))); + ErrorOr<ObjectFile*> ObjOrErr(ObjectFile::createObjectFile(unwrap(MemBuf))); + ObjectFile *Obj = ObjOrErr ? ObjOrErr.get() : 0; + return wrap(Obj); } void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { @@ -68,7 +70,7 @@ void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { // ObjectFile Section iterators LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { - section_iterator SI = unwrap(ObjectFile)->begin_sections(); + section_iterator SI = unwrap(ObjectFile)->section_begin(); return wrap(new section_iterator(SI)); } @@ -78,13 +80,11 @@ void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, LLVMSectionIteratorRef SI) { - return (*unwrap(SI) == unwrap(ObjectFile)->end_sections()) ? 1 : 0; + return (*unwrap(SI) == unwrap(ObjectFile)->section_end()) ? 1 : 0; } void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { - error_code ec; - unwrap(SI)->increment(ec); - if (ec) report_fatal_error("LLVMMoveToNextSection failed: " + ec.message()); + ++(*unwrap(SI)); } void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, @@ -95,7 +95,7 @@ void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, // ObjectFile Symbol iterators LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile) { - symbol_iterator SI = unwrap(ObjectFile)->begin_symbols(); + symbol_iterator SI = unwrap(ObjectFile)->symbol_begin(); return wrap(new symbol_iterator(SI)); } @@ -105,13 +105,11 @@ void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile, LLVMSymbolIteratorRef SI) { - return (*unwrap(SI) == unwrap(ObjectFile)->end_symbols()) ? 1 : 0; + return (*unwrap(SI) == unwrap(ObjectFile)->symbol_end()) ? 1 : 0; } void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { - error_code ec; - unwrap(SI)->increment(ec); - if (ec) report_fatal_error("LLVMMoveToNextSymbol failed: " + ec.message()); + ++(*unwrap(SI)); } // SectionRef accessors @@ -153,7 +151,7 @@ LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, // Section Relocation iterators LLVMRelocationIteratorRef LLVMGetRelocations(LLVMSectionIteratorRef Section) { - relocation_iterator SI = (*unwrap(Section))->begin_relocations(); + relocation_iterator SI = (*unwrap(Section))->relocation_begin(); return wrap(new relocation_iterator(SI)); } @@ -163,14 +161,11 @@ void LLVMDisposeRelocationIterator(LLVMRelocationIteratorRef SI) { LLVMBool LLVMIsRelocationIteratorAtEnd(LLVMSectionIteratorRef Section, LLVMRelocationIteratorRef SI) { - return (*unwrap(SI) == (*unwrap(Section))->end_relocations()) ? 1 : 0; + return (*unwrap(SI) == (*unwrap(Section))->relocation_end()) ? 1 : 0; } void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { - error_code ec; - unwrap(SI)->increment(ec); - if (ec) report_fatal_error("LLVMMoveToNextRelocation failed: " + - ec.message()); + ++(*unwrap(SI)); } diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 0e626d6..d30f0cc 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -12,10 +12,10 @@ //===----------------------------------------------------------------------===// #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/raw_ostream.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -23,8 +23,17 @@ using namespace object; void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) - : Binary(Type, source) { +ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source, + bool BufferOwned) + : SymbolicFile(Type, Source, BufferOwned) {} + +error_code ObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + StringRef Name; + if (error_code EC = getSymbolName(Symb, Name)) + return EC; + OS << Name; + return object_error::success; } error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, @@ -37,26 +46,26 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); } -ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { - if (Object->getBufferSize() < 64) { - delete Object; - return 0; - } +ErrorOr<ObjectFile *> ObjectFile::createObjectFile(MemoryBuffer *Object, + bool BufferOwned, + sys::fs::file_magic Type) { + if (Type == sys::fs::file_magic::unknown) + Type = sys::fs::identify_magic(Object->getBuffer()); - sys::fs::file_magic Type = sys::fs::identify_magic(Object->getBuffer()); switch (Type) { case sys::fs::file_magic::unknown: case sys::fs::file_magic::bitcode: case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: - delete Object; - return 0; + if (BufferOwned) + delete Object; + return object_error::invalid_file_type; case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: case sys::fs::file_magic::elf_core: - return createELFObjectFile(Object); + return createELFObjectFile(Object, BufferOwned); 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: @@ -67,18 +76,18 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { 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); + return createMachOObjectFile(Object, BufferOwned); case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return createCOFFObjectFile(Object); + return createCOFFObjectFile(Object, BufferOwned); } llvm_unreachable("Unexpected Object File Type"); } -ObjectFile *ObjectFile::createObjectFile(StringRef ObjectPath) { - OwningPtr<MemoryBuffer> File; - if (MemoryBuffer::getFile(ObjectPath, File)) - return NULL; - return createObjectFile(File.take()); +ErrorOr<ObjectFile *> ObjectFile::createObjectFile(StringRef ObjectPath) { + std::unique_ptr<MemoryBuffer> File; + if (error_code EC = MemoryBuffer::getFile(ObjectPath, File)) + return EC; + return createObjectFile(File.release()); } diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp new file mode 100644 index 0000000..495f0b6 --- /dev/null +++ b/lib/Object/SymbolicFile.cpp @@ -0,0 +1,67 @@ +//===- SymbolicFile.cpp - Interface that only provides symbols --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a file format independent SymbolicFile class. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/MemoryBuffer.h" + +using namespace llvm; +using namespace object; + +SymbolicFile::SymbolicFile(unsigned int Type, MemoryBuffer *Source, + bool BufferOwned) + : Binary(Type, Source, BufferOwned) {} + +SymbolicFile::~SymbolicFile() {} + +ErrorOr<SymbolicFile *> +SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned, + sys::fs::file_magic Type, + LLVMContext *Context) { + if (Type == sys::fs::file_magic::unknown) + Type = sys::fs::identify_magic(Object->getBuffer()); + + switch (Type) { + case sys::fs::file_magic::bitcode: + if (Context) + return IRObjectFile::createIRObjectFile(Object, *Context, BufferOwned); + // Fallthrough + case sys::fs::file_magic::unknown: + case sys::fs::file_magic::archive: + case sys::fs::file_magic::macho_universal_binary: + case sys::fs::file_magic::windows_resource: + if (BufferOwned) + delete Object; + return object_error::invalid_file_type; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::elf_executable: + case sys::fs::file_magic::elf_shared_object: + case sys::fs::file_magic::elf_core: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::macho_executable: + case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: + case sys::fs::file_magic::macho_core: + case sys::fs::file_magic::macho_preload_executable: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib: + case sys::fs::file_magic::macho_dynamic_linker: + case sys::fs::file_magic::macho_bundle: + case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: + case sys::fs::file_magic::macho_dsym_companion: + case sys::fs::file_magic::coff_object: + case sys::fs::file_magic::coff_import_library: + case sys::fs::file_magic::pecoff_executable: + return ObjectFile::createObjectFile(Object, BufferOwned, Type); + } + llvm_unreachable("Unexpected Binary File Type"); +} diff --git a/lib/Object/YAML.cpp b/lib/Object/YAML.cpp index c527bde..61e9da3 100644 --- a/lib/Object/YAML.cpp +++ b/lib/Object/YAML.cpp @@ -51,10 +51,8 @@ void BinaryRef::writeAsBinary(raw_ostream &OS) const { } void BinaryRef::writeAsHex(raw_ostream &OS) const { - if (binary_size() == 0) { - OS << "\"\""; + if (binary_size() == 0) return; - } if (DataIsHexString) { OS.write((const char *)Data.data(), Data.size()); return; |