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