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