1//===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lldb/Core/ValueObjectMemory.h" 10#include "lldb/Core/Value.h" 11#include "lldb/Core/ValueObject.h" 12#include "lldb/Symbol/Type.h" 13#include "lldb/Target/ExecutionContext.h" 14#include "lldb/Target/Target.h" 15#include "lldb/Utility/DataExtractor.h" 16#include "lldb/Utility/Scalar.h" 17#include "lldb/Utility/Status.h" 18#include "lldb/lldb-types.h" 19#include "llvm/Support/ErrorHandling.h" 20 21#include <assert.h> 22#include <memory> 23 24namespace lldb_private { 25class ExecutionContextScope; 26} 27 28using namespace lldb; 29using namespace lldb_private; 30 31ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 32 llvm::StringRef name, 33 const Address &address, 34 lldb::TypeSP &type_sp) { 35 return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); 36} 37 38ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, 39 llvm::StringRef name, 40 const Address &address, 41 const CompilerType &ast_type) { 42 return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); 43} 44 45ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 46 llvm::StringRef name, 47 const Address &address, 48 lldb::TypeSP &type_sp) 49 : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), 50 m_compiler_type() { 51 // Do not attempt to construct one of these objects with no variable! 52 assert(m_type_sp.get() != nullptr); 53 SetName(ConstString(name)); 54 m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 55 TargetSP target_sp(GetTargetSP()); 56 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 57 if (load_address != LLDB_INVALID_ADDRESS) { 58 m_value.SetValueType(Value::eValueTypeLoadAddress); 59 m_value.GetScalar() = load_address; 60 } else { 61 lldb::addr_t file_address = m_address.GetFileAddress(); 62 if (file_address != LLDB_INVALID_ADDRESS) { 63 m_value.SetValueType(Value::eValueTypeFileAddress); 64 m_value.GetScalar() = file_address; 65 } else { 66 m_value.GetScalar() = m_address.GetOffset(); 67 m_value.SetValueType(Value::eValueTypeScalar); 68 } 69 } 70} 71 72ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, 73 llvm::StringRef name, 74 const Address &address, 75 const CompilerType &ast_type) 76 : ValueObject(exe_scope), m_address(address), m_type_sp(), 77 m_compiler_type(ast_type) { 78 // Do not attempt to construct one of these objects with no variable! 79 assert(m_compiler_type.GetTypeSystem()); 80 assert(m_compiler_type.GetOpaqueQualType()); 81 82 TargetSP target_sp(GetTargetSP()); 83 84 SetName(ConstString(name)); 85 // m_value.SetContext(Value::eContextTypeClangType, 86 // m_compiler_type.GetOpaqueQualType()); 87 m_value.SetCompilerType(m_compiler_type); 88 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 89 if (load_address != LLDB_INVALID_ADDRESS) { 90 m_value.SetValueType(Value::eValueTypeLoadAddress); 91 m_value.GetScalar() = load_address; 92 } else { 93 lldb::addr_t file_address = m_address.GetFileAddress(); 94 if (file_address != LLDB_INVALID_ADDRESS) { 95 m_value.SetValueType(Value::eValueTypeFileAddress); 96 m_value.GetScalar() = file_address; 97 } else { 98 m_value.GetScalar() = m_address.GetOffset(); 99 m_value.SetValueType(Value::eValueTypeScalar); 100 } 101 } 102} 103 104ValueObjectMemory::~ValueObjectMemory() {} 105 106CompilerType ValueObjectMemory::GetCompilerTypeImpl() { 107 if (m_type_sp) 108 return m_type_sp->GetForwardCompilerType(); 109 return m_compiler_type; 110} 111 112ConstString ValueObjectMemory::GetTypeName() { 113 if (m_type_sp) 114 return m_type_sp->GetName(); 115 return m_compiler_type.GetConstTypeName(); 116} 117 118ConstString ValueObjectMemory::GetDisplayTypeName() { 119 if (m_type_sp) 120 return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); 121 return m_compiler_type.GetDisplayTypeName(); 122} 123 124size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { 125 if (m_type_sp) { 126 auto child_count = m_type_sp->GetNumChildren(true); 127 return child_count <= max ? child_count : max; 128 } 129 130 ExecutionContext exe_ctx(GetExecutionContextRef()); 131 const bool omit_empty_base_classes = true; 132 auto child_count = 133 m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx); 134 return child_count <= max ? child_count : max; 135} 136 137uint64_t ValueObjectMemory::GetByteSize() { 138 if (m_type_sp) 139 return m_type_sp->GetByteSize().getValueOr(0); 140 return m_compiler_type.GetByteSize(nullptr).getValueOr(0); 141} 142 143lldb::ValueType ValueObjectMemory::GetValueType() const { 144 // RETHINK: Should this be inherited from somewhere? 145 return lldb::eValueTypeVariableGlobal; 146} 147 148bool ValueObjectMemory::UpdateValue() { 149 SetValueIsValid(false); 150 m_error.Clear(); 151 152 ExecutionContext exe_ctx(GetExecutionContextRef()); 153 154 Target *target = exe_ctx.GetTargetPtr(); 155 if (target) { 156 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 157 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 158 } 159 160 Value old_value(m_value); 161 if (m_address.IsValid()) { 162 Value::ValueType value_type = m_value.GetValueType(); 163 164 switch (value_type) { 165 default: 166 llvm_unreachable("Unhandled expression result value kind..."); 167 168 case Value::eValueTypeScalar: 169 // The variable value is in the Scalar value inside the m_value. We can 170 // point our m_data right to it. 171 m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 172 break; 173 174 case Value::eValueTypeFileAddress: 175 case Value::eValueTypeLoadAddress: 176 case Value::eValueTypeHostAddress: 177 // The DWARF expression result was an address in the inferior process. If 178 // this variable is an aggregate type, we just need the address as the 179 // main value as all child variable objects will rely upon this location 180 // and add an offset and then read their own values as needed. If this 181 // variable is a simple type, we read all data for it into m_data. Make 182 // sure this type has a value before we try and read it 183 184 // If we have a file address, convert it to a load address if we can. 185 if (value_type == Value::eValueTypeFileAddress && 186 exe_ctx.GetProcessPtr()) { 187 lldb::addr_t load_addr = m_address.GetLoadAddress(target); 188 if (load_addr != LLDB_INVALID_ADDRESS) { 189 m_value.SetValueType(Value::eValueTypeLoadAddress); 190 m_value.GetScalar() = load_addr; 191 } 192 } 193 194 if (!CanProvideValue()) { 195 // this value object represents an aggregate type whose children have 196 // values, but this object does not. So we say we are changed if our 197 // location has changed. 198 SetValueDidChange(value_type != old_value.GetValueType() || 199 m_value.GetScalar() != old_value.GetScalar()); 200 } else { 201 // Copy the Value and set the context to use our Variable so it can 202 // extract read its value into m_data appropriately 203 Value value(m_value); 204 if (m_type_sp) 205 value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 206 else { 207 // value.SetContext(Value::eContextTypeClangType, 208 // m_compiler_type.GetOpaqueQualType()); 209 value.SetCompilerType(m_compiler_type); 210 } 211 212 m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 213 } 214 break; 215 } 216 217 SetValueIsValid(m_error.Success()); 218 } 219 return m_error.Success(); 220} 221 222bool ValueObjectMemory::IsInScope() { 223 // FIXME: Maybe try to read the memory address, and if that works, then 224 // we are in scope? 225 return true; 226} 227 228lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } 229