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::GetClangTypeImpl ()
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     return ConstString();
71 }
72 
73 ConstString
74 ValueObjectVariable::GetQualifiedTypeName()
75 {
76     Type * var_type = m_variable_sp->GetType();
77     if (var_type)
78         return var_type->GetQualifiedName();
79     return ConstString();
80 }
81 
82 uint32_t
83 ValueObjectVariable::CalculateNumChildren()
84 {
85     ClangASTType type(GetClangAST(),
86                       GetClangType());
87 
88     if (!type.IsValid())
89         return 0;
90 
91     const bool omit_empty_base_classes = true;
92     return ClangASTContext::GetNumChildren(type.GetASTContext(), type.GetOpaqueQualType(), omit_empty_base_classes);
93 }
94 
95 clang::ASTContext *
96 ValueObjectVariable::GetClangASTImpl ()
97 {
98     Type *var_type = m_variable_sp->GetType();
99     if (var_type)
100         return var_type->GetClangAST();
101     return 0;
102 }
103 
104 size_t
105 ValueObjectVariable::GetByteSize()
106 {
107     ClangASTType type(GetClangAST(),
108                       GetClangType());
109 
110     if (!type.IsValid())
111         return 0;
112 
113     return (ClangASTType::GetClangTypeBitWidth(type.GetASTContext(), type.GetOpaqueQualType()) + 7) / 8;
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                     SetAddressTypeOfChildren(eAddressTypeLoad);
179                     break;
180             }
181 
182             switch (value_type)
183             {
184             default:
185                 assert(!"Unhandled expression result value kind...");
186                 break;
187 
188             case Value::eValueTypeScalar:
189                 // The variable value is in the Scalar value inside the m_value.
190                 // We can point our m_data right to it.
191                 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
192                 break;
193 
194             case Value::eValueTypeFileAddress:
195             case Value::eValueTypeLoadAddress:
196             case Value::eValueTypeHostAddress:
197                 // The DWARF expression result was an address in the inferior
198                 // process. If this variable is an aggregate type, we just need
199                 // the address as the main value as all child variable objects
200                 // will rely upon this location and add an offset and then read
201                 // their own values as needed. If this variable is a simple
202                 // type, we read all data for it into m_data.
203                 // Make sure this type has a value before we try and read it
204 
205                 // If we have a file address, convert it to a load address if we can.
206                 Process *process = exe_ctx.GetProcessPtr();
207                 if (value_type == Value::eValueTypeFileAddress && process && process->IsAlive())
208                 {
209                     lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
210                     if (file_addr != LLDB_INVALID_ADDRESS)
211                     {
212                         SymbolContext var_sc;
213                         variable->CalculateSymbolContext(&var_sc);
214                         if (var_sc.module_sp)
215                         {
216                             ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
217                             if (objfile)
218                             {
219                                 Address so_addr(file_addr, objfile->GetSectionList());
220                                 lldb::addr_t load_addr = so_addr.GetLoadAddress (target);
221                                 if (load_addr != LLDB_INVALID_ADDRESS)
222                                 {
223                                     m_value.SetValueType(Value::eValueTypeLoadAddress);
224                                     m_value.GetScalar() = load_addr;
225                                 }
226                             }
227                         }
228                     }
229                 }
230 
231                 if (ClangASTContext::IsAggregateType (GetClangType()))
232                 {
233                     // this value object represents an aggregate type whose
234                     // children have values, but this object does not. So we
235                     // say we are changed if our location has changed.
236                     SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
237                 }
238                 else
239                 {
240                     // Copy the Value and set the context to use our Variable
241                     // so it can extract read its value into m_data appropriately
242                     Value value(m_value);
243                     value.SetContext(Value::eContextTypeVariable, variable);
244                     m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
245                 }
246                 break;
247             }
248 
249             SetValueIsValid (m_error.Success());
250         }
251     }
252     return m_error.Success();
253 }
254 
255 
256 
257 bool
258 ValueObjectVariable::IsInScope ()
259 {
260     const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef();
261     if (exe_ctx_ref.HasFrameRef())
262     {
263         ExecutionContext exe_ctx (exe_ctx_ref);
264         StackFrame *frame = exe_ctx.GetFramePtr();
265         if (frame)
266         {
267             return m_variable_sp->IsInScope (frame);
268         }
269         else
270         {
271             // This ValueObject had a frame at one time, but now we
272             // can't locate it, so return false since we probably aren't
273             // in scope.
274             return false;
275         }
276     }
277     // We have a variable that wasn't tied to a frame, which
278     // means it is a global and is always in scope.
279     return true;
280 
281 }
282 
283 lldb::ModuleSP
284 ValueObjectVariable::GetModule()
285 {
286     if (m_variable_sp)
287     {
288         SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope();
289         if (sc_scope)
290         {
291             return sc_scope->CalculateSymbolContextModule();
292         }
293     }
294     return lldb::ModuleSP();
295 }
296 
297 SymbolContextScope *
298 ValueObjectVariable::GetSymbolContextScope()
299 {
300     if (m_variable_sp)
301         return m_variable_sp->GetSymbolContextScope();
302     return NULL;
303 }
304 
305 bool
306 ValueObjectVariable::GetDeclaration (Declaration &decl)
307 {
308     if (m_variable_sp)
309     {
310         decl = m_variable_sp->GetDeclaration();
311         return true;
312     }
313     return false;
314 }
315