15ffd83dbSDimitry Andric //===-- Value.cpp ---------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/Value.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Address.h"
120b57cec5SDimitry Andric #include "lldb/Core/Module.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
140b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
150b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
170b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h"
180b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
190b57cec5SDimitry Andric #include "lldb/Target/Process.h"
200b57cec5SDimitry Andric #include "lldb/Target/SectionLoadList.h"
210b57cec5SDimitry Andric #include "lldb/Target/Target.h"
220b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
230b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
240b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
250b57cec5SDimitry Andric #include "lldb/Utility/Endian.h"
260b57cec5SDimitry Andric #include "lldb/Utility/FileSpec.h"
270b57cec5SDimitry Andric #include "lldb/Utility/State.h"
280b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
290b57cec5SDimitry Andric #include "lldb/lldb-defines.h"
300b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
310b57cec5SDimitry Andric #include "lldb/lldb-types.h"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #include <memory>
34bdd1243dSDimitry Andric #include <optional>
350b57cec5SDimitry Andric #include <string>
360b57cec5SDimitry Andric 
37fe6060f1SDimitry Andric #include <cinttypes>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric using namespace lldb;
400b57cec5SDimitry Andric using namespace lldb_private;
410b57cec5SDimitry Andric 
Value()42fe6060f1SDimitry Andric Value::Value() : m_value(), m_compiler_type(), m_data_buffer() {}
430b57cec5SDimitry Andric 
Value(const Scalar & scalar)440b57cec5SDimitry Andric Value::Value(const Scalar &scalar)
4581ad6265SDimitry Andric     : m_value(scalar), m_compiler_type(), m_data_buffer() {}
460b57cec5SDimitry Andric 
Value(const void * bytes,int len)470b57cec5SDimitry Andric Value::Value(const void *bytes, int len)
4881ad6265SDimitry Andric     : m_value(), m_compiler_type(), m_value_type(ValueType::HostAddress),
490b57cec5SDimitry Andric       m_data_buffer() {
500b57cec5SDimitry Andric   SetBytes(bytes, len);
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
Value(const Value & v)530b57cec5SDimitry Andric Value::Value(const Value &v)
54e8d8bef9SDimitry Andric     : m_value(v.m_value), m_compiler_type(v.m_compiler_type),
55e8d8bef9SDimitry Andric       m_context(v.m_context), m_value_type(v.m_value_type),
56e8d8bef9SDimitry Andric       m_context_type(v.m_context_type), m_data_buffer() {
570b57cec5SDimitry Andric   const uintptr_t rhs_value =
580b57cec5SDimitry Andric       (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS);
590b57cec5SDimitry Andric   if ((rhs_value != 0) &&
600b57cec5SDimitry Andric       (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) {
610b57cec5SDimitry Andric     m_data_buffer.CopyData(v.m_data_buffer.GetBytes(),
620b57cec5SDimitry Andric                            v.m_data_buffer.GetByteSize());
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric     m_value = (uintptr_t)m_data_buffer.GetBytes();
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
operator =(const Value & rhs)680b57cec5SDimitry Andric Value &Value::operator=(const Value &rhs) {
690b57cec5SDimitry Andric   if (this != &rhs) {
700b57cec5SDimitry Andric     m_value = rhs.m_value;
710b57cec5SDimitry Andric     m_compiler_type = rhs.m_compiler_type;
720b57cec5SDimitry Andric     m_context = rhs.m_context;
730b57cec5SDimitry Andric     m_value_type = rhs.m_value_type;
740b57cec5SDimitry Andric     m_context_type = rhs.m_context_type;
750b57cec5SDimitry Andric     const uintptr_t rhs_value =
760b57cec5SDimitry Andric         (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS);
770b57cec5SDimitry Andric     if ((rhs_value != 0) &&
780b57cec5SDimitry Andric         (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) {
790b57cec5SDimitry Andric       m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(),
800b57cec5SDimitry Andric                              rhs.m_data_buffer.GetByteSize());
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric       m_value = (uintptr_t)m_data_buffer.GetBytes();
830b57cec5SDimitry Andric     }
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric   return *this;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
SetBytes(const void * bytes,int len)880b57cec5SDimitry Andric void Value::SetBytes(const void *bytes, int len) {
89fe6060f1SDimitry Andric   m_value_type = ValueType::HostAddress;
900b57cec5SDimitry Andric   m_data_buffer.CopyData(bytes, len);
910b57cec5SDimitry Andric   m_value = (uintptr_t)m_data_buffer.GetBytes();
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
AppendBytes(const void * bytes,int len)940b57cec5SDimitry Andric void Value::AppendBytes(const void *bytes, int len) {
95fe6060f1SDimitry Andric   m_value_type = ValueType::HostAddress;
960b57cec5SDimitry Andric   m_data_buffer.AppendData(bytes, len);
970b57cec5SDimitry Andric   m_value = (uintptr_t)m_data_buffer.GetBytes();
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
Dump(Stream * strm)1000b57cec5SDimitry Andric void Value::Dump(Stream *strm) {
1015f757f3fSDimitry Andric   if (!strm)
1025f757f3fSDimitry Andric     return;
1035f757f3fSDimitry Andric   m_value.GetValue(*strm, true);
1040b57cec5SDimitry Andric   strm->Printf(", value_type = %s, context = %p, context_type = %s",
1050b57cec5SDimitry Andric                Value::GetValueTypeAsCString(m_value_type), m_context,
1060b57cec5SDimitry Andric                Value::GetContextTypeAsCString(m_context_type));
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
GetValueType() const1090b57cec5SDimitry Andric Value::ValueType Value::GetValueType() const { return m_value_type; }
1100b57cec5SDimitry Andric 
GetValueAddressType() const1110b57cec5SDimitry Andric AddressType Value::GetValueAddressType() const {
1120b57cec5SDimitry Andric   switch (m_value_type) {
113fe6060f1SDimitry Andric   case ValueType::Invalid:
114fe6060f1SDimitry Andric   case ValueType::Scalar:
1150b57cec5SDimitry Andric     break;
116fe6060f1SDimitry Andric   case ValueType::LoadAddress:
1170b57cec5SDimitry Andric     return eAddressTypeLoad;
118fe6060f1SDimitry Andric   case ValueType::FileAddress:
1190b57cec5SDimitry Andric     return eAddressTypeFile;
120fe6060f1SDimitry Andric   case ValueType::HostAddress:
1210b57cec5SDimitry Andric     return eAddressTypeHost;
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric   return eAddressTypeInvalid;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
GetValueTypeFromAddressType(AddressType address_type)12606c3fb27SDimitry Andric Value::ValueType Value::GetValueTypeFromAddressType(AddressType address_type) {
12706c3fb27SDimitry Andric   switch (address_type) {
12806c3fb27SDimitry Andric     case eAddressTypeFile:
12906c3fb27SDimitry Andric       return Value::ValueType::FileAddress;
13006c3fb27SDimitry Andric     case eAddressTypeLoad:
13106c3fb27SDimitry Andric       return Value::ValueType::LoadAddress;
13206c3fb27SDimitry Andric     case eAddressTypeHost:
13306c3fb27SDimitry Andric       return Value::ValueType::HostAddress;
13406c3fb27SDimitry Andric     case eAddressTypeInvalid:
13506c3fb27SDimitry Andric       return Value::ValueType::Invalid;
13606c3fb27SDimitry Andric   }
13706c3fb27SDimitry Andric   llvm_unreachable("Unexpected address type!");
13806c3fb27SDimitry Andric }
13906c3fb27SDimitry Andric 
GetRegisterInfo() const1400b57cec5SDimitry Andric RegisterInfo *Value::GetRegisterInfo() const {
141fe6060f1SDimitry Andric   if (m_context_type == ContextType::RegisterInfo)
1420b57cec5SDimitry Andric     return static_cast<RegisterInfo *>(m_context);
1430b57cec5SDimitry Andric   return nullptr;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
GetType()1460b57cec5SDimitry Andric Type *Value::GetType() {
147fe6060f1SDimitry Andric   if (m_context_type == ContextType::LLDBType)
1480b57cec5SDimitry Andric     return static_cast<Type *>(m_context);
1490b57cec5SDimitry Andric   return nullptr;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
AppendDataToHostBuffer(const Value & rhs)1520b57cec5SDimitry Andric size_t Value::AppendDataToHostBuffer(const Value &rhs) {
1530b57cec5SDimitry Andric   if (this == &rhs)
1540b57cec5SDimitry Andric     return 0;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   size_t curr_size = m_data_buffer.GetByteSize();
1570b57cec5SDimitry Andric   Status error;
1580b57cec5SDimitry Andric   switch (rhs.GetValueType()) {
159fe6060f1SDimitry Andric   case ValueType::Invalid:
160fe6060f1SDimitry Andric     return 0;
161fe6060f1SDimitry Andric   case ValueType::Scalar: {
1620b57cec5SDimitry Andric     const size_t scalar_size = rhs.m_value.GetByteSize();
1630b57cec5SDimitry Andric     if (scalar_size > 0) {
1640b57cec5SDimitry Andric       const size_t new_size = curr_size + scalar_size;
1650b57cec5SDimitry Andric       if (ResizeData(new_size) == new_size) {
1660b57cec5SDimitry Andric         rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size,
1670b57cec5SDimitry Andric                                     scalar_size, endian::InlHostByteOrder(),
1680b57cec5SDimitry Andric                                     error);
1690b57cec5SDimitry Andric         return scalar_size;
1700b57cec5SDimitry Andric       }
1710b57cec5SDimitry Andric     }
1720b57cec5SDimitry Andric   } break;
173fe6060f1SDimitry Andric   case ValueType::FileAddress:
174fe6060f1SDimitry Andric   case ValueType::LoadAddress:
175fe6060f1SDimitry Andric   case ValueType::HostAddress: {
1760b57cec5SDimitry Andric     const uint8_t *src = rhs.GetBuffer().GetBytes();
1770b57cec5SDimitry Andric     const size_t src_len = rhs.GetBuffer().GetByteSize();
1780b57cec5SDimitry Andric     if (src && src_len > 0) {
1790b57cec5SDimitry Andric       const size_t new_size = curr_size + src_len;
1800b57cec5SDimitry Andric       if (ResizeData(new_size) == new_size) {
1810b57cec5SDimitry Andric         ::memcpy(m_data_buffer.GetBytes() + curr_size, src, src_len);
1820b57cec5SDimitry Andric         return src_len;
1830b57cec5SDimitry Andric       }
1840b57cec5SDimitry Andric     }
1850b57cec5SDimitry Andric   } break;
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric   return 0;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
ResizeData(size_t len)1900b57cec5SDimitry Andric size_t Value::ResizeData(size_t len) {
191fe6060f1SDimitry Andric   m_value_type = ValueType::HostAddress;
1920b57cec5SDimitry Andric   m_data_buffer.SetByteSize(len);
1930b57cec5SDimitry Andric   m_value = (uintptr_t)m_data_buffer.GetBytes();
1940b57cec5SDimitry Andric   return m_data_buffer.GetByteSize();
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
ValueOf(ExecutionContext * exe_ctx)1970b57cec5SDimitry Andric bool Value::ValueOf(ExecutionContext *exe_ctx) {
1980b57cec5SDimitry Andric   switch (m_context_type) {
199fe6060f1SDimitry Andric   case ContextType::Invalid:
200fe6060f1SDimitry Andric   case ContextType::RegisterInfo: // RegisterInfo *
201fe6060f1SDimitry Andric   case ContextType::LLDBType:     // Type *
2020b57cec5SDimitry Andric     break;
2030b57cec5SDimitry Andric 
204fe6060f1SDimitry Andric   case ContextType::Variable: // Variable *
2050b57cec5SDimitry Andric     ResolveValue(exe_ctx);
2060b57cec5SDimitry Andric     return true;
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric   return false;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric 
GetValueByteSize(Status * error_ptr,ExecutionContext * exe_ctx)2110b57cec5SDimitry Andric uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
2120b57cec5SDimitry Andric   switch (m_context_type) {
213fe6060f1SDimitry Andric   case ContextType::RegisterInfo: // RegisterInfo *
2140b57cec5SDimitry Andric     if (GetRegisterInfo()) {
2150b57cec5SDimitry Andric       if (error_ptr)
2160b57cec5SDimitry Andric         error_ptr->Clear();
2170b57cec5SDimitry Andric       return GetRegisterInfo()->byte_size;
2180b57cec5SDimitry Andric     }
2190b57cec5SDimitry Andric     break;
2200b57cec5SDimitry Andric 
221fe6060f1SDimitry Andric   case ContextType::Invalid:
222fe6060f1SDimitry Andric   case ContextType::LLDBType: // Type *
223fe6060f1SDimitry Andric   case ContextType::Variable: // Variable *
2240b57cec5SDimitry Andric   {
2250b57cec5SDimitry Andric     auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
226bdd1243dSDimitry Andric     if (std::optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) {
2270b57cec5SDimitry Andric       if (error_ptr)
2280b57cec5SDimitry Andric         error_ptr->Clear();
2290b57cec5SDimitry Andric       return *size;
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric     break;
2320b57cec5SDimitry Andric   }
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric   if (error_ptr && error_ptr->Success())
2350b57cec5SDimitry Andric     error_ptr->SetErrorString("Unable to determine byte size.");
2360b57cec5SDimitry Andric   return 0;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
GetCompilerType()2390b57cec5SDimitry Andric const CompilerType &Value::GetCompilerType() {
2400b57cec5SDimitry Andric   if (!m_compiler_type.IsValid()) {
2410b57cec5SDimitry Andric     switch (m_context_type) {
242fe6060f1SDimitry Andric     case ContextType::Invalid:
2430b57cec5SDimitry Andric       break;
2440b57cec5SDimitry Andric 
245fe6060f1SDimitry Andric     case ContextType::RegisterInfo:
2460b57cec5SDimitry Andric       break; // TODO: Eventually convert into a compiler type?
2470b57cec5SDimitry Andric 
248fe6060f1SDimitry Andric     case ContextType::LLDBType: {
2490b57cec5SDimitry Andric       Type *lldb_type = GetType();
2500b57cec5SDimitry Andric       if (lldb_type)
2510b57cec5SDimitry Andric         m_compiler_type = lldb_type->GetForwardCompilerType();
2520b57cec5SDimitry Andric     } break;
2530b57cec5SDimitry Andric 
254fe6060f1SDimitry Andric     case ContextType::Variable: {
2550b57cec5SDimitry Andric       Variable *variable = GetVariable();
2560b57cec5SDimitry Andric       if (variable) {
2570b57cec5SDimitry Andric         Type *variable_type = variable->GetType();
2580b57cec5SDimitry Andric         if (variable_type)
2590b57cec5SDimitry Andric           m_compiler_type = variable_type->GetForwardCompilerType();
2600b57cec5SDimitry Andric       }
2610b57cec5SDimitry Andric     } break;
2620b57cec5SDimitry Andric     }
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   return m_compiler_type;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric 
SetCompilerType(const CompilerType & compiler_type)2680b57cec5SDimitry Andric void Value::SetCompilerType(const CompilerType &compiler_type) {
2690b57cec5SDimitry Andric   m_compiler_type = compiler_type;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
GetValueDefaultFormat()2720b57cec5SDimitry Andric lldb::Format Value::GetValueDefaultFormat() {
2730b57cec5SDimitry Andric   switch (m_context_type) {
274fe6060f1SDimitry Andric   case ContextType::RegisterInfo:
2750b57cec5SDimitry Andric     if (GetRegisterInfo())
2760b57cec5SDimitry Andric       return GetRegisterInfo()->format;
2770b57cec5SDimitry Andric     break;
2780b57cec5SDimitry Andric 
279fe6060f1SDimitry Andric   case ContextType::Invalid:
280fe6060f1SDimitry Andric   case ContextType::LLDBType:
281fe6060f1SDimitry Andric   case ContextType::Variable: {
2820b57cec5SDimitry Andric     const CompilerType &ast_type = GetCompilerType();
2830b57cec5SDimitry Andric     if (ast_type.IsValid())
2840b57cec5SDimitry Andric       return ast_type.GetFormat();
2850b57cec5SDimitry Andric   } break;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // Return a good default in case we can't figure anything out
2890b57cec5SDimitry Andric   return eFormatHex;
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
GetData(DataExtractor & data)2920b57cec5SDimitry Andric bool Value::GetData(DataExtractor &data) {
2930b57cec5SDimitry Andric   switch (m_value_type) {
294fe6060f1SDimitry Andric   case ValueType::Invalid:
295fe6060f1SDimitry Andric     return false;
296fe6060f1SDimitry Andric   case ValueType::Scalar:
2970b57cec5SDimitry Andric     if (m_value.GetData(data))
2980b57cec5SDimitry Andric       return true;
2990b57cec5SDimitry Andric     break;
3000b57cec5SDimitry Andric 
301fe6060f1SDimitry Andric   case ValueType::LoadAddress:
302fe6060f1SDimitry Andric   case ValueType::FileAddress:
303fe6060f1SDimitry Andric   case ValueType::HostAddress:
3040b57cec5SDimitry Andric     if (m_data_buffer.GetByteSize()) {
3050b57cec5SDimitry Andric       data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(),
3060b57cec5SDimitry Andric                    data.GetByteOrder());
3070b57cec5SDimitry Andric       return true;
3080b57cec5SDimitry Andric     }
3090b57cec5SDimitry Andric     break;
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   return false;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
GetValueAsData(ExecutionContext * exe_ctx,DataExtractor & data,Module * module)3150b57cec5SDimitry Andric Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
3169dba64beSDimitry Andric                              Module *module) {
3170b57cec5SDimitry Andric   data.Clear();
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   Status error;
3200b57cec5SDimitry Andric   lldb::addr_t address = LLDB_INVALID_ADDRESS;
3210b57cec5SDimitry Andric   AddressType address_type = eAddressTypeFile;
3220b57cec5SDimitry Andric   Address file_so_addr;
3230b57cec5SDimitry Andric   const CompilerType &ast_type = GetCompilerType();
324bdd1243dSDimitry Andric   std::optional<uint64_t> type_size = ast_type.GetByteSize(
325480093f4SDimitry Andric       exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
326480093f4SDimitry Andric   // Nothing to be done for a zero-sized type.
327480093f4SDimitry Andric   if (type_size && *type_size == 0)
328480093f4SDimitry Andric     return error;
329480093f4SDimitry Andric 
3300b57cec5SDimitry Andric   switch (m_value_type) {
331fe6060f1SDimitry Andric   case ValueType::Invalid:
332fe6060f1SDimitry Andric     error.SetErrorString("invalid value");
333fe6060f1SDimitry Andric     break;
334fe6060f1SDimitry Andric   case ValueType::Scalar: {
3350b57cec5SDimitry Andric     data.SetByteOrder(endian::InlHostByteOrder());
3360b57cec5SDimitry Andric     if (ast_type.IsValid())
3370b57cec5SDimitry Andric       data.SetAddressByteSize(ast_type.GetPointerByteSize());
3380b57cec5SDimitry Andric     else
3390b57cec5SDimitry Andric       data.SetAddressByteSize(sizeof(void *));
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     uint32_t limit_byte_size = UINT32_MAX;
3420b57cec5SDimitry Andric 
343480093f4SDimitry Andric     if (type_size)
344480093f4SDimitry Andric       limit_byte_size = *type_size;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric     if (limit_byte_size <= m_value.GetByteSize()) {
3470b57cec5SDimitry Andric       if (m_value.GetData(data, limit_byte_size))
3480b57cec5SDimitry Andric         return error; // Success;
3490b57cec5SDimitry Andric     }
3500b57cec5SDimitry Andric 
351e8d8bef9SDimitry Andric     error.SetErrorString("extracting data from value failed");
3520b57cec5SDimitry Andric     break;
3530b57cec5SDimitry Andric   }
354fe6060f1SDimitry Andric   case ValueType::LoadAddress:
3550b57cec5SDimitry Andric     if (exe_ctx == nullptr) {
3560b57cec5SDimitry Andric       error.SetErrorString("can't read load address (no execution context)");
3570b57cec5SDimitry Andric     } else {
3580b57cec5SDimitry Andric       Process *process = exe_ctx->GetProcessPtr();
3590b57cec5SDimitry Andric       if (process == nullptr || !process->IsAlive()) {
3600b57cec5SDimitry Andric         Target *target = exe_ctx->GetTargetPtr();
3610b57cec5SDimitry Andric         if (target) {
3620b57cec5SDimitry Andric           // Allow expressions to run and evaluate things when the target has
3630b57cec5SDimitry Andric           // memory sections loaded. This allows you to use "target modules
3640b57cec5SDimitry Andric           // load" to load your executable and any shared libraries, then
3650b57cec5SDimitry Andric           // execute commands where you can look at types in data sections.
3660b57cec5SDimitry Andric           const SectionLoadList &target_sections = target->GetSectionLoadList();
3670b57cec5SDimitry Andric           if (!target_sections.IsEmpty()) {
3680b57cec5SDimitry Andric             address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
3690b57cec5SDimitry Andric             if (target_sections.ResolveLoadAddress(address, file_so_addr)) {
3700b57cec5SDimitry Andric               address_type = eAddressTypeLoad;
3710b57cec5SDimitry Andric               data.SetByteOrder(target->GetArchitecture().GetByteOrder());
3720b57cec5SDimitry Andric               data.SetAddressByteSize(
3730b57cec5SDimitry Andric                   target->GetArchitecture().GetAddressByteSize());
3740b57cec5SDimitry Andric             } else
3750b57cec5SDimitry Andric               address = LLDB_INVALID_ADDRESS;
3760b57cec5SDimitry Andric           }
3770b57cec5SDimitry Andric         } else {
3780b57cec5SDimitry Andric           error.SetErrorString("can't read load address (invalid process)");
3790b57cec5SDimitry Andric         }
3800b57cec5SDimitry Andric       } else {
3810b57cec5SDimitry Andric         address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
3820b57cec5SDimitry Andric         address_type = eAddressTypeLoad;
3830b57cec5SDimitry Andric         data.SetByteOrder(
3840b57cec5SDimitry Andric             process->GetTarget().GetArchitecture().GetByteOrder());
3850b57cec5SDimitry Andric         data.SetAddressByteSize(
3860b57cec5SDimitry Andric             process->GetTarget().GetArchitecture().GetAddressByteSize());
3870b57cec5SDimitry Andric       }
3880b57cec5SDimitry Andric     }
3890b57cec5SDimitry Andric     break;
3900b57cec5SDimitry Andric 
391fe6060f1SDimitry Andric   case ValueType::FileAddress:
3920b57cec5SDimitry Andric     if (exe_ctx == nullptr) {
3930b57cec5SDimitry Andric       error.SetErrorString("can't read file address (no execution context)");
3940b57cec5SDimitry Andric     } else if (exe_ctx->GetTargetPtr() == nullptr) {
3950b57cec5SDimitry Andric       error.SetErrorString("can't read file address (invalid target)");
3960b57cec5SDimitry Andric     } else {
3970b57cec5SDimitry Andric       address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
3980b57cec5SDimitry Andric       if (address == LLDB_INVALID_ADDRESS) {
3990b57cec5SDimitry Andric         error.SetErrorString("invalid file address");
4000b57cec5SDimitry Andric       } else {
4010b57cec5SDimitry Andric         if (module == nullptr) {
4020b57cec5SDimitry Andric           // The only thing we can currently lock down to a module so that we
4030b57cec5SDimitry Andric           // can resolve a file address, is a variable.
4040b57cec5SDimitry Andric           Variable *variable = GetVariable();
4050b57cec5SDimitry Andric           if (variable) {
4060b57cec5SDimitry Andric             SymbolContext var_sc;
4070b57cec5SDimitry Andric             variable->CalculateSymbolContext(&var_sc);
4080b57cec5SDimitry Andric             module = var_sc.module_sp.get();
4090b57cec5SDimitry Andric           }
4100b57cec5SDimitry Andric         }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric         if (module) {
4130b57cec5SDimitry Andric           bool resolved = false;
4140b57cec5SDimitry Andric           ObjectFile *objfile = module->GetObjectFile();
4150b57cec5SDimitry Andric           if (objfile) {
4160b57cec5SDimitry Andric             Address so_addr(address, objfile->GetSectionList());
4170b57cec5SDimitry Andric             addr_t load_address =
4180b57cec5SDimitry Andric                 so_addr.GetLoadAddress(exe_ctx->GetTargetPtr());
4190b57cec5SDimitry Andric             bool process_launched_and_stopped =
4200b57cec5SDimitry Andric                 exe_ctx->GetProcessPtr()
4210b57cec5SDimitry Andric                     ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(),
4220b57cec5SDimitry Andric                                           true /* must_exist */)
4230b57cec5SDimitry Andric                     : false;
4240b57cec5SDimitry Andric             // Don't use the load address if the process has exited.
4250b57cec5SDimitry Andric             if (load_address != LLDB_INVALID_ADDRESS &&
4260b57cec5SDimitry Andric                 process_launched_and_stopped) {
4270b57cec5SDimitry Andric               resolved = true;
4280b57cec5SDimitry Andric               address = load_address;
4290b57cec5SDimitry Andric               address_type = eAddressTypeLoad;
4300b57cec5SDimitry Andric               data.SetByteOrder(
4310b57cec5SDimitry Andric                   exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
4320b57cec5SDimitry Andric               data.SetAddressByteSize(exe_ctx->GetTargetRef()
4330b57cec5SDimitry Andric                                           .GetArchitecture()
4340b57cec5SDimitry Andric                                           .GetAddressByteSize());
4350b57cec5SDimitry Andric             } else {
4360b57cec5SDimitry Andric               if (so_addr.IsSectionOffset()) {
4370b57cec5SDimitry Andric                 resolved = true;
4380b57cec5SDimitry Andric                 file_so_addr = so_addr;
4390b57cec5SDimitry Andric                 data.SetByteOrder(objfile->GetByteOrder());
4400b57cec5SDimitry Andric                 data.SetAddressByteSize(objfile->GetAddressByteSize());
4410b57cec5SDimitry Andric               }
4420b57cec5SDimitry Andric             }
4430b57cec5SDimitry Andric           }
4440b57cec5SDimitry Andric           if (!resolved) {
4450b57cec5SDimitry Andric             Variable *variable = GetVariable();
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric             if (module) {
4480b57cec5SDimitry Andric               if (variable)
4490b57cec5SDimitry Andric                 error.SetErrorStringWithFormat(
4500b57cec5SDimitry Andric                     "unable to resolve the module for file address 0x%" PRIx64
4510b57cec5SDimitry Andric                     " for variable '%s' in %s",
4520b57cec5SDimitry Andric                     address, variable->GetName().AsCString(""),
4530b57cec5SDimitry Andric                     module->GetFileSpec().GetPath().c_str());
4540b57cec5SDimitry Andric               else
4550b57cec5SDimitry Andric                 error.SetErrorStringWithFormat(
4560b57cec5SDimitry Andric                     "unable to resolve the module for file address 0x%" PRIx64
4570b57cec5SDimitry Andric                     " in %s",
4580b57cec5SDimitry Andric                     address, module->GetFileSpec().GetPath().c_str());
4590b57cec5SDimitry Andric             } else {
4600b57cec5SDimitry Andric               if (variable)
4610b57cec5SDimitry Andric                 error.SetErrorStringWithFormat(
4620b57cec5SDimitry Andric                     "unable to resolve the module for file address 0x%" PRIx64
4630b57cec5SDimitry Andric                     " for variable '%s'",
4640b57cec5SDimitry Andric                     address, variable->GetName().AsCString(""));
4650b57cec5SDimitry Andric               else
4660b57cec5SDimitry Andric                 error.SetErrorStringWithFormat(
4670b57cec5SDimitry Andric                     "unable to resolve the module for file address 0x%" PRIx64,
4680b57cec5SDimitry Andric                     address);
4690b57cec5SDimitry Andric             }
4700b57cec5SDimitry Andric           }
4710b57cec5SDimitry Andric         } else {
4720b57cec5SDimitry Andric           // Can't convert a file address to anything valid without more
4730b57cec5SDimitry Andric           // context (which Module it came from)
4740b57cec5SDimitry Andric           error.SetErrorString(
4750b57cec5SDimitry Andric               "can't read memory from file address without more context");
4760b57cec5SDimitry Andric         }
4770b57cec5SDimitry Andric       }
4780b57cec5SDimitry Andric     }
4790b57cec5SDimitry Andric     break;
4800b57cec5SDimitry Andric 
481fe6060f1SDimitry Andric   case ValueType::HostAddress:
4820b57cec5SDimitry Andric     address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
4830b57cec5SDimitry Andric     address_type = eAddressTypeHost;
4840b57cec5SDimitry Andric     if (exe_ctx) {
4850b57cec5SDimitry Andric       Target *target = exe_ctx->GetTargetPtr();
4860b57cec5SDimitry Andric       if (target) {
4870b57cec5SDimitry Andric         data.SetByteOrder(target->GetArchitecture().GetByteOrder());
4880b57cec5SDimitry Andric         data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
4890b57cec5SDimitry Andric         break;
4900b57cec5SDimitry Andric       }
4910b57cec5SDimitry Andric     }
4920b57cec5SDimitry Andric     // fallback to host settings
4930b57cec5SDimitry Andric     data.SetByteOrder(endian::InlHostByteOrder());
4940b57cec5SDimitry Andric     data.SetAddressByteSize(sizeof(void *));
4950b57cec5SDimitry Andric     break;
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   // Bail if we encountered any errors
4990b57cec5SDimitry Andric   if (error.Fail())
5000b57cec5SDimitry Andric     return error;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   if (address == LLDB_INVALID_ADDRESS) {
5030b57cec5SDimitry Andric     error.SetErrorStringWithFormat("invalid %s address",
5040b57cec5SDimitry Andric                                    address_type == eAddressTypeHost ? "host"
5050b57cec5SDimitry Andric                                                                     : "load");
5060b57cec5SDimitry Andric     return error;
5070b57cec5SDimitry Andric   }
5080b57cec5SDimitry Andric 
509480093f4SDimitry Andric   // If we got here, we need to read the value from memory.
5100b57cec5SDimitry Andric   size_t byte_size = GetValueByteSize(&error, exe_ctx);
5110b57cec5SDimitry Andric 
512480093f4SDimitry Andric   // Bail if we encountered any errors getting the byte size.
5130b57cec5SDimitry Andric   if (error.Fail())
5140b57cec5SDimitry Andric     return error;
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   // No memory to read for zero-sized types.
5170b57cec5SDimitry Andric   if (byte_size == 0)
5180b57cec5SDimitry Andric     return error;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   // Make sure we have enough room within "data", and if we don't make
5210b57cec5SDimitry Andric   // something large enough that does
5229dba64beSDimitry Andric   if (!data.ValidOffsetForDataOfSize(0, byte_size)) {
5239dba64beSDimitry Andric     auto data_sp = std::make_shared<DataBufferHeap>(byte_size, '\0');
5240b57cec5SDimitry Andric     data.SetData(data_sp);
5250b57cec5SDimitry Andric   }
5260b57cec5SDimitry Andric 
5279dba64beSDimitry Andric   uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size));
5280b57cec5SDimitry Andric   if (dst != nullptr) {
5290b57cec5SDimitry Andric     if (address_type == eAddressTypeHost) {
5300b57cec5SDimitry Andric       // The address is an address in this process, so just copy it.
5310b57cec5SDimitry Andric       if (address == 0) {
532e8d8bef9SDimitry Andric         error.SetErrorString("trying to read from host address of 0.");
5330b57cec5SDimitry Andric         return error;
5340b57cec5SDimitry Andric       }
5350b57cec5SDimitry Andric       memcpy(dst, reinterpret_cast<uint8_t *>(address), byte_size);
5360b57cec5SDimitry Andric     } else if ((address_type == eAddressTypeLoad) ||
5370b57cec5SDimitry Andric                (address_type == eAddressTypeFile)) {
5380b57cec5SDimitry Andric       if (file_so_addr.IsValid()) {
539fe6060f1SDimitry Andric         const bool force_live_memory = true;
540fe6060f1SDimitry Andric         if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, dst, byte_size,
541fe6060f1SDimitry Andric                                                error, force_live_memory) !=
542fe6060f1SDimitry Andric             byte_size) {
5430b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
5440b57cec5SDimitry Andric               "read memory from 0x%" PRIx64 " failed", (uint64_t)address);
5450b57cec5SDimitry Andric         }
5460b57cec5SDimitry Andric       } else {
5470b57cec5SDimitry Andric         // The execution context might have a NULL process, but it might have a
5480b57cec5SDimitry Andric         // valid process in the exe_ctx->target, so use the
5490b57cec5SDimitry Andric         // ExecutionContext::GetProcess accessor to ensure we get the process
5500b57cec5SDimitry Andric         // if there is one.
5510b57cec5SDimitry Andric         Process *process = exe_ctx->GetProcessPtr();
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric         if (process) {
5540b57cec5SDimitry Andric           const size_t bytes_read =
5550b57cec5SDimitry Andric               process->ReadMemory(address, dst, byte_size, error);
5560b57cec5SDimitry Andric           if (bytes_read != byte_size)
5570b57cec5SDimitry Andric             error.SetErrorStringWithFormat(
5580b57cec5SDimitry Andric                 "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
5590b57cec5SDimitry Andric                 (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size);
5600b57cec5SDimitry Andric         } else {
5610b57cec5SDimitry Andric           error.SetErrorStringWithFormat("read memory from 0x%" PRIx64
5620b57cec5SDimitry Andric                                          " failed (invalid process)",
5630b57cec5SDimitry Andric                                          (uint64_t)address);
5640b57cec5SDimitry Andric         }
5650b57cec5SDimitry Andric       }
5660b57cec5SDimitry Andric     } else {
5670b57cec5SDimitry Andric       error.SetErrorStringWithFormat("unsupported AddressType value (%i)",
5680b57cec5SDimitry Andric                                      address_type);
5690b57cec5SDimitry Andric     }
5700b57cec5SDimitry Andric   } else {
571e8d8bef9SDimitry Andric     error.SetErrorString("out of memory");
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   return error;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
ResolveValue(ExecutionContext * exe_ctx,Module * module)5775f757f3fSDimitry Andric Scalar &Value::ResolveValue(ExecutionContext *exe_ctx, Module *module) {
5780b57cec5SDimitry Andric   const CompilerType &compiler_type = GetCompilerType();
5790b57cec5SDimitry Andric   if (compiler_type.IsValid()) {
5800b57cec5SDimitry Andric     switch (m_value_type) {
581fe6060f1SDimitry Andric     case ValueType::Invalid:
582fe6060f1SDimitry Andric     case ValueType::Scalar: // raw scalar value
5830b57cec5SDimitry Andric       break;
5840b57cec5SDimitry Andric 
585fe6060f1SDimitry Andric     case ValueType::FileAddress:
586fe6060f1SDimitry Andric     case ValueType::LoadAddress: // load address value
587fe6060f1SDimitry Andric     case ValueType::HostAddress: // host address value (for memory in the process
5880b57cec5SDimitry Andric                                 // that is using liblldb)
5890b57cec5SDimitry Andric     {
5900b57cec5SDimitry Andric       DataExtractor data;
5910b57cec5SDimitry Andric       lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS);
5925f757f3fSDimitry Andric       Status error(GetValueAsData(exe_ctx, data, module));
5930b57cec5SDimitry Andric       if (error.Success()) {
5940b57cec5SDimitry Andric         Scalar scalar;
595e8d8bef9SDimitry Andric         if (compiler_type.GetValueAsScalar(
596e8d8bef9SDimitry Andric                 data, 0, data.GetByteSize(), scalar,
597e8d8bef9SDimitry Andric                 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr)) {
5980b57cec5SDimitry Andric           m_value = scalar;
599fe6060f1SDimitry Andric           m_value_type = ValueType::Scalar;
6000b57cec5SDimitry Andric         } else {
6010b57cec5SDimitry Andric           if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
6020b57cec5SDimitry Andric             m_value.Clear();
603fe6060f1SDimitry Andric             m_value_type = ValueType::Scalar;
6040b57cec5SDimitry Andric           }
6050b57cec5SDimitry Andric         }
6060b57cec5SDimitry Andric       } else {
6070b57cec5SDimitry Andric         if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) {
6080b57cec5SDimitry Andric           m_value.Clear();
609fe6060f1SDimitry Andric           m_value_type = ValueType::Scalar;
6100b57cec5SDimitry Andric         }
6110b57cec5SDimitry Andric       }
6120b57cec5SDimitry Andric     } break;
6130b57cec5SDimitry Andric     }
6140b57cec5SDimitry Andric   }
6150b57cec5SDimitry Andric   return m_value;
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric 
GetVariable()6180b57cec5SDimitry Andric Variable *Value::GetVariable() {
619fe6060f1SDimitry Andric   if (m_context_type == ContextType::Variable)
6200b57cec5SDimitry Andric     return static_cast<Variable *>(m_context);
6210b57cec5SDimitry Andric   return nullptr;
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
Clear()6240b57cec5SDimitry Andric void Value::Clear() {
6250b57cec5SDimitry Andric   m_value.Clear();
6260b57cec5SDimitry Andric   m_compiler_type.Clear();
627fe6060f1SDimitry Andric   m_value_type = ValueType::Scalar;
6280b57cec5SDimitry Andric   m_context = nullptr;
629fe6060f1SDimitry Andric   m_context_type = ContextType::Invalid;
6300b57cec5SDimitry Andric   m_data_buffer.Clear();
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
GetValueTypeAsCString(ValueType value_type)6330b57cec5SDimitry Andric const char *Value::GetValueTypeAsCString(ValueType value_type) {
6340b57cec5SDimitry Andric   switch (value_type) {
635fe6060f1SDimitry Andric   case ValueType::Invalid:
636fe6060f1SDimitry Andric     return "invalid";
637fe6060f1SDimitry Andric   case ValueType::Scalar:
6380b57cec5SDimitry Andric     return "scalar";
639fe6060f1SDimitry Andric   case ValueType::FileAddress:
6400b57cec5SDimitry Andric     return "file address";
641fe6060f1SDimitry Andric   case ValueType::LoadAddress:
6420b57cec5SDimitry Andric     return "load address";
643fe6060f1SDimitry Andric   case ValueType::HostAddress:
6440b57cec5SDimitry Andric     return "host address";
6450b57cec5SDimitry Andric   };
646fe6060f1SDimitry Andric   llvm_unreachable("enum cases exhausted.");
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
GetContextTypeAsCString(ContextType context_type)6490b57cec5SDimitry Andric const char *Value::GetContextTypeAsCString(ContextType context_type) {
6500b57cec5SDimitry Andric   switch (context_type) {
651fe6060f1SDimitry Andric   case ContextType::Invalid:
6520b57cec5SDimitry Andric     return "invalid";
653fe6060f1SDimitry Andric   case ContextType::RegisterInfo:
6540b57cec5SDimitry Andric     return "RegisterInfo *";
655fe6060f1SDimitry Andric   case ContextType::LLDBType:
6560b57cec5SDimitry Andric     return "Type *";
657fe6060f1SDimitry Andric   case ContextType::Variable:
6580b57cec5SDimitry Andric     return "Variable *";
6590b57cec5SDimitry Andric   };
660fe6060f1SDimitry Andric   llvm_unreachable("enum cases exhausted.");
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric 
ConvertToLoadAddress(Module * module,Target * target)6630b57cec5SDimitry Andric void Value::ConvertToLoadAddress(Module *module, Target *target) {
664fe6060f1SDimitry Andric   if (!module || !target || (GetValueType() != ValueType::FileAddress))
6650b57cec5SDimitry Andric     return;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   lldb::addr_t file_addr = GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
6680b57cec5SDimitry Andric   if (file_addr == LLDB_INVALID_ADDRESS)
6690b57cec5SDimitry Andric     return;
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   Address so_addr;
6720b57cec5SDimitry Andric   if (!module->ResolveFileAddress(file_addr, so_addr))
6730b57cec5SDimitry Andric     return;
6740b57cec5SDimitry Andric   lldb::addr_t load_addr = so_addr.GetLoadAddress(target);
6750b57cec5SDimitry Andric   if (load_addr == LLDB_INVALID_ADDRESS)
6760b57cec5SDimitry Andric     return;
6770b57cec5SDimitry Andric 
678fe6060f1SDimitry Andric   SetValueType(Value::ValueType::LoadAddress);
6790b57cec5SDimitry Andric   GetScalar() = load_addr;
6800b57cec5SDimitry Andric }
6810b57cec5SDimitry Andric 
PushValue(const Value & value)6820b57cec5SDimitry Andric void ValueList::PushValue(const Value &value) { m_values.push_back(value); }
6830b57cec5SDimitry Andric 
GetSize()6840b57cec5SDimitry Andric size_t ValueList::GetSize() { return m_values.size(); }
6850b57cec5SDimitry Andric 
GetValueAtIndex(size_t idx)6860b57cec5SDimitry Andric Value *ValueList::GetValueAtIndex(size_t idx) {
6870b57cec5SDimitry Andric   if (idx < GetSize()) {
6880b57cec5SDimitry Andric     return &(m_values[idx]);
6890b57cec5SDimitry Andric   } else
6900b57cec5SDimitry Andric     return nullptr;
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric 
Clear()6930b57cec5SDimitry Andric void ValueList::Clear() { m_values.clear(); }
694