1 //===-- ValueObjectVariable.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 
11 #include "lldb/Core/ValueObjectVariable.h"
12 
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/ValueObjectList.h"
19 #include "lldb/Core/Value.h"
20 
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Symbol/SymbolContext.h"
23 #include "lldb/Symbol/SymbolContextScope.h"
24 #include "lldb/Symbol/Type.h"
25 #include "lldb/Symbol/Variable.h"
26 
27 #include "lldb/Target/ExecutionContext.h"
28 #include "lldb/Target/Process.h"
29 #include "lldb/Target/RegisterContext.h"
30 #include "lldb/Target/Target.h"
31 #include "lldb/Target/Thread.h"
32 
33 
34 using namespace lldb_private;
35 
36 lldb::ValueObjectSP
37 ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
38 {
39     return (new ValueObjectVariable (exe_scope, var_sp))->GetSP();
40 }
41 
42 ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) :
43     ValueObject(exe_scope),
44     m_variable_sp(var_sp)
45 {
46     // Do not attempt to construct one of these objects with no variable!
47     assert (m_variable_sp.get() != NULL);
48     m_name = var_sp->GetName();
49 }
50 
51 ValueObjectVariable::~ValueObjectVariable()
52 {
53 }
54 
55 lldb::clang_type_t
56 ValueObjectVariable::GetClangType ()
57 {
58     Type *var_type = m_variable_sp->GetType();
59     if (var_type)
60         return var_type->GetClangForwardType();
61     return NULL;
62 }
63 
64 ConstString
65 ValueObjectVariable::GetTypeName()
66 {
67     Type * var_type = m_variable_sp->GetType();
68     if (var_type)
69         return var_type->GetName();
70     ConstString empty_type_name;
71     return empty_type_name;
72 }
73 
74 uint32_t
75 ValueObjectVariable::CalculateNumChildren()
76 {
77     Type *var_type = m_variable_sp->GetType();
78     if (var_type)
79         return var_type->GetNumChildren(true);
80     return 0;
81 }
82 
83 clang::ASTContext *
84 ValueObjectVariable::GetClangAST ()
85 {
86     Type *var_type = m_variable_sp->GetType();
87     if (var_type)
88         return var_type->GetClangAST();
89     return 0;
90 }
91 
92 size_t
93 ValueObjectVariable::GetByteSize()
94 {
95     Type *type = m_variable_sp->GetType();
96     if (type)
97         return type->GetByteSize();
98     return 0;
99 }
100 
101 lldb::ValueType
102 ValueObjectVariable::GetValueType() const
103 {
104     if (m_variable_sp)
105         return m_variable_sp->GetScope();
106     return lldb::eValueTypeInvalid;
107 }
108 
109 bool
110 ValueObjectVariable::UpdateValue ()
111 {
112     SetValueIsValid (false);
113     m_error.Clear();
114 
115     Variable *variable = m_variable_sp.get();
116     DWARFExpression &expr = variable->LocationExpression();
117 
118     if (variable->GetLocationIsConstantValueData())
119     {
120         // expr doesn't contain DWARF bytes, it contains the constant variable
121         // value bytes themselves...
122         if (expr.GetExpressionData(m_data))
123             m_value.SetContext(Value::eContextTypeVariable, variable);
124         else
125             m_error.SetErrorString ("empty constant data");
126     }
127     else
128     {
129         lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
130         ExecutionContext exe_ctx (GetExecutionContextScope());
131 
132         Target *target = exe_ctx.GetTargetPtr();
133         if (target)
134         {
135             m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136             m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
137         }
138 
139         if (expr.IsLocationList())
140         {
141             SymbolContext sc;
142             variable->CalculateSymbolContext (&sc);
143             if (sc.function)
144                 loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
145         }
146         Value old_value(m_value);
147         if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
148         {
149             m_value.SetContext(Value::eContextTypeVariable, variable);
150 
151             Value::ValueType value_type = m_value.GetValueType();
152 
153             switch (value_type)
154             {
155                 case Value::eValueTypeFileAddress:
156                     SetAddressTypeOfChildren(eAddressTypeFile);
157                     break;
158                 case Value::eValueTypeHostAddress:
159                     SetAddressTypeOfChildren(eAddressTypeHost);
160                     break;
161                 case Value::eValueTypeLoadAddress:
162                 case Value::eValueTypeScalar:
163                     SetAddressTypeOfChildren(eAddressTypeLoad);
164                     break;
165             }
166 
167             switch (value_type)
168             {
169             default:
170                 assert(!"Unhandled expression result value kind...");
171                 break;
172 
173             case Value::eValueTypeScalar:
174                 // The variable value is in the Scalar value inside the m_value.
175                 // We can point our m_data right to it.
176                 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule());
177                 break;
178 
179             case Value::eValueTypeFileAddress:
180             case Value::eValueTypeLoadAddress:
181             case Value::eValueTypeHostAddress:
182                 // The DWARF expression result was an address in the inferior
183                 // process. If this variable is an aggregate type, we just need
184                 // the address as the main value as all child variable objects
185                 // will rely upon this location and add an offset and then read
186                 // their own values as needed. If this variable is a simple
187                 // type, we read all data for it into m_data.
188                 // Make sure this type has a value before we try and read it
189 
190                 // If we have a file address, convert it to a load address if we can.
191                 Process *process = exe_ctx.GetProcessPtr();
192                 if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
193                 {
194                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
195                     if (file_addr != LLDB_INVALID_ADDRESS)
196                     {
197                         SymbolContext var_sc;
198                         variable->CalculateSymbolContext(&var_sc);
199                         if (var_sc.module_sp)
200                         {
201                             ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
202                             if (objfile)
203                             {
204                                 Address so_addr(file_addr, objfile->GetSectionList());
205                                 lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
206                                 if (load_addr != LLDB_INVALID_ADDRESS)
207                                 {
208                                     m_value.SetValueType(Value::eValueTypeLoadAddress);
209                                     m_value.GetScalar() = load_addr;
210                                 }
211                             }
212                         }
213                     }
214                 }
215 
216                 if (ClangASTContext::IsAggregateType (GetClangType()))
217                 {
218                     // this value object represents an aggregate type whose
219                     // children have values, but this object does not. So we
220                     // say we are changed if our location has changed.
221                     SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
222                 }
223                 else
224                 {
225                     // Copy the Value and set the context to use our Variable
226                     // so it can extract read its value into m_data appropriately
227                     Value value(m_value);
228                     value.SetContext(Value::eContextTypeVariable, variable);
229                     m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule());
230                 }
231                 break;
232             }
233 
234             SetValueIsValid (m_error.Success());
235         }
236     }
237     return m_error.Success();
238 }
239 
240 
241 
242 bool
243 ValueObjectVariable::IsInScope ()
244 {
245     ExecutionContextScope *exe_scope = GetExecutionContextScope();
246     if (!exe_scope)
247         return true;
248 
249     StackFrame *frame = exe_scope->CalculateStackFrame();
250     if (!frame)
251         return true;
252 
253     return m_variable_sp->IsInScope (frame);
254 }
255 
256 Module *
257 ValueObjectVariable::GetModule()
258 {
259     if (m_variable_sp)
260     {
261         SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
262         if (sc_scope)
263         {
264             SymbolContext sc;
265             sc_scope->CalculateSymbolContext (&sc);
266             return sc.module_sp.get();
267         }
268     }
269     return NULL;
270 }
271 
272 SymbolContextScope *
273 ValueObjectVariable::GetSymbolContextScope()
274 {
275     if (m_variable_sp)
276         return m_variable_sp->GetSymbolContextScope();
277     return NULL;
278 }
279