diff --git a/include/llvm/BinaryFormat/COFF.h b/include/llvm/BinaryFormat/COFF.h index 138e44bfec2..b395db6eaa8 100644 --- a/include/llvm/BinaryFormat/COFF.h +++ b/include/llvm/BinaryFormat/COFF.h @@ -46,6 +46,12 @@ 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 1ef00e2909f..3d32409fd4a 100644 --- a/include/llvm/Object/WindowsResource.h +++ b/include/llvm/Object/WindowsResource.h @@ -43,12 +43,47 @@ #include namespace llvm { - namespace object { class WindowsResource; -enum class Machine { UNKNOWN, ARM, X64, X86 }; +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; +}; class ResourceEntryRef { public: @@ -73,14 +108,6 @@ 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; @@ -88,7 +115,7 @@ private: bool IsStringName; ArrayRef Name; uint16_t NameID; - const HeaderSuffix *Suffix = nullptr; + const WinResHeaderSuffix *Suffix = nullptr; ArrayRef Data; const WindowsResource *OwningRes = nullptr; }; diff --git a/lib/BinaryFormat/Magic.cpp b/lib/BinaryFormat/Magic.cpp index 5d0a71fc780..b19a07a9066 100644 --- a/lib/BinaryFormat/Magic.cpp +++ b/lib/BinaryFormat/Magic.cpp @@ -51,7 +51,8 @@ file_magic llvm::identify_magic(StringRef Magic) { return file_magic::coff_import_library; } // Windows resource file - if (startswith(Magic, "\0\0\0\0\x20\0\0\0\xFF")) + if (Magic.size() >= sizeof(COFF::WinResMagic) && + memcmp(Magic.data(), COFF::WinResMagic, sizeof(COFF::WinResMagic)) == 0) 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 be767a154f9..246eee5ddb3 100644 --- a/lib/Object/WindowsResource.cpp +++ b/lib/Object/WindowsResource.cpp @@ -36,23 +36,19 @@ 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 = ResourceMagicSize + NullEntrySize; + size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE; BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize), support::little); } Expected> WindowsResource::createWindowsResource(MemoryBufferRef Source) { - if (Source.getBufferSize() < ResourceMagicSize + NullEntrySize) + if (Source.getBufferSize() < WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE) return make_error( "File too small to be a resource file", object_error::invalid_file_type); @@ -105,12 +101,10 @@ static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID, } Error ResourceEntryRef::loadNext() { - uint32_t DataSize; - RETURN_IF_ERROR(Reader.readInteger(DataSize)); - uint32_t HeaderSize; - RETURN_IF_ERROR(Reader.readInteger(HeaderSize)); + const WinResHeaderPrefix *Prefix; + RETURN_IF_ERROR(Reader.readObject(Prefix)); - if (HeaderSize < MIN_HEADER_SIZE) + if (Prefix->HeaderSize < MIN_HEADER_SIZE) return make_error("Header size is too small.", object_error::parse_failed); @@ -118,13 +112,13 @@ Error ResourceEntryRef::loadNext() { RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName)); - RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t))); + RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_HEADER_ALIGNMENT)); RETURN_IF_ERROR(Reader.readObject(Suffix)); - RETURN_IF_ERROR(Reader.readArray(Data, DataSize)); + RETURN_IF_ERROR(Reader.readArray(Data, Prefix->DataSize)); - RETURN_IF_ERROR(Reader.padToAlignment(sizeof(uint32_t))); + RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_DATA_ALIGNMENT)); return Error::success(); } @@ -350,6 +344,7 @@ WindowsResourceCOFFWriter::WindowsResourceCOFFWriter( : MachineType(MachineType), Resources(Parser.getTree()), Data(Parser.getData()), StringTable(Parser.getStringTable()) { performFileLayout(); + OutputBuffer = MemoryBuffer::getNewMemBuffer(FileSize); } @@ -467,8 +462,6 @@ 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/tools/llvm-cvtres/llvm-cvtres.cpp b/tools/llvm-cvtres/llvm-cvtres.cpp index 3430b0ab3ad..36c15925e84 100644 --- a/tools/llvm-cvtres/llvm-cvtres.cpp +++ b/tools/llvm-cvtres/llvm-cvtres.cpp @@ -207,6 +207,7 @@ int main(int argc_, const char *argv_[]) { std::copy(OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(), FileBuffer->getBufferStart()); error(FileBuffer->commit()); + if (Verbose) { Expected> BinaryOrErr = createBinary(OutputFile); if (!BinaryOrErr) diff --git a/unittests/BinaryFormat/TestFileMagic.cpp b/unittests/BinaryFormat/TestFileMagic.cpp index fc2c1eef9fb..68b3ade0095 100644 --- a/unittests/BinaryFormat/TestFileMagic.cpp +++ b/unittests/BinaryFormat/TestFileMagic.cpp @@ -76,7 +76,8 @@ 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"; +const char windows_resource[] = + "\x00\x00\x00\x00\x020\x00\x00\x00\xff\xff\x00\x00\xff\xff\x00\x00"; const char macho_dynamically_linked_shared_lib_stub[] = "\xfe\xed\xfa\xce........\x00\x00\x00\x09............";