Path: blob/main/contrib/llvm-project/lldb/source/ValueObject/ValueObject.cpp
213764 views
//===-- ValueObject.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/ValueObject/ValueObject.h"910#include "lldb/Core/Address.h"11#include "lldb/Core/Declaration.h"12#include "lldb/Core/Module.h"13#include "lldb/DataFormatters/DataVisualization.h"14#include "lldb/DataFormatters/DumpValueObjectOptions.h"15#include "lldb/DataFormatters/FormatManager.h"16#include "lldb/DataFormatters/StringPrinter.h"17#include "lldb/DataFormatters/TypeFormat.h"18#include "lldb/DataFormatters/TypeSummary.h"19#include "lldb/DataFormatters/ValueObjectPrinter.h"20#include "lldb/Expression/ExpressionVariable.h"21#include "lldb/Host/Config.h"22#include "lldb/Symbol/CompileUnit.h"23#include "lldb/Symbol/CompilerType.h"24#include "lldb/Symbol/SymbolContext.h"25#include "lldb/Symbol/Type.h"26#include "lldb/Symbol/Variable.h"27#include "lldb/Target/ExecutionContext.h"28#include "lldb/Target/Language.h"29#include "lldb/Target/LanguageRuntime.h"30#include "lldb/Target/Process.h"31#include "lldb/Target/StackFrame.h"32#include "lldb/Target/Target.h"33#include "lldb/Target/Thread.h"34#include "lldb/Target/ThreadList.h"35#include "lldb/Utility/DataBuffer.h"36#include "lldb/Utility/DataBufferHeap.h"37#include "lldb/Utility/Flags.h"38#include "lldb/Utility/LLDBLog.h"39#include "lldb/Utility/Log.h"40#include "lldb/Utility/Scalar.h"41#include "lldb/Utility/Stream.h"42#include "lldb/Utility/StreamString.h"43#include "lldb/ValueObject/ValueObjectCast.h"44#include "lldb/ValueObject/ValueObjectChild.h"45#include "lldb/ValueObject/ValueObjectConstResult.h"46#include "lldb/ValueObject/ValueObjectDynamicValue.h"47#include "lldb/ValueObject/ValueObjectMemory.h"48#include "lldb/ValueObject/ValueObjectSynthetic.h"49#include "lldb/ValueObject/ValueObjectVTable.h"50#include "lldb/lldb-private-types.h"5152#include "llvm/Support/Compiler.h"5354#include <algorithm>55#include <cstdint>56#include <cstdlib>57#include <memory>58#include <optional>59#include <tuple>6061#include <cassert>62#include <cinttypes>63#include <cstdio>64#include <cstring>6566namespace lldb_private {67class ExecutionContextScope;68}69namespace lldb_private {70class SymbolContextScope;71}7273using namespace lldb;74using namespace lldb_private;7576static user_id_t g_value_obj_uid = 0;7778// ValueObject constructor79ValueObject::ValueObject(ValueObject &parent)80: m_parent(&parent), m_update_point(parent.GetUpdatePoint()),81m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {82m_flags.m_is_synthetic_children_generated =83parent.m_flags.m_is_synthetic_children_generated;84m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());85m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());86m_manager->ManageObject(this);87}8889// ValueObject constructor90ValueObject::ValueObject(ExecutionContextScope *exe_scope,91ValueObjectManager &manager,92AddressType child_ptr_or_ref_addr_type)93: m_update_point(exe_scope), m_manager(&manager),94m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),95m_id(++g_value_obj_uid) {96if (exe_scope) {97TargetSP target_sp(exe_scope->CalculateTarget());98if (target_sp) {99const ArchSpec &arch = target_sp->GetArchitecture();100m_data.SetByteOrder(arch.GetByteOrder());101m_data.SetAddressByteSize(arch.GetAddressByteSize());102}103}104m_manager->ManageObject(this);105}106107// Destructor108ValueObject::~ValueObject() = default;109110bool ValueObject::UpdateValueIfNeeded(bool update_format) {111112bool did_change_formats = false;113114if (update_format)115did_change_formats = UpdateFormatsIfNeeded();116117// If this is a constant value, then our success is predicated on whether we118// have an error or not119if (GetIsConstant()) {120// if you are constant, things might still have changed behind your back121// (e.g. you are a frozen object and things have changed deeper than you122// cared to freeze-dry yourself) in this case, your value has not changed,123// but "computed" entries might have, so you might now have a different124// summary, or a different object description. clear these so we will125// recompute them126if (update_format && !did_change_formats)127ClearUserVisibleData(eClearUserVisibleDataItemsSummary |128eClearUserVisibleDataItemsDescription);129return m_error.Success();130}131132bool first_update = IsChecksumEmpty();133134if (NeedsUpdating()) {135m_update_point.SetUpdated();136137// Save the old value using swap to avoid a string copy which also will138// clear our m_value_str139if (m_value_str.empty()) {140m_flags.m_old_value_valid = false;141} else {142m_flags.m_old_value_valid = true;143m_old_value_str.swap(m_value_str);144ClearUserVisibleData(eClearUserVisibleDataItemsValue);145}146147ClearUserVisibleData();148149if (IsInScope()) {150const bool value_was_valid = GetValueIsValid();151SetValueDidChange(false);152153m_error.Clear();154155// Call the pure virtual function to update the value156157bool need_compare_checksums = false;158llvm::SmallVector<uint8_t, 16> old_checksum;159160if (!first_update && CanProvideValue()) {161need_compare_checksums = true;162old_checksum.resize(m_value_checksum.size());163std::copy(m_value_checksum.begin(), m_value_checksum.end(),164old_checksum.begin());165}166167bool success = UpdateValue();168169SetValueIsValid(success);170171if (success) {172UpdateChildrenAddressType();173const uint64_t max_checksum_size = 128;174m_data.Checksum(m_value_checksum, max_checksum_size);175} else {176need_compare_checksums = false;177m_value_checksum.clear();178}179180assert(!need_compare_checksums ||181(!old_checksum.empty() && !m_value_checksum.empty()));182183if (first_update)184SetValueDidChange(false);185else if (!m_flags.m_value_did_change && !success) {186// The value wasn't gotten successfully, so we mark this as changed if187// the value used to be valid and now isn't188SetValueDidChange(value_was_valid);189} else if (need_compare_checksums) {190SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],191m_value_checksum.size()));192}193194} else {195m_error = Status::FromErrorString("out of scope");196}197}198return m_error.Success();199}200201bool ValueObject::UpdateFormatsIfNeeded() {202Log *log = GetLog(LLDBLog::DataFormatters);203LLDB_LOGF(log,204"[%s %p] checking for FormatManager revisions. ValueObject "205"rev: %d - Global rev: %d",206GetName().GetCString(), static_cast<void *>(this),207m_last_format_mgr_revision,208DataVisualization::GetCurrentRevision());209210bool any_change = false;211212if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {213m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();214any_change = true;215216SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));217SetSummaryFormat(218DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));219SetSyntheticChildren(220DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));221}222223return any_change;224}225226void ValueObject::SetNeedsUpdate() {227m_update_point.SetNeedsUpdate();228// We have to clear the value string here so ConstResult children will notice229// if their values are changed by hand (i.e. with SetValueAsCString).230ClearUserVisibleData(eClearUserVisibleDataItemsValue);231}232233void ValueObject::ClearDynamicTypeInformation() {234m_flags.m_children_count_valid = false;235m_flags.m_did_calculate_complete_objc_class_type = false;236m_last_format_mgr_revision = 0;237m_override_type = CompilerType();238SetValueFormat(lldb::TypeFormatImplSP());239SetSummaryFormat(lldb::TypeSummaryImplSP());240SetSyntheticChildren(lldb::SyntheticChildrenSP());241}242243CompilerType ValueObject::MaybeCalculateCompleteType() {244CompilerType compiler_type(GetCompilerTypeImpl());245246if (m_flags.m_did_calculate_complete_objc_class_type) {247if (m_override_type.IsValid())248return m_override_type;249else250return compiler_type;251}252253m_flags.m_did_calculate_complete_objc_class_type = true;254255ProcessSP process_sp(256GetUpdatePoint().GetExecutionContextRef().GetProcessSP());257258if (!process_sp)259return compiler_type;260261if (auto *runtime =262process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {263if (std::optional<CompilerType> complete_type =264runtime->GetRuntimeType(compiler_type)) {265m_override_type = *complete_type;266if (m_override_type.IsValid())267return m_override_type;268}269}270return compiler_type;271}272273DataExtractor &ValueObject::GetDataExtractor() {274UpdateValueIfNeeded(false);275return m_data;276}277278const Status &ValueObject::GetError() {279UpdateValueIfNeeded(false);280return m_error;281}282283const char *ValueObject::GetLocationAsCStringImpl(const Value &value,284const DataExtractor &data) {285if (UpdateValueIfNeeded(false)) {286if (m_location_str.empty()) {287StreamString sstr;288289Value::ValueType value_type = value.GetValueType();290291switch (value_type) {292case Value::ValueType::Invalid:293m_location_str = "invalid";294break;295case Value::ValueType::Scalar:296if (value.GetContextType() == Value::ContextType::RegisterInfo) {297RegisterInfo *reg_info = value.GetRegisterInfo();298if (reg_info) {299if (reg_info->name)300m_location_str = reg_info->name;301else if (reg_info->alt_name)302m_location_str = reg_info->alt_name;303if (m_location_str.empty())304m_location_str = (reg_info->encoding == lldb::eEncodingVector)305? "vector"306: "scalar";307}308}309if (m_location_str.empty())310m_location_str = "scalar";311break;312313case Value::ValueType::LoadAddress:314case Value::ValueType::FileAddress:315case Value::ValueType::HostAddress: {316uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;317sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,318value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));319m_location_str = std::string(sstr.GetString());320} break;321}322}323}324return m_location_str.c_str();325}326327bool ValueObject::ResolveValue(Scalar &scalar) {328if (UpdateValueIfNeeded(329false)) // make sure that you are up to date before returning anything330{331ExecutionContext exe_ctx(GetExecutionContextRef());332Value tmp_value(m_value);333scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());334if (scalar.IsValid()) {335const uint32_t bitfield_bit_size = GetBitfieldBitSize();336if (bitfield_bit_size)337return scalar.ExtractBitfield(bitfield_bit_size,338GetBitfieldBitOffset());339return true;340}341}342return false;343}344345bool ValueObject::IsLogicalTrue(Status &error) {346if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {347LazyBool is_logical_true = language->IsLogicalTrue(*this, error);348switch (is_logical_true) {349case eLazyBoolYes:350case eLazyBoolNo:351return (is_logical_true == true);352case eLazyBoolCalculate:353break;354}355}356357Scalar scalar_value;358359if (!ResolveValue(scalar_value)) {360error = Status::FromErrorString("failed to get a scalar result");361return false;362}363364bool ret;365ret = scalar_value.ULongLong(1) != 0;366error.Clear();367return ret;368}369370ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {371ValueObjectSP child_sp;372// We may need to update our value if we are dynamic373if (IsPossibleDynamicType())374UpdateValueIfNeeded(false);375if (idx < GetNumChildrenIgnoringErrors()) {376// Check if we have already made the child value object?377if (can_create && !m_children.HasChildAtIndex(idx)) {378// No we haven't created the child at this index, so lets have our379// subclass do it and cache the result for quick future access.380m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));381}382383ValueObject *child = m_children.GetChildAtIndex(idx);384if (child != nullptr)385return child->GetSP();386}387return child_sp;388}389390lldb::ValueObjectSP391ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {392if (names.size() == 0)393return GetSP();394ValueObjectSP root(GetSP());395for (llvm::StringRef name : names) {396root = root->GetChildMemberWithName(name);397if (!root) {398return root;399}400}401return root;402}403404llvm::Expected<size_t>405ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {406bool omit_empty_base_classes = true;407return GetCompilerType().GetIndexOfChildWithName(name,408omit_empty_base_classes);409}410411ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,412bool can_create) {413// We may need to update our value if we are dynamic.414if (IsPossibleDynamicType())415UpdateValueIfNeeded(false);416417// When getting a child by name, it could be buried inside some base classes418// (which really aren't part of the expression path), so we need a vector of419// indexes that can get us down to the correct child.420std::vector<uint32_t> child_indexes;421bool omit_empty_base_classes = true;422423if (!GetCompilerType().IsValid())424return ValueObjectSP();425426const size_t num_child_indexes =427GetCompilerType().GetIndexOfChildMemberWithName(428name, omit_empty_base_classes, child_indexes);429if (num_child_indexes == 0)430return nullptr;431432ValueObjectSP child_sp = GetSP();433for (uint32_t idx : child_indexes)434if (child_sp)435child_sp = child_sp->GetChildAtIndex(idx, can_create);436return child_sp;437}438439llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {440UpdateValueIfNeeded();441442if (max < UINT32_MAX) {443if (m_flags.m_children_count_valid) {444size_t children_count = m_children.GetChildrenCount();445return children_count <= max ? children_count : max;446} else447return CalculateNumChildren(max);448}449450if (!m_flags.m_children_count_valid) {451auto num_children_or_err = CalculateNumChildren();452if (num_children_or_err)453SetNumChildren(*num_children_or_err);454else455return num_children_or_err;456}457return m_children.GetChildrenCount();458}459460uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {461auto value_or_err = GetNumChildren(max);462if (value_or_err)463return *value_or_err;464LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),465"{0}");466return 0;467}468469bool ValueObject::MightHaveChildren() {470bool has_children = false;471const uint32_t type_info = GetTypeInfo();472if (type_info) {473if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))474has_children = true;475} else {476has_children = GetNumChildrenIgnoringErrors() > 0;477}478return has_children;479}480481// Should only be called by ValueObject::GetNumChildren()482void ValueObject::SetNumChildren(uint32_t num_children) {483m_flags.m_children_count_valid = true;484m_children.SetChildrenCount(num_children);485}486487ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {488bool omit_empty_base_classes = true;489bool ignore_array_bounds = false;490std::string child_name;491uint32_t child_byte_size = 0;492int32_t child_byte_offset = 0;493uint32_t child_bitfield_bit_size = 0;494uint32_t child_bitfield_bit_offset = 0;495bool child_is_base_class = false;496bool child_is_deref_of_parent = false;497uint64_t language_flags = 0;498const bool transparent_pointers = true;499500ExecutionContext exe_ctx(GetExecutionContextRef());501502auto child_compiler_type_or_err =503GetCompilerType().GetChildCompilerTypeAtIndex(504&exe_ctx, idx, transparent_pointers, omit_empty_base_classes,505ignore_array_bounds, child_name, child_byte_size, child_byte_offset,506child_bitfield_bit_size, child_bitfield_bit_offset,507child_is_base_class, child_is_deref_of_parent, this, language_flags);508if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {509LLDB_LOG_ERROR(GetLog(LLDBLog::Types),510child_compiler_type_or_err.takeError(),511"could not find child: {0}");512return nullptr;513}514515return new ValueObjectChild(516*this, *child_compiler_type_or_err, ConstString(child_name),517child_byte_size, child_byte_offset, child_bitfield_bit_size,518child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,519eAddressTypeInvalid, language_flags);520}521522ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {523bool omit_empty_base_classes = true;524bool ignore_array_bounds = true;525std::string child_name;526uint32_t child_byte_size = 0;527int32_t child_byte_offset = 0;528uint32_t child_bitfield_bit_size = 0;529uint32_t child_bitfield_bit_offset = 0;530bool child_is_base_class = false;531bool child_is_deref_of_parent = false;532uint64_t language_flags = 0;533const bool transparent_pointers = false;534535ExecutionContext exe_ctx(GetExecutionContextRef());536537auto child_compiler_type_or_err =538GetCompilerType().GetChildCompilerTypeAtIndex(539&exe_ctx, 0, transparent_pointers, omit_empty_base_classes,540ignore_array_bounds, child_name, child_byte_size, child_byte_offset,541child_bitfield_bit_size, child_bitfield_bit_offset,542child_is_base_class, child_is_deref_of_parent, this, language_flags);543if (!child_compiler_type_or_err) {544LLDB_LOG_ERROR(GetLog(LLDBLog::Types),545child_compiler_type_or_err.takeError(),546"could not find child: {0}");547return nullptr;548}549550if (child_compiler_type_or_err->IsValid()) {551child_byte_offset += child_byte_size * idx;552553return new ValueObjectChild(554*this, *child_compiler_type_or_err, ConstString(child_name),555child_byte_size, child_byte_offset, child_bitfield_bit_size,556child_bitfield_bit_offset, child_is_base_class,557child_is_deref_of_parent, eAddressTypeInvalid, language_flags);558}559560// In case of an incomplete type, try to use the ValueObject's561// synthetic value to create the child ValueObject.562if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())563return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();564565return nullptr;566}567568bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,569std::string &destination,570lldb::LanguageType lang) {571return GetSummaryAsCString(summary_ptr, destination,572TypeSummaryOptions().SetLanguage(lang));573}574575bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,576std::string &destination,577const TypeSummaryOptions &options) {578destination.clear();579580// If we have a forcefully completed type, don't try and show a summary from581// a valid summary string or function because the type is not complete and582// no member variables or member functions will be available.583if (GetCompilerType().IsForcefullyCompleted()) {584destination = "<incomplete type>";585return true;586}587588// ideally we would like to bail out if passing NULL, but if we do so we end589// up not providing the summary for function pointers anymore590if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)591return false;592593m_flags.m_is_getting_summary = true;594595TypeSummaryOptions actual_options(options);596597if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)598actual_options.SetLanguage(GetPreferredDisplayLanguage());599600// this is a hot path in code and we prefer to avoid setting this string all601// too often also clearing out other information that we might care to see in602// a crash log. might be useful in very specific situations though.603/*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.604Summary provider's description is %s",605GetTypeName().GetCString(),606GetName().GetCString(),607summary_ptr->GetDescription().c_str());*/608609if (UpdateValueIfNeeded(false) && summary_ptr) {610if (HasSyntheticValue())611m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on612// the synthetic children being613// up-to-date (e.g. ${svar%#})614615if (TargetSP target_sp = GetExecutionContextRef().GetTargetSP()) {616SummaryStatisticsSP stats_sp =617target_sp->GetSummaryStatisticsCache()618.GetSummaryStatisticsForProvider(*summary_ptr);619620// Construct RAII types to time and collect data on summary creation.621SummaryStatistics::SummaryInvocation invocation(stats_sp);622summary_ptr->FormatObject(this, destination, actual_options);623} else624summary_ptr->FormatObject(this, destination, actual_options);625}626m_flags.m_is_getting_summary = false;627return !destination.empty();628}629630const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {631if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {632TypeSummaryOptions summary_options;633summary_options.SetLanguage(lang);634GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,635summary_options);636}637if (m_summary_str.empty())638return nullptr;639return m_summary_str.c_str();640}641642bool ValueObject::GetSummaryAsCString(std::string &destination,643const TypeSummaryOptions &options) {644return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);645}646647bool ValueObject::IsCStringContainer(bool check_pointer) {648CompilerType pointee_or_element_compiler_type;649const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));650bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&651pointee_or_element_compiler_type.IsCharType());652if (!is_char_arr_ptr)653return false;654if (!check_pointer)655return true;656if (type_flags.Test(eTypeIsArray))657return true;658addr_t cstr_address = GetPointerValue().address;659return (cstr_address != LLDB_INVALID_ADDRESS);660}661662size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,663uint32_t item_count) {664CompilerType pointee_or_element_compiler_type;665const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);666const bool is_pointer_type = type_info & eTypeIsPointer;667const bool is_array_type = type_info & eTypeIsArray;668if (!(is_pointer_type || is_array_type))669return 0;670671if (item_count == 0)672return 0;673674ExecutionContext exe_ctx(GetExecutionContextRef());675676std::optional<uint64_t> item_type_size =677llvm::expectedToOptional(pointee_or_element_compiler_type.GetByteSize(678exe_ctx.GetBestExecutionContextScope()));679if (!item_type_size)680return 0;681const uint64_t bytes = item_count * *item_type_size;682const uint64_t offset = item_idx * *item_type_size;683684if (item_idx == 0 && item_count == 1) // simply a deref685{686if (is_pointer_type) {687Status error;688ValueObjectSP pointee_sp = Dereference(error);689if (error.Fail() || pointee_sp.get() == nullptr)690return 0;691return pointee_sp->GetData(data, error);692} else {693ValueObjectSP child_sp = GetChildAtIndex(0);694if (child_sp.get() == nullptr)695return 0;696Status error;697return child_sp->GetData(data, error);698}699return true;700} else /* (items > 1) */701{702Status error;703lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;704lldb::DataBufferSP data_sp(heap_buf_ptr =705new lldb_private::DataBufferHeap());706707auto [addr, addr_type] =708is_pointer_type ? GetPointerValue() : GetAddressOf(true);709710switch (addr_type) {711case eAddressTypeFile: {712ModuleSP module_sp(GetModule());713if (module_sp) {714addr = addr + offset;715Address so_addr;716module_sp->ResolveFileAddress(addr, so_addr);717ExecutionContext exe_ctx(GetExecutionContextRef());718Target *target = exe_ctx.GetTargetPtr();719if (target) {720heap_buf_ptr->SetByteSize(bytes);721size_t bytes_read = target->ReadMemory(722so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);723if (error.Success()) {724data.SetData(data_sp);725return bytes_read;726}727}728}729} break;730case eAddressTypeLoad: {731ExecutionContext exe_ctx(GetExecutionContextRef());732if (Target *target = exe_ctx.GetTargetPtr()) {733heap_buf_ptr->SetByteSize(bytes);734Address target_addr;735target_addr.SetLoadAddress(addr + offset, target);736size_t bytes_read =737target->ReadMemory(target_addr, heap_buf_ptr->GetBytes(), bytes,738error, /*force_live_memory=*/true);739if (error.Success() || bytes_read > 0) {740data.SetData(data_sp);741return bytes_read;742}743}744} break;745case eAddressTypeHost: {746auto max_bytes =747GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());748if (max_bytes && *max_bytes > offset) {749size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);750addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);751if (addr == 0 || addr == LLDB_INVALID_ADDRESS)752break;753heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);754data.SetData(data_sp);755return bytes_read;756}757} break;758case eAddressTypeInvalid:759break;760}761}762return 0;763}764765uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {766UpdateValueIfNeeded(false);767ExecutionContext exe_ctx(GetExecutionContextRef());768error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());769if (error.Fail()) {770if (m_data.GetByteSize()) {771data = m_data;772error.Clear();773return data.GetByteSize();774} else {775return 0;776}777}778data.SetAddressByteSize(m_data.GetAddressByteSize());779data.SetByteOrder(m_data.GetByteOrder());780return data.GetByteSize();781}782783bool ValueObject::SetData(DataExtractor &data, Status &error) {784error.Clear();785// Make sure our value is up to date first so that our location and location786// type is valid.787if (!UpdateValueIfNeeded(false)) {788error = Status::FromErrorString("unable to read value");789return false;790}791792uint64_t count = 0;793const Encoding encoding = GetCompilerType().GetEncoding(count);794795const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);796797Value::ValueType value_type = m_value.GetValueType();798799switch (value_type) {800case Value::ValueType::Invalid:801error = Status::FromErrorString("invalid location");802return false;803case Value::ValueType::Scalar: {804Status set_error =805m_value.GetScalar().SetValueFromData(data, encoding, byte_size);806807if (!set_error.Success()) {808error = Status::FromErrorStringWithFormat(809"unable to set scalar value: %s", set_error.AsCString());810return false;811}812} break;813case Value::ValueType::LoadAddress: {814// If it is a load address, then the scalar value is the storage location815// of the data, and we have to shove this value down to that load location.816ExecutionContext exe_ctx(GetExecutionContextRef());817Process *process = exe_ctx.GetProcessPtr();818if (process) {819addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);820size_t bytes_written = process->WriteMemory(821target_addr, data.GetDataStart(), byte_size, error);822if (!error.Success())823return false;824if (bytes_written != byte_size) {825error = Status::FromErrorString("unable to write value to memory");826return false;827}828}829} break;830case Value::ValueType::HostAddress: {831// If it is a host address, then we stuff the scalar as a DataBuffer into832// the Value's data.833DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));834m_data.SetData(buffer_sp, 0);835data.CopyByteOrderedData(0, byte_size,836const_cast<uint8_t *>(m_data.GetDataStart()),837byte_size, m_data.GetByteOrder());838m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();839} break;840case Value::ValueType::FileAddress:841break;842}843844// If we have reached this point, then we have successfully changed the845// value.846SetNeedsUpdate();847return true;848}849850llvm::ArrayRef<uint8_t> ValueObject::GetLocalBuffer() const {851if (m_value.GetValueType() != Value::ValueType::HostAddress)852return {};853auto start = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);854if (start == LLDB_INVALID_ADDRESS)855return {};856// Does our pointer point to this value object's m_data buffer?857if ((uint64_t)m_data.GetDataStart() == start)858return m_data.GetData();859// Does our pointer point to the value's buffer?860if ((uint64_t)m_value.GetBuffer().GetBytes() == start)861return m_value.GetBuffer().GetData();862// Our pointer points to something else. We can't know what the size is.863return {};864}865866static bool CopyStringDataToBufferSP(const StreamString &source,867lldb::WritableDataBufferSP &destination) {868llvm::StringRef src = source.GetString();869src = src.rtrim('\0');870destination = std::make_shared<DataBufferHeap>(src.size(), 0);871memcpy(destination->GetBytes(), src.data(), src.size());872return true;873}874875std::pair<size_t, bool>876ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,877Status &error, bool honor_array) {878bool was_capped = false;879StreamString s;880ExecutionContext exe_ctx(GetExecutionContextRef());881Target *target = exe_ctx.GetTargetPtr();882883if (!target) {884s << "<no target to read from>";885error = Status::FromErrorString("no target to read from");886CopyStringDataToBufferSP(s, buffer_sp);887return {0, was_capped};888}889890const auto max_length = target->GetMaximumSizeOfStringSummary();891892size_t bytes_read = 0;893size_t total_bytes_read = 0;894895CompilerType compiler_type = GetCompilerType();896CompilerType elem_or_pointee_compiler_type;897const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));898if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&899elem_or_pointee_compiler_type.IsCharType()) {900AddrAndType cstr_address;901902size_t cstr_len = 0;903bool capped_data = false;904const bool is_array = type_flags.Test(eTypeIsArray);905if (is_array) {906// We have an array907uint64_t array_size = 0;908if (compiler_type.IsArrayType(nullptr, &array_size)) {909cstr_len = array_size;910if (cstr_len > max_length) {911capped_data = true;912cstr_len = max_length;913}914}915cstr_address = GetAddressOf(true);916} else {917// We have a pointer918cstr_address = GetPointerValue();919}920921if (cstr_address.address == 0 ||922cstr_address.address == LLDB_INVALID_ADDRESS) {923if (cstr_address.type == eAddressTypeHost && is_array) {924const char *cstr = GetDataExtractor().PeekCStr(0);925if (cstr == nullptr) {926s << "<invalid address>";927error = Status::FromErrorString("invalid address");928CopyStringDataToBufferSP(s, buffer_sp);929return {0, was_capped};930}931s << llvm::StringRef(cstr, cstr_len);932CopyStringDataToBufferSP(s, buffer_sp);933return {cstr_len, was_capped};934} else {935s << "<invalid address>";936error = Status::FromErrorString("invalid address");937CopyStringDataToBufferSP(s, buffer_sp);938return {0, was_capped};939}940}941942Address cstr_so_addr(cstr_address.address);943DataExtractor data;944if (cstr_len > 0 && honor_array) {945// I am using GetPointeeData() here to abstract the fact that some946// ValueObjects are actually frozen pointers in the host but the pointed-947// to data lives in the debuggee, and GetPointeeData() automatically948// takes care of this949GetPointeeData(data, 0, cstr_len);950951if ((bytes_read = data.GetByteSize()) > 0) {952total_bytes_read = bytes_read;953for (size_t offset = 0; offset < bytes_read; offset++)954s.Printf("%c", *data.PeekData(offset, 1));955if (capped_data)956was_capped = true;957}958} else {959cstr_len = max_length;960const size_t k_max_buf_size = 64;961962size_t offset = 0;963964int cstr_len_displayed = -1;965bool capped_cstr = false;966// I am using GetPointeeData() here to abstract the fact that some967// ValueObjects are actually frozen pointers in the host but the pointed-968// to data lives in the debuggee, and GetPointeeData() automatically969// takes care of this970while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {971total_bytes_read += bytes_read;972const char *cstr = data.PeekCStr(0);973size_t len = strnlen(cstr, k_max_buf_size);974if (cstr_len_displayed < 0)975cstr_len_displayed = len;976977if (len == 0)978break;979cstr_len_displayed += len;980if (len > bytes_read)981len = bytes_read;982if (len > cstr_len)983len = cstr_len;984985for (size_t offset = 0; offset < bytes_read; offset++)986s.Printf("%c", *data.PeekData(offset, 1));987988if (len < k_max_buf_size)989break;990991if (len >= cstr_len) {992capped_cstr = true;993break;994}995996cstr_len -= len;997offset += len;998}9991000if (cstr_len_displayed >= 0) {1001if (capped_cstr)1002was_capped = true;1003}1004}1005} else {1006error = Status::FromErrorString("not a string object");1007s << "<not a string object>";1008}1009CopyStringDataToBufferSP(s, buffer_sp);1010return {total_bytes_read, was_capped};1011}10121013llvm::Expected<std::string> ValueObject::GetObjectDescription() {1014if (!UpdateValueIfNeeded(true))1015return llvm::createStringError("could not update value");10161017// Return cached value.1018if (!m_object_desc_str.empty())1019return m_object_desc_str;10201021ExecutionContext exe_ctx(GetExecutionContextRef());1022Process *process = exe_ctx.GetProcessPtr();1023if (!process)1024return llvm::createStringError("no process");10251026// Returns the object description produced by one language runtime.1027auto get_object_description =1028[&](LanguageType language) -> llvm::Expected<std::string> {1029if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {1030StreamString s;1031if (llvm::Error error = runtime->GetObjectDescription(s, *this))1032return error;1033m_object_desc_str = s.GetString();1034return m_object_desc_str;1035}1036return llvm::createStringError("no native language runtime");1037};10381039// Try the native language runtime first.1040LanguageType native_language = GetObjectRuntimeLanguage();1041llvm::Expected<std::string> desc = get_object_description(native_language);1042if (desc)1043return desc;10441045// Try the Objective-C language runtime. This fallback is necessary1046// for Objective-C++ and mixed Objective-C / C++ programs.1047if (Language::LanguageIsCFamily(native_language)) {1048// We're going to try again, so let's drop the first error.1049llvm::consumeError(desc.takeError());1050return get_object_description(eLanguageTypeObjC);1051}1052return desc;1053}10541055bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,1056std::string &destination) {1057if (UpdateValueIfNeeded(false))1058return format.FormatObject(this, destination);1059else1060return false;1061}10621063bool ValueObject::GetValueAsCString(lldb::Format format,1064std::string &destination) {1065return GetValueAsCString(TypeFormatImpl_Format(format), destination);1066}10671068const char *ValueObject::GetValueAsCString() {1069if (UpdateValueIfNeeded(true)) {1070lldb::TypeFormatImplSP format_sp;1071lldb::Format my_format = GetFormat();1072if (my_format == lldb::eFormatDefault) {1073if (m_type_format_sp)1074format_sp = m_type_format_sp;1075else {1076if (m_flags.m_is_bitfield_for_scalar)1077my_format = eFormatUnsigned;1078else {1079if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {1080const RegisterInfo *reg_info = m_value.GetRegisterInfo();1081if (reg_info)1082my_format = reg_info->format;1083} else {1084my_format = GetValue().GetCompilerType().GetFormat();1085}1086}1087}1088}1089if (my_format != m_last_format || m_value_str.empty()) {1090m_last_format = my_format;1091if (!format_sp)1092format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);1093if (GetValueAsCString(*format_sp.get(), m_value_str)) {1094if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {1095// The value was gotten successfully, so we consider the value as1096// changed if the value string differs1097SetValueDidChange(m_old_value_str != m_value_str);1098}1099}1100}1101}1102if (m_value_str.empty())1103return nullptr;1104return m_value_str.c_str();1105}11061107// if > 8bytes, 0 is returned. this method should mostly be used to read1108// address values out of pointers1109uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {1110// If our byte size is zero this is an aggregate type that has children1111if (CanProvideValue()) {1112Scalar scalar;1113if (ResolveValue(scalar)) {1114if (success)1115*success = true;1116scalar.MakeUnsigned();1117return scalar.ULongLong(fail_value);1118}1119// fallthrough, otherwise...1120}11211122if (success)1123*success = false;1124return fail_value;1125}11261127int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {1128// If our byte size is zero this is an aggregate type that has children1129if (CanProvideValue()) {1130Scalar scalar;1131if (ResolveValue(scalar)) {1132if (success)1133*success = true;1134scalar.MakeSigned();1135return scalar.SLongLong(fail_value);1136}1137// fallthrough, otherwise...1138}11391140if (success)1141*success = false;1142return fail_value;1143}11441145llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {1146// Make sure the type can be converted to an APSInt.1147if (!GetCompilerType().IsInteger() &&1148!GetCompilerType().IsScopedEnumerationType() &&1149!GetCompilerType().IsEnumerationType() &&1150!GetCompilerType().IsPointerType() &&1151!GetCompilerType().IsNullPtrType() &&1152!GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())1153return llvm::make_error<llvm::StringError>(1154"type cannot be converted to APSInt", llvm::inconvertibleErrorCode());11551156if (CanProvideValue()) {1157Scalar scalar;1158if (ResolveValue(scalar))1159return scalar.GetAPSInt();1160}11611162return llvm::make_error<llvm::StringError>(1163"error occurred; unable to convert to APSInt",1164llvm::inconvertibleErrorCode());1165}11661167llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {1168if (!GetCompilerType().IsFloat())1169return llvm::make_error<llvm::StringError>(1170"type cannot be converted to APFloat", llvm::inconvertibleErrorCode());11711172if (CanProvideValue()) {1173Scalar scalar;1174if (ResolveValue(scalar))1175return scalar.GetAPFloat();1176}11771178return llvm::make_error<llvm::StringError>(1179"error occurred; unable to convert to APFloat",1180llvm::inconvertibleErrorCode());1181}11821183llvm::Expected<bool> ValueObject::GetValueAsBool() {1184CompilerType val_type = GetCompilerType();1185if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||1186val_type.IsPointerType()) {1187auto value_or_err = GetValueAsAPSInt();1188if (value_or_err)1189return value_or_err->getBoolValue();1190}1191if (val_type.IsFloat()) {1192auto value_or_err = GetValueAsAPFloat();1193if (value_or_err)1194return value_or_err->isNonZero();1195}1196if (val_type.IsArrayType())1197return GetAddressOf().address != 0;11981199return llvm::make_error<llvm::StringError>("type cannot be converted to bool",1200llvm::inconvertibleErrorCode());1201}12021203void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {1204// Verify the current object is an integer object1205CompilerType val_type = GetCompilerType();1206if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1207!val_type.IsFloat() && !val_type.IsPointerType() &&1208!val_type.IsScalarType()) {1209error =1210Status::FromErrorString("current value object is not an integer objet");1211return;1212}12131214// Verify the current object is not actually associated with any program1215// variable.1216if (GetVariable()) {1217error = Status::FromErrorString(1218"current value object is not a temporary object");1219return;1220}12211222// Verify the proposed new value is the right size.1223lldb::TargetSP target = GetTargetSP();1224uint64_t byte_size = 0;1225if (auto temp =1226llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))1227byte_size = temp.value();1228if (value.getBitWidth() != byte_size * CHAR_BIT) {1229error = Status::FromErrorString(1230"illegal argument: new value should be of the same size");1231return;1232}12331234lldb::DataExtractorSP data_sp;1235data_sp->SetData(value.getRawData(), byte_size,1236target->GetArchitecture().GetByteOrder());1237data_sp->SetAddressByteSize(1238static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));1239SetData(*data_sp, error);1240}12411242void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,1243Status &error) {1244// Verify the current object is an integer object1245CompilerType val_type = GetCompilerType();1246if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1247!val_type.IsFloat() && !val_type.IsPointerType() &&1248!val_type.IsScalarType()) {1249error =1250Status::FromErrorString("current value object is not an integer objet");1251return;1252}12531254// Verify the current object is not actually associated with any program1255// variable.1256if (GetVariable()) {1257error = Status::FromErrorString(1258"current value object is not a temporary object");1259return;1260}12611262// Verify the proposed new value is the right type.1263CompilerType new_val_type = new_val_sp->GetCompilerType();1264if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&1265!new_val_type.IsPointerType()) {1266error = Status::FromErrorString(1267"illegal argument: new value should be of the same size");1268return;1269}12701271if (new_val_type.IsInteger()) {1272auto value_or_err = new_val_sp->GetValueAsAPSInt();1273if (value_or_err)1274SetValueFromInteger(*value_or_err, error);1275else1276error = Status::FromErrorString("error getting APSInt from new_val_sp");1277} else if (new_val_type.IsFloat()) {1278auto value_or_err = new_val_sp->GetValueAsAPFloat();1279if (value_or_err)1280SetValueFromInteger(value_or_err->bitcastToAPInt(), error);1281else1282error = Status::FromErrorString("error getting APFloat from new_val_sp");1283} else if (new_val_type.IsPointerType()) {1284bool success = true;1285uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);1286if (success) {1287lldb::TargetSP target = GetTargetSP();1288uint64_t num_bits = 0;1289if (auto temp = llvm::expectedToOptional(1290new_val_sp->GetCompilerType().GetBitSize(target.get())))1291num_bits = temp.value();1292SetValueFromInteger(llvm::APInt(num_bits, int_val), error);1293} else1294error = Status::FromErrorString("error converting new_val_sp to integer");1295}1296}12971298// if any more "special cases" are added to1299// ValueObject::DumpPrintableRepresentation() please keep this call up to date1300// by returning true for your new special cases. We will eventually move to1301// checking this call result before trying to display special cases1302bool ValueObject::HasSpecialPrintableRepresentation(1303ValueObjectRepresentationStyle val_obj_display, Format custom_format) {1304Flags flags(GetTypeInfo());1305if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1306val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1307if (IsCStringContainer(true) &&1308(custom_format == eFormatCString || custom_format == eFormatCharArray ||1309custom_format == eFormatChar || custom_format == eFormatVectorOfChar))1310return true;13111312if (flags.Test(eTypeIsArray)) {1313if ((custom_format == eFormatBytes) ||1314(custom_format == eFormatBytesWithASCII))1315return true;13161317if ((custom_format == eFormatVectorOfChar) ||1318(custom_format == eFormatVectorOfFloat32) ||1319(custom_format == eFormatVectorOfFloat64) ||1320(custom_format == eFormatVectorOfSInt16) ||1321(custom_format == eFormatVectorOfSInt32) ||1322(custom_format == eFormatVectorOfSInt64) ||1323(custom_format == eFormatVectorOfSInt8) ||1324(custom_format == eFormatVectorOfUInt128) ||1325(custom_format == eFormatVectorOfUInt16) ||1326(custom_format == eFormatVectorOfUInt32) ||1327(custom_format == eFormatVectorOfUInt64) ||1328(custom_format == eFormatVectorOfUInt8))1329return true;1330}1331}1332return false;1333}13341335bool ValueObject::DumpPrintableRepresentation(1336Stream &s, ValueObjectRepresentationStyle val_obj_display,1337Format custom_format, PrintableRepresentationSpecialCases special,1338bool do_dump_error) {13391340// If the ValueObject has an error, we might end up dumping the type, which1341// is useful, but if we don't even have a type, then don't examine the object1342// further as that's not meaningful, only the error is.1343if (m_error.Fail() && !GetCompilerType().IsValid()) {1344if (do_dump_error)1345s.Printf("<%s>", m_error.AsCString());1346return false;1347}13481349Flags flags(GetTypeInfo());13501351bool allow_special =1352(special == ValueObject::PrintableRepresentationSpecialCases::eAllow);1353const bool only_special = false;13541355if (allow_special) {1356if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1357val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1358// when being asked to get a printable display an array or pointer type1359// directly, try to "do the right thing"13601361if (IsCStringContainer(true) &&1362(custom_format == eFormatCString ||1363custom_format == eFormatCharArray || custom_format == eFormatChar ||1364custom_format ==1365eFormatVectorOfChar)) // print char[] & char* directly1366{1367Status error;1368lldb::WritableDataBufferSP buffer_sp;1369std::pair<size_t, bool> read_string =1370ReadPointedString(buffer_sp, error,1371(custom_format == eFormatVectorOfChar) ||1372(custom_format == eFormatCharArray));1373lldb_private::formatters::StringPrinter::1374ReadBufferAndDumpToStreamOptions options(*this);1375options.SetData(DataExtractor(1376buffer_sp, lldb::eByteOrderInvalid,13778)); // none of this matters for a string - pass some defaults1378options.SetStream(&s);1379options.SetPrefixToken(nullptr);1380options.SetQuote('"');1381options.SetSourceSize(buffer_sp->GetByteSize());1382options.SetIsTruncated(read_string.second);1383options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);1384formatters::StringPrinter::ReadBufferAndDumpToStream<1385lldb_private::formatters::StringPrinter::StringElementType::ASCII>(1386options);1387return !error.Fail();1388}13891390if (custom_format == eFormatEnum)1391return false;13921393// this only works for arrays, because I have no way to know when the1394// pointed memory ends, and no special \0 end of data marker1395if (flags.Test(eTypeIsArray)) {1396if ((custom_format == eFormatBytes) ||1397(custom_format == eFormatBytesWithASCII)) {1398const size_t count = GetNumChildrenIgnoringErrors();13991400s << '[';1401for (size_t low = 0; low < count; low++) {14021403if (low)1404s << ',';14051406ValueObjectSP child = GetChildAtIndex(low);1407if (!child.get()) {1408s << "<invalid child>";1409continue;1410}1411child->DumpPrintableRepresentation(1412s, ValueObject::eValueObjectRepresentationStyleValue,1413custom_format);1414}14151416s << ']';14171418return true;1419}14201421if ((custom_format == eFormatVectorOfChar) ||1422(custom_format == eFormatVectorOfFloat32) ||1423(custom_format == eFormatVectorOfFloat64) ||1424(custom_format == eFormatVectorOfSInt16) ||1425(custom_format == eFormatVectorOfSInt32) ||1426(custom_format == eFormatVectorOfSInt64) ||1427(custom_format == eFormatVectorOfSInt8) ||1428(custom_format == eFormatVectorOfUInt128) ||1429(custom_format == eFormatVectorOfUInt16) ||1430(custom_format == eFormatVectorOfUInt32) ||1431(custom_format == eFormatVectorOfUInt64) ||1432(custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes1433// with ASCII or any vector1434// format should be printed1435// directly1436{1437const size_t count = GetNumChildrenIgnoringErrors();14381439Format format = FormatManager::GetSingleItemFormat(custom_format);14401441s << '[';1442for (size_t low = 0; low < count; low++) {14431444if (low)1445s << ',';14461447ValueObjectSP child = GetChildAtIndex(low);1448if (!child.get()) {1449s << "<invalid child>";1450continue;1451}1452child->DumpPrintableRepresentation(1453s, ValueObject::eValueObjectRepresentationStyleValue, format);1454}14551456s << ']';14571458return true;1459}1460}14611462if ((custom_format == eFormatBoolean) ||1463(custom_format == eFormatBinary) || (custom_format == eFormatChar) ||1464(custom_format == eFormatCharPrintable) ||1465(custom_format == eFormatComplexFloat) ||1466(custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||1467(custom_format == eFormatHexUppercase) ||1468(custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||1469(custom_format == eFormatOSType) ||1470(custom_format == eFormatUnicode16) ||1471(custom_format == eFormatUnicode32) ||1472(custom_format == eFormatUnsigned) ||1473(custom_format == eFormatPointer) ||1474(custom_format == eFormatComplexInteger) ||1475(custom_format == eFormatComplex) ||1476(custom_format == eFormatDefault)) // use the [] operator1477return false;1478}1479}14801481if (only_special)1482return false;14831484bool var_success = false;14851486{1487llvm::StringRef str;14881489// this is a local stream that we are using to ensure that the data pointed1490// to by cstr survives long enough for us to copy it to its destination -1491// it is necessary to have this temporary storage area for cases where our1492// desired output is not backed by some other longer-term storage1493StreamString strm;14941495if (custom_format != eFormatInvalid)1496SetFormat(custom_format);14971498switch (val_obj_display) {1499case eValueObjectRepresentationStyleValue:1500str = GetValueAsCString();1501break;15021503case eValueObjectRepresentationStyleSummary:1504str = GetSummaryAsCString();1505break;15061507case eValueObjectRepresentationStyleLanguageSpecific: {1508llvm::Expected<std::string> desc = GetObjectDescription();1509if (!desc) {1510strm << "error: " << toString(desc.takeError());1511str = strm.GetString();1512} else {1513strm << *desc;1514str = strm.GetString();1515}1516} break;15171518case eValueObjectRepresentationStyleLocation:1519str = GetLocationAsCString();1520break;15211522case eValueObjectRepresentationStyleChildrenCount: {1523if (auto err = GetNumChildren()) {1524strm.Printf("%" PRIu32, *err);1525str = strm.GetString();1526} else {1527strm << "error: " << toString(err.takeError());1528str = strm.GetString();1529}1530break;1531}15321533case eValueObjectRepresentationStyleType:1534str = GetTypeName().GetStringRef();1535break;15361537case eValueObjectRepresentationStyleName:1538str = GetName().GetStringRef();1539break;15401541case eValueObjectRepresentationStyleExpressionPath:1542GetExpressionPath(strm);1543str = strm.GetString();1544break;1545}15461547// If the requested display style produced no output, try falling back to1548// alternative presentations.1549if (str.empty()) {1550if (val_obj_display == eValueObjectRepresentationStyleValue)1551str = GetSummaryAsCString();1552else if (val_obj_display == eValueObjectRepresentationStyleSummary) {1553if (!CanProvideValue()) {1554strm.Printf("%s @ %s", GetTypeName().AsCString(),1555GetLocationAsCString());1556str = strm.GetString();1557} else1558str = GetValueAsCString();1559}1560}15611562if (!str.empty())1563s << str;1564else {1565// We checked for errors at the start, but do it again here in case1566// realizing the value for dumping produced an error.1567if (m_error.Fail()) {1568if (do_dump_error)1569s.Printf("<%s>", m_error.AsCString());1570else1571return false;1572} else if (val_obj_display == eValueObjectRepresentationStyleSummary)1573s.PutCString("<no summary available>");1574else if (val_obj_display == eValueObjectRepresentationStyleValue)1575s.PutCString("<no value available>");1576else if (val_obj_display ==1577eValueObjectRepresentationStyleLanguageSpecific)1578s.PutCString("<not a valid Objective-C object>"); // edit this if we1579// have other runtimes1580// that support a1581// description1582else1583s.PutCString("<no printable representation>");1584}15851586// we should only return false here if we could not do *anything* even if1587// we have an error message as output, that's a success from our callers'1588// perspective, so return true1589var_success = true;15901591if (custom_format != eFormatInvalid)1592SetFormat(eFormatDefault);1593}15941595return var_success;1596}15971598ValueObject::AddrAndType1599ValueObject::GetAddressOf(bool scalar_is_load_address) {1600// Can't take address of a bitfield1601if (IsBitfield())1602return {};16031604if (!UpdateValueIfNeeded(false))1605return {};16061607switch (m_value.GetValueType()) {1608case Value::ValueType::Invalid:1609return {};1610case Value::ValueType::Scalar:1611if (scalar_is_load_address) {1612return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1613eAddressTypeLoad};1614}1615return {};16161617case Value::ValueType::LoadAddress:1618case Value::ValueType::FileAddress:1619return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1620m_value.GetValueAddressType()};1621case Value::ValueType::HostAddress:1622return {LLDB_INVALID_ADDRESS, m_value.GetValueAddressType()};1623}1624llvm_unreachable("Unhandled value type!");1625}16261627ValueObject::AddrAndType ValueObject::GetPointerValue() {1628if (!UpdateValueIfNeeded(false))1629return {};16301631switch (m_value.GetValueType()) {1632case Value::ValueType::Invalid:1633return {};1634case Value::ValueType::Scalar:1635return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1636GetAddressTypeOfChildren()};16371638case Value::ValueType::HostAddress:1639case Value::ValueType::LoadAddress:1640case Value::ValueType::FileAddress: {1641lldb::offset_t data_offset = 0;1642return {m_data.GetAddress(&data_offset), GetAddressTypeOfChildren()};1643}1644}16451646llvm_unreachable("Unhandled value type!");1647}16481649static const char *ConvertBoolean(lldb::LanguageType language_type,1650const char *value_str) {1651if (Language *language = Language::FindPlugin(language_type))1652if (auto boolean = language->GetBooleanFromString(value_str))1653return *boolean ? "1" : "0";16541655return llvm::StringSwitch<const char *>(value_str)1656.Case("true", "1")1657.Case("false", "0")1658.Default(value_str);1659}16601661bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {1662error.Clear();1663// Make sure our value is up to date first so that our location and location1664// type is valid.1665if (!UpdateValueIfNeeded(false)) {1666error = Status::FromErrorString("unable to read value");1667return false;1668}16691670uint64_t count = 0;1671const Encoding encoding = GetCompilerType().GetEncoding(count);16721673const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);16741675Value::ValueType value_type = m_value.GetValueType();16761677if (value_type == Value::ValueType::Scalar) {1678// If the value is already a scalar, then let the scalar change itself:1679m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);1680} else if (byte_size <= 16) {1681if (GetCompilerType().IsBoolean())1682value_str = ConvertBoolean(GetObjectRuntimeLanguage(), value_str);16831684// If the value fits in a scalar, then make a new scalar and again let the1685// scalar code do the conversion, then figure out where to put the new1686// value.1687Scalar new_scalar;1688error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);1689if (error.Success()) {1690switch (value_type) {1691case Value::ValueType::LoadAddress: {1692// If it is a load address, then the scalar value is the storage1693// location of the data, and we have to shove this value down to that1694// load location.1695ExecutionContext exe_ctx(GetExecutionContextRef());1696Process *process = exe_ctx.GetProcessPtr();1697if (process) {1698addr_t target_addr =1699m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1700size_t bytes_written = process->WriteScalarToMemory(1701target_addr, new_scalar, byte_size, error);1702if (!error.Success())1703return false;1704if (bytes_written != byte_size) {1705error = Status::FromErrorString("unable to write value to memory");1706return false;1707}1708}1709} break;1710case Value::ValueType::HostAddress: {1711// If it is a host address, then we stuff the scalar as a DataBuffer1712// into the Value's data.1713DataExtractor new_data;1714new_data.SetByteOrder(m_data.GetByteOrder());17151716DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));1717m_data.SetData(buffer_sp, 0);1718bool success = new_scalar.GetData(new_data);1719if (success) {1720new_data.CopyByteOrderedData(17210, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),1722byte_size, m_data.GetByteOrder());1723}1724m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();17251726} break;1727case Value::ValueType::Invalid:1728error = Status::FromErrorString("invalid location");1729return false;1730case Value::ValueType::FileAddress:1731case Value::ValueType::Scalar:1732break;1733}1734} else {1735return false;1736}1737} else {1738// We don't support setting things bigger than a scalar at present.1739error = Status::FromErrorString("unable to write aggregate data type");1740return false;1741}17421743// If we have reached this point, then we have successfully changed the1744// value.1745SetNeedsUpdate();1746return true;1747}17481749bool ValueObject::GetDeclaration(Declaration &decl) {1750decl.Clear();1751return false;1752}17531754void ValueObject::AddSyntheticChild(ConstString key, ValueObject *valobj) {1755m_synthetic_children[key] = valobj;1756}17571758ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {1759ValueObjectSP synthetic_child_sp;1760std::map<ConstString, ValueObject *>::const_iterator pos =1761m_synthetic_children.find(key);1762if (pos != m_synthetic_children.end())1763synthetic_child_sp = pos->second->GetSP();1764return synthetic_child_sp;1765}17661767bool ValueObject::IsPossibleDynamicType() {1768ExecutionContext exe_ctx(GetExecutionContextRef());1769Process *process = exe_ctx.GetProcessPtr();1770if (process)1771return process->IsPossibleDynamicValue(*this);1772else1773return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);1774}17751776bool ValueObject::IsRuntimeSupportValue() {1777Process *process(GetProcessSP().get());1778if (!process)1779return false;17801781// We trust that the compiler did the right thing and marked runtime support1782// values as artificial.1783if (!GetVariable() || !GetVariable()->IsArtificial())1784return false;17851786if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))1787if (runtime->IsAllowedRuntimeValue(GetName()))1788return false;17891790return true;1791}17921793bool ValueObject::IsNilReference() {1794if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1795return language->IsNilReference(*this);1796}1797return false;1798}17991800bool ValueObject::IsUninitializedReference() {1801if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1802return language->IsUninitializedReference(*this);1803}1804return false;1805}18061807// This allows you to create an array member using and index that doesn't not1808// fall in the normal bounds of the array. Many times structure can be defined1809// as: struct Collection {1810// uint32_t item_count;1811// Item item_array[0];1812// };1813// The size of the "item_array" is 1, but many times in practice there are more1814// items in "item_array".18151816ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,1817bool can_create) {1818ValueObjectSP synthetic_child_sp;1819if (IsPointerType() || IsArrayType()) {1820std::string index_str = llvm::formatv("[{0}]", index);1821ConstString index_const_str(index_str);1822// Check if we have already created a synthetic array member in this valid1823// object. If we have we will re-use it.1824synthetic_child_sp = GetSyntheticChild(index_const_str);1825if (!synthetic_child_sp) {1826ValueObject *synthetic_child;1827// We haven't made a synthetic array member for INDEX yet, so lets make1828// one and cache it for any future reference.1829synthetic_child = CreateSyntheticArrayMember(index);18301831// Cache the value if we got one back...1832if (synthetic_child) {1833AddSyntheticChild(index_const_str, synthetic_child);1834synthetic_child_sp = synthetic_child->GetSP();1835synthetic_child_sp->SetName(ConstString(index_str));1836synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;1837}1838}1839}1840return synthetic_child_sp;1841}18421843ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,1844bool can_create) {1845ValueObjectSP synthetic_child_sp;1846if (IsScalarType()) {1847std::string index_str = llvm::formatv("[{0}-{1}]", from, to);1848ConstString index_const_str(index_str);1849// Check if we have already created a synthetic array member in this valid1850// object. If we have we will re-use it.1851synthetic_child_sp = GetSyntheticChild(index_const_str);1852if (!synthetic_child_sp) {1853uint32_t bit_field_size = to - from + 1;1854uint32_t bit_field_offset = from;1855if (GetDataExtractor().GetByteOrder() == eByteOrderBig)1856bit_field_offset =1857llvm::expectedToOptional(GetByteSize()).value_or(0) * 8 -1858bit_field_size - bit_field_offset;1859// We haven't made a synthetic array member for INDEX yet, so lets make1860// one and cache it for any future reference.1861ValueObjectChild *synthetic_child = new ValueObjectChild(1862*this, GetCompilerType(), index_const_str,1863llvm::expectedToOptional(GetByteSize()).value_or(0), 0,1864bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid,18650);18661867// Cache the value if we got one back...1868if (synthetic_child) {1869AddSyntheticChild(index_const_str, synthetic_child);1870synthetic_child_sp = synthetic_child->GetSP();1871synthetic_child_sp->SetName(ConstString(index_str));1872synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;1873}1874}1875}1876return synthetic_child_sp;1877}18781879ValueObjectSP ValueObject::GetSyntheticChildAtOffset(1880uint32_t offset, const CompilerType &type, bool can_create,1881ConstString name_const_str) {18821883ValueObjectSP synthetic_child_sp;18841885if (name_const_str.IsEmpty()) {1886name_const_str.SetString("@" + std::to_string(offset));1887}18881889// Check if we have already created a synthetic array member in this valid1890// object. If we have we will re-use it.1891synthetic_child_sp = GetSyntheticChild(name_const_str);18921893if (synthetic_child_sp.get())1894return synthetic_child_sp;18951896if (!can_create)1897return {};18981899ExecutionContext exe_ctx(GetExecutionContextRef());1900std::optional<uint64_t> size = llvm::expectedToOptional(1901type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));1902if (!size)1903return {};1904ValueObjectChild *synthetic_child =1905new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1906false, false, eAddressTypeInvalid, 0);1907if (synthetic_child) {1908AddSyntheticChild(name_const_str, synthetic_child);1909synthetic_child_sp = synthetic_child->GetSP();1910synthetic_child_sp->SetName(name_const_str);1911synthetic_child_sp->m_flags.m_is_child_at_offset = true;1912}1913return synthetic_child_sp;1914}19151916ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,1917const CompilerType &type,1918bool can_create,1919ConstString name_const_str) {1920ValueObjectSP synthetic_child_sp;19211922if (name_const_str.IsEmpty()) {1923char name_str[128];1924snprintf(name_str, sizeof(name_str), "base%s@%i",1925type.GetTypeName().AsCString("<unknown>"), offset);1926name_const_str.SetCString(name_str);1927}19281929// Check if we have already created a synthetic array member in this valid1930// object. If we have we will re-use it.1931synthetic_child_sp = GetSyntheticChild(name_const_str);19321933if (synthetic_child_sp.get())1934return synthetic_child_sp;19351936if (!can_create)1937return {};19381939const bool is_base_class = true;19401941ExecutionContext exe_ctx(GetExecutionContextRef());1942std::optional<uint64_t> size = llvm::expectedToOptional(1943type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));1944if (!size)1945return {};1946ValueObjectChild *synthetic_child =1947new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1948is_base_class, false, eAddressTypeInvalid, 0);1949if (synthetic_child) {1950AddSyntheticChild(name_const_str, synthetic_child);1951synthetic_child_sp = synthetic_child->GetSP();1952synthetic_child_sp->SetName(name_const_str);1953}1954return synthetic_child_sp;1955}19561957// your expression path needs to have a leading . or -> (unless it somehow1958// "looks like" an array, in which case it has a leading [ symbol). while the [1959// is meaningful and should be shown to the user, . and -> are just parser1960// design, but by no means added information for the user.. strip them off1961static const char *SkipLeadingExpressionPathSeparators(const char *expression) {1962if (!expression || !expression[0])1963return expression;1964if (expression[0] == '.')1965return expression + 1;1966if (expression[0] == '-' && expression[1] == '>')1967return expression + 2;1968return expression;1969}19701971ValueObjectSP1972ValueObject::GetSyntheticExpressionPathChild(const char *expression,1973bool can_create) {1974ValueObjectSP synthetic_child_sp;1975ConstString name_const_string(expression);1976// Check if we have already created a synthetic array member in this valid1977// object. If we have we will re-use it.1978synthetic_child_sp = GetSyntheticChild(name_const_string);1979if (!synthetic_child_sp) {1980// We haven't made a synthetic array member for expression yet, so lets1981// make one and cache it for any future reference.1982synthetic_child_sp = GetValueForExpressionPath(1983expression, nullptr, nullptr,1984GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(1985GetValueForExpressionPathOptions::SyntheticChildrenTraversal::1986None));19871988// Cache the value if we got one back...1989if (synthetic_child_sp.get()) {1990// FIXME: this causes a "real" child to end up with its name changed to1991// the contents of expression1992AddSyntheticChild(name_const_string, synthetic_child_sp.get());1993synthetic_child_sp->SetName(1994ConstString(SkipLeadingExpressionPathSeparators(expression)));1995}1996}1997return synthetic_child_sp;1998}19992000void ValueObject::CalculateSyntheticValue() {2001TargetSP target_sp(GetTargetSP());2002if (target_sp && !target_sp->GetEnableSyntheticValue()) {2003m_synthetic_value = nullptr;2004return;2005}20062007lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);20082009if (!UpdateFormatsIfNeeded() && m_synthetic_value)2010return;20112012if (m_synthetic_children_sp.get() == nullptr)2013return;20142015if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)2016return;20172018m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);2019}20202021void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {2022if (use_dynamic == eNoDynamicValues)2023return;20242025if (!m_dynamic_value && !IsDynamic()) {2026ExecutionContext exe_ctx(GetExecutionContextRef());2027Process *process = exe_ctx.GetProcessPtr();2028if (process && process->IsPossibleDynamicValue(*this)) {2029ClearDynamicTypeInformation();2030m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);2031}2032}2033}20342035ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {2036if (use_dynamic == eNoDynamicValues)2037return ValueObjectSP();20382039if (!IsDynamic() && m_dynamic_value == nullptr) {2040CalculateDynamicValue(use_dynamic);2041}2042if (m_dynamic_value && m_dynamic_value->GetError().Success())2043return m_dynamic_value->GetSP();2044else2045return ValueObjectSP();2046}20472048ValueObjectSP ValueObject::GetSyntheticValue() {2049CalculateSyntheticValue();20502051if (m_synthetic_value)2052return m_synthetic_value->GetSP();2053else2054return ValueObjectSP();2055}20562057bool ValueObject::HasSyntheticValue() {2058UpdateFormatsIfNeeded();20592060if (m_synthetic_children_sp.get() == nullptr)2061return false;20622063CalculateSyntheticValue();20642065return m_synthetic_value != nullptr;2066}20672068ValueObject *ValueObject::GetNonBaseClassParent() {2069if (GetParent()) {2070if (GetParent()->IsBaseClass())2071return GetParent()->GetNonBaseClassParent();2072else2073return GetParent();2074}2075return nullptr;2076}20772078bool ValueObject::IsBaseClass(uint32_t &depth) {2079if (!IsBaseClass()) {2080depth = 0;2081return false;2082}2083if (GetParent()) {2084GetParent()->IsBaseClass(depth);2085depth = depth + 1;2086return true;2087}2088// TODO: a base of no parent? weird..2089depth = 1;2090return true;2091}20922093void ValueObject::GetExpressionPath(Stream &s,2094GetExpressionPathFormat epformat) {2095// synthetic children do not actually "exist" as part of the hierarchy, and2096// sometimes they are consed up in ways that don't make sense from an2097// underlying language/API standpoint. So, use a special code path here to2098// return something that can hopefully be used in expression2099if (m_flags.m_is_synthetic_children_generated) {2100UpdateValueIfNeeded();21012102if (m_value.GetValueType() == Value::ValueType::LoadAddress) {2103if (IsPointerOrReferenceType()) {2104s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),2105GetValueAsUnsigned(0));2106return;2107} else {2108uint64_t load_addr =2109m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);2110if (load_addr != LLDB_INVALID_ADDRESS) {2111s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),2112load_addr);2113return;2114}2115}2116}21172118if (CanProvideValue()) {2119s.Printf("((%s)%s)", GetTypeName().AsCString("void"),2120GetValueAsCString());2121return;2122}21232124return;2125}21262127const bool is_deref_of_parent = IsDereferenceOfParent();21282129if (is_deref_of_parent &&2130epformat == eGetExpressionPathFormatDereferencePointers) {2131// this is the original format of GetExpressionPath() producing code like2132// *(a_ptr).memberName, which is entirely fine, until you put this into2133// StackFrame::GetValueForVariableExpressionPath() which prefers to see2134// a_ptr->memberName. the eHonorPointers mode is meant to produce strings2135// in this latter format2136s.PutCString("*(");2137}21382139ValueObject *parent = GetParent();21402141if (parent)2142parent->GetExpressionPath(s, epformat);21432144// if we are a deref_of_parent just because we are synthetic array members2145// made up to allow ptr[%d] syntax to work in variable printing, then add our2146// name ([%d]) to the expression path2147if (m_flags.m_is_array_item_for_pointer &&2148epformat == eGetExpressionPathFormatHonorPointers)2149s.PutCString(m_name.GetStringRef());21502151if (!IsBaseClass()) {2152if (!is_deref_of_parent) {2153ValueObject *non_base_class_parent = GetNonBaseClassParent();2154if (non_base_class_parent &&2155!non_base_class_parent->GetName().IsEmpty()) {2156CompilerType non_base_class_parent_compiler_type =2157non_base_class_parent->GetCompilerType();2158if (non_base_class_parent_compiler_type) {2159if (parent && parent->IsDereferenceOfParent() &&2160epformat == eGetExpressionPathFormatHonorPointers) {2161s.PutCString("->");2162} else {2163const uint32_t non_base_class_parent_type_info =2164non_base_class_parent_compiler_type.GetTypeInfo();21652166if (non_base_class_parent_type_info & eTypeIsPointer) {2167s.PutCString("->");2168} else if ((non_base_class_parent_type_info & eTypeHasChildren) &&2169!(non_base_class_parent_type_info & eTypeIsArray)) {2170s.PutChar('.');2171}2172}2173}2174}21752176const char *name = GetName().GetCString();2177if (name)2178s.PutCString(name);2179}2180}21812182if (is_deref_of_parent &&2183epformat == eGetExpressionPathFormatDereferencePointers) {2184s.PutChar(')');2185}2186}21872188// Return the alternate value (synthetic if the input object is non-synthetic2189// and otherwise) this is permitted by the expression path options.2190static ValueObjectSP GetAlternateValue(2191ValueObject &valobj,2192ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal2193synth_traversal) {2194using SynthTraversal =2195ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal;21962197if (valobj.IsSynthetic()) {2198if (synth_traversal == SynthTraversal::FromSynthetic ||2199synth_traversal == SynthTraversal::Both)2200return valobj.GetNonSyntheticValue();2201} else {2202if (synth_traversal == SynthTraversal::ToSynthetic ||2203synth_traversal == SynthTraversal::Both)2204return valobj.GetSyntheticValue();2205}2206return nullptr;2207}22082209// Dereference the provided object or the alternate value, if permitted by the2210// expression path options.2211static ValueObjectSP DereferenceValueOrAlternate(2212ValueObject &valobj,2213ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal2214synth_traversal,2215Status &error) {2216error.Clear();2217ValueObjectSP result = valobj.Dereference(error);2218if (!result || error.Fail()) {2219if (ValueObjectSP alt_obj = GetAlternateValue(valobj, synth_traversal)) {2220error.Clear();2221result = alt_obj->Dereference(error);2222}2223}2224return result;2225}22262227ValueObjectSP ValueObject::GetValueForExpressionPath(2228llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2229ExpressionPathEndResultType *final_value_type,2230const GetValueForExpressionPathOptions &options,2231ExpressionPathAftermath *final_task_on_target) {22322233ExpressionPathScanEndReason dummy_reason_to_stop =2234ValueObject::eExpressionPathScanEndReasonUnknown;2235ExpressionPathEndResultType dummy_final_value_type =2236ValueObject::eExpressionPathEndResultTypeInvalid;2237ExpressionPathAftermath dummy_final_task_on_target =2238ValueObject::eExpressionPathAftermathNothing;22392240ValueObjectSP ret_val = GetValueForExpressionPath_Impl(2241expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,2242final_value_type ? final_value_type : &dummy_final_value_type, options,2243final_task_on_target ? final_task_on_target2244: &dummy_final_task_on_target);22452246if (!final_task_on_target ||2247*final_task_on_target == ValueObject::eExpressionPathAftermathNothing)2248return ret_val;22492250if (ret_val.get() &&2251((final_value_type ? *final_value_type : dummy_final_value_type) ==2252eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress2253// of plain objects2254{2255if ((final_task_on_target ? *final_task_on_target2256: dummy_final_task_on_target) ==2257ValueObject::eExpressionPathAftermathDereference) {2258Status error;2259ValueObjectSP final_value = DereferenceValueOrAlternate(2260*ret_val, options.m_synthetic_children_traversal, error);2261if (error.Fail() || !final_value.get()) {2262if (reason_to_stop)2263*reason_to_stop =2264ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2265if (final_value_type)2266*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2267return ValueObjectSP();2268} else {2269if (final_task_on_target)2270*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2271return final_value;2272}2273}2274if (*final_task_on_target ==2275ValueObject::eExpressionPathAftermathTakeAddress) {2276Status error;2277ValueObjectSP final_value = ret_val->AddressOf(error);2278if (error.Fail() || !final_value.get()) {2279if (reason_to_stop)2280*reason_to_stop =2281ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;2282if (final_value_type)2283*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2284return ValueObjectSP();2285} else {2286if (final_task_on_target)2287*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2288return final_value;2289}2290}2291}2292return ret_val; // final_task_on_target will still have its original value, so2293// you know I did not do it2294}22952296ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(2297llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2298ExpressionPathEndResultType *final_result,2299const GetValueForExpressionPathOptions &options,2300ExpressionPathAftermath *what_next) {2301ValueObjectSP root = GetSP();23022303if (!root)2304return nullptr;23052306llvm::StringRef remainder = expression;23072308while (true) {2309llvm::StringRef temp_expression = remainder;23102311CompilerType root_compiler_type = root->GetCompilerType();2312CompilerType pointee_compiler_type;2313Flags pointee_compiler_type_info;23142315Flags root_compiler_type_info(2316root_compiler_type.GetTypeInfo(&pointee_compiler_type));2317if (pointee_compiler_type)2318pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());23192320if (temp_expression.empty()) {2321*reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;2322return root;2323}23242325switch (temp_expression.front()) {2326case '-': {2327temp_expression = temp_expression.drop_front();2328if (options.m_check_dot_vs_arrow_syntax &&2329root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2330// use -> on a2331// non-pointer and I2332// must catch the error2333{2334*reason_to_stop =2335ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;2336*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2337return ValueObjectSP();2338}2339if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to2340// extract an ObjC IVar2341// when this is forbidden2342root_compiler_type_info.Test(eTypeIsPointer) &&2343options.m_no_fragile_ivar) {2344*reason_to_stop =2345ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;2346*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2347return ValueObjectSP();2348}2349if (!temp_expression.starts_with(">")) {2350*reason_to_stop =2351ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2352*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2353return ValueObjectSP();2354}2355}2356[[fallthrough]];2357case '.': // or fallthrough from ->2358{2359if (options.m_check_dot_vs_arrow_syntax &&2360temp_expression.front() == '.' &&2361root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2362// use . on a pointer2363// and I must catch the2364// error2365{2366*reason_to_stop =2367ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;2368*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2369return nullptr;2370}2371temp_expression = temp_expression.drop_front(); // skip . or >23722373size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);2374if (next_sep_pos == llvm::StringRef::npos) {2375// if no other separator just expand this last layer2376llvm::StringRef child_name = temp_expression;2377ValueObjectSP child_valobj_sp =2378root->GetChildMemberWithName(child_name);2379if (!child_valobj_sp) {2380if (ValueObjectSP altroot = GetAlternateValue(2381*root, options.m_synthetic_children_traversal))2382child_valobj_sp = altroot->GetChildMemberWithName(child_name);2383}2384if (child_valobj_sp) {2385*reason_to_stop =2386ValueObject::eExpressionPathScanEndReasonEndOfString;2387*final_result = ValueObject::eExpressionPathEndResultTypePlain;2388return child_valobj_sp;2389}2390*reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;2391*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2392return nullptr;2393}23942395llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);2396llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);23972398ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name);2399if (!child_valobj_sp) {2400if (ValueObjectSP altroot = GetAlternateValue(2401*root, options.m_synthetic_children_traversal))2402child_valobj_sp = altroot->GetChildMemberWithName(child_name);2403}2404if (child_valobj_sp) {2405root = child_valobj_sp;2406remainder = next_separator;2407*final_result = ValueObject::eExpressionPathEndResultTypePlain;2408continue;2409}2410*reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;2411*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2412return nullptr;2413}2414case '[': {2415if (!root_compiler_type_info.Test(eTypeIsArray) &&2416!root_compiler_type_info.Test(eTypeIsPointer) &&2417!root_compiler_type_info.Test(2418eTypeIsVector)) // if this is not a T[] nor a T*2419{2420if (!root_compiler_type_info.Test(2421eTypeIsScalar)) // if this is not even a scalar...2422{2423if (options.m_synthetic_children_traversal ==2424GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2425None) // ...only chance left is synthetic2426{2427*reason_to_stop =2428ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;2429*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2430return ValueObjectSP();2431}2432} else if (!options.m_allow_bitfields_syntax) // if this is a scalar,2433// check that we can2434// expand bitfields2435{2436*reason_to_stop =2437ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;2438*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2439return ValueObjectSP();2440}2441}2442if (temp_expression[1] ==2443']') // if this is an unbounded range it only works for arrays2444{2445if (!root_compiler_type_info.Test(eTypeIsArray)) {2446*reason_to_stop =2447ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;2448*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2449return nullptr;2450} else // even if something follows, we cannot expand unbounded ranges,2451// just let the caller do it2452{2453*reason_to_stop =2454ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2455*final_result =2456ValueObject::eExpressionPathEndResultTypeUnboundedRange;2457return root;2458}2459}24602461size_t close_bracket_position = temp_expression.find(']', 1);2462if (close_bracket_position ==2463llvm::StringRef::npos) // if there is no ], this is a syntax error2464{2465*reason_to_stop =2466ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2467*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2468return nullptr;2469}24702471llvm::StringRef bracket_expr =2472temp_expression.slice(1, close_bracket_position);24732474// If this was an empty expression it would have been caught by the if2475// above.2476assert(!bracket_expr.empty());24772478if (!bracket_expr.contains('-')) {2479// if no separator, this is of the form [N]. Note that this cannot be2480// an unbounded range of the form [], because that case was handled2481// above with an unconditional return.2482unsigned long index = 0;2483if (bracket_expr.getAsInteger(0, index)) {2484*reason_to_stop =2485ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2486*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2487return nullptr;2488}24892490// from here on we do have a valid index2491if (root_compiler_type_info.Test(eTypeIsArray)) {2492ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);2493if (!child_valobj_sp)2494child_valobj_sp = root->GetSyntheticArrayMember(index, true);2495if (!child_valobj_sp)2496if (root->HasSyntheticValue() &&2497llvm::expectedToStdOptional(2498root->GetSyntheticValue()->GetNumChildren())2499.value_or(0) > index)2500child_valobj_sp =2501root->GetSyntheticValue()->GetChildAtIndex(index);2502if (child_valobj_sp) {2503root = child_valobj_sp;2504remainder =2505temp_expression.substr(close_bracket_position + 1); // skip ]2506*final_result = ValueObject::eExpressionPathEndResultTypePlain;2507continue;2508} else {2509*reason_to_stop =2510ValueObject::eExpressionPathScanEndReasonNoSuchChild;2511*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2512return nullptr;2513}2514} else if (root_compiler_type_info.Test(eTypeIsPointer)) {2515if (*what_next ==2516ValueObject::2517eExpressionPathAftermathDereference && // if this is a2518// ptr-to-scalar, I2519// am accessing it2520// by index and I2521// would have2522// deref'ed anyway,2523// then do it now2524// and use this as2525// a bitfield2526pointee_compiler_type_info.Test(eTypeIsScalar)) {2527Status error;2528root = DereferenceValueOrAlternate(2529*root, options.m_synthetic_children_traversal, error);2530if (error.Fail() || !root) {2531*reason_to_stop =2532ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2533*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2534return nullptr;2535} else {2536*what_next = eExpressionPathAftermathNothing;2537continue;2538}2539} else {2540if (root->GetCompilerType().GetMinimumLanguage() ==2541eLanguageTypeObjC &&2542pointee_compiler_type_info.AllClear(eTypeIsPointer) &&2543root->HasSyntheticValue() &&2544(options.m_synthetic_children_traversal ==2545GetValueForExpressionPathOptions::2546SyntheticChildrenTraversal::ToSynthetic ||2547options.m_synthetic_children_traversal ==2548GetValueForExpressionPathOptions::2549SyntheticChildrenTraversal::Both)) {2550root = root->GetSyntheticValue()->GetChildAtIndex(index);2551} else2552root = root->GetSyntheticArrayMember(index, true);2553if (!root) {2554*reason_to_stop =2555ValueObject::eExpressionPathScanEndReasonNoSuchChild;2556*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2557return nullptr;2558} else {2559remainder =2560temp_expression.substr(close_bracket_position + 1); // skip ]2561*final_result = ValueObject::eExpressionPathEndResultTypePlain;2562continue;2563}2564}2565} else if (root_compiler_type_info.Test(eTypeIsScalar)) {2566root = root->GetSyntheticBitFieldChild(index, index, true);2567if (!root) {2568*reason_to_stop =2569ValueObject::eExpressionPathScanEndReasonNoSuchChild;2570*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2571return nullptr;2572} else // we do not know how to expand members of bitfields, so we2573// just return and let the caller do any further processing2574{2575*reason_to_stop = ValueObject::2576eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2577*final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2578return root;2579}2580} else if (root_compiler_type_info.Test(eTypeIsVector)) {2581root = root->GetChildAtIndex(index);2582if (!root) {2583*reason_to_stop =2584ValueObject::eExpressionPathScanEndReasonNoSuchChild;2585*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2586return ValueObjectSP();2587} else {2588remainder =2589temp_expression.substr(close_bracket_position + 1); // skip ]2590*final_result = ValueObject::eExpressionPathEndResultTypePlain;2591continue;2592}2593} else if (options.m_synthetic_children_traversal ==2594GetValueForExpressionPathOptions::2595SyntheticChildrenTraversal::ToSynthetic ||2596options.m_synthetic_children_traversal ==2597GetValueForExpressionPathOptions::2598SyntheticChildrenTraversal::Both) {2599if (root->HasSyntheticValue())2600root = root->GetSyntheticValue();2601else if (!root->IsSynthetic()) {2602*reason_to_stop =2603ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2604*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2605return nullptr;2606}2607// if we are here, then root itself is a synthetic VO.. should be2608// good to go26092610if (!root) {2611*reason_to_stop =2612ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2613*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2614return nullptr;2615}2616root = root->GetChildAtIndex(index);2617if (!root) {2618*reason_to_stop =2619ValueObject::eExpressionPathScanEndReasonNoSuchChild;2620*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2621return nullptr;2622} else {2623remainder =2624temp_expression.substr(close_bracket_position + 1); // skip ]2625*final_result = ValueObject::eExpressionPathEndResultTypePlain;2626continue;2627}2628} else {2629*reason_to_stop =2630ValueObject::eExpressionPathScanEndReasonNoSuchChild;2631*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2632return nullptr;2633}2634} else {2635// we have a low and a high index2636llvm::StringRef sleft, sright;2637unsigned long low_index, high_index;2638std::tie(sleft, sright) = bracket_expr.split('-');2639if (sleft.getAsInteger(0, low_index) ||2640sright.getAsInteger(0, high_index)) {2641*reason_to_stop =2642ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2643*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2644return nullptr;2645}26462647if (low_index > high_index) // swap indices if required2648std::swap(low_index, high_index);26492650if (root_compiler_type_info.Test(2651eTypeIsScalar)) // expansion only works for scalars2652{2653root = root->GetSyntheticBitFieldChild(low_index, high_index, true);2654if (!root) {2655*reason_to_stop =2656ValueObject::eExpressionPathScanEndReasonNoSuchChild;2657*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2658return nullptr;2659} else {2660*reason_to_stop = ValueObject::2661eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2662*final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2663return root;2664}2665} else if (root_compiler_type_info.Test(2666eTypeIsPointer) && // if this is a ptr-to-scalar, I am2667// accessing it by index and I would2668// have deref'ed anyway, then do it2669// now and use this as a bitfield2670*what_next ==2671ValueObject::eExpressionPathAftermathDereference &&2672pointee_compiler_type_info.Test(eTypeIsScalar)) {2673Status error;2674root = DereferenceValueOrAlternate(2675*root, options.m_synthetic_children_traversal, error);2676if (error.Fail() || !root) {2677*reason_to_stop =2678ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2679*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2680return nullptr;2681} else {2682*what_next = ValueObject::eExpressionPathAftermathNothing;2683continue;2684}2685} else {2686*reason_to_stop =2687ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2688*final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;2689return root;2690}2691}2692break;2693}2694default: // some non-separator is in the way2695{2696*reason_to_stop =2697ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2698*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2699return nullptr;2700}2701}2702}2703}27042705llvm::Error ValueObject::Dump(Stream &s) {2706return Dump(s, DumpValueObjectOptions(*this));2707}27082709llvm::Error ValueObject::Dump(Stream &s,2710const DumpValueObjectOptions &options) {2711ValueObjectPrinter printer(*this, &s, options);2712return printer.PrintValueObject();2713}27142715ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {2716ValueObjectSP valobj_sp;27172718if (UpdateValueIfNeeded(false) && m_error.Success()) {2719ExecutionContext exe_ctx(GetExecutionContextRef());27202721DataExtractor data;2722data.SetByteOrder(m_data.GetByteOrder());2723data.SetAddressByteSize(m_data.GetAddressByteSize());27242725if (IsBitfield()) {2726Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));2727m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());2728} else2729m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());27302731valobj_sp = ValueObjectConstResult::Create(2732exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,2733GetAddressOf().address);2734}27352736if (!valobj_sp) {2737ExecutionContext exe_ctx(GetExecutionContextRef());2738valobj_sp = ValueObjectConstResult::Create(2739exe_ctx.GetBestExecutionContextScope(), m_error.Clone());2740}2741return valobj_sp;2742}27432744ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(2745lldb::DynamicValueType dynValue, bool synthValue) {2746ValueObjectSP result_sp;2747switch (dynValue) {2748case lldb::eDynamicCanRunTarget:2749case lldb::eDynamicDontRunTarget: {2750if (!IsDynamic())2751result_sp = GetDynamicValue(dynValue);2752} break;2753case lldb::eNoDynamicValues: {2754if (IsDynamic())2755result_sp = GetStaticValue();2756} break;2757}2758if (!result_sp)2759result_sp = GetSP();2760assert(result_sp);27612762bool is_synthetic = result_sp->IsSynthetic();2763if (synthValue && !is_synthetic) {2764if (auto synth_sp = result_sp->GetSyntheticValue())2765return synth_sp;2766}2767if (!synthValue && is_synthetic) {2768if (auto non_synth_sp = result_sp->GetNonSyntheticValue())2769return non_synth_sp;2770}27712772return result_sp;2773}27742775ValueObjectSP ValueObject::Dereference(Status &error) {2776if (m_deref_valobj)2777return m_deref_valobj->GetSP();27782779std::string deref_name_str;2780uint32_t deref_byte_size = 0;2781int32_t deref_byte_offset = 0;2782CompilerType compiler_type = GetCompilerType();2783uint64_t language_flags = 0;27842785ExecutionContext exe_ctx(GetExecutionContextRef());27862787CompilerType deref_compiler_type;2788auto deref_compiler_type_or_err = compiler_type.GetDereferencedType(2789&exe_ctx, deref_name_str, deref_byte_size, deref_byte_offset, this,2790language_flags);27912792std::string deref_error;2793if (deref_compiler_type_or_err) {2794deref_compiler_type = *deref_compiler_type_or_err;2795} else {2796deref_error = llvm::toString(deref_compiler_type_or_err.takeError());2797LLDB_LOG(GetLog(LLDBLog::Types), "could not find child: {0}", deref_error);2798}27992800if (deref_compiler_type && deref_byte_size) {2801ConstString deref_name;2802if (!deref_name_str.empty())2803deref_name.SetCString(deref_name_str.c_str());28042805m_deref_valobj =2806new ValueObjectChild(*this, deref_compiler_type, deref_name,2807deref_byte_size, deref_byte_offset, 0, 0, false,2808true, eAddressTypeInvalid, language_flags);2809}28102811// In case of incomplete deref compiler type, use the pointee type and try2812// to recreate a new ValueObjectChild using it.2813if (!m_deref_valobj) {2814// FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.2815// `std::vector<int> &`). Remove ObjC restriction once that's resolved.2816if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&2817HasSyntheticValue()) {2818deref_compiler_type = compiler_type.GetPointeeType();28192820if (deref_compiler_type) {2821ConstString deref_name;2822if (!deref_name_str.empty())2823deref_name.SetCString(deref_name_str.c_str());28242825m_deref_valobj = new ValueObjectChild(2826*this, deref_compiler_type, deref_name, deref_byte_size,2827deref_byte_offset, 0, 0, false, true, eAddressTypeInvalid,2828language_flags);2829}2830}2831}28322833if (!m_deref_valobj && IsSynthetic())2834m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();28352836if (m_deref_valobj) {2837error.Clear();2838return m_deref_valobj->GetSP();2839} else {2840StreamString strm;2841GetExpressionPath(strm);28422843if (deref_error.empty())2844error = Status::FromErrorStringWithFormat(2845"dereference failed: (%s) %s",2846GetTypeName().AsCString("<invalid type>"), strm.GetData());2847else2848error = Status::FromErrorStringWithFormat(2849"dereference failed: %s: (%s) %s", deref_error.c_str(),2850GetTypeName().AsCString("<invalid type>"), strm.GetData());2851return ValueObjectSP();2852}2853}28542855ValueObjectSP ValueObject::AddressOf(Status &error) {2856if (m_addr_of_valobj_sp)2857return m_addr_of_valobj_sp;28582859auto [addr, address_type] = GetAddressOf(/*scalar_is_load_address=*/false);2860error.Clear();2861if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {2862switch (address_type) {2863case eAddressTypeInvalid: {2864StreamString expr_path_strm;2865GetExpressionPath(expr_path_strm);2866error = Status::FromErrorStringWithFormat("'%s' is not in memory",2867expr_path_strm.GetData());2868} break;28692870case eAddressTypeFile:2871case eAddressTypeLoad: {2872CompilerType compiler_type = GetCompilerType();2873if (compiler_type) {2874std::string name(1, '&');2875name.append(m_name.AsCString(""));2876ExecutionContext exe_ctx(GetExecutionContextRef());28772878lldb::DataBufferSP buffer(2879new lldb_private::DataBufferHeap(&addr, sizeof(lldb::addr_t)));2880m_addr_of_valobj_sp = ValueObjectConstResult::Create(2881exe_ctx.GetBestExecutionContextScope(),2882compiler_type.GetPointerType(), ConstString(name.c_str()), buffer,2883endian::InlHostByteOrder(), exe_ctx.GetAddressByteSize());2884}2885} break;2886default:2887break;2888}2889} else {2890StreamString expr_path_strm;2891GetExpressionPath(expr_path_strm);2892error = Status::FromErrorStringWithFormat(2893"'%s' doesn't have a valid address", expr_path_strm.GetData());2894}28952896return m_addr_of_valobj_sp;2897}28982899ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {2900return ValueObjectCast::Create(*this, GetName(), compiler_type);2901}29022903ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {2904// Only allow casts if the original type is equal or larger than the cast2905// type, unless we know this is a load address. Getting the size wrong for2906// a host side storage could leak lldb memory, so we absolutely want to2907// prevent that. We may not always get the right value, for instance if we2908// have an expression result value that's copied into a storage location in2909// the target may not have copied enough memory. I'm not trying to fix that2910// here, I'm just making Cast from a smaller to a larger possible in all the2911// cases where that doesn't risk making a Value out of random lldb memory.2912// You have to check the ValueObject's Value for the address types, since2913// ValueObjects that use live addresses will tell you they fetch data from the2914// live address, but once they are made, they actually don't.2915// FIXME: Can we make ValueObject's with a live address fetch "more data" from2916// the live address if it is still valid?29172918Status error;2919CompilerType my_type = GetCompilerType();29202921ExecutionContextScope *exe_scope =2922ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope();2923if (llvm::expectedToOptional(compiler_type.GetByteSize(exe_scope))2924.value_or(0) <=2925llvm::expectedToOptional(GetCompilerType().GetByteSize(exe_scope))2926.value_or(0) ||2927m_value.GetValueType() == Value::ValueType::LoadAddress)2928return DoCast(compiler_type);29292930error = Status::FromErrorString(2931"Can only cast to a type that is equal to or smaller "2932"than the orignal type.");29332934return ValueObjectConstResult::Create(2935ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),2936std::move(error));2937}29382939lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {2940return ValueObjectCast::Create(*this, new_name, GetCompilerType());2941}29422943ValueObjectSP ValueObject::CastPointerType(const char *name,2944CompilerType &compiler_type) {2945ValueObjectSP valobj_sp;2946addr_t ptr_value = GetPointerValue().address;29472948if (ptr_value != LLDB_INVALID_ADDRESS) {2949Address ptr_addr(ptr_value);2950ExecutionContext exe_ctx(GetExecutionContextRef());2951valobj_sp = ValueObjectMemory::Create(2952exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);2953}2954return valobj_sp;2955}29562957ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {2958ValueObjectSP valobj_sp;2959addr_t ptr_value = GetPointerValue().address;29602961if (ptr_value != LLDB_INVALID_ADDRESS) {2962Address ptr_addr(ptr_value);2963ExecutionContext exe_ctx(GetExecutionContextRef());2964valobj_sp = ValueObjectMemory::Create(2965exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);2966}2967return valobj_sp;2968}29692970lldb::addr_t ValueObject::GetLoadAddress() {2971if (auto target_sp = GetTargetSP()) {2972const bool scalar_is_load_address = true;2973auto [addr_value, addr_type] = GetAddressOf(scalar_is_load_address);2974if (addr_type == eAddressTypeFile) {2975lldb::ModuleSP module_sp(GetModule());2976if (!module_sp)2977addr_value = LLDB_INVALID_ADDRESS;2978else {2979Address tmp_addr;2980module_sp->ResolveFileAddress(addr_value, tmp_addr);2981addr_value = tmp_addr.GetLoadAddress(target_sp.get());2982}2983} else if (addr_type == eAddressTypeHost ||2984addr_type == eAddressTypeInvalid)2985addr_value = LLDB_INVALID_ADDRESS;2986return addr_value;2987}2988return LLDB_INVALID_ADDRESS;2989}29902991llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(2992CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {2993// Make sure the starting type and the target type are both valid for this2994// type of cast; otherwise return the shared pointer to the original2995// (unchanged) ValueObject.2996if (!type.IsPointerType() && !type.IsReferenceType())2997return llvm::make_error<llvm::StringError>(2998"Invalid target type: should be a pointer or a reference",2999llvm::inconvertibleErrorCode());30003001CompilerType start_type = GetCompilerType();3002if (start_type.IsReferenceType())3003start_type = start_type.GetNonReferenceType();30043005auto target_record_type =3006type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3007auto start_record_type =3008start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;30093010if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3011return llvm::make_error<llvm::StringError>(3012"Underlying start & target types should be record types",3013llvm::inconvertibleErrorCode());30143015if (target_record_type.CompareTypes(start_record_type))3016return llvm::make_error<llvm::StringError>(3017"Underlying start & target types should be different",3018llvm::inconvertibleErrorCode());30193020if (base_type_indices.empty())3021return llvm::make_error<llvm::StringError>(3022"Children sequence must be non-empty", llvm::inconvertibleErrorCode());30233024// Both the starting & target types are valid for the cast, and the list of3025// base class indices is non-empty, so we can proceed with the cast.30263027lldb::TargetSP target = GetTargetSP();3028// The `value` can be a pointer, but GetChildAtIndex works for pointers too.3029lldb::ValueObjectSP inner_value = GetSP();30303031for (const uint32_t i : base_type_indices)3032// Create synthetic value if needed.3033inner_value =3034inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);30353036// At this point type of `inner_value` should be the dereferenced target3037// type.3038CompilerType inner_value_type = inner_value->GetCompilerType();3039if (type.IsPointerType()) {3040if (!inner_value_type.CompareTypes(type.GetPointeeType()))3041return llvm::make_error<llvm::StringError>(3042"casted value doesn't match the desired type",3043llvm::inconvertibleErrorCode());30443045uintptr_t addr = inner_value->GetLoadAddress();3046llvm::StringRef name = "";3047ExecutionContext exe_ctx(target.get(), false);3048return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,3049/* do deref */ false);3050}30513052// At this point the target type should be a reference.3053if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))3054return llvm::make_error<llvm::StringError>(3055"casted value doesn't match the desired type",3056llvm::inconvertibleErrorCode());30573058return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));3059}30603061llvm::Expected<lldb::ValueObjectSP>3062ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {3063// Make sure the starting type and the target type are both valid for this3064// type of cast; otherwise return the shared pointer to the original3065// (unchanged) ValueObject.3066if (!type.IsPointerType() && !type.IsReferenceType())3067return llvm::make_error<llvm::StringError>(3068"Invalid target type: should be a pointer or a reference",3069llvm::inconvertibleErrorCode());30703071CompilerType start_type = GetCompilerType();3072if (start_type.IsReferenceType())3073start_type = start_type.GetNonReferenceType();30743075auto target_record_type =3076type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3077auto start_record_type =3078start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;30793080if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3081return llvm::make_error<llvm::StringError>(3082"Underlying start & target types should be record types",3083llvm::inconvertibleErrorCode());30843085if (target_record_type.CompareTypes(start_record_type))3086return llvm::make_error<llvm::StringError>(3087"Underlying start & target types should be different",3088llvm::inconvertibleErrorCode());30893090CompilerType virtual_base;3091if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {3092if (!virtual_base.IsValid())3093return llvm::make_error<llvm::StringError>(3094"virtual base should be valid", llvm::inconvertibleErrorCode());3095return llvm::make_error<llvm::StringError>(3096llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +3097type.TypeDescription() + " via virtual base " +3098virtual_base.TypeDescription()),3099llvm::inconvertibleErrorCode());3100}31013102// Both the starting & target types are valid for the cast, so we can3103// proceed with the cast.31043105lldb::TargetSP target = GetTargetSP();3106auto pointer_type =3107type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();31083109uintptr_t addr =3110type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();31113112llvm::StringRef name = "";3113ExecutionContext exe_ctx(target.get(), false);3114lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(3115name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);31163117if (type.IsPointerType())3118return value;31193120// At this point the target type is a reference. Since `value` is a pointer,3121// it has to be dereferenced.3122Status error;3123return value->Dereference(error);3124}31253126lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {3127bool is_scalar = GetCompilerType().IsScalarType();3128bool is_enum = GetCompilerType().IsEnumerationType();3129bool is_pointer =3130GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();3131bool is_float = GetCompilerType().IsFloat();3132bool is_integer = GetCompilerType().IsInteger();3133ExecutionContext exe_ctx(GetExecutionContextRef());31343135if (!type.IsScalarType())3136return ValueObjectConstResult::Create(3137exe_ctx.GetBestExecutionContextScope(),3138Status::FromErrorString("target type must be a scalar"));31393140if (!is_scalar && !is_enum && !is_pointer)3141return ValueObjectConstResult::Create(3142exe_ctx.GetBestExecutionContextScope(),3143Status::FromErrorString("argument must be a scalar, enum, or pointer"));31443145lldb::TargetSP target = GetTargetSP();3146uint64_t type_byte_size = 0;3147uint64_t val_byte_size = 0;3148if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3149type_byte_size = temp.value();3150if (auto temp =3151llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))3152val_byte_size = temp.value();31533154if (is_pointer) {3155if (!type.IsInteger() && !type.IsBoolean())3156return ValueObjectConstResult::Create(3157exe_ctx.GetBestExecutionContextScope(),3158Status::FromErrorString("target type must be an integer or boolean"));3159if (!type.IsBoolean() && type_byte_size < val_byte_size)3160return ValueObjectConstResult::Create(3161exe_ctx.GetBestExecutionContextScope(),3162Status::FromErrorString(3163"target type cannot be smaller than the pointer type"));3164}31653166if (type.IsBoolean()) {3167if (!is_scalar || is_integer)3168return ValueObject::CreateValueObjectFromBool(3169target, GetValueAsUnsigned(0) != 0, "result");3170else if (is_scalar && is_float) {3171auto float_value_or_err = GetValueAsAPFloat();3172if (float_value_or_err)3173return ValueObject::CreateValueObjectFromBool(3174target, !float_value_or_err->isZero(), "result");3175else3176return ValueObjectConstResult::Create(3177exe_ctx.GetBestExecutionContextScope(),3178Status::FromErrorStringWithFormat(3179"cannot get value as APFloat: %s",3180llvm::toString(float_value_or_err.takeError()).c_str()));3181}3182}31833184if (type.IsInteger()) {3185if (!is_scalar || is_integer) {3186auto int_value_or_err = GetValueAsAPSInt();3187if (int_value_or_err) {3188// Get the value as APSInt and extend or truncate it to the requested3189// size.3190llvm::APSInt ext =3191int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3192return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3193"result");3194} else3195return ValueObjectConstResult::Create(3196exe_ctx.GetBestExecutionContextScope(),3197Status::FromErrorStringWithFormat(3198"cannot get value as APSInt: %s",3199llvm::toString(int_value_or_err.takeError()).c_str()));3200} else if (is_scalar && is_float) {3201llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());3202bool is_exact;3203auto float_value_or_err = GetValueAsAPFloat();3204if (float_value_or_err) {3205llvm::APFloatBase::opStatus status =3206float_value_or_err->convertToInteger(3207integer, llvm::APFloat::rmTowardZero, &is_exact);32083209// Casting floating point values that are out of bounds of the target3210// type is undefined behaviour.3211if (status & llvm::APFloatBase::opInvalidOp)3212return ValueObjectConstResult::Create(3213exe_ctx.GetBestExecutionContextScope(),3214Status::FromErrorStringWithFormat(3215"invalid type cast detected: %s",3216llvm::toString(float_value_or_err.takeError()).c_str()));3217return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3218"result");3219}3220}3221}32223223if (type.IsFloat()) {3224if (!is_scalar) {3225auto int_value_or_err = GetValueAsAPSInt();3226if (int_value_or_err) {3227llvm::APSInt ext =3228int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3229Scalar scalar_int(ext);3230llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(3231type.GetCanonicalType().GetBasicTypeEnumeration());3232return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3233"result");3234} else {3235return ValueObjectConstResult::Create(3236exe_ctx.GetBestExecutionContextScope(),3237Status::FromErrorStringWithFormat(3238"cannot get value as APSInt: %s",3239llvm::toString(int_value_or_err.takeError()).c_str()));3240}3241} else {3242if (is_integer) {3243auto int_value_or_err = GetValueAsAPSInt();3244if (int_value_or_err) {3245Scalar scalar_int(*int_value_or_err);3246llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(3247type.GetCanonicalType().GetBasicTypeEnumeration());3248return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3249"result");3250} else {3251return ValueObjectConstResult::Create(3252exe_ctx.GetBestExecutionContextScope(),3253Status::FromErrorStringWithFormat(3254"cannot get value as APSInt: %s",3255llvm::toString(int_value_or_err.takeError()).c_str()));3256}3257}3258if (is_float) {3259auto float_value_or_err = GetValueAsAPFloat();3260if (float_value_or_err) {3261Scalar scalar_float(*float_value_or_err);3262llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(3263type.GetCanonicalType().GetBasicTypeEnumeration());3264return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3265"result");3266} else {3267return ValueObjectConstResult::Create(3268exe_ctx.GetBestExecutionContextScope(),3269Status::FromErrorStringWithFormat(3270"cannot get value as APFloat: %s",3271llvm::toString(float_value_or_err.takeError()).c_str()));3272}3273}3274}3275}32763277return ValueObjectConstResult::Create(3278exe_ctx.GetBestExecutionContextScope(),3279Status::FromErrorString("Unable to perform requested cast"));3280}32813282lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {3283bool is_enum = GetCompilerType().IsEnumerationType();3284bool is_integer = GetCompilerType().IsInteger();3285bool is_float = GetCompilerType().IsFloat();3286ExecutionContext exe_ctx(GetExecutionContextRef());32873288if (!is_enum && !is_integer && !is_float)3289return ValueObjectConstResult::Create(3290exe_ctx.GetBestExecutionContextScope(),3291Status::FromErrorString(3292"argument must be an integer, a float, or an enum"));32933294if (!type.IsEnumerationType())3295return ValueObjectConstResult::Create(3296exe_ctx.GetBestExecutionContextScope(),3297Status::FromErrorString("target type must be an enum"));32983299lldb::TargetSP target = GetTargetSP();3300uint64_t byte_size = 0;3301if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3302byte_size = temp.value();33033304if (is_float) {3305llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());3306bool is_exact;3307auto value_or_err = GetValueAsAPFloat();3308if (value_or_err) {3309llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(3310integer, llvm::APFloat::rmTowardZero, &is_exact);33113312// Casting floating point values that are out of bounds of the target3313// type is undefined behaviour.3314if (status & llvm::APFloatBase::opInvalidOp)3315return ValueObjectConstResult::Create(3316exe_ctx.GetBestExecutionContextScope(),3317Status::FromErrorStringWithFormat(3318"invalid type cast detected: %s",3319llvm::toString(value_or_err.takeError()).c_str()));3320return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3321"result");3322} else3323return ValueObjectConstResult::Create(3324exe_ctx.GetBestExecutionContextScope(),3325Status::FromErrorString("cannot get value as APFloat"));3326} else {3327// Get the value as APSInt and extend or truncate it to the requested size.3328auto value_or_err = GetValueAsAPSInt();3329if (value_or_err) {3330llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);3331return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3332"result");3333} else3334return ValueObjectConstResult::Create(3335exe_ctx.GetBestExecutionContextScope(),3336Status::FromErrorStringWithFormat(3337"cannot get value as APSInt: %s",3338llvm::toString(value_or_err.takeError()).c_str()));3339}3340return ValueObjectConstResult::Create(3341exe_ctx.GetBestExecutionContextScope(),3342Status::FromErrorString("Cannot perform requested cast"));3343}33443345ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}33463347ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,3348bool use_selected)3349: m_mod_id(), m_exe_ctx_ref() {3350ExecutionContext exe_ctx(exe_scope);3351TargetSP target_sp(exe_ctx.GetTargetSP());3352if (target_sp) {3353m_exe_ctx_ref.SetTargetSP(target_sp);3354ProcessSP process_sp(exe_ctx.GetProcessSP());3355if (!process_sp)3356process_sp = target_sp->GetProcessSP();33573358if (process_sp) {3359m_mod_id = process_sp->GetModID();3360m_exe_ctx_ref.SetProcessSP(process_sp);33613362ThreadSP thread_sp(exe_ctx.GetThreadSP());33633364if (!thread_sp) {3365if (use_selected)3366thread_sp = process_sp->GetThreadList().GetSelectedThread();3367}33683369if (thread_sp) {3370m_exe_ctx_ref.SetThreadSP(thread_sp);33713372StackFrameSP frame_sp(exe_ctx.GetFrameSP());3373if (!frame_sp) {3374if (use_selected)3375frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);3376}3377if (frame_sp)3378m_exe_ctx_ref.SetFrameSP(frame_sp);3379}3380}3381}3382}33833384ValueObject::EvaluationPoint::EvaluationPoint(3385const ValueObject::EvaluationPoint &rhs)3386: m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}33873388ValueObject::EvaluationPoint::~EvaluationPoint() = default;33893390// This function checks the EvaluationPoint against the current process state.3391// If the current state matches the evaluation point, or the evaluation point3392// is already invalid, then we return false, meaning "no change". If the3393// current state is different, we update our state, and return true meaning3394// "yes, change". If we did see a change, we also set m_needs_update to true,3395// so future calls to NeedsUpdate will return true. exe_scope will be set to3396// the current execution context scope.33973398bool ValueObject::EvaluationPoint::SyncWithProcessState(3399bool accept_invalid_exe_ctx) {3400// Start with the target, if it is NULL, then we're obviously not going to3401// get any further:3402const bool thread_and_frame_only_if_stopped = true;3403ExecutionContext exe_ctx(3404m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));34053406if (exe_ctx.GetTargetPtr() == nullptr)3407return false;34083409// If we don't have a process nothing can change.3410Process *process = exe_ctx.GetProcessPtr();3411if (process == nullptr)3412return false;34133414// If our stop id is the current stop ID, nothing has changed:3415ProcessModID current_mod_id = process->GetModID();34163417// If the current stop id is 0, either we haven't run yet, or the process3418// state has been cleared. In either case, we aren't going to be able to sync3419// with the process state.3420if (current_mod_id.GetStopID() == 0)3421return false;34223423bool changed = false;3424const bool was_valid = m_mod_id.IsValid();3425if (was_valid) {3426if (m_mod_id == current_mod_id) {3427// Everything is already up to date in this object, no need to update the3428// execution context scope.3429changed = false;3430} else {3431m_mod_id = current_mod_id;3432m_needs_update = true;3433changed = true;3434}3435}34363437// Now re-look up the thread and frame in case the underlying objects have3438// gone away & been recreated. That way we'll be sure to return a valid3439// exe_scope. If we used to have a thread or a frame but can't find it3440// anymore, then mark ourselves as invalid.34413442if (!accept_invalid_exe_ctx) {3443if (m_exe_ctx_ref.HasThreadRef()) {3444ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());3445if (thread_sp) {3446if (m_exe_ctx_ref.HasFrameRef()) {3447StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());3448if (!frame_sp) {3449// We used to have a frame, but now it is gone3450SetInvalid();3451changed = was_valid;3452}3453}3454} else {3455// We used to have a thread, but now it is gone3456SetInvalid();3457changed = was_valid;3458}3459}3460}34613462return changed;3463}34643465void ValueObject::EvaluationPoint::SetUpdated() {3466ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());3467if (process_sp)3468m_mod_id = process_sp->GetModID();3469m_needs_update = false;3470}34713472void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {3473if ((clear_mask & eClearUserVisibleDataItemsValue) ==3474eClearUserVisibleDataItemsValue)3475m_value_str.clear();34763477if ((clear_mask & eClearUserVisibleDataItemsLocation) ==3478eClearUserVisibleDataItemsLocation)3479m_location_str.clear();34803481if ((clear_mask & eClearUserVisibleDataItemsSummary) ==3482eClearUserVisibleDataItemsSummary)3483m_summary_str.clear();34843485if ((clear_mask & eClearUserVisibleDataItemsDescription) ==3486eClearUserVisibleDataItemsDescription)3487m_object_desc_str.clear();34883489if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==3490eClearUserVisibleDataItemsSyntheticChildren) {3491if (m_synthetic_value)3492m_synthetic_value = nullptr;3493}3494}34953496SymbolContextScope *ValueObject::GetSymbolContextScope() {3497if (m_parent) {3498if (!m_parent->IsPointerOrReferenceType())3499return m_parent->GetSymbolContextScope();3500}3501return nullptr;3502}35033504lldb::ValueObjectSP3505ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,3506llvm::StringRef expression,3507const ExecutionContext &exe_ctx) {3508return CreateValueObjectFromExpression(name, expression, exe_ctx,3509EvaluateExpressionOptions());3510}35113512lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(3513llvm::StringRef name, llvm::StringRef expression,3514const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {3515lldb::ValueObjectSP retval_sp;3516lldb::TargetSP target_sp(exe_ctx.GetTargetSP());3517if (!target_sp)3518return retval_sp;3519if (expression.empty())3520return retval_sp;3521target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),3522retval_sp, options);3523if (retval_sp && !name.empty())3524retval_sp->SetName(ConstString(name));3525return retval_sp;3526}35273528lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(3529llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,3530CompilerType type, bool do_deref) {3531if (type) {3532CompilerType pointer_type(type.GetPointerType());3533if (!do_deref)3534pointer_type = type;3535if (pointer_type) {3536lldb::DataBufferSP buffer(3537new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));3538lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(3539exe_ctx.GetBestExecutionContextScope(), pointer_type,3540ConstString(name), buffer, exe_ctx.GetByteOrder(),3541exe_ctx.GetAddressByteSize()));3542if (ptr_result_valobj_sp) {3543if (do_deref)3544ptr_result_valobj_sp->GetValue().SetValueType(3545Value::ValueType::LoadAddress);3546Status err;3547if (do_deref)3548ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);3549if (ptr_result_valobj_sp && !name.empty())3550ptr_result_valobj_sp->SetName(ConstString(name));3551}3552return ptr_result_valobj_sp;3553}3554}3555return lldb::ValueObjectSP();3556}35573558lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(3559llvm::StringRef name, const DataExtractor &data,3560const ExecutionContext &exe_ctx, CompilerType type) {3561lldb::ValueObjectSP new_value_sp;3562new_value_sp = ValueObjectConstResult::Create(3563exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,3564LLDB_INVALID_ADDRESS);3565new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);3566if (new_value_sp && !name.empty())3567new_value_sp->SetName(ConstString(name));3568return new_value_sp;3569}35703571lldb::ValueObjectSP3572ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,3573const llvm::APInt &v, CompilerType type,3574llvm::StringRef name) {3575ExecutionContext exe_ctx(target.get(), false);3576uint64_t byte_size = 0;3577if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3578byte_size = temp.value();3579lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3580reinterpret_cast<const void *>(v.getRawData()), byte_size,3581exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());3582return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3583}35843585lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(3586lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,3587llvm::StringRef name) {3588return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);3589}35903591lldb::ValueObjectSP3592ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,3593llvm::StringRef name) {3594CompilerType target_type;3595if (target) {3596for (auto type_system_sp : target->GetScratchTypeSystems())3597if (auto compiler_type =3598type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {3599target_type = compiler_type;3600break;3601}3602}3603ExecutionContext exe_ctx(target.get(), false);3604uint64_t byte_size = 0;3605if (auto temp =3606llvm::expectedToOptional(target_type.GetByteSize(target.get())))3607byte_size = temp.value();3608lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3609reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),3610exe_ctx.GetAddressByteSize());3611return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,3612target_type);3613}36143615lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(3616lldb::TargetSP target, CompilerType type, llvm::StringRef name) {3617if (!type.IsNullPtrType()) {3618lldb::ValueObjectSP ret_val;3619return ret_val;3620}3621uintptr_t zero = 0;3622ExecutionContext exe_ctx(target.get(), false);3623uint64_t byte_size = 0;3624if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3625byte_size = temp.value();3626lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3627reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),3628exe_ctx.GetAddressByteSize());3629return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3630}36313632ModuleSP ValueObject::GetModule() {3633ValueObject *root(GetRoot());3634if (root != this)3635return root->GetModule();3636return lldb::ModuleSP();3637}36383639ValueObject *ValueObject::GetRoot() {3640if (m_root)3641return m_root;3642return (m_root = FollowParentChain([](ValueObject *vo) -> bool {3643return (vo->m_parent != nullptr);3644}));3645}36463647ValueObject *3648ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {3649ValueObject *vo = this;3650while (vo) {3651if (!f(vo))3652break;3653vo = vo->m_parent;3654}3655return vo;3656}36573658AddressType ValueObject::GetAddressTypeOfChildren() {3659if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {3660ValueObject *root(GetRoot());3661if (root != this)3662return root->GetAddressTypeOfChildren();3663}3664return m_address_type_of_ptr_or_ref_children;3665}36663667lldb::DynamicValueType ValueObject::GetDynamicValueType() {3668ValueObject *with_dv_info = this;3669while (with_dv_info) {3670if (with_dv_info->HasDynamicValueTypeInfo())3671return with_dv_info->GetDynamicValueTypeImpl();3672with_dv_info = with_dv_info->m_parent;3673}3674return lldb::eNoDynamicValues;3675}36763677lldb::Format ValueObject::GetFormat() const {3678const ValueObject *with_fmt_info = this;3679while (with_fmt_info) {3680if (with_fmt_info->m_format != lldb::eFormatDefault)3681return with_fmt_info->m_format;3682with_fmt_info = with_fmt_info->m_parent;3683}3684return m_format;3685}36863687lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {3688lldb::LanguageType type = m_preferred_display_language;3689if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {3690if (GetRoot()) {3691if (GetRoot() == this) {3692if (StackFrameSP frame_sp = GetFrameSP()) {3693const SymbolContext &sc(3694frame_sp->GetSymbolContext(eSymbolContextCompUnit));3695if (CompileUnit *cu = sc.comp_unit)3696type = cu->GetLanguage();3697}3698} else {3699type = GetRoot()->GetPreferredDisplayLanguage();3700}3701}3702}3703return (m_preferred_display_language = type); // only compute it once3704}37053706void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {3707if (m_preferred_display_language == lldb::eLanguageTypeUnknown)3708SetPreferredDisplayLanguage(lt);3709}37103711bool ValueObject::CanProvideValue() {3712// we need to support invalid types as providers of values because some bare-3713// board debugging scenarios have no notion of types, but still manage to3714// have raw numeric values for things like registers. sigh.3715CompilerType type = GetCompilerType();3716return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));3717}37183719ValueObjectSP ValueObject::Persist() {3720if (!UpdateValueIfNeeded())3721return nullptr;37223723TargetSP target_sp(GetTargetSP());3724if (!target_sp)3725return nullptr;37263727PersistentExpressionState *persistent_state =3728target_sp->GetPersistentExpressionStateForLanguage(3729GetPreferredDisplayLanguage());37303731if (!persistent_state)3732return nullptr;37333734ConstString name = persistent_state->GetNextPersistentVariableName();37353736ValueObjectSP const_result_sp =3737ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);37383739ExpressionVariableSP persistent_var_sp =3740persistent_state->CreatePersistentVariable(const_result_sp);3741persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;3742persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;37433744return persistent_var_sp->GetValueObject();3745}37463747lldb::ValueObjectSP ValueObject::GetVTable() {3748return ValueObjectVTable::Create(*this);3749}375037513752