• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- DNBDataRef.cpp ------------------------------------------*- 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 //  Created by Greg Clayton on 1/11/06.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "DNBDataRef.h"
15 #include "DNBLog.h"
16 #include <assert.h>
17 #include <ctype.h>
18 #include <libkern/OSByteOrder.h>
19 
20 //----------------------------------------------------------------------
21 // Constructor
22 //----------------------------------------------------------------------
23 
DNBDataRef()24 DNBDataRef::DNBDataRef() :
25     m_start(NULL),
26     m_end(NULL),
27     m_swap(false),
28     m_ptrSize(0),
29     m_addrPCRelative(INVALID_NUB_ADDRESS),
30     m_addrTEXT(INVALID_NUB_ADDRESS),
31     m_addrDATA(INVALID_NUB_ADDRESS)
32 {
33 }
34 
35 
36 //----------------------------------------------------------------------
37 // Constructor
38 //----------------------------------------------------------------------
39 
DNBDataRef(const uint8_t * start,size_t size,bool swap)40 DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) :
41     m_start(start),
42     m_end(start+size),
43     m_swap(swap),
44     m_ptrSize(0),
45     m_addrPCRelative(INVALID_NUB_ADDRESS),
46     m_addrTEXT(INVALID_NUB_ADDRESS),
47     m_addrDATA(INVALID_NUB_ADDRESS)
48 {
49 }
50 
51 
52 //----------------------------------------------------------------------
53 // Destructor
54 //----------------------------------------------------------------------
55 
~DNBDataRef()56 DNBDataRef::~DNBDataRef()
57 {
58 }
59 
60 
61 //----------------------------------------------------------------------
62 // Get8
63 //----------------------------------------------------------------------
64 uint8_t
Get8(offset_t * offset_ptr) const65 DNBDataRef::Get8(offset_t *offset_ptr) const
66 {
67     uint8_t val = 0;
68     if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
69     {
70         val = *(m_start + *offset_ptr);
71         *offset_ptr += sizeof(val);
72     }
73     return val;
74 }
75 
76 
77 //----------------------------------------------------------------------
78 // Get16
79 //----------------------------------------------------------------------
80 uint16_t
Get16(offset_t * offset_ptr) const81 DNBDataRef::Get16(offset_t *offset_ptr) const
82 {
83     uint16_t val = 0;
84     if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
85     {
86         const uint8_t *p = m_start + *offset_ptr;
87         val = *(uint16_t*)p;
88 
89         if (m_swap)
90             val = OSSwapInt16(val);
91 
92         // Advance the offset
93         *offset_ptr += sizeof(val);
94     }
95     return val;
96 }
97 
98 
99 //----------------------------------------------------------------------
100 // Get32
101 //----------------------------------------------------------------------
102 uint32_t
Get32(offset_t * offset_ptr) const103 DNBDataRef::Get32(offset_t *offset_ptr) const
104 {
105     uint32_t val = 0;
106     if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
107     {
108         const uint8_t *p = m_start + *offset_ptr;
109         val = *(uint32_t*)p;
110         if (m_swap)
111             val = OSSwapInt32(val);
112 
113         // Advance the offset
114         *offset_ptr += sizeof(val);
115     }
116     return val;
117 }
118 
119 
120 //----------------------------------------------------------------------
121 // Get64
122 //----------------------------------------------------------------------
123 uint64_t
Get64(offset_t * offset_ptr) const124 DNBDataRef::Get64(offset_t *offset_ptr) const
125 {
126     uint64_t val = 0;
127     if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
128     {
129         const uint8_t *p = m_start + *offset_ptr;
130         val = *(uint64_t*)p;
131         if (m_swap)
132             val = OSSwapInt64(val);
133 
134         // Advance the offset
135         *offset_ptr += sizeof(val);
136     }
137     return val;
138 }
139 
140 
141 //----------------------------------------------------------------------
142 // GetMax32
143 //
144 // Used for calls when the size can vary. Fill in extra cases if they
145 // are ever needed.
146 //----------------------------------------------------------------------
147 uint32_t
GetMax32(offset_t * offset_ptr,uint32_t byte_size) const148 DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const
149 {
150     switch (byte_size)
151     {
152         case 1: return Get8 (offset_ptr); break;
153         case 2: return Get16(offset_ptr); break;
154         case 4:    return Get32(offset_ptr); break;
155         default:
156         assert(!"GetMax32 unhandled case!");
157             break;
158     }
159     return 0;
160 }
161 
162 
163 //----------------------------------------------------------------------
164 // GetMax64
165 //
166 // Used for calls when the size can vary. Fill in extra cases if they
167 // are ever needed.
168 //----------------------------------------------------------------------
169 uint64_t
GetMax64(offset_t * offset_ptr,uint32_t size) const170 DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const
171 {
172     switch (size)
173     {
174         case 1: return Get8 (offset_ptr); break;
175         case 2: return Get16(offset_ptr); break;
176         case 4: return Get32(offset_ptr); break;
177         case 8: return Get64(offset_ptr); break;
178         default:
179         assert(!"GetMax64 unhandled case!");
180             break;
181     }
182     return 0;
183 }
184 
185 //----------------------------------------------------------------------
186 // GetPointer
187 //
188 // Extract a pointer value from the buffer. The pointer size must be
189 // set prior to using this using one of the SetPointerSize functions.
190 //----------------------------------------------------------------------
191 uint64_t
GetPointer(offset_t * offset_ptr) const192 DNBDataRef::GetPointer(offset_t *offset_ptr) const
193 {
194     // Must set pointer size prior to using this call
195     assert(m_ptrSize != 0);
196     return GetMax64(offset_ptr, m_ptrSize);
197 }
198 //----------------------------------------------------------------------
199 // GetCStr
200 //----------------------------------------------------------------------
201 const char *
GetCStr(offset_t * offset_ptr,uint32_t fixed_length) const202 DNBDataRef::GetCStr(offset_t *offset_ptr, uint32_t fixed_length) const
203 {
204     const char *s = NULL;
205     if ( m_start < m_end )
206     {
207         s = (char*)m_start + *offset_ptr;
208 
209         // Advance the offset
210         if (fixed_length)
211             *offset_ptr += fixed_length;
212         else
213             *offset_ptr += strlen(s) + 1;
214     }
215     return s;
216 }
217 
218 
219 //----------------------------------------------------------------------
220 // GetData
221 //----------------------------------------------------------------------
222 const uint8_t *
GetData(offset_t * offset_ptr,uint32_t length) const223 DNBDataRef::GetData(offset_t *offset_ptr, uint32_t length) const
224 {
225     const uint8_t *data = NULL;
226     if ( length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length) )
227     {
228         data = m_start + *offset_ptr;
229         *offset_ptr += length;
230     }
231     return data;
232 }
233 
234 
235 //----------------------------------------------------------------------
236 // Get_ULEB128
237 //----------------------------------------------------------------------
238 uint64_t
Get_ULEB128(offset_t * offset_ptr) const239 DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const
240 {
241     uint64_t result = 0;
242     if ( m_start < m_end )
243     {
244         int shift = 0;
245         const uint8_t *src = m_start + *offset_ptr;
246         uint8_t byte;
247         int bytecount = 0;
248 
249         while (src < m_end)
250         {
251             bytecount++;
252             byte = *src++;
253             result |= (byte & 0x7f) << shift;
254             shift += 7;
255             if ((byte & 0x80) == 0)
256                 break;
257         }
258 
259         *offset_ptr += bytecount;
260     }
261     return result;
262 }
263 
264 
265 //----------------------------------------------------------------------
266 // Get_SLEB128
267 //----------------------------------------------------------------------
268 int64_t
Get_SLEB128(offset_t * offset_ptr) const269 DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const
270 {
271     int64_t result = 0;
272 
273     if ( m_start < m_end )
274     {
275         int shift = 0;
276         int size = sizeof (uint32_t) * 8;
277         const uint8_t *src = m_start + *offset_ptr;
278 
279         uint8_t byte = 0;
280         int bytecount = 0;
281 
282         while (src < m_end)
283         {
284             bytecount++;
285             byte = *src++;
286             result |= (byte & 0x7f) << shift;
287             shift += 7;
288             if ((byte & 0x80) == 0)
289                 break;
290         }
291 
292         // Sign bit of byte is 2nd high order bit (0x40)
293         if (shift < size && (byte & 0x40))
294             result |= - (1ll << shift);
295 
296         *offset_ptr += bytecount;
297     }
298     return result;
299 }
300 
301 
302 //----------------------------------------------------------------------
303 // Skip_LEB128
304 //
305 // Skips past ULEB128 and SLEB128 numbers (just updates the offset)
306 //----------------------------------------------------------------------
307 void
Skip_LEB128(offset_t * offset_ptr) const308 DNBDataRef::Skip_LEB128 (offset_t *offset_ptr) const
309 {
310     if ( m_start < m_end )
311     {
312         const uint8_t *start = m_start + *offset_ptr;
313         const uint8_t *src = start;
314 
315         while ((src < m_end) && (*src++ & 0x80))
316             /* Do nothing */;
317 
318         *offset_ptr += src - start;
319     }
320 }
321 
322 uint32_t
Dump(uint32_t startOffset,uint32_t endOffset,uint64_t offsetBase,DNBDataRef::Type type,uint32_t numPerLine,const char * format)323 DNBDataRef::Dump
324 (
325     uint32_t startOffset,
326     uint32_t endOffset,
327     uint64_t offsetBase,
328     DNBDataRef::Type type,
329     uint32_t numPerLine,
330     const char *format
331 )
332 {
333     uint32_t offset;
334     uint32_t count;
335     char str[1024];
336     str[0] = '\0';
337     int str_offset = 0;
338 
339     for (offset = startOffset, count = 0; ValidOffset(offset) && offset < endOffset; ++count)
340     {
341         if ((count % numPerLine) == 0)
342         {
343             // Print out any previous string
344             if (str[0] != '\0')
345                 DNBLog("%s", str);
346             // Reset string offset and fill the current line string with address:
347             str_offset = 0;
348             str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", (uint64_t)(offsetBase + (offset - startOffset)));
349         }
350 
351         // Make sure we don't pass the bounds of our current string buffer on each iteration through this loop
352         if (str_offset >= sizeof(str))
353         {
354             // The last snprintf consumed our string buffer, we will need to dump this out
355             // and reset the string with no address
356             DNBLog("%s", str);
357             str_offset = 0;
358             str[0] = '\0';
359         }
360 
361         // We already checked that there is at least some room in the string str above, so it is safe to make
362         // the snprintf call each time through this loop
363         switch (type)
364         {
365             default:
366             case TypeUInt8:   str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break;
367             case TypeChar:
368                 {
369                     char ch = Get8(&offset);
370                     str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c",    isprint(ch) ? ch : ' ');
371                 }
372                 break;
373             case TypeUInt16:  str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %4.4x",       Get16(&offset)); break;
374             case TypeUInt32:  str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %8.8x",       Get32(&offset)); break;
375             case TypeUInt64:  str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %16.16llx",   Get64(&offset)); break;
376             case TypePointer: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx",      GetPointer(&offset)); break;
377             case TypeULEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx",      Get_ULEB128(&offset)); break;
378             case TypeSLEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %lld",        Get_SLEB128(&offset)); break;
379         }
380     }
381 
382     if (str[0] != '\0')
383         DNBLog("%s", str);
384 
385     return offset;  // Return the offset at which we ended up
386 }
387