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,12 +40,12 @@ Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1); } -static std::vector createGnuDebugLinkSectionContents(StringRef File) { - ErrorOr> LinkTargetOrErr = - MemoryBuffer::getFile(File); - if (!LinkTargetOrErr) - error("'" + File + "': " + LinkTargetOrErr.getError().message()); - auto LinkTarget = std::move(*LinkTargetOrErr); +static Expected> +createGnuDebugLinkSectionContents(StringRef File) { + ErrorOr> FileData = MemoryBuffer::getFile(File); + if (!FileData) + return createFileError(File, FileData.getError()); + auto LinkTarget = std::move(*FileData); uint32_t CRC32 = llvm::crc32(arrayRefFromStringRef(LinkTarget->getBuffer())); StringRef FileName = sys::path::filename(File); @@ -81,12 +81,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 +179,8 @@ Sym.Name = I->getValue(); } - // Actually do removals of symbols. - Obj.removeSymbols([&](const Symbol &Sym) { + std::function(const Symbol &)> 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 || @@ -266,10 +275,10 @@ Error executeObjcopyOnBinary(const CopyConfig &Config, COFFObjectFile &In, Buffer &Out) { COFFReader Reader(In); - Expected> ObjOrErr = Reader.create(); - if (!ObjOrErr) - return createFileError(Config.InputFilename, ObjOrErr.takeError()); - Object *Obj = ObjOrErr->get(); + Expected> O = Reader.create(); + if (!O) + return createFileError(Config.InputFilename, O.takeError()); + Object *Obj = O->get(); assert(Obj && "Unable to deserialize COFF object"); if (Error E = handleArgs(Config, *Obj)) return createFileError(Config.InputFilename, std::move(E)); 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,33 @@ 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) { + std::vector::iterator Current = Symbols.begin(); + std::vector::iterator End = Symbols.end(); + Optional::iterator> LastRemoved; + + for (; Current != End; Current++) { + Expected Remove = ToRemove(*Current); + if (!Remove) + return Remove.takeError(); + + if (*Remove) { + if (!LastRemoved) + LastRemoved = Current; + } else { + if (LastRemoved) { + **LastRemoved = std::move(*Current); + (*LastRemoved)++; + } + } + } + + if (LastRemoved) + Symbols.erase(*LastRemoved, Symbols.end()); + updateSymbols(); + return Error::success(); } Error Object::markSymbols() {