blob: d835e6965d478002cf3d04c8d8475cbbbdac26cb [file] [log] [blame]
Zachary Turner2f3df612017-04-06 21:28:29 +00001//===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===//
Jim Ingham78a685a2011-04-16 00:01:13 +00002//
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
Jim Ingham78a685a2011-04-16 00:01:13 +000010#include "lldb/Core/ValueObjectDynamicValue.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000011#include "lldb/Core/Value.h"
12#include "lldb/Core/ValueObject.h"
Greg Claytona1e5dc82015-08-11 22:53:00 +000013#include "lldb/Symbol/CompilerType.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000014#include "lldb/Symbol/Type.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000015#include "lldb/Target/ExecutionContext.h"
16#include "lldb/Target/LanguageRuntime.h"
17#include "lldb/Target/Process.h"
Jim Ingham78a685a2011-04-16 00:01:13 +000018#include "lldb/Target/Target.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000019#include "lldb/Utility/DataExtractor.h" // for DataExtractor
Zachary Turner2f3df612017-04-06 21:28:29 +000020#include "lldb/Utility/Log.h"
21#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
Pavel Labathd821c992018-08-07 11:07:21 +000022#include "lldb/Utility/Scalar.h" // for Scalar, operator!=
Zachary Turner97206d52017-05-12 04:51:55 +000023#include "lldb/Utility/Status.h" // for Status
Zachary Turner2f3df612017-04-06 21:28:29 +000024#include "lldb/lldb-types.h" // for addr_t, offset_t
25
26#include <string.h> // for strcmp, size_t
27namespace lldb_private {
28class Declaration;
29}
Jim Ingham78a685a2011-04-16 00:01:13 +000030
Jim Ingham78a685a2011-04-16 00:01:13 +000031using namespace lldb_private;
32
Kate Stoneb9c1b512016-09-06 20:57:50 +000033ValueObjectDynamicValue::ValueObjectDynamicValue(
34 ValueObject &parent, lldb::DynamicValueType use_dynamic)
35 : ValueObject(parent), m_address(), m_dynamic_type_info(),
36 m_use_dynamic(use_dynamic) {
37 SetName(parent.GetName());
Jim Ingham78a685a2011-04-16 00:01:13 +000038}
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040ValueObjectDynamicValue::~ValueObjectDynamicValue() {
41 m_owning_valobj_sp.reset();
Jim Ingham78a685a2011-04-16 00:01:13 +000042}
43
Kate Stoneb9c1b512016-09-06 20:57:50 +000044CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
45 const bool success = UpdateValueIfNeeded(false);
46 if (success) {
47 if (m_dynamic_type_info.HasType())
48 return m_value.GetCompilerType();
Jim Ingham78a685a2011-04-16 00:01:13 +000049 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 return m_parent->GetCompilerType();
51 }
52 return m_parent->GetCompilerType();
Jim Ingham78a685a2011-04-16 00:01:13 +000053}
54
Kate Stoneb9c1b512016-09-06 20:57:50 +000055ConstString ValueObjectDynamicValue::GetTypeName() {
56 const bool success = UpdateValueIfNeeded(false);
57 if (success) {
58 if (m_dynamic_type_info.HasName())
59 return m_dynamic_type_info.GetName();
60 }
61 return m_parent->GetTypeName();
Jim Ingham78a685a2011-04-16 00:01:13 +000062}
63
Kate Stoneb9c1b512016-09-06 20:57:50 +000064TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
65 const bool success = UpdateValueIfNeeded(false);
66 if (success && m_type_impl.IsValid()) {
67 return m_type_impl;
68 }
69 return m_parent->GetTypeImpl();
Jim Ingham78a685a2011-04-16 00:01:13 +000070}
71
Kate Stoneb9c1b512016-09-06 20:57:50 +000072ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
73 const bool success = UpdateValueIfNeeded(false);
74 if (success) {
75 if (m_dynamic_type_info.HasName())
76 return m_dynamic_type_info.GetName();
77 }
78 return m_parent->GetQualifiedTypeName();
79}
Jim Ingham78a685a2011-04-16 00:01:13 +000080
Kate Stoneb9c1b512016-09-06 20:57:50 +000081ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
82 const bool success = UpdateValueIfNeeded(false);
83 if (success) {
84 if (m_dynamic_type_info.HasType())
85 return GetCompilerType().GetDisplayTypeName();
86 if (m_dynamic_type_info.HasName())
87 return m_dynamic_type_info.GetName();
88 }
89 return m_parent->GetDisplayTypeName();
90}
Saleem Abdulrasool324a1032014-04-04 04:06:10 +000091
Kate Stoneb9c1b512016-09-06 20:57:50 +000092size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
93 const bool success = UpdateValueIfNeeded(false);
94 if (success && m_dynamic_type_info.HasType()) {
95 auto children_count = GetCompilerType().GetNumChildren(true);
96 return children_count <= max ? children_count : max;
97 } else
98 return m_parent->GetNumChildren(max);
99}
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101uint64_t ValueObjectDynamicValue::GetByteSize() {
102 const bool success = UpdateValueIfNeeded(false);
103 if (success && m_dynamic_type_info.HasType()) {
104 ExecutionContext exe_ctx(GetExecutionContextRef());
105 return m_value.GetValueByteSize(nullptr, &exe_ctx);
106 } else
107 return m_parent->GetByteSize();
108}
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
111 return m_parent->GetValueType();
112}
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000113
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114bool ValueObjectDynamicValue::UpdateValue() {
115 SetValueIsValid(false);
116 m_error.Clear();
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000117
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118 if (!m_parent->UpdateValueIfNeeded(false)) {
119 // The dynamic value failed to get an error, pass the error along
120 if (m_error.Success() && m_parent->GetError().Fail())
121 m_error = m_parent->GetError();
122 return false;
123 }
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000124
Adrian Prantl05097242018-04-30 16:49:04 +0000125 // Setting our type_sp to NULL will route everything back through our parent
126 // which is equivalent to not using dynamic values.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127 if (m_use_dynamic == lldb::eNoDynamicValues) {
128 m_dynamic_type_info.Clear();
129 return true;
130 }
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000131
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132 ExecutionContext exe_ctx(GetExecutionContextRef());
133 Target *target = exe_ctx.GetTargetPtr();
134 if (target) {
135 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
137 }
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 // First make sure our Type and/or Address haven't changed:
140 Process *process = exe_ctx.GetProcessPtr();
141 if (!process)
142 return false;
Enrico Granatadc4db5a2013-10-29 00:28:35 +0000143
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 TypeAndOrName class_type_or_name;
145 Address dynamic_address;
146 bool found_dynamic_type = false;
147 Value::ValueType value_type;
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000148
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 LanguageRuntime *runtime = nullptr;
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000150
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151 lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
152 if (known_type != lldb::eLanguageTypeUnknown &&
153 known_type != lldb::eLanguageTypeC) {
154 runtime = process->GetLanguageRuntime(known_type);
Enrico Granatac74275b2015-09-22 19:45:52 +0000155 if (runtime)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000156 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
157 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
158 value_type);
159 } else {
160 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
161 if (runtime)
162 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
163 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
164 value_type);
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 if (!found_dynamic_type) {
167 runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
168 if (runtime)
169 found_dynamic_type = runtime->GetDynamicTypeAndAddress(
170 *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
171 value_type);
Jim Ingham78a685a2011-04-16 00:01:13 +0000172 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173 }
Saleem Abdulrasool324a1032014-04-04 04:06:10 +0000174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 // Getting the dynamic value may have run the program a bit, and so marked us
Adrian Prantl05097242018-04-30 16:49:04 +0000176 // as needing updating, but we really don't...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177
178 m_update_point.SetUpdated();
179
180 if (runtime && found_dynamic_type) {
181 if (class_type_or_name.HasType()) {
182 m_type_impl =
183 TypeImpl(m_parent->GetCompilerType(),
184 runtime->FixUpDynamicType(class_type_or_name, *m_parent)
185 .GetCompilerType());
186 } else {
187 m_type_impl.Clear();
188 }
189 } else {
190 m_type_impl.Clear();
191 }
192
193 // If we don't have a dynamic type, then make ourselves just a echo of our
Adrian Prantl05097242018-04-30 16:49:04 +0000194 // parent. Or we could return false, and make ourselves an echo of our
195 // parent?
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 if (!found_dynamic_type) {
197 if (m_dynamic_type_info)
198 SetValueDidChange(true);
199 ClearDynamicTypeInformation();
200 m_dynamic_type_info.Clear();
201 m_value = m_parent->GetValue();
202 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
203 return m_error.Success();
204 }
205
206 Value old_value(m_value);
207
208 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
209
210 bool has_changed_type = false;
211
212 if (!m_dynamic_type_info) {
213 m_dynamic_type_info = class_type_or_name;
214 has_changed_type = true;
215 } else if (class_type_or_name != m_dynamic_type_info) {
216 // We are another type, we need to tear down our children...
217 m_dynamic_type_info = class_type_or_name;
218 SetValueDidChange(true);
219 has_changed_type = true;
220 }
221
222 if (has_changed_type)
223 ClearDynamicTypeInformation();
224
225 if (!m_address.IsValid() || m_address != dynamic_address) {
226 if (m_address.IsValid())
227 SetValueDidChange(true);
228
229 // We've moved, so we should be fine...
230 m_address = dynamic_address;
231 lldb::TargetSP target_sp(GetTargetSP());
232 lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
233 m_value.GetScalar() = load_address;
234 }
235
236 if (runtime)
237 m_dynamic_type_info =
238 runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
239
240 // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
241 m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
242
243 m_value.SetValueType(value_type);
244
245 if (has_changed_type && log)
246 log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
247 static_cast<void *>(this), GetTypeName().GetCString());
248
249 if (m_address.IsValid() && m_dynamic_type_info) {
Adrian Prantl05097242018-04-30 16:49:04 +0000250 // The variable value is in the Scalar value inside the m_value. We can
251 // point our m_data right to it.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
253 if (m_error.Success()) {
254 if (!CanProvideValue()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000255 // this value object represents an aggregate type whose children have
256 // values, but this object does not. So we say we are changed if our
257 // location has changed.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
259 m_value.GetScalar() != old_value.GetScalar());
260 }
261
262 SetValueIsValid(true);
263 return true;
264 }
265 }
266
267 // We get here if we've failed above...
268 SetValueIsValid(false);
269 return false;
270}
271
272bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
273
274bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
Zachary Turner97206d52017-05-12 04:51:55 +0000275 Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276 if (!UpdateValueIfNeeded(false)) {
277 error.SetErrorString("unable to read value");
Jim Ingham78a685a2011-04-16 00:01:13 +0000278 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 }
Jim Ingham78a685a2011-04-16 00:01:13 +0000280
Kate Stoneb9c1b512016-09-06 20:57:50 +0000281 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
282 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
Jim Ingham78a685a2011-04-16 00:01:13 +0000283
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
285 error.SetErrorString("unable to read value");
Enrico Granata3b207c62016-07-08 18:39:36 +0000286 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 }
288
Adrian Prantl05097242018-04-30 16:49:04 +0000289 // if we are at an offset from our parent, in order to set ourselves
290 // correctly we would need to change the new value so that it refers to the
291 // correct dynamic type. we choose not to deal with that - if anything more
292 // than a value overwrite is required, you should be using the expression
293 // parser instead of the value editing facility
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294 if (my_value != parent_value) {
295 // but NULL'ing out a value should always be allowed
296 if (strcmp(value_str, "0")) {
297 error.SetErrorString(
298 "unable to modify dynamic value, use 'expression' command");
299 return false;
300 }
301 }
302
303 bool ret_val = m_parent->SetValueFromCString(value_str, error);
304 SetNeedsUpdate();
305 return ret_val;
Enrico Granata3b207c62016-07-08 18:39:36 +0000306}
307
Zachary Turner97206d52017-05-12 04:51:55 +0000308bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 if (!UpdateValueIfNeeded(false)) {
310 error.SetErrorString("unable to read value");
311 return false;
312 }
313
314 uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
315 uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
316
317 if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
318 error.SetErrorString("unable to read value");
319 return false;
320 }
321
Adrian Prantl05097242018-04-30 16:49:04 +0000322 // if we are at an offset from our parent, in order to set ourselves
323 // correctly we would need to change the new value so that it refers to the
324 // correct dynamic type. we choose not to deal with that - if anything more
325 // than a value overwrite is required, you should be using the expression
326 // parser instead of the value editing facility
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327 if (my_value != parent_value) {
328 // but NULL'ing out a value should always be allowed
329 lldb::offset_t offset = 0;
330
331 if (data.GetPointer(&offset) != 0) {
332 error.SetErrorString(
333 "unable to modify dynamic value, use 'expression' command");
334 return false;
335 }
336 }
337
338 bool ret_val = m_parent->SetData(data, error);
339 SetNeedsUpdate();
340 return ret_val;
Enrico Granata3b207c62016-07-08 18:39:36 +0000341}
342
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
344 lldb::LanguageType lang) {
345 this->ValueObject::SetPreferredDisplayLanguage(lang);
346 if (m_parent)
347 m_parent->SetPreferredDisplayLanguage(lang);
Siva Chandra9851b1f2015-08-18 17:56:06 +0000348}
Enrico Granatadc62ffd2015-11-09 19:27:34 +0000349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
351 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
Enrico Granatadc62ffd2015-11-09 19:27:34 +0000352 if (m_parent)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000353 return m_parent->GetPreferredDisplayLanguage();
354 return lldb::eLanguageTypeUnknown;
355 } else
356 return m_preferred_display_language;
Enrico Granatadc62ffd2015-11-09 19:27:34 +0000357}
358
Kate Stoneb9c1b512016-09-06 20:57:50 +0000359bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
360 if (m_parent)
361 return m_parent->IsSyntheticChildrenGenerated();
362 return false;
363}
364
365void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
366 if (m_parent)
367 m_parent->SetSyntheticChildrenGenerated(b);
368 this->ValueObject::SetSyntheticChildrenGenerated(b);
369}
370
371bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
372 if (m_parent)
373 return m_parent->GetDeclaration(decl);
374
375 return ValueObject::GetDeclaration(decl);
376}
377
378uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
379 if (m_parent)
380 return m_parent->GetLanguageFlags();
381 return this->ValueObject::GetLanguageFlags();
382}
383
384void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
385 if (m_parent)
386 m_parent->SetLanguageFlags(flags);
387 else
388 this->ValueObject::SetLanguageFlags(flags);
Enrico Granatadc62ffd2015-11-09 19:27:34 +0000389}