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   const WindowsResource *OwningRes = nullptr;
    130 };
    131 
    132 class WindowsResource : public Binary {
    133 public:
    134   Expected<ResourceEntryRef> getHeadEntry();
    135 
    136   static bool classof(const Binary *V) { return V->isWinRes(); }
    137 
    138   static Expected<std::unique_ptr<WindowsResource>>
    139   createWindowsResource(MemoryBufferRef Source);
    140 
    141 private:
    142   friend class ResourceEntryRef;
    143 
    144   WindowsResource(MemoryBufferRef Source);
    145 
    146   BinaryByteStream BBS;
    147 };
    148 
    149 class WindowsResourceParser {
    150 public:
    151   class TreeNode;
    152   WindowsResourceParser();
    153   Error parse(WindowsResource *WR);
    154   void printTree(raw_ostream &OS) const;
    155   const TreeNode &getTree() const { return Root; }
    156   const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
    157   const ArrayRef<std::vector<UTF16>> getStringTable() const {
    158     return StringTable;
    159   }
    160 
    161   class TreeNode {
    162   public:
    163     template <typename T>
    164     using Children = std::map<T, std::unique_ptr<TreeNode>>;
    165 
    166     void print(ScopedPrinter &Writer, StringRef Name) const;
    167     uint32_t getTreeSize() const;
    168     uint32_t getStringIndex() const { return StringIndex; }
    169     uint32_t getDataIndex() const { return DataIndex; }
    170     uint16_t getMajorVersion() const { return MajorVersion; }
    171     uint16_t getMinorVersion() const { return MinorVersion; }
    172     uint32_t getCharacteristics() const { return Characteristics; }
    173     bool checkIsDataNode() const { return IsDataNode; }
    174     const Children<uint32_t> &getIDChildren() const { return IDChildren; }
    175     const Children<std::string> &getStringChildren() const {
    176       return StringChildren;
    177     }
    178 
    179   private:
    180     friend class WindowsResourceParser;
    181 
    182     static uint32_t StringCount;
    183     static uint32_t DataCount;
    184 
    185     static std::unique_ptr<TreeNode> createStringNode();
    186     static std::unique_ptr<TreeNode> createIDNode();
    187     static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
    188                                                     uint16_t MinorVersion,
    189                                                     uint32_t Characteristics);
    190 
    191     explicit TreeNode(bool IsStringNode);
    192     TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
    193              uint32_t Characteristics);
    194 
    195     void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString,
    196                   bool &IsNewNameString);
    197     TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
    198     TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
    199     TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
    200     TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
    201                        uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
    202                        uint32_t Characteristics = 0);
    203     TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
    204 
    205     bool IsDataNode = false;
    206     uint32_t StringIndex;
    207     uint32_t DataIndex;
    208     Children<uint32_t> IDChildren;
    209     Children<std::string> StringChildren;
    210     uint16_t MajorVersion = 0;
    211     uint16_t MinorVersion = 0;
    212     uint32_t Characteristics = 0;
    213   };
    214 
    215 private:
    216   TreeNode Root;
    217   std::vector<std::vector<uint8_t>> Data;
    218   std::vector<std::vector<UTF16>> StringTable;
    219 };
    220 
    221 Expected<std::unique_ptr<MemoryBuffer>>
    222 writeWindowsResourceCOFF(llvm::COFF::MachineTypes MachineType,
    223                          const WindowsResourceParser &Parser);
    224 
    225 } // namespace object
    226 } // namespace llvm
    227 
    228 #endif
    229