1//===-- ValueObject.cpp ---------------------------------------------------===//
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/ValueObject.h"
10
11#include "lldb/Core/Address.h"
12#include "lldb/Core/Declaration.h"
13#include "lldb/Core/Module.h"
14#include "lldb/Core/ValueObjectCast.h"
15#include "lldb/Core/ValueObjectChild.h"
16#include "lldb/Core/ValueObjectConstResult.h"
17#include "lldb/Core/ValueObjectDynamicValue.h"
18#include "lldb/Core/ValueObjectMemory.h"
19#include "lldb/Core/ValueObjectSyntheticFilter.h"
20#include "lldb/Core/ValueObjectVTable.h"
21#include "lldb/DataFormatters/DataVisualization.h"
22#include "lldb/DataFormatters/DumpValueObjectOptions.h"
23#include "lldb/DataFormatters/FormatManager.h"
24#include "lldb/DataFormatters/StringPrinter.h"
25#include "lldb/DataFormatters/TypeFormat.h"
26#include "lldb/DataFormatters/TypeSummary.h"
27#include "lldb/DataFormatters/ValueObjectPrinter.h"
28#include "lldb/Expression/ExpressionVariable.h"
29#include "lldb/Host/Config.h"
30#include "lldb/Symbol/CompileUnit.h"
31#include "lldb/Symbol/CompilerType.h"
32#include "lldb/Symbol/SymbolContext.h"
33#include "lldb/Symbol/Type.h"
34#include "lldb/Symbol/Variable.h"
35#include "lldb/Target/ExecutionContext.h"
36#include "lldb/Target/Language.h"
37#include "lldb/Target/LanguageRuntime.h"
38#include "lldb/Target/Process.h"
39#include "lldb/Target/StackFrame.h"
40#include "lldb/Target/Target.h"
41#include "lldb/Target/Thread.h"
42#include "lldb/Target/ThreadList.h"
43#include "lldb/Utility/DataBuffer.h"
44#include "lldb/Utility/DataBufferHeap.h"
45#include "lldb/Utility/Flags.h"
46#include "lldb/Utility/LLDBLog.h"
47#include "lldb/Utility/Log.h"
48#include "lldb/Utility/Scalar.h"
49#include "lldb/Utility/Stream.h"
50#include "lldb/Utility/StreamString.h"
51#include "lldb/lldb-private-types.h"
52
53#include "llvm/Support/Compiler.h"
54
55#include <algorithm>
56#include <cstdint>
57#include <cstdlib>
58#include <memory>
59#include <optional>
60#include <tuple>
61
62#include <cassert>
63#include <cinttypes>
64#include <cstdio>
65#include <cstring>
66
67#include <lldb/Core/ValueObject.h>
68
69namespace lldb_private {
70class ExecutionContextScope;
71}
72namespace lldb_private {
73class SymbolContextScope;
74}
75
76using namespace lldb;
77using namespace lldb_private;
78
79static user_id_t g_value_obj_uid = 0;
80
81// ValueObject constructor
82ValueObject::ValueObject(ValueObject &parent)
83 : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),
84 m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {
85 m_flags.m_is_synthetic_children_generated =
86 parent.m_flags.m_is_synthetic_children_generated;
87 m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());
88 m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());
89 m_manager->ManageObject(new_object: this);
90}
91
92// ValueObject constructor
93ValueObject::ValueObject(ExecutionContextScope *exe_scope,
94 ValueObjectManager &manager,
95 AddressType child_ptr_or_ref_addr_type)
96 : m_update_point(exe_scope), m_manager(&manager),
97 m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
98 m_id(++g_value_obj_uid) {
99 if (exe_scope) {
100 TargetSP target_sp(exe_scope->CalculateTarget());
101 if (target_sp) {
102 const ArchSpec &arch = target_sp->GetArchitecture();
103 m_data.SetByteOrder(arch.GetByteOrder());
104 m_data.SetAddressByteSize(arch.GetAddressByteSize());
105 }
106 }
107 m_manager->ManageObject(new_object: this);
108}
109
110// Destructor
111ValueObject::~ValueObject() = default;
112
113bool ValueObject::UpdateValueIfNeeded(bool update_format) {
114
115 bool did_change_formats = false;
116
117 if (update_format)
118 did_change_formats = UpdateFormatsIfNeeded();
119
120 // If this is a constant value, then our success is predicated on whether we
121 // have an error or not
122 if (GetIsConstant()) {
123 // if you are constant, things might still have changed behind your back
124 // (e.g. you are a frozen object and things have changed deeper than you
125 // cared to freeze-dry yourself) in this case, your value has not changed,
126 // but "computed" entries might have, so you might now have a different
127 // summary, or a different object description. clear these so we will
128 // recompute them
129 if (update_format && !did_change_formats)
130 ClearUserVisibleData(items: eClearUserVisibleDataItemsSummary |
131 eClearUserVisibleDataItemsDescription);
132 return m_error.Success();
133 }
134
135 bool first_update = IsChecksumEmpty();
136
137 if (NeedsUpdating()) {
138 m_update_point.SetUpdated();
139
140 // Save the old value using swap to avoid a string copy which also will
141 // clear our m_value_str
142 if (m_value_str.empty()) {
143 m_flags.m_old_value_valid = false;
144 } else {
145 m_flags.m_old_value_valid = true;
146 m_old_value_str.swap(s&: m_value_str);
147 ClearUserVisibleData(items: eClearUserVisibleDataItemsValue);
148 }
149
150 ClearUserVisibleData();
151
152 if (IsInScope()) {
153 const bool value_was_valid = GetValueIsValid();
154 SetValueDidChange(false);
155
156 m_error.Clear();
157
158 // Call the pure virtual function to update the value
159
160 bool need_compare_checksums = false;
161 llvm::SmallVector<uint8_t, 16> old_checksum;
162
163 if (!first_update && CanProvideValue()) {
164 need_compare_checksums = true;
165 old_checksum.resize(N: m_value_checksum.size());
166 std::copy(first: m_value_checksum.begin(), last: m_value_checksum.end(),
167 result: old_checksum.begin());
168 }
169
170 bool success = UpdateValue();
171
172 SetValueIsValid(success);
173
174 if (success) {
175 UpdateChildrenAddressType();
176 const uint64_t max_checksum_size = 128;
177 m_data.Checksum(dest&: m_value_checksum, max_data: max_checksum_size);
178 } else {
179 need_compare_checksums = false;
180 m_value_checksum.clear();
181 }
182
183 assert(!need_compare_checksums ||
184 (!old_checksum.empty() && !m_value_checksum.empty()));
185
186 if (first_update)
187 SetValueDidChange(false);
188 else if (!m_flags.m_value_did_change && !success) {
189 // The value wasn't gotten successfully, so we mark this as changed if
190 // the value used to be valid and now isn't
191 SetValueDidChange(value_was_valid);
192 } else if (need_compare_checksums) {
193 SetValueDidChange(memcmp(s1: &old_checksum[0], s2: &m_value_checksum[0],
194 n: m_value_checksum.size()));
195 }
196
197 } else {
198 m_error.SetErrorString("out of scope");
199 }
200 }
201 return m_error.Success();
202}
203
204bool ValueObject::UpdateFormatsIfNeeded() {
205 Log *log = GetLog(mask: LLDBLog::DataFormatters);
206 LLDB_LOGF(log,
207 "[%s %p] checking for FormatManager revisions. ValueObject "
208 "rev: %d - Global rev: %d",
209 GetName().GetCString(), static_cast<void *>(this),
210 m_last_format_mgr_revision,
211 DataVisualization::GetCurrentRevision());
212
213 bool any_change = false;
214
215 if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {
216 m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
217 any_change = true;
218
219 SetValueFormat(DataVisualization::GetFormat(valobj&: *this, use_dynamic: eNoDynamicValues));
220 SetSummaryFormat(
221 DataVisualization::GetSummaryFormat(valobj&: *this, use_dynamic: GetDynamicValueType()));
222 SetSyntheticChildren(
223 DataVisualization::GetSyntheticChildren(valobj&: *this, use_dynamic: GetDynamicValueType()));
224 }
225
226 return any_change;
227}
228
229void ValueObject::SetNeedsUpdate() {
230 m_update_point.SetNeedsUpdate();
231 // We have to clear the value string here so ConstResult children will notice
232 // if their values are changed by hand (i.e. with SetValueAsCString).
233 ClearUserVisibleData(items: eClearUserVisibleDataItemsValue);
234}
235
236void ValueObject::ClearDynamicTypeInformation() {
237 m_flags.m_children_count_valid = false;
238 m_flags.m_did_calculate_complete_objc_class_type = false;
239 m_last_format_mgr_revision = 0;
240 m_override_type = CompilerType();
241 SetValueFormat(lldb::TypeFormatImplSP());
242 SetSummaryFormat(lldb::TypeSummaryImplSP());
243 SetSyntheticChildren(lldb::SyntheticChildrenSP());
244}
245
246CompilerType ValueObject::MaybeCalculateCompleteType() {
247 CompilerType compiler_type(GetCompilerTypeImpl());
248
249 if (m_flags.m_did_calculate_complete_objc_class_type) {
250 if (m_override_type.IsValid())
251 return m_override_type;
252 else
253 return compiler_type;
254 }
255
256 m_flags.m_did_calculate_complete_objc_class_type = true;
257
258 ProcessSP process_sp(
259 GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
260
261 if (!process_sp)
262 return compiler_type;
263
264 if (auto *runtime =
265 process_sp->GetLanguageRuntime(language: GetObjectRuntimeLanguage())) {
266 if (std::optional<CompilerType> complete_type =
267 runtime->GetRuntimeType(base_type: compiler_type)) {
268 m_override_type = *complete_type;
269 if (m_override_type.IsValid())
270 return m_override_type;
271 }
272 }
273 return compiler_type;
274}
275
276
277
278DataExtractor &ValueObject::GetDataExtractor() {
279 UpdateValueIfNeeded(update_format: false);
280 return m_data;
281}
282
283const Status &ValueObject::GetError() {
284 UpdateValueIfNeeded(update_format: false);
285 return m_error;
286}
287
288const char *ValueObject::GetLocationAsCStringImpl(const Value &value,
289 const DataExtractor &data) {
290 if (UpdateValueIfNeeded(update_format: false)) {
291 if (m_location_str.empty()) {
292 StreamString sstr;
293
294 Value::ValueType value_type = value.GetValueType();
295
296 switch (value_type) {
297 case Value::ValueType::Invalid:
298 m_location_str = "invalid";
299 break;
300 case Value::ValueType::Scalar:
301 if (value.GetContextType() == Value::ContextType::RegisterInfo) {
302 RegisterInfo *reg_info = value.GetRegisterInfo();
303 if (reg_info) {
304 if (reg_info->name)
305 m_location_str = reg_info->name;
306 else if (reg_info->alt_name)
307 m_location_str = reg_info->alt_name;
308 if (m_location_str.empty())
309 m_location_str = (reg_info->encoding == lldb::eEncodingVector)
310 ? "vector"
311 : "scalar";
312 }
313 }
314 if (m_location_str.empty())
315 m_location_str = "scalar";
316 break;
317
318 case Value::ValueType::LoadAddress:
319 case Value::ValueType::FileAddress:
320 case Value::ValueType::HostAddress: {
321 uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
322 sstr.Printf(format: "0x%*.*llx", addr_nibble_size, addr_nibble_size,
323 value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
324 m_location_str = std::string(sstr.GetString());
325 } break;
326 }
327 }
328 }
329 return m_location_str.c_str();
330}
331
332bool ValueObject::ResolveValue(Scalar &scalar) {
333 if (UpdateValueIfNeeded(
334 update_format: false)) // make sure that you are up to date before returning anything
335 {
336 ExecutionContext exe_ctx(GetExecutionContextRef());
337 Value tmp_value(m_value);
338 scalar = tmp_value.ResolveValue(exe_ctx: &exe_ctx, module: GetModule().get());
339 if (scalar.IsValid()) {
340 const uint32_t bitfield_bit_size = GetBitfieldBitSize();
341 if (bitfield_bit_size)
342 return scalar.ExtractBitfield(bit_size: bitfield_bit_size,
343 bit_offset: GetBitfieldBitOffset());
344 return true;
345 }
346 }
347 return false;
348}
349
350bool ValueObject::IsLogicalTrue(Status &error) {
351 if (Language *language = Language::FindPlugin(language: GetObjectRuntimeLanguage())) {
352 LazyBool is_logical_true = language->IsLogicalTrue(valobj&: *this, error);
353 switch (is_logical_true) {
354 case eLazyBoolYes:
355 case eLazyBoolNo:
356 return (is_logical_true == true);
357 case eLazyBoolCalculate:
358 break;
359 }
360 }
361
362 Scalar scalar_value;
363
364 if (!ResolveValue(scalar&: scalar_value)) {
365 error.SetErrorString("failed to get a scalar result");
366 return false;
367 }
368
369 bool ret;
370 ret = scalar_value.ULongLong(fail_value: 1) != 0;
371 error.Clear();
372 return ret;
373}
374
375ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {
376 ValueObjectSP child_sp;
377 // We may need to update our value if we are dynamic
378 if (IsPossibleDynamicType())
379 UpdateValueIfNeeded(update_format: false);
380 if (idx < GetNumChildrenIgnoringErrors()) {
381 // Check if we have already made the child value object?
382 if (can_create && !m_children.HasChildAtIndex(idx)) {
383 // No we haven't created the child at this index, so lets have our
384 // subclass do it and cache the result for quick future access.
385 m_children.SetChildAtIndex(idx, valobj: CreateChildAtIndex(idx, synthetic_array_member: false, synthetic_index: 0));
386 }
387
388 ValueObject *child = m_children.GetChildAtIndex(idx);
389 if (child != nullptr)
390 return child->GetSP();
391 }
392 return child_sp;
393}
394
395lldb::ValueObjectSP
396ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {
397 if (names.size() == 0)
398 return GetSP();
399 ValueObjectSP root(GetSP());
400 for (llvm::StringRef name : names) {
401 root = root->GetChildMemberWithName(name);
402 if (!root) {
403 return root;
404 }
405 }
406 return root;
407}
408
409size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {
410 bool omit_empty_base_classes = true;
411 return GetCompilerType().GetIndexOfChildWithName(name,
412 omit_empty_base_classes);
413}
414
415ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,
416 bool can_create) {
417 // We may need to update our value if we are dynamic.
418 if (IsPossibleDynamicType())
419 UpdateValueIfNeeded(update_format: false);
420
421 // When getting a child by name, it could be buried inside some base classes
422 // (which really aren't part of the expression path), so we need a vector of
423 // indexes that can get us down to the correct child.
424 std::vector<uint32_t> child_indexes;
425 bool omit_empty_base_classes = true;
426
427 if (!GetCompilerType().IsValid())
428 return ValueObjectSP();
429
430 const size_t num_child_indexes =
431 GetCompilerType().GetIndexOfChildMemberWithName(
432 name, omit_empty_base_classes, child_indexes);
433 if (num_child_indexes == 0)
434 return nullptr;
435
436 ValueObjectSP child_sp = GetSP();
437 for (uint32_t idx : child_indexes)
438 if (child_sp)
439 child_sp = child_sp->GetChildAtIndex(idx, can_create);
440 return child_sp;
441}
442
443llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {
444 UpdateValueIfNeeded();
445
446 if (max < UINT32_MAX) {
447 if (m_flags.m_children_count_valid) {
448 size_t children_count = m_children.GetChildrenCount();
449 return children_count <= max ? children_count : max;
450 } else
451 return CalculateNumChildren(max);
452 }
453
454 if (!m_flags.m_children_count_valid) {
455 auto num_children_or_err = CalculateNumChildren();
456 if (num_children_or_err)
457 SetNumChildren(*num_children_or_err);
458 else
459 return num_children_or_err;
460 }
461 return m_children.GetChildrenCount();
462}
463
464uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {
465 auto value_or_err = GetNumChildren(max);
466 if (value_or_err)
467 return *value_or_err;
468 LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),
469 "{0}");
470 return 0;
471}
472
473bool ValueObject::MightHaveChildren() {
474 bool has_children = false;
475 const uint32_t type_info = GetTypeInfo();
476 if (type_info) {
477 if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))
478 has_children = true;
479 } else {
480 has_children = GetNumChildrenIgnoringErrors() > 0;
481 }
482 return has_children;
483}
484
485// Should only be called by ValueObject::GetNumChildren()
486void ValueObject::SetNumChildren(uint32_t num_children) {
487 m_flags.m_children_count_valid = true;
488 m_children.SetChildrenCount(num_children);
489}
490
491ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
492 bool synthetic_array_member,
493 int32_t synthetic_index) {
494 ValueObject *valobj = nullptr;
495
496 bool omit_empty_base_classes = true;
497 bool ignore_array_bounds = synthetic_array_member;
498 std::string child_name_str;
499 uint32_t child_byte_size = 0;
500 int32_t child_byte_offset = 0;
501 uint32_t child_bitfield_bit_size = 0;
502 uint32_t child_bitfield_bit_offset = 0;
503 bool child_is_base_class = false;
504 bool child_is_deref_of_parent = false;
505 uint64_t language_flags = 0;
506
507 const bool transparent_pointers = !synthetic_array_member;
508 CompilerType child_compiler_type;
509
510 ExecutionContext exe_ctx(GetExecutionContextRef());
511
512 child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex(
513 exe_ctx: &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
514 ignore_array_bounds, child_name&: child_name_str, child_byte_size, child_byte_offset,
515 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
516 child_is_deref_of_parent, valobj: this, language_flags);
517 if (child_compiler_type) {
518 if (synthetic_index)
519 child_byte_offset += child_byte_size * synthetic_index;
520
521 ConstString child_name;
522 if (!child_name_str.empty())
523 child_name.SetCString(child_name_str.c_str());
524
525 valobj = new ValueObjectChild(
526 *this, child_compiler_type, child_name, child_byte_size,
527 child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
528 child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
529 language_flags);
530 }
531
532 // In case of an incomplete type, try to use the ValueObject's
533 // synthetic value to create the child ValueObject.
534 if (!valobj && synthetic_array_member) {
535 if (ValueObjectSP synth_valobj_sp = GetSyntheticValue()) {
536 valobj = synth_valobj_sp
537 ->GetChildAtIndex(idx: synthetic_index, can_create: synthetic_array_member)
538 .get();
539 }
540 }
541
542 return valobj;
543}
544
545bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
546 std::string &destination,
547 lldb::LanguageType lang) {
548 return GetSummaryAsCString(summary_ptr, destination,
549 options: TypeSummaryOptions().SetLanguage(lang));
550}
551
552bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,
553 std::string &destination,
554 const TypeSummaryOptions &options) {
555 destination.clear();
556
557 // If we have a forcefully completed type, don't try and show a summary from
558 // a valid summary string or function because the type is not complete and
559 // no member variables or member functions will be available.
560 if (GetCompilerType().IsForcefullyCompleted()) {
561 destination = "<incomplete type>";
562 return true;
563 }
564
565 // ideally we would like to bail out if passing NULL, but if we do so we end
566 // up not providing the summary for function pointers anymore
567 if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)
568 return false;
569
570 m_flags.m_is_getting_summary = true;
571
572 TypeSummaryOptions actual_options(options);
573
574 if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
575 actual_options.SetLanguage(GetPreferredDisplayLanguage());
576
577 // this is a hot path in code and we prefer to avoid setting this string all
578 // too often also clearing out other information that we might care to see in
579 // a crash log. might be useful in very specific situations though.
580 /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.
581 Summary provider's description is %s",
582 GetTypeName().GetCString(),
583 GetName().GetCString(),
584 summary_ptr->GetDescription().c_str());*/
585
586 if (UpdateValueIfNeeded(update_format: false) && summary_ptr) {
587 if (HasSyntheticValue())
588 m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on
589 // the synthetic children being
590 // up-to-date (e.g. ${svar%#})
591 summary_ptr->FormatObject(valobj: this, dest&: destination, options: actual_options);
592 }
593 m_flags.m_is_getting_summary = false;
594 return !destination.empty();
595}
596
597const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {
598 if (UpdateValueIfNeeded(update_format: true) && m_summary_str.empty()) {
599 TypeSummaryOptions summary_options;
600 summary_options.SetLanguage(lang);
601 GetSummaryAsCString(summary_ptr: GetSummaryFormat().get(), destination&: m_summary_str,
602 options: summary_options);
603 }
604 if (m_summary_str.empty())
605 return nullptr;
606 return m_summary_str.c_str();
607}
608
609bool ValueObject::GetSummaryAsCString(std::string &destination,
610 const TypeSummaryOptions &options) {
611 return GetSummaryAsCString(summary_ptr: GetSummaryFormat().get(), destination, options);
612}
613
614bool ValueObject::IsCStringContainer(bool check_pointer) {
615 CompilerType pointee_or_element_compiler_type;
616 const Flags type_flags(GetTypeInfo(pointee_or_element_compiler_type: &pointee_or_element_compiler_type));
617 bool is_char_arr_ptr(type_flags.AnySet(mask: eTypeIsArray | eTypeIsPointer) &&
618 pointee_or_element_compiler_type.IsCharType());
619 if (!is_char_arr_ptr)
620 return false;
621 if (!check_pointer)
622 return true;
623 if (type_flags.Test(bit: eTypeIsArray))
624 return true;
625 addr_t cstr_address = LLDB_INVALID_ADDRESS;
626 AddressType cstr_address_type = eAddressTypeInvalid;
627 cstr_address = GetPointerValue(address_type: &cstr_address_type);
628 return (cstr_address != LLDB_INVALID_ADDRESS);
629}
630
631size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
632 uint32_t item_count) {
633 CompilerType pointee_or_element_compiler_type;
634 const uint32_t type_info = GetTypeInfo(pointee_or_element_compiler_type: &pointee_or_element_compiler_type);
635 const bool is_pointer_type = type_info & eTypeIsPointer;
636 const bool is_array_type = type_info & eTypeIsArray;
637 if (!(is_pointer_type || is_array_type))
638 return 0;
639
640 if (item_count == 0)
641 return 0;
642
643 ExecutionContext exe_ctx(GetExecutionContextRef());
644
645 std::optional<uint64_t> item_type_size =
646 pointee_or_element_compiler_type.GetByteSize(
647 exe_scope: exe_ctx.GetBestExecutionContextScope());
648 if (!item_type_size)
649 return 0;
650 const uint64_t bytes = item_count * *item_type_size;
651 const uint64_t offset = item_idx * *item_type_size;
652
653 if (item_idx == 0 && item_count == 1) // simply a deref
654 {
655 if (is_pointer_type) {
656 Status error;
657 ValueObjectSP pointee_sp = Dereference(error);
658 if (error.Fail() || pointee_sp.get() == nullptr)
659 return 0;
660 return pointee_sp->GetData(data, error);
661 } else {
662 ValueObjectSP child_sp = GetChildAtIndex(idx: 0);
663 if (child_sp.get() == nullptr)
664 return 0;
665 Status error;
666 return child_sp->GetData(data, error);
667 }
668 return true;
669 } else /* (items > 1) */
670 {
671 Status error;
672 lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;
673 lldb::DataBufferSP data_sp(heap_buf_ptr =
674 new lldb_private::DataBufferHeap());
675
676 AddressType addr_type;
677 lldb::addr_t addr = is_pointer_type ? GetPointerValue(address_type: &addr_type)
678 : GetAddressOf(scalar_is_load_address: true, address_type: &addr_type);
679
680 switch (addr_type) {
681 case eAddressTypeFile: {
682 ModuleSP module_sp(GetModule());
683 if (module_sp) {
684 addr = addr + offset;
685 Address so_addr;
686 module_sp->ResolveFileAddress(vm_addr: addr, so_addr);
687 ExecutionContext exe_ctx(GetExecutionContextRef());
688 Target *target = exe_ctx.GetTargetPtr();
689 if (target) {
690 heap_buf_ptr->SetByteSize(bytes);
691 size_t bytes_read = target->ReadMemory(
692 addr: so_addr, dst: heap_buf_ptr->GetBytes(), dst_len: bytes, error, force_live_memory: true);
693 if (error.Success()) {
694 data.SetData(data_sp);
695 return bytes_read;
696 }
697 }
698 }
699 } break;
700 case eAddressTypeLoad: {
701 ExecutionContext exe_ctx(GetExecutionContextRef());
702 Process *process = exe_ctx.GetProcessPtr();
703 if (process) {
704 heap_buf_ptr->SetByteSize(bytes);
705 size_t bytes_read = process->ReadMemory(
706 vm_addr: addr + offset, buf: heap_buf_ptr->GetBytes(), size: bytes, error);
707 if (error.Success() || bytes_read > 0) {
708 data.SetData(data_sp);
709 return bytes_read;
710 }
711 }
712 } break;
713 case eAddressTypeHost: {
714 auto max_bytes =
715 GetCompilerType().GetByteSize(exe_scope: exe_ctx.GetBestExecutionContextScope());
716 if (max_bytes && *max_bytes > offset) {
717 size_t bytes_read = std::min<uint64_t>(a: *max_bytes - offset, b: bytes);
718 addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
719 if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
720 break;
721 heap_buf_ptr->CopyData(src: (uint8_t *)(addr + offset), src_len: bytes_read);
722 data.SetData(data_sp);
723 return bytes_read;
724 }
725 } break;
726 case eAddressTypeInvalid:
727 break;
728 }
729 }
730 return 0;
731}
732
733uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {
734 UpdateValueIfNeeded(update_format: false);
735 ExecutionContext exe_ctx(GetExecutionContextRef());
736 error = m_value.GetValueAsData(exe_ctx: &exe_ctx, data, module: GetModule().get());
737 if (error.Fail()) {
738 if (m_data.GetByteSize()) {
739 data = m_data;
740 error.Clear();
741 return data.GetByteSize();
742 } else {
743 return 0;
744 }
745 }
746 data.SetAddressByteSize(m_data.GetAddressByteSize());
747 data.SetByteOrder(m_data.GetByteOrder());
748 return data.GetByteSize();
749}
750
751bool ValueObject::SetData(DataExtractor &data, Status &error) {
752 error.Clear();
753 // Make sure our value is up to date first so that our location and location
754 // type is valid.
755 if (!UpdateValueIfNeeded(update_format: false)) {
756 error.SetErrorString("unable to read value");
757 return false;
758 }
759
760 uint64_t count = 0;
761 const Encoding encoding = GetCompilerType().GetEncoding(count);
762
763 const size_t byte_size = GetByteSize().value_or(u: 0);
764
765 Value::ValueType value_type = m_value.GetValueType();
766
767 switch (value_type) {
768 case Value::ValueType::Invalid:
769 error.SetErrorString("invalid location");
770 return false;
771 case Value::ValueType::Scalar: {
772 Status set_error =
773 m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
774
775 if (!set_error.Success()) {
776 error.SetErrorStringWithFormat("unable to set scalar value: %s",
777 set_error.AsCString());
778 return false;
779 }
780 } break;
781 case Value::ValueType::LoadAddress: {
782 // If it is a load address, then the scalar value is the storage location
783 // of the data, and we have to shove this value down to that load location.
784 ExecutionContext exe_ctx(GetExecutionContextRef());
785 Process *process = exe_ctx.GetProcessPtr();
786 if (process) {
787 addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
788 size_t bytes_written = process->WriteMemory(
789 vm_addr: target_addr, buf: data.GetDataStart(), size: byte_size, error);
790 if (!error.Success())
791 return false;
792 if (bytes_written != byte_size) {
793 error.SetErrorString("unable to write value to memory");
794 return false;
795 }
796 }
797 } break;
798 case Value::ValueType::HostAddress: {
799 // If it is a host address, then we stuff the scalar as a DataBuffer into
800 // the Value's data.
801 DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
802 m_data.SetData(data_sp: buffer_sp, offset: 0);
803 data.CopyByteOrderedData(src_offset: 0, src_len: byte_size,
804 dst: const_cast<uint8_t *>(m_data.GetDataStart()),
805 dst_len: byte_size, dst_byte_order: m_data.GetByteOrder());
806 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
807 } break;
808 case Value::ValueType::FileAddress:
809 break;
810 }
811
812 // If we have reached this point, then we have successfully changed the
813 // value.
814 SetNeedsUpdate();
815 return true;
816}
817
818static bool CopyStringDataToBufferSP(const StreamString &source,
819 lldb::WritableDataBufferSP &destination) {
820 llvm::StringRef src = source.GetString();
821 src = src.rtrim(Char: '\0');
822 destination = std::make_shared<DataBufferHeap>(args: src.size(), args: 0);
823 memcpy(dest: destination->GetBytes(), src: src.data(), n: src.size());
824 return true;
825}
826
827std::pair<size_t, bool>
828ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
829 Status &error, bool honor_array) {
830 bool was_capped = false;
831 StreamString s;
832 ExecutionContext exe_ctx(GetExecutionContextRef());
833 Target *target = exe_ctx.GetTargetPtr();
834
835 if (!target) {
836 s << "<no target to read from>";
837 error.SetErrorString("no target to read from");
838 CopyStringDataToBufferSP(source: s, destination&: buffer_sp);
839 return {0, was_capped};
840 }
841
842 const auto max_length = target->GetMaximumSizeOfStringSummary();
843
844 size_t bytes_read = 0;
845 size_t total_bytes_read = 0;
846
847 CompilerType compiler_type = GetCompilerType();
848 CompilerType elem_or_pointee_compiler_type;
849 const Flags type_flags(GetTypeInfo(pointee_or_element_compiler_type: &elem_or_pointee_compiler_type));
850 if (type_flags.AnySet(mask: eTypeIsArray | eTypeIsPointer) &&
851 elem_or_pointee_compiler_type.IsCharType()) {
852 addr_t cstr_address = LLDB_INVALID_ADDRESS;
853 AddressType cstr_address_type = eAddressTypeInvalid;
854
855 size_t cstr_len = 0;
856 bool capped_data = false;
857 const bool is_array = type_flags.Test(bit: eTypeIsArray);
858 if (is_array) {
859 // We have an array
860 uint64_t array_size = 0;
861 if (compiler_type.IsArrayType(element_type: nullptr, size: &array_size)) {
862 cstr_len = array_size;
863 if (cstr_len > max_length) {
864 capped_data = true;
865 cstr_len = max_length;
866 }
867 }
868 cstr_address = GetAddressOf(scalar_is_load_address: true, address_type: &cstr_address_type);
869 } else {
870 // We have a pointer
871 cstr_address = GetPointerValue(address_type: &cstr_address_type);
872 }
873
874 if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {
875 if (cstr_address_type == eAddressTypeHost && is_array) {
876 const char *cstr = GetDataExtractor().PeekCStr(offset: 0);
877 if (cstr == nullptr) {
878 s << "<invalid address>";
879 error.SetErrorString("invalid address");
880 CopyStringDataToBufferSP(source: s, destination&: buffer_sp);
881 return {0, was_capped};
882 }
883 s << llvm::StringRef(cstr, cstr_len);
884 CopyStringDataToBufferSP(source: s, destination&: buffer_sp);
885 return {cstr_len, was_capped};
886 } else {
887 s << "<invalid address>";
888 error.SetErrorString("invalid address");
889 CopyStringDataToBufferSP(source: s, destination&: buffer_sp);
890 return {0, was_capped};
891 }
892 }
893
894 Address cstr_so_addr(cstr_address);
895 DataExtractor data;
896 if (cstr_len > 0 && honor_array) {
897 // I am using GetPointeeData() here to abstract the fact that some
898 // ValueObjects are actually frozen pointers in the host but the pointed-
899 // to data lives in the debuggee, and GetPointeeData() automatically
900 // takes care of this
901 GetPointeeData(data, item_idx: 0, item_count: cstr_len);
902
903 if ((bytes_read = data.GetByteSize()) > 0) {
904 total_bytes_read = bytes_read;
905 for (size_t offset = 0; offset < bytes_read; offset++)
906 s.Printf(format: "%c", *data.PeekData(offset, length: 1));
907 if (capped_data)
908 was_capped = true;
909 }
910 } else {
911 cstr_len = max_length;
912 const size_t k_max_buf_size = 64;
913
914 size_t offset = 0;
915
916 int cstr_len_displayed = -1;
917 bool capped_cstr = false;
918 // I am using GetPointeeData() here to abstract the fact that some
919 // ValueObjects are actually frozen pointers in the host but the pointed-
920 // to data lives in the debuggee, and GetPointeeData() automatically
921 // takes care of this
922 while ((bytes_read = GetPointeeData(data, item_idx: offset, item_count: k_max_buf_size)) > 0) {
923 total_bytes_read += bytes_read;
924 const char *cstr = data.PeekCStr(offset: 0);
925 size_t len = strnlen(string: cstr, maxlen: k_max_buf_size);
926 if (cstr_len_displayed < 0)
927 cstr_len_displayed = len;
928
929 if (len == 0)
930 break;
931 cstr_len_displayed += len;
932 if (len > bytes_read)
933 len = bytes_read;
934 if (len > cstr_len)
935 len = cstr_len;
936
937 for (size_t offset = 0; offset < bytes_read; offset++)
938 s.Printf(format: "%c", *data.PeekData(offset, length: 1));
939
940 if (len < k_max_buf_size)
941 break;
942
943 if (len >= cstr_len) {
944 capped_cstr = true;
945 break;
946 }
947
948 cstr_len -= len;
949 offset += len;
950 }
951
952 if (cstr_len_displayed >= 0) {
953 if (capped_cstr)
954 was_capped = true;
955 }
956 }
957 } else {
958 error.SetErrorString("not a string object");
959 s << "<not a string object>";
960 }
961 CopyStringDataToBufferSP(source: s, destination&: buffer_sp);
962 return {total_bytes_read, was_capped};
963}
964
965const char *ValueObject::GetObjectDescription() {
966 if (!UpdateValueIfNeeded(update_format: true))
967 return nullptr;
968
969 // Return cached value.
970 if (!m_object_desc_str.empty())
971 return m_object_desc_str.c_str();
972
973 ExecutionContext exe_ctx(GetExecutionContextRef());
974 Process *process = exe_ctx.GetProcessPtr();
975 if (!process)
976 return nullptr;
977
978 // Returns the object description produced by one language runtime.
979 auto get_object_description = [&](LanguageType language) -> const char * {
980 if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
981 StreamString s;
982 if (runtime->GetObjectDescription(str&: s, object&: *this)) {
983 m_object_desc_str.append(str: std::string(s.GetString()));
984 return m_object_desc_str.c_str();
985 }
986 }
987 return nullptr;
988 };
989
990 // Try the native language runtime first.
991 LanguageType native_language = GetObjectRuntimeLanguage();
992 if (const char *desc = get_object_description(native_language))
993 return desc;
994
995 // Try the Objective-C language runtime. This fallback is necessary
996 // for Objective-C++ and mixed Objective-C / C++ programs.
997 if (Language::LanguageIsCFamily(language: native_language))
998 return get_object_description(eLanguageTypeObjC);
999 return nullptr;
1000}
1001
1002bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
1003 std::string &destination) {
1004 if (UpdateValueIfNeeded(update_format: false))
1005 return format.FormatObject(valobj: this, dest&: destination);
1006 else
1007 return false;
1008}
1009
1010bool ValueObject::GetValueAsCString(lldb::Format format,
1011 std::string &destination) {
1012 return GetValueAsCString(format: TypeFormatImpl_Format(format), destination);
1013}
1014
1015const char *ValueObject::GetValueAsCString() {
1016 if (UpdateValueIfNeeded(update_format: true)) {
1017 lldb::TypeFormatImplSP format_sp;
1018 lldb::Format my_format = GetFormat();
1019 if (my_format == lldb::eFormatDefault) {
1020 if (m_type_format_sp)
1021 format_sp = m_type_format_sp;
1022 else {
1023 if (m_flags.m_is_bitfield_for_scalar)
1024 my_format = eFormatUnsigned;
1025 else {
1026 if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {
1027 const RegisterInfo *reg_info = m_value.GetRegisterInfo();
1028 if (reg_info)
1029 my_format = reg_info->format;
1030 } else {
1031 my_format = GetValue().GetCompilerType().GetFormat();
1032 }
1033 }
1034 }
1035 }
1036 if (my_format != m_last_format || m_value_str.empty()) {
1037 m_last_format = my_format;
1038 if (!format_sp)
1039 format_sp = std::make_shared<TypeFormatImpl_Format>(args&: my_format);
1040 if (GetValueAsCString(format: *format_sp.get(), destination&: m_value_str)) {
1041 if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {
1042 // The value was gotten successfully, so we consider the value as
1043 // changed if the value string differs
1044 SetValueDidChange(m_old_value_str != m_value_str);
1045 }
1046 }
1047 }
1048 }
1049 if (m_value_str.empty())
1050 return nullptr;
1051 return m_value_str.c_str();
1052}
1053
1054// if > 8bytes, 0 is returned. this method should mostly be used to read
1055// address values out of pointers
1056uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {
1057 // If our byte size is zero this is an aggregate type that has children
1058 if (CanProvideValue()) {
1059 Scalar scalar;
1060 if (ResolveValue(scalar)) {
1061 if (success)
1062 *success = true;
1063 scalar.MakeUnsigned();
1064 return scalar.ULongLong(fail_value);
1065 }
1066 // fallthrough, otherwise...
1067 }
1068
1069 if (success)
1070 *success = false;
1071 return fail_value;
1072}
1073
1074int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
1075 // If our byte size is zero this is an aggregate type that has children
1076 if (CanProvideValue()) {
1077 Scalar scalar;
1078 if (ResolveValue(scalar)) {
1079 if (success)
1080 *success = true;
1081 scalar.MakeSigned();
1082 return scalar.SLongLong(fail_value);
1083 }
1084 // fallthrough, otherwise...
1085 }
1086
1087 if (success)
1088 *success = false;
1089 return fail_value;
1090}
1091
1092// if any more "special cases" are added to
1093// ValueObject::DumpPrintableRepresentation() please keep this call up to date
1094// by returning true for your new special cases. We will eventually move to
1095// checking this call result before trying to display special cases
1096bool ValueObject::HasSpecialPrintableRepresentation(
1097 ValueObjectRepresentationStyle val_obj_display, Format custom_format) {
1098 Flags flags(GetTypeInfo());
1099 if (flags.AnySet(mask: eTypeIsArray | eTypeIsPointer) &&
1100 val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1101 if (IsCStringContainer(check_pointer: true) &&
1102 (custom_format == eFormatCString || custom_format == eFormatCharArray ||
1103 custom_format == eFormatChar || custom_format == eFormatVectorOfChar))
1104 return true;
1105
1106 if (flags.Test(bit: eTypeIsArray)) {
1107 if ((custom_format == eFormatBytes) ||
1108 (custom_format == eFormatBytesWithASCII))
1109 return true;
1110
1111 if ((custom_format == eFormatVectorOfChar) ||
1112 (custom_format == eFormatVectorOfFloat32) ||
1113 (custom_format == eFormatVectorOfFloat64) ||
1114 (custom_format == eFormatVectorOfSInt16) ||
1115 (custom_format == eFormatVectorOfSInt32) ||
1116 (custom_format == eFormatVectorOfSInt64) ||
1117 (custom_format == eFormatVectorOfSInt8) ||
1118 (custom_format == eFormatVectorOfUInt128) ||
1119 (custom_format == eFormatVectorOfUInt16) ||
1120 (custom_format == eFormatVectorOfUInt32) ||
1121 (custom_format == eFormatVectorOfUInt64) ||
1122 (custom_format == eFormatVectorOfUInt8))
1123 return true;
1124 }
1125 }
1126 return false;
1127}
1128
1129bool ValueObject::DumpPrintableRepresentation(
1130 Stream &s, ValueObjectRepresentationStyle val_obj_display,
1131 Format custom_format, PrintableRepresentationSpecialCases special,
1132 bool do_dump_error) {
1133
1134 // If the ValueObject has an error, we might end up dumping the type, which
1135 // is useful, but if we don't even have a type, then don't examine the object
1136 // further as that's not meaningful, only the error is.
1137 if (m_error.Fail() && !GetCompilerType().IsValid()) {
1138 if (do_dump_error)
1139 s.Printf(format: "<%s>", m_error.AsCString());
1140 return false;
1141 }
1142
1143 Flags flags(GetTypeInfo());
1144
1145 bool allow_special =
1146 (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);
1147 const bool only_special = false;
1148
1149 if (allow_special) {
1150 if (flags.AnySet(mask: eTypeIsArray | eTypeIsPointer) &&
1151 val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {
1152 // when being asked to get a printable display an array or pointer type
1153 // directly, try to "do the right thing"
1154
1155 if (IsCStringContainer(check_pointer: true) &&
1156 (custom_format == eFormatCString ||
1157 custom_format == eFormatCharArray || custom_format == eFormatChar ||
1158 custom_format ==
1159 eFormatVectorOfChar)) // print char[] & char* directly
1160 {
1161 Status error;
1162 lldb::WritableDataBufferSP buffer_sp;
1163 std::pair<size_t, bool> read_string =
1164 ReadPointedString(buffer_sp, error,
1165 honor_array: (custom_format == eFormatVectorOfChar) ||
1166 (custom_format == eFormatCharArray));
1167 lldb_private::formatters::StringPrinter::
1168 ReadBufferAndDumpToStreamOptions options(*this);
1169 options.SetData(DataExtractor(
1170 buffer_sp, lldb::eByteOrderInvalid,
1171 8)); // none of this matters for a string - pass some defaults
1172 options.SetStream(&s);
1173 options.SetPrefixToken(nullptr);
1174 options.SetQuote('"');
1175 options.SetSourceSize(buffer_sp->GetByteSize());
1176 options.SetIsTruncated(read_string.second);
1177 options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);
1178 formatters::StringPrinter::ReadBufferAndDumpToStream<
1179 lldb_private::formatters::StringPrinter::StringElementType::ASCII>(
1180 options);
1181 return !error.Fail();
1182 }
1183
1184 if (custom_format == eFormatEnum)
1185 return false;
1186
1187 // this only works for arrays, because I have no way to know when the
1188 // pointed memory ends, and no special \0 end of data marker
1189 if (flags.Test(bit: eTypeIsArray)) {
1190 if ((custom_format == eFormatBytes) ||
1191 (custom_format == eFormatBytesWithASCII)) {
1192 const size_t count = GetNumChildrenIgnoringErrors();
1193
1194 s << '[';
1195 for (size_t low = 0; low < count; low++) {
1196
1197 if (low)
1198 s << ',';
1199
1200 ValueObjectSP child = GetChildAtIndex(idx: low);
1201 if (!child.get()) {
1202 s << "<invalid child>";
1203 continue;
1204 }
1205 child->DumpPrintableRepresentation(
1206 s, val_obj_display: ValueObject::eValueObjectRepresentationStyleValue,
1207 custom_format);
1208 }
1209
1210 s << ']';
1211
1212 return true;
1213 }
1214
1215 if ((custom_format == eFormatVectorOfChar) ||
1216 (custom_format == eFormatVectorOfFloat32) ||
1217 (custom_format == eFormatVectorOfFloat64) ||
1218 (custom_format == eFormatVectorOfSInt16) ||
1219 (custom_format == eFormatVectorOfSInt32) ||
1220 (custom_format == eFormatVectorOfSInt64) ||
1221 (custom_format == eFormatVectorOfSInt8) ||
1222 (custom_format == eFormatVectorOfUInt128) ||
1223 (custom_format == eFormatVectorOfUInt16) ||
1224 (custom_format == eFormatVectorOfUInt32) ||
1225 (custom_format == eFormatVectorOfUInt64) ||
1226 (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes
1227 // with ASCII or any vector
1228 // format should be printed
1229 // directly
1230 {
1231 const size_t count = GetNumChildrenIgnoringErrors();
1232
1233 Format format = FormatManager::GetSingleItemFormat(vector_format: custom_format);
1234
1235 s << '[';
1236 for (size_t low = 0; low < count; low++) {
1237
1238 if (low)
1239 s << ',';
1240
1241 ValueObjectSP child = GetChildAtIndex(idx: low);
1242 if (!child.get()) {
1243 s << "<invalid child>";
1244 continue;
1245 }
1246 child->DumpPrintableRepresentation(
1247 s, val_obj_display: ValueObject::eValueObjectRepresentationStyleValue, custom_format: format);
1248 }
1249
1250 s << ']';
1251
1252 return true;
1253 }
1254 }
1255
1256 if ((custom_format == eFormatBoolean) ||
1257 (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||
1258 (custom_format == eFormatCharPrintable) ||
1259 (custom_format == eFormatComplexFloat) ||
1260 (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||
1261 (custom_format == eFormatHexUppercase) ||
1262 (custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||
1263 (custom_format == eFormatOSType) ||
1264 (custom_format == eFormatUnicode16) ||
1265 (custom_format == eFormatUnicode32) ||
1266 (custom_format == eFormatUnsigned) ||
1267 (custom_format == eFormatPointer) ||
1268 (custom_format == eFormatComplexInteger) ||
1269 (custom_format == eFormatComplex) ||
1270 (custom_format == eFormatDefault)) // use the [] operator
1271 return false;
1272 }
1273 }
1274
1275 if (only_special)
1276 return false;
1277
1278 bool var_success = false;
1279
1280 {
1281 llvm::StringRef str;
1282
1283 // this is a local stream that we are using to ensure that the data pointed
1284 // to by cstr survives long enough for us to copy it to its destination -
1285 // it is necessary to have this temporary storage area for cases where our
1286 // desired output is not backed by some other longer-term storage
1287 StreamString strm;
1288
1289 if (custom_format != eFormatInvalid)
1290 SetFormat(custom_format);
1291
1292 switch (val_obj_display) {
1293 case eValueObjectRepresentationStyleValue:
1294 str = GetValueAsCString();
1295 break;
1296
1297 case eValueObjectRepresentationStyleSummary:
1298 str = GetSummaryAsCString();
1299 break;
1300
1301 case eValueObjectRepresentationStyleLanguageSpecific:
1302 str = GetObjectDescription();
1303 break;
1304
1305 case eValueObjectRepresentationStyleLocation:
1306 str = GetLocationAsCString();
1307 break;
1308
1309 case eValueObjectRepresentationStyleChildrenCount:
1310 strm.Printf(format: "%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());
1311 str = strm.GetString();
1312 break;
1313
1314 case eValueObjectRepresentationStyleType:
1315 str = GetTypeName().GetStringRef();
1316 break;
1317
1318 case eValueObjectRepresentationStyleName:
1319 str = GetName().GetStringRef();
1320 break;
1321
1322 case eValueObjectRepresentationStyleExpressionPath:
1323 GetExpressionPath(s&: strm);
1324 str = strm.GetString();
1325 break;
1326 }
1327
1328 // If the requested display style produced no output, try falling back to
1329 // alternative presentations.
1330 if (str.empty()) {
1331 if (val_obj_display == eValueObjectRepresentationStyleValue)
1332 str = GetSummaryAsCString();
1333 else if (val_obj_display == eValueObjectRepresentationStyleSummary) {
1334 if (!CanProvideValue()) {
1335 strm.Printf(format: "%s @ %s", GetTypeName().AsCString(),
1336 GetLocationAsCString());
1337 str = strm.GetString();
1338 } else
1339 str = GetValueAsCString();
1340 }
1341 }
1342
1343 if (!str.empty())
1344 s << str;
1345 else {
1346 // We checked for errors at the start, but do it again here in case
1347 // realizing the value for dumping produced an error.
1348 if (m_error.Fail()) {
1349 if (do_dump_error)
1350 s.Printf(format: "<%s>", m_error.AsCString());
1351 else
1352 return false;
1353 } else if (val_obj_display == eValueObjectRepresentationStyleSummary)
1354 s.PutCString(cstr: "<no summary available>");
1355 else if (val_obj_display == eValueObjectRepresentationStyleValue)
1356 s.PutCString(cstr: "<no value available>");
1357 else if (val_obj_display ==
1358 eValueObjectRepresentationStyleLanguageSpecific)
1359 s.PutCString(cstr: "<not a valid Objective-C object>"); // edit this if we
1360 // have other runtimes
1361 // that support a
1362 // description
1363 else
1364 s.PutCString(cstr: "<no printable representation>");
1365 }
1366
1367 // we should only return false here if we could not do *anything* even if
1368 // we have an error message as output, that's a success from our callers'
1369 // perspective, so return true
1370 var_success = true;
1371
1372 if (custom_format != eFormatInvalid)
1373 SetFormat(eFormatDefault);
1374 }
1375
1376 return var_success;
1377}
1378
1379addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,
1380 AddressType *address_type) {
1381 // Can't take address of a bitfield
1382 if (IsBitfield())
1383 return LLDB_INVALID_ADDRESS;
1384
1385 if (!UpdateValueIfNeeded(update_format: false))
1386 return LLDB_INVALID_ADDRESS;
1387
1388 switch (m_value.GetValueType()) {
1389 case Value::ValueType::Invalid:
1390 return LLDB_INVALID_ADDRESS;
1391 case Value::ValueType::Scalar:
1392 if (scalar_is_load_address) {
1393 if (address_type)
1394 *address_type = eAddressTypeLoad;
1395 return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1396 }
1397 break;
1398
1399 case Value::ValueType::LoadAddress:
1400 case Value::ValueType::FileAddress: {
1401 if (address_type)
1402 *address_type = m_value.GetValueAddressType();
1403 return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1404 } break;
1405 case Value::ValueType::HostAddress: {
1406 if (address_type)
1407 *address_type = m_value.GetValueAddressType();
1408 return LLDB_INVALID_ADDRESS;
1409 } break;
1410 }
1411 if (address_type)
1412 *address_type = eAddressTypeInvalid;
1413 return LLDB_INVALID_ADDRESS;
1414}
1415
1416addr_t ValueObject::GetPointerValue(AddressType *address_type) {
1417 addr_t address = LLDB_INVALID_ADDRESS;
1418 if (address_type)
1419 *address_type = eAddressTypeInvalid;
1420
1421 if (!UpdateValueIfNeeded(update_format: false))
1422 return address;
1423
1424 switch (m_value.GetValueType()) {
1425 case Value::ValueType::Invalid:
1426 return LLDB_INVALID_ADDRESS;
1427 case Value::ValueType::Scalar:
1428 address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1429 break;
1430
1431 case Value::ValueType::HostAddress:
1432 case Value::ValueType::LoadAddress:
1433 case Value::ValueType::FileAddress: {
1434 lldb::offset_t data_offset = 0;
1435 address = m_data.GetAddress(offset_ptr: &data_offset);
1436 } break;
1437 }
1438
1439 if (address_type)
1440 *address_type = GetAddressTypeOfChildren();
1441
1442 return address;
1443}
1444
1445bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {
1446 error.Clear();
1447 // Make sure our value is up to date first so that our location and location
1448 // type is valid.
1449 if (!UpdateValueIfNeeded(update_format: false)) {
1450 error.SetErrorString("unable to read value");
1451 return false;
1452 }
1453
1454 uint64_t count = 0;
1455 const Encoding encoding = GetCompilerType().GetEncoding(count);
1456
1457 const size_t byte_size = GetByteSize().value_or(u: 0);
1458
1459 Value::ValueType value_type = m_value.GetValueType();
1460
1461 if (value_type == Value::ValueType::Scalar) {
1462 // If the value is already a scalar, then let the scalar change itself:
1463 m_value.GetScalar().SetValueFromCString(s: value_str, encoding, byte_size);
1464 } else if (byte_size <= 16) {
1465 // If the value fits in a scalar, then make a new scalar and again let the
1466 // scalar code do the conversion, then figure out where to put the new
1467 // value.
1468 Scalar new_scalar;
1469 error = new_scalar.SetValueFromCString(s: value_str, encoding, byte_size);
1470 if (error.Success()) {
1471 switch (value_type) {
1472 case Value::ValueType::LoadAddress: {
1473 // If it is a load address, then the scalar value is the storage
1474 // location of the data, and we have to shove this value down to that
1475 // load location.
1476 ExecutionContext exe_ctx(GetExecutionContextRef());
1477 Process *process = exe_ctx.GetProcessPtr();
1478 if (process) {
1479 addr_t target_addr =
1480 m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1481 size_t bytes_written = process->WriteScalarToMemory(
1482 vm_addr: target_addr, scalar: new_scalar, size: byte_size, error);
1483 if (!error.Success())
1484 return false;
1485 if (bytes_written != byte_size) {
1486 error.SetErrorString("unable to write value to memory");
1487 return false;
1488 }
1489 }
1490 } break;
1491 case Value::ValueType::HostAddress: {
1492 // If it is a host address, then we stuff the scalar as a DataBuffer
1493 // into the Value's data.
1494 DataExtractor new_data;
1495 new_data.SetByteOrder(m_data.GetByteOrder());
1496
1497 DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
1498 m_data.SetData(data_sp: buffer_sp, offset: 0);
1499 bool success = new_scalar.GetData(data&: new_data);
1500 if (success) {
1501 new_data.CopyByteOrderedData(
1502 src_offset: 0, src_len: byte_size, dst: const_cast<uint8_t *>(m_data.GetDataStart()),
1503 dst_len: byte_size, dst_byte_order: m_data.GetByteOrder());
1504 }
1505 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
1506
1507 } break;
1508 case Value::ValueType::Invalid:
1509 error.SetErrorString("invalid location");
1510 return false;
1511 case Value::ValueType::FileAddress:
1512 case Value::ValueType::Scalar:
1513 break;
1514 }
1515 } else {
1516 return false;
1517 }
1518 } else {
1519 // We don't support setting things bigger than a scalar at present.
1520 error.SetErrorString("unable to write aggregate data type");
1521 return false;
1522 }
1523
1524 // If we have reached this point, then we have successfully changed the
1525 // value.
1526 SetNeedsUpdate();
1527 return true;
1528}
1529
1530bool ValueObject::GetDeclaration(Declaration &decl) {
1531 decl.Clear();
1532 return false;
1533}
1534
1535void ValueObject::AddSyntheticChild(ConstString key,
1536 ValueObject *valobj) {
1537 m_synthetic_children[key] = valobj;
1538}
1539
1540ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {
1541 ValueObjectSP synthetic_child_sp;
1542 std::map<ConstString, ValueObject *>::const_iterator pos =
1543 m_synthetic_children.find(x: key);
1544 if (pos != m_synthetic_children.end())
1545 synthetic_child_sp = pos->second->GetSP();
1546 return synthetic_child_sp;
1547}
1548
1549bool ValueObject::IsPossibleDynamicType() {
1550 ExecutionContext exe_ctx(GetExecutionContextRef());
1551 Process *process = exe_ctx.GetProcessPtr();
1552 if (process)
1553 return process->IsPossibleDynamicValue(in_value&: *this);
1554 else
1555 return GetCompilerType().IsPossibleDynamicType(target_type: nullptr, check_cplusplus: true, check_objc: true);
1556}
1557
1558bool ValueObject::IsRuntimeSupportValue() {
1559 Process *process(GetProcessSP().get());
1560 if (!process)
1561 return false;
1562
1563 // We trust that the compiler did the right thing and marked runtime support
1564 // values as artificial.
1565 if (!GetVariable() || !GetVariable()->IsArtificial())
1566 return false;
1567
1568 if (auto *runtime = process->GetLanguageRuntime(language: GetVariable()->GetLanguage()))
1569 if (runtime->IsAllowedRuntimeValue(name: GetName()))
1570 return false;
1571
1572 return true;
1573}
1574
1575bool ValueObject::IsNilReference() {
1576 if (Language *language = Language::FindPlugin(language: GetObjectRuntimeLanguage())) {
1577 return language->IsNilReference(valobj&: *this);
1578 }
1579 return false;
1580}
1581
1582bool ValueObject::IsUninitializedReference() {
1583 if (Language *language = Language::FindPlugin(language: GetObjectRuntimeLanguage())) {
1584 return language->IsUninitializedReference(valobj&: *this);
1585 }
1586 return false;
1587}
1588
1589// This allows you to create an array member using and index that doesn't not
1590// fall in the normal bounds of the array. Many times structure can be defined
1591// as: struct Collection {
1592// uint32_t item_count;
1593// Item item_array[0];
1594// };
1595// The size of the "item_array" is 1, but many times in practice there are more
1596// items in "item_array".
1597
1598ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,
1599 bool can_create) {
1600 ValueObjectSP synthetic_child_sp;
1601 if (IsPointerType() || IsArrayType()) {
1602 std::string index_str = llvm::formatv(Fmt: "[{0}]", Vals&: index);
1603 ConstString index_const_str(index_str);
1604 // Check if we have already created a synthetic array member in this valid
1605 // object. If we have we will re-use it.
1606 synthetic_child_sp = GetSyntheticChild(key: index_const_str);
1607 if (!synthetic_child_sp) {
1608 ValueObject *synthetic_child;
1609 // We haven't made a synthetic array member for INDEX yet, so lets make
1610 // one and cache it for any future reference.
1611 synthetic_child = CreateChildAtIndex(idx: 0, synthetic_array_member: true, synthetic_index: index);
1612
1613 // Cache the value if we got one back...
1614 if (synthetic_child) {
1615 AddSyntheticChild(key: index_const_str, valobj: synthetic_child);
1616 synthetic_child_sp = synthetic_child->GetSP();
1617 synthetic_child_sp->SetName(ConstString(index_str));
1618 synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;
1619 }
1620 }
1621 }
1622 return synthetic_child_sp;
1623}
1624
1625ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,
1626 bool can_create) {
1627 ValueObjectSP synthetic_child_sp;
1628 if (IsScalarType()) {
1629 std::string index_str = llvm::formatv(Fmt: "[{0}-{1}]", Vals&: from, Vals&: to);
1630 ConstString index_const_str(index_str);
1631 // Check if we have already created a synthetic array member in this valid
1632 // object. If we have we will re-use it.
1633 synthetic_child_sp = GetSyntheticChild(key: index_const_str);
1634 if (!synthetic_child_sp) {
1635 uint32_t bit_field_size = to - from + 1;
1636 uint32_t bit_field_offset = from;
1637 if (GetDataExtractor().GetByteOrder() == eByteOrderBig)
1638 bit_field_offset =
1639 GetByteSize().value_or(u: 0) * 8 - bit_field_size - bit_field_offset;
1640 // We haven't made a synthetic array member for INDEX yet, so lets make
1641 // one and cache it for any future reference.
1642 ValueObjectChild *synthetic_child = new ValueObjectChild(
1643 *this, GetCompilerType(), index_const_str, GetByteSize().value_or(u: 0),
1644 0, bit_field_size, bit_field_offset, false, false,
1645 eAddressTypeInvalid, 0);
1646
1647 // Cache the value if we got one back...
1648 if (synthetic_child) {
1649 AddSyntheticChild(key: index_const_str, valobj: synthetic_child);
1650 synthetic_child_sp = synthetic_child->GetSP();
1651 synthetic_child_sp->SetName(ConstString(index_str));
1652 synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;
1653 }
1654 }
1655 }
1656 return synthetic_child_sp;
1657}
1658
1659ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
1660 uint32_t offset, const CompilerType &type, bool can_create,
1661 ConstString name_const_str) {
1662
1663 ValueObjectSP synthetic_child_sp;
1664
1665 if (name_const_str.IsEmpty()) {
1666 name_const_str.SetString("@" + std::to_string(val: offset));
1667 }
1668
1669 // Check if we have already created a synthetic array member in this valid
1670 // object. If we have we will re-use it.
1671 synthetic_child_sp = GetSyntheticChild(key: name_const_str);
1672
1673 if (synthetic_child_sp.get())
1674 return synthetic_child_sp;
1675
1676 if (!can_create)
1677 return {};
1678
1679 ExecutionContext exe_ctx(GetExecutionContextRef());
1680 std::optional<uint64_t> size =
1681 type.GetByteSize(exe_scope: exe_ctx.GetBestExecutionContextScope());
1682 if (!size)
1683 return {};
1684 ValueObjectChild *synthetic_child =
1685 new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
1686 false, false, eAddressTypeInvalid, 0);
1687 if (synthetic_child) {
1688 AddSyntheticChild(key: name_const_str, valobj: synthetic_child);
1689 synthetic_child_sp = synthetic_child->GetSP();
1690 synthetic_child_sp->SetName(name_const_str);
1691 synthetic_child_sp->m_flags.m_is_child_at_offset = true;
1692 }
1693 return synthetic_child_sp;
1694}
1695
1696ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
1697 const CompilerType &type,
1698 bool can_create,
1699 ConstString name_const_str) {
1700 ValueObjectSP synthetic_child_sp;
1701
1702 if (name_const_str.IsEmpty()) {
1703 char name_str[128];
1704 snprintf(s: name_str, maxlen: sizeof(name_str), format: "base%s@%i",
1705 type.GetTypeName().AsCString(value_if_empty: "<unknown>"), offset);
1706 name_const_str.SetCString(name_str);
1707 }
1708
1709 // Check if we have already created a synthetic array member in this valid
1710 // object. If we have we will re-use it.
1711 synthetic_child_sp = GetSyntheticChild(key: name_const_str);
1712
1713 if (synthetic_child_sp.get())
1714 return synthetic_child_sp;
1715
1716 if (!can_create)
1717 return {};
1718
1719 const bool is_base_class = true;
1720
1721 ExecutionContext exe_ctx(GetExecutionContextRef());
1722 std::optional<uint64_t> size =
1723 type.GetByteSize(exe_scope: exe_ctx.GetBestExecutionContextScope());
1724 if (!size)
1725 return {};
1726 ValueObjectChild *synthetic_child =
1727 new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
1728 is_base_class, false, eAddressTypeInvalid, 0);
1729 if (synthetic_child) {
1730 AddSyntheticChild(key: name_const_str, valobj: synthetic_child);
1731 synthetic_child_sp = synthetic_child->GetSP();
1732 synthetic_child_sp->SetName(name_const_str);
1733 }
1734 return synthetic_child_sp;
1735}
1736
1737// your expression path needs to have a leading . or -> (unless it somehow
1738// "looks like" an array, in which case it has a leading [ symbol). while the [
1739// is meaningful and should be shown to the user, . and -> are just parser
1740// design, but by no means added information for the user.. strip them off
1741static const char *SkipLeadingExpressionPathSeparators(const char *expression) {
1742 if (!expression || !expression[0])
1743 return expression;
1744 if (expression[0] == '.')
1745 return expression + 1;
1746 if (expression[0] == '-' && expression[1] == '>')
1747 return expression + 2;
1748 return expression;
1749}
1750
1751ValueObjectSP
1752ValueObject::GetSyntheticExpressionPathChild(const char *expression,
1753 bool can_create) {
1754 ValueObjectSP synthetic_child_sp;
1755 ConstString name_const_string(expression);
1756 // Check if we have already created a synthetic array member in this valid
1757 // object. If we have we will re-use it.
1758 synthetic_child_sp = GetSyntheticChild(key: name_const_string);
1759 if (!synthetic_child_sp) {
1760 // We haven't made a synthetic array member for expression yet, so lets
1761 // make one and cache it for any future reference.
1762 synthetic_child_sp = GetValueForExpressionPath(
1763 expression, reason_to_stop: nullptr, final_value_type: nullptr,
1764 options: GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(
1765 GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
1766 None));
1767
1768 // Cache the value if we got one back...
1769 if (synthetic_child_sp.get()) {
1770 // FIXME: this causes a "real" child to end up with its name changed to
1771 // the contents of expression
1772 AddSyntheticChild(key: name_const_string, valobj: synthetic_child_sp.get());
1773 synthetic_child_sp->SetName(
1774 ConstString(SkipLeadingExpressionPathSeparators(expression)));
1775 }
1776 }
1777 return synthetic_child_sp;
1778}
1779
1780void ValueObject::CalculateSyntheticValue() {
1781 TargetSP target_sp(GetTargetSP());
1782 if (target_sp && !target_sp->GetEnableSyntheticValue()) {
1783 m_synthetic_value = nullptr;
1784 return;
1785 }
1786
1787 lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
1788
1789 if (!UpdateFormatsIfNeeded() && m_synthetic_value)
1790 return;
1791
1792 if (m_synthetic_children_sp.get() == nullptr)
1793 return;
1794
1795 if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
1796 return;
1797
1798 m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
1799}
1800
1801void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {
1802 if (use_dynamic == eNoDynamicValues)
1803 return;
1804
1805 if (!m_dynamic_value && !IsDynamic()) {
1806 ExecutionContext exe_ctx(GetExecutionContextRef());
1807 Process *process = exe_ctx.GetProcessPtr();
1808 if (process && process->IsPossibleDynamicValue(in_value&: *this)) {
1809 ClearDynamicTypeInformation();
1810 m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);
1811 }
1812 }
1813}
1814
1815ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {
1816 if (use_dynamic == eNoDynamicValues)
1817 return ValueObjectSP();
1818
1819 if (!IsDynamic() && m_dynamic_value == nullptr) {
1820 CalculateDynamicValue(use_dynamic);
1821 }
1822 if (m_dynamic_value && m_dynamic_value->GetError().Success())
1823 return m_dynamic_value->GetSP();
1824 else
1825 return ValueObjectSP();
1826}
1827
1828ValueObjectSP ValueObject::GetSyntheticValue() {
1829 CalculateSyntheticValue();
1830
1831 if (m_synthetic_value)
1832 return m_synthetic_value->GetSP();
1833 else
1834 return ValueObjectSP();
1835}
1836
1837bool ValueObject::HasSyntheticValue() {
1838 UpdateFormatsIfNeeded();
1839
1840 if (m_synthetic_children_sp.get() == nullptr)
1841 return false;
1842
1843 CalculateSyntheticValue();
1844
1845 return m_synthetic_value != nullptr;
1846}
1847
1848ValueObject *ValueObject::GetNonBaseClassParent() {
1849 if (GetParent()) {
1850 if (GetParent()->IsBaseClass())
1851 return GetParent()->GetNonBaseClassParent();
1852 else
1853 return GetParent();
1854 }
1855 return nullptr;
1856}
1857
1858bool ValueObject::IsBaseClass(uint32_t &depth) {
1859 if (!IsBaseClass()) {
1860 depth = 0;
1861 return false;
1862 }
1863 if (GetParent()) {
1864 GetParent()->IsBaseClass(depth);
1865 depth = depth + 1;
1866 return true;
1867 }
1868 // TODO: a base of no parent? weird..
1869 depth = 1;
1870 return true;
1871}
1872
1873void ValueObject::GetExpressionPath(Stream &s,
1874 GetExpressionPathFormat epformat) {
1875 // synthetic children do not actually "exist" as part of the hierarchy, and
1876 // sometimes they are consed up in ways that don't make sense from an
1877 // underlying language/API standpoint. So, use a special code path here to
1878 // return something that can hopefully be used in expression
1879 if (m_flags.m_is_synthetic_children_generated) {
1880 UpdateValueIfNeeded();
1881
1882 if (m_value.GetValueType() == Value::ValueType::LoadAddress) {
1883 if (IsPointerOrReferenceType()) {
1884 s.Printf(format: "((%s)0x%" PRIx64 ")", GetTypeName().AsCString(value_if_empty: "void"),
1885 GetValueAsUnsigned(fail_value: 0));
1886 return;
1887 } else {
1888 uint64_t load_addr =
1889 m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
1890 if (load_addr != LLDB_INVALID_ADDRESS) {
1891 s.Printf(format: "(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString(value_if_empty: "void"),
1892 load_addr);
1893 return;
1894 }
1895 }
1896 }
1897
1898 if (CanProvideValue()) {
1899 s.Printf(format: "((%s)%s)", GetTypeName().AsCString(value_if_empty: "void"),
1900 GetValueAsCString());
1901 return;
1902 }
1903
1904 return;
1905 }
1906
1907 const bool is_deref_of_parent = IsDereferenceOfParent();
1908
1909 if (is_deref_of_parent &&
1910 epformat == eGetExpressionPathFormatDereferencePointers) {
1911 // this is the original format of GetExpressionPath() producing code like
1912 // *(a_ptr).memberName, which is entirely fine, until you put this into
1913 // StackFrame::GetValueForVariableExpressionPath() which prefers to see
1914 // a_ptr->memberName. the eHonorPointers mode is meant to produce strings
1915 // in this latter format
1916 s.PutCString(cstr: "*(");
1917 }
1918
1919 ValueObject *parent = GetParent();
1920
1921 if (parent)
1922 parent->GetExpressionPath(s, epformat);
1923
1924 // if we are a deref_of_parent just because we are synthetic array members
1925 // made up to allow ptr[%d] syntax to work in variable printing, then add our
1926 // name ([%d]) to the expression path
1927 if (m_flags.m_is_array_item_for_pointer &&
1928 epformat == eGetExpressionPathFormatHonorPointers)
1929 s.PutCString(cstr: m_name.GetStringRef());
1930
1931 if (!IsBaseClass()) {
1932 if (!is_deref_of_parent) {
1933 ValueObject *non_base_class_parent = GetNonBaseClassParent();
1934 if (non_base_class_parent &&
1935 !non_base_class_parent->GetName().IsEmpty()) {
1936 CompilerType non_base_class_parent_compiler_type =
1937 non_base_class_parent->GetCompilerType();
1938 if (non_base_class_parent_compiler_type) {
1939 if (parent && parent->IsDereferenceOfParent() &&
1940 epformat == eGetExpressionPathFormatHonorPointers) {
1941 s.PutCString(cstr: "->");
1942 } else {
1943 const uint32_t non_base_class_parent_type_info =
1944 non_base_class_parent_compiler_type.GetTypeInfo();
1945
1946 if (non_base_class_parent_type_info & eTypeIsPointer) {
1947 s.PutCString(cstr: "->");
1948 } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
1949 !(non_base_class_parent_type_info & eTypeIsArray)) {
1950 s.PutChar(ch: '.');
1951 }
1952 }
1953 }
1954 }
1955
1956 const char *name = GetName().GetCString();
1957 if (name)
1958 s.PutCString(cstr: name);
1959 }
1960 }
1961
1962 if (is_deref_of_parent &&
1963 epformat == eGetExpressionPathFormatDereferencePointers) {
1964 s.PutChar(ch: ')');
1965 }
1966}
1967
1968ValueObjectSP ValueObject::GetValueForExpressionPath(
1969 llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
1970 ExpressionPathEndResultType *final_value_type,
1971 const GetValueForExpressionPathOptions &options,
1972 ExpressionPathAftermath *final_task_on_target) {
1973
1974 ExpressionPathScanEndReason dummy_reason_to_stop =
1975 ValueObject::eExpressionPathScanEndReasonUnknown;
1976 ExpressionPathEndResultType dummy_final_value_type =
1977 ValueObject::eExpressionPathEndResultTypeInvalid;
1978 ExpressionPathAftermath dummy_final_task_on_target =
1979 ValueObject::eExpressionPathAftermathNothing;
1980
1981 ValueObjectSP ret_val = GetValueForExpressionPath_Impl(
1982 expression_cstr: expression, reason_to_stop: reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
1983 final_value_type: final_value_type ? final_value_type : &dummy_final_value_type, options,
1984 final_task_on_target: final_task_on_target ? final_task_on_target
1985 : &dummy_final_task_on_target);
1986
1987 if (!final_task_on_target ||
1988 *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
1989 return ret_val;
1990
1991 if (ret_val.get() &&
1992 ((final_value_type ? *final_value_type : dummy_final_value_type) ==
1993 eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress
1994 // of plain objects
1995 {
1996 if ((final_task_on_target ? *final_task_on_target
1997 : dummy_final_task_on_target) ==
1998 ValueObject::eExpressionPathAftermathDereference) {
1999 Status error;
2000 ValueObjectSP final_value = ret_val->Dereference(error);
2001 if (error.Fail() || !final_value.get()) {
2002 if (reason_to_stop)
2003 *reason_to_stop =
2004 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2005 if (final_value_type)
2006 *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2007 return ValueObjectSP();
2008 } else {
2009 if (final_task_on_target)
2010 *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2011 return final_value;
2012 }
2013 }
2014 if (*final_task_on_target ==
2015 ValueObject::eExpressionPathAftermathTakeAddress) {
2016 Status error;
2017 ValueObjectSP final_value = ret_val->AddressOf(error);
2018 if (error.Fail() || !final_value.get()) {
2019 if (reason_to_stop)
2020 *reason_to_stop =
2021 ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
2022 if (final_value_type)
2023 *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
2024 return ValueObjectSP();
2025 } else {
2026 if (final_task_on_target)
2027 *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
2028 return final_value;
2029 }
2030 }
2031 }
2032 return ret_val; // final_task_on_target will still have its original value, so
2033 // you know I did not do it
2034}
2035
2036ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
2037 llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,
2038 ExpressionPathEndResultType *final_result,
2039 const GetValueForExpressionPathOptions &options,
2040 ExpressionPathAftermath *what_next) {
2041 ValueObjectSP root = GetSP();
2042
2043 if (!root)
2044 return nullptr;
2045
2046 llvm::StringRef remainder = expression;
2047
2048 while (true) {
2049 llvm::StringRef temp_expression = remainder;
2050
2051 CompilerType root_compiler_type = root->GetCompilerType();
2052 CompilerType pointee_compiler_type;
2053 Flags pointee_compiler_type_info;
2054
2055 Flags root_compiler_type_info(
2056 root_compiler_type.GetTypeInfo(pointee_or_element_compiler_type: &pointee_compiler_type));
2057 if (pointee_compiler_type)
2058 pointee_compiler_type_info.Reset(flags: pointee_compiler_type.GetTypeInfo());
2059
2060 if (temp_expression.empty()) {
2061 *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
2062 return root;
2063 }
2064
2065 switch (temp_expression.front()) {
2066 case '-': {
2067 temp_expression = temp_expression.drop_front();
2068 if (options.m_check_dot_vs_arrow_syntax &&
2069 root_compiler_type_info.Test(bit: eTypeIsPointer)) // if you are trying to
2070 // use -> on a
2071 // non-pointer and I
2072 // must catch the error
2073 {
2074 *reason_to_stop =
2075 ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
2076 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2077 return ValueObjectSP();
2078 }
2079 if (root_compiler_type_info.Test(bit: eTypeIsObjC) && // if yo are trying to
2080 // extract an ObjC IVar
2081 // when this is forbidden
2082 root_compiler_type_info.Test(bit: eTypeIsPointer) &&
2083 options.m_no_fragile_ivar) {
2084 *reason_to_stop =
2085 ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
2086 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2087 return ValueObjectSP();
2088 }
2089 if (!temp_expression.starts_with(Prefix: ">")) {
2090 *reason_to_stop =
2091 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2092 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2093 return ValueObjectSP();
2094 }
2095 }
2096 [[fallthrough]];
2097 case '.': // or fallthrough from ->
2098 {
2099 if (options.m_check_dot_vs_arrow_syntax &&
2100 temp_expression.front() == '.' &&
2101 root_compiler_type_info.Test(bit: eTypeIsPointer)) // if you are trying to
2102 // use . on a pointer
2103 // and I must catch the
2104 // error
2105 {
2106 *reason_to_stop =
2107 ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
2108 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2109 return nullptr;
2110 }
2111 temp_expression = temp_expression.drop_front(); // skip . or >
2112
2113 size_t next_sep_pos = temp_expression.find_first_of(Chars: "-.[", From: 1);
2114 if (next_sep_pos == llvm::StringRef::npos) // if no other separator just
2115 // expand this last layer
2116 {
2117 llvm::StringRef child_name = temp_expression;
2118 ValueObjectSP child_valobj_sp =
2119 root->GetChildMemberWithName(name: child_name);
2120
2121 if (child_valobj_sp.get()) // we know we are done, so just return
2122 {
2123 *reason_to_stop =
2124 ValueObject::eExpressionPathScanEndReasonEndOfString;
2125 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2126 return child_valobj_sp;
2127 } else {
2128 switch (options.m_synthetic_children_traversal) {
2129 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2130 None:
2131 break;
2132 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2133 FromSynthetic:
2134 if (root->IsSynthetic()) {
2135 child_valobj_sp = root->GetNonSyntheticValue();
2136 if (child_valobj_sp.get())
2137 child_valobj_sp =
2138 child_valobj_sp->GetChildMemberWithName(name: child_name);
2139 }
2140 break;
2141 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2142 ToSynthetic:
2143 if (!root->IsSynthetic()) {
2144 child_valobj_sp = root->GetSyntheticValue();
2145 if (child_valobj_sp.get())
2146 child_valobj_sp =
2147 child_valobj_sp->GetChildMemberWithName(name: child_name);
2148 }
2149 break;
2150 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2151 Both:
2152 if (root->IsSynthetic()) {
2153 child_valobj_sp = root->GetNonSyntheticValue();
2154 if (child_valobj_sp.get())
2155 child_valobj_sp =
2156 child_valobj_sp->GetChildMemberWithName(name: child_name);
2157 } else {
2158 child_valobj_sp = root->GetSyntheticValue();
2159 if (child_valobj_sp.get())
2160 child_valobj_sp =
2161 child_valobj_sp->GetChildMemberWithName(name: child_name);
2162 }
2163 break;
2164 }
2165 }
2166
2167 // if we are here and options.m_no_synthetic_children is true,
2168 // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2169 // branch, and return an error
2170 if (child_valobj_sp.get()) // if it worked, just return
2171 {
2172 *reason_to_stop =
2173 ValueObject::eExpressionPathScanEndReasonEndOfString;
2174 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2175 return child_valobj_sp;
2176 } else {
2177 *reason_to_stop =
2178 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2179 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2180 return nullptr;
2181 }
2182 } else // other layers do expand
2183 {
2184 llvm::StringRef next_separator = temp_expression.substr(Start: next_sep_pos);
2185 llvm::StringRef child_name = temp_expression.slice(Start: 0, End: next_sep_pos);
2186
2187 ValueObjectSP child_valobj_sp =
2188 root->GetChildMemberWithName(name: child_name);
2189 if (child_valobj_sp.get()) // store the new root and move on
2190 {
2191 root = child_valobj_sp;
2192 remainder = next_separator;
2193 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2194 continue;
2195 } else {
2196 switch (options.m_synthetic_children_traversal) {
2197 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2198 None:
2199 break;
2200 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2201 FromSynthetic:
2202 if (root->IsSynthetic()) {
2203 child_valobj_sp = root->GetNonSyntheticValue();
2204 if (child_valobj_sp.get())
2205 child_valobj_sp =
2206 child_valobj_sp->GetChildMemberWithName(name: child_name);
2207 }
2208 break;
2209 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2210 ToSynthetic:
2211 if (!root->IsSynthetic()) {
2212 child_valobj_sp = root->GetSyntheticValue();
2213 if (child_valobj_sp.get())
2214 child_valobj_sp =
2215 child_valobj_sp->GetChildMemberWithName(name: child_name);
2216 }
2217 break;
2218 case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2219 Both:
2220 if (root->IsSynthetic()) {
2221 child_valobj_sp = root->GetNonSyntheticValue();
2222 if (child_valobj_sp.get())
2223 child_valobj_sp =
2224 child_valobj_sp->GetChildMemberWithName(name: child_name);
2225 } else {
2226 child_valobj_sp = root->GetSyntheticValue();
2227 if (child_valobj_sp.get())
2228 child_valobj_sp =
2229 child_valobj_sp->GetChildMemberWithName(name: child_name);
2230 }
2231 break;
2232 }
2233 }
2234
2235 // if we are here and options.m_no_synthetic_children is true,
2236 // child_valobj_sp is going to be a NULL SP, so we hit the "else"
2237 // branch, and return an error
2238 if (child_valobj_sp.get()) // if it worked, move on
2239 {
2240 root = child_valobj_sp;
2241 remainder = next_separator;
2242 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2243 continue;
2244 } else {
2245 *reason_to_stop =
2246 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2247 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2248 return nullptr;
2249 }
2250 }
2251 break;
2252 }
2253 case '[': {
2254 if (!root_compiler_type_info.Test(bit: eTypeIsArray) &&
2255 !root_compiler_type_info.Test(bit: eTypeIsPointer) &&
2256 !root_compiler_type_info.Test(
2257 bit: eTypeIsVector)) // if this is not a T[] nor a T*
2258 {
2259 if (!root_compiler_type_info.Test(
2260 bit: eTypeIsScalar)) // if this is not even a scalar...
2261 {
2262 if (options.m_synthetic_children_traversal ==
2263 GetValueForExpressionPathOptions::SyntheticChildrenTraversal::
2264 None) // ...only chance left is synthetic
2265 {
2266 *reason_to_stop =
2267 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
2268 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2269 return ValueObjectSP();
2270 }
2271 } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,
2272 // check that we can
2273 // expand bitfields
2274 {
2275 *reason_to_stop =
2276 ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
2277 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2278 return ValueObjectSP();
2279 }
2280 }
2281 if (temp_expression[1] ==
2282 ']') // if this is an unbounded range it only works for arrays
2283 {
2284 if (!root_compiler_type_info.Test(bit: eTypeIsArray)) {
2285 *reason_to_stop =
2286 ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
2287 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2288 return nullptr;
2289 } else // even if something follows, we cannot expand unbounded ranges,
2290 // just let the caller do it
2291 {
2292 *reason_to_stop =
2293 ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2294 *final_result =
2295 ValueObject::eExpressionPathEndResultTypeUnboundedRange;
2296 return root;
2297 }
2298 }
2299
2300 size_t close_bracket_position = temp_expression.find(C: ']', From: 1);
2301 if (close_bracket_position ==
2302 llvm::StringRef::npos) // if there is no ], this is a syntax error
2303 {
2304 *reason_to_stop =
2305 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2306 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2307 return nullptr;
2308 }
2309
2310 llvm::StringRef bracket_expr =
2311 temp_expression.slice(Start: 1, End: close_bracket_position);
2312
2313 // If this was an empty expression it would have been caught by the if
2314 // above.
2315 assert(!bracket_expr.empty());
2316
2317 if (!bracket_expr.contains(C: '-')) {
2318 // if no separator, this is of the form [N]. Note that this cannot be
2319 // an unbounded range of the form [], because that case was handled
2320 // above with an unconditional return.
2321 unsigned long index = 0;
2322 if (bracket_expr.getAsInteger(Radix: 0, Result&: index)) {
2323 *reason_to_stop =
2324 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2325 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2326 return nullptr;
2327 }
2328
2329 // from here on we do have a valid index
2330 if (root_compiler_type_info.Test(bit: eTypeIsArray)) {
2331 ValueObjectSP child_valobj_sp = root->GetChildAtIndex(idx: index);
2332 if (!child_valobj_sp)
2333 child_valobj_sp = root->GetSyntheticArrayMember(index, can_create: true);
2334 if (!child_valobj_sp)
2335 if (root->HasSyntheticValue() &&
2336 llvm::expectedToStdOptional(
2337 E: root->GetSyntheticValue()->GetNumChildren())
2338 .value_or(u: 0) > index)
2339 child_valobj_sp =
2340 root->GetSyntheticValue()->GetChildAtIndex(idx: index);
2341 if (child_valobj_sp) {
2342 root = child_valobj_sp;
2343 remainder =
2344 temp_expression.substr(Start: close_bracket_position + 1); // skip ]
2345 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2346 continue;
2347 } else {
2348 *reason_to_stop =
2349 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2350 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2351 return nullptr;
2352 }
2353 } else if (root_compiler_type_info.Test(bit: eTypeIsPointer)) {
2354 if (*what_next ==
2355 ValueObject::
2356 eExpressionPathAftermathDereference && // if this is a
2357 // ptr-to-scalar, I
2358 // am accessing it
2359 // by index and I
2360 // would have
2361 // deref'ed anyway,
2362 // then do it now
2363 // and use this as
2364 // a bitfield
2365 pointee_compiler_type_info.Test(bit: eTypeIsScalar)) {
2366 Status error;
2367 root = root->Dereference(error);
2368 if (error.Fail() || !root) {
2369 *reason_to_stop =
2370 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2371 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2372 return nullptr;
2373 } else {
2374 *what_next = eExpressionPathAftermathNothing;
2375 continue;
2376 }
2377 } else {
2378 if (root->GetCompilerType().GetMinimumLanguage() ==
2379 eLanguageTypeObjC &&
2380 pointee_compiler_type_info.AllClear(mask: eTypeIsPointer) &&
2381 root->HasSyntheticValue() &&
2382 (options.m_synthetic_children_traversal ==
2383 GetValueForExpressionPathOptions::
2384 SyntheticChildrenTraversal::ToSynthetic ||
2385 options.m_synthetic_children_traversal ==
2386 GetValueForExpressionPathOptions::
2387 SyntheticChildrenTraversal::Both)) {
2388 root = root->GetSyntheticValue()->GetChildAtIndex(idx: index);
2389 } else
2390 root = root->GetSyntheticArrayMember(index, can_create: true);
2391 if (!root) {
2392 *reason_to_stop =
2393 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2394 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2395 return nullptr;
2396 } else {
2397 remainder =
2398 temp_expression.substr(Start: close_bracket_position + 1); // skip ]
2399 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2400 continue;
2401 }
2402 }
2403 } else if (root_compiler_type_info.Test(bit: eTypeIsScalar)) {
2404 root = root->GetSyntheticBitFieldChild(from: index, to: index, can_create: true);
2405 if (!root) {
2406 *reason_to_stop =
2407 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2408 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2409 return nullptr;
2410 } else // we do not know how to expand members of bitfields, so we
2411 // just return and let the caller do any further processing
2412 {
2413 *reason_to_stop = ValueObject::
2414 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2415 *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2416 return root;
2417 }
2418 } else if (root_compiler_type_info.Test(bit: eTypeIsVector)) {
2419 root = root->GetChildAtIndex(idx: index);
2420 if (!root) {
2421 *reason_to_stop =
2422 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2423 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2424 return ValueObjectSP();
2425 } else {
2426 remainder =
2427 temp_expression.substr(Start: close_bracket_position + 1); // skip ]
2428 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2429 continue;
2430 }
2431 } else if (options.m_synthetic_children_traversal ==
2432 GetValueForExpressionPathOptions::
2433 SyntheticChildrenTraversal::ToSynthetic ||
2434 options.m_synthetic_children_traversal ==
2435 GetValueForExpressionPathOptions::
2436 SyntheticChildrenTraversal::Both) {
2437 if (root->HasSyntheticValue())
2438 root = root->GetSyntheticValue();
2439 else if (!root->IsSynthetic()) {
2440 *reason_to_stop =
2441 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2442 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2443 return nullptr;
2444 }
2445 // if we are here, then root itself is a synthetic VO.. should be
2446 // good to go
2447
2448 if (!root) {
2449 *reason_to_stop =
2450 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
2451 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2452 return nullptr;
2453 }
2454 root = root->GetChildAtIndex(idx: index);
2455 if (!root) {
2456 *reason_to_stop =
2457 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2458 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2459 return nullptr;
2460 } else {
2461 remainder =
2462 temp_expression.substr(Start: close_bracket_position + 1); // skip ]
2463 *final_result = ValueObject::eExpressionPathEndResultTypePlain;
2464 continue;
2465 }
2466 } else {
2467 *reason_to_stop =
2468 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2469 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2470 return nullptr;
2471 }
2472 } else {
2473 // we have a low and a high index
2474 llvm::StringRef sleft, sright;
2475 unsigned long low_index, high_index;
2476 std::tie(args&: sleft, args&: sright) = bracket_expr.split(Separator: '-');
2477 if (sleft.getAsInteger(Radix: 0, Result&: low_index) ||
2478 sright.getAsInteger(Radix: 0, Result&: high_index)) {
2479 *reason_to_stop =
2480 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2481 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2482 return nullptr;
2483 }
2484
2485 if (low_index > high_index) // swap indices if required
2486 std::swap(a&: low_index, b&: high_index);
2487
2488 if (root_compiler_type_info.Test(
2489 bit: eTypeIsScalar)) // expansion only works for scalars
2490 {
2491 root = root->GetSyntheticBitFieldChild(from: low_index, to: high_index, can_create: true);
2492 if (!root) {
2493 *reason_to_stop =
2494 ValueObject::eExpressionPathScanEndReasonNoSuchChild;
2495 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2496 return nullptr;
2497 } else {
2498 *reason_to_stop = ValueObject::
2499 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
2500 *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
2501 return root;
2502 }
2503 } else if (root_compiler_type_info.Test(
2504 bit: eTypeIsPointer) && // if this is a ptr-to-scalar, I am
2505 // accessing it by index and I would
2506 // have deref'ed anyway, then do it
2507 // now and use this as a bitfield
2508 *what_next ==
2509 ValueObject::eExpressionPathAftermathDereference &&
2510 pointee_compiler_type_info.Test(bit: eTypeIsScalar)) {
2511 Status error;
2512 root = root->Dereference(error);
2513 if (error.Fail() || !root) {
2514 *reason_to_stop =
2515 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
2516 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2517 return nullptr;
2518 } else {
2519 *what_next = ValueObject::eExpressionPathAftermathNothing;
2520 continue;
2521 }
2522 } else {
2523 *reason_to_stop =
2524 ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
2525 *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
2526 return root;
2527 }
2528 }
2529 break;
2530 }
2531 default: // some non-separator is in the way
2532 {
2533 *reason_to_stop =
2534 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
2535 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
2536 return nullptr;
2537 }
2538 }
2539 }
2540}
2541
2542void ValueObject::Dump(Stream &s) { Dump(s, options: DumpValueObjectOptions(*this)); }
2543
2544void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
2545 ValueObjectPrinter printer(*this, &s, options);
2546 printer.PrintValueObject();
2547}
2548
2549ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
2550 ValueObjectSP valobj_sp;
2551
2552 if (UpdateValueIfNeeded(update_format: false) && m_error.Success()) {
2553 ExecutionContext exe_ctx(GetExecutionContextRef());
2554
2555 DataExtractor data;
2556 data.SetByteOrder(m_data.GetByteOrder());
2557 data.SetAddressByteSize(m_data.GetAddressByteSize());
2558
2559 if (IsBitfield()) {
2560 Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
2561 m_error = v.GetValueAsData(exe_ctx: &exe_ctx, data, module: GetModule().get());
2562 } else
2563 m_error = m_value.GetValueAsData(exe_ctx: &exe_ctx, data, module: GetModule().get());
2564
2565 valobj_sp = ValueObjectConstResult::Create(
2566 exe_scope: exe_ctx.GetBestExecutionContextScope(), compiler_type: GetCompilerType(), name, data,
2567 address: GetAddressOf());
2568 }
2569
2570 if (!valobj_sp) {
2571 ExecutionContext exe_ctx(GetExecutionContextRef());
2572 valobj_sp = ValueObjectConstResult::Create(
2573 exe_scope: exe_ctx.GetBestExecutionContextScope(), error: m_error);
2574 }
2575 return valobj_sp;
2576}
2577
2578ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
2579 lldb::DynamicValueType dynValue, bool synthValue) {
2580 ValueObjectSP result_sp;
2581 switch (dynValue) {
2582 case lldb::eDynamicCanRunTarget:
2583 case lldb::eDynamicDontRunTarget: {
2584 if (!IsDynamic())
2585 result_sp = GetDynamicValue(use_dynamic: dynValue);
2586 } break;
2587 case lldb::eNoDynamicValues: {
2588 if (IsDynamic())
2589 result_sp = GetStaticValue();
2590 } break;
2591 }
2592 if (!result_sp)
2593 result_sp = GetSP();
2594 assert(result_sp);
2595
2596 bool is_synthetic = result_sp->IsSynthetic();
2597 if (synthValue && !is_synthetic) {
2598 if (auto synth_sp = result_sp->GetSyntheticValue())
2599 return synth_sp;
2600 }
2601 if (!synthValue && is_synthetic) {
2602 if (auto non_synth_sp = result_sp->GetNonSyntheticValue())
2603 return non_synth_sp;
2604 }
2605
2606 return result_sp;
2607}
2608
2609ValueObjectSP ValueObject::Dereference(Status &error) {
2610 if (m_deref_valobj)
2611 return m_deref_valobj->GetSP();
2612
2613 const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
2614 if (is_pointer_or_reference_type) {
2615 bool omit_empty_base_classes = true;
2616 bool ignore_array_bounds = false;
2617
2618 std::string child_name_str;
2619 uint32_t child_byte_size = 0;
2620 int32_t child_byte_offset = 0;
2621 uint32_t child_bitfield_bit_size = 0;
2622 uint32_t child_bitfield_bit_offset = 0;
2623 bool child_is_base_class = false;
2624 bool child_is_deref_of_parent = false;
2625 const bool transparent_pointers = false;
2626 CompilerType compiler_type = GetCompilerType();
2627 CompilerType child_compiler_type;
2628 uint64_t language_flags = 0;
2629
2630 ExecutionContext exe_ctx(GetExecutionContextRef());
2631
2632 child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex(
2633 exe_ctx: &exe_ctx, idx: 0, transparent_pointers, omit_empty_base_classes,
2634 ignore_array_bounds, child_name&: child_name_str, child_byte_size, child_byte_offset,
2635 child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
2636 child_is_deref_of_parent, valobj: this, language_flags);
2637 if (child_compiler_type && child_byte_size) {
2638 ConstString child_name;
2639 if (!child_name_str.empty())
2640 child_name.SetCString(child_name_str.c_str());
2641
2642 m_deref_valobj = new ValueObjectChild(
2643 *this, child_compiler_type, child_name, child_byte_size,
2644 child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
2645 child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
2646 language_flags);
2647 }
2648
2649 // In case of incomplete child compiler type, use the pointee type and try
2650 // to recreate a new ValueObjectChild using it.
2651 if (!m_deref_valobj) {
2652 // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.
2653 // `std::vector<int> &`). Remove ObjC restriction once that's resolved.
2654 if (Language::LanguageIsObjC(language: GetPreferredDisplayLanguage()) &&
2655 HasSyntheticValue()) {
2656 child_compiler_type = compiler_type.GetPointeeType();
2657
2658 if (child_compiler_type) {
2659 ConstString child_name;
2660 if (!child_name_str.empty())
2661 child_name.SetCString(child_name_str.c_str());
2662
2663 m_deref_valobj = new ValueObjectChild(
2664 *this, child_compiler_type, child_name, child_byte_size,
2665 child_byte_offset, child_bitfield_bit_size,
2666 child_bitfield_bit_offset, child_is_base_class,
2667 child_is_deref_of_parent, eAddressTypeInvalid, language_flags);
2668 }
2669 }
2670 }
2671
2672 } else if (HasSyntheticValue()) {
2673 m_deref_valobj =
2674 GetSyntheticValue()->GetChildMemberWithName(name: "$$dereference$$").get();
2675 } else if (IsSynthetic()) {
2676 m_deref_valobj = GetChildMemberWithName(name: "$$dereference$$").get();
2677 }
2678
2679 if (m_deref_valobj) {
2680 error.Clear();
2681 return m_deref_valobj->GetSP();
2682 } else {
2683 StreamString strm;
2684 GetExpressionPath(s&: strm);
2685
2686 if (is_pointer_or_reference_type)
2687 error.SetErrorStringWithFormat("dereference failed: (%s) %s",
2688 GetTypeName().AsCString(value_if_empty: "<invalid type>"),
2689 strm.GetData());
2690 else
2691 error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",
2692 GetTypeName().AsCString(value_if_empty: "<invalid type>"),
2693 strm.GetData());
2694 return ValueObjectSP();
2695 }
2696}
2697
2698ValueObjectSP ValueObject::AddressOf(Status &error) {
2699 if (m_addr_of_valobj_sp)
2700 return m_addr_of_valobj_sp;
2701
2702 AddressType address_type = eAddressTypeInvalid;
2703 const bool scalar_is_load_address = false;
2704 addr_t addr = GetAddressOf(scalar_is_load_address, address_type: &address_type);
2705 error.Clear();
2706 if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {
2707 switch (address_type) {
2708 case eAddressTypeInvalid: {
2709 StreamString expr_path_strm;
2710 GetExpressionPath(s&: expr_path_strm);
2711 error.SetErrorStringWithFormat("'%s' is not in memory",
2712 expr_path_strm.GetData());
2713 } break;
2714
2715 case eAddressTypeFile:
2716 case eAddressTypeLoad: {
2717 CompilerType compiler_type = GetCompilerType();
2718 if (compiler_type) {
2719 std::string name(1, '&');
2720 name.append(s: m_name.AsCString(value_if_empty: ""));
2721 ExecutionContext exe_ctx(GetExecutionContextRef());
2722 m_addr_of_valobj_sp = ValueObjectConstResult::Create(
2723 exe_scope: exe_ctx.GetBestExecutionContextScope(),
2724 compiler_type: compiler_type.GetPointerType(), name: ConstString(name.c_str()), address: addr,
2725 address_type: eAddressTypeInvalid, addr_byte_size: m_data.GetAddressByteSize());
2726 }
2727 } break;
2728 default:
2729 break;
2730 }
2731 } else {
2732 StreamString expr_path_strm;
2733 GetExpressionPath(s&: expr_path_strm);
2734 error.SetErrorStringWithFormat("'%s' doesn't have a valid address",
2735 expr_path_strm.GetData());
2736 }
2737
2738 return m_addr_of_valobj_sp;
2739}
2740
2741ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {
2742 return ValueObjectCast::Create(parent&: *this, name: GetName(), cast_type: compiler_type);
2743}
2744
2745ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {
2746 // Only allow casts if the original type is equal or larger than the cast
2747 // type, unless we know this is a load address. Getting the size wrong for
2748 // a host side storage could leak lldb memory, so we absolutely want to
2749 // prevent that. We may not always get the right value, for instance if we
2750 // have an expression result value that's copied into a storage location in
2751 // the target may not have copied enough memory. I'm not trying to fix that
2752 // here, I'm just making Cast from a smaller to a larger possible in all the
2753 // cases where that doesn't risk making a Value out of random lldb memory.
2754 // You have to check the ValueObject's Value for the address types, since
2755 // ValueObjects that use live addresses will tell you they fetch data from the
2756 // live address, but once they are made, they actually don't.
2757 // FIXME: Can we make ValueObject's with a live address fetch "more data" from
2758 // the live address if it is still valid?
2759
2760 Status error;
2761 CompilerType my_type = GetCompilerType();
2762
2763 ExecutionContextScope *exe_scope
2764 = ExecutionContext(GetExecutionContextRef())
2765 .GetBestExecutionContextScope();
2766 if (compiler_type.GetByteSize(exe_scope)
2767 <= GetCompilerType().GetByteSize(exe_scope)
2768 || m_value.GetValueType() == Value::ValueType::LoadAddress)
2769 return DoCast(compiler_type);
2770
2771 error.SetErrorString("Can only cast to a type that is equal to or smaller "
2772 "than the orignal type.");
2773
2774 return ValueObjectConstResult::Create(
2775 exe_scope: ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),
2776 error);
2777}
2778
2779lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {
2780 return ValueObjectCast::Create(parent&: *this, name: new_name, cast_type: GetCompilerType());
2781}
2782
2783ValueObjectSP ValueObject::CastPointerType(const char *name,
2784 CompilerType &compiler_type) {
2785 ValueObjectSP valobj_sp;
2786 AddressType address_type;
2787 addr_t ptr_value = GetPointerValue(address_type: &address_type);
2788
2789 if (ptr_value != LLDB_INVALID_ADDRESS) {
2790 Address ptr_addr(ptr_value);
2791 ExecutionContext exe_ctx(GetExecutionContextRef());
2792 valobj_sp = ValueObjectMemory::Create(
2793 exe_scope: exe_ctx.GetBestExecutionContextScope(), name, address: ptr_addr, ast_type: compiler_type);
2794 }
2795 return valobj_sp;
2796}
2797
2798ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
2799 ValueObjectSP valobj_sp;
2800 AddressType address_type;
2801 addr_t ptr_value = GetPointerValue(address_type: &address_type);
2802
2803 if (ptr_value != LLDB_INVALID_ADDRESS) {
2804 Address ptr_addr(ptr_value);
2805 ExecutionContext exe_ctx(GetExecutionContextRef());
2806 valobj_sp = ValueObjectMemory::Create(
2807 exe_scope: exe_ctx.GetBestExecutionContextScope(), name, address: ptr_addr, type_sp);
2808 }
2809 return valobj_sp;
2810}
2811
2812ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
2813
2814ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
2815 bool use_selected)
2816 : m_mod_id(), m_exe_ctx_ref() {
2817 ExecutionContext exe_ctx(exe_scope);
2818 TargetSP target_sp(exe_ctx.GetTargetSP());
2819 if (target_sp) {
2820 m_exe_ctx_ref.SetTargetSP(target_sp);
2821 ProcessSP process_sp(exe_ctx.GetProcessSP());
2822 if (!process_sp)
2823 process_sp = target_sp->GetProcessSP();
2824
2825 if (process_sp) {
2826 m_mod_id = process_sp->GetModID();
2827 m_exe_ctx_ref.SetProcessSP(process_sp);
2828
2829 ThreadSP thread_sp(exe_ctx.GetThreadSP());
2830
2831 if (!thread_sp) {
2832 if (use_selected)
2833 thread_sp = process_sp->GetThreadList().GetSelectedThread();
2834 }
2835
2836 if (thread_sp) {
2837 m_exe_ctx_ref.SetThreadSP(thread_sp);
2838
2839 StackFrameSP frame_sp(exe_ctx.GetFrameSP());
2840 if (!frame_sp) {
2841 if (use_selected)
2842 frame_sp = thread_sp->GetSelectedFrame(select_most_relevant: DoNoSelectMostRelevantFrame);
2843 }
2844 if (frame_sp)
2845 m_exe_ctx_ref.SetFrameSP(frame_sp);
2846 }
2847 }
2848 }
2849}
2850
2851ValueObject::EvaluationPoint::EvaluationPoint(
2852 const ValueObject::EvaluationPoint &rhs)
2853 : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}
2854
2855ValueObject::EvaluationPoint::~EvaluationPoint() = default;
2856
2857// This function checks the EvaluationPoint against the current process state.
2858// If the current state matches the evaluation point, or the evaluation point
2859// is already invalid, then we return false, meaning "no change". If the
2860// current state is different, we update our state, and return true meaning
2861// "yes, change". If we did see a change, we also set m_needs_update to true,
2862// so future calls to NeedsUpdate will return true. exe_scope will be set to
2863// the current execution context scope.
2864
2865bool ValueObject::EvaluationPoint::SyncWithProcessState(
2866 bool accept_invalid_exe_ctx) {
2867 // Start with the target, if it is NULL, then we're obviously not going to
2868 // get any further:
2869 const bool thread_and_frame_only_if_stopped = true;
2870 ExecutionContext exe_ctx(
2871 m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
2872
2873 if (exe_ctx.GetTargetPtr() == nullptr)
2874 return false;
2875
2876 // If we don't have a process nothing can change.
2877 Process *process = exe_ctx.GetProcessPtr();
2878 if (process == nullptr)
2879 return false;
2880
2881 // If our stop id is the current stop ID, nothing has changed:
2882 ProcessModID current_mod_id = process->GetModID();
2883
2884 // If the current stop id is 0, either we haven't run yet, or the process
2885 // state has been cleared. In either case, we aren't going to be able to sync
2886 // with the process state.
2887 if (current_mod_id.GetStopID() == 0)
2888 return false;
2889
2890 bool changed = false;
2891 const bool was_valid = m_mod_id.IsValid();
2892 if (was_valid) {
2893 if (m_mod_id == current_mod_id) {
2894 // Everything is already up to date in this object, no need to update the
2895 // execution context scope.
2896 changed = false;
2897 } else {
2898 m_mod_id = current_mod_id;
2899 m_needs_update = true;
2900 changed = true;
2901 }
2902 }
2903
2904 // Now re-look up the thread and frame in case the underlying objects have
2905 // gone away & been recreated. That way we'll be sure to return a valid
2906 // exe_scope. If we used to have a thread or a frame but can't find it
2907 // anymore, then mark ourselves as invalid.
2908
2909 if (!accept_invalid_exe_ctx) {
2910 if (m_exe_ctx_ref.HasThreadRef()) {
2911 ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());
2912 if (thread_sp) {
2913 if (m_exe_ctx_ref.HasFrameRef()) {
2914 StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());
2915 if (!frame_sp) {
2916 // We used to have a frame, but now it is gone
2917 SetInvalid();
2918 changed = was_valid;
2919 }
2920 }
2921 } else {
2922 // We used to have a thread, but now it is gone
2923 SetInvalid();
2924 changed = was_valid;
2925 }
2926 }
2927 }
2928
2929 return changed;
2930}
2931
2932void ValueObject::EvaluationPoint::SetUpdated() {
2933 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
2934 if (process_sp)
2935 m_mod_id = process_sp->GetModID();
2936 m_needs_update = false;
2937}
2938
2939void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {
2940 if ((clear_mask & eClearUserVisibleDataItemsValue) ==
2941 eClearUserVisibleDataItemsValue)
2942 m_value_str.clear();
2943
2944 if ((clear_mask & eClearUserVisibleDataItemsLocation) ==
2945 eClearUserVisibleDataItemsLocation)
2946 m_location_str.clear();
2947
2948 if ((clear_mask & eClearUserVisibleDataItemsSummary) ==
2949 eClearUserVisibleDataItemsSummary)
2950 m_summary_str.clear();
2951
2952 if ((clear_mask & eClearUserVisibleDataItemsDescription) ==
2953 eClearUserVisibleDataItemsDescription)
2954 m_object_desc_str.clear();
2955
2956 if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==
2957 eClearUserVisibleDataItemsSyntheticChildren) {
2958 if (m_synthetic_value)
2959 m_synthetic_value = nullptr;
2960 }
2961}
2962
2963SymbolContextScope *ValueObject::GetSymbolContextScope() {
2964 if (m_parent) {
2965 if (!m_parent->IsPointerOrReferenceType())
2966 return m_parent->GetSymbolContextScope();
2967 }
2968 return nullptr;
2969}
2970
2971lldb::ValueObjectSP
2972ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,
2973 llvm::StringRef expression,
2974 const ExecutionContext &exe_ctx) {
2975 return CreateValueObjectFromExpression(name, expression, exe_ctx,
2976 options: EvaluateExpressionOptions());
2977}
2978
2979lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
2980 llvm::StringRef name, llvm::StringRef expression,
2981 const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {
2982 lldb::ValueObjectSP retval_sp;
2983 lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
2984 if (!target_sp)
2985 return retval_sp;
2986 if (expression.empty())
2987 return retval_sp;
2988 target_sp->EvaluateExpression(expression, exe_scope: exe_ctx.GetFrameSP().get(),
2989 result_valobj_sp&: retval_sp, options);
2990 if (retval_sp && !name.empty())
2991 retval_sp->SetName(ConstString(name));
2992 return retval_sp;
2993}
2994
2995lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
2996 llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
2997 CompilerType type) {
2998 if (type) {
2999 CompilerType pointer_type(type.GetPointerType());
3000 if (pointer_type) {
3001 lldb::DataBufferSP buffer(
3002 new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
3003 lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(
3004 exe_scope: exe_ctx.GetBestExecutionContextScope(), compiler_type: pointer_type,
3005 name: ConstString(name), result_data_sp: buffer, byte_order: exe_ctx.GetByteOrder(),
3006 addr_size: exe_ctx.GetAddressByteSize()));
3007 if (ptr_result_valobj_sp) {
3008 ptr_result_valobj_sp->GetValue().SetValueType(
3009 Value::ValueType::LoadAddress);
3010 Status err;
3011 ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(error&: err);
3012 if (ptr_result_valobj_sp && !name.empty())
3013 ptr_result_valobj_sp->SetName(ConstString(name));
3014 }
3015 return ptr_result_valobj_sp;
3016 }
3017 }
3018 return lldb::ValueObjectSP();
3019}
3020
3021lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
3022 llvm::StringRef name, const DataExtractor &data,
3023 const ExecutionContext &exe_ctx, CompilerType type) {
3024 lldb::ValueObjectSP new_value_sp;
3025 new_value_sp = ValueObjectConstResult::Create(
3026 exe_scope: exe_ctx.GetBestExecutionContextScope(), compiler_type: type, name: ConstString(name), data,
3027 LLDB_INVALID_ADDRESS);
3028 new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
3029 if (new_value_sp && !name.empty())
3030 new_value_sp->SetName(ConstString(name));
3031 return new_value_sp;
3032}
3033
3034ModuleSP ValueObject::GetModule() {
3035 ValueObject *root(GetRoot());
3036 if (root != this)
3037 return root->GetModule();
3038 return lldb::ModuleSP();
3039}
3040
3041ValueObject *ValueObject::GetRoot() {
3042 if (m_root)
3043 return m_root;
3044 return (m_root = FollowParentChain([](ValueObject *vo) -> bool {
3045 return (vo->m_parent != nullptr);
3046 }));
3047}
3048
3049ValueObject *
3050ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
3051 ValueObject *vo = this;
3052 while (vo) {
3053 if (!f(vo))
3054 break;
3055 vo = vo->m_parent;
3056 }
3057 return vo;
3058}
3059
3060AddressType ValueObject::GetAddressTypeOfChildren() {
3061 if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {
3062 ValueObject *root(GetRoot());
3063 if (root != this)
3064 return root->GetAddressTypeOfChildren();
3065 }
3066 return m_address_type_of_ptr_or_ref_children;
3067}
3068
3069lldb::DynamicValueType ValueObject::GetDynamicValueType() {
3070 ValueObject *with_dv_info = this;
3071 while (with_dv_info) {
3072 if (with_dv_info->HasDynamicValueTypeInfo())
3073 return with_dv_info->GetDynamicValueTypeImpl();
3074 with_dv_info = with_dv_info->m_parent;
3075 }
3076 return lldb::eNoDynamicValues;
3077}
3078
3079lldb::Format ValueObject::GetFormat() const {
3080 const ValueObject *with_fmt_info = this;
3081 while (with_fmt_info) {
3082 if (with_fmt_info->m_format != lldb::eFormatDefault)
3083 return with_fmt_info->m_format;
3084 with_fmt_info = with_fmt_info->m_parent;
3085 }
3086 return m_format;
3087}
3088
3089lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {
3090 lldb::LanguageType type = m_preferred_display_language;
3091 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
3092 if (GetRoot()) {
3093 if (GetRoot() == this) {
3094 if (StackFrameSP frame_sp = GetFrameSP()) {
3095 const SymbolContext &sc(
3096 frame_sp->GetSymbolContext(resolve_scope: eSymbolContextCompUnit));
3097 if (CompileUnit *cu = sc.comp_unit)
3098 type = cu->GetLanguage();
3099 }
3100 } else {
3101 type = GetRoot()->GetPreferredDisplayLanguage();
3102 }
3103 }
3104 }
3105 return (m_preferred_display_language = type); // only compute it once
3106}
3107
3108void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {
3109 if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
3110 SetPreferredDisplayLanguage(lt);
3111}
3112
3113bool ValueObject::CanProvideValue() {
3114 // we need to support invalid types as providers of values because some bare-
3115 // board debugging scenarios have no notion of types, but still manage to
3116 // have raw numeric values for things like registers. sigh.
3117 CompilerType type = GetCompilerType();
3118 return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
3119}
3120
3121
3122
3123ValueObjectSP ValueObject::Persist() {
3124 if (!UpdateValueIfNeeded())
3125 return nullptr;
3126
3127 TargetSP target_sp(GetTargetSP());
3128 if (!target_sp)
3129 return nullptr;
3130
3131 PersistentExpressionState *persistent_state =
3132 target_sp->GetPersistentExpressionStateForLanguage(
3133 language: GetPreferredDisplayLanguage());
3134
3135 if (!persistent_state)
3136 return nullptr;
3137
3138 ConstString name = persistent_state->GetNextPersistentVariableName();
3139
3140 ValueObjectSP const_result_sp =
3141 ValueObjectConstResult::Create(exe_scope: target_sp.get(), value&: GetValue(), name);
3142
3143 ExpressionVariableSP persistent_var_sp =
3144 persistent_state->CreatePersistentVariable(valobj_sp: const_result_sp);
3145 persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;
3146 persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
3147
3148 return persistent_var_sp->GetValueObject();
3149}
3150
3151lldb::ValueObjectSP ValueObject::GetVTable() {
3152 return ValueObjectVTable::Create(parent&: *this);
3153}
3154

source code of lldb/source/Core/ValueObject.cpp