1dda28197Spatrick //===-- DumpDataExtractor.cpp ---------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Core/DumpDataExtractor.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/lldb-defines.h"
12061da546Spatrick #include "lldb/lldb-forward.h"
13061da546Spatrick
14061da546Spatrick #include "lldb/Core/Address.h"
15061da546Spatrick #include "lldb/Core/Disassembler.h"
16061da546Spatrick #include "lldb/Core/ModuleList.h"
17be691f3bSpatrick #include "lldb/Target/ABI.h"
18061da546Spatrick #include "lldb/Target/ExecutionContext.h"
19061da546Spatrick #include "lldb/Target/ExecutionContextScope.h"
20*f6aab3d8Srobert #include "lldb/Target/MemoryRegionInfo.h"
21*f6aab3d8Srobert #include "lldb/Target/MemoryTagManager.h"
22*f6aab3d8Srobert #include "lldb/Target/MemoryTagMap.h"
23be691f3bSpatrick #include "lldb/Target/Process.h"
24061da546Spatrick #include "lldb/Target/SectionLoadList.h"
25061da546Spatrick #include "lldb/Target/Target.h"
26061da546Spatrick #include "lldb/Utility/DataExtractor.h"
27061da546Spatrick #include "lldb/Utility/Log.h"
28061da546Spatrick #include "lldb/Utility/Stream.h"
29061da546Spatrick
30061da546Spatrick #include "llvm/ADT/APFloat.h"
31061da546Spatrick #include "llvm/ADT/APInt.h"
32061da546Spatrick #include "llvm/ADT/ArrayRef.h"
33061da546Spatrick #include "llvm/ADT/SmallVector.h"
34061da546Spatrick
35061da546Spatrick #include <limits>
36061da546Spatrick #include <memory>
37061da546Spatrick #include <string>
38061da546Spatrick
39be691f3bSpatrick #include <cassert>
40be691f3bSpatrick #include <cctype>
41be691f3bSpatrick #include <cinttypes>
42be691f3bSpatrick #include <cmath>
43061da546Spatrick
44061da546Spatrick #include <bitset>
45*f6aab3d8Srobert #include <optional>
46061da546Spatrick #include <sstream>
47061da546Spatrick
48061da546Spatrick using namespace lldb_private;
49061da546Spatrick using namespace lldb;
50061da546Spatrick
51061da546Spatrick #define NON_PRINTABLE_CHAR '.'
52061da546Spatrick
GetAPInt(const DataExtractor & data,lldb::offset_t * offset_ptr,lldb::offset_t byte_size)53*f6aab3d8Srobert static std::optional<llvm::APInt> GetAPInt(const DataExtractor &data,
54061da546Spatrick lldb::offset_t *offset_ptr,
55061da546Spatrick lldb::offset_t byte_size) {
56061da546Spatrick if (byte_size == 0)
57*f6aab3d8Srobert return std::nullopt;
58061da546Spatrick
59061da546Spatrick llvm::SmallVector<uint64_t, 2> uint64_array;
60061da546Spatrick lldb::offset_t bytes_left = byte_size;
61061da546Spatrick uint64_t u64;
62061da546Spatrick const lldb::ByteOrder byte_order = data.GetByteOrder();
63061da546Spatrick if (byte_order == lldb::eByteOrderLittle) {
64061da546Spatrick while (bytes_left > 0) {
65061da546Spatrick if (bytes_left >= 8) {
66061da546Spatrick u64 = data.GetU64(offset_ptr);
67061da546Spatrick bytes_left -= 8;
68061da546Spatrick } else {
69061da546Spatrick u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
70061da546Spatrick bytes_left = 0;
71061da546Spatrick }
72061da546Spatrick uint64_array.push_back(u64);
73061da546Spatrick }
74061da546Spatrick return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
75061da546Spatrick } else if (byte_order == lldb::eByteOrderBig) {
76061da546Spatrick lldb::offset_t be_offset = *offset_ptr + byte_size;
77061da546Spatrick lldb::offset_t temp_offset;
78061da546Spatrick while (bytes_left > 0) {
79061da546Spatrick if (bytes_left >= 8) {
80061da546Spatrick be_offset -= 8;
81061da546Spatrick temp_offset = be_offset;
82061da546Spatrick u64 = data.GetU64(&temp_offset);
83061da546Spatrick bytes_left -= 8;
84061da546Spatrick } else {
85061da546Spatrick be_offset -= bytes_left;
86061da546Spatrick temp_offset = be_offset;
87061da546Spatrick u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
88061da546Spatrick bytes_left = 0;
89061da546Spatrick }
90061da546Spatrick uint64_array.push_back(u64);
91061da546Spatrick }
92061da546Spatrick *offset_ptr += byte_size;
93061da546Spatrick return llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
94061da546Spatrick }
95*f6aab3d8Srobert return std::nullopt;
96061da546Spatrick }
97061da546Spatrick
DumpAPInt(Stream * s,const DataExtractor & data,lldb::offset_t offset,lldb::offset_t byte_size,bool is_signed,unsigned radix)98061da546Spatrick static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
99061da546Spatrick lldb::offset_t offset, lldb::offset_t byte_size,
100061da546Spatrick bool is_signed, unsigned radix) {
101*f6aab3d8Srobert std::optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size);
102*f6aab3d8Srobert if (apint) {
103*f6aab3d8Srobert std::string apint_str = toString(*apint, radix, is_signed);
104061da546Spatrick switch (radix) {
105061da546Spatrick case 2:
106061da546Spatrick s->Write("0b", 2);
107061da546Spatrick break;
108061da546Spatrick case 8:
109061da546Spatrick s->Write("0", 1);
110061da546Spatrick break;
111061da546Spatrick case 10:
112061da546Spatrick break;
113061da546Spatrick }
114061da546Spatrick s->Write(apint_str.c_str(), apint_str.size());
115061da546Spatrick }
116061da546Spatrick return offset;
117061da546Spatrick }
118061da546Spatrick
119dda28197Spatrick /// Dumps decoded instructions to a stream.
DumpInstructions(const DataExtractor & DE,Stream * s,ExecutionContextScope * exe_scope,offset_t start_offset,uint64_t base_addr,size_t number_of_instructions)120dda28197Spatrick static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,
121dda28197Spatrick ExecutionContextScope *exe_scope,
122dda28197Spatrick offset_t start_offset,
123dda28197Spatrick uint64_t base_addr,
124dda28197Spatrick size_t number_of_instructions) {
125dda28197Spatrick offset_t offset = start_offset;
126dda28197Spatrick
127dda28197Spatrick TargetSP target_sp;
128dda28197Spatrick if (exe_scope)
129dda28197Spatrick target_sp = exe_scope->CalculateTarget();
130dda28197Spatrick if (target_sp) {
131dda28197Spatrick DisassemblerSP disassembler_sp(
132dda28197Spatrick Disassembler::FindPlugin(target_sp->GetArchitecture(),
133dda28197Spatrick target_sp->GetDisassemblyFlavor(), nullptr));
134dda28197Spatrick if (disassembler_sp) {
135dda28197Spatrick lldb::addr_t addr = base_addr + start_offset;
136dda28197Spatrick lldb_private::Address so_addr;
137dda28197Spatrick bool data_from_file = true;
138dda28197Spatrick if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
139dda28197Spatrick data_from_file = false;
140dda28197Spatrick } else {
141dda28197Spatrick if (target_sp->GetSectionLoadList().IsEmpty() ||
142dda28197Spatrick !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
143dda28197Spatrick so_addr.SetRawAddress(addr);
144dda28197Spatrick }
145dda28197Spatrick
146dda28197Spatrick size_t bytes_consumed = disassembler_sp->DecodeInstructions(
147dda28197Spatrick so_addr, DE, start_offset, number_of_instructions, false,
148dda28197Spatrick data_from_file);
149dda28197Spatrick
150dda28197Spatrick if (bytes_consumed) {
151dda28197Spatrick offset += bytes_consumed;
152dda28197Spatrick const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
153dda28197Spatrick const bool show_bytes = true;
154*f6aab3d8Srobert const bool show_control_flow_kind = true;
155dda28197Spatrick ExecutionContext exe_ctx;
156dda28197Spatrick exe_scope->CalculateExecutionContext(exe_ctx);
157*f6aab3d8Srobert disassembler_sp->GetInstructionList().Dump(
158*f6aab3d8Srobert s, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
159dda28197Spatrick }
160dda28197Spatrick }
161dda28197Spatrick } else
162dda28197Spatrick s->Printf("invalid target");
163dda28197Spatrick
164dda28197Spatrick return offset;
165dda28197Spatrick }
166dda28197Spatrick
167dda28197Spatrick /// Prints the specific escape sequence of the given character to the stream.
168dda28197Spatrick /// If the character doesn't have a known specific escape sequence (e.g., '\a',
169dda28197Spatrick /// '\n' but not generic escape sequences such as'\x12'), this function will
170dda28197Spatrick /// not modify the stream and return false.
TryDumpSpecialEscapedChar(Stream & s,const char c)171dda28197Spatrick static bool TryDumpSpecialEscapedChar(Stream &s, const char c) {
172dda28197Spatrick switch (c) {
173dda28197Spatrick case '\033':
174dda28197Spatrick // Common non-standard escape code for 'escape'.
175dda28197Spatrick s.Printf("\\e");
176dda28197Spatrick return true;
177dda28197Spatrick case '\a':
178dda28197Spatrick s.Printf("\\a");
179dda28197Spatrick return true;
180dda28197Spatrick case '\b':
181dda28197Spatrick s.Printf("\\b");
182dda28197Spatrick return true;
183dda28197Spatrick case '\f':
184dda28197Spatrick s.Printf("\\f");
185dda28197Spatrick return true;
186dda28197Spatrick case '\n':
187dda28197Spatrick s.Printf("\\n");
188dda28197Spatrick return true;
189dda28197Spatrick case '\r':
190dda28197Spatrick s.Printf("\\r");
191dda28197Spatrick return true;
192dda28197Spatrick case '\t':
193dda28197Spatrick s.Printf("\\t");
194dda28197Spatrick return true;
195dda28197Spatrick case '\v':
196dda28197Spatrick s.Printf("\\v");
197dda28197Spatrick return true;
198dda28197Spatrick case '\0':
199dda28197Spatrick s.Printf("\\0");
200dda28197Spatrick return true;
201dda28197Spatrick default:
202dda28197Spatrick return false;
203dda28197Spatrick }
204dda28197Spatrick }
205dda28197Spatrick
206dda28197Spatrick /// Dump the character to a stream. A character that is not printable will be
207dda28197Spatrick /// represented by its escape sequence.
DumpCharacter(Stream & s,const char c)208dda28197Spatrick static void DumpCharacter(Stream &s, const char c) {
209dda28197Spatrick if (TryDumpSpecialEscapedChar(s, c))
210dda28197Spatrick return;
211dda28197Spatrick if (llvm::isPrint(c)) {
212dda28197Spatrick s.PutChar(c);
213dda28197Spatrick return;
214dda28197Spatrick }
215dda28197Spatrick s.Printf("\\x%2.2x", c);
216dda28197Spatrick }
217dda28197Spatrick
218be691f3bSpatrick /// Dump a floating point type.
219be691f3bSpatrick template <typename FloatT>
DumpFloatingPoint(std::ostringstream & ss,FloatT f)220be691f3bSpatrick void DumpFloatingPoint(std::ostringstream &ss, FloatT f) {
221be691f3bSpatrick static_assert(std::is_floating_point<FloatT>::value,
222be691f3bSpatrick "Only floating point types can be dumped.");
223be691f3bSpatrick // NaN and Inf are potentially implementation defined and on Darwin it
224be691f3bSpatrick // seems NaNs are printed without their sign. Manually implement dumping them
225be691f3bSpatrick // here to avoid having to deal with platform differences.
226be691f3bSpatrick if (std::isnan(f)) {
227be691f3bSpatrick if (std::signbit(f))
228be691f3bSpatrick ss << '-';
229be691f3bSpatrick ss << "nan";
230be691f3bSpatrick return;
231be691f3bSpatrick }
232be691f3bSpatrick if (std::isinf(f)) {
233be691f3bSpatrick if (std::signbit(f))
234be691f3bSpatrick ss << '-';
235be691f3bSpatrick ss << "inf";
236be691f3bSpatrick return;
237be691f3bSpatrick }
238be691f3bSpatrick ss << f;
239be691f3bSpatrick }
240be691f3bSpatrick
241*f6aab3d8Srobert static std::optional<MemoryTagMap>
GetMemoryTags(lldb::addr_t addr,size_t length,ExecutionContextScope * exe_scope)242*f6aab3d8Srobert GetMemoryTags(lldb::addr_t addr, size_t length,
243*f6aab3d8Srobert ExecutionContextScope *exe_scope) {
244*f6aab3d8Srobert assert(addr != LLDB_INVALID_ADDRESS);
245*f6aab3d8Srobert
246*f6aab3d8Srobert if (!exe_scope)
247*f6aab3d8Srobert return std::nullopt;
248*f6aab3d8Srobert
249*f6aab3d8Srobert TargetSP target_sp = exe_scope->CalculateTarget();
250*f6aab3d8Srobert if (!target_sp)
251*f6aab3d8Srobert return std::nullopt;
252*f6aab3d8Srobert
253*f6aab3d8Srobert ProcessSP process_sp = target_sp->CalculateProcess();
254*f6aab3d8Srobert if (!process_sp)
255*f6aab3d8Srobert return std::nullopt;
256*f6aab3d8Srobert
257*f6aab3d8Srobert llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
258*f6aab3d8Srobert process_sp->GetMemoryTagManager();
259*f6aab3d8Srobert if (!tag_manager_or_err) {
260*f6aab3d8Srobert llvm::consumeError(tag_manager_or_err.takeError());
261*f6aab3d8Srobert return std::nullopt;
262*f6aab3d8Srobert }
263*f6aab3d8Srobert
264*f6aab3d8Srobert MemoryRegionInfos memory_regions;
265*f6aab3d8Srobert // Don't check return status, list will be just empty if an error happened.
266*f6aab3d8Srobert process_sp->GetMemoryRegions(memory_regions);
267*f6aab3d8Srobert
268*f6aab3d8Srobert llvm::Expected<std::vector<MemoryTagManager::TagRange>> tagged_ranges_or_err =
269*f6aab3d8Srobert (*tag_manager_or_err)
270*f6aab3d8Srobert ->MakeTaggedRanges(addr, addr + length, memory_regions);
271*f6aab3d8Srobert // Here we know that our range will not be inverted but we must still check
272*f6aab3d8Srobert // for an error.
273*f6aab3d8Srobert if (!tagged_ranges_or_err) {
274*f6aab3d8Srobert llvm::consumeError(tagged_ranges_or_err.takeError());
275*f6aab3d8Srobert return std::nullopt;
276*f6aab3d8Srobert }
277*f6aab3d8Srobert if (tagged_ranges_or_err->empty())
278*f6aab3d8Srobert return std::nullopt;
279*f6aab3d8Srobert
280*f6aab3d8Srobert MemoryTagMap memory_tag_map(*tag_manager_or_err);
281*f6aab3d8Srobert for (const MemoryTagManager::TagRange &range : *tagged_ranges_or_err) {
282*f6aab3d8Srobert llvm::Expected<std::vector<lldb::addr_t>> tags_or_err =
283*f6aab3d8Srobert process_sp->ReadMemoryTags(range.GetRangeBase(), range.GetByteSize());
284*f6aab3d8Srobert
285*f6aab3d8Srobert if (tags_or_err)
286*f6aab3d8Srobert memory_tag_map.InsertTags(range.GetRangeBase(), *tags_or_err);
287*f6aab3d8Srobert else
288*f6aab3d8Srobert llvm::consumeError(tags_or_err.takeError());
289*f6aab3d8Srobert }
290*f6aab3d8Srobert
291*f6aab3d8Srobert if (memory_tag_map.Empty())
292*f6aab3d8Srobert return std::nullopt;
293*f6aab3d8Srobert
294*f6aab3d8Srobert return memory_tag_map;
295*f6aab3d8Srobert }
296*f6aab3d8Srobert
printMemoryTags(const DataExtractor & DE,Stream * s,lldb::addr_t addr,size_t len,const std::optional<MemoryTagMap> & memory_tag_map)297*f6aab3d8Srobert static void printMemoryTags(const DataExtractor &DE, Stream *s,
298*f6aab3d8Srobert lldb::addr_t addr, size_t len,
299*f6aab3d8Srobert const std::optional<MemoryTagMap> &memory_tag_map) {
300*f6aab3d8Srobert std::vector<std::optional<lldb::addr_t>> tags =
301*f6aab3d8Srobert memory_tag_map->GetTags(addr, len);
302*f6aab3d8Srobert
303*f6aab3d8Srobert // Only print if there is at least one tag for this line
304*f6aab3d8Srobert if (tags.empty())
305*f6aab3d8Srobert return;
306*f6aab3d8Srobert
307*f6aab3d8Srobert s->Printf(" (tag%s:", tags.size() > 1 ? "s" : "");
308*f6aab3d8Srobert // Some granules may not be tagged but print something for them
309*f6aab3d8Srobert // so that the ordering remains intact.
310*f6aab3d8Srobert for (auto tag : tags) {
311*f6aab3d8Srobert if (tag)
312*f6aab3d8Srobert s->Printf(" 0x%" PRIx64, *tag);
313*f6aab3d8Srobert else
314*f6aab3d8Srobert s->PutCString(" <no tag>");
315*f6aab3d8Srobert }
316*f6aab3d8Srobert s->PutCString(")");
317*f6aab3d8Srobert }
318*f6aab3d8Srobert
GetFloatSemantics(const TargetSP & target_sp,size_t byte_size)319*f6aab3d8Srobert static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
320*f6aab3d8Srobert size_t byte_size) {
321*f6aab3d8Srobert if (target_sp) {
322*f6aab3d8Srobert auto type_system_or_err =
323*f6aab3d8Srobert target_sp->GetScratchTypeSystemForLanguage(eLanguageTypeC);
324*f6aab3d8Srobert if (!type_system_or_err)
325*f6aab3d8Srobert llvm::consumeError(type_system_or_err.takeError());
326*f6aab3d8Srobert else if (auto ts = *type_system_or_err)
327*f6aab3d8Srobert return ts->GetFloatTypeSemantics(byte_size);
328*f6aab3d8Srobert }
329*f6aab3d8Srobert // No target, just make a reasonable guess
330*f6aab3d8Srobert switch(byte_size) {
331*f6aab3d8Srobert case 2:
332*f6aab3d8Srobert return llvm::APFloat::IEEEhalf();
333*f6aab3d8Srobert case 4:
334*f6aab3d8Srobert return llvm::APFloat::IEEEsingle();
335*f6aab3d8Srobert case 8:
336*f6aab3d8Srobert return llvm::APFloat::IEEEdouble();
337*f6aab3d8Srobert }
338*f6aab3d8Srobert return llvm::APFloat::Bogus();
339*f6aab3d8Srobert }
340*f6aab3d8Srobert
DumpDataExtractor(const DataExtractor & DE,Stream * s,offset_t start_offset,lldb::Format item_format,size_t item_byte_size,size_t item_count,size_t num_per_line,uint64_t base_addr,uint32_t item_bit_size,uint32_t item_bit_offset,ExecutionContextScope * exe_scope,bool show_memory_tags)341061da546Spatrick lldb::offset_t lldb_private::DumpDataExtractor(
342061da546Spatrick const DataExtractor &DE, Stream *s, offset_t start_offset,
343061da546Spatrick lldb::Format item_format, size_t item_byte_size, size_t item_count,
344061da546Spatrick size_t num_per_line, uint64_t base_addr,
345061da546Spatrick uint32_t item_bit_size, // If zero, this is not a bitfield value, if
346061da546Spatrick // non-zero, the value is a bitfield
347061da546Spatrick uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
348061da546Spatrick // shift amount to apply to a bitfield
349*f6aab3d8Srobert ExecutionContextScope *exe_scope, bool show_memory_tags) {
350061da546Spatrick if (s == nullptr)
351061da546Spatrick return start_offset;
352061da546Spatrick
353061da546Spatrick if (item_format == eFormatPointer) {
354061da546Spatrick if (item_byte_size != 4 && item_byte_size != 8)
355061da546Spatrick item_byte_size = s->GetAddressByteSize();
356061da546Spatrick }
357061da546Spatrick
358061da546Spatrick offset_t offset = start_offset;
359061da546Spatrick
360*f6aab3d8Srobert std::optional<MemoryTagMap> memory_tag_map;
361*f6aab3d8Srobert if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS)
362*f6aab3d8Srobert memory_tag_map =
363*f6aab3d8Srobert GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope);
364*f6aab3d8Srobert
365dda28197Spatrick if (item_format == eFormatInstruction)
366dda28197Spatrick return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
367dda28197Spatrick item_count);
368061da546Spatrick
369061da546Spatrick if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
370061da546Spatrick item_byte_size > 8)
371061da546Spatrick item_format = eFormatHex;
372061da546Spatrick
373061da546Spatrick lldb::offset_t line_start_offset = start_offset;
374061da546Spatrick for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
375061da546Spatrick ++count) {
376*f6aab3d8Srobert // If we are at the beginning or end of a line
377*f6aab3d8Srobert // Note that the last line is handled outside this for loop.
378061da546Spatrick if ((count % num_per_line) == 0) {
379*f6aab3d8Srobert // If we are at the end of a line
380061da546Spatrick if (count > 0) {
381061da546Spatrick if (item_format == eFormatBytesWithASCII &&
382061da546Spatrick offset > line_start_offset) {
383061da546Spatrick s->Printf("%*s",
384061da546Spatrick static_cast<int>(
385061da546Spatrick (num_per_line - (offset - line_start_offset)) * 3 + 2),
386061da546Spatrick "");
387061da546Spatrick DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
388061da546Spatrick offset - line_start_offset, SIZE_MAX,
389061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
390061da546Spatrick }
391*f6aab3d8Srobert
392*f6aab3d8Srobert if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
393*f6aab3d8Srobert size_t line_len = offset - line_start_offset;
394*f6aab3d8Srobert lldb::addr_t line_base =
395*f6aab3d8Srobert base_addr +
396*f6aab3d8Srobert (offset - start_offset - line_len) / DE.getTargetByteSize();
397*f6aab3d8Srobert printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
398*f6aab3d8Srobert }
399*f6aab3d8Srobert
400061da546Spatrick s->EOL();
401061da546Spatrick }
402061da546Spatrick if (base_addr != LLDB_INVALID_ADDRESS)
403061da546Spatrick s->Printf("0x%8.8" PRIx64 ": ",
404061da546Spatrick (uint64_t)(base_addr +
405061da546Spatrick (offset - start_offset) / DE.getTargetByteSize()));
406061da546Spatrick
407061da546Spatrick line_start_offset = offset;
408061da546Spatrick } else if (item_format != eFormatChar &&
409061da546Spatrick item_format != eFormatCharPrintable &&
410061da546Spatrick item_format != eFormatCharArray && count > 0) {
411061da546Spatrick s->PutChar(' ');
412061da546Spatrick }
413061da546Spatrick
414061da546Spatrick switch (item_format) {
415061da546Spatrick case eFormatBoolean:
416061da546Spatrick if (item_byte_size <= 8)
417061da546Spatrick s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
418061da546Spatrick item_bit_size, item_bit_offset)
419061da546Spatrick ? "true"
420061da546Spatrick : "false");
421061da546Spatrick else {
422061da546Spatrick s->Printf("error: unsupported byte size (%" PRIu64
423061da546Spatrick ") for boolean format",
424061da546Spatrick (uint64_t)item_byte_size);
425061da546Spatrick return offset;
426061da546Spatrick }
427061da546Spatrick break;
428061da546Spatrick
429061da546Spatrick case eFormatBinary:
430061da546Spatrick if (item_byte_size <= 8) {
431061da546Spatrick uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
432061da546Spatrick item_bit_size, item_bit_offset);
433061da546Spatrick // Avoid std::bitset<64>::to_string() since it is missing in earlier
434061da546Spatrick // C++ libraries
435061da546Spatrick std::string binary_value(64, '0');
436061da546Spatrick std::bitset<64> bits(uval64);
437061da546Spatrick for (uint32_t i = 0; i < 64; ++i)
438061da546Spatrick if (bits[i])
439061da546Spatrick binary_value[64 - 1 - i] = '1';
440061da546Spatrick if (item_bit_size > 0)
441061da546Spatrick s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
442061da546Spatrick else if (item_byte_size > 0 && item_byte_size <= 8)
443061da546Spatrick s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
444061da546Spatrick } else {
445061da546Spatrick const bool is_signed = false;
446061da546Spatrick const unsigned radix = 2;
447061da546Spatrick offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
448061da546Spatrick }
449061da546Spatrick break;
450061da546Spatrick
451061da546Spatrick case eFormatBytes:
452061da546Spatrick case eFormatBytesWithASCII:
453061da546Spatrick for (uint32_t i = 0; i < item_byte_size; ++i) {
454061da546Spatrick s->Printf("%2.2x", DE.GetU8(&offset));
455061da546Spatrick }
456061da546Spatrick
457061da546Spatrick // Put an extra space between the groups of bytes if more than one is
458061da546Spatrick // being dumped in a group (item_byte_size is more than 1).
459061da546Spatrick if (item_byte_size > 1)
460061da546Spatrick s->PutChar(' ');
461061da546Spatrick break;
462061da546Spatrick
463061da546Spatrick case eFormatChar:
464061da546Spatrick case eFormatCharPrintable:
465061da546Spatrick case eFormatCharArray: {
466061da546Spatrick // Reject invalid item_byte_size.
467061da546Spatrick if (item_byte_size > 8) {
468061da546Spatrick s->Printf("error: unsupported byte size (%" PRIu64 ") for char format",
469061da546Spatrick (uint64_t)item_byte_size);
470061da546Spatrick return offset;
471061da546Spatrick }
472061da546Spatrick
473061da546Spatrick // If we are only printing one character surround it with single quotes
474061da546Spatrick if (item_count == 1 && item_format == eFormatChar)
475061da546Spatrick s->PutChar('\'');
476061da546Spatrick
477061da546Spatrick const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,
478061da546Spatrick item_bit_size, item_bit_offset);
479dda28197Spatrick if (llvm::isPrint(ch))
480061da546Spatrick s->Printf("%c", (char)ch);
481061da546Spatrick else if (item_format != eFormatCharPrintable) {
482dda28197Spatrick if (!TryDumpSpecialEscapedChar(*s, ch)) {
483061da546Spatrick if (item_byte_size == 1)
484061da546Spatrick s->Printf("\\x%2.2x", (uint8_t)ch);
485061da546Spatrick else
486061da546Spatrick s->Printf("%" PRIu64, ch);
487061da546Spatrick }
488061da546Spatrick } else {
489061da546Spatrick s->PutChar(NON_PRINTABLE_CHAR);
490061da546Spatrick }
491061da546Spatrick
492061da546Spatrick // If we are only printing one character surround it with single quotes
493061da546Spatrick if (item_count == 1 && item_format == eFormatChar)
494061da546Spatrick s->PutChar('\'');
495061da546Spatrick } break;
496061da546Spatrick
497061da546Spatrick case eFormatEnum: // Print enum value as a signed integer when we don't get
498061da546Spatrick // the enum type
499061da546Spatrick case eFormatDecimal:
500061da546Spatrick if (item_byte_size <= 8)
501061da546Spatrick s->Printf("%" PRId64,
502061da546Spatrick DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
503061da546Spatrick item_bit_offset));
504061da546Spatrick else {
505061da546Spatrick const bool is_signed = true;
506061da546Spatrick const unsigned radix = 10;
507061da546Spatrick offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
508061da546Spatrick }
509061da546Spatrick break;
510061da546Spatrick
511061da546Spatrick case eFormatUnsigned:
512061da546Spatrick if (item_byte_size <= 8)
513061da546Spatrick s->Printf("%" PRIu64,
514061da546Spatrick DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
515061da546Spatrick item_bit_offset));
516061da546Spatrick else {
517061da546Spatrick const bool is_signed = false;
518061da546Spatrick const unsigned radix = 10;
519061da546Spatrick offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
520061da546Spatrick }
521061da546Spatrick break;
522061da546Spatrick
523061da546Spatrick case eFormatOctal:
524061da546Spatrick if (item_byte_size <= 8)
525061da546Spatrick s->Printf("0%" PRIo64,
526061da546Spatrick DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
527061da546Spatrick item_bit_offset));
528061da546Spatrick else {
529061da546Spatrick const bool is_signed = false;
530061da546Spatrick const unsigned radix = 8;
531061da546Spatrick offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
532061da546Spatrick }
533061da546Spatrick break;
534061da546Spatrick
535061da546Spatrick case eFormatOSType: {
536061da546Spatrick uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
537061da546Spatrick item_bit_size, item_bit_offset);
538061da546Spatrick s->PutChar('\'');
539061da546Spatrick for (uint32_t i = 0; i < item_byte_size; ++i) {
540061da546Spatrick uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
541dda28197Spatrick DumpCharacter(*s, ch);
542061da546Spatrick }
543061da546Spatrick s->PutChar('\'');
544061da546Spatrick } break;
545061da546Spatrick
546061da546Spatrick case eFormatCString: {
547061da546Spatrick const char *cstr = DE.GetCStr(&offset);
548061da546Spatrick
549061da546Spatrick if (!cstr) {
550061da546Spatrick s->Printf("NULL");
551061da546Spatrick offset = LLDB_INVALID_OFFSET;
552061da546Spatrick } else {
553061da546Spatrick s->PutChar('\"');
554061da546Spatrick
555061da546Spatrick while (const char c = *cstr) {
556dda28197Spatrick DumpCharacter(*s, c);
557061da546Spatrick ++cstr;
558061da546Spatrick }
559061da546Spatrick
560061da546Spatrick s->PutChar('\"');
561061da546Spatrick }
562061da546Spatrick } break;
563061da546Spatrick
564061da546Spatrick case eFormatPointer:
565061da546Spatrick DumpAddress(s->AsRawOstream(),
566061da546Spatrick DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
567061da546Spatrick item_bit_offset),
568061da546Spatrick sizeof(addr_t));
569061da546Spatrick break;
570061da546Spatrick
571061da546Spatrick case eFormatComplexInteger: {
572061da546Spatrick size_t complex_int_byte_size = item_byte_size / 2;
573061da546Spatrick
574061da546Spatrick if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
575061da546Spatrick s->Printf("%" PRIu64,
576061da546Spatrick DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
577061da546Spatrick s->Printf(" + %" PRIu64 "i",
578061da546Spatrick DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
579061da546Spatrick } else {
580061da546Spatrick s->Printf("error: unsupported byte size (%" PRIu64
581061da546Spatrick ") for complex integer format",
582061da546Spatrick (uint64_t)item_byte_size);
583061da546Spatrick return offset;
584061da546Spatrick }
585061da546Spatrick } break;
586061da546Spatrick
587061da546Spatrick case eFormatComplex:
588061da546Spatrick if (sizeof(float) * 2 == item_byte_size) {
589061da546Spatrick float f32_1 = DE.GetFloat(&offset);
590061da546Spatrick float f32_2 = DE.GetFloat(&offset);
591061da546Spatrick
592061da546Spatrick s->Printf("%g + %gi", f32_1, f32_2);
593061da546Spatrick break;
594061da546Spatrick } else if (sizeof(double) * 2 == item_byte_size) {
595061da546Spatrick double d64_1 = DE.GetDouble(&offset);
596061da546Spatrick double d64_2 = DE.GetDouble(&offset);
597061da546Spatrick
598061da546Spatrick s->Printf("%lg + %lgi", d64_1, d64_2);
599061da546Spatrick break;
600061da546Spatrick } else if (sizeof(long double) * 2 == item_byte_size) {
601061da546Spatrick long double ld64_1 = DE.GetLongDouble(&offset);
602061da546Spatrick long double ld64_2 = DE.GetLongDouble(&offset);
603061da546Spatrick s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
604061da546Spatrick break;
605061da546Spatrick } else {
606061da546Spatrick s->Printf("error: unsupported byte size (%" PRIu64
607061da546Spatrick ") for complex float format",
608061da546Spatrick (uint64_t)item_byte_size);
609061da546Spatrick return offset;
610061da546Spatrick }
611061da546Spatrick break;
612061da546Spatrick
613061da546Spatrick default:
614061da546Spatrick case eFormatDefault:
615061da546Spatrick case eFormatHex:
616061da546Spatrick case eFormatHexUppercase: {
617061da546Spatrick bool wantsuppercase = (item_format == eFormatHexUppercase);
618061da546Spatrick switch (item_byte_size) {
619061da546Spatrick case 1:
620061da546Spatrick case 2:
621061da546Spatrick case 4:
622061da546Spatrick case 8:
623061da546Spatrick s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
624061da546Spatrick (int)(2 * item_byte_size), (int)(2 * item_byte_size),
625061da546Spatrick DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
626061da546Spatrick item_bit_offset));
627061da546Spatrick break;
628061da546Spatrick default: {
629061da546Spatrick assert(item_bit_size == 0 && item_bit_offset == 0);
630061da546Spatrick const uint8_t *bytes =
631061da546Spatrick (const uint8_t *)DE.GetData(&offset, item_byte_size);
632061da546Spatrick if (bytes) {
633061da546Spatrick s->PutCString("0x");
634061da546Spatrick uint32_t idx;
635061da546Spatrick if (DE.GetByteOrder() == eByteOrderBig) {
636061da546Spatrick for (idx = 0; idx < item_byte_size; ++idx)
637061da546Spatrick s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
638061da546Spatrick } else {
639061da546Spatrick for (idx = 0; idx < item_byte_size; ++idx)
640061da546Spatrick s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
641061da546Spatrick bytes[item_byte_size - 1 - idx]);
642061da546Spatrick }
643061da546Spatrick }
644061da546Spatrick } break;
645061da546Spatrick }
646061da546Spatrick } break;
647061da546Spatrick
648061da546Spatrick case eFormatFloat: {
649061da546Spatrick TargetSP target_sp;
650061da546Spatrick if (exe_scope)
651061da546Spatrick target_sp = exe_scope->CalculateTarget();
652*f6aab3d8Srobert
653*f6aab3d8Srobert std::optional<unsigned> format_max_padding;
654*f6aab3d8Srobert if (target_sp)
655*f6aab3d8Srobert format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat();
656*f6aab3d8Srobert
657061da546Spatrick // Show full precision when printing float values
658061da546Spatrick const unsigned format_precision = 0;
659061da546Spatrick
660*f6aab3d8Srobert const llvm::fltSemantics &semantics =
661*f6aab3d8Srobert GetFloatSemantics(target_sp, item_byte_size);
662061da546Spatrick
663061da546Spatrick // Recalculate the byte size in case of a difference. This is possible
664061da546Spatrick // when item_byte_size is 16 (128-bit), because you could get back the
665061da546Spatrick // x87DoubleExtended semantics which has a byte size of 10 (80-bit).
666061da546Spatrick const size_t semantics_byte_size =
667061da546Spatrick (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
668*f6aab3d8Srobert std::optional<llvm::APInt> apint =
669061da546Spatrick GetAPInt(DE, &offset, semantics_byte_size);
670*f6aab3d8Srobert if (apint) {
671*f6aab3d8Srobert llvm::APFloat apfloat(semantics, *apint);
672*f6aab3d8Srobert llvm::SmallVector<char, 256> sv;
673*f6aab3d8Srobert if (format_max_padding)
674*f6aab3d8Srobert apfloat.toString(sv, format_precision, *format_max_padding);
675*f6aab3d8Srobert else
676*f6aab3d8Srobert apfloat.toString(sv, format_precision);
677*f6aab3d8Srobert s->AsRawOstream() << sv;
678061da546Spatrick } else {
679*f6aab3d8Srobert s->Format("error: unsupported byte size ({0}) for float format",
680*f6aab3d8Srobert item_byte_size);
681061da546Spatrick return offset;
682061da546Spatrick }
683061da546Spatrick } break;
684061da546Spatrick
685061da546Spatrick case eFormatUnicode16:
686061da546Spatrick s->Printf("U+%4.4x", DE.GetU16(&offset));
687061da546Spatrick break;
688061da546Spatrick
689061da546Spatrick case eFormatUnicode32:
690061da546Spatrick s->Printf("U+0x%8.8x", DE.GetU32(&offset));
691061da546Spatrick break;
692061da546Spatrick
693061da546Spatrick case eFormatAddressInfo: {
694061da546Spatrick addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
695061da546Spatrick item_bit_offset);
696061da546Spatrick s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
697061da546Spatrick (int)(2 * item_byte_size), addr);
698061da546Spatrick if (exe_scope) {
699061da546Spatrick TargetSP target_sp(exe_scope->CalculateTarget());
700061da546Spatrick lldb_private::Address so_addr;
701061da546Spatrick if (target_sp) {
702061da546Spatrick if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
703061da546Spatrick so_addr)) {
704061da546Spatrick s->PutChar(' ');
705061da546Spatrick so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
706061da546Spatrick Address::DumpStyleModuleWithFileAddress);
707061da546Spatrick } else {
708061da546Spatrick so_addr.SetOffset(addr);
709061da546Spatrick so_addr.Dump(s, exe_scope,
710061da546Spatrick Address::DumpStyleResolvedPointerDescription);
711be691f3bSpatrick if (ProcessSP process_sp = exe_scope->CalculateProcess()) {
712be691f3bSpatrick if (ABISP abi_sp = process_sp->GetABI()) {
713be691f3bSpatrick addr_t addr_fixed = abi_sp->FixCodeAddress(addr);
714be691f3bSpatrick if (target_sp->GetSectionLoadList().ResolveLoadAddress(
715be691f3bSpatrick addr_fixed, so_addr)) {
716be691f3bSpatrick s->PutChar(' ');
717be691f3bSpatrick s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),
718be691f3bSpatrick (int)(2 * item_byte_size), addr_fixed);
719be691f3bSpatrick s->PutChar(' ');
720be691f3bSpatrick so_addr.Dump(s, exe_scope,
721be691f3bSpatrick Address::DumpStyleResolvedDescription,
722be691f3bSpatrick Address::DumpStyleModuleWithFileAddress);
723be691f3bSpatrick }
724be691f3bSpatrick }
725be691f3bSpatrick }
726061da546Spatrick }
727061da546Spatrick }
728061da546Spatrick }
729061da546Spatrick } break;
730061da546Spatrick
731061da546Spatrick case eFormatHexFloat:
732061da546Spatrick if (sizeof(float) == item_byte_size) {
733061da546Spatrick char float_cstr[256];
734061da546Spatrick llvm::APFloat ap_float(DE.GetFloat(&offset));
735061da546Spatrick ap_float.convertToHexString(float_cstr, 0, false,
736061da546Spatrick llvm::APFloat::rmNearestTiesToEven);
737061da546Spatrick s->Printf("%s", float_cstr);
738061da546Spatrick break;
739061da546Spatrick } else if (sizeof(double) == item_byte_size) {
740061da546Spatrick char float_cstr[256];
741061da546Spatrick llvm::APFloat ap_float(DE.GetDouble(&offset));
742061da546Spatrick ap_float.convertToHexString(float_cstr, 0, false,
743061da546Spatrick llvm::APFloat::rmNearestTiesToEven);
744061da546Spatrick s->Printf("%s", float_cstr);
745061da546Spatrick break;
746061da546Spatrick } else {
747061da546Spatrick s->Printf("error: unsupported byte size (%" PRIu64
748061da546Spatrick ") for hex float format",
749061da546Spatrick (uint64_t)item_byte_size);
750061da546Spatrick return offset;
751061da546Spatrick }
752061da546Spatrick break;
753061da546Spatrick
754061da546Spatrick // please keep the single-item formats below in sync with
755061da546Spatrick // FormatManager::GetSingleItemFormat if you fail to do so, users will
756061da546Spatrick // start getting different outputs depending on internal implementation
757061da546Spatrick // details they should not care about ||
758061da546Spatrick case eFormatVectorOfChar: // ||
759061da546Spatrick s->PutChar('{'); // \/
760061da546Spatrick offset =
761061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
762061da546Spatrick item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
763061da546Spatrick s->PutChar('}');
764061da546Spatrick break;
765061da546Spatrick
766061da546Spatrick case eFormatVectorOfSInt8:
767061da546Spatrick s->PutChar('{');
768061da546Spatrick offset =
769061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
770061da546Spatrick item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
771061da546Spatrick s->PutChar('}');
772061da546Spatrick break;
773061da546Spatrick
774061da546Spatrick case eFormatVectorOfUInt8:
775061da546Spatrick s->PutChar('{');
776061da546Spatrick offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
777061da546Spatrick item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
778061da546Spatrick s->PutChar('}');
779061da546Spatrick break;
780061da546Spatrick
781061da546Spatrick case eFormatVectorOfSInt16:
782061da546Spatrick s->PutChar('{');
783061da546Spatrick offset = DumpDataExtractor(
784061da546Spatrick DE, s, offset, eFormatDecimal, sizeof(uint16_t),
785061da546Spatrick item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
786061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
787061da546Spatrick s->PutChar('}');
788061da546Spatrick break;
789061da546Spatrick
790061da546Spatrick case eFormatVectorOfUInt16:
791061da546Spatrick s->PutChar('{');
792061da546Spatrick offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
793061da546Spatrick item_byte_size / sizeof(uint16_t),
794061da546Spatrick item_byte_size / sizeof(uint16_t),
795061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
796061da546Spatrick s->PutChar('}');
797061da546Spatrick break;
798061da546Spatrick
799061da546Spatrick case eFormatVectorOfSInt32:
800061da546Spatrick s->PutChar('{');
801061da546Spatrick offset = DumpDataExtractor(
802061da546Spatrick DE, s, offset, eFormatDecimal, sizeof(uint32_t),
803061da546Spatrick item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
804061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
805061da546Spatrick s->PutChar('}');
806061da546Spatrick break;
807061da546Spatrick
808061da546Spatrick case eFormatVectorOfUInt32:
809061da546Spatrick s->PutChar('{');
810061da546Spatrick offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
811061da546Spatrick item_byte_size / sizeof(uint32_t),
812061da546Spatrick item_byte_size / sizeof(uint32_t),
813061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
814061da546Spatrick s->PutChar('}');
815061da546Spatrick break;
816061da546Spatrick
817061da546Spatrick case eFormatVectorOfSInt64:
818061da546Spatrick s->PutChar('{');
819061da546Spatrick offset = DumpDataExtractor(
820061da546Spatrick DE, s, offset, eFormatDecimal, sizeof(uint64_t),
821061da546Spatrick item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
822061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
823061da546Spatrick s->PutChar('}');
824061da546Spatrick break;
825061da546Spatrick
826061da546Spatrick case eFormatVectorOfUInt64:
827061da546Spatrick s->PutChar('{');
828061da546Spatrick offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
829061da546Spatrick item_byte_size / sizeof(uint64_t),
830061da546Spatrick item_byte_size / sizeof(uint64_t),
831061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
832061da546Spatrick s->PutChar('}');
833061da546Spatrick break;
834061da546Spatrick
835061da546Spatrick case eFormatVectorOfFloat16:
836061da546Spatrick s->PutChar('{');
837061da546Spatrick offset =
838061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
839061da546Spatrick item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
840061da546Spatrick s->PutChar('}');
841061da546Spatrick break;
842061da546Spatrick
843061da546Spatrick case eFormatVectorOfFloat32:
844061da546Spatrick s->PutChar('{');
845061da546Spatrick offset =
846061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
847061da546Spatrick item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
848061da546Spatrick s->PutChar('}');
849061da546Spatrick break;
850061da546Spatrick
851061da546Spatrick case eFormatVectorOfFloat64:
852061da546Spatrick s->PutChar('{');
853061da546Spatrick offset =
854061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
855061da546Spatrick item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
856061da546Spatrick s->PutChar('}');
857061da546Spatrick break;
858061da546Spatrick
859061da546Spatrick case eFormatVectorOfUInt128:
860061da546Spatrick s->PutChar('{');
861061da546Spatrick offset =
862061da546Spatrick DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
863061da546Spatrick item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
864061da546Spatrick s->PutChar('}');
865061da546Spatrick break;
866061da546Spatrick }
867061da546Spatrick }
868061da546Spatrick
869*f6aab3d8Srobert // If anything was printed we want to catch the end of the last line.
870*f6aab3d8Srobert // Since we will exit the for loop above before we get a chance to append to
871*f6aab3d8Srobert // it normally.
872*f6aab3d8Srobert if (offset > line_start_offset) {
873*f6aab3d8Srobert if (item_format == eFormatBytesWithASCII) {
874*f6aab3d8Srobert s->Printf("%*s",
875*f6aab3d8Srobert static_cast<int>(
876061da546Spatrick (num_per_line - (offset - line_start_offset)) * 3 + 2),
877061da546Spatrick "");
878061da546Spatrick DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
879061da546Spatrick offset - line_start_offset, SIZE_MAX,
880061da546Spatrick LLDB_INVALID_ADDRESS, 0, 0);
881061da546Spatrick }
882*f6aab3d8Srobert
883*f6aab3d8Srobert if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
884*f6aab3d8Srobert size_t line_len = offset - line_start_offset;
885*f6aab3d8Srobert lldb::addr_t line_base = base_addr + (offset - start_offset - line_len) /
886*f6aab3d8Srobert DE.getTargetByteSize();
887*f6aab3d8Srobert printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
888*f6aab3d8Srobert }
889*f6aab3d8Srobert }
890*f6aab3d8Srobert
891061da546Spatrick return offset; // Return the offset at which we ended up
892061da546Spatrick }
893061da546Spatrick
DumpHexBytes(Stream * s,const void * src,size_t src_len,uint32_t bytes_per_line,lldb::addr_t base_addr)894061da546Spatrick void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,
895061da546Spatrick uint32_t bytes_per_line,
896061da546Spatrick lldb::addr_t base_addr) {
897061da546Spatrick DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
898061da546Spatrick DumpDataExtractor(data, s,
899061da546Spatrick 0, // Offset into "src"
900061da546Spatrick lldb::eFormatBytes, // Dump as hex bytes
901061da546Spatrick 1, // Size of each item is 1 for single bytes
902061da546Spatrick src_len, // Number of bytes
903061da546Spatrick bytes_per_line, // Num bytes per line
904061da546Spatrick base_addr, // Base address
905061da546Spatrick 0, 0); // Bitfield info
906061da546Spatrick }
907