1*78a685aaSJim Ingham //===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===//
2*78a685aaSJim Ingham //
3*78a685aaSJim Ingham //                     The LLVM Compiler Infrastructure
4*78a685aaSJim Ingham //
5*78a685aaSJim Ingham // This file is distributed under the University of Illinois Open Source
6*78a685aaSJim Ingham // License. See LICENSE.TXT for details.
7*78a685aaSJim Ingham //
8*78a685aaSJim Ingham //===----------------------------------------------------------------------===//
9*78a685aaSJim Ingham 
10*78a685aaSJim Ingham 
11*78a685aaSJim Ingham #include "lldb/Core/ValueObjectDynamicValue.h"
12*78a685aaSJim Ingham 
13*78a685aaSJim Ingham // C Includes
14*78a685aaSJim Ingham // C++ Includes
15*78a685aaSJim Ingham // Other libraries and framework includes
16*78a685aaSJim Ingham // Project includes
17*78a685aaSJim Ingham #include "lldb/Core/Module.h"
18*78a685aaSJim Ingham #include "lldb/Core/ValueObjectList.h"
19*78a685aaSJim Ingham #include "lldb/Core/Value.h"
20*78a685aaSJim Ingham #include "lldb/Core/ValueObject.h"
21*78a685aaSJim Ingham 
22*78a685aaSJim Ingham #include "lldb/Symbol/ObjectFile.h"
23*78a685aaSJim Ingham #include "lldb/Symbol/SymbolContext.h"
24*78a685aaSJim Ingham #include "lldb/Symbol/Type.h"
25*78a685aaSJim Ingham #include "lldb/Symbol/Variable.h"
26*78a685aaSJim Ingham 
27*78a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h"
28*78a685aaSJim Ingham #include "lldb/Target/LanguageRuntime.h"
29*78a685aaSJim Ingham #include "lldb/Target/Process.h"
30*78a685aaSJim Ingham #include "lldb/Target/RegisterContext.h"
31*78a685aaSJim Ingham #include "lldb/Target/Target.h"
32*78a685aaSJim Ingham #include "lldb/Target/Thread.h"
33*78a685aaSJim Ingham 
34*78a685aaSJim Ingham 
35*78a685aaSJim Ingham using namespace lldb_private;
36*78a685aaSJim Ingham 
37*78a685aaSJim Ingham ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent) :
38*78a685aaSJim Ingham     ValueObject(parent),
39*78a685aaSJim Ingham     m_address (),
40*78a685aaSJim Ingham     m_type_sp()
41*78a685aaSJim Ingham {
42*78a685aaSJim Ingham     // THINK ABOUT: It looks ugly to doctor up the name like this.  But if
43*78a685aaSJim Ingham     // people find it confusing to tell the difference, we may want to do something...
44*78a685aaSJim Ingham 
45*78a685aaSJim Ingham //    std::string dynamic_name ("<dynamic value for \"");
46*78a685aaSJim Ingham //    dynamic_name.append(parent.GetName().AsCString());
47*78a685aaSJim Ingham //    dynamic_name.append("\">");
48*78a685aaSJim Ingham //
49*78a685aaSJim Ingham //    SetName (dynamic_name.c_str());
50*78a685aaSJim Ingham     SetName (parent.GetName().AsCString());
51*78a685aaSJim Ingham }
52*78a685aaSJim Ingham 
53*78a685aaSJim Ingham ValueObjectDynamicValue::~ValueObjectDynamicValue()
54*78a685aaSJim Ingham {
55*78a685aaSJim Ingham     m_owning_valobj_sp.reset();
56*78a685aaSJim Ingham }
57*78a685aaSJim Ingham 
58*78a685aaSJim Ingham lldb::clang_type_t
59*78a685aaSJim Ingham ValueObjectDynamicValue::GetClangType ()
60*78a685aaSJim Ingham {
61*78a685aaSJim Ingham     if (m_type_sp)
62*78a685aaSJim Ingham         return m_value.GetClangType();
63*78a685aaSJim Ingham     else
64*78a685aaSJim Ingham         return m_parent->GetClangType();
65*78a685aaSJim Ingham }
66*78a685aaSJim Ingham 
67*78a685aaSJim Ingham ConstString
68*78a685aaSJim Ingham ValueObjectDynamicValue::GetTypeName()
69*78a685aaSJim Ingham {
70*78a685aaSJim Ingham     // FIXME: Maybe cache the name, but have to clear it out if the type changes...
71*78a685aaSJim Ingham     if (!UpdateValueIfNeeded())
72*78a685aaSJim Ingham         return ConstString("<unknown type>");
73*78a685aaSJim Ingham 
74*78a685aaSJim Ingham     if (m_type_sp)
75*78a685aaSJim Ingham         return ClangASTType::GetClangTypeName (GetClangType());
76*78a685aaSJim Ingham     else
77*78a685aaSJim Ingham         return m_parent->GetTypeName();
78*78a685aaSJim Ingham }
79*78a685aaSJim Ingham 
80*78a685aaSJim Ingham uint32_t
81*78a685aaSJim Ingham ValueObjectDynamicValue::CalculateNumChildren()
82*78a685aaSJim Ingham {
83*78a685aaSJim Ingham     if (!UpdateValueIfNeeded())
84*78a685aaSJim Ingham         return 0;
85*78a685aaSJim Ingham 
86*78a685aaSJim Ingham     if (m_type_sp)
87*78a685aaSJim Ingham         return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
88*78a685aaSJim Ingham     else
89*78a685aaSJim Ingham         return m_parent->GetNumChildren();
90*78a685aaSJim Ingham }
91*78a685aaSJim Ingham 
92*78a685aaSJim Ingham clang::ASTContext *
93*78a685aaSJim Ingham ValueObjectDynamicValue::GetClangAST ()
94*78a685aaSJim Ingham {
95*78a685aaSJim Ingham     if (!UpdateValueIfNeeded())
96*78a685aaSJim Ingham         return NULL;
97*78a685aaSJim Ingham 
98*78a685aaSJim Ingham     if (m_type_sp)
99*78a685aaSJim Ingham         return m_type_sp->GetClangAST();
100*78a685aaSJim Ingham     else
101*78a685aaSJim Ingham         return m_parent->GetClangAST ();
102*78a685aaSJim Ingham }
103*78a685aaSJim Ingham 
104*78a685aaSJim Ingham size_t
105*78a685aaSJim Ingham ValueObjectDynamicValue::GetByteSize()
106*78a685aaSJim Ingham {
107*78a685aaSJim Ingham     if (!UpdateValueIfNeeded())
108*78a685aaSJim Ingham         return 0;
109*78a685aaSJim Ingham 
110*78a685aaSJim Ingham     if (m_type_sp)
111*78a685aaSJim Ingham         return m_value.GetValueByteSize(GetClangAST(), NULL);
112*78a685aaSJim Ingham     else
113*78a685aaSJim Ingham         return m_parent->GetByteSize();
114*78a685aaSJim Ingham }
115*78a685aaSJim Ingham 
116*78a685aaSJim Ingham lldb::ValueType
117*78a685aaSJim Ingham ValueObjectDynamicValue::GetValueType() const
118*78a685aaSJim Ingham {
119*78a685aaSJim Ingham     return m_parent->GetValueType();
120*78a685aaSJim Ingham }
121*78a685aaSJim Ingham 
122*78a685aaSJim Ingham bool
123*78a685aaSJim Ingham ValueObjectDynamicValue::UpdateValue ()
124*78a685aaSJim Ingham {
125*78a685aaSJim Ingham     SetValueIsValid (false);
126*78a685aaSJim Ingham     m_error.Clear();
127*78a685aaSJim Ingham 
128*78a685aaSJim Ingham     if (!m_parent->UpdateValueIfNeeded())
129*78a685aaSJim Ingham     {
130*78a685aaSJim Ingham         return false;
131*78a685aaSJim Ingham     }
132*78a685aaSJim Ingham 
133*78a685aaSJim Ingham     ExecutionContext exe_ctx (GetExecutionContextScope());
134*78a685aaSJim Ingham 
135*78a685aaSJim Ingham     if (exe_ctx.target)
136*78a685aaSJim Ingham     {
137*78a685aaSJim Ingham         m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
138*78a685aaSJim Ingham         m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
139*78a685aaSJim Ingham     }
140*78a685aaSJim Ingham 
141*78a685aaSJim Ingham     // First make sure our Type and/or Address haven't changed:
142*78a685aaSJim Ingham     Process *process = m_update_point.GetProcess();
143*78a685aaSJim Ingham     if (!process)
144*78a685aaSJim Ingham         return false;
145*78a685aaSJim Ingham 
146*78a685aaSJim Ingham     lldb::TypeSP dynamic_type_sp;
147*78a685aaSJim Ingham     Address dynamic_address;
148*78a685aaSJim Ingham     bool found_dynamic_type = false;
149*78a685aaSJim Ingham 
150*78a685aaSJim Ingham     lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
151*78a685aaSJim Ingham     if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
152*78a685aaSJim Ingham     {
153*78a685aaSJim Ingham         LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
154*78a685aaSJim Ingham         if (runtime)
155*78a685aaSJim Ingham             found_dynamic_type = runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
156*78a685aaSJim Ingham     }
157*78a685aaSJim Ingham     else
158*78a685aaSJim Ingham     {
159*78a685aaSJim Ingham         LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
160*78a685aaSJim Ingham         if (cpp_runtime)
161*78a685aaSJim Ingham             found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
162*78a685aaSJim Ingham 
163*78a685aaSJim Ingham         if (!found_dynamic_type)
164*78a685aaSJim Ingham         {
165*78a685aaSJim Ingham             LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
166*78a685aaSJim Ingham             if (objc_runtime)
167*78a685aaSJim Ingham                 found_dynamic_type = cpp_runtime->GetDynamicValue(*m_parent, dynamic_type_sp, dynamic_address);
168*78a685aaSJim Ingham         }
169*78a685aaSJim Ingham     }
170*78a685aaSJim Ingham 
171*78a685aaSJim Ingham     // If we don't have a dynamic type, then make ourselves just a echo of our parent.
172*78a685aaSJim Ingham     // Or we could return false, and make ourselves an echo of our parent?
173*78a685aaSJim Ingham     if (!found_dynamic_type)
174*78a685aaSJim Ingham     {
175*78a685aaSJim Ingham         if (m_type_sp)
176*78a685aaSJim Ingham             SetValueDidChange(true);
177*78a685aaSJim Ingham         m_value = m_parent->GetValue();
178*78a685aaSJim Ingham         m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
179*78a685aaSJim Ingham         return m_error.Success();
180*78a685aaSJim Ingham     }
181*78a685aaSJim Ingham 
182*78a685aaSJim Ingham     Value old_value(m_value);
183*78a685aaSJim Ingham 
184*78a685aaSJim Ingham     if (!m_type_sp)
185*78a685aaSJim Ingham     {
186*78a685aaSJim Ingham         m_type_sp = dynamic_type_sp;
187*78a685aaSJim Ingham     }
188*78a685aaSJim Ingham     else if (dynamic_type_sp != m_type_sp)
189*78a685aaSJim Ingham     {
190*78a685aaSJim Ingham         // We are another type, we need to tear down our children...
191*78a685aaSJim Ingham         m_type_sp = dynamic_type_sp;
192*78a685aaSJim Ingham         SetValueDidChange (true);
193*78a685aaSJim Ingham     }
194*78a685aaSJim Ingham 
195*78a685aaSJim Ingham     if (!m_address.IsValid() || m_address != dynamic_address)
196*78a685aaSJim Ingham     {
197*78a685aaSJim Ingham         if (m_address.IsValid())
198*78a685aaSJim Ingham             SetValueDidChange (true);
199*78a685aaSJim Ingham 
200*78a685aaSJim Ingham         // We've moved, so we should be fine...
201*78a685aaSJim Ingham         m_address = dynamic_address;
202*78a685aaSJim Ingham         lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget());
203*78a685aaSJim Ingham         m_value.GetScalar() = load_address;
204*78a685aaSJim Ingham     }
205*78a685aaSJim Ingham 
206*78a685aaSJim Ingham     // The type will always be the type of the dynamic object.  If our parent's type was a pointer,
207*78a685aaSJim Ingham     // then our type should be a pointer to the type of the dynamic object.  If a reference, then the original type
208*78a685aaSJim Ingham     // should be okay...
209*78a685aaSJim Ingham     lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType();
210*78a685aaSJim Ingham     lldb::clang_type_t corrected_type = orig_type;
211*78a685aaSJim Ingham     if (m_parent->IsPointerType())
212*78a685aaSJim Ingham         corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type);
213*78a685aaSJim Ingham     else if (m_parent->IsPointerOrReferenceType())
214*78a685aaSJim Ingham         corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type);
215*78a685aaSJim Ingham 
216*78a685aaSJim Ingham     m_value.SetContext (Value::eContextTypeClangType, corrected_type);
217*78a685aaSJim Ingham 
218*78a685aaSJim Ingham     // Our address is the location of the dynamic type stored in memory.  It isn't a load address,
219*78a685aaSJim Ingham     // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
220*78a685aaSJim Ingham     m_value.SetValueType(Value::eValueTypeScalar);
221*78a685aaSJim Ingham 
222*78a685aaSJim Ingham     if (m_address.IsValid() && m_type_sp)
223*78a685aaSJim Ingham     {
224*78a685aaSJim Ingham         // The variable value is in the Scalar value inside the m_value.
225*78a685aaSJim Ingham         // We can point our m_data right to it.
226*78a685aaSJim Ingham         m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
227*78a685aaSJim Ingham         if (m_error.Success())
228*78a685aaSJim Ingham         {
229*78a685aaSJim Ingham             if (ClangASTContext::IsAggregateType (GetClangType()))
230*78a685aaSJim Ingham             {
231*78a685aaSJim Ingham                 // this value object represents an aggregate type whose
232*78a685aaSJim Ingham                 // children have values, but this object does not. So we
233*78a685aaSJim Ingham                 // say we are changed if our location has changed.
234*78a685aaSJim Ingham                 SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
235*78a685aaSJim Ingham             }
236*78a685aaSJim Ingham 
237*78a685aaSJim Ingham             SetValueIsValid (true);
238*78a685aaSJim Ingham             return true;
239*78a685aaSJim Ingham         }
240*78a685aaSJim Ingham     }
241*78a685aaSJim Ingham 
242*78a685aaSJim Ingham     // We get here if we've failed above...
243*78a685aaSJim Ingham     SetValueIsValid (false);
244*78a685aaSJim Ingham     return false;
245*78a685aaSJim Ingham }
246*78a685aaSJim Ingham 
247*78a685aaSJim Ingham 
248*78a685aaSJim Ingham 
249*78a685aaSJim Ingham bool
250*78a685aaSJim Ingham ValueObjectDynamicValue::IsInScope ()
251*78a685aaSJim Ingham {
252*78a685aaSJim Ingham     return m_parent->IsInScope();
253*78a685aaSJim Ingham }
254*78a685aaSJim Ingham 
255