summaryrefslogtreecommitdiff
path: root/lib/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-26 20:32:52 +0000
commit08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch)
tree80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/Object
parent7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff)
Notes
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/COFFObjectFile.cpp20
-rw-r--r--lib/Object/IRSymtab.cpp36
-rw-r--r--lib/Object/MachOObjectFile.cpp39
-rw-r--r--lib/Object/WasmObjectFile.cpp93
-rw-r--r--lib/Object/WindowsResource.cpp270
5 files changed, 279 insertions, 179 deletions
diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp
index 579c8dde366a0..9a760d86e7e22 100644
--- a/lib/Object/COFFObjectFile.cpp
+++ b/lib/Object/COFFObjectFile.cpp
@@ -650,6 +650,23 @@ std::error_code COFFObjectFile::initDebugDirectoryPtr() {
return std::error_code();
}
+std::error_code COFFObjectFile::initLoadConfigPtr() {
+ // Get the RVA of the debug directory. Do nothing if it does not exist.
+ const data_directory *DataEntry;
+ if (getDataDirectory(COFF::LOAD_CONFIG_TABLE, DataEntry))
+ return std::error_code();
+
+ // Do nothing if the RVA is NULL.
+ if (DataEntry->RelativeVirtualAddress == 0)
+ return std::error_code();
+ uintptr_t IntPtr = 0;
+ if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr))
+ return EC;
+
+ LoadConfig = (const void *)IntPtr;
+ return std::error_code();
+}
+
COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
: ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr),
COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr),
@@ -784,6 +801,9 @@ COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC)
if ((EC = initDebugDirectoryPtr()))
return;
+ if ((EC = initLoadConfigPtr()))
+ return;
+
EC = std::error_code();
}
diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp
index a6cd5dda12d3e..7bca032a7be1d 100644
--- a/lib/Object/IRSymtab.cpp
+++ b/lib/Object/IRSymtab.cpp
@@ -46,15 +46,15 @@ namespace {
/// Stores the temporary state that is required to build an IR symbol table.
struct Builder {
SmallVector<char, 0> &Symtab;
- SmallVector<char, 0> &Strtab;
+ StringTableBuilder &StrtabBuilder;
+ StringSaver Saver;
- Builder(SmallVector<char, 0> &Symtab, SmallVector<char, 0> &Strtab)
- : Symtab(Symtab), Strtab(Strtab) {}
-
- StringTableBuilder StrtabBuilder{StringTableBuilder::RAW};
-
- BumpPtrAllocator Alloc;
- StringSaver Saver{Alloc};
+ // This ctor initializes a StringSaver using the passed in BumpPtrAllocator.
+ // The StringTableBuilder does not create a copy of any strings added to it,
+ // so this provides somewhere to store any strings that we create.
+ Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
+ BumpPtrAllocator &Alloc)
+ : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc) {}
DenseMap<const Comdat *, unsigned> ComdatMap;
Mangler Mang;
@@ -240,7 +240,7 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
return Err;
COFFLinkerOptsOS.flush();
- setStr(Hdr.COFFLinkerOpts, COFFLinkerOpts);
+ setStr(Hdr.COFFLinkerOpts, Saver.save(COFFLinkerOpts));
// We are about to fill in the header's range fields, so reserve space for it
// and copy it in afterwards.
@@ -251,19 +251,15 @@ Error Builder::build(ArrayRef<Module *> IRMods) {
writeRange(Hdr.Uncommons, Uncommons);
*reinterpret_cast<storage::Header *>(Symtab.data()) = Hdr;
-
- raw_svector_ostream OS(Strtab);
- StrtabBuilder.finalizeInOrder();
- StrtabBuilder.write(OS);
-
return Error::success();
}
} // end anonymous namespace
Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
- SmallVector<char, 0> &Strtab) {
- return Builder(Symtab, Strtab).build(Mods);
+ StringTableBuilder &StrtabBuilder,
+ BumpPtrAllocator &Alloc) {
+ return Builder(Symtab, StrtabBuilder, Alloc).build(Mods);
}
// Upgrade a vector of bitcode modules created by an old version of LLVM by
@@ -285,9 +281,15 @@ static Expected<FileContents> upgrade(ArrayRef<BitcodeModule> BMs) {
OwnedMods.push_back(std::move(*MOrErr));
}
- if (Error E = build(Mods, FC.Symtab, FC.Strtab))
+ StringTableBuilder StrtabBuilder(StringTableBuilder::RAW);
+ BumpPtrAllocator Alloc;
+ if (Error E = build(Mods, FC.Symtab, StrtabBuilder, Alloc))
return std::move(E);
+ StrtabBuilder.finalizeInOrder();
+ FC.Strtab.resize(StrtabBuilder.getSize());
+ StrtabBuilder.write((uint8_t *)FC.Strtab.data());
+
FC.TheReader = {{FC.Symtab.data(), FC.Symtab.size()},
{FC.Strtab.data(), FC.Strtab.size()}};
return std::move(FC);
diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp
index 7804bbe06f83e..2e4da9f15aa13 100644
--- a/lib/Object/MachOObjectFile.cpp
+++ b/lib/Object/MachOObjectFile.cpp
@@ -1951,13 +1951,29 @@ MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
return relocation_iterator(RelocationRef(Ret, this));
}
+relocation_iterator MachOObjectFile::extrel_begin() const {
+ DataRefImpl Ret;
+ Ret.d.a = 0; // Would normally be a section index.
+ Ret.d.b = 0; // Index into the external relocations
+ return relocation_iterator(RelocationRef(Ret, this));
+}
+
+relocation_iterator MachOObjectFile::extrel_end() const {
+ MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
+ DataRefImpl Ret;
+ Ret.d.a = 0; // Would normally be a section index.
+ Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
+ return relocation_iterator(RelocationRef(Ret, this));
+}
+
void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
++Rel.d.b;
}
uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
- assert(getHeader().filetype == MachO::MH_OBJECT &&
- "Only implemented for MH_OBJECT");
+ assert((getHeader().filetype == MachO::MH_OBJECT ||
+ getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
+ "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
MachO::any_relocation_info RE = getRelocation(Rel);
return getAnyRelocationAddress(RE);
}
@@ -4086,15 +4102,20 @@ MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const {
MachO::any_relocation_info
MachOObjectFile::getRelocation(DataRefImpl Rel) const {
- DataRefImpl Sec;
- Sec.d.a = Rel.d.a;
uint32_t Offset;
- if (is64Bit()) {
- MachO::section_64 Sect = getSection64(Sec);
- Offset = Sect.reloff;
+ if (getHeader().filetype == MachO::MH_OBJECT) {
+ DataRefImpl Sec;
+ Sec.d.a = Rel.d.a;
+ if (is64Bit()) {
+ MachO::section_64 Sect = getSection64(Sec);
+ Offset = Sect.reloff;
+ } else {
+ MachO::section Sect = getSection(Sec);
+ Offset = Sect.reloff;
+ }
} else {
- MachO::section Sect = getSection(Sec);
- Offset = Sect.reloff;
+ MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
+ Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations
}
auto P = reinterpret_cast<const MachO::any_relocation_info *>(
diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp
index 2304098c1dc9f..d15860674aeb9 100644
--- a/lib/Object/WasmObjectFile.cpp
+++ b/lib/Object/WasmObjectFile.cpp
@@ -28,6 +28,8 @@
#include <cstring>
#include <system_error>
+#define DEBUG_TYPE "wasm-object"
+
using namespace llvm;
using namespace object;
@@ -256,6 +258,7 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
while (Ptr < End) {
uint8_t Type = readVarint7(Ptr);
uint32_t Size = readVaruint32(Ptr);
+ const uint8_t *SubSectionEnd = Ptr + Size;
switch (Type) {
case wasm::WASM_NAMES_FUNCTION: {
uint32_t Count = readVaruint32(Ptr);
@@ -275,6 +278,9 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
Ptr += Size;
break;
}
+ if (Ptr != SubSectionEnd)
+ return make_error<GenericBinaryError>("Name sub-section ended prematurely",
+ object_error::parse_failed);
}
if (Ptr != End)
@@ -283,6 +289,50 @@ Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
return Error::success();
}
+Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
+ const uint8_t *End) {
+ while (Ptr < End) {
+ uint8_t Type = readVarint7(Ptr);
+ uint32_t Size = readVaruint32(Ptr);
+ const uint8_t *SubSectionEnd = Ptr + Size;
+ switch (Type) {
+ case wasm::WASM_SYMBOL_INFO: {
+ uint32_t Count = readVaruint32(Ptr);
+ while (Count--) {
+ StringRef Symbol = readString(Ptr);
+ DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n");
+ uint32_t Flags = readVaruint32(Ptr);
+ auto iter = SymbolMap.find(Symbol);
+ if (iter == SymbolMap.end()) {
+ return make_error<GenericBinaryError>(
+ "Invalid symbol name in linking section",
+ object_error::parse_failed);
+ }
+ uint32_t SymIndex = iter->second;
+ assert(SymIndex < Symbols.size());
+ Symbols[SymIndex].Flags = Flags;
+ DEBUG(dbgs() << "Set symbol flags index:"
+ << SymIndex << " name:"
+ << Symbols[SymIndex].Name << " exptected:"
+ << Symbol << " flags: " << Flags << "\n");
+ }
+ break;
+ }
+ case wasm::WASM_STACK_POINTER:
+ default:
+ Ptr += Size;
+ break;
+ }
+ if (Ptr != SubSectionEnd)
+ return make_error<GenericBinaryError>(
+ "Linking sub-section ended prematurely", object_error::parse_failed);
+ }
+ if (Ptr != End)
+ return make_error<GenericBinaryError>("Linking section ended prematurely",
+ object_error::parse_failed);
+ return Error::success();
+}
+
WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
for (WasmSection& Section : Sections) {
if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
@@ -325,6 +375,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
+ case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
break;
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
@@ -332,7 +383,8 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
Reloc.Addend = readVarint32(Ptr);
break;
default:
- return make_error<GenericBinaryError>("Bad relocation type",
+ return make_error<GenericBinaryError>("Bad relocation type: " +
+ Twine(Reloc.Type),
object_error::parse_failed);
}
Section->Relocations.push_back(Reloc);
@@ -349,6 +401,9 @@ Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
if (Sec.Name == "name") {
if (Error Err = parseNameSection(Ptr, End))
return Err;
+ } else if (Sec.Name == "linking") {
+ if (Error Err = parseLinkingSection(Ptr, End))
+ return Err;
} else if (Sec.Name.startswith("reloc.")) {
if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
return Err;
@@ -400,14 +455,20 @@ Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End)
switch (Im.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
Im.SigIndex = readVaruint32(Ptr);
+ SymbolMap.try_emplace(Im.Field, Symbols.size());
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
Sections.size(), i);
+ DEBUG(dbgs() << "Adding import: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_GLOBAL:
Im.Global.Type = readVarint7(Ptr);
Im.Global.Mutable = readVaruint1(Ptr);
+ SymbolMap.try_emplace(Im.Field, Symbols.size());
Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
Sections.size(), i);
+ DEBUG(dbgs() << "Adding import: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_MEMORY:
Im.Memory = readLimits(Ptr);
@@ -496,15 +557,20 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
Ex.Name = readString(Ptr);
Ex.Kind = readUint8(Ptr);
Ex.Index = readVaruint32(Ptr);
- Exports.push_back(Ex);
switch (Ex.Kind) {
case wasm::WASM_EXTERNAL_FUNCTION:
+ SymbolMap.try_emplace(Ex.Name, Symbols.size());
Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
Sections.size(), i);
+ DEBUG(dbgs() << "Adding export: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_GLOBAL:
+ SymbolMap.try_emplace(Ex.Name, Symbols.size());
Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
Sections.size(), i);
+ DEBUG(dbgs() << "Adding export: " << Symbols.back()
+ << " sym index:" << Symbols.size() << "\n");
break;
case wasm::WASM_EXTERNAL_MEMORY:
case wasm::WASM_EXTERNAL_TABLE:
@@ -513,6 +579,7 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
return make_error<GenericBinaryError>(
"Unexpected export kind", object_error::parse_failed);
}
+ Exports.push_back(Ex);
}
if (Ptr != End)
return make_error<GenericBinaryError>("Export section ended prematurely",
@@ -620,6 +687,10 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
uint32_t Result = SymbolRef::SF_None;
const WasmSymbol &Sym = getWasmSymbol(Symb);
+ DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
+ if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
+ Result |= SymbolRef::SF_Weak;
+
switch (Sym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
@@ -629,6 +700,7 @@ uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
Result |= SymbolRef::SF_Executable;
+ Result |= SymbolRef::SF_FormatSpecific;
break;
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
Result |= SymbolRef::SF_Undefined;
@@ -662,8 +734,7 @@ const WasmSymbol &WasmObjectFile::getWasmSymbol(const SymbolRef &Symb) const {
}
Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
- const WasmSymbol &Sym = getWasmSymbol(Symb);
- return Sym.Name;
+ return getWasmSymbol(Symb).Name;
}
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
@@ -671,8 +742,18 @@ Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
}
uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
- const WasmSymbol &Sym = getWasmSymbol(Symb);
- return Sym.ElementIndex;
+ const WasmSymbol& Sym = getWasmSymbol(Symb);
+ switch (Sym.Type) {
+ case WasmSymbol::SymbolType::FUNCTION_IMPORT:
+ case WasmSymbol::SymbolType::GLOBAL_IMPORT:
+ return 0;
+ case WasmSymbol::SymbolType::FUNCTION_EXPORT:
+ case WasmSymbol::SymbolType::GLOBAL_EXPORT:
+ return Exports[Sym.ElementIndex].Index;
+ case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
+ return Sym.ElementIndex;
+ }
+ llvm_unreachable("invalid symbol type");
}
uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {
diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp
index 3f6080d48f9d1..ff9b9ca35eb5b 100644
--- a/lib/Object/WindowsResource.cpp
+++ b/lib/Object/WindowsResource.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/Object/WindowsResource.h"
-#include "llvm/BinaryFormat/COFF.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/MathExtras.h"
@@ -21,6 +20,9 @@
#include <sstream>
#include <system_error>
+using namespace llvm;
+using namespace object;
+
namespace llvm {
namespace object {
@@ -34,23 +36,19 @@ const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
// 8-byte because it makes everyone happy.
const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);
-static const size_t ResourceMagicSize = 16;
-
-static const size_t NullEntrySize = 16;
-
uint32_t WindowsResourceParser::TreeNode::StringCount = 0;
uint32_t WindowsResourceParser::TreeNode::DataCount = 0;
WindowsResource::WindowsResource(MemoryBufferRef Source)
: Binary(Binary::ID_WinRes, Source) {
- size_t LeadingSize = ResourceMagicSize + NullEntrySize;
+ size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE;
BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
support::little);
}
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
- if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize)
+ if (Source.getBufferSize() < WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE)
return make_error<GenericBinaryError>(
"File too small to be a resource file",
object_error::invalid_file_type);
@@ -103,12 +101,10 @@ static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID,
}
Error ResourceEntryRef::loadNext() {
- uint32_t DataSize;
- RETURN_IF_ERROR(Reader.readInteger(DataSize));
- uint32_t HeaderSize;
- RETURN_IF_ERROR(Reader.readInteger(HeaderSize));
+ const WinResHeaderPrefix *Prefix;
+ RETURN_IF_ERROR(Reader.readObject(Prefix));
- if (HeaderSize < MIN_HEADER_SIZE)
+ if (Prefix->HeaderSize < MIN_HEADER_SIZE)
return make_error<GenericBinaryError>("Header size is too small.",
object_error::parse_failed);
@@ -116,13 +112,13 @@ Error ResourceEntryRef::loadNext() {
RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName));
- RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+ RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_HEADER_ALIGNMENT));
RETURN_IF_ERROR(Reader.readObject(Suffix));
- RETURN_IF_ERROR(Reader.readArray(Data, DataSize));
+ RETURN_IF_ERROR(Reader.readArray(Data, Prefix->DataSize));
- RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t)));
+ RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_DATA_ALIGNMENT));
return Error::success();
}
@@ -246,14 +242,14 @@ WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef,
std::string NameString;
ArrayRef<UTF16> CorrectedName;
std::vector<UTF16> EndianCorrectedName;
- if (llvm::sys::IsBigEndianHost) {
+ if (sys::IsBigEndianHost) {
EndianCorrectedName.resize(NameRef.size() + 1);
std::copy(NameRef.begin(), NameRef.end(), EndianCorrectedName.begin() + 1);
EndianCorrectedName[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
CorrectedName = makeArrayRef(EndianCorrectedName);
} else
CorrectedName = NameRef;
- llvm::convertUTF16ToUTF8String(CorrectedName, NameString);
+ convertUTF16ToUTF8String(CorrectedName, NameString);
auto Child = StringChildren.find(NameString);
if (Child == StringChildren.end()) {
@@ -282,17 +278,17 @@ void WindowsResourceParser::TreeNode::print(ScopedPrinter &Writer,
// the directory strings or the relocations of the .rsrc section.
uint32_t WindowsResourceParser::TreeNode::getTreeSize() const {
uint32_t Size = (IDChildren.size() + StringChildren.size()) *
- sizeof(llvm::object::coff_resource_dir_entry);
+ sizeof(coff_resource_dir_entry);
// Reached a node pointing to a data entry.
if (IsDataNode) {
- Size += sizeof(llvm::object::coff_resource_data_entry);
+ Size += sizeof(coff_resource_data_entry);
return Size;
}
// If the node does not point to data, it must have a directory table pointing
// to other nodes.
- Size += sizeof(llvm::object::coff_resource_dir_table);
+ Size += sizeof(coff_resource_dir_table);
for (auto const &Child : StringChildren) {
Size += Child.second->getTreeSize();
@@ -305,9 +301,9 @@ uint32_t WindowsResourceParser::TreeNode::getTreeSize() const {
class WindowsResourceCOFFWriter {
public:
- WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType,
+ WindowsResourceCOFFWriter(COFF::MachineTypes MachineType,
const WindowsResourceParser &Parser, Error &E);
- Error write();
+ std::unique_ptr<MemoryBuffer> write();
private:
void performFileLayout();
@@ -323,10 +319,10 @@ private:
void writeDirectoryTree();
void writeDirectoryStringTable();
void writeFirstSectionRelocations();
- std::unique_ptr<FileOutputBuffer> Buffer;
- uint8_t *BufferStart;
+ std::unique_ptr<MemoryBuffer> OutputBuffer;
+ char *BufferStart;
uint64_t CurrentOffset = 0;
- Machine MachineType;
+ COFF::MachineTypes MachineType;
const WindowsResourceParser::TreeNode &Resources;
const ArrayRef<std::vector<uint8_t>> Data;
uint64_t FileSize;
@@ -343,28 +339,21 @@ private:
};
WindowsResourceCOFFWriter::WindowsResourceCOFFWriter(
- StringRef OutputFile, Machine MachineType,
- const WindowsResourceParser &Parser, Error &E)
+ COFF::MachineTypes MachineType, const WindowsResourceParser &Parser,
+ Error &E)
: MachineType(MachineType), Resources(Parser.getTree()),
Data(Parser.getData()), StringTable(Parser.getStringTable()) {
performFileLayout();
- ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(OutputFile, FileSize);
- if (!BufferOrErr) {
- E = errorCodeToError(BufferOrErr.getError());
- return;
- }
-
- Buffer = std::move(*BufferOrErr);
+ OutputBuffer = MemoryBuffer::getNewMemBuffer(FileSize);
}
void WindowsResourceCOFFWriter::performFileLayout() {
// Add size of COFF header.
- FileSize = llvm::COFF::Header16Size;
+ FileSize = COFF::Header16Size;
// one .rsrc section header for directory tree, another for resource data.
- FileSize += 2 * llvm::COFF::SectionSize;
+ FileSize += 2 * COFF::SectionSize;
performSectionOneLayout();
performSectionTwoLayout();
@@ -372,9 +361,9 @@ void WindowsResourceCOFFWriter::performFileLayout() {
// We have reached the address of the symbol table.
SymbolTableOffset = FileSize;
- FileSize += llvm::COFF::Symbol16Size; // size of the @feat.00 symbol.
- FileSize += 4 * llvm::COFF::Symbol16Size; // symbol + aux for each section.
- FileSize += Data.size() * llvm::COFF::Symbol16Size; // 1 symbol per resource.
+ FileSize += COFF::Symbol16Size; // size of the @feat.00 symbol.
+ FileSize += 4 * COFF::Symbol16Size; // symbol + aux for each section.
+ FileSize += Data.size() * COFF::Symbol16Size; // 1 symbol per resource.
FileSize += 4; // four null bytes for the string table.
}
@@ -395,8 +384,8 @@ void WindowsResourceCOFFWriter::performSectionOneLayout() {
// account for the relocations of section one.
SectionOneRelocations = FileSize + SectionOneSize;
FileSize += SectionOneSize;
- FileSize += Data.size() *
- llvm::COFF::RelocationSize; // one relocation for each resource.
+ FileSize +=
+ Data.size() * COFF::RelocationSize; // one relocation for each resource.
FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}
@@ -407,7 +396,7 @@ void WindowsResourceCOFFWriter::performSectionTwoLayout() {
SectionTwoSize = 0;
for (auto const &Entry : Data) {
DataOffsets.push_back(SectionTwoSize);
- SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t));
+ SectionTwoSize += alignTo(Entry.size(), sizeof(uint64_t));
}
FileSize += SectionTwoSize;
FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
@@ -420,8 +409,8 @@ static std::time_t getTime() {
return Now;
}
-Error WindowsResourceCOFFWriter::write() {
- BufferStart = Buffer->getBufferStart();
+std::unique_ptr<MemoryBuffer> WindowsResourceCOFFWriter::write() {
+ BufferStart = const_cast<char *>(OutputBuffer->getBufferStart());
writeCOFFHeader();
writeFirstSectionHeader();
@@ -431,29 +420,24 @@ Error WindowsResourceCOFFWriter::write() {
writeSymbolTable();
writeStringTable();
- if (auto EC = Buffer->commit()) {
- return errorCodeToError(EC);
- }
-
- return Error::success();
+ return std::move(OutputBuffer);
}
void WindowsResourceCOFFWriter::writeCOFFHeader() {
// Write the COFF header.
- auto *Header =
- reinterpret_cast<llvm::object::coff_file_header *>(BufferStart);
+ auto *Header = reinterpret_cast<coff_file_header *>(BufferStart);
switch (MachineType) {
- case Machine::ARM:
- Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ Header->Machine = COFF::IMAGE_FILE_MACHINE_ARMNT;
break;
- case Machine::X64:
- Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ Header->Machine = COFF::IMAGE_FILE_MACHINE_AMD64;
break;
- case Machine::X86:
- Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386;
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ Header->Machine = COFF::IMAGE_FILE_MACHINE_I386;
break;
default:
- Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+ Header->Machine = COFF::IMAGE_FILE_MACHINE_UNKNOWN;
}
Header->NumberOfSections = 2;
Header->TimeDateStamp = getTime();
@@ -461,15 +445,15 @@ void WindowsResourceCOFFWriter::writeCOFFHeader() {
// One symbol for every resource plus 2 for each section and @feat.00
Header->NumberOfSymbols = Data.size() + 5;
Header->SizeOfOptionalHeader = 0;
- Header->Characteristics = llvm::COFF::IMAGE_FILE_32BIT_MACHINE;
+ Header->Characteristics = COFF::IMAGE_FILE_32BIT_MACHINE;
}
void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
// Write the first section header.
- CurrentOffset += sizeof(llvm::object::coff_file_header);
- auto *SectionOneHeader = reinterpret_cast<llvm::object::coff_section *>(
- BufferStart + CurrentOffset);
- strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize);
+ CurrentOffset += sizeof(coff_file_header);
+ auto *SectionOneHeader =
+ reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);
+ strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)COFF::NameSize);
SectionOneHeader->VirtualSize = 0;
SectionOneHeader->VirtualAddress = 0;
SectionOneHeader->SizeOfRawData = SectionOneSize;
@@ -478,19 +462,16 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
SectionOneHeader->PointerToLinenumbers = 0;
SectionOneHeader->NumberOfRelocations = Data.size();
SectionOneHeader->NumberOfLinenumbers = 0;
- SectionOneHeader->Characteristics = llvm::COFF::IMAGE_SCN_ALIGN_1BYTES;
- SectionOneHeader->Characteristics +=
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
- SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;
- SectionOneHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ;
+ SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+ SectionOneHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ;
}
void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
// Write the second section header.
- CurrentOffset += sizeof(llvm::object::coff_section);
- auto *SectionTwoHeader = reinterpret_cast<llvm::object::coff_section *>(
- BufferStart + CurrentOffset);
- strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize);
+ CurrentOffset += sizeof(coff_section);
+ auto *SectionTwoHeader =
+ reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);
+ strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)COFF::NameSize);
SectionTwoHeader->VirtualSize = 0;
SectionTwoHeader->VirtualAddress = 0;
SectionTwoHeader->SizeOfRawData = SectionTwoSize;
@@ -499,14 +480,13 @@ void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
SectionTwoHeader->PointerToLinenumbers = 0;
SectionTwoHeader->NumberOfRelocations = 0;
SectionTwoHeader->NumberOfLinenumbers = 0;
- SectionTwoHeader->Characteristics =
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
- SectionTwoHeader->Characteristics += llvm::COFF::IMAGE_SCN_MEM_READ;
+ SectionTwoHeader->Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+ SectionTwoHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ;
}
void WindowsResourceCOFFWriter::writeFirstSection() {
// Write section one.
- CurrentOffset += sizeof(llvm::object::coff_section);
+ CurrentOffset += sizeof(coff_section);
writeDirectoryTree();
writeDirectoryStringTable();
@@ -529,70 +509,65 @@ void WindowsResourceCOFFWriter::writeSecondSection() {
void WindowsResourceCOFFWriter::writeSymbolTable() {
// Now write the symbol table.
// First, the feat symbol.
- auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
- CurrentOffset);
- strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)llvm::COFF::NameSize);
+ auto *Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
+ strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)COFF::NameSize);
Symbol->Value = 0x11;
Symbol->SectionNumber = 0xffff;
- Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
- Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
+ Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
+ Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 0;
- CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ CurrentOffset += sizeof(coff_symbol16);
// Now write the .rsrc1 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
- CurrentOffset);
- strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)llvm::COFF::NameSize);
+ Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
+ strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)COFF::NameSize);
Symbol->Value = 0;
Symbol->SectionNumber = 1;
- Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
- Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
+ Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
+ Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 1;
- CurrentOffset += sizeof(llvm::object::coff_symbol16);
- auto *Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
- BufferStart + CurrentOffset);
+ CurrentOffset += sizeof(coff_symbol16);
+ auto *Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +
+ CurrentOffset);
Aux->Length = SectionOneSize;
Aux->NumberOfRelocations = Data.size();
Aux->NumberOfLinenumbers = 0;
Aux->CheckSum = 0;
Aux->NumberLowPart = 0;
Aux->Selection = 0;
- CurrentOffset += sizeof(llvm::object::coff_aux_section_definition);
+ CurrentOffset += sizeof(coff_aux_section_definition);
// Now write the .rsrc2 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
- CurrentOffset);
- strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)llvm::COFF::NameSize);
+ Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
+ strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)COFF::NameSize);
Symbol->Value = 0;
Symbol->SectionNumber = 2;
- Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
- Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
+ Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
+ Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 1;
- CurrentOffset += sizeof(llvm::object::coff_symbol16);
- Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
- BufferStart + CurrentOffset);
+ CurrentOffset += sizeof(coff_symbol16);
+ Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +
+ CurrentOffset);
Aux->Length = SectionTwoSize;
Aux->NumberOfRelocations = 0;
Aux->NumberOfLinenumbers = 0;
Aux->CheckSum = 0;
Aux->NumberLowPart = 0;
Aux->Selection = 0;
- CurrentOffset += sizeof(llvm::object::coff_aux_section_definition);
+ CurrentOffset += sizeof(coff_aux_section_definition);
// Now write a symbol for each relocation.
for (unsigned i = 0; i < Data.size(); i++) {
char RelocationName[9];
sprintf(RelocationName, "$R%06X", DataOffsets[i]);
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
- CurrentOffset);
- strncpy(Symbol->Name.ShortName, RelocationName,
- (size_t)llvm::COFF::NameSize);
+ Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
+ strncpy(Symbol->Name.ShortName, RelocationName, (size_t)COFF::NameSize);
Symbol->Value = DataOffsets[i];
Symbol->SectionNumber = 1;
- Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
- Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
+ Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
+ Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 0;
- CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ CurrentOffset += sizeof(coff_symbol16);
}
}
@@ -607,18 +582,18 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
// COFF objects.
std::queue<const WindowsResourceParser::TreeNode *> Queue;
Queue.push(&Resources);
- uint32_t NextLevelOffset = sizeof(llvm::object::coff_resource_dir_table) +
- (Resources.getStringChildren().size() +
- Resources.getIDChildren().size()) *
- sizeof(llvm::object::coff_resource_dir_entry);
+ uint32_t NextLevelOffset =
+ sizeof(coff_resource_dir_table) + (Resources.getStringChildren().size() +
+ Resources.getIDChildren().size()) *
+ sizeof(coff_resource_dir_entry);
std::vector<const WindowsResourceParser::TreeNode *> DataEntriesTreeOrder;
uint32_t CurrentRelativeOffset = 0;
while (!Queue.empty()) {
auto CurrentNode = Queue.front();
Queue.pop();
- auto *Table = reinterpret_cast<llvm::object::coff_resource_dir_table *>(
- BufferStart + CurrentOffset);
+ auto *Table = reinterpret_cast<coff_resource_dir_table *>(BufferStart +
+ CurrentOffset);
Table->Characteristics = CurrentNode->getCharacteristics();
Table->TimeDateStamp = 0;
Table->MajorVersion = CurrentNode->getMajorVersion();
@@ -627,63 +602,63 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
auto &StringChildren = CurrentNode->getStringChildren();
Table->NumberOfNameEntries = StringChildren.size();
Table->NumberOfIDEntries = IDChildren.size();
- CurrentOffset += sizeof(llvm::object::coff_resource_dir_table);
- CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_table);
+ CurrentOffset += sizeof(coff_resource_dir_table);
+ CurrentRelativeOffset += sizeof(coff_resource_dir_table);
// Write the directory entries immediately following each directory table.
for (auto const &Child : StringChildren) {
- auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
- BufferStart + CurrentOffset);
+ auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +
+ CurrentOffset);
Entry->Identifier.NameOffset =
StringTableOffsets[Child.second->getStringIndex()];
if (Child.second->checkIsDataNode()) {
Entry->Offset.DataEntryOffset = NextLevelOffset;
- NextLevelOffset += sizeof(llvm::object::coff_resource_data_entry);
+ NextLevelOffset += sizeof(coff_resource_data_entry);
DataEntriesTreeOrder.push_back(Child.second.get());
} else {
Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
- NextLevelOffset += sizeof(llvm::object::coff_resource_dir_table) +
+ NextLevelOffset += sizeof(coff_resource_dir_table) +
(Child.second->getStringChildren().size() +
Child.second->getIDChildren().size()) *
- sizeof(llvm::object::coff_resource_dir_entry);
+ sizeof(coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry);
- CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += sizeof(coff_resource_dir_entry);
+ CurrentRelativeOffset += sizeof(coff_resource_dir_entry);
}
for (auto const &Child : IDChildren) {
- auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
- BufferStart + CurrentOffset);
+ auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +
+ CurrentOffset);
Entry->Identifier.ID = Child.first;
if (Child.second->checkIsDataNode()) {
Entry->Offset.DataEntryOffset = NextLevelOffset;
- NextLevelOffset += sizeof(llvm::object::coff_resource_data_entry);
+ NextLevelOffset += sizeof(coff_resource_data_entry);
DataEntriesTreeOrder.push_back(Child.second.get());
} else {
Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
- NextLevelOffset += sizeof(llvm::object::coff_resource_dir_table) +
+ NextLevelOffset += sizeof(coff_resource_dir_table) +
(Child.second->getStringChildren().size() +
Child.second->getIDChildren().size()) *
- sizeof(llvm::object::coff_resource_dir_entry);
+ sizeof(coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry);
- CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += sizeof(coff_resource_dir_entry);
+ CurrentRelativeOffset += sizeof(coff_resource_dir_entry);
}
}
RelocationAddresses.resize(Data.size());
// Now write all the resource data entries.
for (auto DataNodes : DataEntriesTreeOrder) {
- auto *Entry = reinterpret_cast<llvm::object::coff_resource_data_entry *>(
- BufferStart + CurrentOffset);
+ auto *Entry = reinterpret_cast<coff_resource_data_entry *>(BufferStart +
+ CurrentOffset);
RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
Entry->DataRVA = 0; // Set to zero because it is a relocation.
Entry->DataSize = Data[DataNodes->getDataIndex()].size();
Entry->Codepage = 0;
Entry->Reserved = 0;
- CurrentOffset += sizeof(llvm::object::coff_resource_data_entry);
- CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry);
+ CurrentOffset += sizeof(coff_resource_data_entry);
+ CurrentRelativeOffset += sizeof(coff_resource_data_entry);
}
}
@@ -710,33 +685,34 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
// .rsrc section.
uint32_t NextSymbolIndex = 5;
for (unsigned i = 0; i < Data.size(); i++) {
- auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(
- BufferStart + CurrentOffset);
+ auto *Reloc =
+ reinterpret_cast<coff_relocation *>(BufferStart + CurrentOffset);
Reloc->VirtualAddress = RelocationAddresses[i];
Reloc->SymbolTableIndex = NextSymbolIndex++;
switch (MachineType) {
- case Machine::ARM:
- Reloc->Type = llvm::COFF::IMAGE_REL_ARM_ADDR32NB;
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ Reloc->Type = COFF::IMAGE_REL_ARM_ADDR32NB;
break;
- case Machine::X64:
- Reloc->Type = llvm::COFF::IMAGE_REL_AMD64_ADDR32NB;
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ Reloc->Type = COFF::IMAGE_REL_AMD64_ADDR32NB;
break;
- case Machine::X86:
- Reloc->Type = llvm::COFF::IMAGE_REL_I386_DIR32NB;
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB;
break;
default:
Reloc->Type = 0;
}
- CurrentOffset += sizeof(llvm::object::coff_relocation);
+ CurrentOffset += sizeof(coff_relocation);
}
}
-Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType,
- const WindowsResourceParser &Parser) {
+Expected<std::unique_ptr<MemoryBuffer>>
+writeWindowsResourceCOFF(COFF::MachineTypes MachineType,
+ const WindowsResourceParser &Parser) {
Error E = Error::success();
- WindowsResourceCOFFWriter Writer(OutputFile, MachineType, Parser, E);
+ WindowsResourceCOFFWriter Writer(MachineType, Parser, E);
if (E)
- return E;
+ return std::move(E);
return Writer.write();
}