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