xref: /openbsd-src/gnu/llvm/lldb/source/Core/Value.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- Value.cpp ---------------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Core/Value.h"
10061da546Spatrick 
11061da546Spatrick #include "lldb/Core/Address.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Symbol/CompilerType.h"
14061da546Spatrick #include "lldb/Symbol/ObjectFile.h"
15061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
16061da546Spatrick #include "lldb/Symbol/Type.h"
17061da546Spatrick #include "lldb/Symbol/Variable.h"
18061da546Spatrick #include "lldb/Target/ExecutionContext.h"
19061da546Spatrick #include "lldb/Target/Process.h"
20061da546Spatrick #include "lldb/Target/SectionLoadList.h"
21061da546Spatrick #include "lldb/Target/Target.h"
22061da546Spatrick #include "lldb/Utility/ConstString.h"
23061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
24061da546Spatrick #include "lldb/Utility/DataExtractor.h"
25061da546Spatrick #include "lldb/Utility/Endian.h"
26061da546Spatrick #include "lldb/Utility/FileSpec.h"
27061da546Spatrick #include "lldb/Utility/State.h"
28061da546Spatrick #include "lldb/Utility/Stream.h"
29061da546Spatrick #include "lldb/lldb-defines.h"
30061da546Spatrick #include "lldb/lldb-forward.h"
31061da546Spatrick #include "lldb/lldb-types.h"
32061da546Spatrick 
33061da546Spatrick #include <memory>
34*f6aab3d8Srobert #include <optional>
35061da546Spatrick #include <string>
36061da546Spatrick 
37be691f3bSpatrick #include <cinttypes>
38061da546Spatrick 
39061da546Spatrick using namespace lldb;
40061da546Spatrick using namespace lldb_private;
41061da546Spatrick 
Value()42be691f3bSpatrick Value::Value() : m_value(), m_compiler_type(), m_data_buffer() {}
43061da546Spatrick 
Value(const Scalar & scalar)44061da546Spatrick Value::Value(const Scalar &scalar)
45*f6aab3d8Srobert     : m_value(scalar), m_compiler_type(), m_data_buffer() {}
46061da546Spatrick 
Value(const void * bytes,int len)47061da546Spatrick Value::Value(const void *bytes, int len)
48*f6aab3d8Srobert     : m_value(), m_compiler_type(), m_value_type(ValueType::HostAddress),
49061da546Spatrick       m_data_buffer() {
50061da546Spatrick   SetBytes(bytes, len);
51061da546Spatrick }
52061da546Spatrick 
Value(const Value & v)53061da546Spatrick Value::Value(const Value &v)
54be691f3bSpatrick     : m_value(v.m_value), m_compiler_type(v.m_compiler_type),
55be691f3bSpatrick       m_context(v.m_context), m_value_type(v.m_value_type),
56be691f3bSpatrick       m_context_type(v.m_context_type), m_data_buffer() {
57061da546Spatrick   const uintptr_t rhs_value =
58061da546Spatrick       (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);
59061da546Spatrick   if ((rhs_value != 0) &&
60061da546Spatrick       (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) {
61061da546Spatrick     m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
62061da546Spatrick                            v.m_data_buffer.GetByteSize());
63061da546Spatrick 
64061da546Spatrick     m_value = (uintptr_t)m_data_buffer.GetBytes();
65061da546Spatrick   }
66061da546Spatrick }
67061da546Spatrick 
operator =(const Value & rhs)68061da546Spatrick Value &Value::operator=(const Value &rhs) {
69061da546Spatrick   if (this != &rhs) {
70061da546Spatrick     m_value = rhs.m_value;
71061da546Spatrick     m_compiler_type = rhs.m_compiler_type;
72061da546Spatrick     m_context = rhs.m_context;
73061da546Spatrick     m_value_type = rhs.m_value_type;
74061da546Spatrick     m_context_type = rhs.m_context_type;
75061da546Spatrick     const uintptr_t rhs_value =
76061da546Spatrick         (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS);
77061da546Spatrick     if ((rhs_value != 0) &&
78061da546Spatrick         (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) {
79061da546Spatrick       m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),
80061da546Spatrick                              rhs.m_data_buffer.GetByteSize());
81061da546Spatrick 
82061da546Spatrick       m_value = (uintptr_t)m_data_buffer.GetBytes();
83061da546Spatrick     }
84061da546Spatrick   }
85061da546Spatrick   return *this;
86061da546Spatrick }
87061da546Spatrick 
SetBytes(const void * bytes,int len)88061da546Spatrick void Value::SetBytes(const void *bytes, int len) {
89be691f3bSpatrick   m_value_type = ValueType::HostAddress;
90061da546Spatrick   m_data_buffer.CopyData(bytes, len);
91061da546Spatrick   m_value = (uintptr_t)m_data_buffer.GetBytes();
92061da546Spatrick }
93061da546Spatrick 
AppendBytes(const void * bytes,int len)94061da546Spatrick void Value::AppendBytes(const void *bytes, int len) {
95be691f3bSpatrick   m_value_type = ValueType::HostAddress;
96061da546Spatrick   m_data_buffer.AppendData(bytes, len);
97061da546Spatrick   m_value = (uintptr_t)m_data_buffer.GetBytes();
98061da546Spatrick }
99061da546Spatrick 
Dump(Stream * strm)100061da546Spatrick void Value::Dump(Stream *strm) {
101061da546Spatrick   m_value.GetValue(strm, true);
102061da546Spatrick   strm->Printf(", value_type = %s, context = %p, context_type = %s",
103061da546Spatrick                Value::GetValueTypeAsCString(m_value_type), m_context,
104061da546Spatrick                Value::GetContextTypeAsCString(m_context_type));
105061da546Spatrick }
106061da546Spatrick 
GetValueType() const107061da546Spatrick Value::ValueType Value::GetValueType() const { return m_value_type; }
108061da546Spatrick 
GetValueAddressType() const109061da546Spatrick AddressType Value::GetValueAddressType() const {
110061da546Spatrick   switch (m_value_type) {
111be691f3bSpatrick   case ValueType::Invalid:
112be691f3bSpatrick   case ValueType::Scalar:
113061da546Spatrick     break;
114be691f3bSpatrick   case ValueType::LoadAddress:
115061da546Spatrick     return eAddressTypeLoad;
116be691f3bSpatrick   case ValueType::FileAddress:
117061da546Spatrick     return eAddressTypeFile;
118be691f3bSpatrick   case ValueType::HostAddress:
119061da546Spatrick     return eAddressTypeHost;
120061da546Spatrick   }
121061da546Spatrick   return eAddressTypeInvalid;
122061da546Spatrick }
123061da546Spatrick 
GetRegisterInfo() const124061da546Spatrick RegisterInfo *Value::GetRegisterInfo() const {
125be691f3bSpatrick   if (m_context_type == ContextType::RegisterInfo)
126061da546Spatrick     return static_cast<RegisterInfo *>(m_context);
127061da546Spatrick   return nullptr;
128061da546Spatrick }
129061da546Spatrick 
GetType()130061da546Spatrick Type *Value::GetType() {
131be691f3bSpatrick   if (m_context_type == ContextType::LLDBType)
132061da546Spatrick     return static_cast<Type *>(m_context);
133061da546Spatrick   return nullptr;
134061da546Spatrick }
135061da546Spatrick 
AppendDataToHostBuffer(const Value & rhs)136061da546Spatrick size_t Value::AppendDataToHostBuffer(const Value &rhs) {
137061da546Spatrick   if (this == &rhs)
138061da546Spatrick     return 0;
139061da546Spatrick 
140061da546Spatrick   size_t curr_size = m_data_buffer.GetByteSize();
141061da546Spatrick   Status error;
142061da546Spatrick   switch (rhs.GetValueType()) {
143be691f3bSpatrick   case ValueType::Invalid:
144be691f3bSpatrick     return 0;
145be691f3bSpatrick   case ValueType::Scalar: {
146061da546Spatrick     const size_t scalar_size = rhs.m_value.GetByteSize();
147061da546Spatrick     if (scalar_size > 0) {
148061da546Spatrick       const size_t new_size = curr_size + scalar_size;
149061da546Spatrick       if (ResizeData(new_size) == new_size) {
150061da546Spatrick         rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size,
151061da546Spatrick                                     scalar_size, endian::InlHostByteOrder(),
152061da546Spatrick                                     error);
153061da546Spatrick         return scalar_size;
154061da546Spatrick       }
155061da546Spatrick     }
156061da546Spatrick   } break;
157be691f3bSpatrick   case ValueType::FileAddress:
158be691f3bSpatrick   case ValueType::LoadAddress:
159be691f3bSpatrick   case ValueType::HostAddress: {
160061da546Spatrick     const uint8_t *src = rhs.GetBuffer().GetBytes();
161061da546Spatrick     const size_t src_len = rhs.GetBuffer().GetByteSize();
162061da546Spatrick     if (src && src_len > 0) {
163061da546Spatrick       const size_t new_size = curr_size + src_len;
164061da546Spatrick       if (ResizeData(new_size) == new_size) {
165061da546Spatrick         ::memcpy(m_data_buffer.GetBytes() + curr_size, src, src_len);
166061da546Spatrick         return src_len;
167061da546Spatrick       }
168061da546Spatrick     }
169061da546Spatrick   } break;
170061da546Spatrick   }
171061da546Spatrick   return 0;
172061da546Spatrick }
173061da546Spatrick 
ResizeData(size_t len)174061da546Spatrick size_t Value::ResizeData(size_t len) {
175be691f3bSpatrick   m_value_type = ValueType::HostAddress;
176061da546Spatrick   m_data_buffer.SetByteSize(len);
177061da546Spatrick   m_value = (uintptr_t)m_data_buffer.GetBytes();
178061da546Spatrick   return m_data_buffer.GetByteSize();
179061da546Spatrick }
180061da546Spatrick 
ValueOf(ExecutionContext * exe_ctx)181061da546Spatrick bool Value::ValueOf(ExecutionContext *exe_ctx) {
182061da546Spatrick   switch (m_context_type) {
183be691f3bSpatrick   case ContextType::Invalid:
184be691f3bSpatrick   case ContextType::RegisterInfo: // RegisterInfo *
185be691f3bSpatrick   case ContextType::LLDBType:     // Type *
186061da546Spatrick     break;
187061da546Spatrick 
188be691f3bSpatrick   case ContextType::Variable: // Variable *
189061da546Spatrick     ResolveValue(exe_ctx);
190061da546Spatrick     return true;
191061da546Spatrick   }
192061da546Spatrick   return false;
193061da546Spatrick }
194061da546Spatrick 
GetValueByteSize(Status * error_ptr,ExecutionContext * exe_ctx)195061da546Spatrick uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
196061da546Spatrick   switch (m_context_type) {
197be691f3bSpatrick   case ContextType::RegisterInfo: // RegisterInfo *
198061da546Spatrick     if (GetRegisterInfo()) {
199061da546Spatrick       if (error_ptr)
200061da546Spatrick         error_ptr->Clear();
201061da546Spatrick       return GetRegisterInfo()->byte_size;
202061da546Spatrick     }
203061da546Spatrick     break;
204061da546Spatrick 
205be691f3bSpatrick   case ContextType::Invalid:
206be691f3bSpatrick   case ContextType::LLDBType: // Type *
207be691f3bSpatrick   case ContextType::Variable: // Variable *
208061da546Spatrick   {
209061da546Spatrick     auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
210*f6aab3d8Srobert     if (std::optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) {
211061da546Spatrick       if (error_ptr)
212061da546Spatrick         error_ptr->Clear();
213061da546Spatrick       return *size;
214061da546Spatrick     }
215061da546Spatrick     break;
216061da546Spatrick   }
217061da546Spatrick   }
218061da546Spatrick   if (error_ptr && error_ptr->Success())
219061da546Spatrick     error_ptr->SetErrorString("Unable to determine byte size.");
220061da546Spatrick   return 0;
221061da546Spatrick }
222061da546Spatrick 
GetCompilerType()223061da546Spatrick const CompilerType &Value::GetCompilerType() {
224061da546Spatrick   if (!m_compiler_type.IsValid()) {
225061da546Spatrick     switch (m_context_type) {
226be691f3bSpatrick     case ContextType::Invalid:
227061da546Spatrick       break;
228061da546Spatrick 
229be691f3bSpatrick     case ContextType::RegisterInfo:
230061da546Spatrick       break; // TODO: Eventually convert into a compiler type?
231061da546Spatrick 
232be691f3bSpatrick     case ContextType::LLDBType: {
233061da546Spatrick       Type *lldb_type = GetType();
234061da546Spatrick       if (lldb_type)
235061da546Spatrick         m_compiler_type = lldb_type->GetForwardCompilerType();
236061da546Spatrick     } break;
237061da546Spatrick 
238be691f3bSpatrick     case ContextType::Variable: {
239061da546Spatrick       Variable *variable = GetVariable();
240061da546Spatrick       if (variable) {
241061da546Spatrick         Type *variable_type = variable->GetType();
242061da546Spatrick         if (variable_type)
243061da546Spatrick           m_compiler_type = variable_type->GetForwardCompilerType();
244061da546Spatrick       }
245061da546Spatrick     } break;
246061da546Spatrick     }
247061da546Spatrick   }
248061da546Spatrick 
249061da546Spatrick   return m_compiler_type;
250061da546Spatrick }
251061da546Spatrick 
SetCompilerType(const CompilerType & compiler_type)252061da546Spatrick void Value::SetCompilerType(const CompilerType &compiler_type) {
253061da546Spatrick   m_compiler_type = compiler_type;
254061da546Spatrick }
255061da546Spatrick 
GetValueDefaultFormat()256061da546Spatrick lldb::Format Value::GetValueDefaultFormat() {
257061da546Spatrick   switch (m_context_type) {
258be691f3bSpatrick   case ContextType::RegisterInfo:
259061da546Spatrick     if (GetRegisterInfo())
260061da546Spatrick       return GetRegisterInfo()->format;
261061da546Spatrick     break;
262061da546Spatrick 
263be691f3bSpatrick   case ContextType::Invalid:
264be691f3bSpatrick   case ContextType::LLDBType:
265be691f3bSpatrick   case ContextType::Variable: {
266061da546Spatrick     const CompilerType &ast_type = GetCompilerType();
267061da546Spatrick     if (ast_type.IsValid())
268061da546Spatrick       return ast_type.GetFormat();
269061da546Spatrick   } break;
270061da546Spatrick   }
271061da546Spatrick 
272061da546Spatrick   // Return a good default in case we can't figure anything out
273061da546Spatrick   return eFormatHex;
274061da546Spatrick }
275061da546Spatrick 
GetData(DataExtractor & data)276061da546Spatrick bool Value::GetData(DataExtractor &data) {
277061da546Spatrick   switch (m_value_type) {
278be691f3bSpatrick   case ValueType::Invalid:
279be691f3bSpatrick     return false;
280be691f3bSpatrick   case ValueType::Scalar:
281061da546Spatrick     if (m_value.GetData(data))
282061da546Spatrick       return true;
283061da546Spatrick     break;
284061da546Spatrick 
285be691f3bSpatrick   case ValueType::LoadAddress:
286be691f3bSpatrick   case ValueType::FileAddress:
287be691f3bSpatrick   case ValueType::HostAddress:
288061da546Spatrick     if (m_data_buffer.GetByteSize()) {
289061da546Spatrick       data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(),
290061da546Spatrick                    data.GetByteOrder());
291061da546Spatrick       return true;
292061da546Spatrick     }
293061da546Spatrick     break;
294061da546Spatrick   }
295061da546Spatrick 
296061da546Spatrick   return false;
297061da546Spatrick }
298061da546Spatrick 
GetValueAsData(ExecutionContext * exe_ctx,DataExtractor & data,Module * module)299061da546Spatrick Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
300061da546Spatrick                              Module *module) {
301061da546Spatrick   data.Clear();
302061da546Spatrick 
303061da546Spatrick   Status error;
304061da546Spatrick   lldb::addr_t address = LLDB_INVALID_ADDRESS;
305061da546Spatrick   AddressType address_type = eAddressTypeFile;
306061da546Spatrick   Address file_so_addr;
307061da546Spatrick   const CompilerType &ast_type = GetCompilerType();
308*f6aab3d8Srobert   std::optional<uint64_t> type_size = ast_type.GetByteSize(
309061da546Spatrick       exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
310061da546Spatrick   // Nothing to be done for a zero-sized type.
311061da546Spatrick   if (type_size && *type_size == 0)
312061da546Spatrick     return error;
313061da546Spatrick 
314061da546Spatrick   switch (m_value_type) {
315be691f3bSpatrick   case ValueType::Invalid:
316be691f3bSpatrick     error.SetErrorString("invalid value");
317061da546Spatrick     break;
318be691f3bSpatrick   case ValueType::Scalar: {
319061da546Spatrick     data.SetByteOrder(endian::InlHostByteOrder());
320061da546Spatrick     if (ast_type.IsValid())
321061da546Spatrick       data.SetAddressByteSize(ast_type.GetPointerByteSize());
322061da546Spatrick     else
323061da546Spatrick       data.SetAddressByteSize(sizeof(void *));
324061da546Spatrick 
325061da546Spatrick     uint32_t limit_byte_size = UINT32_MAX;
326061da546Spatrick 
327061da546Spatrick     if (type_size)
328061da546Spatrick       limit_byte_size = *type_size;
329061da546Spatrick 
330061da546Spatrick     if (limit_byte_size <= m_value.GetByteSize()) {
331061da546Spatrick       if (m_value.GetData(data, limit_byte_size))
332061da546Spatrick         return error; // Success;
333061da546Spatrick     }
334061da546Spatrick 
335be691f3bSpatrick     error.SetErrorString("extracting data from value failed");
336061da546Spatrick     break;
337061da546Spatrick   }
338be691f3bSpatrick   case ValueType::LoadAddress:
339061da546Spatrick     if (exe_ctx == nullptr) {
340061da546Spatrick       error.SetErrorString("can't read load address (no execution context)");
341061da546Spatrick     } else {
342061da546Spatrick       Process *process = exe_ctx->GetProcessPtr();
343061da546Spatrick       if (process == nullptr || !process->IsAlive()) {
344061da546Spatrick         Target *target = exe_ctx->GetTargetPtr();
345061da546Spatrick         if (target) {
346061da546Spatrick           // Allow expressions to run and evaluate things when the target has
347061da546Spatrick           // memory sections loaded. This allows you to use "target modules
348061da546Spatrick           // load" to load your executable and any shared libraries, then
349061da546Spatrick           // execute commands where you can look at types in data sections.
350061da546Spatrick           const SectionLoadList &target_sections = target->GetSectionLoadList();
351061da546Spatrick           if (!target_sections.IsEmpty()) {
352061da546Spatrick             address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
353061da546Spatrick             if (target_sections.ResolveLoadAddress(address, file_so_addr)) {
354061da546Spatrick               address_type = eAddressTypeLoad;
355061da546Spatrick               data.SetByteOrder(target->GetArchitecture().GetByteOrder());
356061da546Spatrick               data.SetAddressByteSize(
357061da546Spatrick                   target->GetArchitecture().GetAddressByteSize());
358061da546Spatrick             } else
359061da546Spatrick               address = LLDB_INVALID_ADDRESS;
360061da546Spatrick           }
361061da546Spatrick         } else {
362061da546Spatrick           error.SetErrorString("can't read load address (invalid process)");
363061da546Spatrick         }
364061da546Spatrick       } else {
365061da546Spatrick         address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
366061da546Spatrick         address_type = eAddressTypeLoad;
367061da546Spatrick         data.SetByteOrder(
368061da546Spatrick             process->GetTarget().GetArchitecture().GetByteOrder());
369061da546Spatrick         data.SetAddressByteSize(
370061da546Spatrick             process->GetTarget().GetArchitecture().GetAddressByteSize());
371061da546Spatrick       }
372061da546Spatrick     }
373061da546Spatrick     break;
374061da546Spatrick 
375be691f3bSpatrick   case ValueType::FileAddress:
376061da546Spatrick     if (exe_ctx == nullptr) {
377061da546Spatrick       error.SetErrorString("can't read file address (no execution context)");
378061da546Spatrick     } else if (exe_ctx->GetTargetPtr() == nullptr) {
379061da546Spatrick       error.SetErrorString("can't read file address (invalid target)");
380061da546Spatrick     } else {
381061da546Spatrick       address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
382061da546Spatrick       if (address == LLDB_INVALID_ADDRESS) {
383061da546Spatrick         error.SetErrorString("invalid file address");
384061da546Spatrick       } else {
385061da546Spatrick         if (module == nullptr) {
386061da546Spatrick           // The only thing we can currently lock down to a module so that we
387061da546Spatrick           // can resolve a file address, is a variable.
388061da546Spatrick           Variable *variable = GetVariable();
389061da546Spatrick           if (variable) {
390061da546Spatrick             SymbolContext var_sc;
391061da546Spatrick             variable->CalculateSymbolContext(&var_sc);
392061da546Spatrick             module = var_sc.module_sp.get();
393061da546Spatrick           }
394061da546Spatrick         }
395061da546Spatrick 
396061da546Spatrick         if (module) {
397061da546Spatrick           bool resolved = false;
398061da546Spatrick           ObjectFile *objfile = module->GetObjectFile();
399061da546Spatrick           if (objfile) {
400061da546Spatrick             Address so_addr(address, objfile->GetSectionList());
401061da546Spatrick             addr_t load_address =
402061da546Spatrick                 so_addr.GetLoadAddress(exe_ctx->GetTargetPtr());
403061da546Spatrick             bool process_launched_and_stopped =
404061da546Spatrick                 exe_ctx->GetProcessPtr()
405061da546Spatrick                     ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(),
406061da546Spatrick                                           true /* must_exist */)
407061da546Spatrick                     : false;
408061da546Spatrick             // Don't use the load address if the process has exited.
409061da546Spatrick             if (load_address != LLDB_INVALID_ADDRESS &&
410061da546Spatrick                 process_launched_and_stopped) {
411061da546Spatrick               resolved = true;
412061da546Spatrick               address = load_address;
413061da546Spatrick               address_type = eAddressTypeLoad;
414061da546Spatrick               data.SetByteOrder(
415061da546Spatrick                   exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
416061da546Spatrick               data.SetAddressByteSize(exe_ctx->GetTargetRef()
417061da546Spatrick                                           .GetArchitecture()
418061da546Spatrick                                           .GetAddressByteSize());
419061da546Spatrick             } else {
420061da546Spatrick               if (so_addr.IsSectionOffset()) {
421061da546Spatrick                 resolved = true;
422061da546Spatrick                 file_so_addr = so_addr;
423061da546Spatrick                 data.SetByteOrder(objfile->GetByteOrder());
424061da546Spatrick                 data.SetAddressByteSize(objfile->GetAddressByteSize());
425061da546Spatrick               }
426061da546Spatrick             }
427061da546Spatrick           }
428061da546Spatrick           if (!resolved) {
429061da546Spatrick             Variable *variable = GetVariable();
430061da546Spatrick 
431061da546Spatrick             if (module) {
432061da546Spatrick               if (variable)
433061da546Spatrick                 error.SetErrorStringWithFormat(
434061da546Spatrick                     "unable to resolve the module for file address 0x%" PRIx64
435061da546Spatrick                     " for variable '%s' in %s",
436061da546Spatrick                     address, variable->GetName().AsCString(""),
437061da546Spatrick                     module->GetFileSpec().GetPath().c_str());
438061da546Spatrick               else
439061da546Spatrick                 error.SetErrorStringWithFormat(
440061da546Spatrick                     "unable to resolve the module for file address 0x%" PRIx64
441061da546Spatrick                     " in %s",
442061da546Spatrick                     address, module->GetFileSpec().GetPath().c_str());
443061da546Spatrick             } else {
444061da546Spatrick               if (variable)
445061da546Spatrick                 error.SetErrorStringWithFormat(
446061da546Spatrick                     "unable to resolve the module for file address 0x%" PRIx64
447061da546Spatrick                     " for variable '%s'",
448061da546Spatrick                     address, variable->GetName().AsCString(""));
449061da546Spatrick               else
450061da546Spatrick                 error.SetErrorStringWithFormat(
451061da546Spatrick                     "unable to resolve the module for file address 0x%" PRIx64,
452061da546Spatrick                     address);
453061da546Spatrick             }
454061da546Spatrick           }
455061da546Spatrick         } else {
456061da546Spatrick           // Can't convert a file address to anything valid without more
457061da546Spatrick           // context (which Module it came from)
458061da546Spatrick           error.SetErrorString(
459061da546Spatrick               "can't read memory from file address without more context");
460061da546Spatrick         }
461061da546Spatrick       }
462061da546Spatrick     }
463061da546Spatrick     break;
464061da546Spatrick 
465be691f3bSpatrick   case ValueType::HostAddress:
466061da546Spatrick     address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
467061da546Spatrick     address_type = eAddressTypeHost;
468061da546Spatrick     if (exe_ctx) {
469061da546Spatrick       Target *target = exe_ctx->GetTargetPtr();
470061da546Spatrick       if (target) {
471061da546Spatrick         data.SetByteOrder(target->GetArchitecture().GetByteOrder());
472061da546Spatrick         data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
473061da546Spatrick         break;
474061da546Spatrick       }
475061da546Spatrick     }
476061da546Spatrick     // fallback to host settings
477061da546Spatrick     data.SetByteOrder(endian::InlHostByteOrder());
478061da546Spatrick     data.SetAddressByteSize(sizeof(void *));
479061da546Spatrick     break;
480061da546Spatrick   }
481061da546Spatrick 
482061da546Spatrick   // Bail if we encountered any errors
483061da546Spatrick   if (error.Fail())
484061da546Spatrick     return error;
485061da546Spatrick 
486061da546Spatrick   if (address == LLDB_INVALID_ADDRESS) {
487061da546Spatrick     error.SetErrorStringWithFormat("invalid %s address",
488061da546Spatrick                                    address_type == eAddressTypeHost ? "host"
489061da546Spatrick                                                                     : "load");
490061da546Spatrick     return error;
491061da546Spatrick   }
492061da546Spatrick 
493061da546Spatrick   // If we got here, we need to read the value from memory.
494061da546Spatrick   size_t byte_size = GetValueByteSize(&error, exe_ctx);
495061da546Spatrick 
496061da546Spatrick   // Bail if we encountered any errors getting the byte size.
497061da546Spatrick   if (error.Fail())
498061da546Spatrick     return error;
499061da546Spatrick 
500061da546Spatrick   // No memory to read for zero-sized types.
501061da546Spatrick   if (byte_size == 0)
502061da546Spatrick     return error;
503061da546Spatrick 
504061da546Spatrick   // Make sure we have enough room within "data", and if we don't make
505061da546Spatrick   // something large enough that does
506061da546Spatrick   if (!data.ValidOffsetForDataOfSize(0, byte_size)) {
507061da546Spatrick     auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
508061da546Spatrick     data.SetData(data_sp);
509061da546Spatrick   }
510061da546Spatrick 
511061da546Spatrick   uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size));
512061da546Spatrick   if (dst != nullptr) {
513061da546Spatrick     if (address_type == eAddressTypeHost) {
514061da546Spatrick       // The address is an address in this process, so just copy it.
515061da546Spatrick       if (address == 0) {
516be691f3bSpatrick         error.SetErrorString("trying to read from host address of 0.");
517061da546Spatrick         return error;
518061da546Spatrick       }
519061da546Spatrick       memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size);
520061da546Spatrick     } else if ((address_type == eAddressTypeLoad) ||
521061da546Spatrick                (address_type == eAddressTypeFile)) {
522061da546Spatrick       if (file_so_addr.IsValid()) {
523be691f3bSpatrick         const bool force_live_memory = true;
524be691f3bSpatrick         if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, dst, byte_size,
525be691f3bSpatrick                                                error, force_live_memory) !=
526be691f3bSpatrick             byte_size) {
527061da546Spatrick           error.SetErrorStringWithFormat(
528061da546Spatrick               "read memory from 0x%" PRIx64 " failed", (uint64_t)address);
529061da546Spatrick         }
530061da546Spatrick       } else {
531061da546Spatrick         // The execution context might have a NULL process, but it might have a
532061da546Spatrick         // valid process in the exe_ctx->target, so use the
533061da546Spatrick         // ExecutionContext::GetProcess accessor to ensure we get the process
534061da546Spatrick         // if there is one.
535061da546Spatrick         Process *process = exe_ctx->GetProcessPtr();
536061da546Spatrick 
537061da546Spatrick         if (process) {
538061da546Spatrick           const size_t bytes_read =
539061da546Spatrick               process->ReadMemory(address, dst, byte_size, error);
540061da546Spatrick           if (bytes_read != byte_size)
541061da546Spatrick             error.SetErrorStringWithFormat(
542061da546Spatrick                 "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
543061da546Spatrick                 (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size);
544061da546Spatrick         } else {
545061da546Spatrick           error.SetErrorStringWithFormat("read memory from 0x%" PRIx64
546061da546Spatrick                                          " failed (invalid process)",
547061da546Spatrick                                          (uint64_t)address);
548061da546Spatrick         }
549061da546Spatrick       }
550061da546Spatrick     } else {
551061da546Spatrick       error.SetErrorStringWithFormat("unsupported AddressType value (%i)",
552061da546Spatrick                                      address_type);
553061da546Spatrick     }
554061da546Spatrick   } else {
555be691f3bSpatrick     error.SetErrorString("out of memory");
556061da546Spatrick   }
557061da546Spatrick 
558061da546Spatrick   return error;
559061da546Spatrick }
560061da546Spatrick 
ResolveValue(ExecutionContext * exe_ctx)561061da546Spatrick Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) {
562061da546Spatrick   const CompilerType &compiler_type = GetCompilerType();
563061da546Spatrick   if (compiler_type.IsValid()) {
564061da546Spatrick     switch (m_value_type) {
565be691f3bSpatrick     case ValueType::Invalid:
566be691f3bSpatrick     case ValueType::Scalar: // raw scalar value
567061da546Spatrick       break;
568061da546Spatrick 
569be691f3bSpatrick     case ValueType::FileAddress:
570be691f3bSpatrick     case ValueType::LoadAddress: // load address value
571be691f3bSpatrick     case ValueType::HostAddress: // host address value (for memory in the process
572061da546Spatrick                                 // that is using liblldb)
573061da546Spatrick     {
574061da546Spatrick       DataExtractor data;
575061da546Spatrick       lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
576061da546Spatrick       Status error(GetValueAsData(exe_ctx, data, nullptr));
577061da546Spatrick       if (error.Success()) {
578061da546Spatrick         Scalar scalar;
579be691f3bSpatrick         if (compiler_type.GetValueAsScalar(
580be691f3bSpatrick                 data, 0, data.GetByteSize(), scalar,
581be691f3bSpatrick                 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) {
582061da546Spatrick           m_value = scalar;
583be691f3bSpatrick           m_value_type = ValueType::Scalar;
584061da546Spatrick         } else {
585061da546Spatrick           if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
586061da546Spatrick             m_value.Clear();
587be691f3bSpatrick             m_value_type = ValueType::Scalar;
588061da546Spatrick           }
589061da546Spatrick         }
590061da546Spatrick       } else {
591061da546Spatrick         if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
592061da546Spatrick           m_value.Clear();
593be691f3bSpatrick           m_value_type = ValueType::Scalar;
594061da546Spatrick         }
595061da546Spatrick       }
596061da546Spatrick     } break;
597061da546Spatrick     }
598061da546Spatrick   }
599061da546Spatrick   return m_value;
600061da546Spatrick }
601061da546Spatrick 
GetVariable()602061da546Spatrick Variable *Value::GetVariable() {
603be691f3bSpatrick   if (m_context_type == ContextType::Variable)
604061da546Spatrick     return static_cast<Variable *>(m_context);
605061da546Spatrick   return nullptr;
606061da546Spatrick }
607061da546Spatrick 
Clear()608061da546Spatrick void Value::Clear() {
609061da546Spatrick   m_value.Clear();
610061da546Spatrick   m_compiler_type.Clear();
611be691f3bSpatrick   m_value_type = ValueType::Scalar;
612061da546Spatrick   m_context = nullptr;
613be691f3bSpatrick   m_context_type = ContextType::Invalid;
614061da546Spatrick   m_data_buffer.Clear();
615061da546Spatrick }
616061da546Spatrick 
GetValueTypeAsCString(ValueType value_type)617061da546Spatrick const char *Value::GetValueTypeAsCString(ValueType value_type) {
618061da546Spatrick   switch (value_type) {
619be691f3bSpatrick   case ValueType::Invalid:
620be691f3bSpatrick     return "invalid";
621be691f3bSpatrick   case ValueType::Scalar:
622061da546Spatrick     return "scalar";
623be691f3bSpatrick   case ValueType::FileAddress:
624061da546Spatrick     return "file address";
625be691f3bSpatrick   case ValueType::LoadAddress:
626061da546Spatrick     return "load address";
627be691f3bSpatrick   case ValueType::HostAddress:
628061da546Spatrick     return "host address";
629061da546Spatrick   };
630be691f3bSpatrick   llvm_unreachable("enum cases exhausted.");
631061da546Spatrick }
632061da546Spatrick 
GetContextTypeAsCString(ContextType context_type)633061da546Spatrick const char *Value::GetContextTypeAsCString(ContextType context_type) {
634061da546Spatrick   switch (context_type) {
635be691f3bSpatrick   case ContextType::Invalid:
636061da546Spatrick     return "invalid";
637be691f3bSpatrick   case ContextType::RegisterInfo:
638061da546Spatrick     return "RegisterInfo *";
639be691f3bSpatrick   case ContextType::LLDBType:
640061da546Spatrick     return "Type *";
641be691f3bSpatrick   case ContextType::Variable:
642061da546Spatrick     return "Variable *";
643061da546Spatrick   };
644be691f3bSpatrick   llvm_unreachable("enum cases exhausted.");
645061da546Spatrick }
646061da546Spatrick 
ConvertToLoadAddress(Module * module,Target * target)647061da546Spatrick void Value::ConvertToLoadAddress(Module *module, Target *target) {
648be691f3bSpatrick   if (!module || !target || (GetValueType() != ValueType::FileAddress))
649061da546Spatrick     return;
650061da546Spatrick 
651061da546Spatrick   lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
652061da546Spatrick   if (file_addr == LLDB_INVALID_ADDRESS)
653061da546Spatrick     return;
654061da546Spatrick 
655061da546Spatrick   Address so_addr;
656061da546Spatrick   if (!module->ResolveFileAddress(file_addr, so_addr))
657061da546Spatrick     return;
658061da546Spatrick   lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
659061da546Spatrick   if (load_addr == LLDB_INVALID_ADDRESS)
660061da546Spatrick     return;
661061da546Spatrick 
662be691f3bSpatrick   SetValueType(Value::ValueType::LoadAddress);
663061da546Spatrick   GetScalar() = load_addr;
664061da546Spatrick }
665061da546Spatrick 
PushValue(const Value & value)666061da546Spatrick void ValueList::PushValue(const Value &value) { m_values.push_back(value); }
667061da546Spatrick 
GetSize()668061da546Spatrick size_t ValueList::GetSize() { return m_values.size(); }
669061da546Spatrick 
GetValueAtIndex(size_t idx)670061da546Spatrick Value *ValueList::GetValueAtIndex(size_t idx) {
671061da546Spatrick   if (idx < GetSize()) {
672061da546Spatrick     return &(m_values[idx]);
673061da546Spatrick   } else
674061da546Spatrick     return nullptr;
675061da546Spatrick }
676061da546Spatrick 
Clear()677061da546Spatrick void ValueList::Clear() { m_values.clear(); }
678