blob: 8c12b0afac69177cf89a609c339c2c86592d138d [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Kate Stoneb9c1b512016-09-06 20:57:50 +000024DNBDataRef::DNBDataRef()
25 : m_start(NULL), m_end(NULL), m_swap(false), m_ptrSize(0),
26 m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
27 m_addrDATA(INVALID_NUB_ADDRESS) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
29//----------------------------------------------------------------------
30// Constructor
31//----------------------------------------------------------------------
32
Kate Stoneb9c1b512016-09-06 20:57:50 +000033DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap)
34 : m_start(start), m_end(start + size), m_swap(swap), m_ptrSize(0),
35 m_addrPCRelative(INVALID_NUB_ADDRESS), m_addrTEXT(INVALID_NUB_ADDRESS),
36 m_addrDATA(INVALID_NUB_ADDRESS) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
38//----------------------------------------------------------------------
39// Destructor
40//----------------------------------------------------------------------
41
Kate Stoneb9c1b512016-09-06 20:57:50 +000042DNBDataRef::~DNBDataRef() {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
44//----------------------------------------------------------------------
45// Get8
46//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000047uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {
48 uint8_t val = 0;
49 if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
50 val = *(m_start + *offset_ptr);
51 *offset_ptr += sizeof(val);
52 }
53 return val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054}
55
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056//----------------------------------------------------------------------
57// Get16
58//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000059uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {
60 uint16_t val = 0;
61 if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
62 const uint8_t *p = m_start + *offset_ptr;
Vedant Kumar01e86df2017-12-01 23:24:12 +000063 memcpy(&val, p, sizeof(uint16_t));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 if (m_swap)
66 val = OSSwapInt16(val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 // Advance the offset
69 *offset_ptr += sizeof(val);
70 }
71 return val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000072}
73
Chris Lattner30fdc8d2010-06-08 16:52:24 +000074//----------------------------------------------------------------------
75// Get32
76//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000077uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {
78 uint32_t val = 0;
79 if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
80 const uint8_t *p = m_start + *offset_ptr;
Vedant Kumar01e86df2017-12-01 23:24:12 +000081 memcpy(&val, p, sizeof(uint32_t));
Kate Stoneb9c1b512016-09-06 20:57:50 +000082 if (m_swap)
83 val = OSSwapInt32(val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000084
Kate Stoneb9c1b512016-09-06 20:57:50 +000085 // Advance the offset
86 *offset_ptr += sizeof(val);
87 }
88 return val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000089}
90
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091//----------------------------------------------------------------------
92// Get64
93//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000094uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {
95 uint64_t val = 0;
96 if (ValidOffsetForDataOfSize(*offset_ptr, sizeof(val))) {
97 const uint8_t *p = m_start + *offset_ptr;
Vedant Kumar01e86df2017-12-01 23:24:12 +000098 memcpy(&val, p, sizeof(uint64_t));
Kate Stoneb9c1b512016-09-06 20:57:50 +000099 if (m_swap)
100 val = OSSwapInt64(val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 // Advance the offset
103 *offset_ptr += sizeof(val);
104 }
105 return val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106}
107
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000108//----------------------------------------------------------------------
109// GetMax32
110//
111// Used for calls when the size can vary. Fill in extra cases if they
112// are ever needed.
113//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {
115 switch (byte_size) {
116 case 1:
117 return Get8(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000118 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 case 2:
120 return Get16(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000121 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122 case 4:
123 return Get32(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000124 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 default:
Vedant Kumar01e86df2017-12-01 23:24:12 +0000126 assert(false && "GetMax32 unhandled case!");
David Blaikiea77ec682017-01-06 01:42:56 +0000127 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 }
David Blaikiea77ec682017-01-06 01:42:56 +0000129 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130}
131
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000132//----------------------------------------------------------------------
133// GetMax64
134//
135// Used for calls when the size can vary. Fill in extra cases if they
136// are ever needed.
137//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {
139 switch (size) {
140 case 1:
141 return Get8(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000142 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 case 2:
144 return Get16(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000145 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 case 4:
147 return Get32(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000148 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 case 8:
150 return Get64(offset_ptr);
David Blaikiea77ec682017-01-06 01:42:56 +0000151 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 default:
Vedant Kumar01e86df2017-12-01 23:24:12 +0000153 assert(false && "GetMax64 unhandled case!");
David Blaikiea77ec682017-01-06 01:42:56 +0000154 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 }
David Blaikiea77ec682017-01-06 01:42:56 +0000156 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000157}
158
159//----------------------------------------------------------------------
160// GetPointer
161//
162// Extract a pointer value from the buffer. The pointer size must be
163// set prior to using this using one of the SetPointerSize functions.
164//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165uint64_t DNBDataRef::GetPointer(offset_t *offset_ptr) const {
166 // Must set pointer size prior to using this call
167 assert(m_ptrSize != 0);
168 return GetMax64(offset_ptr, m_ptrSize);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170//----------------------------------------------------------------------
171// GetCStr
172//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173const char *DNBDataRef::GetCStr(offset_t *offset_ptr,
174 uint32_t fixed_length) const {
175 const char *s = NULL;
176 if (m_start < m_end) {
Vedant Kumar01e86df2017-12-01 23:24:12 +0000177 s = (const char *)m_start + *offset_ptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179 // Advance the offset
180 if (fixed_length)
181 *offset_ptr += fixed_length;
182 else
183 *offset_ptr += strlen(s) + 1;
184 }
185 return s;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000186}
187
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188//----------------------------------------------------------------------
189// GetData
190//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191const uint8_t *DNBDataRef::GetData(offset_t *offset_ptr,
192 uint32_t length) const {
193 const uint8_t *data = NULL;
194 if (length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length)) {
195 data = m_start + *offset_ptr;
196 *offset_ptr += length;
197 }
198 return data;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000199}
200
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201//----------------------------------------------------------------------
202// Get_ULEB128
203//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {
205 uint64_t result = 0;
206 if (m_start < m_end) {
207 int shift = 0;
208 const uint8_t *src = m_start + *offset_ptr;
209 uint8_t byte;
210 int bytecount = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211
Kate Stoneb9c1b512016-09-06 20:57:50 +0000212 while (src < m_end) {
213 bytecount++;
214 byte = *src++;
215 result |= (uint64_t)(byte & 0x7f) << shift;
216 shift += 7;
217 if ((byte & 0x80) == 0)
218 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221 *offset_ptr += bytecount;
222 }
223 return result;
224}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225
226//----------------------------------------------------------------------
227// Get_SLEB128
228//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {
230 int64_t result = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 if (m_start < m_end) {
233 int shift = 0;
234 int size = sizeof(uint32_t) * 8;
235 const uint8_t *src = m_start + *offset_ptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 uint8_t byte = 0;
238 int bytecount = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240 while (src < m_end) {
241 bytecount++;
242 byte = *src++;
243 result |= (int64_t)(byte & 0x7f) << shift;
244 shift += 7;
245 if ((byte & 0x80) == 0)
246 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000247 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 // Sign bit of byte is 2nd high order bit (0x40)
250 if (shift < size && (byte & 0x40))
251 result |= -(1ll << shift);
252
253 *offset_ptr += bytecount;
254 }
255 return result;
256}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257
258//----------------------------------------------------------------------
259// Skip_LEB128
260//
261// Skips past ULEB128 and SLEB128 numbers (just updates the offset)
262//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263void DNBDataRef::Skip_LEB128(offset_t *offset_ptr) const {
264 if (m_start < m_end) {
265 const uint8_t *start = m_start + *offset_ptr;
266 const uint8_t *src = start;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000267
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268 while ((src < m_end) && (*src++ & 0x80))
269 /* Do nothing */;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000270
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271 *offset_ptr += src - start;
272 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273}
274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,
276 uint64_t offsetBase, DNBDataRef::Type type,
277 uint32_t numPerLine, const char *format) {
278 uint32_t offset;
279 uint32_t count;
280 char str[1024];
281 str[0] = '\0';
282 size_t str_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000283
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 for (offset = startOffset, count = 0;
285 ValidOffset(offset) && offset < endOffset; ++count) {
286 if ((count % numPerLine) == 0) {
287 // Print out any previous string
288 if (str[0] != '\0')
289 DNBLog("%s", str);
290 // Reset string offset and fill the current line string with address:
291 str_offset = 0;
292 str_offset += snprintf(str, sizeof(str), "0x%8.8llx:",
293 (uint64_t)(offsetBase + (offset - startOffset)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294 }
295
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 // Make sure we don't pass the bounds of our current string buffer on each
297 // iteration through this loop
298 if (str_offset >= sizeof(str)) {
299 // The last snprintf consumed our string buffer, we will need to dump this
300 // out
301 // and reset the string with no address
302 DNBLog("%s", str);
303 str_offset = 0;
304 str[0] = '\0';
305 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306
Kate Stoneb9c1b512016-09-06 20:57:50 +0000307 // We already checked that there is at least some room in the string str
308 // above, so it is safe to make
309 // the snprintf call each time through this loop
310 switch (type) {
311 case TypeUInt8:
312 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
313 format ? format : " %2.2x", Get8(&offset));
314 break;
315 case TypeChar: {
316 char ch = Get8(&offset);
317 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
318 format ? format : " %c", isprint(ch) ? ch : ' ');
319 } break;
320 case TypeUInt16:
321 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
322 format ? format : " %4.4x", Get16(&offset));
323 break;
324 case TypeUInt32:
325 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
326 format ? format : " %8.8x", Get32(&offset));
327 break;
328 case TypeUInt64:
329 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
330 format ? format : " %16.16llx", Get64(&offset));
331 break;
332 case TypePointer:
333 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
334 format ? format : " 0x%llx", GetPointer(&offset));
335 break;
336 case TypeULEB128:
337 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
338 format ? format : " 0x%llx", Get_ULEB128(&offset));
339 break;
340 case TypeSLEB128:
341 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset,
342 format ? format : " %lld", Get_SLEB128(&offset));
343 break;
344 }
345 }
346
347 if (str[0] != '\0')
348 DNBLog("%s", str);
349
350 return offset; // Return the offset at which we ended up
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351}