1 //===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Created by Greg Clayton on 1/11/06.
12 //===----------------------------------------------------------------------===//
14 #include "DNBDataRef.h"
18 #include <libkern/OSByteOrder.h>
20 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
24 DNBDataRef::DNBDataRef() :
29 m_addrPCRelative(INVALID_NUB_ADDRESS),
30 m_addrTEXT(INVALID_NUB_ADDRESS),
31 m_addrDATA(INVALID_NUB_ADDRESS)
36 //----------------------------------------------------------------------
38 //----------------------------------------------------------------------
40 DNBDataRef::DNBDataRef(const uint8_t *start, size_t size, bool swap) :
45 m_addrPCRelative(INVALID_NUB_ADDRESS),
46 m_addrTEXT(INVALID_NUB_ADDRESS),
47 m_addrDATA(INVALID_NUB_ADDRESS)
52 //----------------------------------------------------------------------
54 //----------------------------------------------------------------------
56 DNBDataRef::~DNBDataRef()
61 //----------------------------------------------------------------------
63 //----------------------------------------------------------------------
65 DNBDataRef::Get8(offset_t *offset_ptr) const
68 if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
70 val = *(m_start + *offset_ptr);
71 *offset_ptr += sizeof(val);
77 //----------------------------------------------------------------------
79 //----------------------------------------------------------------------
81 DNBDataRef::Get16(offset_t *offset_ptr) const
84 if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
86 const uint8_t *p = m_start + *offset_ptr;
90 val = OSSwapInt16(val);
93 *offset_ptr += sizeof(val);
99 //----------------------------------------------------------------------
101 //----------------------------------------------------------------------
103 DNBDataRef::Get32(offset_t *offset_ptr) const
106 if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
108 const uint8_t *p = m_start + *offset_ptr;
111 val = OSSwapInt32(val);
113 // Advance the offset
114 *offset_ptr += sizeof(val);
120 //----------------------------------------------------------------------
122 //----------------------------------------------------------------------
124 DNBDataRef::Get64(offset_t *offset_ptr) const
127 if ( ValidOffsetForDataOfSize(*offset_ptr, sizeof(val)) )
129 const uint8_t *p = m_start + *offset_ptr;
132 val = OSSwapInt64(val);
134 // Advance the offset
135 *offset_ptr += sizeof(val);
141 //----------------------------------------------------------------------
144 // Used for calls when the size can vary. Fill in extra cases if they
146 //----------------------------------------------------------------------
148 DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const
152 case 1: return Get8 (offset_ptr); break;
153 case 2: return Get16(offset_ptr); break;
154 case 4: return Get32(offset_ptr); break;
156 assert(!"GetMax32 unhandled case!");
163 //----------------------------------------------------------------------
166 // Used for calls when the size can vary. Fill in extra cases if they
168 //----------------------------------------------------------------------
170 DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const
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;
179 assert(!"GetMax64 unhandled case!");
185 //----------------------------------------------------------------------
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 //----------------------------------------------------------------------
192 DNBDataRef::GetPointer(offset_t *offset_ptr) const
194 // Must set pointer size prior to using this call
195 assert(m_ptrSize != 0);
196 return GetMax64(offset_ptr, m_ptrSize);
198 //----------------------------------------------------------------------
200 //----------------------------------------------------------------------
202 DNBDataRef::GetCStr(offset_t *offset_ptr, uint32_t fixed_length) const
204 const char *s = NULL;
205 if ( m_start < m_end )
207 s = (char*)m_start + *offset_ptr;
209 // Advance the offset
211 *offset_ptr += fixed_length;
213 *offset_ptr += strlen(s) + 1;
219 //----------------------------------------------------------------------
221 //----------------------------------------------------------------------
223 DNBDataRef::GetData(offset_t *offset_ptr, uint32_t length) const
225 const uint8_t *data = NULL;
226 if ( length > 0 && ValidOffsetForDataOfSize(*offset_ptr, length) )
228 data = m_start + *offset_ptr;
229 *offset_ptr += length;
235 //----------------------------------------------------------------------
237 //----------------------------------------------------------------------
239 DNBDataRef::Get_ULEB128 (offset_t *offset_ptr) const
242 if ( m_start < m_end )
245 const uint8_t *src = m_start + *offset_ptr;
253 result |= (uint64_t)(byte & 0x7f) << shift;
255 if ((byte & 0x80) == 0)
259 *offset_ptr += bytecount;
265 //----------------------------------------------------------------------
267 //----------------------------------------------------------------------
269 DNBDataRef::Get_SLEB128 (offset_t *offset_ptr) const
273 if ( m_start < m_end )
276 int size = sizeof (uint32_t) * 8;
277 const uint8_t *src = m_start + *offset_ptr;
286 result |= (int64_t)(byte & 0x7f) << shift;
288 if ((byte & 0x80) == 0)
292 // Sign bit of byte is 2nd high order bit (0x40)
293 if (shift < size && (byte & 0x40))
294 result |= - (1ll << shift);
296 *offset_ptr += bytecount;
302 //----------------------------------------------------------------------
305 // Skips past ULEB128 and SLEB128 numbers (just updates the offset)
306 //----------------------------------------------------------------------
308 DNBDataRef::Skip_LEB128 (offset_t *offset_ptr) const
310 if ( m_start < m_end )
312 const uint8_t *start = m_start + *offset_ptr;
313 const uint8_t *src = start;
315 while ((src < m_end) && (*src++ & 0x80))
318 *offset_ptr += src - start;
325 uint32_t startOffset,
328 DNBDataRef::Type type,
337 size_t str_offset = 0;
339 for (offset = startOffset, count = 0; ValidOffset(offset) && offset < endOffset; ++count)
341 if ((count % numPerLine) == 0)
343 // Print out any previous string
346 // Reset string offset and fill the current line string with address:
348 str_offset += snprintf(str, sizeof(str), "0x%8.8llx:", (uint64_t)(offsetBase + (offset - startOffset)));
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))
354 // The last snprintf consumed our string buffer, we will need to dump this out
355 // and reset the string with no address
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
365 case TypeUInt8: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break;
368 char ch = Get8(&offset);
369 str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c", isprint(ch) ? ch : ' ');
372 case TypeUInt16: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %4.4x", Get16(&offset)); break;
373 case TypeUInt32: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %8.8x", Get32(&offset)); break;
374 case TypeUInt64: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %16.16llx", Get64(&offset)); break;
375 case TypePointer: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", GetPointer(&offset)); break;
376 case TypeULEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " 0x%llx", Get_ULEB128(&offset)); break;
377 case TypeSLEB128: str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %lld", Get_SLEB128(&offset)); break;
384 return offset; // Return the offset at which we ended up