Index: tools/llvm-objcopy/Object.h =================================================================== --- tools/llvm-objcopy/Object.h +++ tools/llvm-objcopy/Object.h @@ -613,9 +613,22 @@ }; class Reader { +public: + enum class ReaderKind { + BinaryKind, + ELFKind, + }; + +private: + const ReaderKind Kind; + +protected: + Reader(ReaderKind K) : Kind(K) {} + public: virtual ~Reader(); virtual std::unique_ptr create() const = 0; + ReaderKind getKind() const { return Kind; } }; using object::Binary; @@ -647,13 +660,25 @@ void build(); }; +class BinaryReader : public Reader { +public: + BinaryReader() : Reader(ReaderKind::BinaryKind) {} + std::unique_ptr create() const override; + static bool classof(const Reader *R) { + return R->getKind() == ReaderKind::BinaryKind; + } +}; + class ELFReader : public Reader { Binary *Bin; public: ElfType getElfType() const; std::unique_ptr create() const override; - explicit ELFReader(Binary *B) : Bin(B){}; + explicit ELFReader(Binary *B) : Reader(ReaderKind::ELFKind), Bin(B) {} + static bool classof(const Reader *R) { + return R->getKind() == ReaderKind::ELFKind; + } }; class Object { Index: tools/llvm-objcopy/Object.cpp =================================================================== --- tools/llvm-objcopy/Object.cpp +++ tools/llvm-objcopy/Object.cpp @@ -925,6 +925,10 @@ Reader::~Reader() {} +std::unique_ptr BinaryReader::create() const { + error("--input-target Binary is currently unsupported"); +} + ElfType ELFReader::getElfType() const { if (isa>(Bin)) return ELFT_ELF32LE; Index: tools/llvm-objcopy/llvm-objcopy.cpp =================================================================== --- tools/llvm-objcopy/llvm-objcopy.cpp +++ tools/llvm-objcopy/llvm-objcopy.cpp @@ -288,14 +288,27 @@ return !IsDWOSection(Sec); } +static Optional GetOutputElfType(const CopyConfig &Config, + const Reader &Reader) { + if (Config.OutputFormat == "binary") + return None; + // We must be an ELFReader -- it's the only implementation currently used. + // TODO: support BinaryReader. In that case, read from + // Config.BinaryArchitecture config to determine output type. + const auto *ER = dyn_cast(&Reader); + return ER->getElfType(); +} + static std::unique_ptr CreateWriter(const CopyConfig &Config, Object &Obj, Buffer &Buf, - ElfType OutputElfType) { + Optional OutputElfType) { if (Config.OutputFormat == "binary") { return llvm::make_unique(Obj, Buf); } // Depending on the initial ELFT and OutputFormat we need a different Writer. - switch (OutputElfType) { + if (!OutputElfType) + llvm_unreachable("Unknown output ELF type"); + switch (OutputElfType.getValue()) { case ELFT_ELF32LE: return llvm::make_unique>(Obj, Buf, !Config.StripSections); @@ -313,11 +326,12 @@ } static void SplitDWOToFile(const CopyConfig &Config, const Reader &Reader, - StringRef File, ElfType OutputElfType) { + StringRef File) { auto DWOFile = Reader.create(); DWOFile->removeSections( [&](const SectionBase &Sec) { return OnlyKeepDWOPred(*DWOFile, Sec); }); FileBuffer FB(File); + Optional OutputElfType = GetOutputElfType(Config, Reader); auto Writer = CreateWriter(Config, *DWOFile, FB, OutputElfType); Writer->finalize(); Writer->write(); @@ -331,10 +345,10 @@ // depend a) on the order the options occur in or b) on some opaque priority // system. The only priority is that keeps/copies overrule removes. static void HandleArgs(const CopyConfig &Config, Object &Obj, - const Reader &Reader, ElfType OutputElfType) { + const Reader &Reader) { if (!Config.SplitDWO.empty()) { - SplitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType); + SplitDWOToFile(Config, Reader, Config.SplitDWO); } // TODO: update or remove symbols only if there is an option that affects @@ -559,15 +573,15 @@ Obj.addSection(Config.AddGnuDebugLink); } -static void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Binary &Binary, +static void ExecuteElfObjcopyOnBinary(const CopyConfig &Config, Reader &Reader, Buffer &Out) { - ELFReader Reader(&Binary); std::unique_ptr Obj = Reader.create(); - HandleArgs(Config, *Obj, Reader, Reader.getElfType()); + HandleArgs(Config, *Obj, Reader); + Optional OutputElfType = GetOutputElfType(Config, Reader); std::unique_ptr Writer = - CreateWriter(Config, *Obj, Out, Reader.getElfType()); + CreateWriter(Config, *Obj, Out, OutputElfType); Writer->finalize(); Writer->write(); } @@ -614,7 +628,8 @@ reportError(Ar.getFileName(), ChildNameOrErr.takeError()); MemBuffer MB(ChildNameOrErr.get()); - ExecuteElfObjcopyOnBinary(Config, **ChildOrErr, MB); + ELFReader Reader(ChildOrErr->get()); + ExecuteElfObjcopyOnBinary(Config, Reader, MB); Expected Member = NewArchiveMember::getOldMember(Child, true); @@ -643,7 +658,8 @@ return ExecuteElfObjcopyOnArchive(Config, *Ar); FileBuffer FB(Config.OutputFilename); - ExecuteElfObjcopyOnBinary(Config, *BinaryOrErr.get().getBinary(), FB); + ELFReader Reader(BinaryOrErr.get().getBinary()); + ExecuteElfObjcopyOnBinary(Config, Reader, FB); } // ParseObjcopyOptions returns the config and sets the input arguments. If a