diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -12,7 +12,6 @@ #include "Object.h" #include "Reader.h" #include "Writer.h" -#include "llvm-objcopy.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -10,7 +10,6 @@ #include "Buffer.h" #include "CopyConfig.h" #include "Object.h" -#include "llvm-objcopy.h" #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" @@ -266,19 +265,23 @@ static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader, StringRef File, ElfType OutputElfType) { - auto DWOFile = Reader.create(false); + Expected> DWOFile = Reader.create(false); + if (!DWOFile) + return DWOFile.takeError(); + auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) { - return onlyKeepDWOPred(*DWOFile, Sec); + return onlyKeepDWOPred(**DWOFile, Sec); }; - if (Error E = DWOFile->removeSections(Config.AllowBrokenLinks, - OnlyKeepDWOPred)) + if (Error E = + (*DWOFile)->removeSections(Config.AllowBrokenLinks, OnlyKeepDWOPred)) return E; if (Config.OutputArch) { - DWOFile->Machine = Config.OutputArch.getValue().EMachine; - DWOFile->OSABI = Config.OutputArch.getValue().OSABI; + (*DWOFile)->Machine = Config.OutputArch.getValue().EMachine; + (*DWOFile)->OSABI = Config.OutputArch.getValue().OSABI; } FileBuffer FB(File); - auto Writer = createWriter(Config, *DWOFile, FB, OutputElfType); + std::unique_ptr Writer = + createWriter(Config, **DWOFile, FB, OutputElfType); if (Error E = Writer->finalize()) return E; return Writer->write(); @@ -313,12 +316,12 @@ StringRef(Sec.Name).startswith(".debug"); } -static void replaceDebugSections( +static Error replaceDebugSections( Object &Obj, SectionPred &RemovePred, function_ref shouldReplace, - function_ref addSection) { + function_ref(const SectionBase *)> addSection) { // Build a list of the debug sections we are going to replace. - // We can't call `addSection` while iterating over sections, + // We can't call `AddSection` while iterating over sections, // because it would mutate the sections array. SmallVector ToReplace; for (auto &Sec : Obj.sections()) @@ -327,8 +330,13 @@ // Build a mapping from original section to a new one. DenseMap FromTo; - for (SectionBase *S : ToReplace) - FromTo[S] = addSection(S); + for (SectionBase *S : ToReplace) { + Expected NewSection = addSection(S); + if (!NewSection) + return NewSection.takeError(); + + FromTo[S] = *NewSection; + } // Now we want to update the target sections of relocation // sections. Also we will update the relocations themselves @@ -339,6 +347,8 @@ RemovePred = [shouldReplace, RemovePred](const SectionBase &Sec) { return shouldReplace(Sec) || RemovePred(Sec); }; + + return Error::success(); } static bool isUnneededSymbol(const Symbol &Sym) { @@ -577,20 +587,28 @@ }; } - if (Config.CompressionType != DebugCompressionType::None) - replaceDebugSections(Obj, RemovePred, isCompressable, - [&Config, &Obj](const SectionBase *S) { - return &Obj.addSection( - *S, Config.CompressionType); - }); - else if (Config.DecompressDebugSections) - replaceDebugSections( - Obj, RemovePred, - [](const SectionBase &S) { return isa(&S); }, - [&Obj](const SectionBase *S) { - auto CS = cast(S); - return &Obj.addSection(*CS); - }); + if (Config.CompressionType != DebugCompressionType::None) { + if (Error Err = replaceDebugSections( + Obj, RemovePred, isCompressable, + [&Config, &Obj](const SectionBase *S) -> Expected { + Expected NewSection = + CompressedSection::create(*S, Config.CompressionType); + if (!NewSection) + return NewSection.takeError(); + + return &Obj.addSection(std::move(*NewSection)); + })) + return Err; + } else if (Config.DecompressDebugSections) { + if (Error Err = replaceDebugSections( + Obj, RemovePred, + [](const SectionBase &S) { return isa(&S); }, + [&Obj](const SectionBase *S) { + const CompressedSection *CS = cast(S); + return &Obj.addSection(*CS); + })) + return Err; + } return Obj.removeSections(Config.AllowBrokenLinks, RemovePred); } @@ -740,9 +758,9 @@ // If the symbol table was previously removed, we need to create a new one // before adding new symbols. - if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty()) { - Obj.addNewSymbolTable(); - } + if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty()) + if (Error E = Obj.addNewSymbolTable()) + return E; for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) { SectionBase *Sec = Obj.findSection(SI.SectionName); @@ -769,12 +787,15 @@ Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In, Buffer &Out) { IHexReader Reader(&In); - std::unique_ptr Obj = Reader.create(true); + Expected> Obj = Reader.create(true); + if (!Obj) + return Obj.takeError(); + const ElfType OutputElfType = getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); - if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) return E; - return writeOutput(Config, *Obj, Out, OutputElfType); + return writeOutput(Config, **Obj, Out, OutputElfType); } Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In, @@ -782,21 +803,26 @@ uint8_t NewSymbolVisibility = Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT); BinaryReader Reader(&In, NewSymbolVisibility); - std::unique_ptr Obj = Reader.create(true); + Expected> Obj = Reader.create(true); + if (!Obj) + return Obj.takeError(); // Prefer OutputArch (-O) if set, otherwise fallback to BinaryArch // (-B). const ElfType OutputElfType = getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); - if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) return E; - return writeOutput(Config, *Obj, Out, OutputElfType); + return writeOutput(Config, **Obj, Out, OutputElfType); } Error executeObjcopyOnBinary(const CopyConfig &Config, object::ELFObjectFileBase &In, Buffer &Out) { ELFReader Reader(&In, Config.ExtractPartition); - std::unique_ptr Obj = Reader.create(!Config.SymbolsToAdd.empty()); + Expected> Obj = + Reader.create(!Config.SymbolsToAdd.empty()); + if (!Obj) + return Obj.takeError(); // Prefer OutputArch (-O) if set, otherwise infer it from the input. const ElfType OutputElfType = Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue()) @@ -822,10 +848,10 @@ Config.BuildIdLinkInput.getValue(), BuildIdBytes)) return E; - if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) return createFileError(Config.InputFilename, std::move(E)); - if (Error E = writeOutput(Config, *Obj, Out, OutputElfType)) + if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) return createFileError(Config.InputFilename, std::move(E)); if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput) if (Error E = diff --git a/llvm/tools/llvm-objcopy/ELF/Object.h b/llvm/tools/llvm-objcopy/ELF/Object.h --- a/llvm/tools/llvm-objcopy/ELF/Object.h +++ b/llvm/tools/llvm-objcopy/ELF/Object.h @@ -61,10 +61,11 @@ iterator end() const { return iterator(Sections.data() + Sections.size()); } size_t size() const { return Sections.size(); } - SectionBase *getSection(uint32_t Index, Twine ErrMsg); + Expected getSection(uint32_t Index, Twine ErrMsg); template - T *getSectionOfType(uint32_t Index, Twine IndexErrMsg, Twine TypeErrMsg); + Expected getSectionOfType(uint32_t Index, Twine IndexErrMsg, + Twine TypeErrMsg); }; enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE }; @@ -73,34 +74,34 @@ public: virtual ~SectionVisitor() = default; - virtual void visit(const Section &Sec) = 0; - virtual void visit(const OwnedDataSection &Sec) = 0; - virtual void visit(const StringTableSection &Sec) = 0; - virtual void visit(const SymbolTableSection &Sec) = 0; - virtual void visit(const RelocationSection &Sec) = 0; - virtual void visit(const DynamicRelocationSection &Sec) = 0; - virtual void visit(const GnuDebugLinkSection &Sec) = 0; - virtual void visit(const GroupSection &Sec) = 0; - virtual void visit(const SectionIndexSection &Sec) = 0; - virtual void visit(const CompressedSection &Sec) = 0; - virtual void visit(const DecompressedSection &Sec) = 0; + virtual Error visit(const Section &Sec) = 0; + virtual Error visit(const OwnedDataSection &Sec) = 0; + virtual Error visit(const StringTableSection &Sec) = 0; + virtual Error visit(const SymbolTableSection &Sec) = 0; + virtual Error visit(const RelocationSection &Sec) = 0; + virtual Error visit(const DynamicRelocationSection &Sec) = 0; + virtual Error visit(const GnuDebugLinkSection &Sec) = 0; + virtual Error visit(const GroupSection &Sec) = 0; + virtual Error visit(const SectionIndexSection &Sec) = 0; + virtual Error visit(const CompressedSection &Sec) = 0; + virtual Error visit(const DecompressedSection &Sec) = 0; }; class MutableSectionVisitor { public: virtual ~MutableSectionVisitor() = default; - virtual void visit(Section &Sec) = 0; - virtual void visit(OwnedDataSection &Sec) = 0; - virtual void visit(StringTableSection &Sec) = 0; - virtual void visit(SymbolTableSection &Sec) = 0; - virtual void visit(RelocationSection &Sec) = 0; - virtual void visit(DynamicRelocationSection &Sec) = 0; - virtual void visit(GnuDebugLinkSection &Sec) = 0; - virtual void visit(GroupSection &Sec) = 0; - virtual void visit(SectionIndexSection &Sec) = 0; - virtual void visit(CompressedSection &Sec) = 0; - virtual void visit(DecompressedSection &Sec) = 0; + virtual Error visit(Section &Sec) = 0; + virtual Error visit(OwnedDataSection &Sec) = 0; + virtual Error visit(StringTableSection &Sec) = 0; + virtual Error visit(SymbolTableSection &Sec) = 0; + virtual Error visit(RelocationSection &Sec) = 0; + virtual Error visit(DynamicRelocationSection &Sec) = 0; + virtual Error visit(GnuDebugLinkSection &Sec) = 0; + virtual Error visit(GroupSection &Sec) = 0; + virtual Error visit(SectionIndexSection &Sec) = 0; + virtual Error visit(CompressedSection &Sec) = 0; + virtual Error visit(DecompressedSection &Sec) = 0; }; class SectionWriter : public SectionVisitor { @@ -110,17 +111,17 @@ public: virtual ~SectionWriter() = default; - void visit(const Section &Sec) override; - void visit(const OwnedDataSection &Sec) override; - void visit(const StringTableSection &Sec) override; - void visit(const DynamicRelocationSection &Sec) override; - virtual void visit(const SymbolTableSection &Sec) override = 0; - virtual void visit(const RelocationSection &Sec) override = 0; - virtual void visit(const GnuDebugLinkSection &Sec) override = 0; - virtual void visit(const GroupSection &Sec) override = 0; - virtual void visit(const SectionIndexSection &Sec) override = 0; - virtual void visit(const CompressedSection &Sec) override = 0; - virtual void visit(const DecompressedSection &Sec) override = 0; + Error visit(const Section &Sec) override; + Error visit(const OwnedDataSection &Sec) override; + Error visit(const StringTableSection &Sec) override; + Error visit(const DynamicRelocationSection &Sec) override; + virtual Error visit(const SymbolTableSection &Sec) override = 0; + virtual Error visit(const RelocationSection &Sec) override = 0; + virtual Error visit(const GnuDebugLinkSection &Sec) override = 0; + virtual Error visit(const GroupSection &Sec) override = 0; + virtual Error visit(const SectionIndexSection &Sec) override = 0; + virtual Error visit(const CompressedSection &Sec) override = 0; + virtual Error visit(const DecompressedSection &Sec) override = 0; explicit SectionWriter(Buffer &Buf) : Out(Buf) {} }; @@ -134,13 +135,13 @@ public: virtual ~ELFSectionWriter() {} - void visit(const SymbolTableSection &Sec) override; - void visit(const RelocationSection &Sec) override; - void visit(const GnuDebugLinkSection &Sec) override; - void visit(const GroupSection &Sec) override; - void visit(const SectionIndexSection &Sec) override; - void visit(const CompressedSection &Sec) override; - void visit(const DecompressedSection &Sec) override; + Error visit(const SymbolTableSection &Sec) override; + Error visit(const RelocationSection &Sec) override; + Error visit(const GnuDebugLinkSection &Sec) override; + Error visit(const GroupSection &Sec) override; + Error visit(const SectionIndexSection &Sec) override; + Error visit(const CompressedSection &Sec) override; + Error visit(const DecompressedSection &Sec) override; explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {} }; @@ -154,17 +155,17 @@ using Elf_Xword = typename ELFT::Xword; public: - void visit(Section &Sec) override; - void visit(OwnedDataSection &Sec) override; - void visit(StringTableSection &Sec) override; - void visit(DynamicRelocationSection &Sec) override; - void visit(SymbolTableSection &Sec) override; - void visit(RelocationSection &Sec) override; - void visit(GnuDebugLinkSection &Sec) override; - void visit(GroupSection &Sec) override; - void visit(SectionIndexSection &Sec) override; - void visit(CompressedSection &Sec) override; - void visit(DecompressedSection &Sec) override; + Error visit(Section &Sec) override; + Error visit(OwnedDataSection &Sec) override; + Error visit(StringTableSection &Sec) override; + Error visit(DynamicRelocationSection &Sec) override; + Error visit(SymbolTableSection &Sec) override; + Error visit(RelocationSection &Sec) override; + Error visit(GnuDebugLinkSection &Sec) override; + Error visit(GroupSection &Sec) override; + Error visit(SectionIndexSection &Sec) override; + Error visit(CompressedSection &Sec) override; + Error visit(DecompressedSection &Sec) override; }; #define MAKE_SEC_WRITER_FRIEND \ @@ -178,13 +179,13 @@ public: virtual ~BinarySectionWriter() {} - void visit(const SymbolTableSection &Sec) override; - void visit(const RelocationSection &Sec) override; - void visit(const GnuDebugLinkSection &Sec) override; - void visit(const GroupSection &Sec) override; - void visit(const SectionIndexSection &Sec) override; - void visit(const CompressedSection &Sec) override; - void visit(const DecompressedSection &Sec) override; + Error visit(const SymbolTableSection &Sec) override; + Error visit(const RelocationSection &Sec) override; + Error visit(const GnuDebugLinkSection &Sec) override; + Error visit(const GroupSection &Sec) override; + Error visit(const SectionIndexSection &Sec) override; + Error visit(const CompressedSection &Sec) override; + Error visit(const DecompressedSection &Sec) override; explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {} }; @@ -285,10 +286,10 @@ explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {} uint64_t getBufferOffset() const { return Offset; } - void visit(const Section &Sec) final; - void visit(const OwnedDataSection &Sec) final; - void visit(const StringTableSection &Sec) override; - void visit(const DynamicRelocationSection &Sec) final; + Error visit(const Section &Sec) final; + Error visit(const OwnedDataSection &Sec) final; + Error visit(const StringTableSection &Sec) override; + Error visit(const DynamicRelocationSection &Sec) final; using BinarySectionWriter::visit; }; @@ -298,7 +299,7 @@ IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {} void writeData(uint8_t Type, uint16_t Addr, ArrayRef Data) override; - void visit(const StringTableSection &Sec) override; + Error visit(const StringTableSection &Sec) override; }; class Writer { @@ -329,7 +330,7 @@ void writePhdrs(); void writeShdrs(); - void writeSectionData(); + Error writeSectionData(); void writeSegmentData(); void assignOffsets(); @@ -412,15 +413,15 @@ virtual ~SectionBase() = default; - virtual void initialize(SectionTableRef SecTable); + virtual Error initialize(SectionTableRef SecTable); virtual void finalize(); // Remove references to these sections. The list of sections must be sorted. virtual Error removeSectionReferences(bool AllowBrokenLinks, function_ref ToRemove); virtual Error removeSymbols(function_ref ToRemove); - virtual void accept(SectionVisitor &Visitor) const = 0; - virtual void accept(MutableSectionVisitor &Visitor) = 0; + virtual Error accept(SectionVisitor &Visitor) const = 0; + virtual Error accept(MutableSectionVisitor &Visitor) = 0; virtual void markSymbols(); virtual void replaceSectionReferences(const DenseMap &); @@ -481,11 +482,11 @@ public: explicit Section(ArrayRef Data) : Contents(Data) {} - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; Error removeSectionReferences(bool AllowBrokenLinks, function_ref ToRemove) override; - void initialize(SectionTableRef SecTable) override; + Error initialize(SectionTableRef SecTable) override; void finalize() override; }; @@ -513,8 +514,8 @@ } void appendHexData(StringRef HexData); - void accept(SectionVisitor &Sec) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Sec) const override; + Error accept(MutableSectionVisitor &Visitor) override; }; class CompressedSection : public SectionBase { @@ -526,21 +527,28 @@ SmallVector CompressedData; public: - CompressedSection(const SectionBase &Sec, - DebugCompressionType CompressionType); - CompressedSection(ArrayRef CompressedData, uint64_t DecompressedSize, - uint64_t DecompressedAlign); + static Expected + create(const SectionBase &Sec, DebugCompressionType CompressionType); + static Expected create(ArrayRef CompressedData, + uint64_t DecompressedSize, + uint64_t DecompressedAlign); uint64_t getDecompressedSize() const { return DecompressedSize; } uint64_t getDecompressedAlign() const { return DecompressedAlign; } - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; static bool classof(const SectionBase *S) { return (S->OriginalFlags & ELF::SHF_COMPRESSED) || (StringRef(S->Name).startswith(".zdebug")); } + +private: + CompressedSection(const SectionBase &Sec, + DebugCompressionType CompressionType, Error &Err); + CompressedSection(ArrayRef CompressedData, uint64_t DecompressedSize, + uint64_t DecompressedAlign); }; class DecompressedSection : public SectionBase { @@ -556,8 +564,8 @@ Name = "." + Name.substr(2); } - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; }; // There are two types of string tables that can exist, dynamic and not dynamic. @@ -581,8 +589,8 @@ void addString(StringRef Name); uint32_t findIndex(StringRef Name) const; void prepareForLayout(); - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; static bool classof(const SectionBase *S) { if (S->OriginalFlags & ELF::SHF_ALLOC) @@ -647,10 +655,10 @@ Size = NumSymbols * 4; } void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; } - void initialize(SectionTableRef SecTable) override; + Error initialize(SectionTableRef SecTable) override; void finalize() override; - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; SectionIndexSection() { Name = ".symtab_shndx"; @@ -688,16 +696,16 @@ const SectionIndexSection *getShndxTable() const { return SectionIndexTable; } void fillShndxTable(); const SectionBase *getStrTab() const { return SymbolNames; } - const Symbol *getSymbolByIndex(uint32_t Index) const; - Symbol *getSymbolByIndex(uint32_t Index); + Expected getSymbolByIndex(uint32_t Index) const; + Expected getSymbolByIndex(uint32_t Index); void updateSymbols(function_ref Callable); Error removeSectionReferences(bool AllowBrokenLinks, function_ref ToRemove) override; - void initialize(SectionTableRef SecTable) override; + Error initialize(SectionTableRef SecTable) override; void finalize() override; - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; Error removeSymbols(function_ref ToRemove) override; void replaceSectionReferences( const DenseMap &FromTo) override; @@ -748,7 +756,7 @@ SymTabType *Symbols = nullptr; public: - void initialize(SectionTableRef SecTable) override; + Error initialize(SectionTableRef SecTable) override; void finalize() override; }; @@ -760,8 +768,8 @@ public: void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; Error removeSectionReferences(bool AllowBrokenLinks, function_ref ToRemove) override; Error removeSymbols(function_ref ToRemove) override; @@ -798,8 +806,8 @@ void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; } void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); } - void accept(SectionVisitor &) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &) const override; + Error accept(MutableSectionVisitor &Visitor) override; void finalize() override; Error removeSectionReferences( bool AllowBrokenLinks, @@ -843,8 +851,8 @@ public: explicit DynamicRelocationSection(ArrayRef Data) : Contents(Data) {} - void accept(SectionVisitor &) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &) const override; + Error accept(MutableSectionVisitor &Visitor) override; Error removeSectionReferences( bool AllowBrokenLinks, function_ref ToRemove) override; @@ -868,14 +876,14 @@ public: // If we add this section from an external source we can use this ctor. explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC); - void accept(SectionVisitor &Visitor) const override; - void accept(MutableSectionVisitor &Visitor) override; + Error accept(SectionVisitor &Visitor) const override; + Error accept(MutableSectionVisitor &Visitor) override; }; class Reader { public: virtual ~Reader(); - virtual std::unique_ptr create(bool EnsureSymtab) const = 0; + virtual Expected> create(bool EnsureSymtab) const = 0; }; using object::Binary; @@ -891,7 +899,7 @@ void initHeaderSegment(); StringTableSection *addStrTab(); SymbolTableSection *addSymTab(StringTableSection *StrTab); - void initSections(); + Error initSections(); public: BasicELFBuilder() : Obj(std::make_unique()) {} @@ -907,7 +915,7 @@ : BasicELFBuilder(), MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {} - std::unique_ptr build(); + Expected> build(); }; class IHexELFBuilder : public BasicELFBuilder { @@ -919,7 +927,7 @@ IHexELFBuilder(const std::vector &Records) : BasicELFBuilder(), Records(Records) {} - std::unique_ptr build(); + Expected> build(); }; template class ELFBuilder { @@ -934,13 +942,13 @@ Optional ExtractPartition; void setParentSegment(Segment &Child); - void readProgramHeaders(const ELFFile &HeadersFile); - void initGroupSection(GroupSection *GroupSec); - void initSymbolTable(SymbolTableSection *SymTab); - void readSectionHeaders(); - void readSections(bool EnsureSymtab); - void findEhdrOffset(); - SectionBase &makeSection(const Elf_Shdr &Shdr); + Error readProgramHeaders(const ELFFile &HeadersFile); + Error initGroupSection(GroupSection *GroupSec); + Error initSymbolTable(SymbolTableSection *SymTab); + Error readSectionHeaders(); + Error readSections(bool EnsureSymtab); + Error findEhdrOffset(); + Expected makeSection(const Elf_Shdr &Shdr); public: ELFBuilder(const ELFObjectFile &ElfObj, Object &Obj, @@ -948,7 +956,7 @@ : ElfFile(*ElfObj.getELFFile()), Obj(Obj), ExtractPartition(ExtractPartition) {} - void build(bool EnsureSymtab); + Error build(bool EnsureSymtab); }; class BinaryReader : public Reader { @@ -958,7 +966,7 @@ public: BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility) : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {} - std::unique_ptr create(bool EnsureSymtab) const override; + Expected> create(bool EnsureSymtab) const override; }; class IHexReader : public Reader { @@ -980,7 +988,7 @@ public: IHexReader(MemoryBuffer *MB) : MemBuf(MB) {} - std::unique_ptr create(bool EnsureSymtab) const override; + Expected> create(bool EnsureSymtab) const override; }; class ELFReader : public Reader { @@ -988,7 +996,7 @@ Optional ExtractPartition; public: - std::unique_ptr create(bool EnsureSymtab) const override; + Expected> create(bool EnsureSymtab) const override; explicit ELFReader(Binary *B, Optional ExtractPartition) : Bin(B), ExtractPartition(ExtractPartition) {} }; @@ -1072,7 +1080,7 @@ Ptr->Index = Sections.size(); return *Ptr; } - void addNewSymbolTable(); + Error addNewSymbolTable(); Segment &addSegment(ArrayRef Data) { Segments.emplace_back(std::make_unique(Data)); return *Segments.back(); diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp --- a/llvm/tools/llvm-objcopy/ELF/Object.cpp +++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "Object.h" -#include "llvm-objcopy.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" @@ -15,6 +14,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Object/ELF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Endian.h" @@ -60,7 +60,7 @@ return Error::success(); } -void SectionBase::initialize(SectionTableRef SecTable) {} +Error SectionBase::initialize(SectionTableRef) { return Error::success(); } void SectionBase::finalize() {} void SectionBase::markSymbols() {} void SectionBase::replaceSectionReferences( @@ -82,72 +82,98 @@ Shdr.sh_entsize = Sec.EntrySize; } -template void ELFSectionSizer::visit(Section &Sec) {} +template Error ELFSectionSizer::visit(Section &) { + return Error::success(); +} -template -void ELFSectionSizer::visit(OwnedDataSection &Sec) {} +template Error ELFSectionSizer::visit(OwnedDataSection &) { + return Error::success(); +} -template -void ELFSectionSizer::visit(StringTableSection &Sec) {} +template Error ELFSectionSizer::visit(StringTableSection &) { + return Error::success(); +} template -void ELFSectionSizer::visit(DynamicRelocationSection &Sec) {} +Error ELFSectionSizer::visit(DynamicRelocationSection &) { + return Error::success(); +} template -void ELFSectionSizer::visit(SymbolTableSection &Sec) { +Error ELFSectionSizer::visit(SymbolTableSection &Sec) { Sec.EntrySize = sizeof(Elf_Sym); Sec.Size = Sec.Symbols.size() * Sec.EntrySize; // Align to the largest field in Elf_Sym. Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word); + return Error::success(); } template -void ELFSectionSizer::visit(RelocationSection &Sec) { +Error ELFSectionSizer::visit(RelocationSection &Sec) { Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela); Sec.Size = Sec.Relocations.size() * Sec.EntrySize; // Align to the largest field in Elf_Rel(a). Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word); + return Error::success(); } template -void ELFSectionSizer::visit(GnuDebugLinkSection &Sec) {} +Error ELFSectionSizer::visit(GnuDebugLinkSection &) { + return Error::success(); +} -template void ELFSectionSizer::visit(GroupSection &Sec) { +template Error ELFSectionSizer::visit(GroupSection &Sec) { Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word); + return Error::success(); } template -void ELFSectionSizer::visit(SectionIndexSection &Sec) {} +Error ELFSectionSizer::visit(SectionIndexSection &) { + return Error::success(); +} -template -void ELFSectionSizer::visit(CompressedSection &Sec) {} +template Error ELFSectionSizer::visit(CompressedSection &) { + return Error::success(); +} template -void ELFSectionSizer::visit(DecompressedSection &Sec) {} +Error ELFSectionSizer::visit(DecompressedSection &) { + return Error::success(); +} -void BinarySectionWriter::visit(const SectionIndexSection &Sec) { - error("cannot write symbol section index table '" + Sec.Name + "' "); +Error BinarySectionWriter::visit(const SectionIndexSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write symbol section index table '" + + Sec.Name + "' "); } -void BinarySectionWriter::visit(const SymbolTableSection &Sec) { - error("cannot write symbol table '" + Sec.Name + "' out to binary"); +Error BinarySectionWriter::visit(const SymbolTableSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write symbol table '" + Sec.Name + + "' out to binary"); } -void BinarySectionWriter::visit(const RelocationSection &Sec) { - error("cannot write relocation section '" + Sec.Name + "' out to binary"); +Error BinarySectionWriter::visit(const RelocationSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write relocation section '" + Sec.Name + + "' out to binary"); } -void BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) { - error("cannot write '" + Sec.Name + "' out to binary"); +Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write '" + Sec.Name + "' out to binary"); } -void BinarySectionWriter::visit(const GroupSection &Sec) { - error("cannot write '" + Sec.Name + "' out to binary"); +Error BinarySectionWriter::visit(const GroupSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write '" + Sec.Name + "' out to binary"); } -void SectionWriter::visit(const Section &Sec) { +Error SectionWriter::visit(const Section &Sec) { if (Sec.Type != SHT_NOBITS) llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset); + + return Error::success(); } static bool addressOverflows32bit(uint64_t Addr) { @@ -352,30 +378,34 @@ return Base; } -void IHexSectionWriterBase::writeData(uint8_t Type, uint16_t Addr, +void IHexSectionWriterBase::writeData(uint8_t, uint16_t, ArrayRef Data) { Offset += IHexRecord::getLineLength(Data.size()); } -void IHexSectionWriterBase::visit(const Section &Sec) { +Error IHexSectionWriterBase::visit(const Section &Sec) { writeSection(&Sec, Sec.Contents); + return Error::success(); } -void IHexSectionWriterBase::visit(const OwnedDataSection &Sec) { +Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) { writeSection(&Sec, Sec.Data); + return Error::success(); } -void IHexSectionWriterBase::visit(const StringTableSection &Sec) { +Error IHexSectionWriterBase::visit(const StringTableSection &Sec) { // Check that sizer has already done its work assert(Sec.Size == Sec.StrTabBuilder.getSize()); // We are free to pass an invalid pointer to writeSection as long // as we don't actually write any data. The real writer class has // to override this method . writeSection(&Sec, {nullptr, static_cast(Sec.Size)}); + return Error::success(); } -void IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) { +Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) { writeSection(&Sec, Sec.Contents); + return Error::success(); } void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr, @@ -385,19 +415,25 @@ Offset += HexData.size(); } -void IHexSectionWriter::visit(const StringTableSection &Sec) { +Error IHexSectionWriter::visit(const StringTableSection &Sec) { assert(Sec.Size == Sec.StrTabBuilder.getSize()); std::vector Data(Sec.Size); Sec.StrTabBuilder.write(Data.data()); writeSection(&Sec, Data); + return Error::success(); } -void Section::accept(SectionVisitor &Visitor) const { Visitor.visit(*this); } +Error Section::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); +} -void Section::accept(MutableSectionVisitor &Visitor) { Visitor.visit(*this); } +Error Section::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); +} -void SectionWriter::visit(const OwnedDataSection &Sec) { +Error SectionWriter::visit(const OwnedDataSection &Sec) { llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset); + return Error::success(); } static constexpr std::array ZlibGnuMagic = {{'Z', 'L', 'I', 'B'}}; @@ -424,7 +460,7 @@ } template -void ELFSectionWriter::visit(const DecompressedSection &Sec) { +Error ELFSectionWriter::visit(const DecompressedSection &Sec) { const size_t DataOffset = isDataGnuCompressed(Sec.OriginalData) ? (ZlibGnuMagic.size() + sizeof(Sec.Size)) : sizeof(Elf_Chdr_Impl); @@ -434,32 +470,37 @@ Sec.OriginalData.size() - DataOffset); SmallVector DecompressedContent; - if (Error E = zlib::uncompress(CompressedContent, DecompressedContent, - static_cast(Sec.Size))) - reportError(Sec.Name, std::move(E)); + if (Error Err = zlib::uncompress(CompressedContent, DecompressedContent, + static_cast(Sec.Size))) + return createStringError(errc::invalid_argument, + "'" + Sec.Name + "': " + toString(std::move(Err))); uint8_t *Buf = Out.getBufferStart() + Sec.Offset; std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf); + + return Error::success(); } -void BinarySectionWriter::visit(const DecompressedSection &Sec) { - error("cannot write compressed section '" + Sec.Name + "' "); +Error BinarySectionWriter::visit(const DecompressedSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write compressed section '" + Sec.Name + + "' "); } -void DecompressedSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error DecompressedSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void DecompressedSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error DecompressedSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } -void OwnedDataSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error OwnedDataSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void OwnedDataSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } void OwnedDataSection::appendHexData(StringRef HexData) { @@ -471,16 +512,18 @@ Size = Data.size(); } -void BinarySectionWriter::visit(const CompressedSection &Sec) { - error("cannot write compressed section '" + Sec.Name + "' "); +Error BinarySectionWriter::visit(const CompressedSection &Sec) { + return createStringError(errc::operation_not_permitted, + "cannot write compressed section '" + Sec.Name + + "' "); } template -void ELFSectionWriter::visit(const CompressedSection &Sec) { +Error ELFSectionWriter::visit(const CompressedSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; if (Sec.CompressionType == DebugCompressionType::None) { std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf); - return; + return Error::success(); } if (Sec.CompressionType == DebugCompressionType::GNU) { @@ -501,17 +544,42 @@ } std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf); + return Error::success(); +} + +Expected +CompressedSection::create(const SectionBase &Sec, + DebugCompressionType CompressionType) { + Error Err = Error::success(); + CompressedSection Section(Sec, CompressionType, Err); + + if (Err) + return std::move(Err); + + return Section; +} +Expected +CompressedSection::create(ArrayRef CompressedData, + uint64_t DecompressedSize, + uint64_t DecompressedAlign) { + return CompressedSection(CompressedData, DecompressedSize, DecompressedAlign); } CompressedSection::CompressedSection(const SectionBase &Sec, - DebugCompressionType CompressionType) + DebugCompressionType CompressionType, + Error &OutErr) : SectionBase(Sec), CompressionType(CompressionType), DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) { - if (Error E = zlib::compress( + ErrorAsOutParameter EAO(&OutErr); + + if (Error Err = zlib::compress( StringRef(reinterpret_cast(OriginalData.data()), OriginalData.size()), - CompressedData)) - reportError(Name, std::move(E)); + CompressedData)) { + OutErr = createStringError(llvm::errc::invalid_argument, + "'" + Name + "': " + toString(std::move(Err))); + return; + } size_t ChdrSize; if (CompressionType == DebugCompressionType::GNU) { @@ -537,12 +605,12 @@ OriginalData = CompressedData; } -void CompressedSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error CompressedSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void CompressedSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error CompressedSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); } @@ -556,42 +624,51 @@ Size = StrTabBuilder.getSize(); } -void SectionWriter::visit(const StringTableSection &Sec) { +Error SectionWriter::visit(const StringTableSection &Sec) { Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset); + return Error::success(); } -void StringTableSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error StringTableSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void StringTableSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error StringTableSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } template -void ELFSectionWriter::visit(const SectionIndexSection &Sec) { +Error ELFSectionWriter::visit(const SectionIndexSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; llvm::copy(Sec.Indexes, reinterpret_cast(Buf)); + return Error::success(); } -void SectionIndexSection::initialize(SectionTableRef SecTable) { +Error SectionIndexSection::initialize(SectionTableRef SecTable) { Size = 0; - setSymTab(SecTable.getSectionOfType( - Link, - "Link field value " + Twine(Link) + " in section " + Name + " is invalid", - "Link field value " + Twine(Link) + " in section " + Name + - " is not a symbol table")); + Expected Sec = + SecTable.getSectionOfType( + Link, + "Link field value " + Twine(Link) + " in section " + Name + + " is invalid", + "Link field value " + Twine(Link) + " in section " + Name + + " is not a symbol table"); + if (!Sec) + return Sec.takeError(); + + setSymTab(*Sec); Symbols->setShndxTable(this); + return Error::success(); } void SectionIndexSection::finalize() { Link = Symbols->Index; } -void SectionIndexSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error SectionIndexSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void SectionIndexSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) { @@ -718,14 +795,20 @@ Sym->DefinedIn = To; } -void SymbolTableSection::initialize(SectionTableRef SecTable) { +Error SymbolTableSection::initialize(SectionTableRef SecTable) { Size = 0; - setStrTab(SecTable.getSectionOfType( - Link, - "Symbol table has link index of " + Twine(Link) + - " which is not a valid index", - "Symbol table has link index of " + Twine(Link) + - " which is not a string table")); + Expected Sec = + SecTable.getSectionOfType( + Link, + "Symbol table has link index of " + Twine(Link) + + " which is not a valid index", + "Symbol table has link index of " + Twine(Link) + + " which is not a string table"); + if (!Sec) + return Sec.takeError(); + + setStrTab(*Sec); + return Error::success(); } void SymbolTableSection::finalize() { @@ -770,19 +853,25 @@ } } -const Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) const { +Expected +SymbolTableSection::getSymbolByIndex(uint32_t Index) const { if (Symbols.size() <= Index) - error("invalid symbol index: " + Twine(Index)); + return createStringError(errc::invalid_argument, + "invalid symbol index: " + Twine(Index)); return Symbols[Index].get(); } -Symbol *SymbolTableSection::getSymbolByIndex(uint32_t Index) { - return const_cast( - static_cast(this)->getSymbolByIndex(Index)); +Expected SymbolTableSection::getSymbolByIndex(uint32_t Index) { + Expected Sym = + static_cast(this)->getSymbolByIndex(Index); + if (!Sym) + return Sym.takeError(); + + return const_cast(*Sym); } template -void ELFSectionWriter::visit(const SymbolTableSection &Sec) { +Error ELFSectionWriter::visit(const SymbolTableSection &Sec) { Elf_Sym *Sym = reinterpret_cast(Out.getBufferStart() + Sec.Offset); // Loop though symbols setting each entry of the symbol table. for (const std::unique_ptr &Symbol : Sec.Symbols) { @@ -795,14 +884,15 @@ Sym->st_shndx = Symbol->getShndx(); ++Sym; } + return Error::success(); } -void SymbolTableSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error SymbolTableSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void SymbolTableSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } Error RelocationSection::removeSectionReferences( @@ -834,22 +924,33 @@ } template -void RelocSectionWithSymtabBase::initialize( +Error RelocSectionWithSymtabBase::initialize( SectionTableRef SecTable) { - if (Link != SHN_UNDEF) - setSymTab(SecTable.getSectionOfType( + if (Link != SHN_UNDEF) { + Expected Sec = SecTable.getSectionOfType( Link, "Link field value " + Twine(Link) + " in section " + Name + " is invalid", "Link field value " + Twine(Link) + " in section " + Name + - " is not a symbol table")); + " is not a symbol table"); + if (!Sec) + return Sec.takeError(); - if (Info != SHN_UNDEF) - setSection(SecTable.getSection(Info, "Info field value " + Twine(Info) + - " in section " + Name + - " is invalid")); - else + setSymTab(*Sec); + } + + if (Info != SHN_UNDEF) { + Expected Sec = + SecTable.getSection(Info, "Info field value " + Twine(Info) + + " in section " + Name + " is invalid"); + if (!Sec) + return Sec.takeError(); + + setSection(*Sec); + } else setSection(nullptr); + + return Error::success(); } template @@ -880,20 +981,21 @@ } template -void ELFSectionWriter::visit(const RelocationSection &Sec) { +Error ELFSectionWriter::visit(const RelocationSection &Sec) { uint8_t *Buf = Out.getBufferStart() + Sec.Offset; if (Sec.Type == SHT_REL) writeRel(Sec.Relocations, reinterpret_cast(Buf)); else writeRel(Sec.Relocations, reinterpret_cast(Buf)); + return Error::success(); } -void RelocationSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error RelocationSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void RelocationSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error RelocationSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } Error RelocationSection::removeSymbols( @@ -920,16 +1022,17 @@ SecToApplyRel = To; } -void SectionWriter::visit(const DynamicRelocationSection &Sec) { +Error SectionWriter::visit(const DynamicRelocationSection &Sec) { llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset); + return Error::success(); } -void DynamicRelocationSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } Error DynamicRelocationSection::removeSectionReferences( @@ -1015,14 +1118,22 @@ Sec->Flags &= ~SHF_GROUP; } -void Section::initialize(SectionTableRef SecTable) { +Error Section::initialize(SectionTableRef SecTable) { if (Link == ELF::SHN_UNDEF) - return; - LinkSection = + return Error::success(); + + Expected Sec = SecTable.getSection(Link, "Link field value " + Twine(Link) + " in section " + Name + " is invalid"); + if (!Sec) + return Sec.takeError(); + + LinkSection = *Sec; + if (LinkSection->Type == ELF::SHT_SYMTAB) LinkSection = nullptr; + + return Error::success(); } void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; } @@ -1051,37 +1162,39 @@ } template -void ELFSectionWriter::visit(const GnuDebugLinkSection &Sec) { +Error ELFSectionWriter::visit(const GnuDebugLinkSection &Sec) { unsigned char *Buf = Out.getBufferStart() + Sec.Offset; Elf_Word *CRC = reinterpret_cast(Buf + Sec.Size - sizeof(Elf_Word)); *CRC = Sec.CRC32; llvm::copy(Sec.FileName, Buf); + return Error::success(); } -void GnuDebugLinkSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } template -void ELFSectionWriter::visit(const GroupSection &Sec) { +Error ELFSectionWriter::visit(const GroupSection &Sec) { ELF::Elf32_Word *Buf = reinterpret_cast(Out.getBufferStart() + Sec.Offset); *Buf++ = Sec.FlagWord; for (SectionBase *S : Sec.GroupMembers) support::endian::write32(Buf++, S->Index); + return Error::success(); } -void GroupSection::accept(SectionVisitor &Visitor) const { - Visitor.visit(*this); +Error GroupSection::accept(SectionVisitor &Visitor) const { + return Visitor.visit(*this); } -void GroupSection::accept(MutableSectionVisitor &Visitor) { - Visitor.visit(*this); +Error GroupSection::accept(MutableSectionVisitor &Visitor) { + return Visitor.visit(*this); } // Returns true IFF a section is wholly inside the range of a segment @@ -1161,9 +1274,12 @@ return &SymTab; } -void BasicELFBuilder::initSections() { +Error BasicELFBuilder::initSections() { for (SectionBase &Sec : Obj->sections()) - Sec.initialize(Obj->sections()); + if (Error Err = Sec.initialize(Obj->sections())) + return Err; + + return Error::success(); } void BinaryELFBuilder::addData(SymbolTableSection *SymTab) { @@ -1190,12 +1306,13 @@ 0); } -std::unique_ptr BinaryELFBuilder::build() { +Expected> BinaryELFBuilder::build() { initFileHeader(); initHeaderSegment(); SymbolTableSection *SymTab = addSymTab(addStrTab()); - initSections(); + if (Error Err = initSections()) + return std::move(Err); addData(SymTab); return std::move(Obj); @@ -1246,12 +1363,13 @@ } } -std::unique_ptr IHexELFBuilder::build() { +Expected> IHexELFBuilder::build() { initFileHeader(); initHeaderSegment(); StringTableSection *StrTab = addStrTab(); addSymTab(StrTab); - initSections(); + if (Error Err = initSections()) + return std::move(Err); addDataSections(); return std::move(Obj); @@ -1273,27 +1391,37 @@ } } -template void ELFBuilder::findEhdrOffset() { +template Error ELFBuilder::findEhdrOffset() { if (!ExtractPartition) - return; + return Error::success(); for (const SectionBase &Sec : Obj.sections()) { if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) { EhdrOffset = Sec.Offset; - return; + return Error::success(); } } - error("could not find partition named '" + *ExtractPartition + "'"); + return createStringError(errc::invalid_argument, + "could not find partition named '" + + *ExtractPartition + "'"); } template -void ELFBuilder::readProgramHeaders(const ELFFile &HeadersFile) { +Error ELFBuilder::readProgramHeaders(const ELFFile &HeadersFile) { uint32_t Index = 0; - for (const auto &Phdr : unwrapOrError(HeadersFile.program_headers())) { + + Expected::Elf_Phdr_Range> Headers = + HeadersFile.program_headers(); + if (!Headers) + return Headers.takeError(); + + for (const typename ELFFile::Elf_Phdr &Phdr : *Headers) { if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize()) - error("program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) + - " and file size 0x" + Twine::utohexstr(Phdr.p_filesz) + - " goes past the end of the file"); + return createStringError( + errc::invalid_argument, + "program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) + + " and file size 0x" + Twine::utohexstr(Phdr.p_filesz) + + " goes past the end of the file"); ArrayRef Data{HeadersFile.base() + Phdr.p_offset, (size_t)Phdr.p_filesz}; @@ -1341,13 +1469,16 @@ setParentSegment(Child); setParentSegment(ElfHdr); setParentSegment(PrHdr); + + return Error::success(); } template -void ELFBuilder::initGroupSection(GroupSection *GroupSec) { +Error ELFBuilder::initGroupSection(GroupSection *GroupSec) { if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0) - error("invalid alignment " + Twine(GroupSec->Align) + " of group section '" + - GroupSec->Name + "'"); + return createStringError(errc::invalid_argument, + "invalid alignment " + Twine(GroupSec->Align) + + " of group section '" + GroupSec->Name + "'"); SectionTableRef SecTable = Obj.sections(); if (GroupSec->Link != SHN_UNDEF) { auto SymTab = SecTable.template getSectionOfType( @@ -1356,16 +1487,23 @@ GroupSec->Name + "' is invalid", "link field value '" + Twine(GroupSec->Link) + "' in section '" + GroupSec->Name + "' is not a symbol table"); - Symbol *Sym = SymTab->getSymbolByIndex(GroupSec->Info); + if (!SymTab) + return SymTab.takeError(); + + Expected Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info); if (!Sym) - error("info field value '" + Twine(GroupSec->Info) + "' in section '" + - GroupSec->Name + "' is not a valid symbol index"); - GroupSec->setSymTab(SymTab); - GroupSec->setSymbol(Sym); + return createStringError(errc::invalid_argument, + "info field value '" + Twine(GroupSec->Info) + + "' in section '" + GroupSec->Name + + "' is not a valid symbol index"); + GroupSec->setSymTab(*SymTab); + GroupSec->setSymbol(*Sym); } if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) || GroupSec->Contents.empty()) - error("the content of the section " + GroupSec->Name + " is malformed"); + return createStringError(errc::invalid_argument, + "the content of the section " + GroupSec->Name + + " is malformed"); const ELF::Elf32_Word *Word = reinterpret_cast(GroupSec->Contents.data()); const ELF::Elf32_Word *End = @@ -1373,57 +1511,99 @@ GroupSec->setFlagWord(*Word++); for (; Word != End; ++Word) { uint32_t Index = support::endian::read32(Word); - GroupSec->addMember(SecTable.getSection( + Expected Sec = SecTable.getSection( Index, "group member index " + Twine(Index) + " in section '" + - GroupSec->Name + "' is invalid")); + GroupSec->Name + "' is invalid"); + if (!Sec) + return Sec.takeError(); + + GroupSec->addMember(*Sec); } + + return Error::success(); } template -void ELFBuilder::initSymbolTable(SymbolTableSection *SymTab) { - const Elf_Shdr &Shdr = *unwrapOrError(ElfFile.getSection(SymTab->Index)); - StringRef StrTabData = unwrapOrError(ElfFile.getStringTableForSymtab(Shdr)); +Error ELFBuilder::initSymbolTable(SymbolTableSection *SymTab) { + Expected Shdr = ElfFile.getSection(SymTab->Index); + if (!Shdr) + return Shdr.takeError(); + + Expected StrTabData = ElfFile.getStringTableForSymtab(**Shdr); + if (!StrTabData) + return StrTabData.takeError(); + ArrayRef ShndxData; - auto Symbols = unwrapOrError(ElfFile.symbols(&Shdr)); - for (const auto &Sym : Symbols) { + Expected::Elf_Sym_Range> Symbols = + ElfFile.symbols(*Shdr); + if (!Symbols) + return Symbols.takeError(); + + for (const typename ELFFile::Elf_Sym &Sym : *Symbols) { SectionBase *DefSection = nullptr; - StringRef Name = unwrapOrError(Sym.getName(StrTabData)); + + Expected Name = Sym.getName(*StrTabData); + if (!Name) + return Name.takeError(); if (Sym.st_shndx == SHN_XINDEX) { if (SymTab->getShndxTable() == nullptr) - error("symbol '" + Name + - "' has index SHN_XINDEX but no SHT_SYMTAB_SHNDX section exists"); + return createStringError(errc::invalid_argument, + "symbol '" + *Name + + "' has index SHN_XINDEX but no " + "SHT_SYMTAB_SHNDX section exists"); if (ShndxData.data() == nullptr) { - const Elf_Shdr &ShndxSec = - *unwrapOrError(ElfFile.getSection(SymTab->getShndxTable()->Index)); - ShndxData = unwrapOrError( - ElfFile.template getSectionContentsAsArray(ShndxSec)); - if (ShndxData.size() != Symbols.size()) - error("symbol section index table does not have the same number of " - "entries as the symbol table"); + Expected ShndxSec = + ElfFile.getSection(SymTab->getShndxTable()->Index); + if (!ShndxSec) + return ShndxSec.takeError(); + + Expected> Data = + ElfFile.template getSectionContentsAsArray(**ShndxSec); + if (!Data) + return Data.takeError(); + + ShndxData = *Data; + if (ShndxData.size() != Symbols->size()) + return createStringError( + errc::invalid_argument, + "symbol section index table does not have the same number of " + "entries as the symbol table"); } - Elf_Word Index = ShndxData[&Sym - Symbols.begin()]; - DefSection = Obj.sections().getSection( + Elf_Word Index = ShndxData[&Sym - Symbols->begin()]; + Expected Sec = Obj.sections().getSection( Index, - "symbol '" + Name + "' has invalid section index " + Twine(Index)); + "symbol '" + *Name + "' has invalid section index " + Twine(Index)); + if (!Sec) + return Sec.takeError(); + + DefSection = *Sec; } else if (Sym.st_shndx >= SHN_LORESERVE) { if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) { - error( - "symbol '" + Name + - "' has unsupported value greater than or equal to SHN_LORESERVE: " + - Twine(Sym.st_shndx)); + return createStringError( + errc::invalid_argument, + "symbol '" + *Name + + "' has unsupported value greater than or equal " + "to SHN_LORESERVE: " + + Twine(Sym.st_shndx)); } } else if (Sym.st_shndx != SHN_UNDEF) { - DefSection = Obj.sections().getSection( - Sym.st_shndx, "symbol '" + Name + + Expected Sec = Obj.sections().getSection( + Sym.st_shndx, "symbol '" + *Name + "' is defined has invalid section index " + Twine(Sym.st_shndx)); + if (!Sec) + return Sec.takeError(); + + DefSection = *Sec; } - SymTab->addSymbol(Name, Sym.getBinding(), Sym.getType(), DefSection, + SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection, Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size); } + + return Error::success(); } template @@ -1435,8 +1615,8 @@ } template -static void initRelocations(RelocationSection *Relocs, - SymbolTableSection *SymbolTable, T RelRange) { +static Error initRelocations(RelocationSection *Relocs, + SymbolTableSection *SymbolTable, T RelRange) { for (const auto &Rel : RelRange) { Relocation ToAdd; ToAdd.Offset = Rel.r_offset; @@ -1445,39 +1625,54 @@ if (uint32_t Sym = Rel.getSymbol(false)) { if (!SymbolTable) - error("'" + Relocs->Name + - "': relocation references symbol with index " + Twine(Sym) + - ", but there is no symbol table"); - ToAdd.RelocSymbol = SymbolTable->getSymbolByIndex(Sym); + return createStringError( + errc::invalid_argument, + "'" + Relocs->Name + "': relocation references symbol with index " + + Twine(Sym) + ", but there is no symbol table"); + Expected SymByIndex = SymbolTable->getSymbolByIndex(Sym); + if (!SymByIndex) + return SymByIndex.takeError(); + + ToAdd.RelocSymbol = *SymByIndex; } Relocs->addRelocation(ToAdd); } + + return Error::success(); } -SectionBase *SectionTableRef::getSection(uint32_t Index, Twine ErrMsg) { +Expected SectionTableRef::getSection(uint32_t Index, + Twine ErrMsg) { if (Index == SHN_UNDEF || Index > Sections.size()) - error(ErrMsg); + return createStringError(errc::invalid_argument, ErrMsg); return Sections[Index - 1].get(); } template -T *SectionTableRef::getSectionOfType(uint32_t Index, Twine IndexErrMsg, - Twine TypeErrMsg) { - if (T *Sec = dyn_cast(getSection(Index, IndexErrMsg))) +Expected SectionTableRef::getSectionOfType(uint32_t Index, + Twine IndexErrMsg, + Twine TypeErrMsg) { + Expected BaseSec = getSection(Index, IndexErrMsg); + if (!BaseSec) + return BaseSec.takeError(); + + if (T *Sec = dyn_cast(*BaseSec)) return Sec; - error(TypeErrMsg); + + return createStringError(errc::invalid_argument, TypeErrMsg); } template -SectionBase &ELFBuilder::makeSection(const Elf_Shdr &Shdr) { - ArrayRef Data; +Expected ELFBuilder::makeSection(const Elf_Shdr &Shdr) { switch (Shdr.sh_type) { case SHT_REL: case SHT_RELA: if (Shdr.sh_flags & SHF_ALLOC) { - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection(*Data); + else + return Data.takeError(); } return Obj.addSection(); case SHT_STRTAB: @@ -1485,25 +1680,35 @@ // mean altering the memory image. There are no special link types or // anything so we can just use a Section. if (Shdr.sh_flags & SHF_ALLOC) { - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection
(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection
(*Data); + else + return Data.takeError(); } return Obj.addSection(); case SHT_HASH: case SHT_GNU_HASH: // Hash tables should refer to SHT_DYNSYM which we're not going to change. // Because of this we don't need to mess with the hash tables either. - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection
(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection
(*Data); + else + return Data.takeError(); case SHT_GROUP: - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection(*Data); + else + return Data.takeError(); case SHT_DYNSYM: - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection(*Data); + else + return Data.takeError(); case SHT_DYNAMIC: - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); - return Obj.addSection(Data); + if (Expected> Data = ElfFile.getSectionContents(Shdr)) + return Obj.addSection(*Data); + else + return Data.takeError(); case SHT_SYMTAB: { auto &SymTab = Obj.addSection(); Obj.SymbolTable = &SymTab; @@ -1515,114 +1720,175 @@ return ShndxSection; } case SHT_NOBITS: - return Obj.addSection
(Data); + return Obj.addSection
(ArrayRef()); default: { - Data = unwrapOrError(ElfFile.getSectionContents(Shdr)); + Expected> Data = ElfFile.getSectionContents(Shdr); + if (!Data) + return Data.takeError(); + + Expected Name = ElfFile.getSectionName(Shdr); + if (!Name) + return Name.takeError(); - StringRef Name = unwrapOrError(ElfFile.getSectionName(Shdr)); - if (Name.startswith(".zdebug") || (Shdr.sh_flags & ELF::SHF_COMPRESSED)) { + if (Name->startswith(".zdebug") || (Shdr.sh_flags & ELF::SHF_COMPRESSED)) { uint64_t DecompressedSize, DecompressedAlign; std::tie(DecompressedSize, DecompressedAlign) = - getDecompressedSizeAndAlignment(Data); - return Obj.addSection(Data, DecompressedSize, - DecompressedAlign); + getDecompressedSizeAndAlignment(*Data); + Expected NewSection = + CompressedSection::create(*Data, DecompressedSize, DecompressedAlign); + if (!NewSection) + return NewSection.takeError(); + + return Obj.addSection(std::move(*NewSection)); } - return Obj.addSection
(Data); + return Obj.addSection
(*Data); } } } -template void ELFBuilder::readSectionHeaders() { +template Error ELFBuilder::readSectionHeaders() { uint32_t Index = 0; - for (const auto &Shdr : unwrapOrError(ElfFile.sections())) { + Expected::Elf_Shdr_Range> Sections = + ElfFile.sections(); + if (!Sections) + return Sections.takeError(); + + for (const typename ELFFile::Elf_Shdr &Shdr : *Sections) { if (Index == 0) { ++Index; continue; } - auto &Sec = makeSection(Shdr); - Sec.Name = std::string(unwrapOrError(ElfFile.getSectionName(Shdr))); - Sec.Type = Sec.OriginalType = Shdr.sh_type; - Sec.Flags = Sec.OriginalFlags = Shdr.sh_flags; - Sec.Addr = Shdr.sh_addr; - Sec.Offset = Shdr.sh_offset; - Sec.OriginalOffset = Shdr.sh_offset; - Sec.Size = Shdr.sh_size; - Sec.Link = Shdr.sh_link; - Sec.Info = Shdr.sh_info; - Sec.Align = Shdr.sh_addralign; - Sec.EntrySize = Shdr.sh_entsize; - Sec.Index = Index++; - Sec.OriginalData = + Expected Sec = makeSection(Shdr); + if (!Sec) + return Sec.takeError(); + + Expected SecName = ElfFile.getSectionName(Shdr); + if (!SecName) + return SecName.takeError(); + Sec->Name = SecName->str(); + Sec->Type = Sec->OriginalType = Shdr.sh_type; + Sec->Flags = Sec->OriginalFlags = Shdr.sh_flags; + Sec->Addr = Shdr.sh_addr; + Sec->Offset = Shdr.sh_offset; + Sec->OriginalOffset = Shdr.sh_offset; + Sec->Size = Shdr.sh_size; + Sec->Link = Shdr.sh_link; + Sec->Info = Shdr.sh_info; + Sec->Align = Shdr.sh_addralign; + Sec->EntrySize = Shdr.sh_entsize; + Sec->Index = Index++; + Sec->OriginalData = ArrayRef(ElfFile.base() + Shdr.sh_offset, (Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size); } + + return Error::success(); } -template void ELFBuilder::readSections(bool EnsureSymtab) { +template Error ELFBuilder::readSections(bool EnsureSymtab) { uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx; - if (ShstrIndex == SHN_XINDEX) - ShstrIndex = unwrapOrError(ElfFile.getSection(0))->sh_link; + if (ShstrIndex == SHN_XINDEX) { + Expected Sec = ElfFile.getSection(0); + if (!Sec) + return Sec.takeError(); + + ShstrIndex = (*Sec)->sh_link; + } if (ShstrIndex == SHN_UNDEF) Obj.HadShdrs = false; - else - Obj.SectionNames = + else { + Expected Sec = Obj.sections().template getSectionOfType( ShstrIndex, "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " + " is invalid", "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " + " does not reference a string table"); + if (!Sec) + return Sec.takeError(); + + Obj.SectionNames = *Sec; + } // If a section index table exists we'll need to initialize it before we // initialize the symbol table because the symbol table might need to // reference it. if (Obj.SectionIndexTable) - Obj.SectionIndexTable->initialize(Obj.sections()); + if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections())) + return Err; // Now that all of the sections have been added we can fill out some extra // details about symbol tables. We need the symbol table filled out before // any relocations. if (Obj.SymbolTable) { - Obj.SymbolTable->initialize(Obj.sections()); - initSymbolTable(Obj.SymbolTable); + if (Error Err = Obj.SymbolTable->initialize(Obj.sections())) + return Err; + if (Error Err = initSymbolTable(Obj.SymbolTable)) + return Err; } else if (EnsureSymtab) { - Obj.addNewSymbolTable(); + if (Error Err = Obj.addNewSymbolTable()) + return Err; } // Now that all sections and symbols have been added we can add // relocations that reference symbols and set the link and info fields for // relocation sections. - for (auto &Sec : Obj.sections()) { + for (SectionBase &Sec : Obj.sections()) { if (&Sec == Obj.SymbolTable) continue; - Sec.initialize(Obj.sections()); + if (Error Err = Sec.initialize(Obj.sections())) + return Err; if (auto RelSec = dyn_cast(&Sec)) { - auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index; - if (RelSec->Type == SHT_REL) - initRelocations(RelSec, Obj.SymbolTable, - unwrapOrError(ElfFile.rels(*Shdr))); - else - initRelocations(RelSec, Obj.SymbolTable, - unwrapOrError(ElfFile.relas(*Shdr))); + Expected::Elf_Shdr_Range> Sections = + ElfFile.sections(); + if (!Sections) + return Sections.takeError(); + + const typename ELFFile::Elf_Shdr *Shdr = + Sections->begin() + RelSec->Index; + if (RelSec->Type == SHT_REL) { + Expected::Elf_Rel_Range> Rels = + ElfFile.rels(*Shdr); + if (!Rels) + return Rels.takeError(); + + if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Rels)) + return Err; + } else { + Expected::Elf_Rela_Range> Relas = + ElfFile.relas(*Shdr); + if (!Relas) + return Relas.takeError(); + + if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Relas)) + return Err; + } } else if (auto GroupSec = dyn_cast(&Sec)) { - initGroupSection(GroupSec); + if (Error Err = initGroupSection(GroupSec)) + return Err; } } + + return Error::success(); } -template void ELFBuilder::build(bool EnsureSymtab) { - readSectionHeaders(); - findEhdrOffset(); +template Error ELFBuilder::build(bool EnsureSymtab) { + if (Error E = readSectionHeaders()) + return E; + if (Error E = findEhdrOffset()) + return E; // The ELFFile whose ELF headers and program headers are copied into the // output file. Normally the same as ElfFile, but if we're extracting a // loadable partition it will point to the partition's headers. - ELFFile HeadersFile = unwrapOrError(ELFFile::create(toStringRef( - {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}))); + Expected> HeadersFile = ELFFile::create(toStringRef( + {ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset})); + if (!HeadersFile) + return HeadersFile.takeError(); - auto &Ehdr = HeadersFile.getHeader(); + const typename ELFFile::Elf_Ehdr &Ehdr = HeadersFile->getHeader(); Obj.OSABI = Ehdr.e_ident[EI_OSABI]; Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION]; Obj.Type = Ehdr.e_type; @@ -1631,15 +1897,17 @@ Obj.Entry = Ehdr.e_entry; Obj.Flags = Ehdr.e_flags; - readSections(EnsureSymtab); - readProgramHeaders(HeadersFile); + if (Error E = readSections(EnsureSymtab)) + return E; + return readProgramHeaders(*HeadersFile); } Writer::~Writer() {} Reader::~Reader() {} -std::unique_ptr BinaryReader::create(bool /*EnsureSymtab*/) const { +Expected> +BinaryReader::create(bool /*EnsureSymtab*/) const { return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build(); } @@ -1669,31 +1937,39 @@ return std::move(Records); } -std::unique_ptr IHexReader::create(bool /*EnsureSymtab*/) const { - std::vector Records = unwrapOrError(parse()); - return IHexELFBuilder(Records).build(); +Expected> +IHexReader::create(bool /*EnsureSymtab*/) const { + Expected> Records = parse(); + if (!Records) + return Records.takeError(); + + return IHexELFBuilder(*Records).build(); } -std::unique_ptr ELFReader::create(bool EnsureSymtab) const { +Expected> ELFReader::create(bool EnsureSymtab) const { auto Obj = std::make_unique(); if (auto *O = dyn_cast>(Bin)) { ELFBuilder Builder(*O, *Obj, ExtractPartition); - Builder.build(EnsureSymtab); - return Obj; + if (Error Err = Builder.build(EnsureSymtab)) + return std::move(Err); + return std::move(Obj); } else if (auto *O = dyn_cast>(Bin)) { ELFBuilder Builder(*O, *Obj, ExtractPartition); - Builder.build(EnsureSymtab); - return Obj; + if (Error Err = Builder.build(EnsureSymtab)) + return std::move(Err); + return std::move(Obj); } else if (auto *O = dyn_cast>(Bin)) { ELFBuilder Builder(*O, *Obj, ExtractPartition); - Builder.build(EnsureSymtab); - return Obj; + if (Error Err = Builder.build(EnsureSymtab)) + return std::move(Err); + return std::move(Obj); } else if (auto *O = dyn_cast>(Bin)) { ELFBuilder Builder(*O, *Obj, ExtractPartition); - Builder.build(EnsureSymtab); - return Obj; + if (Error Err = Builder.build(EnsureSymtab)) + return std::move(Err); + return std::move(Obj); } - error("invalid file type"); + return createStringError(errc::invalid_argument, "invalid file type"); } template void ELFWriter::writeEhdr() { @@ -1787,13 +2063,16 @@ writeShdr(Sec); } -template void ELFWriter::writeSectionData() { +template Error ELFWriter::writeSectionData() { for (SectionBase &Sec : Obj.sections()) // Segments are responsible for writing their contents, so only write the // section data if the section is not in a segment. Note that this renders // sections in segments effectively immutable. if (Sec.ParentSegment == nullptr) - Sec.accept(*SecWriter); + if (Error Err = Sec.accept(*SecWriter)) + return Err; + + return Error::success(); } template void ELFWriter::writeSegmentData() { @@ -1880,7 +2159,7 @@ return Error::success(); } -void Object::addNewSymbolTable() { +Error Object::addNewSymbolTable() { assert(!SymbolTable && "Object must not has a SymbolTable."); // Reuse an existing SHT_STRTAB section if it exists. @@ -1901,10 +2180,13 @@ SymbolTableSection &SymTab = addSection(); SymTab.Name = ".symtab"; SymTab.Link = StrTab->Index; - SymTab.initialize(sections()); + if (Error Err = SymTab.initialize(sections())) + return Err; SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0); SymbolTable = &SymTab; + + return Error::success(); } void Object::sortSections() { @@ -2118,7 +2400,8 @@ writeSegmentData(); writeEhdr(); writePhdrs(); - writeSectionData(); + if (Error E = writeSectionData()) + return E; if (WriteSectionHeaders) writeShdrs(); return Buf.commit(); @@ -2207,7 +2490,8 @@ auto SecSizer = std::make_unique>(); for (SectionBase &Sec : Obj.sections()) { Sec.Index = Index++; - Sec.accept(*SecSizer); + if (Error Err = Sec.accept(*SecSizer)) + return Err; } // The symbol table does not update all other sections on update. For @@ -2248,7 +2532,9 @@ Error BinaryWriter::write() { for (const SectionBase &Sec : Obj.allocSections()) - Sec.accept(*SecWriter); + if (Error Err = Sec.accept(*SecWriter)) + return Err; + return Buf.commit(); } @@ -2320,7 +2606,8 @@ IHexSectionWriter Writer(Buf); // Write sections. for (const SectionBase *Sec : Sections) - Sec->accept(Writer); + if (Error Err = Sec->accept(Writer)) + return Err; uint64_t Offset = Writer.getBufferOffset(); // Write entry point address. @@ -2374,7 +2661,8 @@ IHexSectionWriterBase LengthCalc(Buf); for (const SectionBase *Sec : Sections) - Sec->accept(LengthCalc); + if (Error Err = Sec->accept(LengthCalc)) + return Err; // We need space to write section records + StartAddress record // (if start adress is not zero) + EndOfFile record. 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 @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "MachOReader.h" -#include "../llvm-objcopy.h" #include "Object.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/Object/MachO.h" diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp --- a/llvm/tools/llvm-objcopy/MachO/Object.cpp +++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// #include "Object.h" -#include "../llvm-objcopy.h" #include "llvm/ADT/SmallPtrSet.h" #include diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.h b/llvm/tools/llvm-objcopy/llvm-objcopy.h deleted file mode 100644 --- a/llvm/tools/llvm-objcopy/llvm-objcopy.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- llvm-objcopy.h -------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_OBJCOPY_OBJCOPY_H -#define LLVM_TOOLS_OBJCOPY_OBJCOPY_H - -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { -namespace objcopy { - -LLVM_ATTRIBUTE_NORETURN extern void error(Twine Message); -LLVM_ATTRIBUTE_NORETURN extern void error(Error E); -LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, Error E); -LLVM_ATTRIBUTE_NORETURN extern void reportError(StringRef File, - std::error_code EC); - -// This is taken from llvm-readobj. -// [see here](llvm/tools/llvm-readobj/llvm-readobj.h:38) -template T unwrapOrError(Expected EO) { - if (EO) - return *EO; - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(EO.takeError(), OS); - OS.flush(); - error(Buf); -} - -} // end namespace objcopy -} // end namespace llvm - -#endif // LLVM_TOOLS_OBJCOPY_OBJCOPY_H diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp --- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp +++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm-objcopy.h" #include "Buffer.h" #include "COFF/COFFObjcopy.h" #include "CopyConfig.h" @@ -57,36 +56,6 @@ // The name this program was invoked as. StringRef ToolName; -LLVM_ATTRIBUTE_NORETURN void error(Twine Message) { - WithColor::error(errs(), ToolName) << Message << "\n"; - exit(1); -} - -LLVM_ATTRIBUTE_NORETURN void error(Error E) { - assert(E); - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(std::move(E), OS); - OS.flush(); - WithColor::error(errs(), ToolName) << Buf; - exit(1); -} - -LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, std::error_code EC) { - assert(EC); - error(createFileError(File, EC)); -} - -LLVM_ATTRIBUTE_NORETURN void reportError(StringRef File, Error E) { - assert(E); - std::string Buf; - raw_string_ostream OS(Buf); - logAllUnhandledErrors(std::move(E), OS); - OS.flush(); - WithColor::error(errs(), ToolName) << "'" << File << "': " << Buf; - exit(1); -} - ErrorSuccess reportWarning(Error E) { assert(E); WithColor::warning(errs(), ToolName) << toString(std::move(E)) << '\n'; diff --git a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp --- a/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/wasm/WasmObjcopy.cpp @@ -12,7 +12,6 @@ #include "Object.h" #include "Reader.h" #include "Writer.h" -#include "llvm-objcopy.h" #include "llvm/Support/Errc.h" namespace llvm {