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