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 @@ -173,32 +173,6 @@ return createStringError(EC, FullMsg.c_str(), std::forward(Args)...); } -static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader, - StringRef File, ElfType OutputElfType) { - Expected> DWOFile = Reader.create(false); - if (!DWOFile) - return DWOFile.takeError(); - - auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) { - return onlyKeepDWOPred(**DWOFile, Sec); - }; - 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; - } - - return writeToFile(File, [&](raw_ostream &OutFile) -> Error { - std::unique_ptr Writer = - createWriter(Config, **DWOFile, OutFile, OutputElfType); - if (Error E = Writer->finalize()) - return E; - return Writer->write(); - }); -} - static Error dumpSectionToFile(StringRef SecName, StringRef Filename, Object &Obj) { for (auto &Sec : Obj.sections()) { @@ -374,7 +348,7 @@ }; } - if (Config.StripDWO || !Config.SplitDWO.empty()) + if (Config.StripDWO) RemovePred = [RemovePred](const SectionBase &Sec) { return isDWOSection(Sec) || RemovePred(Sec); }; @@ -532,21 +506,22 @@ // any previous removals. Lastly whether or not something is removed shouldn't // 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 Error handleArgs(const CopyConfig &Config, Object &Obj, - const Reader &Reader, ElfType OutputElfType) { +static Error handleArgs(const CopyConfig &Config, Object &Obj) { if (Config.StripSwiftSymbols || Config.KeepUndefined) return createStringError(llvm::errc::invalid_argument, "option not supported by llvm-objcopy for ELF"); - if (!Config.SplitDWO.empty()) - if (Error E = - splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType)) - return E; if (Config.OutputArch) { Obj.Machine = Config.OutputArch.getValue().EMachine; Obj.OSABI = Config.OutputArch.getValue().OSABI; } + if (!Config.SplitDWO.empty() && Config.ExtractDWO) { + return Obj.removeSections( + Config.AllowBrokenLinks, + [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }); + } + // Dump sections before add/remove for compatibility with GNU objcopy. for (StringRef Flag : Config.DumpSection) { StringRef SectionName; @@ -706,7 +681,7 @@ const ElfType OutputElfType = getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); - if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj)) return E; return writeOutput(Config, **Obj, Out, OutputElfType); } @@ -724,7 +699,7 @@ // (-B). const ElfType OutputElfType = getOutputElfType(Config.OutputArch.getValueOr(MachineInfo())); - if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj)) return E; return writeOutput(Config, **Obj, Out, OutputElfType); } @@ -741,7 +716,7 @@ Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue()) : getOutputElfType(In); - if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType)) + if (Error E = handleArgs(Config, **Obj)) return createFileError(Config.InputFilename, std::move(E)); if (Error E = writeOutput(Config, **Obj, Out, OutputElfType)) 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 @@ -322,44 +322,68 @@ Stat.permissions(static_cast(0777)); } - using ProcessRawFn = Error (*)(CopyConfig &, MemoryBuffer &, raw_ostream &); - ProcessRawFn ProcessRaw; - switch (Config.InputFormat) { - case FileFormat::Binary: - ProcessRaw = executeObjcopyOnRawBinary; - break; - case FileFormat::IHex: - ProcessRaw = executeObjcopyOnIHex; - break; - default: - ProcessRaw = nullptr; - } + std::function ObjcopyFunc; - if (ProcessRaw) { - auto BufOrErr = MemoryBuffer::getFileOrSTDIN(Config.InputFilename); + OwningBinary BinaryHolder; + std::unique_ptr MemoryBufferHolder; + + if (Config.InputFormat == FileFormat::Binary || + Config.InputFormat == FileFormat::IHex) { + ErrorOr> BufOrErr = + MemoryBuffer::getFileOrSTDIN(Config.InputFilename); if (!BufOrErr) return createFileError(Config.InputFilename, BufOrErr.getError()); - - if (Error E = writeToFile( - Config.OutputFilename, [&](raw_ostream &OutFile) -> Error { - return ProcessRaw(Config, *BufOrErr->get(), OutFile); - })) - return E; + MemoryBufferHolder = std::move(*BufOrErr); + + if (Config.InputFormat == FileFormat::Binary) + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + // Handle FileFormat::Binary. + return executeObjcopyOnRawBinary(Config, *MemoryBufferHolder, OutFile); + }; + else + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + // Handle FileFormat::IHex. + return executeObjcopyOnIHex(Config, *MemoryBufferHolder, OutFile); + }; } else { Expected> BinaryOrErr = createBinary(Config.InputFilename); if (!BinaryOrErr) return createFileError(Config.InputFilename, BinaryOrErr.takeError()); + BinaryHolder = std::move(*BinaryOrErr); - if (Archive *Ar = dyn_cast(BinaryOrErr.get().getBinary())) { + if (Archive *Ar = dyn_cast(BinaryHolder.getBinary())) { + // Handle Archive. if (Error E = executeObjcopyOnArchive(Config, *Ar)) return E; } else { - if (Error E = writeToFile( - Config.OutputFilename, [&](raw_ostream &OutFile) -> Error { - return executeObjcopyOnBinary( - Config, *BinaryOrErr.get().getBinary(), OutFile); - })) + // Handle llvm::object::Binary. + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + return executeObjcopyOnBinary(Config, *BinaryHolder.getBinary(), + OutFile); + }; + } + } + + if (ObjcopyFunc) { + if (Config.SplitDWO.empty()) { + // Apply transformations described by Config and store result into + // Config.OutputFilename using specified ObjcopyFunc function. + if (Error E = writeToFile(Config.OutputFilename, ObjcopyFunc)) + return E; + } else { + Config.ExtractDWO = true; + Config.StripDWO = false; + // Copy .dwo tables from the Config.InputFilename into Config.SplitDWO + // file using specified ObjcopyFunc function. + if (Error E = writeToFile(Config.SplitDWO, ObjcopyFunc)) + return E; + Config.ExtractDWO = false; + Config.StripDWO = true; + // Apply transformations described by Config, remove .dwo tables and + // store result into Config.OutputFilename using specified ObjcopyFunc + // function. + if (Error E = writeToFile(Config.OutputFilename, ObjcopyFunc)) return E; } }