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()) { @@ -364,6 +338,25 @@ return Obj.removeSymbols(RemoveSymbolsPred); } +static Error keepOrRemoveDWOSections(const CopyConfig &Config, Object &Obj) { + assert(!Config.SplitDWO.empty()); + assert(Config.ExtractDWO != Config.StripDWO); + + if (Config.ExtractDWO) { + return Obj.removeSections( + Config.AllowBrokenLinks, + [&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); }); + } + + if (Config.StripDWO) { + return Obj.removeSections( + Config.AllowBrokenLinks, + [](const SectionBase &Sec) { return isDWOSection(Sec); }); + } + + llvm_unreachable("Ambigous SplitDWO option"); +} + static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) { SectionPred RemovePred = [](const SectionBase &) { return false; }; @@ -374,7 +367,7 @@ }; } - if (Config.StripDWO || !Config.SplitDWO.empty()) + if (Config.StripDWO) RemovePred = [RemovePred](const SectionBase &Sec) { return isDWOSection(Sec) || RemovePred(Sec); }; @@ -532,21 +525,19 @@ // 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()) + return keepOrRemoveDWOSections(Config, Obj); + // Dump sections before add/remove for compatibility with GNU objcopy. for (StringRef Flag : Config.DumpSection) { StringRef SectionName; @@ -706,7 +697,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 +715,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 +732,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 @@ -326,48 +326,77 @@ 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 = nullptr; + + OwningBinary BinaryHolder; + std::unique_ptr MemoryBufferHolder; - if (ProcessRaw) { - auto BufOrErr = MemoryBuffer::getFileOrSTDIN(Config.InputFilename); + if (Config.InputFormat == FileFormat::Binary) { + // Handle FileFormat::Binary. + ErrorOr> BufOrErr = + MemoryBuffer::getFileOrSTDIN(Config.InputFilename); if (!BufOrErr) return createFileError(Config.InputFilename, BufOrErr.getError()); + MemoryBufferHolder = std::move(*BufOrErr); + + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + return executeObjcopyOnRawBinary(Config, *MemoryBufferHolder, OutFile); + }; + } else if (Config.InputFormat == FileFormat::IHex) { + // Handle FileFormat::IHex. + ErrorOr> BufOrErr = + MemoryBuffer::getFileOrSTDIN(Config.InputFilename); + if (!BufOrErr) + return createFileError(Config.InputFilename, BufOrErr.getError()); + MemoryBufferHolder = std::move(*BufOrErr); - if (Error E = writeToFile( - Config.OutputFilename, [&](raw_ostream &OutFile) -> Error { - return ProcessRaw(Config, *BufOrErr->get(), OutFile); - })) - return E; + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + 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); - }, - Config.InputFilename != "-" && - Config.InputFilename == Config.OutputFilename, - Stat.getUser(), Stat.getGroup())) + // Handle llvm::object::Binary. + ObjcopyFunc = [&](raw_ostream &OutFile) -> Error { + return executeObjcopyOnBinary(Config, *BinaryHolder.getBinary(), + OutFile); + }; + } + } + + if (ObjcopyFunc) { + if (Config.SplitDWO.empty()) { + if (Error E = + writeToFile(Config.OutputFilename, ObjcopyFunc, + Config.InputFilename != "-" && + Config.InputFilename == Config.OutputFilename, + Stat.getUser(), Stat.getGroup())) + return E; + } else { + Config.ExtractDWO = true; + Config.StripDWO = false; + if (Error E = + writeToFile(Config.SplitDWO, ObjcopyFunc, + Config.InputFilename != "-" && + Config.InputFilename == Config.OutputFilename, + Stat.getUser(), Stat.getGroup())) + return E; + Config.ExtractDWO = false; + Config.StripDWO = true; + if (Error E = + writeToFile(Config.OutputFilename, ObjcopyFunc, + Config.InputFilename != "-" && + Config.InputFilename == Config.OutputFilename, + Stat.getUser(), Stat.getGroup())) return E; } }