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 @@ -40,11 +40,12 @@ Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1); } -static std::vector createGnuDebugLinkSectionContents(StringRef File) { +static Expected> +createGnuDebugLinkSectionContents(StringRef File) { ErrorOr> LinkTargetOrErr = MemoryBuffer::getFile(File); if (!LinkTargetOrErr) - error("'" + File + "': " + LinkTargetOrErr.getError().message()); + return createFileError(File, LinkTargetOrErr.getError()); auto LinkTarget = std::move(*LinkTargetOrErr); uint32_t CRC32 = llvm::crc32(arrayRefFromStringRef(LinkTarget->getBuffer())); @@ -81,12 +82,17 @@ Obj.addSections(Sec); } -static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { - std::vector Contents = +static Error addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { + Expected> Contents = createGnuDebugLinkSectionContents(DebugLinkFile); - addSection(Obj, ".gnu_debuglink", Contents, + if (!Contents) + return Contents.takeError(); + + addSection(Obj, ".gnu_debuglink", *Contents, IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE); + + return Error::success(); } static void setSectionFlags(Section &Sec, SectionFlag AllFlags) { @@ -174,8 +180,7 @@ Sym.Name = I->getValue(); } - // Actually do removals of symbols. - Obj.removeSymbols([&](const Symbol &Sym) { + auto ToRemove = [&](const Symbol &Sym) -> Expected { // For StripAll, all relocations have been stripped and we remove all // symbols. if (Config.StripAll || Config.StripAllGNU) @@ -184,11 +189,10 @@ if (Config.SymbolsToRemove.matches(Sym.Name)) { // Explicitly removing a referenced symbol is an error. if (Sym.Referenced) - reportError(Config.OutputFilename, - createStringError(llvm::errc::invalid_argument, - "not stripping symbol '%s' because it is " - "named in a relocation", - Sym.Name.str().c_str())); + return createStringError( + llvm::errc::invalid_argument, + "'" + Config.OutputFilename + "': not stripping symbol '" + + Sym.Name.str() + "' because it is named in a relocation"); return true; } @@ -213,7 +217,11 @@ } return false; - }); + }; + + // Actually do removals of symbols. + if (Error Err = Obj.removeSymbols(ToRemove)) + return Err; if (!Config.SetSectionFlags.empty()) for (Section &Sec : Obj.getMutableSections()) { @@ -239,7 +247,8 @@ } if (!Config.AddGnuDebugLink.empty()) - addGnuDebugLink(Obj, Config.AddGnuDebugLink); + if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink)) + return E; if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || Config.BuildIdLinkInput || Config.BuildIdLinkOutput || diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h --- a/llvm/tools/llvm-objcopy/COFF/Object.h +++ b/llvm/tools/llvm-objcopy/COFF/Object.h @@ -116,7 +116,7 @@ const Symbol *findSymbol(size_t UniqueId) const; void addSymbols(ArrayRef NewSymbols); - void removeSymbols(function_ref ToRemove); + Error removeSymbols(function_ref(const Symbol &)> ToRemove); // Set the Referenced field on all Symbols, based on relocations in // all sections. diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp --- a/llvm/tools/llvm-objcopy/COFF/Object.cpp +++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp @@ -37,12 +37,23 @@ return It->second; } -void Object::removeSymbols(function_ref ToRemove) { - Symbols.erase( - std::remove_if(std::begin(Symbols), std::end(Symbols), - [ToRemove](const Symbol &Sym) { return ToRemove(Sym); }), - std::end(Symbols)); +Error Object::removeSymbols( + function_ref(const Symbol &)> ToRemove) { + Error Errs = Error::success(); + Symbols.erase(std::remove_if(std::begin(Symbols), std::end(Symbols), + [ToRemove, &Errs](const Symbol &Sym) { + Expected ShouldRemove = ToRemove(Sym); + if (!ShouldRemove) { + Errs = joinErrors(std::move(Errs), + ShouldRemove.takeError()); + return false; + } + return *ShouldRemove; + }), + std::end(Symbols)); + updateSymbols(); + return Errs; } Error Object::markSymbols() {