diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h --- a/llvm/tools/llvm-objcopy/CopyConfig.h +++ b/llvm/tools/llvm-objcopy/CopyConfig.h @@ -236,10 +236,10 @@ // success or returns an Error otherwise. Error parseELFConfig() { if (!ELF) { - Expected ELFConfig = elf::parseConfig(*this); - if (!ELFConfig) + if (Expected ELFConfig = elf::parseConfig(*this)) + ELF = *ELFConfig; + else return ELFConfig.takeError(); - ELF = *ELFConfig; } return Error::success(); } diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -355,33 +355,35 @@ Error executeObjcopyOnBinary(const CopyConfig &Config, object::MachOObjectFile &In, Buffer &Out) { MachOReader Reader(In); - std::unique_ptr O = Reader.create(); - if (!O) - return createFileError( - Config.InputFilename, - createStringError(object_error::parse_failed, - "unable to deserialize MachO object")); - - if (Error E = handleArgs(Config, *O)) - return createFileError(Config.InputFilename, std::move(E)); - - // Page size used for alignment of segment sizes in Mach-O executables and - // dynamic libraries. - uint64_t PageSize; - switch (In.getArch()) { - case Triple::ArchType::arm: - case Triple::ArchType::aarch64: - case Triple::ArchType::aarch64_32: - PageSize = 16384; - break; - default: - PageSize = 4096; - } + if (Expected> O = Reader.create()) { + if (!*O) + return createFileError( + Config.InputFilename, + createStringError(object_error::parse_failed, + "unable to deserialize MachO object")); + + if (Error E = handleArgs(Config, **O)) + return createFileError(Config.InputFilename, std::move(E)); + + // Page size used for alignment of segment sizes in Mach-O executables and + // dynamic libraries. + uint64_t PageSize; + switch (In.getArch()) { + case Triple::ArchType::arm: + case Triple::ArchType::aarch64: + case Triple::ArchType::aarch64_32: + PageSize = 16384; + break; + default: + PageSize = 4096; + } - MachOWriter Writer(*O, In.is64Bit(), In.isLittleEndian(), PageSize, Out); - if (auto E = Writer.finalize()) - return E; - return Writer.write(); + MachOWriter Writer(**O, In.is64Bit(), In.isLittleEndian(), PageSize, Out); + if (auto E = Writer.finalize()) + return E; + return Writer.write(); + } else + return O.takeError(); } } // end namespace macho diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/tools/llvm-objcopy/MachO/MachOReader.h --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.h @@ -21,14 +21,14 @@ class Reader { public: virtual ~Reader(){}; - virtual std::unique_ptr create() const = 0; + virtual Expected> create() const = 0; }; class MachOReader : public Reader { const object::MachOObjectFile &MachOObj; void readHeader(Object &O) const; - void readLoadCommands(Object &O) const; + Error readLoadCommands(Object &O) const; void readSymbolTable(Object &O) const; void setSymbolInRelocationInfo(Object &O) const; void readRebaseInfo(Object &O) const; @@ -46,7 +46,7 @@ public: explicit MachOReader(const object::MachOObjectFile &Obj) : MachOObj(Obj) {} - std::unique_ptr create() const override; + Expected> create() const override; }; } // end namespace macho diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp @@ -59,9 +59,8 @@ return S; } -// TODO: get rid of reportError and make MachOReader return Expected<> instead. template -std::vector> +Expected>> extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd, const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex) { @@ -86,14 +85,14 @@ Expected SecRef = MachOObj.getSection(NextSectionIndex++); if (!SecRef) - reportError(MachOObj.getFileName(), SecRef.takeError()); + return errorWithContext(MachOObj.getFileName(), SecRef.takeError()); if (Expected> E = MachOObj.getSectionContents(SecRef->getRawDataRefImpl())) S.Content = StringRef(reinterpret_cast(E->data()), E->size()); else - reportError(MachOObj.getFileName(), E.takeError()); + return errorWithContext(MachOObj.getFileName(), E.takeError()); S.Relocations.reserve(S.NReloc); for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()), @@ -113,7 +112,7 @@ return Sections; } -void MachOReader::readLoadCommands(Object &O) const { +Error MachOReader::readLoadCommands(Object &O) const { // For MachO sections indices start from 1. uint32_t NextSectionIndex = 1; for (auto LoadCmd : MachOObj.load_commands()) { @@ -123,13 +122,20 @@ O.CodeSignatureCommandIndex = O.LoadCommands.size(); break; case MachO::LC_SEGMENT: - LC.Sections = extractSections( - LoadCmd, MachOObj, NextSectionIndex); + if (Expected>> Sections = + extractSections( + LoadCmd, MachOObj, NextSectionIndex)) + LC.Sections = std::move(*Sections); + else + return Sections.takeError(); break; case MachO::LC_SEGMENT_64: - LC.Sections = - extractSections( - LoadCmd, MachOObj, NextSectionIndex); + if (Expected>> Sections = + extractSections( + LoadCmd, MachOObj, NextSectionIndex)) + LC.Sections = std::move(*Sections); + else + return Sections.takeError(); break; case MachO::LC_SYMTAB: O.SymTabCommandIndex = O.LoadCommands.size(); @@ -177,6 +183,7 @@ } O.LoadCommands.push_back(std::move(LC)); } + return Error::success(); } template @@ -308,10 +315,11 @@ } } -std::unique_ptr MachOReader::create() const { +Expected> MachOReader::create() const { auto Obj = std::make_unique(); readHeader(*Obj); - readLoadCommands(*Obj); + if (Error E = readLoadCommands(*Obj)) + return std::move(E); readSymbolTable(*Obj); setSymbolInRelocationInfo(*Obj); readRebaseInfo(*Obj); diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/tools/llvm-objcopy/llvm-objcopy.h --- a/llvm/tools/llvm-objcopy/llvm-objcopy.h +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.h @@ -24,6 +24,23 @@ LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, std::error_code EC); +inline Error errorWithContext(StringRef Context, Error E) { + assert(E); + std::string Buf; + raw_string_ostream OS(Buf); + Optional EC; + handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { + OS << "'" + Context + "': "; + if (!EC) + EC = EI.convertToErrorCode(); + EI.log(OS); + OS << "\n"; + }); + OS.flush(); + + return createStringError(*EC, Buf); +} + // This is taken from llvm-readobj. // [see here](llvm/tools/llvm-readobj/llvm-readobj.h:38) template T unwrapOrError(Expected EO) {