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 size_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 uint64_t
106 ValueObjectVariable::GetByteSize()
107 {
108     ClangASTType type(GetClangAST(), GetClangType());
109 
110     if (!type.IsValid())
111         return 0;
112 
113     return type.GetClangTypeByteSize();
114 }
115 
116 lldb::ValueType
117 ValueObjectVariable::GetValueType() const
118 {
119     if (m_variable_sp)
120         return m_variable_sp->GetScope();
121     return lldb::eValueTypeInvalid;
122 }
123 
124 bool
125 ValueObjectVariable::UpdateValue ()
126 {
127     SetValueIsValid (false);
128     m_error.Clear();
129 
130     Variable *variable = m_variable_sp.get();
131     DWARFExpression &expr = variable->LocationExpression();
132 
133     if (variable->GetLocationIsConstantValueData())
134     {
135         // expr doesn't contain DWARF bytes, it contains the constant variable
136         // value bytes themselves...
137         if (expr.GetExpressionData(m_data))
138             m_value.SetContext(Value::eContextTypeVariable, variable);
139         else
140             m_error.SetErrorString ("empty constant data");
141     }
142     else
143     {
144         lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
145         ExecutionContext exe_ctx (GetExecutionContextRef());
146 
147         Target *target = exe_ctx.GetTargetPtr();
148         if (target)
149         {
150             m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
151             m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
152         }
153 
154         if (expr.IsLocationList())
155         {
156             SymbolContext sc;
157             variable->CalculateSymbolContext (&sc);
158             if (sc.function)
159                 loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target);
160         }
161         Value old_value(m_value);
162         if (expr.Evaluate (&exe_ctx, GetClangAST(), NULL, NULL, NULL, loclist_base_load_addr, NULL, m_value, &m_error))
163         {
164             m_value.SetContext(Value::eContextTypeVariable, variable);
165 
166             Value::ValueType value_type = m_value.GetValueType();
167 
168             switch (value_type)
169             {
170                 case Value::eValueTypeFileAddress:
171                     SetAddressTypeOfChildren(eAddressTypeFile);
172                     break;
173                 case Value::eValueTypeHostAddress:
174                     SetAddressTypeOfChildren(eAddressTypeHost);
175                     break;
176                 case Value::eValueTypeLoadAddress:
177                 case Value::eValueTypeScalar:
178                 case Value::eValueTypeVector:
179                     SetAddressTypeOfChildren(eAddressTypeLoad);
180                     break;
181             }
182 
183             switch (value_type)
184             {
185             default:
186                 assert(!"Unhandled expression result value kind...");
187                 break;
188 
189             case Value::eValueTypeScalar:
190                 // The variable value is in the Scalar value inside the m_value.
191                 // We can point our m_data right to it.
192                 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
193                 break;
194 
195             case Value::eValueTypeFileAddress:
196             case Value::eValueTypeLoadAddress:
197             case Value::eValueTypeHostAddress:
198                 // The DWARF expression result was an address in the inferior
199                 // process. If this variable is an aggregate type, we just need
200                 // the address as the main value as all child variable objects
201                 // will rely upon this location and add an offset and then read
202                 // their own values as needed. If this variable is a simple
203                 // type, we read all data for it into m_data.
204                 // Make sure this type has a value before we try and read it
205 
206                 // If we have a file address, convert it to a load address if we can.
207                 Process *process = exe_ctx.GetProcessPtr();
208                 if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
209                 {
210                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
211                     if (file_addr != LLDB_INVALID_ADDRESS)
212                     {
213                         SymbolContext var_sc;
214                         variable->CalculateSymbolContext(&var_sc);
215                         if (var_sc.module_sp)
216                         {
217                             ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
218                             if (objfile)
219                             {
220                                 Address so_addr(file_addr, objfile->GetSectionList());
221                                 lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
222                                 if (load_addr != LLDB_INVALID_ADDRESS)
223                                 {
224                                     m_value.SetValueType(Value::eValueTypeLoadAddress);
225                                     m_value.GetScalar() = load_addr;
226                                 }
227                             }
228                         }
229                     }
230                 }
231 
232                 if (ClangASTContext::IsAggregateType (GetClangType()))
233                 {
234                     // this value object represents an aggregate type whose
235                     // children have values, but this object does not. So we
236                     // say we are changed if our location has changed.
237                     SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
238                 }
239                 else
240                 {
241                     // Copy the Value and set the context to use our Variable
242                     // so it can extract read its value into m_data appropriately
243                     Value value(m_value);
244                     value.SetContext(Value::eContextTypeVariable, variable);
245                     m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
246                 }
247                 break;
248             }
249 
250             SetValueIsValid (m_error.Success());
251         }
252     }
253     return m_error.Success();
254 }
255 
256 
257 
258 bool
259 ValueObjectVariable::IsInScope ()
260 {
261     const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
262     if (exe_ctx_ref.HasFrameRef())
263     {
264         ExecutionContext exe_ctx (exe_ctx_ref);
265         StackFrame *frame = exe_ctx.GetFramePtr();
266         if (frame)
267         {
268             return m_variable_sp->IsInScope (frame);
269         }
270         else
271         {
272             // This ValueObject had a frame at one time, but now we
273             // can't locate it, so return false since we probably aren't
274             // in scope.
275             return false;
276         }
277     }
278     // We have a variable that wasn't tied to a frame, which
279     // means it is a global and is always in scope.
280     return true;
281 
282 }
283 
284 lldb::ModuleSP
285 ValueObjectVariable::GetModule()
286 {
287     if (m_variable_sp)
288     {
289         SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
290         if (sc_scope)
291         {
292             return sc_scope->CalculateSymbolContextModule();
293         }
294     }
295     return lldb::ModuleSP();
296 }
297 
298 SymbolContextScope *
299 ValueObjectVariable::GetSymbolContextScope()
300 {
301     if (m_variable_sp)
302         return m_variable_sp->GetSymbolContextScope();
303     return NULL;
304 }
305 
306 bool
307 ValueObjectVariable::GetDeclaration (Declaration &decl)
308 {
309     if (m_variable_sp)
310     {
311         decl = m_variable_sp->GetDeclaration();
312         return true;
313     }
314     return false;
315 }
316