Coverage Report

Created: 2023-09-30 09:22

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