brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.3 KiB · a0dc752 Raw
922 lines · cpp
1//===-- DumpDataExtractor.cpp ---------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//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/ABI.h"18#include "lldb/Target/ExecutionContext.h"19#include "lldb/Target/ExecutionContextScope.h"20#include "lldb/Target/MemoryRegionInfo.h"21#include "lldb/Target/MemoryTagManager.h"22#include "lldb/Target/MemoryTagMap.h"23#include "lldb/Target/Process.h"24#include "lldb/Target/SectionLoadList.h"25#include "lldb/Target/Target.h"26#include "lldb/Utility/DataExtractor.h"27#include "lldb/Utility/Log.h"28#include "lldb/Utility/Stream.h"29 30#include "llvm/ADT/APFloat.h"31#include "llvm/ADT/APInt.h"32#include "llvm/ADT/ArrayRef.h"33#include "llvm/ADT/SmallVector.h"34 35#include <limits>36#include <memory>37#include <string>38 39#include <cassert>40#include <cctype>41#include <cinttypes>42#include <cmath>43 44#include <bitset>45#include <optional>46#include <sstream>47 48using namespace lldb_private;49using namespace lldb;50 51#define NON_PRINTABLE_CHAR '.'52 53static std::optional<llvm::APInt> GetAPInt(const DataExtractor &data,54                                           lldb::offset_t *offset_ptr,55                                           lldb::offset_t byte_size) {56  if (byte_size == 0)57    return std::nullopt;58 59  llvm::SmallVector<uint64_t, 2> uint64_array;60  lldb::offset_t bytes_left = byte_size;61  uint64_t u64;62  const lldb::ByteOrder byte_order = data.GetByteOrder();63  if (byte_order == lldb::eByteOrderLittle) {64    while (bytes_left > 0) {65      if (bytes_left >= 8) {66        u64 = data.GetU64(offset_ptr);67        bytes_left -= 8;68      } else {69        u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);70        bytes_left = 0;71      }72      uint64_array.push_back(u64);73    }74    return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));75  } else if (byte_order == lldb::eByteOrderBig) {76    lldb::offset_t be_offset = *offset_ptr + byte_size;77    lldb::offset_t temp_offset;78    while (bytes_left > 0) {79      if (bytes_left >= 8) {80        be_offset -= 8;81        temp_offset = be_offset;82        u64 = data.GetU64(&temp_offset);83        bytes_left -= 8;84      } else {85        be_offset -= bytes_left;86        temp_offset = be_offset;87        u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);88        bytes_left = 0;89      }90      uint64_array.push_back(u64);91    }92    *offset_ptr += byte_size;93    return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));94  }95  return std::nullopt;96}97 98static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,99                                lldb::offset_t offset, lldb::offset_t byte_size,100                                bool is_signed, unsigned radix) {101  std::optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size);102  if (apint) {103    std::string apint_str = toString(*apint, radix, is_signed);104    switch (radix) {105    case 2:106      s->Write("0b", 2);107      break;108    case 8:109      s->Write("0", 1);110      break;111    case 10:112      break;113    }114    s->Write(apint_str.c_str(), apint_str.size());115  }116  return offset;117}118 119/// Dumps decoded instructions to a stream.120static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,121                                       ExecutionContextScope *exe_scope,122                                       offset_t start_offset,123                                       uint64_t base_addr,124                                       size_t number_of_instructions) {125  offset_t offset = start_offset;126 127  TargetSP target_sp;128  if (exe_scope)129    target_sp = exe_scope->CalculateTarget();130  if (target_sp) {131    DisassemblerSP disassembler_sp(Disassembler::FindPlugin(132        target_sp->GetArchitecture(), target_sp->GetDisassemblyFlavor(),133        target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),134        nullptr));135    if (disassembler_sp) {136      lldb::addr_t addr = base_addr + start_offset;137      lldb_private::Address so_addr;138      bool data_from_file = true;139      if (target_sp->ResolveLoadAddress(addr, so_addr)) {140        data_from_file = false;141      } else {142        if (!target_sp->HasLoadedSections() ||143            !target_sp->GetImages().ResolveFileAddress(addr, so_addr))144          so_addr.SetRawAddress(addr);145      }146 147      size_t bytes_consumed = disassembler_sp->DecodeInstructions(148          so_addr, DE, start_offset, number_of_instructions, false,149          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 = false;155        const bool show_control_flow_kind = false;156        ExecutionContext exe_ctx;157        exe_scope->CalculateExecutionContext(exe_ctx);158        disassembler_sp->GetInstructionList().Dump(159            s, show_address, show_bytes, show_control_flow_kind, &exe_ctx);160      } else if (number_of_instructions)161        s->Printf("failed to decode instructions at 0x%" PRIx64 ".", addr);162    }163  } else164    s->Printf("invalid target");165 166  return offset;167}168 169/// Prints the specific escape sequence of the given character to the stream.170/// If the character doesn't have a known specific escape sequence (e.g., '\a',171/// '\n' but not generic escape sequences such as'\x12'), this function will172/// not modify the stream and return false.173static bool TryDumpSpecialEscapedChar(Stream &s, const char c) {174  switch (c) {175  case '\033':176    // Common non-standard escape code for 'escape'.177    s.Printf("\\e");178    return true;179  case '\a':180    s.Printf("\\a");181    return true;182  case '\b':183    s.Printf("\\b");184    return true;185  case '\f':186    s.Printf("\\f");187    return true;188  case '\n':189    s.Printf("\\n");190    return true;191  case '\r':192    s.Printf("\\r");193    return true;194  case '\t':195    s.Printf("\\t");196    return true;197  case '\v':198    s.Printf("\\v");199    return true;200  case '\0':201    s.Printf("\\0");202    return true;203  default:204    return false;205  }206}207 208/// Dump the character to a stream. A character that is not printable will be209/// represented by its escape sequence.210static void DumpCharacter(Stream &s, const char c) {211  if (TryDumpSpecialEscapedChar(s, c))212    return;213  if (llvm::isPrint(c)) {214    s.PutChar(c);215    return;216  }217  s.Printf("\\x%2.2hhx", c);218}219 220/// Dump a floating point type.221template <typename FloatT>222void DumpFloatingPoint(std::ostringstream &ss, FloatT f) {223  static_assert(std::is_floating_point<FloatT>::value,224                "Only floating point types can be dumped.");225  // NaN and Inf are potentially implementation defined and on Darwin it226  // seems NaNs are printed without their sign. Manually implement dumping them227  // here to avoid having to deal with platform differences.228  if (std::isnan(f)) {229    if (std::signbit(f))230      ss << '-';231    ss << "nan";232    return;233  }234  if (std::isinf(f)) {235    if (std::signbit(f))236      ss << '-';237    ss << "inf";238    return;239  }240  ss << f;241}242 243static std::optional<MemoryTagMap>244GetMemoryTags(lldb::addr_t addr, size_t length,245              ExecutionContextScope *exe_scope) {246  assert(addr != LLDB_INVALID_ADDRESS);247 248  if (!exe_scope)249    return std::nullopt;250 251  TargetSP target_sp = exe_scope->CalculateTarget();252  if (!target_sp)253    return std::nullopt;254 255  ProcessSP process_sp = target_sp->CalculateProcess();256  if (!process_sp)257    return std::nullopt;258 259  llvm::Expected<const MemoryTagManager *> tag_manager_or_err =260      process_sp->GetMemoryTagManager();261  if (!tag_manager_or_err) {262    llvm::consumeError(tag_manager_or_err.takeError());263    return std::nullopt;264  }265 266  MemoryRegionInfos memory_regions;267  // Don't check return status, list will be just empty if an error happened.268  process_sp->GetMemoryRegions(memory_regions);269 270  llvm::Expected<std::vector<MemoryTagManager::TagRange>> tagged_ranges_or_err =271      (*tag_manager_or_err)272          ->MakeTaggedRanges(addr, addr + length, memory_regions);273  // Here we know that our range will not be inverted but we must still check274  // for an error.275  if (!tagged_ranges_or_err) {276    llvm::consumeError(tagged_ranges_or_err.takeError());277    return std::nullopt;278  }279  if (tagged_ranges_or_err->empty())280    return std::nullopt;281 282  MemoryTagMap memory_tag_map(*tag_manager_or_err);283  for (const MemoryTagManager::TagRange &range : *tagged_ranges_or_err) {284    llvm::Expected<std::vector<lldb::addr_t>> tags_or_err =285        process_sp->ReadMemoryTags(range.GetRangeBase(), range.GetByteSize());286 287    if (tags_or_err)288      memory_tag_map.InsertTags(range.GetRangeBase(), *tags_or_err);289    else290      llvm::consumeError(tags_or_err.takeError());291  }292 293  if (memory_tag_map.Empty())294    return std::nullopt;295 296  return memory_tag_map;297}298 299static void printMemoryTags(const DataExtractor &DE, Stream *s,300                            lldb::addr_t addr, size_t len,301                            const std::optional<MemoryTagMap> &memory_tag_map) {302  std::vector<std::optional<lldb::addr_t>> tags =303      memory_tag_map->GetTags(addr, len);304 305  // Only print if there is at least one tag for this line306  if (tags.empty())307    return;308 309  s->Printf(" (tag%s:", tags.size() > 1 ? "s" : "");310  // Some granules may not be tagged but print something for them311  // so that the ordering remains intact.312  for (auto tag : tags) {313    if (tag)314      s->Printf(" 0x%" PRIx64, *tag);315    else316      s->PutCString(" <no tag>");317  }318  s->PutCString(")");319}320 321static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,322                                                   size_t byte_size,323                                                   lldb::Format format) {324  if (target_sp) {325    auto type_system_or_err =326      target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);327    if (!type_system_or_err)328      llvm::consumeError(type_system_or_err.takeError());329    else if (auto ts = *type_system_or_err)330      return ts->GetFloatTypeSemantics(byte_size, format);331  }332  // No target, just make a reasonable guess333  switch(byte_size) {334    case 2:335      return llvm::APFloat::IEEEhalf();336    case 4:337      return llvm::APFloat::IEEEsingle();338    case 8:339      return llvm::APFloat::IEEEdouble();340    case 16:341      if (format == eFormatFloat128) {342        return llvm::APFloat::IEEEquad();343      }344      // Otherwise it's ambigious whether a 16-byte float is a float128 or a345      // target-specific long double.346    }347  return llvm::APFloat::Bogus();348}349 350lldb::offset_t lldb_private::DumpDataExtractor(351    const DataExtractor &DE, Stream *s, offset_t start_offset,352    lldb::Format item_format, size_t item_byte_size, size_t item_count,353    size_t num_per_line, uint64_t base_addr,354    uint32_t item_bit_size,   // If zero, this is not a bitfield value, if355                              // non-zero, the value is a bitfield356    uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the357                              // shift amount to apply to a bitfield358    ExecutionContextScope *exe_scope, bool show_memory_tags) {359  if (s == nullptr)360    return start_offset;361 362  if (item_format == eFormatPointer) {363    if (item_byte_size != 4 && item_byte_size != 8)364      item_byte_size = s->GetAddressByteSize();365  }366 367  offset_t offset = start_offset;368 369  std::optional<MemoryTagMap> memory_tag_map;370  if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS)371    memory_tag_map =372        GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope);373 374  if (item_format == eFormatInstruction)375    return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,376                            item_count);377 378  if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&379      item_byte_size > 8)380    item_format = eFormatHex;381 382  lldb::offset_t line_start_offset = start_offset;383  for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;384       ++count) {385    // If we are at the beginning or end of a line386    // Note that the last line is handled outside this for loop.387    if ((count % num_per_line) == 0) {388      // If we are at the end of a line389      if (count > 0) {390        if (item_format == eFormatBytesWithASCII &&391            offset > line_start_offset) {392          s->Printf("%*s",393                    static_cast<int>(394                        (num_per_line - (offset - line_start_offset)) * 3 + 2),395                    "");396          DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,397                            offset - line_start_offset, SIZE_MAX,398                            LLDB_INVALID_ADDRESS, 0, 0);399        }400 401        if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {402          size_t line_len = offset - line_start_offset;403          lldb::addr_t line_base =404              base_addr +405              (offset - start_offset - line_len) / DE.getTargetByteSize();406          printMemoryTags(DE, s, line_base, line_len, memory_tag_map);407        }408 409        s->EOL();410      }411      if (base_addr != LLDB_INVALID_ADDRESS)412        s->Printf("0x%8.8" PRIx64 ": ",413                  (uint64_t)(base_addr +414                             (offset - start_offset) / DE.getTargetByteSize()));415 416      line_start_offset = offset;417    } else if (item_format != eFormatChar &&418               item_format != eFormatCharPrintable &&419               item_format != eFormatCharArray && count > 0) {420      s->PutChar(' ');421    }422 423    switch (item_format) {424    case eFormatBoolean:425      if (item_byte_size <= 8)426        s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,427                                             item_bit_size, item_bit_offset)428                            ? "true"429                            : "false");430      else {431        s->Printf("error: unsupported byte size (%" PRIu64432                  ") for boolean format",433                  (uint64_t)item_byte_size);434        return offset;435      }436      break;437 438    case eFormatBinary:439      if (item_byte_size <= 8) {440        uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,441                                               item_bit_size, item_bit_offset);442        // Avoid std::bitset<64>::to_string() since it is missing in earlier443        // C++ libraries444        std::string binary_value(64, '0');445        std::bitset<64> bits(uval64);446        for (uint32_t i = 0; i < 64; ++i)447          if (bits[i])448            binary_value[64 - 1 - i] = '1';449        if (item_bit_size > 0)450          s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);451        else if (item_byte_size > 0 && item_byte_size <= 8)452          s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);453      } else {454        const bool is_signed = false;455        const unsigned radix = 2;456        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);457      }458      break;459 460    case eFormatBytes:461    case eFormatBytesWithASCII:462      for (uint32_t i = 0; i < item_byte_size; ++i) {463        s->Printf("%2.2x", DE.GetU8(&offset));464      }465 466      // Put an extra space between the groups of bytes if more than one is467      // being dumped in a group (item_byte_size is more than 1).468      if (item_byte_size > 1)469        s->PutChar(' ');470      break;471 472    case eFormatChar:473    case eFormatCharPrintable:474    case eFormatCharArray: {475      // Reject invalid item_byte_size.476      if (item_byte_size > 8) {477        s->Printf("error: unsupported byte size (%" PRIu64 ") for char format",478                  (uint64_t)item_byte_size);479        return offset;480      }481 482      // If we are only printing one character surround it with single quotes483      if (item_count == 1 && item_format == eFormatChar)484        s->PutChar('\'');485 486      const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,487                                               item_bit_size, item_bit_offset);488      if (llvm::isPrint(ch))489        s->Printf("%c", (char)ch);490      else if (item_format != eFormatCharPrintable) {491        if (!TryDumpSpecialEscapedChar(*s, ch)) {492          if (item_byte_size == 1)493            s->Printf("\\x%2.2x", (uint8_t)ch);494          else495            s->Printf("%" PRIu64, ch);496        }497      } else {498        s->PutChar(NON_PRINTABLE_CHAR);499      }500 501      // If we are only printing one character surround it with single quotes502      if (item_count == 1 && item_format == eFormatChar)503        s->PutChar('\'');504    } break;505 506    case eFormatEnum: // Print enum value as a signed integer when we don't get507                      // the enum type508    case eFormatDecimal:509      if (item_byte_size <= 8)510        s->Printf("%" PRId64,511                  DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,512                                       item_bit_offset));513      else {514        const bool is_signed = true;515        const unsigned radix = 10;516        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);517      }518      break;519 520    case eFormatUnsigned:521      if (item_byte_size <= 8)522        s->Printf("%" PRIu64,523                  DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,524                                       item_bit_offset));525      else {526        const bool is_signed = false;527        const unsigned radix = 10;528        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);529      }530      break;531 532    case eFormatOctal:533      if (item_byte_size <= 8)534        s->Printf("0%" PRIo64,535                  DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,536                                       item_bit_offset));537      else {538        const bool is_signed = false;539        const unsigned radix = 8;540        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);541      }542      break;543 544    case eFormatOSType: {545      uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,546                                             item_bit_size, item_bit_offset);547      s->PutChar('\'');548      for (uint32_t i = 0; i < item_byte_size; ++i) {549        uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));550        DumpCharacter(*s, ch);551      }552      s->PutChar('\'');553    } break;554 555    case eFormatCString: {556      const char *cstr = DE.GetCStr(&offset);557 558      if (!cstr) {559        s->Printf("NULL");560        offset = LLDB_INVALID_OFFSET;561      } else {562        s->PutChar('\"');563 564        while (const char c = *cstr) {565          DumpCharacter(*s, c);566          ++cstr;567        }568 569        s->PutChar('\"');570      }571    } break;572 573    case eFormatPointer:574      DumpAddress(s->AsRawOstream(),575                  DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,576                                       item_bit_offset),577                  sizeof(addr_t));578      break;579 580    case eFormatComplexInteger: {581      size_t complex_int_byte_size = item_byte_size / 2;582 583      if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {584        s->Printf("%" PRIu64,585                  DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));586        s->Printf(" + %" PRIu64 "i",587                  DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));588      } else {589        s->Printf("error: unsupported byte size (%" PRIu64590                  ") for complex integer format",591                  (uint64_t)item_byte_size);592        return offset;593      }594    } break;595 596    case eFormatComplex:597      if (sizeof(float) * 2 == item_byte_size) {598        float f32_1 = DE.GetFloat(&offset);599        float f32_2 = DE.GetFloat(&offset);600 601        s->Printf("%g + %gi", f32_1, f32_2);602        break;603      } else if (sizeof(double) * 2 == item_byte_size) {604        double d64_1 = DE.GetDouble(&offset);605        double d64_2 = DE.GetDouble(&offset);606 607        s->Printf("%lg + %lgi", d64_1, d64_2);608        break;609      } else if (sizeof(long double) * 2 == item_byte_size) {610        long double ld64_1 = DE.GetLongDouble(&offset);611        long double ld64_2 = DE.GetLongDouble(&offset);612        s->Printf("%Lg + %Lgi", ld64_1, ld64_2);613        break;614      } else {615        s->Printf("error: unsupported byte size (%" PRIu64616                  ") for complex float format",617                  (uint64_t)item_byte_size);618        return offset;619      }620      break;621 622    default:623    case eFormatDefault:624    case eFormatHex:625    case eFormatHexUppercase: {626      bool wantsuppercase = (item_format == eFormatHexUppercase);627      switch (item_byte_size) {628      case 1:629      case 2:630      case 4:631      case 8:632        if (Target::GetGlobalProperties()633                .ShowHexVariableValuesWithLeadingZeroes()) {634          s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,635                    (int)(2 * item_byte_size), (int)(2 * item_byte_size),636                    DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,637                                         item_bit_offset));638        } else {639          s->Printf(wantsuppercase ? "0x%" PRIX64 : "0x%" PRIx64,640                    DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,641                                         item_bit_offset));642        }643        break;644      default: {645        assert(item_bit_size == 0 && item_bit_offset == 0);646        const uint8_t *bytes =647            (const uint8_t *)DE.GetData(&offset, item_byte_size);648        if (bytes) {649          s->PutCString("0x");650          uint32_t idx;651          if (DE.GetByteOrder() == eByteOrderBig) {652            for (idx = 0; idx < item_byte_size; ++idx)653              s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);654          } else {655            for (idx = 0; idx < item_byte_size; ++idx)656              s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",657                        bytes[item_byte_size - 1 - idx]);658          }659        }660      } break;661      }662    } break;663 664    case eFormatFloat128:665    case eFormatFloat: {666      TargetSP target_sp;667      if (exe_scope)668        target_sp = exe_scope->CalculateTarget();669 670      std::optional<unsigned> format_max_padding;671      if (target_sp)672        format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat();673 674      // Show full precision when printing float values675      const unsigned format_precision = 0;676 677      const llvm::fltSemantics &semantics =678          GetFloatSemantics(target_sp, item_byte_size, item_format);679 680      // Recalculate the byte size in case of a difference. This is possible681      // when item_byte_size is 16 (128-bit), because you could get back the682      // x87DoubleExtended semantics which has a byte size of 10 (80-bit).683      const size_t semantics_byte_size =684          (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;685      std::optional<llvm::APInt> apint =686          GetAPInt(DE, &offset, semantics_byte_size);687      if (apint) {688        llvm::APFloat apfloat(semantics, *apint);689        llvm::SmallVector<char, 256> sv;690        if (format_max_padding)691          apfloat.toString(sv, format_precision, *format_max_padding);692        else693          apfloat.toString(sv, format_precision);694        s->AsRawOstream() << sv;695      } else {696        s->Format("error: unsupported byte size ({0}) for float format",697                  item_byte_size);698        return offset;699      }700    } break;701 702    case eFormatUnicode16:703      s->Printf("U+%4.4x", DE.GetU16(&offset));704      break;705 706    case eFormatUnicode32:707      s->Printf("U+0x%8.8x", DE.GetU32(&offset));708      break;709 710    case eFormatAddressInfo: {711      addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,712                                         item_bit_offset);713      s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),714                (int)(2 * item_byte_size), addr);715      if (exe_scope) {716        TargetSP target_sp(exe_scope->CalculateTarget());717        lldb_private::Address so_addr;718        if (target_sp) {719          if (target_sp->ResolveLoadAddress(addr, so_addr)) {720            s->PutChar(' ');721            so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,722                         Address::DumpStyleModuleWithFileAddress);723          } else {724            so_addr.SetOffset(addr);725            so_addr.Dump(s, exe_scope,726                         Address::DumpStyleResolvedPointerDescription);727            if (ProcessSP process_sp = exe_scope->CalculateProcess()) {728              if (ABISP abi_sp = process_sp->GetABI()) {729                addr_t addr_fixed = abi_sp->FixCodeAddress(addr);730                if (target_sp->ResolveLoadAddress(addr_fixed, so_addr)) {731                  s->PutChar(' ');732                  s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),733                            (int)(2 * item_byte_size), addr_fixed);734                  s->PutChar(' ');735                  so_addr.Dump(s, exe_scope,736                               Address::DumpStyleResolvedDescription,737                               Address::DumpStyleModuleWithFileAddress);738                }739              }740            }741          }742        }743      }744    } break;745 746    case eFormatHexFloat:747      if (sizeof(float) == item_byte_size) {748        char float_cstr[256];749        llvm::APFloat ap_float(DE.GetFloat(&offset));750        ap_float.convertToHexString(float_cstr, 0, false,751                                    llvm::APFloat::rmNearestTiesToEven);752        s->Printf("%s", float_cstr);753        break;754      } else if (sizeof(double) == item_byte_size) {755        char float_cstr[256];756        llvm::APFloat ap_float(DE.GetDouble(&offset));757        ap_float.convertToHexString(float_cstr, 0, false,758                                    llvm::APFloat::rmNearestTiesToEven);759        s->Printf("%s", float_cstr);760        break;761      } else {762        s->Printf("error: unsupported byte size (%" PRIu64763                  ") for hex float format",764                  (uint64_t)item_byte_size);765        return offset;766      }767      break;768 769    // please keep the single-item formats below in sync with770    // FormatManager::GetSingleItemFormat if you fail to do so, users will771    // start getting different outputs depending on internal implementation772    // details they should not care about ||773    case eFormatVectorOfChar: //   ||774      s->PutChar('{');        //   \/775      offset =776          DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,777                            item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);778      s->PutChar('}');779      break;780 781    case eFormatVectorOfSInt8:782      s->PutChar('{');783      offset =784          DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,785                            item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);786      s->PutChar('}');787      break;788 789    case eFormatVectorOfUInt8:790      s->PutChar('{');791      offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,792                                 item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);793      s->PutChar('}');794      break;795 796    case eFormatVectorOfSInt16:797      s->PutChar('{');798      offset = DumpDataExtractor(799          DE, s, offset, eFormatDecimal, sizeof(uint16_t),800          item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),801          LLDB_INVALID_ADDRESS, 0, 0);802      s->PutChar('}');803      break;804 805    case eFormatVectorOfUInt16:806      s->PutChar('{');807      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),808                                 item_byte_size / sizeof(uint16_t),809                                 item_byte_size / sizeof(uint16_t),810                                 LLDB_INVALID_ADDRESS, 0, 0);811      s->PutChar('}');812      break;813 814    case eFormatVectorOfSInt32:815      s->PutChar('{');816      offset = DumpDataExtractor(817          DE, s, offset, eFormatDecimal, sizeof(uint32_t),818          item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),819          LLDB_INVALID_ADDRESS, 0, 0);820      s->PutChar('}');821      break;822 823    case eFormatVectorOfUInt32:824      s->PutChar('{');825      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),826                                 item_byte_size / sizeof(uint32_t),827                                 item_byte_size / sizeof(uint32_t),828                                 LLDB_INVALID_ADDRESS, 0, 0);829      s->PutChar('}');830      break;831 832    case eFormatVectorOfSInt64:833      s->PutChar('{');834      offset = DumpDataExtractor(835          DE, s, offset, eFormatDecimal, sizeof(uint64_t),836          item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),837          LLDB_INVALID_ADDRESS, 0, 0);838      s->PutChar('}');839      break;840 841    case eFormatVectorOfUInt64:842      s->PutChar('{');843      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),844                                 item_byte_size / sizeof(uint64_t),845                                 item_byte_size / sizeof(uint64_t),846                                 LLDB_INVALID_ADDRESS, 0, 0);847      s->PutChar('}');848      break;849 850    case eFormatVectorOfFloat16:851      s->PutChar('{');852      offset =853          DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,854                            item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);855      s->PutChar('}');856      break;857 858    case eFormatVectorOfFloat32:859      s->PutChar('{');860      offset =861          DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,862                            item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);863      s->PutChar('}');864      break;865 866    case eFormatVectorOfFloat64:867      s->PutChar('{');868      offset =869          DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,870                            item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);871      s->PutChar('}');872      break;873 874    case eFormatVectorOfUInt128:875      s->PutChar('{');876      offset =877          DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,878                            item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);879      s->PutChar('}');880      break;881    }882  }883 884  // If anything was printed we want to catch the end of the last line.885  // Since we will exit the for loop above before we get a chance to append to886  // it normally.887  if (offset > line_start_offset) {888    if (item_format == eFormatBytesWithASCII) {889      s->Printf("%*s",890                static_cast<int>(891                    (num_per_line - (offset - line_start_offset)) * 3 + 2),892                "");893      DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,894                        offset - line_start_offset, SIZE_MAX,895                        LLDB_INVALID_ADDRESS, 0, 0);896    }897 898    if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {899      size_t line_len = offset - line_start_offset;900      lldb::addr_t line_base = base_addr + (offset - start_offset - line_len) /901                                               DE.getTargetByteSize();902      printMemoryTags(DE, s, line_base, line_len, memory_tag_map);903    }904  }905 906  return offset; // Return the offset at which we ended up907}908 909void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,910                                uint32_t bytes_per_line,911                                lldb::addr_t base_addr) {912  DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);913  DumpDataExtractor(data, s,914                    0,                  // Offset into "src"915                    lldb::eFormatBytes, // Dump as hex bytes916                    1,              // Size of each item is 1 for single bytes917                    src_len,        // Number of bytes918                    bytes_per_line, // Num bytes per line919                    base_addr,      // Base address920                    0, 0);          // Bitfield info921}922