180814287SRaphael Isemann //===-- ValueObjectMemory.cpp ---------------------------------------------===//
278a685aaSJim Ingham //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
678a685aaSJim Ingham //
778a685aaSJim Ingham //===----------------------------------------------------------------------===//
878a685aaSJim Ingham 
978a685aaSJim Ingham #include "lldb/Core/ValueObjectMemory.h"
1078a685aaSJim Ingham #include "lldb/Core/Value.h"
1178a685aaSJim Ingham #include "lldb/Core/ValueObject.h"
1278a685aaSJim Ingham #include "lldb/Symbol/Type.h"
1378a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h"
1478a685aaSJim Ingham #include "lldb/Target/Target.h"
15672d2c12SJonas Devlieghere #include "lldb/Utility/DataExtractor.h"
16672d2c12SJonas Devlieghere #include "lldb/Utility/Scalar.h"
17672d2c12SJonas Devlieghere #include "lldb/Utility/Status.h"
18672d2c12SJonas Devlieghere #include "lldb/lldb-types.h"
19672d2c12SJonas Devlieghere #include "llvm/Support/ErrorHandling.h"
202f3df613SZachary Turner 
2176e47d48SRaphael Isemann #include <cassert>
22672d2c12SJonas Devlieghere #include <memory>
232f3df613SZachary Turner 
242f3df613SZachary Turner namespace lldb_private {
252f3df613SZachary Turner class ExecutionContextScope;
262f3df613SZachary Turner }
2778a685aaSJim Ingham 
2858b59f95SJim Ingham using namespace lldb;
2978a685aaSJim Ingham using namespace lldb_private;
3078a685aaSJim Ingham 
Create(ExecutionContextScope * exe_scope,llvm::StringRef name,const Address & address,lldb::TypeSP & type_sp)31b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
3222a2628fSZachary Turner                                         llvm::StringRef name,
3358b59f95SJim Ingham                                         const Address &address,
34b9c1b51eSKate Stone                                         lldb::TypeSP &type_sp) {
35363f05b8SPavel Labath   auto manager_sp = ValueObjectManager::Create();
36363f05b8SPavel Labath   return (new ValueObjectMemory(exe_scope, *manager_sp, name, address, type_sp))
37363f05b8SPavel Labath       ->GetSP();
3858b59f95SJim Ingham }
3958b59f95SJim Ingham 
Create(ExecutionContextScope * exe_scope,llvm::StringRef name,const Address & address,const CompilerType & ast_type)40b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
4122a2628fSZachary Turner                                         llvm::StringRef name,
4284c39663SGreg Clayton                                         const Address &address,
43b9c1b51eSKate Stone                                         const CompilerType &ast_type) {
44363f05b8SPavel Labath   auto manager_sp = ValueObjectManager::Create();
45363f05b8SPavel Labath   return (new ValueObjectMemory(exe_scope, *manager_sp, name, address,
46363f05b8SPavel Labath                                 ast_type))
47363f05b8SPavel Labath       ->GetSP();
4884c39663SGreg Clayton }
4984c39663SGreg Clayton 
ValueObjectMemory(ExecutionContextScope * exe_scope,ValueObjectManager & manager,llvm::StringRef name,const Address & address,lldb::TypeSP & type_sp)5078a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
51363f05b8SPavel Labath                                      ValueObjectManager &manager,
5222a2628fSZachary Turner                                      llvm::StringRef name,
5322a2628fSZachary Turner                                      const Address &address,
54b9c1b51eSKate Stone                                      lldb::TypeSP &type_sp)
55363f05b8SPavel Labath     : ValueObject(exe_scope, manager), m_address(address), m_type_sp(type_sp),
56b9c1b51eSKate Stone       m_compiler_type() {
5778a685aaSJim Ingham   // Do not attempt to construct one of these objects with no variable!
58248a1305SKonrad Kleine   assert(m_type_sp.get() != nullptr);
596f3533fbSEnrico Granata   SetName(ConstString(name));
60057efa99SAdrian Prantl   m_value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());
61cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
62cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
63b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
64057efa99SAdrian Prantl     m_value.SetValueType(Value::ValueType::LoadAddress);
6578a685aaSJim Ingham     m_value.GetScalar() = load_address;
66b9c1b51eSKate Stone   } else {
6778a685aaSJim Ingham     lldb::addr_t file_address = m_address.GetFileAddress();
68b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
69057efa99SAdrian Prantl       m_value.SetValueType(Value::ValueType::FileAddress);
7078a685aaSJim Ingham       m_value.GetScalar() = file_address;
71b9c1b51eSKate Stone     } else {
7278a685aaSJim Ingham       m_value.GetScalar() = m_address.GetOffset();
73057efa99SAdrian Prantl       m_value.SetValueType(Value::ValueType::Scalar);
7478a685aaSJim Ingham     }
7578a685aaSJim Ingham   }
7678a685aaSJim Ingham }
7778a685aaSJim Ingham 
ValueObjectMemory(ExecutionContextScope * exe_scope,ValueObjectManager & manager,llvm::StringRef name,const Address & address,const CompilerType & ast_type)7884c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
79363f05b8SPavel Labath                                      ValueObjectManager &manager,
8022a2628fSZachary Turner                                      llvm::StringRef name,
8122a2628fSZachary Turner                                      const Address &address,
82b9c1b51eSKate Stone                                      const CompilerType &ast_type)
83363f05b8SPavel Labath     : ValueObject(exe_scope, manager), m_address(address), m_type_sp(),
84b9c1b51eSKate Stone       m_compiler_type(ast_type) {
8584c39663SGreg Clayton   // Do not attempt to construct one of these objects with no variable!
863ad353f3SBruce Mitchener   assert(m_compiler_type.GetTypeSystem());
873ad353f3SBruce Mitchener   assert(m_compiler_type.GetOpaqueQualType());
8884c39663SGreg Clayton 
89cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
90cc4d0146SGreg Clayton 
916f3533fbSEnrico Granata   SetName(ConstString(name));
923ad353f3SBruce Mitchener   m_value.SetCompilerType(m_compiler_type);
93cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
94b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
95057efa99SAdrian Prantl     m_value.SetValueType(Value::ValueType::LoadAddress);
9684c39663SGreg Clayton     m_value.GetScalar() = load_address;
97b9c1b51eSKate Stone   } else {
9884c39663SGreg Clayton     lldb::addr_t file_address = m_address.GetFileAddress();
99b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
100057efa99SAdrian Prantl       m_value.SetValueType(Value::ValueType::FileAddress);
10184c39663SGreg Clayton       m_value.GetScalar() = file_address;
102b9c1b51eSKate Stone     } else {
10384c39663SGreg Clayton       m_value.GetScalar() = m_address.GetOffset();
104057efa99SAdrian Prantl       m_value.SetValueType(Value::ValueType::Scalar);
10584c39663SGreg Clayton     }
10684c39663SGreg Clayton   }
10784c39663SGreg Clayton }
10884c39663SGreg Clayton 
109*fd2433e1SJonas Devlieghere ValueObjectMemory::~ValueObjectMemory() = default;
11078a685aaSJim Ingham 
GetCompilerTypeImpl()111b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
11284c39663SGreg Clayton   if (m_type_sp)
11399558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType();
1143ad353f3SBruce Mitchener   return m_compiler_type;
11578a685aaSJim Ingham }
11678a685aaSJim Ingham 
GetTypeName()117b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() {
11884c39663SGreg Clayton   if (m_type_sp)
11978a685aaSJim Ingham     return m_type_sp->GetName();
12030ce956aSRaphael Isemann   return m_compiler_type.GetTypeName();
12178a685aaSJim Ingham }
12278a685aaSJim Ingham 
GetDisplayTypeName()123b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() {
124e8daa2f8SEnrico Granata   if (m_type_sp)
12599558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();
1263ad353f3SBruce Mitchener   return m_compiler_type.GetDisplayTypeName();
127e8daa2f8SEnrico Granata }
128e8daa2f8SEnrico Granata 
CalculateNumChildren(uint32_t max)129b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
130b9c1b51eSKate Stone   if (m_type_sp) {
1319ac7a6c5SSiva Chandra     auto child_count = m_type_sp->GetNumChildren(true);
1329ac7a6c5SSiva Chandra     return child_count <= max ? child_count : max;
1339ac7a6c5SSiva Chandra   }
1349ac7a6c5SSiva Chandra 
135eca07c59SAdrian Prantl   ExecutionContext exe_ctx(GetExecutionContextRef());
13684c39663SGreg Clayton   const bool omit_empty_base_classes = true;
137eca07c59SAdrian Prantl   auto child_count =
138eca07c59SAdrian Prantl       m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
1399ac7a6c5SSiva Chandra   return child_count <= max ? child_count : max;
14078a685aaSJim Ingham }
14178a685aaSJim Ingham 
GetByteSize()142113f56fbSAdrian Prantl llvm::Optional<uint64_t> ValueObjectMemory::GetByteSize() {
14302f58373SAdrian Prantl   ExecutionContext exe_ctx(GetExecutionContextRef());
14484c39663SGreg Clayton   if (m_type_sp)
145113f56fbSAdrian Prantl     return m_type_sp->GetByteSize(exe_ctx.GetBestExecutionContextScope());
146113f56fbSAdrian Prantl   return m_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
14778a685aaSJim Ingham }
14878a685aaSJim Ingham 
GetValueType() const149b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const {
15078a685aaSJim Ingham   // RETHINK: Should this be inherited from somewhere?
15178a685aaSJim Ingham   return lldb::eValueTypeVariableGlobal;
15278a685aaSJim Ingham }
15378a685aaSJim Ingham 
UpdateValue()154b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() {
15578a685aaSJim Ingham   SetValueIsValid(false);
15678a685aaSJim Ingham   m_error.Clear();
15778a685aaSJim Ingham 
158cc4d0146SGreg Clayton   ExecutionContext exe_ctx(GetExecutionContextRef());
15978a685aaSJim Ingham 
160c14ee32dSGreg Clayton   Target *target = exe_ctx.GetTargetPtr();
161b9c1b51eSKate Stone   if (target) {
162c14ee32dSGreg Clayton     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
163c14ee32dSGreg Clayton     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
16478a685aaSJim Ingham   }
16578a685aaSJim Ingham 
16678a685aaSJim Ingham   Value old_value(m_value);
167b9c1b51eSKate Stone   if (m_address.IsValid()) {
16878a685aaSJim Ingham     Value::ValueType value_type = m_value.GetValueType();
16978a685aaSJim Ingham 
170b9c1b51eSKate Stone     switch (value_type) {
171057efa99SAdrian Prantl     case Value::ValueType::Invalid:
172057efa99SAdrian Prantl       m_error.SetErrorString("Invalid value");
173057efa99SAdrian Prantl       return false;
174057efa99SAdrian Prantl     case Value::ValueType::Scalar:
17505097246SAdrian Prantl       // The variable value is in the Scalar value inside the m_value. We can
17605097246SAdrian Prantl       // point our m_data right to it.
177d9cbd2acSAdrian Prantl       m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
17878a685aaSJim Ingham       break;
17978a685aaSJim Ingham 
180057efa99SAdrian Prantl     case Value::ValueType::FileAddress:
181057efa99SAdrian Prantl     case Value::ValueType::LoadAddress:
182057efa99SAdrian Prantl     case Value::ValueType::HostAddress:
18305097246SAdrian Prantl       // The DWARF expression result was an address in the inferior process. If
18405097246SAdrian Prantl       // this variable is an aggregate type, we just need the address as the
18505097246SAdrian Prantl       // main value as all child variable objects will rely upon this location
18605097246SAdrian Prantl       // and add an offset and then read their own values as needed. If this
18705097246SAdrian Prantl       // variable is a simple type, we read all data for it into m_data. Make
18805097246SAdrian Prantl       // sure this type has a value before we try and read it
18978a685aaSJim Ingham 
19078a685aaSJim Ingham       // If we have a file address, convert it to a load address if we can.
191057efa99SAdrian Prantl       if (value_type == Value::ValueType::FileAddress &&
192b9c1b51eSKate Stone           exe_ctx.GetProcessPtr()) {
193c14ee32dSGreg Clayton         lldb::addr_t load_addr = m_address.GetLoadAddress(target);
194b9c1b51eSKate Stone         if (load_addr != LLDB_INVALID_ADDRESS) {
195057efa99SAdrian Prantl           m_value.SetValueType(Value::ValueType::LoadAddress);
19678a685aaSJim Ingham           m_value.GetScalar() = load_addr;
19778a685aaSJim Ingham         }
19878a685aaSJim Ingham       }
19978a685aaSJim Ingham 
200b9c1b51eSKate Stone       if (!CanProvideValue()) {
20105097246SAdrian Prantl         // this value object represents an aggregate type whose children have
20205097246SAdrian Prantl         // values, but this object does not. So we say we are changed if our
20305097246SAdrian Prantl         // location has changed.
204b9c1b51eSKate Stone         SetValueDidChange(value_type != old_value.GetValueType() ||
205b9c1b51eSKate Stone                           m_value.GetScalar() != old_value.GetScalar());
206b9c1b51eSKate Stone       } else {
20705097246SAdrian Prantl         // Copy the Value and set the context to use our Variable so it can
20805097246SAdrian Prantl         // extract read its value into m_data appropriately
20978a685aaSJim Ingham         Value value(m_value);
21084c39663SGreg Clayton         if (m_type_sp)
211057efa99SAdrian Prantl           value.SetContext(Value::ContextType::LLDBType, m_type_sp.get());
212b9c1b51eSKate Stone         else {
2133ad353f3SBruce Mitchener           value.SetCompilerType(m_compiler_type);
21457ee3067SGreg Clayton         }
21584c39663SGreg Clayton 
216d9cbd2acSAdrian Prantl         m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
21778a685aaSJim Ingham       }
21878a685aaSJim Ingham       break;
21978a685aaSJim Ingham     }
22078a685aaSJim Ingham 
22178a685aaSJim Ingham     SetValueIsValid(m_error.Success());
22278a685aaSJim Ingham   }
22378a685aaSJim Ingham   return m_error.Success();
22478a685aaSJim Ingham }
22578a685aaSJim Ingham 
IsInScope()226b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() {
22778a685aaSJim Ingham   // FIXME: Maybe try to read the memory address, and if that works, then
22878a685aaSJim Ingham   // we are in scope?
22978a685aaSJim Ingham   return true;
23078a685aaSJim Ingham }
23178a685aaSJim Ingham 
GetModule()232b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); }
233