blob: 3dd360d98767f76f0ff14ed10bc67ec62661f248 [file] [log] [blame]
Jim Ingham78a685a2011-04-16 00:01:13 +00001//===-- 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
35using namespace lldb_private;
36
Jim Ingham2837b762011-05-04 03:43:18 +000037ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) :
Jim Ingham78a685a2011-04-16 00:01:13 +000038 ValueObject(parent),
39 m_address (),
Jim Ingham2837b762011-05-04 03:43:18 +000040 m_type_sp(),
41 m_use_dynamic (use_dynamic)
Jim Ingham78a685a2011-04-16 00:01:13 +000042{
Enrico Granatad8b5fce2011-08-02 23:12:24 +000043 m_last_format_mgr_dynamic = use_dynamic;
Enrico Granata6f3533f2011-07-29 19:53:35 +000044 SetName (parent.GetName());
Jim Ingham78a685a2011-04-16 00:01:13 +000045}
46
47ValueObjectDynamicValue::~ValueObjectDynamicValue()
48{
49 m_owning_valobj_sp.reset();
50}
51
52lldb::clang_type_t
53ValueObjectDynamicValue::GetClangType ()
54{
55 if (m_type_sp)
56 return m_value.GetClangType();
57 else
58 return m_parent->GetClangType();
59}
60
61ConstString
62ValueObjectDynamicValue::GetTypeName()
63{
Enrico Granatac3e320a2011-08-02 17:27:39 +000064 const bool success = UpdateValueIfNeeded(false);
Greg Clayton5ad63942011-05-31 20:18:39 +000065 if (success && m_type_sp)
Greg Claytone3055942011-06-30 02:28:26 +000066 return ClangASTType::GetConstTypeName (GetClangType());
Jim Ingham78a685a2011-04-16 00:01:13 +000067 else
68 return m_parent->GetTypeName();
69}
70
71uint32_t
72ValueObjectDynamicValue::CalculateNumChildren()
73{
Enrico Granatac3e320a2011-08-02 17:27:39 +000074 const bool success = UpdateValueIfNeeded(false);
Greg Clayton5ad63942011-05-31 20:18:39 +000075 if (success && m_type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +000076 return ClangASTContext::GetNumChildren (GetClangAST (), GetClangType(), true);
77 else
78 return m_parent->GetNumChildren();
79}
80
81clang::ASTContext *
82ValueObjectDynamicValue::GetClangAST ()
83{
Enrico Granata0a3958e2011-07-02 00:25:22 +000084 const bool success = UpdateValueIfNeeded(false);
Greg Clayton5ad63942011-05-31 20:18:39 +000085 if (success && m_type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +000086 return m_type_sp->GetClangAST();
87 else
88 return m_parent->GetClangAST ();
89}
90
91size_t
92ValueObjectDynamicValue::GetByteSize()
93{
Enrico Granatac3e320a2011-08-02 17:27:39 +000094 const bool success = UpdateValueIfNeeded(false);
Greg Clayton5ad63942011-05-31 20:18:39 +000095 if (success && m_type_sp)
Jim Ingham78a685a2011-04-16 00:01:13 +000096 return m_value.GetValueByteSize(GetClangAST(), NULL);
97 else
98 return m_parent->GetByteSize();
99}
100
101lldb::ValueType
102ValueObjectDynamicValue::GetValueType() const
103{
104 return m_parent->GetValueType();
105}
106
107bool
108ValueObjectDynamicValue::UpdateValue ()
109{
110 SetValueIsValid (false);
111 m_error.Clear();
112
Enrico Granatac3e320a2011-08-02 17:27:39 +0000113 if (!m_parent->UpdateValueIfNeeded(false))
Jim Ingham78a685a2011-04-16 00:01:13 +0000114 {
Greg Clayton007d5be2011-05-30 00:49:24 +0000115 // The dynamic value failed to get an error, pass the error along
116 if (m_error.Success() && m_parent->GetError().Fail())
117 m_error = m_parent->GetError();
Jim Ingham78a685a2011-04-16 00:01:13 +0000118 return false;
119 }
120
Jim Ingham2837b762011-05-04 03:43:18 +0000121 // Setting our type_sp to NULL will route everything back through our
122 // parent which is equivalent to not using dynamic values.
123 if (m_use_dynamic == lldb::eNoDynamicValues)
124 {
125 m_type_sp.reset();
126 return true;
127 }
128
Jim Ingham78a685a2011-04-16 00:01:13 +0000129 ExecutionContext exe_ctx (GetExecutionContextScope());
130
131 if (exe_ctx.target)
132 {
133 m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
134 m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
135 }
136
137 // First make sure our Type and/or Address haven't changed:
Enrico Granata6f3533f2011-07-29 19:53:35 +0000138 Process *process = m_update_point.GetProcessSP().get();
Jim Ingham78a685a2011-04-16 00:01:13 +0000139 if (!process)
140 return false;
141
Jim Ingham61be0902011-05-02 18:13:59 +0000142 TypeAndOrName class_type_or_name;
Jim Ingham78a685a2011-04-16 00:01:13 +0000143 Address dynamic_address;
144 bool found_dynamic_type = false;
145
146 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
147 if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC)
148 {
149 LanguageRuntime *runtime = process->GetLanguageRuntime (known_type);
150 if (runtime)
Jim Ingham2837b762011-05-04 03:43:18 +0000151 found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
Jim Ingham78a685a2011-04-16 00:01:13 +0000152 }
153 else
154 {
155 LanguageRuntime *cpp_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus);
156 if (cpp_runtime)
Jim Ingham2837b762011-05-04 03:43:18 +0000157 found_dynamic_type = cpp_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
Jim Ingham78a685a2011-04-16 00:01:13 +0000158
159 if (!found_dynamic_type)
160 {
161 LanguageRuntime *objc_runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC);
162 if (objc_runtime)
Enrico Granata9910bc82011-08-03 02:18:51 +0000163 found_dynamic_type = objc_runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address);
Jim Ingham78a685a2011-04-16 00:01:13 +0000164 }
165 }
166
Jim Ingham61be0902011-05-02 18:13:59 +0000167 lldb::TypeSP dynamic_type_sp = class_type_or_name.GetTypeSP();
168
169 // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really
170 // don't...
171
172 m_update_point.SetUpdated();
173
Jim Ingham78a685a2011-04-16 00:01:13 +0000174 // If we don't have a dynamic type, then make ourselves just a echo of our parent.
175 // Or we could return false, and make ourselves an echo of our parent?
176 if (!found_dynamic_type)
177 {
178 if (m_type_sp)
179 SetValueDidChange(true);
180 m_value = m_parent->GetValue();
Greg Clayton644247c2011-07-07 01:59:51 +0000181 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule());
Jim Ingham78a685a2011-04-16 00:01:13 +0000182 return m_error.Success();
183 }
184
185 Value old_value(m_value);
186
187 if (!m_type_sp)
188 {
189 m_type_sp = dynamic_type_sp;
190 }
191 else if (dynamic_type_sp != m_type_sp)
192 {
193 // We are another type, we need to tear down our children...
194 m_type_sp = dynamic_type_sp;
195 SetValueDidChange (true);
196 }
197
198 if (!m_address.IsValid() || m_address != dynamic_address)
199 {
200 if (m_address.IsValid())
201 SetValueDidChange (true);
202
203 // We've moved, so we should be fine...
204 m_address = dynamic_address;
Enrico Granata6f3533f2011-07-29 19:53:35 +0000205 lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get());
Jim Ingham78a685a2011-04-16 00:01:13 +0000206 m_value.GetScalar() = load_address;
207 }
208
209 // The type will always be the type of the dynamic object. If our parent's type was a pointer,
210 // then our type should be a pointer to the type of the dynamic object. If a reference, then the original type
211 // should be okay...
212 lldb::clang_type_t orig_type = m_type_sp->GetClangForwardType();
213 lldb::clang_type_t corrected_type = orig_type;
214 if (m_parent->IsPointerType())
215 corrected_type = ClangASTContext::CreatePointerType (m_type_sp->GetClangAST(), orig_type);
216 else if (m_parent->IsPointerOrReferenceType())
217 corrected_type = ClangASTContext::CreateLValueReferenceType (m_type_sp->GetClangAST(), orig_type);
218
219 m_value.SetContext (Value::eContextTypeClangType, corrected_type);
220
221 // Our address is the location of the dynamic type stored in memory. It isn't a load address,
222 // because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
223 m_value.SetValueType(Value::eValueTypeScalar);
224
225 if (m_address.IsValid() && m_type_sp)
226 {
227 // The variable value is in the Scalar value inside the m_value.
228 // We can point our m_data right to it.
Greg Clayton644247c2011-07-07 01:59:51 +0000229 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule());
Jim Ingham78a685a2011-04-16 00:01:13 +0000230 if (m_error.Success())
231 {
232 if (ClangASTContext::IsAggregateType (GetClangType()))
233 {
234 // this value object represents an aggregate type whose
235 // children have values, but this object does not. So we
236 // say we are changed if our location has changed.
237 SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
238 }
239
240 SetValueIsValid (true);
241 return true;
242 }
243 }
244
245 // We get here if we've failed above...
246 SetValueIsValid (false);
247 return false;
248}
249
250
251
252bool
253ValueObjectDynamicValue::IsInScope ()
254{
255 return m_parent->IsInScope();
256}
257