summaryrefslogtreecommitdiff
path: root/lib/Object
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-10 13:44:06 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-10 13:44:06 +0000
commit7ab83427af0f77b59941ceba41d509d7d097b065 (patch)
treecc41c05b1db454e3d802f34df75e636ee922ad87 /lib/Object
parentd288ef4c1788d3a951a7558c68312c2d320612b1 (diff)
Diffstat (limited to 'lib/Object')
-rw-r--r--lib/Object/Archive.cpp2
-rw-r--r--lib/Object/ArchiveWriter.cpp3
-rw-r--r--lib/Object/Binary.cpp69
-rw-r--r--lib/Object/COFFImportFile.cpp14
-rw-r--r--lib/Object/COFFObjectFile.cpp2
-rw-r--r--lib/Object/Decompressor.cpp2
-rw-r--r--lib/Object/ELF.cpp34
-rw-r--r--lib/Object/ELFObjectFile.cpp6
-rw-r--r--lib/Object/IRObjectFile.cpp33
-rw-r--r--lib/Object/IRSymtab.cpp47
-rw-r--r--lib/Object/LLVMBuild.txt2
-rw-r--r--lib/Object/MachOObjectFile.cpp12
-rw-r--r--lib/Object/ModuleSymbolTable.cpp6
-rw-r--r--lib/Object/Object.cpp2
-rw-r--r--lib/Object/ObjectFile.cpp61
-rw-r--r--lib/Object/SymbolicFile.cpp64
-rw-r--r--lib/Object/WasmObjectFile.cpp4
-rw-r--r--lib/Object/WindowsResource.cpp518
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