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