diff options
Diffstat (limited to 'gnu/llvm/lib/Object')
| -rw-r--r-- | gnu/llvm/lib/Object/Archive.cpp | 189 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/ArchiveWriter.cpp | 208 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/Binary.cpp | 14 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/COFFObjectFile.cpp | 158 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/ELF.cpp | 20 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/ELFObjectFile.cpp | 67 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/Error.cpp | 43 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/IRObjectFile.cpp | 41 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/MachOObjectFile.cpp | 404 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/MachOUniversal.cpp | 120 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp | 126 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/Object.cpp | 40 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/ObjectFile.cpp | 38 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/RecordStreamer.cpp | 16 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/RecordStreamer.h | 4 | ||||
| -rw-r--r-- | gnu/llvm/lib/Object/SymbolicFile.cpp | 14 |
17 files changed, 1021 insertions, 485 deletions
diff --git a/gnu/llvm/lib/Object/Archive.cpp b/gnu/llvm/lib/Object/Archive.cpp index 99b0650c8b7..daf301e2e7e 100644 --- a/gnu/llvm/lib/Object/Archive.cpp +++ b/gnu/llvm/lib/Object/Archive.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/Archive.h" -#include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Endian.h" @@ -52,14 +51,14 @@ ErrorOr<uint32_t> ArchiveMemberHeader::getSize() const { sys::fs::perms ArchiveMemberHeader::getAccessMode() const { unsigned Ret; - if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(" ").getAsInteger(8, Ret)) + if (StringRef(AccessMode, sizeof(AccessMode)).rtrim(' ').getAsInteger(8, Ret)) llvm_unreachable("Access mode is not an octal number."); return static_cast<sys::fs::perms>(Ret); } sys::TimeValue ArchiveMemberHeader::getLastModified() const { unsigned Seconds; - if (StringRef(LastModified, sizeof(LastModified)).rtrim(" ") + if (StringRef(LastModified, sizeof(LastModified)).rtrim(' ') .getAsInteger(10, Seconds)) llvm_unreachable("Last modified time not a decimal number."); @@ -70,14 +69,20 @@ sys::TimeValue ArchiveMemberHeader::getLastModified() const { unsigned ArchiveMemberHeader::getUID() const { unsigned Ret; - if (StringRef(UID, sizeof(UID)).rtrim(" ").getAsInteger(10, Ret)) + StringRef User = StringRef(UID, sizeof(UID)).rtrim(' '); + if (User.empty()) + return 0; + if (User.getAsInteger(10, Ret)) llvm_unreachable("UID time not a decimal number."); return Ret; } unsigned ArchiveMemberHeader::getGID() const { unsigned Ret; - if (StringRef(GID, sizeof(GID)).rtrim(" ").getAsInteger(10, Ret)) + StringRef Group = StringRef(GID, sizeof(GID)).rtrim(' '); + if (Group.empty()) + return 0; + if (Group.getAsInteger(10, Ret)) llvm_unreachable("GID time not a decimal number."); return Ret; } @@ -108,7 +113,7 @@ Archive::Child::Child(const Archive *Parent, const char *Start, StringRef Name = getRawName(); if (Name.startswith("#1/")) { uint64_t NameSize; - if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) + if (Name.substr(3).rtrim(' ').getAsInteger(10, NameSize)) llvm_unreachable("Long name length is not an integer"); StartOfFile += NameSize; } @@ -136,6 +141,21 @@ bool Archive::Child::isThinMember() const { return Parent->IsThin && Name != "/" && Name != "//"; } +ErrorOr<std::string> Archive::Child::getFullName() const { + assert(isThinMember()); + ErrorOr<StringRef> NameOrErr = getName(); + if (std::error_code EC = NameOrErr.getError()) + return EC; + StringRef Name = *NameOrErr; + if (sys::path::is_absolute(Name)) + return Name; + + SmallString<128> FullName = sys::path::parent_path( + Parent->getMemoryBufferRef().getBufferIdentifier()); + sys::path::append(FullName, Name); + return StringRef(FullName); +} + ErrorOr<StringRef> Archive::Child::getBuffer() const { if (!isThinMember()) { ErrorOr<uint32_t> Size = getSize(); @@ -143,12 +163,10 @@ ErrorOr<StringRef> Archive::Child::getBuffer() const { return EC; return StringRef(Data.data() + StartOfFile, Size.get()); } - ErrorOr<StringRef> Name = getName(); - if (std::error_code EC = Name.getError()) + ErrorOr<std::string> FullNameOrEr = getFullName(); + if (std::error_code EC = FullNameOrEr.getError()) return EC; - SmallString<128> FullName = sys::path::parent_path( - Parent->getMemoryBufferRef().getBufferIdentifier()); - sys::path::append(FullName, *Name); + const std::string &FullName = *FullNameOrEr; ErrorOr<std::unique_ptr<MemoryBuffer>> Buf = MemoryBuffer::getFile(FullName); if (std::error_code EC = Buf.getError()) return EC; @@ -197,7 +215,7 @@ ErrorOr<StringRef> Archive::Child::getName() const { // It's a long name. // Get the offset. std::size_t offset; - if (name.substr(1).rtrim(" ").getAsInteger(10, offset)) + if (name.substr(1).rtrim(' ').getAsInteger(10, offset)) llvm_unreachable("Long name offset is not an integer"); // Verify it. @@ -213,10 +231,14 @@ ErrorOr<StringRef> Archive::Child::getName() const { return StringRef(addr); } else if (name.startswith("#1/")) { uint64_t name_size; - if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) + if (name.substr(3).rtrim(' ').getAsInteger(10, name_size)) llvm_unreachable("Long name length is not an ingeter"); - return Data.substr(sizeof(ArchiveMemberHeader), name_size) - .rtrim(StringRef("\0", 1)); + return Data.substr(sizeof(ArchiveMemberHeader), name_size).rtrim('\0'); + } else { + // It is not a long name so trim the blanks at the end of the name. + if (name[name.size() - 1] != '/') { + return name.rtrim(' '); + } } // It's a simple name. if (name[name.size() - 1] == '/') @@ -235,20 +257,23 @@ ErrorOr<MemoryBufferRef> Archive::Child::getMemoryBufferRef() const { return MemoryBufferRef(*Buf, Name); } -ErrorOr<std::unique_ptr<Binary>> +Expected<std::unique_ptr<Binary>> Archive::Child::getAsBinary(LLVMContext *Context) const { ErrorOr<MemoryBufferRef> BuffOrErr = getMemoryBufferRef(); if (std::error_code EC = BuffOrErr.getError()) - return EC; + return errorCodeToError(EC); - return createBinary(BuffOrErr.get(), Context); + auto BinaryOrErr = createBinary(BuffOrErr.get(), Context); + if (BinaryOrErr) + return std::move(*BinaryOrErr); + return BinaryOrErr.takeError(); } -ErrorOr<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) { - std::error_code EC; - std::unique_ptr<Archive> Ret(new Archive(Source, EC)); - if (EC) - return EC; +Expected<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) { + Error Err; + std::unique_ptr<Archive> Ret(new Archive(Source, Err)); + if (Err) + return std::move(Err); return std::move(Ret); } @@ -257,8 +282,9 @@ void Archive::setFirstRegular(const Child &C) { FirstRegularStartOfFile = C.StartOfFile; } -Archive::Archive(MemoryBufferRef Source, std::error_code &ec) +Archive::Archive(MemoryBufferRef Source, Error &Err) : Binary(Binary::ID_Archive, Source) { + ErrorAsOutParameter ErrAsOutParam(Err); StringRef Buffer = Data.getBuffer(); // Check for sufficient magic. if (Buffer.startswith(ThinMagic)) { @@ -266,27 +292,33 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) } else if (Buffer.startswith(Magic)) { IsThin = false; } else { - ec = object_error::invalid_file_type; + Err = make_error<GenericBinaryError>("File too small to be an archive", + object_error::invalid_file_type); return; } // Get the special members. - child_iterator I = child_begin(false); - if ((ec = I->getError())) + child_iterator I = child_begin(Err, false); + if (Err) return; child_iterator E = child_end(); + // This is at least a valid empty archive. Since an empty archive is the + // same in all formats, just claim it to be gnu to make sure Format is + // initialized. + Format = K_GNU; + if (I == E) { - ec = std::error_code(); + Err = Error::success(); return; } - const Child *C = &**I; + const Child *C = &*I; auto Increment = [&]() { ++I; - if ((ec = I->getError())) + if (Err) return true; - C = &**I; + C = &*I; return false; }; @@ -311,8 +343,11 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) // seem to create the third member if there's no member whose filename // exceeds 15 characters. So the third member is optional. - if (Name == "__.SYMDEF") { - Format = K_BSD; + if (Name == "__.SYMDEF" || Name == "__.SYMDEF_64") { + if (Name == "__.SYMDEF") + Format = K_BSD; + else // Name == "__.SYMDEF_64" + Format = K_DARWIN64; // We know that the symbol table is not an external file, so we just assert // there is no error. SymbolTable = *C->getBuffer(); @@ -320,7 +355,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) return; setFirstRegular(*C); - ec = std::error_code(); + Err = Error::success(); return; } @@ -328,9 +363,10 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) Format = K_BSD; // We know this is BSD, so getName will work since there is no string table. ErrorOr<StringRef> NameOrErr = C->getName(); - ec = NameOrErr.getError(); - if (ec) + if (auto ec = NameOrErr.getError()) { + Err = errorCodeToError(ec); return; + } Name = NameOrErr.get(); if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") { // We know that the symbol table is not an external file, so we just @@ -339,6 +375,14 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (Increment()) return; } + else if (Name == "__.SYMDEF_64 SORTED" || Name == "__.SYMDEF_64") { + Format = K_DARWIN64; + // We know that the symbol table is not an external file, so we just + // assert there is no error. + SymbolTable = *C->getBuffer(); + if (Increment()) + return; + } setFirstRegular(*C); return; } @@ -359,7 +403,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (Increment()) return; if (I == E) { - ec = std::error_code(); + Err = Error::success(); return; } Name = C->getRawName(); @@ -373,19 +417,19 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (Increment()) return; setFirstRegular(*C); - ec = std::error_code(); + Err = Error::success(); return; } if (Name[0] != '/') { Format = has64SymTable ? K_MIPS64 : K_GNU; setFirstRegular(*C); - ec = std::error_code(); + Err = Error::success(); return; } if (Name != "/") { - ec = object_error::parse_failed; + Err = errorCodeToError(object_error::parse_failed); return; } @@ -399,7 +443,7 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) if (I == E) { setFirstRegular(*C); - ec = std::error_code(); + Err = Error::success(); return; } @@ -414,26 +458,32 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec) } setFirstRegular(*C); - ec = std::error_code(); + Err = Error::success(); } -Archive::child_iterator Archive::child_begin(bool SkipInternal) const { +Archive::child_iterator Archive::child_begin(Error &Err, + bool SkipInternal) const { if (Data.getBufferSize() == 8) // empty archive. return child_end(); if (SkipInternal) - return Child(this, FirstRegularData, FirstRegularStartOfFile); + return child_iterator(Child(this, FirstRegularData, + FirstRegularStartOfFile), + &Err); const char *Loc = Data.getBufferStart() + strlen(Magic); std::error_code EC; - Child c(this, Loc, &EC); - if (EC) - return child_iterator(EC); - return child_iterator(c); + Child C(this, Loc, &EC); + if (EC) { + ErrorAsOutParameter ErrAsOutParam(Err); + Err = errorCodeToError(EC); + return child_end(); + } + return child_iterator(C, &Err); } Archive::child_iterator Archive::child_end() const { - return Child(this, nullptr, nullptr); + return child_iterator(Child(this, nullptr, nullptr), nullptr); } StringRef Archive::Symbol::getName() const { @@ -443,7 +493,7 @@ StringRef Archive::Symbol::getName() const { ErrorOr<Archive::Child> Archive::Symbol::getMember() const { const char *Buf = Parent->getSymbolTable().begin(); const char *Offsets = Buf; - if (Parent->kind() == K_MIPS64) + if (Parent->kind() == K_MIPS64 || Parent->kind() == K_DARWIN64) Offsets += sizeof(uint64_t); else Offsets += sizeof(uint32_t); @@ -460,6 +510,14 @@ ErrorOr<Archive::Child> Archive::Symbol::getMember() const { // the archive of the member that defines the symbol. Which is what // is needed here. Offset = read32le(Offsets + SymbolIndex * 8 + 4); + } else if (Parent->kind() == K_DARWIN64) { + // The SymbolIndex is an index into the ranlib_64 structs that start at + // Offsets (the first uint64_t is the number of bytes of the ranlib_64 + // structs). The ranlib_64 structs are a pair of uint64_t's the first + // being a string table offset and the second being the offset into + // the archive of the member that defines the symbol. Which is what + // is needed here. + Offset = read64le(Offsets + SymbolIndex * 16 + 8); } else { // Skip offsets. uint32_t MemberCount = read32le(Buf); @@ -559,6 +617,22 @@ Archive::symbol_iterator Archive::symbol_begin() const { // Skip the byte count of the string table. buf += sizeof(uint32_t); buf += ran_strx; + } else if (kind() == K_DARWIN64) { + // The __.SYMDEF_64 or "__.SYMDEF_64 SORTED" member starts with a uint64_t + // which is the number of bytes of ranlib_64 structs that follow. The + // ranlib_64 structs are a pair of uint64_t's the first being a string + // table offset and the second being the offset into the archive of the + // member that define the symbol. After that the next uint64_t is the byte + // count of the string table followed by the string table. + uint64_t ranlib_count = 0; + ranlib_count = read64le(buf) / 16; + const char *ranlibs = buf + 8; + uint64_t ran_strx = 0; + ran_strx = read64le(ranlibs); + buf += sizeof(uint64_t) + (ranlib_count * (2 * (sizeof(uint64_t)))); + // Skip the byte count of the string table. + buf += sizeof(uint64_t); + buf += ran_strx; } else { uint32_t member_count = 0; uint32_t symbol_count = 0; @@ -585,27 +659,28 @@ uint32_t Archive::getNumberOfSymbols() const { return read64be(buf); if (kind() == K_BSD) return read32le(buf) / 8; + if (kind() == K_DARWIN64) + return read64le(buf) / 16; 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 { +Expected<Optional<Archive::Child>> Archive::findSym(StringRef name) const { Archive::symbol_iterator bs = symbol_begin(); Archive::symbol_iterator es = symbol_end(); for (; bs != es; ++bs) { StringRef SymName = bs->getName(); if (SymName == name) { - ErrorOr<Archive::child_iterator> ResultOrErr = bs->getMember(); - // FIXME: Should we really eat the error? - if (ResultOrErr.getError()) - return child_end(); - return ResultOrErr.get(); + if (auto MemberOrErr = bs->getMember()) + return Child(*MemberOrErr); + else + return errorCodeToError(MemberOrErr.getError()); } } - return child_end(); + return Optional<Child>(); } bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); } diff --git a/gnu/llvm/lib/Object/ArchiveWriter.cpp b/gnu/llvm/lib/Object/ArchiveWriter.cpp index c7343fdc171..53573262104 100644 --- a/gnu/llvm/lib/Object/ArchiveWriter.cpp +++ b/gnu/llvm/lib/Object/ArchiveWriter.cpp @@ -34,45 +34,61 @@ using namespace llvm; -NewArchiveIterator::NewArchiveIterator(const object::Archive::Child &OldMember, - StringRef Name) - : IsNewMember(false), Name(Name), OldMember(OldMember) {} - -NewArchiveIterator::NewArchiveIterator(StringRef FileName) - : IsNewMember(true), Name(FileName), OldMember(nullptr, nullptr, nullptr) {} - -StringRef NewArchiveIterator::getName() const { return Name; } - -bool NewArchiveIterator::isNewMember() const { return IsNewMember; } - -const object::Archive::Child &NewArchiveIterator::getOld() const { - assert(!IsNewMember); - return OldMember; -} - -StringRef NewArchiveIterator::getNew() const { - assert(IsNewMember); - return Name; +NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef) + : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {} + +Expected<NewArchiveMember> +NewArchiveMember::getOldMember(const object::Archive::Child &OldMember, + bool Deterministic) { + ErrorOr<llvm::MemoryBufferRef> BufOrErr = OldMember.getMemoryBufferRef(); + if (!BufOrErr) + return errorCodeToError(BufOrErr.getError()); + + NewArchiveMember M; + M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false); + if (!Deterministic) { + M.ModTime = OldMember.getLastModified(); + M.UID = OldMember.getUID(); + M.GID = OldMember.getGID(); + M.Perms = OldMember.getAccessMode(); + } + return std::move(M); } -llvm::ErrorOr<int> -NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const { - assert(IsNewMember); - int NewFD; - if (auto EC = sys::fs::openFileForRead(Name, NewFD)) - return EC; - assert(NewFD != -1); +Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName, + bool Deterministic) { + sys::fs::file_status Status; + int FD; + if (auto EC = sys::fs::openFileForRead(FileName, FD)) + return errorCodeToError(EC); + assert(FD != -1); - if (auto EC = sys::fs::status(NewFD, NewStatus)) - return EC; + if (auto EC = sys::fs::status(FD, Status)) + return errorCodeToError(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; + if (Status.type() == sys::fs::file_type::directory_file) + return errorCodeToError(make_error_code(errc::is_a_directory)); + + ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr = + MemoryBuffer::getOpenFile(FD, FileName, Status.getSize(), false); + if (!MemberBufferOrErr) + return errorCodeToError(MemberBufferOrErr.getError()); + + if (close(FD) != 0) + return errorCodeToError(std::error_code(errno, std::generic_category())); + + NewArchiveMember M; + M.Buf = std::move(*MemberBufferOrErr); + if (!Deterministic) { + M.ModTime = Status.getLastModificationTime(); + M.UID = Status.getUser(); + M.GID = Status.getGroup(); + M.Perms = Status.permissions(); + } + return std::move(M); } template <typename T> @@ -178,12 +194,13 @@ static std::string computeRelativePath(StringRef From, StringRef To) { } static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName, - ArrayRef<NewArchiveIterator> Members, + ArrayRef<NewArchiveMember> Members, std::vector<unsigned> &StringMapIndexes, bool Thin) { unsigned StartOffset = 0; - for (const NewArchiveIterator &I : Members) { - StringRef Name = sys::path::filename(I.getName()); + for (const NewArchiveMember &M : Members) { + StringRef Path = M.Buf->getBufferIdentifier(); + StringRef Name = sys::path::filename(Path); if (!useStringTable(Thin, Name)) continue; if (StartOffset == 0) { @@ -194,7 +211,7 @@ static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName, StringMapIndexes.push_back(Out.tell() - StartOffset); if (Thin) - Out << computeRelativePath(ArcName, I.getName()); + Out << computeRelativePath(ArcName, Path); else Out << Name; @@ -221,8 +238,7 @@ static sys::TimeValue now(bool Deterministic) { // Returns the offset of the first reference to a member offset. static ErrorOr<unsigned> writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, - ArrayRef<NewArchiveIterator> Members, - ArrayRef<MemoryBufferRef> Buffers, + ArrayRef<NewArchiveMember> Members, std::vector<unsigned> &MemberOffsetRefs, bool Deterministic) { unsigned HeaderStartOffset = 0; unsigned BodyStartOffset = 0; @@ -230,12 +246,15 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, raw_svector_ostream NameOS(NameBuf); LLVMContext Context; for (unsigned MemberNum = 0, N = Members.size(); MemberNum < N; ++MemberNum) { - MemoryBufferRef MemberBuffer = Buffers[MemberNum]; - ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr = + MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef(); + Expected<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. + if (!ObjOrErr) { + // FIXME: check only for "not an object file" errors. + consumeError(ObjOrErr.takeError()); + continue; + } object::SymbolicFile &Obj = *ObjOrErr.get(); if (!HeaderStartOffset) { @@ -302,9 +321,12 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, std::pair<StringRef, std::error_code> llvm::writeArchive(StringRef ArcName, - std::vector<NewArchiveIterator> &NewMembers, + std::vector<NewArchiveMember> &NewMembers, bool WriteSymtab, object::Archive::Kind Kind, - bool Deterministic, bool Thin) { + bool Deterministic, bool Thin, + std::unique_ptr<MemoryBuffer> OldArchiveBuf) { + assert((!Thin || Kind == object::Archive::K_GNU) && + "Only the gnu format has a thin mode"); SmallString<128> TmpArchive; int TmpArchiveFD; if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a", @@ -324,44 +346,10 @@ llvm::writeArchive(StringRef ArcName, 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 { - const object::Archive::Child &OldMember = Member.getOld(); - assert((!Thin || OldMember.getParent()->isThin()) && - "Thin archives cannot refers to member of other archives"); - 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, Kind, NewMembers, Members, MemberOffsetRefs, Deterministic); + Out, Kind, NewMembers, MemberOffsetRefs, Deterministic); if (auto EC = MemberReferenceOffsetOrErr.getError()) return std::make_pair(ArcName, EC); MemberReferenceOffset = MemberReferenceOffsetOrErr.get(); @@ -371,55 +359,18 @@ llvm::writeArchive(StringRef ArcName, if (Kind != object::Archive::K_BSD) writeStringTable(Out, ArcName, NewMembers, StringMapIndexes, Thin); - unsigned MemberNum = 0; - unsigned NewMemberNum = 0; std::vector<unsigned>::iterator StringMapIndexIter = StringMapIndexes.begin(); std::vector<unsigned> MemberOffset; - for (const NewArchiveIterator &I : NewMembers) { - MemoryBufferRef File = Members[MemberNum++]; + for (const NewArchiveMember &M : NewMembers) { + MemoryBufferRef File = M.Buf->getMemBufferRef(); unsigned Pos = Out.tell(); MemberOffset.push_back(Pos); - sys::TimeValue ModTime; - unsigned UID; - unsigned GID; - unsigned Perms; - if (Deterministic) { - ModTime.fromEpochTime(0); - UID = 0; - GID = 0; - Perms = 0644; - } else if (I.isNewMember()) { - const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum]; - ModTime = Status.getLastModificationTime(); - UID = Status.getUser(); - GID = Status.getGroup(); - Perms = Status.permissions(); - } else { - const object::Archive::Child &OldMember = I.getOld(); - ModTime = OldMember.getLastModified(); - UID = OldMember.getUID(); - GID = OldMember.getGID(); - Perms = OldMember.getAccessMode(); - } - - if (I.isNewMember()) { - StringRef FileName = I.getNew(); - const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++]; - printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName), - StringMapIndexIter, ModTime, UID, GID, Perms, - Status.getSize()); - } else { - const object::Archive::Child &OldMember = I.getOld(); - ErrorOr<uint32_t> Size = OldMember.getSize(); - if (std::error_code EC = Size.getError()) - return std::make_pair("", EC); - StringRef FileName = I.getName(); - printMemberHeader(Out, Kind, Thin, sys::path::filename(FileName), - StringMapIndexIter, ModTime, UID, GID, Perms, - Size.get()); - } + printMemberHeader(Out, Kind, Thin, + sys::path::filename(M.Buf->getBufferIdentifier()), + StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms, + M.Buf->getBufferSize()); if (!Thin) Out << File.getBuffer(); @@ -439,6 +390,19 @@ llvm::writeArchive(StringRef ArcName, Output.keep(); Out.close(); + + // At this point, we no longer need whatever backing memory + // was used to generate the NewMembers. On Windows, this buffer + // could be a mapped view of the file we want to replace (if + // we're updating an existing archive, say). In that case, the + // rename would still succeed, but it would leave behind a + // temporary file (actually the original file renamed) because + // a file cannot be deleted while there's a handle open on it, + // only renamed. So by freeing this buffer, this ensures that + // the last open handle on the destination file, if any, is + // closed before we attempt to rename. + OldArchiveBuf.reset(); + sys::fs::rename(TmpArchive, ArcName); return std::make_pair("", std::error_code()); } diff --git a/gnu/llvm/lib/Object/Binary.cpp b/gnu/llvm/lib/Object/Binary.cpp index a2b167a665c..ec051fec375 100644 --- a/gnu/llvm/lib/Object/Binary.cpp +++ b/gnu/llvm/lib/Object/Binary.cpp @@ -36,7 +36,7 @@ StringRef Binary::getFileName() const { return Data.getBufferIdentifier(); } MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; } -ErrorOr<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, +Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, LLVMContext *Context) { sys::fs::file_magic Type = sys::fs::identify_magic(Buffer.getBuffer()); @@ -69,22 +69,22 @@ ErrorOr<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, case sys::fs::file_magic::unknown: case sys::fs::file_magic::windows_resource: // Unrecognized object file format. - return object_error::invalid_file_type; + return errorCodeToError(object_error::invalid_file_type); } llvm_unreachable("Unexpected Binary File Type"); } -ErrorOr<OwningBinary<Binary>> object::createBinary(StringRef Path) { +Expected<OwningBinary<Binary>> object::createBinary(StringRef Path) { ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = MemoryBuffer::getFileOrSTDIN(Path); if (std::error_code EC = FileOrErr.getError()) - return EC; + return errorCodeToError(EC); std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get(); - ErrorOr<std::unique_ptr<Binary>> BinOrErr = + Expected<std::unique_ptr<Binary>> BinOrErr = createBinary(Buffer->getMemBufferRef()); - if (std::error_code EC = BinOrErr.getError()) - return EC; + if (!BinOrErr) + return BinOrErr.takeError(); std::unique_ptr<Binary> &Bin = BinOrErr.get(); return OwningBinary<Binary>(std::move(Bin), std::move(Buffer)); diff --git a/gnu/llvm/lib/Object/CMakeLists.txt b/gnu/llvm/lib/Object/CMakeLists.txt index 2ac2ee51dc2..0a37cc360fe 100644 --- a/gnu/llvm/lib/Object/CMakeLists.txt +++ b/gnu/llvm/lib/Object/CMakeLists.txt @@ -3,20 +3,18 @@ add_llvm_library(LLVMObject ArchiveWriter.cpp Binary.cpp COFFObjectFile.cpp - COFFYAML.cpp ELF.cpp ELFObjectFile.cpp - ELFYAML.cpp Error.cpp IRObjectFile.cpp MachOObjectFile.cpp MachOUniversal.cpp + ModuleSummaryIndexObjectFile.cpp Object.cpp ObjectFile.cpp RecordStreamer.cpp SymbolicFile.cpp SymbolSize.cpp - FunctionIndexObjectFile.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object diff --git a/gnu/llvm/lib/Object/COFFObjectFile.cpp b/gnu/llvm/lib/Object/COFFObjectFile.cpp index 4cd6aff5f17..0f790086cfc 100644 --- a/gnu/llvm/lib/Object/COFFObjectFile.cpp +++ b/gnu/llvm/lib/Object/COFFObjectFile.cpp @@ -13,7 +13,6 @@ #include "llvm/Object/COFF.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" @@ -145,12 +144,12 @@ void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { } } -ErrorOr<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { +Expected<StringRef> COFFObjectFile::getSymbolName(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); StringRef Result; std::error_code EC = getSymbolName(Symb, Result); if (EC) - return EC; + return errorCodeToError(EC); return Result; } @@ -158,7 +157,7 @@ uint64_t COFFObjectFile::getSymbolValueImpl(DataRefImpl Ref) const { return getCOFFSymbol(Ref).getValue(); } -ErrorOr<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { +Expected<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { uint64_t Result = getSymbolValue(Ref); COFFSymbolRef Symb = getCOFFSymbol(Ref); int32_t SectionNumber = Symb.getSectionNumber(); @@ -169,7 +168,7 @@ ErrorOr<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { const coff_section *Section = nullptr; if (std::error_code EC = getSection(SectionNumber, Section)) - return EC; + return errorCodeToError(EC); Result += Section->VirtualAddress; // The section VirtualAddress does not include ImageBase, and we want to @@ -179,7 +178,7 @@ ErrorOr<uint64_t> COFFObjectFile::getSymbolAddress(DataRefImpl Ref) const { return Result; } -SymbolRef::Type COFFObjectFile::getSymbolType(DataRefImpl Ref) const { +Expected<SymbolRef::Type> COFFObjectFile::getSymbolType(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); int32_t SectionNumber = Symb.getSectionNumber(); @@ -235,14 +234,14 @@ uint64_t COFFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Ref) const { return Symb.getValue(); } -ErrorOr<section_iterator> +Expected<section_iterator> COFFObjectFile::getSymbolSection(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) return section_end(); const coff_section *Sec = nullptr; if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) - return EC; + return errorCodeToError(EC); DataRefImpl Ret; Ret.p = reinterpret_cast<uintptr_t>(Sec); return section_iterator(SectionRef(Ret, this)); @@ -290,7 +289,11 @@ std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); + return Sec->getAlignment(); +} + +bool COFFObjectFile::isSectionCompressed(DataRefImpl Sec) const { + return false; } bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { @@ -450,6 +453,27 @@ std::error_code COFFObjectFile::getRvaPtr(uint32_t Addr, uintptr_t &Res) const { return object_error::parse_failed; } +std::error_code +COFFObjectFile::getRvaAndSizeAsBytes(uint32_t RVA, uint32_t Size, + ArrayRef<uint8_t> &Contents) const { + for (const SectionRef &S : sections()) { + const coff_section *Section = getCOFFSection(S); + uint32_t SectionStart = Section->VirtualAddress; + // Check if this RVA is within the section bounds. Be careful about integer + // overflow. + uint32_t OffsetIntoSection = RVA - SectionStart; + if (SectionStart <= RVA && OffsetIntoSection < Section->VirtualSize && + Size <= Section->VirtualSize - OffsetIntoSection) { + uintptr_t Begin = + uintptr_t(base()) + Section->PointerToRawData + OffsetIntoSection; + Contents = + ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(Begin), Size); + return std::error_code(); + } + } + return object_error::parse_failed; +} + // Returns hint and name fields, assuming \p Rva is pointing to a Hint/Name // table entry. std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, @@ -463,6 +487,35 @@ std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint, return std::error_code(); } +std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir, + const debug_pdb_info *&PDBInfo, + StringRef &PDBFileName) const { + ArrayRef<uint8_t> InfoBytes; + if (std::error_code EC = getRvaAndSizeAsBytes( + DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes)) + return EC; + if (InfoBytes.size() < sizeof(debug_pdb_info) + 1) + return object_error::parse_failed; + PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data()); + InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info)); + PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()), + InfoBytes.size()); + // Truncate the name at the first null byte. Ignore any padding. + PDBFileName = PDBFileName.split('\0').first; + return std::error_code(); +} + +std::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo, + StringRef &PDBFileName) const { + for (const debug_directory &D : debug_directories()) + if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) + return getDebugPDBInfo(&D, PDBInfo, PDBFileName); + // If we get here, there is no PDB info to return. + PDBInfo = nullptr; + PDBFileName = StringRef(); + return std::error_code(); +} + // Find the import table. std::error_code COFFObjectFile::initImportTablePtr() { // First, we get the RVA of the import table. If the file lacks a pointer to @@ -476,15 +529,14 @@ std::error_code COFFObjectFile::initImportTablePtr() { return std::error_code(); uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; - // -1 because the last entry is the null entry. - NumberOfImportDirectory = DataEntry->Size / - sizeof(import_directory_table_entry) - 1; // Find the section that contains the RVA. This is needed because the RVA is // the import table's memory address which is different from its file offset. uintptr_t IntPtr = 0; if (std::error_code EC = getRvaPtr(ImportTableRva, IntPtr)) return EC; + if (std::error_code EC = checkOffset(Data, IntPtr, DataEntry->Size)) + return EC; ImportDirectory = reinterpret_cast< const import_directory_table_entry *>(IntPtr); return std::error_code(); @@ -548,15 +600,40 @@ std::error_code COFFObjectFile::initBaseRelocPtr() { return std::error_code(); } +std::error_code COFFObjectFile::initDebugDirectoryPtr() { + // Get the RVA of the debug directory. Do nothing if it does not exist. + const data_directory *DataEntry; + if (getDataDirectory(COFF::DEBUG_DIRECTORY, DataEntry)) + return std::error_code(); + + // Do nothing if the RVA is NULL. + if (DataEntry->RelativeVirtualAddress == 0) + return std::error_code(); + + // Check that the size is a multiple of the entry size. + if (DataEntry->Size % sizeof(debug_directory) != 0) + return object_error::parse_failed; + + uintptr_t IntPtr = 0; + if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return EC; + DebugDirectoryBegin = reinterpret_cast<const debug_directory *>(IntPtr); + if (std::error_code EC = getRvaPtr( + DataEntry->RelativeVirtualAddress + DataEntry->Size, IntPtr)) + return EC; + DebugDirectoryEnd = reinterpret_cast<const debug_directory *>(IntPtr); + return std::error_code(); +} + COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), - ImportDirectory(nullptr), NumberOfImportDirectory(0), + ImportDirectory(nullptr), DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), - ExportDirectory(nullptr), BaseRelocHeader(nullptr), - BaseRelocEnd(nullptr) { + ExportDirectory(nullptr), BaseRelocHeader(nullptr), BaseRelocEnd(nullptr), + DebugDirectoryBegin(nullptr), DebugDirectoryEnd(nullptr) { // Check that we at least have enough room for a header. if (!checkSize(Data, EC, sizeof(coff_file_header))) return; @@ -672,6 +749,10 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) if ((EC = initBaseRelocPtr())) return; + // Initialize the pointer to the export table. + if ((EC = initDebugDirectoryPtr())) + return; + EC = std::error_code(); } @@ -689,13 +770,17 @@ basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { } import_directory_iterator COFFObjectFile::import_directory_begin() const { + if (!ImportDirectory) + return import_directory_end(); + if (ImportDirectory[0].ImportLookupTableRVA == 0) + return import_directory_end(); return import_directory_iterator( ImportDirectoryEntryRef(ImportDirectory, 0, this)); } import_directory_iterator COFFObjectFile::import_directory_end() const { return import_directory_iterator( - ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); + ImportDirectoryEntryRef(nullptr, -1, this)); } delay_import_directory_iterator @@ -947,10 +1032,10 @@ uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { std::error_code COFFObjectFile::getSectionContents(const coff_section *Sec, ArrayRef<uint8_t> &Res) const { - // PointerToRawData and SizeOfRawData won't make sense for BSS sections, - // don't do anything interesting for them. - assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && - "BSS sections don't have contents!"); + // In COFF, a virtual section won't have any in-file + // content, so the file pointer to the content will be zero. + if (Sec->PointerToRawData == 0) + return object_error::parse_failed; // The only thing that we need to verify is that the contents is contained // within the file bounds. We don't need to make sure it doesn't cover other // data, as there's nothing that says that is not allowed. @@ -1116,12 +1201,15 @@ operator==(const ImportDirectoryEntryRef &Other) const { void ImportDirectoryEntryRef::moveNext() { ++Index; + if (ImportTable[Index].ImportLookupTableRVA == 0) { + Index = -1; + ImportTable = nullptr; + } } std::error_code ImportDirectoryEntryRef::getImportTableEntry( const import_directory_table_entry *&Result) const { - Result = ImportTable + Index; - return std::error_code(); + return getObject(Result, OwningObject->Data, ImportTable + Index); } static imported_symbol_iterator @@ -1198,16 +1286,6 @@ ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { return std::error_code(); } -std::error_code ImportDirectoryEntryRef::getImportLookupEntry( - const import_lookup_table_entry32 *&Result) const { - uintptr_t IntPtr = 0; - uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; - if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) - return EC; - Result = reinterpret_cast<const import_lookup_table_entry32 *>(IntPtr); - return std::error_code(); -} - bool DelayImportDirectoryEntryRef:: operator==(const DelayImportDirectoryEntryRef &Other) const { return Table == Other.Table && Index == Other.Index; @@ -1391,6 +1469,22 @@ ImportedSymbolRef::getSymbolName(StringRef &Result) const { return std::error_code(); } +std::error_code ImportedSymbolRef::isOrdinal(bool &Result) const { + if (Entry32) + Result = Entry32[Index].isOrdinal(); + else + Result = Entry64[Index].isOrdinal(); + return std::error_code(); +} + +std::error_code ImportedSymbolRef::getHintNameRVA(uint32_t &Result) const { + if (Entry32) + Result = Entry32[Index].getHintNameRVA(); + else + Result = Entry64[Index].getHintNameRVA(); + return std::error_code(); +} + std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { uint32_t RVA; if (Entry32) { diff --git a/gnu/llvm/lib/Object/ELF.cpp b/gnu/llvm/lib/Object/ELF.cpp index 12b772d930b..2dde18a2428 100644 --- a/gnu/llvm/lib/Object/ELF.cpp +++ b/gnu/llvm/lib/Object/ELF.cpp @@ -61,6 +61,13 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { break; } break; + case ELF::EM_LANAI: + switch (Type) { +#include "llvm/Support/ELFRelocs/Lanai.def" + default: + break; + } + break; case ELF::EM_PPC: switch (Type) { #include "llvm/Support/ELFRelocs/PowerPC.def" @@ -98,6 +105,19 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { break; } break; + case ELF::EM_AMDGPU: + switch (Type) { +#include "llvm/Support/ELFRelocs/AMDGPU.def" + default: + break; + } + case ELF::EM_BPF: + switch (Type) { +#include "llvm/Support/ELFRelocs/BPF.def" + default: + break; + } + break; default: break; } diff --git a/gnu/llvm/lib/Object/ELFObjectFile.cpp b/gnu/llvm/lib/Object/ELFObjectFile.cpp index c7df30a5903..4bd69e34e3c 100644 --- a/gnu/llvm/lib/Object/ELFObjectFile.cpp +++ b/gnu/llvm/lib/Object/ELFObjectFile.cpp @@ -55,4 +55,71 @@ ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { return std::move(R); } +SubtargetFeatures ELFObjectFileBase::getFeatures() const { + switch (getEMachine()) { + case ELF::EM_MIPS: { + SubtargetFeatures Features; + unsigned PlatformFlags; + getPlatformFlags(PlatformFlags); + + switch (PlatformFlags & ELF::EF_MIPS_ARCH) { + case ELF::EF_MIPS_ARCH_1: + break; + case ELF::EF_MIPS_ARCH_2: + Features.AddFeature("mips2"); + break; + case ELF::EF_MIPS_ARCH_3: + Features.AddFeature("mips3"); + break; + case ELF::EF_MIPS_ARCH_4: + Features.AddFeature("mips4"); + break; + case ELF::EF_MIPS_ARCH_5: + Features.AddFeature("mips5"); + break; + case ELF::EF_MIPS_ARCH_32: + Features.AddFeature("mips32"); + break; + case ELF::EF_MIPS_ARCH_64: + Features.AddFeature("mips64"); + break; + case ELF::EF_MIPS_ARCH_32R2: + Features.AddFeature("mips32r2"); + break; + case ELF::EF_MIPS_ARCH_64R2: + Features.AddFeature("mips64r2"); + break; + case ELF::EF_MIPS_ARCH_32R6: + Features.AddFeature("mips32r6"); + break; + case ELF::EF_MIPS_ARCH_64R6: + Features.AddFeature("mips64r6"); + break; + default: + llvm_unreachable("Unknown EF_MIPS_ARCH value"); + } + + switch (PlatformFlags & ELF::EF_MIPS_MACH) { + case ELF::EF_MIPS_MACH_NONE: + // No feature associated with this value. + break; + case ELF::EF_MIPS_MACH_OCTEON: + Features.AddFeature("cnmips"); + break; + default: + llvm_unreachable("Unknown EF_MIPS_ARCH value"); + } + + if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16) + Features.AddFeature("mips16"); + if (PlatformFlags & ELF::EF_MIPS_MICROMIPS) + Features.AddFeature("micromips"); + + return Features; + } + default: + return SubtargetFeatures(); + } +} + } // end namespace llvm diff --git a/gnu/llvm/lib/Object/Error.cpp b/gnu/llvm/lib/Object/Error.cpp index 7ecc3a19af9..2357526b789 100644 --- a/gnu/llvm/lib/Object/Error.cpp +++ b/gnu/llvm/lib/Object/Error.cpp @@ -19,6 +19,9 @@ using namespace llvm; using namespace object; namespace { +// FIXME: This class is only here to support the transition to llvm::Error. It +// will be removed once this transition is complete. Clients should prefer to +// deal with the Error value directly, rather than converting to error_code. class _object_error_category : public std::error_category { public: const char* name() const LLVM_NOEXCEPT override; @@ -47,21 +50,45 @@ std::string _object_error_category::message(int EV) const { return "Invalid section index"; case object_error::bitcode_section_not_found: return "Bitcode section not found in object file"; - case object_error::elf_invalid_dynamic_table_size: - return "Invalid dynamic table size"; - 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."); } +char BinaryError::ID = 0; +char GenericBinaryError::ID = 0; + +GenericBinaryError::GenericBinaryError(Twine Msg) : Msg(Msg.str()) {} + +GenericBinaryError::GenericBinaryError(Twine Msg, object_error ECOverride) + : Msg(Msg.str()) { + setErrorCode(make_error_code(ECOverride)); +} + +void GenericBinaryError::log(raw_ostream &OS) const { + OS << Msg; +} + static ManagedStatic<_object_error_category> error_category; const std::error_category &object::object_category() { return *error_category; } + +llvm::Error llvm::object::isNotObjectErrorInvalidFileType(llvm::Error Err) { + if (auto Err2 = + handleErrors(std::move(Err), + [](std::unique_ptr<ECError> M) { + // Try to handle 'M'. If successful, return a success value from + // the handler. + if (M->convertToErrorCode() == object_error::invalid_file_type) + return Error::success(); + + // We failed to handle 'M' - return it from the handler. + // This value will be passed back from catchErrors and + // wind up in Err2, where it will be returned from this function. + return Error(std::move(M)); + })) + return Err2; + return Err; +} diff --git a/gnu/llvm/lib/Object/IRObjectFile.cpp b/gnu/llvm/lib/Object/IRObjectFile.cpp index c35c413b3c3..42c8ecd62da 100644 --- a/gnu/llvm/lib/Object/IRObjectFile.cpp +++ b/gnu/llvm/lib/Object/IRObjectFile.cpp @@ -24,9 +24,9 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.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" #include "llvm/Support/SourceMgr.h" @@ -38,12 +38,20 @@ using namespace object; IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) { Mang.reset(new Mangler()); + CollectAsmUndefinedRefs(Triple(M->getTargetTriple()), M->getModuleInlineAsm(), + [this](StringRef Name, BasicSymbolRef::Flags Flags) { + AsmSymbols.emplace_back(Name, std::move(Flags)); + }); +} - const std::string &InlineAsm = M->getModuleInlineAsm(); +// Parse inline ASM and collect the list of symbols that are not defined in +// the current module. This is inspired from IRObjectFile. +void IRObjectFile::CollectAsmUndefinedRefs( + const Triple &TT, StringRef InlineAsm, + function_ref<void(StringRef, BasicSymbolRef::Flags)> AsmUndefinedRefs) { if (InlineAsm.empty()) return; - Triple TT(M->getTargetTriple()); std::string Err; const Target *T = TargetRegistry::lookupTarget(TT.str(), Err); if (!T) @@ -68,7 +76,7 @@ IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) MCObjectFileInfo MOFI; MCContext MCCtx(MAI.get(), MRI.get(), &MOFI); - MOFI.InitMCObjectFileInfo(TT, Reloc::Default, CodeModel::Default, MCCtx); + MOFI.InitMCObjectFileInfo(TT, /*PIC*/ false, CodeModel::Default, MCCtx); std::unique_ptr<RecordStreamer> Streamer(new RecordStreamer(MCCtx)); T->createNullTargetStreamer(*Streamer); @@ -105,9 +113,12 @@ IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> Mod) Res |= BasicSymbolRef::SF_Undefined; Res |= BasicSymbolRef::SF_Global; break; + case RecordStreamer::GlobalWeak: + Res |= BasicSymbolRef::SF_Weak; + Res |= BasicSymbolRef::SF_Global; + break; } - AsmSymbols.push_back( - std::make_pair<std::string, uint32_t>(Key, std::move(Res))); + AsmUndefinedRefs(Key, BasicSymbolRef::Flags(Res)); } } @@ -231,13 +242,14 @@ uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { Res |= BasicSymbolRef::SF_Global; if (GV->hasCommonLinkage()) Res |= BasicSymbolRef::SF_Common; - if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) + if (GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || + GV->hasExternalWeakLinkage()) Res |= BasicSymbolRef::SF_Weak; if (GV->getName().startswith("llvm.")) Res |= BasicSymbolRef::SF_FormatSpecific; else if (auto *Var = dyn_cast<GlobalVariable>(GV)) { - if (Var->getSection() == StringRef("llvm.metadata")) + if (Var->getSection() == "llvm.metadata") Res |= BasicSymbolRef::SF_FormatSpecific; } @@ -265,10 +277,7 @@ basic_symbol_iterator IRObjectFile::symbol_end_impl() const { ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { for (const SectionRef &Sec : Obj.sections()) { - StringRef SecName; - if (std::error_code EC = Sec.getName(SecName)) - return EC; - if (SecName == ".llvmbc") { + if (Sec.isBitcode()) { StringRef SecContents; if (std::error_code EC = Sec.getContents(SecContents)) return EC; @@ -287,10 +296,10 @@ ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Ob case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::macho_object: case sys::fs::file_magic::coff_object: { - ErrorOr<std::unique_ptr<ObjectFile>> ObjFile = + Expected<std::unique_ptr<ObjectFile>> ObjFile = ObjectFile::createObjectFile(Object, Type); if (!ObjFile) - return ObjFile.getError(); + return errorToErrorCode(ObjFile.takeError()); return findBitcodeInObject(*ObjFile->get()); } default: @@ -305,8 +314,8 @@ llvm::object::IRObjectFile::create(MemoryBufferRef Object, if (!BCOrErr) return BCOrErr.getError(); - std::unique_ptr<MemoryBuffer> Buff( - MemoryBuffer::getMemBuffer(BCOrErr.get(), false)); + std::unique_ptr<MemoryBuffer> Buff = + MemoryBuffer::getMemBuffer(BCOrErr.get(), false); ErrorOr<std::unique_ptr<Module>> MOrErr = getLazyBitcodeModule(std::move(Buff), Context, diff --git a/gnu/llvm/lib/Object/MachOObjectFile.cpp b/gnu/llvm/lib/Object/MachOObjectFile.cpp index d1f79b225ee..563236f95a5 100644 --- a/gnu/llvm/lib/Object/MachOObjectFile.cpp +++ b/gnu/llvm/lib/Object/MachOObjectFile.cpp @@ -38,6 +38,13 @@ namespace { }; } +static Error +malformedError(Twine Msg) { + std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")"; + return make_error<GenericBinaryError>(std::move(StringMsg), + object_error::parse_failed); +} + // FIXME: Replace all uses of this function with getStructOrErr. template <typename T> static T getStruct(const MachOObjectFile *O, const char *P) { @@ -53,10 +60,10 @@ static T getStruct(const MachOObjectFile *O, const char *P) { } template <typename T> -static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) { +static Expected<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; + return malformedError("Structure read out-of-range"); T Cmd; memcpy(&Cmd, P, sizeof(T)); @@ -161,120 +168,180 @@ 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 Expected<MachOObjectFile::LoadCommandInfo> +getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr, + uint32_t LoadCommandIndex) { + if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) { + if (CmdOrErr->cmdsize < 8) + return malformedError("load command " + Twine(LoadCommandIndex) + + " with size less than 8 bytes"); + return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr}); + } else + return CmdOrErr.takeError(); } -static ErrorOr<MachOObjectFile::LoadCommandInfo> +static Expected<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)); + if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds) + return malformedError("load command 0 extends past the end all load " + "commands in the file"); + return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0); } -static ErrorOr<MachOObjectFile::LoadCommandInfo> -getNextLoadCommandInfo(const MachOObjectFile *Obj, +static Expected<MachOObjectFile::LoadCommandInfo> +getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex, const MachOObjectFile::LoadCommandInfo &L) { - return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize); + unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) + : sizeof(MachO::mach_header); + if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) > + Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds) + return malformedError("load command " + Twine(LoadCommandIndex + 1) + + " extends past the end all load commands in the file"); + return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1); } 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(); + Error &Err) { + if (sizeof(T) > Obj->getData().size()) { + Err = malformedError("the mach header extends past the end of the " + "file"); + return; + } + if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0))) + Header = *HeaderOrErr; else - EC = HeaderOrErr.getError(); + Err = HeaderOrErr.takeError(); } // 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( +static Error parseSegmentLoadCommand( const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, - SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment) { + SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment, + uint32_t LoadCommandIndex, const char *CmdName) { 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 = + return malformedError("load command " + Twine(LoadCommandIndex) + + " " + CmdName + " cmdsize too small"); + if (auto SegOrErr = getStructOrErr<SegmentCmd>(Obj, Load.Ptr)) { + 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(); + if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || + S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) + return malformedError("load command " + Twine(LoadCommandIndex) + + " inconsistent cmdsize in " + CmdName + + " for the number of 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); + } else + return SegOrErr.takeError(); + + return Error::success(); +} + +Expected<std::unique_ptr<MachOObjectFile>> +MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, + bool Is64Bits) { + Error Err; + std::unique_ptr<MachOObjectFile> Obj( + new MachOObjectFile(std::move(Object), IsLittleEndian, + Is64Bits, Err)); + if (Err) + return std::move(Err); + return std::move(Obj); } MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, - bool Is64bits, std::error_code &EC) + bool Is64bits, Error &Err) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), HasPageZeroSegment(false) { - if (is64Bit()) - parseHeader(this, Header64, EC); - else - parseHeader(this, Header, EC); - if (EC) + ErrorAsOutParameter ErrAsOutParam(Err); + uint64_t BigSize; + if (is64Bit()) { + parseHeader(this, Header64, Err); + BigSize = sizeof(MachO::mach_header_64); + } else { + parseHeader(this, Header, Err); + BigSize = sizeof(MachO::mach_header); + } + if (Err) return; + BigSize += getHeader().sizeofcmds; + if (getData().data() + BigSize > getData().end()) { + Err = malformedError("load commands extend past the end of the file"); + return; + } uint32_t LoadCommandCount = getHeader().ncmds; if (LoadCommandCount == 0) return; - auto LoadOrErr = getFirstLoadCommandInfo(this); - if (!LoadOrErr) { - EC = LoadOrErr.getError(); + LoadCommandInfo Load; + if (auto LoadOrErr = getFirstLoadCommandInfo(this)) + Load = *LoadOrErr; + else { + Err = LoadOrErr.takeError(); return; } - LoadCommandInfo Load = LoadOrErr.get(); + for (unsigned I = 0; I < LoadCommandCount; ++I) { + if (is64Bit()) { + if (Load.C.cmdsize % 8 != 0) { + // We have a hack here to allow 64-bit Mach-O core files to have + // LC_THREAD commands that are only a multiple of 4 and not 8 to be + // allowed since the macOS kernel produces them. + if (getHeader().filetype != MachO::MH_CORE || + Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { + Err = malformedError("load command " + Twine(I) + " cmdsize not a " + "multiple of 8"); + return; + } + } + } else { + if (Load.C.cmdsize % 4 != 0) { + Err = malformedError("load command " + Twine(I) + " cmdsize not a " + "multiple of 4"); + return; + } + } LoadCommands.push_back(Load); if (Load.C.cmd == MachO::LC_SYMTAB) { // Multiple symbol tables if (SymtabLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple symbol tables"); return; } SymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { // Multiple dynamic symbol tables if (DysymtabLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple dynamic symbol tables"); return; } DysymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { // Multiple data in code tables if (DataInCodeLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple data-in-code tables"); 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; + Err = malformedError("Multiple linker optimization hint tables"); return; } LinkOptHintsLoadCmd = Load.Ptr; @@ -282,24 +349,25 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { // Multiple dyldinfo load commands if (DyldInfoLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple dyldinfo load commands"); return; } DyldInfoLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_UUID) { // Multiple UUID load commands if (UuidLoadCmd) { - EC = object_error::parse_failed; + Err = malformedError("Multiple UUID load commands"); return; } UuidLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { - if ((EC = parseSegmentLoadCommand<MachO::segment_command_64>( - this, Load, Sections, HasPageZeroSegment))) + if ((Err = parseSegmentLoadCommand<MachO::segment_command_64>( + this, Load, Sections, HasPageZeroSegment, I, + "LC_SEGMENT_64"))) return; } else if (Load.C.cmd == MachO::LC_SEGMENT) { - if ((EC = parseSegmentLoadCommand<MachO::segment_command>( - this, Load, Sections, HasPageZeroSegment))) + if ((Err = parseSegmentLoadCommand<MachO::segment_command>( + this, Load, Sections, HasPageZeroSegment, I, "LC_SEGMENT"))) return; } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || @@ -309,15 +377,66 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, Libraries.push_back(Load.Ptr); } if (I < LoadCommandCount - 1) { - auto LoadOrErr = getNextLoadCommandInfo(this, Load); - if (!LoadOrErr) { - EC = LoadOrErr.getError(); + if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) + Load = *LoadOrErr; + else { + Err = LoadOrErr.takeError(); return; } - Load = LoadOrErr.get(); + } + } + if (!SymtabLoadCmd) { + if (DysymtabLoadCmd) { + Err = malformedError("contains LC_DYSYMTAB load command without a " + "LC_SYMTAB load command"); + return; + } + } else if (DysymtabLoadCmd) { + MachO::symtab_command Symtab = + getStruct<MachO::symtab_command>(this, SymtabLoadCmd); + MachO::dysymtab_command Dysymtab = + getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); + if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { + Err = malformedError("ilocalsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + uint64_t BigSize = Dysymtab.ilocalsym; + BigSize += Dysymtab.nlocalsym; + if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " + "command extends past the end of the symbol table"); + return; + } + if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { + Err = malformedError("nextdefsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + BigSize = Dysymtab.iextdefsym; + BigSize += Dysymtab.nextdefsym; + if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " + "load command extends past the end of the symbol " + "table"); + return; + } + if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { + Err = malformedError("nundefsym in LC_DYSYMTAB load command " + "extends past the end of the symbol table"); + return; + } + BigSize = Dysymtab.iundefsym; + BigSize += Dysymtab.nundefsym; + if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { + Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " + " command extends past the end of the symbol table"); + return; } } assert(LoadCommands.size() == LoadCommandCount); + + Err = Error::success(); } void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { @@ -327,13 +446,14 @@ void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.p += SymbolTableEntrySize; } -ErrorOr<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { +Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 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."); + if (Start < getData().begin() || Start >= getData().end()) { + return malformedError("bad string index: " + Twine(Entry.n_strx) + + " for symbol at index " + Twine(getSymbolIndex(Symb))); + } return StringRef(Start); } @@ -372,7 +492,7 @@ uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { return getNValue(Sym); } -ErrorOr<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { +Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { return getSymbolValue(Sym); } @@ -389,7 +509,8 @@ uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { return getNValue(DRI); } -SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const { +Expected<SymbolRef::Type> +MachOObjectFile::getSymbolType(DataRefImpl Symb) const { MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t n_type = Entry.n_type; @@ -401,7 +522,10 @@ SymbolRef::Type MachOObjectFile::getSymbolType(DataRefImpl Symb) const { case MachO::N_UNDF : return SymbolRef::ST_Unknown; case MachO::N_SECT : - section_iterator Sec = *getSymbolSection(Symb); + Expected<section_iterator> SecOrError = getSymbolSection(Symb); + if (!SecOrError) + return SecOrError.takeError(); + section_iterator Sec = *SecOrError; if (Sec->isData() || Sec->isBSS()) return SymbolRef::ST_Data; return SymbolRef::ST_Function; @@ -448,7 +572,7 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { return Result; } -ErrorOr<section_iterator> +Expected<section_iterator> MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); uint8_t index = Entry.n_sect; @@ -457,8 +581,10 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { return section_end(); DataRefImpl DRI; DRI.d.a = index - 1; - if (DRI.d.a >= Sections.size()) - report_fatal_error("getSymbolSection: Invalid section index."); + if (DRI.d.a >= Sections.size()){ + return malformedError("bad section index: " + Twine((int)index) + + " for symbol at index " + Twine(getSymbolIndex(Symb))); + } return section_iterator(SectionRef(DRI, this)); } @@ -546,6 +672,10 @@ uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { return uint64_t(1) << Align; } +bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { + return false; +} + bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { uint32_t Flags = getSectionFlags(this, Sec); return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; @@ -576,6 +706,14 @@ bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; } +bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { + StringRef SegmentName = getSectionFinalSegmentName(Sec); + StringRef SectName; + if (!getSectionName(Sec, SectName)) + return (SegmentName == "__LLVM" && SectName == "__bitcode"); + return false; +} + relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl Ret; Ret.d.a = Sec.d.a; @@ -942,15 +1080,20 @@ MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { } basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { + DataRefImpl DRI; + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd || Symtab.nsyms == 0) + return basic_symbol_iterator(SymbolRef(DRI, this)); + return getSymbolByIndex(0); } basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { DataRefImpl DRI; - if (!SymtabLoadCmd) + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd || Symtab.nsyms == 0) return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); @@ -961,20 +1104,29 @@ basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { } basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { - DataRefImpl DRI; - if (!SymtabLoadCmd) - return basic_symbol_iterator(SymbolRef(DRI, this)); - MachO::symtab_command Symtab = getSymtabLoadCommand(); - if (Index >= Symtab.nsyms) + if (!SymtabLoadCmd || Index >= Symtab.nsyms) report_fatal_error("Requested symbol index is out of range."); unsigned SymbolTableEntrySize = is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); + DataRefImpl DRI; DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); DRI.p += Index * SymbolTableEntrySize; return basic_symbol_iterator(SymbolRef(DRI, this)); } +uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { + MachO::symtab_command Symtab = getSymtabLoadCommand(); + if (!SymtabLoadCmd) + report_fatal_error("getSymbolIndex() called with no symbol table symbol"); + unsigned SymbolTableEntrySize = + is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); + DataRefImpl DRIstart; + DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); + uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; + return Index; +} + section_iterator MachOObjectFile::section_begin() const { DataRefImpl DRI; return section_iterator(SectionRef(DRI, this)); @@ -1036,8 +1188,8 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { } } -Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault) { +Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault) { if (McpuDefault) *McpuDefault = nullptr; @@ -1077,13 +1229,13 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, case MachO::CPU_SUBTYPE_ARM_V7EM: if (McpuDefault) *McpuDefault = "cortex-m4"; - return Triple("armv7em-apple-darwin"); + return Triple("thumbv7em-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7K: return Triple("armv7k-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7M: if (McpuDefault) *McpuDefault = "cortex-m3"; - return Triple("armv7m-apple-darwin"); + return Triple("thumbv7m-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7S: return Triple("armv7s-apple-darwin"); default: @@ -1115,56 +1267,6 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, } } -Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault) { - if (McpuDefault) - *McpuDefault = nullptr; - - switch (CPUType) { - case MachO::CPU_TYPE_ARM: - switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { - case MachO::CPU_SUBTYPE_ARM_V4T: - return Triple("thumbv4t-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V5TEJ: - return Triple("thumbv5e-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_XSCALE: - return Triple("xscale-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V6: - return Triple("thumbv6-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V6M: - if (McpuDefault) - *McpuDefault = "cortex-m0"; - return Triple("thumbv6m-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7: - return Triple("thumbv7-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7EM: - if (McpuDefault) - *McpuDefault = "cortex-m4"; - return Triple("thumbv7em-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7K: - return Triple("thumbv7k-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7M: - if (McpuDefault) - *McpuDefault = "cortex-m3"; - return Triple("thumbv7m-apple-darwin"); - case MachO::CPU_SUBTYPE_ARM_V7S: - return Triple("thumbv7s-apple-darwin"); - default: - return Triple(); - } - default: - return Triple(); - } -} - -Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, - const char **McpuDefault, Triple *ThumbTriple) { - Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); - *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, - McpuDefault); - return T; -} - Triple MachOObjectFile::getHostArch() { return Triple(sys::getDefaultTargetTriple()); } @@ -1194,10 +1296,8 @@ unsigned MachOObjectFile::getArch() const { return getArch(getCPUType(this)); } -Triple MachOObjectFile::getArch(const char **McpuDefault, - Triple *ThumbTriple) const { - *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault); - return getArch(Header.cputype, Header.cpusubtype, McpuDefault); +Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { + return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); } relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { @@ -2307,23 +2407,17 @@ bool MachOObjectFile::isRelocatableObject() const { return getHeader().filetype == MachO::MH_OBJECT; } -ErrorOr<std::unique_ptr<MachOObjectFile>> +Expected<std::unique_ptr<MachOObjectFile>> ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { StringRef Magic = Buffer.getBuffer().slice(0, 4); - std::error_code EC; - std::unique_ptr<MachOObjectFile> Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); - else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); - else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); - else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); - else - return object_error::parse_failed; - - if (EC) - return EC; - return std::move(Ret); + return MachOObjectFile::create(Buffer, false, false); + if (Magic == "\xCE\xFA\xED\xFE") + return MachOObjectFile::create(Buffer, true, false); + if (Magic == "\xFE\xED\xFA\xCF") + return MachOObjectFile::create(Buffer, false, true); + if (Magic == "\xCF\xFA\xED\xFE") + return MachOObjectFile::create(Buffer, true, true); + return make_error<GenericBinaryError>("Unrecognized MachO magic number", + object_error::invalid_file_type); } diff --git a/gnu/llvm/lib/Object/MachOUniversal.cpp b/gnu/llvm/lib/Object/MachOUniversal.cpp index a1c83b9b7f8..66c9151eb69 100644 --- a/gnu/llvm/lib/Object/MachOUniversal.cpp +++ b/gnu/llvm/lib/Object/MachOUniversal.cpp @@ -22,22 +22,11 @@ using namespace llvm; using namespace object; -template<typename T> -static void SwapStruct(T &Value); - -template<> -void SwapStruct(MachO::fat_header &H) { - sys::swapByteOrder(H.magic); - sys::swapByteOrder(H.nfat_arch); -} - -template<> -void SwapStruct(MachO::fat_arch &H) { - sys::swapByteOrder(H.cputype); - sys::swapByteOrder(H.cpusubtype); - sys::swapByteOrder(H.offset); - sys::swapByteOrder(H.size); - sys::swapByteOrder(H.align); +static Error +malformedError(Twine Msg) { + std::string StringMsg = "truncated or malformed fat file (" + Msg.str() + ")"; + return make_error<GenericBinaryError>(std::move(StringMsg), + object_error::parse_failed); } template<typename T> @@ -46,7 +35,7 @@ static T getUniversalBinaryStruct(const char *Ptr) { memcpy(&Res, Ptr, sizeof(T)); // Universal binary headers have big-endian byte order. if (sys::IsLittleEndianHost) - SwapStruct(Res); + swapStruct(Res); return Res; } @@ -58,34 +47,53 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch( } else { // Parse object header. StringRef ParentData = Parent->getData(); - const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) + - Index * sizeof(MachO::fat_arch); - Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos); - if (ParentData.size() < Header.offset + Header.size) { - clear(); + if (Parent->getMagic() == MachO::FAT_MAGIC) { + const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) + + Index * sizeof(MachO::fat_arch); + Header = getUniversalBinaryStruct<MachO::fat_arch>(HeaderPos); + if (ParentData.size() < Header.offset + Header.size) { + clear(); + } + } else { // Parent->getMagic() == MachO::FAT_MAGIC_64 + const char *HeaderPos = ParentData.begin() + sizeof(MachO::fat_header) + + Index * sizeof(MachO::fat_arch_64); + Header64 = getUniversalBinaryStruct<MachO::fat_arch_64>(HeaderPos); + if (ParentData.size() < Header64.offset + Header64.size) { + clear(); + } } } } -ErrorOr<std::unique_ptr<MachOObjectFile>> +Expected<std::unique_ptr<MachOObjectFile>> MachOUniversalBinary::ObjectForArch::getAsObjectFile() const { if (!Parent) - return object_error::parse_failed; + report_fatal_error("MachOUniversalBinary::ObjectForArch::getAsObjectFile() " + "called when Parent is a nullptr"); StringRef ParentData = Parent->getData(); - StringRef ObjectData = ParentData.substr(Header.offset, Header.size); + StringRef ObjectData; + if (Parent->getMagic() == MachO::FAT_MAGIC) + ObjectData = ParentData.substr(Header.offset, Header.size); + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + ObjectData = ParentData.substr(Header64.offset, Header64.size); StringRef ObjectName = Parent->getFileName(); MemoryBufferRef ObjBuffer(ObjectData, ObjectName); return ObjectFile::createMachOObjectFile(ObjBuffer); } -ErrorOr<std::unique_ptr<Archive>> +Expected<std::unique_ptr<Archive>> MachOUniversalBinary::ObjectForArch::getAsArchive() const { if (!Parent) - return object_error::parse_failed; + report_fatal_error("MachOUniversalBinary::ObjectForArch::getAsArchive() " + "called when Parent is a nullptr"); StringRef ParentData = Parent->getData(); - StringRef ObjectData = ParentData.substr(Header.offset, Header.size); + StringRef ObjectData; + if (Parent->getMagic() == MachO::FAT_MAGIC) + ObjectData = ParentData.substr(Header.offset, Header.size); + else // Parent->getMagic() == MachO::FAT_MAGIC_64 + ObjectData = ParentData.substr(Header64.offset, Header64.size); StringRef ObjectName = Parent->getFileName(); MemoryBufferRef ObjBuffer(ObjectData, ObjectName); return Archive::create(ObjBuffer); @@ -93,44 +101,64 @@ MachOUniversalBinary::ObjectForArch::getAsArchive() const { void MachOUniversalBinary::anchor() { } -ErrorOr<std::unique_ptr<MachOUniversalBinary>> +Expected<std::unique_ptr<MachOUniversalBinary>> MachOUniversalBinary::create(MemoryBufferRef Source) { - std::error_code EC; + Error Err; std::unique_ptr<MachOUniversalBinary> Ret( - new MachOUniversalBinary(Source, EC)); - if (EC) - return EC; + new MachOUniversalBinary(Source, Err)); + if (Err) + return std::move(Err); return std::move(Ret); } -MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, - std::error_code &ec) - : Binary(Binary::ID_MachOUniversalBinary, Source), NumberOfObjects(0) { +MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, Error &Err) + : Binary(Binary::ID_MachOUniversalBinary, Source), Magic(0), + NumberOfObjects(0) { + ErrorAsOutParameter ErrAsOutParam(Err); if (Data.getBufferSize() < sizeof(MachO::fat_header)) { - ec = object_error::invalid_file_type; + Err = make_error<GenericBinaryError>("File too small to be a Mach-O " + "universal file", + object_error::invalid_file_type); return; } // Check for magic value and sufficient header size. StringRef Buf = getData(); - MachO::fat_header H= getUniversalBinaryStruct<MachO::fat_header>(Buf.begin()); + MachO::fat_header H = + getUniversalBinaryStruct<MachO::fat_header>(Buf.begin()); + Magic = H.magic; NumberOfObjects = H.nfat_arch; - uint32_t MinSize = sizeof(MachO::fat_header) + - sizeof(MachO::fat_arch) * NumberOfObjects; - if (H.magic != MachO::FAT_MAGIC || Buf.size() < MinSize) { - ec = object_error::parse_failed; + uint32_t MinSize = sizeof(MachO::fat_header); + if (Magic == MachO::FAT_MAGIC) + MinSize += sizeof(MachO::fat_arch) * NumberOfObjects; + else if (Magic == MachO::FAT_MAGIC_64) + MinSize += sizeof(MachO::fat_arch_64) * NumberOfObjects; + else { + Err = malformedError("bad magic number"); + return; + } + if (Buf.size() < MinSize) { + Err = malformedError("fat_arch" + + Twine(Magic == MachO::FAT_MAGIC ? "" : "_64") + + " structs would extend past the end of the file"); return; } - ec = std::error_code(); + Err = Error::success(); } -ErrorOr<std::unique_ptr<MachOObjectFile>> +Expected<std::unique_ptr<MachOObjectFile>> MachOUniversalBinary::getObjectForArch(StringRef ArchName) const { if (Triple(ArchName).getArch() == Triple::ArchType::UnknownArch) - return object_error::arch_not_found; + return make_error<GenericBinaryError>("Unknown architecture " + "named: " + + ArchName, + object_error::arch_not_found); for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) { if (I->getArchTypeName() == ArchName) return I->getAsObjectFile(); } - return object_error::arch_not_found; + return make_error<GenericBinaryError>("fat file does not " + "contain " + + ArchName, + object_error::arch_not_found); } diff --git a/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp b/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp new file mode 100644 index 00000000000..e6b1040d8f5 --- /dev/null +++ b/gnu/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp @@ -0,0 +1,126 @@ +//===- ModuleSummaryIndexObjectFile.cpp - Summary index file implementation ==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Part of the ModuleSummaryIndexObjectFile class implementation. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/ModuleSummaryIndexObjectFile.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/ModuleSummaryIndex.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; +using namespace object; + +ModuleSummaryIndexObjectFile::ModuleSummaryIndexObjectFile( + MemoryBufferRef Object, std::unique_ptr<ModuleSummaryIndex> I) + : SymbolicFile(Binary::ID_ModuleSummaryIndex, Object), Index(std::move(I)) { +} + +ModuleSummaryIndexObjectFile::~ModuleSummaryIndexObjectFile() {} + +std::unique_ptr<ModuleSummaryIndex> ModuleSummaryIndexObjectFile::takeIndex() { + return std::move(Index); +} + +ErrorOr<MemoryBufferRef> +ModuleSummaryIndexObjectFile::findBitcodeInObject(const ObjectFile &Obj) { + for (const SectionRef &Sec : Obj.sections()) { + if (Sec.isBitcode()) { + StringRef SecContents; + if (std::error_code EC = Sec.getContents(SecContents)) + return EC; + return MemoryBufferRef(SecContents, Obj.getFileName()); + } + } + + return object_error::bitcode_section_not_found; +} + +ErrorOr<MemoryBufferRef> +ModuleSummaryIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { + sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); + switch (Type) { + case sys::fs::file_magic::bitcode: + return Object; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + Expected<std::unique_ptr<ObjectFile>> ObjFile = + ObjectFile::createObjectFile(Object, Type); + if (!ObjFile) + return errorToErrorCode(ObjFile.takeError()); + return findBitcodeInObject(*ObjFile->get()); + } + default: + return object_error::invalid_file_type; + } +} + +// Looks for module summary index in the given memory buffer. +// returns true if found, else false. +bool ModuleSummaryIndexObjectFile::hasGlobalValueSummaryInMemBuffer( + MemoryBufferRef Object, + const DiagnosticHandlerFunction &DiagnosticHandler) { + ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); + if (!BCOrErr) + return false; + + return hasGlobalValueSummary(BCOrErr.get(), DiagnosticHandler); +} + +// Parse module summary index in the given memory buffer. +// Return new ModuleSummaryIndexObjectFile instance containing parsed +// module summary/index. +ErrorOr<std::unique_ptr<ModuleSummaryIndexObjectFile>> +ModuleSummaryIndexObjectFile::create( + MemoryBufferRef Object, + const DiagnosticHandlerFunction &DiagnosticHandler) { + std::unique_ptr<ModuleSummaryIndex> Index; + + ErrorOr<MemoryBufferRef> BCOrErr = findBitcodeInMemBuffer(Object); + if (!BCOrErr) + return BCOrErr.getError(); + + ErrorOr<std::unique_ptr<ModuleSummaryIndex>> IOrErr = + getModuleSummaryIndex(BCOrErr.get(), DiagnosticHandler); + + if (std::error_code EC = IOrErr.getError()) + return EC; + + Index = std::move(IOrErr.get()); + + return llvm::make_unique<ModuleSummaryIndexObjectFile>(Object, + std::move(Index)); +} + +// Parse the module summary index out of an IR file and return the summary +// index object if found, or nullptr if not. +ErrorOr<std::unique_ptr<ModuleSummaryIndex>> llvm::getModuleSummaryIndexForFile( + StringRef Path, const DiagnosticHandlerFunction &DiagnosticHandler) { + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(Path); + std::error_code EC = FileOrErr.getError(); + if (EC) + return EC; + MemoryBufferRef BufferRef = (FileOrErr.get())->getMemBufferRef(); + ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr = + object::ModuleSummaryIndexObjectFile::create(BufferRef, + DiagnosticHandler); + EC = ObjOrErr.getError(); + if (EC) + return EC; + + object::ModuleSummaryIndexObjectFile &Obj = **ObjOrErr; + return Obj.takeIndex(); +} diff --git a/gnu/llvm/lib/Object/Object.cpp b/gnu/llvm/lib/Object/Object.cpp index b44c1a16fd0..6df481b060e 100644 --- a/gnu/llvm/lib/Object/Object.cpp +++ b/gnu/llvm/lib/Object/Object.cpp @@ -61,11 +61,14 @@ wrap(const relocation_iterator *SI) { // ObjectFile creation LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { std::unique_ptr<MemoryBuffer> Buf(unwrap(MemBuf)); - ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr( + Expected<std::unique_ptr<ObjectFile>> ObjOrErr( ObjectFile::createObjectFile(Buf->getMemBufferRef())); std::unique_ptr<ObjectFile> Obj; - if (!ObjOrErr) + if (!ObjOrErr) { + // TODO: Actually report errors helpfully. + consumeError(ObjOrErr.takeError()); return nullptr; + } auto *Ret = new OwningBinary<ObjectFile>(std::move(ObjOrErr.get()), std::move(Buf)); return wrap(Ret); @@ -98,9 +101,14 @@ void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, LLVMSymbolIteratorRef Sym) { - ErrorOr<section_iterator> SecOrErr = (*unwrap(Sym))->getSection(); - if (std::error_code ec = SecOrErr.getError()) - report_fatal_error(ec.message()); + Expected<section_iterator> SecOrErr = (*unwrap(Sym))->getSection(); + if (!SecOrErr) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(SecOrErr.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } *unwrap(Sect) = *SecOrErr; } @@ -175,16 +183,26 @@ void LLVMMoveToNextRelocation(LLVMRelocationIteratorRef SI) { // SymbolRef accessors const char *LLVMGetSymbolName(LLVMSymbolIteratorRef SI) { - ErrorOr<StringRef> Ret = (*unwrap(SI))->getName(); - if (std::error_code EC = Ret.getError()) - report_fatal_error(EC.message()); + Expected<StringRef> Ret = (*unwrap(SI))->getName(); + if (!Ret) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(Ret.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } return Ret->data(); } uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI) { - ErrorOr<uint64_t> Ret = (*unwrap(SI))->getAddress(); - if (std::error_code EC = Ret.getError()) - report_fatal_error(EC.message()); + Expected<uint64_t> Ret = (*unwrap(SI))->getAddress(); + if (!Ret) { + std::string Buf; + raw_string_ostream OS(Buf); + logAllUnhandledErrors(Ret.takeError(), OS, ""); + OS.flush(); + report_fatal_error(Buf); + } return *Ret; } diff --git a/gnu/llvm/lib/Object/ObjectFile.cpp b/gnu/llvm/lib/Object/ObjectFile.cpp index d12dc411361..92f9c1f4f0a 100644 --- a/gnu/llvm/lib/Object/ObjectFile.cpp +++ b/gnu/llvm/lib/Object/ObjectFile.cpp @@ -29,9 +29,12 @@ ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source) : SymbolicFile(Type, Source) {} bool SectionRef::containsSymbol(SymbolRef S) const { - ErrorOr<section_iterator> SymSec = S.getSection(); - if (!SymSec) + Expected<section_iterator> SymSec = S.getSection(); + if (!SymSec) { + // TODO: Actually report errors helpfully. + consumeError(SymSec.takeError()); return false; + } return *this == **SymSec; } @@ -46,20 +49,27 @@ uint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const { std::error_code ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { - ErrorOr<StringRef> Name = getSymbolName(Symb); - if (std::error_code EC = Name.getError()) - return EC; + Expected<StringRef> Name = getSymbolName(Symb); + if (!Name) + return errorToErrorCode(Name.takeError()); OS << *Name; return std::error_code(); } uint32_t ObjectFile::getSymbolAlignment(DataRefImpl DRI) const { return 0; } +bool ObjectFile::isSectionBitcode(DataRefImpl Sec) const { + StringRef SectName; + if (!getSectionName(Sec, SectName)) + return SectName == ".llvmbc"; + return false; +} + section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); } -ErrorOr<std::unique_ptr<ObjectFile>> +Expected<std::unique_ptr<ObjectFile>> ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { StringRef Data = Object.getBuffer(); if (Type == sys::fs::file_magic::unknown) @@ -71,13 +81,13 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: - return object_error::invalid_file_type; + return errorCodeToError(object_error::invalid_file_type); case sys::fs::file_magic::elf: case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: case sys::fs::file_magic::elf_core: - return createELFObjectFile(Object); + return errorOrToExpected(createELFObjectFile(Object)); case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: @@ -93,23 +103,23 @@ ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return createCOFFObjectFile(Object); + return errorOrToExpected(createCOFFObjectFile(Object)); } llvm_unreachable("Unexpected Object File Type"); } -ErrorOr<OwningBinary<ObjectFile>> +Expected<OwningBinary<ObjectFile>> ObjectFile::createObjectFile(StringRef ObjectPath) { ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = MemoryBuffer::getFile(ObjectPath); if (std::error_code EC = FileOrErr.getError()) - return EC; + return errorCodeToError(EC); std::unique_ptr<MemoryBuffer> Buffer = std::move(FileOrErr.get()); - ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = + Expected<std::unique_ptr<ObjectFile>> ObjOrErr = createObjectFile(Buffer->getMemBufferRef()); - if (std::error_code EC = ObjOrErr.getError()) - return EC; + if (!ObjOrErr) + ObjOrErr.takeError(); std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get()); return OwningBinary<ObjectFile>(std::move(Obj), std::move(Buffer)); diff --git a/gnu/llvm/lib/Object/RecordStreamer.cpp b/gnu/llvm/lib/Object/RecordStreamer.cpp index 42dbd3e0c2d..f03bd5e5fb9 100644 --- a/gnu/llvm/lib/Object/RecordStreamer.cpp +++ b/gnu/llvm/lib/Object/RecordStreamer.cpp @@ -23,21 +23,26 @@ void RecordStreamer::markDefined(const MCSymbol &Symbol) { case Used: S = Defined; break; + case GlobalWeak: + break; } } -void RecordStreamer::markGlobal(const MCSymbol &Symbol) { +void RecordStreamer::markGlobal(const MCSymbol &Symbol, + MCSymbolAttr Attribute) { State &S = Symbols[Symbol.getName()]; switch (S) { case DefinedGlobal: case Defined: - S = DefinedGlobal; + S = (Attribute == MCSA_Weak) ? GlobalWeak : DefinedGlobal; break; case NeverSeen: case Global: case Used: - S = Global; + S = (Attribute == MCSA_Weak) ? GlobalWeak : Global; + break; + case GlobalWeak: break; } } @@ -48,6 +53,7 @@ void RecordStreamer::markUsed(const MCSymbol &Symbol) { case DefinedGlobal: case Defined: case Global: + case GlobalWeak: break; case NeverSeen: @@ -84,8 +90,8 @@ void RecordStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { bool RecordStreamer::EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) { - if (Attribute == MCSA_Global) - markGlobal(*Symbol); + if (Attribute == MCSA_Global || Attribute == MCSA_Weak) + markGlobal(*Symbol, Attribute); return true; } diff --git a/gnu/llvm/lib/Object/RecordStreamer.h b/gnu/llvm/lib/Object/RecordStreamer.h index d8610610c33..71337a60591 100644 --- a/gnu/llvm/lib/Object/RecordStreamer.h +++ b/gnu/llvm/lib/Object/RecordStreamer.h @@ -15,12 +15,12 @@ namespace llvm { class RecordStreamer : public MCStreamer { public: - enum State { NeverSeen, Global, Defined, DefinedGlobal, Used }; + enum State { NeverSeen, Global, GlobalWeak, Defined, DefinedGlobal, Used }; private: StringMap<State> Symbols; void markDefined(const MCSymbol &Symbol); - void markGlobal(const MCSymbol &Symbol); + void markGlobal(const MCSymbol &Symbol, MCSymbolAttr Attribute); void markUsed(const MCSymbol &Symbol); void visitUsedSymbol(const MCSymbol &Sym) override; diff --git a/gnu/llvm/lib/Object/SymbolicFile.cpp b/gnu/llvm/lib/Object/SymbolicFile.cpp index bf79dfb8da6..1e8e31b6b22 100644 --- a/gnu/llvm/lib/Object/SymbolicFile.cpp +++ b/gnu/llvm/lib/Object/SymbolicFile.cpp @@ -26,7 +26,7 @@ SymbolicFile::SymbolicFile(unsigned int Type, MemoryBufferRef Source) SymbolicFile::~SymbolicFile() {} -ErrorOr<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( +Expected<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( MemoryBufferRef Object, sys::fs::file_magic Type, LLVMContext *Context) { StringRef Data = Object.getBuffer(); if (Type == sys::fs::file_magic::unknown) @@ -35,13 +35,13 @@ ErrorOr<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( switch (Type) { case sys::fs::file_magic::bitcode: if (Context) - return IRObjectFile::create(Object, *Context); + return errorOrToExpected(IRObjectFile::create(Object, *Context)); // Fallthrough case sys::fs::file_magic::unknown: case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: - return object_error::invalid_file_type; + return errorCodeToError(object_error::invalid_file_type); case sys::fs::file_magic::elf: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: @@ -63,7 +63,7 @@ ErrorOr<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::macho_object: case sys::fs::file_magic::coff_object: { - ErrorOr<std::unique_ptr<ObjectFile>> Obj = + Expected<std::unique_ptr<ObjectFile>> Obj = ObjectFile::createObjectFile(Object, Type); if (!Obj || !Context) return std::move(Obj); @@ -73,9 +73,9 @@ ErrorOr<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( if (!BCData) return std::move(Obj); - return IRObjectFile::create( - MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()), - *Context); + return errorOrToExpected(IRObjectFile::create( + MemoryBufferRef(BCData->getBuffer(), + Object.getBufferIdentifier()), *Context)); } } llvm_unreachable("Unexpected Binary File Type"); |
