diff options
Diffstat (limited to 'contrib/llvm/lib/Object')
-rw-r--r-- | contrib/llvm/lib/Object/Archive.cpp | 122 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ArchiveWriter.cpp | 338 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Binary.cpp | 1 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/COFFObjectFile.cpp | 210 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/COFFYAML.cpp | 6 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ELFObjectFile.cpp | 53 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ELFYAML.cpp | 218 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Error.cpp | 7 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/IRObjectFile.cpp | 37 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/MachOObjectFile.cpp | 603 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/MachOUniversal.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/Object.cpp | 13 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/ObjectFile.cpp | 9 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/RecordStreamer.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/RecordStreamer.h | 4 | ||||
-rw-r--r-- | contrib/llvm/lib/Object/SymbolicFile.cpp | 1 |
16 files changed, 963 insertions, 663 deletions
diff --git a/contrib/llvm/lib/Object/Archive.cpp b/contrib/llvm/lib/Object/Archive.cpp index 5aada91..54ed954 100644 --- a/contrib/llvm/lib/Object/Archive.cpp +++ b/contrib/llvm/lib/Object/Archive.cpp @@ -20,6 +20,7 @@ using namespace llvm; using namespace object; +using namespace llvm::support::endian; static const char *const Magic = "!<arch>\n"; static const char *const ThinMagic = "!<thin>\n"; @@ -110,6 +111,10 @@ uint64_t Archive::Child::getSize() const { return Data.size() - StartOfFile; } +uint64_t Archive::Child::getRawSize() const { + return getHeader()->getSize(); +} + Archive::Child Archive::Child::getNext() const { size_t SpaceToSkip = Data.size(); // If it's odd, add 1 to make it even. @@ -125,6 +130,13 @@ Archive::Child Archive::Child::getNext() const { return Child(Parent, NextLoc); } +uint64_t Archive::Child::getChildOffset() const { + const char *a = Parent->Data.getBuffer().data(); + const char *c = Data.data(); + uint64_t offset = c - a; + return offset; +} + ErrorOr<StringRef> Archive::Child::getName() const { StringRef name = getRawName(); // Check if it's a special name. @@ -151,7 +163,7 @@ ErrorOr<StringRef> Archive::Child::getName() const { return object_error::parse_failed; // GNU long file names end with a /. - if (Parent->kind() == K_GNU) { + if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) { StringRef::size_type End = StringRef(addr).find('/'); return StringRef(addr, End); } @@ -212,7 +224,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) child_iterator e = child_end(); if (i == e) { - ec = object_error::success; + ec = std::error_code(); return; } @@ -242,7 +254,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) SymbolTable = i; ++i; FirstRegular = i; - ec = object_error::success; + ec = std::error_code(); return; } @@ -262,8 +274,16 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) return; } - if (Name == "/") { + // MIPS 64-bit ELF archives use a special format of a symbol table. + // This format is marked by `ar_name` field equals to "/SYM64/". + // For detailed description see page 96 in the following document: + // http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf + + bool has64SymTable = false; + if (Name == "/" || Name == "/SYM64/") { SymbolTable = i; + if (Name == "/SYM64/") + has64SymTable = true; ++i; if (i == e) { @@ -274,18 +294,18 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) } if (Name == "//") { - Format = K_GNU; + Format = has64SymTable ? K_MIPS64 : K_GNU; StringTable = i; ++i; FirstRegular = i; - ec = object_error::success; + ec = std::error_code(); return; } if (Name[0] != '/') { - Format = K_GNU; + Format = has64SymTable ? K_MIPS64 : K_GNU; FirstRegular = i; - ec = object_error::success; + ec = std::error_code(); return; } @@ -300,7 +320,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) ++i; if (i == e) { FirstRegular = i; - ec = object_error::success; + ec = std::error_code(); return; } @@ -312,7 +332,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) } FirstRegular = i; - ec = object_error::success; + ec = std::error_code(); } Archive::child_iterator Archive::child_begin(bool SkipInternal) const { @@ -337,11 +357,16 @@ StringRef Archive::Symbol::getName() const { ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const { const char *Buf = Parent->SymbolTable->getBuffer().begin(); - const char *Offsets = Buf + 4; + const char *Offsets = Buf; + if (Parent->kind() == K_MIPS64) + Offsets += sizeof(uint64_t); + else + Offsets += sizeof(uint32_t); uint32_t Offset = 0; if (Parent->kind() == K_GNU) { - Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) - + SymbolIndex); + Offset = read32be(Offsets + SymbolIndex * 4); + } else if (Parent->kind() == K_MIPS64) { + Offset = read64be(Offsets + SymbolIndex * 8); } else if (Parent->kind() == K_BSD) { // 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 @@ -349,36 +374,29 @@ ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const { // 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); + Offset = read32le(Offsets + SymbolIndex * 8 + 4); } else { - uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); - // Skip offsets. - Buf += sizeof(support::ulittle32_t) - + (MemberCount * sizeof(support::ulittle32_t)); - - uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); + uint32_t MemberCount = read32le(Buf); + Buf += MemberCount * 4 + 4; + uint32_t SymbolCount = read32le(Buf); if (SymbolIndex >= SymbolCount) return object_error::parse_failed; // Skip SymbolCount to get to the indices table. - const char *Indices = Buf + sizeof(support::ulittle32_t); + const char *Indices = Buf + 4; // Get the index of the offset in the file member offset table for this // symbol. - uint16_t OffsetIndex = - *(reinterpret_cast<const support::ulittle16_t*>(Indices) - + SymbolIndex); + uint16_t OffsetIndex = read16le(Indices + SymbolIndex * 2); // Subtract 1 since OffsetIndex is 1 based. --OffsetIndex; if (OffsetIndex >= MemberCount) return object_error::parse_failed; - Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets) - + OffsetIndex); + Offset = read32le(Offsets + OffsetIndex * 4); } const char *Loc = Parent->getData().begin() + Offset; @@ -404,8 +422,7 @@ Archive::Symbol Archive::Symbol::getNext() const { // 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); + RanlibCount = read32le(Buf) / 8; // 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. @@ -413,10 +430,8 @@ Archive::Symbol Archive::Symbol::getNext() const { 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)); + CurRanStrx = read32le(Ranlibs + t.SymbolIndex * 8); + NextRanStrx = read32le(Ranlibs + (t.SymbolIndex + 1) * 8); t.StringIndex -= CurRanStrx; t.StringIndex += NextRanStrx; } @@ -436,8 +451,11 @@ Archive::symbol_iterator Archive::symbol_begin() const { const char *buf = SymbolTable->getBuffer().begin(); if (kind() == K_GNU) { uint32_t symbol_count = 0; - symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); + symbol_count = read32be(buf); buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_MIPS64) { + uint64_t symbol_count = read64be(buf); + buf += sizeof(uint64_t) + (symbol_count * (sizeof(uint64_t))); } else if (kind() == K_BSD) { // The __.SYMDEF or "__.SYMDEF SORTED" member starts with a uint32_t // which is the number of bytes of ranlib structs that follow. The ranlib @@ -446,11 +464,10 @@ Archive::symbol_iterator Archive::symbol_begin() const { // 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); + ranlib_count = read32le(buf) / 8; const char *ranlibs = buf + 4; uint32_t ran_strx = 0; - ran_strx = *(reinterpret_cast<const support::ulittle32_t *>(ranlibs)); + ran_strx = read32le(ranlibs); buf += sizeof(uint32_t) + (ranlib_count * (2 * (sizeof(uint32_t)))); // Skip the byte count of the string table. buf += sizeof(uint32_t); @@ -458,9 +475,9 @@ Archive::symbol_iterator Archive::symbol_begin() const { } else { uint32_t member_count = 0; uint32_t symbol_count = 0; - member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + member_count = read32le(buf); buf += 4 + (member_count * 4); // Skip offsets. - symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + symbol_count = read32le(buf); buf += 4 + (symbol_count * 2); // Skip indices. } uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin(); @@ -470,22 +487,21 @@ Archive::symbol_iterator Archive::symbol_begin() const { Archive::symbol_iterator Archive::symbol_end() const { if (!hasSymbolTable()) return symbol_iterator(Symbol(this, 0, 0)); + return symbol_iterator(Symbol(this, getNumberOfSymbols(), 0)); +} +uint32_t Archive::getNumberOfSymbols() const { const char *buf = SymbolTable->getBuffer().begin(); - uint32_t symbol_count = 0; - if (kind() == K_GNU) { - symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); - } else if (kind() == K_BSD) { - 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); - buf += 4 + (member_count * 4); // Skip offsets. - symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); - } - return symbol_iterator( - Symbol(this, symbol_count, 0)); + if (kind() == K_GNU) + return read32be(buf); + if (kind() == K_MIPS64) + return read64be(buf); + if (kind() == K_BSD) + return read32le(buf) / 8; + uint32_t member_count = 0; + member_count = read32le(buf); + buf += 4 + (member_count * 4); // Skip offsets. + return read32le(buf); } Archive::child_iterator Archive::findSym(StringRef name) const { diff --git a/contrib/llvm/lib/Object/ArchiveWriter.cpp b/contrib/llvm/lib/Object/ArchiveWriter.cpp new file mode 100644 index 0000000..00a56d1 --- /dev/null +++ b/contrib/llvm/lib/Object/ArchiveWriter.cpp @@ -0,0 +1,338 @@ +//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the writeArchive function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ArchiveWriter.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/SymbolicFile.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/Errc.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/raw_ostream.h" + +#if !defined(_MSC_VER) && !defined(__MINGW32__) +#include <unistd.h> +#else +#include <io.h> +#endif + +using namespace llvm; + +NewArchiveIterator::NewArchiveIterator() {} + +NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I, + StringRef Name) + : IsNewMember(false), Name(Name), OldI(I) {} + +NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name) + : IsNewMember(true), Name(Name), NewFilename(NewFilename) {} + +StringRef NewArchiveIterator::getName() const { return Name; } + +bool NewArchiveIterator::isNewMember() const { return IsNewMember; } + +object::Archive::child_iterator NewArchiveIterator::getOld() const { + assert(!IsNewMember); + return OldI; +} + +StringRef NewArchiveIterator::getNew() const { + assert(IsNewMember); + return NewFilename; +} + +llvm::ErrorOr<int> +NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const { + assert(IsNewMember); + int NewFD; + if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD)) + return EC; + assert(NewFD != -1); + + if (auto EC = sys::fs::status(NewFD, NewStatus)) + return EC; + + // Opening a directory doesn't make sense. Let it fail. + // Linux cannot open directories with open(2), although + // cygwin and *bsd can. + if (NewStatus.type() == sys::fs::file_type::directory_file) + return make_error_code(errc::is_a_directory); + + return NewFD; +} + +template <typename T> +static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size, + bool MayTruncate = false) { + uint64_t OldPos = OS.tell(); + OS << Data; + unsigned SizeSoFar = OS.tell() - OldPos; + if (Size > SizeSoFar) { + OS.indent(Size - SizeSoFar); + } else if (Size < SizeSoFar) { + assert(MayTruncate && "Data doesn't fit in Size"); + // Some of the data this is used for (like UID) can be larger than the + // space available in the archive format. Truncate in that case. + OS.seek(OldPos + Size); + } +} + +static void print32BE(raw_ostream &Out, uint32_t Val) { + support::endian::Writer<support::big>(Out).write(Val); +} + +static void printRestOfMemberHeader(raw_fd_ostream &Out, + const sys::TimeValue &ModTime, unsigned UID, + unsigned GID, unsigned Perms, + unsigned Size) { + printWithSpacePadding(Out, ModTime.toEpochTime(), 12); + printWithSpacePadding(Out, UID, 6, true); + printWithSpacePadding(Out, GID, 6, true); + printWithSpacePadding(Out, format("%o", Perms), 8); + printWithSpacePadding(Out, Size, 10); + Out << "`\n"; +} + +static void printMemberHeader(raw_fd_ostream &Out, StringRef Name, + const sys::TimeValue &ModTime, unsigned UID, + unsigned GID, unsigned Perms, unsigned Size) { + printWithSpacePadding(Out, Twine(Name) + "/", 16); + printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); +} + +static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset, + const sys::TimeValue &ModTime, unsigned UID, + unsigned GID, unsigned Perms, unsigned Size) { + Out << '/'; + printWithSpacePadding(Out, NameOffset, 15); + printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size); +} + +static void writeStringTable(raw_fd_ostream &Out, + ArrayRef<NewArchiveIterator> Members, + std::vector<unsigned> &StringMapIndexes) { + unsigned StartOffset = 0; + for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), + E = Members.end(); + I != E; ++I) { + StringRef Name = I->getName(); + if (Name.size() < 16) + continue; + if (StartOffset == 0) { + printWithSpacePadding(Out, "//", 58); + Out << "`\n"; + StartOffset = Out.tell(); + } + StringMapIndexes.push_back(Out.tell() - StartOffset); + Out << Name << "/\n"; + } + if (StartOffset == 0) + return; + if (Out.tell() % 2) + Out << '\n'; + int Pos = Out.tell(); + Out.seek(StartOffset - 12); + printWithSpacePadding(Out, Pos - StartOffset, 10); + Out.seek(Pos); +} + +// Returns the offset of the first reference to a member offset. +static ErrorOr<unsigned> +writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members, + ArrayRef<MemoryBufferRef> Buffers, + std::vector<unsigned> &MemberOffsetRefs) { + unsigned StartOffset = 0; + unsigned MemberNum = 0; + std::string NameBuf; + raw_string_ostream NameOS(NameBuf); + unsigned NumSyms = 0; + LLVMContext Context; + for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(), + E = Members.end(); + I != E; ++I, ++MemberNum) { + MemoryBufferRef MemberBuffer = Buffers[MemberNum]; + ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + object::SymbolicFile::createSymbolicFile( + MemberBuffer, sys::fs::file_magic::unknown, &Context); + if (!ObjOrErr) + continue; // FIXME: check only for "not an object file" errors. + object::SymbolicFile &Obj = *ObjOrErr.get(); + + if (!StartOffset) { + printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0); + StartOffset = Out.tell(); + print32BE(Out, 0); + } + + for (const object::BasicSymbolRef &S : Obj.symbols()) { + uint32_t Symflags = S.getFlags(); + if (Symflags & object::SymbolRef::SF_FormatSpecific) + continue; + if (!(Symflags & object::SymbolRef::SF_Global)) + continue; + if (Symflags & object::SymbolRef::SF_Undefined) + continue; + if (auto EC = S.printName(NameOS)) + return EC; + NameOS << '\0'; + ++NumSyms; + MemberOffsetRefs.push_back(MemberNum); + print32BE(Out, 0); + } + } + Out << NameOS.str(); + + if (StartOffset == 0) + return 0; + + if (Out.tell() % 2) + Out << '\0'; + + unsigned Pos = Out.tell(); + Out.seek(StartOffset - 12); + printWithSpacePadding(Out, Pos - StartOffset, 10); + Out.seek(StartOffset); + print32BE(Out, NumSyms); + Out.seek(Pos); + return StartOffset + 4; +} + +std::pair<StringRef, std::error_code> +llvm::writeArchive(StringRef ArcName, + std::vector<NewArchiveIterator> &NewMembers, + bool WriteSymtab) { + SmallString<128> TmpArchive; + int TmpArchiveFD; + if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a", + TmpArchiveFD, TmpArchive)) + return std::make_pair(ArcName, EC); + + tool_output_file Output(TmpArchive, TmpArchiveFD); + raw_fd_ostream &Out = Output.os(); + Out << "!<arch>\n"; + + std::vector<unsigned> MemberOffsetRefs; + + std::vector<std::unique_ptr<MemoryBuffer>> Buffers; + std::vector<MemoryBufferRef> Members; + std::vector<sys::fs::file_status> NewMemberStatus; + + for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) { + NewArchiveIterator &Member = NewMembers[I]; + MemoryBufferRef MemberRef; + + if (Member.isNewMember()) { + StringRef Filename = Member.getNew(); + NewMemberStatus.resize(NewMemberStatus.size() + 1); + sys::fs::file_status &Status = NewMemberStatus.back(); + ErrorOr<int> FD = Member.getFD(Status); + if (auto EC = FD.getError()) + return std::make_pair(Filename, EC); + ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr = + MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(), + false); + if (auto EC = MemberBufferOrErr.getError()) + return std::make_pair(Filename, EC); + if (close(FD.get()) != 0) + return std::make_pair(Filename, + std::error_code(errno, std::generic_category())); + Buffers.push_back(std::move(MemberBufferOrErr.get())); + MemberRef = Buffers.back()->getMemBufferRef(); + } else { + object::Archive::child_iterator OldMember = Member.getOld(); + ErrorOr<MemoryBufferRef> MemberBufferOrErr = + OldMember->getMemoryBufferRef(); + if (auto EC = MemberBufferOrErr.getError()) + return std::make_pair("", EC); + MemberRef = MemberBufferOrErr.get(); + } + Members.push_back(MemberRef); + } + + unsigned MemberReferenceOffset = 0; + if (WriteSymtab) { + ErrorOr<unsigned> MemberReferenceOffsetOrErr = + writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs); + if (auto EC = MemberReferenceOffsetOrErr.getError()) + return std::make_pair(ArcName, EC); + MemberReferenceOffset = MemberReferenceOffsetOrErr.get(); + } + + std::vector<unsigned> StringMapIndexes; + writeStringTable(Out, NewMembers, StringMapIndexes); + + unsigned MemberNum = 0; + unsigned LongNameMemberNum = 0; + unsigned NewMemberNum = 0; + std::vector<unsigned> MemberOffset; + for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(), + E = NewMembers.end(); + I != E; ++I, ++MemberNum) { + + unsigned Pos = Out.tell(); + MemberOffset.push_back(Pos); + + MemoryBufferRef File = Members[MemberNum]; + if (I->isNewMember()) { + StringRef FileName = I->getNew(); + const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum]; + NewMemberNum++; + + StringRef Name = sys::path::filename(FileName); + if (Name.size() < 16) + printMemberHeader(Out, Name, Status.getLastModificationTime(), + Status.getUser(), Status.getGroup(), + Status.permissions(), Status.getSize()); + else + printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], + Status.getLastModificationTime(), Status.getUser(), + Status.getGroup(), Status.permissions(), + Status.getSize()); + } else { + object::Archive::child_iterator OldMember = I->getOld(); + StringRef Name = I->getName(); + + if (Name.size() < 16) + printMemberHeader(Out, Name, OldMember->getLastModified(), + OldMember->getUID(), OldMember->getGID(), + OldMember->getAccessMode(), OldMember->getSize()); + else + printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++], + OldMember->getLastModified(), OldMember->getUID(), + OldMember->getGID(), OldMember->getAccessMode(), + OldMember->getSize()); + } + + Out << File.getBuffer(); + + if (Out.tell() % 2) + Out << '\n'; + } + + if (MemberReferenceOffset) { + Out.seek(MemberReferenceOffset); + for (unsigned MemberNum : MemberOffsetRefs) + print32BE(Out, MemberOffset[MemberNum]); + } + + Output.keep(); + Out.close(); + sys::fs::rename(TmpArchive, ArcName); + return std::make_pair("", std::error_code()); +} diff --git a/contrib/llvm/lib/Object/Binary.cpp b/contrib/llvm/lib/Object/Binary.cpp index c56eeb1..a2b167a 100644 --- a/contrib/llvm/lib/Object/Binary.cpp +++ b/contrib/llvm/lib/Object/Binary.cpp @@ -58,6 +58,7 @@ ErrorOr<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: + case sys::fs::file_magic::macho_kext_bundle: case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: diff --git a/contrib/llvm/lib/Object/COFFObjectFile.cpp b/contrib/llvm/lib/Object/COFFObjectFile.cpp index cde6fdc..e2f559e 100644 --- a/contrib/llvm/lib/Object/COFFObjectFile.cpp +++ b/contrib/llvm/lib/Object/COFFObjectFile.cpp @@ -46,7 +46,7 @@ static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, Addr < uintptr_t(M.getBufferStart())) { return object_error::unexpected_eof; } - return object_error::success; + return std::error_code(); } // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. @@ -59,7 +59,7 @@ static std::error_code getObject(const T *&Obj, MemoryBufferRef M, if (std::error_code EC = checkOffset(M, Addr, Size)) return EC; Obj = reinterpret_cast<const T *>(Addr); - return object_error::success; + return std::error_code(); } // Decode a string table entry in base 64 (//AAAAAA). Expects \arg Str without @@ -156,11 +156,11 @@ std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, if (Symb.isAnyUndefined()) { Result = UnknownAddressOrSize; - return object_error::success; + return std::error_code(); } if (Symb.isCommon()) { Result = UnknownAddressOrSize; - return object_error::success; + return std::error_code(); } int32_t SectionNumber = Symb.getSectionNumber(); if (!COFF::isReservedSectionNumber(SectionNumber)) { @@ -169,11 +169,11 @@ std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, return EC; Result = Section->VirtualAddress + Symb.getValue(); - return object_error::success; + return std::error_code(); } Result = Symb.getValue(); - return object_error::success; + return std::error_code(); } std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, @@ -190,7 +190,9 @@ std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, Result = SymbolRef::ST_Data; } else if (Symb.isFileRecord()) { Result = SymbolRef::ST_File; - } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { + } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG || + Symb.isSectionDefinition()) { + // TODO: perhaps we need a new symbol type ST_Section. Result = SymbolRef::ST_Debug; } else if (!COFF::isReservedSectionNumber(SectionNumber)) { const coff_section *Section = nullptr; @@ -203,7 +205,7 @@ std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) Result = SymbolRef::ST_Data; } - return object_error::success; + return std::error_code(); } uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { @@ -234,65 +236,12 @@ uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { return Result; } -std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, - uint64_t &Result) const { +uint64_t COFFObjectFile::getSymbolSize(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); - if (Symb.isAnyUndefined()) { - Result = UnknownAddressOrSize; - return object_error::success; - } - if (Symb.isCommon()) { - Result = Symb.getValue(); - return object_error::success; - } - - // Let's attempt to get the size of the symbol by looking at the address of - // the symbol after the symbol in question. - uint64_t SymbAddr; - if (std::error_code EC = getSymbolAddress(Ref, SymbAddr)) - return EC; - int32_t SectionNumber = Symb.getSectionNumber(); - if (COFF::isReservedSectionNumber(SectionNumber)) { - // Absolute and debug symbols aren't sorted in any interesting way. - Result = 0; - return object_error::success; - } - const section_iterator SecEnd = section_end(); - uint64_t AfterAddr = UnknownAddressOrSize; - for (const symbol_iterator &SymbI : symbols()) { - section_iterator SecI = SecEnd; - if (std::error_code EC = SymbI->getSection(SecI)) - return EC; - // Check the symbol's section, skip it if it's in the wrong section. - // First, make sure it is in any section. - if (SecI == SecEnd) - continue; - // Second, make sure it is in the same section as the symbol in question. - if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref)) - continue; - uint64_t Addr; - if (std::error_code EC = SymbI->getAddress(Addr)) - return EC; - // We want to compare our symbol in question with the closest possible - // symbol that comes after. - if (AfterAddr > Addr && Addr > SymbAddr) - AfterAddr = Addr; - } - if (AfterAddr == UnknownAddressOrSize) { - // No symbol comes after this one, assume that everything after our symbol - // is part of it. - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(SectionNumber, Section)) - return EC; - Result = Section->SizeOfRawData - Symb.getValue(); - } else { - // Take the difference between our symbol and the symbol that comes after - // our symbol. - Result = AfterAddr - SymbAddr; - } - - return object_error::success; + if (Symb.isCommon()) + return Symb.getValue(); + return UnknownAddressOrSize; } std::error_code @@ -309,7 +258,7 @@ COFFObjectFile::getSymbolSection(DataRefImpl Ref, Ref.p = reinterpret_cast<uintptr_t>(Sec); Result = section_iterator(SectionRef(Ref, this)); } - return object_error::success; + return std::error_code(); } void COFFObjectFile::moveSectionNext(DataRefImpl &Ref) const { @@ -359,12 +308,17 @@ bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + const uint32_t BssFlags = COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ | + COFF::IMAGE_SCN_MEM_WRITE; + return (Sec->Characteristics & BssFlags) == BssFlags; } bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + // In COFF, a virtual section won't have any in-file + // content, so the file pointer to the content will be zero. + return Sec->PointerToRawData == 0; } bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, @@ -463,7 +417,7 @@ std::error_code COFFObjectFile::initSymbolTablePtr() { // Check that the string table is null terminated if has any in it. if (StringTableSize > 4 && StringTable[StringTableSize - 1] != 0) return object_error::parse_failed; - return object_error::success; + return std::error_code(); } // Returns the file offset for the given VA. @@ -484,7 +438,7 @@ std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { if (SectionStart <= Addr && Addr < SectionEnd) { uint32_t Offset = Addr - SectionStart; Res = uintptr_t(base()) + Section->PointerToRawData + Offset; - return object_error::success; + return std::error_code(); } } return object_error::parse_failed; @@ -500,7 +454,7 @@ std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, const uint8_t *Ptr = reinterpret_cast<const uint8_t *>(IntPtr); Hint = *reinterpret_cast<const ulittle16_t *>(Ptr); Name = StringRef(reinterpret_cast<const char *>(Ptr + 2)); - return object_error::success; + return std::error_code(); } // Find the import table. @@ -509,11 +463,11 @@ std::error_code COFFObjectFile::initImportTablePtr() { // the import table, do nothing. const data_directory *DataEntry; if (getDataDirectory(COFF::IMPORT_TABLE, DataEntry)) - return object_error::success; + return std::error_code(); // Do nothing if the pointer to import table is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return object_error::success; + return std::error_code(); uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; // -1 because the last entry is the null entry. @@ -527,16 +481,16 @@ std::error_code COFFObjectFile::initImportTablePtr() { return EC; ImportDirectory = reinterpret_cast< const import_directory_table_entry *>(IntPtr); - return object_error::success; + return std::error_code(); } // Initializes DelayImportDirectory and NumberOfDelayImportDirectory. std::error_code COFFObjectFile::initDelayImportTablePtr() { const data_directory *DataEntry; if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) - return object_error::success; + return std::error_code(); if (DataEntry->RelativeVirtualAddress == 0) - return object_error::success; + return std::error_code(); uint32_t RVA = DataEntry->RelativeVirtualAddress; NumberOfDelayImportDirectory = DataEntry->Size / @@ -547,7 +501,7 @@ std::error_code COFFObjectFile::initDelayImportTablePtr() { return EC; DelayImportDirectory = reinterpret_cast< const delay_import_directory_table_entry *>(IntPtr); - return object_error::success; + return std::error_code(); } // Find the export table. @@ -556,11 +510,11 @@ std::error_code COFFObjectFile::initExportTablePtr() { // the export table, do nothing. const data_directory *DataEntry; if (getDataDirectory(COFF::EXPORT_TABLE, DataEntry)) - return object_error::success; + return std::error_code(); // Do nothing if the pointer to export table is NULL. if (DataEntry->RelativeVirtualAddress == 0) - return object_error::success; + return std::error_code(); uint32_t ExportTableRva = DataEntry->RelativeVirtualAddress; uintptr_t IntPtr = 0; @@ -568,15 +522,15 @@ std::error_code COFFObjectFile::initExportTablePtr() { return EC; ExportDirectory = reinterpret_cast<const export_directory_table_entry *>(IntPtr); - return object_error::success; + return std::error_code(); } std::error_code COFFObjectFile::initBaseRelocPtr() { const data_directory *DataEntry; if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) - return object_error::success; + return std::error_code(); if (DataEntry->RelativeVirtualAddress == 0) - return object_error::success; + return std::error_code(); uintptr_t IntPtr = 0; if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) @@ -585,7 +539,7 @@ std::error_code COFFObjectFile::initBaseRelocPtr() { IntPtr); BaseRelocEnd = reinterpret_cast<coff_base_reloc_block_header *>( IntPtr + DataEntry->Size); - return object_error::success; + return std::error_code(); } COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) @@ -650,7 +604,7 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if (COFFHeader) { // The prior checkSize call may have failed. This isn't a hard error // because we were just trying to sniff out bigobj. - EC = object_error::success; + EC = std::error_code(); CurPtr += sizeof(coff_file_header); if (COFFHeader->isImportLibrary()) @@ -712,7 +666,7 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if ((EC = initBaseRelocPtr())) return; - EC = object_error::success; + EC = std::error_code(); } basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { @@ -838,13 +792,13 @@ iterator_range<base_reloc_iterator> COFFObjectFile::base_relocs() const { std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { Res = PE32Header; - return object_error::success; + return std::error_code(); } std::error_code COFFObjectFile::getPE32PlusHeader(const pe32plus_header *&Res) const { Res = PE32PlusHeader; - return object_error::success; + return std::error_code(); } std::error_code @@ -863,18 +817,18 @@ COFFObjectFile::getDataDirectory(uint32_t Index, return object_error::parse_failed; } Res = &DataDirectory[Index]; - return object_error::success; + return std::error_code(); } std::error_code COFFObjectFile::getSection(int32_t Index, const coff_section *&Result) const { Result = nullptr; if (COFF::isReservedSectionNumber(Index)) - return object_error::success; + return std::error_code(); if (static_cast<uint32_t>(Index) <= getNumberOfSections()) { // We already verified the section table data, so no need to check again. Result = SectionTable + (Index - 1); - return object_error::success; + return std::error_code(); } return object_error::parse_failed; } @@ -887,7 +841,7 @@ std::error_code COFFObjectFile::getString(uint32_t Offset, if (Offset >= StringTableSize) return object_error::unexpected_eof; Result = StringRef(StringTable + Offset); - return object_error::success; + return std::error_code(); } std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, @@ -897,7 +851,7 @@ std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, uint32_t Offset = Symbol.getStringTableOffset().Offset; if (std::error_code EC = getString(Offset, Res)) return EC; - return object_error::success; + return std::error_code(); } if (Symbol.getShortName()[COFF::NameSize - 1] == 0) @@ -906,7 +860,7 @@ std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, else // Not null terminated, use all 8 bytes. Res = StringRef(Symbol.getShortName(), COFF::NameSize); - return object_error::success; + return std::error_code(); } ArrayRef<uint8_t> @@ -957,7 +911,7 @@ std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, } Res = Name; - return object_error::success; + return std::error_code(); } uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { @@ -995,7 +949,7 @@ COFFObjectFile::getSectionContents(const coff_section *Sec, if (checkOffset(Data, ConStart, SectionSize)) return object_error::parse_failed; Res = makeArrayRef(reinterpret_cast<const uint8_t *>(ConStart), SectionSize); - return object_error::success; + return std::error_code(); } const coff_relocation *COFFObjectFile::toRel(DataRefImpl Rel) const { @@ -1020,7 +974,7 @@ std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, getObject(VirtualAddressPtr, Data, &R->VirtualAddress)) return EC; Res = *VirtualAddressPtr; - return object_error::success; + return std::error_code(); } symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { @@ -1041,7 +995,7 @@ std::error_code COFFObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const coff_relocation* R = toRel(Rel); Res = R->Type; - return object_error::success; + return std::error_code(); } const coff_section * @@ -1142,27 +1096,11 @@ COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, Res = "Unknown"; } Result.append(Res.begin(), Res.end()); - return object_error::success; + return std::error_code(); } #undef LLVM_COFF_SWITCH_RELOC_TYPE_NAME -std::error_code -COFFObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { - const coff_relocation *Reloc = toRel(Rel); - DataRefImpl Sym; - ErrorOr<COFFSymbolRef> Symb = getSymbol(Reloc->SymbolTableIndex); - if (std::error_code EC = Symb.getError()) - return EC; - Sym.p = reinterpret_cast<uintptr_t>(Symb->getRawPtr()); - StringRef SymName; - if (std::error_code EC = getSymbolName(Sym, SymName)) - return EC; - Result.append(SymName.begin(), SymName.end()); - return object_error::success; -} - bool COFFObjectFile::isRelocatableObject() const { return !DataDirectory; } @@ -1179,7 +1117,7 @@ void ImportDirectoryEntryRef::moveNext() { std::error_code ImportDirectoryEntryRef::getImportTableEntry( const import_directory_table_entry *&Result) const { Result = ImportTable + Index; - return object_error::success; + return std::error_code(); } static imported_symbol_iterator @@ -1241,19 +1179,19 @@ std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return object_error::success; + return std::error_code(); } std::error_code ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { Result = ImportTable[Index].ImportLookupTableRVA; - return object_error::success; + return std::error_code(); } std::error_code ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { Result = ImportTable[Index].ImportAddressTableRVA; - return object_error::success; + return std::error_code(); } std::error_code ImportDirectoryEntryRef::getImportLookupEntry( @@ -1263,7 +1201,7 @@ std::error_code ImportDirectoryEntryRef::getImportLookupEntry( if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); - return object_error::success; + return std::error_code(); } bool DelayImportDirectoryEntryRef:: @@ -1297,13 +1235,13 @@ std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return object_error::success; + return std::error_code(); } std::error_code DelayImportDirectoryEntryRef:: getDelayImportTable(const delay_import_directory_table_entry *&Result) const { Result = Table; - return object_error::success; + return std::error_code(); } std::error_code DelayImportDirectoryEntryRef:: @@ -1317,7 +1255,7 @@ getImportAddress(int AddrIndex, uint64_t &Result) const { Result = *reinterpret_cast<const ulittle64_t *>(IntPtr); else Result = *reinterpret_cast<const ulittle32_t *>(IntPtr); - return object_error::success; + return std::error_code(); } bool ExportDirectoryEntryRef:: @@ -1337,20 +1275,20 @@ std::error_code ExportDirectoryEntryRef::getDllName(StringRef &Result) const { OwningObject->getRvaPtr(ExportTable->NameRVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return object_error::success; + return std::error_code(); } // Returns the starting ordinal number. std::error_code ExportDirectoryEntryRef::getOrdinalBase(uint32_t &Result) const { Result = ExportTable->OrdinalBase; - return object_error::success; + return std::error_code(); } // Returns the export ordinal of the current export symbol. std::error_code ExportDirectoryEntryRef::getOrdinal(uint32_t &Result) const { Result = ExportTable->OrdinalBase + Index; - return object_error::success; + return std::error_code(); } // Returns the address of the current export symbol. @@ -1362,7 +1300,7 @@ std::error_code ExportDirectoryEntryRef::getExportRVA(uint32_t &Result) const { const export_address_table_entry *entry = reinterpret_cast<const export_address_table_entry *>(IntPtr); Result = entry[Index].ExportRVA; - return object_error::success; + return std::error_code(); } // Returns the name of the current export symbol. If the symbol is exported only @@ -1388,10 +1326,10 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { if (std::error_code EC = OwningObject->getRvaPtr(NamePtr[Offset], IntPtr)) return EC; Result = StringRef(reinterpret_cast<const char *>(IntPtr)); - return object_error::success; + return std::error_code(); } Result = ""; - return object_error::success; + return std::error_code(); } bool ImportedSymbolRef:: @@ -1410,11 +1348,11 @@ ImportedSymbolRef::getSymbolName(StringRef &Result) const { if (Entry32) { // If a symbol is imported only by ordinal, it has no name. if (Entry32[Index].isOrdinal()) - return object_error::success; + return std::error_code(); RVA = Entry32[Index].getHintNameRVA(); } else { if (Entry64[Index].isOrdinal()) - return object_error::success; + return std::error_code(); RVA = Entry64[Index].getHintNameRVA(); } uintptr_t IntPtr = 0; @@ -1422,7 +1360,7 @@ ImportedSymbolRef::getSymbolName(StringRef &Result) const { return EC; // +2 because the first two bytes is hint. Result = StringRef(reinterpret_cast<const char *>(IntPtr + 2)); - return object_error::success; + return std::error_code(); } std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { @@ -1430,13 +1368,13 @@ std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { if (Entry32) { if (Entry32[Index].isOrdinal()) { Result = Entry32[Index].getOrdinal(); - return object_error::success; + return std::error_code(); } RVA = Entry32[Index].getHintNameRVA(); } else { if (Entry64[Index].isOrdinal()) { Result = Entry64[Index].getOrdinal(); - return object_error::success; + return std::error_code(); } RVA = Entry64[Index].getHintNameRVA(); } @@ -1444,7 +1382,7 @@ std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; Result = *reinterpret_cast<const ulittle16_t *>(IntPtr); - return object_error::success; + return std::error_code(); } ErrorOr<std::unique_ptr<COFFObjectFile>> @@ -1481,11 +1419,11 @@ void BaseRelocRef::moveNext() { std::error_code BaseRelocRef::getType(uint8_t &Type) const { auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); Type = Entry[Index].getType(); - return object_error::success; + return std::error_code(); } std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { auto *Entry = reinterpret_cast<const coff_base_reloc_block_entry *>(Header + 1); Result = Header->PageRVA + Entry[Index].getOffset(); - return object_error::success; + return std::error_code(); } diff --git a/contrib/llvm/lib/Object/COFFYAML.cpp b/contrib/llvm/lib/Object/COFFYAML.cpp index 9a24b53..dda4b7f 100644 --- a/contrib/llvm/lib/Object/COFFYAML.cpp +++ b/contrib/llvm/lib/Object/COFFYAML.cpp @@ -335,7 +335,7 @@ struct NDLLCharacteristics { COFF::DLLCharacteristics Characteristics; }; -} +} // namespace void MappingTraits<COFFYAML::Relocation>::mapping(IO &IO, COFFYAML::Relocation &Rel) { @@ -497,5 +497,5 @@ void MappingTraits<COFFYAML::Object>::mapping(IO &IO, COFFYAML::Object &Obj) { IO.mapRequired("symbols", Obj.Symbols); } -} -} +} // namespace yaml +} // namespace llvm diff --git a/contrib/llvm/lib/Object/ELFObjectFile.cpp b/contrib/llvm/lib/Object/ELFObjectFile.cpp index 8ccb253..c7df30a 100644 --- a/contrib/llvm/lib/Object/ELFObjectFile.cpp +++ b/contrib/llvm/lib/Object/ELFObjectFile.cpp @@ -27,51 +27,28 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { std::size_t MaxAlignment = 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); + if (MaxAlignment < 2) + return object_error::parse_failed; + 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)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::little, 2, false>>(Obj, EC)); - else - 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)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::big, 2, false>>(Obj, EC)); + if (Ident.first == ELF::ELFCLASS32) { + if (Ident.second == ELF::ELFDATA2LSB) + R.reset(new ELFObjectFile<ELFType<support::little, false>>(Obj, EC)); + else if (Ident.second == ELF::ELFDATA2MSB) + R.reset(new ELFObjectFile<ELFType<support::big, false>>(Obj, EC)); else 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)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::big, 2, true>>(Obj, EC)); - else - 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)); - else -#endif - if (MaxAlignment >= 2) - R.reset(new ELFObjectFile<ELFType<support::little, 2, true>>(Obj, EC)); + } else if (Ident.first == ELF::ELFCLASS64) { + if (Ident.second == ELF::ELFDATA2LSB) + R.reset(new ELFObjectFile<ELFType<support::little, true>>(Obj, EC)); + else if (Ident.second == ELF::ELFDATA2MSB) + R.reset(new ELFObjectFile<ELFType<support::big, true>>(Obj, EC)); else return object_error::parse_failed; + } else { + return object_error::parse_failed; } - else - llvm_unreachable("Buffer is not an ELF object file!"); if (EC) return EC; diff --git a/contrib/llvm/lib/Object/ELFYAML.cpp b/contrib/llvm/lib/Object/ELFYAML.cpp index 7e35fb5..50730a9 100644 --- a/contrib/llvm/lib/Object/ELFYAML.cpp +++ b/contrib/llvm/lib/Object/ELFYAML.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/ELFYAML.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/MipsABIFlags.h" namespace llvm { @@ -30,6 +31,7 @@ ScalarEnumerationTraits<ELFYAML::ELF_ET>::enumeration(IO &IO, ECase(ET_DYN) ECase(ET_CORE) #undef ECase + IO.enumFallback<Hex16>(Value); } void @@ -42,7 +44,7 @@ ScalarEnumerationTraits<ELFYAML::ELF_EM>::enumeration(IO &IO, ECase(EM_386) ECase(EM_68K) ECase(EM_88K) - ECase(EM_486) + ECase(EM_IAMCU) ECase(EM_860) ECase(EM_MIPS) ECase(EM_S370) @@ -234,6 +236,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( ECase(ELFOSABI_NSK) ECase(ELFOSABI_AROS) ECase(ELFOSABI_FENIXOS) + ECase(ELFOSABI_CLOUDABI) ECase(ELFOSABI_C6000_ELFABI) ECase(ELFOSABI_C6000_LINUX) ECase(ELFOSABI_ARM) @@ -264,10 +267,33 @@ void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, BCase(EF_MIPS_CPIC) BCase(EF_MIPS_ABI2) BCase(EF_MIPS_32BITMODE) + BCase(EF_MIPS_FP64) BCase(EF_MIPS_NAN2008) - BCase(EF_MIPS_ABI_O32) BCase(EF_MIPS_MICROMIPS) BCase(EF_MIPS_ARCH_ASE_M16) + BCase(EF_MIPS_ARCH_ASE_MDMX) + BCaseMask(EF_MIPS_ABI_O32, EF_MIPS_ABI) + BCaseMask(EF_MIPS_ABI_O64, EF_MIPS_ABI) + BCaseMask(EF_MIPS_ABI_EABI32, EF_MIPS_ABI) + BCaseMask(EF_MIPS_ABI_EABI64, EF_MIPS_ABI) + BCaseMask(EF_MIPS_MACH_3900, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_4010, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_4100, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_4650, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_4120, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_4111, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_SB1, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_OCTEON, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_XLR, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_OCTEON2, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_OCTEON3, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_5400, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_5900, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_5500, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_9000, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_LS2E, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_LS2F, EF_MIPS_MACH) + BCaseMask(EF_MIPS_MACH_LS3A, EF_MIPS_MACH) BCaseMask(EF_MIPS_ARCH_1, EF_MIPS_ARCH) BCaseMask(EF_MIPS_ARCH_2, EF_MIPS_ARCH) BCaseMask(EF_MIPS_ARCH_3, EF_MIPS_ARCH) @@ -414,6 +440,16 @@ void ScalarBitSetTraits<ELFYAML::ELF_STO>::bitset(IO &IO, #undef BCaseMask } +void ScalarEnumerationTraits<ELFYAML::ELF_RSS>::enumeration( + IO &IO, ELFYAML::ELF_RSS &Value) { +#define ECase(X) IO.enumCase(Value, #X, ELF::X); + ECase(RSS_UNDEF) + ECase(RSS_GP) + ECase(RSS_GP0) + ECase(RSS_LOC) +#undef ECase +} + void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( IO &IO, ELFYAML::ELF_REL &Value) { const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); @@ -444,6 +480,93 @@ void ScalarEnumerationTraits<ELFYAML::ELF_REL>::enumeration( #undef ELF_RELOC } +void ScalarEnumerationTraits<ELFYAML::MIPS_AFL_REG>::enumeration( + IO &IO, ELFYAML::MIPS_AFL_REG &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); + ECase(REG_NONE) + ECase(REG_32) + ECase(REG_64) + ECase(REG_128) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::MIPS_ABI_FP>::enumeration( + IO &IO, ELFYAML::MIPS_ABI_FP &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::Val_GNU_MIPS_ABI_##X); + ECase(FP_ANY) + ECase(FP_DOUBLE) + ECase(FP_SINGLE) + ECase(FP_SOFT) + ECase(FP_OLD_64) + ECase(FP_XX) + ECase(FP_64) + ECase(FP_64A) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::MIPS_AFL_EXT>::enumeration( + IO &IO, ELFYAML::MIPS_AFL_EXT &Value) { +#define ECase(X) IO.enumCase(Value, #X, Mips::AFL_##X); + ECase(EXT_NONE) + ECase(EXT_XLR) + ECase(EXT_OCTEON2) + ECase(EXT_OCTEONP) + ECase(EXT_LOONGSON_3A) + ECase(EXT_OCTEON) + ECase(EXT_5900) + ECase(EXT_4650) + ECase(EXT_4010) + ECase(EXT_4100) + ECase(EXT_3900) + ECase(EXT_10000) + ECase(EXT_SB1) + ECase(EXT_4111) + ECase(EXT_4120) + ECase(EXT_5400) + ECase(EXT_5500) + ECase(EXT_LOONGSON_2E) + ECase(EXT_LOONGSON_2F) + ECase(EXT_OCTEON3) +#undef ECase +} + +void ScalarEnumerationTraits<ELFYAML::MIPS_ISA>::enumeration( + IO &IO, ELFYAML::MIPS_ISA &Value) { + IO.enumCase(Value, "MIPS1", 1); + IO.enumCase(Value, "MIPS2", 2); + IO.enumCase(Value, "MIPS3", 3); + IO.enumCase(Value, "MIPS4", 4); + IO.enumCase(Value, "MIPS5", 5); + IO.enumCase(Value, "MIPS32", 32); + IO.enumCase(Value, "MIPS64", 64); +} + +void ScalarBitSetTraits<ELFYAML::MIPS_AFL_ASE>::bitset( + IO &IO, ELFYAML::MIPS_AFL_ASE &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_ASE_##X); + BCase(DSP) + BCase(DSPR2) + BCase(EVA) + BCase(MCU) + BCase(MDMX) + BCase(MIPS3D) + BCase(MT) + BCase(SMARTMIPS) + BCase(VIRT) + BCase(MSA) + BCase(MIPS16) + BCase(MICROMIPS) + BCase(XPA) +#undef BCase +} + +void ScalarBitSetTraits<ELFYAML::MIPS_AFL_FLAGS1>::bitset( + IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value) { +#define BCase(X) IO.bitSetCase(Value, #X, Mips::AFL_FLAGS1_##X); + BCase(ODDSPREG) +#undef BCase +} + void MappingTraits<ELFYAML::FileHeader>::mapping(IO &IO, ELFYAML::FileHeader &FileHdr) { IO.mapRequired("Class", FileHdr.Class); @@ -467,7 +590,7 @@ struct NormalizedOther { ELFYAML::ELF_STV Visibility; ELFYAML::ELF_STO Other; }; -} +} // namespace void MappingTraits<ELFYAML::Symbol>::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); @@ -495,6 +618,7 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { IO.mapOptional("Address", Section.Address, Hex64(0)); IO.mapOptional("Link", Section.Link, StringRef()); IO.mapOptional("AddressAlign", Section.AddressAlign, Hex64(0)); + IO.mapOptional("Info", Section.Info, StringRef()); } static void sectionMapping(IO &IO, ELFYAML::RawContentSection &Section) { @@ -505,10 +629,39 @@ 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); } +static void groupSectionMapping(IO &IO, ELFYAML::Group &group) { + commonSectionMapping(IO, group); + IO.mapRequired("Members", group.Members); +} + +void MappingTraits<ELFYAML::SectionOrType>::mapping( + IO &IO, ELFYAML::SectionOrType §ionOrType) { + IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); +} + +static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Version", Section.Version, Hex16(0)); + IO.mapRequired("ISA", Section.ISALevel); + IO.mapOptional("ISARevision", Section.ISARevision, Hex8(0)); + IO.mapOptional("ISAExtension", Section.ISAExtension, + ELFYAML::MIPS_AFL_EXT(Mips::AFL_EXT_NONE)); + IO.mapOptional("ASEs", Section.ASEs, ELFYAML::MIPS_AFL_ASE(0)); + IO.mapOptional("FpABI", Section.FpABI, + ELFYAML::MIPS_ABI_FP(Mips::Val_GNU_MIPS_ABI_FP_ANY)); + IO.mapOptional("GPRSize", Section.GPRSize, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("CPR1Size", Section.CPR1Size, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("CPR2Size", Section.CPR2Size, + ELFYAML::MIPS_AFL_REG(Mips::AFL_REG_NONE)); + IO.mapOptional("Flags1", Section.Flags1, ELFYAML::MIPS_AFL_FLAGS1(0)); + IO.mapOptional("Flags2", Section.Flags2, Hex32(0)); +} + void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( IO &IO, std::unique_ptr<ELFYAML::Section> &Section) { ELFYAML::ELF_SHT sectionType; @@ -524,6 +677,16 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::RelocationSection()); sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get())); break; + case ELF::SHT_GROUP: + if (!IO.outputting()) + Section.reset(new ELFYAML::Group()); + groupSectionMapping(IO, *cast<ELFYAML::Group>(Section.get())); + break; + case ELF::SHT_MIPS_ABIFLAGS: + if (!IO.outputting()) + Section.reset(new ELFYAML::MipsABIFlags()); + sectionMapping(IO, *cast<ELFYAML::MipsABIFlags>(Section.get())); + break; default: if (!IO.outputting()) Section.reset(new ELFYAML::RawContentSection()); @@ -539,12 +702,49 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return "Section size must be greater or equal to the content size"; } +namespace { +struct NormalizedMips64RelType { + NormalizedMips64RelType(IO &) + : Type(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + Type2(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + Type3(ELFYAML::ELF_REL(ELF::R_MIPS_NONE)), + SpecSym(ELFYAML::ELF_REL(ELF::RSS_UNDEF)) {} + NormalizedMips64RelType(IO &, ELFYAML::ELF_REL Original) + : Type(Original & 0xFF), Type2(Original >> 8 & 0xFF), + Type3(Original >> 16 & 0xFF), SpecSym(Original >> 24 & 0xFF) {} + + ELFYAML::ELF_REL denormalize(IO &) { + ELFYAML::ELF_REL Res = Type | Type2 << 8 | Type3 << 16 | SpecSym << 24; + return Res; + } + + ELFYAML::ELF_REL Type; + ELFYAML::ELF_REL Type2; + ELFYAML::ELF_REL Type3; + ELFYAML::ELF_RSS SpecSym; +}; +} // namespace + void MappingTraits<ELFYAML::Relocation>::mapping(IO &IO, ELFYAML::Relocation &Rel) { + const auto *Object = static_cast<ELFYAML::Object *>(IO.getContext()); + assert(Object && "The IO context is not initialized"); + IO.mapRequired("Offset", Rel.Offset); IO.mapRequired("Symbol", Rel.Symbol); - IO.mapRequired("Type", Rel.Type); - IO.mapOptional("Addend", Rel.Addend); + + if (Object->Header.Machine == ELFYAML::ELF_EM(ELF::EM_MIPS) && + Object->Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64)) { + MappingNormalization<NormalizedMips64RelType, ELFYAML::ELF_REL> Key( + IO, Rel.Type); + IO.mapRequired("Type", Key->Type); + IO.mapOptional("Type2", Key->Type2, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); + IO.mapOptional("Type3", Key->Type3, ELFYAML::ELF_REL(ELF::R_MIPS_NONE)); + IO.mapOptional("SpecSym", Key->SpecSym, ELFYAML::ELF_RSS(ELF::RSS_UNDEF)); + } else + IO.mapRequired("Type", Rel.Type); + + IO.mapOptional("Addend", Rel.Addend, (int64_t)0); } void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { @@ -556,5 +756,11 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { IO.setContext(nullptr); } +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) + } // end namespace yaml } // end namespace llvm diff --git a/contrib/llvm/lib/Object/Error.cpp b/contrib/llvm/lib/Object/Error.cpp index d2daab7..644a178 100644 --- a/contrib/llvm/lib/Object/Error.cpp +++ b/contrib/llvm/lib/Object/Error.cpp @@ -33,7 +33,6 @@ const char *_object_error_category::name() const LLVM_NOEXCEPT { 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: return "No object file for requested architecture"; case object_error::invalid_file_type: @@ -44,6 +43,12 @@ std::string _object_error_category::message(int EV) const { return "The end of the file was unexpectedly encountered"; case object_error::bitcode_section_not_found: return "Bitcode section not found in object file"; + case object_error::macho_small_load_command: + return "Mach-O load command with size < 8 bytes"; + case object_error::macho_load_segment_too_many_sections: + return "Mach-O segment load command contains too many sections"; + case object_error::macho_load_segment_too_small: + return "Mach-O segment load command size is too small"; } llvm_unreachable("An enumerator of object_error does not have a message " "defined."); diff --git a/contrib/llvm/lib/Object/IRObjectFile.cpp b/contrib/llvm/lib/Object/IRObjectFile.cpp index 423ed9e..e90e08d 100644 --- a/contrib/llvm/lib/Object/IRObjectFile.cpp +++ b/contrib/llvm/lib/Object/IRObjectFile.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/IRObjectFile.h" #include "RecordStreamer.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/LLVMContext.h" @@ -24,6 +25,7 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" @@ -35,33 +37,30 @@ using namespace object; IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) : SymbolicFile(Binary::ID_IR, 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)); + // Setup a mangler with the DataLayout. + const DataLayout &DL = M->getDataLayout(); + Mang.reset(new Mangler(&DL)); const std::string &InlineAsm = M->getModuleInlineAsm(); if (InlineAsm.empty()) return; - StringRef Triple = M->getTargetTriple(); + Triple TT(M->getTargetTriple()); std::string Err; - const Target *T = TargetRegistry::lookupTarget(Triple, Err); + const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); if (!T) return; - std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(Triple)); + std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TT.str())); if (!MRI) return; - std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, Triple)); + std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TT.str())); if (!MAI) return; std::unique_ptr<MCSubtargetInfo> STI( - T->createMCSubtargetInfo(Triple, "", "")); + T->createMCSubtargetInfo(TT.str(), "", "")); if (!STI) return; @@ -71,8 +70,9 @@ IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); - MOFI.InitMCObjectFileInfo(Triple, Reloc::Default, CodeModel::Default, MCCtx); + MOFI.InitMCObjectFileInfo(TT, Reloc::Default, CodeModel::Default, MCCtx); std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); + T->createNullTargetStreamer(*Streamer); std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; @@ -195,15 +195,18 @@ std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, unsigned Index = getAsmSymIndex(Symb); assert(Index <= AsmSymbols.size()); OS << AsmSymbols[Index].first; - return object_error::success;; + return std::error_code(); } + if (GV->hasDLLImportStorageClass()) + OS << "__imp_"; + if (Mang) Mang->getNameWithPrefix(OS, GV, false); else OS << GV->getName(); - return object_error::success; + return std::error_code(); } uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { @@ -301,10 +304,12 @@ llvm::object::IRObjectFile::create(MemoryBufferRef Object, std::unique_ptr<MemoryBuffer> Buff( MemoryBuffer::getMemBuffer(BCOrErr.get(), false)); - ErrorOr<Module *> MOrErr = getLazyBitcodeModule(std::move(Buff), Context); + ErrorOr<std::unique_ptr<Module>> MOrErr = + getLazyBitcodeModule(std::move(Buff), Context, nullptr, + /*ShouldLazyLoadMetadata*/ true); if (std::error_code EC = MOrErr.getError()) return EC; - std::unique_ptr<Module> M(MOrErr.get()); + std::unique_ptr<Module> &M = MOrErr.get(); return llvm::make_unique<IRObjectFile>(Object, std::move(M)); } diff --git a/contrib/llvm/lib/Object/MachOObjectFile.cpp b/contrib/llvm/lib/Object/MachOObjectFile.cpp index e476976..f76dd0d 100644 --- a/contrib/llvm/lib/Object/MachOObjectFile.cpp +++ b/contrib/llvm/lib/Object/MachOObjectFile.cpp @@ -38,8 +38,13 @@ namespace { }; } -template<typename T> +// FIXME: Replace all uses of this function with getStructOrErr. +template <typename T> static T getStruct(const MachOObjectFile *O, const char *P) { + // Don't read before the beginning or past the end of the file + if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) + report_fatal_error("Malformed MachO file."); + T Cmd; memcpy(&Cmd, P, sizeof(T)); if (O->isLittleEndian() != sys::IsLittleEndianHost) @@ -47,28 +52,19 @@ static T getStruct(const MachOObjectFile *O, const char *P) { return Cmd; } -static uint32_t -getSegmentLoadCommandNumSections(const MachOObjectFile *O, - const MachOObjectFile::LoadCommandInfo &L) { - if (O->is64Bit()) { - MachO::segment_command_64 S = O->getSegment64LoadCommand(L); - return S.nsects; - } - MachO::segment_command S = O->getSegmentLoadCommand(L); - return S.nsects; -} +template <typename T> +static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) { + // Don't read before the beginning or past the end of the file + if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) + return object_error::parse_failed; -static bool isPageZeroSegment(const MachOObjectFile *O, - const MachOObjectFile::LoadCommandInfo &L) { - if (O->is64Bit()) { - MachO::segment_command_64 S = O->getSegment64LoadCommand(L); - return StringRef("__PAGEZERO").equals(S.segname); - } - MachO::segment_command S = O->getSegmentLoadCommand(L); - return StringRef("__PAGEZERO").equals(S.segname); + T Cmd; + memcpy(&Cmd, P, sizeof(T)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + MachO::swapStruct(Cmd); + return Cmd; } - static const char * getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, unsigned Sec) { @@ -113,70 +109,6 @@ static unsigned getCPUType(const MachOObjectFile *O) { return O->getHeader().cputype; } -static void printRelocationTargetName(const MachOObjectFile *O, - const MachO::any_relocation_info &RE, - raw_string_ostream &fmt) { - bool IsScattered = O->isRelocationScattered(RE); - - // Target of a scattered relocation is an address. In the interest of - // generating pretty output, scan through the symbol table looking for a - // symbol that aligns with that address. If we find one, print it. - // Otherwise, we just print the hex address of the target. - if (IsScattered) { - uint32_t Val = O->getPlainRelocationSymbolNum(RE); - - for (const SymbolRef &Symbol : O->symbols()) { - std::error_code ec; - uint64_t Addr; - StringRef Name; - - if ((ec = Symbol.getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) - continue; - if ((ec = Symbol.getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (const SectionRef &Section : O->sections()) { - std::error_code ec; - - StringRef Name; - uint64_t Addr = Section.getAddress(); - if (Addr != Val) - continue; - if ((ec = Section.getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = O->getPlainRelocationExternal(RE); - uint64_t Val = O->getPlainRelocationSymbolNum(RE); - - if (isExtern) { - symbol_iterator SI = O->symbol_begin(); - advance(SI, Val); - SI->getName(S); - } else { - section_iterator SI = O->section_begin(); - // Adjust for the fact that sections are 1-indexed. - advance(SI, Val - 1); - SI->getName(S); - } - - fmt << S; -} - static uint32_t getPlainRelocationAddress(const MachO::any_relocation_info &RE) { return RE.r_word0; @@ -229,21 +161,95 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } +static ErrorOr<MachOObjectFile::LoadCommandInfo> +getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr) { + auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr); + if (!CmdOrErr) + return CmdOrErr.getError(); + if (CmdOrErr->cmdsize < 8) + return object_error::macho_small_load_command; + MachOObjectFile::LoadCommandInfo Load; + Load.Ptr = Ptr; + Load.C = CmdOrErr.get(); + return Load; +} + +static ErrorOr<MachOObjectFile::LoadCommandInfo> +getFirstLoadCommandInfo(const MachOObjectFile *Obj) { + unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) + : sizeof(MachO::mach_header); + return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize)); +} + +static ErrorOr<MachOObjectFile::LoadCommandInfo> +getNextLoadCommandInfo(const MachOObjectFile *Obj, + const MachOObjectFile::LoadCommandInfo &L) { + return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize); +} + +template <typename T> +static void parseHeader(const MachOObjectFile *Obj, T &Header, + std::error_code &EC) { + auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)); + if (HeaderOrErr) + Header = HeaderOrErr.get(); + else + EC = HeaderOrErr.getError(); +} + +// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all +// sections to \param Sections, and optionally sets +// \param IsPageZeroSegment to true. +template <typename SegmentCmd> +static std::error_code parseSegmentLoadCommand( + const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, + SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) { + const unsigned SegmentLoadSize = sizeof(SegmentCmd); + if (Load.C.cmdsize < SegmentLoadSize) + return object_error::macho_load_segment_too_small; + auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr); + if (!SegOrErr) + return SegOrErr.getError(); + SegmentCmd S = SegOrErr.get(); + const unsigned SectionSize = + Obj->is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section); + if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || + S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) + return object_error::macho_load_segment_too_many_sections; + for (unsigned J = 0; J < S.nsects; ++J) { + const char *Sec = getSectionPtr(Obj, Load, J); + Sections.push_back(Sec); + } + IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); + return std::error_code(); +} + MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64bits, std::error_code &EC) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), - DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), - UuidLoadCmd(nullptr), HasPageZeroSegment(false) { - uint32_t LoadCommandCount = this->getHeader().ncmds; - if (LoadCommandCount == 0) + DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), + DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), + HasPageZeroSegment(false) { + if (is64Bit()) + parseHeader(this, Header64, EC); + else + parseHeader(this, Header, EC); + if (EC) return; - MachO::LoadCommandType SegmentLoadType = is64Bit() ? - MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; + uint32_t LoadCommandCount = getHeader().ncmds; + if (LoadCommandCount == 0) + return; - MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); - for (unsigned I = 0; ; ++I) { + auto LoadOrErr = getFirstLoadCommandInfo(this); + if (!LoadOrErr) { + EC = LoadOrErr.getError(); + return; + } + LoadCommandInfo Load = LoadOrErr.get(); + for (unsigned I = 0; I < LoadCommandCount; ++I) { + LoadCommands.push_back(Load); if (Load.C.cmd == MachO::LC_SYMTAB) { // Multiple symbol tables if (SymtabLoadCmd) { @@ -265,6 +271,13 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, return; } DataInCodeLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { + // Multiple linker optimization hint tables + if (LinkOptHintsLoadCmd) { + EC = object_error::parse_failed; + return; + } + LinkOptHintsLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYLD_INFO || Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { // Multiple dyldinfo load commands @@ -280,14 +293,14 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, return; } UuidLoadCmd = Load.Ptr; - } else if (Load.C.cmd == SegmentLoadType) { - uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); - for (unsigned J = 0; J < NumSections; ++J) { - const char *Sec = getSectionPtr(this, Load, J); - Sections.push_back(Sec); - } - if (isPageZeroSegment(this, Load)) - HasPageZeroSegment = true; + } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { + if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>( + this, Load, Sections, HasPageZeroSegment))) + return; + } else if (Load.C.cmd == MachO::LC_SEGMENT) { + if ((EC = parseSegmentLoadCommand<MachO::segment_command>( + this, Load, Sections, HasPageZeroSegment))) + return; } 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 || @@ -295,12 +308,16 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { Libraries.push_back(Load.Ptr); } - - if (I == LoadCommandCount - 1) - break; - else - Load = getNextLoadCommandInfo(Load); + if (I < LoadCommandCount - 1) { + auto LoadOrErr = getNextLoadCommandInfo(this, Load); + if (!LoadOrErr) { + EC = LoadOrErr.getError(); + return; + } + Load = LoadOrErr.get(); + } } + assert(LoadCommands.size() == LoadCommandCount); } void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { @@ -315,8 +332,11 @@ std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, StringRef StringTable = getStringTableData(); MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); const char *Start = &StringTable.data()[Entry.n_strx]; + if (Start < getData().begin() || Start >= getData().end()) + report_fatal_error( + "Symbol name entry points before beginning or past end of file."); Res = StringRef(Start); - return object_error::success; + return std::error_code(); } unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { @@ -346,7 +366,7 @@ std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, return object_error::parse_failed; const char *Start = &StringTable.data()[NValue]; Res = StringRef(Start); - return object_error::success; + return std::error_code(); } std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, @@ -366,67 +386,25 @@ std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, else Res = Entry.n_value; } - return object_error::success; + return std::error_code(); } -std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, - uint32_t &Result) const { +uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { uint32_t flags = getSymbolFlags(DRI); if (flags & SymbolRef::SF_Common) { MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); - Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); - } else { - Result = 0; + return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); } - return object_error::success; + return 0; } -std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, - uint64_t &Result) const { - uint64_t BeginOffset; - uint64_t EndOffset = 0; - uint8_t SectionIndex; - - MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); +uint64_t MachOObjectFile::getSymbolSize(DataRefImpl DRI) const { uint64_t Value; getSymbolAddress(DRI, Value); - if (Value == UnknownAddressOrSize) { - Result = UnknownAddressOrSize; - return object_error::success; - } - - BeginOffset = Value; - - SectionIndex = Entry.n_sect; - if (!SectionIndex) { - uint32_t flags = getSymbolFlags(DRI); - if (flags & SymbolRef::SF_Common) - Result = Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - for (const SymbolRef &Symbol : symbols()) { - DataRefImpl DRI = Symbol.getRawDataRefImpl(); - Entry = getSymbolTableEntryBase(this, DRI); - getSymbolAddress(DRI, Value); - if (Value == UnknownAddressOrSize) - continue; - if (Entry.n_sect == SectionIndex && Value > BeginOffset) - if (!EndOffset || Value < EndOffset) - EndOffset = Value; - } - if (!EndOffset) { - DataRefImpl Sec; - Sec.d.a = SectionIndex-1; - uint64_t Size = getSectionSize(Sec); - EndOffset = getSectionAddress(Sec); - EndOffset += Size; - } - Result = EndOffset - BeginOffset; - return object_error::success; + uint32_t flags = getSymbolFlags(DRI); + if (flags & SymbolRef::SF_Common) + return Value; + return UnknownAddressOrSize; } std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, @@ -439,7 +417,7 @@ std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, // If this is a STAB debugging symbol, we can do nothing more. if (n_type & MachO::N_STAB) { Res = SymbolRef::ST_Debug; - return object_error::success; + return std::error_code(); } switch (n_type & MachO::N_TYPE) { @@ -450,7 +428,7 @@ std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, Res = SymbolRef::ST_Function; break; } - return object_error::success; + return std::error_code(); } uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { @@ -478,6 +456,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { if (Value && Value != UnknownAddressOrSize) Result |= SymbolRef::SF_Common; } + + if (!(MachOType & MachO::N_PEXT)) + Result |= SymbolRef::SF_Exported; } if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) @@ -502,10 +483,12 @@ std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, } else { DataRefImpl DRI; DRI.d.a = index - 1; + if (DRI.d.a >= Sections.size()) + report_fatal_error("getSymbolSection: Invalid section index."); Res = section_iterator(SectionRef(DRI, this)); } - return object_error::success; + return std::error_code(); } void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { @@ -516,7 +499,7 @@ std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { ArrayRef<char> Raw = getSectionRawName(Sec); Result = parseSegmentOrSectionName(Raw.data()); - return object_error::success; + return std::error_code(); } uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { @@ -547,7 +530,7 @@ std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, } Res = this->getData().substr(Offset, Size); - return object_error::success; + return std::error_code(); } uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { @@ -642,7 +625,7 @@ std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, Sec.d.a = Rel.d.a; uint64_t SecAddress = getSectionAddress(Sec); Res = SecAddress + Offset; - return object_error::success; + return std::error_code(); } std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, @@ -651,7 +634,7 @@ std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, "Only implemented for MH_OBJECT"); MachO::any_relocation_info RE = getRelocation(Rel); Res = getAnyRelocationAddress(RE); - return object_error::success; + return std::error_code(); } symbol_iterator @@ -675,11 +658,16 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { return symbol_iterator(SymbolRef(Sym, this)); } +section_iterator +MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { + return section_iterator(getAnyRelocationSection(getRelocation(Rel))); +} + 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; + return std::error_code(); } std::error_code @@ -791,183 +779,7 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, break; } Result.append(res.begin(), res.end()); - return object_error::success; -} - -std::error_code -MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl<char> &Result) const { - MachO::any_relocation_info RE = getRelocation(Rel); - - unsigned Arch = this->getArch(); - - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - unsigned Type = this->getAnyRelocationType(RE); - bool IsPCRel = this->getAnyRelocationPCRel(RE); - - // Determine any addends that should be displayed with the relocation. - // These require decoding the relocation type, which is triple-specific. - - // X86_64 has entirely custom relocation types. - if (Arch == Triple::x86_64) { - bool isPCRel = getAnyRelocationPCRel(RE); - - switch (Type) { - case MachO::X86_64_RELOC_GOT_LOAD: - case MachO::X86_64_RELOC_GOT: { - printRelocationTargetName(this, RE, fmt); - fmt << "@GOT"; - if (isPCRel) fmt << "PCREL"; - break; - } - case MachO::X86_64_RELOC_SUBTRACTOR: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = getAnyRelocationType(RENext); - if (RType != MachO::X86_64_RELOC_UNSIGNED) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - // The X86_64_RELOC_UNSIGNED contains the minuend symbol; - // X86_64_RELOC_SUBTRACTOR contains the subtrahend. - printRelocationTargetName(this, RENext, fmt); - fmt << "-"; - printRelocationTargetName(this, RE, fmt); - break; - } - case MachO::X86_64_RELOC_TLV: - printRelocationTargetName(this, RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - case MachO::X86_64_RELOC_SIGNED_1: - printRelocationTargetName(this, RE, fmt); - fmt << "-1"; - break; - case MachO::X86_64_RELOC_SIGNED_2: - printRelocationTargetName(this, RE, fmt); - fmt << "-2"; - break; - case MachO::X86_64_RELOC_SIGNED_4: - printRelocationTargetName(this, RE, fmt); - fmt << "-4"; - break; - default: - printRelocationTargetName(this, RE, fmt); - break; - } - // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm || - Arch == Triple::ppc) { - // Generic relocation types... - switch (Type) { - case MachO::GENERIC_RELOC_PAIR: // prints no info - return object_error::success; - case MachO::GENERIC_RELOC_SECTDIFF: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - - if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - printRelocationTargetName(this, RE, fmt); - fmt << "-"; - printRelocationTargetName(this, RENext, fmt); - break; - } - } - - if (Arch == Triple::x86 || Arch == Triple::ppc) { - switch (Type) { - case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - if (RType != MachO::GENERIC_RELOC_PAIR) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - printRelocationTargetName(this, RE, fmt); - fmt << "-"; - printRelocationTargetName(this, RENext, fmt); - break; - } - case MachO::GENERIC_RELOC_TLV: { - printRelocationTargetName(this, RE, fmt); - fmt << "@TLV"; - if (IsPCRel) fmt << "P"; - break; - } - default: - printRelocationTargetName(this, RE, fmt); - } - } else { // ARM-specific relocations - switch (Type) { - case MachO::ARM_RELOC_HALF: - case MachO::ARM_RELOC_HALF_SECTDIFF: { - // Half relocations steal a bit from the length field to encode - // whether this is an upper16 or a lower16 relocation. - bool isUpper = getAnyRelocationLength(RE) >> 1; - - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - printRelocationTargetName(this, RE, fmt); - - DataRefImpl RelNext = Rel; - moveRelocationNext(RelNext); - MachO::any_relocation_info RENext = getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - unsigned RType = getAnyRelocationType(RENext); - if (RType != MachO::ARM_RELOC_PAIR) - report_fatal_error("Expected ARM_RELOC_PAIR after " - "ARM_RELOC_HALF"); - - // NOTE: The half of the target virtual address is stashed in the - // address field of the secondary relocation, but we can't reverse - // engineer the constant offset from it without decoding the movw/movt - // instruction to find the other half in its immediate field. - - // ARM_RELOC_HALF_SECTDIFF encodes the second section in the - // symbol/section pointer of the follow-on relocation. - if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { - fmt << "-"; - printRelocationTargetName(this, RENext, fmt); - } - - fmt << ")"; - break; - } - default: { - printRelocationTargetName(this, RE, fmt); - } - } - } - } else - printRelocationTargetName(this, RE, fmt); - - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - return object_error::success; + return std::error_code(); } std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, @@ -995,7 +807,12 @@ std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, } } - return object_error::success; + return std::error_code(); +} + +uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { + MachO::any_relocation_info RE = getRelocation(Rel); + return getAnyRelocationLength(RE); } // @@ -1173,7 +990,7 @@ std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, } Res = LibrariesShortNames[Index]; - return object_error::success; + return std::error_code(); } basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { @@ -1201,7 +1018,8 @@ basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { return basic_symbol_iterator(SymbolRef(DRI, this)); MachO::symtab_command Symtab = getSymtabLoadCommand(); - assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); + if (Index >= Symtab.nsyms) + report_fatal_error("Requested symbol index is out of range."); unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); @@ -1414,6 +1232,7 @@ bool MachOObjectFile::isValidArch(StringRef ArchFlag) { .Case("armv5e", true) .Case("armv6", true) .Case("armv6m", true) + .Case("armv7", true) .Case("armv7em", true) .Case("armv7k", true) .Case("armv7m", true) @@ -1430,21 +1249,8 @@ unsigned MachOObjectFile::getArch() const { Triple MachOObjectFile::getArch(const char **McpuDefault, Triple *ThumbTriple) const { - Triple T; - if (is64Bit()) { - MachO::mach_header_64 H_64; - H_64 = getHeader64(); - T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault); - *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype, - McpuDefault); - } else { - MachO::mach_header H; - H = getHeader(); - T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault); - *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype, - McpuDefault); - } - return T; + *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault); + return getArch(Header.cputype, Header.cpusubtype, McpuDefault); } relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { @@ -1501,7 +1307,7 @@ bool ExportEntry::operator==(const ExportEntry &Other) const { if (Stack.size() != Other.Stack.size()) return false; // Not equal if different cumulative strings. - if (!CumulativeString.str().equals(Other.CumulativeString.str())) + if (!CumulativeString.equals(Other.CumulativeString)) return false; // Equal if all nodes in both stacks match. for (unsigned i=0; i < Stack.size(); ++i) { @@ -1523,7 +1329,7 @@ uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { } StringRef ExportEntry::name() const { - return CumulativeString.str(); + return CumulativeString; } uint64_t ExportEntry::flags() const { @@ -2097,6 +1903,22 @@ iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { MachOBindEntry::Kind::Weak); } +MachOObjectFile::load_command_iterator +MachOObjectFile::begin_load_commands() const { + return LoadCommands.begin(); +} + +MachOObjectFile::load_command_iterator +MachOObjectFile::end_load_commands() const { + return LoadCommands.end(); +} + +iterator_range<MachOObjectFile::load_command_iterator> +MachOObjectFile::load_commands() const { + return iterator_range<load_command_iterator>(begin_load_commands(), + end_load_commands()); +} + StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); @@ -2105,6 +1927,7 @@ MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { ArrayRef<char> MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { + assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); const section_base *Base = reinterpret_cast<const section_base *>(Sections[Sec.d.a]); return makeArrayRef(Base->sectname); @@ -2112,6 +1935,7 @@ MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { ArrayRef<char> MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); const section_base *Base = reinterpret_cast<const section_base *>(Sections[Sec.d.a]); return makeArrayRef(Base->segname); @@ -2184,40 +2008,25 @@ MachOObjectFile::getAnyRelocationType( } SectionRef -MachOObjectFile::getRelocationSection( +MachOObjectFile::getAnyRelocationSection( const MachO::any_relocation_info &RE) const { if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) return *section_end(); - unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; + unsigned SecNum = getPlainRelocationSymbolNum(RE); + if (SecNum == MachO::R_ABS || SecNum > Sections.size()) + return *section_end(); DataRefImpl DRI; - DRI.d.a = SecNum; + DRI.d.a = SecNum - 1; return SectionRef(DRI, this); } -MachOObjectFile::LoadCommandInfo -MachOObjectFile::getFirstLoadCommandInfo() const { - MachOObjectFile::LoadCommandInfo Load; - - unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : - sizeof(MachO::mach_header); - Load.Ptr = getPtr(this, HeaderSize); - Load.C = getStruct<MachO::load_command>(this, Load.Ptr); - return Load; -} - -MachOObjectFile::LoadCommandInfo -MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { - MachOObjectFile::LoadCommandInfo Next; - Next.Ptr = L.Ptr + L.C.cmdsize; - Next.C = getStruct<MachO::load_command>(this, Next.Ptr); - return Next; -} - MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { + assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); return getStruct<MachO::section>(this, Sections[DRI.d.a]); } MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { + assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); } @@ -2375,12 +2184,13 @@ MachOObjectFile::getDice(DataRefImpl Rel) const { return getStruct<MachO::data_in_code_entry>(this, P); } -MachO::mach_header MachOObjectFile::getHeader() const { - return getStruct<MachO::mach_header>(this, getPtr(this, 0)); +const MachO::mach_header &MachOObjectFile::getHeader() const { + return Header; } -MachO::mach_header_64 MachOObjectFile::getHeader64() const { - return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); +const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { + assert(is64Bit()); + return Header64; } uint32_t MachOObjectFile::getIndirectSymbolTableEntry( @@ -2455,6 +2265,21 @@ MachOObjectFile::getDataInCodeLoadCommand() const { return Cmd; } +MachO::linkedit_data_command +MachOObjectFile::getLinkOptHintsLoadCommand() const { + if (LinkOptHintsLoadCmd) + return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); + + // If there is no LinkOptHintsLoadCmd return a load command with zero'ed + // fields. + MachO::linkedit_data_command Cmd; + Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; + Cmd.cmdsize = sizeof(MachO::linkedit_data_command); + Cmd.dataoff = 0; + Cmd.datasize = 0; + return Cmd; +} + ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { if (!DyldInfoLoadCmd) return ArrayRef<uint8_t>(); diff --git a/contrib/llvm/lib/Object/MachOUniversal.cpp b/contrib/llvm/lib/Object/MachOUniversal.cpp index a01c838..2705e7d 100644 --- a/contrib/llvm/lib/Object/MachOUniversal.cpp +++ b/contrib/llvm/lib/Object/MachOUniversal.cpp @@ -120,7 +120,7 @@ MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, ec = object_error::parse_failed; return; } - ec = object_error::success; + ec = std::error_code(); } static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { diff --git a/contrib/llvm/lib/Object/Object.cpp b/contrib/llvm/lib/Object/Object.cpp index 84a5df0..85f2436 100644 --- a/contrib/llvm/lib/Object/Object.cpp +++ b/contrib/llvm/lib/Object/Object.cpp @@ -187,10 +187,7 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { } uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI) { - uint64_t ret; - if (std::error_code ec = (*unwrap(SI))->getSize(ret)) - report_fatal_error(ec.message()); - return ret; + return (*unwrap(SI))->getSize(); } // RelocationRef accessors @@ -233,12 +230,6 @@ const char *LLVMGetRelocationTypeName(LLVMRelocationIteratorRef RI) { // NOTE: Caller takes ownership of returned string. const char *LLVMGetRelocationValueString(LLVMRelocationIteratorRef RI) { - SmallVector<char, 0> ret; - if (std::error_code ec = (*unwrap(RI))->getValueString(ret)) - report_fatal_error(ec.message()); - - char *str = static_cast<char*>(malloc(ret.size())); - std::copy(ret.begin(), ret.end(), str); - return str; + return strdup(""); } diff --git a/contrib/llvm/lib/Object/ObjectFile.cpp b/contrib/llvm/lib/Object/ObjectFile.cpp index fd78271..f6667d9 100644 --- a/contrib/llvm/lib/Object/ObjectFile.cpp +++ b/contrib/llvm/lib/Object/ObjectFile.cpp @@ -34,14 +34,10 @@ std::error_code ObjectFile::printSymbolName(raw_ostream &OS, if (std::error_code EC = getSymbolName(Symb, Name)) return EC; OS << Name; - return object_error::success; + return std::error_code(); } -std::error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, - uint32_t &Result) const { - Result = 0; - return object_error::success; -} +uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; } section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); @@ -76,6 +72,7 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: + case sys::fs::file_magic::macho_kext_bundle: return createMachOObjectFile(Object); case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: diff --git a/contrib/llvm/lib/Object/RecordStreamer.cpp b/contrib/llvm/lib/Object/RecordStreamer.cpp index 081fadd..42dbd3e 100644 --- a/contrib/llvm/lib/Object/RecordStreamer.cpp +++ b/contrib/llvm/lib/Object/RecordStreamer.cpp @@ -89,7 +89,7 @@ bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, return true; } -void RecordStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, +void RecordStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { markDefined(*Symbol); } diff --git a/contrib/llvm/lib/Object/RecordStreamer.h b/contrib/llvm/lib/Object/RecordStreamer.h index 7dacbdf..d694a9f 100644 --- a/contrib/llvm/lib/Object/RecordStreamer.h +++ b/contrib/llvm/lib/Object/RecordStreamer.h @@ -33,10 +33,10 @@ public: 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, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; }; -} +} // namespace llvm #endif diff --git a/contrib/llvm/lib/Object/SymbolicFile.cpp b/contrib/llvm/lib/Object/SymbolicFile.cpp index de98a12..854e68e 100644 --- a/contrib/llvm/lib/Object/SymbolicFile.cpp +++ b/contrib/llvm/lib/Object/SymbolicFile.cpp @@ -53,6 +53,7 @@ ErrorOr<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: + case sys::fs::file_magic::macho_kext_bundle: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: return ObjectFile::createObjectFile(Object, Type); |