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