DumpDataExtractor.cpp revision 360784
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
43using namespace lldb_private;
44using namespace lldb;
45
46#define NON_PRINTABLE_CHAR '.'
47
48static 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
65static 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
110static 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
131lldb::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
802void 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