diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-26 20:32:52 +0000 |
commit | 08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (patch) | |
tree | 80108f0f128657f8623f8f66ad9735b4d88e7b47 /lib/Object | |
parent | 7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (diff) |
Notes
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 20 | ||||
-rw-r--r-- | lib/Object/IRSymtab.cpp | 36 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 39 | ||||
-rw-r--r-- | lib/Object/WasmObjectFile.cpp | 93 | ||||
-rw-r--r-- | lib/Object/WindowsResource.cpp | 270 |
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(); } |