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