diff options
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Android.mk | 8 | ||||
-rw-r--r-- | lib/Object/Archive.cpp | 182 | ||||
-rw-r--r-- | lib/Object/Binary.cpp | 28 | ||||
-rw-r--r-- | lib/Object/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 287 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 51 | ||||
-rw-r--r-- | lib/Object/ELFYAML.cpp | 13 | ||||
-rw-r--r-- | lib/Object/Error.cpp | 17 | ||||
-rw-r--r-- | lib/Object/IRObjectFile.cpp | 208 | ||||
-rw-r--r-- | lib/Object/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 696 | ||||
-rw-r--r-- | lib/Object/MachOUniversal.cpp | 75 | ||||
-rw-r--r-- | lib/Object/Object.cpp | 32 | ||||
-rw-r--r-- | lib/Object/ObjectFile.cpp | 38 | ||||
-rw-r--r-- | lib/Object/RecordStreamer.cpp | 100 | ||||
-rw-r--r-- | lib/Object/RecordStreamer.h | 42 | ||||
-rw-r--r-- | lib/Object/StringTableBuilder.cpp | 51 | ||||
-rw-r--r-- | lib/Object/SymbolicFile.cpp | 14 | ||||
-rw-r--r-- | lib/Object/YAML.cpp | 66 |
19 files changed, 1225 insertions, 688 deletions
diff --git a/lib/Object/Android.mk b/lib/Object/Android.mk index 4385f5a..acda4f2 100644 --- a/lib/Object/Android.mk +++ b/lib/Object/Android.mk @@ -7,17 +7,15 @@ object_SRC_FILES := \ COFFYAML.cpp \ ELF.cpp \ ELFObjectFile.cpp \ + ELFYAML.cpp \ Error.cpp \ IRObjectFile.cpp \ MachOObjectFile.cpp \ MachOUniversal.cpp \ Object.cpp \ ObjectFile.cpp \ - StringTableBuilder.cpp \ - SymbolicFile.cpp \ - YAML.cpp \ - ELFYAML.cpp \ - + RecordStreamer.cpp \ + SymbolicFile.cpp # For the host # ===================================================== diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 304ca47..6d09bdb 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -115,18 +115,14 @@ Archive::Child Archive::Child::getNext() const { return Child(Parent, NextLoc); } -error_code Archive::Child::getName(StringRef &Result) const { +ErrorOr<StringRef> Archive::Child::getName() const { StringRef name = getRawName(); // Check if it's a special name. if (name[0] == '/') { - if (name.size() == 1) { // Linker member. - Result = name; - return object_error::success; - } - if (name.size() == 2 && name[1] == '/') { // String table. - Result = name; - return object_error::success; - } + if (name.size() == 1) // Linker member. + return name; + if (name.size() == 2 && name[1] == '/') // String table. + return name; // It's a long name. // Get the offset. std::size_t offset; @@ -147,68 +143,62 @@ error_code Archive::Child::getName(StringRef &Result) const { // GNU long file names end with a /. if (Parent->kind() == K_GNU) { StringRef::size_type End = StringRef(addr).find('/'); - Result = StringRef(addr, End); - } else { - Result = addr; + return StringRef(addr, End); } - return object_error::success; + return StringRef(addr); } else if (name.startswith("#1/")) { uint64_t name_size; if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) llvm_unreachable("Long name length is not an ingeter"); - Result = Data.substr(sizeof(ArchiveMemberHeader), name_size) + return Data.substr(sizeof(ArchiveMemberHeader), name_size) .rtrim(StringRef("\0", 1)); - return object_error::success; } // It's a simple name. if (name[name.size() - 1] == '/') - Result = name.substr(0, name.size() - 1); - else - Result = name; - return object_error::success; + return name.substr(0, name.size() - 1); + return name; } -error_code Archive::Child::getMemoryBuffer(std::unique_ptr<MemoryBuffer> &Result, - bool FullPath) const { - StringRef Name; - if (error_code ec = getName(Name)) - return ec; +ErrorOr<std::unique_ptr<MemoryBuffer>> +Archive::Child::getMemoryBuffer(bool FullPath) const { + ErrorOr<StringRef> NameOrErr = getName(); + if (std::error_code EC = NameOrErr.getError()) + return EC; + StringRef Name = NameOrErr.get(); SmallString<128> Path; - Result.reset(MemoryBuffer::getMemBuffer( - getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + ")") - .toStringRef(Path) - : Name, + std::unique_ptr<MemoryBuffer> Ret(MemoryBuffer::getMemBuffer( + getBuffer(), + FullPath + ? (Twine(Parent->getFileName()) + "(" + Name + ")").toStringRef(Path) + : Name, false)); - return error_code::success(); + return std::move(Ret); } -error_code Archive::Child::getAsBinary(std::unique_ptr<Binary> &Result, - LLVMContext *Context) const { +ErrorOr<std::unique_ptr<Binary>> +Archive::Child::getAsBinary(LLVMContext *Context) const { std::unique_ptr<Binary> ret; - std::unique_ptr<MemoryBuffer> Buff; - if (error_code ec = getMemoryBuffer(Buff)) - return ec; - ErrorOr<Binary *> BinaryOrErr = createBinary(Buff.release(), Context); - if (error_code EC = BinaryOrErr.getError()) + ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr = getMemoryBuffer(); + if (std::error_code EC = BuffOrErr.getError()) return EC; - Result.reset(BinaryOrErr.get()); - return object_error::success; + + std::unique_ptr<MemoryBuffer> Buff(BuffOrErr.get().release()); + return createBinary(Buff, Context); } -ErrorOr<Archive*> Archive::create(MemoryBuffer *Source) { - error_code EC; - std::unique_ptr<Archive> Ret(new Archive(Source, EC)); +ErrorOr<Archive *> Archive::create(std::unique_ptr<MemoryBuffer> Source) { + std::error_code EC; + std::unique_ptr<Archive> Ret(new Archive(std::move(Source), EC)); if (EC) return EC; return Ret.release(); } -Archive::Archive(MemoryBuffer *source, error_code &ec) - : Binary(Binary::ID_Archive, source), SymbolTable(child_end()) { +Archive::Archive(std::unique_ptr<MemoryBuffer> Source, std::error_code &ec) + : Binary(Binary::ID_Archive, std::move(Source)), SymbolTable(child_end()) { // Check for sufficient magic. - assert(source); - if (source->getBufferSize() < 8 || - StringRef(source->getBufferStart(), 8) != Magic) { + if (Data->getBufferSize() < 8 || + StringRef(Data->getBufferStart(), 8) != Magic) { ec = object_error::invalid_file_type; return; } @@ -255,9 +245,11 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) if (Name.startswith("#1/")) { Format = K_BSD; // We know this is BSD, so getName will work since there is no string table. - ec = i->getName(Name); + ErrorOr<StringRef> NameOrErr = i->getName(); + ec = NameOrErr.getError(); if (ec) return; + Name = NameOrErr.get(); if (Name == "__.SYMDEF SORTED") { SymbolTable = i; ++i; @@ -335,12 +327,11 @@ Archive::child_iterator Archive::child_end() const { return Child(this, nullptr); } -error_code Archive::Symbol::getName(StringRef &Result) const { - Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); - return object_error::success; +StringRef Archive::Symbol::getName() const { + return Parent->SymbolTable->getBuffer().begin() + StringIndex; } -error_code Archive::Symbol::getMember(child_iterator &Result) const { +ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const { const char *Buf = Parent->SymbolTable->getBuffer().begin(); const char *Offsets = Buf + 4; uint32_t Offset = 0; @@ -348,7 +339,14 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) + SymbolIndex); } else if (Parent->kind() == K_BSD) { - llvm_unreachable("BSD format is not supported"); + // The SymbolIndex is an index into the ranlib structs that start at + // Offsets (the first uint32_t is the number of bytes of the ranlib + // structs). The ranlib structs are a pair of uint32_t's the first + // being a string table offset and the second being the offset into + // the archive of the member that defines the symbol. Which is what + // is needed here. + Offset = *(reinterpret_cast<const support::ulittle32_t *>(Offsets) + + (SymbolIndex * 2) + 1); } else { uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); @@ -380,16 +378,49 @@ error_code Archive::Symbol::getMember(child_iterator &Result) const { } const char *Loc = Parent->getData().begin() + Offset; - Result = Child(Parent, Loc); - - return object_error::success; + child_iterator Iter(Child(Parent, Loc)); + return Iter; } Archive::Symbol Archive::Symbol::getNext() const { Symbol t(*this); - // Go to one past next null. - t.StringIndex = - Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; + if (Parent->kind() == K_BSD) { + // t.StringIndex is an offset from the start of the __.SYMDEF or + // "__.SYMDEF SORTED" member into the string table for the ranlib + // struct indexed by t.SymbolIndex . To change t.StringIndex to the + // offset in the string table for t.SymbolIndex+1 we subtract the + // its offset from the start of the string table for t.SymbolIndex + // and add the offset of the string table for t.SymbolIndex+1. + + // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t + // which is the number of bytes of ranlib structs that follow. The ranlib + // structs are a pair of uint32_t's the first being a string table offset + // and the second being the offset into the archive of the member that + // define the symbol. After that the next uint32_t is the byte count of + // the string table followed by the string table. + const char *Buf = Parent->SymbolTable->getBuffer().begin(); + uint32_t RanlibCount = 0; + RanlibCount = (*reinterpret_cast<const support::ulittle32_t *>(Buf)) / + (sizeof(uint32_t) * 2); + // If t.SymbolIndex + 1 will be past the count of symbols (the RanlibCount) + // don't change the t.StringIndex as we don't want to reference a ranlib + // past RanlibCount. + if (t.SymbolIndex + 1 < RanlibCount) { + const char *Ranlibs = Buf + 4; + uint32_t CurRanStrx = 0; + uint32_t NextRanStrx = 0; + CurRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + + (t.SymbolIndex * 2)); + NextRanStrx = *(reinterpret_cast<const support::ulittle32_t *>(Ranlibs) + + ((t.SymbolIndex + 1) * 2)); + t.StringIndex -= CurRanStrx; + t.StringIndex += NextRanStrx; + } + } else { + // Go to one past next null. + t.StringIndex = + Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; + } ++t.SymbolIndex; return t; } @@ -404,7 +435,22 @@ Archive::symbol_iterator Archive::symbol_begin() const { symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); } else if (kind() == K_BSD) { - llvm_unreachable("BSD archive format is not supported"); + // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t + // which is the number of bytes of ranlib structs that follow. The ranlib + // structs are a pair of uint32_t's the first being a string table offset + // and the second being the offset into the archive of the member that + // define the symbol. After that the next uint32_t is the byte count of + // the string table followed by the string table. + uint32_t ranlib_count = 0; + ranlib_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / + (sizeof(uint32_t) * 2); + const char *ranlibs = buf + 4; + uint32_t ran_strx = 0; + ran_strx = *(reinterpret_cast<const support::ulittle32_t *>(ranlibs)); + buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); + // Skip the byte count of the string table. + buf += sizeof(uint32_t); + buf += ran_strx; } else { uint32_t member_count = 0; uint32_t symbol_count = 0; @@ -426,7 +472,8 @@ Archive::symbol_iterator Archive::symbol_end() const { if (kind() == K_GNU) { symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); } else if (kind() == K_BSD) { - llvm_unreachable("BSD archive format is not supported"); + symbol_count = (*reinterpret_cast<const support::ulittle32_t *>(buf)) / + (sizeof(uint32_t) * 2); } else { uint32_t member_count = 0; member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); @@ -440,16 +487,15 @@ Archive::symbol_iterator Archive::symbol_end() const { Archive::child_iterator Archive::findSym(StringRef name) const { 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 child_end(); - if (symname == name) { - if (bs->getMember(result)) + StringRef SymName = bs->getName(); + if (SymName == name) { + ErrorOr<Archive::child_iterator> ResultOrErr = bs->getMember(); + // FIXME: Should we really eat the error? + if (ResultOrErr.getError()) return child_end(); - return result; + return ResultOrErr.get(); } } return child_end(); diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 63fd3ed..9f6a685 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -25,13 +25,10 @@ using namespace llvm; using namespace object; -Binary::~Binary() { - if (BufferOwned) - delete Data; -} +Binary::~Binary() {} -Binary::Binary(unsigned int Type, MemoryBuffer *Source, bool BufferOwned) - : TypeID(Type), BufferOwned(BufferOwned), Data(Source) {} +Binary::Binary(unsigned int Type, std::unique_ptr<MemoryBuffer> Source) + : TypeID(Type), Data(std::move(Source)) {} StringRef Binary::getData() const { return Data->getBuffer(); @@ -41,14 +38,13 @@ StringRef Binary::getFileName() const { return Data->getBufferIdentifier(); } -ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source, +ErrorOr<Binary *> object::createBinary(std::unique_ptr<MemoryBuffer> &Buffer, LLVMContext *Context) { - std::unique_ptr<MemoryBuffer> scopedSource(Source); - sys::fs::file_magic Type = sys::fs::identify_magic(Source->getBuffer()); + sys::fs::file_magic Type = sys::fs::identify_magic(Buffer->getBuffer()); switch (Type) { case sys::fs::file_magic::archive: - return Archive::create(scopedSource.release()); + return Archive::create(std::move(Buffer)); case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: @@ -67,10 +63,9 @@ ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source, case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: case sys::fs::file_magic::bitcode: - return ObjectFile::createSymbolicFile(scopedSource.release(), true, Type, - Context); + return ObjectFile::createSymbolicFile(Buffer, Type, Context); case sys::fs::file_magic::macho_universal_binary: - return MachOUniversalBinary::create(scopedSource.release()); + return MachOUniversalBinary::create(std::move(Buffer)); case sys::fs::file_magic::unknown: case sys::fs::file_magic::windows_resource: // Unrecognized object file format. @@ -80,8 +75,9 @@ ErrorOr<Binary *> object::createBinary(MemoryBuffer *Source, } ErrorOr<Binary *> object::createBinary(StringRef Path) { - std::unique_ptr<MemoryBuffer> File; - if (error_code EC = MemoryBuffer::getFileOrSTDIN(Path, File)) + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Path); + if (std::error_code EC = FileOrErr.getError()) return EC; - return createBinary(File.release()); + return createBinary(FileOrErr.get()); } diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index cd8c9ef..5b08e42 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -12,7 +12,6 @@ add_llvm_library(LLVMObject MachOUniversal.cpp Object.cpp ObjectFile.cpp - StringTableBuilder.cpp + RecordStreamer.cpp SymbolicFile.cpp - YAML.cpp ) diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 262c040..46ef87d 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -31,8 +31,9 @@ using support::ulittle32_t; using support::little16_t; // Returns false if size is greater than the buffer size. And sets ec. -static bool checkSize(const MemoryBuffer *M, error_code &EC, uint64_t Size) { - if (M->getBufferSize() < Size) { +static bool checkSize(const MemoryBuffer &M, std::error_code &EC, + uint64_t Size) { + if (M.getBufferSize() < Size) { EC = object_error::unexpected_eof; return false; } @@ -41,13 +42,13 @@ static 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> -static error_code getObject(const T *&Obj, const MemoryBuffer *M, - const uint8_t *Ptr, const size_t Size = sizeof(T)) { +template <typename T> +static std::error_code getObject(const T *&Obj, const MemoryBuffer &M, + const uint8_t *Ptr, + const size_t Size = sizeof(T)) { uintptr_t Addr = uintptr_t(Ptr); - if (Addr + Size < Addr || - Addr + Size < Size || - Addr + Size > uintptr_t(M->getBufferEnd())) { + if (Addr + Size < Addr || Addr + Size < Size || + Addr + Size > uintptr_t(M.getBufferEnd())) { return object_error::unexpected_eof; } Obj = reinterpret_cast<const T *>(Addr); @@ -129,17 +130,17 @@ void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { Ref.p = reinterpret_cast<uintptr_t>(Symb); } -error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, - StringRef &Result) const { +std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, + StringRef &Result) const { const coff_symbol *Symb = toSymb(Ref); return getSymbolName(Symb, Result); } -error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, - uint64_t &Result) const { +std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, + uint64_t &Result) const { const coff_symbol *Symb = toSymb(Ref); const coff_section *Section = nullptr; - if (error_code EC = getSection(Symb->SectionNumber, Section)) + if (std::error_code EC = getSection(Symb->SectionNumber, Section)) return EC; if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) @@ -151,8 +152,8 @@ error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, return object_error::success; } -error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, - SymbolRef::Type &Result) const { +std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, + SymbolRef::Type &Result) const { const coff_symbol *Symb = toSymb(Ref); Result = SymbolRef::ST_Other; if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && @@ -164,7 +165,7 @@ error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, uint32_t Characteristics = 0; if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { const coff_section *Section = nullptr; - if (error_code EC = getSection(Symb->SectionNumber, Section)) + if (std::error_code EC = getSection(Symb->SectionNumber, Section)) return EC; Characteristics = Section->Characteristics; } @@ -202,14 +203,14 @@ uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { return Result; } -error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, - uint64_t &Result) const { +std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, + uint64_t &Result) const { // FIXME: Return the correct size. This requires looking at all the symbols // in the same section as this symbol, and looking for either the next // symbol, or the end of the section. const coff_symbol *Symb = toSymb(Ref); const coff_section *Section = nullptr; - if (error_code EC = getSection(Symb->SectionNumber, Section)) + if (std::error_code EC = getSection(Symb->SectionNumber, Section)) return EC; if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) @@ -221,14 +222,16 @@ error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, return object_error::success; } -error_code COFFObjectFile::getSymbolSection(DataRefImpl Ref, - section_iterator &Result) const { +std::error_code +COFFObjectFile::getSymbolSection(DataRefImpl Ref, + section_iterator &Result) const { const coff_symbol *Symb = toSymb(Ref); if (COFF::isReservedSectionNumber(Symb->SectionNumber)) { Result = section_end(); } else { const coff_section *Sec = nullptr; - if (error_code EC = getSection(Symb->SectionNumber, Sec)) return EC; + if (std::error_code EC = getSection(Symb->SectionNumber, Sec)) + return EC; DataRefImpl Ref; Ref.p = reinterpret_cast<uintptr_t>(Sec); Result = section_iterator(SectionRef(Ref, this)); @@ -242,37 +245,37 @@ void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { Ref.p = reinterpret_cast<uintptr_t>(Sec); } -error_code COFFObjectFile::getSectionName(DataRefImpl Ref, - StringRef &Result) const { +std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, + StringRef &Result) const { const coff_section *Sec = toSec(Ref); return getSectionName(Sec, Result); } -error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, - uint64_t &Result) const { +std::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, + uint64_t &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->VirtualAddress; return object_error::success; } -error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, - uint64_t &Result) const { +std::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, + uint64_t &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->SizeOfRawData; return object_error::success; } -error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, - StringRef &Result) const { +std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, + StringRef &Result) const { const coff_section *Sec = toSec(Ref); ArrayRef<uint8_t> Res; - error_code EC = getSectionContents(Sec, Res); + std::error_code EC = getSectionContents(Sec, Res); Result = StringRef(reinterpret_cast<const char*>(Res.data()), Res.size()); return EC; } -error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, - uint64_t &Res) const { +std::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, + uint64_t &Res) const { const coff_section *Sec = toSec(Ref); if (!Sec) return object_error::parse_failed; @@ -280,62 +283,64 @@ error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, return object_error::success; } -error_code COFFObjectFile::isSectionText(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionText(DataRefImpl Ref, + bool &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; return object_error::success; } -error_code COFFObjectFile::isSectionData(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionData(DataRefImpl Ref, + bool &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, + bool &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, - bool &Result) const { +std::error_code +COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, + bool &Result) const { // FIXME: Unimplemented Result = true; return object_error::success; } -error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, + bool &Result) const { const coff_section *Sec = toSec(Ref); Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; return object_error::success; } -error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, - bool &Result) const { +std::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, - DataRefImpl SymbRef, - bool &Result) const { +std::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, + DataRefImpl SymbRef, + bool &Result) const { const coff_section *Sec = toSec(SecRef); const coff_symbol *Symb = toSymb(SymbRef); const coff_section *SymbSec = nullptr; - if (error_code EC = getSection(Symb->SectionNumber, SymbSec)) return EC; + if (std::error_code EC = getSection(Symb->SectionNumber, SymbSec)) + return EC; if (SymbSec == Sec) Result = true; else @@ -390,9 +395,9 @@ relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { } // Initialize the pointer to the symbol table. -error_code COFFObjectFile::initSymbolTablePtr() { - if (error_code EC = getObject( - SymbolTable, Data, base() + COFFHeader->PointerToSymbolTable, +std::error_code COFFObjectFile::initSymbolTablePtr() { + if (std::error_code EC = getObject( + SymbolTable, *Data, base() + COFFHeader->PointerToSymbolTable, COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) return EC; @@ -403,11 +408,12 @@ error_code COFFObjectFile::initSymbolTablePtr() { base() + COFFHeader->PointerToSymbolTable + COFFHeader->NumberOfSymbols * sizeof(coff_symbol); const ulittle32_t *StringTableSizePtr; - if (error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) + if (std::error_code EC = + getObject(StringTableSizePtr, *Data, StringTableAddr)) return EC; StringTableSize = *StringTableSizePtr; - if (error_code EC = - getObject(StringTable, Data, StringTableAddr, StringTableSize)) + if (std::error_code EC = + getObject(StringTable, *Data, StringTableAddr, StringTableSize)) return EC; // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some @@ -422,7 +428,7 @@ error_code COFFObjectFile::initSymbolTablePtr() { } // Returns the file offset for the given VA. -error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { +std::error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { uint64_t ImageBase = PE32Header ? (uint64_t)PE32Header->ImageBase : (uint64_t)PE32PlusHeader->ImageBase; uint64_t Rva = Addr - ImageBase; @@ -431,7 +437,7 @@ error_code COFFObjectFile::getVaPtr(uint64_t Addr, uintptr_t &Res) const { } // Returns the file offset for the given RVA. -error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { +std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { for (const SectionRef &S : sections()) { const coff_section *Section = getCOFFSection(S); uint32_t SectionStart = Section->VirtualAddress; @@ -447,10 +453,10 @@ error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name // table entry. -error_code COFFObjectFile:: -getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { +std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, + StringRef &Name) const { uintptr_t IntPtr = 0; - if (error_code EC = getRvaPtr(Rva, IntPtr)) + if (std::error_code EC = getRvaPtr(Rva, IntPtr)) return EC; const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); @@ -459,7 +465,7 @@ getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const { } // Find the import table. -error_code COFFObjectFile::initImportTablePtr() { +std::error_code COFFObjectFile::initImportTablePtr() { // First, we get the RVA of the import table. If the file lacks a pointer to // the import table, do nothing. const data_directory *DataEntry; @@ -477,7 +483,7 @@ 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)) + if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) return EC; ImportDirectory = reinterpret_cast< const import_directory_table_entry *>(IntPtr); @@ -485,7 +491,7 @@ error_code COFFObjectFile::initImportTablePtr() { } // Find the export table. -error_code COFFObjectFile::initExportTablePtr() { +std::error_code COFFObjectFile::initExportTablePtr() { // First, we get the RVA of the export table. If the file lacks a pointer to // the export table, do nothing. const data_directory *DataEntry; @@ -498,22 +504,23 @@ error_code COFFObjectFile::initExportTablePtr() { uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; uintptr_t IntPtr = 0; - if (error_code EC = getRvaPtr(ExportTableRva, IntPtr)) + if (std::error_code EC = getRvaPtr(ExportTableRva, IntPtr)) return EC; ExportDirectory = reinterpret_cast<const export_directory_table_entry *>(IntPtr); return object_error::success; } -COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, - bool BufferOwned) - : ObjectFile(Binary::ID_COFF, Object, BufferOwned), COFFHeader(nullptr), +COFFObjectFile::COFFObjectFile(std::unique_ptr<MemoryBuffer> Object, + std::error_code &EC) + : ObjectFile(Binary::ID_COFF, std::move(Object)), COFFHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr), StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0), ExportDirectory(nullptr) { // Check that we at least have enough room for a header. - if (!checkSize(Data, EC, sizeof(coff_file_header))) return; + if (!checkSize(*Data, EC, sizeof(coff_file_header))) + return; // The current location in the file where we are looking at. uint64_t CurPtr = 0; @@ -526,7 +533,8 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, 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) { @@ -537,13 +545,13 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, HasPEHeader = true; } - if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) + if ((EC = getObject(COFFHeader, *Data, base() + CurPtr))) return; CurPtr += sizeof(coff_file_header); if (HasPEHeader) { const pe32_header *Header; - if ((EC = getObject(Header, Data, base() + CurPtr))) + if ((EC = getObject(Header, *Data, base() + CurPtr))) return; const uint8_t *DataDirAddr; @@ -561,7 +569,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, EC = object_error::parse_failed; return; } - if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) + if ((EC = getObject(DataDirectory, *Data, DataDirAddr, DataDirSize))) return; CurPtr += COFFHeader->SizeOfOptionalHeader; } @@ -569,7 +577,7 @@ COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &EC, if (COFFHeader->isImportLibrary()) return; - if ((EC = getObject(SectionTable, Data, base() + CurPtr, + if ((EC = getObject(SectionTable, *Data, base() + CurPtr, COFFHeader->NumberOfSections * sizeof(coff_section)))) return; @@ -686,28 +694,30 @@ unsigned COFFObjectFile::getArch() const { // This method is kept here because lld uses this. As soon as we make // lld to use getCOFFHeader, this method will be removed. -error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { +std::error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { return getCOFFHeader(Res); } -error_code COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { +std::error_code +COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { Res = COFFHeader; return object_error::success; } -error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { +std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { Res = PE32Header; return object_error::success; } -error_code +std::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 { +std::error_code +COFFObjectFile::getDataDirectory(uint32_t Index, + const data_directory *&Res) const { // Error if if there's no data directory or the index is out of range. if (!DataDirectory) return object_error::parse_failed; @@ -720,8 +730,8 @@ error_code COFFObjectFile::getDataDirectory(uint32_t Index, return object_error::success; } -error_code COFFObjectFile::getSection(int32_t Index, - const coff_section *&Result) const { +std::error_code COFFObjectFile::getSection(int32_t Index, + const coff_section *&Result) const { // Check for special index values. if (COFF::isReservedSectionNumber(Index)) Result = nullptr; @@ -733,8 +743,8 @@ error_code COFFObjectFile::getSection(int32_t Index, return object_error::success; } -error_code COFFObjectFile::getString(uint32_t Offset, - StringRef &Result) const { +std::error_code COFFObjectFile::getString(uint32_t Offset, + StringRef &Result) const { if (StringTableSize <= 4) // Tried to get a string from an empty string table. return object_error::parse_failed; @@ -744,8 +754,8 @@ error_code COFFObjectFile::getString(uint32_t Offset, return object_error::success; } -error_code COFFObjectFile::getSymbol(uint32_t Index, - const coff_symbol *&Result) const { +std::error_code COFFObjectFile::getSymbol(uint32_t Index, + const coff_symbol *&Result) const { if (Index < COFFHeader->NumberOfSymbols) Result = SymbolTable + Index; else @@ -753,12 +763,12 @@ error_code COFFObjectFile::getSymbol(uint32_t Index, return object_error::success; } -error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, - StringRef &Res) const { +std::error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, + StringRef &Res) const { // Check for string table entry. First 4 bytes are 0. if (Symbol->Name.Offset.Zeroes == 0) { uint32_t Offset = Symbol->Name.Offset.Offset; - if (error_code EC = getString(Offset, Res)) + if (std::error_code EC = getString(Offset, Res)) return EC; return object_error::success; } @@ -795,8 +805,8 @@ ArrayRef<uint8_t> COFFObjectFile::getSymbolAuxData( Symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); } -error_code COFFObjectFile::getSectionName(const coff_section *Sec, - StringRef &Res) const { +std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, + StringRef &Res) const { StringRef Name; if (Sec->Name[7] == 0) // Null terminated, let ::strlen figure out the length. @@ -815,7 +825,7 @@ error_code COFFObjectFile::getSectionName(const coff_section *Sec, if (Name.substr(1).getAsInteger(10, Offset)) return object_error::parse_failed; } - if (error_code EC = getString(Offset, Name)) + if (std::error_code EC = getString(Offset, Name)) return EC; } @@ -823,8 +833,9 @@ error_code COFFObjectFile::getSectionName(const coff_section *Sec, return object_error::success; } -error_code COFFObjectFile::getSectionContents(const coff_section *Sec, - ArrayRef<uint8_t> &Res) const { +std::error_code +COFFObjectFile::getSectionContents(const coff_section *Sec, + ArrayRef<uint8_t> &Res) const { // The only thing that we need to verify is that the contents is contained // within the file bounds. We don't need to make sure it doesn't cover other // data, as there's nothing that says that is not allowed. @@ -846,13 +857,13 @@ void COFFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { reinterpret_cast<const coff_relocation*>(Rel.p) + 1); } -error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { +std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); } -error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { +std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { Res = toRel(Rel)->VirtualAddress; return object_error::success; } @@ -864,8 +875,8 @@ symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { return symbol_iterator(SymbolRef(Ref, this)); } -error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { +std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { const coff_relocation* R = toRel(Rel); Res = R->Type; return object_error::success; @@ -891,8 +902,9 @@ COFFObjectFile::getCOFFRelocation(const RelocationRef &Reloc) const { Res = #reloc_type; \ break; -error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +std::error_code +COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { const coff_relocation *Reloc = toRel(Rel); StringRef Res; switch (COFFHeader->Machine) { @@ -966,26 +978,29 @@ error_code COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME -error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { +std::error_code +COFFObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl<char> &Result) const { const coff_relocation *Reloc = toRel(Rel); const coff_symbol *Symb = nullptr; - if (error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb)) return EC; + if (std::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; + if (std::error_code EC = getSymbolName(Sym, SymName)) + return EC; Result.append(SymName.begin(), SymName.end()); return object_error::success; } -error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const { +std::error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, + LibraryRef &Result) const { report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); } -error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Result) const { +std::error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, + StringRef &Result) const { report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); } @@ -998,24 +1013,25 @@ void ImportDirectoryEntryRef::moveNext() { ++Index; } -error_code ImportDirectoryEntryRef:: -getImportTableEntry(const import_directory_table_entry *&Result) const { +std::error_code ImportDirectoryEntryRef::getImportTableEntry( + const import_directory_table_entry *&Result) const { Result = ImportTable; return object_error::success; } -error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { +std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (error_code EC = OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) + if (std::error_code EC = + OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); return object_error::success; } -error_code ImportDirectoryEntryRef::getImportLookupEntry( +std::error_code ImportDirectoryEntryRef::getImportLookupEntry( const import_lookup_table_entry32 *&Result) const { uintptr_t IntPtr = 0; - if (error_code EC = + if (std::error_code EC = OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) return EC; Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); @@ -1033,31 +1049,33 @@ void ExportDirectoryEntryRef::moveNext() { // 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 { +std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (error_code EC = OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) + if (std::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 { +std::error_code +ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { Result = ExportTable->OrdinalBase; return object_error::success; } // Returns the export ordinal of the current export symbol. -error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { +std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { Result = ExportTable->OrdinalBase + Index; return object_error::success; } // Returns the address of the current export symbol. -error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { +std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { uintptr_t IntPtr = 0; - if (error_code EC = OwningObject->getRvaPtr( - ExportTable->ExportAddressTableRVA, IntPtr)) + if (std::error_code EC = + OwningObject->getRvaPtr(ExportTable->ExportAddressTableRVA, IntPtr)) return EC; const export_address_table_entry *entry = reinterpret_cast<const export_address_table_entry *>(IntPtr); @@ -1067,10 +1085,11 @@ error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { // 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 { +std::error_code +ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { uintptr_t IntPtr = 0; - if (error_code EC = OwningObject->getRvaPtr( - ExportTable->OrdinalTableRVA, IntPtr)) + if (std::error_code EC = + OwningObject->getRvaPtr(ExportTable->OrdinalTableRVA, IntPtr)) return EC; const ulittle16_t *Start = reinterpret_cast<const ulittle16_t *>(IntPtr); @@ -1080,11 +1099,11 @@ error_code ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { I < E; ++I, ++Offset) { if (*I != Index) continue; - if (error_code EC = OwningObject->getRvaPtr( - ExportTable->NamePointerRVA, IntPtr)) + if (std::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)) + if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); return object_error::success; @@ -1093,11 +1112,11 @@ error_code ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { return object_error::success; } -ErrorOr<ObjectFile *> ObjectFile::createCOFFObjectFile(MemoryBuffer *Object, - bool BufferOwned) { - error_code EC; +ErrorOr<ObjectFile *> +ObjectFile::createCOFFObjectFile(std::unique_ptr<MemoryBuffer> Object) { + std::error_code EC; std::unique_ptr<COFFObjectFile> Ret( - new COFFObjectFile(Object, EC, BufferOwned)); + new COFFObjectFile(std::move(Object), EC)); if (EC) return EC; return Ret.release(); diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index a2c4df2..4f0f60b 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -17,65 +17,66 @@ namespace llvm { using namespace object; -ErrorOr<ObjectFile *> ObjectFile::createELFObjectFile(MemoryBuffer *Obj, - bool BufferOwned) { - std::pair<unsigned char, unsigned char> Ident = getElfArchType(Obj); +ErrorOr<ObjectFile *> +ObjectFile::createELFObjectFile(std::unique_ptr<MemoryBuffer> &Obj) { + std::pair<unsigned char, unsigned char> Ident = + getElfArchType(Obj->getBuffer()); std::size_t MaxAlignment = 1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart())); - error_code EC; + std::error_code EC; std::unique_ptr<ObjectFile> R; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - R.reset(new ELFObjectFile<ELFType<support::little, 4, false> >( - Obj, EC, BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::little, 4, false>>( + std::move(Obj), EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::little, 2, false> >( - Obj, EC, BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::little, 2, false>>( + std::move(Obj), EC)); else - llvm_unreachable("Invalid alignment for ELF file!"); + return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - R.reset(new ELFObjectFile<ELFType<support::big, 4, false> >(Obj, EC, - BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::big, 4, false>>(std::move(Obj), + EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::big, 2, false> >(Obj, EC, - BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::big, 2, false>>(std::move(Obj), + EC)); else - llvm_unreachable("Invalid alignment for ELF file!"); + return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 8) - R.reset(new ELFObjectFile<ELFType<support::big, 8, true> >(Obj, EC, - BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::big, 8, true>>(std::move(Obj), + EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::big, 2, true> >(Obj, EC, - BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::big, 2, true>>(std::move(Obj), + EC)); else - llvm_unreachable("Invalid alignment for ELF file!"); + return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 8) - R.reset(new ELFObjectFile<ELFType<support::little, 8, true> >( - Obj, EC, BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::little, 8, true>>( + std::move(Obj), EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::little, 2, true> >( - Obj, EC, BufferOwned)); + R.reset(new ELFObjectFile<ELFType<support::little, 2, true>>( + std::move(Obj), EC)); else - llvm_unreachable("Invalid alignment for ELF file!"); + return object_error::parse_failed; } else - report_fatal_error("Buffer is not an ELF object file!"); + llvm_unreachable("Buffer is not an ELF object file!"); if (EC) return EC; diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index 7d50f23..dc3d467 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -368,6 +368,16 @@ void ScalarEnumerationTraits<ELFYAML::ELF_STT>::enumeration( #undef ECase } +void ScalarEnumerationTraits<ELFYAML::ELF_STV>::enumeration( + IO &IO, ELFYAML::ELF_STV &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(STV_DEFAULT) + ECase(STV_INTERNAL) + ECase(STV_HIDDEN) + ECase(STV_PROTECTED) +#undef ECase +} + void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( IO &IO, ELFYAML::ELF_REL &Value) { const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); @@ -649,6 +659,7 @@ void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Value", Symbol.Value, Hex64(0)); IO.mapOptional("Size", Symbol.Size, Hex64(0)); + IO.mapOptional("Visibility", Symbol.Visibility, ELFYAML::ELF_STV(0)); } void MappingTraits<ELFYAML::LocalGlobalWeakSymbols>::mapping( @@ -664,7 +675,6 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { IO.mapOptional("Flags", Section.Flags, ELFYAML::ELF_SHF(0)); IO.mapOptional("Address", Section.Address, Hex64(0)); IO.mapOptional("Link", Section.Link, StringRef()); - IO.mapOptional("Info", Section.Info, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); } @@ -676,6 +686,7 @@ static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { commonSectionMapping(IO, Section); + IO.mapOptional("Info", Section.Info, StringRef()); IO.mapOptional("Relocations", Section.Relocations); } diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp index 8e50869..9d25269 100644 --- a/lib/Object/Error.cpp +++ b/lib/Object/Error.cpp @@ -18,11 +18,10 @@ using namespace llvm; using namespace object; namespace { -class _object_error_category : public error_category { +class _object_error_category : public std::error_category { public: - const char* name() const override; + const char* name() const LLVM_NOEXCEPT override; std::string message(int ev) const override; - error_condition default_error_condition(int ev) const override; }; } @@ -30,8 +29,8 @@ const char *_object_error_category::name() const { return "llvm.object"; } -std::string _object_error_category::message(int ev) const { - object_error::Impl E = static_cast<object_error::Impl>(ev); +std::string _object_error_category::message(int EV) const { + object_error E = static_cast<object_error>(EV); switch (E) { case object_error::success: return "Success"; case object_error::arch_not_found: @@ -47,13 +46,7 @@ std::string _object_error_category::message(int ev) const { "defined."); } -error_condition _object_error_category::default_error_condition(int ev) const { - if (ev == object_error::success) - return errc::success; - return errc::invalid_argument; -} - -const error_category &object::object_category() { +const std::error_category &object::object_category() { static _object_error_category o; return o; } diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp index a8aba26..5323d92 100644 --- a/lib/Object/IRObjectFile.cpp +++ b/lib/Object/IRObjectFile.cpp @@ -11,34 +11,119 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/IRObjectFile.h" +#include "RecordStreamer.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/GVMaterializer.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" -#include "llvm/Object/IRObjectFile.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace object; -IRObjectFile::IRObjectFile(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()); - +IRObjectFile::IRObjectFile(std::unique_ptr<MemoryBuffer> Object, + std::unique_ptr<Module> Mod) + : SymbolicFile(Binary::ID_IR, std::move(Object)), M(std::move(Mod)) { // If we have a DataLayout, setup a mangler. const DataLayout *DL = M->getDataLayout(); if (!DL) return; Mang.reset(new Mangler(DL)); + + const std::string &InlineAsm = M->getModuleInlineAsm(); + if (InlineAsm.empty()) + return; + + StringRef Triple = M->getTargetTriple(); + std::string Err; + const Target *T = TargetRegistry::lookupTarget(Triple, Err); + if (!T) + return; + + std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); + if (!MRI) + return; + + std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); + if (!MAI) + return; + + std::unique_ptr<MCSubtargetInfo> STI( + T->createMCSubtargetInfo(Triple, "", "")); + if (!STI) + return; + + std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo()); + if (!MCII) + return; + + MCObjectFileInfo MOFI; + MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); + MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); + std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); + + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); + SourceMgr SrcMgr; + SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); + std::unique_ptr<MCAsmParser> Parser( + createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); + + MCTargetOptions MCOptions; + std::unique_ptr<MCTargetAsmParser> TAP( + T->createMCAsmParser(*STI, *Parser, *MCII, MCOptions)); + if (!TAP) + return; + + Parser->setTargetParser(*TAP); + if (Parser->Run(false)) + return; + + for (auto &KV : *Streamer) { + StringRef Key = KV.first(); + RecordStreamer::State Value = KV.second; + uint32_t Res = BasicSymbolRef::SF_None; + switch (Value) { + case RecordStreamer::NeverSeen: + llvm_unreachable("foo"); + case RecordStreamer::DefinedGlobal: + Res |= BasicSymbolRef::SF_Global; + break; + case RecordStreamer::Defined: + break; + case RecordStreamer::Global: + case RecordStreamer::Used: + Res |= BasicSymbolRef::SF_Undefined; + Res |= BasicSymbolRef::SF_Global; + break; + } + AsmSymbols.push_back( + std::make_pair<std::string, uint32_t>(Key, std::move(Res))); + } } -static const GlobalValue &getGV(DataRefImpl &Symb) { - return *reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); +IRObjectFile::~IRObjectFile() { + GVMaterializer *GVM = M->getMaterializer(); + if (GVM) + GVM->releaseBuffer(); + } + +static const GlobalValue *getGV(DataRefImpl &Symb) { + if ((Symb.p & 3) == 3) + return nullptr; + + return reinterpret_cast<GlobalValue*>(Symb.p & ~uintptr_t(3)); } static uintptr_t skipEmpty(Module::const_alias_iterator I, const Module &M) { @@ -62,68 +147,109 @@ static uintptr_t skipEmpty(Module::const_iterator I, const Module &M) { return reinterpret_cast<uintptr_t>(GV) | 0; } +static unsigned getAsmSymIndex(DataRefImpl Symb) { + assert((Symb.p & uintptr_t(3)) == 3); + uintptr_t Index = Symb.p & ~uintptr_t(3); + Index >>= 2; + return Index; +} + void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - const GlobalValue *GV = &getGV(Symb); - const Module &M = *GV->getParent(); + const GlobalValue *GV = getGV(Symb); uintptr_t Res; + switch (Symb.p & 3) { case 0: { Module::const_iterator Iter(static_cast<const Function*>(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); break; } case 1: { Module::const_global_iterator Iter(static_cast<const GlobalVariable*>(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); break; } case 2: { Module::const_alias_iterator Iter(static_cast<const GlobalAlias*>(GV)); ++Iter; - Res = skipEmpty(Iter, M); + Res = skipEmpty(Iter, *M); + break; + } + case 3: { + unsigned Index = getAsmSymIndex(Symb); + assert(Index < AsmSymbols.size()); + ++Index; + Res = (Index << 2) | 3; 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); +std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { + const GlobalValue *GV = getGV(Symb); + if (!GV) { + unsigned Index = getAsmSymIndex(Symb); + assert(Index <= AsmSymbols.size()); + OS << AsmSymbols[Index].first; + return object_error::success;; + } if (Mang) - Mang->getNameWithPrefix(OS, &GV, false); + Mang->getNameWithPrefix(OS, GV, false); else - OS << GV.getName(); + OS << GV->getName(); return object_error::success; } +static bool isDeclaration(const GlobalValue &V) { + if (V.hasAvailableExternallyLinkage()) + return true; + + if (V.isMaterializable()) + return false; + + return V.isDeclaration(); +} + uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { - const GlobalValue &GV = getGV(Symb); + const GlobalValue *GV = getGV(Symb); + + if (!GV) { + unsigned Index = getAsmSymIndex(Symb); + assert(Index <= AsmSymbols.size()); + return AsmSymbols[Index].second; + } uint32_t Res = BasicSymbolRef::SF_None; - if (GV.isDeclaration() || GV.hasAvailableExternallyLinkage()) + if (isDeclaration(*GV)) Res |= BasicSymbolRef::SF_Undefined; - if (GV.hasPrivateLinkage()) + if (GV->hasPrivateLinkage()) Res |= BasicSymbolRef::SF_FormatSpecific; - if (!GV.hasLocalLinkage()) + if (!GV->hasLocalLinkage()) Res |= BasicSymbolRef::SF_Global; - if (GV.hasCommonLinkage()) + if (GV->hasCommonLinkage()) Res |= BasicSymbolRef::SF_Common; - if (GV.hasLinkOnceLinkage() || GV.hasWeakLinkage()) + if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) Res |= BasicSymbolRef::SF_Weak; + if (GV->getName().startswith("llvm.")) + Res |= BasicSymbolRef::SF_FormatSpecific; + else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { + if (Var->getSection() == StringRef("llvm.metadata")) + Res |= BasicSymbolRef::SF_FormatSpecific; + } + return Res; } -const GlobalValue &IRObjectFile::getSymbolGV(DataRefImpl Symb) const { - const GlobalValue &GV = getGV(Symb); +const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { + const GlobalValue *GV = getGV(Symb); return GV; } @@ -136,16 +262,18 @@ basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { basic_symbol_iterator IRObjectFile::symbol_end_impl() const { DataRefImpl Ret; - Ret.p = 3; + uint64_t NumAsm = AsmSymbols.size(); + NumAsm <<= 2; + Ret.p = 3 | NumAsm; 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) +ErrorOr<IRObjectFile *> llvm::object::IRObjectFile::createIRObjectFile( + std::unique_ptr<MemoryBuffer> Object, LLVMContext &Context) { + ErrorOr<Module *> MOrErr = getLazyBitcodeModule(Object.get(), Context); + if (std::error_code EC = MOrErr.getError()) return EC; - return Ret.release(); + + std::unique_ptr<Module> M(MOrErr.get()); + return new IRObjectFile(std::move(Object), std::move(M)); } diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt index 7813832..8acacba 100644 --- a/lib/Object/LLVMBuild.txt +++ b/lib/Object/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Object parent = Libraries -required_libraries = BitReader Core Support +required_libraries = BitReader Core Support MC MCParser diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c6bab03..4919114 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -28,6 +28,7 @@ using namespace llvm; using namespace object; namespace llvm { + namespace object { struct nlist_base { @@ -43,190 +44,195 @@ struct section_base { }; template<typename T> -static void SwapValue(T &Value) { - Value = sys::SwapByteOrder(Value); -} - -template<typename T> static void SwapStruct(T &Value); template<> void SwapStruct(MachO::any_relocation_info &H) { - SwapValue(H.r_word0); - SwapValue(H.r_word1); + sys::swapByteOrder(H.r_word0); + sys::swapByteOrder(H.r_word1); } template<> void SwapStruct(MachO::load_command &L) { - SwapValue(L.cmd); - SwapValue(L.cmdsize); + sys::swapByteOrder(L.cmd); + sys::swapByteOrder(L.cmdsize); } template<> void SwapStruct(nlist_base &S) { - SwapValue(S.n_strx); - SwapValue(S.n_desc); + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); } template<> void SwapStruct(MachO::section &S) { - SwapValue(S.addr); - SwapValue(S.size); - SwapValue(S.offset); - SwapValue(S.align); - SwapValue(S.reloff); - SwapValue(S.nreloc); - SwapValue(S.flags); - SwapValue(S.reserved1); - SwapValue(S.reserved2); + sys::swapByteOrder(S.addr); + sys::swapByteOrder(S.size); + sys::swapByteOrder(S.offset); + sys::swapByteOrder(S.align); + sys::swapByteOrder(S.reloff); + sys::swapByteOrder(S.nreloc); + sys::swapByteOrder(S.flags); + sys::swapByteOrder(S.reserved1); + sys::swapByteOrder(S.reserved2); } template<> void SwapStruct(MachO::section_64 &S) { - SwapValue(S.addr); - SwapValue(S.size); - SwapValue(S.offset); - SwapValue(S.align); - SwapValue(S.reloff); - SwapValue(S.nreloc); - SwapValue(S.flags); - SwapValue(S.reserved1); - SwapValue(S.reserved2); - SwapValue(S.reserved3); + sys::swapByteOrder(S.addr); + sys::swapByteOrder(S.size); + sys::swapByteOrder(S.offset); + sys::swapByteOrder(S.align); + sys::swapByteOrder(S.reloff); + sys::swapByteOrder(S.nreloc); + sys::swapByteOrder(S.flags); + sys::swapByteOrder(S.reserved1); + sys::swapByteOrder(S.reserved2); + sys::swapByteOrder(S.reserved3); } template<> void SwapStruct(MachO::nlist &S) { - SwapValue(S.n_strx); - SwapValue(S.n_desc); - SwapValue(S.n_value); + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); + sys::swapByteOrder(S.n_value); } template<> void SwapStruct(MachO::nlist_64 &S) { - SwapValue(S.n_strx); - SwapValue(S.n_desc); - SwapValue(S.n_value); + sys::swapByteOrder(S.n_strx); + sys::swapByteOrder(S.n_desc); + sys::swapByteOrder(S.n_value); } template<> void SwapStruct(MachO::mach_header &H) { - SwapValue(H.magic); - SwapValue(H.cputype); - SwapValue(H.cpusubtype); - SwapValue(H.filetype); - SwapValue(H.ncmds); - SwapValue(H.sizeofcmds); - SwapValue(H.flags); + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.filetype); + sys::swapByteOrder(H.ncmds); + sys::swapByteOrder(H.sizeofcmds); + sys::swapByteOrder(H.flags); } template<> void SwapStruct(MachO::mach_header_64 &H) { - SwapValue(H.magic); - SwapValue(H.cputype); - SwapValue(H.cpusubtype); - SwapValue(H.filetype); - SwapValue(H.ncmds); - SwapValue(H.sizeofcmds); - SwapValue(H.flags); - SwapValue(H.reserved); + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.filetype); + sys::swapByteOrder(H.ncmds); + sys::swapByteOrder(H.sizeofcmds); + sys::swapByteOrder(H.flags); + sys::swapByteOrder(H.reserved); } template<> void SwapStruct(MachO::symtab_command &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.symoff); - SwapValue(C.nsyms); - SwapValue(C.stroff); - SwapValue(C.strsize); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.symoff); + sys::swapByteOrder(C.nsyms); + sys::swapByteOrder(C.stroff); + sys::swapByteOrder(C.strsize); } template<> void SwapStruct(MachO::dysymtab_command &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.ilocalsym); - SwapValue(C.nlocalsym); - SwapValue(C.iextdefsym); - SwapValue(C.nextdefsym); - SwapValue(C.iundefsym); - SwapValue(C.nundefsym); - SwapValue(C.tocoff); - SwapValue(C.ntoc); - SwapValue(C.modtaboff); - SwapValue(C.nmodtab); - SwapValue(C.extrefsymoff); - SwapValue(C.nextrefsyms); - SwapValue(C.indirectsymoff); - SwapValue(C.nindirectsyms); - SwapValue(C.extreloff); - SwapValue(C.nextrel); - SwapValue(C.locreloff); - SwapValue(C.nlocrel); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.ilocalsym); + sys::swapByteOrder(C.nlocalsym); + sys::swapByteOrder(C.iextdefsym); + sys::swapByteOrder(C.nextdefsym); + sys::swapByteOrder(C.iundefsym); + sys::swapByteOrder(C.nundefsym); + sys::swapByteOrder(C.tocoff); + sys::swapByteOrder(C.ntoc); + sys::swapByteOrder(C.modtaboff); + sys::swapByteOrder(C.nmodtab); + sys::swapByteOrder(C.extrefsymoff); + sys::swapByteOrder(C.nextrefsyms); + sys::swapByteOrder(C.indirectsymoff); + sys::swapByteOrder(C.nindirectsyms); + sys::swapByteOrder(C.extreloff); + sys::swapByteOrder(C.nextrel); + sys::swapByteOrder(C.locreloff); + sys::swapByteOrder(C.nlocrel); } template<> void SwapStruct(MachO::linkedit_data_command &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.dataoff); - SwapValue(C.datasize); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.dataoff); + sys::swapByteOrder(C.datasize); } template<> void SwapStruct(MachO::segment_command &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.vmaddr); - SwapValue(C.vmsize); - SwapValue(C.fileoff); - SwapValue(C.filesize); - SwapValue(C.maxprot); - SwapValue(C.initprot); - SwapValue(C.nsects); - SwapValue(C.flags); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.vmaddr); + sys::swapByteOrder(C.vmsize); + sys::swapByteOrder(C.fileoff); + sys::swapByteOrder(C.filesize); + sys::swapByteOrder(C.maxprot); + sys::swapByteOrder(C.initprot); + sys::swapByteOrder(C.nsects); + sys::swapByteOrder(C.flags); } template<> void SwapStruct(MachO::segment_command_64 &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.vmaddr); - SwapValue(C.vmsize); - SwapValue(C.fileoff); - SwapValue(C.filesize); - SwapValue(C.maxprot); - SwapValue(C.initprot); - SwapValue(C.nsects); - SwapValue(C.flags); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.vmaddr); + sys::swapByteOrder(C.vmsize); + sys::swapByteOrder(C.fileoff); + sys::swapByteOrder(C.filesize); + sys::swapByteOrder(C.maxprot); + sys::swapByteOrder(C.initprot); + sys::swapByteOrder(C.nsects); + sys::swapByteOrder(C.flags); } template<> void SwapStruct(uint32_t &C) { - SwapValue(C); + sys::swapByteOrder(C); } template<> void SwapStruct(MachO::linker_options_command &C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.count); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.count); } template<> void SwapStruct(MachO::version_min_command&C) { - SwapValue(C.cmd); - SwapValue(C.cmdsize); - SwapValue(C.version); - SwapValue(C.reserved); + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.version); + sys::swapByteOrder(C.reserved); +} + +template<> +void SwapStruct(MachO::dylib_command&C) { + sys::swapByteOrder(C.cmd); + sys::swapByteOrder(C.cmdsize); + sys::swapByteOrder(C.dylib.name); + sys::swapByteOrder(C.dylib.timestamp); + sys::swapByteOrder(C.dylib.current_version); + sys::swapByteOrder(C.dylib.compatibility_version); } template<> void SwapStruct(MachO::data_in_code_entry &C) { - SwapValue(C.offset); - SwapValue(C.length); - SwapValue(C.kind); + sys::swapByteOrder(C.offset); + sys::swapByteOrder(C.length); + sys::swapByteOrder(C.kind); } template<typename T> @@ -306,7 +312,7 @@ static void printRelocationTargetName(const MachOObjectFile *O, uint32_t Val = O->getPlainRelocationSymbolNum(RE); for (const SymbolRef &Symbol : O->symbols()) { - error_code ec; + std::error_code ec; uint64_t Addr; StringRef Name; @@ -323,7 +329,7 @@ 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 (const SectionRef &Section : O->sections()) { - error_code ec; + std::error_code ec; uint64_t Addr; StringRef Name; @@ -416,10 +422,10 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, - bool Is64bits, error_code &EC, - bool BufferOwned) - : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object, BufferOwned), +MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, + bool IsLittleEndian, bool Is64bits, + std::error_code &EC) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), DataInCodeLoadCmd(nullptr) { uint32_t LoadCommandCount = this->getHeader().ncmds; @@ -443,6 +449,12 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, const char *Sec = getSectionPtr(this, Load, J); Sections.push_back(Sec); } + } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || + Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || + Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || + Load.C.cmd == MachO::LC_REEXPORT_DYLIB || + Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { + Libraries.push_back(Load.Ptr); } if (I == LoadCommandCount - 1) @@ -459,8 +471,8 @@ void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.p += SymbolTableEntrySize; } -error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Res) const { +std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Res) const { StringRef StringTable = getStringTableData(); nlist_base Entry = getSymbolTableEntryBase(this, Symb); const char *Start = &StringTable.data()[Entry.n_strx]; @@ -468,8 +480,32 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const { +// getIndirectName() returns the name of the alias'ed symbol who's string table +// index is in the n_value field. +std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, + StringRef &Res) const { + StringRef StringTable = getStringTableData(); + uint64_t NValue; + if (is64Bit()) { + MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); + NValue = Entry.n_value; + if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) + return object_error::parse_failed; + } else { + MachO::nlist Entry = getSymbolTableEntry(Symb); + NValue = Entry.n_value; + if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) + return object_error::parse_failed; + } + if (NValue >= StringTable.size()) + return object_error::parse_failed; + const char *Start = &StringTable.data()[NValue]; + Res = StringRef(Start); + return object_error::success; +} + +std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const { if (is64Bit()) { MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && @@ -488,8 +524,8 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, - uint32_t &Result) const { +std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { uint32_t flags = getSymbolFlags(DRI); if (flags & SymbolRef::SF_Common) { nlist_base Entry = getSymbolTableEntryBase(this, DRI); @@ -500,8 +536,8 @@ error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, - uint64_t &Result) const { +std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; @@ -549,8 +585,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { +std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const { nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t n_type = Entry.n_type; @@ -584,6 +620,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) Result |= SymbolRef::SF_Undefined; + if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) + Result |= SymbolRef::SF_Indirect; + if (MachOType & MachO::N_STAB) Result |= SymbolRef::SF_FormatSpecific; @@ -606,9 +645,8 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { return Result; } -error_code -MachOObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { +std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t index = Entry.n_sect; @@ -627,15 +665,15 @@ void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; } -error_code -MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { +std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { ArrayRef<char> Raw = getSectionRawName(Sec); Result = parseSegmentOrSectionName(Raw.data()); return object_error::success; } -error_code -MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const { if (is64Bit()) { MachO::section_64 Sect = getSection64(Sec); Res = Sect.addr; @@ -646,8 +684,8 @@ MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { return object_error::success; } -error_code -MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Res) const { if (is64Bit()) { MachO::section_64 Sect = getSection64(Sec); Res = Sect.size; @@ -659,8 +697,8 @@ MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { return object_error::success; } -error_code -MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { +std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { uint32_t Offset; uint64_t Size; @@ -678,8 +716,8 @@ MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { return object_error::success; } -error_code -MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { +std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { uint32_t Align; if (is64Bit()) { MachO::section_64 Sect = getSection64(Sec); @@ -693,14 +731,15 @@ MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { return object_error::success; } -error_code -MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { +std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, + bool &Res) const { uint32_t Flags = getSectionFlags(this, Sec); Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; return object_error::success; } -error_code MachOObjectFile::isSectionData(DataRefImpl Sec, bool &Result) const { +std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, + bool &Result) const { uint32_t Flags = getSectionFlags(this, Sec); unsigned SectionType = Flags & MachO::SECTION_TYPE; Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && @@ -709,7 +748,8 @@ error_code MachOObjectFile::isSectionData(DataRefImpl Sec, bool &Result) const { return object_error::success; } -error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, bool &Result) const { +std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, + bool &Result) const { uint32_t Flags = getSectionFlags(this, Sec); unsigned SectionType = Flags & MachO::SECTION_TYPE; Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && @@ -718,7 +758,7 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, bool &Result) const { return object_error::success; } -error_code +std::error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { // FIXME: Unimplemented. @@ -726,15 +766,15 @@ MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, return object_error::success; } -error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code -MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { +std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, + bool &Res) const { uint32_t Flags = getSectionFlags(this, Sec); unsigned SectionType = Flags & MachO::SECTION_TYPE; Res = SectionType == MachO::S_ZEROFILL || @@ -742,8 +782,8 @@ MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { return object_error::success; } -error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { // Consider using the code from isSectionText to look for __const sections. // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS // to use section attributes to distinguish code from data. @@ -753,9 +793,9 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, return object_error::success; } -error_code -MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const { +std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { SymbolRef::Type ST; this->getSymbolType(Symb, ST); if (ST == SymbolRef::ST_Unknown) { @@ -803,8 +843,8 @@ void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { ++Rel.d.b; } -error_code -MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { +std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { uint64_t Offset; getRelocationOffset(Rel, Offset); @@ -816,8 +856,8 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { return object_error::success; } -error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { +std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { assert(getHeader().filetype == MachO::MH_OBJECT && "Only implemented for MH_OBJECT"); MachO::any_relocation_info RE = getRelocation(Rel); @@ -828,6 +868,9 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, symbol_iterator MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { MachO::any_relocation_info RE = getRelocation(Rel); + if (isRelocationScattered(RE)) + return symbol_end(); + uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); bool isExtern = getPlainRelocationExternal(RE); if (!isExtern) @@ -843,14 +886,14 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { return symbol_iterator(SymbolRef(Sym, this)); } -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { +std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { MachO::any_relocation_info RE = getRelocation(Rel); Res = getAnyRelocationType(RE); return object_error::success; } -error_code +std::error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { StringRef res; @@ -963,7 +1006,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, return object_error::success; } -error_code +std::error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl<char> &Result) const { MachO::any_relocation_info RE = getRelocation(Rel); @@ -1139,8 +1182,8 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, return object_error::success; } -error_code -MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { +std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, + bool &Result) const { unsigned Arch = getArch(); uint64_t Type; getRelocationType(Rel, Type); @@ -1167,16 +1210,199 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { return object_error::success; } -error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { +std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } -error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { +std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, + StringRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } +// +// guessLibraryShortName() is passed a name of a dynamic library and returns a +// guess on what the short name is. Then name is returned as a substring of the +// StringRef Name passed in. The name of the dynamic library is recognized as +// a framework if it has one of the two following forms: +// Foo.framework/Versions/A/Foo +// Foo.framework/Foo +// Where A and Foo can be any string. And may contain a trailing suffix +// starting with an underbar. If the Name is recognized as a framework then +// isFramework is set to true else it is set to false. If the Name has a +// suffix then Suffix is set to the substring in Name that contains the suffix +// else it is set to a NULL StringRef. +// +// The Name of the dynamic library is recognized as a library name if it has +// one of the two following forms: +// libFoo.A.dylib +// libFoo.dylib +// The library may have a suffix trailing the name Foo of the form: +// libFoo_profile.A.dylib +// libFoo_profile.dylib +// +// The Name of the dynamic library is also recognized as a library name if it +// has the following form: +// Foo.qtx +// +// If the Name of the dynamic library is none of the forms above then a NULL +// StringRef is returned. +// +StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, + bool &isFramework, + StringRef &Suffix) { + StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; + size_t a, b, c, d, Idx; + + isFramework = false; + Suffix = StringRef(); + + // Pull off the last component and make Foo point to it + a = Name.rfind('/'); + if (a == Name.npos || a == 0) + goto guess_library; + Foo = Name.slice(a+1, Name.npos); + + // Look for a suffix starting with a '_' + Idx = Foo.rfind('_'); + if (Idx != Foo.npos && Foo.size() >= 2) { + Suffix = Foo.slice(Idx, Foo.npos); + Foo = Foo.slice(0, Idx); + } + + // First look for the form Foo.framework/Foo + b = Name.rfind('/', a); + if (b == Name.npos) + Idx = 0; + else + Idx = b+1; + F = Name.slice(Idx, Idx + Foo.size()); + DotFramework = Name.slice(Idx + Foo.size(), + Idx + Foo.size() + sizeof(".framework/")-1); + if (F == Foo && DotFramework == ".framework/") { + isFramework = true; + return Foo; + } + + // Next look for the form Foo.framework/Versions/A/Foo + if (b == Name.npos) + goto guess_library; + c = Name.rfind('/', b); + if (c == Name.npos || c == 0) + goto guess_library; + V = Name.slice(c+1, Name.npos); + if (!V.startswith("Versions/")) + goto guess_library; + d = Name.rfind('/', c); + if (d == Name.npos) + Idx = 0; + else + Idx = d+1; + F = Name.slice(Idx, Idx + Foo.size()); + DotFramework = Name.slice(Idx + Foo.size(), + Idx + Foo.size() + sizeof(".framework/")-1); + if (F == Foo && DotFramework == ".framework/") { + isFramework = true; + return Foo; + } + +guess_library: + // pull off the suffix after the "." and make a point to it + a = Name.rfind('.'); + if (a == Name.npos || a == 0) + return StringRef(); + Dylib = Name.slice(a, Name.npos); + if (Dylib != ".dylib") + goto guess_qtx; + + // First pull off the version letter for the form Foo.A.dylib if any. + if (a >= 3) { + Dot = Name.slice(a-2, a-1); + if (Dot == ".") + a = a - 2; + } + + b = Name.rfind('/', a); + if (b == Name.npos) + b = 0; + else + b = b+1; + // ignore any suffix after an underbar like Foo_profile.A.dylib + Idx = Name.find('_', b); + if (Idx != Name.npos && Idx != b) { + Lib = Name.slice(b, Idx); + Suffix = Name.slice(Idx, a); + } + else + Lib = Name.slice(b, a); + // There are incorrect library names of the form: + // libATS.A_profile.dylib so check for these. + if (Lib.size() >= 3) { + Dot = Lib.slice(Lib.size()-2, Lib.size()-1); + if (Dot == ".") + Lib = Lib.slice(0, Lib.size()-2); + } + return Lib; + +guess_qtx: + Qtx = Name.slice(a, Name.npos); + if (Qtx != ".qtx") + return StringRef(); + b = Name.rfind('/', a); + if (b == Name.npos) + Lib = Name.slice(0, a); + else + Lib = Name.slice(b+1, a); + // There are library names of the form: QT.A.qtx so check for these. + if (Lib.size() >= 3) { + Dot = Lib.slice(Lib.size()-2, Lib.size()-1); + if (Dot == ".") + Lib = Lib.slice(0, Lib.size()-2); + } + return Lib; +} + +// getLibraryShortNameByIndex() is used to get the short name of the library +// for an undefined symbol in a linked Mach-O binary that was linked with the +// normal two-level namespace default (that is MH_TWOLEVEL in the header). +// It is passed the index (0 - based) of the library as translated from +// GET_LIBRARY_ORDINAL (1 - based). +std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, + StringRef &Res) { + if (Index >= Libraries.size()) + return object_error::parse_failed; + + MachO::dylib_command D = + getStruct<MachO::dylib_command>(this, Libraries[Index]); + if (D.dylib.name >= D.cmdsize) + return object_error::parse_failed; + + // If the cache of LibrariesShortNames is not built up do that first for + // all the Libraries. + if (LibrariesShortNames.size() == 0) { + for (unsigned i = 0; i < Libraries.size(); i++) { + MachO::dylib_command D = + getStruct<MachO::dylib_command>(this, Libraries[i]); + if (D.dylib.name >= D.cmdsize) { + LibrariesShortNames.push_back(StringRef()); + continue; + } + const char *P = (const char *)(Libraries[i]) + D.dylib.name; + StringRef Name = StringRef(P); + StringRef Suffix; + bool isFramework; + StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); + if (shortName == StringRef()) + LibrariesShortNames.push_back(Name); + else + LibrariesShortNames.push_back(shortName); + } + } + + Res = LibrariesShortNames[Index]; + return object_error::success; +} + basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { return getSymbolByIndex(0); } @@ -1288,6 +1514,108 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { } } +Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { + switch (CPUType) { + case MachO::CPU_TYPE_I386: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_I386_ALL: + return Triple("i386-apple-darwin"); + default: + return Triple(); + } + case MachO::CPU_TYPE_X86_64: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_X86_64_ALL: + return Triple("x86_64-apple-darwin"); + case MachO::CPU_SUBTYPE_X86_64_H: + return Triple("x86_64h-apple-darwin"); + default: + return Triple(); + } + case MachO::CPU_TYPE_ARM: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_ARM_V4T: + return Triple("armv4t-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V5TEJ: + return Triple("armv5e-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V6: + return Triple("armv6-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V6M: + return Triple("armv6m-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7EM: + return Triple("armv7em-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7K: + return Triple("armv7k-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7M: + return Triple("armv7m-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7S: + return Triple("armv7s-apple-darwin"); + default: + return Triple(); + } + case MachO::CPU_TYPE_ARM64: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_ARM64_ALL: + return Triple("arm64-apple-darwin"); + default: + return Triple(); + } + case MachO::CPU_TYPE_POWERPC: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_POWERPC_ALL: + return Triple("ppc-apple-darwin"); + default: + return Triple(); + } + case MachO::CPU_TYPE_POWERPC64: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_POWERPC_ALL: + return Triple("ppc64-apple-darwin"); + default: + return Triple(); + } + default: + return Triple(); + } +} + +Triple MachOObjectFile::getHostArch() { + return Triple(sys::getDefaultTargetTriple()); +} + +Triple MachOObjectFile::getArch(StringRef ArchFlag) { + if (ArchFlag == "i386") + return Triple("i386-apple-darwin"); + else if (ArchFlag == "x86_64") + return Triple("x86_64-apple-darwin"); + else if (ArchFlag == "x86_64h") + return Triple("x86_64h-apple-darwin"); + else if (ArchFlag == "armv4t" || ArchFlag == "arm") + return Triple("armv4t-apple-darwin"); + else if (ArchFlag == "armv5e") + return Triple("armv5e-apple-darwin"); + else if (ArchFlag == "armv6") + return Triple("armv6-apple-darwin"); + else if (ArchFlag == "armv6m") + return Triple("armv6m-apple-darwin"); + else if (ArchFlag == "armv7em") + return Triple("armv7em-apple-darwin"); + else if (ArchFlag == "armv7k") + return Triple("armv7k-apple-darwin"); + else if (ArchFlag == "armv7k") + return Triple("armv7m-apple-darwin"); + else if (ArchFlag == "armv7s") + return Triple("armv7s-apple-darwin"); + else if (ArchFlag == "arm64") + return Triple("arm64-apple-darwin"); + else if (ArchFlag == "ppc") + return Triple("ppc-apple-darwin"); + else if (ArchFlag == "ppc64") + return Triple("ppc64-apple-darwin"); + else + return Triple(); +} + unsigned MachOObjectFile::getArch() const { return getArch(getCPUType(this)); } @@ -1498,6 +1826,12 @@ MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { return getStruct<MachO::version_min_command>(this, L.Ptr); } +MachO::dylib_command +MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { + return getStruct<MachO::dylib_command>(this, L.Ptr); +} + + MachO::any_relocation_info MachOObjectFile::getRelocation(DataRefImpl Rel) const { DataRefImpl Sec; @@ -1574,7 +1908,7 @@ StringRef MachOObjectFile::getStringTableData() const { bool MachOObjectFile::is64Bit() const { return getType() == getMachOType(false, true) || - getType() == getMachOType(true, true); + getType() == getMachOType(true, true); } void MachOObjectFile::ReadULEB128s(uint64_t Index, @@ -1589,23 +1923,25 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -ErrorOr<ObjectFile *> ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer, - bool BufferOwned) { +const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const { + return Sections[Rel.d.a]; +} + +ErrorOr<ObjectFile *> +ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); - error_code EC; + std::error_code EC; std::unique_ptr<MachOObjectFile> Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(Buffer, false, false, EC, BufferOwned)); + Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, false, EC, BufferOwned)); + Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(Buffer, false, true, EC, BufferOwned)); + Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, true, EC, BufferOwned)); - else { - delete Buffer; + Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); + else return object_error::parse_failed; - } if (EC) return EC; diff --git a/lib/Object/MachOUniversal.cpp b/lib/Object/MachOUniversal.cpp index 5085efd..4ba5d96 100644 --- a/lib/Object/MachOUniversal.cpp +++ b/lib/Object/MachOUniversal.cpp @@ -23,26 +23,21 @@ using namespace llvm; using namespace object; template<typename T> -static void SwapValue(T &Value) { - Value = sys::SwapByteOrder(Value); -} - -template<typename T> static void SwapStruct(T &Value); template<> void SwapStruct(MachO::fat_header &H) { - SwapValue(H.magic); - SwapValue(H.nfat_arch); + sys::swapByteOrder(H.magic); + sys::swapByteOrder(H.nfat_arch); } template<> void SwapStruct(MachO::fat_arch &H) { - SwapValue(H.cputype); - SwapValue(H.cpusubtype); - SwapValue(H.offset); - SwapValue(H.size); - SwapValue(H.align); + sys::swapByteOrder(H.cputype); + sys::swapByteOrder(H.cpusubtype); + sys::swapByteOrder(H.offset); + sys::swapByteOrder(H.size); + sys::swapByteOrder(H.align); } template<typename T> @@ -58,7 +53,7 @@ static T getUniversalBinaryStruct(const char *Ptr) { MachOUniversalBinary::ObjectForArch::ObjectForArch( const MachOUniversalBinary *Parent, uint32_t Index) : Parent(Parent), Index(Index) { - if (!Parent || Index > Parent->getNumberOfObjects()) { + if (!Parent || Index >= Parent->getNumberOfObjects()) { clear(); } else { // Parse object header. @@ -72,37 +67,29 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch( } } -error_code MachOUniversalBinary::ObjectForArch::getAsObjectFile( - std::unique_ptr<ObjectFile> &Result) const { +ErrorOr<std::unique_ptr<ObjectFile>> +MachOUniversalBinary::ObjectForArch::getAsObjectFile() const { if (Parent) { StringRef ParentData = Parent->getData(); StringRef ObjectData = ParentData.substr(Header.offset, Header.size); - std::string ObjectName = - Parent->getFileName().str() + ":" + - Triple::getArchTypeName(MachOObjectFile::getArch(Header.cputype)); - MemoryBuffer *ObjBuffer = MemoryBuffer::getMemBuffer( - ObjectData, ObjectName, false); - ErrorOr<ObjectFile *> Obj = ObjectFile::createMachOObjectFile(ObjBuffer); - if (error_code EC = Obj.getError()) - return EC; - Result.reset(Obj.get()); - return object_error::success; + std::string ObjectName = Parent->getFileName().str(); + std::unique_ptr<MemoryBuffer> ObjBuffer( + MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); + return ObjectFile::createMachOObjectFile(ObjBuffer); } return object_error::parse_failed; } -error_code MachOUniversalBinary::ObjectForArch::getAsArchive( +std::error_code MachOUniversalBinary::ObjectForArch::getAsArchive( std::unique_ptr<Archive> &Result) const { if (Parent) { StringRef ParentData = Parent->getData(); StringRef ObjectData = ParentData.substr(Header.offset, Header.size); - std::string ObjectName = - Parent->getFileName().str() + ":" + - Triple::getArchTypeName(MachOObjectFile::getArch(Header.cputype)); - MemoryBuffer *ObjBuffer = MemoryBuffer::getMemBuffer( - ObjectData, ObjectName, false); - ErrorOr<Archive *> Obj = Archive::create(ObjBuffer); - if (error_code EC = Obj.getError()) + std::string ObjectName = Parent->getFileName().str(); + std::unique_ptr<MemoryBuffer> ObjBuffer( + MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); + ErrorOr<Archive *> Obj = Archive::create(std::move(ObjBuffer)); + if (std::error_code EC = Obj.getError()) return EC; Result.reset(Obj.get()); return object_error::success; @@ -113,20 +100,20 @@ error_code MachOUniversalBinary::ObjectForArch::getAsArchive( void MachOUniversalBinary::anchor() { } ErrorOr<MachOUniversalBinary *> -MachOUniversalBinary::create(MemoryBuffer *Source) { - error_code EC; +MachOUniversalBinary::create(std::unique_ptr<MemoryBuffer> Source) { + std::error_code EC; std::unique_ptr<MachOUniversalBinary> Ret( - new MachOUniversalBinary(Source, EC)); + new MachOUniversalBinary(std::move(Source), EC)); if (EC) return EC; return Ret.release(); } -MachOUniversalBinary::MachOUniversalBinary(MemoryBuffer *Source, - error_code &ec) - : Binary(Binary::ID_MachOUniversalBinary, Source), - NumberOfObjects(0) { - if (Source->getBufferSize() < sizeof(MachO::fat_header)) { +MachOUniversalBinary::MachOUniversalBinary(std::unique_ptr<MemoryBuffer> Source, + std::error_code &ec) + : Binary(Binary::ID_MachOUniversalBinary, std::move(Source)), + NumberOfObjects(0) { + if (Data->getBufferSize() < sizeof(MachO::fat_header)) { ec = object_error::invalid_file_type; return; } @@ -155,14 +142,14 @@ static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { } } -error_code MachOUniversalBinary::getObjectForArch( - Triple::ArchType Arch, std::unique_ptr<ObjectFile> &Result) const { +ErrorOr<std::unique_ptr<ObjectFile>> +MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch) const { MachO::CPUType CTM; if (!getCTMForArch(Arch, CTM)) return object_error::arch_not_found; for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) { if (I->getCPUType() == static_cast<uint32_t>(CTM)) - return I->getAsObjectFile(Result); + return I->getAsObjectFile(); } return object_error::arch_not_found; } diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index b0068a8..567d87f 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -59,7 +59,9 @@ wrap(const relocation_iterator *SI) { // ObjectFile creation LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { - ErrorOr<ObjectFile*> ObjOrErr(ObjectFile::createObjectFile(unwrap(MemBuf))); + std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf)); + ErrorOr<ObjectFile *> ObjOrErr(ObjectFile::createObjectFile(Buf)); + Buf.release(); ObjectFile *Obj = ObjOrErr ? ObjOrErr.get() : nullptr; return wrap(Obj); } @@ -89,7 +91,7 @@ void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, LLVMSymbolIteratorRef Sym) { - if (error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect))) + if (std::error_code ec = (*unwrap(Sym))->getSection(*unwrap(Sect))) report_fatal_error(ec.message()); } @@ -115,28 +117,28 @@ void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { // SectionRef accessors const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { StringRef ret; - if (error_code ec = (*unwrap(SI))->getName(ret)) + if (std::error_code ec = (*unwrap(SI))->getName(ret)) report_fatal_error(ec.message()); return ret.data(); } uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { uint64_t ret; - if (error_code ec = (*unwrap(SI))->getSize(ret)) + if (std::error_code ec = (*unwrap(SI))->getSize(ret)) report_fatal_error(ec.message()); return ret; } const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { StringRef ret; - if (error_code ec = (*unwrap(SI))->getContents(ret)) + if (std::error_code ec = (*unwrap(SI))->getContents(ret)) report_fatal_error(ec.message()); return ret.data(); } uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { uint64_t ret; - if (error_code ec = (*unwrap(SI))->getAddress(ret)) + if (std::error_code ec = (*unwrap(SI))->getAddress(ret)) report_fatal_error(ec.message()); return ret; } @@ -144,7 +146,7 @@ uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, LLVMSymbolIteratorRef Sym) { bool ret; - if (error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret)) + if (std::error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret)) report_fatal_error(ec.message()); return ret; } @@ -172,21 +174,21 @@ void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { // SymbolRef accessors const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { StringRef ret; - if (error_code ec = (*unwrap(SI))->getName(ret)) + if (std::error_code ec = (*unwrap(SI))->getName(ret)) report_fatal_error(ec.message()); return ret.data(); } uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { uint64_t ret; - if (error_code ec = (*unwrap(SI))->getAddress(ret)) + if (std::error_code ec = (*unwrap(SI))->getAddress(ret)) report_fatal_error(ec.message()); return ret; } uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { uint64_t ret; - if (error_code ec = (*unwrap(SI))->getSize(ret)) + if (std::error_code ec = (*unwrap(SI))->getSize(ret)) report_fatal_error(ec.message()); return ret; } @@ -194,14 +196,14 @@ uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { // RelocationRef accessors uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI) { uint64_t ret; - if (error_code ec = (*unwrap(RI))->getAddress(ret)) + if (std::error_code ec = (*unwrap(RI))->getAddress(ret)) report_fatal_error(ec.message()); return ret; } uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI) { uint64_t ret; - if (error_code ec = (*unwrap(RI))->getOffset(ret)) + if (std::error_code ec = (*unwrap(RI))->getOffset(ret)) report_fatal_error(ec.message()); return ret; } @@ -213,7 +215,7 @@ LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI) { uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { uint64_t ret; - if (error_code ec = (*unwrap(RI))->getType(ret)) + if (std::error_code ec = (*unwrap(RI))->getType(ret)) report_fatal_error(ec.message()); return ret; } @@ -221,7 +223,7 @@ uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI) { // NOTE: Caller takes ownership of returned string. const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { SmallVector<char, 0> ret; - if (error_code ec = (*unwrap(RI))->getTypeName(ret)) + if (std::error_code ec = (*unwrap(RI))->getTypeName(ret)) report_fatal_error(ec.message()); char *str = static_cast<char*>(malloc(ret.size())); @@ -232,7 +234,7 @@ const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { // NOTE: Caller takes ownership of returned string. const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { SmallVector<char, 0> ret; - if (error_code ec = (*unwrap(RI))->getValueString(ret)) + if (std::error_code ec = (*unwrap(RI))->getValueString(ret)) report_fatal_error(ec.message()); char *str = static_cast<char*>(malloc(ret.size())); diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index d30f0cc..f5488c6 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -16,28 +16,27 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include <system_error> using namespace llvm; using namespace object; void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *Source, - bool BufferOwned) - : SymbolicFile(Type, Source, BufferOwned) {} +ObjectFile::ObjectFile(unsigned int Type, std::unique_ptr<MemoryBuffer> Source) + : SymbolicFile(Type, std::move(Source)) {} -error_code ObjectFile::printSymbolName(raw_ostream &OS, - DataRefImpl Symb) const { +std::error_code ObjectFile::printSymbolName(raw_ostream &OS, + DataRefImpl Symb) const { StringRef Name; - if (error_code EC = getSymbolName(Symb, Name)) + if (std::error_code EC = getSymbolName(Symb, Name)) return EC; OS << Name; return object_error::success; } -error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, - uint32_t &Result) const { +std::error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { Result = 0; return object_error::success; } @@ -46,9 +45,9 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); } -ErrorOr<ObjectFile *> ObjectFile::createObjectFile(MemoryBuffer *Object, - bool BufferOwned, - sys::fs::file_magic Type) { +ErrorOr<ObjectFile *> +ObjectFile::createObjectFile(std::unique_ptr<MemoryBuffer> &Object, + sys::fs::file_magic Type) { if (Type == sys::fs::file_magic::unknown) Type = sys::fs::identify_magic(Object->getBuffer()); @@ -58,14 +57,12 @@ ErrorOr<ObjectFile *> ObjectFile::createObjectFile(MemoryBuffer *Object, 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: - return createELFObjectFile(Object, BufferOwned); + return createELFObjectFile(Object); case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: @@ -76,18 +73,19 @@ ErrorOr<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, BufferOwned); + return createMachOObjectFile(Object); case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return createCOFFObjectFile(Object, BufferOwned); + return createCOFFObjectFile(std::move(Object)); } llvm_unreachable("Unexpected Object File Type"); } ErrorOr<ObjectFile *> ObjectFile::createObjectFile(StringRef ObjectPath) { - std::unique_ptr<MemoryBuffer> File; - if (error_code EC = MemoryBuffer::getFile(ObjectPath, File)) + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFile(ObjectPath); + if (std::error_code EC = FileOrErr.getError()) return EC; - return createObjectFile(File.release()); + return createObjectFile(FileOrErr.get()); } diff --git a/lib/Object/RecordStreamer.cpp b/lib/Object/RecordStreamer.cpp new file mode 100644 index 0000000..081fadd --- /dev/null +++ b/lib/Object/RecordStreamer.cpp @@ -0,0 +1,100 @@ +//===-- RecordStreamer.cpp - Record asm definde and used symbols ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RecordStreamer.h" +#include "llvm/MC/MCSymbol.h" +using namespace llvm; + +void RecordStreamer::markDefined(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Global: + S = DefinedGlobal; + break; + case NeverSeen: + case Defined: + case Used: + S = Defined; + break; + } +} + +void RecordStreamer::markGlobal(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + S = DefinedGlobal; + break; + + case NeverSeen: + case Global: + case Used: + S = Global; + break; + } +} + +void RecordStreamer::markUsed(const MCSymbol &Symbol) { + State &S = Symbols[Symbol.getName()]; + switch (S) { + case DefinedGlobal: + case Defined: + case Global: + break; + + case NeverSeen: + case Used: + S = Used; + break; + } +} + +void RecordStreamer::visitUsedSymbol(const MCSymbol &Sym) { markUsed(Sym); } + +RecordStreamer::const_iterator RecordStreamer::begin() { + return Symbols.begin(); +} + +RecordStreamer::const_iterator RecordStreamer::end() { return Symbols.end(); } + +RecordStreamer::RecordStreamer(MCContext &Context) : MCStreamer(Context) {} + +void RecordStreamer::EmitInstruction(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCStreamer::EmitInstruction(Inst, STI); +} + +void RecordStreamer::EmitLabel(MCSymbol *Symbol) { + MCStreamer::EmitLabel(Symbol); + markDefined(*Symbol); +} + +void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { + markDefined(*Symbol); + MCStreamer::EmitAssignment(Symbol, Value); +} + +bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, + MCSymbolAttr Attribute) { + if (Attribute == MCSA_Global) + markGlobal(*Symbol); + return true; +} + +void RecordStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + markDefined(*Symbol); +} + +void RecordStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) { + markDefined(*Symbol); +} diff --git a/lib/Object/RecordStreamer.h b/lib/Object/RecordStreamer.h new file mode 100644 index 0000000..10e70ef --- /dev/null +++ b/lib/Object/RecordStreamer.h @@ -0,0 +1,42 @@ +//===-- RecordStreamer.h - Record asm defined and used symbols ---*- C++ -*===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_RECORD_STREAMER +#define LLVM_OBJECT_RECORD_STREAMER + +#include "llvm/MC/MCStreamer.h" + +namespace llvm { +class RecordStreamer : public MCStreamer { +public: + enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; + +private: + StringMap<State> Symbols; + void markDefined(const MCSymbol &Symbol); + void markGlobal(const MCSymbol &Symbol); + void markUsed(const MCSymbol &Symbol); + void visitUsedSymbol(const MCSymbol &Sym) override; + +public: + typedef StringMap<State>::const_iterator const_iterator; + const_iterator begin(); + const_iterator end(); + RecordStreamer(MCContext &Context); + void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; + void EmitLabel(MCSymbol *Symbol) override; + void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; + bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; + void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; + void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment) override; +}; +} +#endif diff --git a/lib/Object/StringTableBuilder.cpp b/lib/Object/StringTableBuilder.cpp deleted file mode 100644 index 9152834..0000000 --- a/lib/Object/StringTableBuilder.cpp +++ /dev/null @@ -1,51 +0,0 @@ -//===-- StringTableBuilder.cpp - String table building utility ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Object/StringTableBuilder.h" - -using namespace llvm; - -static bool compareBySuffix(StringRef a, StringRef b) { - size_t sizeA = a.size(); - size_t sizeB = b.size(); - size_t len = std::min(sizeA, sizeB); - for (size_t i = 0; i < len; ++i) { - char ca = a[sizeA - i - 1]; - char cb = b[sizeB - i - 1]; - if (ca != cb) - return ca > cb; - } - return sizeA > sizeB; -} - -void StringTableBuilder::finalize() { - SmallVector<StringRef, 8> Strings; - for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i) - Strings.push_back(i->getKey()); - - std::sort(Strings.begin(), Strings.end(), compareBySuffix); - - // FIXME: Starting with a null byte is ELF specific. Generalize this so we - // can use the class with other object formats. - StringTable += '\x00'; - - StringRef Previous; - for (StringRef s : Strings) { - if (Previous.endswith(s)) { - StringIndexMap[s] = StringTable.size() - 1 - s.size(); - continue; - } - - StringIndexMap[s] = StringTable.size(); - StringTable += s; - StringTable += '\x00'; - Previous = s; - } -} diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp index 495f0b6..30cf1a0 100644 --- a/lib/Object/SymbolicFile.cpp +++ b/lib/Object/SymbolicFile.cpp @@ -19,14 +19,14 @@ using namespace llvm; using namespace object; -SymbolicFile::SymbolicFile(unsigned int Type, MemoryBuffer *Source, - bool BufferOwned) - : Binary(Type, Source, BufferOwned) {} +SymbolicFile::SymbolicFile(unsigned int Type, + std::unique_ptr<MemoryBuffer> Source) + : Binary(Type, std::move(Source)) {} SymbolicFile::~SymbolicFile() {} ErrorOr<SymbolicFile *> -SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned, +SymbolicFile::createSymbolicFile(std::unique_ptr<MemoryBuffer> &Object, sys::fs::file_magic Type, LLVMContext *Context) { if (Type == sys::fs::file_magic::unknown) @@ -35,14 +35,12 @@ SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned, switch (Type) { case sys::fs::file_magic::bitcode: if (Context) - return IRObjectFile::createIRObjectFile(Object, *Context, BufferOwned); + return IRObjectFile::createIRObjectFile(std::move(Object), *Context); // Fallthrough case sys::fs::file_magic::unknown: case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: - if (BufferOwned) - delete Object; return object_error::invalid_file_type; case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: @@ -61,7 +59,7 @@ SymbolicFile::createSymbolicFile(MemoryBuffer *Object, bool BufferOwned, 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); + return ObjectFile::createObjectFile(Object, Type); } llvm_unreachable("Unexpected Binary File Type"); } diff --git a/lib/Object/YAML.cpp b/lib/Object/YAML.cpp deleted file mode 100644 index 61e9da3..0000000 --- a/lib/Object/YAML.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//===- YAML.cpp - YAMLIO utilities for object files -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility classes for handling the YAML representation of -// object files. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/YAML.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Support/raw_ostream.h" -#include <cctype> - -using namespace llvm; -using namespace object::yaml; - -void yaml::ScalarTraits<object::yaml::BinaryRef>::output( - const object::yaml::BinaryRef &Val, void *, llvm::raw_ostream &Out) { - Val.writeAsHex(Out); -} - -StringRef yaml::ScalarTraits<object::yaml::BinaryRef>::input( - StringRef Scalar, void *, object::yaml::BinaryRef &Val) { - if (Scalar.size() % 2 != 0) - return "BinaryRef hex string must contain an even number of nybbles."; - // TODO: Can we improve YAMLIO to permit a more accurate diagnostic here? - // (e.g. a caret pointing to the offending character). - for (unsigned I = 0, N = Scalar.size(); I != N; ++I) - if (!isxdigit(Scalar[I])) - return "BinaryRef hex string must contain only hex digits."; - Val = object::yaml::BinaryRef(Scalar); - return StringRef(); -} - -void BinaryRef::writeAsBinary(raw_ostream &OS) const { - if (!DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (unsigned I = 0, N = Data.size(); I != N; I += 2) { - uint8_t Byte; - StringRef((const char *)&Data[I], 2).getAsInteger(16, Byte); - OS.write(Byte); - } -} - -void BinaryRef::writeAsHex(raw_ostream &OS) const { - if (binary_size() == 0) - return; - if (DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); - return; - } - for (ArrayRef<uint8_t>::iterator I = Data.begin(), E = Data.end(); I != E; - ++I) { - uint8_t Byte = *I; - OS << hexdigit(Byte >> 4); - OS << hexdigit(Byte & 0xf); - } -} |