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