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