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