1 | //===-- RegisterValue.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/Utility/RegisterValue.h" |
10 | |
11 | #include "lldb/Utility/DataExtractor.h" |
12 | #include "lldb/Utility/Scalar.h" |
13 | #include "lldb/Utility/Status.h" |
14 | #include "lldb/Utility/Stream.h" |
15 | #include "lldb/Utility/StreamString.h" |
16 | #include "lldb/lldb-defines.h" |
17 | #include "lldb/lldb-private-types.h" |
18 | |
19 | #include "llvm/ADT/ArrayRef.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | |
22 | #include <cstdint> |
23 | #include <string> |
24 | #include <tuple> |
25 | #include <vector> |
26 | |
27 | #include <cassert> |
28 | #include <cinttypes> |
29 | #include <cstdio> |
30 | |
31 | using namespace lldb; |
32 | using namespace lldb_private; |
33 | |
34 | bool RegisterValue::(DataExtractor &data) const { |
35 | return data.SetData(bytes: GetBytes(), length: GetByteSize(), byte_order: GetByteOrder()) > 0; |
36 | } |
37 | |
38 | uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo ®_info, void *dst, |
39 | uint32_t dst_len, |
40 | lldb::ByteOrder dst_byte_order, |
41 | Status &error) const { |
42 | // ReadRegister should have already been called on this object prior to |
43 | // calling this. |
44 | if (GetType() == eTypeInvalid) { |
45 | // No value has been read into this object... |
46 | error.SetErrorStringWithFormat( |
47 | "invalid register value type for register %s" , reg_info.name); |
48 | return 0; |
49 | } |
50 | |
51 | const uint32_t src_len = reg_info.byte_size; |
52 | |
53 | // Extract the register data into a data extractor |
54 | DataExtractor reg_data; |
55 | if (!GetData(data&: reg_data)) { |
56 | error.SetErrorString("invalid register value to copy into" ); |
57 | return 0; |
58 | } |
59 | |
60 | // Prepare a memory buffer that contains some or all of the register value |
61 | const uint32_t bytes_copied = |
62 | reg_data.CopyByteOrderedData(src_offset: 0, // src offset |
63 | src_len, // src length |
64 | dst, // dst buffer |
65 | dst_len, // dst length |
66 | dst_byte_order); // dst byte order |
67 | if (bytes_copied == 0) |
68 | error.SetErrorStringWithFormat( |
69 | "failed to copy data for register write of %s" , reg_info.name); |
70 | |
71 | return bytes_copied; |
72 | } |
73 | |
74 | uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo ®_info, |
75 | const void *src, uint32_t src_len, |
76 | lldb::ByteOrder src_byte_order, |
77 | Status &error) { |
78 | // Moving from addr into a register |
79 | // |
80 | // Case 1: src_len == dst_len |
81 | // |
82 | // |AABBCCDD| Address contents |
83 | // |AABBCCDD| Register contents |
84 | // |
85 | // Case 2: src_len > dst_len |
86 | // |
87 | // Status! (The register should always be big enough to hold the data) |
88 | // |
89 | // Case 3: src_len < dst_len |
90 | // |
91 | // |AABB| Address contents |
92 | // |AABB0000| Register contents [on little-endian hardware] |
93 | // |0000AABB| Register contents [on big-endian hardware] |
94 | const uint32_t dst_len = reg_info.byte_size; |
95 | |
96 | if (src_len > dst_len) { |
97 | error.SetErrorStringWithFormat( |
98 | "%u bytes is too big to store in register %s (%u bytes)" , src_len, |
99 | reg_info.name, dst_len); |
100 | return 0; |
101 | } |
102 | |
103 | // Use a data extractor to correctly copy and pad the bytes read into the |
104 | // register value |
105 | DataExtractor src_data(src, src_len, src_byte_order, 4); |
106 | |
107 | error = SetValueFromData(reg_info, data&: src_data, offset: 0, partial_data_ok: true); |
108 | if (error.Fail()) |
109 | return 0; |
110 | |
111 | // If SetValueFromData succeeded, we must have copied all of src_len |
112 | return src_len; |
113 | } |
114 | |
115 | bool RegisterValue::GetScalarValue(Scalar &scalar) const { |
116 | switch (m_type) { |
117 | case eTypeInvalid: |
118 | break; |
119 | case eTypeBytes: { |
120 | DataExtractor data(buffer.bytes.data(), buffer.bytes.size(), |
121 | buffer.byte_order, 1); |
122 | if (scalar.SetValueFromData(data, encoding: lldb::eEncodingUint, byte_size: buffer.bytes.size()) |
123 | .Success()) |
124 | return true; |
125 | } break; |
126 | case eTypeUInt8: |
127 | case eTypeUInt16: |
128 | case eTypeUInt32: |
129 | case eTypeUInt64: |
130 | case eTypeUInt128: |
131 | case eTypeFloat: |
132 | case eTypeDouble: |
133 | case eTypeLongDouble: |
134 | scalar = m_scalar; |
135 | return true; |
136 | } |
137 | return false; |
138 | } |
139 | |
140 | void RegisterValue::Clear() { m_type = eTypeInvalid; } |
141 | |
142 | RegisterValue::Type RegisterValue::SetType(const RegisterInfo ®_info) { |
143 | // To change the type, we simply copy the data in again, using the new format |
144 | RegisterValue copy; |
145 | DataExtractor copy_data; |
146 | if (copy.CopyValue(rhs: *this) && copy.GetData(data&: copy_data)) { |
147 | Status error = SetValueFromData(reg_info, data&: copy_data, offset: 0, partial_data_ok: true); |
148 | assert(error.Success() && "Expected SetValueFromData to succeed." ); |
149 | UNUSED_IF_ASSERT_DISABLED(error); |
150 | } |
151 | |
152 | return m_type; |
153 | } |
154 | |
155 | Status RegisterValue::(const RegisterInfo ®_info, |
156 | DataExtractor &src, |
157 | lldb::offset_t src_offset, |
158 | bool partial_data_ok) { |
159 | Status error; |
160 | |
161 | if (src.GetByteSize() == 0) { |
162 | error.SetErrorString("empty data." ); |
163 | return error; |
164 | } |
165 | |
166 | if (reg_info.byte_size == 0) { |
167 | error.SetErrorString("invalid register info." ); |
168 | return error; |
169 | } |
170 | |
171 | uint32_t src_len = src.GetByteSize() - src_offset; |
172 | |
173 | if (!partial_data_ok && (src_len < reg_info.byte_size)) { |
174 | error.SetErrorString("not enough data." ); |
175 | return error; |
176 | } |
177 | |
178 | // Cap the data length if there is more than enough bytes for this register |
179 | // value |
180 | if (src_len > reg_info.byte_size) |
181 | src_len = reg_info.byte_size; |
182 | |
183 | type128 int128; |
184 | |
185 | m_type = eTypeInvalid; |
186 | switch (reg_info.encoding) { |
187 | case eEncodingInvalid: |
188 | break; |
189 | case eEncodingUint: |
190 | case eEncodingSint: |
191 | if (reg_info.byte_size == 1) |
192 | SetUInt8(src.GetMaxU32(offset_ptr: &src_offset, byte_size: src_len)); |
193 | else if (reg_info.byte_size <= 2) |
194 | SetUInt16(src.GetMaxU32(offset_ptr: &src_offset, byte_size: src_len)); |
195 | else if (reg_info.byte_size <= 4) |
196 | SetUInt32(uint: src.GetMaxU32(offset_ptr: &src_offset, byte_size: src_len)); |
197 | else if (reg_info.byte_size <= 8) |
198 | SetUInt64(uint: src.GetMaxU64(offset_ptr: &src_offset, byte_size: src_len)); |
199 | else if (reg_info.byte_size <= 16) { |
200 | uint64_t data1 = src.GetU64(offset_ptr: &src_offset); |
201 | uint64_t data2 = src.GetU64(offset_ptr: &src_offset); |
202 | if (src.GetByteSize() == eByteOrderBig) { |
203 | int128.x[0] = data1; |
204 | int128.x[1] = data2; |
205 | } else { |
206 | int128.x[0] = data2; |
207 | int128.x[1] = data1; |
208 | } |
209 | SetUInt128(llvm::APInt(128, 2, int128.x)); |
210 | } |
211 | break; |
212 | case eEncodingIEEE754: |
213 | if (reg_info.byte_size == sizeof(float)) |
214 | SetFloat(src.GetFloat(offset_ptr: &src_offset)); |
215 | else if (reg_info.byte_size == sizeof(double)) |
216 | SetDouble(src.GetDouble(offset_ptr: &src_offset)); |
217 | else if (reg_info.byte_size == sizeof(long double)) |
218 | SetLongDouble(src.GetLongDouble(offset_ptr: &src_offset)); |
219 | break; |
220 | case eEncodingVector: { |
221 | m_type = eTypeBytes; |
222 | assert(reg_info.byte_size <= kMaxRegisterByteSize); |
223 | buffer.bytes.resize(N: reg_info.byte_size); |
224 | buffer.byte_order = src.GetByteOrder(); |
225 | if (src.CopyByteOrderedData( |
226 | src_offset, // offset within "src" to start extracting data |
227 | src_len, // src length |
228 | dst: buffer.bytes.data(), // dst buffer |
229 | dst_len: buffer.bytes.size(), // dst length |
230 | dst_byte_order: buffer.byte_order) == 0) // dst byte order |
231 | { |
232 | error.SetErrorStringWithFormat( |
233 | "failed to copy data for register write of %s" , reg_info.name); |
234 | return error; |
235 | } |
236 | } |
237 | } |
238 | |
239 | if (m_type == eTypeInvalid) |
240 | error.SetErrorStringWithFormat( |
241 | "invalid register value type for register %s" , reg_info.name); |
242 | return error; |
243 | } |
244 | |
245 | // Helper function for RegisterValue::SetValueFromString() |
246 | static bool ParseVectorEncoding(const RegisterInfo *reg_info, |
247 | llvm::StringRef vector_str, |
248 | const uint32_t byte_size, |
249 | RegisterValue *reg_value) { |
250 | // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a |
251 | // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". |
252 | vector_str = vector_str.trim(); |
253 | vector_str.consume_front(Prefix: "{" ); |
254 | vector_str.consume_back(Suffix: "}" ); |
255 | vector_str = vector_str.trim(); |
256 | |
257 | char Sep = ' '; |
258 | |
259 | // The first split should give us: |
260 | // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f |
261 | // 0x2a 0x3e'). |
262 | llvm::StringRef car; |
263 | llvm::StringRef cdr = vector_str; |
264 | std::tie(args&: car, args&: cdr) = vector_str.split(Separator: Sep); |
265 | std::vector<uint8_t> bytes; |
266 | unsigned byte = 0; |
267 | |
268 | // Using radix auto-sensing by passing 0 as the radix. Keep on processing the |
269 | // vector elements as long as the parsing succeeds and the vector size is < |
270 | // byte_size. |
271 | while (!car.getAsInteger(Radix: 0, Result&: byte) && bytes.size() < byte_size) { |
272 | bytes.push_back(x: byte); |
273 | std::tie(args&: car, args&: cdr) = cdr.split(Separator: Sep); |
274 | } |
275 | |
276 | // Check for vector of exact byte_size elements. |
277 | if (bytes.size() != byte_size) |
278 | return false; |
279 | |
280 | reg_value->SetBytes(bytes: &(bytes.front()), length: byte_size, byte_order: eByteOrderLittle); |
281 | return true; |
282 | } |
283 | |
284 | static bool UInt64ValueIsValidForByteSize(uint64_t uval64, |
285 | size_t total_byte_size) { |
286 | if (total_byte_size > 8) |
287 | return false; |
288 | |
289 | if (total_byte_size == 8) |
290 | return true; |
291 | |
292 | const uint64_t max = |
293 | (static_cast<uint64_t>(1) << static_cast<uint64_t>(total_byte_size * 8)) - |
294 | 1; |
295 | return uval64 <= max; |
296 | } |
297 | |
298 | static bool SInt64ValueIsValidForByteSize(int64_t sval64, |
299 | size_t total_byte_size) { |
300 | if (total_byte_size > 8) |
301 | return false; |
302 | |
303 | if (total_byte_size == 8) |
304 | return true; |
305 | |
306 | const int64_t max = (static_cast<int64_t>(1) |
307 | << static_cast<uint64_t>(total_byte_size * 8 - 1)) - |
308 | 1; |
309 | const int64_t min = ~(max); |
310 | return min <= sval64 && sval64 <= max; |
311 | } |
312 | |
313 | Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info, |
314 | llvm::StringRef value_str) { |
315 | Status error; |
316 | if (reg_info == nullptr) { |
317 | error.SetErrorString("Invalid register info argument." ); |
318 | return error; |
319 | } |
320 | |
321 | m_type = eTypeInvalid; |
322 | if (value_str.empty()) { |
323 | error.SetErrorString("Invalid c-string value string." ); |
324 | return error; |
325 | } |
326 | const uint32_t byte_size = reg_info->byte_size; |
327 | |
328 | uint64_t uval64; |
329 | int64_t ival64; |
330 | float flt_val; |
331 | double dbl_val; |
332 | long double ldbl_val; |
333 | switch (reg_info->encoding) { |
334 | case eEncodingInvalid: |
335 | error.SetErrorString("Invalid encoding." ); |
336 | break; |
337 | |
338 | case eEncodingUint: |
339 | if (byte_size > sizeof(uint64_t)) { |
340 | error.SetErrorStringWithFormat( |
341 | "unsupported unsigned integer byte size: %u" , byte_size); |
342 | break; |
343 | } |
344 | if (value_str.getAsInteger(Radix: 0, Result&: uval64)) { |
345 | error.SetErrorStringWithFormatv( |
346 | format: "'{0}' is not a valid unsigned integer string value" , args&: value_str); |
347 | break; |
348 | } |
349 | |
350 | if (!UInt64ValueIsValidForByteSize(uval64, total_byte_size: byte_size)) { |
351 | error.SetErrorStringWithFormat( |
352 | "value 0x%" PRIx64 |
353 | " is too large to fit in a %u byte unsigned integer value" , |
354 | uval64, byte_size); |
355 | break; |
356 | } |
357 | |
358 | if (!SetUInt(uint: uval64, byte_size: reg_info->byte_size)) { |
359 | error.SetErrorStringWithFormat( |
360 | "unsupported unsigned integer byte size: %u" , byte_size); |
361 | break; |
362 | } |
363 | break; |
364 | |
365 | case eEncodingSint: |
366 | if (byte_size > sizeof(long long)) { |
367 | error.SetErrorStringWithFormat("unsupported signed integer byte size: %u" , |
368 | byte_size); |
369 | break; |
370 | } |
371 | |
372 | if (value_str.getAsInteger(Radix: 0, Result&: ival64)) { |
373 | error.SetErrorStringWithFormatv( |
374 | format: "'{0}' is not a valid signed integer string value" , args&: value_str); |
375 | break; |
376 | } |
377 | |
378 | if (!SInt64ValueIsValidForByteSize(sval64: ival64, total_byte_size: byte_size)) { |
379 | error.SetErrorStringWithFormat( |
380 | "value 0x%" PRIx64 |
381 | " is too large to fit in a %u byte signed integer value" , |
382 | ival64, byte_size); |
383 | break; |
384 | } |
385 | |
386 | if (!SetUInt(uint: ival64, byte_size: reg_info->byte_size)) { |
387 | error.SetErrorStringWithFormat("unsupported signed integer byte size: %u" , |
388 | byte_size); |
389 | break; |
390 | } |
391 | break; |
392 | |
393 | case eEncodingIEEE754: { |
394 | std::string value_string = std::string(value_str); |
395 | if (byte_size == sizeof(float)) { |
396 | if (::sscanf(s: value_string.c_str(), format: "%f" , &flt_val) != 1) { |
397 | error.SetErrorStringWithFormat("'%s' is not a valid float string value" , |
398 | value_string.c_str()); |
399 | break; |
400 | } |
401 | m_scalar = flt_val; |
402 | m_type = eTypeFloat; |
403 | } else if (byte_size == sizeof(double)) { |
404 | if (::sscanf(s: value_string.c_str(), format: "%lf" , &dbl_val) != 1) { |
405 | error.SetErrorStringWithFormat("'%s' is not a valid float string value" , |
406 | value_string.c_str()); |
407 | break; |
408 | } |
409 | m_scalar = dbl_val; |
410 | m_type = eTypeDouble; |
411 | } else if (byte_size == sizeof(long double)) { |
412 | if (::sscanf(s: value_string.c_str(), format: "%Lf" , &ldbl_val) != 1) { |
413 | error.SetErrorStringWithFormat("'%s' is not a valid float string value" , |
414 | value_string.c_str()); |
415 | break; |
416 | } |
417 | m_scalar = ldbl_val; |
418 | m_type = eTypeLongDouble; |
419 | } else { |
420 | error.SetErrorStringWithFormat("unsupported float byte size: %u" , |
421 | byte_size); |
422 | return error; |
423 | } |
424 | break; |
425 | } |
426 | case eEncodingVector: |
427 | if (!ParseVectorEncoding(reg_info, vector_str: value_str, byte_size, reg_value: this)) |
428 | error.SetErrorString("unrecognized vector encoding string value." ); |
429 | break; |
430 | } |
431 | |
432 | return error; |
433 | } |
434 | |
435 | bool RegisterValue::SignExtend(uint32_t sign_bitpos) { |
436 | switch (m_type) { |
437 | case eTypeInvalid: |
438 | break; |
439 | |
440 | case eTypeUInt8: |
441 | case eTypeUInt16: |
442 | case eTypeUInt32: |
443 | case eTypeUInt64: |
444 | case eTypeUInt128: |
445 | return m_scalar.SignExtend(bit_pos: sign_bitpos); |
446 | case eTypeFloat: |
447 | case eTypeDouble: |
448 | case eTypeLongDouble: |
449 | case eTypeBytes: |
450 | break; |
451 | } |
452 | return false; |
453 | } |
454 | |
455 | bool RegisterValue::CopyValue(const RegisterValue &rhs) { |
456 | if (this == &rhs) |
457 | return rhs.m_type != eTypeInvalid; |
458 | |
459 | m_type = rhs.m_type; |
460 | switch (m_type) { |
461 | case eTypeInvalid: |
462 | return false; |
463 | case eTypeUInt8: |
464 | case eTypeUInt16: |
465 | case eTypeUInt32: |
466 | case eTypeUInt64: |
467 | case eTypeUInt128: |
468 | case eTypeFloat: |
469 | case eTypeDouble: |
470 | case eTypeLongDouble: |
471 | m_scalar = rhs.m_scalar; |
472 | break; |
473 | case eTypeBytes: |
474 | buffer.bytes = rhs.buffer.bytes; |
475 | buffer.byte_order = rhs.buffer.byte_order; |
476 | break; |
477 | } |
478 | return true; |
479 | } |
480 | |
481 | uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, |
482 | bool *success_ptr) const { |
483 | if (success_ptr) |
484 | *success_ptr = true; |
485 | |
486 | switch (m_type) { |
487 | default: |
488 | break; |
489 | case eTypeUInt8: |
490 | case eTypeUInt16: |
491 | return m_scalar.UShort(fail_value); |
492 | case eTypeBytes: { |
493 | switch (buffer.bytes.size()) { |
494 | default: |
495 | break; |
496 | case 1: |
497 | case 2: |
498 | return *reinterpret_cast<const uint16_t *>(buffer.bytes.data()); |
499 | } |
500 | } break; |
501 | } |
502 | if (success_ptr) |
503 | *success_ptr = false; |
504 | return fail_value; |
505 | } |
506 | |
507 | uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, |
508 | bool *success_ptr) const { |
509 | if (success_ptr) |
510 | *success_ptr = true; |
511 | switch (m_type) { |
512 | default: |
513 | break; |
514 | case eTypeUInt8: |
515 | case eTypeUInt16: |
516 | case eTypeUInt32: |
517 | case eTypeFloat: |
518 | case eTypeDouble: |
519 | case eTypeLongDouble: |
520 | return m_scalar.UInt(fail_value); |
521 | case eTypeBytes: { |
522 | switch (buffer.bytes.size()) { |
523 | default: |
524 | break; |
525 | case 1: |
526 | case 2: |
527 | case 4: |
528 | return *reinterpret_cast<const uint32_t *>(buffer.bytes.data()); |
529 | } |
530 | } break; |
531 | } |
532 | if (success_ptr) |
533 | *success_ptr = false; |
534 | return fail_value; |
535 | } |
536 | |
537 | uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, |
538 | bool *success_ptr) const { |
539 | if (success_ptr) |
540 | *success_ptr = true; |
541 | switch (m_type) { |
542 | default: |
543 | break; |
544 | case eTypeUInt8: |
545 | case eTypeUInt16: |
546 | case eTypeUInt32: |
547 | case eTypeUInt64: |
548 | case eTypeFloat: |
549 | case eTypeDouble: |
550 | case eTypeLongDouble: |
551 | return m_scalar.ULongLong(fail_value); |
552 | case eTypeBytes: { |
553 | switch (buffer.bytes.size()) { |
554 | default: |
555 | break; |
556 | case 1: |
557 | return *(const uint8_t *)buffer.bytes.data(); |
558 | case 2: |
559 | return *reinterpret_cast<const uint16_t *>(buffer.bytes.data()); |
560 | case 4: |
561 | return *reinterpret_cast<const uint32_t *>(buffer.bytes.data()); |
562 | case 8: |
563 | return *reinterpret_cast<const uint64_t *>(buffer.bytes.data()); |
564 | } |
565 | } break; |
566 | } |
567 | if (success_ptr) |
568 | *success_ptr = false; |
569 | return fail_value; |
570 | } |
571 | |
572 | llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, |
573 | bool *success_ptr) const { |
574 | if (success_ptr) |
575 | *success_ptr = true; |
576 | switch (m_type) { |
577 | default: |
578 | break; |
579 | case eTypeUInt8: |
580 | case eTypeUInt16: |
581 | case eTypeUInt32: |
582 | case eTypeUInt64: |
583 | case eTypeUInt128: |
584 | case eTypeFloat: |
585 | case eTypeDouble: |
586 | case eTypeLongDouble: |
587 | return m_scalar.UInt128(fail_value); |
588 | case eTypeBytes: { |
589 | switch (buffer.bytes.size()) { |
590 | default: |
591 | break; |
592 | case 1: |
593 | case 2: |
594 | case 4: |
595 | case 8: |
596 | case 16: |
597 | return llvm::APInt( |
598 | BITWIDTH_INT128, NUM_OF_WORDS_INT128, |
599 | (reinterpret_cast<const type128 *>(buffer.bytes.data()))->x); |
600 | } |
601 | } break; |
602 | } |
603 | if (success_ptr) |
604 | *success_ptr = false; |
605 | return fail_value; |
606 | } |
607 | |
608 | float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { |
609 | if (success_ptr) |
610 | *success_ptr = true; |
611 | switch (m_type) { |
612 | default: |
613 | break; |
614 | case eTypeUInt32: |
615 | case eTypeUInt64: |
616 | case eTypeUInt128: |
617 | case eTypeFloat: |
618 | case eTypeDouble: |
619 | case eTypeLongDouble: |
620 | return m_scalar.Float(fail_value); |
621 | } |
622 | if (success_ptr) |
623 | *success_ptr = false; |
624 | return fail_value; |
625 | } |
626 | |
627 | double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { |
628 | if (success_ptr) |
629 | *success_ptr = true; |
630 | switch (m_type) { |
631 | default: |
632 | break; |
633 | |
634 | case eTypeUInt32: |
635 | case eTypeUInt64: |
636 | case eTypeUInt128: |
637 | case eTypeFloat: |
638 | case eTypeDouble: |
639 | case eTypeLongDouble: |
640 | return m_scalar.Double(fail_value); |
641 | } |
642 | if (success_ptr) |
643 | *success_ptr = false; |
644 | return fail_value; |
645 | } |
646 | |
647 | long double RegisterValue::GetAsLongDouble(long double fail_value, |
648 | bool *success_ptr) const { |
649 | if (success_ptr) |
650 | *success_ptr = true; |
651 | switch (m_type) { |
652 | default: |
653 | break; |
654 | |
655 | case eTypeUInt32: |
656 | case eTypeUInt64: |
657 | case eTypeUInt128: |
658 | case eTypeFloat: |
659 | case eTypeDouble: |
660 | case eTypeLongDouble: |
661 | return m_scalar.LongDouble(); |
662 | } |
663 | if (success_ptr) |
664 | *success_ptr = false; |
665 | return fail_value; |
666 | } |
667 | |
668 | const void *RegisterValue::GetBytes() const { |
669 | switch (m_type) { |
670 | case eTypeInvalid: |
671 | break; |
672 | case eTypeUInt8: |
673 | case eTypeUInt16: |
674 | case eTypeUInt32: |
675 | case eTypeUInt64: |
676 | case eTypeUInt128: |
677 | case eTypeFloat: |
678 | case eTypeDouble: |
679 | case eTypeLongDouble: |
680 | m_scalar.GetBytes(storage: buffer.bytes); |
681 | return buffer.bytes.data(); |
682 | case eTypeBytes: |
683 | return buffer.bytes.data(); |
684 | } |
685 | return nullptr; |
686 | } |
687 | |
688 | uint32_t RegisterValue::GetByteSize() const { |
689 | switch (m_type) { |
690 | case eTypeInvalid: |
691 | break; |
692 | case eTypeUInt8: |
693 | return 1; |
694 | case eTypeUInt16: |
695 | return 2; |
696 | case eTypeUInt32: |
697 | case eTypeUInt64: |
698 | case eTypeUInt128: |
699 | case eTypeFloat: |
700 | case eTypeDouble: |
701 | case eTypeLongDouble: |
702 | return m_scalar.GetByteSize(); |
703 | case eTypeBytes: |
704 | return buffer.bytes.size(); |
705 | } |
706 | return 0; |
707 | } |
708 | |
709 | bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { |
710 | if (byte_size == 0) { |
711 | SetUInt64(uint); |
712 | } else if (byte_size == 1) { |
713 | SetUInt8(uint); |
714 | } else if (byte_size <= 2) { |
715 | SetUInt16(uint); |
716 | } else if (byte_size <= 4) { |
717 | SetUInt32(uint); |
718 | } else if (byte_size <= 8) { |
719 | SetUInt64(uint); |
720 | } else if (byte_size <= 16) { |
721 | SetUInt128(llvm::APInt(128, uint)); |
722 | } else |
723 | return false; |
724 | return true; |
725 | } |
726 | |
727 | void RegisterValue::SetBytes(const void *bytes, size_t length, |
728 | lldb::ByteOrder byte_order) { |
729 | if (bytes && length > 0) { |
730 | m_type = eTypeBytes; |
731 | buffer.bytes.resize(N: length); |
732 | memcpy(dest: buffer.bytes.data(), src: bytes, n: length); |
733 | buffer.byte_order = byte_order; |
734 | } else { |
735 | m_type = eTypeInvalid; |
736 | buffer.bytes.resize(N: 0); |
737 | } |
738 | } |
739 | |
740 | bool RegisterValue::operator==(const RegisterValue &rhs) const { |
741 | if (m_type == rhs.m_type) { |
742 | switch (m_type) { |
743 | case eTypeInvalid: |
744 | return true; |
745 | case eTypeUInt8: |
746 | case eTypeUInt16: |
747 | case eTypeUInt32: |
748 | case eTypeUInt64: |
749 | case eTypeUInt128: |
750 | case eTypeFloat: |
751 | case eTypeDouble: |
752 | case eTypeLongDouble: |
753 | return m_scalar == rhs.m_scalar; |
754 | case eTypeBytes: |
755 | return buffer.bytes == rhs.buffer.bytes; |
756 | } |
757 | } |
758 | return false; |
759 | } |
760 | |
761 | bool RegisterValue::operator!=(const RegisterValue &rhs) const { |
762 | return !(*this == rhs); |
763 | } |
764 | |
765 | bool RegisterValue::ClearBit(uint32_t bit) { |
766 | switch (m_type) { |
767 | case eTypeInvalid: |
768 | break; |
769 | |
770 | case eTypeUInt8: |
771 | case eTypeUInt16: |
772 | case eTypeUInt32: |
773 | case eTypeUInt64: |
774 | case eTypeUInt128: |
775 | if (bit < (GetByteSize() * 8)) { |
776 | return m_scalar.ClearBit(bit); |
777 | } |
778 | break; |
779 | |
780 | case eTypeFloat: |
781 | case eTypeDouble: |
782 | case eTypeLongDouble: |
783 | break; |
784 | |
785 | case eTypeBytes: |
786 | if (buffer.byte_order == eByteOrderBig || |
787 | buffer.byte_order == eByteOrderLittle) { |
788 | uint32_t byte_idx; |
789 | if (buffer.byte_order == eByteOrderBig) |
790 | byte_idx = buffer.bytes.size() - (bit / 8) - 1; |
791 | else |
792 | byte_idx = bit / 8; |
793 | |
794 | const uint32_t byte_bit = bit % 8; |
795 | if (byte_idx < buffer.bytes.size()) { |
796 | buffer.bytes[byte_idx] &= ~(1u << byte_bit); |
797 | return true; |
798 | } |
799 | } |
800 | break; |
801 | } |
802 | return false; |
803 | } |
804 | |
805 | bool RegisterValue::SetBit(uint32_t bit) { |
806 | switch (m_type) { |
807 | case eTypeInvalid: |
808 | break; |
809 | |
810 | case eTypeUInt8: |
811 | case eTypeUInt16: |
812 | case eTypeUInt32: |
813 | case eTypeUInt64: |
814 | case eTypeUInt128: |
815 | if (bit < (GetByteSize() * 8)) { |
816 | return m_scalar.SetBit(bit); |
817 | } |
818 | break; |
819 | |
820 | case eTypeFloat: |
821 | case eTypeDouble: |
822 | case eTypeLongDouble: |
823 | break; |
824 | |
825 | case eTypeBytes: |
826 | if (buffer.byte_order == eByteOrderBig || |
827 | buffer.byte_order == eByteOrderLittle) { |
828 | uint32_t byte_idx; |
829 | if (buffer.byte_order == eByteOrderBig) |
830 | byte_idx = buffer.bytes.size() - (bit / 8) - 1; |
831 | else |
832 | byte_idx = bit / 8; |
833 | |
834 | const uint32_t byte_bit = bit % 8; |
835 | if (byte_idx < buffer.bytes.size()) { |
836 | buffer.bytes[byte_idx] |= (1u << byte_bit); |
837 | return true; |
838 | } |
839 | } |
840 | break; |
841 | } |
842 | return false; |
843 | } |
844 | |