Home | History | Annotate | Download | only in Object
      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