diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:06 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-06-10 13:44:06 +0000 |
commit | 7ab83427af0f77b59941ceba41d509d7d097b065 (patch) | |
tree | cc41c05b1db454e3d802f34df75e636ee922ad87 /lib/Object | |
parent | d288ef4c1788d3a951a7558c68312c2d320612b1 (diff) |
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Archive.cpp | 2 | ||||
-rw-r--r-- | lib/Object/ArchiveWriter.cpp | 3 | ||||
-rw-r--r-- | lib/Object/Binary.cpp | 69 | ||||
-rw-r--r-- | lib/Object/COFFImportFile.cpp | 14 | ||||
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 2 | ||||
-rw-r--r-- | lib/Object/Decompressor.cpp | 2 | ||||
-rw-r--r-- | lib/Object/ELF.cpp | 34 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 6 | ||||
-rw-r--r-- | lib/Object/IRObjectFile.cpp | 33 | ||||
-rw-r--r-- | lib/Object/IRSymtab.cpp | 47 | ||||
-rw-r--r-- | lib/Object/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 12 | ||||
-rw-r--r-- | lib/Object/ModuleSymbolTable.cpp | 6 | ||||
-rw-r--r-- | lib/Object/Object.cpp | 2 | ||||
-rw-r--r-- | lib/Object/ObjectFile.cpp | 61 | ||||
-rw-r--r-- | lib/Object/SymbolicFile.cpp | 64 | ||||
-rw-r--r-- | lib/Object/WasmObjectFile.cpp | 4 | ||||
-rw-r--r-- | lib/Object/WindowsResource.cpp | 518 |
18 files changed, 728 insertions, 153 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index c4924f85a907..977cccc11dcd 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/Archive.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/Binary.h" #include "llvm/Object/Error.h" #include "llvm/Support/Chrono.h" diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp index 5b233aab2018..e1c35ed6a6a0 100644 --- a/lib/Object/ArchiveWriter.cpp +++ b/lib/Object/ArchiveWriter.cpp @@ -14,6 +14,7 @@ #include "llvm/Object/ArchiveWriter.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ObjectFile.h" @@ -290,7 +291,7 @@ writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind, MemoryBufferRef MemberBuffer = Members[MemberNum].Buf->getMemBufferRef(); Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr = object::SymbolicFile::createSymbolicFile( - MemberBuffer, sys::fs::file_magic::unknown, &Context); + MemberBuffer, llvm::file_magic::unknown, &Context); if (!ObjOrErr) { // FIXME: check only for "not an object file" errors. consumeError(ObjOrErr.takeError()); diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 116af3c917be..c4565db459e6 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/Binary.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Object/Archive.h" -#include "llvm/Object/Binary.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" @@ -43,41 +44,41 @@ MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; } Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer, LLVMContext *Context) { - sys::fs::file_magic Type = sys::fs::identify_magic(Buffer.getBuffer()); + file_magic Type = identify_magic(Buffer.getBuffer()); switch (Type) { - case sys::fs::file_magic::archive: - return Archive::create(Buffer); - case sys::fs::file_magic::elf: - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - case sys::fs::file_magic::macho_kext_bundle: - case sys::fs::file_magic::coff_object: - case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: - case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::wasm_object: - return ObjectFile::createSymbolicFile(Buffer, Type, Context); - case sys::fs::file_magic::macho_universal_binary: - return MachOUniversalBinary::create(Buffer); - case sys::fs::file_magic::windows_resource: - return WindowsResource::createWindowsResource(Buffer); - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::coff_cl_gl_object: - // Unrecognized object file format. - return errorCodeToError(object_error::invalid_file_type); + case file_magic::archive: + return Archive::create(Buffer); + case file_magic::elf: + case file_magic::elf_relocatable: + case file_magic::elf_executable: + case file_magic::elf_shared_object: + case file_magic::elf_core: + case file_magic::macho_object: + case file_magic::macho_executable: + case file_magic::macho_fixed_virtual_memory_shared_lib: + case file_magic::macho_core: + case file_magic::macho_preload_executable: + case file_magic::macho_dynamically_linked_shared_lib: + case file_magic::macho_dynamic_linker: + case file_magic::macho_bundle: + case file_magic::macho_dynamically_linked_shared_lib_stub: + case file_magic::macho_dsym_companion: + case file_magic::macho_kext_bundle: + case file_magic::coff_object: + case file_magic::coff_import_library: + case file_magic::pecoff_executable: + case file_magic::bitcode: + case file_magic::wasm_object: + return ObjectFile::createSymbolicFile(Buffer, Type, Context); + case file_magic::macho_universal_binary: + return MachOUniversalBinary::create(Buffer); + case file_magic::windows_resource: + return WindowsResource::createWindowsResource(Buffer); + case file_magic::unknown: + case file_magic::coff_cl_gl_object: + // Unrecognized object file format. + return errorCodeToError(object_error::invalid_file_type); } llvm_unreachable("Unexpected Binary File Type"); } diff --git a/lib/Object/COFFImportFile.cpp b/lib/Object/COFFImportFile.cpp index 37962d84d855..740bf94d40e0 100644 --- a/lib/Object/COFFImportFile.cpp +++ b/lib/Object/COFFImportFile.cpp @@ -285,11 +285,13 @@ ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) { IMAGE_SYM_CLASS_EXTERNAL, 0}, }; - reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset = + // TODO: Name.Offset.Offset here and in the all similar places below + // suggests a names refactoring. Maybe StringTableOffset.Value? + SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t); - reinterpret_cast<StringTableOffset &>(SymbolTable[5].Name).Offset = + SymbolTable[5].Name.Offset.Offset = sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1; - reinterpret_cast<StringTableOffset &>(SymbolTable[6].Name).Offset = + SymbolTable[6].Name.Offset.Offset = sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 + NullImportDescriptorSymbolName.length() + 1; append(Buffer, SymbolTable); @@ -354,8 +356,7 @@ ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) { IMAGE_SYM_CLASS_EXTERNAL, 0}, }; - reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset = - sizeof(uint32_t); + SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t); append(Buffer, SymbolTable); // String Table @@ -437,8 +438,7 @@ NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) { IMAGE_SYM_CLASS_EXTERNAL, 0}, }; - reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset = - sizeof(uint32_t); + SymbolTable[0].Name.Offset.Offset = sizeof(uint32_t); append(Buffer, SymbolTable); // String Table diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 7372f24cb9a8..579c8dde366a 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -15,12 +15,12 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/BinaryFormat/COFF.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Object/Error.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" diff --git a/lib/Object/Decompressor.cpp b/lib/Object/Decompressor.cpp index 89d199a3f3f6..53f084d7620e 100644 --- a/lib/Object/Decompressor.cpp +++ b/lib/Object/Decompressor.cpp @@ -8,11 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/Decompressor.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Compression.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/ELF.h" using namespace llvm; using namespace llvm::support::endian; diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index 5798a3540f53..9bc28dc14a29 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/ELF.h" -#include "llvm/Support/ELF.h" +#include "llvm/BinaryFormat/ELF.h" using namespace llvm; using namespace object; @@ -24,7 +24,7 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, switch (Machine) { case ELF::EM_X86_64: switch (Type) { -#include "llvm/Support/ELFRelocs/x86_64.def" +#include "llvm/BinaryFormat/ELFRelocs/x86_64.def" default: break; } @@ -32,77 +32,77 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, case ELF::EM_386: case ELF::EM_IAMCU: switch (Type) { -#include "llvm/Support/ELFRelocs/i386.def" +#include "llvm/BinaryFormat/ELFRelocs/i386.def" default: break; } break; case ELF::EM_MIPS: switch (Type) { -#include "llvm/Support/ELFRelocs/Mips.def" +#include "llvm/BinaryFormat/ELFRelocs/Mips.def" default: break; } break; case ELF::EM_AARCH64: switch (Type) { -#include "llvm/Support/ELFRelocs/AArch64.def" +#include "llvm/BinaryFormat/ELFRelocs/AArch64.def" default: break; } break; case ELF::EM_ARM: switch (Type) { -#include "llvm/Support/ELFRelocs/ARM.def" +#include "llvm/BinaryFormat/ELFRelocs/ARM.def" default: break; } break; case ELF::EM_AVR: switch (Type) { -#include "llvm/Support/ELFRelocs/AVR.def" +#include "llvm/BinaryFormat/ELFRelocs/AVR.def" default: break; } break; case ELF::EM_HEXAGON: switch (Type) { -#include "llvm/Support/ELFRelocs/Hexagon.def" +#include "llvm/BinaryFormat/ELFRelocs/Hexagon.def" default: break; } break; case ELF::EM_LANAI: switch (Type) { -#include "llvm/Support/ELFRelocs/Lanai.def" +#include "llvm/BinaryFormat/ELFRelocs/Lanai.def" default: break; } break; case ELF::EM_PPC: switch (Type) { -#include "llvm/Support/ELFRelocs/PowerPC.def" +#include "llvm/BinaryFormat/ELFRelocs/PowerPC.def" default: break; } break; case ELF::EM_PPC64: switch (Type) { -#include "llvm/Support/ELFRelocs/PowerPC64.def" +#include "llvm/BinaryFormat/ELFRelocs/PowerPC64.def" default: break; } break; case ELF::EM_RISCV: switch (Type) { -#include "llvm/Support/ELFRelocs/RISCV.def" +#include "llvm/BinaryFormat/ELFRelocs/RISCV.def" default: break; } break; case ELF::EM_S390: switch (Type) { -#include "llvm/Support/ELFRelocs/SystemZ.def" +#include "llvm/BinaryFormat/ELFRelocs/SystemZ.def" default: break; } @@ -111,27 +111,27 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, case ELF::EM_SPARC32PLUS: case ELF::EM_SPARCV9: switch (Type) { -#include "llvm/Support/ELFRelocs/Sparc.def" +#include "llvm/BinaryFormat/ELFRelocs/Sparc.def" default: break; } break; case ELF::EM_WEBASSEMBLY: switch (Type) { -#include "llvm/Support/ELFRelocs/WebAssembly.def" +#include "llvm/BinaryFormat/ELFRelocs/WebAssembly.def" default: break; } break; case ELF::EM_AMDGPU: switch (Type) { -#include "llvm/Support/ELFRelocs/AMDGPU.def" +#include "llvm/BinaryFormat/ELFRelocs/AMDGPU.def" default: break; } case ELF::EM_BPF: switch (Type) { -#include "llvm/Support/ELFRelocs/BPF.def" +#include "llvm/BinaryFormat/ELFRelocs/BPF.def" default: break; } diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 86f033bb6cbf..fa136d782b5a 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -11,15 +11,15 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/ELFObjectFile.h" #include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/ELF.h" -#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ELFTypes.h" #include "llvm/Object/Error.h" -#include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/ARMAttributeParser.h" -#include "llvm/Support/ELF.h" +#include "llvm/Support/ARMBuildAttributes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp index adbf0de6d1bc..e7807b038335 100644 --- a/lib/Object/IRObjectFile.cpp +++ b/lib/Object/IRObjectFile.cpp @@ -14,6 +14,7 @@ #include "llvm/Object/IRObjectFile.h" #include "RecordStreamer.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/LLVMContext.h" @@ -95,13 +96,13 @@ ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInObject(const ObjectFile &Obj } ErrorOr<MemoryBufferRef> IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { - sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); + file_magic Type = identify_magic(Object.getBuffer()); switch (Type) { - case sys::fs::file_magic::bitcode: + case file_magic::bitcode: return Object; - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::coff_object: { + case file_magic::elf_relocatable: + case file_magic::macho_object: + case file_magic::coff_object: { Expected<std::unique_ptr<ObjectFile>> ObjFile = ObjectFile::createObjectFile(Object, Type); if (!ObjFile) @@ -138,3 +139,25 @@ IRObjectFile::create(MemoryBufferRef Object, LLVMContext &Context) { return std::unique_ptr<IRObjectFile>( new IRObjectFile(*BCOrErr, std::move(Mods))); } + +Expected<IRSymtabFile> object::readIRSymtab(MemoryBufferRef MBRef) { + IRSymtabFile F; + ErrorOr<MemoryBufferRef> BCOrErr = + IRObjectFile::findBitcodeInMemBuffer(MBRef); + if (!BCOrErr) + return errorCodeToError(BCOrErr.getError()); + + Expected<BitcodeFileContents> BFCOrErr = getBitcodeFileContents(*BCOrErr); + if (!BFCOrErr) + return BFCOrErr.takeError(); + + Expected<irsymtab::FileContents> FCOrErr = irsymtab::readBitcode(*BFCOrErr); + if (!FCOrErr) + return FCOrErr.takeError(); + + F.Mods = std::move(BFCOrErr->Mods); + F.Symtab = std::move(FCOrErr->Symtab); + F.Strtab = std::move(FCOrErr->Strtab); + F.TheReader = std::move(FCOrErr->TheReader); + return std::move(F); +} diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp index 5f0837882d60..d21acdb1d556 100644 --- a/lib/Object/IRSymtab.cpp +++ b/lib/Object/IRSymtab.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/IRSymtab.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" @@ -22,15 +23,16 @@ #include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/MC/StringTableBuilder.h" -#include "llvm/Object/IRSymtab.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Error.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/raw_ostream.h" #include <cassert> #include <string> #include <utility> @@ -88,6 +90,10 @@ struct Builder { }; Error Builder::addModule(Module *M) { + if (M->getDataLayoutStr().empty()) + return make_error<StringError>("input module has no datalayout", + inconvertibleErrorCode()); + SmallPtrSet<GlobalValue *, 8> Used; collectUsedGlobalVariables(*M, Used, /*CompilerUsed*/ false); @@ -259,3 +265,40 @@ Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab, SmallVector<char, 0> &Strtab) { return Builder(Symtab, Strtab).build(Mods); } + +// Upgrade a vector of bitcode modules created by an old version of LLVM by +// creating an irsymtab for them in the current format. +static Expected<FileContents> upgrade(ArrayRef<BitcodeModule> BMs) { + FileContents FC; + + LLVMContext Ctx; + std::vector<Module *> Mods; + std::vector<std::unique_ptr<Module>> OwnedMods; + for (auto BM : BMs) { + Expected<std::unique_ptr<Module>> MOrErr = + BM.getLazyModule(Ctx, /*ShouldLazyLoadMetadata*/ true, + /*IsImporting*/ false); + if (!MOrErr) + return MOrErr.takeError(); + + Mods.push_back(MOrErr->get()); + OwnedMods.push_back(std::move(*MOrErr)); + } + + if (Error E = build(Mods, FC.Symtab, FC.Strtab)) + return std::move(E); + + FC.TheReader = {{FC.Symtab.data(), FC.Symtab.size()}, + {FC.Strtab.data(), FC.Strtab.size()}}; + return std::move(FC); +} + +Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) { + if (BFC.Mods.empty()) + return make_error<StringError>("Bitcode file does not contain any modules", + inconvertibleErrorCode()); + + // Right now we have no on-disk representation of symbol tables, so we always + // upgrade. + return upgrade(BFC.Mods); +} diff --git a/lib/Object/LLVMBuild.txt b/lib/Object/LLVMBuild.txt index bae578c76f7e..687713bab6a2 100644 --- a/lib/Object/LLVMBuild.txt +++ b/lib/Object/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = Object parent = Libraries -required_libraries = BitReader Core MC MCParser Support +required_libraries = BitReader Core MC BinaryFormat MCParser Support diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 084159a61f55..7804bbe06f83 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -14,13 +14,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/MachO.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" @@ -32,10 +33,9 @@ #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -4314,3 +4314,9 @@ ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, return make_error<GenericBinaryError>("Unrecognized MachO magic number", object_error::invalid_file_type); } + +StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const { + return StringSwitch<StringRef>(Name) + .Case("debug_str_offs", "debug_str_offsets") + .Default(Name); +} diff --git a/lib/Object/ModuleSymbolTable.cpp b/lib/Object/ModuleSymbolTable.cpp index a5b42725d817..f2e7a218c13a 100644 --- a/lib/Object/ModuleSymbolTable.cpp +++ b/lib/Object/ModuleSymbolTable.cpp @@ -13,9 +13,10 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/ModuleSymbolTable.h" #include "RecordStreamer.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" @@ -36,16 +37,15 @@ #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetOptions.h" -#include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstdint> diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 6df481b060e1..1d2859cfbe9d 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/SmallVector.h" #include "llvm-c/Object.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Object/ObjectFile.h" using namespace llvm; diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 1f60e7157bd9..8377dd0d73fa 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/ObjectFile.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Object/Binary.h" #include "llvm/Object/COFF.h" #include "llvm/Object/Error.h" #include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/Wasm.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -79,42 +80,42 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { } Expected<std::unique_ptr<ObjectFile>> -ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { +ObjectFile::createObjectFile(MemoryBufferRef Object, file_magic Type) { StringRef Data = Object.getBuffer(); - if (Type == sys::fs::file_magic::unknown) - Type = sys::fs::identify_magic(Data); + if (Type == file_magic::unknown) + Type = identify_magic(Data); switch (Type) { - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::bitcode: - case sys::fs::file_magic::coff_cl_gl_object: - case sys::fs::file_magic::archive: - case sys::fs::file_magic::macho_universal_binary: - case sys::fs::file_magic::windows_resource: + case file_magic::unknown: + case file_magic::bitcode: + case file_magic::coff_cl_gl_object: + case file_magic::archive: + case file_magic::macho_universal_binary: + case file_magic::windows_resource: return errorCodeToError(object_error::invalid_file_type); - case sys::fs::file_magic::elf: - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: + case file_magic::elf: + case file_magic::elf_relocatable: + case file_magic::elf_executable: + case file_magic::elf_shared_object: + case file_magic::elf_core: return errorOrToExpected(createELFObjectFile(Object)); - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - case sys::fs::file_magic::macho_kext_bundle: + case file_magic::macho_object: + case file_magic::macho_executable: + case file_magic::macho_fixed_virtual_memory_shared_lib: + case file_magic::macho_core: + case file_magic::macho_preload_executable: + case file_magic::macho_dynamically_linked_shared_lib: + case file_magic::macho_dynamic_linker: + case file_magic::macho_bundle: + case file_magic::macho_dynamically_linked_shared_lib_stub: + case file_magic::macho_dsym_companion: + case file_magic::macho_kext_bundle: return createMachOObjectFile(Object); - case sys::fs::file_magic::coff_object: - case sys::fs::file_magic::coff_import_library: - case sys::fs::file_magic::pecoff_executable: + case file_magic::coff_object: + case file_magic::coff_import_library: + case file_magic::pecoff_executable: return errorOrToExpected(createCOFFObjectFile(Object)); - case sys::fs::file_magic::wasm_object: + case file_magic::wasm_object: return createWasmObjectFile(Object); } llvm_unreachable("Unexpected Object File Type"); diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp index 16cff5c228bd..1042d29d2350 100644 --- a/lib/Object/SymbolicFile.cpp +++ b/lib/Object/SymbolicFile.cpp @@ -11,12 +11,13 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/SymbolicFile.h" #include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/Error.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" @@ -34,45 +35,46 @@ SymbolicFile::SymbolicFile(unsigned int Type, MemoryBufferRef Source) SymbolicFile::~SymbolicFile() = default; -Expected<std::unique_ptr<SymbolicFile>> SymbolicFile::createSymbolicFile( - MemoryBufferRef Object, sys::fs::file_magic Type, LLVMContext *Context) { +Expected<std::unique_ptr<SymbolicFile>> +SymbolicFile::createSymbolicFile(MemoryBufferRef Object, file_magic Type, + LLVMContext *Context) { StringRef Data = Object.getBuffer(); - if (Type == sys::fs::file_magic::unknown) - Type = sys::fs::identify_magic(Data); + if (Type == file_magic::unknown) + Type = identify_magic(Data); switch (Type) { - case sys::fs::file_magic::bitcode: + case file_magic::bitcode: if (Context) return IRObjectFile::create(Object, *Context); LLVM_FALLTHROUGH; - case sys::fs::file_magic::unknown: - case sys::fs::file_magic::archive: - case sys::fs::file_magic::coff_cl_gl_object: - case sys::fs::file_magic::macho_universal_binary: - case sys::fs::file_magic::windows_resource: + case file_magic::unknown: + case file_magic::archive: + case file_magic::coff_cl_gl_object: + case file_magic::macho_universal_binary: + case file_magic::windows_resource: return errorCodeToError(object_error::invalid_file_type); - case sys::fs::file_magic::elf: - case sys::fs::file_magic::elf_executable: - case sys::fs::file_magic::elf_shared_object: - case sys::fs::file_magic::elf_core: - case sys::fs::file_magic::macho_executable: - case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: - case sys::fs::file_magic::macho_core: - case sys::fs::file_magic::macho_preload_executable: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib: - case sys::fs::file_magic::macho_dynamic_linker: - case sys::fs::file_magic::macho_bundle: - case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: - case sys::fs::file_magic::macho_dsym_companion: - case sys::fs::file_magic::macho_kext_bundle: - case sys::fs::file_magic::pecoff_executable: - case sys::fs::file_magic::wasm_object: + case file_magic::elf: + case file_magic::elf_executable: + case file_magic::elf_shared_object: + case file_magic::elf_core: + case file_magic::macho_executable: + case file_magic::macho_fixed_virtual_memory_shared_lib: + case file_magic::macho_core: + case file_magic::macho_preload_executable: + case file_magic::macho_dynamically_linked_shared_lib: + case file_magic::macho_dynamic_linker: + case file_magic::macho_bundle: + case file_magic::macho_dynamically_linked_shared_lib_stub: + case file_magic::macho_dsym_companion: + case file_magic::macho_kext_bundle: + case file_magic::pecoff_executable: + case file_magic::wasm_object: return ObjectFile::createObjectFile(Object, Type); - case sys::fs::file_magic::coff_import_library: + case file_magic::coff_import_library: return std::unique_ptr<SymbolicFile>(new COFFImportFile(Object)); - case sys::fs::file_magic::elf_relocatable: - case sys::fs::file_magic::macho_object: - case sys::fs::file_magic::coff_object: { + case file_magic::elf_relocatable: + case file_magic::macho_object: + case file_magic::coff_object: { Expected<std::unique_ptr<ObjectFile>> Obj = ObjectFile::createObjectFile(Object, Type); if (!Obj || !Context) diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp index f565d7a33e55..2304098c1dc9 100644 --- a/lib/Object/WasmObjectFile.cpp +++ b/lib/Object/WasmObjectFile.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/BinaryFormat/Wasm.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Object/Binary.h" #include "llvm/Object/Error.h" @@ -21,7 +22,6 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" -#include "llvm/Support/Wasm.h" #include <algorithm> #include <cassert> #include <cstdint> @@ -830,7 +830,7 @@ void WasmObjectFile::getRelocationTypeName( break; switch (Rel.Type) { -#include "llvm/Support/WasmRelocs/WebAssembly.def" +#include "llvm/BinaryFormat/WasmRelocs/WebAssembly.def" } #undef WASM_RELOC diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp index e46d38e466a0..041659e7aa23 100644 --- a/lib/Object/WindowsResource.cpp +++ b/lib/Object/WindowsResource.cpp @@ -12,7 +12,12 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/WindowsResource.h" -#include "llvm/Support/COFF.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" +#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/MathExtras.h" +#include <ctime> +#include <queue> #include <sstream> #include <system_error> @@ -29,6 +34,9 @@ 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; @@ -115,7 +123,7 @@ Error ResourceEntryRef::loadNext() { return Error::success(); } -WindowsResourceParser::WindowsResourceParser() {} +WindowsResourceParser::WindowsResourceParser() : Root(false) {} Error WindowsResourceParser::parse(WindowsResource *WR) { auto EntryOrErr = WR->getHeadEntry(); @@ -124,9 +132,16 @@ Error WindowsResourceParser::parse(WindowsResource *WR) { ResourceEntryRef Entry = EntryOrErr.get(); bool End = false; - while (!End) { + Data.push_back(Entry.getData()); + + if (Entry.checkTypeString()) + StringTable.push_back(Entry.getTypeString()); + + if (Entry.checkNameString()) + StringTable.push_back(Entry.getNameString()); + Root.addEntry(Entry); RETURN_IF_ERROR(Entry.moveNext(End)); @@ -146,8 +161,37 @@ void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry) { NameNode.addLanguageNode(Entry); } -WindowsResourceParser::TreeNode::TreeNode(ArrayRef<UTF16> NameRef) - : Name(NameRef) {} +WindowsResourceParser::TreeNode::TreeNode(bool IsStringNode) { + if (IsStringNode) + StringIndex = StringCount++; +} + +WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion, + uint16_t MinorVersion, + uint32_t Characteristics) + : IsDataNode(true), MajorVersion(MajorVersion), MinorVersion(MinorVersion), + Characteristics(Characteristics) { + if (IsDataNode) + DataIndex = DataCount++; +} + +std::unique_ptr<WindowsResourceParser::TreeNode> +WindowsResourceParser::TreeNode::createStringNode() { + return std::unique_ptr<TreeNode>(new TreeNode(true)); +} + +std::unique_ptr<WindowsResourceParser::TreeNode> +WindowsResourceParser::TreeNode::createIDNode() { + return std::unique_ptr<TreeNode>(new TreeNode(false)); +} + +std::unique_ptr<WindowsResourceParser::TreeNode> +WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion, + uint16_t MinorVersion, + uint32_t Characteristics) { + return std::unique_ptr<TreeNode>( + new TreeNode(MajorVersion, MinorVersion, Characteristics)); +} WindowsResourceParser::TreeNode & WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) { @@ -168,14 +212,18 @@ WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry) { WindowsResourceParser::TreeNode & WindowsResourceParser::TreeNode::addLanguageNode( const ResourceEntryRef &Entry) { - return addChild(Entry.getLanguage()); + return addChild(Entry.getLanguage(), true, Entry.getMajorVersion(), + Entry.getMinorVersion(), Entry.getCharacteristics()); } -WindowsResourceParser::TreeNode & -WindowsResourceParser::TreeNode::addChild(uint32_t ID) { +WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addChild( + uint32_t ID, bool IsDataNode, uint16_t MajorVersion, uint16_t MinorVersion, + uint32_t Characteristics) { auto Child = IDChildren.find(ID); if (Child == IDChildren.end()) { - auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(ID); + auto NewChild = + IsDataNode ? createDataNode(MajorVersion, MinorVersion, Characteristics) + : createIDNode(); WindowsResourceParser::TreeNode &Node = *NewChild; IDChildren.emplace(ID, std::move(NewChild)); return Node; @@ -199,7 +247,7 @@ WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef) { auto Child = StringChildren.find(NameString); if (Child == StringChildren.end()) { - auto NewChild = llvm::make_unique<WindowsResourceParser::TreeNode>(NameRef); + auto NewChild = createStringNode(); WindowsResourceParser::TreeNode &Node = *NewChild; StringChildren.emplace(NameString, std::move(NewChild)); return Node; @@ -218,5 +266,455 @@ void WindowsResourceParser::TreeNode::print(ScopedPrinter &Writer, } } +// This function returns the size of the entire resource tree, including +// directory tables, directory entries, and data entries. It does not include +// 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); + + // Reached a node pointing to a data entry. + if (IsDataNode) { + Size += sizeof(llvm::object::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); + + for (auto const &Child : StringChildren) { + Size += Child.second->getTreeSize(); + } + for (auto const &Child : IDChildren) { + Size += Child.second->getTreeSize(); + } + return Size; +} + +class WindowsResourceCOFFWriter { +public: + WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType, + const WindowsResourceParser &Parser, Error &E); + + Error write(); + +private: + void performFileLayout(); + void performSectionOneLayout(); + void performSectionTwoLayout(); + void writeCOFFHeader(); + void writeFirstSectionHeader(); + void writeSecondSectionHeader(); + void writeFirstSection(); + void writeSecondSection(); + void writeSymbolTable(); + void writeStringTable(); + void writeDirectoryTree(); + void writeDirectoryStringTable(); + void writeFirstSectionRelocations(); + std::unique_ptr<FileOutputBuffer> Buffer; + uint8_t *Current; + Machine MachineType; + const WindowsResourceParser::TreeNode &Resources; + const ArrayRef<std::vector<uint8_t>> Data; + uint64_t FileSize; + uint32_t SymbolTableOffset; + uint32_t SectionOneSize; + uint32_t SectionOneOffset; + uint32_t SectionOneRelocations; + uint32_t SectionTwoSize; + uint32_t SectionTwoOffset; + const ArrayRef<std::vector<UTF16>> StringTable; + std::vector<uint32_t> StringTableOffsets; + std::vector<uint32_t> DataOffsets; + std::vector<uint32_t> RelocationAddresses; +}; + +WindowsResourceCOFFWriter::WindowsResourceCOFFWriter( + StringRef OutputFile, Machine 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); +} + +void WindowsResourceCOFFWriter::performFileLayout() { + // Add size of COFF header. + FileSize = llvm::COFF::Header16Size; + + // one .rsrc section header for directory tree, another for resource data. + FileSize += 2 * llvm::COFF::SectionSize; + + performSectionOneLayout(); + performSectionTwoLayout(); + + // 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 += 4; // four null bytes for the string table. +} + +void WindowsResourceCOFFWriter::performSectionOneLayout() { + SectionOneOffset = FileSize; + + SectionOneSize = Resources.getTreeSize(); + uint32_t CurrentStringOffset = SectionOneSize; + uint32_t TotalStringTableSize = 0; + for (auto const &String : StringTable) { + StringTableOffsets.push_back(CurrentStringOffset); + uint32_t StringSize = String.size() * sizeof(UTF16) + sizeof(uint16_t); + CurrentStringOffset += StringSize; + TotalStringTableSize += StringSize; + } + SectionOneSize += alignTo(TotalStringTableSize, sizeof(uint32_t)); + + // account for the relocations of section one. + SectionOneRelocations = FileSize + SectionOneSize; + FileSize += SectionOneSize; + FileSize += Data.size() * + llvm::COFF::RelocationSize; // one relocation for each resource. +} + +void WindowsResourceCOFFWriter::performSectionTwoLayout() { + // add size of .rsrc$2 section, which contains all resource data on 8-byte + // alignment. + SectionTwoOffset = FileSize; + SectionTwoSize = 0; + for (auto const &Entry : Data) { + DataOffsets.push_back(SectionTwoSize); + SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t)); + } + FileSize += SectionTwoSize; +} + +static std::time_t getTime() { + std::time_t Now = time(nullptr); + if (Now < 0 || !isUInt<32>(Now)) + return UINT32_MAX; + return Now; +} + +Error WindowsResourceCOFFWriter::write() { + Current = Buffer->getBufferStart(); + + writeCOFFHeader(); + writeFirstSectionHeader(); + writeSecondSectionHeader(); + writeFirstSection(); + writeSecondSection(); + writeSymbolTable(); + writeStringTable(); + + if (auto EC = Buffer->commit()) { + return errorCodeToError(EC); + } + + return Error::success(); +} + +void WindowsResourceCOFFWriter::writeCOFFHeader() { + // Write the COFF header. + auto *Header = reinterpret_cast<llvm::object::coff_file_header *>(Current); + switch (MachineType) { + case Machine::ARM: + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; + break; + case Machine::X64: + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_AMD64; + break; + case Machine::X86: + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_I386; + break; + default: + Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN; + } + Header->NumberOfSections = 2; + Header->TimeDateStamp = getTime(); + Header->PointerToSymbolTable = SymbolTableOffset; + // 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; +} + +void WindowsResourceCOFFWriter::writeFirstSectionHeader() { + // Write the first section header. + Current += sizeof(llvm::object::coff_file_header); + auto *SectionOneHeader = + reinterpret_cast<llvm::object::coff_section *>(Current); + strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize); + SectionOneHeader->VirtualSize = 0; + SectionOneHeader->VirtualAddress = 0; + SectionOneHeader->SizeOfRawData = SectionOneSize; + SectionOneHeader->PointerToRawData = SectionOneOffset; + SectionOneHeader->PointerToRelocations = SectionOneRelocations; + 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; +} + +void WindowsResourceCOFFWriter::writeSecondSectionHeader() { + // Write the second section header. + Current += sizeof(llvm::object::coff_section); + auto *SectionTwoHeader = + reinterpret_cast<llvm::object::coff_section *>(Current); + strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize); + SectionTwoHeader->VirtualSize = 0; + SectionTwoHeader->VirtualAddress = 0; + SectionTwoHeader->SizeOfRawData = SectionTwoSize; + SectionTwoHeader->PointerToRawData = SectionTwoOffset; + SectionTwoHeader->PointerToRelocations = 0; + 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; +} + +void WindowsResourceCOFFWriter::writeFirstSection() { + // Write section one. + Current += sizeof(llvm::object::coff_section); + + writeDirectoryTree(); + writeDirectoryStringTable(); + writeFirstSectionRelocations(); +} + +void WindowsResourceCOFFWriter::writeSecondSection() { + // Now write the .rsrc$02 section. + for (auto const &RawDataEntry : Data) { + std::copy(RawDataEntry.begin(), RawDataEntry.end(), Current); + Current += alignTo(RawDataEntry.size(), sizeof(uint64_t)); + } +} + +void WindowsResourceCOFFWriter::writeSymbolTable() { + // Now write the symbol table. + // First, the feat symbol. + auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current); + strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)llvm::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->NumberOfAuxSymbols = 0; + Current += sizeof(llvm::object::coff_symbol16); + + // Now write the .rsrc1 symbol + aux. + Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current); + strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)llvm::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->NumberOfAuxSymbols = 1; + Current += sizeof(llvm::object::coff_symbol16); + auto *Aux = + reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current); + Aux->Length = SectionOneSize; + Aux->NumberOfRelocations = Data.size(); + Aux->NumberOfLinenumbers = 0; + Aux->CheckSum = 0; + Aux->NumberLowPart = 0; + Aux->Selection = 0; + Current += sizeof(llvm::object::coff_aux_section_definition); + + // Now write the .rsrc2 symbol + aux. + Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current); + strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)llvm::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->NumberOfAuxSymbols = 1; + Current += sizeof(llvm::object::coff_symbol16); + Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current); + Aux->Length = SectionTwoSize; + Aux->NumberOfRelocations = 0; + Aux->NumberOfLinenumbers = 0; + Aux->CheckSum = 0; + Aux->NumberLowPart = 0; + Aux->Selection = 0; + Current += sizeof(llvm::object::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 *>(Current); + strncpy(Symbol->Name.ShortName, RelocationName, + (size_t)llvm::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->NumberOfAuxSymbols = 0; + Current += sizeof(llvm::object::coff_symbol16); + } +} + +void WindowsResourceCOFFWriter::writeStringTable() { + // Just 4 null bytes for the string table. + auto COFFStringTable = reinterpret_cast<uint32_t *>(Current); + *COFFStringTable = 0; +} + +void WindowsResourceCOFFWriter::writeDirectoryTree() { + // Traverse parsed resource tree breadth-first and write the corresponding + // 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); + 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 *>(Current); + Table->Characteristics = CurrentNode->getCharacteristics(); + Table->TimeDateStamp = 0; + Table->MajorVersion = CurrentNode->getMajorVersion(); + Table->MinorVersion = CurrentNode->getMinorVersion(); + auto &IDChildren = CurrentNode->getIDChildren(); + auto &StringChildren = CurrentNode->getStringChildren(); + Table->NumberOfNameEntries = StringChildren.size(); + Table->NumberOfIDEntries = IDChildren.size(); + Current += sizeof(llvm::object::coff_resource_dir_table); + CurrentRelativeOffset += sizeof(llvm::object::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 *>(Current); + Entry->Identifier.NameOffset = + StringTableOffsets[Child.second->getStringIndex()]; + if (Child.second->checkIsDataNode()) { + Entry->Offset.DataEntryOffset = NextLevelOffset; + NextLevelOffset += sizeof(llvm::object::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) + + (Child.second->getStringChildren().size() + + Child.second->getIDChildren().size()) * + sizeof(llvm::object::coff_resource_dir_entry); + Queue.push(Child.second.get()); + } + Current += sizeof(llvm::object::coff_resource_dir_entry); + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry); + } + for (auto const &Child : IDChildren) { + auto *Entry = + reinterpret_cast<llvm::object::coff_resource_dir_entry *>(Current); + Entry->Identifier.ID = Child.first; + if (Child.second->checkIsDataNode()) { + Entry->Offset.DataEntryOffset = NextLevelOffset; + NextLevelOffset += sizeof(llvm::object::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) + + (Child.second->getStringChildren().size() + + Child.second->getIDChildren().size()) * + sizeof(llvm::object::coff_resource_dir_entry); + Queue.push(Child.second.get()); + } + Current += sizeof(llvm::object::coff_resource_dir_entry); + CurrentRelativeOffset += sizeof(llvm::object::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 *>(Current); + 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; + Current += sizeof(llvm::object::coff_resource_data_entry); + CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry); + } +} + +void WindowsResourceCOFFWriter::writeDirectoryStringTable() { + // Now write the directory string table for .rsrc$01 + uint32_t TotalStringTableSize = 0; + for (auto String : StringTable) { + auto *LengthField = reinterpret_cast<uint16_t *>(Current); + uint16_t Length = String.size(); + *LengthField = Length; + Current += sizeof(uint16_t); + auto *Start = reinterpret_cast<UTF16 *>(Current); + std::copy(String.begin(), String.end(), Start); + Current += Length * sizeof(UTF16); + TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t); + } + Current += + alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize; +} + +void WindowsResourceCOFFWriter::writeFirstSectionRelocations() { + + // Now write the relocations for .rsrc$01 + // Five symbols already in table before we start, @feat.00 and 2 for each + // .rsrc section. + uint32_t NextSymbolIndex = 5; + for (unsigned i = 0; i < Data.size(); i++) { + auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(Current); + Reloc->VirtualAddress = RelocationAddresses[i]; + Reloc->SymbolTableIndex = NextSymbolIndex++; + switch (MachineType) { + case Machine::ARM: + Reloc->Type = llvm::COFF::IMAGE_REL_ARM_ADDR32NB; + break; + case Machine::X64: + Reloc->Type = llvm::COFF::IMAGE_REL_AMD64_ADDR32NB; + break; + case Machine::X86: + Reloc->Type = llvm::COFF::IMAGE_REL_I386_DIR32NB; + break; + default: + Reloc->Type = 0; + } + Current += sizeof(llvm::object::coff_relocation); + } +} + +Error writeWindowsResourceCOFF(StringRef OutputFile, Machine MachineType, + const WindowsResourceParser &Parser) { + Error E = Error::success(); + WindowsResourceCOFFWriter Writer(OutputFile, MachineType, Parser, E); + if (E) + return E; + return Writer.write(); +} + } // namespace object } // namespace llvm |