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