summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Object/WindowsResource.cpp113
1 files changed, 67 insertions, 46 deletions
diff --git a/llvm/lib/Object/WindowsResource.cpp b/llvm/lib/Object/WindowsResource.cpp
index a7e126da52a..3d689fe1e9a 100644
--- a/llvm/lib/Object/WindowsResource.cpp
+++ b/llvm/lib/Object/WindowsResource.cpp
@@ -30,6 +30,10 @@ namespace object {
const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
+// COFF files seem to be inconsistent with alignment between sections, just use
+// 8-byte because it makes everyone happy.
+const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);
+
static const size_t ResourceMagicSize = 16;
static const size_t NullEntrySize = 16;
@@ -320,7 +324,8 @@ private:
void writeDirectoryStringTable();
void writeFirstSectionRelocations();
std::unique_ptr<FileOutputBuffer> Buffer;
- uint8_t *Current;
+ uint8_t *BufferStart;
+ uint64_t CurrentOffset = 0;
Machine MachineType;
const WindowsResourceParser::TreeNode &Resources;
const ArrayRef<std::vector<uint8_t>> Data;
@@ -392,6 +397,7 @@ void WindowsResourceCOFFWriter::performSectionOneLayout() {
FileSize += SectionOneSize;
FileSize += Data.size() *
llvm::COFF::RelocationSize; // one relocation for each resource.
+ FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}
void WindowsResourceCOFFWriter::performSectionTwoLayout() {
@@ -404,6 +410,7 @@ void WindowsResourceCOFFWriter::performSectionTwoLayout() {
SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t));
}
FileSize += SectionTwoSize;
+ FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}
static std::time_t getTime() {
@@ -414,7 +421,7 @@ static std::time_t getTime() {
}
Error WindowsResourceCOFFWriter::write() {
- Current = Buffer->getBufferStart();
+ BufferStart = Buffer->getBufferStart();
writeCOFFHeader();
writeFirstSectionHeader();
@@ -433,7 +440,8 @@ Error WindowsResourceCOFFWriter::write() {
void WindowsResourceCOFFWriter::writeCOFFHeader() {
// Write the COFF header.
- auto *Header = reinterpret_cast<llvm::object::coff_file_header *>(Current);
+ auto *Header =
+ reinterpret_cast<llvm::object::coff_file_header *>(BufferStart);
switch (MachineType) {
case Machine::ARM:
Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
@@ -458,9 +466,9 @@ void WindowsResourceCOFFWriter::writeCOFFHeader() {
void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
// Write the first section header.
- Current += sizeof(llvm::object::coff_file_header);
- auto *SectionOneHeader =
- reinterpret_cast<llvm::object::coff_section *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_file_header);
+ auto *SectionOneHeader = reinterpret_cast<llvm::object::coff_section *>(
+ BufferStart + CurrentOffset);
strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize);
SectionOneHeader->VirtualSize = 0;
SectionOneHeader->VirtualAddress = 0;
@@ -479,9 +487,9 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
// Write the second section header.
- Current += sizeof(llvm::object::coff_section);
- auto *SectionTwoHeader =
- reinterpret_cast<llvm::object::coff_section *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_section);
+ auto *SectionTwoHeader = reinterpret_cast<llvm::object::coff_section *>(
+ BufferStart + CurrentOffset);
strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize);
SectionTwoHeader->VirtualSize = 0;
SectionTwoHeader->VirtualAddress = 0;
@@ -498,75 +506,85 @@ void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
void WindowsResourceCOFFWriter::writeFirstSection() {
// Write section one.
- Current += sizeof(llvm::object::coff_section);
+ CurrentOffset += sizeof(llvm::object::coff_section);
writeDirectoryTree();
writeDirectoryStringTable();
writeFirstSectionRelocations();
+
+ CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}
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));
+ std::copy(RawDataEntry.begin(), RawDataEntry.end(),
+ BufferStart + CurrentOffset);
+ CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t));
}
+
+ CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}
void WindowsResourceCOFFWriter::writeSymbolTable() {
// Now write the symbol table.
// First, the feat symbol.
- auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
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);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
// Now write the .rsrc1 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
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);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ auto *Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
+ BufferStart + CurrentOffset);
Aux->Length = SectionOneSize;
Aux->NumberOfRelocations = Data.size();
Aux->NumberOfLinenumbers = 0;
Aux->CheckSum = 0;
Aux->NumberLowPart = 0;
Aux->Selection = 0;
- Current += sizeof(llvm::object::coff_aux_section_definition);
+ CurrentOffset += sizeof(llvm::object::coff_aux_section_definition);
// Now write the .rsrc2 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
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);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
+ BufferStart + CurrentOffset);
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);
+ CurrentOffset += 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);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
strncpy(Symbol->Name.ShortName, RelocationName,
(size_t)llvm::COFF::NameSize);
Symbol->Value = DataOffsets[i];
@@ -574,14 +592,15 @@ void WindowsResourceCOFFWriter::writeSymbolTable() {
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);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
}
}
void WindowsResourceCOFFWriter::writeStringTable() {
// Just 4 null bytes for the string table.
- auto COFFStringTable = reinterpret_cast<void *>(Current);
- memset(COFFStringTable, 0, 4);
+ auto COFFStringTable =
+ reinterpret_cast<uint32_t *>(BufferStart + CurrentOffset);
+ *COFFStringTable = 0;
}
void WindowsResourceCOFFWriter::writeDirectoryTree() {
@@ -599,8 +618,8 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
while (!Queue.empty()) {
auto CurrentNode = Queue.front();
Queue.pop();
- auto *Table =
- reinterpret_cast<llvm::object::coff_resource_dir_table *>(Current);
+ auto *Table = reinterpret_cast<llvm::object::coff_resource_dir_table *>(
+ BufferStart + CurrentOffset);
Table->Characteristics = CurrentNode->getCharacteristics();
Table->TimeDateStamp = 0;
Table->MajorVersion = CurrentNode->getMajorVersion();
@@ -609,13 +628,13 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
auto &StringChildren = CurrentNode->getStringChildren();
Table->NumberOfNameEntries = StringChildren.size();
Table->NumberOfIDEntries = IDChildren.size();
- Current += sizeof(llvm::object::coff_resource_dir_table);
+ CurrentOffset += 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);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
+ BufferStart + CurrentOffset);
Entry->Identifier.NameOffset =
StringTableOffsets[Child.second->getStringIndex()];
if (Child.second->checkIsDataNode()) {
@@ -630,12 +649,12 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
sizeof(llvm::object::coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- Current += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += 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);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
+ BufferStart + CurrentOffset);
Entry->Identifier.ID = Child.first;
if (Child.second->checkIsDataNode()) {
Entry->Offset.DataEntryOffset = NextLevelOffset;
@@ -649,7 +668,7 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
sizeof(llvm::object::coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- Current += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
}
}
@@ -657,14 +676,14 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
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);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_data_entry *>(
+ BufferStart + CurrentOffset);
RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
Entry->DataRVA = 0; // Set to zero because it is a relocation.
Entry->DataSize = Data[DataNodes->getDataIndex()].size();
Entry->Codepage = 0;
Entry->Reserved = 0;
- Current += sizeof(llvm::object::coff_resource_data_entry);
+ CurrentOffset += sizeof(llvm::object::coff_resource_data_entry);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry);
}
}
@@ -673,16 +692,17 @@ 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);
+ auto *LengthField =
+ reinterpret_cast<uint16_t *>(BufferStart + CurrentOffset);
uint16_t Length = String.size();
*LengthField = Length;
- Current += sizeof(uint16_t);
- auto *Start = reinterpret_cast<UTF16 *>(Current);
+ CurrentOffset += sizeof(uint16_t);
+ auto *Start = reinterpret_cast<UTF16 *>(BufferStart + CurrentOffset);
std::copy(String.begin(), String.end(), Start);
- Current += Length * sizeof(UTF16);
+ CurrentOffset += Length * sizeof(UTF16);
TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);
}
- Current +=
+ CurrentOffset +=
alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize;
}
@@ -693,7 +713,8 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
// .rsrc section.
uint32_t NextSymbolIndex = 5;
for (unsigned i = 0; i < Data.size(); i++) {
- auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(Current);
+ auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(
+ BufferStart + CurrentOffset);
Reloc->VirtualAddress = RelocationAddresses[i];
Reloc->SymbolTableIndex = NextSymbolIndex++;
switch (MachineType) {
@@ -709,7 +730,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
default:
Reloc->Type = 0;
}
- Current += sizeof(llvm::object::coff_relocation);
+ CurrentOffset += sizeof(llvm::object::coff_relocation);
}
}
OpenPOWER on IntegriCloud