xref: /llvm-project/lldb/source/Core/DumpDataExtractor.cpp (revision c4fb7180cbbe977f1ab1ce945a691550f8fdd1fb)
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-exception
6 //
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 
48 using namespace lldb_private;
49 using namespace lldb;
50 
51 #define NON_PRINTABLE_CHAR '.'
52 
53 static 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 
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);
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.
120 static 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       }
161     }
162   } else
163     s->Printf("invalid target");
164 
165   return offset;
166 }
167 
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) {
173   switch (c) {
174   case '\033':
175     // Common non-standard escape code for 'escape'.
176     s.Printf("\\e");
177     return true;
178   case '\a':
179     s.Printf("\\a");
180     return true;
181   case '\b':
182     s.Printf("\\b");
183     return true;
184   case '\f':
185     s.Printf("\\f");
186     return true;
187   case '\n':
188     s.Printf("\\n");
189     return true;
190   case '\r':
191     s.Printf("\\r");
192     return true;
193   case '\t':
194     s.Printf("\\t");
195     return true;
196   case '\v':
197     s.Printf("\\v");
198     return true;
199   case '\0':
200     s.Printf("\\0");
201     return true;
202   default:
203     return false;
204   }
205 }
206 
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))
211     return;
212   if (llvm::isPrint(c)) {
213     s.PutChar(c);
214     return;
215   }
216   s.Printf("\\x%2.2hhx", c);
217 }
218 
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.
227   if (std::isnan(f)) {
228     if (std::signbit(f))
229       ss << '-';
230     ss << "nan";
231     return;
232   }
233   if (std::isinf(f)) {
234     if (std::signbit(f))
235       ss << '-';
236     ss << "inf";
237     return;
238   }
239   ss << f;
240 }
241 
242 static std::optional<MemoryTagMap>
243 GetMemoryTags(lldb::addr_t addr, size_t length,
244               ExecutionContextScope *exe_scope) {
245   assert(addr != LLDB_INVALID_ADDRESS);
246 
247   if (!exe_scope)
248     return std::nullopt;
249 
250   TargetSP target_sp = exe_scope->CalculateTarget();
251   if (!target_sp)
252     return std::nullopt;
253 
254   ProcessSP process_sp = target_sp->CalculateProcess();
255   if (!process_sp)
256     return std::nullopt;
257 
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());
262     return std::nullopt;
263   }
264 
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);
268 
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
273   // for an error.
274   if (!tagged_ranges_or_err) {
275     llvm::consumeError(tagged_ranges_or_err.takeError());
276     return std::nullopt;
277   }
278   if (tagged_ranges_or_err->empty())
279     return std::nullopt;
280 
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());
285 
286     if (tags_or_err)
287       memory_tag_map.InsertTags(range.GetRangeBase(), *tags_or_err);
288     else
289       llvm::consumeError(tags_or_err.takeError());
290   }
291 
292   if (memory_tag_map.Empty())
293     return std::nullopt;
294 
295   return memory_tag_map;
296 }
297 
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);
303 
304   // Only print if there is at least one tag for this line
305   if (tags.empty())
306     return;
307 
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) {
312     if (tag)
313       s->Printf(" 0x%" PRIx64, *tag);
314     else
315       s->PutCString(" <no tag>");
316   }
317   s->PutCString(")");
318 }
319 
320 static const llvm::fltSemantics &GetFloatSemantics(const TargetSP &target_sp,
321                                                    size_t byte_size) {
322   if (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);
329   }
330   // No target, just make a reasonable guess
331   switch(byte_size) {
332     case 2:
333       return llvm::APFloat::IEEEhalf();
334     case 4:
335       return llvm::APFloat::IEEEsingle();
336     case 8:
337       return llvm::APFloat::IEEEdouble();
338   }
339   return llvm::APFloat::Bogus();
340 }
341 
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) {
351   if (s == nullptr)
352     return start_offset;
353 
354   if (item_format == eFormatPointer) {
355     if (item_byte_size != 4 && item_byte_size != 8)
356       item_byte_size = s->GetAddressByteSize();
357   }
358 
359   offset_t offset = start_offset;
360 
361   std::optional<MemoryTagMap> memory_tag_map;
362   if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS)
363     memory_tag_map =
364         GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope);
365 
366   if (item_format == eFormatInstruction)
367     return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
368                             item_count);
369 
370   if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
371       item_byte_size > 8)
372     item_format = eFormatHex;
373 
374   lldb::offset_t line_start_offset = start_offset;
375   for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
376        ++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
381       if (count > 0) {
382         if (item_format == eFormatBytesWithASCII &&
383             offset > line_start_offset) {
384           s->Printf("%*s",
385                     static_cast<int>(
386                         (num_per_line - (offset - line_start_offset)) * 3 + 2),
387                     "");
388           DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
389                             offset - line_start_offset, SIZE_MAX,
390                             LLDB_INVALID_ADDRESS, 0, 0);
391         }
392 
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 =
396               base_addr +
397               (offset - start_offset - line_len) / DE.getTargetByteSize();
398           printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
399         }
400 
401         s->EOL();
402       }
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()));
407 
408       line_start_offset = offset;
409     } else if (item_format != eFormatChar &&
410                item_format != eFormatCharPrintable &&
411                item_format != eFormatCharArray && count > 0) {
412       s->PutChar(' ');
413     }
414 
415     switch (item_format) {
416     case eFormatBoolean:
417       if (item_byte_size <= 8)
418         s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
419                                              item_bit_size, item_bit_offset)
420                             ? "true"
421                             : "false");
422       else {
423         s->Printf("error: unsupported byte size (%" PRIu64
424                   ") for boolean format",
425                   (uint64_t)item_byte_size);
426         return offset;
427       }
428       break;
429 
430     case eFormatBinary:
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
435         // C++ libraries
436         std::string binary_value(64, '0');
437         std::bitset<64> bits(uval64);
438         for (uint32_t i = 0; i < 64; ++i)
439           if (bits[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);
445       } else {
446         const bool is_signed = false;
447         const unsigned radix = 2;
448         offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
449       }
450       break;
451 
452     case eFormatBytes:
453     case eFormatBytesWithASCII:
454       for (uint32_t i = 0; i < item_byte_size; ++i) {
455         s->Printf("%2.2x", DE.GetU8(&offset));
456       }
457 
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)
461         s->PutChar(' ');
462       break;
463 
464     case eFormatChar:
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);
471         return offset;
472       }
473 
474       // If we are only printing one character surround it with single quotes
475       if (item_count == 1 && item_format == eFormatChar)
476         s->PutChar('\'');
477 
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);
486           else
487             s->Printf("%" PRIu64, ch);
488         }
489       } else {
490         s->PutChar(NON_PRINTABLE_CHAR);
491       }
492 
493       // If we are only printing one character surround it with single quotes
494       if (item_count == 1 && item_format == eFormatChar)
495         s->PutChar('\'');
496     } break;
497 
498     case eFormatEnum: // Print enum value as a signed integer when we don't get
499                       // the enum type
500     case eFormatDecimal:
501       if (item_byte_size <= 8)
502         s->Printf("%" PRId64,
503                   DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
504                                        item_bit_offset));
505       else {
506         const bool is_signed = true;
507         const unsigned radix = 10;
508         offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
509       }
510       break;
511 
512     case eFormatUnsigned:
513       if (item_byte_size <= 8)
514         s->Printf("%" PRIu64,
515                   DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
516                                        item_bit_offset));
517       else {
518         const bool is_signed = false;
519         const unsigned radix = 10;
520         offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
521       }
522       break;
523 
524     case eFormatOctal:
525       if (item_byte_size <= 8)
526         s->Printf("0%" PRIo64,
527                   DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
528                                        item_bit_offset));
529       else {
530         const bool is_signed = false;
531         const unsigned radix = 8;
532         offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
533       }
534       break;
535 
536     case eFormatOSType: {
537       uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
538                                              item_bit_size, item_bit_offset);
539       s->PutChar('\'');
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);
543       }
544       s->PutChar('\'');
545     } break;
546 
547     case eFormatCString: {
548       const char *cstr = DE.GetCStr(&offset);
549 
550       if (!cstr) {
551         s->Printf("NULL");
552         offset = LLDB_INVALID_OFFSET;
553       } else {
554         s->PutChar('\"');
555 
556         while (const char c = *cstr) {
557           DumpCharacter(*s, c);
558           ++cstr;
559         }
560 
561         s->PutChar('\"');
562       }
563     } break;
564 
565     case eFormatPointer:
566       DumpAddress(s->AsRawOstream(),
567                   DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
568                                        item_bit_offset),
569                   sizeof(addr_t));
570       break;
571 
572     case eFormatComplexInteger: {
573       size_t complex_int_byte_size = item_byte_size / 2;
574 
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));
580       } else {
581         s->Printf("error: unsupported byte size (%" PRIu64
582                   ") for complex integer format",
583                   (uint64_t)item_byte_size);
584         return offset;
585       }
586     } break;
587 
588     case eFormatComplex:
589       if (sizeof(float) * 2 == item_byte_size) {
590         float f32_1 = DE.GetFloat(&offset);
591         float f32_2 = DE.GetFloat(&offset);
592 
593         s->Printf("%g + %gi", f32_1, f32_2);
594         break;
595       } else if (sizeof(double) * 2 == item_byte_size) {
596         double d64_1 = DE.GetDouble(&offset);
597         double d64_2 = DE.GetDouble(&offset);
598 
599         s->Printf("%lg + %lgi", d64_1, d64_2);
600         break;
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);
605         break;
606       } else {
607         s->Printf("error: unsupported byte size (%" PRIu64
608                   ") for complex float format",
609                   (uint64_t)item_byte_size);
610         return offset;
611       }
612       break;
613 
614     default:
615     case eFormatDefault:
616     case eFormatHex:
617     case eFormatHexUppercase: {
618       bool wantsuppercase = (item_format == eFormatHexUppercase);
619       switch (item_byte_size) {
620       case 1:
621       case 2:
622       case 4:
623       case 8:
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,
629                                          item_bit_offset));
630         } else {
631           s->Printf(wantsuppercase ? "0x%" PRIX64 : "0x%" PRIx64,
632                     DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
633                                          item_bit_offset));
634         }
635         break;
636       default: {
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);
640         if (bytes) {
641           s->PutCString("0x");
642           uint32_t idx;
643           if (DE.GetByteOrder() == eByteOrderBig) {
644             for (idx = 0; idx < item_byte_size; ++idx)
645               s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
646           } else {
647             for (idx = 0; idx < item_byte_size; ++idx)
648               s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
649                         bytes[item_byte_size - 1 - idx]);
650           }
651         }
652       } break;
653       }
654     } break;
655 
656     case eFormatFloat: {
657       TargetSP target_sp;
658       if (exe_scope)
659         target_sp = exe_scope->CalculateTarget();
660 
661       std::optional<unsigned> format_max_padding;
662       if (target_sp)
663         format_max_padding = target_sp->GetMaxZeroPaddingInFloatFormat();
664 
665       // Show full precision when printing float values
666       const unsigned format_precision = 0;
667 
668       const llvm::fltSemantics &semantics =
669           GetFloatSemantics(target_sp, item_byte_size);
670 
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);
678       if (apint) {
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);
683         else
684           apfloat.toString(sv, format_precision);
685         s->AsRawOstream() << sv;
686       } else {
687         s->Format("error: unsupported byte size ({0}) for float format",
688                   item_byte_size);
689         return offset;
690       }
691     } break;
692 
693     case eFormatUnicode16:
694       s->Printf("U+%4.4x", DE.GetU16(&offset));
695       break;
696 
697     case eFormatUnicode32:
698       s->Printf("U+0x%8.8x", DE.GetU32(&offset));
699       break;
700 
701     case eFormatAddressInfo: {
702       addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
703                                          item_bit_offset);
704       s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
705                 (int)(2 * item_byte_size), addr);
706       if (exe_scope) {
707         TargetSP target_sp(exe_scope->CalculateTarget());
708         lldb_private::Address so_addr;
709         if (target_sp) {
710           if (target_sp->ResolveLoadAddress(addr, so_addr)) {
711             s->PutChar(' ');
712             so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
713                          Address::DumpStyleModuleWithFileAddress);
714           } else {
715             so_addr.SetOffset(addr);
716             so_addr.Dump(s, exe_scope,
717                          Address::DumpStyleResolvedPointerDescription);
718             if (ProcessSP process_sp = exe_scope->CalculateProcess()) {
719               if (ABISP abi_sp = process_sp->GetABI()) {
720                 addr_t addr_fixed = abi_sp->FixCodeAddress(addr);
721                 if (target_sp->ResolveLoadAddress(addr_fixed, so_addr)) {
722                   s->PutChar(' ');
723                   s->Printf("(0x%*.*" PRIx64 ")", (int)(2 * item_byte_size),
724                             (int)(2 * item_byte_size), addr_fixed);
725                   s->PutChar(' ');
726                   so_addr.Dump(s, exe_scope,
727                                Address::DumpStyleResolvedDescription,
728                                Address::DumpStyleModuleWithFileAddress);
729                 }
730               }
731             }
732           }
733         }
734       }
735     } break;
736 
737     case eFormatHexFloat:
738       if (sizeof(float) == item_byte_size) {
739         char float_cstr[256];
740         llvm::APFloat ap_float(DE.GetFloat(&offset));
741         ap_float.convertToHexString(float_cstr, 0, false,
742                                     llvm::APFloat::rmNearestTiesToEven);
743         s->Printf("%s", float_cstr);
744         break;
745       } else if (sizeof(double) == item_byte_size) {
746         char float_cstr[256];
747         llvm::APFloat ap_float(DE.GetDouble(&offset));
748         ap_float.convertToHexString(float_cstr, 0, false,
749                                     llvm::APFloat::rmNearestTiesToEven);
750         s->Printf("%s", float_cstr);
751         break;
752       } else {
753         s->Printf("error: unsupported byte size (%" PRIu64
754                   ") for hex float format",
755                   (uint64_t)item_byte_size);
756         return offset;
757       }
758       break;
759 
760     // please keep the single-item formats below in sync with
761     // FormatManager::GetSingleItemFormat if you fail to do so, users will
762     // start getting different outputs depending on internal implementation
763     // details they should not care about ||
764     case eFormatVectorOfChar: //   ||
765       s->PutChar('{');        //   \/
766       offset =
767           DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
768                             item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
769       s->PutChar('}');
770       break;
771 
772     case eFormatVectorOfSInt8:
773       s->PutChar('{');
774       offset =
775           DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
776                             item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
777       s->PutChar('}');
778       break;
779 
780     case eFormatVectorOfUInt8:
781       s->PutChar('{');
782       offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
783                                  item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
784       s->PutChar('}');
785       break;
786 
787     case eFormatVectorOfSInt16:
788       s->PutChar('{');
789       offset = DumpDataExtractor(
790           DE, s, offset, eFormatDecimal, sizeof(uint16_t),
791           item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
792           LLDB_INVALID_ADDRESS, 0, 0);
793       s->PutChar('}');
794       break;
795 
796     case eFormatVectorOfUInt16:
797       s->PutChar('{');
798       offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
799                                  item_byte_size / sizeof(uint16_t),
800                                  item_byte_size / sizeof(uint16_t),
801                                  LLDB_INVALID_ADDRESS, 0, 0);
802       s->PutChar('}');
803       break;
804 
805     case eFormatVectorOfSInt32:
806       s->PutChar('{');
807       offset = DumpDataExtractor(
808           DE, s, offset, eFormatDecimal, sizeof(uint32_t),
809           item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
810           LLDB_INVALID_ADDRESS, 0, 0);
811       s->PutChar('}');
812       break;
813 
814     case eFormatVectorOfUInt32:
815       s->PutChar('{');
816       offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
817                                  item_byte_size / sizeof(uint32_t),
818                                  item_byte_size / sizeof(uint32_t),
819                                  LLDB_INVALID_ADDRESS, 0, 0);
820       s->PutChar('}');
821       break;
822 
823     case eFormatVectorOfSInt64:
824       s->PutChar('{');
825       offset = DumpDataExtractor(
826           DE, s, offset, eFormatDecimal, sizeof(uint64_t),
827           item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
828           LLDB_INVALID_ADDRESS, 0, 0);
829       s->PutChar('}');
830       break;
831 
832     case eFormatVectorOfUInt64:
833       s->PutChar('{');
834       offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
835                                  item_byte_size / sizeof(uint64_t),
836                                  item_byte_size / sizeof(uint64_t),
837                                  LLDB_INVALID_ADDRESS, 0, 0);
838       s->PutChar('}');
839       break;
840 
841     case eFormatVectorOfFloat16:
842       s->PutChar('{');
843       offset =
844           DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
845                             item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
846       s->PutChar('}');
847       break;
848 
849     case eFormatVectorOfFloat32:
850       s->PutChar('{');
851       offset =
852           DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
853                             item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
854       s->PutChar('}');
855       break;
856 
857     case eFormatVectorOfFloat64:
858       s->PutChar('{');
859       offset =
860           DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
861                             item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
862       s->PutChar('}');
863       break;
864 
865     case eFormatVectorOfUInt128:
866       s->PutChar('{');
867       offset =
868           DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
869                             item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
870       s->PutChar('}');
871       break;
872     }
873   }
874 
875   // If anything was printed we want to catch the end of the last line.
876   // Since we will exit the for loop above before we get a chance to append to
877   // it normally.
878   if (offset > line_start_offset) {
879     if (item_format == eFormatBytesWithASCII) {
880       s->Printf("%*s",
881                 static_cast<int>(
882                     (num_per_line - (offset - line_start_offset)) * 3 + 2),
883                 "");
884       DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
885                         offset - line_start_offset, SIZE_MAX,
886                         LLDB_INVALID_ADDRESS, 0, 0);
887     }
888 
889     if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
890       size_t line_len = offset - line_start_offset;
891       lldb::addr_t line_base = base_addr + (offset - start_offset - line_len) /
892                                                DE.getTargetByteSize();
893       printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
894     }
895   }
896 
897   return offset; // Return the offset at which we ended up
898 }
899 
900 void lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,
901                                 uint32_t bytes_per_line,
902                                 lldb::addr_t base_addr) {
903   DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
904   DumpDataExtractor(data, s,
905                     0,                  // Offset into "src"
906                     lldb::eFormatBytes, // Dump as hex bytes
907                     1,              // Size of each item is 1 for single bytes
908                     src_len,        // Number of bytes
909                     bytes_per_line, // Num bytes per line
910                     base_addr,      // Base address
911                     0, 0);          // Bitfield info
912 }
913