Revert "Revert "Fix alignment bug in COFF emission.""

This revert was done so that my other patch to add test framework could
land separately.  Now the revert can be reverted and this patch can
reland.

This reverts commit 18b3c75b2b0d32601fb60a06b9672c33d6f0dff9.

llvm-svn: 305259
This commit is contained in:
Eric Beckmann 2017-06-13 00:19:43 +00:00
parent 1301759792
commit 382eaabb1f
1 changed files with 67 additions and 46 deletions

View File

@ -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);
}
}