File indexing completed on 2026-05-10 08:44:20
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef LLVM_OBJECT_WINDOWSRESOURCE_H
0029 #define LLVM_OBJECT_WINDOWSRESOURCE_H
0030
0031 #include "llvm/ADT/ArrayRef.h"
0032 #include "llvm/BinaryFormat/COFF.h"
0033 #include "llvm/Object/Binary.h"
0034 #include "llvm/Object/Error.h"
0035 #include "llvm/Support/BinaryByteStream.h"
0036 #include "llvm/Support/BinaryStreamReader.h"
0037 #include "llvm/Support/ConvertUTF.h"
0038 #include "llvm/Support/Endian.h"
0039 #include "llvm/Support/Error.h"
0040
0041 #include <map>
0042
0043 namespace llvm {
0044
0045 class raw_ostream;
0046 class ScopedPrinter;
0047
0048 namespace object {
0049
0050 class WindowsResource;
0051 class ResourceSectionRef;
0052 struct coff_resource_dir_table;
0053
0054 const size_t WIN_RES_MAGIC_SIZE = 16;
0055 const size_t WIN_RES_NULL_ENTRY_SIZE = 16;
0056 const uint32_t WIN_RES_HEADER_ALIGNMENT = 4;
0057 const uint32_t WIN_RES_DATA_ALIGNMENT = 4;
0058 const uint16_t WIN_RES_PURE_MOVEABLE = 0x0030;
0059
0060 struct WinResHeaderPrefix {
0061 support::ulittle32_t DataSize;
0062 support::ulittle32_t HeaderSize;
0063 };
0064
0065
0066
0067 struct WinResIDs {
0068 uint16_t TypeFlag;
0069 support::ulittle16_t TypeID;
0070 uint16_t NameFlag;
0071 support::ulittle16_t NameID;
0072
0073 void setType(uint16_t ID) {
0074 TypeFlag = 0xffff;
0075 TypeID = ID;
0076 }
0077
0078 void setName(uint16_t ID) {
0079 NameFlag = 0xffff;
0080 NameID = ID;
0081 }
0082 };
0083
0084 struct WinResHeaderSuffix {
0085 support::ulittle32_t DataVersion;
0086 support::ulittle16_t MemoryFlags;
0087 support::ulittle16_t Language;
0088 support::ulittle32_t Version;
0089 support::ulittle32_t Characteristics;
0090 };
0091
0092 class EmptyResError : public GenericBinaryError {
0093 public:
0094 EmptyResError(Twine Msg, object_error ECOverride)
0095 : GenericBinaryError(Msg, ECOverride) {}
0096 };
0097
0098 class ResourceEntryRef {
0099 public:
0100 Error moveNext(bool &End);
0101 bool checkTypeString() const { return IsStringType; }
0102 ArrayRef<UTF16> getTypeString() const { return Type; }
0103 uint16_t getTypeID() const { return TypeID; }
0104 bool checkNameString() const { return IsStringName; }
0105 ArrayRef<UTF16> getNameString() const { return Name; }
0106 uint16_t getNameID() const { return NameID; }
0107 uint16_t getDataVersion() const { return Suffix->DataVersion; }
0108 uint16_t getLanguage() const { return Suffix->Language; }
0109 uint16_t getMemoryFlags() const { return Suffix->MemoryFlags; }
0110 uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
0111 uint16_t getMinorVersion() const { return Suffix->Version; }
0112 uint32_t getCharacteristics() const { return Suffix->Characteristics; }
0113 ArrayRef<uint8_t> getData() const { return Data; }
0114
0115 private:
0116 friend class WindowsResource;
0117
0118 ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner);
0119 Error loadNext();
0120
0121 static Expected<ResourceEntryRef> create(BinaryStreamRef Ref,
0122 const WindowsResource *Owner);
0123
0124 BinaryStreamReader Reader;
0125 const WindowsResource *Owner;
0126 bool IsStringType;
0127 ArrayRef<UTF16> Type;
0128 uint16_t TypeID;
0129 bool IsStringName;
0130 ArrayRef<UTF16> Name;
0131 uint16_t NameID;
0132 const WinResHeaderSuffix *Suffix = nullptr;
0133 ArrayRef<uint8_t> Data;
0134 };
0135
0136 class WindowsResource : public Binary {
0137 public:
0138 Expected<ResourceEntryRef> getHeadEntry();
0139
0140 static bool classof(const Binary *V) { return V->isWinRes(); }
0141
0142 static Expected<std::unique_ptr<WindowsResource>>
0143 createWindowsResource(MemoryBufferRef Source);
0144
0145 private:
0146 friend class ResourceEntryRef;
0147
0148 WindowsResource(MemoryBufferRef Source);
0149
0150 BinaryByteStream BBS;
0151 };
0152
0153 class WindowsResourceParser {
0154 public:
0155 class TreeNode;
0156 WindowsResourceParser(bool MinGW = false);
0157 Error parse(WindowsResource *WR, std::vector<std::string> &Duplicates);
0158 Error parse(ResourceSectionRef &RSR, StringRef Filename,
0159 std::vector<std::string> &Duplicates);
0160 void cleanUpManifests(std::vector<std::string> &Duplicates);
0161 void printTree(raw_ostream &OS) const;
0162 const TreeNode &getTree() const { return Root; }
0163 ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
0164 ArrayRef<std::vector<UTF16>> getStringTable() const { return StringTable; }
0165
0166 class TreeNode {
0167 public:
0168 template <typename T>
0169 using Children = std::map<T, std::unique_ptr<TreeNode>>;
0170
0171 void print(ScopedPrinter &Writer, StringRef Name) const;
0172 uint32_t getTreeSize() const;
0173 uint32_t getStringIndex() const { return StringIndex; }
0174 uint32_t getDataIndex() const { return DataIndex; }
0175 uint16_t getMajorVersion() const { return MajorVersion; }
0176 uint16_t getMinorVersion() const { return MinorVersion; }
0177 uint32_t getCharacteristics() const { return Characteristics; }
0178 bool checkIsDataNode() const { return IsDataNode; }
0179 const Children<uint32_t> &getIDChildren() const { return IDChildren; }
0180 const Children<std::string> &getStringChildren() const {
0181 return StringChildren;
0182 }
0183
0184 private:
0185 friend class WindowsResourceParser;
0186
0187
0188 static std::unique_ptr<TreeNode> createStringNode(uint32_t Index);
0189 static std::unique_ptr<TreeNode> createIDNode();
0190
0191 static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
0192 uint16_t MinorVersion,
0193 uint32_t Characteristics,
0194 uint32_t Origin,
0195 uint32_t DataIndex);
0196
0197 explicit TreeNode(uint32_t StringIndex);
0198 TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
0199 uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex);
0200
0201 bool addEntry(const ResourceEntryRef &Entry, uint32_t Origin,
0202 std::vector<std::vector<uint8_t>> &Data,
0203 std::vector<std::vector<UTF16>> &StringTable,
0204 TreeNode *&Result);
0205 TreeNode &addTypeNode(const ResourceEntryRef &Entry,
0206 std::vector<std::vector<UTF16>> &StringTable);
0207 TreeNode &addNameNode(const ResourceEntryRef &Entry,
0208 std::vector<std::vector<UTF16>> &StringTable);
0209 bool addLanguageNode(const ResourceEntryRef &Entry, uint32_t Origin,
0210 std::vector<std::vector<uint8_t>> &Data,
0211 TreeNode *&Result);
0212 bool addDataChild(uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
0213 uint32_t Characteristics, uint32_t Origin,
0214 uint32_t DataIndex, TreeNode *&Result);
0215 TreeNode &addIDChild(uint32_t ID);
0216 TreeNode &addNameChild(ArrayRef<UTF16> NameRef,
0217 std::vector<std::vector<UTF16>> &StringTable);
0218 void shiftDataIndexDown(uint32_t Index);
0219
0220 bool IsDataNode = false;
0221 uint32_t StringIndex;
0222 uint32_t DataIndex;
0223 Children<uint32_t> IDChildren;
0224 Children<std::string> StringChildren;
0225 uint16_t MajorVersion = 0;
0226 uint16_t MinorVersion = 0;
0227 uint32_t Characteristics = 0;
0228
0229
0230
0231 uint32_t Origin;
0232 };
0233
0234 struct StringOrID {
0235 bool IsString;
0236 ArrayRef<UTF16> String;
0237 uint32_t ID = ~0u;
0238
0239 StringOrID(uint32_t ID) : IsString(false), ID(ID) {}
0240 StringOrID(ArrayRef<UTF16> String) : IsString(true), String(String) {}
0241 };
0242
0243 private:
0244 Error addChildren(TreeNode &Node, ResourceSectionRef &RSR,
0245 const coff_resource_dir_table &Table, uint32_t Origin,
0246 std::vector<StringOrID> &Context,
0247 std::vector<std::string> &Duplicates);
0248 bool shouldIgnoreDuplicate(const ResourceEntryRef &Entry) const;
0249 bool shouldIgnoreDuplicate(const std::vector<StringOrID> &Context) const;
0250
0251 TreeNode Root;
0252 std::vector<std::vector<uint8_t>> Data;
0253 std::vector<std::vector<UTF16>> StringTable;
0254
0255 std::vector<std::string> InputFilenames;
0256
0257 bool MinGW;
0258 };
0259
0260 Expected<std::unique_ptr<MemoryBuffer>>
0261 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
0262 const WindowsResourceParser &Parser,
0263 uint32_t TimeDateStamp);
0264
0265 void printResourceTypeName(uint16_t TypeID, raw_ostream &OS);
0266 }
0267 }
0268
0269 #endif