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