178a685aaSJim Ingham //===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===//
278a685aaSJim Ingham //
378a685aaSJim Ingham //                     The LLVM Compiler Infrastructure
478a685aaSJim Ingham //
578a685aaSJim Ingham // This file is distributed under the University of Illinois Open Source
678a685aaSJim Ingham // License. See LICENSE.TXT for details.
778a685aaSJim Ingham //
878a685aaSJim Ingham //===----------------------------------------------------------------------===//
978a685aaSJim Ingham 
1078a685aaSJim Ingham #include "lldb/Core/ValueObjectMemory.h"
1178a685aaSJim Ingham 
12*2f3df613SZachary Turner #include "lldb/Core/ArchSpec.h" // for ArchSpec
13*2f3df613SZachary Turner #include "lldb/Core/Scalar.h"   // for Scalar, operator!=
1478a685aaSJim Ingham #include "lldb/Core/Value.h"
1578a685aaSJim Ingham #include "lldb/Core/ValueObject.h"
1678a685aaSJim Ingham #include "lldb/Symbol/Type.h"
1778a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h"
1878a685aaSJim Ingham #include "lldb/Target/Target.h"
19*2f3df613SZachary Turner #include "lldb/Utility/DataExtractor.h" // for DataExtractor
20*2f3df613SZachary Turner #include "lldb/Utility/Error.h"         // for Error
21*2f3df613SZachary Turner #include "lldb/lldb-types.h"            // for addr_t
22*2f3df613SZachary Turner #include "llvm/Support/ErrorHandling.h" // for llvm_unreachable
23*2f3df613SZachary Turner 
24*2f3df613SZachary Turner #include <assert.h> // for assert
25*2f3df613SZachary Turner #include <memory>   // for shared_ptr
26*2f3df613SZachary Turner 
27*2f3df613SZachary Turner namespace lldb_private {
28*2f3df613SZachary Turner class ExecutionContextScope;
29*2f3df613SZachary Turner }
3078a685aaSJim Ingham 
3158b59f95SJim Ingham using namespace lldb;
3278a685aaSJim Ingham using namespace lldb_private;
3378a685aaSJim Ingham 
34b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
3522a2628fSZachary Turner                                         llvm::StringRef name,
3658b59f95SJim Ingham                                         const Address &address,
37b9c1b51eSKate Stone                                         lldb::TypeSP &type_sp) {
3858b59f95SJim Ingham   return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP();
3958b59f95SJim Ingham }
4058b59f95SJim Ingham 
41b9c1b51eSKate Stone ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
4222a2628fSZachary Turner                                         llvm::StringRef name,
4384c39663SGreg Clayton                                         const Address &address,
44b9c1b51eSKate Stone                                         const CompilerType &ast_type) {
4584c39663SGreg Clayton   return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP();
4684c39663SGreg Clayton }
4784c39663SGreg Clayton 
4878a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
4922a2628fSZachary Turner                                      llvm::StringRef name,
5022a2628fSZachary Turner                                      const Address &address,
51b9c1b51eSKate Stone                                      lldb::TypeSP &type_sp)
52b9c1b51eSKate Stone     : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp),
53b9c1b51eSKate Stone       m_compiler_type() {
5478a685aaSJim Ingham   // Do not attempt to construct one of these objects with no variable!
5578a685aaSJim Ingham   assert(m_type_sp.get() != NULL);
566f3533fbSEnrico Granata   SetName(ConstString(name));
5778a685aaSJim Ingham   m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
58cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
59cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
60b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
6178a685aaSJim Ingham     m_value.SetValueType(Value::eValueTypeLoadAddress);
6278a685aaSJim Ingham     m_value.GetScalar() = load_address;
63b9c1b51eSKate Stone   } else {
6478a685aaSJim Ingham     lldb::addr_t file_address = m_address.GetFileAddress();
65b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
6678a685aaSJim Ingham       m_value.SetValueType(Value::eValueTypeFileAddress);
6778a685aaSJim Ingham       m_value.GetScalar() = file_address;
68b9c1b51eSKate Stone     } else {
6978a685aaSJim Ingham       m_value.GetScalar() = m_address.GetOffset();
7078a685aaSJim Ingham       m_value.SetValueType(Value::eValueTypeScalar);
7178a685aaSJim Ingham     }
7278a685aaSJim Ingham   }
7378a685aaSJim Ingham }
7478a685aaSJim Ingham 
7584c39663SGreg Clayton ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
7622a2628fSZachary Turner                                      llvm::StringRef name,
7722a2628fSZachary Turner                                      const Address &address,
78b9c1b51eSKate Stone                                      const CompilerType &ast_type)
79b9c1b51eSKate Stone     : ValueObject(exe_scope), m_address(address), m_type_sp(),
80b9c1b51eSKate Stone       m_compiler_type(ast_type) {
8184c39663SGreg Clayton   // Do not attempt to construct one of these objects with no variable!
823ad353f3SBruce Mitchener   assert(m_compiler_type.GetTypeSystem());
833ad353f3SBruce Mitchener   assert(m_compiler_type.GetOpaqueQualType());
8484c39663SGreg Clayton 
85cc4d0146SGreg Clayton   TargetSP target_sp(GetTargetSP());
86cc4d0146SGreg Clayton 
876f3533fbSEnrico Granata   SetName(ConstString(name));
88b9c1b51eSKate Stone   //    m_value.SetContext(Value::eContextTypeClangType,
89b9c1b51eSKate Stone   //    m_compiler_type.GetOpaqueQualType());
903ad353f3SBruce Mitchener   m_value.SetCompilerType(m_compiler_type);
91cc4d0146SGreg Clayton   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
92b9c1b51eSKate Stone   if (load_address != LLDB_INVALID_ADDRESS) {
9384c39663SGreg Clayton     m_value.SetValueType(Value::eValueTypeLoadAddress);
9484c39663SGreg Clayton     m_value.GetScalar() = load_address;
95b9c1b51eSKate Stone   } else {
9684c39663SGreg Clayton     lldb::addr_t file_address = m_address.GetFileAddress();
97b9c1b51eSKate Stone     if (file_address != LLDB_INVALID_ADDRESS) {
9884c39663SGreg Clayton       m_value.SetValueType(Value::eValueTypeFileAddress);
9984c39663SGreg Clayton       m_value.GetScalar() = file_address;
100b9c1b51eSKate Stone     } else {
10184c39663SGreg Clayton       m_value.GetScalar() = m_address.GetOffset();
10284c39663SGreg Clayton       m_value.SetValueType(Value::eValueTypeScalar);
10384c39663SGreg Clayton     }
10484c39663SGreg Clayton   }
10584c39663SGreg Clayton }
10684c39663SGreg Clayton 
107b9c1b51eSKate Stone ValueObjectMemory::~ValueObjectMemory() {}
10878a685aaSJim Ingham 
109b9c1b51eSKate Stone CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
11084c39663SGreg Clayton   if (m_type_sp)
11199558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType();
1123ad353f3SBruce Mitchener   return m_compiler_type;
11378a685aaSJim Ingham }
11478a685aaSJim Ingham 
115b9c1b51eSKate Stone ConstString ValueObjectMemory::GetTypeName() {
11684c39663SGreg Clayton   if (m_type_sp)
11778a685aaSJim Ingham     return m_type_sp->GetName();
1183ad353f3SBruce Mitchener   return m_compiler_type.GetConstTypeName();
11978a685aaSJim Ingham }
12078a685aaSJim Ingham 
121b9c1b51eSKate Stone ConstString ValueObjectMemory::GetDisplayTypeName() {
122e8daa2f8SEnrico Granata   if (m_type_sp)
12399558cc4SGreg Clayton     return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();
1243ad353f3SBruce Mitchener   return m_compiler_type.GetDisplayTypeName();
125e8daa2f8SEnrico Granata }
126e8daa2f8SEnrico Granata 
127b9c1b51eSKate Stone size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
128b9c1b51eSKate Stone   if (m_type_sp) {
1299ac7a6c5SSiva Chandra     auto child_count = m_type_sp->GetNumChildren(true);
1309ac7a6c5SSiva Chandra     return child_count <= max ? child_count : max;
1319ac7a6c5SSiva Chandra   }
1329ac7a6c5SSiva Chandra 
13384c39663SGreg Clayton   const bool omit_empty_base_classes = true;
1349ac7a6c5SSiva Chandra   auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes);
1359ac7a6c5SSiva Chandra   return child_count <= max ? child_count : max;
13678a685aaSJim Ingham }
13778a685aaSJim Ingham 
138b9c1b51eSKate Stone uint64_t ValueObjectMemory::GetByteSize() {
13984c39663SGreg Clayton   if (m_type_sp)
14078a685aaSJim Ingham     return m_type_sp->GetByteSize();
1413ad353f3SBruce Mitchener   return m_compiler_type.GetByteSize(nullptr);
14278a685aaSJim Ingham }
14378a685aaSJim Ingham 
144b9c1b51eSKate Stone lldb::ValueType ValueObjectMemory::GetValueType() const {
14578a685aaSJim Ingham   // RETHINK: Should this be inherited from somewhere?
14678a685aaSJim Ingham   return lldb::eValueTypeVariableGlobal;
14778a685aaSJim Ingham }
14878a685aaSJim Ingham 
149b9c1b51eSKate Stone bool ValueObjectMemory::UpdateValue() {
15078a685aaSJim Ingham   SetValueIsValid(false);
15178a685aaSJim Ingham   m_error.Clear();
15278a685aaSJim Ingham 
153cc4d0146SGreg Clayton   ExecutionContext exe_ctx(GetExecutionContextRef());
15478a685aaSJim Ingham 
155c14ee32dSGreg Clayton   Target *target = exe_ctx.GetTargetPtr();
156b9c1b51eSKate Stone   if (target) {
157c14ee32dSGreg Clayton     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
158c14ee32dSGreg Clayton     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
15978a685aaSJim Ingham   }
16078a685aaSJim Ingham 
16178a685aaSJim Ingham   Value old_value(m_value);
162b9c1b51eSKate Stone   if (m_address.IsValid()) {
16378a685aaSJim Ingham     Value::ValueType value_type = m_value.GetValueType();
16478a685aaSJim Ingham 
165b9c1b51eSKate Stone     switch (value_type) {
16678a685aaSJim Ingham     default:
167a322f36cSDavid Blaikie       llvm_unreachable("Unhandled expression result value kind...");
16878a685aaSJim Ingham 
16978a685aaSJim Ingham     case Value::eValueTypeScalar:
17078a685aaSJim Ingham       // The variable value is in the Scalar value inside the m_value.
17178a685aaSJim Ingham       // We can point our m_data right to it.
17257ee3067SGreg Clayton       m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
17378a685aaSJim Ingham       break;
17478a685aaSJim Ingham 
17578a685aaSJim Ingham     case Value::eValueTypeFileAddress:
17678a685aaSJim Ingham     case Value::eValueTypeLoadAddress:
17778a685aaSJim Ingham     case Value::eValueTypeHostAddress:
17878a685aaSJim Ingham       // The DWARF expression result was an address in the inferior
17978a685aaSJim Ingham       // process. If this variable is an aggregate type, we just need
18078a685aaSJim Ingham       // the address as the main value as all child variable objects
18178a685aaSJim Ingham       // will rely upon this location and add an offset and then read
18278a685aaSJim Ingham       // their own values as needed. If this variable is a simple
18378a685aaSJim Ingham       // type, we read all data for it into m_data.
18478a685aaSJim Ingham       // Make sure this type has a value before we try and read it
18578a685aaSJim Ingham 
18678a685aaSJim Ingham       // If we have a file address, convert it to a load address if we can.
187b9c1b51eSKate Stone       if (value_type == Value::eValueTypeFileAddress &&
188b9c1b51eSKate Stone           exe_ctx.GetProcessPtr()) {
189c14ee32dSGreg Clayton         lldb::addr_t load_addr = m_address.GetLoadAddress(target);
190b9c1b51eSKate Stone         if (load_addr != LLDB_INVALID_ADDRESS) {
19178a685aaSJim Ingham           m_value.SetValueType(Value::eValueTypeLoadAddress);
19278a685aaSJim Ingham           m_value.GetScalar() = load_addr;
19378a685aaSJim Ingham         }
19478a685aaSJim Ingham       }
19578a685aaSJim Ingham 
196b9c1b51eSKate Stone       if (!CanProvideValue()) {
19778a685aaSJim Ingham         // this value object represents an aggregate type whose
19878a685aaSJim Ingham         // children have values, but this object does not. So we
19978a685aaSJim Ingham         // say we are changed if our location has changed.
200b9c1b51eSKate Stone         SetValueDidChange(value_type != old_value.GetValueType() ||
201b9c1b51eSKate Stone                           m_value.GetScalar() != old_value.GetScalar());
202b9c1b51eSKate Stone       } else {
20378a685aaSJim Ingham         // Copy the Value and set the context to use our Variable
20478a685aaSJim Ingham         // so it can extract read its value into m_data appropriately
20578a685aaSJim Ingham         Value value(m_value);
20684c39663SGreg Clayton         if (m_type_sp)
20778a685aaSJim Ingham           value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
208b9c1b51eSKate Stone         else {
209b9c1b51eSKate Stone           // value.SetContext(Value::eContextTypeClangType,
210b9c1b51eSKate Stone           // m_compiler_type.GetOpaqueQualType());
2113ad353f3SBruce Mitchener           value.SetCompilerType(m_compiler_type);
21257ee3067SGreg Clayton         }
21384c39663SGreg Clayton 
21457ee3067SGreg Clayton         m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
21578a685aaSJim Ingham       }
21678a685aaSJim Ingham       break;
21778a685aaSJim Ingham     }
21878a685aaSJim Ingham 
21978a685aaSJim Ingham     SetValueIsValid(m_error.Success());
22078a685aaSJim Ingham   }
22178a685aaSJim Ingham   return m_error.Success();
22278a685aaSJim Ingham }
22378a685aaSJim Ingham 
224b9c1b51eSKate Stone bool ValueObjectMemory::IsInScope() {
22578a685aaSJim Ingham   // FIXME: Maybe try to read the memory address, and if that works, then
22678a685aaSJim Ingham   // we are in scope?
22778a685aaSJim Ingham   return true;
22878a685aaSJim Ingham }
22978a685aaSJim Ingham 
230b9c1b51eSKate Stone lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); }
231