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