]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Core / ValueObjectDynamicValue.cpp
1 //===-- ValueObjectDynamicValue.cpp ------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "lldb/Core/ValueObjectDynamicValue.h"
10 #include "lldb/Core/Value.h"
11 #include "lldb/Core/ValueObject.h"
12 #include "lldb/Symbol/CompilerType.h"
13 #include "lldb/Symbol/Type.h"
14 #include "lldb/Target/ExecutionContext.h"
15 #include "lldb/Target/LanguageRuntime.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/DataExtractor.h"
19 #include "lldb/Utility/Log.h"
20 #include "lldb/Utility/Logging.h"
21 #include "lldb/Utility/Scalar.h"
22 #include "lldb/Utility/Status.h"
23 #include "lldb/lldb-types.h"
24
25 #include <string.h>
26 namespace lldb_private {
27 class Declaration;
28 }
29
30 using namespace lldb_private;
31
32 ValueObjectDynamicValue::ValueObjectDynamicValue(
33     ValueObject &parent, lldb::DynamicValueType use_dynamic)
34     : ValueObject(parent), m_address(), m_dynamic_type_info(),
35       m_use_dynamic(use_dynamic) {
36   SetName(parent.GetName());
37 }
38
39 ValueObjectDynamicValue::~ValueObjectDynamicValue() {
40   m_owning_valobj_sp.reset();
41 }
42
43 CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
44   const bool success = UpdateValueIfNeeded(false);
45   if (success) {
46     if (m_dynamic_type_info.HasType())
47       return m_value.GetCompilerType();
48     else
49       return m_parent->GetCompilerType();
50   }
51   return m_parent->GetCompilerType();
52 }
53
54 ConstString ValueObjectDynamicValue::GetTypeName() {
55   const bool success = UpdateValueIfNeeded(false);
56   if (success) {
57     if (m_dynamic_type_info.HasName())
58       return m_dynamic_type_info.GetName();
59   }
60   return m_parent->GetTypeName();
61 }
62
63 TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
64   const bool success = UpdateValueIfNeeded(false);
65   if (success && m_type_impl.IsValid()) {
66     return m_type_impl;
67   }
68   return m_parent->GetTypeImpl();
69 }
70
71 ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
72   const bool success = UpdateValueIfNeeded(false);
73   if (success) {
74     if (m_dynamic_type_info.HasName())
75       return m_dynamic_type_info.GetName();
76   }
77   return m_parent->GetQualifiedTypeName();
78 }
79
80 ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
81   const bool success = UpdateValueIfNeeded(false);
82   if (success) {
83     if (m_dynamic_type_info.HasType())
84       return GetCompilerType().GetDisplayTypeName();
85     if (m_dynamic_type_info.HasName())
86       return m_dynamic_type_info.GetName();
87   }
88   return m_parent->GetDisplayTypeName();
89 }
90
91 size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
92   const bool success = UpdateValueIfNeeded(false);
93   if (success && m_dynamic_type_info.HasType()) {
94     ExecutionContext exe_ctx(GetExecutionContextRef());
95     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
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 parent
126   // 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 don't...
177
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
194   // parent. Or we could return false, and make ourselves an echo of our
195   // parent?
196   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, 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     LLDB_LOGF(log, "[%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) {
250     // The variable value is in the Scalar value inside the m_value. We can
251     // point our m_data right to it.
252     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
253     if (m_error.Success()) {
254       if (!CanProvideValue()) {
255         // 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.
258         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
272 bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
273
274 bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
275                                                   Status &error) {
276   if (!UpdateValueIfNeeded(false)) {
277     error.SetErrorString("unable to read value");
278     return false;
279   }
280
281   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
282   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
283
284   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
285     error.SetErrorString("unable to read value");
286     return false;
287   }
288
289   // 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
294   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;
306 }
307
308 bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
309   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
322   // 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
327   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;
341 }
342
343 void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
344     lldb::LanguageType lang) {
345   this->ValueObject::SetPreferredDisplayLanguage(lang);
346   if (m_parent)
347     m_parent->SetPreferredDisplayLanguage(lang);
348 }
349
350 lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
351   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
352     if (m_parent)
353       return m_parent->GetPreferredDisplayLanguage();
354     return lldb::eLanguageTypeUnknown;
355   } else
356     return m_preferred_display_language;
357 }
358
359 bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
360   if (m_parent)
361     return m_parent->IsSyntheticChildrenGenerated();
362   return false;
363 }
364
365 void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
366   if (m_parent)
367     m_parent->SetSyntheticChildrenGenerated(b);
368   this->ValueObject::SetSyntheticChildrenGenerated(b);
369 }
370
371 bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
372   if (m_parent)
373     return m_parent->GetDeclaration(decl);
374
375   return ValueObject::GetDeclaration(decl);
376 }
377
378 uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
379   if (m_parent)
380     return m_parent->GetLanguageFlags();
381   return this->ValueObject::GetLanguageFlags();
382 }
383
384 void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
385   if (m_parent)
386     m_parent->SetLanguageFlags(flags);
387   else
388     this->ValueObject::SetLanguageFlags(flags);
389 }