]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/ValueObjectDynamicValue.cpp
MFV r340865:
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / ValueObjectDynamicValue.cpp
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 #include "lldb/Core/ValueObjectDynamicValue.h"
11 #include "lldb/Core/Scalar.h" // for Scalar, operator!=
12 #include "lldb/Core/Value.h"
13 #include "lldb/Core/ValueObject.h"
14 #include "lldb/Symbol/CompilerType.h"
15 #include "lldb/Symbol/Type.h"
16 #include "lldb/Target/ExecutionContext.h"
17 #include "lldb/Target/LanguageRuntime.h"
18 #include "lldb/Target/Process.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/DataExtractor.h" // for DataExtractor
21 #include "lldb/Utility/Log.h"
22 #include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
23 #include "lldb/Utility/Status.h"  // for Status
24 #include "lldb/lldb-types.h"      // for addr_t, offset_t
25
26 #include <string.h> // for strcmp, size_t
27 namespace lldb_private {
28 class Declaration;
29 }
30
31 using namespace lldb_private;
32
33 ValueObjectDynamicValue::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());
38 }
39
40 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
41   m_owning_valobj_sp.reset();
42 }
43
44 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
45   const bool success = UpdateValueIfNeeded(false);
46   if (success) {
47     if (m_dynamic_type_info.HasType())
48       return m_value.GetCompilerType();
49     else
50       return m_parent->GetCompilerType();
51   }
52   return m_parent->GetCompilerType();
53 }
54
55 ConstString 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();
62 }
63
64 TypeImpl 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();
70 }
71
72 ConstString 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 }
80
81 ConstString 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 }
91
92 size_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 }
100
101 uint64_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 }
109
110 lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
111   return m_parent->GetValueType();
112 }
113
114 bool ValueObjectDynamicValue::UpdateValue() {
115   SetValueIsValid(false);
116   m_error.Clear();
117
118   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   }
124
125   // Setting our type_sp to NULL will route everything back through our
126   // parent which is equivalent to not using dynamic values.
127   if (m_use_dynamic == lldb::eNoDynamicValues) {
128     m_dynamic_type_info.Clear();
129     return true;
130   }
131
132   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   }
138
139   // First make sure our Type and/or Address haven't changed:
140   Process *process = exe_ctx.GetProcessPtr();
141   if (!process)
142     return false;
143
144   TypeAndOrName class_type_or_name;
145   Address dynamic_address;
146   bool found_dynamic_type = false;
147   Value::ValueType value_type;
148
149   LanguageRuntime *runtime = nullptr;
150
151   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
152   if (known_type != lldb::eLanguageTypeUnknown &&
153       known_type != lldb::eLanguageTypeC) {
154     runtime = process->GetLanguageRuntime(known_type);
155     if (runtime)
156       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);
165
166     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);
172     }
173   }
174
175   // Getting the dynamic value may have run the program a bit, and so marked us
176   // as needing updating, but we really
177   // don't...
178
179   m_update_point.SetUpdated();
180
181   if (runtime && found_dynamic_type) {
182     if (class_type_or_name.HasType()) {
183       m_type_impl =
184           TypeImpl(m_parent->GetCompilerType(),
185                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
186                        .GetCompilerType());
187     } else {
188       m_type_impl.Clear();
189     }
190   } else {
191     m_type_impl.Clear();
192   }
193
194   // If we don't have a dynamic type, then make ourselves just a echo of our
195   // parent.
196   // Or we could return false, and make ourselves an echo of our parent?
197   if (!found_dynamic_type) {
198     if (m_dynamic_type_info)
199       SetValueDidChange(true);
200     ClearDynamicTypeInformation();
201     m_dynamic_type_info.Clear();
202     m_value = m_parent->GetValue();
203     m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
204     return m_error.Success();
205   }
206
207   Value old_value(m_value);
208
209   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
210
211   bool has_changed_type = false;
212
213   if (!m_dynamic_type_info) {
214     m_dynamic_type_info = class_type_or_name;
215     has_changed_type = true;
216   } else if (class_type_or_name != m_dynamic_type_info) {
217     // We are another type, we need to tear down our children...
218     m_dynamic_type_info = class_type_or_name;
219     SetValueDidChange(true);
220     has_changed_type = true;
221   }
222
223   if (has_changed_type)
224     ClearDynamicTypeInformation();
225
226   if (!m_address.IsValid() || m_address != dynamic_address) {
227     if (m_address.IsValid())
228       SetValueDidChange(true);
229
230     // We've moved, so we should be fine...
231     m_address = dynamic_address;
232     lldb::TargetSP target_sp(GetTargetSP());
233     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
234     m_value.GetScalar() = load_address;
235   }
236
237   if (runtime)
238     m_dynamic_type_info =
239         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
240
241   // m_value.SetContext (Value::eContextTypeClangType, corrected_type);
242   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
243
244   m_value.SetValueType(value_type);
245
246   if (has_changed_type && log)
247     log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(),
248                 static_cast<void *>(this), GetTypeName().GetCString());
249
250   if (m_address.IsValid() && m_dynamic_type_info) {
251     // The variable value is in the Scalar value inside the m_value.
252     // We can point our m_data right to it.
253     m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
254     if (m_error.Success()) {
255       if (!CanProvideValue()) {
256         // this value object represents an aggregate type whose
257         // children have values, but this object does not. So we
258         // say we are changed if our location has changed.
259         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
260                           m_value.GetScalar() != old_value.GetScalar());
261       }
262
263       SetValueIsValid(true);
264       return true;
265     }
266   }
267
268   // We get here if we've failed above...
269   SetValueIsValid(false);
270   return false;
271 }
272
273 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
274
275 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
276                                                   Status &error) {
277   if (!UpdateValueIfNeeded(false)) {
278     error.SetErrorString("unable to read value");
279     return false;
280   }
281
282   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
283   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
284
285   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
286     error.SetErrorString("unable to read value");
287     return false;
288   }
289
290   // if we are at an offset from our parent, in order to set ourselves correctly
291   // we would need
292   // to change the new value so that it refers to the correct dynamic type. we
293   // choose not to deal
294   // with that - if anything more than a value overwrite is required, you should
295   // be using the
296   // expression parser instead of the value editing facility
297   if (my_value != parent_value) {
298     // but NULL'ing out a value should always be allowed
299     if (strcmp(value_str, "0")) {
300       error.SetErrorString(
301           "unable to modify dynamic value, use 'expression' command");
302       return false;
303     }
304   }
305
306   bool ret_val = m_parent->SetValueFromCString(value_str, error);
307   SetNeedsUpdate();
308   return ret_val;
309 }
310
311 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
312   if (!UpdateValueIfNeeded(false)) {
313     error.SetErrorString("unable to read value");
314     return false;
315   }
316
317   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
318   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
319
320   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
321     error.SetErrorString("unable to read value");
322     return false;
323   }
324
325   // if we are at an offset from our parent, in order to set ourselves correctly
326   // we would need
327   // to change the new value so that it refers to the correct dynamic type. we
328   // choose not to deal
329   // with that - if anything more than a value overwrite is required, you should
330   // be using the
331   // expression parser instead of the value editing facility
332   if (my_value != parent_value) {
333     // but NULL'ing out a value should always be allowed
334     lldb::offset_t offset = 0;
335
336     if (data.GetPointer(&offset) != 0) {
337       error.SetErrorString(
338           "unable to modify dynamic value, use 'expression' command");
339       return false;
340     }
341   }
342
343   bool ret_val = m_parent->SetData(data, error);
344   SetNeedsUpdate();
345   return ret_val;
346 }
347
348 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
349     lldb::LanguageType lang) {
350   this->ValueObject::SetPreferredDisplayLanguage(lang);
351   if (m_parent)
352     m_parent->SetPreferredDisplayLanguage(lang);
353 }
354
355 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
356   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
357     if (m_parent)
358       return m_parent->GetPreferredDisplayLanguage();
359     return lldb::eLanguageTypeUnknown;
360   } else
361     return m_preferred_display_language;
362 }
363
364 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
365   if (m_parent)
366     return m_parent->IsSyntheticChildrenGenerated();
367   return false;
368 }
369
370 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
371   if (m_parent)
372     m_parent->SetSyntheticChildrenGenerated(b);
373   this->ValueObject::SetSyntheticChildrenGenerated(b);
374 }
375
376 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
377   if (m_parent)
378     return m_parent->GetDeclaration(decl);
379
380   return ValueObject::GetDeclaration(decl);
381 }
382
383 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
384   if (m_parent)
385     return m_parent->GetLanguageFlags();
386   return this->ValueObject::GetLanguageFlags();
387 }
388
389 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
390   if (m_parent)
391     m_parent->SetLanguageFlags(flags);
392   else
393     this->ValueObject::SetLanguageFlags(flags);
394 }