1 //===-- WindowsResource.h ---------------------------------------*- C++-*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 // 10 // This file declares the .res file class. .res files are intermediate 11 // products of the typical resource-compilation process on Windows. This 12 // process is as follows: 13 // 14 // .rc file(s) ---(rc.exe)---> .res file(s) ---(cvtres.exe)---> COFF file 15 // 16 // .rc files are human-readable scripts that list all resources a program uses. 17 // 18 // They are compiled into .res files, which are a list of the resources in 19 // binary form. 20 // 21 // Finally the data stored in the .res is compiled into a COFF file, where it 22 // is organized in a directory tree structure for optimized access by the 23 // program during runtime. 24 // 25 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648007(v=vs.85).aspx 26 // 27 //===---------------------------------------------------------------------===// 28 29 #ifndef LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H 30 #define LLVM_INCLUDE_LLVM_OBJECT_RESFILE_H 31 32 #include "llvm/ADT/ArrayRef.h" 33 #include "llvm/BinaryFormat/COFF.h" 34 #include "llvm/Object/Binary.h" 35 #include "llvm/Object/Error.h" 36 #include "llvm/Support/BinaryByteStream.h" 37 #include "llvm/Support/BinaryStreamReader.h" 38 #include "llvm/Support/ConvertUTF.h" 39 #include "llvm/Support/Endian.h" 40 #include "llvm/Support/Error.h" 41 #include "llvm/Support/ScopedPrinter.h" 42 43 #include <map> 44 45 namespace llvm { 46 namespace object { 47 48 class WindowsResource; 49 50 const size_t WIN_RES_MAGIC_SIZE = 16; 51 const size_t WIN_RES_NULL_ENTRY_SIZE = 16; 52 const uint32_t WIN_RES_HEADER_ALIGNMENT = 4; 53 const uint32_t WIN_RES_DATA_ALIGNMENT = 4; 54 const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030; 55 56 struct WinResHeaderPrefix { 57 support::ulittle32_t DataSize; 58 support::ulittle32_t HeaderSize; 59 }; 60 61 // Type and Name may each either be an integer ID or a string. This struct is 62 // only used in the case where they are both IDs. 63 struct WinResIDs { 64 uint16_t TypeFlag; 65 support::ulittle16_t TypeID; 66 uint16_t NameFlag; 67 support::ulittle16_t NameID; 68 69 void setType(uint16_t ID) { 70 TypeFlag = 0xffff; 71 TypeID = ID; 72 } 73 74 void setName(uint16_t ID) { 75 NameFlag = 0xffff; 76 NameID = ID; 77 } 78 }; 79 80 struct WinResHeaderSuffix { 81 support::ulittle32_t DataVersion; 82 support::ulittle16_t MemoryFlags; 83 support::ulittle16_t Language; 84 support::ulittle32_t Version; 85 support::ulittle32_t Characteristics; 86 }; 87 88 class EmptyResError : public GenericBinaryError { 89 public: 90 EmptyResError(Twine Msg, object_error ECOverride) 91 : GenericBinaryError(Msg, ECOverride) {} 92 }; 93 94 class ResourceEntryRef { 95 public: 96 Error moveNext(bool &End); 97 bool checkTypeString() const { return IsStringType; } 98 ArrayRef<UTF16> getTypeString() const { return Type; } 99 uint16_t getTypeID() const { return TypeID; } 100 bool checkNameString() const { return IsStringName; } 101 ArrayRef<UTF16> getNameString() const { return Name; } 102 uint16_t getNameID() const { return NameID; } 103 uint16_t getDataVersion() const { return Suffix->DataVersion; } 104 uint16_t getLanguage() const { return Suffix->Language; } 105 uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; } 106 uint16_t getMajorVersion() const { return Suffix->Version >> 16; } 107 uint16_t getMinorVersion() const { return Suffix->Version; } 108 uint32_t getCharacteristics() const { return Suffix->Characteristics; } 109 ArrayRef<uint8_t> getData() const { return Data; } 110 111 private: 112 friend class WindowsResource; 113 114 ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner); 115 Error loadNext(); 116 117 static Expected<ResourceEntryRef> create(BinaryStreamRef Ref, 118 const WindowsResource *Owner); 119 120 BinaryStreamReader Reader; 121 bool IsStringType; 122 ArrayRef<UTF16> Type; 123 uint16_t TypeID; 124 bool IsStringName; 125 ArrayRef<UTF16> Name; 126 uint16_t NameID; 127 const WinResHeaderSuffix *Suffix = nullptr; 128 ArrayRef<uint8_t> Data; 129 }; 130 131 class WindowsResource : public Binary { 132 public: 133 Expected<ResourceEntryRef> getHeadEntry(); 134 135 static bool classof(const Binary *V) { return V->isWinRes(); } 136 137 static Expected<std::unique_ptr<WindowsResource>> 138 createWindowsResource(MemoryBufferRef Source); 139 140 private: 141 friend class ResourceEntryRef; 142 143 WindowsResource(MemoryBufferRef Source); 144 145 BinaryByteStream BBS; 146 }; 147 148 class WindowsResourceParser { 149 public: 150 class TreeNode; 151 WindowsResourceParser(); 152 Error parse(WindowsResource *WR); 153 void printTree(raw_ostream &OS) const; 154 const TreeNode &getTree() const { return Root; } 155 const ArrayRef<std::vector<uint8_t>> getData() const { return Data; } 156 const ArrayRef<std::vector<UTF16>> getStringTable() const { 157 return StringTable; 158 } 159 160 class TreeNode { 161 public: 162 template <typename T> 163 using Children = std::map<T, std::unique_ptr<TreeNode>>; 164 165 void print(ScopedPrinter &Writer, StringRef Name) const; 166 uint32_t getTreeSize() const; 167 uint32_t getStringIndex() const { return StringIndex; } 168 uint32_t getDataIndex() const { return DataIndex; } 169 uint16_t getMajorVersion() const { return MajorVersion; } 170 uint16_t getMinorVersion() const { return MinorVersion; } 171 uint32_t getCharacteristics() const { return Characteristics; } 172 bool checkIsDataNode() const { return IsDataNode; } 173 const Children<uint32_t> &getIDChildren() const { return IDChildren; } 174 const Children<std::string> &getStringChildren() const { 175 return StringChildren; 176 } 177 178 private: 179 friend class WindowsResourceParser; 180 181 static uint32_t StringCount; 182 static uint32_t DataCount; 183 184 static std::unique_ptr<TreeNode> createStringNode(); 185 static std::unique_ptr<TreeNode> createIDNode(); 186 static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion, 187 uint16_t MinorVersion, 188 uint32_t Characteristics); 189 190 explicit TreeNode(bool IsStringNode); 191 TreeNode(uint16_t MajorVersion, uint16_t MinorVersion, 192 uint32_t Characteristics); 193 194 void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString, 195 bool &IsNewNameString); 196 TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString); 197 TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString); 198 TreeNode &addLanguageNode(const ResourceEntryRef &Entry); 199 TreeNode &addChild(uint32_t ID, bool IsDataNode = false, 200 uint16_t MajorVersion = 0, uint16_t MinorVersion = 0, 201 uint32_t Characteristics = 0); 202 TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString); 203 204 bool IsDataNode = false; 205 uint32_t StringIndex; 206 uint32_t DataIndex; 207 Children<uint32_t> IDChildren; 208 Children<std::string> StringChildren; 209 uint16_t MajorVersion = 0; 210 uint16_t MinorVersion = 0; 211 uint32_t Characteristics = 0; 212 }; 213 214 private: 215 TreeNode Root; 216 std::vector<std::vector<uint8_t>> Data; 217 std::vector<std::vector<UTF16>> StringTable; 218 }; 219 220 Expected<std::unique_ptr<MemoryBuffer>> 221 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType, 222 const WindowsResourceParser &Parser); 223 224 } // namespace object 225 } // namespace llvm 226 227 #endif 228