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