diff --git a/include/llvm/BinaryFormat/COFF.h b/include/llvm/BinaryFormat/COFF.h index b395db6eaa8..138e44bfec2 100644 --- a/include/llvm/BinaryFormat/COFF.h +++ b/include/llvm/BinaryFormat/COFF.h @@ -46,12 +46,6 @@ static const char ClGlObjMagic[] = { '\xac', '\x9b', '\xd6', '\xb6', '\x22', '\x26', '\x53', '\xc2', }; -// The signature bytes that start a .res file. -static const char WinResMagic[] = { - '\x00', '\x00', '\x00', '\x00', '\x20', '\x00', '\x00', '\x00', - '\xff', '\xff', '\x00', '\x00', '\xff', '\xff', '\x00', '\x00', -}; - // Sizes in bytes of various things in the COFF format. enum { Header16Size = 20, diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h index 3d32409fd4a..1ef00e2909f 100644 --- a/include/llvm/Object/WindowsResource.h +++ b/include/llvm/Object/WindowsResource.h @@ -43,47 +43,12 @@ #include namespace llvm { + namespace object { class WindowsResource; -const size_t WIN_RES_MAGIC_SIZE = 16; -const size_t WIN_RES_NULL_ENTRY_SIZE = 16; -const uint32_t WIN_RES_HEADER_ALIGNMENT = 4; -const uint32_t WIN_RES_DATA_ALIGNMENT = 4; -const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030; - -struct WinResHeaderPrefix { - support::ulittle32_t DataSize; - support::ulittle32_t HeaderSize; -}; - -// Type and Name may each either be an integer ID or a string. This struct is -// only used in the case where they are both IDs. -struct WinResIDs { - uint16_t TypeFlag; - support::ulittle16_t TypeID; - uint16_t NameFlag; - support::ulittle16_t NameID; - - void setType(uint16_t ID) { - TypeFlag = 0xffff; - TypeID = ID; - } - - void setName(uint16_t ID) { - NameFlag = 0xffff; - NameID = ID; - } -}; - -struct WinResHeaderSuffix { - support::ulittle32_t DataVersion; - support::ulittle16_t MemoryFlags; - support::ulittle16_t Language; - support::ulittle32_t Version; - support::ulittle32_t Characteristics; -}; +enum class Machine { UNKNOWN, ARM, X64, X86 }; class ResourceEntryRef { public: @@ -108,6 +73,14 @@ private: Error loadNext(); + struct HeaderSuffix { + support::ulittle32_t DataVersion; + support::ulittle16_t MemoryFlags; + support::ulittle16_t Language; + support::ulittle32_t Version; + support::ulittle32_t Characteristics; + }; + BinaryStreamReader Reader; bool IsStringType; ArrayRef Type; @@ -115,7 +88,7 @@ private: bool IsStringName; ArrayRef Name; uint16_t NameID; - const WinResHeaderSuffix *Suffix = nullptr; + const HeaderSuffix *Suffix = nullptr; ArrayRef Data; const WindowsResource *OwningRes = nullptr; }; diff --git a/lib/BinaryFormat/Magic.cpp b/lib/BinaryFormat/Magic.cpp index f24f22c88a8..ca4d93f99d9 100644 --- a/lib/BinaryFormat/Magic.cpp +++ b/lib/BinaryFormat/Magic.cpp @@ -51,8 +51,7 @@ file_magic llvm::identify_magic(StringRef Magic) { return file_magic::coff_import_library; } // Windows resource file - if (Magic.size() >= sizeof(COFF::WinResMagic) && - memcmp(Magic.data(), COFF::WinResMagic, sizeof(COFF::WinResMagic)) == 0) + if (startswith(Magic, "\0\0\0\0\x20\0\0\0\xFF")) return file_magic::windows_resource; // 0x0000 = COFF unknown machine type if (Magic[1] == 0) diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp index ff9b9ca35eb..35d5dd4ac47 100644 --- a/lib/Object/WindowsResource.cpp +++ b/lib/Object/WindowsResource.cpp @@ -36,19 +36,23 @@ const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t); // 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; + uint32_t WindowsResourceParser::TreeNode::StringCount = 0; uint32_t WindowsResourceParser::TreeNode::DataCount = 0; WindowsResource::WindowsResource(MemoryBufferRef Source) : Binary(Binary::ID_WinRes, Source) { - size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE; + size_t LeadingSize = ResourceMagicSize + NullEntrySize; BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize), support::little); } Expected> WindowsResource::createWindowsResource(MemoryBufferRef Source) { - if (Source.getBufferSize() < WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE) + if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize) return make_error( "File too small to be a resource file", object_error::invalid_file_type); @@ -101,10 +105,12 @@ static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID, } Error ResourceEntryRef::loadNext() { - const WinResHeaderPrefix *Prefix; - RETURN_IF_ERROR(Reader.readObject(Prefix)); + uint32_t DataSize; + RETURN_IF_ERROR(Reader.readInteger(DataSize)); + uint32_t HeaderSize; + RETURN_IF_ERROR(Reader.readInteger(HeaderSize)); - if (Prefix->HeaderSize < MIN_HEADER_SIZE) + if (HeaderSize < MIN_HEADER_SIZE) return make_error("Header size is too small.", object_error::parse_failed); @@ -112,13 +118,13 @@ Error ResourceEntryRef::loadNext() { RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName)); - RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_HEADER_ALIGNMENT)); + RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t))); RETURN_IF_ERROR(Reader.readObject(Suffix)); - RETURN_IF_ERROR(Reader.readArray(Data, Prefix->DataSize)); + RETURN_IF_ERROR(Reader.readArray(Data, DataSize)); - RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_DATA_ALIGNMENT)); + RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t))); return Error::success(); } @@ -319,6 +325,7 @@ private: void writeDirectoryTree(); void writeDirectoryStringTable(); void writeFirstSectionRelocations(); + std::unique_ptr OutputBuffer; char *BufferStart; uint64_t CurrentOffset = 0; @@ -462,6 +469,8 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() { SectionOneHeader->PointerToLinenumbers = 0; SectionOneHeader->NumberOfRelocations = Data.size(); SectionOneHeader->NumberOfLinenumbers = 0; + SectionOneHeader->Characteristics = COFF::IMAGE_SCN_ALIGN_1BYTES; + SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; SectionOneHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ; } diff --git a/unittests/BinaryFormat/TestFileMagic.cpp b/unittests/BinaryFormat/TestFileMagic.cpp index 68b3ade0095..fc2c1eef9fb 100644 --- a/unittests/BinaryFormat/TestFileMagic.cpp +++ b/unittests/BinaryFormat/TestFileMagic.cpp @@ -76,8 +76,7 @@ const char macho_dsym_companion[] = "\xfe\xed\xfa\xce........\x00\x00\x00\x0a............"; const char macho_kext_bundle[] = "\xfe\xed\xfa\xce........\x00\x00\x00\x0b............"; -const char windows_resource[] = - "\x00\x00\x00\x00\x020\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00"; +const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; const char macho_dynamically_linked_shared_lib_stub[] = "\xfe\xed\xfa\xce........\x00\x00\x00\x09............";