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