]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/DNBDataRef.cpp
Vendor import of lldb release_39 branch r276489:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / DNBDataRef.cpp
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
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
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
56 DNBDataRef::~DNBDataRef()
57 {
58 }
59
60
61 //----------------------------------------------------------------------
62 // Get8
63 //----------------------------------------------------------------------
64 uint8_t
65 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
81 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
103 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
124 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
148 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
170 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
192 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 *
202 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 *
223 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
239 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 |= (uint64_t)(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
269 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 |= (int64_t)(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
308 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
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     size_t 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             case TypeUInt8:   str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %2.2x", Get8(&offset)); break;
366             case TypeChar:
367                 {
368                     char ch = Get8(&offset);
369                     str_offset += snprintf(str + str_offset, sizeof(str) - str_offset, format ? format : " %c",    isprint(ch) ? ch : ' ');
370                 }
371                 break;
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;
378         }
379     }
380
381     if (str[0] != '\0')
382         DNBLog("%s", str);
383
384     return offset;  // Return the offset at which we ended up
385 }