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