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