Value.cpp revision 360784
1//===-- Value.cpp -----------------------------------------------*- C++ -*-===// 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/Value.h" 10 11#include "lldb/Core/Address.h" 12#include "lldb/Core/Module.h" 13#include "lldb/Symbol/CompilerType.h" 14#include "lldb/Symbol/ObjectFile.h" 15#include "lldb/Symbol/SymbolContext.h" 16#include "lldb/Symbol/Type.h" 17#include "lldb/Symbol/Variable.h" 18#include "lldb/Target/ExecutionContext.h" 19#include "lldb/Target/Process.h" 20#include "lldb/Target/SectionLoadList.h" 21#include "lldb/Target/Target.h" 22#include "lldb/Utility/ConstString.h" 23#include "lldb/Utility/DataBufferHeap.h" 24#include "lldb/Utility/DataExtractor.h" 25#include "lldb/Utility/Endian.h" 26#include "lldb/Utility/FileSpec.h" 27#include "lldb/Utility/State.h" 28#include "lldb/Utility/Stream.h" 29#include "lldb/lldb-defines.h" 30#include "lldb/lldb-forward.h" 31#include "lldb/lldb-types.h" 32 33#include <memory> 34#include <string> 35 36#include <inttypes.h> 37 38using namespace lldb; 39using namespace lldb_private; 40 41Value::Value() 42 : m_value(), m_vector(), m_compiler_type(), m_context(nullptr), 43 m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), 44 m_data_buffer() {} 45 46Value::Value(const Scalar &scalar) 47 : m_value(scalar), m_vector(), m_compiler_type(), m_context(nullptr), 48 m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), 49 m_data_buffer() {} 50 51Value::Value(const void *bytes, int len) 52 : m_value(), m_vector(), m_compiler_type(), m_context(nullptr), 53 m_value_type(eValueTypeHostAddress), m_context_type(eContextTypeInvalid), 54 m_data_buffer() { 55 SetBytes(bytes, len); 56} 57 58Value::Value(const Value &v) 59 : m_value(v.m_value), m_vector(v.m_vector), 60 m_compiler_type(v.m_compiler_type), m_context(v.m_context), 61 m_value_type(v.m_value_type), m_context_type(v.m_context_type), 62 m_data_buffer() { 63 const uintptr_t rhs_value = 64 (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS); 65 if ((rhs_value != 0) && 66 (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) { 67 m_data_buffer.CopyData(v.m_data_buffer.GetBytes(), 68 v.m_data_buffer.GetByteSize()); 69 70 m_value = (uintptr_t)m_data_buffer.GetBytes(); 71 } 72} 73 74Value &Value::operator=(const Value &rhs) { 75 if (this != &rhs) { 76 m_value = rhs.m_value; 77 m_vector = rhs.m_vector; 78 m_compiler_type = rhs.m_compiler_type; 79 m_context = rhs.m_context; 80 m_value_type = rhs.m_value_type; 81 m_context_type = rhs.m_context_type; 82 const uintptr_t rhs_value = 83 (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS); 84 if ((rhs_value != 0) && 85 (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) { 86 m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(), 87 rhs.m_data_buffer.GetByteSize()); 88 89 m_value = (uintptr_t)m_data_buffer.GetBytes(); 90 } 91 } 92 return *this; 93} 94 95void Value::SetBytes(const void *bytes, int len) { 96 m_value_type = eValueTypeHostAddress; 97 m_data_buffer.CopyData(bytes, len); 98 m_value = (uintptr_t)m_data_buffer.GetBytes(); 99} 100 101void Value::AppendBytes(const void *bytes, int len) { 102 m_value_type = eValueTypeHostAddress; 103 m_data_buffer.AppendData(bytes, len); 104 m_value = (uintptr_t)m_data_buffer.GetBytes(); 105} 106 107void Value::Dump(Stream *strm) { 108 m_value.GetValue(strm, true); 109 strm->Printf(", value_type = %s, context = %p, context_type = %s", 110 Value::GetValueTypeAsCString(m_value_type), m_context, 111 Value::GetContextTypeAsCString(m_context_type)); 112} 113 114Value::ValueType Value::GetValueType() const { return m_value_type; } 115 116AddressType Value::GetValueAddressType() const { 117 switch (m_value_type) { 118 default: 119 case eValueTypeScalar: 120 break; 121 case eValueTypeLoadAddress: 122 return eAddressTypeLoad; 123 case eValueTypeFileAddress: 124 return eAddressTypeFile; 125 case eValueTypeHostAddress: 126 return eAddressTypeHost; 127 } 128 return eAddressTypeInvalid; 129} 130 131RegisterInfo *Value::GetRegisterInfo() const { 132 if (m_context_type == eContextTypeRegisterInfo) 133 return static_cast<RegisterInfo *>(m_context); 134 return nullptr; 135} 136 137Type *Value::GetType() { 138 if (m_context_type == eContextTypeLLDBType) 139 return static_cast<Type *>(m_context); 140 return nullptr; 141} 142 143size_t Value::AppendDataToHostBuffer(const Value &rhs) { 144 if (this == &rhs) 145 return 0; 146 147 size_t curr_size = m_data_buffer.GetByteSize(); 148 Status error; 149 switch (rhs.GetValueType()) { 150 case eValueTypeScalar: { 151 const size_t scalar_size = rhs.m_value.GetByteSize(); 152 if (scalar_size > 0) { 153 const size_t new_size = curr_size + scalar_size; 154 if (ResizeData(new_size) == new_size) { 155 rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size, 156 scalar_size, endian::InlHostByteOrder(), 157 error); 158 return scalar_size; 159 } 160 } 161 } break; 162 case eValueTypeVector: { 163 const size_t vector_size = rhs.m_vector.length; 164 if (vector_size > 0) { 165 const size_t new_size = curr_size + vector_size; 166 if (ResizeData(new_size) == new_size) { 167 ::memcpy(m_data_buffer.GetBytes() + curr_size, rhs.m_vector.bytes, 168 vector_size); 169 return vector_size; 170 } 171 } 172 } break; 173 case eValueTypeFileAddress: 174 case eValueTypeLoadAddress: 175 case eValueTypeHostAddress: { 176 const uint8_t *src = rhs.GetBuffer().GetBytes(); 177 const size_t src_len = rhs.GetBuffer().GetByteSize(); 178 if (src && src_len > 0) { 179 const size_t new_size = curr_size + src_len; 180 if (ResizeData(new_size) == new_size) { 181 ::memcpy(m_data_buffer.GetBytes() + curr_size, src, src_len); 182 return src_len; 183 } 184 } 185 } break; 186 } 187 return 0; 188} 189 190size_t Value::ResizeData(size_t len) { 191 m_value_type = eValueTypeHostAddress; 192 m_data_buffer.SetByteSize(len); 193 m_value = (uintptr_t)m_data_buffer.GetBytes(); 194 return m_data_buffer.GetByteSize(); 195} 196 197bool Value::ValueOf(ExecutionContext *exe_ctx) { 198 switch (m_context_type) { 199 case eContextTypeInvalid: 200 case eContextTypeRegisterInfo: // RegisterInfo * 201 case eContextTypeLLDBType: // Type * 202 break; 203 204 case eContextTypeVariable: // Variable * 205 ResolveValue(exe_ctx); 206 return true; 207 } 208 return false; 209} 210 211uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) { 212 switch (m_context_type) { 213 case eContextTypeRegisterInfo: // RegisterInfo * 214 if (GetRegisterInfo()) { 215 if (error_ptr) 216 error_ptr->Clear(); 217 return GetRegisterInfo()->byte_size; 218 } 219 break; 220 221 case eContextTypeInvalid: 222 case eContextTypeLLDBType: // Type * 223 case eContextTypeVariable: // Variable * 224 { 225 auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; 226 if (llvm::Optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) { 227 if (error_ptr) 228 error_ptr->Clear(); 229 return *size; 230 } 231 break; 232 } 233 } 234 if (error_ptr && error_ptr->Success()) 235 error_ptr->SetErrorString("Unable to determine byte size."); 236 return 0; 237} 238 239const CompilerType &Value::GetCompilerType() { 240 if (!m_compiler_type.IsValid()) { 241 switch (m_context_type) { 242 case eContextTypeInvalid: 243 break; 244 245 case eContextTypeRegisterInfo: 246 break; // TODO: Eventually convert into a compiler type? 247 248 case eContextTypeLLDBType: { 249 Type *lldb_type = GetType(); 250 if (lldb_type) 251 m_compiler_type = lldb_type->GetForwardCompilerType(); 252 } break; 253 254 case eContextTypeVariable: { 255 Variable *variable = GetVariable(); 256 if (variable) { 257 Type *variable_type = variable->GetType(); 258 if (variable_type) 259 m_compiler_type = variable_type->GetForwardCompilerType(); 260 } 261 } break; 262 } 263 } 264 265 return m_compiler_type; 266} 267 268void Value::SetCompilerType(const CompilerType &compiler_type) { 269 m_compiler_type = compiler_type; 270} 271 272lldb::Format Value::GetValueDefaultFormat() { 273 switch (m_context_type) { 274 case eContextTypeRegisterInfo: 275 if (GetRegisterInfo()) 276 return GetRegisterInfo()->format; 277 break; 278 279 case eContextTypeInvalid: 280 case eContextTypeLLDBType: 281 case eContextTypeVariable: { 282 const CompilerType &ast_type = GetCompilerType(); 283 if (ast_type.IsValid()) 284 return ast_type.GetFormat(); 285 } break; 286 } 287 288 // Return a good default in case we can't figure anything out 289 return eFormatHex; 290} 291 292bool Value::GetData(DataExtractor &data) { 293 switch (m_value_type) { 294 default: 295 break; 296 297 case eValueTypeScalar: 298 if (m_value.GetData(data)) 299 return true; 300 break; 301 302 case eValueTypeLoadAddress: 303 case eValueTypeFileAddress: 304 case eValueTypeHostAddress: 305 if (m_data_buffer.GetByteSize()) { 306 data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), 307 data.GetByteOrder()); 308 return true; 309 } 310 break; 311 } 312 313 return false; 314} 315 316Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, 317 Module *module) { 318 data.Clear(); 319 320 Status error; 321 lldb::addr_t address = LLDB_INVALID_ADDRESS; 322 AddressType address_type = eAddressTypeFile; 323 Address file_so_addr; 324 const CompilerType &ast_type = GetCompilerType(); 325 llvm::Optional<uint64_t> type_size = ast_type.GetByteSize( 326 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); 327 // Nothing to be done for a zero-sized type. 328 if (type_size && *type_size == 0) 329 return error; 330 331 switch (m_value_type) { 332 case eValueTypeVector: 333 if (ast_type.IsValid()) 334 data.SetAddressByteSize(ast_type.GetPointerByteSize()); 335 else 336 data.SetAddressByteSize(sizeof(void *)); 337 data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order); 338 break; 339 340 case eValueTypeScalar: { 341 data.SetByteOrder(endian::InlHostByteOrder()); 342 if (ast_type.IsValid()) 343 data.SetAddressByteSize(ast_type.GetPointerByteSize()); 344 else 345 data.SetAddressByteSize(sizeof(void *)); 346 347 uint32_t limit_byte_size = UINT32_MAX; 348 349 if (type_size) 350 limit_byte_size = *type_size; 351 352 if (limit_byte_size <= m_value.GetByteSize()) { 353 if (m_value.GetData(data, limit_byte_size)) 354 return error; // Success; 355 } 356 357 error.SetErrorStringWithFormat("extracting data from value failed"); 358 break; 359 } 360 case eValueTypeLoadAddress: 361 if (exe_ctx == nullptr) { 362 error.SetErrorString("can't read load address (no execution context)"); 363 } else { 364 Process *process = exe_ctx->GetProcessPtr(); 365 if (process == nullptr || !process->IsAlive()) { 366 Target *target = exe_ctx->GetTargetPtr(); 367 if (target) { 368 // Allow expressions to run and evaluate things when the target has 369 // memory sections loaded. This allows you to use "target modules 370 // load" to load your executable and any shared libraries, then 371 // execute commands where you can look at types in data sections. 372 const SectionLoadList &target_sections = target->GetSectionLoadList(); 373 if (!target_sections.IsEmpty()) { 374 address = m_value.ULongLong(LLDB_INVALID_ADDRESS); 375 if (target_sections.ResolveLoadAddress(address, file_so_addr)) { 376 address_type = eAddressTypeLoad; 377 data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 378 data.SetAddressByteSize( 379 target->GetArchitecture().GetAddressByteSize()); 380 } else 381 address = LLDB_INVALID_ADDRESS; 382 } 383 } else { 384 error.SetErrorString("can't read load address (invalid process)"); 385 } 386 } else { 387 address = m_value.ULongLong(LLDB_INVALID_ADDRESS); 388 address_type = eAddressTypeLoad; 389 data.SetByteOrder( 390 process->GetTarget().GetArchitecture().GetByteOrder()); 391 data.SetAddressByteSize( 392 process->GetTarget().GetArchitecture().GetAddressByteSize()); 393 } 394 } 395 break; 396 397 case eValueTypeFileAddress: 398 if (exe_ctx == nullptr) { 399 error.SetErrorString("can't read file address (no execution context)"); 400 } else if (exe_ctx->GetTargetPtr() == nullptr) { 401 error.SetErrorString("can't read file address (invalid target)"); 402 } else { 403 address = m_value.ULongLong(LLDB_INVALID_ADDRESS); 404 if (address == LLDB_INVALID_ADDRESS) { 405 error.SetErrorString("invalid file address"); 406 } else { 407 if (module == nullptr) { 408 // The only thing we can currently lock down to a module so that we 409 // can resolve a file address, is a variable. 410 Variable *variable = GetVariable(); 411 if (variable) { 412 SymbolContext var_sc; 413 variable->CalculateSymbolContext(&var_sc); 414 module = var_sc.module_sp.get(); 415 } 416 } 417 418 if (module) { 419 bool resolved = false; 420 ObjectFile *objfile = module->GetObjectFile(); 421 if (objfile) { 422 Address so_addr(address, objfile->GetSectionList()); 423 addr_t load_address = 424 so_addr.GetLoadAddress(exe_ctx->GetTargetPtr()); 425 bool process_launched_and_stopped = 426 exe_ctx->GetProcessPtr() 427 ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), 428 true /* must_exist */) 429 : false; 430 // Don't use the load address if the process has exited. 431 if (load_address != LLDB_INVALID_ADDRESS && 432 process_launched_and_stopped) { 433 resolved = true; 434 address = load_address; 435 address_type = eAddressTypeLoad; 436 data.SetByteOrder( 437 exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); 438 data.SetAddressByteSize(exe_ctx->GetTargetRef() 439 .GetArchitecture() 440 .GetAddressByteSize()); 441 } else { 442 if (so_addr.IsSectionOffset()) { 443 resolved = true; 444 file_so_addr = so_addr; 445 data.SetByteOrder(objfile->GetByteOrder()); 446 data.SetAddressByteSize(objfile->GetAddressByteSize()); 447 } 448 } 449 } 450 if (!resolved) { 451 Variable *variable = GetVariable(); 452 453 if (module) { 454 if (variable) 455 error.SetErrorStringWithFormat( 456 "unable to resolve the module for file address 0x%" PRIx64 457 " for variable '%s' in %s", 458 address, variable->GetName().AsCString(""), 459 module->GetFileSpec().GetPath().c_str()); 460 else 461 error.SetErrorStringWithFormat( 462 "unable to resolve the module for file address 0x%" PRIx64 463 " in %s", 464 address, module->GetFileSpec().GetPath().c_str()); 465 } else { 466 if (variable) 467 error.SetErrorStringWithFormat( 468 "unable to resolve the module for file address 0x%" PRIx64 469 " for variable '%s'", 470 address, variable->GetName().AsCString("")); 471 else 472 error.SetErrorStringWithFormat( 473 "unable to resolve the module for file address 0x%" PRIx64, 474 address); 475 } 476 } 477 } else { 478 // Can't convert a file address to anything valid without more 479 // context (which Module it came from) 480 error.SetErrorString( 481 "can't read memory from file address without more context"); 482 } 483 } 484 } 485 break; 486 487 case eValueTypeHostAddress: 488 address = m_value.ULongLong(LLDB_INVALID_ADDRESS); 489 address_type = eAddressTypeHost; 490 if (exe_ctx) { 491 Target *target = exe_ctx->GetTargetPtr(); 492 if (target) { 493 data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 494 data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 495 break; 496 } 497 } 498 // fallback to host settings 499 data.SetByteOrder(endian::InlHostByteOrder()); 500 data.SetAddressByteSize(sizeof(void *)); 501 break; 502 } 503 504 // Bail if we encountered any errors 505 if (error.Fail()) 506 return error; 507 508 if (address == LLDB_INVALID_ADDRESS) { 509 error.SetErrorStringWithFormat("invalid %s address", 510 address_type == eAddressTypeHost ? "host" 511 : "load"); 512 return error; 513 } 514 515 // If we got here, we need to read the value from memory. 516 size_t byte_size = GetValueByteSize(&error, exe_ctx); 517 518 // Bail if we encountered any errors getting the byte size. 519 if (error.Fail()) 520 return error; 521 522 // No memory to read for zero-sized types. 523 if (byte_size == 0) 524 return error; 525 526 // Make sure we have enough room within "data", and if we don't make 527 // something large enough that does 528 if (!data.ValidOffsetForDataOfSize(0, byte_size)) { 529 auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0'); 530 data.SetData(data_sp); 531 } 532 533 uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); 534 if (dst != nullptr) { 535 if (address_type == eAddressTypeHost) { 536 // The address is an address in this process, so just copy it. 537 if (address == 0) { 538 error.SetErrorStringWithFormat( 539 "trying to read from host address of 0."); 540 return error; 541 } 542 memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size); 543 } else if ((address_type == eAddressTypeLoad) || 544 (address_type == eAddressTypeFile)) { 545 if (file_so_addr.IsValid()) { 546 // We have a file address that we were able to translate into a section 547 // offset address so we might be able to read this from the object 548 // files if we don't have a live process. Lets always try and read from 549 // the process if we have one though since we want to read the actual 550 // value by setting "prefer_file_cache" to false. 551 const bool prefer_file_cache = false; 552 if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, 553 dst, byte_size, 554 error) != byte_size) { 555 error.SetErrorStringWithFormat( 556 "read memory from 0x%" PRIx64 " failed", (uint64_t)address); 557 } 558 } else { 559 // The execution context might have a NULL process, but it might have a 560 // valid process in the exe_ctx->target, so use the 561 // ExecutionContext::GetProcess accessor to ensure we get the process 562 // if there is one. 563 Process *process = exe_ctx->GetProcessPtr(); 564 565 if (process) { 566 const size_t bytes_read = 567 process->ReadMemory(address, dst, byte_size, error); 568 if (bytes_read != byte_size) 569 error.SetErrorStringWithFormat( 570 "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", 571 (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); 572 } else { 573 error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 574 " failed (invalid process)", 575 (uint64_t)address); 576 } 577 } 578 } else { 579 error.SetErrorStringWithFormat("unsupported AddressType value (%i)", 580 address_type); 581 } 582 } else { 583 error.SetErrorStringWithFormat("out of memory"); 584 } 585 586 return error; 587} 588 589Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { 590 const CompilerType &compiler_type = GetCompilerType(); 591 if (compiler_type.IsValid()) { 592 switch (m_value_type) { 593 case eValueTypeScalar: // raw scalar value 594 break; 595 596 default: 597 case eValueTypeFileAddress: 598 case eValueTypeLoadAddress: // load address value 599 case eValueTypeHostAddress: // host address value (for memory in the process 600 // that is using liblldb) 601 { 602 DataExtractor data; 603 lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); 604 Status error(GetValueAsData(exe_ctx, data, nullptr)); 605 if (error.Success()) { 606 Scalar scalar; 607 if (compiler_type.GetValueAsScalar(data, 0, data.GetByteSize(), 608 scalar)) { 609 m_value = scalar; 610 m_value_type = eValueTypeScalar; 611 } else { 612 if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { 613 m_value.Clear(); 614 m_value_type = eValueTypeScalar; 615 } 616 } 617 } else { 618 if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { 619 m_value.Clear(); 620 m_value_type = eValueTypeScalar; 621 } 622 } 623 } break; 624 } 625 } 626 return m_value; 627} 628 629Variable *Value::GetVariable() { 630 if (m_context_type == eContextTypeVariable) 631 return static_cast<Variable *>(m_context); 632 return nullptr; 633} 634 635void Value::Clear() { 636 m_value.Clear(); 637 m_vector.Clear(); 638 m_compiler_type.Clear(); 639 m_value_type = eValueTypeScalar; 640 m_context = nullptr; 641 m_context_type = eContextTypeInvalid; 642 m_data_buffer.Clear(); 643} 644 645const char *Value::GetValueTypeAsCString(ValueType value_type) { 646 switch (value_type) { 647 case eValueTypeScalar: 648 return "scalar"; 649 case eValueTypeVector: 650 return "vector"; 651 case eValueTypeFileAddress: 652 return "file address"; 653 case eValueTypeLoadAddress: 654 return "load address"; 655 case eValueTypeHostAddress: 656 return "host address"; 657 }; 658 return "???"; 659} 660 661const char *Value::GetContextTypeAsCString(ContextType context_type) { 662 switch (context_type) { 663 case eContextTypeInvalid: 664 return "invalid"; 665 case eContextTypeRegisterInfo: 666 return "RegisterInfo *"; 667 case eContextTypeLLDBType: 668 return "Type *"; 669 case eContextTypeVariable: 670 return "Variable *"; 671 }; 672 return "???"; 673} 674 675void Value::ConvertToLoadAddress(Module *module, Target *target) { 676 if (!module || !target || (GetValueType() != eValueTypeFileAddress)) 677 return; 678 679 lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 680 if (file_addr == LLDB_INVALID_ADDRESS) 681 return; 682 683 Address so_addr; 684 if (!module->ResolveFileAddress(file_addr, so_addr)) 685 return; 686 lldb::addr_t load_addr = so_addr.GetLoadAddress(target); 687 if (load_addr == LLDB_INVALID_ADDRESS) 688 return; 689 690 SetValueType(Value::eValueTypeLoadAddress); 691 GetScalar() = load_addr; 692} 693 694ValueList::ValueList(const ValueList &rhs) { m_values = rhs.m_values; } 695 696const ValueList &ValueList::operator=(const ValueList &rhs) { 697 m_values = rhs.m_values; 698 return *this; 699} 700 701void ValueList::PushValue(const Value &value) { m_values.push_back(value); } 702 703size_t ValueList::GetSize() { return m_values.size(); } 704 705Value *ValueList::GetValueAtIndex(size_t idx) { 706 if (idx < GetSize()) { 707 return &(m_values[idx]); 708 } else 709 return nullptr; 710} 711 712void ValueList::Clear() { m_values.clear(); } 713