Line data Source code
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 0 : TypeFlag = 0xffff;
71 : TypeID = ID;
72 : }
73 :
74 : void setName(uint16_t ID) {
75 0 : 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 0 : : GenericBinaryError(Msg, ECOverride) {}
92 : };
93 :
94 38 : class ResourceEntryRef {
95 : public:
96 : Error moveNext(bool &End);
97 0 : bool checkTypeString() const { return IsStringType; }
98 0 : ArrayRef<UTF16> getTypeString() const { return Type; }
99 0 : uint16_t getTypeID() const { return TypeID; }
100 0 : bool checkNameString() const { return IsStringName; }
101 0 : ArrayRef<UTF16> getNameString() const { return Name; }
102 0 : uint16_t getNameID() const { return NameID; }
103 0 : uint16_t getDataVersion() const { return Suffix->DataVersion; }
104 0 : uint16_t getLanguage() const { return Suffix->Language; }
105 0 : uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
106 271 : uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
107 0 : uint16_t getMinorVersion() const { return Suffix->Version; }
108 0 : uint32_t getCharacteristics() const { return Suffix->Characteristics; }
109 0 : 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 15 : 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 12 : 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 0 : 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 0 : uint32_t getStringIndex() const { return StringIndex; }
168 0 : uint32_t getDataIndex() const { return DataIndex; }
169 0 : uint16_t getMajorVersion() const { return MajorVersion; }
170 0 : uint16_t getMinorVersion() const { return MinorVersion; }
171 0 : uint32_t getCharacteristics() const { return Characteristics; }
172 0 : 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
|