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
1606c3fb27SDimitry 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
isDebugSection(const Section & Sec)3181ad6265SDimitry Andric static bool isDebugSection(const Section &Sec) {
32*5f757f3fSDimitry Andric return Sec.Name.starts_with(".debug");
3381ad6265SDimitry Andric }
3481ad6265SDimitry Andric
getNextRVA(const Object & Obj)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>>
createGnuDebugLinkSectionContents(StringRef File)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.
addSection(Object & Obj,StringRef Name,ArrayRef<uint8_t> Contents,uint32_t Characteristics)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
addGnuDebugLink(Object & Obj,StringRef DebugLinkFile)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
flagsToCharacteristics(SectionFlag AllFlags,uint32_t OldChar)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
dumpSection(Object & O,StringRef SectionName,StringRef FileName)13406c3fb27SDimitry Andric static Error dumpSection(Object &O, StringRef SectionName, StringRef FileName) {
13506c3fb27SDimitry Andric for (const coff::Section &Section : O.getSections()) {
13606c3fb27SDimitry Andric if (Section.Name != SectionName)
13706c3fb27SDimitry Andric continue;
13806c3fb27SDimitry Andric
13906c3fb27SDimitry Andric ArrayRef<uint8_t> Contents = Section.getContents();
14006c3fb27SDimitry Andric
14106c3fb27SDimitry Andric std::unique_ptr<FileOutputBuffer> Buffer;
14206c3fb27SDimitry Andric if (auto B = FileOutputBuffer::create(FileName, Contents.size()))
14306c3fb27SDimitry Andric Buffer = std::move(*B);
14406c3fb27SDimitry Andric else
14506c3fb27SDimitry Andric return B.takeError();
14606c3fb27SDimitry Andric
14706c3fb27SDimitry Andric llvm::copy(Contents, Buffer->getBufferStart());
14806c3fb27SDimitry Andric if (Error E = Buffer->commit())
14906c3fb27SDimitry Andric return E;
15006c3fb27SDimitry Andric
15106c3fb27SDimitry Andric return Error::success();
15206c3fb27SDimitry Andric }
15306c3fb27SDimitry Andric return createStringError(object_error::parse_failed, "section '%s' not found",
15406c3fb27SDimitry Andric SectionName.str().c_str());
15506c3fb27SDimitry Andric }
15606c3fb27SDimitry Andric
handleArgs(const CommonConfig & Config,const COFFConfig & COFFConfig,Object & Obj)15781ad6265SDimitry Andric static Error handleArgs(const CommonConfig &Config,
15881ad6265SDimitry Andric const COFFConfig &COFFConfig, Object &Obj) {
15906c3fb27SDimitry Andric for (StringRef Op : Config.DumpSection) {
16006c3fb27SDimitry Andric auto [Section, File] = Op.split('=');
16106c3fb27SDimitry Andric if (Error E = dumpSection(Obj, Section, File))
16206c3fb27SDimitry Andric return E;
16306c3fb27SDimitry Andric }
16406c3fb27SDimitry 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
executeObjcopyOnBinary(const CommonConfig & Config,const COFFConfig & COFFConfig,COFFObjectFile & In,raw_ostream & Out)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