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 class ResourceEntryRef {
     51 public:
     52   Error moveNext(bool &End);
     53   bool checkTypeString() const { return IsStringType; }
     54   ArrayRef<UTF16> getTypeString() const { return Type; }
     55   uint16_t getTypeID() const { return TypeID; }
     56   bool checkNameString() const { return IsStringName; }
     57   ArrayRef<UTF16> getNameString() const { return Name; }
     58   uint16_t getNameID() const { return NameID; }
     59   uint16_t getLanguage() const { return Suffix->Language; }
     60   uint16_t getMajorVersion() const { return Suffix->Version >> 16; }
     61   uint16_t getMinorVersion() const { return Suffix->Version; }
     62   uint32_t getCharacteristics() const { return Suffix->Characteristics; }
     63   ArrayRef<uint8_t> getData() const { return Data; }
     64 
     65 private:
     66   friend class WindowsResource;
     67 
     68   ResourceEntryRef(BinaryStreamRef Ref, const WindowsResource *Owner,
     69                    Error &Err);
     70 
     71   Error loadNext();
     72 
     73   struct HeaderSuffix {
     74     support::ulittle32_t DataVersion;
     75     support::ulittle16_t MemoryFlags;
     76     support::ulittle16_t Language;
     77     support::ulittle32_t Version;
     78     support::ulittle32_t Characteristics;
     79   };
     80 
     81   BinaryStreamReader Reader;
     82   bool IsStringType;
     83   ArrayRef<UTF16> Type;
     84   uint16_t TypeID;
     85   bool IsStringName;
     86   ArrayRef<UTF16> Name;
     87   uint16_t NameID;
     88   const HeaderSuffix *Suffix = nullptr;
     89   ArrayRef<uint8_t> Data;
     90   const WindowsResource *OwningRes = nullptr;
     91 };
     92 
     93 class WindowsResource : public Binary {
     94 public:
     95   Expected<ResourceEntryRef> getHeadEntry();
     96 
     97   static bool classof(const Binary *V) { return V->isWinRes(); }
     98 
     99   static Expected<std::unique_ptr<WindowsResource>>
    100   createWindowsResource(MemoryBufferRef Source);
    101 
    102 private:
    103   friend class ResourceEntryRef;
    104 
    105   WindowsResource(MemoryBufferRef Source);
    106 
    107   BinaryByteStream BBS;
    108 };
    109 
    110 class WindowsResourceParser {
    111 public:
    112   class TreeNode;
    113   WindowsResourceParser();
    114   Error parse(WindowsResource *WR);
    115   void printTree(raw_ostream &OS) const;
    116   const TreeNode &getTree() const { return Root; }
    117   const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
    118   const ArrayRef<std::vector<UTF16>> getStringTable() const {
    119     return StringTable;
    120   }
    121 
    122   class TreeNode {
    123   public:
    124     template <typename T>
    125     using Children = std::map<T, std::unique_ptr<TreeNode>>;
    126 
    127     void print(ScopedPrinter &Writer, StringRef Name) const;
    128     uint32_t getTreeSize() const;
    129     uint32_t getStringIndex() const { return StringIndex; }
    130     uint32_t getDataIndex() const { return DataIndex; }
    131     uint16_t getMajorVersion() const { return MajorVersion; }
    132     uint16_t getMinorVersion() const { return MinorVersion; }
    133     uint32_t getCharacteristics() const { return Characteristics; }
    134     bool checkIsDataNode() const { return IsDataNode; }
    135     const Children<uint32_t> &getIDChildren() const { return IDChildren; }
    136     const Children<std::string> &getStringChildren() const {
    137       return StringChildren;
    138     }
    139 
    140   private:
    141     friend class WindowsResourceParser;
    142 
    143     static uint32_t StringCount;
    144     static uint32_t DataCount;
    145 
    146     static std::unique_ptr<TreeNode> createStringNode();
    147     static std::unique_ptr<TreeNode> createIDNode();
    148     static std::unique_ptr<TreeNode> createDataNode(uint16_t MajorVersion,
    149                                                     uint16_t MinorVersion,
    150                                                     uint32_t Characteristics);
    151 
    152     explicit TreeNode(bool IsStringNode);
    153     TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
    154              uint32_t Characteristics);
    155 
    156     void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString,
    157                   bool &IsNewNameString);
    158     TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
    159     TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
    160     TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
    161     TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
    162                        uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
    163                        uint32_t Characteristics = 0);
    164     TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
    165 
    166     bool IsDataNode = false;
    167     uint32_t StringIndex;
    168     uint32_t DataIndex;
    169     Children<uint32_t> IDChildren;
    170     Children<std::string> StringChildren;
    171     uint16_t MajorVersion = 0;
    172     uint16_t MinorVersion = 0;
    173     uint32_t Characteristics = 0;
    174   };
    175 
    176 private:
    177   TreeNode Root;
    178   std::vector<std::vector<uint8_t>> Data;
    179   std::vector<std::vector<UTF16>> StringTable;
    180 };
    181 
    182 Error writeWindowsResourceCOFF(std::unique_ptr<MemoryBuffer> &OutputBuffer,
    183                                llvm::COFF::MachineTypes MachineType,
    184                                const WindowsResourceParser &Parser);
    185 
    186 } // namespace object
    187 } // namespace llvm
    188 
    189 #endif
    190