1//===-- DumpDataExtractor.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
9#include "lldb/Core/DumpDataExtractor.h"
10
11#include "lldb/lldb-defines.h"
12#include "lldb/lldb-forward.h"
13
14#include "lldb/Core/Address.h"
15#include "lldb/Core/Disassembler.h"
16#include "lldb/Core/ModuleList.h"
17#include "lldb/Target/ABI.h"
18#include "lldb/Target/ExecutionContext.h"
19#include "lldb/Target/ExecutionContextScope.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Target/SectionLoadList.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Utility/DataExtractor.h"
24#include "lldb/Utility/Log.h"
25#include "lldb/Utility/Stream.h"
26
27#include "llvm/ADT/APFloat.h"
28#include "llvm/ADT/APInt.h"
29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/Optional.h"
31#include "llvm/ADT/SmallVector.h"
32
33#include <limits>
34#include <memory>
35#include <string>
36
37#include <assert.h>
38#include <ctype.h>
39#include <inttypes.h>
40#include <math.h>
41
42#include <bitset>
43#include <sstream>
44
45using namespace lldb_private;
46using namespace lldb;
47
48#define NON_PRINTABLE_CHAR '.'
49
50static float half2float(uint16_t half) {
51 union {
52 float f;
53 uint32_t u;
54 } u;
55 int32_t v = (int16_t)half;
56
57 if (0 == (v & 0x7c00)) {
58 u.u = v & 0x80007FFFU;
59 return u.f * ldexpf(1, 125);
60 }
61
62 v <<= 13;
63 u.u = v | 0x70000000U;
64 return u.f * ldexpf(1, -112);
65}
66
67static llvm::Optional<llvm::APInt> GetAPInt(const DataExtractor &data,
68 lldb::offset_t *offset_ptr,
69 lldb::offset_t byte_size) {
70 if (byte_size == 0)
71 return llvm::None;
72
73 llvm::SmallVector<uint64_t, 2> uint64_array;
74 lldb::offset_t bytes_left = byte_size;
75 uint64_t u64;
76 const lldb::ByteOrder byte_order = data.GetByteOrder();
77 if (byte_order == lldb::eByteOrderLittle) {
78 while (bytes_left > 0) {
79 if (bytes_left >= 8) {
80 u64 = data.GetU64(offset_ptr);
81 bytes_left -= 8;
82 } else {
83 u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
84 bytes_left = 0;
85 }
86 uint64_array.push_back(u64);
87 }
88 return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
89 } else if (byte_order == lldb::eByteOrderBig) {
90 lldb::offset_t be_offset = *offset_ptr + byte_size;
91 lldb::offset_t temp_offset;
92 while (bytes_left > 0) {
93 if (bytes_left >= 8) {
94 be_offset -= 8;
95 temp_offset = be_offset;
96 u64 = data.GetU64(&temp_offset);
97 bytes_left -= 8;
98 } else {
99 be_offset -= bytes_left;
100 temp_offset = be_offset;
101 u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
102 bytes_left = 0;
103 }
104 uint64_array.push_back(u64);
105 }
106 *offset_ptr += byte_size;
107 return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
108 }
109 return llvm::None;
110}
111
112static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
113 lldb::offset_t offset, lldb::offset_t byte_size,
114 bool is_signed, unsigned radix) {
115 llvm::Optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size);
116 if (apint.hasValue()) {
117 std::string apint_str(apint.getValue().toString(radix, is_signed));
118 switch (radix) {
119 case 2:
120 s->Write("0b", 2);
121 break;
122 case 8:
123 s->Write("0", 1);
124 break;
125 case 10:
126 break;
127 }
128 s->Write(apint_str.c_str(), apint_str.size());
129 }
130 return offset;
131}
132
133/// Dumps decoded instructions to a stream.
134static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,
135 ExecutionContextScope *exe_scope,
136 offset_t start_offset,
137 uint64_t base_addr,
138 size_t number_of_instructions) {
139 offset_t offset = start_offset;
140
141 TargetSP target_sp;
142 if (exe_scope)
143 target_sp = exe_scope->CalculateTarget();
144 if (target_sp) {
145 DisassemblerSP disassembler_sp(
146 Disassembler::FindPlugin(target_sp->GetArchitecture(),
147 target_sp->GetDisassemblyFlavor(), nullptr));
148 if (disassembler_sp) {
149 lldb::addr_t addr = base_addr + start_offset;
150 lldb_private::Address so_addr;
151 bool data_from_file = true;
152 if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
153 data_from_file = false;
154 } else {
155 if (target_sp->GetSectionLoadList().IsEmpty() ||
156 !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
157 so_addr.SetRawAddress(addr);
158 }
159
160 size_t bytes_consumed = disassembler_sp->DecodeInstructions(
161 so_addr, DE, start_offset, number_of_instructions, false,
162 data_from_file);
163
164 if (bytes_consumed) {
165 offset += bytes_consumed;
166 const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
167 const bool show_bytes = true;
168 ExecutionContext exe_ctx;
169 exe_scope->CalculateExecutionContext(exe_ctx);
170 disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes,
171 &exe_ctx);
172 }
173 }
174 } else
175 s->Printf("invalid target");
176
177 return offset;
178}
179
180/// Prints the specific escape sequence of the given character to the stream.
181/// If the character doesn't have a known specific escape sequence (e.g., '\a',
182/// '\n' but not generic escape sequences such as'\x12'), this function will
183/// not modify the stream and return false.
184static bool TryDumpSpecialEscapedChar(Stream &s, const char c) {
185 switch (c) {
186 case '\033':
187 // Common non-standard escape code for 'escape'.
188 s.Printf("\\e");
189 return true;
190 case '\a':
191 s.Printf("\\a");
192 return true;
193 case '\b':
194 s.Printf("\\b");
195 return true;
196 case '\f':
197 s.Printf("\\f");
198 return true;
199 case '\n':
200 s.Printf("\\n");
201 return true;
202 case '\r':
203 s.Printf("\\r");
204 return true;
205 case '\t':
206 s.Printf("\\t");
207 return true;
208 case '\v':
209 s.Printf("\\v");
210 return true;
211 case '\0':
212 s.Printf("\\0");
213 return true;
214 default:
215 return false;
216 }
217}
218
219/// Dump the character to a stream. A character that is not printable will be
220/// represented by its escape sequence.
221static void DumpCharacter(Stream &s, const char c) {
222 if (TryDumpSpecialEscapedChar(s, c))
223 return;
224 if (llvm::isPrint(c)) {
225 s.PutChar(c);
226 return;
227 }
228 s.Printf("\\x%2.2x", c);
229}
230
231lldb::offset_t lldb_private::DumpDataExtractor(
232 const DataExtractor &DE, Stream *s, offset_t start_offset,
233 lldb::Format item_format, size_t item_byte_size, size_t item_count,
234 size_t num_per_line, uint64_t base_addr,
235 uint32_t item_bit_size, // If zero, this is not a bitfield value, if
236 // non-zero, the value is a bitfield
237 uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
238 // shift amount to apply to a bitfield
239 ExecutionContextScope *exe_scope) {
240 if (s == nullptr)
241 return start_offset;
242
243 if (item_format == eFormatPointer) {
244 if (item_byte_size != 4 && item_byte_size != 8)
245 item_byte_size = s->GetAddressByteSize();
246 }
247
248 offset_t offset = start_offset;
249
250 if (item_format == eFormatInstruction)
251 return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
252 item_count);
253
254 if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
255 item_byte_size > 8)
256 item_format = eFormatHex;
257
258 lldb::offset_t line_start_offset = start_offset;
259 for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
260 ++count) {
261 if ((count % num_per_line) == 0) {
262 if (count > 0) {
263 if (item_format == eFormatBytesWithASCII &&
264 offset > line_start_offset) {
265 s->Printf("%*s",
266 static_cast<int>(
267 (num_per_line - (offset - line_start_offset)) * 3 + 2),
268 "");
269 DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
270 offset - line_start_offset, SIZE_MAX,
271 LLDB_INVALID_ADDRESS, 0, 0);
272 }
273 s->EOL();
274 }
275 if (base_addr != LLDB_INVALID_ADDRESS)
276 s->Printf("0x%8.8" PRIx64 ": ",
277 (uint64_t)(base_addr +
278 (offset - start_offset) / DE.getTargetByteSize()));
279
280 line_start_offset = offset;
281 } else if (item_format != eFormatChar &&
282 item_format != eFormatCharPrintable &&
283 item_format != eFormatCharArray && count > 0) {
284 s->PutChar(' ');
285 }
286
287 switch (item_format) {
288 case eFormatBoolean:
289 if (item_byte_size <= 8)
290 s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
291 item_bit_size, item_bit_offset)
292 ? "true"
293 : "false");
294 else {
295 s->Printf("error: unsupported byte size (%" PRIu64
296 ") for boolean format",
297 (uint64_t)item_byte_size);
298 return offset;
299 }
300 break;
301
302 case eFormatBinary:
303 if (item_byte_size <= 8) {
304 uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
305 item_bit_size, item_bit_offset);
306 // Avoid std::bitset<64>::to_string() since it is missing in earlier
307 // C++ libraries
308 std::string binary_value(64, '0');
309 std::bitset<64> bits(uval64);
310 for (uint32_t i = 0; i < 64; ++i)
311 if (bits[i])
312 binary_value[64 - 1 - i] = '1';
313 if (item_bit_size > 0)
314 s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
315 else if (item_byte_size > 0 && item_byte_size <= 8)
316 s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
317 } else {
318 const bool is_signed = false;
319 const unsigned radix = 2;
320 offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
321 }
322 break;
323
324 case eFormatBytes:
325 case eFormatBytesWithASCII:
326 for (uint32_t i = 0; i < item_byte_size; ++i) {
327 s->Printf("%2.2x", DE.GetU8(&offset));
328 }
329
330 // Put an extra space between the groups of bytes if more than one is
331 // being dumped in a group (item_byte_size is more than 1).
332 if (item_byte_size > 1)
333 s->PutChar(' ');
334 break;
335
336 case eFormatChar:
337 case eFormatCharPrintable:
338 case eFormatCharArray: {
339 // Reject invalid item_byte_size.
340 if (item_byte_size > 8) {
341 s->Printf("error: unsupported byte size (%" PRIu64 ") for char format",
342 (uint64_t)item_byte_size);
343 return offset;
344 }
345
346 // If we are only printing one character surround it with single quotes
347 if (item_count == 1 && item_format == eFormatChar)
348 s->PutChar('\'');
349
350 const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,
351 item_bit_size, item_bit_offset);
352 if (llvm::isPrint(ch))
353 s->Printf("%c", (char)ch);
354 else if (item_format != eFormatCharPrintable) {
355 if (!TryDumpSpecialEscapedChar(*s, ch)) {
356 if (item_byte_size == 1)
357 s->Printf("\\x%2.2x", (uint8_t)ch);
358 else
359 s->Printf("%" PRIu64, ch);
360 }
361 } else {
362 s->PutChar(NON_PRINTABLE_CHAR);
363 }
364
365 // If we are only printing one character surround it with single quotes
366 if (item_count == 1 && item_format == eFormatChar)
367 s->PutChar('\'');
368 } break;
369
370 case eFormatEnum: // Print enum value as a signed integer when we don't get
371 // the enum type
372 case eFormatDecimal:
373 if (item_byte_size <= 8)
374 s->Printf("%" PRId64,
375 DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
376 item_bit_offset));
377 else {
378 const bool is_signed = true;
379 const unsigned radix = 10;
380 offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
381 }
382 break;
383
384 case eFormatUnsigned:
385 if (item_byte_size <= 8)
386 s->Printf("%" PRIu64,
387 DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
388 item_bit_offset));
389 else {
390 const bool is_signed = false;
391 const unsigned radix = 10;
392 offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
393 }
394 break;
395
396 case eFormatOctal:
397 if (item_byte_size <= 8)
398 s->Printf("0%" PRIo64,
399 DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
400 item_bit_offset));
401 else {
402 const bool is_signed = false;
403 const unsigned radix = 8;
404 offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
405 }
406 break;
407
408 case eFormatOSType: {
409 uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
410 item_bit_size, item_bit_offset);
411 s->PutChar('\'');
412 for (uint32_t i = 0; i < item_byte_size; ++i) {
413 uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
414 DumpCharacter(*s, ch);
415 }
416 s->PutChar('\'');
417 } break;
418
419 case eFormatCString: {
420 const char *cstr = DE.GetCStr(&offset);
421
422 if (!cstr) {
423 s->Printf("NULL");
424 offset = LLDB_INVALID_OFFSET;
425 } else {
426 s->PutChar('\"');
427
428 while (const char c = *cstr) {
429 DumpCharacter(*s, c);
430 ++cstr;
431 }
432
433 s->PutChar('\"');
434 }
435 } break;
436
437 case eFormatPointer:
438 DumpAddress(s->AsRawOstream(),
439 DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
440 item_bit_offset),
441 sizeof(addr_t));
442 break;
443
444 case eFormatComplexInteger: {
445 size_t complex_int_byte_size = item_byte_size / 2;
446
447 if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
448 s->Printf("%" PRIu64,
449 DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
450 s->Printf(" + %" PRIu64 "i",
451 DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
452 } else {
453 s->Printf("error: unsupported byte size (%" PRIu64
454 ") for complex integer format",
455 (uint64_t)item_byte_size);
456 return offset;
457 }
458 } break;
459
460 case eFormatComplex:
461 if (sizeof(float) * 2 == item_byte_size) {
462 float f32_1 = DE.GetFloat(&offset);
463 float f32_2 = DE.GetFloat(&offset);
464
465 s->Printf("%g + %gi", f32_1, f32_2);
466 break;
467 } else if (sizeof(double) * 2 == item_byte_size) {
468 double d64_1 = DE.GetDouble(&offset);
469 double d64_2 = DE.GetDouble(&offset);
470
471 s->Printf("%lg + %lgi", d64_1, d64_2);
472 break;
473 } else if (sizeof(long double) * 2 == item_byte_size) {
474 long double ld64_1 = DE.GetLongDouble(&offset);
475 long double ld64_2 = DE.GetLongDouble(&offset);
476 s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
477 break;
478 } else {
479 s->Printf("error: unsupported byte size (%" PRIu64
480 ") for complex float format",
481 (uint64_t)item_byte_size);
482 return offset;
483 }
484 break;
485
486 default:
487 case eFormatDefault:
488 case eFormatHex:
489 case eFormatHexUppercase: {
490 bool wantsuppercase = (item_format == eFormatHexUppercase);
491 switch (item_byte_size) {
492 case 1:
493 case 2:
494 case 4:
495 case 8:
496 s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
497 (int)(2 * item_byte_size), (int)(2 * item_byte_size),
498 DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
499 item_bit_offset));
500 break;
501 default: {
502 assert(item_bit_size == 0 && item_bit_offset == 0);
503 const uint8_t *bytes =
504 (const uint8_t *)DE.GetData(&offset, item_byte_size);
505 if (bytes) {
506 s->PutCString("0x");
507 uint32_t idx;
508 if (DE.GetByteOrder() == eByteOrderBig) {
509 for (idx = 0; idx < item_byte_size; ++idx)
510 s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
511 } else {
512 for (idx = 0; idx < item_byte_size; ++idx)
513 s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
514 bytes[item_byte_size - 1 - idx]);
515 }
516 }
517 } break;
518 }
519 } break;
520
521 case eFormatFloat: {
522 TargetSP target_sp;
523 bool used_upfloat = false;
524 if (exe_scope)
525 target_sp = exe_scope->CalculateTarget();
526 if (target_sp) {
527 auto type_system_or_err =
528 target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
529 if (!type_system_or_err) {
530 llvm::consumeError(type_system_or_err.takeError());
531 } else {
532 auto &type_system = *type_system_or_err;
533 llvm::SmallVector<char, 256> sv;
534 // Show full precision when printing float values
535 const unsigned format_precision = 0;
536 const unsigned format_max_padding =
537 target_sp->GetMaxZeroPaddingInFloatFormat();
538
539 const auto &semantics =
540 type_system.GetFloatTypeSemantics(item_byte_size);
541
542 // Recalculate the byte size in case of a difference. This is possible
543 // when item_byte_size is 16 (128-bit), because you could get back the
544 // x87DoubleExtended semantics which has a byte size of 10 (80-bit).
545 const size_t semantics_byte_size =
546 (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
547 llvm::Optional<llvm::APInt> apint =
548 GetAPInt(DE, &offset, semantics_byte_size);
549 if (apint.hasValue()) {
550 llvm::APFloat apfloat(semantics, apint.getValue());
551 apfloat.toString(sv, format_precision, format_max_padding);
552 if (!sv.empty()) {
553 s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data());
554 used_upfloat = true;
555 }
556 }
557 }
558 }
559
560 if (!used_upfloat) {
561 std::ostringstream ss;
562 if (item_byte_size == sizeof(float) || item_byte_size == 2) {
563 float f;
564 if (item_byte_size == 2) {
565 uint16_t half = DE.GetU16(&offset);
566 f = half2float(half);
567 } else {
568 f = DE.GetFloat(&offset);
569 }
570 ss.precision(std::numeric_limits<float>::digits10);
571 ss << f;
572 } else if (item_byte_size == sizeof(double)) {
573 ss.precision(std::numeric_limits<double>::digits10);
574 ss << DE.GetDouble(&offset);
575 } else if (item_byte_size == sizeof(long double) ||
576 item_byte_size == 10) {
577 ss.precision(std::numeric_limits<long double>::digits10);
578 ss << DE.GetLongDouble(&offset);
579 } else {
580 s->Printf("error: unsupported byte size (%" PRIu64
581 ") for float format",
582 (uint64_t)item_byte_size);
583 return offset;
584 }
585 ss.flush();
586 s->Printf("%s", ss.str().c_str());
587 }
588 } break;
589
590 case eFormatUnicode16:
591 s->Printf("U+%4.4x", DE.GetU16(&offset));
592 break;
593
594 case eFormatUnicode32:
595 s->Printf("U+0x%8.8x", DE.GetU32(&offset));
596 break;
597
598 case eFormatAddressInfo: {
599 addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
600 item_bit_offset);
601 s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
602 (int)(2 * item_byte_size), addr);
603 if (exe_scope) {
604 TargetSP target_sp(exe_scope->CalculateTarget());
605 lldb_private::Address so_addr;
606 if (target_sp) {
607 if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
608 so_addr)) {
609 s->PutChar(' ');
610 so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
611 Address::DumpStyleModuleWithFileAddress);
612 } else {
613 so_addr.SetOffset(addr);
614 so_addr.Dump(s, exe_scope,
615 Address::DumpStyleResolvedPointerDescription);
616 if (ProcessSP process_sp = exe_scope->CalculateProcess()) {
617 if (ABISP abi_sp = process_sp->GetABI()) {
618 addr_t addr_fixed = abi_sp->FixCodeAddress(addr);
619 if (target_sp->GetSectionLoadList().ResolveLoadAddress(
620 addr_fixed, so_addr)) {
621 s->PutChar(' ');
622 s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),
623 (int)(2 * item_byte_size), addr_fixed);
624 s->PutChar(' ');
625 so_addr.Dump(s, exe_scope,
626 Address::DumpStyleResolvedDescription,
627 Address::DumpStyleModuleWithFileAddress);
628 }
629 }
630 }
631 }
632 }
633 }
634 } break;
635
636 case eFormatHexFloat:
637 if (sizeof(float) == item_byte_size) {
638 char float_cstr[256];
639 llvm::APFloat ap_float(DE.GetFloat(&offset));
640 ap_float.convertToHexString(float_cstr, 0, false,
641 llvm::APFloat::rmNearestTiesToEven);
642 s->Printf("%s", float_cstr);
643 break;
644 } else if (sizeof(double) == item_byte_size) {
645 char float_cstr[256];
646 llvm::APFloat ap_float(DE.GetDouble(&offset));
647 ap_float.convertToHexString(float_cstr, 0, false,
648 llvm::APFloat::rmNearestTiesToEven);
649 s->Printf("%s", float_cstr);
650 break;
651 } else {
652 s->Printf("error: unsupported byte size (%" PRIu64
653 ") for hex float format",
654 (uint64_t)item_byte_size);
655 return offset;
656 }
657 break;
658
659 // please keep the single-item formats below in sync with
660 // FormatManager::GetSingleItemFormat if you fail to do so, users will
661 // start getting different outputs depending on internal implementation
662 // details they should not care about ||
663 case eFormatVectorOfChar: // ||
664 s->PutChar('{'); // \/
665 offset =
666 DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
667 item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
668 s->PutChar('}');
669 break;
670
671 case eFormatVectorOfSInt8:
672 s->PutChar('{');
673 offset =
674 DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
675 item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
676 s->PutChar('}');
677 break;
678
679 case eFormatVectorOfUInt8:
680 s->PutChar('{');
681 offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
682 item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
683 s->PutChar('}');
684 break;
685
686 case eFormatVectorOfSInt16:
687 s->PutChar('{');
688 offset = DumpDataExtractor(
689 DE, s, offset, eFormatDecimal, sizeof(uint16_t),
690 item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
691 LLDB_INVALID_ADDRESS, 0, 0);
692 s->PutChar('}');
693 break;
694
695 case eFormatVectorOfUInt16:
696 s->PutChar('{');
697 offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
698 item_byte_size / sizeof(uint16_t),
699 item_byte_size / sizeof(uint16_t),
700 LLDB_INVALID_ADDRESS, 0, 0);
701 s->PutChar('}');
702 break;
703
704 case eFormatVectorOfSInt32:
705 s->PutChar('{');
706 offset = DumpDataExtractor(
707 DE, s, offset, eFormatDecimal, sizeof(uint32_t),
708 item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
709 LLDB_INVALID_ADDRESS, 0, 0);
710 s->PutChar('}');
711 break;
712
713 case eFormatVectorOfUInt32:
714 s->PutChar('{');
715 offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
716 item_byte_size / sizeof(uint32_t),
717 item_byte_size / sizeof(uint32_t),
718 LLDB_INVALID_ADDRESS, 0, 0);
719 s->PutChar('}');
720 break;
721
722 case eFormatVectorOfSInt64:
723 s->PutChar('{');
724 offset = DumpDataExtractor(
725 DE, s, offset, eFormatDecimal, sizeof(uint64_t),
726 item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
727 LLDB_INVALID_ADDRESS, 0, 0);
728 s->PutChar('}');
729 break;
730
731 case eFormatVectorOfUInt64:
732 s->PutChar('{');
733 offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
734 item_byte_size / sizeof(uint64_t),
735 item_byte_size / sizeof(uint64_t),
736 LLDB_INVALID_ADDRESS, 0, 0);
737 s->PutChar('}');
738 break;
739
740 case eFormatVectorOfFloat16:
741 s->PutChar('{');
742 offset =
743 DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
744 item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
745 s->PutChar('}');
746 break;
747
748 case eFormatVectorOfFloat32:
749 s->PutChar('{');
750 offset =
751 DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
752 item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
753 s->PutChar('}');
754 break;
755
756 case eFormatVectorOfFloat64:
757 s->PutChar('{');
758 offset =
759 DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
760 item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
761 s->PutChar('}');
762 break;
763
764 case eFormatVectorOfUInt128:
765 s->PutChar('{');
766 offset =
767 DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
768 item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
769 s->PutChar('}');
770 break;
771 }
772 }
773
774 if (item_format == eFormatBytesWithASCII && offset > line_start_offset) {
775 s->Printf("%*s", static_cast<int>(
776 (num_per_line - (offset - line_start_offset)) * 3 + 2),
777 "");
778 DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
779 offset - line_start_offset, SIZE_MAX,
780 LLDB_INVALID_ADDRESS, 0, 0);
781 }
782 return offset; // Return the offset at which we ended up
783}
784
785void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,
786 uint32_t bytes_per_line,
787 lldb::addr_t base_addr) {
788 DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
789 DumpDataExtractor(data, s,
790 0, // Offset into "src"
791 lldb::eFormatBytes, // Dump as hex bytes
792 1, // Size of each item is 1 for single bytes
793 src_len, // Number of bytes
794 bytes_per_line, // Num bytes per line
795 base_addr, // Base address
796 0, 0); // Bitfield info
797}
798