178a685aaSJim Ingham //===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===//
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 
21672d2c12SJonas Devlieghere #include <assert.h>
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 
31b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
3222a2628fSZachary Turner                                         llvm::StringRef name,
3358b59f95SJim Ingham                                         const Address &address,
34b9c1b51eSKate Stone                                         lldb::TypeSP &type_sp) {
3558b59f95SJim Ingham   return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP();
3658b59f95SJim Ingham }
3758b59f95SJim Ingham 
38b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
3922a2628fSZachary Turner                                         llvm::StringRef name,
4084c39663SGreg Clayton                                         const Address &address,
41b9c1b51eSKate Stone                                         const CompilerType &ast_type) {
4284c39663SGreg Clayton   return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP();
4384c39663SGreg Clayton }
4484c39663SGreg Clayton 
4578a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
4622a2628fSZachary Turner                                      llvm::StringRef name,
4722a2628fSZachary Turner                                      const Address &address,
48b9c1b51eSKate Stone                                      lldb::TypeSP &type_sp)
49b9c1b51eSKate Stone     : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp),
50b9c1b51eSKate Stone       m_compiler_type() {
5178a685aaSJim Ingham   // Do not attempt to construct one of these objects with no variable!
52248a1305SKonrad Kleine   assert(m_type_sp.get() != nullptr);
536f3533fbSEnrico Granata   SetName(ConstString(name));
5478a685aaSJim Ingham   m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
55cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
56cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
57b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
5878a685aaSJim Ingham     m_value.SetValueType(Value::eValueTypeLoadAddress);
5978a685aaSJim Ingham     m_value.GetScalar() = load_address;
60b9c1b51eSKate Stone   } else {
6178a685aaSJim Ingham     lldb::addr_t file_address = m_address.GetFileAddress();
62b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
6378a685aaSJim Ingham       m_value.SetValueType(Value::eValueTypeFileAddress);
6478a685aaSJim Ingham       m_value.GetScalar() = file_address;
65b9c1b51eSKate Stone     } else {
6678a685aaSJim Ingham       m_value.GetScalar() = m_address.GetOffset();
6778a685aaSJim Ingham       m_value.SetValueType(Value::eValueTypeScalar);
6878a685aaSJim Ingham     }
6978a685aaSJim Ingham   }
7078a685aaSJim Ingham }
7178a685aaSJim Ingham 
7284c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
7322a2628fSZachary Turner                                      llvm::StringRef name,
7422a2628fSZachary Turner                                      const Address &address,
75b9c1b51eSKate Stone                                      const CompilerType &ast_type)
76b9c1b51eSKate Stone     : ValueObject(exe_scope), m_address(address), m_type_sp(),
77b9c1b51eSKate Stone       m_compiler_type(ast_type) {
7884c39663SGreg Clayton   // Do not attempt to construct one of these objects with no variable!
793ad353f3SBruce Mitchener   assert(m_compiler_type.GetTypeSystem());
803ad353f3SBruce Mitchener   assert(m_compiler_type.GetOpaqueQualType());
8184c39663SGreg Clayton 
82cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
83cc4d0146SGreg Clayton 
846f3533fbSEnrico Granata   SetName(ConstString(name));
85b9c1b51eSKate Stone   //    m_value.SetContext(Value::eContextTypeClangType,
86b9c1b51eSKate Stone   //    m_compiler_type.GetOpaqueQualType());
873ad353f3SBruce Mitchener   m_value.SetCompilerType(m_compiler_type);
88cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
89b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
9084c39663SGreg Clayton     m_value.SetValueType(Value::eValueTypeLoadAddress);
9184c39663SGreg Clayton     m_value.GetScalar() = load_address;
92b9c1b51eSKate Stone   } else {
9384c39663SGreg Clayton     lldb::addr_t file_address = m_address.GetFileAddress();
94b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
9584c39663SGreg Clayton       m_value.SetValueType(Value::eValueTypeFileAddress);
9684c39663SGreg Clayton       m_value.GetScalar() = file_address;
97b9c1b51eSKate Stone     } else {
9884c39663SGreg Clayton       m_value.GetScalar() = m_address.GetOffset();
9984c39663SGreg Clayton       m_value.SetValueType(Value::eValueTypeScalar);
10084c39663SGreg Clayton     }
10184c39663SGreg Clayton   }
10284c39663SGreg Clayton }
10384c39663SGreg Clayton 
104b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {}
10578a685aaSJim Ingham 
106b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
10784c39663SGreg Clayton   if (m_type_sp)
10899558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType();
1093ad353f3SBruce Mitchener   return m_compiler_type;
11078a685aaSJim Ingham }
11178a685aaSJim Ingham 
112b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() {
11384c39663SGreg Clayton   if (m_type_sp)
11478a685aaSJim Ingham     return m_type_sp->GetName();
1153ad353f3SBruce Mitchener   return m_compiler_type.GetConstTypeName();
11678a685aaSJim Ingham }
11778a685aaSJim Ingham 
118b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() {
119e8daa2f8SEnrico Granata   if (m_type_sp)
12099558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();
1213ad353f3SBruce Mitchener   return m_compiler_type.GetDisplayTypeName();
122e8daa2f8SEnrico Granata }
123e8daa2f8SEnrico Granata 
124b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
125b9c1b51eSKate Stone   if (m_type_sp) {
1269ac7a6c5SSiva Chandra     auto child_count = m_type_sp->GetNumChildren(true);
1279ac7a6c5SSiva Chandra     return child_count <= max ? child_count : max;
1289ac7a6c5SSiva Chandra   }
1299ac7a6c5SSiva Chandra 
130eca07c59SAdrian Prantl   ExecutionContext exe_ctx(GetExecutionContextRef());
13184c39663SGreg Clayton   const bool omit_empty_base_classes = true;
132eca07c59SAdrian Prantl   auto child_count =
133eca07c59SAdrian Prantl       m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
1349ac7a6c5SSiva Chandra   return child_count <= max ? child_count : max;
13578a685aaSJim Ingham }
13678a685aaSJim Ingham 
137b9c1b51eSKate Stone uint64_t ValueObjectMemory::GetByteSize() {
13884c39663SGreg Clayton   if (m_type_sp)
139d13777aaSAdrian Prantl     return m_type_sp->GetByteSize().getValueOr(0);
140d13777aaSAdrian Prantl   return m_compiler_type.GetByteSize(nullptr).getValueOr(0);
14178a685aaSJim Ingham }
14278a685aaSJim Ingham 
143b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const {
14478a685aaSJim Ingham   // RETHINK: Should this be inherited from somewhere?
14578a685aaSJim Ingham   return lldb::eValueTypeVariableGlobal;
14678a685aaSJim Ingham }
14778a685aaSJim Ingham 
148b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() {
14978a685aaSJim Ingham   SetValueIsValid(false);
15078a685aaSJim Ingham   m_error.Clear();
15178a685aaSJim Ingham 
152cc4d0146SGreg Clayton   ExecutionContext exe_ctx(GetExecutionContextRef());
15378a685aaSJim Ingham 
154c14ee32dSGreg Clayton   Target *target = exe_ctx.GetTargetPtr();
155b9c1b51eSKate Stone   if (target) {
156c14ee32dSGreg Clayton     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
157c14ee32dSGreg Clayton     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
15878a685aaSJim Ingham   }
15978a685aaSJim Ingham 
16078a685aaSJim Ingham   Value old_value(m_value);
161b9c1b51eSKate Stone   if (m_address.IsValid()) {
16278a685aaSJim Ingham     Value::ValueType value_type = m_value.GetValueType();
16378a685aaSJim Ingham 
164b9c1b51eSKate Stone     switch (value_type) {
16578a685aaSJim Ingham     default:
166a322f36cSDavid Blaikie       llvm_unreachable("Unhandled expression result value kind...");
16778a685aaSJim Ingham 
16878a685aaSJim Ingham     case Value::eValueTypeScalar:
16905097246SAdrian Prantl       // The variable value is in the Scalar value inside the m_value. We can
17005097246SAdrian Prantl       // point our m_data right to it.
171*d9cbd2acSAdrian Prantl       m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
17278a685aaSJim Ingham       break;
17378a685aaSJim Ingham 
17478a685aaSJim Ingham     case Value::eValueTypeFileAddress:
17578a685aaSJim Ingham     case Value::eValueTypeLoadAddress:
17678a685aaSJim Ingham     case Value::eValueTypeHostAddress:
17705097246SAdrian Prantl       // The DWARF expression result was an address in the inferior process. If
17805097246SAdrian Prantl       // this variable is an aggregate type, we just need the address as the
17905097246SAdrian Prantl       // main value as all child variable objects will rely upon this location
18005097246SAdrian Prantl       // and add an offset and then read their own values as needed. If this
18105097246SAdrian Prantl       // variable is a simple type, we read all data for it into m_data. Make
18205097246SAdrian Prantl       // sure this type has a value before we try and read it
18378a685aaSJim Ingham 
18478a685aaSJim Ingham       // If we have a file address, convert it to a load address if we can.
185b9c1b51eSKate Stone       if (value_type == Value::eValueTypeFileAddress &&
186b9c1b51eSKate Stone           exe_ctx.GetProcessPtr()) {
187c14ee32dSGreg Clayton         lldb::addr_t load_addr = m_address.GetLoadAddress(target);
188b9c1b51eSKate Stone         if (load_addr != LLDB_INVALID_ADDRESS) {
18978a685aaSJim Ingham           m_value.SetValueType(Value::eValueTypeLoadAddress);
19078a685aaSJim Ingham           m_value.GetScalar() = load_addr;
19178a685aaSJim Ingham         }
19278a685aaSJim Ingham       }
19378a685aaSJim Ingham 
194b9c1b51eSKate Stone       if (!CanProvideValue()) {
19505097246SAdrian Prantl         // this value object represents an aggregate type whose children have
19605097246SAdrian Prantl         // values, but this object does not. So we say we are changed if our
19705097246SAdrian Prantl         // location has changed.
198b9c1b51eSKate Stone         SetValueDidChange(value_type != old_value.GetValueType() ||
199b9c1b51eSKate Stone                           m_value.GetScalar() != old_value.GetScalar());
200b9c1b51eSKate Stone       } else {
20105097246SAdrian Prantl         // Copy the Value and set the context to use our Variable so it can
20205097246SAdrian Prantl         // extract read its value into m_data appropriately
20378a685aaSJim Ingham         Value value(m_value);
20484c39663SGreg Clayton         if (m_type_sp)
20578a685aaSJim Ingham           value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
206b9c1b51eSKate Stone         else {
207b9c1b51eSKate Stone           // value.SetContext(Value::eContextTypeClangType,
208b9c1b51eSKate Stone           // m_compiler_type.GetOpaqueQualType());
2093ad353f3SBruce Mitchener           value.SetCompilerType(m_compiler_type);
21057ee3067SGreg Clayton         }
21184c39663SGreg Clayton 
212*d9cbd2acSAdrian Prantl         m_error = value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
21378a685aaSJim Ingham       }
21478a685aaSJim Ingham       break;
21578a685aaSJim Ingham     }
21678a685aaSJim Ingham 
21778a685aaSJim Ingham     SetValueIsValid(m_error.Success());
21878a685aaSJim Ingham   }
21978a685aaSJim Ingham   return m_error.Success();
22078a685aaSJim Ingham }
22178a685aaSJim Ingham 
222b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() {
22378a685aaSJim Ingham   // FIXME: Maybe try to read the memory address, and if that works, then
22478a685aaSJim Ingham   // we are in scope?
22578a685aaSJim Ingham   return true;
22678a685aaSJim Ingham }
22778a685aaSJim Ingham 
228b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); }
229