ErrorOr<std::vector<MemoryBufferRef>> BinaryHolder::MapArchiveAndGetMemberBuffers( StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) { StringRef ArchiveFilename = Filename.substr(0, Filename.find('(')); auto ErrOrBuff = MemoryBuffer::getFileOrSTDIN(ArchiveFilename); if (auto Err = ErrOrBuff.getError()) return Err; if (Verbose) outs() << "\topened new archive '" << ArchiveFilename << "'\n"; changeBackingMemoryBuffer(std::move(*ErrOrBuff)); std::vector<MemoryBufferRef> ArchiveBuffers; auto ErrOrFat = object::MachOUniversalBinary::create( CurrentMemoryBuffer->getMemBufferRef()); if (!ErrOrFat) { consumeError(ErrOrFat.takeError()); // Not a fat binary must be a standard one. ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef()); } else { CurrentFatBinary = std::move(*ErrOrFat); CurrentFatBinaryName = ArchiveFilename; ArchiveBuffers = getMachOFatMemoryBuffers( CurrentFatBinaryName, *CurrentMemoryBuffer, *CurrentFatBinary); } for (auto MemRef : ArchiveBuffers) { auto ErrOrArchive = object::Archive::create(MemRef); if (!ErrOrArchive) return errorToErrorCode(ErrOrArchive.takeError()); CurrentArchives.push_back(std::move(*ErrOrArchive)); } return GetArchiveMemberBuffers(Filename, Timestamp); }
ErrorOr<std::vector<MemoryBufferRef>> BinaryHolder::GetArchiveMemberBuffers( StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) { if (CurrentArchives.empty()) return make_error_code(errc::no_such_file_or_directory); StringRef CurArchiveName = CurrentArchives.front()->getFileName(); if (!Filename.startswith(Twine(CurArchiveName, "(").str())) return make_error_code(errc::no_such_file_or_directory); // Remove the archive name and the parens around the archive member name. Filename = Filename.substr(CurArchiveName.size() + 1).drop_back(); std::vector<MemoryBufferRef> Buffers; Buffers.reserve(CurrentArchives.size()); for (const auto &CurrentArchive : CurrentArchives) { Error Err = Error::success(); for (auto Child : CurrentArchive->children(Err)) { if (auto NameOrErr = Child.getName()) { if (*NameOrErr == Filename) { auto ModTimeOrErr = Child.getLastModified(); if (!ModTimeOrErr) return errorToErrorCode(ModTimeOrErr.takeError()); if (Timestamp != sys::TimePoint<>() && Timestamp != ModTimeOrErr.get()) { if (Verbose) outs() << "\tmember had timestamp mismatch.\n"; continue; } if (Verbose) outs() << "\tfound member in current archive.\n"; auto ErrOrMem = Child.getMemoryBufferRef(); if (!ErrOrMem) return errorToErrorCode(ErrOrMem.takeError()); Buffers.push_back(*ErrOrMem); } } } if (Err) return errorToErrorCode(std::move(Err)); } if (Buffers.empty()) return make_error_code(errc::no_such_file_or_directory); return Buffers; }
void ObjectFile::parse() { // Parse a memory buffer as a COFF file. auto BinOrErr = createBinary(MB); if (!BinOrErr) error(errorToErrorCode(BinOrErr.takeError()), "Failed to parse object file"); std::unique_ptr<Binary> Bin = std::move(*BinOrErr); if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) { Bin.release(); COFFObj.reset(Obj); } else { error(Twine(getName()) + " is not a COFF file."); } // Read section and symbol tables. initializeChunks(); initializeSymbols(); initializeSEH(); }
ErrorOr<std::vector<const object::ObjectFile *>> BinaryHolder::GetObjectFiles(StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) { auto ErrOrMemBufferRefs = GetMemoryBuffersForFile(Filename, Timestamp); if (auto Err = ErrOrMemBufferRefs.getError()) return Err; std::vector<const object::ObjectFile *> Objects; Objects.reserve(ErrOrMemBufferRefs->size()); CurrentObjectFiles.clear(); for (auto MemBuf : *ErrOrMemBufferRefs) { auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemBuf); if (!ErrOrObjectFile) return errorToErrorCode(ErrOrObjectFile.takeError()); Objects.push_back(ErrOrObjectFile->get()); CurrentObjectFiles.push_back(std::move(*ErrOrObjectFile)); } return std::move(Objects); }