LLDB mainline
DataExtractor.cpp
Go to the documentation of this file.
1//===-- DataExtractor.cpp -------------------------------------------------===//
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
10
11#include "lldb/lldb-defines.h"
13#include "lldb/lldb-forward.h"
14#include "lldb/lldb-types.h"
15
19#include "lldb/Utility/Log.h"
20#include "lldb/Utility/Stream.h"
22#include "lldb/Utility/UUID.h"
23
24#include "llvm/ADT/ArrayRef.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/Support/LEB128.h"
28#include "llvm/Support/MD5.h"
29#include "llvm/Support/MathExtras.h"
30
31#include <algorithm>
32#include <array>
33#include <cassert>
34#include <cstdint>
35#include <string>
36
37#include <cctype>
38#include <cinttypes>
39#include <cstring>
40
41using namespace lldb;
42using namespace lldb_private;
43
44static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) {
45 uint16_t value;
46 memcpy(&value, ptr + offset, 2);
47 return value;
48}
49
50static inline uint32_t ReadInt32(const unsigned char *ptr,
51 offset_t offset = 0) {
52 uint32_t value;
53 memcpy(&value, ptr + offset, 4);
54 return value;
55}
56
57static inline uint64_t ReadInt64(const unsigned char *ptr,
58 offset_t offset = 0) {
59 uint64_t value;
60 memcpy(&value, ptr + offset, 8);
61 return value;
62}
63
64static inline uint16_t ReadInt16(const void *ptr) {
65 uint16_t value;
66 memcpy(&value, ptr, 2);
67 return value;
68}
69
70static inline uint16_t ReadSwapInt16(const unsigned char *ptr,
71 offset_t offset) {
72 uint16_t value;
73 memcpy(&value, ptr + offset, 2);
74 return llvm::byteswap<uint16_t>(value);
75}
76
77static inline uint32_t ReadSwapInt32(const unsigned char *ptr,
78 offset_t offset) {
79 uint32_t value;
80 memcpy(&value, ptr + offset, 4);
81 return llvm::byteswap<uint32_t>(value);
82}
83
84static inline uint64_t ReadSwapInt64(const unsigned char *ptr,
85 offset_t offset) {
86 uint64_t value;
87 memcpy(&value, ptr + offset, 8);
88 return llvm::byteswap<uint64_t>(value);
89}
90
91static inline uint16_t ReadSwapInt16(const void *ptr) {
92 uint16_t value;
93 memcpy(&value, ptr, 2);
94 return llvm::byteswap<uint16_t>(value);
95}
96
97static inline uint32_t ReadSwapInt32(const void *ptr) {
98 uint32_t value;
99 memcpy(&value, ptr, 4);
100 return llvm::byteswap<uint32_t>(value);
101}
102
103static inline uint64_t ReadSwapInt64(const void *ptr) {
104 uint64_t value;
105 memcpy(&value, ptr, 8);
106 return llvm::byteswap<uint64_t>(value);
107}
108
109static inline uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size,
110 ByteOrder byte_order) {
111 uint64_t res = 0;
112 if (byte_order == eByteOrderBig)
113 for (size_t i = 0; i < byte_size; ++i)
114 res = (res << 8) | data[i];
115 else {
116 assert(byte_order == eByteOrderLittle);
117 for (size_t i = 0; i < byte_size; ++i)
118 res = (res << 8) | data[byte_size - 1 - i];
119 }
120 return res;
121}
122
124 : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
125 m_data_sp() {}
126
127// This constructor allows us to use data that is owned by someone else. The
128// data must stay around as long as this object is valid.
129DataExtractor::DataExtractor(const void *data, offset_t length,
130 ByteOrder endian, uint32_t addr_size,
131 uint32_t target_byte_size /*=1*/)
132 : m_start(const_cast<uint8_t *>(static_cast<const uint8_t *>(data))),
133 m_end(const_cast<uint8_t *>(static_cast<const uint8_t *>(data)) + length),
135 m_target_byte_size(target_byte_size) {
136 assert(addr_size >= 1 && addr_size <= 8);
137}
138
139// Make a shared pointer reference to the shared data in "data_sp" and set the
140// endian swapping setting to "swap", and the address size to "addr_size". The
141// shared data reference will ensure the data lives as long as any
142// DataExtractor objects exist that have a reference to this data.
144 uint32_t addr_size,
145 uint32_t target_byte_size /*=1*/)
146 : m_byte_order(endian), m_addr_size(addr_size), m_data_sp(),
147 m_target_byte_size(target_byte_size) {
148 assert(addr_size >= 1 && addr_size <= 8);
149 SetData(data_sp);
150}
151
152// Make a shared pointer reference to the shared data in "data_sp".
154 uint32_t target_byte_size)
155 : m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)),
156 m_data_sp(data_sp), m_target_byte_size(target_byte_size) {
157 if (data_sp)
158 SetData(data_sp);
159}
160
161// Initialize this object with a subset of the data bytes in "data". If "data"
162// contains shared data, then a reference to this shared data will added and
163// the shared data will stay around as long as any object contains a reference
164// to that data. The endian swap and address size settings are copied from
165// "data".
167 offset_t length, uint32_t target_byte_size /*=1*/)
169 m_data_sp(), m_target_byte_size(target_byte_size) {
170 assert(m_addr_size >= 1 && m_addr_size <= 8);
171 if (data.ValidOffset(offset)) {
172 offset_t bytes_available = data.GetByteSize() - offset;
173 if (length > bytes_available)
174 length = bytes_available;
175 SetData(data, offset, length);
176 }
177}
178
185
186// Assignment operator
188 if (this != &rhs) {
189 m_start = rhs.m_start;
190 m_end = rhs.m_end;
193 m_data_sp = rhs.m_data_sp;
194 }
195 return *this;
196}
197
199
200// Clears the object contents back to a default invalid state, and release any
201// references to shared data that this object may contain.
203 m_start = nullptr;
204 m_end = nullptr;
206 m_addr_size = sizeof(void *);
207 m_data_sp.reset();
208}
209
210// If this object contains shared data, this function returns the offset into
211// that shared data. Else zero is returned.
213 if (m_start != nullptr) {
214 const DataBuffer *data = m_data_sp.get();
215 if (data != nullptr) {
216 const uint8_t *data_bytes = data->GetBytes();
217 if (data_bytes != nullptr) {
218 assert(m_start >= data_bytes);
219 return m_start - data_bytes;
220 }
221 }
222 }
223 return 0;
224}
225
226// Set the data with which this object will extract from to data starting at
227// BYTES and set the length of the data to LENGTH bytes long. The data is
228// externally owned must be around at least as long as this object points to
229// the data. No copy of the data is made, this object just refers to this data
230// and can extract from it. If this object refers to any shared data upon
231// entry, the reference to that data will be released. Is SWAP is set to true,
232// any data extracted will be endian swapped.
236 m_data_sp.reset();
237 if (bytes == nullptr || length == 0) {
238 m_start = nullptr;
239 m_end = nullptr;
240 } else {
241 m_start = const_cast<uint8_t *>(static_cast<const uint8_t *>(bytes));
242 m_end = m_start + length;
243 }
244 return GetByteSize();
245}
246
247// Assign the data for this object to be a subrange in "data" starting
248// "data_offset" bytes into "data" and ending "data_length" bytes later. If
249// "data_offset" is not a valid offset into "data", then this object will
250// contain no bytes. If "data_offset" is within "data" yet "data_length" is too
251// large, the length will be capped at the number of bytes remaining in "data".
252// If "data" contains a shared pointer to other data, then a ref counted
253// pointer to that data will be made in this object. If "data" doesn't contain
254// a shared pointer to data, then the bytes referred to in "data" will need to
255// exist at least as long as this object refers to those bytes. The address
256// size and endian swap settings are copied from the current values in "data".
258 offset_t data_offset,
259 offset_t data_length) {
261 assert(m_addr_size >= 1 && m_addr_size <= 8);
262 // If "data" contains shared pointer to data, then we can use that
263 if (data.m_data_sp) {
265 return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset,
266 data_length);
267 }
268
269 // We have a DataExtractor object that just has a pointer to bytes
270 if (data.ValidOffset(data_offset)) {
271 if (data_length > data.GetByteSize() - data_offset)
272 data_length = data.GetByteSize() - data_offset;
273 return SetData(data.GetDataStart() + data_offset, data_length,
274 data.GetByteOrder());
275 }
276 return 0;
277}
278
279// Assign the data for this object to be a subrange of the shared data in
280// "data_sp" starting "data_offset" bytes into "data_sp" and ending
281// "data_length" bytes later. If "data_offset" is not a valid offset into
282// "data_sp", then this object will contain no bytes. If "data_offset" is
283// within "data_sp" yet "data_length" is too large, the length will be capped
284// at the number of bytes remaining in "data_sp". A ref counted pointer to the
285// data in "data_sp" will be made in this object IF the number of bytes this
286// object refers to in greater than zero (if at least one byte was available
287// starting at "data_offset") to ensure the data stays around as long as it is
288// needed. The address size and endian swap settings will remain unchanged from
289// their current settings.
291 offset_t data_offset,
292 offset_t data_length) {
293 m_start = m_end = nullptr;
294
295 if (data_length > 0) {
296 m_data_sp = data_sp;
297 if (data_sp) {
298 const size_t data_size = data_sp->GetByteSize();
299 if (data_offset < data_size) {
300 m_start = data_sp->GetBytes() + data_offset;
301 const size_t bytes_left = data_size - data_offset;
302 // Cap the length of we asked for too many
303 if (data_length <= bytes_left)
304 m_end = m_start + data_length; // We got all the bytes we wanted
305 else
306 m_end = m_start + bytes_left; // Not all the bytes requested were
307 // available in the shared data
308 }
309 }
310 }
311
312 size_t new_size = GetByteSize();
313
314 // Don't hold a shared pointer to the data buffer if we don't share any valid
315 // bytes in the shared buffer.
316 if (new_size == 0)
317 m_data_sp.reset();
318
319 return new_size;
320}
321
322// Extract a single unsigned char from the binary data and update the offset
323// pointed to by "offset_ptr".
324//
325// RETURNS the byte that was extracted, or zero on failure.
326uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
327 const uint8_t *data = static_cast<const uint8_t *>(GetData(offset_ptr, 1));
328 if (data)
329 return *data;
330 return 0;
331}
332
333// Extract "count" unsigned chars from the binary data and update the offset
334// pointed to by "offset_ptr". The extracted data is copied into "dst".
335//
336// RETURNS the non-nullptr buffer pointer upon successful extraction of
337// all the requested bytes, or nullptr when the data is not available in the
338// buffer due to being out of bounds, or insufficient data.
339void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
340 uint32_t count) const {
341 const uint8_t *data =
342 static_cast<const uint8_t *>(GetData(offset_ptr, count));
343 if (data) {
344 // Copy the data into the buffer
345 memcpy(dst, data, count);
346 // Return a non-nullptr pointer to the converted data as an indicator of
347 // success
348 return dst;
349 }
350 return nullptr;
351}
352
353// Extract a single uint16_t from the data and update the offset pointed to by
354// "offset_ptr".
355//
356// RETURNS the uint16_t that was extracted, or zero on failure.
357uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const {
358 uint16_t val = 0;
359 const uint8_t *data =
360 static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
361 if (data) {
363 val = ReadSwapInt16(data);
364 else
365 val = ReadInt16(data);
366 }
367 return val;
368}
369
370uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const {
371 uint16_t val;
373 val = ReadInt16(m_start, *offset_ptr);
374 else
375 val = ReadSwapInt16(m_start, *offset_ptr);
376 *offset_ptr += sizeof(val);
377 return val;
378}
379
380uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const {
381 uint32_t val;
383 val = ReadInt32(m_start, *offset_ptr);
384 else
385 val = ReadSwapInt32(m_start, *offset_ptr);
386 *offset_ptr += sizeof(val);
387 return val;
388}
389
390uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
391 uint64_t val;
393 val = ReadInt64(m_start, *offset_ptr);
394 else
395 val = ReadSwapInt64(m_start, *offset_ptr);
396 *offset_ptr += sizeof(val);
397 return val;
398}
399
400// Extract "count" uint16_t values from the binary data and update the offset
401// pointed to by "offset_ptr". The extracted data is copied into "dst".
402//
403// RETURNS the non-nullptr buffer pointer upon successful extraction of
404// all the requested bytes, or nullptr when the data is not available in the
405// buffer due to being out of bounds, or insufficient data.
406void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
407 uint32_t count) const {
408 const size_t src_size = sizeof(uint16_t) * count;
409 const uint16_t *src =
410 static_cast<const uint16_t *>(GetData(offset_ptr, src_size));
411 if (src) {
413 uint16_t *dst_pos = static_cast<uint16_t *>(void_dst);
414 uint16_t *dst_end = dst_pos + count;
415 const uint16_t *src_pos = src;
416 while (dst_pos < dst_end) {
417 *dst_pos = ReadSwapInt16(src_pos);
418 ++dst_pos;
419 ++src_pos;
420 }
421 } else {
422 memcpy(void_dst, src, src_size);
423 }
424 // Return a non-nullptr pointer to the converted data as an indicator of
425 // success
426 return void_dst;
427 }
428 return nullptr;
429}
430
431// Extract a single uint32_t from the data and update the offset pointed to by
432// "offset_ptr".
433//
434// RETURNS the uint32_t that was extracted, or zero on failure.
435uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
436 uint32_t val = 0;
437 const uint8_t *data =
438 static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
439 if (data) {
441 val = ReadSwapInt32(data);
442 } else {
443 memcpy(&val, data, 4);
444 }
445 }
446 return val;
447}
448
449// Extract "count" uint32_t values from the binary data and update the offset
450// pointed to by "offset_ptr". The extracted data is copied into "dst".
451//
452// RETURNS the non-nullptr buffer pointer upon successful extraction of
453// all the requested bytes, or nullptr when the data is not available in the
454// buffer due to being out of bounds, or insufficient data.
455void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
456 uint32_t count) const {
457 const size_t src_size = sizeof(uint32_t) * count;
458 const uint32_t *src =
459 static_cast<const uint32_t *>(GetData(offset_ptr, src_size));
460 if (src) {
462 uint32_t *dst_pos = static_cast<uint32_t *>(void_dst);
463 uint32_t *dst_end = dst_pos + count;
464 const uint32_t *src_pos = src;
465 while (dst_pos < dst_end) {
466 *dst_pos = ReadSwapInt32(src_pos);
467 ++dst_pos;
468 ++src_pos;
469 }
470 } else {
471 memcpy(void_dst, src, src_size);
472 }
473 // Return a non-nullptr pointer to the converted data as an indicator of
474 // success
475 return void_dst;
476 }
477 return nullptr;
478}
479
480// Extract a single uint64_t from the data and update the offset pointed to by
481// "offset_ptr".
482//
483// RETURNS the uint64_t that was extracted, or zero on failure.
484uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
485 uint64_t val = 0;
486 const uint8_t *data =
487 static_cast<const uint8_t *>(GetData(offset_ptr, sizeof(val)));
488 if (data) {
490 val = ReadSwapInt64(data);
491 } else {
492 memcpy(&val, data, 8);
493 }
494 }
495 return val;
496}
497
498// GetU64
499//
500// Get multiple consecutive 64 bit values. Return true if the entire read
501// succeeds and increment the offset pointed to by offset_ptr, else return
502// false and leave the offset pointed to by offset_ptr unchanged.
503void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
504 uint32_t count) const {
505 const size_t src_size = sizeof(uint64_t) * count;
506 const uint64_t *src =
507 static_cast<const uint64_t *>(GetData(offset_ptr, src_size));
508 if (src) {
510 uint64_t *dst_pos = static_cast<uint64_t *>(void_dst);
511 uint64_t *dst_end = dst_pos + count;
512 const uint64_t *src_pos = src;
513 while (dst_pos < dst_end) {
514 *dst_pos = ReadSwapInt64(src_pos);
515 ++dst_pos;
516 ++src_pos;
517 }
518 } else {
519 memcpy(void_dst, src, src_size);
520 }
521 // Return a non-nullptr pointer to the converted data as an indicator of
522 // success
523 return void_dst;
524 }
525 return nullptr;
526}
527
529 size_t byte_size) const {
530 lldbassert(byte_size > 0 && byte_size <= 4 && "GetMaxU32 invalid byte_size!");
531 return GetMaxU64(offset_ptr, byte_size);
532}
533
535 size_t byte_size) const {
536 lldbassert(byte_size > 0 && byte_size <= 8 && "GetMaxU64 invalid byte_size!");
537 switch (byte_size) {
538 case 1:
539 return GetU8(offset_ptr);
540 case 2:
541 return GetU16(offset_ptr);
542 case 4:
543 return GetU32(offset_ptr);
544 case 8:
545 return GetU64(offset_ptr);
546 default: {
547 // General case.
548 const uint8_t *data =
549 static_cast<const uint8_t *>(GetData(offset_ptr, byte_size));
550 if (data == nullptr)
551 return 0;
552 return ReadMaxInt64(data, byte_size, m_byte_order);
553 }
554 }
555 return 0;
556}
557
559 size_t byte_size) const {
560 switch (byte_size) {
561 case 1:
562 return GetU8_unchecked(offset_ptr);
563 case 2:
564 return GetU16_unchecked(offset_ptr);
565 case 4:
566 return GetU32_unchecked(offset_ptr);
567 case 8:
568 return GetU64_unchecked(offset_ptr);
569 default: {
570 uint64_t res = ReadMaxInt64(&m_start[*offset_ptr], byte_size, m_byte_order);
571 *offset_ptr += byte_size;
572 return res;
573 }
574 }
575 return 0;
576}
577
578int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t byte_size) const {
579 uint64_t u64 = GetMaxU64(offset_ptr, byte_size);
580 return llvm::SignExtend64(u64, 8 * byte_size);
581}
582
583uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size,
584 uint32_t bitfield_bit_size,
585 uint32_t bitfield_bit_offset) const {
586 assert(bitfield_bit_size <= 64);
587 uint64_t uval64 = GetMaxU64(offset_ptr, size);
588
589 if (bitfield_bit_size == 0)
590 return uval64;
591
592 int32_t lsbcount = bitfield_bit_offset;
594 lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
595
596 if (lsbcount > 0)
597 uval64 >>= lsbcount;
598
599 uint64_t bitfield_mask =
600 (bitfield_bit_size == 64
601 ? std::numeric_limits<uint64_t>::max()
602 : ((static_cast<uint64_t>(1) << bitfield_bit_size) - 1));
603 if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64)
604 return uval64;
605
606 uval64 &= bitfield_mask;
607
608 return uval64;
609}
610
611int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size,
612 uint32_t bitfield_bit_size,
613 uint32_t bitfield_bit_offset) const {
614 assert(size >= 1 && "GetMaxS64Bitfield size must be >= 1");
615 assert(size <= 8 && "GetMaxS64Bitfield size must be <= 8");
616 int64_t sval64 = GetMaxS64(offset_ptr, size);
617 if (bitfield_bit_size == 0)
618 return sval64;
619 int32_t lsbcount = bitfield_bit_offset;
621 lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size;
622 if (lsbcount > 0)
623 sval64 >>= lsbcount;
624 uint64_t bitfield_mask = llvm::maskTrailingOnes<uint64_t>(bitfield_bit_size);
625 sval64 &= bitfield_mask;
626 // sign extend if needed
627 if (sval64 & ((static_cast<uint64_t>(1)) << (bitfield_bit_size - 1)))
628 sval64 |= ~bitfield_mask;
629 return sval64;
630}
631
632float DataExtractor::GetFloat(offset_t *offset_ptr) const {
633 return Get<float>(offset_ptr, 0.0f);
634}
635
636double DataExtractor::GetDouble(offset_t *offset_ptr) const {
637 return Get<double>(offset_ptr, 0.0);
638}
639
640long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
641 long double val = 0.0;
642#if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) || \
643 defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64)
644 *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val),
646#else
647 *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val,
648 sizeof(val), endian::InlHostByteOrder());
649#endif
650 return val;
651}
652
653// Extract a single address from the data and update the offset pointed to by
654// "offset_ptr". The size of the extracted address comes from the
655// "this->m_addr_size" member variable and should be set correctly prior to
656// extracting any address values.
657//
658// RETURNS the address that was extracted, or zero on failure.
659uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const {
660 assert(m_addr_size >= 1 && m_addr_size <= 8);
661 return GetMaxU64(offset_ptr, m_addr_size);
662}
663
665 assert(m_addr_size >= 1 && m_addr_size <= 8);
666 return GetMaxU64_unchecked(offset_ptr, m_addr_size);
667}
668
670 ByteOrder dst_byte_order, void *dst) const {
671 const uint8_t *src = PeekData(offset, length);
672 if (src) {
673 if (dst_byte_order != GetByteOrder()) {
674 for (uint32_t i = 0; i < length; ++i)
675 (static_cast<uint8_t *>(dst))[i] = src[length - i - 1];
676 } else
677 ::memcpy(dst, src, length);
678 return length;
679 }
680 return 0;
681}
682
683// Extract data as it exists in target memory
685 void *dst) const {
686 const uint8_t *src = PeekData(offset, length);
687 if (src) {
688 ::memcpy(dst, src, length);
689 return length;
690 }
691 return 0;
692}
693
694// Extract data and swap if needed when doing the copy
697 void *dst_void_ptr, offset_t dst_len,
698 ByteOrder dst_byte_order) const {
699 // Validate the source info
700 if (!ValidOffsetForDataOfSize(src_offset, src_len))
701 assert(ValidOffsetForDataOfSize(src_offset, src_len));
702 assert(src_len > 0);
704
705 // Validate the destination info
706 assert(dst_void_ptr != nullptr);
707 assert(dst_len > 0);
708 assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
709
710 // Validate that only a word- or register-sized dst is byte swapped
711 assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 ||
712 dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
713 dst_len == 32);
714
715 // Must have valid byte orders set in this object and for destination
716 if (!(dst_byte_order == eByteOrderBig ||
717 dst_byte_order == eByteOrderLittle) ||
719 return 0;
720
721 uint8_t *dst = static_cast<uint8_t *>(dst_void_ptr);
722 const uint8_t *src = PeekData(src_offset, src_len);
723 if (src) {
724 if (dst_len >= src_len) {
725 // We are copying the entire value from src into dst. Calculate how many,
726 // if any, zeroes we need for the most significant bytes if "dst_len" is
727 // greater than "src_len"...
728 const size_t num_zeroes = dst_len - src_len;
729 if (dst_byte_order == eByteOrderBig) {
730 // Big endian, so we lead with zeroes...
731 if (num_zeroes > 0)
732 ::memset(dst, 0, num_zeroes);
733 // Then either copy or swap the rest
735 ::memcpy(dst + num_zeroes, src, src_len);
736 } else {
737 for (uint32_t i = 0; i < src_len; ++i)
738 dst[i + num_zeroes] = src[src_len - 1 - i];
739 }
740 } else {
741 // Little endian destination, so we lead the value bytes
743 for (uint32_t i = 0; i < src_len; ++i)
744 dst[i] = src[src_len - 1 - i];
745 } else {
746 ::memcpy(dst, src, src_len);
747 }
748 // And zero the rest...
749 if (num_zeroes > 0)
750 ::memset(dst + src_len, 0, num_zeroes);
751 }
752 return src_len;
753 } else {
754 // We are only copying some of the value from src into dst..
755
756 if (dst_byte_order == eByteOrderBig) {
757 // Big endian dst
759 // Big endian dst, with big endian src
760 ::memcpy(dst, src + (src_len - dst_len), dst_len);
761 } else {
762 // Big endian dst, with little endian src
763 for (uint32_t i = 0; i < dst_len; ++i)
764 dst[i] = src[dst_len - 1 - i];
765 }
766 } else {
767 // Little endian dst
769 // Little endian dst, with big endian src
770 for (uint32_t i = 0; i < dst_len; ++i)
771 dst[i] = src[src_len - 1 - i];
772 } else {
773 // Little endian dst, with big endian src
774 ::memcpy(dst, src, dst_len);
775 }
776 }
777 return dst_len;
778 }
779 }
780 return 0;
781}
782
783// Extracts a variable length NULL terminated C string from the data at the
784// offset pointed to by "offset_ptr". The "offset_ptr" will be updated with
785// the offset of the byte that follows the NULL terminator byte.
786//
787// If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is
788// non-zero and there aren't enough available bytes, nullptr will be returned
789// and "offset_ptr" will not be updated.
790const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
791 const char *start = reinterpret_cast<const char *>(PeekData(*offset_ptr, 1));
792 // Already at the end of the data.
793 if (!start)
794 return nullptr;
795
796 const char *end = reinterpret_cast<const char *>(m_end);
797
798 // Check all bytes for a null terminator that terminates a C string.
799 const char *terminator_or_end = std::find(start, end, '\0');
800
801 // We didn't find a null terminator, so return nullptr to indicate that there
802 // is no valid C string at that offset.
803 if (terminator_or_end == end)
804 return nullptr;
805
806 // Update offset_ptr for the caller to point to the data behind the
807 // terminator (which is 1 byte long).
808 *offset_ptr += (terminator_or_end - start + 1UL);
809 return start;
810}
811
812// Extracts a NULL terminated C string from the fixed length field of length
813// "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be
814// updated with the offset of the byte that follows the fixed length field.
815//
816// If the offset pointed to by "offset_ptr" is out of bounds, or if the offset
817// plus the length of the field is out of bounds, or if the field does not
818// contain a NULL terminator byte, nullptr will be returned and "offset_ptr"
819// will not be updated.
820const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
821 const char *cstr = reinterpret_cast<const char *>(PeekData(*offset_ptr, len));
822 if (cstr != nullptr) {
823 if (memchr(cstr, '\0', len) == nullptr) {
824 return nullptr;
825 }
826 *offset_ptr += len;
827 return cstr;
828 }
829 return nullptr;
830}
831
832// Peeks at a string in the contained data. No verification is done to make
833// sure the entire string lies within the bounds of this object's data, only
834// "offset" is verified to be a valid offset.
835//
836// Returns a valid C string pointer if "offset" is a valid offset in this
837// object's data, else nullptr is returned.
838const char *DataExtractor::PeekCStr(offset_t offset) const {
839 return reinterpret_cast<const char *>(PeekData(offset, 1));
840}
841
842// Extracts an unsigned LEB128 number from this object's data starting at the
843// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
844// will be updated with the offset of the byte following the last extracted
845// byte.
846//
847// Returned the extracted integer value.
848uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
849 const uint8_t *src = PeekData(*offset_ptr, 1);
850 if (src == nullptr)
851 return 0;
852
853 unsigned byte_count = 0;
854 uint64_t result = llvm::decodeULEB128(src, &byte_count, m_end);
855 *offset_ptr += byte_count;
856 return result;
857}
858
859// Extracts an signed LEB128 number from this object's data starting at the
860// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
861// will be updated with the offset of the byte following the last extracted
862// byte.
863//
864// Returned the extracted integer value.
865int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
866 const uint8_t *src = PeekData(*offset_ptr, 1);
867 if (src == nullptr)
868 return 0;
869
870 unsigned byte_count = 0;
871 int64_t result = llvm::decodeSLEB128(src, &byte_count, m_end);
872 *offset_ptr += byte_count;
873 return result;
874}
875
876// Skips a ULEB128 number (signed or unsigned) from this object's data starting
877// at the offset pointed to by "offset_ptr". The offset pointed to by
878// "offset_ptr" will be updated with the offset of the byte following the last
879// extracted byte.
880//
881// Returns the number of bytes consumed during the extraction.
882uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
883 uint32_t bytes_consumed = 0;
884 const uint8_t *src = PeekData(*offset_ptr, 1);
885 if (src == nullptr)
886 return 0;
887
888 const uint8_t *end = m_end;
889
890 if (src < end) {
891 const uint8_t *src_pos = src;
892 while ((src_pos < end) && (*src_pos++ & 0x80))
893 ++bytes_consumed;
894 *offset_ptr += src_pos - src;
895 }
896 return bytes_consumed;
897}
898
899// Dumps bytes from this object's data to the stream "s" starting
900// "start_offset" bytes into this data, and ending with the byte before
901// "end_offset". "base_addr" will be added to the offset into the dumped data
902// when showing the offset into the data in the output information.
903// "num_per_line" objects of type "type" will be dumped with the option to
904// override the format for each object with "type_format". "type_format" is a
905// printf style formatting string. If "type_format" is nullptr, then an
906// appropriate format string will be used for the supplied "type". If the
907// stream "s" is nullptr, then the output will be send to Log().
909 offset_t length, uint64_t base_addr,
910 uint32_t num_per_line,
911 DataExtractor::Type type) const {
912 if (log == nullptr)
913 return start_offset;
914
915 offset_t offset;
916 offset_t end_offset;
917 uint32_t count;
918 StreamString sstr;
919 for (offset = start_offset, end_offset = offset + length, count = 0;
920 ValidOffset(offset) && offset < end_offset; ++count) {
921 if ((count % num_per_line) == 0) {
922 // Print out any previous string
923 if (sstr.GetSize() > 0) {
924 log->PutString(sstr.GetString());
925 sstr.Clear();
926 }
927 // Reset string offset and fill the current line string with address:
928 if (base_addr != LLDB_INVALID_ADDRESS)
929 sstr.Printf("0x%8.8" PRIx64 ":",
930 static_cast<uint64_t>(base_addr + (offset - start_offset)));
931 }
932
933 switch (type) {
934 case TypeUInt8:
935 sstr.Printf(" %2.2x", GetU8(&offset));
936 break;
937 case TypeChar: {
938 char ch = GetU8(&offset);
939 sstr.Printf(" %c", llvm::isPrint(ch) ? ch : ' ');
940 } break;
941 case TypeUInt16:
942 sstr.Printf(" %4.4x", GetU16(&offset));
943 break;
944 case TypeUInt32:
945 sstr.Printf(" %8.8x", GetU32(&offset));
946 break;
947 case TypeUInt64:
948 sstr.Printf(" %16.16" PRIx64, GetU64(&offset));
949 break;
950 case TypePointer:
951 sstr.Printf(" 0x%" PRIx64, GetAddress(&offset));
952 break;
953 case TypeULEB128:
954 sstr.Printf(" 0x%" PRIx64, GetULEB128(&offset));
955 break;
956 case TypeSLEB128:
957 sstr.Printf(" %" PRId64, GetSLEB128(&offset));
958 break;
959 }
960 }
961
962 if (!sstr.Empty())
963 log->PutString(sstr.GetString());
964
965 return offset; // Return the offset at which we ended up
966}
967
968size_t DataExtractor::Copy(DataExtractor &dest_data) const {
969 if (m_data_sp) {
970 // we can pass along the SP to the data
971 dest_data.SetData(m_data_sp);
972 } else {
973 const uint8_t *base_ptr = m_start;
974 size_t data_size = GetByteSize();
975 dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size)));
976 }
977 return GetByteSize();
978}
979
981 if (rhs.GetByteOrder() != GetByteOrder())
982 return false;
983
984 if (rhs.GetByteSize() == 0)
985 return true;
986
987 if (GetByteSize() == 0)
988 return (rhs.Copy(*this) > 0);
989
990 size_t bytes = GetByteSize() + rhs.GetByteSize();
991
992 DataBufferHeap *buffer_heap_ptr = nullptr;
993 DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
994
995 if (!buffer_sp || buffer_heap_ptr == nullptr)
996 return false;
997
998 uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
999
1000 memcpy(bytes_ptr, GetDataStart(), GetByteSize());
1001 memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize());
1002
1003 SetData(buffer_sp);
1004
1005 return true;
1006}
1007
1008bool DataExtractor::Append(void *buf, offset_t length) {
1009 if (buf == nullptr)
1010 return false;
1011
1012 if (length == 0)
1013 return true;
1014
1015 size_t bytes = GetByteSize() + length;
1016
1017 DataBufferHeap *buffer_heap_ptr = nullptr;
1018 DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0));
1019
1020 if (!buffer_sp || buffer_heap_ptr == nullptr)
1021 return false;
1022
1023 uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes();
1024
1025 if (GetByteSize() > 0)
1026 memcpy(bytes_ptr, GetDataStart(), GetByteSize());
1027
1028 memcpy(bytes_ptr + GetByteSize(), buf, length);
1029
1030 SetData(buffer_sp);
1031
1032 return true;
1033}
1034
1036 uint64_t max_data) {
1037 if (max_data == 0)
1038 max_data = GetByteSize();
1039 else
1040 max_data = std::min(max_data, GetByteSize());
1041
1042 llvm::MD5 md5;
1043
1044 const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data);
1045 md5.update(data);
1046
1047 llvm::MD5::MD5Result result;
1048 md5.final(result);
1049
1050 dest.clear();
1051 dest.append(result.begin(), result.end());
1052}
static uint64_t ReadSwapInt64(const unsigned char *ptr, offset_t offset)
static uint64_t ReadInt64(const unsigned char *ptr, offset_t offset=0)
static uint16_t ReadSwapInt16(const unsigned char *ptr, offset_t offset)
static uint16_t ReadInt16(const unsigned char *ptr, offset_t offset)
static uint32_t ReadInt32(const unsigned char *ptr, offset_t offset=0)
static uint64_t ReadMaxInt64(const uint8_t *data, size_t byte_size, ByteOrder byte_order)
static uint32_t ReadSwapInt32(const unsigned char *ptr, offset_t offset)
#define lldbassert(x)
Definition LLDBAssert.h:16
A subclass of DataBuffer that stores a data buffer on the heap.
A pure virtual protocol class for abstracted read only data buffers.
Definition DataBuffer.h:42
const uint8_t * GetBytes() const
Get a const pointer to the data.
Definition DataBuffer.h:57
uint64_t GetULEB128(lldb::offset_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
size_t GetSharedDataOffset() const
Get the shared data offset.
float GetFloat(lldb::offset_t *offset_ptr) const
Extract a float from *offset_ptr.
virtual uint32_t GetU32_unchecked(lldb::offset_t *offset_ptr) const
const char * GetCStr(lldb::offset_t *offset_ptr) const
Extract a C string from *offset_ptr.
size_t Copy(DataExtractor &dest_data) const
T Get(lldb::offset_t *offset_ptr, T fail_value) const
int64_t GetMaxS64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an signed integer of size byte_size from *offset_ptr.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
bool ValidOffsetForDataOfSize(lldb::offset_t offset, lldb::offset_t length) const
Test the availability of length bytes of data from offset.
long double GetLongDouble(lldb::offset_t *offset_ptr) const
void Clear()
Clears the object state.
const uint8_t * m_start
A pointer to the first byte of data.
lldb::DataBufferSP m_data_sp
The shared pointer to data that can be shared among multiple instances.
uint32_t GetMaxU32(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an integer of size byte_size from *offset_ptr.
virtual const uint8_t * PeekData(lldb::offset_t offset, lldb::offset_t length) const
Peek at a bytes at offset.
uint64_t GetAddress_unchecked(lldb::offset_t *offset_ptr) const
const DataExtractor & operator=(const DataExtractor &rhs)
Assignment operator.
lldb::offset_t CopyData(lldb::offset_t offset, lldb::offset_t length, void *dst) const
Copy length bytes from *offset, without swapping bytes.
uint64_t GetMaxU64_unchecked(lldb::offset_t *offset_ptr, size_t byte_size) const
uint32_t Skip_LEB128(lldb::offset_t *offset_ptr) const
Skip an LEB128 number at *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
const uint8_t * m_end
A pointer to the byte that is past the end of the data.
DataExtractor()
Default constructor.
uint32_t m_target_byte_size
Making it const would require implementation of move assignment operator.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint64_t GetAddress(lldb::offset_t *offset_ptr) const
Extract an address from *offset_ptr.
Type
Type enumerations used in the dump routines.
@ TypeUInt32
Format output as unsigned 32 bit integers.
@ TypeSLEB128
Format output as SLEB128 numbers.
@ TypeUInt8
Format output as unsigned 8 bit integers.
@ TypeUInt64
Format output as unsigned 64 bit integers.
@ TypeULEB128
Format output as ULEB128 numbers.
@ TypePointer
Format output as pointers.
@ TypeUInt16
Format output as unsigned 16 bit integers.
@ TypeChar
Format output as characters.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint64_t GetMaxU64Bitfield(lldb::offset_t *offset_ptr, size_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const
Extract an unsigned integer of size byte_size from *offset_ptr, then extract the bitfield from this v...
lldb::ByteOrder m_byte_order
The byte order of the data we are extracting from.
void Checksum(llvm::SmallVectorImpl< uint8_t > &dest, uint64_t max_data=0)
bool Append(DataExtractor &rhs)
const uint8_t * GetDataStart() const
Get the data start pointer.
bool ValidOffset(lldb::offset_t offset) const
Test the validity of offset.
lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
uint32_t m_addr_size
The address size to use when extracting addresses.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
virtual uint8_t GetU8_unchecked(lldb::offset_t *offset_ptr) const
int64_t GetSLEB128(lldb::offset_t *offset_ptr) const
Extract a signed LEB128 value from *offset_ptr.
virtual uint64_t GetU64_unchecked(lldb::offset_t *offset_ptr) const
llvm::ArrayRef< uint8_t > GetData() const
int64_t GetMaxS64Bitfield(lldb::offset_t *offset_ptr, size_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const
Extract an signed integer of size size from *offset_ptr, then extract and sign-extend the bitfield fr...
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
virtual uint16_t GetU16_unchecked(lldb::offset_t *offset_ptr) const
lldb::offset_t PutToLog(Log *log, lldb::offset_t offset, lldb::offset_t length, uint64_t base_addr, uint32_t num_per_line, Type type) const
Dumps the binary data as type objects to stream s (or to Log() if s is nullptr) starting offset bytes...
lldb::offset_t CopyByteOrderedData(lldb::offset_t src_offset, lldb::offset_t src_len, void *dst, lldb::offset_t dst_len, lldb::ByteOrder dst_byte_order) const
Copy dst_len bytes from *offset_ptr and ensure the copied data is treated as a value that can be swap...
double GetDouble(lldb::offset_t *offset_ptr) const
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
const char * PeekCStr(lldb::offset_t offset) const
Peek at a C string at offset.
virtual ~DataExtractor()
Destructor.
size_t ExtractBytes(lldb::offset_t offset, lldb::offset_t length, lldb::ByteOrder dst_byte_order, void *dst) const
Extract an arbitrary number of bytes in the specified byte order.
void PutString(llvm::StringRef str)
Definition Log.cpp:147
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
uint8_t * GetBytes()
Get a pointer to the data.
Definition DataBuffer.h:108
#define LLDB_INVALID_ADDRESS
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
uint64_t offset_t
Definition lldb-types.h:85
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP