1 //===-- DumpDataExtractor.cpp ---------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/DumpDataExtractor.h"
11 #include "lldb/lldb-defines.h"
12 #include "lldb/lldb-forward.h"
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"
30 #include "llvm/ADT/APFloat.h"
31 #include "llvm/ADT/APInt.h"
32 #include "llvm/ADT/ArrayRef.h"
33 #include "llvm/ADT/SmallVector.h"
48 using namespace lldb_private
;
51 #define NON_PRINTABLE_CHAR '.'
53 static std::optional
<llvm::APInt
> GetAPInt(const DataExtractor
&data
,
54 lldb::offset_t
*offset_ptr
,
55 lldb::offset_t byte_size
) {
59 llvm::SmallVector
<uint64_t, 2> uint64_array
;
60 lldb::offset_t bytes_left
= byte_size
;
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
);
69 u64
= data
.GetMaxU64(offset_ptr
, (uint32_t)bytes_left
);
72 uint64_array
.push_back(u64
);
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) {
81 temp_offset
= be_offset
;
82 u64
= data
.GetU64(&temp_offset
);
85 be_offset
-= bytes_left
;
86 temp_offset
= be_offset
;
87 u64
= data
.GetMaxU64(&temp_offset
, (uint32_t)bytes_left
);
90 uint64_array
.push_back(u64
);
92 *offset_ptr
+= byte_size
;
93 return llvm::APInt(byte_size
* 8, llvm::ArrayRef
<uint64_t>(uint64_array
));
98 static 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
);
103 std::string apint_str
= toString(*apint
, radix
, is_signed
);
114 s
->Write(apint_str
.c_str(), apint_str
.size());
119 /// Dumps decoded instructions to a stream.
120 static lldb::offset_t
DumpInstructions(const DataExtractor
&DE
, Stream
*s
,
121 ExecutionContextScope
*exe_scope
,
122 offset_t start_offset
,
124 size_t number_of_instructions
) {
125 offset_t offset
= start_offset
;
129 target_sp
= exe_scope
->CalculateTarget();
131 DisassemblerSP
disassembler_sp(Disassembler::FindPlugin(
132 target_sp
->GetArchitecture(), target_sp
->GetDisassemblyFlavor(),
133 target_sp
->GetDisassemblyCPU(), target_sp
->GetDisassemblyFeatures(),
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
->GetSectionLoadList().ResolveLoadAddress(addr
, so_addr
)) {
140 data_from_file
= false;
142 if (target_sp
->GetSectionLoadList().IsEmpty() ||
143 !target_sp
->GetImages().ResolveFileAddress(addr
, so_addr
))
144 so_addr
.SetRawAddress(addr
);
147 size_t bytes_consumed
= disassembler_sp
->DecodeInstructions(
148 so_addr
, DE
, start_offset
, number_of_instructions
, false,
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
);
163 s
->Printf("invalid target");
168 /// Prints the specific escape sequence of the given character to the stream.
169 /// If the character doesn't have a known specific escape sequence (e.g., '\a',
170 /// '\n' but not generic escape sequences such as'\x12'), this function will
171 /// not modify the stream and return false.
172 static bool TryDumpSpecialEscapedChar(Stream
&s
, const char c
) {
175 // Common non-standard escape code for 'escape'.
207 /// Dump the character to a stream. A character that is not printable will be
208 /// represented by its escape sequence.
209 static void DumpCharacter(Stream
&s
, const char c
) {
210 if (TryDumpSpecialEscapedChar(s
, c
))
212 if (llvm::isPrint(c
)) {
216 s
.Printf("\\x%2.2hhx", c
);
219 /// Dump a floating point type.
220 template <typename FloatT
>
221 void DumpFloatingPoint(std::ostringstream
&ss
, FloatT f
) {
222 static_assert(std::is_floating_point
<FloatT
>::value
,
223 "Only floating point types can be dumped.");
224 // NaN and Inf are potentially implementation defined and on Darwin it
225 // seems NaNs are printed without their sign. Manually implement dumping them
226 // here to avoid having to deal with platform differences.
242 static std::optional
<MemoryTagMap
>
243 GetMemoryTags(lldb::addr_t addr
, size_t length
,
244 ExecutionContextScope
*exe_scope
) {
245 assert(addr
!= LLDB_INVALID_ADDRESS
);
250 TargetSP target_sp
= exe_scope
->CalculateTarget();
254 ProcessSP process_sp
= target_sp
->CalculateProcess();
258 llvm::Expected
<const MemoryTagManager
*> tag_manager_or_err
=
259 process_sp
->GetMemoryTagManager();
260 if (!tag_manager_or_err
) {
261 llvm::consumeError(tag_manager_or_err
.takeError());
265 MemoryRegionInfos memory_regions
;
266 // Don't check return status, list will be just empty if an error happened.
267 process_sp
->GetMemoryRegions(memory_regions
);
269 llvm::Expected
<std::vector
<MemoryTagManager::TagRange
>> tagged_ranges_or_err
=
270 (*tag_manager_or_err
)
271 ->MakeTaggedRanges(addr
, addr
+ length
, memory_regions
);
272 // Here we know that our range will not be inverted but we must still check
274 if (!tagged_ranges_or_err
) {
275 llvm::consumeError(tagged_ranges_or_err
.takeError());
278 if (tagged_ranges_or_err
->empty())
281 MemoryTagMap
memory_tag_map(*tag_manager_or_err
);
282 for (const MemoryTagManager::TagRange
&range
: *tagged_ranges_or_err
) {
283 llvm::Expected
<std::vector
<lldb::addr_t
>> tags_or_err
=
284 process_sp
->ReadMemoryTags(range
.GetRangeBase(), range
.GetByteSize());
287 memory_tag_map
.InsertTags(range
.GetRangeBase(), *tags_or_err
);
289 llvm::consumeError(tags_or_err
.takeError());
292 if (memory_tag_map
.Empty())
295 return memory_tag_map
;
298 static void printMemoryTags(const DataExtractor
&DE
, Stream
*s
,
299 lldb::addr_t addr
, size_t len
,
300 const std::optional
<MemoryTagMap
> &memory_tag_map
) {
301 std::vector
<std::optional
<lldb::addr_t
>> tags
=
302 memory_tag_map
->GetTags(addr
, len
);
304 // Only print if there is at least one tag for this line
308 s
->Printf(" (tag%s:", tags
.size() > 1 ? "s" : "");
309 // Some granules may not be tagged but print something for them
310 // so that the ordering remains intact.
311 for (auto tag
: tags
) {
313 s
->Printf(" 0x%" PRIx64
, *tag
);
315 s
->PutCString(" <no tag>");
320 static const llvm::fltSemantics
&GetFloatSemantics(const TargetSP
&target_sp
,
323 auto type_system_or_err
=
324 target_sp
->GetScratchTypeSystemForLanguage(eLanguageTypeC
);
325 if (!type_system_or_err
)
326 llvm::consumeError(type_system_or_err
.takeError());
327 else if (auto ts
= *type_system_or_err
)
328 return ts
->GetFloatTypeSemantics(byte_size
);
330 // No target, just make a reasonable guess
333 return llvm::APFloat::IEEEhalf();
335 return llvm::APFloat::IEEEsingle();
337 return llvm::APFloat::IEEEdouble();
339 return llvm::APFloat::Bogus();
342 lldb::offset_t
lldb_private::DumpDataExtractor(
343 const DataExtractor
&DE
, Stream
*s
, offset_t start_offset
,
344 lldb::Format item_format
, size_t item_byte_size
, size_t item_count
,
345 size_t num_per_line
, uint64_t base_addr
,
346 uint32_t item_bit_size
, // If zero, this is not a bitfield value, if
347 // non-zero, the value is a bitfield
348 uint32_t item_bit_offset
, // If "item_bit_size" is non-zero, this is the
349 // shift amount to apply to a bitfield
350 ExecutionContextScope
*exe_scope
, bool show_memory_tags
) {
354 if (item_format
== eFormatPointer
) {
355 if (item_byte_size
!= 4 && item_byte_size
!= 8)
356 item_byte_size
= s
->GetAddressByteSize();
359 offset_t offset
= start_offset
;
361 std::optional
<MemoryTagMap
> memory_tag_map
;
362 if (show_memory_tags
&& base_addr
!= LLDB_INVALID_ADDRESS
)
364 GetMemoryTags(base_addr
, DE
.GetByteSize() - offset
, exe_scope
);
366 if (item_format
== eFormatInstruction
)
367 return DumpInstructions(DE
, s
, exe_scope
, start_offset
, base_addr
,
370 if ((item_format
== eFormatOSType
|| item_format
== eFormatAddressInfo
) &&
372 item_format
= eFormatHex
;
374 lldb::offset_t line_start_offset
= start_offset
;
375 for (uint32_t count
= 0; DE
.ValidOffset(offset
) && count
< item_count
;
377 // If we are at the beginning or end of a line
378 // Note that the last line is handled outside this for loop.
379 if ((count
% num_per_line
) == 0) {
380 // If we are at the end of a line
382 if (item_format
== eFormatBytesWithASCII
&&
383 offset
> line_start_offset
) {
386 (num_per_line
- (offset
- line_start_offset
)) * 3 + 2),
388 DumpDataExtractor(DE
, s
, line_start_offset
, eFormatCharPrintable
, 1,
389 offset
- line_start_offset
, SIZE_MAX
,
390 LLDB_INVALID_ADDRESS
, 0, 0);
393 if (base_addr
!= LLDB_INVALID_ADDRESS
&& memory_tag_map
) {
394 size_t line_len
= offset
- line_start_offset
;
395 lldb::addr_t line_base
=
397 (offset
- start_offset
- line_len
) / DE
.getTargetByteSize();
398 printMemoryTags(DE
, s
, line_base
, line_len
, memory_tag_map
);
403 if (base_addr
!= LLDB_INVALID_ADDRESS
)
404 s
->Printf("0x%8.8" PRIx64
": ",
405 (uint64_t)(base_addr
+
406 (offset
- start_offset
) / DE
.getTargetByteSize()));
408 line_start_offset
= offset
;
409 } else if (item_format
!= eFormatChar
&&
410 item_format
!= eFormatCharPrintable
&&
411 item_format
!= eFormatCharArray
&& count
> 0) {
415 switch (item_format
) {
417 if (item_byte_size
<= 8)
418 s
->Printf("%s", DE
.GetMaxU64Bitfield(&offset
, item_byte_size
,
419 item_bit_size
, item_bit_offset
)
423 s
->Printf("error: unsupported byte size (%" PRIu64
424 ") for boolean format",
425 (uint64_t)item_byte_size
);
431 if (item_byte_size
<= 8) {
432 uint64_t uval64
= DE
.GetMaxU64Bitfield(&offset
, item_byte_size
,
433 item_bit_size
, item_bit_offset
);
434 // Avoid std::bitset<64>::to_string() since it is missing in earlier
436 std::string
binary_value(64, '0');
437 std::bitset
<64> bits(uval64
);
438 for (uint32_t i
= 0; i
< 64; ++i
)
440 binary_value
[64 - 1 - i
] = '1';
441 if (item_bit_size
> 0)
442 s
->Printf("0b%s", binary_value
.c_str() + 64 - item_bit_size
);
443 else if (item_byte_size
> 0 && item_byte_size
<= 8)
444 s
->Printf("0b%s", binary_value
.c_str() + 64 - item_byte_size
* 8);
446 const bool is_signed
= false;
447 const unsigned radix
= 2;
448 offset
= DumpAPInt(s
, DE
, offset
, item_byte_size
, is_signed
, radix
);
453 case eFormatBytesWithASCII
:
454 for (uint32_t i
= 0; i
< item_byte_size
; ++i
) {
455 s
->Printf("%2.2x", DE
.GetU8(&offset
));
458 // Put an extra space between the groups of bytes if more than one is
459 // being dumped in a group (item_byte_size is more than 1).
460 if (item_byte_size
> 1)
465 case eFormatCharPrintable
:
466 case eFormatCharArray
: {
467 // Reject invalid item_byte_size.
468 if (item_byte_size
> 8) {
469 s
->Printf("error: unsupported byte size (%" PRIu64
") for char format",
470 (uint64_t)item_byte_size
);
474 // If we are only printing one character surround it with single quotes
475 if (item_count
== 1 && item_format
== eFormatChar
)
478 const uint64_t ch
= DE
.GetMaxU64Bitfield(&offset
, item_byte_size
,
479 item_bit_size
, item_bit_offset
);
480 if (llvm::isPrint(ch
))
481 s
->Printf("%c", (char)ch
);
482 else if (item_format
!= eFormatCharPrintable
) {
483 if (!TryDumpSpecialEscapedChar(*s
, ch
)) {
484 if (item_byte_size
== 1)
485 s
->Printf("\\x%2.2x", (uint8_t)ch
);
487 s
->Printf("%" PRIu64
, ch
);
490 s
->PutChar(NON_PRINTABLE_CHAR
);
493 // If we are only printing one character surround it with single quotes
494 if (item_count
== 1 && item_format
== eFormatChar
)
498 case eFormatEnum
: // Print enum value as a signed integer when we don't get
501 if (item_byte_size
<= 8)
502 s
->Printf("%" PRId64
,
503 DE
.GetMaxS64Bitfield(&offset
, item_byte_size
, item_bit_size
,
506 const bool is_signed
= true;
507 const unsigned radix
= 10;
508 offset
= DumpAPInt(s
, DE
, offset
, item_byte_size
, is_signed
, radix
);
512 case eFormatUnsigned
:
513 if (item_byte_size
<= 8)
514 s
->Printf("%" PRIu64
,
515 DE
.GetMaxU64Bitfield(&offset
, item_byte_size
, item_bit_size
,
518 const bool is_signed
= false;
519 const unsigned radix
= 10;
520 offset
= DumpAPInt(s
, DE
, offset
, item_byte_size
, is_signed
, radix
);
525 if (item_byte_size
<= 8)
526 s
->Printf("0%" PRIo64
,
527 DE
.GetMaxS64Bitfield(&offset
, item_byte_size
, item_bit_size
,
530 const bool is_signed
= false;
531 const unsigned radix
= 8;
532 offset
= DumpAPInt(s
, DE
, offset
, item_byte_size
, is_signed
, radix
);
536 case eFormatOSType
: {
537 uint64_t uval64
= DE
.GetMaxU64Bitfield(&offset
, item_byte_size
,
538 item_bit_size
, item_bit_offset
);
540 for (uint32_t i
= 0; i
< item_byte_size
; ++i
) {
541 uint8_t ch
= (uint8_t)(uval64
>> ((item_byte_size
- i
- 1) * 8));
542 DumpCharacter(*s
, ch
);
547 case eFormatCString
: {
548 const char *cstr
= DE
.GetCStr(&offset
);
552 offset
= LLDB_INVALID_OFFSET
;
556 while (const char c
= *cstr
) {
557 DumpCharacter(*s
, c
);
566 DumpAddress(s
->AsRawOstream(),
567 DE
.GetMaxU64Bitfield(&offset
, item_byte_size
, item_bit_size
,
572 case eFormatComplexInteger
: {
573 size_t complex_int_byte_size
= item_byte_size
/ 2;
575 if (complex_int_byte_size
> 0 && complex_int_byte_size
<= 8) {
576 s
->Printf("%" PRIu64
,
577 DE
.GetMaxU64Bitfield(&offset
, complex_int_byte_size
, 0, 0));
578 s
->Printf(" + %" PRIu64
"i",
579 DE
.GetMaxU64Bitfield(&offset
, complex_int_byte_size
, 0, 0));
581 s
->Printf("error: unsupported byte size (%" PRIu64
582 ") for complex integer format",
583 (uint64_t)item_byte_size
);
589 if (sizeof(float) * 2 == item_byte_size
) {
590 float f32_1
= DE
.GetFloat(&offset
);
591 float f32_2
= DE
.GetFloat(&offset
);
593 s
->Printf("%g + %gi", f32_1
, f32_2
);
595 } else if (sizeof(double) * 2 == item_byte_size
) {
596 double d64_1
= DE
.GetDouble(&offset
);
597 double d64_2
= DE
.GetDouble(&offset
);
599 s
->Printf("%lg + %lgi", d64_1
, d64_2
);
601 } else if (sizeof(long double) * 2 == item_byte_size
) {
602 long double ld64_1
= DE
.GetLongDouble(&offset
);
603 long double ld64_2
= DE
.GetLongDouble(&offset
);
604 s
->Printf("%Lg + %Lgi", ld64_1
, ld64_2
);
607 s
->Printf("error: unsupported byte size (%" PRIu64
608 ") for complex float format",
609 (uint64_t)item_byte_size
);
617 case eFormatHexUppercase
: {
618 bool wantsuppercase
= (item_format
== eFormatHexUppercase
);
619 switch (item_byte_size
) {
624 if (Target::GetGlobalProperties()
625 .ShowHexVariableValuesWithLeadingZeroes()) {
626 s
->Printf(wantsuppercase
? "0x%*.*" PRIX64
: "0x%*.*" PRIx64
,
627 (int)(2 * item_byte_size
), (int)(2 * item_byte_size
),
628 DE
.GetMaxU64Bitfield(&offset
, item_byte_size
, item_bit_size
,
631 s
->Printf(wantsuppercase
? "0x%" PRIX64
: "0x%" PRIx64
,
632 DE
.GetMaxU64Bitfield(&offset
, item_byte_size
, item_bit_size
,
637 assert(item_bit_size
== 0 && item_bit_offset
== 0);
638 const uint8_t *bytes
=
639 (const uint8_t *)DE
.GetData(&offset
, item_byte_size
);
643 if (DE
.GetByteOrder() == eByteOrderBig
) {
644 for (idx
= 0; idx
< item_byte_size
; ++idx
)
645 s
->Printf(wantsuppercase
? "%2.2X" : "%2.2x", bytes
[idx
]);
647 for (idx
= 0; idx
< item_byte_size
; ++idx
)
648 s
->Printf(wantsuppercase
? "%2.2X" : "%2.2x",
649 bytes
[item_byte_size
- 1 - idx
]);
659 target_sp
= exe_scope
->CalculateTarget();
661 std::optional
<unsigned> format_max_padding
;
663 format_max_padding
= target_sp
->GetMaxZeroPaddingInFloatFormat();
665 // Show full precision when printing float values
666 const unsigned format_precision
= 0;
668 const llvm::fltSemantics
&semantics
=
669 GetFloatSemantics(target_sp
, item_byte_size
);
671 // Recalculate the byte size in case of a difference. This is possible
672 // when item_byte_size is 16 (128-bit), because you could get back the
673 // x87DoubleExtended semantics which has a byte size of 10 (80-bit).
674 const size_t semantics_byte_size
=
675 (llvm::APFloat::getSizeInBits(semantics
) + 7) / 8;
676 std::optional
<llvm::APInt
> apint
=
677 GetAPInt(DE
, &offset
, semantics_byte_size
);
679 llvm::APFloat
apfloat(semantics
, *apint
);
680 llvm::SmallVector
<char, 256> sv
;
681 if (format_max_padding
)
682 apfloat
.toString(sv
, format_precision
, *format_max_padding
);
684 apfloat
.toString(sv
, format_precision
);
685 s
->AsRawOstream() << sv
;
687 s
->Format("error: unsupported byte size ({0}) for float format",
693 case eFormatUnicode16
:
694 s
->Printf("U+%4.4x", DE
.GetU16(&offset
));
697 case eFormatUnicode32
:
698 s
->Printf("U+0x%8.8x", DE
.GetU32(&offset
));
701 case eFormatAddressInfo
: {
702 addr_t addr
= DE
.GetMaxU64Bitfield(&offset
, item_byte_size
, item_bit_size
,
704 s
->Printf("0x%*.*" PRIx64
, (int)(2 * item_byte_size
),
705 (int)(2 * item_byte_size
), addr
);
707 TargetSP
target_sp(exe_scope
->CalculateTarget());
708 lldb_private::Address so_addr
;
710 if (target_sp
->GetSectionLoadList().ResolveLoadAddress(addr
,
713 so_addr
.Dump(s
, exe_scope
, Address::DumpStyleResolvedDescription
,
714 Address::DumpStyleModuleWithFileAddress
);
716 so_addr
.SetOffset(addr
);
717 so_addr
.Dump(s
, exe_scope
,
718 Address::DumpStyleResolvedPointerDescription
);
719 if (ProcessSP process_sp
= exe_scope
->CalculateProcess()) {
720 if (ABISP abi_sp
= process_sp
->GetABI()) {
721 addr_t addr_fixed
= abi_sp
->FixCodeAddress(addr
);
722 if (target_sp
->GetSectionLoadList().ResolveLoadAddress(
723 addr_fixed
, so_addr
)) {
725 s
->Printf("(0x%*.*" PRIx64
")", (int)(2 * item_byte_size
),
726 (int)(2 * item_byte_size
), addr_fixed
);
728 so_addr
.Dump(s
, exe_scope
,
729 Address::DumpStyleResolvedDescription
,
730 Address::DumpStyleModuleWithFileAddress
);
739 case eFormatHexFloat
:
740 if (sizeof(float) == item_byte_size
) {
741 char float_cstr
[256];
742 llvm::APFloat
ap_float(DE
.GetFloat(&offset
));
743 ap_float
.convertToHexString(float_cstr
, 0, false,
744 llvm::APFloat::rmNearestTiesToEven
);
745 s
->Printf("%s", float_cstr
);
747 } else if (sizeof(double) == item_byte_size
) {
748 char float_cstr
[256];
749 llvm::APFloat
ap_float(DE
.GetDouble(&offset
));
750 ap_float
.convertToHexString(float_cstr
, 0, false,
751 llvm::APFloat::rmNearestTiesToEven
);
752 s
->Printf("%s", float_cstr
);
755 s
->Printf("error: unsupported byte size (%" PRIu64
756 ") for hex float format",
757 (uint64_t)item_byte_size
);
762 // please keep the single-item formats below in sync with
763 // FormatManager::GetSingleItemFormat if you fail to do so, users will
764 // start getting different outputs depending on internal implementation
765 // details they should not care about ||
766 case eFormatVectorOfChar
: // ||
767 s
->PutChar('{'); // \/
769 DumpDataExtractor(DE
, s
, offset
, eFormatCharArray
, 1, item_byte_size
,
770 item_byte_size
, LLDB_INVALID_ADDRESS
, 0, 0);
774 case eFormatVectorOfSInt8
:
777 DumpDataExtractor(DE
, s
, offset
, eFormatDecimal
, 1, item_byte_size
,
778 item_byte_size
, LLDB_INVALID_ADDRESS
, 0, 0);
782 case eFormatVectorOfUInt8
:
784 offset
= DumpDataExtractor(DE
, s
, offset
, eFormatHex
, 1, item_byte_size
,
785 item_byte_size
, LLDB_INVALID_ADDRESS
, 0, 0);
789 case eFormatVectorOfSInt16
:
791 offset
= DumpDataExtractor(
792 DE
, s
, offset
, eFormatDecimal
, sizeof(uint16_t),
793 item_byte_size
/ sizeof(uint16_t), item_byte_size
/ sizeof(uint16_t),
794 LLDB_INVALID_ADDRESS
, 0, 0);
798 case eFormatVectorOfUInt16
:
800 offset
= DumpDataExtractor(DE
, s
, offset
, eFormatHex
, sizeof(uint16_t),
801 item_byte_size
/ sizeof(uint16_t),
802 item_byte_size
/ sizeof(uint16_t),
803 LLDB_INVALID_ADDRESS
, 0, 0);
807 case eFormatVectorOfSInt32
:
809 offset
= DumpDataExtractor(
810 DE
, s
, offset
, eFormatDecimal
, sizeof(uint32_t),
811 item_byte_size
/ sizeof(uint32_t), item_byte_size
/ sizeof(uint32_t),
812 LLDB_INVALID_ADDRESS
, 0, 0);
816 case eFormatVectorOfUInt32
:
818 offset
= DumpDataExtractor(DE
, s
, offset
, eFormatHex
, sizeof(uint32_t),
819 item_byte_size
/ sizeof(uint32_t),
820 item_byte_size
/ sizeof(uint32_t),
821 LLDB_INVALID_ADDRESS
, 0, 0);
825 case eFormatVectorOfSInt64
:
827 offset
= DumpDataExtractor(
828 DE
, s
, offset
, eFormatDecimal
, sizeof(uint64_t),
829 item_byte_size
/ sizeof(uint64_t), item_byte_size
/ sizeof(uint64_t),
830 LLDB_INVALID_ADDRESS
, 0, 0);
834 case eFormatVectorOfUInt64
:
836 offset
= DumpDataExtractor(DE
, s
, offset
, eFormatHex
, sizeof(uint64_t),
837 item_byte_size
/ sizeof(uint64_t),
838 item_byte_size
/ sizeof(uint64_t),
839 LLDB_INVALID_ADDRESS
, 0, 0);
843 case eFormatVectorOfFloat16
:
846 DumpDataExtractor(DE
, s
, offset
, eFormatFloat
, 2, item_byte_size
/ 2,
847 item_byte_size
/ 2, LLDB_INVALID_ADDRESS
, 0, 0);
851 case eFormatVectorOfFloat32
:
854 DumpDataExtractor(DE
, s
, offset
, eFormatFloat
, 4, item_byte_size
/ 4,
855 item_byte_size
/ 4, LLDB_INVALID_ADDRESS
, 0, 0);
859 case eFormatVectorOfFloat64
:
862 DumpDataExtractor(DE
, s
, offset
, eFormatFloat
, 8, item_byte_size
/ 8,
863 item_byte_size
/ 8, LLDB_INVALID_ADDRESS
, 0, 0);
867 case eFormatVectorOfUInt128
:
870 DumpDataExtractor(DE
, s
, offset
, eFormatHex
, 16, item_byte_size
/ 16,
871 item_byte_size
/ 16, LLDB_INVALID_ADDRESS
, 0, 0);
877 // If anything was printed we want to catch the end of the last line.
878 // Since we will exit the for loop above before we get a chance to append to
880 if (offset
> line_start_offset
) {
881 if (item_format
== eFormatBytesWithASCII
) {
884 (num_per_line
- (offset
- line_start_offset
)) * 3 + 2),
886 DumpDataExtractor(DE
, s
, line_start_offset
, eFormatCharPrintable
, 1,
887 offset
- line_start_offset
, SIZE_MAX
,
888 LLDB_INVALID_ADDRESS
, 0, 0);
891 if (base_addr
!= LLDB_INVALID_ADDRESS
&& memory_tag_map
) {
892 size_t line_len
= offset
- line_start_offset
;
893 lldb::addr_t line_base
= base_addr
+ (offset
- start_offset
- line_len
) /
894 DE
.getTargetByteSize();
895 printMemoryTags(DE
, s
, line_base
, line_len
, memory_tag_map
);
899 return offset
; // Return the offset at which we ended up
902 void lldb_private::DumpHexBytes(Stream
*s
, const void *src
, size_t src_len
,
903 uint32_t bytes_per_line
,
904 lldb::addr_t base_addr
) {
905 DataExtractor
data(src
, src_len
, lldb::eByteOrderLittle
, 4);
906 DumpDataExtractor(data
, s
,
907 0, // Offset into "src"
908 lldb::eFormatBytes
, // Dump as hex bytes
909 1, // Size of each item is 1 for single bytes
910 src_len
, // Number of bytes
911 bytes_per_line
, // Num bytes per line
912 base_addr
, // Base address
913 0, 0); // Bitfield info