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