Home | History | Annotate | Download | only in Support
      1 //===-- DataExtractor.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 #ifndef LLVM_SUPPORT_DATAEXTRACTOR_H
     11 #define LLVM_SUPPORT_DATAEXTRACTOR_H
     12 
     13 #include "llvm/ADT/StringRef.h"
     14 #include "llvm/Support/DataTypes.h"
     15 
     16 namespace llvm {
     17 class DataExtractor {
     18   StringRef Data;
     19   uint8_t IsLittleEndian;
     20   uint8_t AddressSize;
     21 public:
     22   /// Construct with a buffer that is owned by the caller.
     23   ///
     24   /// This constructor allows us to use data that is owned by the
     25   /// caller. The data must stay around as long as this object is
     26   /// valid.
     27   DataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
     28     : Data(Data), IsLittleEndian(IsLittleEndian), AddressSize(AddressSize) {}
     29 
     30   /// \brief Get the data pointed to by this extractor.
     31   StringRef getData() const { return Data; }
     32   /// \brief Get the endianness for this extractor.
     33   bool isLittleEndian() const { return IsLittleEndian; }
     34   /// \brief Get the address size for this extractor.
     35   uint8_t getAddressSize() const { return AddressSize; }
     36   /// \brief Set the address size for this extractor.
     37   void setAddressSize(uint8_t Size) { AddressSize = Size; }
     38 
     39   /// Extract a C string from \a *offset_ptr.
     40   ///
     41   /// Returns a pointer to a C String from the data at the offset
     42   /// pointed to by \a offset_ptr. A variable length NULL terminated C
     43   /// string will be extracted and the \a offset_ptr will be
     44   /// updated with the offset of the byte that follows the NULL
     45   /// terminator byte.
     46   ///
     47   /// @param[in,out] offset_ptr
     48   ///     A pointer to an offset within the data that will be advanced
     49   ///     by the appropriate number of bytes if the value is extracted
     50   ///     correctly. If the offset is out of bounds or there are not
     51   ///     enough bytes to extract this value, the offset will be left
     52   ///     unmodified.
     53   ///
     54   /// @return
     55   ///     A pointer to the C string value in the data. If the offset
     56   ///     pointed to by \a offset_ptr is out of bounds, or if the
     57   ///     offset plus the length of the C string is out of bounds,
     58   ///     NULL will be returned.
     59   const char *getCStr(uint32_t *offset_ptr) const;
     60 
     61   /// Extract a C string from \a *OffsetPtr.
     62   ///
     63   /// Returns a StringRef for the C String from the data at the offset
     64   /// pointed to by \a OffsetPtr. A variable length NULL terminated C
     65   /// string will be extracted and the \a OffsetPtr will be
     66   /// updated with the offset of the byte that follows the NULL
     67   /// terminator byte.
     68   ///
     69   /// \param[in,out] OffsetPtr
     70   ///     A pointer to an offset within the data that will be advanced
     71   ///     by the appropriate number of bytes if the value is extracted
     72   ///     correctly. If the offset is out of bounds or there are not
     73   ///     enough bytes to extract this value, the offset will be left
     74   ///     unmodified.
     75   ///
     76   /// \return
     77   ///     A StringRef for the C string value in the data. If the offset
     78   ///     pointed to by \a OffsetPtr is out of bounds, or if the
     79   ///     offset plus the length of the C string is out of bounds,
     80   ///     a default-initialized StringRef will be returned.
     81   StringRef getCStrRef(uint32_t *OffsetPtr) const;
     82 
     83   /// Extract an unsigned integer of size \a byte_size from \a
     84   /// *offset_ptr.
     85   ///
     86   /// Extract a single unsigned integer value and update the offset
     87   /// pointed to by \a offset_ptr. The size of the extracted integer
     88   /// is specified by the \a byte_size argument. \a byte_size should
     89   /// have a value greater than or equal to one and less than or equal
     90   /// to eight since the return value is 64 bits wide. Any
     91   /// \a byte_size values less than 1 or greater than 8 will result in
     92   /// nothing being extracted, and zero being returned.
     93   ///
     94   /// @param[in,out] offset_ptr
     95   ///     A pointer to an offset within the data that will be advanced
     96   ///     by the appropriate number of bytes if the value is extracted
     97   ///     correctly. If the offset is out of bounds or there are not
     98   ///     enough bytes to extract this value, the offset will be left
     99   ///     unmodified.
    100   ///
    101   /// @param[in] byte_size
    102   ///     The size in byte of the integer to extract.
    103   ///
    104   /// @return
    105   ///     The unsigned integer value that was extracted, or zero on
    106   ///     failure.
    107   uint64_t getUnsigned(uint32_t *offset_ptr, uint32_t byte_size) const;
    108 
    109   /// Extract an signed integer of size \a byte_size from \a *offset_ptr.
    110   ///
    111   /// Extract a single signed integer value (sign extending if required)
    112   /// and update the offset pointed to by \a offset_ptr. The size of
    113   /// the extracted integer is specified by the \a byte_size argument.
    114   /// \a byte_size should have a value greater than or equal to one
    115   /// and less than or equal to eight since the return value is 64
    116   /// bits wide. Any \a byte_size values less than 1 or greater than
    117   /// 8 will result in nothing being extracted, and zero being returned.
    118   ///
    119   /// @param[in,out] offset_ptr
    120   ///     A pointer to an offset within the data that will be advanced
    121   ///     by the appropriate number of bytes if the value is extracted
    122   ///     correctly. If the offset is out of bounds or there are not
    123   ///     enough bytes to extract this value, the offset will be left
    124   ///     unmodified.
    125   ///
    126   /// @param[in] size
    127   ///     The size in bytes of the integer to extract.
    128   ///
    129   /// @return
    130   ///     The sign extended signed integer value that was extracted,
    131   ///     or zero on failure.
    132   int64_t getSigned(uint32_t *offset_ptr, uint32_t size) const;
    133 
    134   //------------------------------------------------------------------
    135   /// Extract an pointer from \a *offset_ptr.
    136   ///
    137   /// Extract a single pointer from the data and update the offset
    138   /// pointed to by \a offset_ptr. The size of the extracted pointer
    139   /// is \a getAddressSize(), so the address size has to be
    140   /// set correctly prior to extracting any pointer values.
    141   ///
    142   /// @param[in,out] offset_ptr
    143   ///     A pointer to an offset within the data that will be advanced
    144   ///     by the appropriate number of bytes if the value is extracted
    145   ///     correctly. If the offset is out of bounds or there are not
    146   ///     enough bytes to extract this value, the offset will be left
    147   ///     unmodified.
    148   ///
    149   /// @return
    150   ///     The extracted pointer value as a 64 integer.
    151   uint64_t getAddress(uint32_t *offset_ptr) const {
    152     return getUnsigned(offset_ptr, AddressSize);
    153   }
    154 
    155   /// Extract a uint8_t value from \a *offset_ptr.
    156   ///
    157   /// Extract a single uint8_t from the binary data at the offset
    158   /// pointed to by \a offset_ptr, and advance the offset on success.
    159   ///
    160   /// @param[in,out] offset_ptr
    161   ///     A pointer to an offset within the data that will be advanced
    162   ///     by the appropriate number of bytes if the value is extracted
    163   ///     correctly. If the offset is out of bounds or there are not
    164   ///     enough bytes to extract this value, the offset will be left
    165   ///     unmodified.
    166   ///
    167   /// @return
    168   ///     The extracted uint8_t value.
    169   uint8_t getU8(uint32_t *offset_ptr) const;
    170 
    171   /// Extract \a count uint8_t values from \a *offset_ptr.
    172   ///
    173   /// Extract \a count uint8_t values from the binary data at the
    174   /// offset pointed to by \a offset_ptr, and advance the offset on
    175   /// success. The extracted values are copied into \a dst.
    176   ///
    177   /// @param[in,out] offset_ptr
    178   ///     A pointer to an offset within the data that will be advanced
    179   ///     by the appropriate number of bytes if the value is extracted
    180   ///     correctly. If the offset is out of bounds or there are not
    181   ///     enough bytes to extract this value, the offset will be left
    182   ///     unmodified.
    183   ///
    184   /// @param[out] dst
    185   ///     A buffer to copy \a count uint8_t values into. \a dst must
    186   ///     be large enough to hold all requested data.
    187   ///
    188   /// @param[in] count
    189   ///     The number of uint8_t values to extract.
    190   ///
    191   /// @return
    192   ///     \a dst if all values were properly extracted and copied,
    193   ///     NULL otherise.
    194   uint8_t *getU8(uint32_t *offset_ptr, uint8_t *dst, uint32_t count) const;
    195 
    196   //------------------------------------------------------------------
    197   /// Extract a uint16_t value from \a *offset_ptr.
    198   ///
    199   /// Extract a single uint16_t from the binary data at the offset
    200   /// pointed to by \a offset_ptr, and update the offset on success.
    201   ///
    202   /// @param[in,out] offset_ptr
    203   ///     A pointer to an offset within the data that will be advanced
    204   ///     by the appropriate number of bytes if the value is extracted
    205   ///     correctly. If the offset is out of bounds or there are not
    206   ///     enough bytes to extract this value, the offset will be left
    207   ///     unmodified.
    208   ///
    209   /// @return
    210   ///     The extracted uint16_t value.
    211   //------------------------------------------------------------------
    212   uint16_t getU16(uint32_t *offset_ptr) const;
    213 
    214   /// Extract \a count uint16_t values from \a *offset_ptr.
    215   ///
    216   /// Extract \a count uint16_t values from the binary data at the
    217   /// offset pointed to by \a offset_ptr, and advance the offset on
    218   /// success. The extracted values are copied into \a dst.
    219   ///
    220   /// @param[in,out] offset_ptr
    221   ///     A pointer to an offset within the data that will be advanced
    222   ///     by the appropriate number of bytes if the value is extracted
    223   ///     correctly. If the offset is out of bounds or there are not
    224   ///     enough bytes to extract this value, the offset will be left
    225   ///     unmodified.
    226   ///
    227   /// @param[out] dst
    228   ///     A buffer to copy \a count uint16_t values into. \a dst must
    229   ///     be large enough to hold all requested data.
    230   ///
    231   /// @param[in] count
    232   ///     The number of uint16_t values to extract.
    233   ///
    234   /// @return
    235   ///     \a dst if all values were properly extracted and copied,
    236   ///     NULL otherise.
    237   uint16_t *getU16(uint32_t *offset_ptr, uint16_t *dst, uint32_t count) const;
    238 
    239   /// Extract a uint32_t value from \a *offset_ptr.
    240   ///
    241   /// Extract a single uint32_t from the binary data at the offset
    242   /// pointed to by \a offset_ptr, and update the offset on success.
    243   ///
    244   /// @param[in,out] offset_ptr
    245   ///     A pointer to an offset within the data that will be advanced
    246   ///     by the appropriate number of bytes if the value is extracted
    247   ///     correctly. If the offset is out of bounds or there are not
    248   ///     enough bytes to extract this value, the offset will be left
    249   ///     unmodified.
    250   ///
    251   /// @return
    252   ///     The extracted uint32_t value.
    253   uint32_t getU32(uint32_t *offset_ptr) const;
    254 
    255   /// Extract \a count uint32_t values from \a *offset_ptr.
    256   ///
    257   /// Extract \a count uint32_t values from the binary data at the
    258   /// offset pointed to by \a offset_ptr, and advance the offset on
    259   /// success. The extracted values are copied into \a dst.
    260   ///
    261   /// @param[in,out] offset_ptr
    262   ///     A pointer to an offset within the data that will be advanced
    263   ///     by the appropriate number of bytes if the value is extracted
    264   ///     correctly. If the offset is out of bounds or there are not
    265   ///     enough bytes to extract this value, the offset will be left
    266   ///     unmodified.
    267   ///
    268   /// @param[out] dst
    269   ///     A buffer to copy \a count uint32_t values into. \a dst must
    270   ///     be large enough to hold all requested data.
    271   ///
    272   /// @param[in] count
    273   ///     The number of uint32_t values to extract.
    274   ///
    275   /// @return
    276   ///     \a dst if all values were properly extracted and copied,
    277   ///     NULL otherise.
    278   uint32_t *getU32(uint32_t *offset_ptr, uint32_t *dst, uint32_t count) const;
    279 
    280   /// Extract a uint64_t value from \a *offset_ptr.
    281   ///
    282   /// Extract a single uint64_t from the binary data at the offset
    283   /// pointed to by \a offset_ptr, and update the offset on success.
    284   ///
    285   /// @param[in,out] offset_ptr
    286   ///     A pointer to an offset within the data that will be advanced
    287   ///     by the appropriate number of bytes if the value is extracted
    288   ///     correctly. If the offset is out of bounds or there are not
    289   ///     enough bytes to extract this value, the offset will be left
    290   ///     unmodified.
    291   ///
    292   /// @return
    293   ///     The extracted uint64_t value.
    294   uint64_t getU64(uint32_t *offset_ptr) const;
    295 
    296   /// Extract \a count uint64_t values from \a *offset_ptr.
    297   ///
    298   /// Extract \a count uint64_t values from the binary data at the
    299   /// offset pointed to by \a offset_ptr, and advance the offset on
    300   /// success. The extracted values are copied into \a dst.
    301   ///
    302   /// @param[in,out] offset_ptr
    303   ///     A pointer to an offset within the data that will be advanced
    304   ///     by the appropriate number of bytes if the value is extracted
    305   ///     correctly. If the offset is out of bounds or there are not
    306   ///     enough bytes to extract this value, the offset will be left
    307   ///     unmodified.
    308   ///
    309   /// @param[out] dst
    310   ///     A buffer to copy \a count uint64_t values into. \a dst must
    311   ///     be large enough to hold all requested data.
    312   ///
    313   /// @param[in] count
    314   ///     The number of uint64_t values to extract.
    315   ///
    316   /// @return
    317   ///     \a dst if all values were properly extracted and copied,
    318   ///     NULL otherise.
    319   uint64_t *getU64(uint32_t *offset_ptr, uint64_t *dst, uint32_t count) const;
    320 
    321   /// Extract a signed LEB128 value from \a *offset_ptr.
    322   ///
    323   /// Extracts an signed LEB128 number from this object's data
    324   /// starting at the offset pointed to by \a offset_ptr. The offset
    325   /// pointed to by \a offset_ptr will be updated with the offset of
    326   /// the byte following the last extracted byte.
    327   ///
    328   /// @param[in,out] offset_ptr
    329   ///     A pointer to an offset within the data that will be advanced
    330   ///     by the appropriate number of bytes if the value is extracted
    331   ///     correctly. If the offset is out of bounds or there are not
    332   ///     enough bytes to extract this value, the offset will be left
    333   ///     unmodified.
    334   ///
    335   /// @return
    336   ///     The extracted signed integer value.
    337   int64_t getSLEB128(uint32_t *offset_ptr) const;
    338 
    339   /// Extract a unsigned LEB128 value from \a *offset_ptr.
    340   ///
    341   /// Extracts an unsigned LEB128 number from this object's data
    342   /// starting at the offset pointed to by \a offset_ptr. The offset
    343   /// pointed to by \a offset_ptr will be updated with the offset of
    344   /// the byte following the last extracted byte.
    345   ///
    346   /// @param[in,out] offset_ptr
    347   ///     A pointer to an offset within the data that will be advanced
    348   ///     by the appropriate number of bytes if the value is extracted
    349   ///     correctly. If the offset is out of bounds or there are not
    350   ///     enough bytes to extract this value, the offset will be left
    351   ///     unmodified.
    352   ///
    353   /// @return
    354   ///     The extracted unsigned integer value.
    355   uint64_t getULEB128(uint32_t *offset_ptr) const;
    356 
    357   /// Test the validity of \a offset.
    358   ///
    359   /// @return
    360   ///     \b true if \a offset is a valid offset into the data in this
    361   ///     object, \b false otherwise.
    362   bool isValidOffset(uint32_t offset) const { return Data.size() > offset; }
    363 
    364   /// Test the availability of \a length bytes of data from \a offset.
    365   ///
    366   /// @return
    367   ///     \b true if \a offset is a valid offset and there are \a
    368   ///     length bytes available at that offset, \b false otherwise.
    369   bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const {
    370     return offset + length >= offset && isValidOffset(offset + length - 1);
    371   }
    372 
    373   /// Test the availability of enough bytes of data for a pointer from
    374   /// \a offset. The size of a pointer is \a getAddressSize().
    375   ///
    376   /// @return
    377   ///     \b true if \a offset is a valid offset and there are enough
    378   ///     bytes for a pointer available at that offset, \b false
    379   ///     otherwise.
    380   bool isValidOffsetForAddress(uint32_t offset) const {
    381     return isValidOffsetForDataOfSize(offset, AddressSize);
    382   }
    383 };
    384 
    385 } // namespace llvm
    386 
    387 #endif
    388