Index: llvm/trunk/lib/Object/WindowsResource.cpp =================================================================== --- llvm/trunk/lib/Object/WindowsResource.cpp +++ llvm/trunk/lib/Object/WindowsResource.cpp @@ -30,6 +30,10 @@ 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 @@ void writeDirectoryStringTable(); void writeFirstSectionRelocations(); std::unique_ptr Buffer; - uint8_t *Current; + uint8_t *BufferStart; + uint64_t CurrentOffset = 0; Machine MachineType; const WindowsResourceParser::TreeNode &Resources; const ArrayRef> Data; @@ -392,6 +397,7 @@ 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 @@ SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t)); } FileSize += SectionTwoSize; + FileSize = alignTo(FileSize, SECTION_ALIGNMENT); } static std::time_t getTime() { @@ -414,7 +421,7 @@ } Error WindowsResourceCOFFWriter::write() { - Current = Buffer->getBufferStart(); + BufferStart = Buffer->getBufferStart(); writeCOFFHeader(); writeFirstSectionHeader(); @@ -433,7 +440,8 @@ void WindowsResourceCOFFWriter::writeCOFFHeader() { // Write the COFF header. - auto *Header = reinterpret_cast(Current); + auto *Header = + reinterpret_cast(BufferStart); switch (MachineType) { case Machine::ARM: Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT; @@ -458,9 +466,9 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() { // Write the first section header. - Current += sizeof(llvm::object::coff_file_header); - auto *SectionOneHeader = - reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_file_header); + auto *SectionOneHeader = reinterpret_cast( + BufferStart + CurrentOffset); strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize); SectionOneHeader->VirtualSize = 0; SectionOneHeader->VirtualAddress = 0; @@ -479,9 +487,9 @@ void WindowsResourceCOFFWriter::writeSecondSectionHeader() { // Write the second section header. - Current += sizeof(llvm::object::coff_section); - auto *SectionTwoHeader = - reinterpret_cast(Current); + CurrentOffset += sizeof(llvm::object::coff_section); + auto *SectionTwoHeader = reinterpret_cast( + BufferStart + CurrentOffset); strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize); SectionTwoHeader->VirtualSize = 0; SectionTwoHeader->VirtualAddress = 0; @@ -498,75 +506,85 @@ 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(Current); + auto *Symbol = reinterpret_cast(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(Current); + Symbol = reinterpret_cast(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(Current); + CurrentOffset += sizeof(llvm::object::coff_symbol16); + auto *Aux = reinterpret_cast( + 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(Current); + Symbol = reinterpret_cast(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(Current); + CurrentOffset += sizeof(llvm::object::coff_symbol16); + Aux = reinterpret_cast( + 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(Current); + Symbol = reinterpret_cast(BufferStart + + CurrentOffset); strncpy(Symbol->Name.ShortName, RelocationName, (size_t)llvm::COFF::NameSize); Symbol->Value = DataOffsets[i]; @@ -574,14 +592,15 @@ 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(Current); - memset(COFFStringTable, 0, 4); + auto COFFStringTable = + reinterpret_cast(BufferStart + CurrentOffset); + *COFFStringTable = 0; } void WindowsResourceCOFFWriter::writeDirectoryTree() { @@ -599,8 +618,8 @@ while (!Queue.empty()) { auto CurrentNode = Queue.front(); Queue.pop(); - auto *Table = - reinterpret_cast(Current); + auto *Table = reinterpret_cast( + BufferStart + CurrentOffset); Table->Characteristics = CurrentNode->getCharacteristics(); Table->TimeDateStamp = 0; Table->MajorVersion = CurrentNode->getMajorVersion(); @@ -609,13 +628,13 @@ 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(Current); + auto *Entry = reinterpret_cast( + BufferStart + CurrentOffset); Entry->Identifier.NameOffset = StringTableOffsets[Child.second->getStringIndex()]; if (Child.second->checkIsDataNode()) { @@ -630,12 +649,12 @@ 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(Current); + auto *Entry = reinterpret_cast( + BufferStart + CurrentOffset); Entry->Identifier.ID = Child.first; if (Child.second->checkIsDataNode()) { Entry->Offset.DataEntryOffset = NextLevelOffset; @@ -649,7 +668,7 @@ 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 @@ RelocationAddresses.resize(Data.size()); // Now write all the resource data entries. for (auto DataNodes : DataEntriesTreeOrder) { - auto *Entry = - reinterpret_cast(Current); + auto *Entry = reinterpret_cast( + 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 @@ // Now write the directory string table for .rsrc$01 uint32_t TotalStringTableSize = 0; for (auto String : StringTable) { - auto *LengthField = reinterpret_cast(Current); + auto *LengthField = + reinterpret_cast(BufferStart + CurrentOffset); uint16_t Length = String.size(); *LengthField = Length; - Current += sizeof(uint16_t); - auto *Start = reinterpret_cast(Current); + CurrentOffset += sizeof(uint16_t); + auto *Start = reinterpret_cast(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 @@ // .rsrc section. uint32_t NextSymbolIndex = 5; for (unsigned i = 0; i < Data.size(); i++) { - auto *Reloc = reinterpret_cast(Current); + auto *Reloc = reinterpret_cast( + BufferStart + CurrentOffset); Reloc->VirtualAddress = RelocationAddresses[i]; Reloc->SymbolTableIndex = NextSymbolIndex++; switch (MachineType) { @@ -709,7 +730,7 @@ default: Reloc->Type = 0; } - Current += sizeof(llvm::object::coff_relocation); + CurrentOffset += sizeof(llvm::object::coff_relocation); } }