Path: blob/main/contrib/llvm-project/lldb/source/Core/ValueObject.cpp
39587 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/Core/ValueObject.h"910#include "lldb/Core/Address.h"11#include "lldb/Core/Declaration.h"12#include "lldb/Core/Module.h"13#include "lldb/Core/ValueObjectCast.h"14#include "lldb/Core/ValueObjectChild.h"15#include "lldb/Core/ValueObjectConstResult.h"16#include "lldb/Core/ValueObjectDynamicValue.h"17#include "lldb/Core/ValueObjectMemory.h"18#include "lldb/Core/ValueObjectSyntheticFilter.h"19#include "lldb/Core/ValueObjectVTable.h"20#include "lldb/DataFormatters/DataVisualization.h"21#include "lldb/DataFormatters/DumpValueObjectOptions.h"22#include "lldb/DataFormatters/FormatManager.h"23#include "lldb/DataFormatters/StringPrinter.h"24#include "lldb/DataFormatters/TypeFormat.h"25#include "lldb/DataFormatters/TypeSummary.h"26#include "lldb/DataFormatters/ValueObjectPrinter.h"27#include "lldb/Expression/ExpressionVariable.h"28#include "lldb/Host/Config.h"29#include "lldb/Symbol/CompileUnit.h"30#include "lldb/Symbol/CompilerType.h"31#include "lldb/Symbol/SymbolContext.h"32#include "lldb/Symbol/Type.h"33#include "lldb/Symbol/Variable.h"34#include "lldb/Target/ExecutionContext.h"35#include "lldb/Target/Language.h"36#include "lldb/Target/LanguageRuntime.h"37#include "lldb/Target/Process.h"38#include "lldb/Target/StackFrame.h"39#include "lldb/Target/Target.h"40#include "lldb/Target/Thread.h"41#include "lldb/Target/ThreadList.h"42#include "lldb/Utility/DataBuffer.h"43#include "lldb/Utility/DataBufferHeap.h"44#include "lldb/Utility/Flags.h"45#include "lldb/Utility/LLDBLog.h"46#include "lldb/Utility/Log.h"47#include "lldb/Utility/Scalar.h"48#include "lldb/Utility/Stream.h"49#include "lldb/Utility/StreamString.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>6566#include <lldb/Core/ValueObject.h>6768namespace lldb_private {69class ExecutionContextScope;70}71namespace lldb_private {72class SymbolContextScope;73}7475using namespace lldb;76using namespace lldb_private;7778static user_id_t g_value_obj_uid = 0;7980// ValueObject constructor81ValueObject::ValueObject(ValueObject &parent)82: m_parent(&parent), m_update_point(parent.GetUpdatePoint()),83m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {84m_flags.m_is_synthetic_children_generated =85parent.m_flags.m_is_synthetic_children_generated;86m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());87m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());88m_manager->ManageObject(this);89}9091// ValueObject constructor92ValueObject::ValueObject(ExecutionContextScope *exe_scope,93ValueObjectManager &manager,94AddressType child_ptr_or_ref_addr_type)95: m_update_point(exe_scope), m_manager(&manager),96m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),97m_id(++g_value_obj_uid) {98if (exe_scope) {99TargetSP target_sp(exe_scope->CalculateTarget());100if (target_sp) {101const ArchSpec &arch = target_sp->GetArchitecture();102m_data.SetByteOrder(arch.GetByteOrder());103m_data.SetAddressByteSize(arch.GetAddressByteSize());104}105}106m_manager->ManageObject(this);107}108109// Destructor110ValueObject::~ValueObject() = default;111112bool ValueObject::UpdateValueIfNeeded(bool update_format) {113114bool did_change_formats = false;115116if (update_format)117did_change_formats = UpdateFormatsIfNeeded();118119// If this is a constant value, then our success is predicated on whether we120// have an error or not121if (GetIsConstant()) {122// if you are constant, things might still have changed behind your back123// (e.g. you are a frozen object and things have changed deeper than you124// cared to freeze-dry yourself) in this case, your value has not changed,125// but "computed" entries might have, so you might now have a different126// summary, or a different object description. clear these so we will127// recompute them128if (update_format && !did_change_formats)129ClearUserVisibleData(eClearUserVisibleDataItemsSummary |130eClearUserVisibleDataItemsDescription);131return m_error.Success();132}133134bool first_update = IsChecksumEmpty();135136if (NeedsUpdating()) {137m_update_point.SetUpdated();138139// Save the old value using swap to avoid a string copy which also will140// clear our m_value_str141if (m_value_str.empty()) {142m_flags.m_old_value_valid = false;143} else {144m_flags.m_old_value_valid = true;145m_old_value_str.swap(m_value_str);146ClearUserVisibleData(eClearUserVisibleDataItemsValue);147}148149ClearUserVisibleData();150151if (IsInScope()) {152const bool value_was_valid = GetValueIsValid();153SetValueDidChange(false);154155m_error.Clear();156157// Call the pure virtual function to update the value158159bool need_compare_checksums = false;160llvm::SmallVector<uint8_t, 16> old_checksum;161162if (!first_update && CanProvideValue()) {163need_compare_checksums = true;164old_checksum.resize(m_value_checksum.size());165std::copy(m_value_checksum.begin(), m_value_checksum.end(),166old_checksum.begin());167}168169bool success = UpdateValue();170171SetValueIsValid(success);172173if (success) {174UpdateChildrenAddressType();175const uint64_t max_checksum_size = 128;176m_data.Checksum(m_value_checksum, max_checksum_size);177} else {178need_compare_checksums = false;179m_value_checksum.clear();180}181182assert(!need_compare_checksums ||183(!old_checksum.empty() && !m_value_checksum.empty()));184185if (first_update)186SetValueDidChange(false);187else if (!m_flags.m_value_did_change && !success) {188// The value wasn't gotten successfully, so we mark this as changed if189// the value used to be valid and now isn't190SetValueDidChange(value_was_valid);191} else if (need_compare_checksums) {192SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],193m_value_checksum.size()));194}195196} else {197m_error.SetErrorString("out of scope");198}199}200return m_error.Success();201}202203bool ValueObject::UpdateFormatsIfNeeded() {204Log *log = GetLog(LLDBLog::DataFormatters);205LLDB_LOGF(log,206"[%s %p] checking for FormatManager revisions. ValueObject "207"rev: %d - Global rev: %d",208GetName().GetCString(), static_cast<void *>(this),209m_last_format_mgr_revision,210DataVisualization::GetCurrentRevision());211212bool any_change = false;213214if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {215m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();216any_change = true;217218SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));219SetSummaryFormat(220DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));221SetSyntheticChildren(222DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));223}224225return any_change;226}227228void ValueObject::SetNeedsUpdate() {229m_update_point.SetNeedsUpdate();230// We have to clear the value string here so ConstResult children will notice231// if their values are changed by hand (i.e. with SetValueAsCString).232ClearUserVisibleData(eClearUserVisibleDataItemsValue);233}234235void ValueObject::ClearDynamicTypeInformation() {236m_flags.m_children_count_valid = false;237m_flags.m_did_calculate_complete_objc_class_type = false;238m_last_format_mgr_revision = 0;239m_override_type = CompilerType();240SetValueFormat(lldb::TypeFormatImplSP());241SetSummaryFormat(lldb::TypeSummaryImplSP());242SetSyntheticChildren(lldb::SyntheticChildrenSP());243}244245CompilerType ValueObject::MaybeCalculateCompleteType() {246CompilerType compiler_type(GetCompilerTypeImpl());247248if (m_flags.m_did_calculate_complete_objc_class_type) {249if (m_override_type.IsValid())250return m_override_type;251else252return compiler_type;253}254255m_flags.m_did_calculate_complete_objc_class_type = true;256257ProcessSP process_sp(258GetUpdatePoint().GetExecutionContextRef().GetProcessSP());259260if (!process_sp)261return compiler_type;262263if (auto *runtime =264process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {265if (std::optional<CompilerType> complete_type =266runtime->GetRuntimeType(compiler_type)) {267m_override_type = *complete_type;268if (m_override_type.IsValid())269return m_override_type;270}271}272return compiler_type;273}274275276277DataExtractor &ValueObject::GetDataExtractor() {278UpdateValueIfNeeded(false);279return m_data;280}281282const Status &ValueObject::GetError() {283UpdateValueIfNeeded(false);284return m_error;285}286287const char *ValueObject::GetLocationAsCStringImpl(const Value &value,288const DataExtractor &data) {289if (UpdateValueIfNeeded(false)) {290if (m_location_str.empty()) {291StreamString sstr;292293Value::ValueType value_type = value.GetValueType();294295switch (value_type) {296case Value::ValueType::Invalid:297m_location_str = "invalid";298break;299case Value::ValueType::Scalar:300if (value.GetContextType() == Value::ContextType::RegisterInfo) {301RegisterInfo *reg_info = value.GetRegisterInfo();302if (reg_info) {303if (reg_info->name)304m_location_str = reg_info->name;305else if (reg_info->alt_name)306m_location_str = reg_info->alt_name;307if (m_location_str.empty())308m_location_str = (reg_info->encoding == lldb::eEncodingVector)309? "vector"310: "scalar";311}312}313if (m_location_str.empty())314m_location_str = "scalar";315break;316317case Value::ValueType::LoadAddress:318case Value::ValueType::FileAddress:319case Value::ValueType::HostAddress: {320uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;321sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,322value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));323m_location_str = std::string(sstr.GetString());324} break;325}326}327}328return m_location_str.c_str();329}330331bool ValueObject::ResolveValue(Scalar &scalar) {332if (UpdateValueIfNeeded(333false)) // make sure that you are up to date before returning anything334{335ExecutionContext exe_ctx(GetExecutionContextRef());336Value tmp_value(m_value);337scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());338if (scalar.IsValid()) {339const uint32_t bitfield_bit_size = GetBitfieldBitSize();340if (bitfield_bit_size)341return scalar.ExtractBitfield(bitfield_bit_size,342GetBitfieldBitOffset());343return true;344}345}346return false;347}348349bool ValueObject::IsLogicalTrue(Status &error) {350if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {351LazyBool is_logical_true = language->IsLogicalTrue(*this, error);352switch (is_logical_true) {353case eLazyBoolYes:354case eLazyBoolNo:355return (is_logical_true == true);356case eLazyBoolCalculate:357break;358}359}360361Scalar scalar_value;362363if (!ResolveValue(scalar_value)) {364error.SetErrorString("failed to get a scalar result");365return false;366}367368bool ret;369ret = scalar_value.ULongLong(1) != 0;370error.Clear();371return ret;372}373374ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {375ValueObjectSP child_sp;376// We may need to update our value if we are dynamic377if (IsPossibleDynamicType())378UpdateValueIfNeeded(false);379if (idx < GetNumChildrenIgnoringErrors()) {380// Check if we have already made the child value object?381if (can_create && !m_children.HasChildAtIndex(idx)) {382// No we haven't created the child at this index, so lets have our383// subclass do it and cache the result for quick future access.384m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));385}386387ValueObject *child = m_children.GetChildAtIndex(idx);388if (child != nullptr)389return child->GetSP();390}391return child_sp;392}393394lldb::ValueObjectSP395ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {396if (names.size() == 0)397return GetSP();398ValueObjectSP root(GetSP());399for (llvm::StringRef name : names) {400root = root->GetChildMemberWithName(name);401if (!root) {402return root;403}404}405return root;406}407408size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {409bool omit_empty_base_classes = true;410return GetCompilerType().GetIndexOfChildWithName(name,411omit_empty_base_classes);412}413414ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,415bool can_create) {416// We may need to update our value if we are dynamic.417if (IsPossibleDynamicType())418UpdateValueIfNeeded(false);419420// When getting a child by name, it could be buried inside some base classes421// (which really aren't part of the expression path), so we need a vector of422// indexes that can get us down to the correct child.423std::vector<uint32_t> child_indexes;424bool omit_empty_base_classes = true;425426if (!GetCompilerType().IsValid())427return ValueObjectSP();428429const size_t num_child_indexes =430GetCompilerType().GetIndexOfChildMemberWithName(431name, omit_empty_base_classes, child_indexes);432if (num_child_indexes == 0)433return nullptr;434435ValueObjectSP child_sp = GetSP();436for (uint32_t idx : child_indexes)437if (child_sp)438child_sp = child_sp->GetChildAtIndex(idx, can_create);439return child_sp;440}441442llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {443UpdateValueIfNeeded();444445if (max < UINT32_MAX) {446if (m_flags.m_children_count_valid) {447size_t children_count = m_children.GetChildrenCount();448return children_count <= max ? children_count : max;449} else450return CalculateNumChildren(max);451}452453if (!m_flags.m_children_count_valid) {454auto num_children_or_err = CalculateNumChildren();455if (num_children_or_err)456SetNumChildren(*num_children_or_err);457else458return num_children_or_err;459}460return m_children.GetChildrenCount();461}462463uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {464auto value_or_err = GetNumChildren(max);465if (value_or_err)466return *value_or_err;467LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),468"{0}");469return 0;470}471472bool ValueObject::MightHaveChildren() {473bool has_children = false;474const uint32_t type_info = GetTypeInfo();475if (type_info) {476if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))477has_children = true;478} else {479has_children = GetNumChildrenIgnoringErrors() > 0;480}481return has_children;482}483484// Should only be called by ValueObject::GetNumChildren()485void ValueObject::SetNumChildren(uint32_t num_children) {486m_flags.m_children_count_valid = true;487m_children.SetChildrenCount(num_children);488}489490ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {491bool omit_empty_base_classes = true;492bool ignore_array_bounds = false;493std::string child_name;494uint32_t child_byte_size = 0;495int32_t child_byte_offset = 0;496uint32_t child_bitfield_bit_size = 0;497uint32_t child_bitfield_bit_offset = 0;498bool child_is_base_class = false;499bool child_is_deref_of_parent = false;500uint64_t language_flags = 0;501const bool transparent_pointers = true;502503ExecutionContext exe_ctx(GetExecutionContextRef());504505auto child_compiler_type_or_err =506GetCompilerType().GetChildCompilerTypeAtIndex(507&exe_ctx, idx, transparent_pointers, omit_empty_base_classes,508ignore_array_bounds, child_name, child_byte_size, child_byte_offset,509child_bitfield_bit_size, child_bitfield_bit_offset,510child_is_base_class, child_is_deref_of_parent, this, language_flags);511if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {512LLDB_LOG_ERROR(GetLog(LLDBLog::Types),513child_compiler_type_or_err.takeError(),514"could not find child: {0}");515return nullptr;516}517518return new ValueObjectChild(519*this, *child_compiler_type_or_err, ConstString(child_name),520child_byte_size, child_byte_offset, child_bitfield_bit_size,521child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,522eAddressTypeInvalid, language_flags);523}524525ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {526bool omit_empty_base_classes = true;527bool ignore_array_bounds = true;528std::string child_name;529uint32_t child_byte_size = 0;530int32_t child_byte_offset = 0;531uint32_t child_bitfield_bit_size = 0;532uint32_t child_bitfield_bit_offset = 0;533bool child_is_base_class = false;534bool child_is_deref_of_parent = false;535uint64_t language_flags = 0;536const bool transparent_pointers = false;537538ExecutionContext exe_ctx(GetExecutionContextRef());539540auto child_compiler_type_or_err =541GetCompilerType().GetChildCompilerTypeAtIndex(542&exe_ctx, 0, transparent_pointers, omit_empty_base_classes,543ignore_array_bounds, child_name, child_byte_size, child_byte_offset,544child_bitfield_bit_size, child_bitfield_bit_offset,545child_is_base_class, child_is_deref_of_parent, this, language_flags);546if (!child_compiler_type_or_err) {547LLDB_LOG_ERROR(GetLog(LLDBLog::Types),548child_compiler_type_or_err.takeError(),549"could not find child: {0}");550return nullptr;551}552553if (child_compiler_type_or_err->IsValid()) {554child_byte_offset += child_byte_size * idx;555556return new ValueObjectChild(557*this, *child_compiler_type_or_err, ConstString(child_name),558child_byte_size, child_byte_offset, child_bitfield_bit_size,559child_bitfield_bit_offset, child_is_base_class,560child_is_deref_of_parent, eAddressTypeInvalid, language_flags);561}562563// In case of an incomplete type, try to use the ValueObject's564// synthetic value to create the child ValueObject.565if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())566return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();567568return nullptr;569}570571bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,572std::string &destination,573lldb::LanguageType lang) {574return GetSummaryAsCString(summary_ptr, destination,575TypeSummaryOptions().SetLanguage(lang));576}577578bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,579std::string &destination,580const TypeSummaryOptions &options) {581destination.clear();582583// If we have a forcefully completed type, don't try and show a summary from584// a valid summary string or function because the type is not complete and585// no member variables or member functions will be available.586if (GetCompilerType().IsForcefullyCompleted()) {587destination = "<incomplete type>";588return true;589}590591// ideally we would like to bail out if passing NULL, but if we do so we end592// up not providing the summary for function pointers anymore593if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)594return false;595596m_flags.m_is_getting_summary = true;597598TypeSummaryOptions actual_options(options);599600if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)601actual_options.SetLanguage(GetPreferredDisplayLanguage());602603// this is a hot path in code and we prefer to avoid setting this string all604// too often also clearing out other information that we might care to see in605// a crash log. might be useful in very specific situations though.606/*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.607Summary provider's description is %s",608GetTypeName().GetCString(),609GetName().GetCString(),610summary_ptr->GetDescription().c_str());*/611612if (UpdateValueIfNeeded(false) && summary_ptr) {613if (HasSyntheticValue())614m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on615// the synthetic children being616// up-to-date (e.g. ${svar%#})617summary_ptr->FormatObject(this, destination, actual_options);618}619m_flags.m_is_getting_summary = false;620return !destination.empty();621}622623const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {624if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {625TypeSummaryOptions summary_options;626summary_options.SetLanguage(lang);627GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,628summary_options);629}630if (m_summary_str.empty())631return nullptr;632return m_summary_str.c_str();633}634635bool ValueObject::GetSummaryAsCString(std::string &destination,636const TypeSummaryOptions &options) {637return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);638}639640bool ValueObject::IsCStringContainer(bool check_pointer) {641CompilerType pointee_or_element_compiler_type;642const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));643bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&644pointee_or_element_compiler_type.IsCharType());645if (!is_char_arr_ptr)646return false;647if (!check_pointer)648return true;649if (type_flags.Test(eTypeIsArray))650return true;651addr_t cstr_address = LLDB_INVALID_ADDRESS;652AddressType cstr_address_type = eAddressTypeInvalid;653cstr_address = GetPointerValue(&cstr_address_type);654return (cstr_address != LLDB_INVALID_ADDRESS);655}656657size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,658uint32_t item_count) {659CompilerType pointee_or_element_compiler_type;660const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);661const bool is_pointer_type = type_info & eTypeIsPointer;662const bool is_array_type = type_info & eTypeIsArray;663if (!(is_pointer_type || is_array_type))664return 0;665666if (item_count == 0)667return 0;668669ExecutionContext exe_ctx(GetExecutionContextRef());670671std::optional<uint64_t> item_type_size =672pointee_or_element_compiler_type.GetByteSize(673exe_ctx.GetBestExecutionContextScope());674if (!item_type_size)675return 0;676const uint64_t bytes = item_count * *item_type_size;677const uint64_t offset = item_idx * *item_type_size;678679if (item_idx == 0 && item_count == 1) // simply a deref680{681if (is_pointer_type) {682Status error;683ValueObjectSP pointee_sp = Dereference(error);684if (error.Fail() || pointee_sp.get() == nullptr)685return 0;686return pointee_sp->GetData(data, error);687} else {688ValueObjectSP child_sp = GetChildAtIndex(0);689if (child_sp.get() == nullptr)690return 0;691Status error;692return child_sp->GetData(data, error);693}694return true;695} else /* (items > 1) */696{697Status error;698lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;699lldb::DataBufferSP data_sp(heap_buf_ptr =700new lldb_private::DataBufferHeap());701702AddressType addr_type;703lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type)704: GetAddressOf(true, &addr_type);705706switch (addr_type) {707case eAddressTypeFile: {708ModuleSP module_sp(GetModule());709if (module_sp) {710addr = addr + offset;711Address so_addr;712module_sp->ResolveFileAddress(addr, so_addr);713ExecutionContext exe_ctx(GetExecutionContextRef());714Target *target = exe_ctx.GetTargetPtr();715if (target) {716heap_buf_ptr->SetByteSize(bytes);717size_t bytes_read = target->ReadMemory(718so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);719if (error.Success()) {720data.SetData(data_sp);721return bytes_read;722}723}724}725} break;726case eAddressTypeLoad: {727ExecutionContext exe_ctx(GetExecutionContextRef());728Process *process = exe_ctx.GetProcessPtr();729if (process) {730heap_buf_ptr->SetByteSize(bytes);731size_t bytes_read = process->ReadMemory(732addr + offset, heap_buf_ptr->GetBytes(), bytes, error);733if (error.Success() || bytes_read > 0) {734data.SetData(data_sp);735return bytes_read;736}737}738} break;739case eAddressTypeHost: {740auto max_bytes =741GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());742if (max_bytes && *max_bytes > offset) {743size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);744addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);745if (addr == 0 || addr == LLDB_INVALID_ADDRESS)746break;747heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);748data.SetData(data_sp);749return bytes_read;750}751} break;752case eAddressTypeInvalid:753break;754}755}756return 0;757}758759uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {760UpdateValueIfNeeded(false);761ExecutionContext exe_ctx(GetExecutionContextRef());762error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());763if (error.Fail()) {764if (m_data.GetByteSize()) {765data = m_data;766error.Clear();767return data.GetByteSize();768} else {769return 0;770}771}772data.SetAddressByteSize(m_data.GetAddressByteSize());773data.SetByteOrder(m_data.GetByteOrder());774return data.GetByteSize();775}776777bool ValueObject::SetData(DataExtractor &data, Status &error) {778error.Clear();779// Make sure our value is up to date first so that our location and location780// type is valid.781if (!UpdateValueIfNeeded(false)) {782error.SetErrorString("unable to read value");783return false;784}785786uint64_t count = 0;787const Encoding encoding = GetCompilerType().GetEncoding(count);788789const size_t byte_size = GetByteSize().value_or(0);790791Value::ValueType value_type = m_value.GetValueType();792793switch (value_type) {794case Value::ValueType::Invalid:795error.SetErrorString("invalid location");796return false;797case Value::ValueType::Scalar: {798Status set_error =799m_value.GetScalar().SetValueFromData(data, encoding, byte_size);800801if (!set_error.Success()) {802error.SetErrorStringWithFormat("unable to set scalar value: %s",803set_error.AsCString());804return false;805}806} break;807case Value::ValueType::LoadAddress: {808// If it is a load address, then the scalar value is the storage location809// of the data, and we have to shove this value down to that load location.810ExecutionContext exe_ctx(GetExecutionContextRef());811Process *process = exe_ctx.GetProcessPtr();812if (process) {813addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);814size_t bytes_written = process->WriteMemory(815target_addr, data.GetDataStart(), byte_size, error);816if (!error.Success())817return false;818if (bytes_written != byte_size) {819error.SetErrorString("unable to write value to memory");820return false;821}822}823} break;824case Value::ValueType::HostAddress: {825// If it is a host address, then we stuff the scalar as a DataBuffer into826// the Value's data.827DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));828m_data.SetData(buffer_sp, 0);829data.CopyByteOrderedData(0, byte_size,830const_cast<uint8_t *>(m_data.GetDataStart()),831byte_size, m_data.GetByteOrder());832m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();833} break;834case Value::ValueType::FileAddress:835break;836}837838// If we have reached this point, then we have successfully changed the839// value.840SetNeedsUpdate();841return true;842}843844static bool CopyStringDataToBufferSP(const StreamString &source,845lldb::WritableDataBufferSP &destination) {846llvm::StringRef src = source.GetString();847src = src.rtrim('\0');848destination = std::make_shared<DataBufferHeap>(src.size(), 0);849memcpy(destination->GetBytes(), src.data(), src.size());850return true;851}852853std::pair<size_t, bool>854ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,855Status &error, bool honor_array) {856bool was_capped = false;857StreamString s;858ExecutionContext exe_ctx(GetExecutionContextRef());859Target *target = exe_ctx.GetTargetPtr();860861if (!target) {862s << "<no target to read from>";863error.SetErrorString("no target to read from");864CopyStringDataToBufferSP(s, buffer_sp);865return {0, was_capped};866}867868const auto max_length = target->GetMaximumSizeOfStringSummary();869870size_t bytes_read = 0;871size_t total_bytes_read = 0;872873CompilerType compiler_type = GetCompilerType();874CompilerType elem_or_pointee_compiler_type;875const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));876if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&877elem_or_pointee_compiler_type.IsCharType()) {878addr_t cstr_address = LLDB_INVALID_ADDRESS;879AddressType cstr_address_type = eAddressTypeInvalid;880881size_t cstr_len = 0;882bool capped_data = false;883const bool is_array = type_flags.Test(eTypeIsArray);884if (is_array) {885// We have an array886uint64_t array_size = 0;887if (compiler_type.IsArrayType(nullptr, &array_size)) {888cstr_len = array_size;889if (cstr_len > max_length) {890capped_data = true;891cstr_len = max_length;892}893}894cstr_address = GetAddressOf(true, &cstr_address_type);895} else {896// We have a pointer897cstr_address = GetPointerValue(&cstr_address_type);898}899900if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) {901if (cstr_address_type == eAddressTypeHost && is_array) {902const char *cstr = GetDataExtractor().PeekCStr(0);903if (cstr == nullptr) {904s << "<invalid address>";905error.SetErrorString("invalid address");906CopyStringDataToBufferSP(s, buffer_sp);907return {0, was_capped};908}909s << llvm::StringRef(cstr, cstr_len);910CopyStringDataToBufferSP(s, buffer_sp);911return {cstr_len, was_capped};912} else {913s << "<invalid address>";914error.SetErrorString("invalid address");915CopyStringDataToBufferSP(s, buffer_sp);916return {0, was_capped};917}918}919920Address cstr_so_addr(cstr_address);921DataExtractor data;922if (cstr_len > 0 && honor_array) {923// I am using GetPointeeData() here to abstract the fact that some924// ValueObjects are actually frozen pointers in the host but the pointed-925// to data lives in the debuggee, and GetPointeeData() automatically926// takes care of this927GetPointeeData(data, 0, cstr_len);928929if ((bytes_read = data.GetByteSize()) > 0) {930total_bytes_read = bytes_read;931for (size_t offset = 0; offset < bytes_read; offset++)932s.Printf("%c", *data.PeekData(offset, 1));933if (capped_data)934was_capped = true;935}936} else {937cstr_len = max_length;938const size_t k_max_buf_size = 64;939940size_t offset = 0;941942int cstr_len_displayed = -1;943bool capped_cstr = false;944// I am using GetPointeeData() here to abstract the fact that some945// ValueObjects are actually frozen pointers in the host but the pointed-946// to data lives in the debuggee, and GetPointeeData() automatically947// takes care of this948while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {949total_bytes_read += bytes_read;950const char *cstr = data.PeekCStr(0);951size_t len = strnlen(cstr, k_max_buf_size);952if (cstr_len_displayed < 0)953cstr_len_displayed = len;954955if (len == 0)956break;957cstr_len_displayed += len;958if (len > bytes_read)959len = bytes_read;960if (len > cstr_len)961len = cstr_len;962963for (size_t offset = 0; offset < bytes_read; offset++)964s.Printf("%c", *data.PeekData(offset, 1));965966if (len < k_max_buf_size)967break;968969if (len >= cstr_len) {970capped_cstr = true;971break;972}973974cstr_len -= len;975offset += len;976}977978if (cstr_len_displayed >= 0) {979if (capped_cstr)980was_capped = true;981}982}983} else {984error.SetErrorString("not a string object");985s << "<not a string object>";986}987CopyStringDataToBufferSP(s, buffer_sp);988return {total_bytes_read, was_capped};989}990991llvm::Expected<std::string> ValueObject::GetObjectDescription() {992if (!UpdateValueIfNeeded(true))993return llvm::createStringError("could not update value");994995// Return cached value.996if (!m_object_desc_str.empty())997return m_object_desc_str;998999ExecutionContext exe_ctx(GetExecutionContextRef());1000Process *process = exe_ctx.GetProcessPtr();1001if (!process)1002return llvm::createStringError("no process");10031004// Returns the object description produced by one language runtime.1005auto get_object_description =1006[&](LanguageType language) -> llvm::Expected<std::string> {1007if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {1008StreamString s;1009if (llvm::Error error = runtime->GetObjectDescription(s, *this))1010return error;1011m_object_desc_str = s.GetString();1012return m_object_desc_str;1013}1014return llvm::createStringError("no native language runtime");1015};10161017// Try the native language runtime first.1018LanguageType native_language = GetObjectRuntimeLanguage();1019llvm::Expected<std::string> desc = get_object_description(native_language);1020if (desc)1021return desc;10221023// Try the Objective-C language runtime. This fallback is necessary1024// for Objective-C++ and mixed Objective-C / C++ programs.1025if (Language::LanguageIsCFamily(native_language)) {1026// We're going to try again, so let's drop the first error.1027llvm::consumeError(desc.takeError());1028return get_object_description(eLanguageTypeObjC);1029}1030return desc;1031}10321033bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,1034std::string &destination) {1035if (UpdateValueIfNeeded(false))1036return format.FormatObject(this, destination);1037else1038return false;1039}10401041bool ValueObject::GetValueAsCString(lldb::Format format,1042std::string &destination) {1043return GetValueAsCString(TypeFormatImpl_Format(format), destination);1044}10451046const char *ValueObject::GetValueAsCString() {1047if (UpdateValueIfNeeded(true)) {1048lldb::TypeFormatImplSP format_sp;1049lldb::Format my_format = GetFormat();1050if (my_format == lldb::eFormatDefault) {1051if (m_type_format_sp)1052format_sp = m_type_format_sp;1053else {1054if (m_flags.m_is_bitfield_for_scalar)1055my_format = eFormatUnsigned;1056else {1057if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {1058const RegisterInfo *reg_info = m_value.GetRegisterInfo();1059if (reg_info)1060my_format = reg_info->format;1061} else {1062my_format = GetValue().GetCompilerType().GetFormat();1063}1064}1065}1066}1067if (my_format != m_last_format || m_value_str.empty()) {1068m_last_format = my_format;1069if (!format_sp)1070format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);1071if (GetValueAsCString(*format_sp.get(), m_value_str)) {1072if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {1073// The value was gotten successfully, so we consider the value as1074// changed if the value string differs1075SetValueDidChange(m_old_value_str != m_value_str);1076}1077}1078}1079}1080if (m_value_str.empty())1081return nullptr;1082return m_value_str.c_str();1083}10841085// if > 8bytes, 0 is returned. this method should mostly be used to read1086// address values out of pointers1087uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {1088// If our byte size is zero this is an aggregate type that has children1089if (CanProvideValue()) {1090Scalar scalar;1091if (ResolveValue(scalar)) {1092if (success)1093*success = true;1094scalar.MakeUnsigned();1095return scalar.ULongLong(fail_value);1096}1097// fallthrough, otherwise...1098}10991100if (success)1101*success = false;1102return fail_value;1103}11041105int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {1106// If our byte size is zero this is an aggregate type that has children1107if (CanProvideValue()) {1108Scalar scalar;1109if (ResolveValue(scalar)) {1110if (success)1111*success = true;1112scalar.MakeSigned();1113return scalar.SLongLong(fail_value);1114}1115// fallthrough, otherwise...1116}11171118if (success)1119*success = false;1120return fail_value;1121}11221123llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {1124// Make sure the type can be converted to an APSInt.1125if (!GetCompilerType().IsInteger() &&1126!GetCompilerType().IsScopedEnumerationType() &&1127!GetCompilerType().IsEnumerationType() &&1128!GetCompilerType().IsPointerType() &&1129!GetCompilerType().IsNullPtrType() &&1130!GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())1131return llvm::make_error<llvm::StringError>(1132"type cannot be converted to APSInt", llvm::inconvertibleErrorCode());11331134if (CanProvideValue()) {1135Scalar scalar;1136if (ResolveValue(scalar))1137return scalar.GetAPSInt();1138}11391140return llvm::make_error<llvm::StringError>(1141"error occurred; unable to convert to APSInt",1142llvm::inconvertibleErrorCode());1143}11441145llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {1146if (!GetCompilerType().IsFloat())1147return llvm::make_error<llvm::StringError>(1148"type cannot be converted to APFloat", llvm::inconvertibleErrorCode());11491150if (CanProvideValue()) {1151Scalar scalar;1152if (ResolveValue(scalar))1153return scalar.GetAPFloat();1154}11551156return llvm::make_error<llvm::StringError>(1157"error occurred; unable to convert to APFloat",1158llvm::inconvertibleErrorCode());1159}11601161llvm::Expected<bool> ValueObject::GetValueAsBool() {1162CompilerType val_type = GetCompilerType();1163if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||1164val_type.IsPointerType()) {1165auto value_or_err = GetValueAsAPSInt();1166if (value_or_err)1167return value_or_err->getBoolValue();1168}1169if (val_type.IsFloat()) {1170auto value_or_err = GetValueAsAPFloat();1171if (value_or_err)1172return value_or_err->isNonZero();1173}1174if (val_type.IsArrayType())1175return GetAddressOf() != 0;11761177return llvm::make_error<llvm::StringError>("type cannot be converted to bool",1178llvm::inconvertibleErrorCode());1179}11801181void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {1182// Verify the current object is an integer object1183CompilerType val_type = GetCompilerType();1184if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1185!val_type.IsFloat() && !val_type.IsPointerType() &&1186!val_type.IsScalarType()) {1187error.SetErrorString("current value object is not an integer objet");1188return;1189}11901191// Verify the current object is not actually associated with any program1192// variable.1193if (GetVariable()) {1194error.SetErrorString("current value object is not a temporary object");1195return;1196}11971198// Verify the proposed new value is the right size.1199lldb::TargetSP target = GetTargetSP();1200uint64_t byte_size = 0;1201if (auto temp = GetCompilerType().GetByteSize(target.get()))1202byte_size = temp.value();1203if (value.getBitWidth() != byte_size * CHAR_BIT) {1204error.SetErrorString(1205"illegal argument: new value should be of the same size");1206return;1207}12081209lldb::DataExtractorSP data_sp;1210data_sp->SetData(value.getRawData(), byte_size,1211target->GetArchitecture().GetByteOrder());1212data_sp->SetAddressByteSize(1213static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));1214SetData(*data_sp, error);1215}12161217void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,1218Status &error) {1219// Verify the current object is an integer object1220CompilerType val_type = GetCompilerType();1221if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1222!val_type.IsFloat() && !val_type.IsPointerType() &&1223!val_type.IsScalarType()) {1224error.SetErrorString("current value object is not an integer objet");1225return;1226}12271228// Verify the current object is not actually associated with any program1229// variable.1230if (GetVariable()) {1231error.SetErrorString("current value object is not a temporary object");1232return;1233}12341235// Verify the proposed new value is the right type.1236CompilerType new_val_type = new_val_sp->GetCompilerType();1237if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&1238!new_val_type.IsPointerType()) {1239error.SetErrorString(1240"illegal argument: new value should be of the same size");1241return;1242}12431244if (new_val_type.IsInteger()) {1245auto value_or_err = new_val_sp->GetValueAsAPSInt();1246if (value_or_err)1247SetValueFromInteger(*value_or_err, error);1248else1249error.SetErrorString("error getting APSInt from new_val_sp");1250} else if (new_val_type.IsFloat()) {1251auto value_or_err = new_val_sp->GetValueAsAPFloat();1252if (value_or_err)1253SetValueFromInteger(value_or_err->bitcastToAPInt(), error);1254else1255error.SetErrorString("error getting APFloat from new_val_sp");1256} else if (new_val_type.IsPointerType()) {1257bool success = true;1258uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);1259if (success) {1260lldb::TargetSP target = GetTargetSP();1261uint64_t num_bits = 0;1262if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get()))1263num_bits = temp.value();1264SetValueFromInteger(llvm::APInt(num_bits, int_val), error);1265} else1266error.SetErrorString("error converting new_val_sp to integer");1267}1268}12691270// if any more "special cases" are added to1271// ValueObject::DumpPrintableRepresentation() please keep this call up to date1272// by returning true for your new special cases. We will eventually move to1273// checking this call result before trying to display special cases1274bool ValueObject::HasSpecialPrintableRepresentation(1275ValueObjectRepresentationStyle val_obj_display, Format custom_format) {1276Flags flags(GetTypeInfo());1277if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1278val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1279if (IsCStringContainer(true) &&1280(custom_format == eFormatCString || custom_format == eFormatCharArray ||1281custom_format == eFormatChar || custom_format == eFormatVectorOfChar))1282return true;12831284if (flags.Test(eTypeIsArray)) {1285if ((custom_format == eFormatBytes) ||1286(custom_format == eFormatBytesWithASCII))1287return true;12881289if ((custom_format == eFormatVectorOfChar) ||1290(custom_format == eFormatVectorOfFloat32) ||1291(custom_format == eFormatVectorOfFloat64) ||1292(custom_format == eFormatVectorOfSInt16) ||1293(custom_format == eFormatVectorOfSInt32) ||1294(custom_format == eFormatVectorOfSInt64) ||1295(custom_format == eFormatVectorOfSInt8) ||1296(custom_format == eFormatVectorOfUInt128) ||1297(custom_format == eFormatVectorOfUInt16) ||1298(custom_format == eFormatVectorOfUInt32) ||1299(custom_format == eFormatVectorOfUInt64) ||1300(custom_format == eFormatVectorOfUInt8))1301return true;1302}1303}1304return false;1305}13061307bool ValueObject::DumpPrintableRepresentation(1308Stream &s, ValueObjectRepresentationStyle val_obj_display,1309Format custom_format, PrintableRepresentationSpecialCases special,1310bool do_dump_error) {13111312// If the ValueObject has an error, we might end up dumping the type, which1313// is useful, but if we don't even have a type, then don't examine the object1314// further as that's not meaningful, only the error is.1315if (m_error.Fail() && !GetCompilerType().IsValid()) {1316if (do_dump_error)1317s.Printf("<%s>", m_error.AsCString());1318return false;1319}13201321Flags flags(GetTypeInfo());13221323bool allow_special =1324(special == ValueObject::PrintableRepresentationSpecialCases::eAllow);1325const bool only_special = false;13261327if (allow_special) {1328if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1329val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1330// when being asked to get a printable display an array or pointer type1331// directly, try to "do the right thing"13321333if (IsCStringContainer(true) &&1334(custom_format == eFormatCString ||1335custom_format == eFormatCharArray || custom_format == eFormatChar ||1336custom_format ==1337eFormatVectorOfChar)) // print char[] & char* directly1338{1339Status error;1340lldb::WritableDataBufferSP buffer_sp;1341std::pair<size_t, bool> read_string =1342ReadPointedString(buffer_sp, error,1343(custom_format == eFormatVectorOfChar) ||1344(custom_format == eFormatCharArray));1345lldb_private::formatters::StringPrinter::1346ReadBufferAndDumpToStreamOptions options(*this);1347options.SetData(DataExtractor(1348buffer_sp, lldb::eByteOrderInvalid,13498)); // none of this matters for a string - pass some defaults1350options.SetStream(&s);1351options.SetPrefixToken(nullptr);1352options.SetQuote('"');1353options.SetSourceSize(buffer_sp->GetByteSize());1354options.SetIsTruncated(read_string.second);1355options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);1356formatters::StringPrinter::ReadBufferAndDumpToStream<1357lldb_private::formatters::StringPrinter::StringElementType::ASCII>(1358options);1359return !error.Fail();1360}13611362if (custom_format == eFormatEnum)1363return false;13641365// this only works for arrays, because I have no way to know when the1366// pointed memory ends, and no special \0 end of data marker1367if (flags.Test(eTypeIsArray)) {1368if ((custom_format == eFormatBytes) ||1369(custom_format == eFormatBytesWithASCII)) {1370const size_t count = GetNumChildrenIgnoringErrors();13711372s << '[';1373for (size_t low = 0; low < count; low++) {13741375if (low)1376s << ',';13771378ValueObjectSP child = GetChildAtIndex(low);1379if (!child.get()) {1380s << "<invalid child>";1381continue;1382}1383child->DumpPrintableRepresentation(1384s, ValueObject::eValueObjectRepresentationStyleValue,1385custom_format);1386}13871388s << ']';13891390return true;1391}13921393if ((custom_format == eFormatVectorOfChar) ||1394(custom_format == eFormatVectorOfFloat32) ||1395(custom_format == eFormatVectorOfFloat64) ||1396(custom_format == eFormatVectorOfSInt16) ||1397(custom_format == eFormatVectorOfSInt32) ||1398(custom_format == eFormatVectorOfSInt64) ||1399(custom_format == eFormatVectorOfSInt8) ||1400(custom_format == eFormatVectorOfUInt128) ||1401(custom_format == eFormatVectorOfUInt16) ||1402(custom_format == eFormatVectorOfUInt32) ||1403(custom_format == eFormatVectorOfUInt64) ||1404(custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes1405// with ASCII or any vector1406// format should be printed1407// directly1408{1409const size_t count = GetNumChildrenIgnoringErrors();14101411Format format = FormatManager::GetSingleItemFormat(custom_format);14121413s << '[';1414for (size_t low = 0; low < count; low++) {14151416if (low)1417s << ',';14181419ValueObjectSP child = GetChildAtIndex(low);1420if (!child.get()) {1421s << "<invalid child>";1422continue;1423}1424child->DumpPrintableRepresentation(1425s, ValueObject::eValueObjectRepresentationStyleValue, format);1426}14271428s << ']';14291430return true;1431}1432}14331434if ((custom_format == eFormatBoolean) ||1435(custom_format == eFormatBinary) || (custom_format == eFormatChar) ||1436(custom_format == eFormatCharPrintable) ||1437(custom_format == eFormatComplexFloat) ||1438(custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||1439(custom_format == eFormatHexUppercase) ||1440(custom_format == eFormatFloat) || (custom_format == eFormatOctal) ||1441(custom_format == eFormatOSType) ||1442(custom_format == eFormatUnicode16) ||1443(custom_format == eFormatUnicode32) ||1444(custom_format == eFormatUnsigned) ||1445(custom_format == eFormatPointer) ||1446(custom_format == eFormatComplexInteger) ||1447(custom_format == eFormatComplex) ||1448(custom_format == eFormatDefault)) // use the [] operator1449return false;1450}1451}14521453if (only_special)1454return false;14551456bool var_success = false;14571458{1459llvm::StringRef str;14601461// this is a local stream that we are using to ensure that the data pointed1462// to by cstr survives long enough for us to copy it to its destination -1463// it is necessary to have this temporary storage area for cases where our1464// desired output is not backed by some other longer-term storage1465StreamString strm;14661467if (custom_format != eFormatInvalid)1468SetFormat(custom_format);14691470switch (val_obj_display) {1471case eValueObjectRepresentationStyleValue:1472str = GetValueAsCString();1473break;14741475case eValueObjectRepresentationStyleSummary:1476str = GetSummaryAsCString();1477break;14781479case eValueObjectRepresentationStyleLanguageSpecific: {1480llvm::Expected<std::string> desc = GetObjectDescription();1481if (!desc) {1482strm << "error: " << toString(desc.takeError());1483str = strm.GetString();1484} else {1485strm << *desc;1486str = strm.GetString();1487}1488} break;14891490case eValueObjectRepresentationStyleLocation:1491str = GetLocationAsCString();1492break;14931494case eValueObjectRepresentationStyleChildrenCount:1495strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors());1496str = strm.GetString();1497break;14981499case eValueObjectRepresentationStyleType:1500str = GetTypeName().GetStringRef();1501break;15021503case eValueObjectRepresentationStyleName:1504str = GetName().GetStringRef();1505break;15061507case eValueObjectRepresentationStyleExpressionPath:1508GetExpressionPath(strm);1509str = strm.GetString();1510break;1511}15121513// If the requested display style produced no output, try falling back to1514// alternative presentations.1515if (str.empty()) {1516if (val_obj_display == eValueObjectRepresentationStyleValue)1517str = GetSummaryAsCString();1518else if (val_obj_display == eValueObjectRepresentationStyleSummary) {1519if (!CanProvideValue()) {1520strm.Printf("%s @ %s", GetTypeName().AsCString(),1521GetLocationAsCString());1522str = strm.GetString();1523} else1524str = GetValueAsCString();1525}1526}15271528if (!str.empty())1529s << str;1530else {1531// We checked for errors at the start, but do it again here in case1532// realizing the value for dumping produced an error.1533if (m_error.Fail()) {1534if (do_dump_error)1535s.Printf("<%s>", m_error.AsCString());1536else1537return false;1538} else if (val_obj_display == eValueObjectRepresentationStyleSummary)1539s.PutCString("<no summary available>");1540else if (val_obj_display == eValueObjectRepresentationStyleValue)1541s.PutCString("<no value available>");1542else if (val_obj_display ==1543eValueObjectRepresentationStyleLanguageSpecific)1544s.PutCString("<not a valid Objective-C object>"); // edit this if we1545// have other runtimes1546// that support a1547// description1548else1549s.PutCString("<no printable representation>");1550}15511552// we should only return false here if we could not do *anything* even if1553// we have an error message as output, that's a success from our callers'1554// perspective, so return true1555var_success = true;15561557if (custom_format != eFormatInvalid)1558SetFormat(eFormatDefault);1559}15601561return var_success;1562}15631564addr_t ValueObject::GetAddressOf(bool scalar_is_load_address,1565AddressType *address_type) {1566// Can't take address of a bitfield1567if (IsBitfield())1568return LLDB_INVALID_ADDRESS;15691570if (!UpdateValueIfNeeded(false))1571return LLDB_INVALID_ADDRESS;15721573switch (m_value.GetValueType()) {1574case Value::ValueType::Invalid:1575return LLDB_INVALID_ADDRESS;1576case Value::ValueType::Scalar:1577if (scalar_is_load_address) {1578if (address_type)1579*address_type = eAddressTypeLoad;1580return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1581}1582break;15831584case Value::ValueType::LoadAddress:1585case Value::ValueType::FileAddress: {1586if (address_type)1587*address_type = m_value.GetValueAddressType();1588return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1589} break;1590case Value::ValueType::HostAddress: {1591if (address_type)1592*address_type = m_value.GetValueAddressType();1593return LLDB_INVALID_ADDRESS;1594} break;1595}1596if (address_type)1597*address_type = eAddressTypeInvalid;1598return LLDB_INVALID_ADDRESS;1599}16001601addr_t ValueObject::GetPointerValue(AddressType *address_type) {1602addr_t address = LLDB_INVALID_ADDRESS;1603if (address_type)1604*address_type = eAddressTypeInvalid;16051606if (!UpdateValueIfNeeded(false))1607return address;16081609switch (m_value.GetValueType()) {1610case Value::ValueType::Invalid:1611return LLDB_INVALID_ADDRESS;1612case Value::ValueType::Scalar:1613address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1614break;16151616case Value::ValueType::HostAddress:1617case Value::ValueType::LoadAddress:1618case Value::ValueType::FileAddress: {1619lldb::offset_t data_offset = 0;1620address = m_data.GetAddress(&data_offset);1621} break;1622}16231624if (address_type)1625*address_type = GetAddressTypeOfChildren();16261627return address;1628}16291630bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {1631error.Clear();1632// Make sure our value is up to date first so that our location and location1633// type is valid.1634if (!UpdateValueIfNeeded(false)) {1635error.SetErrorString("unable to read value");1636return false;1637}16381639uint64_t count = 0;1640const Encoding encoding = GetCompilerType().GetEncoding(count);16411642const size_t byte_size = GetByteSize().value_or(0);16431644Value::ValueType value_type = m_value.GetValueType();16451646if (value_type == Value::ValueType::Scalar) {1647// If the value is already a scalar, then let the scalar change itself:1648m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);1649} else if (byte_size <= 16) {1650// If the value fits in a scalar, then make a new scalar and again let the1651// scalar code do the conversion, then figure out where to put the new1652// value.1653Scalar new_scalar;1654error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);1655if (error.Success()) {1656switch (value_type) {1657case Value::ValueType::LoadAddress: {1658// If it is a load address, then the scalar value is the storage1659// location of the data, and we have to shove this value down to that1660// load location.1661ExecutionContext exe_ctx(GetExecutionContextRef());1662Process *process = exe_ctx.GetProcessPtr();1663if (process) {1664addr_t target_addr =1665m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1666size_t bytes_written = process->WriteScalarToMemory(1667target_addr, new_scalar, byte_size, error);1668if (!error.Success())1669return false;1670if (bytes_written != byte_size) {1671error.SetErrorString("unable to write value to memory");1672return false;1673}1674}1675} break;1676case Value::ValueType::HostAddress: {1677// If it is a host address, then we stuff the scalar as a DataBuffer1678// into the Value's data.1679DataExtractor new_data;1680new_data.SetByteOrder(m_data.GetByteOrder());16811682DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));1683m_data.SetData(buffer_sp, 0);1684bool success = new_scalar.GetData(new_data);1685if (success) {1686new_data.CopyByteOrderedData(16870, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),1688byte_size, m_data.GetByteOrder());1689}1690m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();16911692} break;1693case Value::ValueType::Invalid:1694error.SetErrorString("invalid location");1695return false;1696case Value::ValueType::FileAddress:1697case Value::ValueType::Scalar:1698break;1699}1700} else {1701return false;1702}1703} else {1704// We don't support setting things bigger than a scalar at present.1705error.SetErrorString("unable to write aggregate data type");1706return false;1707}17081709// If we have reached this point, then we have successfully changed the1710// value.1711SetNeedsUpdate();1712return true;1713}17141715bool ValueObject::GetDeclaration(Declaration &decl) {1716decl.Clear();1717return false;1718}17191720void ValueObject::AddSyntheticChild(ConstString key,1721ValueObject *valobj) {1722m_synthetic_children[key] = valobj;1723}17241725ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {1726ValueObjectSP synthetic_child_sp;1727std::map<ConstString, ValueObject *>::const_iterator pos =1728m_synthetic_children.find(key);1729if (pos != m_synthetic_children.end())1730synthetic_child_sp = pos->second->GetSP();1731return synthetic_child_sp;1732}17331734bool ValueObject::IsPossibleDynamicType() {1735ExecutionContext exe_ctx(GetExecutionContextRef());1736Process *process = exe_ctx.GetProcessPtr();1737if (process)1738return process->IsPossibleDynamicValue(*this);1739else1740return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);1741}17421743bool ValueObject::IsRuntimeSupportValue() {1744Process *process(GetProcessSP().get());1745if (!process)1746return false;17471748// We trust that the compiler did the right thing and marked runtime support1749// values as artificial.1750if (!GetVariable() || !GetVariable()->IsArtificial())1751return false;17521753if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))1754if (runtime->IsAllowedRuntimeValue(GetName()))1755return false;17561757return true;1758}17591760bool ValueObject::IsNilReference() {1761if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1762return language->IsNilReference(*this);1763}1764return false;1765}17661767bool ValueObject::IsUninitializedReference() {1768if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1769return language->IsUninitializedReference(*this);1770}1771return false;1772}17731774// This allows you to create an array member using and index that doesn't not1775// fall in the normal bounds of the array. Many times structure can be defined1776// as: struct Collection {1777// uint32_t item_count;1778// Item item_array[0];1779// };1780// The size of the "item_array" is 1, but many times in practice there are more1781// items in "item_array".17821783ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,1784bool can_create) {1785ValueObjectSP synthetic_child_sp;1786if (IsPointerType() || IsArrayType()) {1787std::string index_str = llvm::formatv("[{0}]", index);1788ConstString index_const_str(index_str);1789// Check if we have already created a synthetic array member in this valid1790// object. If we have we will re-use it.1791synthetic_child_sp = GetSyntheticChild(index_const_str);1792if (!synthetic_child_sp) {1793ValueObject *synthetic_child;1794// We haven't made a synthetic array member for INDEX yet, so lets make1795// one and cache it for any future reference.1796synthetic_child = CreateSyntheticArrayMember(index);17971798// Cache the value if we got one back...1799if (synthetic_child) {1800AddSyntheticChild(index_const_str, synthetic_child);1801synthetic_child_sp = synthetic_child->GetSP();1802synthetic_child_sp->SetName(ConstString(index_str));1803synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;1804}1805}1806}1807return synthetic_child_sp;1808}18091810ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,1811bool can_create) {1812ValueObjectSP synthetic_child_sp;1813if (IsScalarType()) {1814std::string index_str = llvm::formatv("[{0}-{1}]", from, to);1815ConstString index_const_str(index_str);1816// Check if we have already created a synthetic array member in this valid1817// object. If we have we will re-use it.1818synthetic_child_sp = GetSyntheticChild(index_const_str);1819if (!synthetic_child_sp) {1820uint32_t bit_field_size = to - from + 1;1821uint32_t bit_field_offset = from;1822if (GetDataExtractor().GetByteOrder() == eByteOrderBig)1823bit_field_offset =1824GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset;1825// We haven't made a synthetic array member for INDEX yet, so lets make1826// one and cache it for any future reference.1827ValueObjectChild *synthetic_child = new ValueObjectChild(1828*this, GetCompilerType(), index_const_str, GetByteSize().value_or(0),18290, bit_field_size, bit_field_offset, false, false,1830eAddressTypeInvalid, 0);18311832// Cache the value if we got one back...1833if (synthetic_child) {1834AddSyntheticChild(index_const_str, synthetic_child);1835synthetic_child_sp = synthetic_child->GetSP();1836synthetic_child_sp->SetName(ConstString(index_str));1837synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;1838}1839}1840}1841return synthetic_child_sp;1842}18431844ValueObjectSP ValueObject::GetSyntheticChildAtOffset(1845uint32_t offset, const CompilerType &type, bool can_create,1846ConstString name_const_str) {18471848ValueObjectSP synthetic_child_sp;18491850if (name_const_str.IsEmpty()) {1851name_const_str.SetString("@" + std::to_string(offset));1852}18531854// Check if we have already created a synthetic array member in this valid1855// object. If we have we will re-use it.1856synthetic_child_sp = GetSyntheticChild(name_const_str);18571858if (synthetic_child_sp.get())1859return synthetic_child_sp;18601861if (!can_create)1862return {};18631864ExecutionContext exe_ctx(GetExecutionContextRef());1865std::optional<uint64_t> size =1866type.GetByteSize(exe_ctx.GetBestExecutionContextScope());1867if (!size)1868return {};1869ValueObjectChild *synthetic_child =1870new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1871false, false, eAddressTypeInvalid, 0);1872if (synthetic_child) {1873AddSyntheticChild(name_const_str, synthetic_child);1874synthetic_child_sp = synthetic_child->GetSP();1875synthetic_child_sp->SetName(name_const_str);1876synthetic_child_sp->m_flags.m_is_child_at_offset = true;1877}1878return synthetic_child_sp;1879}18801881ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,1882const CompilerType &type,1883bool can_create,1884ConstString name_const_str) {1885ValueObjectSP synthetic_child_sp;18861887if (name_const_str.IsEmpty()) {1888char name_str[128];1889snprintf(name_str, sizeof(name_str), "base%s@%i",1890type.GetTypeName().AsCString("<unknown>"), offset);1891name_const_str.SetCString(name_str);1892}18931894// Check if we have already created a synthetic array member in this valid1895// object. If we have we will re-use it.1896synthetic_child_sp = GetSyntheticChild(name_const_str);18971898if (synthetic_child_sp.get())1899return synthetic_child_sp;19001901if (!can_create)1902return {};19031904const bool is_base_class = true;19051906ExecutionContext exe_ctx(GetExecutionContextRef());1907std::optional<uint64_t> size =1908type.GetByteSize(exe_ctx.GetBestExecutionContextScope());1909if (!size)1910return {};1911ValueObjectChild *synthetic_child =1912new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1913is_base_class, false, eAddressTypeInvalid, 0);1914if (synthetic_child) {1915AddSyntheticChild(name_const_str, synthetic_child);1916synthetic_child_sp = synthetic_child->GetSP();1917synthetic_child_sp->SetName(name_const_str);1918}1919return synthetic_child_sp;1920}19211922// your expression path needs to have a leading . or -> (unless it somehow1923// "looks like" an array, in which case it has a leading [ symbol). while the [1924// is meaningful and should be shown to the user, . and -> are just parser1925// design, but by no means added information for the user.. strip them off1926static const char *SkipLeadingExpressionPathSeparators(const char *expression) {1927if (!expression || !expression[0])1928return expression;1929if (expression[0] == '.')1930return expression + 1;1931if (expression[0] == '-' && expression[1] == '>')1932return expression + 2;1933return expression;1934}19351936ValueObjectSP1937ValueObject::GetSyntheticExpressionPathChild(const char *expression,1938bool can_create) {1939ValueObjectSP synthetic_child_sp;1940ConstString name_const_string(expression);1941// Check if we have already created a synthetic array member in this valid1942// object. If we have we will re-use it.1943synthetic_child_sp = GetSyntheticChild(name_const_string);1944if (!synthetic_child_sp) {1945// We haven't made a synthetic array member for expression yet, so lets1946// make one and cache it for any future reference.1947synthetic_child_sp = GetValueForExpressionPath(1948expression, nullptr, nullptr,1949GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(1950GetValueForExpressionPathOptions::SyntheticChildrenTraversal::1951None));19521953// Cache the value if we got one back...1954if (synthetic_child_sp.get()) {1955// FIXME: this causes a "real" child to end up with its name changed to1956// the contents of expression1957AddSyntheticChild(name_const_string, synthetic_child_sp.get());1958synthetic_child_sp->SetName(1959ConstString(SkipLeadingExpressionPathSeparators(expression)));1960}1961}1962return synthetic_child_sp;1963}19641965void ValueObject::CalculateSyntheticValue() {1966TargetSP target_sp(GetTargetSP());1967if (target_sp && !target_sp->GetEnableSyntheticValue()) {1968m_synthetic_value = nullptr;1969return;1970}19711972lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);19731974if (!UpdateFormatsIfNeeded() && m_synthetic_value)1975return;19761977if (m_synthetic_children_sp.get() == nullptr)1978return;19791980if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)1981return;19821983m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);1984}19851986void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {1987if (use_dynamic == eNoDynamicValues)1988return;19891990if (!m_dynamic_value && !IsDynamic()) {1991ExecutionContext exe_ctx(GetExecutionContextRef());1992Process *process = exe_ctx.GetProcessPtr();1993if (process && process->IsPossibleDynamicValue(*this)) {1994ClearDynamicTypeInformation();1995m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);1996}1997}1998}19992000ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {2001if (use_dynamic == eNoDynamicValues)2002return ValueObjectSP();20032004if (!IsDynamic() && m_dynamic_value == nullptr) {2005CalculateDynamicValue(use_dynamic);2006}2007if (m_dynamic_value && m_dynamic_value->GetError().Success())2008return m_dynamic_value->GetSP();2009else2010return ValueObjectSP();2011}20122013ValueObjectSP ValueObject::GetSyntheticValue() {2014CalculateSyntheticValue();20152016if (m_synthetic_value)2017return m_synthetic_value->GetSP();2018else2019return ValueObjectSP();2020}20212022bool ValueObject::HasSyntheticValue() {2023UpdateFormatsIfNeeded();20242025if (m_synthetic_children_sp.get() == nullptr)2026return false;20272028CalculateSyntheticValue();20292030return m_synthetic_value != nullptr;2031}20322033ValueObject *ValueObject::GetNonBaseClassParent() {2034if (GetParent()) {2035if (GetParent()->IsBaseClass())2036return GetParent()->GetNonBaseClassParent();2037else2038return GetParent();2039}2040return nullptr;2041}20422043bool ValueObject::IsBaseClass(uint32_t &depth) {2044if (!IsBaseClass()) {2045depth = 0;2046return false;2047}2048if (GetParent()) {2049GetParent()->IsBaseClass(depth);2050depth = depth + 1;2051return true;2052}2053// TODO: a base of no parent? weird..2054depth = 1;2055return true;2056}20572058void ValueObject::GetExpressionPath(Stream &s,2059GetExpressionPathFormat epformat) {2060// synthetic children do not actually "exist" as part of the hierarchy, and2061// sometimes they are consed up in ways that don't make sense from an2062// underlying language/API standpoint. So, use a special code path here to2063// return something that can hopefully be used in expression2064if (m_flags.m_is_synthetic_children_generated) {2065UpdateValueIfNeeded();20662067if (m_value.GetValueType() == Value::ValueType::LoadAddress) {2068if (IsPointerOrReferenceType()) {2069s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),2070GetValueAsUnsigned(0));2071return;2072} else {2073uint64_t load_addr =2074m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);2075if (load_addr != LLDB_INVALID_ADDRESS) {2076s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),2077load_addr);2078return;2079}2080}2081}20822083if (CanProvideValue()) {2084s.Printf("((%s)%s)", GetTypeName().AsCString("void"),2085GetValueAsCString());2086return;2087}20882089return;2090}20912092const bool is_deref_of_parent = IsDereferenceOfParent();20932094if (is_deref_of_parent &&2095epformat == eGetExpressionPathFormatDereferencePointers) {2096// this is the original format of GetExpressionPath() producing code like2097// *(a_ptr).memberName, which is entirely fine, until you put this into2098// StackFrame::GetValueForVariableExpressionPath() which prefers to see2099// a_ptr->memberName. the eHonorPointers mode is meant to produce strings2100// in this latter format2101s.PutCString("*(");2102}21032104ValueObject *parent = GetParent();21052106if (parent)2107parent->GetExpressionPath(s, epformat);21082109// if we are a deref_of_parent just because we are synthetic array members2110// made up to allow ptr[%d] syntax to work in variable printing, then add our2111// name ([%d]) to the expression path2112if (m_flags.m_is_array_item_for_pointer &&2113epformat == eGetExpressionPathFormatHonorPointers)2114s.PutCString(m_name.GetStringRef());21152116if (!IsBaseClass()) {2117if (!is_deref_of_parent) {2118ValueObject *non_base_class_parent = GetNonBaseClassParent();2119if (non_base_class_parent &&2120!non_base_class_parent->GetName().IsEmpty()) {2121CompilerType non_base_class_parent_compiler_type =2122non_base_class_parent->GetCompilerType();2123if (non_base_class_parent_compiler_type) {2124if (parent && parent->IsDereferenceOfParent() &&2125epformat == eGetExpressionPathFormatHonorPointers) {2126s.PutCString("->");2127} else {2128const uint32_t non_base_class_parent_type_info =2129non_base_class_parent_compiler_type.GetTypeInfo();21302131if (non_base_class_parent_type_info & eTypeIsPointer) {2132s.PutCString("->");2133} else if ((non_base_class_parent_type_info & eTypeHasChildren) &&2134!(non_base_class_parent_type_info & eTypeIsArray)) {2135s.PutChar('.');2136}2137}2138}2139}21402141const char *name = GetName().GetCString();2142if (name)2143s.PutCString(name);2144}2145}21462147if (is_deref_of_parent &&2148epformat == eGetExpressionPathFormatDereferencePointers) {2149s.PutChar(')');2150}2151}21522153ValueObjectSP ValueObject::GetValueForExpressionPath(2154llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2155ExpressionPathEndResultType *final_value_type,2156const GetValueForExpressionPathOptions &options,2157ExpressionPathAftermath *final_task_on_target) {21582159ExpressionPathScanEndReason dummy_reason_to_stop =2160ValueObject::eExpressionPathScanEndReasonUnknown;2161ExpressionPathEndResultType dummy_final_value_type =2162ValueObject::eExpressionPathEndResultTypeInvalid;2163ExpressionPathAftermath dummy_final_task_on_target =2164ValueObject::eExpressionPathAftermathNothing;21652166ValueObjectSP ret_val = GetValueForExpressionPath_Impl(2167expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,2168final_value_type ? final_value_type : &dummy_final_value_type, options,2169final_task_on_target ? final_task_on_target2170: &dummy_final_task_on_target);21712172if (!final_task_on_target ||2173*final_task_on_target == ValueObject::eExpressionPathAftermathNothing)2174return ret_val;21752176if (ret_val.get() &&2177((final_value_type ? *final_value_type : dummy_final_value_type) ==2178eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress2179// of plain objects2180{2181if ((final_task_on_target ? *final_task_on_target2182: dummy_final_task_on_target) ==2183ValueObject::eExpressionPathAftermathDereference) {2184Status error;2185ValueObjectSP final_value = ret_val->Dereference(error);2186if (error.Fail() || !final_value.get()) {2187if (reason_to_stop)2188*reason_to_stop =2189ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2190if (final_value_type)2191*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2192return ValueObjectSP();2193} else {2194if (final_task_on_target)2195*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2196return final_value;2197}2198}2199if (*final_task_on_target ==2200ValueObject::eExpressionPathAftermathTakeAddress) {2201Status error;2202ValueObjectSP final_value = ret_val->AddressOf(error);2203if (error.Fail() || !final_value.get()) {2204if (reason_to_stop)2205*reason_to_stop =2206ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;2207if (final_value_type)2208*final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2209return ValueObjectSP();2210} else {2211if (final_task_on_target)2212*final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2213return final_value;2214}2215}2216}2217return ret_val; // final_task_on_target will still have its original value, so2218// you know I did not do it2219}22202221ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(2222llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2223ExpressionPathEndResultType *final_result,2224const GetValueForExpressionPathOptions &options,2225ExpressionPathAftermath *what_next) {2226ValueObjectSP root = GetSP();22272228if (!root)2229return nullptr;22302231llvm::StringRef remainder = expression;22322233while (true) {2234llvm::StringRef temp_expression = remainder;22352236CompilerType root_compiler_type = root->GetCompilerType();2237CompilerType pointee_compiler_type;2238Flags pointee_compiler_type_info;22392240Flags root_compiler_type_info(2241root_compiler_type.GetTypeInfo(&pointee_compiler_type));2242if (pointee_compiler_type)2243pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());22442245if (temp_expression.empty()) {2246*reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;2247return root;2248}22492250switch (temp_expression.front()) {2251case '-': {2252temp_expression = temp_expression.drop_front();2253if (options.m_check_dot_vs_arrow_syntax &&2254root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2255// use -> on a2256// non-pointer and I2257// must catch the error2258{2259*reason_to_stop =2260ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;2261*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2262return ValueObjectSP();2263}2264if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to2265// extract an ObjC IVar2266// when this is forbidden2267root_compiler_type_info.Test(eTypeIsPointer) &&2268options.m_no_fragile_ivar) {2269*reason_to_stop =2270ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;2271*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2272return ValueObjectSP();2273}2274if (!temp_expression.starts_with(">")) {2275*reason_to_stop =2276ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2277*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2278return ValueObjectSP();2279}2280}2281[[fallthrough]];2282case '.': // or fallthrough from ->2283{2284if (options.m_check_dot_vs_arrow_syntax &&2285temp_expression.front() == '.' &&2286root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2287// use . on a pointer2288// and I must catch the2289// error2290{2291*reason_to_stop =2292ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;2293*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2294return nullptr;2295}2296temp_expression = temp_expression.drop_front(); // skip . or >22972298size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);2299if (next_sep_pos == llvm::StringRef::npos) // if no other separator just2300// expand this last layer2301{2302llvm::StringRef child_name = temp_expression;2303ValueObjectSP child_valobj_sp =2304root->GetChildMemberWithName(child_name);23052306if (child_valobj_sp.get()) // we know we are done, so just return2307{2308*reason_to_stop =2309ValueObject::eExpressionPathScanEndReasonEndOfString;2310*final_result = ValueObject::eExpressionPathEndResultTypePlain;2311return child_valobj_sp;2312} else {2313switch (options.m_synthetic_children_traversal) {2314case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2315None:2316break;2317case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2318FromSynthetic:2319if (root->IsSynthetic()) {2320child_valobj_sp = root->GetNonSyntheticValue();2321if (child_valobj_sp.get())2322child_valobj_sp =2323child_valobj_sp->GetChildMemberWithName(child_name);2324}2325break;2326case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2327ToSynthetic:2328if (!root->IsSynthetic()) {2329child_valobj_sp = root->GetSyntheticValue();2330if (child_valobj_sp.get())2331child_valobj_sp =2332child_valobj_sp->GetChildMemberWithName(child_name);2333}2334break;2335case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2336Both:2337if (root->IsSynthetic()) {2338child_valobj_sp = root->GetNonSyntheticValue();2339if (child_valobj_sp.get())2340child_valobj_sp =2341child_valobj_sp->GetChildMemberWithName(child_name);2342} else {2343child_valobj_sp = root->GetSyntheticValue();2344if (child_valobj_sp.get())2345child_valobj_sp =2346child_valobj_sp->GetChildMemberWithName(child_name);2347}2348break;2349}2350}23512352// if we are here and options.m_no_synthetic_children is true,2353// child_valobj_sp is going to be a NULL SP, so we hit the "else"2354// branch, and return an error2355if (child_valobj_sp.get()) // if it worked, just return2356{2357*reason_to_stop =2358ValueObject::eExpressionPathScanEndReasonEndOfString;2359*final_result = ValueObject::eExpressionPathEndResultTypePlain;2360return child_valobj_sp;2361} else {2362*reason_to_stop =2363ValueObject::eExpressionPathScanEndReasonNoSuchChild;2364*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2365return nullptr;2366}2367} else // other layers do expand2368{2369llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);2370llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);23712372ValueObjectSP child_valobj_sp =2373root->GetChildMemberWithName(child_name);2374if (child_valobj_sp.get()) // store the new root and move on2375{2376root = child_valobj_sp;2377remainder = next_separator;2378*final_result = ValueObject::eExpressionPathEndResultTypePlain;2379continue;2380} else {2381switch (options.m_synthetic_children_traversal) {2382case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2383None:2384break;2385case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2386FromSynthetic:2387if (root->IsSynthetic()) {2388child_valobj_sp = root->GetNonSyntheticValue();2389if (child_valobj_sp.get())2390child_valobj_sp =2391child_valobj_sp->GetChildMemberWithName(child_name);2392}2393break;2394case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2395ToSynthetic:2396if (!root->IsSynthetic()) {2397child_valobj_sp = root->GetSyntheticValue();2398if (child_valobj_sp.get())2399child_valobj_sp =2400child_valobj_sp->GetChildMemberWithName(child_name);2401}2402break;2403case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2404Both:2405if (root->IsSynthetic()) {2406child_valobj_sp = root->GetNonSyntheticValue();2407if (child_valobj_sp.get())2408child_valobj_sp =2409child_valobj_sp->GetChildMemberWithName(child_name);2410} else {2411child_valobj_sp = root->GetSyntheticValue();2412if (child_valobj_sp.get())2413child_valobj_sp =2414child_valobj_sp->GetChildMemberWithName(child_name);2415}2416break;2417}2418}24192420// if we are here and options.m_no_synthetic_children is true,2421// child_valobj_sp is going to be a NULL SP, so we hit the "else"2422// branch, and return an error2423if (child_valobj_sp.get()) // if it worked, move on2424{2425root = child_valobj_sp;2426remainder = next_separator;2427*final_result = ValueObject::eExpressionPathEndResultTypePlain;2428continue;2429} else {2430*reason_to_stop =2431ValueObject::eExpressionPathScanEndReasonNoSuchChild;2432*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2433return nullptr;2434}2435}2436break;2437}2438case '[': {2439if (!root_compiler_type_info.Test(eTypeIsArray) &&2440!root_compiler_type_info.Test(eTypeIsPointer) &&2441!root_compiler_type_info.Test(2442eTypeIsVector)) // if this is not a T[] nor a T*2443{2444if (!root_compiler_type_info.Test(2445eTypeIsScalar)) // if this is not even a scalar...2446{2447if (options.m_synthetic_children_traversal ==2448GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2449None) // ...only chance left is synthetic2450{2451*reason_to_stop =2452ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;2453*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2454return ValueObjectSP();2455}2456} else if (!options.m_allow_bitfields_syntax) // if this is a scalar,2457// check that we can2458// expand bitfields2459{2460*reason_to_stop =2461ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;2462*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2463return ValueObjectSP();2464}2465}2466if (temp_expression[1] ==2467']') // if this is an unbounded range it only works for arrays2468{2469if (!root_compiler_type_info.Test(eTypeIsArray)) {2470*reason_to_stop =2471ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;2472*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2473return nullptr;2474} else // even if something follows, we cannot expand unbounded ranges,2475// just let the caller do it2476{2477*reason_to_stop =2478ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2479*final_result =2480ValueObject::eExpressionPathEndResultTypeUnboundedRange;2481return root;2482}2483}24842485size_t close_bracket_position = temp_expression.find(']', 1);2486if (close_bracket_position ==2487llvm::StringRef::npos) // if there is no ], this is a syntax error2488{2489*reason_to_stop =2490ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2491*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2492return nullptr;2493}24942495llvm::StringRef bracket_expr =2496temp_expression.slice(1, close_bracket_position);24972498// If this was an empty expression it would have been caught by the if2499// above.2500assert(!bracket_expr.empty());25012502if (!bracket_expr.contains('-')) {2503// if no separator, this is of the form [N]. Note that this cannot be2504// an unbounded range of the form [], because that case was handled2505// above with an unconditional return.2506unsigned long index = 0;2507if (bracket_expr.getAsInteger(0, index)) {2508*reason_to_stop =2509ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2510*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2511return nullptr;2512}25132514// from here on we do have a valid index2515if (root_compiler_type_info.Test(eTypeIsArray)) {2516ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);2517if (!child_valobj_sp)2518child_valobj_sp = root->GetSyntheticArrayMember(index, true);2519if (!child_valobj_sp)2520if (root->HasSyntheticValue() &&2521llvm::expectedToStdOptional(2522root->GetSyntheticValue()->GetNumChildren())2523.value_or(0) > index)2524child_valobj_sp =2525root->GetSyntheticValue()->GetChildAtIndex(index);2526if (child_valobj_sp) {2527root = child_valobj_sp;2528remainder =2529temp_expression.substr(close_bracket_position + 1); // skip ]2530*final_result = ValueObject::eExpressionPathEndResultTypePlain;2531continue;2532} else {2533*reason_to_stop =2534ValueObject::eExpressionPathScanEndReasonNoSuchChild;2535*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2536return nullptr;2537}2538} else if (root_compiler_type_info.Test(eTypeIsPointer)) {2539if (*what_next ==2540ValueObject::2541eExpressionPathAftermathDereference && // if this is a2542// ptr-to-scalar, I2543// am accessing it2544// by index and I2545// would have2546// deref'ed anyway,2547// then do it now2548// and use this as2549// a bitfield2550pointee_compiler_type_info.Test(eTypeIsScalar)) {2551Status error;2552root = root->Dereference(error);2553if (error.Fail() || !root) {2554*reason_to_stop =2555ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2556*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2557return nullptr;2558} else {2559*what_next = eExpressionPathAftermathNothing;2560continue;2561}2562} else {2563if (root->GetCompilerType().GetMinimumLanguage() ==2564eLanguageTypeObjC &&2565pointee_compiler_type_info.AllClear(eTypeIsPointer) &&2566root->HasSyntheticValue() &&2567(options.m_synthetic_children_traversal ==2568GetValueForExpressionPathOptions::2569SyntheticChildrenTraversal::ToSynthetic ||2570options.m_synthetic_children_traversal ==2571GetValueForExpressionPathOptions::2572SyntheticChildrenTraversal::Both)) {2573root = root->GetSyntheticValue()->GetChildAtIndex(index);2574} else2575root = root->GetSyntheticArrayMember(index, true);2576if (!root) {2577*reason_to_stop =2578ValueObject::eExpressionPathScanEndReasonNoSuchChild;2579*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2580return nullptr;2581} else {2582remainder =2583temp_expression.substr(close_bracket_position + 1); // skip ]2584*final_result = ValueObject::eExpressionPathEndResultTypePlain;2585continue;2586}2587}2588} else if (root_compiler_type_info.Test(eTypeIsScalar)) {2589root = root->GetSyntheticBitFieldChild(index, index, true);2590if (!root) {2591*reason_to_stop =2592ValueObject::eExpressionPathScanEndReasonNoSuchChild;2593*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2594return nullptr;2595} else // we do not know how to expand members of bitfields, so we2596// just return and let the caller do any further processing2597{2598*reason_to_stop = ValueObject::2599eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2600*final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2601return root;2602}2603} else if (root_compiler_type_info.Test(eTypeIsVector)) {2604root = root->GetChildAtIndex(index);2605if (!root) {2606*reason_to_stop =2607ValueObject::eExpressionPathScanEndReasonNoSuchChild;2608*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2609return ValueObjectSP();2610} else {2611remainder =2612temp_expression.substr(close_bracket_position + 1); // skip ]2613*final_result = ValueObject::eExpressionPathEndResultTypePlain;2614continue;2615}2616} else if (options.m_synthetic_children_traversal ==2617GetValueForExpressionPathOptions::2618SyntheticChildrenTraversal::ToSynthetic ||2619options.m_synthetic_children_traversal ==2620GetValueForExpressionPathOptions::2621SyntheticChildrenTraversal::Both) {2622if (root->HasSyntheticValue())2623root = root->GetSyntheticValue();2624else if (!root->IsSynthetic()) {2625*reason_to_stop =2626ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2627*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2628return nullptr;2629}2630// if we are here, then root itself is a synthetic VO.. should be2631// good to go26322633if (!root) {2634*reason_to_stop =2635ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2636*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2637return nullptr;2638}2639root = root->GetChildAtIndex(index);2640if (!root) {2641*reason_to_stop =2642ValueObject::eExpressionPathScanEndReasonNoSuchChild;2643*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2644return nullptr;2645} else {2646remainder =2647temp_expression.substr(close_bracket_position + 1); // skip ]2648*final_result = ValueObject::eExpressionPathEndResultTypePlain;2649continue;2650}2651} else {2652*reason_to_stop =2653ValueObject::eExpressionPathScanEndReasonNoSuchChild;2654*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2655return nullptr;2656}2657} else {2658// we have a low and a high index2659llvm::StringRef sleft, sright;2660unsigned long low_index, high_index;2661std::tie(sleft, sright) = bracket_expr.split('-');2662if (sleft.getAsInteger(0, low_index) ||2663sright.getAsInteger(0, high_index)) {2664*reason_to_stop =2665ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2666*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2667return nullptr;2668}26692670if (low_index > high_index) // swap indices if required2671std::swap(low_index, high_index);26722673if (root_compiler_type_info.Test(2674eTypeIsScalar)) // expansion only works for scalars2675{2676root = root->GetSyntheticBitFieldChild(low_index, high_index, true);2677if (!root) {2678*reason_to_stop =2679ValueObject::eExpressionPathScanEndReasonNoSuchChild;2680*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2681return nullptr;2682} else {2683*reason_to_stop = ValueObject::2684eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2685*final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2686return root;2687}2688} else if (root_compiler_type_info.Test(2689eTypeIsPointer) && // if this is a ptr-to-scalar, I am2690// accessing it by index and I would2691// have deref'ed anyway, then do it2692// now and use this as a bitfield2693*what_next ==2694ValueObject::eExpressionPathAftermathDereference &&2695pointee_compiler_type_info.Test(eTypeIsScalar)) {2696Status error;2697root = root->Dereference(error);2698if (error.Fail() || !root) {2699*reason_to_stop =2700ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2701*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2702return nullptr;2703} else {2704*what_next = ValueObject::eExpressionPathAftermathNothing;2705continue;2706}2707} else {2708*reason_to_stop =2709ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2710*final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;2711return root;2712}2713}2714break;2715}2716default: // some non-separator is in the way2717{2718*reason_to_stop =2719ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2720*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2721return nullptr;2722}2723}2724}2725}27262727llvm::Error ValueObject::Dump(Stream &s) {2728return Dump(s, DumpValueObjectOptions(*this));2729}27302731llvm::Error ValueObject::Dump(Stream &s,2732const DumpValueObjectOptions &options) {2733ValueObjectPrinter printer(*this, &s, options);2734return printer.PrintValueObject();2735}27362737ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {2738ValueObjectSP valobj_sp;27392740if (UpdateValueIfNeeded(false) && m_error.Success()) {2741ExecutionContext exe_ctx(GetExecutionContextRef());27422743DataExtractor data;2744data.SetByteOrder(m_data.GetByteOrder());2745data.SetAddressByteSize(m_data.GetAddressByteSize());27462747if (IsBitfield()) {2748Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));2749m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());2750} else2751m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());27522753valobj_sp = ValueObjectConstResult::Create(2754exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,2755GetAddressOf());2756}27572758if (!valobj_sp) {2759ExecutionContext exe_ctx(GetExecutionContextRef());2760valobj_sp = ValueObjectConstResult::Create(2761exe_ctx.GetBestExecutionContextScope(), m_error);2762}2763return valobj_sp;2764}27652766ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(2767lldb::DynamicValueType dynValue, bool synthValue) {2768ValueObjectSP result_sp;2769switch (dynValue) {2770case lldb::eDynamicCanRunTarget:2771case lldb::eDynamicDontRunTarget: {2772if (!IsDynamic())2773result_sp = GetDynamicValue(dynValue);2774} break;2775case lldb::eNoDynamicValues: {2776if (IsDynamic())2777result_sp = GetStaticValue();2778} break;2779}2780if (!result_sp)2781result_sp = GetSP();2782assert(result_sp);27832784bool is_synthetic = result_sp->IsSynthetic();2785if (synthValue && !is_synthetic) {2786if (auto synth_sp = result_sp->GetSyntheticValue())2787return synth_sp;2788}2789if (!synthValue && is_synthetic) {2790if (auto non_synth_sp = result_sp->GetNonSyntheticValue())2791return non_synth_sp;2792}27932794return result_sp;2795}27962797ValueObjectSP ValueObject::Dereference(Status &error) {2798if (m_deref_valobj)2799return m_deref_valobj->GetSP();28002801const bool is_pointer_or_reference_type = IsPointerOrReferenceType();2802if (is_pointer_or_reference_type) {2803bool omit_empty_base_classes = true;2804bool ignore_array_bounds = false;28052806std::string child_name_str;2807uint32_t child_byte_size = 0;2808int32_t child_byte_offset = 0;2809uint32_t child_bitfield_bit_size = 0;2810uint32_t child_bitfield_bit_offset = 0;2811bool child_is_base_class = false;2812bool child_is_deref_of_parent = false;2813const bool transparent_pointers = false;2814CompilerType compiler_type = GetCompilerType();2815uint64_t language_flags = 0;28162817ExecutionContext exe_ctx(GetExecutionContextRef());28182819CompilerType child_compiler_type;2820auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex(2821&exe_ctx, 0, transparent_pointers, omit_empty_base_classes,2822ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,2823child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,2824child_is_deref_of_parent, this, language_flags);2825if (!child_compiler_type_or_err)2826LLDB_LOG_ERROR(GetLog(LLDBLog::Types),2827child_compiler_type_or_err.takeError(),2828"could not find child: {0}");2829else2830child_compiler_type = *child_compiler_type_or_err;28312832if (child_compiler_type && child_byte_size) {2833ConstString child_name;2834if (!child_name_str.empty())2835child_name.SetCString(child_name_str.c_str());28362837m_deref_valobj = new ValueObjectChild(2838*this, child_compiler_type, child_name, child_byte_size,2839child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,2840child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,2841language_flags);2842}28432844// In case of incomplete child compiler type, use the pointee type and try2845// to recreate a new ValueObjectChild using it.2846if (!m_deref_valobj) {2847// FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.2848// `std::vector<int> &`). Remove ObjC restriction once that's resolved.2849if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&2850HasSyntheticValue()) {2851child_compiler_type = compiler_type.GetPointeeType();28522853if (child_compiler_type) {2854ConstString child_name;2855if (!child_name_str.empty())2856child_name.SetCString(child_name_str.c_str());28572858m_deref_valobj = new ValueObjectChild(2859*this, child_compiler_type, child_name, child_byte_size,2860child_byte_offset, child_bitfield_bit_size,2861child_bitfield_bit_offset, child_is_base_class,2862child_is_deref_of_parent, eAddressTypeInvalid, language_flags);2863}2864}2865}28662867} else if (HasSyntheticValue()) {2868m_deref_valobj =2869GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get();2870} else if (IsSynthetic()) {2871m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();2872}28732874if (m_deref_valobj) {2875error.Clear();2876return m_deref_valobj->GetSP();2877} else {2878StreamString strm;2879GetExpressionPath(strm);28802881if (is_pointer_or_reference_type)2882error.SetErrorStringWithFormat("dereference failed: (%s) %s",2883GetTypeName().AsCString("<invalid type>"),2884strm.GetData());2885else2886error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s",2887GetTypeName().AsCString("<invalid type>"),2888strm.GetData());2889return ValueObjectSP();2890}2891}28922893ValueObjectSP ValueObject::AddressOf(Status &error) {2894if (m_addr_of_valobj_sp)2895return m_addr_of_valobj_sp;28962897AddressType address_type = eAddressTypeInvalid;2898const bool scalar_is_load_address = false;2899addr_t addr = GetAddressOf(scalar_is_load_address, &address_type);2900error.Clear();2901if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {2902switch (address_type) {2903case eAddressTypeInvalid: {2904StreamString expr_path_strm;2905GetExpressionPath(expr_path_strm);2906error.SetErrorStringWithFormat("'%s' is not in memory",2907expr_path_strm.GetData());2908} break;29092910case eAddressTypeFile:2911case eAddressTypeLoad: {2912CompilerType compiler_type = GetCompilerType();2913if (compiler_type) {2914std::string name(1, '&');2915name.append(m_name.AsCString(""));2916ExecutionContext exe_ctx(GetExecutionContextRef());2917m_addr_of_valobj_sp = ValueObjectConstResult::Create(2918exe_ctx.GetBestExecutionContextScope(),2919compiler_type.GetPointerType(), ConstString(name.c_str()), addr,2920eAddressTypeInvalid, m_data.GetAddressByteSize());2921}2922} break;2923default:2924break;2925}2926} else {2927StreamString expr_path_strm;2928GetExpressionPath(expr_path_strm);2929error.SetErrorStringWithFormat("'%s' doesn't have a valid address",2930expr_path_strm.GetData());2931}29322933return m_addr_of_valobj_sp;2934}29352936ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {2937return ValueObjectCast::Create(*this, GetName(), compiler_type);2938}29392940ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {2941// Only allow casts if the original type is equal or larger than the cast2942// type, unless we know this is a load address. Getting the size wrong for2943// a host side storage could leak lldb memory, so we absolutely want to2944// prevent that. We may not always get the right value, for instance if we2945// have an expression result value that's copied into a storage location in2946// the target may not have copied enough memory. I'm not trying to fix that2947// here, I'm just making Cast from a smaller to a larger possible in all the2948// cases where that doesn't risk making a Value out of random lldb memory.2949// You have to check the ValueObject's Value for the address types, since2950// ValueObjects that use live addresses will tell you they fetch data from the2951// live address, but once they are made, they actually don't.2952// FIXME: Can we make ValueObject's with a live address fetch "more data" from2953// the live address if it is still valid?29542955Status error;2956CompilerType my_type = GetCompilerType();29572958ExecutionContextScope *exe_scope2959= ExecutionContext(GetExecutionContextRef())2960.GetBestExecutionContextScope();2961if (compiler_type.GetByteSize(exe_scope)2962<= GetCompilerType().GetByteSize(exe_scope)2963|| m_value.GetValueType() == Value::ValueType::LoadAddress)2964return DoCast(compiler_type);29652966error.SetErrorString("Can only cast to a type that is equal to or smaller "2967"than the orignal type.");29682969return ValueObjectConstResult::Create(2970ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),2971error);2972}29732974lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {2975return ValueObjectCast::Create(*this, new_name, GetCompilerType());2976}29772978ValueObjectSP ValueObject::CastPointerType(const char *name,2979CompilerType &compiler_type) {2980ValueObjectSP valobj_sp;2981AddressType address_type;2982addr_t ptr_value = GetPointerValue(&address_type);29832984if (ptr_value != LLDB_INVALID_ADDRESS) {2985Address ptr_addr(ptr_value);2986ExecutionContext exe_ctx(GetExecutionContextRef());2987valobj_sp = ValueObjectMemory::Create(2988exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);2989}2990return valobj_sp;2991}29922993ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {2994ValueObjectSP valobj_sp;2995AddressType address_type;2996addr_t ptr_value = GetPointerValue(&address_type);29972998if (ptr_value != LLDB_INVALID_ADDRESS) {2999Address ptr_addr(ptr_value);3000ExecutionContext exe_ctx(GetExecutionContextRef());3001valobj_sp = ValueObjectMemory::Create(3002exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);3003}3004return valobj_sp;3005}30063007lldb::addr_t ValueObject::GetLoadAddress() {3008lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;3009if (auto target_sp = GetTargetSP()) {3010const bool scalar_is_load_address = true;3011AddressType addr_type;3012addr_value = GetAddressOf(scalar_is_load_address, &addr_type);3013if (addr_type == eAddressTypeFile) {3014lldb::ModuleSP module_sp(GetModule());3015if (!module_sp)3016addr_value = LLDB_INVALID_ADDRESS;3017else {3018Address tmp_addr;3019module_sp->ResolveFileAddress(addr_value, tmp_addr);3020addr_value = tmp_addr.GetLoadAddress(target_sp.get());3021}3022} else if (addr_type == eAddressTypeHost ||3023addr_type == eAddressTypeInvalid)3024addr_value = LLDB_INVALID_ADDRESS;3025}3026return addr_value;3027}30283029llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(3030CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {3031// Make sure the starting type and the target type are both valid for this3032// type of cast; otherwise return the shared pointer to the original3033// (unchanged) ValueObject.3034if (!type.IsPointerType() && !type.IsReferenceType())3035return llvm::make_error<llvm::StringError>(3036"Invalid target type: should be a pointer or a reference",3037llvm::inconvertibleErrorCode());30383039CompilerType start_type = GetCompilerType();3040if (start_type.IsReferenceType())3041start_type = start_type.GetNonReferenceType();30423043auto target_record_type =3044type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3045auto start_record_type =3046start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;30473048if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3049return llvm::make_error<llvm::StringError>(3050"Underlying start & target types should be record types",3051llvm::inconvertibleErrorCode());30523053if (target_record_type.CompareTypes(start_record_type))3054return llvm::make_error<llvm::StringError>(3055"Underlying start & target types should be different",3056llvm::inconvertibleErrorCode());30573058if (base_type_indices.empty())3059return llvm::make_error<llvm::StringError>(3060"Children sequence must be non-empty", llvm::inconvertibleErrorCode());30613062// Both the starting & target types are valid for the cast, and the list of3063// base class indices is non-empty, so we can proceed with the cast.30643065lldb::TargetSP target = GetTargetSP();3066// The `value` can be a pointer, but GetChildAtIndex works for pointers too.3067lldb::ValueObjectSP inner_value = GetSP();30683069for (const uint32_t i : base_type_indices)3070// Create synthetic value if needed.3071inner_value =3072inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);30733074// At this point type of `inner_value` should be the dereferenced target3075// type.3076CompilerType inner_value_type = inner_value->GetCompilerType();3077if (type.IsPointerType()) {3078if (!inner_value_type.CompareTypes(type.GetPointeeType()))3079return llvm::make_error<llvm::StringError>(3080"casted value doesn't match the desired type",3081llvm::inconvertibleErrorCode());30823083uintptr_t addr = inner_value->GetLoadAddress();3084llvm::StringRef name = "";3085ExecutionContext exe_ctx(target.get(), false);3086return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,3087/* do deref */ false);3088}30893090// At this point the target type should be a reference.3091if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))3092return llvm::make_error<llvm::StringError>(3093"casted value doesn't match the desired type",3094llvm::inconvertibleErrorCode());30953096return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));3097}30983099llvm::Expected<lldb::ValueObjectSP>3100ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {3101// Make sure the starting type and the target type are both valid for this3102// type of cast; otherwise return the shared pointer to the original3103// (unchanged) ValueObject.3104if (!type.IsPointerType() && !type.IsReferenceType())3105return llvm::make_error<llvm::StringError>(3106"Invalid target type: should be a pointer or a reference",3107llvm::inconvertibleErrorCode());31083109CompilerType start_type = GetCompilerType();3110if (start_type.IsReferenceType())3111start_type = start_type.GetNonReferenceType();31123113auto target_record_type =3114type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3115auto start_record_type =3116start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;31173118if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3119return llvm::make_error<llvm::StringError>(3120"Underlying start & target types should be record types",3121llvm::inconvertibleErrorCode());31223123if (target_record_type.CompareTypes(start_record_type))3124return llvm::make_error<llvm::StringError>(3125"Underlying start & target types should be different",3126llvm::inconvertibleErrorCode());31273128CompilerType virtual_base;3129if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {3130if (!virtual_base.IsValid())3131return llvm::make_error<llvm::StringError>(3132"virtual base should be valid", llvm::inconvertibleErrorCode());3133return llvm::make_error<llvm::StringError>(3134llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +3135type.TypeDescription() + " via virtual base " +3136virtual_base.TypeDescription()),3137llvm::inconvertibleErrorCode());3138}31393140// Both the starting & target types are valid for the cast, so we can3141// proceed with the cast.31423143lldb::TargetSP target = GetTargetSP();3144auto pointer_type =3145type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();31463147uintptr_t addr =3148type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();31493150llvm::StringRef name = "";3151ExecutionContext exe_ctx(target.get(), false);3152lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(3153name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);31543155if (type.IsPointerType())3156return value;31573158// At this point the target type is a reference. Since `value` is a pointer,3159// it has to be dereferenced.3160Status error;3161return value->Dereference(error);3162}31633164lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {3165bool is_scalar = GetCompilerType().IsScalarType();3166bool is_enum = GetCompilerType().IsEnumerationType();3167bool is_pointer =3168GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();3169bool is_float = GetCompilerType().IsFloat();3170bool is_integer = GetCompilerType().IsInteger();31713172if (!type.IsScalarType()) {3173m_error.SetErrorString("target type must be a scalar");3174return GetSP();3175}31763177if (!is_scalar && !is_enum && !is_pointer) {3178m_error.SetErrorString("argument must be a scalar, enum, or pointer");3179return GetSP();3180}31813182lldb::TargetSP target = GetTargetSP();3183uint64_t type_byte_size = 0;3184uint64_t val_byte_size = 0;3185if (auto temp = type.GetByteSize(target.get()))3186type_byte_size = temp.value();3187if (auto temp = GetCompilerType().GetByteSize(target.get()))3188val_byte_size = temp.value();31893190if (is_pointer) {3191if (!type.IsInteger() && !type.IsBoolean()) {3192m_error.SetErrorString("target type must be an integer or boolean");3193return GetSP();3194}3195if (!type.IsBoolean() && type_byte_size < val_byte_size) {3196m_error.SetErrorString(3197"target type cannot be smaller than the pointer type");3198return GetSP();3199}3200}32013202if (type.IsBoolean()) {3203if (!is_scalar || is_integer)3204return ValueObject::CreateValueObjectFromBool(3205target, GetValueAsUnsigned(0) != 0, "result");3206else if (is_scalar && is_float) {3207auto float_value_or_err = GetValueAsAPFloat();3208if (float_value_or_err)3209return ValueObject::CreateValueObjectFromBool(3210target, !float_value_or_err->isZero(), "result");3211else {3212m_error.SetErrorStringWithFormat(3213"cannot get value as APFloat: %s",3214llvm::toString(float_value_or_err.takeError()).c_str());3215return GetSP();3216}3217}3218}32193220if (type.IsInteger()) {3221if (!is_scalar || is_integer) {3222auto int_value_or_err = GetValueAsAPSInt();3223if (int_value_or_err) {3224// Get the value as APSInt and extend or truncate it to the requested3225// size.3226llvm::APSInt ext =3227int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3228return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3229"result");3230} else {3231m_error.SetErrorStringWithFormat(3232"cannot get value as APSInt: %s",3233llvm::toString(int_value_or_err.takeError()).c_str());3234;3235return GetSP();3236}3237} else if (is_scalar && is_float) {3238llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());3239bool is_exact;3240auto float_value_or_err = GetValueAsAPFloat();3241if (float_value_or_err) {3242llvm::APFloatBase::opStatus status =3243float_value_or_err->convertToInteger(3244integer, llvm::APFloat::rmTowardZero, &is_exact);32453246// Casting floating point values that are out of bounds of the target3247// type is undefined behaviour.3248if (status & llvm::APFloatBase::opInvalidOp) {3249m_error.SetErrorStringWithFormat(3250"invalid type cast detected: %s",3251llvm::toString(float_value_or_err.takeError()).c_str());3252return GetSP();3253}3254return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3255"result");3256}3257}3258}32593260if (type.IsFloat()) {3261if (!is_scalar) {3262auto int_value_or_err = GetValueAsAPSInt();3263if (int_value_or_err) {3264llvm::APSInt ext =3265int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3266Scalar scalar_int(ext);3267llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(3268type.GetCanonicalType().GetBasicTypeEnumeration());3269return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3270"result");3271} else {3272m_error.SetErrorStringWithFormat(3273"cannot get value as APSInt: %s",3274llvm::toString(int_value_or_err.takeError()).c_str());3275return GetSP();3276}3277} else {3278if (is_integer) {3279auto int_value_or_err = GetValueAsAPSInt();3280if (int_value_or_err) {3281Scalar scalar_int(*int_value_or_err);3282llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(3283type.GetCanonicalType().GetBasicTypeEnumeration());3284return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3285"result");3286} else {3287m_error.SetErrorStringWithFormat(3288"cannot get value as APSInt: %s",3289llvm::toString(int_value_or_err.takeError()).c_str());3290return GetSP();3291}3292}3293if (is_float) {3294auto float_value_or_err = GetValueAsAPFloat();3295if (float_value_or_err) {3296Scalar scalar_float(*float_value_or_err);3297llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(3298type.GetCanonicalType().GetBasicTypeEnumeration());3299return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3300"result");3301} else {3302m_error.SetErrorStringWithFormat(3303"cannot get value as APFloat: %s",3304llvm::toString(float_value_or_err.takeError()).c_str());3305return GetSP();3306}3307}3308}3309}33103311m_error.SetErrorString("Unable to perform requested cast");3312return GetSP();3313}33143315lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {3316bool is_enum = GetCompilerType().IsEnumerationType();3317bool is_integer = GetCompilerType().IsInteger();3318bool is_float = GetCompilerType().IsFloat();33193320if (!is_enum && !is_integer && !is_float) {3321m_error.SetErrorString("argument must be an integer, a float, or an enum");3322return GetSP();3323}33243325if (!type.IsEnumerationType()) {3326m_error.SetErrorString("target type must be an enum");3327return GetSP();3328}33293330lldb::TargetSP target = GetTargetSP();3331uint64_t byte_size = 0;3332if (auto temp = type.GetByteSize(target.get()))3333byte_size = temp.value();33343335if (is_float) {3336llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());3337bool is_exact;3338auto value_or_err = GetValueAsAPFloat();3339if (value_or_err) {3340llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(3341integer, llvm::APFloat::rmTowardZero, &is_exact);33423343// Casting floating point values that are out of bounds of the target3344// type is undefined behaviour.3345if (status & llvm::APFloatBase::opInvalidOp) {3346m_error.SetErrorStringWithFormat(3347"invalid type cast detected: %s",3348llvm::toString(value_or_err.takeError()).c_str());3349return GetSP();3350}3351return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3352"result");3353} else {3354m_error.SetErrorString("cannot get value as APFloat");3355return GetSP();3356}3357} else {3358// Get the value as APSInt and extend or truncate it to the requested size.3359auto value_or_err = GetValueAsAPSInt();3360if (value_or_err) {3361llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);3362return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3363"result");3364} else {3365m_error.SetErrorStringWithFormat(3366"cannot get value as APSInt: %s",3367llvm::toString(value_or_err.takeError()).c_str());3368return GetSP();3369}3370}3371m_error.SetErrorString("Cannot perform requested cast");3372return GetSP();3373}33743375ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}33763377ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,3378bool use_selected)3379: m_mod_id(), m_exe_ctx_ref() {3380ExecutionContext exe_ctx(exe_scope);3381TargetSP target_sp(exe_ctx.GetTargetSP());3382if (target_sp) {3383m_exe_ctx_ref.SetTargetSP(target_sp);3384ProcessSP process_sp(exe_ctx.GetProcessSP());3385if (!process_sp)3386process_sp = target_sp->GetProcessSP();33873388if (process_sp) {3389m_mod_id = process_sp->GetModID();3390m_exe_ctx_ref.SetProcessSP(process_sp);33913392ThreadSP thread_sp(exe_ctx.GetThreadSP());33933394if (!thread_sp) {3395if (use_selected)3396thread_sp = process_sp->GetThreadList().GetSelectedThread();3397}33983399if (thread_sp) {3400m_exe_ctx_ref.SetThreadSP(thread_sp);34013402StackFrameSP frame_sp(exe_ctx.GetFrameSP());3403if (!frame_sp) {3404if (use_selected)3405frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);3406}3407if (frame_sp)3408m_exe_ctx_ref.SetFrameSP(frame_sp);3409}3410}3411}3412}34133414ValueObject::EvaluationPoint::EvaluationPoint(3415const ValueObject::EvaluationPoint &rhs)3416: m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}34173418ValueObject::EvaluationPoint::~EvaluationPoint() = default;34193420// This function checks the EvaluationPoint against the current process state.3421// If the current state matches the evaluation point, or the evaluation point3422// is already invalid, then we return false, meaning "no change". If the3423// current state is different, we update our state, and return true meaning3424// "yes, change". If we did see a change, we also set m_needs_update to true,3425// so future calls to NeedsUpdate will return true. exe_scope will be set to3426// the current execution context scope.34273428bool ValueObject::EvaluationPoint::SyncWithProcessState(3429bool accept_invalid_exe_ctx) {3430// Start with the target, if it is NULL, then we're obviously not going to3431// get any further:3432const bool thread_and_frame_only_if_stopped = true;3433ExecutionContext exe_ctx(3434m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));34353436if (exe_ctx.GetTargetPtr() == nullptr)3437return false;34383439// If we don't have a process nothing can change.3440Process *process = exe_ctx.GetProcessPtr();3441if (process == nullptr)3442return false;34433444// If our stop id is the current stop ID, nothing has changed:3445ProcessModID current_mod_id = process->GetModID();34463447// If the current stop id is 0, either we haven't run yet, or the process3448// state has been cleared. In either case, we aren't going to be able to sync3449// with the process state.3450if (current_mod_id.GetStopID() == 0)3451return false;34523453bool changed = false;3454const bool was_valid = m_mod_id.IsValid();3455if (was_valid) {3456if (m_mod_id == current_mod_id) {3457// Everything is already up to date in this object, no need to update the3458// execution context scope.3459changed = false;3460} else {3461m_mod_id = current_mod_id;3462m_needs_update = true;3463changed = true;3464}3465}34663467// Now re-look up the thread and frame in case the underlying objects have3468// gone away & been recreated. That way we'll be sure to return a valid3469// exe_scope. If we used to have a thread or a frame but can't find it3470// anymore, then mark ourselves as invalid.34713472if (!accept_invalid_exe_ctx) {3473if (m_exe_ctx_ref.HasThreadRef()) {3474ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());3475if (thread_sp) {3476if (m_exe_ctx_ref.HasFrameRef()) {3477StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());3478if (!frame_sp) {3479// We used to have a frame, but now it is gone3480SetInvalid();3481changed = was_valid;3482}3483}3484} else {3485// We used to have a thread, but now it is gone3486SetInvalid();3487changed = was_valid;3488}3489}3490}34913492return changed;3493}34943495void ValueObject::EvaluationPoint::SetUpdated() {3496ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());3497if (process_sp)3498m_mod_id = process_sp->GetModID();3499m_needs_update = false;3500}35013502void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {3503if ((clear_mask & eClearUserVisibleDataItemsValue) ==3504eClearUserVisibleDataItemsValue)3505m_value_str.clear();35063507if ((clear_mask & eClearUserVisibleDataItemsLocation) ==3508eClearUserVisibleDataItemsLocation)3509m_location_str.clear();35103511if ((clear_mask & eClearUserVisibleDataItemsSummary) ==3512eClearUserVisibleDataItemsSummary)3513m_summary_str.clear();35143515if ((clear_mask & eClearUserVisibleDataItemsDescription) ==3516eClearUserVisibleDataItemsDescription)3517m_object_desc_str.clear();35183519if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==3520eClearUserVisibleDataItemsSyntheticChildren) {3521if (m_synthetic_value)3522m_synthetic_value = nullptr;3523}3524}35253526SymbolContextScope *ValueObject::GetSymbolContextScope() {3527if (m_parent) {3528if (!m_parent->IsPointerOrReferenceType())3529return m_parent->GetSymbolContextScope();3530}3531return nullptr;3532}35333534lldb::ValueObjectSP3535ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,3536llvm::StringRef expression,3537const ExecutionContext &exe_ctx) {3538return CreateValueObjectFromExpression(name, expression, exe_ctx,3539EvaluateExpressionOptions());3540}35413542lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(3543llvm::StringRef name, llvm::StringRef expression,3544const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {3545lldb::ValueObjectSP retval_sp;3546lldb::TargetSP target_sp(exe_ctx.GetTargetSP());3547if (!target_sp)3548return retval_sp;3549if (expression.empty())3550return retval_sp;3551target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),3552retval_sp, options);3553if (retval_sp && !name.empty())3554retval_sp->SetName(ConstString(name));3555return retval_sp;3556}35573558lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(3559llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,3560CompilerType type, bool do_deref) {3561if (type) {3562CompilerType pointer_type(type.GetPointerType());3563if (!do_deref)3564pointer_type = type;3565if (pointer_type) {3566lldb::DataBufferSP buffer(3567new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));3568lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(3569exe_ctx.GetBestExecutionContextScope(), pointer_type,3570ConstString(name), buffer, exe_ctx.GetByteOrder(),3571exe_ctx.GetAddressByteSize()));3572if (ptr_result_valobj_sp) {3573if (do_deref)3574ptr_result_valobj_sp->GetValue().SetValueType(3575Value::ValueType::LoadAddress);3576Status err;3577if (do_deref)3578ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);3579if (ptr_result_valobj_sp && !name.empty())3580ptr_result_valobj_sp->SetName(ConstString(name));3581}3582return ptr_result_valobj_sp;3583}3584}3585return lldb::ValueObjectSP();3586}35873588lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(3589llvm::StringRef name, const DataExtractor &data,3590const ExecutionContext &exe_ctx, CompilerType type) {3591lldb::ValueObjectSP new_value_sp;3592new_value_sp = ValueObjectConstResult::Create(3593exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,3594LLDB_INVALID_ADDRESS);3595new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);3596if (new_value_sp && !name.empty())3597new_value_sp->SetName(ConstString(name));3598return new_value_sp;3599}36003601lldb::ValueObjectSP3602ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,3603const llvm::APInt &v, CompilerType type,3604llvm::StringRef name) {3605ExecutionContext exe_ctx(target.get(), false);3606uint64_t byte_size = 0;3607if (auto temp = type.GetByteSize(target.get()))3608byte_size = temp.value();3609lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3610reinterpret_cast<const void *>(v.getRawData()), byte_size,3611exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());3612return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3613}36143615lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(3616lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,3617llvm::StringRef name) {3618return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);3619}36203621lldb::ValueObjectSP3622ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,3623llvm::StringRef name) {3624CompilerType target_type;3625if (target) {3626for (auto type_system_sp : target->GetScratchTypeSystems())3627if (auto compiler_type =3628type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {3629target_type = compiler_type;3630break;3631}3632}3633ExecutionContext exe_ctx(target.get(), false);3634uint64_t byte_size = 0;3635if (auto temp = target_type.GetByteSize(target.get()))3636byte_size = temp.value();3637lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3638reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),3639exe_ctx.GetAddressByteSize());3640return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,3641target_type);3642}36433644lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(3645lldb::TargetSP target, CompilerType type, llvm::StringRef name) {3646if (!type.IsNullPtrType()) {3647lldb::ValueObjectSP ret_val;3648return ret_val;3649}3650uintptr_t zero = 0;3651ExecutionContext exe_ctx(target.get(), false);3652uint64_t byte_size = 0;3653if (auto temp = type.GetByteSize(target.get()))3654byte_size = temp.value();3655lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3656reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),3657exe_ctx.GetAddressByteSize());3658return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3659}36603661ModuleSP ValueObject::GetModule() {3662ValueObject *root(GetRoot());3663if (root != this)3664return root->GetModule();3665return lldb::ModuleSP();3666}36673668ValueObject *ValueObject::GetRoot() {3669if (m_root)3670return m_root;3671return (m_root = FollowParentChain([](ValueObject *vo) -> bool {3672return (vo->m_parent != nullptr);3673}));3674}36753676ValueObject *3677ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {3678ValueObject *vo = this;3679while (vo) {3680if (!f(vo))3681break;3682vo = vo->m_parent;3683}3684return vo;3685}36863687AddressType ValueObject::GetAddressTypeOfChildren() {3688if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {3689ValueObject *root(GetRoot());3690if (root != this)3691return root->GetAddressTypeOfChildren();3692}3693return m_address_type_of_ptr_or_ref_children;3694}36953696lldb::DynamicValueType ValueObject::GetDynamicValueType() {3697ValueObject *with_dv_info = this;3698while (with_dv_info) {3699if (with_dv_info->HasDynamicValueTypeInfo())3700return with_dv_info->GetDynamicValueTypeImpl();3701with_dv_info = with_dv_info->m_parent;3702}3703return lldb::eNoDynamicValues;3704}37053706lldb::Format ValueObject::GetFormat() const {3707const ValueObject *with_fmt_info = this;3708while (with_fmt_info) {3709if (with_fmt_info->m_format != lldb::eFormatDefault)3710return with_fmt_info->m_format;3711with_fmt_info = with_fmt_info->m_parent;3712}3713return m_format;3714}37153716lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {3717lldb::LanguageType type = m_preferred_display_language;3718if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {3719if (GetRoot()) {3720if (GetRoot() == this) {3721if (StackFrameSP frame_sp = GetFrameSP()) {3722const SymbolContext &sc(3723frame_sp->GetSymbolContext(eSymbolContextCompUnit));3724if (CompileUnit *cu = sc.comp_unit)3725type = cu->GetLanguage();3726}3727} else {3728type = GetRoot()->GetPreferredDisplayLanguage();3729}3730}3731}3732return (m_preferred_display_language = type); // only compute it once3733}37343735void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {3736if (m_preferred_display_language == lldb::eLanguageTypeUnknown)3737SetPreferredDisplayLanguage(lt);3738}37393740bool ValueObject::CanProvideValue() {3741// we need to support invalid types as providers of values because some bare-3742// board debugging scenarios have no notion of types, but still manage to3743// have raw numeric values for things like registers. sigh.3744CompilerType type = GetCompilerType();3745return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));3746}3747374837493750ValueObjectSP ValueObject::Persist() {3751if (!UpdateValueIfNeeded())3752return nullptr;37533754TargetSP target_sp(GetTargetSP());3755if (!target_sp)3756return nullptr;37573758PersistentExpressionState *persistent_state =3759target_sp->GetPersistentExpressionStateForLanguage(3760GetPreferredDisplayLanguage());37613762if (!persistent_state)3763return nullptr;37643765ConstString name = persistent_state->GetNextPersistentVariableName();37663767ValueObjectSP const_result_sp =3768ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);37693770ExpressionVariableSP persistent_var_sp =3771persistent_state->CreatePersistentVariable(const_result_sp);3772persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;3773persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;37743775return persistent_var_sp->GetValueObject();3776}37773778lldb::ValueObjectSP ValueObject::GetVTable() {3779return ValueObjectVTable::Create(*this);3780}378137823783