DumpDataExtractor.cpp revision 317027
1317027Sdim//===-- DumpDataExtractor.cpp -----------------------------------*- C++ -*-===//
2317027Sdim//
3317027Sdim//                     The LLVM Compiler Infrastructure
4317027Sdim//
5317027Sdim// This file is distributed under the University of Illinois Open Source
6317027Sdim// License. See LICENSE.TXT for details.
7317027Sdim//
8317027Sdim//===----------------------------------------------------------------------===//
9317027Sdim
10317027Sdim#include "lldb/Core/DumpDataExtractor.h"
11317027Sdim
12317027Sdim#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
13317027Sdim#include "lldb/lldb-forward.h" // for TargetSP, DisassemblerSP
14317027Sdim
15317027Sdim#include "lldb/Core/Address.h" // for Address
16317027Sdim#include "lldb/Core/Disassembler.h"
17317027Sdim#include "lldb/Core/ModuleList.h" // for ModuleList
18317027Sdim#include "lldb/Symbol/ClangASTContext.h"
19317027Sdim#include "lldb/Target/ExecutionContext.h"
20317027Sdim#include "lldb/Target/ExecutionContextScope.h"
21317027Sdim#include "lldb/Target/SectionLoadList.h"
22317027Sdim#include "lldb/Target/Target.h"
23317027Sdim#include "lldb/Utility/DataExtractor.h"
24317027Sdim#include "lldb/Utility/Stream.h"
25317027Sdim
26317027Sdim#include "clang/AST/ASTContext.h"    // for ASTContext
27317027Sdim#include "clang/AST/CanonicalType.h" // for CanQualType
28317027Sdim
29317027Sdim#include "llvm/ADT/APFloat.h"     // for APFloat, APFloatBase:...
30317027Sdim#include "llvm/ADT/APInt.h"       // for APInt
31317027Sdim#include "llvm/ADT/ArrayRef.h"    // for ArrayRef
32317027Sdim#include "llvm/ADT/SmallVector.h" // for SmallVector
33317027Sdim
34317027Sdim#include <limits> // for numeric_limits, numer...
35317027Sdim#include <memory> // for shared_ptr
36317027Sdim#include <string> // for string, basic_string
37317027Sdim
38317027Sdim#include <assert.h>   // for assert
39317027Sdim#include <ctype.h>    // for isprint
40317027Sdim#include <inttypes.h> // for PRIu64, PRIx64, PRIX64
41317027Sdim#include <math.h>     // for ldexpf
42317027Sdim
43317027Sdim#include <bitset>
44317027Sdim#include <sstream>
45317027Sdim
46317027Sdimusing namespace lldb_private;
47317027Sdimusing namespace lldb;
48317027Sdim
49317027Sdim#define NON_PRINTABLE_CHAR '.'
50317027Sdim
51317027Sdimstatic float half2float(uint16_t half) {
52317027Sdim  union {
53317027Sdim    float f;
54317027Sdim    uint32_t u;
55317027Sdim  } u;
56317027Sdim  int32_t v = (int16_t)half;
57317027Sdim
58317027Sdim  if (0 == (v & 0x7c00)) {
59317027Sdim    u.u = v & 0x80007FFFU;
60317027Sdim    return u.f * ldexpf(1, 125);
61317027Sdim  }
62317027Sdim
63317027Sdim  v <<= 13;
64317027Sdim  u.u = v | 0x70000000U;
65317027Sdim  return u.f * ldexpf(1, -112);
66317027Sdim}
67317027Sdim
68317027Sdimstatic bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr,
69317027Sdim                     lldb::offset_t byte_size, llvm::APInt &result) {
70317027Sdim  llvm::SmallVector<uint64_t, 2> uint64_array;
71317027Sdim  lldb::offset_t bytes_left = byte_size;
72317027Sdim  uint64_t u64;
73317027Sdim  const lldb::ByteOrder byte_order = data.GetByteOrder();
74317027Sdim  if (byte_order == lldb::eByteOrderLittle) {
75317027Sdim    while (bytes_left > 0) {
76317027Sdim      if (bytes_left >= 8) {
77317027Sdim        u64 = data.GetU64(offset_ptr);
78317027Sdim        bytes_left -= 8;
79317027Sdim      } else {
80317027Sdim        u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left);
81317027Sdim        bytes_left = 0;
82317027Sdim      }
83317027Sdim      uint64_array.push_back(u64);
84317027Sdim    }
85317027Sdim    result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
86317027Sdim    return true;
87317027Sdim  } else if (byte_order == lldb::eByteOrderBig) {
88317027Sdim    lldb::offset_t be_offset = *offset_ptr + byte_size;
89317027Sdim    lldb::offset_t temp_offset;
90317027Sdim    while (bytes_left > 0) {
91317027Sdim      if (bytes_left >= 8) {
92317027Sdim        be_offset -= 8;
93317027Sdim        temp_offset = be_offset;
94317027Sdim        u64 = data.GetU64(&temp_offset);
95317027Sdim        bytes_left -= 8;
96317027Sdim      } else {
97317027Sdim        be_offset -= bytes_left;
98317027Sdim        temp_offset = be_offset;
99317027Sdim        u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left);
100317027Sdim        bytes_left = 0;
101317027Sdim      }
102317027Sdim      uint64_array.push_back(u64);
103317027Sdim    }
104317027Sdim    *offset_ptr += byte_size;
105317027Sdim    result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array));
106317027Sdim    return true;
107317027Sdim  }
108317027Sdim  return false;
109317027Sdim}
110317027Sdim
111317027Sdimstatic lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
112317027Sdim                                lldb::offset_t offset, lldb::offset_t byte_size,
113317027Sdim                                bool is_signed, unsigned radix) {
114317027Sdim  llvm::APInt apint;
115317027Sdim  if (GetAPInt(data, &offset, byte_size, apint)) {
116317027Sdim    std::string apint_str(apint.toString(radix, is_signed));
117317027Sdim    switch (radix) {
118317027Sdim    case 2:
119317027Sdim      s->Write("0b", 2);
120317027Sdim      break;
121317027Sdim    case 8:
122317027Sdim      s->Write("0", 1);
123317027Sdim      break;
124317027Sdim    case 10:
125317027Sdim      break;
126317027Sdim    }
127317027Sdim    s->Write(apint_str.c_str(), apint_str.size());
128317027Sdim  }
129317027Sdim  return offset;
130317027Sdim}
131317027Sdim
132317027Sdimlldb::offset_t lldb_private::DumpDataExtractor(
133317027Sdim    const DataExtractor &DE, Stream *s, offset_t start_offset,
134317027Sdim    lldb::Format item_format, size_t item_byte_size, size_t item_count,
135317027Sdim    size_t num_per_line, uint64_t base_addr,
136317027Sdim    uint32_t item_bit_size,   // If zero, this is not a bitfield value, if
137317027Sdim                              // non-zero, the value is a bitfield
138317027Sdim    uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
139317027Sdim                              // shift amount to apply to a bitfield
140317027Sdim    ExecutionContextScope *exe_scope) {
141317027Sdim  if (s == nullptr)
142317027Sdim    return start_offset;
143317027Sdim
144317027Sdim  if (item_format == eFormatPointer) {
145317027Sdim    if (item_byte_size != 4 && item_byte_size != 8)
146317027Sdim      item_byte_size = s->GetAddressByteSize();
147317027Sdim  }
148317027Sdim
149317027Sdim  offset_t offset = start_offset;
150317027Sdim
151317027Sdim  if (item_format == eFormatInstruction) {
152317027Sdim    TargetSP target_sp;
153317027Sdim    if (exe_scope)
154317027Sdim      target_sp = exe_scope->CalculateTarget();
155317027Sdim    if (target_sp) {
156317027Sdim      DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
157317027Sdim          target_sp->GetArchitecture(), nullptr, nullptr));
158317027Sdim      if (disassembler_sp) {
159317027Sdim        lldb::addr_t addr = base_addr + start_offset;
160317027Sdim        lldb_private::Address so_addr;
161317027Sdim        bool data_from_file = true;
162317027Sdim        if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
163317027Sdim          data_from_file = false;
164317027Sdim        } else {
165317027Sdim          if (target_sp->GetSectionLoadList().IsEmpty() ||
166317027Sdim              !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
167317027Sdim            so_addr.SetRawAddress(addr);
168317027Sdim        }
169317027Sdim
170317027Sdim        size_t bytes_consumed = disassembler_sp->DecodeInstructions(
171317027Sdim            so_addr, DE, start_offset, item_count, false, data_from_file);
172317027Sdim
173317027Sdim        if (bytes_consumed) {
174317027Sdim          offset += bytes_consumed;
175317027Sdim          const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
176317027Sdim          const bool show_bytes = true;
177317027Sdim          ExecutionContext exe_ctx;
178317027Sdim          exe_scope->CalculateExecutionContext(exe_ctx);
179317027Sdim          disassembler_sp->GetInstructionList().Dump(s, show_address,
180317027Sdim                                                     show_bytes, &exe_ctx);
181317027Sdim        }
182317027Sdim      }
183317027Sdim    } else
184317027Sdim      s->Printf("invalid target");
185317027Sdim
186317027Sdim    return offset;
187317027Sdim  }
188317027Sdim
189317027Sdim  if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
190317027Sdim      item_byte_size > 8)
191317027Sdim    item_format = eFormatHex;
192317027Sdim
193317027Sdim  lldb::offset_t line_start_offset = start_offset;
194317027Sdim  for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
195317027Sdim       ++count) {
196317027Sdim    if ((count % num_per_line) == 0) {
197317027Sdim      if (count > 0) {
198317027Sdim        if (item_format == eFormatBytesWithASCII &&
199317027Sdim            offset > line_start_offset) {
200317027Sdim          s->Printf("%*s",
201317027Sdim                    static_cast<int>(
202317027Sdim                        (num_per_line - (offset - line_start_offset)) * 3 + 2),
203317027Sdim                    "");
204317027Sdim          DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
205317027Sdim                            offset - line_start_offset, SIZE_MAX,
206317027Sdim                            LLDB_INVALID_ADDRESS, 0, 0);
207317027Sdim        }
208317027Sdim        s->EOL();
209317027Sdim      }
210317027Sdim      if (base_addr != LLDB_INVALID_ADDRESS)
211317027Sdim        s->Printf("0x%8.8" PRIx64 ": ",
212317027Sdim                  (uint64_t)(base_addr +
213317027Sdim                             (offset - start_offset) / DE.getTargetByteSize()));
214317027Sdim
215317027Sdim      line_start_offset = offset;
216317027Sdim    } else if (item_format != eFormatChar &&
217317027Sdim               item_format != eFormatCharPrintable &&
218317027Sdim               item_format != eFormatCharArray && count > 0) {
219317027Sdim      s->PutChar(' ');
220317027Sdim    }
221317027Sdim
222317027Sdim    switch (item_format) {
223317027Sdim    case eFormatBoolean:
224317027Sdim      if (item_byte_size <= 8)
225317027Sdim        s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size,
226317027Sdim                                             item_bit_size, item_bit_offset)
227317027Sdim                            ? "true"
228317027Sdim                            : "false");
229317027Sdim      else {
230317027Sdim        s->Printf("error: unsupported byte size (%" PRIu64
231317027Sdim                  ") for boolean format",
232317027Sdim                  (uint64_t)item_byte_size);
233317027Sdim        return offset;
234317027Sdim      }
235317027Sdim      break;
236317027Sdim
237317027Sdim    case eFormatBinary:
238317027Sdim      if (item_byte_size <= 8) {
239317027Sdim        uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
240317027Sdim                                               item_bit_size, item_bit_offset);
241317027Sdim        // Avoid std::bitset<64>::to_string() since it is missing in
242317027Sdim        // earlier C++ libraries
243317027Sdim        std::string binary_value(64, '0');
244317027Sdim        std::bitset<64> bits(uval64);
245317027Sdim        for (uint32_t i = 0; i < 64; ++i)
246317027Sdim          if (bits[i])
247317027Sdim            binary_value[64 - 1 - i] = '1';
248317027Sdim        if (item_bit_size > 0)
249317027Sdim          s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size);
250317027Sdim        else if (item_byte_size > 0 && item_byte_size <= 8)
251317027Sdim          s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8);
252317027Sdim      } else {
253317027Sdim        const bool is_signed = false;
254317027Sdim        const unsigned radix = 2;
255317027Sdim        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
256317027Sdim      }
257317027Sdim      break;
258317027Sdim
259317027Sdim    case eFormatBytes:
260317027Sdim    case eFormatBytesWithASCII:
261317027Sdim      for (uint32_t i = 0; i < item_byte_size; ++i) {
262317027Sdim        s->Printf("%2.2x", DE.GetU8(&offset));
263317027Sdim      }
264317027Sdim
265317027Sdim      // Put an extra space between the groups of bytes if more than one
266317027Sdim      // is being dumped in a group (item_byte_size is more than 1).
267317027Sdim      if (item_byte_size > 1)
268317027Sdim        s->PutChar(' ');
269317027Sdim      break;
270317027Sdim
271317027Sdim    case eFormatChar:
272317027Sdim    case eFormatCharPrintable:
273317027Sdim    case eFormatCharArray: {
274317027Sdim      // If we are only printing one character surround it with single
275317027Sdim      // quotes
276317027Sdim      if (item_count == 1 && item_format == eFormatChar)
277317027Sdim        s->PutChar('\'');
278317027Sdim
279317027Sdim      const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size,
280317027Sdim                                               item_bit_size, item_bit_offset);
281317027Sdim      if (isprint(ch))
282317027Sdim        s->Printf("%c", (char)ch);
283317027Sdim      else if (item_format != eFormatCharPrintable) {
284317027Sdim        switch (ch) {
285317027Sdim        case '\033':
286317027Sdim          s->Printf("\\e");
287317027Sdim          break;
288317027Sdim        case '\a':
289317027Sdim          s->Printf("\\a");
290317027Sdim          break;
291317027Sdim        case '\b':
292317027Sdim          s->Printf("\\b");
293317027Sdim          break;
294317027Sdim        case '\f':
295317027Sdim          s->Printf("\\f");
296317027Sdim          break;
297317027Sdim        case '\n':
298317027Sdim          s->Printf("\\n");
299317027Sdim          break;
300317027Sdim        case '\r':
301317027Sdim          s->Printf("\\r");
302317027Sdim          break;
303317027Sdim        case '\t':
304317027Sdim          s->Printf("\\t");
305317027Sdim          break;
306317027Sdim        case '\v':
307317027Sdim          s->Printf("\\v");
308317027Sdim          break;
309317027Sdim        case '\0':
310317027Sdim          s->Printf("\\0");
311317027Sdim          break;
312317027Sdim        default:
313317027Sdim          if (item_byte_size == 1)
314317027Sdim            s->Printf("\\x%2.2x", (uint8_t)ch);
315317027Sdim          else
316317027Sdim            s->Printf("%" PRIu64, ch);
317317027Sdim          break;
318317027Sdim        }
319317027Sdim      } else {
320317027Sdim        s->PutChar(NON_PRINTABLE_CHAR);
321317027Sdim      }
322317027Sdim
323317027Sdim      // If we are only printing one character surround it with single quotes
324317027Sdim      if (item_count == 1 && item_format == eFormatChar)
325317027Sdim        s->PutChar('\'');
326317027Sdim    } break;
327317027Sdim
328317027Sdim    case eFormatEnum: // Print enum value as a signed integer when we don't get
329317027Sdim                      // the enum type
330317027Sdim    case eFormatDecimal:
331317027Sdim      if (item_byte_size <= 8)
332317027Sdim        s->Printf("%" PRId64,
333317027Sdim                  DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
334317027Sdim                                       item_bit_offset));
335317027Sdim      else {
336317027Sdim        const bool is_signed = true;
337317027Sdim        const unsigned radix = 10;
338317027Sdim        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
339317027Sdim      }
340317027Sdim      break;
341317027Sdim
342317027Sdim    case eFormatUnsigned:
343317027Sdim      if (item_byte_size <= 8)
344317027Sdim        s->Printf("%" PRIu64,
345317027Sdim                  DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
346317027Sdim                                       item_bit_offset));
347317027Sdim      else {
348317027Sdim        const bool is_signed = false;
349317027Sdim        const unsigned radix = 10;
350317027Sdim        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
351317027Sdim      }
352317027Sdim      break;
353317027Sdim
354317027Sdim    case eFormatOctal:
355317027Sdim      if (item_byte_size <= 8)
356317027Sdim        s->Printf("0%" PRIo64,
357317027Sdim                  DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size,
358317027Sdim                                       item_bit_offset));
359317027Sdim      else {
360317027Sdim        const bool is_signed = false;
361317027Sdim        const unsigned radix = 8;
362317027Sdim        offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix);
363317027Sdim      }
364317027Sdim      break;
365317027Sdim
366317027Sdim    case eFormatOSType: {
367317027Sdim      uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size,
368317027Sdim                                             item_bit_size, item_bit_offset);
369317027Sdim      s->PutChar('\'');
370317027Sdim      for (uint32_t i = 0; i < item_byte_size; ++i) {
371317027Sdim        uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8));
372317027Sdim        if (isprint(ch))
373317027Sdim          s->Printf("%c", ch);
374317027Sdim        else {
375317027Sdim          switch (ch) {
376317027Sdim          case '\033':
377317027Sdim            s->Printf("\\e");
378317027Sdim            break;
379317027Sdim          case '\a':
380317027Sdim            s->Printf("\\a");
381317027Sdim            break;
382317027Sdim          case '\b':
383317027Sdim            s->Printf("\\b");
384317027Sdim            break;
385317027Sdim          case '\f':
386317027Sdim            s->Printf("\\f");
387317027Sdim            break;
388317027Sdim          case '\n':
389317027Sdim            s->Printf("\\n");
390317027Sdim            break;
391317027Sdim          case '\r':
392317027Sdim            s->Printf("\\r");
393317027Sdim            break;
394317027Sdim          case '\t':
395317027Sdim            s->Printf("\\t");
396317027Sdim            break;
397317027Sdim          case '\v':
398317027Sdim            s->Printf("\\v");
399317027Sdim            break;
400317027Sdim          case '\0':
401317027Sdim            s->Printf("\\0");
402317027Sdim            break;
403317027Sdim          default:
404317027Sdim            s->Printf("\\x%2.2x", ch);
405317027Sdim            break;
406317027Sdim          }
407317027Sdim        }
408317027Sdim      }
409317027Sdim      s->PutChar('\'');
410317027Sdim    } break;
411317027Sdim
412317027Sdim    case eFormatCString: {
413317027Sdim      const char *cstr = DE.GetCStr(&offset);
414317027Sdim
415317027Sdim      if (!cstr) {
416317027Sdim        s->Printf("NULL");
417317027Sdim        offset = LLDB_INVALID_OFFSET;
418317027Sdim      } else {
419317027Sdim        s->PutChar('\"');
420317027Sdim
421317027Sdim        while (const char c = *cstr) {
422317027Sdim          if (isprint(c)) {
423317027Sdim            s->PutChar(c);
424317027Sdim          } else {
425317027Sdim            switch (c) {
426317027Sdim            case '\033':
427317027Sdim              s->Printf("\\e");
428317027Sdim              break;
429317027Sdim            case '\a':
430317027Sdim              s->Printf("\\a");
431317027Sdim              break;
432317027Sdim            case '\b':
433317027Sdim              s->Printf("\\b");
434317027Sdim              break;
435317027Sdim            case '\f':
436317027Sdim              s->Printf("\\f");
437317027Sdim              break;
438317027Sdim            case '\n':
439317027Sdim              s->Printf("\\n");
440317027Sdim              break;
441317027Sdim            case '\r':
442317027Sdim              s->Printf("\\r");
443317027Sdim              break;
444317027Sdim            case '\t':
445317027Sdim              s->Printf("\\t");
446317027Sdim              break;
447317027Sdim            case '\v':
448317027Sdim              s->Printf("\\v");
449317027Sdim              break;
450317027Sdim            default:
451317027Sdim              s->Printf("\\x%2.2x", c);
452317027Sdim              break;
453317027Sdim            }
454317027Sdim          }
455317027Sdim
456317027Sdim          ++cstr;
457317027Sdim        }
458317027Sdim
459317027Sdim        s->PutChar('\"');
460317027Sdim      }
461317027Sdim    } break;
462317027Sdim
463317027Sdim    case eFormatPointer:
464317027Sdim      s->Address(DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
465317027Sdim                                      item_bit_offset),
466317027Sdim                 sizeof(addr_t));
467317027Sdim      break;
468317027Sdim
469317027Sdim    case eFormatComplexInteger: {
470317027Sdim      size_t complex_int_byte_size = item_byte_size / 2;
471317027Sdim
472317027Sdim      if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) {
473317027Sdim        s->Printf("%" PRIu64,
474317027Sdim                  DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
475317027Sdim        s->Printf(" + %" PRIu64 "i",
476317027Sdim                  DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0));
477317027Sdim      } else {
478317027Sdim        s->Printf("error: unsupported byte size (%" PRIu64
479317027Sdim                  ") for complex integer format",
480317027Sdim                  (uint64_t)item_byte_size);
481317027Sdim        return offset;
482317027Sdim      }
483317027Sdim    } break;
484317027Sdim
485317027Sdim    case eFormatComplex:
486317027Sdim      if (sizeof(float) * 2 == item_byte_size) {
487317027Sdim        float f32_1 = DE.GetFloat(&offset);
488317027Sdim        float f32_2 = DE.GetFloat(&offset);
489317027Sdim
490317027Sdim        s->Printf("%g + %gi", f32_1, f32_2);
491317027Sdim        break;
492317027Sdim      } else if (sizeof(double) * 2 == item_byte_size) {
493317027Sdim        double d64_1 = DE.GetDouble(&offset);
494317027Sdim        double d64_2 = DE.GetDouble(&offset);
495317027Sdim
496317027Sdim        s->Printf("%lg + %lgi", d64_1, d64_2);
497317027Sdim        break;
498317027Sdim      } else if (sizeof(long double) * 2 == item_byte_size) {
499317027Sdim        long double ld64_1 = DE.GetLongDouble(&offset);
500317027Sdim        long double ld64_2 = DE.GetLongDouble(&offset);
501317027Sdim        s->Printf("%Lg + %Lgi", ld64_1, ld64_2);
502317027Sdim        break;
503317027Sdim      } else {
504317027Sdim        s->Printf("error: unsupported byte size (%" PRIu64
505317027Sdim                  ") for complex float format",
506317027Sdim                  (uint64_t)item_byte_size);
507317027Sdim        return offset;
508317027Sdim      }
509317027Sdim      break;
510317027Sdim
511317027Sdim    default:
512317027Sdim    case eFormatDefault:
513317027Sdim    case eFormatHex:
514317027Sdim    case eFormatHexUppercase: {
515317027Sdim      bool wantsuppercase = (item_format == eFormatHexUppercase);
516317027Sdim      switch (item_byte_size) {
517317027Sdim      case 1:
518317027Sdim      case 2:
519317027Sdim      case 4:
520317027Sdim      case 8:
521317027Sdim        s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64,
522317027Sdim                  (int)(2 * item_byte_size), (int)(2 * item_byte_size),
523317027Sdim                  DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
524317027Sdim                                       item_bit_offset));
525317027Sdim        break;
526317027Sdim      default: {
527317027Sdim        assert(item_bit_size == 0 && item_bit_offset == 0);
528317027Sdim        const uint8_t *bytes =
529317027Sdim            (const uint8_t *)DE.GetData(&offset, item_byte_size);
530317027Sdim        if (bytes) {
531317027Sdim          s->PutCString("0x");
532317027Sdim          uint32_t idx;
533317027Sdim          if (DE.GetByteOrder() == eByteOrderBig) {
534317027Sdim            for (idx = 0; idx < item_byte_size; ++idx)
535317027Sdim              s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]);
536317027Sdim          } else {
537317027Sdim            for (idx = 0; idx < item_byte_size; ++idx)
538317027Sdim              s->Printf(wantsuppercase ? "%2.2X" : "%2.2x",
539317027Sdim                        bytes[item_byte_size - 1 - idx]);
540317027Sdim          }
541317027Sdim        }
542317027Sdim      } break;
543317027Sdim      }
544317027Sdim    } break;
545317027Sdim
546317027Sdim    case eFormatFloat: {
547317027Sdim      TargetSP target_sp;
548317027Sdim      bool used_apfloat = false;
549317027Sdim      if (exe_scope)
550317027Sdim        target_sp = exe_scope->CalculateTarget();
551317027Sdim      if (target_sp) {
552317027Sdim        ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext();
553317027Sdim        if (clang_ast) {
554317027Sdim          clang::ASTContext *ast = clang_ast->getASTContext();
555317027Sdim          if (ast) {
556317027Sdim            llvm::SmallVector<char, 256> sv;
557317027Sdim            // Show full precision when printing float values
558317027Sdim            const unsigned format_precision = 0;
559317027Sdim            const unsigned format_max_padding = 100;
560317027Sdim            size_t item_bit_size = item_byte_size * 8;
561317027Sdim
562317027Sdim            if (item_bit_size == ast->getTypeSize(ast->FloatTy)) {
563317027Sdim              llvm::APInt apint(item_bit_size,
564317027Sdim                                DE.GetMaxU64(&offset, item_byte_size));
565317027Sdim              llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy),
566317027Sdim                                    apint);
567317027Sdim              apfloat.toString(sv, format_precision, format_max_padding);
568317027Sdim            } else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) {
569317027Sdim              llvm::APInt apint;
570317027Sdim              if (GetAPInt(DE, &offset, item_byte_size, apint)) {
571317027Sdim                llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy),
572317027Sdim                                      apint);
573317027Sdim                apfloat.toString(sv, format_precision, format_max_padding);
574317027Sdim              }
575317027Sdim            } else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) {
576317027Sdim              const auto &semantics =
577317027Sdim                  ast->getFloatTypeSemantics(ast->LongDoubleTy);
578317027Sdim              const auto byte_size =
579317027Sdim                  (llvm::APFloat::getSizeInBits(semantics) + 7) / 8;
580317027Sdim
581317027Sdim              llvm::APInt apint;
582317027Sdim              if (GetAPInt(DE, &offset, byte_size, apint)) {
583317027Sdim                llvm::APFloat apfloat(semantics, apint);
584317027Sdim                apfloat.toString(sv, format_precision, format_max_padding);
585317027Sdim              }
586317027Sdim            } else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) {
587317027Sdim              llvm::APInt apint(item_bit_size, DE.GetU16(&offset));
588317027Sdim              llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy),
589317027Sdim                                    apint);
590317027Sdim              apfloat.toString(sv, format_precision, format_max_padding);
591317027Sdim            }
592317027Sdim
593317027Sdim            if (!sv.empty()) {
594317027Sdim              s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data());
595317027Sdim              used_apfloat = true;
596317027Sdim            }
597317027Sdim          }
598317027Sdim        }
599317027Sdim      }
600317027Sdim
601317027Sdim      if (!used_apfloat) {
602317027Sdim        std::ostringstream ss;
603317027Sdim        if (item_byte_size == sizeof(float) || item_byte_size == 2) {
604317027Sdim          float f;
605317027Sdim          if (item_byte_size == 2) {
606317027Sdim            uint16_t half = DE.GetU16(&offset);
607317027Sdim            f = half2float(half);
608317027Sdim          } else {
609317027Sdim            f = DE.GetFloat(&offset);
610317027Sdim          }
611317027Sdim          ss.precision(std::numeric_limits<float>::digits10);
612317027Sdim          ss << f;
613317027Sdim        } else if (item_byte_size == sizeof(double)) {
614317027Sdim          ss.precision(std::numeric_limits<double>::digits10);
615317027Sdim          ss << DE.GetDouble(&offset);
616317027Sdim        } else if (item_byte_size == sizeof(long double) ||
617317027Sdim                   item_byte_size == 10) {
618317027Sdim          ss.precision(std::numeric_limits<long double>::digits10);
619317027Sdim          ss << DE.GetLongDouble(&offset);
620317027Sdim        } else {
621317027Sdim          s->Printf("error: unsupported byte size (%" PRIu64
622317027Sdim                    ") for float format",
623317027Sdim                    (uint64_t)item_byte_size);
624317027Sdim          return offset;
625317027Sdim        }
626317027Sdim        ss.flush();
627317027Sdim        s->Printf("%s", ss.str().c_str());
628317027Sdim      }
629317027Sdim    } break;
630317027Sdim
631317027Sdim    case eFormatUnicode16:
632317027Sdim      s->Printf("U+%4.4x", DE.GetU16(&offset));
633317027Sdim      break;
634317027Sdim
635317027Sdim    case eFormatUnicode32:
636317027Sdim      s->Printf("U+0x%8.8x", DE.GetU32(&offset));
637317027Sdim      break;
638317027Sdim
639317027Sdim    case eFormatAddressInfo: {
640317027Sdim      addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size,
641317027Sdim                                         item_bit_offset);
642317027Sdim      s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size),
643317027Sdim                (int)(2 * item_byte_size), addr);
644317027Sdim      if (exe_scope) {
645317027Sdim        TargetSP target_sp(exe_scope->CalculateTarget());
646317027Sdim        lldb_private::Address so_addr;
647317027Sdim        if (target_sp) {
648317027Sdim          if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr,
649317027Sdim                                                                 so_addr)) {
650317027Sdim            s->PutChar(' ');
651317027Sdim            so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription,
652317027Sdim                         Address::DumpStyleModuleWithFileAddress);
653317027Sdim          } else {
654317027Sdim            so_addr.SetOffset(addr);
655317027Sdim            so_addr.Dump(s, exe_scope,
656317027Sdim                         Address::DumpStyleResolvedPointerDescription);
657317027Sdim          }
658317027Sdim        }
659317027Sdim      }
660317027Sdim    } break;
661317027Sdim
662317027Sdim    case eFormatHexFloat:
663317027Sdim      if (sizeof(float) == item_byte_size) {
664317027Sdim        char float_cstr[256];
665317027Sdim        llvm::APFloat ap_float(DE.GetFloat(&offset));
666317027Sdim        ap_float.convertToHexString(float_cstr, 0, false,
667317027Sdim                                    llvm::APFloat::rmNearestTiesToEven);
668317027Sdim        s->Printf("%s", float_cstr);
669317027Sdim        break;
670317027Sdim      } else if (sizeof(double) == item_byte_size) {
671317027Sdim        char float_cstr[256];
672317027Sdim        llvm::APFloat ap_float(DE.GetDouble(&offset));
673317027Sdim        ap_float.convertToHexString(float_cstr, 0, false,
674317027Sdim                                    llvm::APFloat::rmNearestTiesToEven);
675317027Sdim        s->Printf("%s", float_cstr);
676317027Sdim        break;
677317027Sdim      } else {
678317027Sdim        s->Printf("error: unsupported byte size (%" PRIu64
679317027Sdim                  ") for hex float format",
680317027Sdim                  (uint64_t)item_byte_size);
681317027Sdim        return offset;
682317027Sdim      }
683317027Sdim      break;
684317027Sdim
685317027Sdim    // please keep the single-item formats below in sync with
686317027Sdim    // FormatManager::GetSingleItemFormat
687317027Sdim    // if you fail to do so, users will start getting different outputs
688317027Sdim    // depending on internal
689317027Sdim    // implementation details they should not care about ||
690317027Sdim    case eFormatVectorOfChar: //   ||
691317027Sdim      s->PutChar('{');        //   \/
692317027Sdim      offset =
693317027Sdim          DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size,
694317027Sdim                            item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
695317027Sdim      s->PutChar('}');
696317027Sdim      break;
697317027Sdim
698317027Sdim    case eFormatVectorOfSInt8:
699317027Sdim      s->PutChar('{');
700317027Sdim      offset =
701317027Sdim          DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size,
702317027Sdim                            item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
703317027Sdim      s->PutChar('}');
704317027Sdim      break;
705317027Sdim
706317027Sdim    case eFormatVectorOfUInt8:
707317027Sdim      s->PutChar('{');
708317027Sdim      offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size,
709317027Sdim                                 item_byte_size, LLDB_INVALID_ADDRESS, 0, 0);
710317027Sdim      s->PutChar('}');
711317027Sdim      break;
712317027Sdim
713317027Sdim    case eFormatVectorOfSInt16:
714317027Sdim      s->PutChar('{');
715317027Sdim      offset = DumpDataExtractor(
716317027Sdim          DE, s, offset, eFormatDecimal, sizeof(uint16_t),
717317027Sdim          item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t),
718317027Sdim          LLDB_INVALID_ADDRESS, 0, 0);
719317027Sdim      s->PutChar('}');
720317027Sdim      break;
721317027Sdim
722317027Sdim    case eFormatVectorOfUInt16:
723317027Sdim      s->PutChar('{');
724317027Sdim      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t),
725317027Sdim                                 item_byte_size / sizeof(uint16_t),
726317027Sdim                                 item_byte_size / sizeof(uint16_t),
727317027Sdim                                 LLDB_INVALID_ADDRESS, 0, 0);
728317027Sdim      s->PutChar('}');
729317027Sdim      break;
730317027Sdim
731317027Sdim    case eFormatVectorOfSInt32:
732317027Sdim      s->PutChar('{');
733317027Sdim      offset = DumpDataExtractor(
734317027Sdim          DE, s, offset, eFormatDecimal, sizeof(uint32_t),
735317027Sdim          item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t),
736317027Sdim          LLDB_INVALID_ADDRESS, 0, 0);
737317027Sdim      s->PutChar('}');
738317027Sdim      break;
739317027Sdim
740317027Sdim    case eFormatVectorOfUInt32:
741317027Sdim      s->PutChar('{');
742317027Sdim      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t),
743317027Sdim                                 item_byte_size / sizeof(uint32_t),
744317027Sdim                                 item_byte_size / sizeof(uint32_t),
745317027Sdim                                 LLDB_INVALID_ADDRESS, 0, 0);
746317027Sdim      s->PutChar('}');
747317027Sdim      break;
748317027Sdim
749317027Sdim    case eFormatVectorOfSInt64:
750317027Sdim      s->PutChar('{');
751317027Sdim      offset = DumpDataExtractor(
752317027Sdim          DE, s, offset, eFormatDecimal, sizeof(uint64_t),
753317027Sdim          item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t),
754317027Sdim          LLDB_INVALID_ADDRESS, 0, 0);
755317027Sdim      s->PutChar('}');
756317027Sdim      break;
757317027Sdim
758317027Sdim    case eFormatVectorOfUInt64:
759317027Sdim      s->PutChar('{');
760317027Sdim      offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t),
761317027Sdim                                 item_byte_size / sizeof(uint64_t),
762317027Sdim                                 item_byte_size / sizeof(uint64_t),
763317027Sdim                                 LLDB_INVALID_ADDRESS, 0, 0);
764317027Sdim      s->PutChar('}');
765317027Sdim      break;
766317027Sdim
767317027Sdim    case eFormatVectorOfFloat16:
768317027Sdim      s->PutChar('{');
769317027Sdim      offset =
770317027Sdim          DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2,
771317027Sdim                            item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0);
772317027Sdim      s->PutChar('}');
773317027Sdim      break;
774317027Sdim
775317027Sdim    case eFormatVectorOfFloat32:
776317027Sdim      s->PutChar('{');
777317027Sdim      offset =
778317027Sdim          DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4,
779317027Sdim                            item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0);
780317027Sdim      s->PutChar('}');
781317027Sdim      break;
782317027Sdim
783317027Sdim    case eFormatVectorOfFloat64:
784317027Sdim      s->PutChar('{');
785317027Sdim      offset =
786317027Sdim          DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8,
787317027Sdim                            item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0);
788317027Sdim      s->PutChar('}');
789317027Sdim      break;
790317027Sdim
791317027Sdim    case eFormatVectorOfUInt128:
792317027Sdim      s->PutChar('{');
793317027Sdim      offset =
794317027Sdim          DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16,
795317027Sdim                            item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0);
796317027Sdim      s->PutChar('}');
797317027Sdim      break;
798317027Sdim    }
799317027Sdim  }
800317027Sdim
801317027Sdim  if (item_format == eFormatBytesWithASCII && offset > line_start_offset) {
802317027Sdim    s->Printf("%*s", static_cast<int>(
803317027Sdim                         (num_per_line - (offset - line_start_offset)) * 3 + 2),
804317027Sdim              "");
805317027Sdim    DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
806317027Sdim                      offset - line_start_offset, SIZE_MAX,
807317027Sdim                      LLDB_INVALID_ADDRESS, 0, 0);
808317027Sdim  }
809317027Sdim  return offset; // Return the offset at which we ended up
810317027Sdim}
811317027Sdim
812317027Sdimvoid lldb_private::DumpHexBytes(Stream *s, const void *src, size_t src_len,
813317027Sdim                                uint32_t bytes_per_line,
814317027Sdim                                lldb::addr_t base_addr) {
815317027Sdim  DataExtractor data(src, src_len, lldb::eByteOrderLittle, 4);
816317027Sdim  DumpDataExtractor(data, s,
817317027Sdim                    0,                  // Offset into "src"
818317027Sdim                    lldb::eFormatBytes, // Dump as hex bytes
819317027Sdim                    1,              // Size of each item is 1 for single bytes
820317027Sdim                    src_len,        // Number of bytes
821317027Sdim                    bytes_per_line, // Num bytes per line
822317027Sdim                    base_addr,      // Base address
823317027Sdim                    0, 0);          // Bitfield info
824317027Sdim}
825