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