181ad6265SDimitry Andric //===- COFFObjcopy.cpp ----------------------------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #include "llvm/ObjCopy/COFF/COFFObjcopy.h" 1081ad6265SDimitry Andric #include "COFFObject.h" 1181ad6265SDimitry Andric #include "COFFReader.h" 1281ad6265SDimitry Andric #include "COFFWriter.h" 1381ad6265SDimitry Andric #include "llvm/ObjCopy/COFF/COFFConfig.h" 1481ad6265SDimitry Andric #include "llvm/ObjCopy/CommonConfig.h" 1581ad6265SDimitry Andric 16*06c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 1781ad6265SDimitry Andric #include "llvm/Object/Binary.h" 1881ad6265SDimitry Andric #include "llvm/Object/COFF.h" 1981ad6265SDimitry Andric #include "llvm/Support/CRC.h" 2081ad6265SDimitry Andric #include "llvm/Support/Errc.h" 2181ad6265SDimitry Andric #include "llvm/Support/Path.h" 2281ad6265SDimitry Andric #include <cassert> 2381ad6265SDimitry Andric 2481ad6265SDimitry Andric namespace llvm { 2581ad6265SDimitry Andric namespace objcopy { 2681ad6265SDimitry Andric namespace coff { 2781ad6265SDimitry Andric 2881ad6265SDimitry Andric using namespace object; 2981ad6265SDimitry Andric using namespace COFF; 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric static bool isDebugSection(const Section &Sec) { 3281ad6265SDimitry Andric return Sec.Name.startswith(".debug"); 3381ad6265SDimitry Andric } 3481ad6265SDimitry Andric 3581ad6265SDimitry Andric static uint64_t getNextRVA(const Object &Obj) { 3681ad6265SDimitry Andric if (Obj.getSections().empty()) 3781ad6265SDimitry Andric return 0; 3881ad6265SDimitry Andric const Section &Last = Obj.getSections().back(); 3981ad6265SDimitry Andric return alignTo(Last.Header.VirtualAddress + Last.Header.VirtualSize, 4081ad6265SDimitry Andric Obj.IsPE ? Obj.PeHeader.SectionAlignment : 1); 4181ad6265SDimitry Andric } 4281ad6265SDimitry Andric 4381ad6265SDimitry Andric static Expected<std::vector<uint8_t>> 4481ad6265SDimitry Andric createGnuDebugLinkSectionContents(StringRef File) { 4581ad6265SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> LinkTargetOrErr = 4681ad6265SDimitry Andric MemoryBuffer::getFile(File); 4781ad6265SDimitry Andric if (!LinkTargetOrErr) 4881ad6265SDimitry Andric return createFileError(File, LinkTargetOrErr.getError()); 4981ad6265SDimitry Andric auto LinkTarget = std::move(*LinkTargetOrErr); 5081ad6265SDimitry Andric uint32_t CRC32 = llvm::crc32(arrayRefFromStringRef(LinkTarget->getBuffer())); 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric StringRef FileName = sys::path::filename(File); 5381ad6265SDimitry Andric size_t CRCPos = alignTo(FileName.size() + 1, 4); 5481ad6265SDimitry Andric std::vector<uint8_t> Data(CRCPos + 4); 5581ad6265SDimitry Andric memcpy(Data.data(), FileName.data(), FileName.size()); 5681ad6265SDimitry Andric support::endian::write32le(Data.data() + CRCPos, CRC32); 5781ad6265SDimitry Andric return Data; 5881ad6265SDimitry Andric } 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric // Adds named section with given contents to the object. 6181ad6265SDimitry Andric static void addSection(Object &Obj, StringRef Name, ArrayRef<uint8_t> Contents, 6281ad6265SDimitry Andric uint32_t Characteristics) { 6381ad6265SDimitry Andric bool NeedVA = Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | 6481ad6265SDimitry Andric IMAGE_SCN_MEM_WRITE); 6581ad6265SDimitry Andric 6681ad6265SDimitry Andric Section Sec; 6781ad6265SDimitry Andric Sec.setOwnedContents(Contents); 6881ad6265SDimitry Andric Sec.Name = Name; 6981ad6265SDimitry Andric Sec.Header.VirtualSize = NeedVA ? Sec.getContents().size() : 0u; 7081ad6265SDimitry Andric Sec.Header.VirtualAddress = NeedVA ? getNextRVA(Obj) : 0u; 7181ad6265SDimitry Andric Sec.Header.SizeOfRawData = 7281ad6265SDimitry Andric NeedVA ? alignTo(Sec.Header.VirtualSize, 7381ad6265SDimitry Andric Obj.IsPE ? Obj.PeHeader.FileAlignment : 1) 7481ad6265SDimitry Andric : Sec.getContents().size(); 7581ad6265SDimitry Andric // Sec.Header.PointerToRawData is filled in by the writer. 7681ad6265SDimitry Andric Sec.Header.PointerToRelocations = 0; 7781ad6265SDimitry Andric Sec.Header.PointerToLinenumbers = 0; 7881ad6265SDimitry Andric // Sec.Header.NumberOfRelocations is filled in by the writer. 7981ad6265SDimitry Andric Sec.Header.NumberOfLinenumbers = 0; 8081ad6265SDimitry Andric Sec.Header.Characteristics = Characteristics; 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric Obj.addSections(Sec); 8381ad6265SDimitry Andric } 8481ad6265SDimitry Andric 8581ad6265SDimitry Andric static Error addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) { 8681ad6265SDimitry Andric Expected<std::vector<uint8_t>> Contents = 8781ad6265SDimitry Andric createGnuDebugLinkSectionContents(DebugLinkFile); 8881ad6265SDimitry Andric if (!Contents) 8981ad6265SDimitry Andric return Contents.takeError(); 9081ad6265SDimitry Andric 9181ad6265SDimitry Andric addSection(Obj, ".gnu_debuglink", *Contents, 9281ad6265SDimitry Andric IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | 9381ad6265SDimitry Andric IMAGE_SCN_MEM_DISCARDABLE); 9481ad6265SDimitry Andric 9581ad6265SDimitry Andric return Error::success(); 9681ad6265SDimitry Andric } 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric static uint32_t flagsToCharacteristics(SectionFlag AllFlags, uint32_t OldChar) { 9981ad6265SDimitry Andric // Need to preserve alignment flags. 10081ad6265SDimitry Andric const uint32_t PreserveMask = 10181ad6265SDimitry Andric IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_ALIGN_4BYTES | 10281ad6265SDimitry Andric IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_ALIGN_16BYTES | 10381ad6265SDimitry Andric IMAGE_SCN_ALIGN_32BYTES | IMAGE_SCN_ALIGN_64BYTES | 10481ad6265SDimitry Andric IMAGE_SCN_ALIGN_128BYTES | IMAGE_SCN_ALIGN_256BYTES | 10581ad6265SDimitry Andric IMAGE_SCN_ALIGN_512BYTES | IMAGE_SCN_ALIGN_1024BYTES | 10681ad6265SDimitry Andric IMAGE_SCN_ALIGN_2048BYTES | IMAGE_SCN_ALIGN_4096BYTES | 10781ad6265SDimitry Andric IMAGE_SCN_ALIGN_8192BYTES; 10881ad6265SDimitry Andric 10981ad6265SDimitry Andric // Setup new section characteristics based on the flags provided in command 11081ad6265SDimitry Andric // line. 11181ad6265SDimitry Andric uint32_t NewCharacteristics = (OldChar & PreserveMask) | IMAGE_SCN_MEM_READ; 11281ad6265SDimitry Andric 11381ad6265SDimitry Andric if ((AllFlags & SectionFlag::SecAlloc) && !(AllFlags & SectionFlag::SecLoad)) 11481ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA; 11581ad6265SDimitry Andric if (AllFlags & SectionFlag::SecNoload) 11681ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; 11781ad6265SDimitry Andric if (!(AllFlags & SectionFlag::SecReadonly)) 11881ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_MEM_WRITE; 11981ad6265SDimitry Andric if (AllFlags & SectionFlag::SecDebug) 12081ad6265SDimitry Andric NewCharacteristics |= 12181ad6265SDimitry Andric IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE; 12281ad6265SDimitry Andric if (AllFlags & SectionFlag::SecCode) 12381ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE; 12481ad6265SDimitry Andric if (AllFlags & SectionFlag::SecData) 12581ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA; 12681ad6265SDimitry Andric if (AllFlags & SectionFlag::SecShare) 12781ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_MEM_SHARED; 12881ad6265SDimitry Andric if (AllFlags & SectionFlag::SecExclude) 12981ad6265SDimitry Andric NewCharacteristics |= IMAGE_SCN_LNK_REMOVE; 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric return NewCharacteristics; 13281ad6265SDimitry Andric } 13381ad6265SDimitry Andric 134*06c3fb27SDimitry Andric static Error dumpSection(Object &O, StringRef SectionName, StringRef FileName) { 135*06c3fb27SDimitry Andric for (const coff::Section &Section : O.getSections()) { 136*06c3fb27SDimitry Andric if (Section.Name != SectionName) 137*06c3fb27SDimitry Andric continue; 138*06c3fb27SDimitry Andric 139*06c3fb27SDimitry Andric ArrayRef<uint8_t> Contents = Section.getContents(); 140*06c3fb27SDimitry Andric 141*06c3fb27SDimitry Andric std::unique_ptr<FileOutputBuffer> Buffer; 142*06c3fb27SDimitry Andric if (auto B = FileOutputBuffer::create(FileName, Contents.size())) 143*06c3fb27SDimitry Andric Buffer = std::move(*B); 144*06c3fb27SDimitry Andric else 145*06c3fb27SDimitry Andric return B.takeError(); 146*06c3fb27SDimitry Andric 147*06c3fb27SDimitry Andric llvm::copy(Contents, Buffer->getBufferStart()); 148*06c3fb27SDimitry Andric if (Error E = Buffer->commit()) 149*06c3fb27SDimitry Andric return E; 150*06c3fb27SDimitry Andric 151*06c3fb27SDimitry Andric return Error::success(); 152*06c3fb27SDimitry Andric } 153*06c3fb27SDimitry Andric return createStringError(object_error::parse_failed, "section '%s' not found", 154*06c3fb27SDimitry Andric SectionName.str().c_str()); 155*06c3fb27SDimitry Andric } 156*06c3fb27SDimitry Andric 15781ad6265SDimitry Andric static Error handleArgs(const CommonConfig &Config, 15881ad6265SDimitry Andric const COFFConfig &COFFConfig, Object &Obj) { 159*06c3fb27SDimitry Andric for (StringRef Op : Config.DumpSection) { 160*06c3fb27SDimitry Andric auto [Section, File] = Op.split('='); 161*06c3fb27SDimitry Andric if (Error E = dumpSection(Obj, Section, File)) 162*06c3fb27SDimitry Andric return E; 163*06c3fb27SDimitry Andric } 164*06c3fb27SDimitry Andric 16581ad6265SDimitry Andric // Perform the actual section removals. 16681ad6265SDimitry Andric Obj.removeSections([&Config](const Section &Sec) { 16781ad6265SDimitry Andric // Contrary to --only-keep-debug, --only-section fully removes sections that 16881ad6265SDimitry Andric // aren't mentioned. 16981ad6265SDimitry Andric if (!Config.OnlySection.empty() && !Config.OnlySection.matches(Sec.Name)) 17081ad6265SDimitry Andric return true; 17181ad6265SDimitry Andric 17281ad6265SDimitry Andric if (Config.StripDebug || Config.StripAll || Config.StripAllGNU || 17381ad6265SDimitry Andric Config.DiscardMode == DiscardType::All || Config.StripUnneeded) { 17481ad6265SDimitry Andric if (isDebugSection(Sec) && 17581ad6265SDimitry Andric (Sec.Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0) 17681ad6265SDimitry Andric return true; 17781ad6265SDimitry Andric } 17881ad6265SDimitry Andric 17981ad6265SDimitry Andric if (Config.ToRemove.matches(Sec.Name)) 18081ad6265SDimitry Andric return true; 18181ad6265SDimitry Andric 18281ad6265SDimitry Andric return false; 18381ad6265SDimitry Andric }); 18481ad6265SDimitry Andric 18581ad6265SDimitry Andric if (Config.OnlyKeepDebug) { 18681ad6265SDimitry Andric // For --only-keep-debug, we keep all other sections, but remove their 18781ad6265SDimitry Andric // content. The VirtualSize field in the section header is kept intact. 18881ad6265SDimitry Andric Obj.truncateSections([](const Section &Sec) { 18981ad6265SDimitry Andric return !isDebugSection(Sec) && Sec.Name != ".buildid" && 19081ad6265SDimitry Andric ((Sec.Header.Characteristics & 19181ad6265SDimitry Andric (IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA)) != 0); 19281ad6265SDimitry Andric }); 19381ad6265SDimitry Andric } 19481ad6265SDimitry Andric 19581ad6265SDimitry Andric // StripAll removes all symbols and thus also removes all relocations. 19681ad6265SDimitry Andric if (Config.StripAll || Config.StripAllGNU) 19781ad6265SDimitry Andric for (Section &Sec : Obj.getMutableSections()) 19881ad6265SDimitry Andric Sec.Relocs.clear(); 19981ad6265SDimitry Andric 20081ad6265SDimitry Andric // If we need to do per-symbol removals, initialize the Referenced field. 20181ad6265SDimitry Andric if (Config.StripUnneeded || Config.DiscardMode == DiscardType::All || 20281ad6265SDimitry Andric !Config.SymbolsToRemove.empty()) 20381ad6265SDimitry Andric if (Error E = Obj.markSymbols()) 20481ad6265SDimitry Andric return E; 20581ad6265SDimitry Andric 20681ad6265SDimitry Andric for (Symbol &Sym : Obj.getMutableSymbols()) { 20781ad6265SDimitry Andric auto I = Config.SymbolsToRename.find(Sym.Name); 20881ad6265SDimitry Andric if (I != Config.SymbolsToRename.end()) 20981ad6265SDimitry Andric Sym.Name = I->getValue(); 21081ad6265SDimitry Andric } 21181ad6265SDimitry Andric 21281ad6265SDimitry Andric auto ToRemove = [&](const Symbol &Sym) -> Expected<bool> { 21381ad6265SDimitry Andric // For StripAll, all relocations have been stripped and we remove all 21481ad6265SDimitry Andric // symbols. 21581ad6265SDimitry Andric if (Config.StripAll || Config.StripAllGNU) 21681ad6265SDimitry Andric return true; 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric if (Config.SymbolsToRemove.matches(Sym.Name)) { 21981ad6265SDimitry Andric // Explicitly removing a referenced symbol is an error. 22081ad6265SDimitry Andric if (Sym.Referenced) 22181ad6265SDimitry Andric return createStringError( 22281ad6265SDimitry Andric llvm::errc::invalid_argument, 22381ad6265SDimitry Andric "'" + Config.OutputFilename + "': not stripping symbol '" + 22481ad6265SDimitry Andric Sym.Name.str() + "' because it is named in a relocation"); 22581ad6265SDimitry Andric return true; 22681ad6265SDimitry Andric } 22781ad6265SDimitry Andric 22881ad6265SDimitry Andric if (!Sym.Referenced) { 22981ad6265SDimitry Andric // With --strip-unneeded, GNU objcopy removes all unreferenced local 23081ad6265SDimitry Andric // symbols, and any unreferenced undefined external. 23181ad6265SDimitry Andric // With --strip-unneeded-symbol we strip only specific unreferenced 23281ad6265SDimitry Andric // local symbol instead of removing all of such. 23381ad6265SDimitry Andric if (Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC || 23481ad6265SDimitry Andric Sym.Sym.SectionNumber == 0) 23581ad6265SDimitry Andric if (Config.StripUnneeded || 23681ad6265SDimitry Andric Config.UnneededSymbolsToRemove.matches(Sym.Name)) 23781ad6265SDimitry Andric return true; 23881ad6265SDimitry Andric 23981ad6265SDimitry Andric // GNU objcopy keeps referenced local symbols and external symbols 24081ad6265SDimitry Andric // if --discard-all is set, similar to what --strip-unneeded does, 24181ad6265SDimitry Andric // but undefined local symbols are kept when --discard-all is set. 24281ad6265SDimitry Andric if (Config.DiscardMode == DiscardType::All && 24381ad6265SDimitry Andric Sym.Sym.StorageClass == IMAGE_SYM_CLASS_STATIC && 24481ad6265SDimitry Andric Sym.Sym.SectionNumber != 0) 24581ad6265SDimitry Andric return true; 24681ad6265SDimitry Andric } 24781ad6265SDimitry Andric 24881ad6265SDimitry Andric return false; 24981ad6265SDimitry Andric }; 25081ad6265SDimitry Andric 25181ad6265SDimitry Andric // Actually do removals of symbols. 25281ad6265SDimitry Andric if (Error Err = Obj.removeSymbols(ToRemove)) 25381ad6265SDimitry Andric return Err; 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric if (!Config.SetSectionFlags.empty()) 25681ad6265SDimitry Andric for (Section &Sec : Obj.getMutableSections()) { 25781ad6265SDimitry Andric const auto It = Config.SetSectionFlags.find(Sec.Name); 25881ad6265SDimitry Andric if (It != Config.SetSectionFlags.end()) 25981ad6265SDimitry Andric Sec.Header.Characteristics = flagsToCharacteristics( 26081ad6265SDimitry Andric It->second.NewFlags, Sec.Header.Characteristics); 26181ad6265SDimitry Andric } 26281ad6265SDimitry Andric 26381ad6265SDimitry Andric for (const NewSectionInfo &NewSection : Config.AddSection) { 26481ad6265SDimitry Andric uint32_t Characteristics; 26581ad6265SDimitry Andric const auto It = Config.SetSectionFlags.find(NewSection.SectionName); 26681ad6265SDimitry Andric if (It != Config.SetSectionFlags.end()) 26781ad6265SDimitry Andric Characteristics = flagsToCharacteristics(It->second.NewFlags, 0); 26881ad6265SDimitry Andric else 26981ad6265SDimitry Andric Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_1BYTES; 27081ad6265SDimitry Andric 27181ad6265SDimitry Andric addSection(Obj, NewSection.SectionName, 272bdd1243dSDimitry Andric ArrayRef(reinterpret_cast<const uint8_t *>( 27381ad6265SDimitry Andric NewSection.SectionData->getBufferStart()), 27481ad6265SDimitry Andric NewSection.SectionData->getBufferSize()), 27581ad6265SDimitry Andric Characteristics); 27681ad6265SDimitry Andric } 27781ad6265SDimitry Andric 27881ad6265SDimitry Andric for (const NewSectionInfo &NewSection : Config.UpdateSection) { 27981ad6265SDimitry Andric auto It = llvm::find_if(Obj.getMutableSections(), [&](auto &Sec) { 28081ad6265SDimitry Andric return Sec.Name == NewSection.SectionName; 28181ad6265SDimitry Andric }); 28281ad6265SDimitry Andric if (It == Obj.getMutableSections().end()) 28381ad6265SDimitry Andric return createStringError(errc::invalid_argument, 28481ad6265SDimitry Andric "could not find section with name '%s'", 28581ad6265SDimitry Andric NewSection.SectionName.str().c_str()); 28681ad6265SDimitry Andric size_t ContentSize = It->getContents().size(); 28781ad6265SDimitry Andric if (!ContentSize) 28881ad6265SDimitry Andric return createStringError( 28981ad6265SDimitry Andric errc::invalid_argument, 29081ad6265SDimitry Andric "section '%s' cannot be updated because it does not have contents", 29181ad6265SDimitry Andric NewSection.SectionName.str().c_str()); 29281ad6265SDimitry Andric if (ContentSize < NewSection.SectionData->getBufferSize()) 29381ad6265SDimitry Andric return createStringError( 29481ad6265SDimitry Andric errc::invalid_argument, 29581ad6265SDimitry Andric "new section cannot be larger than previous section"); 29681ad6265SDimitry Andric It->setOwnedContents({NewSection.SectionData->getBufferStart(), 29781ad6265SDimitry Andric NewSection.SectionData->getBufferEnd()}); 29881ad6265SDimitry Andric } 29981ad6265SDimitry Andric 30081ad6265SDimitry Andric if (!Config.AddGnuDebugLink.empty()) 30181ad6265SDimitry Andric if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink)) 30281ad6265SDimitry Andric return E; 30381ad6265SDimitry Andric 30481ad6265SDimitry Andric if (COFFConfig.Subsystem || COFFConfig.MajorSubsystemVersion || 30581ad6265SDimitry Andric COFFConfig.MinorSubsystemVersion) { 30681ad6265SDimitry Andric if (!Obj.IsPE) 30781ad6265SDimitry Andric return createStringError( 30881ad6265SDimitry Andric errc::invalid_argument, 30981ad6265SDimitry Andric "'" + Config.OutputFilename + 31081ad6265SDimitry Andric "': unable to set subsystem on a relocatable object file"); 31181ad6265SDimitry Andric if (COFFConfig.Subsystem) 31281ad6265SDimitry Andric Obj.PeHeader.Subsystem = *COFFConfig.Subsystem; 31381ad6265SDimitry Andric if (COFFConfig.MajorSubsystemVersion) 31481ad6265SDimitry Andric Obj.PeHeader.MajorSubsystemVersion = *COFFConfig.MajorSubsystemVersion; 31581ad6265SDimitry Andric if (COFFConfig.MinorSubsystemVersion) 31681ad6265SDimitry Andric Obj.PeHeader.MinorSubsystemVersion = *COFFConfig.MinorSubsystemVersion; 31781ad6265SDimitry Andric } 31881ad6265SDimitry Andric 31981ad6265SDimitry Andric return Error::success(); 32081ad6265SDimitry Andric } 32181ad6265SDimitry Andric 32281ad6265SDimitry Andric Error executeObjcopyOnBinary(const CommonConfig &Config, 32381ad6265SDimitry Andric const COFFConfig &COFFConfig, COFFObjectFile &In, 32481ad6265SDimitry Andric raw_ostream &Out) { 32581ad6265SDimitry Andric COFFReader Reader(In); 32681ad6265SDimitry Andric Expected<std::unique_ptr<Object>> ObjOrErr = Reader.create(); 32781ad6265SDimitry Andric if (!ObjOrErr) 32881ad6265SDimitry Andric return createFileError(Config.InputFilename, ObjOrErr.takeError()); 32981ad6265SDimitry Andric Object *Obj = ObjOrErr->get(); 33081ad6265SDimitry Andric assert(Obj && "Unable to deserialize COFF object"); 33181ad6265SDimitry Andric if (Error E = handleArgs(Config, COFFConfig, *Obj)) 33281ad6265SDimitry Andric return createFileError(Config.InputFilename, std::move(E)); 33381ad6265SDimitry Andric COFFWriter Writer(*Obj, Out); 33481ad6265SDimitry Andric if (Error E = Writer.write()) 33581ad6265SDimitry Andric return createFileError(Config.OutputFilename, std::move(E)); 33681ad6265SDimitry Andric return Error::success(); 33781ad6265SDimitry Andric } 33881ad6265SDimitry Andric 33981ad6265SDimitry Andric } // end namespace coff 34081ad6265SDimitry Andric } // end namespace objcopy 34181ad6265SDimitry Andric } // end namespace llvm 342