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