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