1//===-- DNBDataRef.cpp ------------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Created by Greg Clayton on 1/11/06.
10//
11//===----------------------------------------------------------------------===//
12
13#include "DNBDataRef.h"
14#include "DNBLog.h"
15#include <cassert>
16#include <cctype>
17#include <libkern/OSByteOrder.h>
18
19// Constructor
20
21DNBDataRef::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) {}
25
26// Constructor
27
28DNBDataRef::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) {}
32
33// Destructor
34
35DNBDataRef::~DNBDataRef() = default;
36
37// Get8
38uint8_t DNBDataRef::Get8(offset_t *offset_ptr) const {
39 uint8_t val = 0;
40 if (ValidOffsetForDataOfSize(offset: *offset_ptr, num_bytes: sizeof(val))) {
41 val = *(m_start + *offset_ptr);
42 *offset_ptr += sizeof(val);
43 }
44 return val;
45}
46
47// Get16
48uint16_t DNBDataRef::Get16(offset_t *offset_ptr) const {
49 uint16_t val = 0;
50 if (ValidOffsetForDataOfSize(offset: *offset_ptr, num_bytes: sizeof(val))) {
51 const uint8_t *p = m_start + *offset_ptr;
52 memcpy(dest: &val, src: p, n: sizeof(uint16_t));
53
54 if (m_swap)
55 val = OSSwapInt16(val);
56
57 // Advance the offset
58 *offset_ptr += sizeof(val);
59 }
60 return val;
61}
62
63// Get32
64uint32_t DNBDataRef::Get32(offset_t *offset_ptr) const {
65 uint32_t val = 0;
66 if (ValidOffsetForDataOfSize(offset: *offset_ptr, num_bytes: sizeof(val))) {
67 const uint8_t *p = m_start + *offset_ptr;
68 memcpy(dest: &val, src: p, n: sizeof(uint32_t));
69 if (m_swap)
70 val = OSSwapInt32(val);
71
72 // Advance the offset
73 *offset_ptr += sizeof(val);
74 }
75 return val;
76}
77
78// Get64
79uint64_t DNBDataRef::Get64(offset_t *offset_ptr) const {
80 uint64_t val = 0;
81 if (ValidOffsetForDataOfSize(offset: *offset_ptr, num_bytes: sizeof(val))) {
82 const uint8_t *p = m_start + *offset_ptr;
83 memcpy(dest: &val, src: p, n: sizeof(uint64_t));
84 if (m_swap)
85 val = OSSwapInt64(val);
86
87 // Advance the offset
88 *offset_ptr += sizeof(val);
89 }
90 return val;
91}
92
93// GetMax32
94//
95// Used for calls when the size can vary. Fill in extra cases if they
96// are ever needed.
97uint32_t DNBDataRef::GetMax32(offset_t *offset_ptr, uint32_t byte_size) const {
98 switch (byte_size) {
99 case 1:
100 return Get8(offset_ptr);
101 break;
102 case 2:
103 return Get16(offset_ptr);
104 break;
105 case 4:
106 return Get32(offset_ptr);
107 break;
108 default:
109 assert(false && "GetMax32 unhandled case!");
110 break;
111 }
112 return 0;
113}
114
115// GetMax64
116//
117// Used for calls when the size can vary. Fill in extra cases if they
118// are ever needed.
119uint64_t DNBDataRef::GetMax64(offset_t *offset_ptr, uint32_t size) const {
120 switch (size) {
121 case 1:
122 return Get8(offset_ptr);
123 break;
124 case 2:
125 return Get16(offset_ptr);
126 break;
127 case 4:
128 return Get32(offset_ptr);
129 break;
130 case 8:
131 return Get64(offset_ptr);
132 break;
133 default:
134 assert(false && "GetMax64 unhandled case!");
135 break;
136 }
137 return 0;
138}
139
140// GetPointer
141//
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.
144uint64_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, size: m_ptrSize);
148}
149// GetCStr
150const 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;
155
156 // Advance the offset
157 if (fixed_length)
158 *offset_ptr += fixed_length;
159 else
160 *offset_ptr += strlen(s: s) + 1;
161 }
162 return s;
163}
164
165// GetData
166const 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: *offset_ptr, num_bytes: length)) {
170 data = m_start + *offset_ptr;
171 *offset_ptr += length;
172 }
173 return data;
174}
175
176// Get_ULEB128
177uint64_t DNBDataRef::Get_ULEB128(offset_t *offset_ptr) const {
178 uint64_t result = 0;
179 if (m_start < m_end) {
180 int shift = 0;
181 const uint8_t *src = m_start + *offset_ptr;
182 uint8_t byte;
183 int bytecount = 0;
184
185 while (src < m_end) {
186 bytecount++;
187 byte = *src++;
188 result |= (uint64_t)(byte & 0x7f) << shift;
189 shift += 7;
190 if ((byte & 0x80) == 0)
191 break;
192 }
193
194 *offset_ptr += bytecount;
195 }
196 return result;
197}
198
199// Get_SLEB128
200int64_t DNBDataRef::Get_SLEB128(offset_t *offset_ptr) const {
201 int64_t result = 0;
202
203 if (m_start < m_end) {
204 int shift = 0;
205 int size = sizeof(uint32_t) * 8;
206 const uint8_t *src = m_start + *offset_ptr;
207
208 uint8_t byte = 0;
209 int bytecount = 0;
210
211 while (src < m_end) {
212 bytecount++;
213 byte = *src++;
214 result |= (int64_t)(byte & 0x7f) << shift;
215 shift += 7;
216 if ((byte & 0x80) == 0)
217 break;
218 }
219
220 // Sign bit of byte is 2nd high order bit (0x40)
221 if (shift < size && (byte & 0x40))
222 result |= -(1ll << shift);
223
224 *offset_ptr += bytecount;
225 }
226 return result;
227}
228
229// Skip_LEB128
230//
231// Skips past ULEB128 and SLEB128 numbers (just updates the offset)
232void 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;
236
237 while ((src < m_end) && (*src++ & 0x80))
238 /* Do nothing */;
239
240 *offset_ptr += src - start;
241 }
242}
243
244uint32_t DNBDataRef::Dump(uint32_t startOffset, uint32_t endOffset,
245 uint64_t offsetBase, DNBDataRef::Type type,
246 uint32_t numPerLine, const char *format) {
247 uint32_t offset;
248 uint32_t count;
249 char str[1024];
250 str[0] = '\0';
251 size_t str_offset = 0;
252
253 for (offset = startOffset, count = 0;
254 ValidOffset(offset) && offset < endOffset; ++count) {
255 if ((count % numPerLine) == 0) {
256 // Print out any previous string
257 if (str[0] != '\0')
258 DNBLog("%s", str);
259 // Reset string offset and fill the current line string with address:
260 str_offset = 0;
261 str_offset += snprintf(s: str, maxlen: sizeof(str), format: "0x%8.8llx:",
262 (uint64_t)(offsetBase + (offset - startOffset)));
263 }
264
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
269 // out
270 // and reset the string with no address
271 DNBLog("%s", str);
272 str_offset = 0;
273 str[0] = '\0';
274 }
275
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
279 switch (type) {
280 case TypeUInt8:
281 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
282 format: format ? format : " %2.2x", Get8(offset_ptr: &offset));
283 break;
284 case TypeChar: {
285 char ch = Get8(offset_ptr: &offset);
286 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
287 format: format ? format : " %c", isprint(ch) ? ch : ' ');
288 } break;
289 case TypeUInt16:
290 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
291 format: format ? format : " %4.4x", Get16(offset_ptr: &offset));
292 break;
293 case TypeUInt32:
294 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
295 format: format ? format : " %8.8x", Get32(offset_ptr: &offset));
296 break;
297 case TypeUInt64:
298 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
299 format: format ? format : " %16.16llx", Get64(offset_ptr: &offset));
300 break;
301 case TypePointer:
302 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
303 format: format ? format : " 0x%llx", GetPointer(offset_ptr: &offset));
304 break;
305 case TypeULEB128:
306 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
307 format: format ? format : " 0x%llx", Get_ULEB128(offset_ptr: &offset));
308 break;
309 case TypeSLEB128:
310 str_offset += snprintf(s: str + str_offset, maxlen: sizeof(str) - str_offset,
311 format: format ? format : " %lld", Get_SLEB128(offset_ptr: &offset));
312 break;
313 }
314 }
315
316 if (str[0] != '\0')
317 DNBLog("%s", str);
318
319 return offset; // Return the offset at which we ended up
320}
321

source code of lldb/tools/debugserver/source/DNBDataRef.cpp