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