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