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 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/Module.h"
17 #include "lldb/Core/Value.h"
18 #include "lldb/Core/ValueObject.h"
19 #include "lldb/Core/ValueObjectList.h"
20 
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Symbol/SymbolContext.h"
23 #include "lldb/Symbol/Type.h"
24 #include "lldb/Symbol/Variable.h"
25 
26 #include "lldb/Target/ExecutionContext.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/RegisterContext.h"
29 #include "lldb/Target/Target.h"
30 #include "lldb/Target/Thread.h"
31 
32 using namespace lldb;
33 using namespace lldb_private;
34 
35 ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
36                                         const char *name,
37                                         const Address &address,
38                                         lldb::TypeSP &type_sp) {
39   return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP();
40 }
41 
42 ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope,
43                                         const char *name,
44                                         const Address &address,
45                                         const CompilerType &ast_type) {
46   return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP();
47 }
48 
49 ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope,
50                                      const char *name, 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                                      const char *name, const Address &address,
77                                      const CompilerType &ast_type)
78     : ValueObject(exe_scope), m_address(address), m_type_sp(),
79       m_compiler_type(ast_type) {
80   // Do not attempt to construct one of these objects with no variable!
81   assert(m_compiler_type.GetTypeSystem());
82   assert(m_compiler_type.GetOpaqueQualType());
83 
84   TargetSP target_sp(GetTargetSP());
85 
86   SetName(ConstString(name));
87   //    m_value.SetContext(Value::eContextTypeClangType,
88   //    m_compiler_type.GetOpaqueQualType());
89   m_value.SetCompilerType(m_compiler_type);
90   lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
91   if (load_address != LLDB_INVALID_ADDRESS) {
92     m_value.SetValueType(Value::eValueTypeLoadAddress);
93     m_value.GetScalar() = load_address;
94   } else {
95     lldb::addr_t file_address = m_address.GetFileAddress();
96     if (file_address != LLDB_INVALID_ADDRESS) {
97       m_value.SetValueType(Value::eValueTypeFileAddress);
98       m_value.GetScalar() = file_address;
99     } else {
100       m_value.GetScalar() = m_address.GetOffset();
101       m_value.SetValueType(Value::eValueTypeScalar);
102     }
103   }
104 }
105 
106 ValueObjectMemory::~ValueObjectMemory() {}
107 
108 CompilerType ValueObjectMemory::GetCompilerTypeImpl() {
109   if (m_type_sp)
110     return m_type_sp->GetForwardCompilerType();
111   return m_compiler_type;
112 }
113 
114 ConstString ValueObjectMemory::GetTypeName() {
115   if (m_type_sp)
116     return m_type_sp->GetName();
117   return m_compiler_type.GetConstTypeName();
118 }
119 
120 ConstString ValueObjectMemory::GetDisplayTypeName() {
121   if (m_type_sp)
122     return m_type_sp->GetForwardCompilerType().GetDisplayTypeName();
123   return m_compiler_type.GetDisplayTypeName();
124 }
125 
126 size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
127   if (m_type_sp) {
128     auto child_count = m_type_sp->GetNumChildren(true);
129     return child_count <= max ? child_count : max;
130   }
131 
132   const bool omit_empty_base_classes = true;
133   auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes);
134   return child_count <= max ? child_count : max;
135 }
136 
137 uint64_t ValueObjectMemory::GetByteSize() {
138   if (m_type_sp)
139     return m_type_sp->GetByteSize();
140   return m_compiler_type.GetByteSize(nullptr);
141 }
142 
143 lldb::ValueType ValueObjectMemory::GetValueType() const {
144   // RETHINK: Should this be inherited from somewhere?
145   return lldb::eValueTypeVariableGlobal;
146 }
147 
148 bool 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       assert(!"Unhandled expression result value kind...");
167       break;
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