1 //===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Created by Greg Clayton on 1/11/06.
11 //===----------------------------------------------------------------------===//
13 #include "DNBDataRef.h"
17 #include <libkern/OSByteOrder.h>
21 DNBDataRef::DNBDataRef()
22 : m_start(NULL
), m_end(NULL
), m_swap(false), m_ptrSize(0),
23 m_addrPCRelative(INVALID_NUB_ADDRESS
), m_addrTEXT(INVALID_NUB_ADDRESS
),
24 m_addrDATA(INVALID_NUB_ADDRESS
) {}
28 DNBDataRef::DNBDataRef(const uint8_t *start
, size_t size
, bool swap
)
29 : m_start(start
), m_end(start
+ size
), m_swap(swap
), m_ptrSize(0),
30 m_addrPCRelative(INVALID_NUB_ADDRESS
), m_addrTEXT(INVALID_NUB_ADDRESS
),
31 m_addrDATA(INVALID_NUB_ADDRESS
) {}
35 DNBDataRef::~DNBDataRef() {}
38 uint8_t DNBDataRef::Get8(offset_t
*offset_ptr
) const {
40 if (ValidOffsetForDataOfSize(*offset_ptr
, sizeof(val
))) {
41 val
= *(m_start
+ *offset_ptr
);
42 *offset_ptr
+= sizeof(val
);
48 uint16_t DNBDataRef::Get16(offset_t
*offset_ptr
) const {
50 if (ValidOffsetForDataOfSize(*offset_ptr
, sizeof(val
))) {
51 const uint8_t *p
= m_start
+ *offset_ptr
;
52 memcpy(&val
, p
, sizeof(uint16_t));
55 val
= OSSwapInt16(val
);
58 *offset_ptr
+= sizeof(val
);
64 uint32_t DNBDataRef::Get32(offset_t
*offset_ptr
) const {
66 if (ValidOffsetForDataOfSize(*offset_ptr
, sizeof(val
))) {
67 const uint8_t *p
= m_start
+ *offset_ptr
;
68 memcpy(&val
, p
, sizeof(uint32_t));
70 val
= OSSwapInt32(val
);
73 *offset_ptr
+= sizeof(val
);
79 uint64_t DNBDataRef::Get64(offset_t
*offset_ptr
) const {
81 if (ValidOffsetForDataOfSize(*offset_ptr
, sizeof(val
))) {
82 const uint8_t *p
= m_start
+ *offset_ptr
;
83 memcpy(&val
, p
, sizeof(uint64_t));
85 val
= OSSwapInt64(val
);
88 *offset_ptr
+= sizeof(val
);
95 // Used for calls when the size can vary. Fill in extra cases if they
97 uint32_t DNBDataRef::GetMax32(offset_t
*offset_ptr
, uint32_t byte_size
) const {
100 return Get8(offset_ptr
);
103 return Get16(offset_ptr
);
106 return Get32(offset_ptr
);
109 assert(false && "GetMax32 unhandled case!");
117 // Used for calls when the size can vary. Fill in extra cases if they
119 uint64_t DNBDataRef::GetMax64(offset_t
*offset_ptr
, uint32_t size
) const {
122 return Get8(offset_ptr
);
125 return Get16(offset_ptr
);
128 return Get32(offset_ptr
);
131 return Get64(offset_ptr
);
134 assert(false && "GetMax64 unhandled case!");
142 // Extract a pointer value from the buffer. The pointer size must be
143 // set prior to using this using one of the SetPointerSize functions.
144 uint64_t DNBDataRef::GetPointer(offset_t
*offset_ptr
) const {
145 // Must set pointer size prior to using this call
146 assert(m_ptrSize
!= 0);
147 return GetMax64(offset_ptr
, m_ptrSize
);
150 const char *DNBDataRef::GetCStr(offset_t
*offset_ptr
,
151 uint32_t fixed_length
) const {
152 const char *s
= NULL
;
153 if (m_start
< m_end
) {
154 s
= (const char *)m_start
+ *offset_ptr
;
156 // Advance the offset
158 *offset_ptr
+= fixed_length
;
160 *offset_ptr
+= strlen(s
) + 1;
166 const uint8_t *DNBDataRef::GetData(offset_t
*offset_ptr
,
167 uint32_t length
) const {
168 const uint8_t *data
= NULL
;
169 if (length
> 0 && ValidOffsetForDataOfSize(*offset_ptr
, length
)) {
170 data
= m_start
+ *offset_ptr
;
171 *offset_ptr
+= length
;
177 uint64_t DNBDataRef::Get_ULEB128(offset_t
*offset_ptr
) const {
179 if (m_start
< m_end
) {
181 const uint8_t *src
= m_start
+ *offset_ptr
;
185 while (src
< m_end
) {
188 result
|= (uint64_t)(byte
& 0x7f) << shift
;
190 if ((byte
& 0x80) == 0)
194 *offset_ptr
+= bytecount
;
200 int64_t DNBDataRef::Get_SLEB128(offset_t
*offset_ptr
) const {
203 if (m_start
< m_end
) {
205 int size
= sizeof(uint32_t) * 8;
206 const uint8_t *src
= m_start
+ *offset_ptr
;
211 while (src
< m_end
) {
214 result
|= (int64_t)(byte
& 0x7f) << shift
;
216 if ((byte
& 0x80) == 0)
220 // Sign bit of byte is 2nd high order bit (0x40)
221 if (shift
< size
&& (byte
& 0x40))
222 result
|= -(1ll << shift
);
224 *offset_ptr
+= bytecount
;
231 // Skips past ULEB128 and SLEB128 numbers (just updates the offset)
232 void DNBDataRef::Skip_LEB128(offset_t
*offset_ptr
) const {
233 if (m_start
< m_end
) {
234 const uint8_t *start
= m_start
+ *offset_ptr
;
235 const uint8_t *src
= start
;
237 while ((src
< m_end
) && (*src
++ & 0x80))
240 *offset_ptr
+= src
- start
;
244 uint32_t DNBDataRef::Dump(uint32_t startOffset
, uint32_t endOffset
,
245 uint64_t offsetBase
, DNBDataRef::Type type
,
246 uint32_t numPerLine
, const char *format
) {
251 size_t str_offset
= 0;
253 for (offset
= startOffset
, count
= 0;
254 ValidOffset(offset
) && offset
< endOffset
; ++count
) {
255 if ((count
% numPerLine
) == 0) {
256 // Print out any previous string
259 // Reset string offset and fill the current line string with address:
261 str_offset
+= snprintf(str
, sizeof(str
), "0x%8.8llx:",
262 (uint64_t)(offsetBase
+ (offset
- startOffset
)));
265 // Make sure we don't pass the bounds of our current string buffer on each
266 // iteration through this loop
267 if (str_offset
>= sizeof(str
)) {
268 // The last snprintf consumed our string buffer, we will need to dump this
270 // and reset the string with no address
276 // We already checked that there is at least some room in the string str
277 // above, so it is safe to make
278 // the snprintf call each time through this loop
281 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
282 format
? format
: " %2.2x", Get8(&offset
));
285 char ch
= Get8(&offset
);
286 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
287 format
? format
: " %c", isprint(ch
) ? ch
: ' ');
290 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
291 format
? format
: " %4.4x", Get16(&offset
));
294 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
295 format
? format
: " %8.8x", Get32(&offset
));
298 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
299 format
? format
: " %16.16llx", Get64(&offset
));
302 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
303 format
? format
: " 0x%llx", GetPointer(&offset
));
306 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
307 format
? format
: " 0x%llx", Get_ULEB128(&offset
));
310 str_offset
+= snprintf(str
+ str_offset
, sizeof(str
) - str_offset
,
311 format
? format
: " %lld", Get_SLEB128(&offset
));
319 return offset
; // Return the offset at which we ended up