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