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