15ffd83dbSDimitry Andric //===-- ValueObject.cpp ---------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Address.h" 12fe6060f1SDimitry Andric #include "lldb/Core/Declaration.h" 130b57cec5SDimitry Andric #include "lldb/Core/Module.h" 140b57cec5SDimitry Andric #include "lldb/Core/ValueObjectCast.h" 150b57cec5SDimitry Andric #include "lldb/Core/ValueObjectChild.h" 160b57cec5SDimitry Andric #include "lldb/Core/ValueObjectConstResult.h" 170b57cec5SDimitry Andric #include "lldb/Core/ValueObjectDynamicValue.h" 180b57cec5SDimitry Andric #include "lldb/Core/ValueObjectMemory.h" 190b57cec5SDimitry Andric #include "lldb/Core/ValueObjectSyntheticFilter.h" 205f757f3fSDimitry Andric #include "lldb/Core/ValueObjectVTable.h" 210b57cec5SDimitry Andric #include "lldb/DataFormatters/DataVisualization.h" 220b57cec5SDimitry Andric #include "lldb/DataFormatters/DumpValueObjectOptions.h" 230b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatManager.h" 240b57cec5SDimitry Andric #include "lldb/DataFormatters/StringPrinter.h" 250b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeFormat.h" 260b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeSummary.h" 270b57cec5SDimitry Andric #include "lldb/DataFormatters/ValueObjectPrinter.h" 280b57cec5SDimitry Andric #include "lldb/Expression/ExpressionVariable.h" 29480093f4SDimitry Andric #include "lldb/Host/Config.h" 300b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 310b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h" 320b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 330b57cec5SDimitry Andric #include "lldb/Symbol/Type.h" 340b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 350b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 360b57cec5SDimitry Andric #include "lldb/Target/Language.h" 370b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h" 380b57cec5SDimitry Andric #include "lldb/Target/Process.h" 390b57cec5SDimitry Andric #include "lldb/Target/StackFrame.h" 400b57cec5SDimitry Andric #include "lldb/Target/Target.h" 410b57cec5SDimitry Andric #include "lldb/Target/Thread.h" 420b57cec5SDimitry Andric #include "lldb/Target/ThreadList.h" 430b57cec5SDimitry Andric #include "lldb/Utility/DataBuffer.h" 440b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 450b57cec5SDimitry Andric #include "lldb/Utility/Flags.h" 4681ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 470b57cec5SDimitry Andric #include "lldb/Utility/Log.h" 480b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 490b57cec5SDimitry Andric #include "lldb/Utility/Stream.h" 500b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h" 510b57cec5SDimitry Andric #include "lldb/lldb-private-types.h" 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #include <algorithm> 560b57cec5SDimitry Andric #include <cstdint> 570b57cec5SDimitry Andric #include <cstdlib> 580b57cec5SDimitry Andric #include <memory> 59bdd1243dSDimitry Andric #include <optional> 600b57cec5SDimitry Andric #include <tuple> 610b57cec5SDimitry Andric 62fe6060f1SDimitry Andric #include <cassert> 63fe6060f1SDimitry Andric #include <cinttypes> 64fe6060f1SDimitry Andric #include <cstdio> 65fe6060f1SDimitry Andric #include <cstring> 66fe6060f1SDimitry Andric 67fe6060f1SDimitry Andric #include <lldb/Core/ValueObject.h> 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric namespace lldb_private { 700b57cec5SDimitry Andric class ExecutionContextScope; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric namespace lldb_private { 730b57cec5SDimitry Andric class SymbolContextScope; 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric using namespace lldb; 770b57cec5SDimitry Andric using namespace lldb_private; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static user_id_t g_value_obj_uid = 0; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // ValueObject constructor 820b57cec5SDimitry Andric ValueObject::ValueObject(ValueObject &parent) 83fe6060f1SDimitry Andric : m_parent(&parent), m_update_point(parent.GetUpdatePoint()), 84fe6060f1SDimitry Andric m_manager(parent.GetManager()), m_id(++g_value_obj_uid) { 85fe6060f1SDimitry Andric m_flags.m_is_synthetic_children_generated = 86fe6060f1SDimitry Andric parent.m_flags.m_is_synthetic_children_generated; 87480093f4SDimitry Andric m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder()); 88480093f4SDimitry Andric m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize()); 890b57cec5SDimitry Andric m_manager->ManageObject(this); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // ValueObject constructor 930b57cec5SDimitry Andric ValueObject::ValueObject(ExecutionContextScope *exe_scope, 945ffd83dbSDimitry Andric ValueObjectManager &manager, 950b57cec5SDimitry Andric AddressType child_ptr_or_ref_addr_type) 96fe6060f1SDimitry Andric : m_update_point(exe_scope), m_manager(&manager), 970b57cec5SDimitry Andric m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), 98fe6060f1SDimitry Andric m_id(++g_value_obj_uid) { 99480093f4SDimitry Andric if (exe_scope) { 100480093f4SDimitry Andric TargetSP target_sp(exe_scope->CalculateTarget()); 101480093f4SDimitry Andric if (target_sp) { 102480093f4SDimitry Andric const ArchSpec &arch = target_sp->GetArchitecture(); 103480093f4SDimitry Andric m_data.SetByteOrder(arch.GetByteOrder()); 104480093f4SDimitry Andric m_data.SetAddressByteSize(arch.GetAddressByteSize()); 105480093f4SDimitry Andric } 106480093f4SDimitry Andric } 1070b57cec5SDimitry Andric m_manager->ManageObject(this); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // Destructor 111fe6060f1SDimitry Andric ValueObject::~ValueObject() = default; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric bool ValueObject::UpdateValueIfNeeded(bool update_format) { 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric bool did_change_formats = false; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (update_format) 1180b57cec5SDimitry Andric did_change_formats = UpdateFormatsIfNeeded(); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // If this is a constant value, then our success is predicated on whether we 1210b57cec5SDimitry Andric // have an error or not 1220b57cec5SDimitry Andric if (GetIsConstant()) { 1230b57cec5SDimitry Andric // if you are constant, things might still have changed behind your back 1240b57cec5SDimitry Andric // (e.g. you are a frozen object and things have changed deeper than you 1250b57cec5SDimitry Andric // cared to freeze-dry yourself) in this case, your value has not changed, 1260b57cec5SDimitry Andric // but "computed" entries might have, so you might now have a different 1270b57cec5SDimitry Andric // summary, or a different object description. clear these so we will 1280b57cec5SDimitry Andric // recompute them 1290b57cec5SDimitry Andric if (update_format && !did_change_formats) 1300b57cec5SDimitry Andric ClearUserVisibleData(eClearUserVisibleDataItemsSummary | 1310b57cec5SDimitry Andric eClearUserVisibleDataItemsDescription); 1320b57cec5SDimitry Andric return m_error.Success(); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric bool first_update = IsChecksumEmpty(); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric if (NeedsUpdating()) { 1380b57cec5SDimitry Andric m_update_point.SetUpdated(); 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // Save the old value using swap to avoid a string copy which also will 1410b57cec5SDimitry Andric // clear our m_value_str 1420b57cec5SDimitry Andric if (m_value_str.empty()) { 143fe6060f1SDimitry Andric m_flags.m_old_value_valid = false; 1440b57cec5SDimitry Andric } else { 145fe6060f1SDimitry Andric m_flags.m_old_value_valid = true; 1460b57cec5SDimitry Andric m_old_value_str.swap(m_value_str); 1470b57cec5SDimitry Andric ClearUserVisibleData(eClearUserVisibleDataItemsValue); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric ClearUserVisibleData(); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric if (IsInScope()) { 1530b57cec5SDimitry Andric const bool value_was_valid = GetValueIsValid(); 1540b57cec5SDimitry Andric SetValueDidChange(false); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric m_error.Clear(); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Call the pure virtual function to update the value 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric bool need_compare_checksums = false; 1610b57cec5SDimitry Andric llvm::SmallVector<uint8_t, 16> old_checksum; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric if (!first_update && CanProvideValue()) { 1640b57cec5SDimitry Andric need_compare_checksums = true; 1650b57cec5SDimitry Andric old_checksum.resize(m_value_checksum.size()); 1660b57cec5SDimitry Andric std::copy(m_value_checksum.begin(), m_value_checksum.end(), 1670b57cec5SDimitry Andric old_checksum.begin()); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric bool success = UpdateValue(); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric SetValueIsValid(success); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric if (success) { 175480093f4SDimitry Andric UpdateChildrenAddressType(); 1760b57cec5SDimitry Andric const uint64_t max_checksum_size = 128; 1770b57cec5SDimitry Andric m_data.Checksum(m_value_checksum, max_checksum_size); 1780b57cec5SDimitry Andric } else { 1790b57cec5SDimitry Andric need_compare_checksums = false; 1800b57cec5SDimitry Andric m_value_checksum.clear(); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric assert(!need_compare_checksums || 1840b57cec5SDimitry Andric (!old_checksum.empty() && !m_value_checksum.empty())); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric if (first_update) 1870b57cec5SDimitry Andric SetValueDidChange(false); 188fe6060f1SDimitry Andric else if (!m_flags.m_value_did_change && !success) { 1890b57cec5SDimitry Andric // The value wasn't gotten successfully, so we mark this as changed if 1900b57cec5SDimitry Andric // the value used to be valid and now isn't 1910b57cec5SDimitry Andric SetValueDidChange(value_was_valid); 1920b57cec5SDimitry Andric } else if (need_compare_checksums) { 1930b57cec5SDimitry Andric SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], 1940b57cec5SDimitry Andric m_value_checksum.size())); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric } else { 1980b57cec5SDimitry Andric m_error.SetErrorString("out of scope"); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric return m_error.Success(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric bool ValueObject::UpdateFormatsIfNeeded() { 20581ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters); 2069dba64beSDimitry Andric LLDB_LOGF(log, 2079dba64beSDimitry Andric "[%s %p] checking for FormatManager revisions. ValueObject " 2080b57cec5SDimitry Andric "rev: %d - Global rev: %d", 2090b57cec5SDimitry Andric GetName().GetCString(), static_cast<void *>(this), 2100b57cec5SDimitry Andric m_last_format_mgr_revision, 2110b57cec5SDimitry Andric DataVisualization::GetCurrentRevision()); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric bool any_change = false; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) { 2160b57cec5SDimitry Andric m_last_format_mgr_revision = DataVisualization::GetCurrentRevision(); 2170b57cec5SDimitry Andric any_change = true; 2180b57cec5SDimitry Andric 219*0fca6ea1SDimitry Andric SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType())); 2200b57cec5SDimitry Andric SetSummaryFormat( 2210b57cec5SDimitry Andric DataVisualization::GetSummaryFormat(*this, GetDynamicValueType())); 2220b57cec5SDimitry Andric SetSyntheticChildren( 2230b57cec5SDimitry Andric DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType())); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric return any_change; 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric void ValueObject::SetNeedsUpdate() { 2300b57cec5SDimitry Andric m_update_point.SetNeedsUpdate(); 2310b57cec5SDimitry Andric // We have to clear the value string here so ConstResult children will notice 2320b57cec5SDimitry Andric // if their values are changed by hand (i.e. with SetValueAsCString). 2330b57cec5SDimitry Andric ClearUserVisibleData(eClearUserVisibleDataItemsValue); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric void ValueObject::ClearDynamicTypeInformation() { 237fe6060f1SDimitry Andric m_flags.m_children_count_valid = false; 238fe6060f1SDimitry Andric m_flags.m_did_calculate_complete_objc_class_type = false; 2390b57cec5SDimitry Andric m_last_format_mgr_revision = 0; 2400b57cec5SDimitry Andric m_override_type = CompilerType(); 2410b57cec5SDimitry Andric SetValueFormat(lldb::TypeFormatImplSP()); 2420b57cec5SDimitry Andric SetSummaryFormat(lldb::TypeSummaryImplSP()); 2430b57cec5SDimitry Andric SetSyntheticChildren(lldb::SyntheticChildrenSP()); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric CompilerType ValueObject::MaybeCalculateCompleteType() { 2470b57cec5SDimitry Andric CompilerType compiler_type(GetCompilerTypeImpl()); 2480b57cec5SDimitry Andric 249fe6060f1SDimitry Andric if (m_flags.m_did_calculate_complete_objc_class_type) { 2500b57cec5SDimitry Andric if (m_override_type.IsValid()) 2510b57cec5SDimitry Andric return m_override_type; 2520b57cec5SDimitry Andric else 2530b57cec5SDimitry Andric return compiler_type; 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 256fe6060f1SDimitry Andric m_flags.m_did_calculate_complete_objc_class_type = true; 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric ProcessSP process_sp( 2590b57cec5SDimitry Andric GetUpdatePoint().GetExecutionContextRef().GetProcessSP()); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric if (!process_sp) 2620b57cec5SDimitry Andric return compiler_type; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (auto *runtime = 2650b57cec5SDimitry Andric process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) { 266bdd1243dSDimitry Andric if (std::optional<CompilerType> complete_type = 2670b57cec5SDimitry Andric runtime->GetRuntimeType(compiler_type)) { 26881ad6265SDimitry Andric m_override_type = *complete_type; 2690b57cec5SDimitry Andric if (m_override_type.IsValid()) 2700b57cec5SDimitry Andric return m_override_type; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric return compiler_type; 2740b57cec5SDimitry Andric } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric DataExtractor &ValueObject::GetDataExtractor() { 2790b57cec5SDimitry Andric UpdateValueIfNeeded(false); 2800b57cec5SDimitry Andric return m_data; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric const Status &ValueObject::GetError() { 2840b57cec5SDimitry Andric UpdateValueIfNeeded(false); 2850b57cec5SDimitry Andric return m_error; 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric const char *ValueObject::GetLocationAsCStringImpl(const Value &value, 2890b57cec5SDimitry Andric const DataExtractor &data) { 2900b57cec5SDimitry Andric if (UpdateValueIfNeeded(false)) { 2910b57cec5SDimitry Andric if (m_location_str.empty()) { 2920b57cec5SDimitry Andric StreamString sstr; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric Value::ValueType value_type = value.GetValueType(); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric switch (value_type) { 297fe6060f1SDimitry Andric case Value::ValueType::Invalid: 298fe6060f1SDimitry Andric m_location_str = "invalid"; 299fe6060f1SDimitry Andric break; 300fe6060f1SDimitry Andric case Value::ValueType::Scalar: 301fe6060f1SDimitry Andric if (value.GetContextType() == Value::ContextType::RegisterInfo) { 3020b57cec5SDimitry Andric RegisterInfo *reg_info = value.GetRegisterInfo(); 3030b57cec5SDimitry Andric if (reg_info) { 3040b57cec5SDimitry Andric if (reg_info->name) 3050b57cec5SDimitry Andric m_location_str = reg_info->name; 3060b57cec5SDimitry Andric else if (reg_info->alt_name) 3070b57cec5SDimitry Andric m_location_str = reg_info->alt_name; 3080b57cec5SDimitry Andric if (m_location_str.empty()) 3090b57cec5SDimitry Andric m_location_str = (reg_info->encoding == lldb::eEncodingVector) 3100b57cec5SDimitry Andric ? "vector" 3110b57cec5SDimitry Andric : "scalar"; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric if (m_location_str.empty()) 315e8d8bef9SDimitry Andric m_location_str = "scalar"; 3160b57cec5SDimitry Andric break; 3170b57cec5SDimitry Andric 318fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 319fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 320fe6060f1SDimitry Andric case Value::ValueType::HostAddress: { 3210b57cec5SDimitry Andric uint32_t addr_nibble_size = data.GetAddressByteSize() * 2; 3220b57cec5SDimitry Andric sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, 3230b57cec5SDimitry Andric value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS)); 3245ffd83dbSDimitry Andric m_location_str = std::string(sstr.GetString()); 3250b57cec5SDimitry Andric } break; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric return m_location_str.c_str(); 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric bool ValueObject::ResolveValue(Scalar &scalar) { 3330b57cec5SDimitry Andric if (UpdateValueIfNeeded( 3340b57cec5SDimitry Andric false)) // make sure that you are up to date before returning anything 3350b57cec5SDimitry Andric { 3360b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 3370b57cec5SDimitry Andric Value tmp_value(m_value); 3385f757f3fSDimitry Andric scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get()); 3390b57cec5SDimitry Andric if (scalar.IsValid()) { 3400b57cec5SDimitry Andric const uint32_t bitfield_bit_size = GetBitfieldBitSize(); 3410b57cec5SDimitry Andric if (bitfield_bit_size) 3420b57cec5SDimitry Andric return scalar.ExtractBitfield(bitfield_bit_size, 3430b57cec5SDimitry Andric GetBitfieldBitOffset()); 3440b57cec5SDimitry Andric return true; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric return false; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool ValueObject::IsLogicalTrue(Status &error) { 3510b57cec5SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { 3520b57cec5SDimitry Andric LazyBool is_logical_true = language->IsLogicalTrue(*this, error); 3530b57cec5SDimitry Andric switch (is_logical_true) { 3540b57cec5SDimitry Andric case eLazyBoolYes: 3550b57cec5SDimitry Andric case eLazyBoolNo: 3560b57cec5SDimitry Andric return (is_logical_true == true); 3570b57cec5SDimitry Andric case eLazyBoolCalculate: 3580b57cec5SDimitry Andric break; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric Scalar scalar_value; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric if (!ResolveValue(scalar_value)) { 3650b57cec5SDimitry Andric error.SetErrorString("failed to get a scalar result"); 3660b57cec5SDimitry Andric return false; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric bool ret; 3700b57cec5SDimitry Andric ret = scalar_value.ULongLong(1) != 0; 3710b57cec5SDimitry Andric error.Clear(); 3720b57cec5SDimitry Andric return ret; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 375*0fca6ea1SDimitry Andric ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) { 3760b57cec5SDimitry Andric ValueObjectSP child_sp; 3770b57cec5SDimitry Andric // We may need to update our value if we are dynamic 3780b57cec5SDimitry Andric if (IsPossibleDynamicType()) 3790b57cec5SDimitry Andric UpdateValueIfNeeded(false); 380*0fca6ea1SDimitry Andric if (idx < GetNumChildrenIgnoringErrors()) { 3810b57cec5SDimitry Andric // Check if we have already made the child value object? 3820b57cec5SDimitry Andric if (can_create && !m_children.HasChildAtIndex(idx)) { 3830b57cec5SDimitry Andric // No we haven't created the child at this index, so lets have our 3840b57cec5SDimitry Andric // subclass do it and cache the result for quick future access. 385*0fca6ea1SDimitry Andric m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx)); 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric ValueObject *child = m_children.GetChildAtIndex(idx); 3890b57cec5SDimitry Andric if (child != nullptr) 3900b57cec5SDimitry Andric return child->GetSP(); 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric return child_sp; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric lldb::ValueObjectSP 39606c3fb27SDimitry Andric ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) { 3970b57cec5SDimitry Andric if (names.size() == 0) 3980b57cec5SDimitry Andric return GetSP(); 3990b57cec5SDimitry Andric ValueObjectSP root(GetSP()); 40006c3fb27SDimitry Andric for (llvm::StringRef name : names) { 40106c3fb27SDimitry Andric root = root->GetChildMemberWithName(name); 4020b57cec5SDimitry Andric if (!root) { 4030b57cec5SDimitry Andric return root; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric } 4060b57cec5SDimitry Andric return root; 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 40906c3fb27SDimitry Andric size_t ValueObject::GetIndexOfChildWithName(llvm::StringRef name) { 4100b57cec5SDimitry Andric bool omit_empty_base_classes = true; 41106c3fb27SDimitry Andric return GetCompilerType().GetIndexOfChildWithName(name, 4120b57cec5SDimitry Andric omit_empty_base_classes); 4130b57cec5SDimitry Andric } 4140b57cec5SDimitry Andric 41506c3fb27SDimitry Andric ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name, 4160b57cec5SDimitry Andric bool can_create) { 4175ffd83dbSDimitry Andric // We may need to update our value if we are dynamic. 4180b57cec5SDimitry Andric if (IsPossibleDynamicType()) 4190b57cec5SDimitry Andric UpdateValueIfNeeded(false); 4200b57cec5SDimitry Andric 4215ffd83dbSDimitry Andric // When getting a child by name, it could be buried inside some base classes 4225ffd83dbSDimitry Andric // (which really aren't part of the expression path), so we need a vector of 4235ffd83dbSDimitry Andric // indexes that can get us down to the correct child. 4240b57cec5SDimitry Andric std::vector<uint32_t> child_indexes; 4250b57cec5SDimitry Andric bool omit_empty_base_classes = true; 426480093f4SDimitry Andric 427480093f4SDimitry Andric if (!GetCompilerType().IsValid()) 428480093f4SDimitry Andric return ValueObjectSP(); 429480093f4SDimitry Andric 4300b57cec5SDimitry Andric const size_t num_child_indexes = 4310b57cec5SDimitry Andric GetCompilerType().GetIndexOfChildMemberWithName( 43206c3fb27SDimitry Andric name, omit_empty_base_classes, child_indexes); 4335ffd83dbSDimitry Andric if (num_child_indexes == 0) 4345ffd83dbSDimitry Andric return nullptr; 4350b57cec5SDimitry Andric 4365ffd83dbSDimitry Andric ValueObjectSP child_sp = GetSP(); 4375ffd83dbSDimitry Andric for (uint32_t idx : child_indexes) 4385ffd83dbSDimitry Andric if (child_sp) 4395ffd83dbSDimitry Andric child_sp = child_sp->GetChildAtIndex(idx, can_create); 4400b57cec5SDimitry Andric return child_sp; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 443*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) { 4440b57cec5SDimitry Andric UpdateValueIfNeeded(); 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric if (max < UINT32_MAX) { 447fe6060f1SDimitry Andric if (m_flags.m_children_count_valid) { 4480b57cec5SDimitry Andric size_t children_count = m_children.GetChildrenCount(); 4490b57cec5SDimitry Andric return children_count <= max ? children_count : max; 4500b57cec5SDimitry Andric } else 4510b57cec5SDimitry Andric return CalculateNumChildren(max); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 454fe6060f1SDimitry Andric if (!m_flags.m_children_count_valid) { 455*0fca6ea1SDimitry Andric auto num_children_or_err = CalculateNumChildren(); 456*0fca6ea1SDimitry Andric if (num_children_or_err) 457*0fca6ea1SDimitry Andric SetNumChildren(*num_children_or_err); 458*0fca6ea1SDimitry Andric else 459*0fca6ea1SDimitry Andric return num_children_or_err; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric return m_children.GetChildrenCount(); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 464*0fca6ea1SDimitry Andric uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) { 465*0fca6ea1SDimitry Andric auto value_or_err = GetNumChildren(max); 466*0fca6ea1SDimitry Andric if (value_or_err) 467*0fca6ea1SDimitry Andric return *value_or_err; 468*0fca6ea1SDimitry Andric LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(), 469*0fca6ea1SDimitry Andric "{0}"); 470*0fca6ea1SDimitry Andric return 0; 471*0fca6ea1SDimitry Andric } 472*0fca6ea1SDimitry Andric 4730b57cec5SDimitry Andric bool ValueObject::MightHaveChildren() { 4740b57cec5SDimitry Andric bool has_children = false; 4750b57cec5SDimitry Andric const uint32_t type_info = GetTypeInfo(); 4760b57cec5SDimitry Andric if (type_info) { 4770b57cec5SDimitry Andric if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference)) 4780b57cec5SDimitry Andric has_children = true; 4790b57cec5SDimitry Andric } else { 480*0fca6ea1SDimitry Andric has_children = GetNumChildrenIgnoringErrors() > 0; 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric return has_children; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric // Should only be called by ValueObject::GetNumChildren() 486*0fca6ea1SDimitry Andric void ValueObject::SetNumChildren(uint32_t num_children) { 487fe6060f1SDimitry Andric m_flags.m_children_count_valid = true; 4880b57cec5SDimitry Andric m_children.SetChildrenCount(num_children); 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 491*0fca6ea1SDimitry Andric ValueObject *ValueObject::CreateChildAtIndex(size_t idx) { 4920b57cec5SDimitry Andric bool omit_empty_base_classes = true; 493*0fca6ea1SDimitry Andric bool ignore_array_bounds = false; 494*0fca6ea1SDimitry Andric std::string child_name; 4950b57cec5SDimitry Andric uint32_t child_byte_size = 0; 4960b57cec5SDimitry Andric int32_t child_byte_offset = 0; 4970b57cec5SDimitry Andric uint32_t child_bitfield_bit_size = 0; 4980b57cec5SDimitry Andric uint32_t child_bitfield_bit_offset = 0; 4990b57cec5SDimitry Andric bool child_is_base_class = false; 5000b57cec5SDimitry Andric bool child_is_deref_of_parent = false; 5010b57cec5SDimitry Andric uint64_t language_flags = 0; 502*0fca6ea1SDimitry Andric const bool transparent_pointers = true; 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 5050b57cec5SDimitry Andric 506*0fca6ea1SDimitry Andric auto child_compiler_type_or_err = 507*0fca6ea1SDimitry Andric GetCompilerType().GetChildCompilerTypeAtIndex( 5080b57cec5SDimitry Andric &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, 509*0fca6ea1SDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset, 510*0fca6ea1SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, 511*0fca6ea1SDimitry Andric child_is_base_class, child_is_deref_of_parent, this, language_flags); 512*0fca6ea1SDimitry Andric if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) { 513*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), 514*0fca6ea1SDimitry Andric child_compiler_type_or_err.takeError(), 515*0fca6ea1SDimitry Andric "could not find child: {0}"); 516*0fca6ea1SDimitry Andric return nullptr; 517*0fca6ea1SDimitry Andric } 5180b57cec5SDimitry Andric 519*0fca6ea1SDimitry Andric return new ValueObjectChild( 520*0fca6ea1SDimitry Andric *this, *child_compiler_type_or_err, ConstString(child_name), 521*0fca6ea1SDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size, 522*0fca6ea1SDimitry Andric child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent, 523*0fca6ea1SDimitry Andric eAddressTypeInvalid, language_flags); 524*0fca6ea1SDimitry Andric } 5250b57cec5SDimitry Andric 526*0fca6ea1SDimitry Andric ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) { 527*0fca6ea1SDimitry Andric bool omit_empty_base_classes = true; 528*0fca6ea1SDimitry Andric bool ignore_array_bounds = true; 529*0fca6ea1SDimitry Andric std::string child_name; 530*0fca6ea1SDimitry Andric uint32_t child_byte_size = 0; 531*0fca6ea1SDimitry Andric int32_t child_byte_offset = 0; 532*0fca6ea1SDimitry Andric uint32_t child_bitfield_bit_size = 0; 533*0fca6ea1SDimitry Andric uint32_t child_bitfield_bit_offset = 0; 534*0fca6ea1SDimitry Andric bool child_is_base_class = false; 535*0fca6ea1SDimitry Andric bool child_is_deref_of_parent = false; 536*0fca6ea1SDimitry Andric uint64_t language_flags = 0; 537*0fca6ea1SDimitry Andric const bool transparent_pointers = false; 538*0fca6ea1SDimitry Andric 539*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 540*0fca6ea1SDimitry Andric 541*0fca6ea1SDimitry Andric auto child_compiler_type_or_err = 542*0fca6ea1SDimitry Andric GetCompilerType().GetChildCompilerTypeAtIndex( 543*0fca6ea1SDimitry Andric &exe_ctx, 0, transparent_pointers, omit_empty_base_classes, 544*0fca6ea1SDimitry Andric ignore_array_bounds, child_name, child_byte_size, child_byte_offset, 545*0fca6ea1SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, 546*0fca6ea1SDimitry Andric child_is_base_class, child_is_deref_of_parent, this, language_flags); 547*0fca6ea1SDimitry Andric if (!child_compiler_type_or_err) { 548*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), 549*0fca6ea1SDimitry Andric child_compiler_type_or_err.takeError(), 550*0fca6ea1SDimitry Andric "could not find child: {0}"); 551*0fca6ea1SDimitry Andric return nullptr; 552*0fca6ea1SDimitry Andric } 553*0fca6ea1SDimitry Andric 554*0fca6ea1SDimitry Andric if (child_compiler_type_or_err->IsValid()) { 555*0fca6ea1SDimitry Andric child_byte_offset += child_byte_size * idx; 556*0fca6ea1SDimitry Andric 557*0fca6ea1SDimitry Andric return new ValueObjectChild( 558*0fca6ea1SDimitry Andric *this, *child_compiler_type_or_err, ConstString(child_name), 559*0fca6ea1SDimitry Andric child_byte_size, child_byte_offset, child_bitfield_bit_size, 560*0fca6ea1SDimitry Andric child_bitfield_bit_offset, child_is_base_class, 561*0fca6ea1SDimitry Andric child_is_deref_of_parent, eAddressTypeInvalid, language_flags); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5645ffd83dbSDimitry Andric // In case of an incomplete type, try to use the ValueObject's 5655ffd83dbSDimitry Andric // synthetic value to create the child ValueObject. 566*0fca6ea1SDimitry Andric if (ValueObjectSP synth_valobj_sp = GetSyntheticValue()) 567*0fca6ea1SDimitry Andric return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get(); 5685ffd83dbSDimitry Andric 569*0fca6ea1SDimitry Andric return nullptr; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr, 5730b57cec5SDimitry Andric std::string &destination, 5740b57cec5SDimitry Andric lldb::LanguageType lang) { 5750b57cec5SDimitry Andric return GetSummaryAsCString(summary_ptr, destination, 5760b57cec5SDimitry Andric TypeSummaryOptions().SetLanguage(lang)); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr, 5800b57cec5SDimitry Andric std::string &destination, 5810b57cec5SDimitry Andric const TypeSummaryOptions &options) { 5820b57cec5SDimitry Andric destination.clear(); 5830b57cec5SDimitry Andric 584bdd1243dSDimitry Andric // If we have a forcefully completed type, don't try and show a summary from 585bdd1243dSDimitry Andric // a valid summary string or function because the type is not complete and 586bdd1243dSDimitry Andric // no member variables or member functions will be available. 587bdd1243dSDimitry Andric if (GetCompilerType().IsForcefullyCompleted()) { 588bdd1243dSDimitry Andric destination = "<incomplete type>"; 589bdd1243dSDimitry Andric return true; 590bdd1243dSDimitry Andric } 591bdd1243dSDimitry Andric 5920b57cec5SDimitry Andric // ideally we would like to bail out if passing NULL, but if we do so we end 5930b57cec5SDimitry Andric // up not providing the summary for function pointers anymore 594fe6060f1SDimitry Andric if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary) 5950b57cec5SDimitry Andric return false; 5960b57cec5SDimitry Andric 597fe6060f1SDimitry Andric m_flags.m_is_getting_summary = true; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric TypeSummaryOptions actual_options(options); 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown) 6020b57cec5SDimitry Andric actual_options.SetLanguage(GetPreferredDisplayLanguage()); 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric // this is a hot path in code and we prefer to avoid setting this string all 6050b57cec5SDimitry Andric // too often also clearing out other information that we might care to see in 6060b57cec5SDimitry Andric // a crash log. might be useful in very specific situations though. 6070b57cec5SDimitry Andric /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. 6080b57cec5SDimitry Andric Summary provider's description is %s", 6090b57cec5SDimitry Andric GetTypeName().GetCString(), 6100b57cec5SDimitry Andric GetName().GetCString(), 6110b57cec5SDimitry Andric summary_ptr->GetDescription().c_str());*/ 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric if (UpdateValueIfNeeded(false) && summary_ptr) { 6140b57cec5SDimitry Andric if (HasSyntheticValue()) 6150b57cec5SDimitry Andric m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on 6160b57cec5SDimitry Andric // the synthetic children being 6170b57cec5SDimitry Andric // up-to-date (e.g. ${svar%#}) 6180b57cec5SDimitry Andric summary_ptr->FormatObject(this, destination, actual_options); 6190b57cec5SDimitry Andric } 620fe6060f1SDimitry Andric m_flags.m_is_getting_summary = false; 6210b57cec5SDimitry Andric return !destination.empty(); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) { 6250b57cec5SDimitry Andric if (UpdateValueIfNeeded(true) && m_summary_str.empty()) { 6260b57cec5SDimitry Andric TypeSummaryOptions summary_options; 6270b57cec5SDimitry Andric summary_options.SetLanguage(lang); 6280b57cec5SDimitry Andric GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str, 6290b57cec5SDimitry Andric summary_options); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric if (m_summary_str.empty()) 6320b57cec5SDimitry Andric return nullptr; 6330b57cec5SDimitry Andric return m_summary_str.c_str(); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric bool ValueObject::GetSummaryAsCString(std::string &destination, 6370b57cec5SDimitry Andric const TypeSummaryOptions &options) { 6380b57cec5SDimitry Andric return GetSummaryAsCString(GetSummaryFormat().get(), destination, options); 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric bool ValueObject::IsCStringContainer(bool check_pointer) { 6420b57cec5SDimitry Andric CompilerType pointee_or_element_compiler_type; 6430b57cec5SDimitry Andric const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type)); 6440b57cec5SDimitry Andric bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) && 6450b57cec5SDimitry Andric pointee_or_element_compiler_type.IsCharType()); 6460b57cec5SDimitry Andric if (!is_char_arr_ptr) 6470b57cec5SDimitry Andric return false; 6480b57cec5SDimitry Andric if (!check_pointer) 6490b57cec5SDimitry Andric return true; 6500b57cec5SDimitry Andric if (type_flags.Test(eTypeIsArray)) 6510b57cec5SDimitry Andric return true; 6520b57cec5SDimitry Andric addr_t cstr_address = LLDB_INVALID_ADDRESS; 6530b57cec5SDimitry Andric AddressType cstr_address_type = eAddressTypeInvalid; 6545ffd83dbSDimitry Andric cstr_address = GetPointerValue(&cstr_address_type); 6550b57cec5SDimitry Andric return (cstr_address != LLDB_INVALID_ADDRESS); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, 6590b57cec5SDimitry Andric uint32_t item_count) { 6600b57cec5SDimitry Andric CompilerType pointee_or_element_compiler_type; 6610b57cec5SDimitry Andric const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type); 6620b57cec5SDimitry Andric const bool is_pointer_type = type_info & eTypeIsPointer; 6630b57cec5SDimitry Andric const bool is_array_type = type_info & eTypeIsArray; 6640b57cec5SDimitry Andric if (!(is_pointer_type || is_array_type)) 6650b57cec5SDimitry Andric return 0; 6660b57cec5SDimitry Andric 6670b57cec5SDimitry Andric if (item_count == 0) 6680b57cec5SDimitry Andric return 0; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 6710b57cec5SDimitry Andric 672bdd1243dSDimitry Andric std::optional<uint64_t> item_type_size = 6730b57cec5SDimitry Andric pointee_or_element_compiler_type.GetByteSize( 6740b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope()); 6750b57cec5SDimitry Andric if (!item_type_size) 6760b57cec5SDimitry Andric return 0; 6770b57cec5SDimitry Andric const uint64_t bytes = item_count * *item_type_size; 6780b57cec5SDimitry Andric const uint64_t offset = item_idx * *item_type_size; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric if (item_idx == 0 && item_count == 1) // simply a deref 6810b57cec5SDimitry Andric { 6820b57cec5SDimitry Andric if (is_pointer_type) { 6830b57cec5SDimitry Andric Status error; 6840b57cec5SDimitry Andric ValueObjectSP pointee_sp = Dereference(error); 6850b57cec5SDimitry Andric if (error.Fail() || pointee_sp.get() == nullptr) 6860b57cec5SDimitry Andric return 0; 6870b57cec5SDimitry Andric return pointee_sp->GetData(data, error); 6880b57cec5SDimitry Andric } else { 68906c3fb27SDimitry Andric ValueObjectSP child_sp = GetChildAtIndex(0); 6900b57cec5SDimitry Andric if (child_sp.get() == nullptr) 6910b57cec5SDimitry Andric return 0; 6920b57cec5SDimitry Andric Status error; 6930b57cec5SDimitry Andric return child_sp->GetData(data, error); 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric return true; 6960b57cec5SDimitry Andric } else /* (items > 1) */ 6970b57cec5SDimitry Andric { 6980b57cec5SDimitry Andric Status error; 6990b57cec5SDimitry Andric lldb_private::DataBufferHeap *heap_buf_ptr = nullptr; 7000b57cec5SDimitry Andric lldb::DataBufferSP data_sp(heap_buf_ptr = 7010b57cec5SDimitry Andric new lldb_private::DataBufferHeap()); 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric AddressType addr_type; 7040b57cec5SDimitry Andric lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type) 7050b57cec5SDimitry Andric : GetAddressOf(true, &addr_type); 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric switch (addr_type) { 7080b57cec5SDimitry Andric case eAddressTypeFile: { 7090b57cec5SDimitry Andric ModuleSP module_sp(GetModule()); 7100b57cec5SDimitry Andric if (module_sp) { 7110b57cec5SDimitry Andric addr = addr + offset; 7120b57cec5SDimitry Andric Address so_addr; 7130b57cec5SDimitry Andric module_sp->ResolveFileAddress(addr, so_addr); 7140b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 7150b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 7160b57cec5SDimitry Andric if (target) { 7170b57cec5SDimitry Andric heap_buf_ptr->SetByteSize(bytes); 7180b57cec5SDimitry Andric size_t bytes_read = target->ReadMemory( 719fe6060f1SDimitry Andric so_addr, heap_buf_ptr->GetBytes(), bytes, error, true); 7200b57cec5SDimitry Andric if (error.Success()) { 7210b57cec5SDimitry Andric data.SetData(data_sp); 7220b57cec5SDimitry Andric return bytes_read; 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric } 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric } break; 7270b57cec5SDimitry Andric case eAddressTypeLoad: { 7280b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 7290b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 7300b57cec5SDimitry Andric if (process) { 7310b57cec5SDimitry Andric heap_buf_ptr->SetByteSize(bytes); 7320b57cec5SDimitry Andric size_t bytes_read = process->ReadMemory( 7330b57cec5SDimitry Andric addr + offset, heap_buf_ptr->GetBytes(), bytes, error); 7340b57cec5SDimitry Andric if (error.Success() || bytes_read > 0) { 7350b57cec5SDimitry Andric data.SetData(data_sp); 7360b57cec5SDimitry Andric return bytes_read; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric } break; 7400b57cec5SDimitry Andric case eAddressTypeHost: { 7410b57cec5SDimitry Andric auto max_bytes = 7420b57cec5SDimitry Andric GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); 7430b57cec5SDimitry Andric if (max_bytes && *max_bytes > offset) { 7440b57cec5SDimitry Andric size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes); 7450b57cec5SDimitry Andric addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 7460b57cec5SDimitry Andric if (addr == 0 || addr == LLDB_INVALID_ADDRESS) 7470b57cec5SDimitry Andric break; 7480b57cec5SDimitry Andric heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read); 7490b57cec5SDimitry Andric data.SetData(data_sp); 7500b57cec5SDimitry Andric return bytes_read; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric } break; 7530b57cec5SDimitry Andric case eAddressTypeInvalid: 7540b57cec5SDimitry Andric break; 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric } 7570b57cec5SDimitry Andric return 0; 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric uint64_t ValueObject::GetData(DataExtractor &data, Status &error) { 7610b57cec5SDimitry Andric UpdateValueIfNeeded(false); 7620b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 7639dba64beSDimitry Andric error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get()); 7640b57cec5SDimitry Andric if (error.Fail()) { 7650b57cec5SDimitry Andric if (m_data.GetByteSize()) { 7660b57cec5SDimitry Andric data = m_data; 7670b57cec5SDimitry Andric error.Clear(); 7680b57cec5SDimitry Andric return data.GetByteSize(); 7690b57cec5SDimitry Andric } else { 7700b57cec5SDimitry Andric return 0; 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric data.SetAddressByteSize(m_data.GetAddressByteSize()); 7740b57cec5SDimitry Andric data.SetByteOrder(m_data.GetByteOrder()); 7750b57cec5SDimitry Andric return data.GetByteSize(); 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric bool ValueObject::SetData(DataExtractor &data, Status &error) { 7790b57cec5SDimitry Andric error.Clear(); 7800b57cec5SDimitry Andric // Make sure our value is up to date first so that our location and location 7810b57cec5SDimitry Andric // type is valid. 7820b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) { 7830b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 7840b57cec5SDimitry Andric return false; 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric uint64_t count = 0; 7880b57cec5SDimitry Andric const Encoding encoding = GetCompilerType().GetEncoding(count); 7890b57cec5SDimitry Andric 79081ad6265SDimitry Andric const size_t byte_size = GetByteSize().value_or(0); 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric Value::ValueType value_type = m_value.GetValueType(); 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric switch (value_type) { 795fe6060f1SDimitry Andric case Value::ValueType::Invalid: 796fe6060f1SDimitry Andric error.SetErrorString("invalid location"); 797fe6060f1SDimitry Andric return false; 798fe6060f1SDimitry Andric case Value::ValueType::Scalar: { 7990b57cec5SDimitry Andric Status set_error = 8000b57cec5SDimitry Andric m_value.GetScalar().SetValueFromData(data, encoding, byte_size); 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric if (!set_error.Success()) { 8030b57cec5SDimitry Andric error.SetErrorStringWithFormat("unable to set scalar value: %s", 8040b57cec5SDimitry Andric set_error.AsCString()); 8050b57cec5SDimitry Andric return false; 8060b57cec5SDimitry Andric } 8070b57cec5SDimitry Andric } break; 808fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: { 8090b57cec5SDimitry Andric // If it is a load address, then the scalar value is the storage location 8100b57cec5SDimitry Andric // of the data, and we have to shove this value down to that load location. 8110b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 8120b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 8130b57cec5SDimitry Andric if (process) { 8140b57cec5SDimitry Andric addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 8150b57cec5SDimitry Andric size_t bytes_written = process->WriteMemory( 8160b57cec5SDimitry Andric target_addr, data.GetDataStart(), byte_size, error); 8170b57cec5SDimitry Andric if (!error.Success()) 8180b57cec5SDimitry Andric return false; 8190b57cec5SDimitry Andric if (bytes_written != byte_size) { 8200b57cec5SDimitry Andric error.SetErrorString("unable to write value to memory"); 8210b57cec5SDimitry Andric return false; 8220b57cec5SDimitry Andric } 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric } break; 825fe6060f1SDimitry Andric case Value::ValueType::HostAddress: { 8260b57cec5SDimitry Andric // If it is a host address, then we stuff the scalar as a DataBuffer into 8270b57cec5SDimitry Andric // the Value's data. 8280b57cec5SDimitry Andric DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); 8290b57cec5SDimitry Andric m_data.SetData(buffer_sp, 0); 8300b57cec5SDimitry Andric data.CopyByteOrderedData(0, byte_size, 8310b57cec5SDimitry Andric const_cast<uint8_t *>(m_data.GetDataStart()), 8320b57cec5SDimitry Andric byte_size, m_data.GetByteOrder()); 8330b57cec5SDimitry Andric m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); 8340b57cec5SDimitry Andric } break; 835fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 8360b57cec5SDimitry Andric break; 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric // If we have reached this point, then we have successfully changed the 8400b57cec5SDimitry Andric // value. 8410b57cec5SDimitry Andric SetNeedsUpdate(); 8420b57cec5SDimitry Andric return true; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric static bool CopyStringDataToBufferSP(const StreamString &source, 84681ad6265SDimitry Andric lldb::WritableDataBufferSP &destination) { 847349cc55cSDimitry Andric llvm::StringRef src = source.GetString(); 84881ad6265SDimitry Andric src = src.rtrim('\0'); 849349cc55cSDimitry Andric destination = std::make_shared<DataBufferHeap>(src.size(), 0); 850349cc55cSDimitry Andric memcpy(destination->GetBytes(), src.data(), src.size()); 8510b57cec5SDimitry Andric return true; 8520b57cec5SDimitry Andric } 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric std::pair<size_t, bool> 85581ad6265SDimitry Andric ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp, 8567a6dacacSDimitry Andric Status &error, bool honor_array) { 8570b57cec5SDimitry Andric bool was_capped = false; 8580b57cec5SDimitry Andric StreamString s; 8590b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 8600b57cec5SDimitry Andric Target *target = exe_ctx.GetTargetPtr(); 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric if (!target) { 8630b57cec5SDimitry Andric s << "<no target to read from>"; 8640b57cec5SDimitry Andric error.SetErrorString("no target to read from"); 8650b57cec5SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp); 8660b57cec5SDimitry Andric return {0, was_capped}; 8670b57cec5SDimitry Andric } 8680b57cec5SDimitry Andric 8697a6dacacSDimitry Andric const auto max_length = target->GetMaximumSizeOfStringSummary(); 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric size_t bytes_read = 0; 8720b57cec5SDimitry Andric size_t total_bytes_read = 0; 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric CompilerType compiler_type = GetCompilerType(); 8750b57cec5SDimitry Andric CompilerType elem_or_pointee_compiler_type; 8760b57cec5SDimitry Andric const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type)); 8770b57cec5SDimitry Andric if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) && 8780b57cec5SDimitry Andric elem_or_pointee_compiler_type.IsCharType()) { 8790b57cec5SDimitry Andric addr_t cstr_address = LLDB_INVALID_ADDRESS; 8800b57cec5SDimitry Andric AddressType cstr_address_type = eAddressTypeInvalid; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric size_t cstr_len = 0; 8830b57cec5SDimitry Andric bool capped_data = false; 8840b57cec5SDimitry Andric const bool is_array = type_flags.Test(eTypeIsArray); 8850b57cec5SDimitry Andric if (is_array) { 8860b57cec5SDimitry Andric // We have an array 8870b57cec5SDimitry Andric uint64_t array_size = 0; 888fe6060f1SDimitry Andric if (compiler_type.IsArrayType(nullptr, &array_size)) { 8890b57cec5SDimitry Andric cstr_len = array_size; 8900b57cec5SDimitry Andric if (cstr_len > max_length) { 8910b57cec5SDimitry Andric capped_data = true; 8920b57cec5SDimitry Andric cstr_len = max_length; 8930b57cec5SDimitry Andric } 8940b57cec5SDimitry Andric } 8950b57cec5SDimitry Andric cstr_address = GetAddressOf(true, &cstr_address_type); 8960b57cec5SDimitry Andric } else { 8970b57cec5SDimitry Andric // We have a pointer 8980b57cec5SDimitry Andric cstr_address = GetPointerValue(&cstr_address_type); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) { 9020b57cec5SDimitry Andric if (cstr_address_type == eAddressTypeHost && is_array) { 9030b57cec5SDimitry Andric const char *cstr = GetDataExtractor().PeekCStr(0); 9040b57cec5SDimitry Andric if (cstr == nullptr) { 9050b57cec5SDimitry Andric s << "<invalid address>"; 9060b57cec5SDimitry Andric error.SetErrorString("invalid address"); 9070b57cec5SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp); 9080b57cec5SDimitry Andric return {0, was_capped}; 9090b57cec5SDimitry Andric } 910349cc55cSDimitry Andric s << llvm::StringRef(cstr, cstr_len); 911349cc55cSDimitry Andric CopyStringDataToBufferSP(s, buffer_sp); 9120b57cec5SDimitry Andric return {cstr_len, was_capped}; 9130b57cec5SDimitry Andric } else { 9140b57cec5SDimitry Andric s << "<invalid address>"; 9150b57cec5SDimitry Andric error.SetErrorString("invalid address"); 9160b57cec5SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp); 9170b57cec5SDimitry Andric return {0, was_capped}; 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric Address cstr_so_addr(cstr_address); 9220b57cec5SDimitry Andric DataExtractor data; 9230b57cec5SDimitry Andric if (cstr_len > 0 && honor_array) { 9240b57cec5SDimitry Andric // I am using GetPointeeData() here to abstract the fact that some 9250b57cec5SDimitry Andric // ValueObjects are actually frozen pointers in the host but the pointed- 9260b57cec5SDimitry Andric // to data lives in the debuggee, and GetPointeeData() automatically 9270b57cec5SDimitry Andric // takes care of this 9280b57cec5SDimitry Andric GetPointeeData(data, 0, cstr_len); 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric if ((bytes_read = data.GetByteSize()) > 0) { 9310b57cec5SDimitry Andric total_bytes_read = bytes_read; 9320b57cec5SDimitry Andric for (size_t offset = 0; offset < bytes_read; offset++) 9330b57cec5SDimitry Andric s.Printf("%c", *data.PeekData(offset, 1)); 9340b57cec5SDimitry Andric if (capped_data) 9350b57cec5SDimitry Andric was_capped = true; 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric } else { 9380b57cec5SDimitry Andric cstr_len = max_length; 9390b57cec5SDimitry Andric const size_t k_max_buf_size = 64; 9400b57cec5SDimitry Andric 9410b57cec5SDimitry Andric size_t offset = 0; 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric int cstr_len_displayed = -1; 9440b57cec5SDimitry Andric bool capped_cstr = false; 9450b57cec5SDimitry Andric // I am using GetPointeeData() here to abstract the fact that some 9460b57cec5SDimitry Andric // ValueObjects are actually frozen pointers in the host but the pointed- 9470b57cec5SDimitry Andric // to data lives in the debuggee, and GetPointeeData() automatically 9480b57cec5SDimitry Andric // takes care of this 9490b57cec5SDimitry Andric while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) { 9500b57cec5SDimitry Andric total_bytes_read += bytes_read; 9510b57cec5SDimitry Andric const char *cstr = data.PeekCStr(0); 9520b57cec5SDimitry Andric size_t len = strnlen(cstr, k_max_buf_size); 9530b57cec5SDimitry Andric if (cstr_len_displayed < 0) 9540b57cec5SDimitry Andric cstr_len_displayed = len; 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric if (len == 0) 9570b57cec5SDimitry Andric break; 9580b57cec5SDimitry Andric cstr_len_displayed += len; 9590b57cec5SDimitry Andric if (len > bytes_read) 9600b57cec5SDimitry Andric len = bytes_read; 9610b57cec5SDimitry Andric if (len > cstr_len) 9620b57cec5SDimitry Andric len = cstr_len; 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric for (size_t offset = 0; offset < bytes_read; offset++) 9650b57cec5SDimitry Andric s.Printf("%c", *data.PeekData(offset, 1)); 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric if (len < k_max_buf_size) 9680b57cec5SDimitry Andric break; 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric if (len >= cstr_len) { 9710b57cec5SDimitry Andric capped_cstr = true; 9720b57cec5SDimitry Andric break; 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric cstr_len -= len; 9760b57cec5SDimitry Andric offset += len; 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric if (cstr_len_displayed >= 0) { 9800b57cec5SDimitry Andric if (capped_cstr) 9810b57cec5SDimitry Andric was_capped = true; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric } 9840b57cec5SDimitry Andric } else { 9850b57cec5SDimitry Andric error.SetErrorString("not a string object"); 9860b57cec5SDimitry Andric s << "<not a string object>"; 9870b57cec5SDimitry Andric } 9880b57cec5SDimitry Andric CopyStringDataToBufferSP(s, buffer_sp); 9890b57cec5SDimitry Andric return {total_bytes_read, was_capped}; 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 992*0fca6ea1SDimitry Andric llvm::Expected<std::string> ValueObject::GetObjectDescription() { 9930b57cec5SDimitry Andric if (!UpdateValueIfNeeded(true)) 994*0fca6ea1SDimitry Andric return llvm::createStringError("could not update value"); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // Return cached value. 9970b57cec5SDimitry Andric if (!m_object_desc_str.empty()) 998*0fca6ea1SDimitry Andric return m_object_desc_str; 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 10010b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 10020b57cec5SDimitry Andric if (!process) 1003*0fca6ea1SDimitry Andric return llvm::createStringError("no process"); 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric // Returns the object description produced by one language runtime. 1006*0fca6ea1SDimitry Andric auto get_object_description = 1007*0fca6ea1SDimitry Andric [&](LanguageType language) -> llvm::Expected<std::string> { 10080b57cec5SDimitry Andric if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) { 10090b57cec5SDimitry Andric StreamString s; 1010*0fca6ea1SDimitry Andric if (llvm::Error error = runtime->GetObjectDescription(s, *this)) 1011*0fca6ea1SDimitry Andric return error; 1012*0fca6ea1SDimitry Andric m_object_desc_str = s.GetString(); 1013*0fca6ea1SDimitry Andric return m_object_desc_str; 10140b57cec5SDimitry Andric } 1015*0fca6ea1SDimitry Andric return llvm::createStringError("no native language runtime"); 10160b57cec5SDimitry Andric }; 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric // Try the native language runtime first. 10190b57cec5SDimitry Andric LanguageType native_language = GetObjectRuntimeLanguage(); 1020*0fca6ea1SDimitry Andric llvm::Expected<std::string> desc = get_object_description(native_language); 1021*0fca6ea1SDimitry Andric if (desc) 10220b57cec5SDimitry Andric return desc; 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric // Try the Objective-C language runtime. This fallback is necessary 10250b57cec5SDimitry Andric // for Objective-C++ and mixed Objective-C / C++ programs. 1026*0fca6ea1SDimitry Andric if (Language::LanguageIsCFamily(native_language)) { 1027*0fca6ea1SDimitry Andric // We're going to try again, so let's drop the first error. 1028*0fca6ea1SDimitry Andric llvm::consumeError(desc.takeError()); 10290b57cec5SDimitry Andric return get_object_description(eLanguageTypeObjC); 1030*0fca6ea1SDimitry Andric } 1031*0fca6ea1SDimitry Andric return desc; 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format, 10350b57cec5SDimitry Andric std::string &destination) { 10360b57cec5SDimitry Andric if (UpdateValueIfNeeded(false)) 10370b57cec5SDimitry Andric return format.FormatObject(this, destination); 10380b57cec5SDimitry Andric else 10390b57cec5SDimitry Andric return false; 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric bool ValueObject::GetValueAsCString(lldb::Format format, 10430b57cec5SDimitry Andric std::string &destination) { 10440b57cec5SDimitry Andric return GetValueAsCString(TypeFormatImpl_Format(format), destination); 10450b57cec5SDimitry Andric } 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric const char *ValueObject::GetValueAsCString() { 10480b57cec5SDimitry Andric if (UpdateValueIfNeeded(true)) { 10490b57cec5SDimitry Andric lldb::TypeFormatImplSP format_sp; 10500b57cec5SDimitry Andric lldb::Format my_format = GetFormat(); 10510b57cec5SDimitry Andric if (my_format == lldb::eFormatDefault) { 10520b57cec5SDimitry Andric if (m_type_format_sp) 10530b57cec5SDimitry Andric format_sp = m_type_format_sp; 10540b57cec5SDimitry Andric else { 1055fe6060f1SDimitry Andric if (m_flags.m_is_bitfield_for_scalar) 10560b57cec5SDimitry Andric my_format = eFormatUnsigned; 10570b57cec5SDimitry Andric else { 1058fe6060f1SDimitry Andric if (m_value.GetContextType() == Value::ContextType::RegisterInfo) { 10590b57cec5SDimitry Andric const RegisterInfo *reg_info = m_value.GetRegisterInfo(); 10600b57cec5SDimitry Andric if (reg_info) 10610b57cec5SDimitry Andric my_format = reg_info->format; 10620b57cec5SDimitry Andric } else { 10630b57cec5SDimitry Andric my_format = GetValue().GetCompilerType().GetFormat(); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric if (my_format != m_last_format || m_value_str.empty()) { 10690b57cec5SDimitry Andric m_last_format = my_format; 10700b57cec5SDimitry Andric if (!format_sp) 10710b57cec5SDimitry Andric format_sp = std::make_shared<TypeFormatImpl_Format>(my_format); 10720b57cec5SDimitry Andric if (GetValueAsCString(*format_sp.get(), m_value_str)) { 1073fe6060f1SDimitry Andric if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) { 10740b57cec5SDimitry Andric // The value was gotten successfully, so we consider the value as 10750b57cec5SDimitry Andric // changed if the value string differs 10760b57cec5SDimitry Andric SetValueDidChange(m_old_value_str != m_value_str); 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric } 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric if (m_value_str.empty()) 10820b57cec5SDimitry Andric return nullptr; 10830b57cec5SDimitry Andric return m_value_str.c_str(); 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric // if > 8bytes, 0 is returned. this method should mostly be used to read 10870b57cec5SDimitry Andric // address values out of pointers 10880b57cec5SDimitry Andric uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) { 10890b57cec5SDimitry Andric // If our byte size is zero this is an aggregate type that has children 10900b57cec5SDimitry Andric if (CanProvideValue()) { 10910b57cec5SDimitry Andric Scalar scalar; 10920b57cec5SDimitry Andric if (ResolveValue(scalar)) { 10930b57cec5SDimitry Andric if (success) 10940b57cec5SDimitry Andric *success = true; 10955ffd83dbSDimitry Andric scalar.MakeUnsigned(); 10960b57cec5SDimitry Andric return scalar.ULongLong(fail_value); 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric // fallthrough, otherwise... 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric if (success) 11020b57cec5SDimitry Andric *success = false; 11030b57cec5SDimitry Andric return fail_value; 11040b57cec5SDimitry Andric } 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) { 11070b57cec5SDimitry Andric // If our byte size is zero this is an aggregate type that has children 11080b57cec5SDimitry Andric if (CanProvideValue()) { 11090b57cec5SDimitry Andric Scalar scalar; 11100b57cec5SDimitry Andric if (ResolveValue(scalar)) { 11110b57cec5SDimitry Andric if (success) 11120b57cec5SDimitry Andric *success = true; 11135ffd83dbSDimitry Andric scalar.MakeSigned(); 11140b57cec5SDimitry Andric return scalar.SLongLong(fail_value); 11150b57cec5SDimitry Andric } 11160b57cec5SDimitry Andric // fallthrough, otherwise... 11170b57cec5SDimitry Andric } 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric if (success) 11200b57cec5SDimitry Andric *success = false; 11210b57cec5SDimitry Andric return fail_value; 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric 1124*0fca6ea1SDimitry Andric llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() { 1125*0fca6ea1SDimitry Andric // Make sure the type can be converted to an APSInt. 1126*0fca6ea1SDimitry Andric if (!GetCompilerType().IsInteger() && 1127*0fca6ea1SDimitry Andric !GetCompilerType().IsScopedEnumerationType() && 1128*0fca6ea1SDimitry Andric !GetCompilerType().IsEnumerationType() && 1129*0fca6ea1SDimitry Andric !GetCompilerType().IsPointerType() && 1130*0fca6ea1SDimitry Andric !GetCompilerType().IsNullPtrType() && 1131*0fca6ea1SDimitry Andric !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean()) 1132*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 1133*0fca6ea1SDimitry Andric "type cannot be converted to APSInt", llvm::inconvertibleErrorCode()); 1134*0fca6ea1SDimitry Andric 1135*0fca6ea1SDimitry Andric if (CanProvideValue()) { 1136*0fca6ea1SDimitry Andric Scalar scalar; 1137*0fca6ea1SDimitry Andric if (ResolveValue(scalar)) 1138*0fca6ea1SDimitry Andric return scalar.GetAPSInt(); 1139*0fca6ea1SDimitry Andric } 1140*0fca6ea1SDimitry Andric 1141*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 1142*0fca6ea1SDimitry Andric "error occurred; unable to convert to APSInt", 1143*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 1144*0fca6ea1SDimitry Andric } 1145*0fca6ea1SDimitry Andric 1146*0fca6ea1SDimitry Andric llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() { 1147*0fca6ea1SDimitry Andric if (!GetCompilerType().IsFloat()) 1148*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 1149*0fca6ea1SDimitry Andric "type cannot be converted to APFloat", llvm::inconvertibleErrorCode()); 1150*0fca6ea1SDimitry Andric 1151*0fca6ea1SDimitry Andric if (CanProvideValue()) { 1152*0fca6ea1SDimitry Andric Scalar scalar; 1153*0fca6ea1SDimitry Andric if (ResolveValue(scalar)) 1154*0fca6ea1SDimitry Andric return scalar.GetAPFloat(); 1155*0fca6ea1SDimitry Andric } 1156*0fca6ea1SDimitry Andric 1157*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 1158*0fca6ea1SDimitry Andric "error occurred; unable to convert to APFloat", 1159*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 1160*0fca6ea1SDimitry Andric } 1161*0fca6ea1SDimitry Andric 1162*0fca6ea1SDimitry Andric llvm::Expected<bool> ValueObject::GetValueAsBool() { 1163*0fca6ea1SDimitry Andric CompilerType val_type = GetCompilerType(); 1164*0fca6ea1SDimitry Andric if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() || 1165*0fca6ea1SDimitry Andric val_type.IsPointerType()) { 1166*0fca6ea1SDimitry Andric auto value_or_err = GetValueAsAPSInt(); 1167*0fca6ea1SDimitry Andric if (value_or_err) 1168*0fca6ea1SDimitry Andric return value_or_err->getBoolValue(); 1169*0fca6ea1SDimitry Andric } 1170*0fca6ea1SDimitry Andric if (val_type.IsFloat()) { 1171*0fca6ea1SDimitry Andric auto value_or_err = GetValueAsAPFloat(); 1172*0fca6ea1SDimitry Andric if (value_or_err) 1173*0fca6ea1SDimitry Andric return value_or_err->isNonZero(); 1174*0fca6ea1SDimitry Andric } 1175*0fca6ea1SDimitry Andric if (val_type.IsArrayType()) 1176*0fca6ea1SDimitry Andric return GetAddressOf() != 0; 1177*0fca6ea1SDimitry Andric 1178*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>("type cannot be converted to bool", 1179*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 1180*0fca6ea1SDimitry Andric } 1181*0fca6ea1SDimitry Andric 1182*0fca6ea1SDimitry Andric void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) { 1183*0fca6ea1SDimitry Andric // Verify the current object is an integer object 1184*0fca6ea1SDimitry Andric CompilerType val_type = GetCompilerType(); 1185*0fca6ea1SDimitry Andric if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() && 1186*0fca6ea1SDimitry Andric !val_type.IsFloat() && !val_type.IsPointerType() && 1187*0fca6ea1SDimitry Andric !val_type.IsScalarType()) { 1188*0fca6ea1SDimitry Andric error.SetErrorString("current value object is not an integer objet"); 1189*0fca6ea1SDimitry Andric return; 1190*0fca6ea1SDimitry Andric } 1191*0fca6ea1SDimitry Andric 1192*0fca6ea1SDimitry Andric // Verify the current object is not actually associated with any program 1193*0fca6ea1SDimitry Andric // variable. 1194*0fca6ea1SDimitry Andric if (GetVariable()) { 1195*0fca6ea1SDimitry Andric error.SetErrorString("current value object is not a temporary object"); 1196*0fca6ea1SDimitry Andric return; 1197*0fca6ea1SDimitry Andric } 1198*0fca6ea1SDimitry Andric 1199*0fca6ea1SDimitry Andric // Verify the proposed new value is the right size. 1200*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 1201*0fca6ea1SDimitry Andric uint64_t byte_size = 0; 1202*0fca6ea1SDimitry Andric if (auto temp = GetCompilerType().GetByteSize(target.get())) 1203*0fca6ea1SDimitry Andric byte_size = temp.value(); 1204*0fca6ea1SDimitry Andric if (value.getBitWidth() != byte_size * CHAR_BIT) { 1205*0fca6ea1SDimitry Andric error.SetErrorString( 1206*0fca6ea1SDimitry Andric "illegal argument: new value should be of the same size"); 1207*0fca6ea1SDimitry Andric return; 1208*0fca6ea1SDimitry Andric } 1209*0fca6ea1SDimitry Andric 1210*0fca6ea1SDimitry Andric lldb::DataExtractorSP data_sp; 1211*0fca6ea1SDimitry Andric data_sp->SetData(value.getRawData(), byte_size, 1212*0fca6ea1SDimitry Andric target->GetArchitecture().GetByteOrder()); 1213*0fca6ea1SDimitry Andric data_sp->SetAddressByteSize( 1214*0fca6ea1SDimitry Andric static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize())); 1215*0fca6ea1SDimitry Andric SetData(*data_sp, error); 1216*0fca6ea1SDimitry Andric } 1217*0fca6ea1SDimitry Andric 1218*0fca6ea1SDimitry Andric void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp, 1219*0fca6ea1SDimitry Andric Status &error) { 1220*0fca6ea1SDimitry Andric // Verify the current object is an integer object 1221*0fca6ea1SDimitry Andric CompilerType val_type = GetCompilerType(); 1222*0fca6ea1SDimitry Andric if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() && 1223*0fca6ea1SDimitry Andric !val_type.IsFloat() && !val_type.IsPointerType() && 1224*0fca6ea1SDimitry Andric !val_type.IsScalarType()) { 1225*0fca6ea1SDimitry Andric error.SetErrorString("current value object is not an integer objet"); 1226*0fca6ea1SDimitry Andric return; 1227*0fca6ea1SDimitry Andric } 1228*0fca6ea1SDimitry Andric 1229*0fca6ea1SDimitry Andric // Verify the current object is not actually associated with any program 1230*0fca6ea1SDimitry Andric // variable. 1231*0fca6ea1SDimitry Andric if (GetVariable()) { 1232*0fca6ea1SDimitry Andric error.SetErrorString("current value object is not a temporary object"); 1233*0fca6ea1SDimitry Andric return; 1234*0fca6ea1SDimitry Andric } 1235*0fca6ea1SDimitry Andric 1236*0fca6ea1SDimitry Andric // Verify the proposed new value is the right type. 1237*0fca6ea1SDimitry Andric CompilerType new_val_type = new_val_sp->GetCompilerType(); 1238*0fca6ea1SDimitry Andric if (!new_val_type.IsInteger() && !new_val_type.IsFloat() && 1239*0fca6ea1SDimitry Andric !new_val_type.IsPointerType()) { 1240*0fca6ea1SDimitry Andric error.SetErrorString( 1241*0fca6ea1SDimitry Andric "illegal argument: new value should be of the same size"); 1242*0fca6ea1SDimitry Andric return; 1243*0fca6ea1SDimitry Andric } 1244*0fca6ea1SDimitry Andric 1245*0fca6ea1SDimitry Andric if (new_val_type.IsInteger()) { 1246*0fca6ea1SDimitry Andric auto value_or_err = new_val_sp->GetValueAsAPSInt(); 1247*0fca6ea1SDimitry Andric if (value_or_err) 1248*0fca6ea1SDimitry Andric SetValueFromInteger(*value_or_err, error); 1249*0fca6ea1SDimitry Andric else 1250*0fca6ea1SDimitry Andric error.SetErrorString("error getting APSInt from new_val_sp"); 1251*0fca6ea1SDimitry Andric } else if (new_val_type.IsFloat()) { 1252*0fca6ea1SDimitry Andric auto value_or_err = new_val_sp->GetValueAsAPFloat(); 1253*0fca6ea1SDimitry Andric if (value_or_err) 1254*0fca6ea1SDimitry Andric SetValueFromInteger(value_or_err->bitcastToAPInt(), error); 1255*0fca6ea1SDimitry Andric else 1256*0fca6ea1SDimitry Andric error.SetErrorString("error getting APFloat from new_val_sp"); 1257*0fca6ea1SDimitry Andric } else if (new_val_type.IsPointerType()) { 1258*0fca6ea1SDimitry Andric bool success = true; 1259*0fca6ea1SDimitry Andric uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success); 1260*0fca6ea1SDimitry Andric if (success) { 1261*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 1262*0fca6ea1SDimitry Andric uint64_t num_bits = 0; 1263*0fca6ea1SDimitry Andric if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get())) 1264*0fca6ea1SDimitry Andric num_bits = temp.value(); 1265*0fca6ea1SDimitry Andric SetValueFromInteger(llvm::APInt(num_bits, int_val), error); 1266*0fca6ea1SDimitry Andric } else 1267*0fca6ea1SDimitry Andric error.SetErrorString("error converting new_val_sp to integer"); 1268*0fca6ea1SDimitry Andric } 1269*0fca6ea1SDimitry Andric } 1270*0fca6ea1SDimitry Andric 12710b57cec5SDimitry Andric // if any more "special cases" are added to 12720b57cec5SDimitry Andric // ValueObject::DumpPrintableRepresentation() please keep this call up to date 12730b57cec5SDimitry Andric // by returning true for your new special cases. We will eventually move to 12740b57cec5SDimitry Andric // checking this call result before trying to display special cases 12750b57cec5SDimitry Andric bool ValueObject::HasSpecialPrintableRepresentation( 12760b57cec5SDimitry Andric ValueObjectRepresentationStyle val_obj_display, Format custom_format) { 12770b57cec5SDimitry Andric Flags flags(GetTypeInfo()); 12780b57cec5SDimitry Andric if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && 12790b57cec5SDimitry Andric val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { 12800b57cec5SDimitry Andric if (IsCStringContainer(true) && 12810b57cec5SDimitry Andric (custom_format == eFormatCString || custom_format == eFormatCharArray || 12820b57cec5SDimitry Andric custom_format == eFormatChar || custom_format == eFormatVectorOfChar)) 12830b57cec5SDimitry Andric return true; 12840b57cec5SDimitry Andric 12850b57cec5SDimitry Andric if (flags.Test(eTypeIsArray)) { 12860b57cec5SDimitry Andric if ((custom_format == eFormatBytes) || 12870b57cec5SDimitry Andric (custom_format == eFormatBytesWithASCII)) 12880b57cec5SDimitry Andric return true; 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric if ((custom_format == eFormatVectorOfChar) || 12910b57cec5SDimitry Andric (custom_format == eFormatVectorOfFloat32) || 12920b57cec5SDimitry Andric (custom_format == eFormatVectorOfFloat64) || 12930b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt16) || 12940b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt32) || 12950b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt64) || 12960b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt8) || 12970b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt128) || 12980b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt16) || 12990b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt32) || 13000b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt64) || 13010b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt8)) 13020b57cec5SDimitry Andric return true; 13030b57cec5SDimitry Andric } 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric return false; 13060b57cec5SDimitry Andric } 13070b57cec5SDimitry Andric 13080b57cec5SDimitry Andric bool ValueObject::DumpPrintableRepresentation( 13090b57cec5SDimitry Andric Stream &s, ValueObjectRepresentationStyle val_obj_display, 13100b57cec5SDimitry Andric Format custom_format, PrintableRepresentationSpecialCases special, 13110b57cec5SDimitry Andric bool do_dump_error) { 13120b57cec5SDimitry Andric 131306c3fb27SDimitry Andric // If the ValueObject has an error, we might end up dumping the type, which 131406c3fb27SDimitry Andric // is useful, but if we don't even have a type, then don't examine the object 131506c3fb27SDimitry Andric // further as that's not meaningful, only the error is. 131606c3fb27SDimitry Andric if (m_error.Fail() && !GetCompilerType().IsValid()) { 131706c3fb27SDimitry Andric if (do_dump_error) 131806c3fb27SDimitry Andric s.Printf("<%s>", m_error.AsCString()); 131906c3fb27SDimitry Andric return false; 132006c3fb27SDimitry Andric } 132106c3fb27SDimitry Andric 13220b57cec5SDimitry Andric Flags flags(GetTypeInfo()); 13230b57cec5SDimitry Andric 13240b57cec5SDimitry Andric bool allow_special = 13250b57cec5SDimitry Andric (special == ValueObject::PrintableRepresentationSpecialCases::eAllow); 13260b57cec5SDimitry Andric const bool only_special = false; 13270b57cec5SDimitry Andric 13280b57cec5SDimitry Andric if (allow_special) { 13290b57cec5SDimitry Andric if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && 13300b57cec5SDimitry Andric val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { 13310b57cec5SDimitry Andric // when being asked to get a printable display an array or pointer type 13320b57cec5SDimitry Andric // directly, try to "do the right thing" 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric if (IsCStringContainer(true) && 13350b57cec5SDimitry Andric (custom_format == eFormatCString || 13360b57cec5SDimitry Andric custom_format == eFormatCharArray || custom_format == eFormatChar || 13370b57cec5SDimitry Andric custom_format == 13380b57cec5SDimitry Andric eFormatVectorOfChar)) // print char[] & char* directly 13390b57cec5SDimitry Andric { 13400b57cec5SDimitry Andric Status error; 134181ad6265SDimitry Andric lldb::WritableDataBufferSP buffer_sp; 13427a6dacacSDimitry Andric std::pair<size_t, bool> read_string = 13437a6dacacSDimitry Andric ReadPointedString(buffer_sp, error, 13447a6dacacSDimitry Andric (custom_format == eFormatVectorOfChar) || 13450b57cec5SDimitry Andric (custom_format == eFormatCharArray)); 13460b57cec5SDimitry Andric lldb_private::formatters::StringPrinter:: 13470b57cec5SDimitry Andric ReadBufferAndDumpToStreamOptions options(*this); 13480b57cec5SDimitry Andric options.SetData(DataExtractor( 13490b57cec5SDimitry Andric buffer_sp, lldb::eByteOrderInvalid, 13500b57cec5SDimitry Andric 8)); // none of this matters for a string - pass some defaults 13510b57cec5SDimitry Andric options.SetStream(&s); 13520b57cec5SDimitry Andric options.SetPrefixToken(nullptr); 13530b57cec5SDimitry Andric options.SetQuote('"'); 13540b57cec5SDimitry Andric options.SetSourceSize(buffer_sp->GetByteSize()); 13550b57cec5SDimitry Andric options.SetIsTruncated(read_string.second); 1356349cc55cSDimitry Andric options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar); 13570b57cec5SDimitry Andric formatters::StringPrinter::ReadBufferAndDumpToStream< 13580b57cec5SDimitry Andric lldb_private::formatters::StringPrinter::StringElementType::ASCII>( 13590b57cec5SDimitry Andric options); 13600b57cec5SDimitry Andric return !error.Fail(); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric if (custom_format == eFormatEnum) 13640b57cec5SDimitry Andric return false; 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric // this only works for arrays, because I have no way to know when the 13670b57cec5SDimitry Andric // pointed memory ends, and no special \0 end of data marker 13680b57cec5SDimitry Andric if (flags.Test(eTypeIsArray)) { 13690b57cec5SDimitry Andric if ((custom_format == eFormatBytes) || 13700b57cec5SDimitry Andric (custom_format == eFormatBytesWithASCII)) { 1371*0fca6ea1SDimitry Andric const size_t count = GetNumChildrenIgnoringErrors(); 13720b57cec5SDimitry Andric 13730b57cec5SDimitry Andric s << '['; 13740b57cec5SDimitry Andric for (size_t low = 0; low < count; low++) { 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andric if (low) 13770b57cec5SDimitry Andric s << ','; 13780b57cec5SDimitry Andric 137906c3fb27SDimitry Andric ValueObjectSP child = GetChildAtIndex(low); 13800b57cec5SDimitry Andric if (!child.get()) { 13810b57cec5SDimitry Andric s << "<invalid child>"; 13820b57cec5SDimitry Andric continue; 13830b57cec5SDimitry Andric } 13840b57cec5SDimitry Andric child->DumpPrintableRepresentation( 13850b57cec5SDimitry Andric s, ValueObject::eValueObjectRepresentationStyleValue, 13860b57cec5SDimitry Andric custom_format); 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric s << ']'; 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric return true; 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric if ((custom_format == eFormatVectorOfChar) || 13950b57cec5SDimitry Andric (custom_format == eFormatVectorOfFloat32) || 13960b57cec5SDimitry Andric (custom_format == eFormatVectorOfFloat64) || 13970b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt16) || 13980b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt32) || 13990b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt64) || 14000b57cec5SDimitry Andric (custom_format == eFormatVectorOfSInt8) || 14010b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt128) || 14020b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt16) || 14030b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt32) || 14040b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt64) || 14050b57cec5SDimitry Andric (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes 14060b57cec5SDimitry Andric // with ASCII or any vector 14070b57cec5SDimitry Andric // format should be printed 14080b57cec5SDimitry Andric // directly 14090b57cec5SDimitry Andric { 1410*0fca6ea1SDimitry Andric const size_t count = GetNumChildrenIgnoringErrors(); 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric Format format = FormatManager::GetSingleItemFormat(custom_format); 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric s << '['; 14150b57cec5SDimitry Andric for (size_t low = 0; low < count; low++) { 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric if (low) 14180b57cec5SDimitry Andric s << ','; 14190b57cec5SDimitry Andric 142006c3fb27SDimitry Andric ValueObjectSP child = GetChildAtIndex(low); 14210b57cec5SDimitry Andric if (!child.get()) { 14220b57cec5SDimitry Andric s << "<invalid child>"; 14230b57cec5SDimitry Andric continue; 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric child->DumpPrintableRepresentation( 14260b57cec5SDimitry Andric s, ValueObject::eValueObjectRepresentationStyleValue, format); 14270b57cec5SDimitry Andric } 14280b57cec5SDimitry Andric 14290b57cec5SDimitry Andric s << ']'; 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric return true; 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric } 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric if ((custom_format == eFormatBoolean) || 14360b57cec5SDimitry Andric (custom_format == eFormatBinary) || (custom_format == eFormatChar) || 14370b57cec5SDimitry Andric (custom_format == eFormatCharPrintable) || 14380b57cec5SDimitry Andric (custom_format == eFormatComplexFloat) || 14390b57cec5SDimitry Andric (custom_format == eFormatDecimal) || (custom_format == eFormatHex) || 14400b57cec5SDimitry Andric (custom_format == eFormatHexUppercase) || 14410b57cec5SDimitry Andric (custom_format == eFormatFloat) || (custom_format == eFormatOctal) || 14420b57cec5SDimitry Andric (custom_format == eFormatOSType) || 14430b57cec5SDimitry Andric (custom_format == eFormatUnicode16) || 14440b57cec5SDimitry Andric (custom_format == eFormatUnicode32) || 14450b57cec5SDimitry Andric (custom_format == eFormatUnsigned) || 14460b57cec5SDimitry Andric (custom_format == eFormatPointer) || 14470b57cec5SDimitry Andric (custom_format == eFormatComplexInteger) || 14480b57cec5SDimitry Andric (custom_format == eFormatComplex) || 14490b57cec5SDimitry Andric (custom_format == eFormatDefault)) // use the [] operator 14500b57cec5SDimitry Andric return false; 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric 14540b57cec5SDimitry Andric if (only_special) 14550b57cec5SDimitry Andric return false; 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric bool var_success = false; 14580b57cec5SDimitry Andric 14590b57cec5SDimitry Andric { 14600b57cec5SDimitry Andric llvm::StringRef str; 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric // this is a local stream that we are using to ensure that the data pointed 14630b57cec5SDimitry Andric // to by cstr survives long enough for us to copy it to its destination - 14640b57cec5SDimitry Andric // it is necessary to have this temporary storage area for cases where our 14650b57cec5SDimitry Andric // desired output is not backed by some other longer-term storage 14660b57cec5SDimitry Andric StreamString strm; 14670b57cec5SDimitry Andric 14680b57cec5SDimitry Andric if (custom_format != eFormatInvalid) 14690b57cec5SDimitry Andric SetFormat(custom_format); 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric switch (val_obj_display) { 14720b57cec5SDimitry Andric case eValueObjectRepresentationStyleValue: 14730b57cec5SDimitry Andric str = GetValueAsCString(); 14740b57cec5SDimitry Andric break; 14750b57cec5SDimitry Andric 14760b57cec5SDimitry Andric case eValueObjectRepresentationStyleSummary: 14770b57cec5SDimitry Andric str = GetSummaryAsCString(); 14780b57cec5SDimitry Andric break; 14790b57cec5SDimitry Andric 1480*0fca6ea1SDimitry Andric case eValueObjectRepresentationStyleLanguageSpecific: { 1481*0fca6ea1SDimitry Andric llvm::Expected<std::string> desc = GetObjectDescription(); 1482*0fca6ea1SDimitry Andric if (!desc) { 1483*0fca6ea1SDimitry Andric strm << "error: " << toString(desc.takeError()); 1484*0fca6ea1SDimitry Andric str = strm.GetString(); 1485*0fca6ea1SDimitry Andric } else { 1486*0fca6ea1SDimitry Andric strm << *desc; 1487*0fca6ea1SDimitry Andric str = strm.GetString(); 1488*0fca6ea1SDimitry Andric } 1489*0fca6ea1SDimitry Andric } break; 14900b57cec5SDimitry Andric 14910b57cec5SDimitry Andric case eValueObjectRepresentationStyleLocation: 14920b57cec5SDimitry Andric str = GetLocationAsCString(); 14930b57cec5SDimitry Andric break; 14940b57cec5SDimitry Andric 14950b57cec5SDimitry Andric case eValueObjectRepresentationStyleChildrenCount: 1496*0fca6ea1SDimitry Andric strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildrenIgnoringErrors()); 14970b57cec5SDimitry Andric str = strm.GetString(); 14980b57cec5SDimitry Andric break; 14990b57cec5SDimitry Andric 15000b57cec5SDimitry Andric case eValueObjectRepresentationStyleType: 15010b57cec5SDimitry Andric str = GetTypeName().GetStringRef(); 15020b57cec5SDimitry Andric break; 15030b57cec5SDimitry Andric 15040b57cec5SDimitry Andric case eValueObjectRepresentationStyleName: 15050b57cec5SDimitry Andric str = GetName().GetStringRef(); 15060b57cec5SDimitry Andric break; 15070b57cec5SDimitry Andric 15080b57cec5SDimitry Andric case eValueObjectRepresentationStyleExpressionPath: 15095ffd83dbSDimitry Andric GetExpressionPath(strm); 15100b57cec5SDimitry Andric str = strm.GetString(); 15110b57cec5SDimitry Andric break; 15120b57cec5SDimitry Andric } 15130b57cec5SDimitry Andric 1514*0fca6ea1SDimitry Andric // If the requested display style produced no output, try falling back to 1515*0fca6ea1SDimitry Andric // alternative presentations. 15160b57cec5SDimitry Andric if (str.empty()) { 15170b57cec5SDimitry Andric if (val_obj_display == eValueObjectRepresentationStyleValue) 15180b57cec5SDimitry Andric str = GetSummaryAsCString(); 15190b57cec5SDimitry Andric else if (val_obj_display == eValueObjectRepresentationStyleSummary) { 15200b57cec5SDimitry Andric if (!CanProvideValue()) { 15210b57cec5SDimitry Andric strm.Printf("%s @ %s", GetTypeName().AsCString(), 15220b57cec5SDimitry Andric GetLocationAsCString()); 15230b57cec5SDimitry Andric str = strm.GetString(); 15240b57cec5SDimitry Andric } else 15250b57cec5SDimitry Andric str = GetValueAsCString(); 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric if (!str.empty()) 15300b57cec5SDimitry Andric s << str; 15310b57cec5SDimitry Andric else { 153206c3fb27SDimitry Andric // We checked for errors at the start, but do it again here in case 153306c3fb27SDimitry Andric // realizing the value for dumping produced an error. 15340b57cec5SDimitry Andric if (m_error.Fail()) { 15350b57cec5SDimitry Andric if (do_dump_error) 15360b57cec5SDimitry Andric s.Printf("<%s>", m_error.AsCString()); 15370b57cec5SDimitry Andric else 15380b57cec5SDimitry Andric return false; 15390b57cec5SDimitry Andric } else if (val_obj_display == eValueObjectRepresentationStyleSummary) 15400b57cec5SDimitry Andric s.PutCString("<no summary available>"); 15410b57cec5SDimitry Andric else if (val_obj_display == eValueObjectRepresentationStyleValue) 15420b57cec5SDimitry Andric s.PutCString("<no value available>"); 15430b57cec5SDimitry Andric else if (val_obj_display == 15440b57cec5SDimitry Andric eValueObjectRepresentationStyleLanguageSpecific) 15450b57cec5SDimitry Andric s.PutCString("<not a valid Objective-C object>"); // edit this if we 15460b57cec5SDimitry Andric // have other runtimes 15470b57cec5SDimitry Andric // that support a 15480b57cec5SDimitry Andric // description 15490b57cec5SDimitry Andric else 15500b57cec5SDimitry Andric s.PutCString("<no printable representation>"); 15510b57cec5SDimitry Andric } 15520b57cec5SDimitry Andric 15530b57cec5SDimitry Andric // we should only return false here if we could not do *anything* even if 15540b57cec5SDimitry Andric // we have an error message as output, that's a success from our callers' 15550b57cec5SDimitry Andric // perspective, so return true 15560b57cec5SDimitry Andric var_success = true; 15570b57cec5SDimitry Andric 15580b57cec5SDimitry Andric if (custom_format != eFormatInvalid) 15590b57cec5SDimitry Andric SetFormat(eFormatDefault); 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andric return var_success; 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric addr_t ValueObject::GetAddressOf(bool scalar_is_load_address, 15660b57cec5SDimitry Andric AddressType *address_type) { 15670b57cec5SDimitry Andric // Can't take address of a bitfield 15680b57cec5SDimitry Andric if (IsBitfield()) 15690b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) 15720b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric switch (m_value.GetValueType()) { 1575fe6060f1SDimitry Andric case Value::ValueType::Invalid: 1576fe6060f1SDimitry Andric return LLDB_INVALID_ADDRESS; 1577fe6060f1SDimitry Andric case Value::ValueType::Scalar: 15780b57cec5SDimitry Andric if (scalar_is_load_address) { 15790b57cec5SDimitry Andric if (address_type) 15800b57cec5SDimitry Andric *address_type = eAddressTypeLoad; 15810b57cec5SDimitry Andric return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric break; 15840b57cec5SDimitry Andric 1585fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 1586fe6060f1SDimitry Andric case Value::ValueType::FileAddress: { 15870b57cec5SDimitry Andric if (address_type) 15880b57cec5SDimitry Andric *address_type = m_value.GetValueAddressType(); 15890b57cec5SDimitry Andric return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 15900b57cec5SDimitry Andric } break; 1591fe6060f1SDimitry Andric case Value::ValueType::HostAddress: { 15920b57cec5SDimitry Andric if (address_type) 15930b57cec5SDimitry Andric *address_type = m_value.GetValueAddressType(); 15940b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 15950b57cec5SDimitry Andric } break; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric if (address_type) 15980b57cec5SDimitry Andric *address_type = eAddressTypeInvalid; 15990b57cec5SDimitry Andric return LLDB_INVALID_ADDRESS; 16000b57cec5SDimitry Andric } 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric addr_t ValueObject::GetPointerValue(AddressType *address_type) { 16030b57cec5SDimitry Andric addr_t address = LLDB_INVALID_ADDRESS; 16040b57cec5SDimitry Andric if (address_type) 16050b57cec5SDimitry Andric *address_type = eAddressTypeInvalid; 16060b57cec5SDimitry Andric 16070b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) 16080b57cec5SDimitry Andric return address; 16090b57cec5SDimitry Andric 16100b57cec5SDimitry Andric switch (m_value.GetValueType()) { 1611fe6060f1SDimitry Andric case Value::ValueType::Invalid: 1612fe6060f1SDimitry Andric return LLDB_INVALID_ADDRESS; 1613fe6060f1SDimitry Andric case Value::ValueType::Scalar: 16140b57cec5SDimitry Andric address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 16150b57cec5SDimitry Andric break; 16160b57cec5SDimitry Andric 1617fe6060f1SDimitry Andric case Value::ValueType::HostAddress: 1618fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 1619fe6060f1SDimitry Andric case Value::ValueType::FileAddress: { 16200b57cec5SDimitry Andric lldb::offset_t data_offset = 0; 16215ffd83dbSDimitry Andric address = m_data.GetAddress(&data_offset); 16220b57cec5SDimitry Andric } break; 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric 16250b57cec5SDimitry Andric if (address_type) 16260b57cec5SDimitry Andric *address_type = GetAddressTypeOfChildren(); 16270b57cec5SDimitry Andric 16280b57cec5SDimitry Andric return address; 16290b57cec5SDimitry Andric } 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric bool ValueObject::SetValueFromCString(const char *value_str, Status &error) { 16320b57cec5SDimitry Andric error.Clear(); 16330b57cec5SDimitry Andric // Make sure our value is up to date first so that our location and location 16340b57cec5SDimitry Andric // type is valid. 16350b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) { 16360b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 16370b57cec5SDimitry Andric return false; 16380b57cec5SDimitry Andric } 16390b57cec5SDimitry Andric 16400b57cec5SDimitry Andric uint64_t count = 0; 16410b57cec5SDimitry Andric const Encoding encoding = GetCompilerType().GetEncoding(count); 16420b57cec5SDimitry Andric 164381ad6265SDimitry Andric const size_t byte_size = GetByteSize().value_or(0); 16440b57cec5SDimitry Andric 16450b57cec5SDimitry Andric Value::ValueType value_type = m_value.GetValueType(); 16460b57cec5SDimitry Andric 1647fe6060f1SDimitry Andric if (value_type == Value::ValueType::Scalar) { 16480b57cec5SDimitry Andric // If the value is already a scalar, then let the scalar change itself: 16490b57cec5SDimitry Andric m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size); 16500b57cec5SDimitry Andric } else if (byte_size <= 16) { 16510b57cec5SDimitry Andric // If the value fits in a scalar, then make a new scalar and again let the 16520b57cec5SDimitry Andric // scalar code do the conversion, then figure out where to put the new 16530b57cec5SDimitry Andric // value. 16540b57cec5SDimitry Andric Scalar new_scalar; 16550b57cec5SDimitry Andric error = new_scalar.SetValueFromCString(value_str, encoding, byte_size); 16560b57cec5SDimitry Andric if (error.Success()) { 16570b57cec5SDimitry Andric switch (value_type) { 1658fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: { 16590b57cec5SDimitry Andric // If it is a load address, then the scalar value is the storage 16600b57cec5SDimitry Andric // location of the data, and we have to shove this value down to that 16610b57cec5SDimitry Andric // load location. 16620b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 16630b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 16640b57cec5SDimitry Andric if (process) { 16650b57cec5SDimitry Andric addr_t target_addr = 16660b57cec5SDimitry Andric m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 16670b57cec5SDimitry Andric size_t bytes_written = process->WriteScalarToMemory( 16680b57cec5SDimitry Andric target_addr, new_scalar, byte_size, error); 16690b57cec5SDimitry Andric if (!error.Success()) 16700b57cec5SDimitry Andric return false; 16710b57cec5SDimitry Andric if (bytes_written != byte_size) { 16720b57cec5SDimitry Andric error.SetErrorString("unable to write value to memory"); 16730b57cec5SDimitry Andric return false; 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric } break; 1677fe6060f1SDimitry Andric case Value::ValueType::HostAddress: { 16780b57cec5SDimitry Andric // If it is a host address, then we stuff the scalar as a DataBuffer 16790b57cec5SDimitry Andric // into the Value's data. 16800b57cec5SDimitry Andric DataExtractor new_data; 16810b57cec5SDimitry Andric new_data.SetByteOrder(m_data.GetByteOrder()); 16820b57cec5SDimitry Andric 16830b57cec5SDimitry Andric DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); 16840b57cec5SDimitry Andric m_data.SetData(buffer_sp, 0); 16850b57cec5SDimitry Andric bool success = new_scalar.GetData(new_data); 16860b57cec5SDimitry Andric if (success) { 16870b57cec5SDimitry Andric new_data.CopyByteOrderedData( 16880b57cec5SDimitry Andric 0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()), 16890b57cec5SDimitry Andric byte_size, m_data.GetByteOrder()); 16900b57cec5SDimitry Andric } 16910b57cec5SDimitry Andric m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric } break; 1694fe6060f1SDimitry Andric case Value::ValueType::Invalid: 1695fe6060f1SDimitry Andric error.SetErrorString("invalid location"); 1696fe6060f1SDimitry Andric return false; 1697fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 1698fe6060f1SDimitry Andric case Value::ValueType::Scalar: 16990b57cec5SDimitry Andric break; 17000b57cec5SDimitry Andric } 17010b57cec5SDimitry Andric } else { 17020b57cec5SDimitry Andric return false; 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric } else { 17050b57cec5SDimitry Andric // We don't support setting things bigger than a scalar at present. 17060b57cec5SDimitry Andric error.SetErrorString("unable to write aggregate data type"); 17070b57cec5SDimitry Andric return false; 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric // If we have reached this point, then we have successfully changed the 17110b57cec5SDimitry Andric // value. 17120b57cec5SDimitry Andric SetNeedsUpdate(); 17130b57cec5SDimitry Andric return true; 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric 17160b57cec5SDimitry Andric bool ValueObject::GetDeclaration(Declaration &decl) { 17170b57cec5SDimitry Andric decl.Clear(); 17180b57cec5SDimitry Andric return false; 17190b57cec5SDimitry Andric } 17200b57cec5SDimitry Andric 17210b57cec5SDimitry Andric void ValueObject::AddSyntheticChild(ConstString key, 17220b57cec5SDimitry Andric ValueObject *valobj) { 17230b57cec5SDimitry Andric m_synthetic_children[key] = valobj; 17240b57cec5SDimitry Andric } 17250b57cec5SDimitry Andric 17260b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const { 17270b57cec5SDimitry Andric ValueObjectSP synthetic_child_sp; 17280b57cec5SDimitry Andric std::map<ConstString, ValueObject *>::const_iterator pos = 17290b57cec5SDimitry Andric m_synthetic_children.find(key); 17300b57cec5SDimitry Andric if (pos != m_synthetic_children.end()) 17310b57cec5SDimitry Andric synthetic_child_sp = pos->second->GetSP(); 17320b57cec5SDimitry Andric return synthetic_child_sp; 17330b57cec5SDimitry Andric } 17340b57cec5SDimitry Andric 17350b57cec5SDimitry Andric bool ValueObject::IsPossibleDynamicType() { 17360b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 17370b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 17380b57cec5SDimitry Andric if (process) 17390b57cec5SDimitry Andric return process->IsPossibleDynamicValue(*this); 17400b57cec5SDimitry Andric else 17410b57cec5SDimitry Andric return GetCompilerType().IsPossibleDynamicType(nullptr, true, true); 17420b57cec5SDimitry Andric } 17430b57cec5SDimitry Andric 17440b57cec5SDimitry Andric bool ValueObject::IsRuntimeSupportValue() { 17450b57cec5SDimitry Andric Process *process(GetProcessSP().get()); 17460b57cec5SDimitry Andric if (!process) 17470b57cec5SDimitry Andric return false; 17480b57cec5SDimitry Andric 1749fe6060f1SDimitry Andric // We trust that the compiler did the right thing and marked runtime support 17500b57cec5SDimitry Andric // values as artificial. 17510b57cec5SDimitry Andric if (!GetVariable() || !GetVariable()->IsArtificial()) 17520b57cec5SDimitry Andric return false; 17530b57cec5SDimitry Andric 17549dba64beSDimitry Andric if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage())) 17555ffd83dbSDimitry Andric if (runtime->IsAllowedRuntimeValue(GetName())) 17560b57cec5SDimitry Andric return false; 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric return true; 17590b57cec5SDimitry Andric } 17600b57cec5SDimitry Andric 17610b57cec5SDimitry Andric bool ValueObject::IsNilReference() { 17620b57cec5SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { 17630b57cec5SDimitry Andric return language->IsNilReference(*this); 17640b57cec5SDimitry Andric } 17650b57cec5SDimitry Andric return false; 17660b57cec5SDimitry Andric } 17670b57cec5SDimitry Andric 17680b57cec5SDimitry Andric bool ValueObject::IsUninitializedReference() { 17690b57cec5SDimitry Andric if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { 17700b57cec5SDimitry Andric return language->IsUninitializedReference(*this); 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric return false; 17730b57cec5SDimitry Andric } 17740b57cec5SDimitry Andric 17750b57cec5SDimitry Andric // This allows you to create an array member using and index that doesn't not 17760b57cec5SDimitry Andric // fall in the normal bounds of the array. Many times structure can be defined 17770b57cec5SDimitry Andric // as: struct Collection { 17780b57cec5SDimitry Andric // uint32_t item_count; 17790b57cec5SDimitry Andric // Item item_array[0]; 17800b57cec5SDimitry Andric // }; 17810b57cec5SDimitry Andric // The size of the "item_array" is 1, but many times in practice there are more 17820b57cec5SDimitry Andric // items in "item_array". 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index, 17850b57cec5SDimitry Andric bool can_create) { 1786*0fca6ea1SDimitry Andric ValueObjectSP synthetic_child_sp; 1787*0fca6ea1SDimitry Andric if (IsPointerType() || IsArrayType()) { 1788e8d8bef9SDimitry Andric std::string index_str = llvm::formatv("[{0}]", index); 17890b57cec5SDimitry Andric ConstString index_const_str(index_str); 17900b57cec5SDimitry Andric // Check if we have already created a synthetic array member in this valid 17910b57cec5SDimitry Andric // object. If we have we will re-use it. 1792*0fca6ea1SDimitry Andric synthetic_child_sp = GetSyntheticChild(index_const_str); 1793*0fca6ea1SDimitry Andric if (!synthetic_child_sp) { 1794*0fca6ea1SDimitry Andric ValueObject *synthetic_child; 17950b57cec5SDimitry Andric // We haven't made a synthetic array member for INDEX yet, so lets make 17960b57cec5SDimitry Andric // one and cache it for any future reference. 1797*0fca6ea1SDimitry Andric synthetic_child = CreateSyntheticArrayMember(index); 17980b57cec5SDimitry Andric 1799*0fca6ea1SDimitry Andric // Cache the value if we got one back... 1800*0fca6ea1SDimitry Andric if (synthetic_child) { 18010b57cec5SDimitry Andric AddSyntheticChild(index_const_str, synthetic_child); 1802*0fca6ea1SDimitry Andric synthetic_child_sp = synthetic_child->GetSP(); 18030b57cec5SDimitry Andric synthetic_child_sp->SetName(ConstString(index_str)); 1804fe6060f1SDimitry Andric synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true; 1805*0fca6ea1SDimitry Andric } 1806*0fca6ea1SDimitry Andric } 1807*0fca6ea1SDimitry Andric } 18080b57cec5SDimitry Andric return synthetic_child_sp; 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric 18110b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to, 18120b57cec5SDimitry Andric bool can_create) { 1813*0fca6ea1SDimitry Andric ValueObjectSP synthetic_child_sp; 1814*0fca6ea1SDimitry Andric if (IsScalarType()) { 1815e8d8bef9SDimitry Andric std::string index_str = llvm::formatv("[{0}-{1}]", from, to); 18160b57cec5SDimitry Andric ConstString index_const_str(index_str); 18170b57cec5SDimitry Andric // Check if we have already created a synthetic array member in this valid 18180b57cec5SDimitry Andric // object. If we have we will re-use it. 1819*0fca6ea1SDimitry Andric synthetic_child_sp = GetSyntheticChild(index_const_str); 1820*0fca6ea1SDimitry Andric if (!synthetic_child_sp) { 18210b57cec5SDimitry Andric uint32_t bit_field_size = to - from + 1; 18220b57cec5SDimitry Andric uint32_t bit_field_offset = from; 18230b57cec5SDimitry Andric if (GetDataExtractor().GetByteOrder() == eByteOrderBig) 18240b57cec5SDimitry Andric bit_field_offset = 182581ad6265SDimitry Andric GetByteSize().value_or(0) * 8 - bit_field_size - bit_field_offset; 18260b57cec5SDimitry Andric // We haven't made a synthetic array member for INDEX yet, so lets make 18270b57cec5SDimitry Andric // one and cache it for any future reference. 18280b57cec5SDimitry Andric ValueObjectChild *synthetic_child = new ValueObjectChild( 1829*0fca6ea1SDimitry Andric *this, GetCompilerType(), index_const_str, GetByteSize().value_or(0), 1830*0fca6ea1SDimitry Andric 0, bit_field_size, bit_field_offset, false, false, 1831*0fca6ea1SDimitry Andric eAddressTypeInvalid, 0); 18320b57cec5SDimitry Andric 1833*0fca6ea1SDimitry Andric // Cache the value if we got one back... 1834*0fca6ea1SDimitry Andric if (synthetic_child) { 18350b57cec5SDimitry Andric AddSyntheticChild(index_const_str, synthetic_child); 1836*0fca6ea1SDimitry Andric synthetic_child_sp = synthetic_child->GetSP(); 18370b57cec5SDimitry Andric synthetic_child_sp->SetName(ConstString(index_str)); 1838fe6060f1SDimitry Andric synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true; 1839*0fca6ea1SDimitry Andric } 1840*0fca6ea1SDimitry Andric } 1841*0fca6ea1SDimitry Andric } 18420b57cec5SDimitry Andric return synthetic_child_sp; 18430b57cec5SDimitry Andric } 18440b57cec5SDimitry Andric 18450b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticChildAtOffset( 18460b57cec5SDimitry Andric uint32_t offset, const CompilerType &type, bool can_create, 18470b57cec5SDimitry Andric ConstString name_const_str) { 18480b57cec5SDimitry Andric 18490b57cec5SDimitry Andric ValueObjectSP synthetic_child_sp; 18500b57cec5SDimitry Andric 1851*0fca6ea1SDimitry Andric if (name_const_str.IsEmpty()) { 1852e8d8bef9SDimitry Andric name_const_str.SetString("@" + std::to_string(offset)); 1853*0fca6ea1SDimitry Andric } 18540b57cec5SDimitry Andric 18550b57cec5SDimitry Andric // Check if we have already created a synthetic array member in this valid 18560b57cec5SDimitry Andric // object. If we have we will re-use it. 18570b57cec5SDimitry Andric synthetic_child_sp = GetSyntheticChild(name_const_str); 18580b57cec5SDimitry Andric 18590b57cec5SDimitry Andric if (synthetic_child_sp.get()) 18600b57cec5SDimitry Andric return synthetic_child_sp; 18610b57cec5SDimitry Andric 18620b57cec5SDimitry Andric if (!can_create) 1863*0fca6ea1SDimitry Andric return {}; 18640b57cec5SDimitry Andric 18650b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1866bdd1243dSDimitry Andric std::optional<uint64_t> size = 18670b57cec5SDimitry Andric type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 18680b57cec5SDimitry Andric if (!size) 1869*0fca6ea1SDimitry Andric return {}; 18700b57cec5SDimitry Andric ValueObjectChild *synthetic_child = 18710b57cec5SDimitry Andric new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0, 18720b57cec5SDimitry Andric false, false, eAddressTypeInvalid, 0); 18730b57cec5SDimitry Andric if (synthetic_child) { 18740b57cec5SDimitry Andric AddSyntheticChild(name_const_str, synthetic_child); 18750b57cec5SDimitry Andric synthetic_child_sp = synthetic_child->GetSP(); 18760b57cec5SDimitry Andric synthetic_child_sp->SetName(name_const_str); 1877fe6060f1SDimitry Andric synthetic_child_sp->m_flags.m_is_child_at_offset = true; 18780b57cec5SDimitry Andric } 18790b57cec5SDimitry Andric return synthetic_child_sp; 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset, 18830b57cec5SDimitry Andric const CompilerType &type, 18840b57cec5SDimitry Andric bool can_create, 18850b57cec5SDimitry Andric ConstString name_const_str) { 18860b57cec5SDimitry Andric ValueObjectSP synthetic_child_sp; 18870b57cec5SDimitry Andric 18880b57cec5SDimitry Andric if (name_const_str.IsEmpty()) { 18890b57cec5SDimitry Andric char name_str[128]; 18900b57cec5SDimitry Andric snprintf(name_str, sizeof(name_str), "base%s@%i", 18910b57cec5SDimitry Andric type.GetTypeName().AsCString("<unknown>"), offset); 18920b57cec5SDimitry Andric name_const_str.SetCString(name_str); 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric // Check if we have already created a synthetic array member in this valid 18960b57cec5SDimitry Andric // object. If we have we will re-use it. 18970b57cec5SDimitry Andric synthetic_child_sp = GetSyntheticChild(name_const_str); 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric if (synthetic_child_sp.get()) 19000b57cec5SDimitry Andric return synthetic_child_sp; 19010b57cec5SDimitry Andric 19020b57cec5SDimitry Andric if (!can_create) 1903*0fca6ea1SDimitry Andric return {}; 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric const bool is_base_class = true; 19060b57cec5SDimitry Andric 19070b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 1908bdd1243dSDimitry Andric std::optional<uint64_t> size = 19090b57cec5SDimitry Andric type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); 19100b57cec5SDimitry Andric if (!size) 1911*0fca6ea1SDimitry Andric return {}; 19120b57cec5SDimitry Andric ValueObjectChild *synthetic_child = 19130b57cec5SDimitry Andric new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0, 19140b57cec5SDimitry Andric is_base_class, false, eAddressTypeInvalid, 0); 19150b57cec5SDimitry Andric if (synthetic_child) { 19160b57cec5SDimitry Andric AddSyntheticChild(name_const_str, synthetic_child); 19170b57cec5SDimitry Andric synthetic_child_sp = synthetic_child->GetSP(); 19180b57cec5SDimitry Andric synthetic_child_sp->SetName(name_const_str); 19190b57cec5SDimitry Andric } 19200b57cec5SDimitry Andric return synthetic_child_sp; 19210b57cec5SDimitry Andric } 19220b57cec5SDimitry Andric 19230b57cec5SDimitry Andric // your expression path needs to have a leading . or -> (unless it somehow 19240b57cec5SDimitry Andric // "looks like" an array, in which case it has a leading [ symbol). while the [ 19250b57cec5SDimitry Andric // is meaningful and should be shown to the user, . and -> are just parser 19260b57cec5SDimitry Andric // design, but by no means added information for the user.. strip them off 19270b57cec5SDimitry Andric static const char *SkipLeadingExpressionPathSeparators(const char *expression) { 19280b57cec5SDimitry Andric if (!expression || !expression[0]) 19290b57cec5SDimitry Andric return expression; 19300b57cec5SDimitry Andric if (expression[0] == '.') 19310b57cec5SDimitry Andric return expression + 1; 19320b57cec5SDimitry Andric if (expression[0] == '-' && expression[1] == '>') 19330b57cec5SDimitry Andric return expression + 2; 19340b57cec5SDimitry Andric return expression; 19350b57cec5SDimitry Andric } 19360b57cec5SDimitry Andric 19370b57cec5SDimitry Andric ValueObjectSP 19380b57cec5SDimitry Andric ValueObject::GetSyntheticExpressionPathChild(const char *expression, 19390b57cec5SDimitry Andric bool can_create) { 1940*0fca6ea1SDimitry Andric ValueObjectSP synthetic_child_sp; 19410b57cec5SDimitry Andric ConstString name_const_string(expression); 19420b57cec5SDimitry Andric // Check if we have already created a synthetic array member in this valid 19430b57cec5SDimitry Andric // object. If we have we will re-use it. 1944*0fca6ea1SDimitry Andric synthetic_child_sp = GetSyntheticChild(name_const_string); 1945*0fca6ea1SDimitry Andric if (!synthetic_child_sp) { 19460b57cec5SDimitry Andric // We haven't made a synthetic array member for expression yet, so lets 19470b57cec5SDimitry Andric // make one and cache it for any future reference. 1948*0fca6ea1SDimitry Andric synthetic_child_sp = GetValueForExpressionPath( 1949*0fca6ea1SDimitry Andric expression, nullptr, nullptr, 1950*0fca6ea1SDimitry Andric GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal( 1951*0fca6ea1SDimitry Andric GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 1952*0fca6ea1SDimitry Andric None)); 19530b57cec5SDimitry Andric 1954*0fca6ea1SDimitry Andric // Cache the value if we got one back... 1955*0fca6ea1SDimitry Andric if (synthetic_child_sp.get()) { 19560b57cec5SDimitry Andric // FIXME: this causes a "real" child to end up with its name changed to 19570b57cec5SDimitry Andric // the contents of expression 1958*0fca6ea1SDimitry Andric AddSyntheticChild(name_const_string, synthetic_child_sp.get()); 1959*0fca6ea1SDimitry Andric synthetic_child_sp->SetName( 19600b57cec5SDimitry Andric ConstString(SkipLeadingExpressionPathSeparators(expression))); 1961*0fca6ea1SDimitry Andric } 1962*0fca6ea1SDimitry Andric } 1963*0fca6ea1SDimitry Andric return synthetic_child_sp; 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric 19665ffd83dbSDimitry Andric void ValueObject::CalculateSyntheticValue() { 19670b57cec5SDimitry Andric TargetSP target_sp(GetTargetSP()); 19680b57cec5SDimitry Andric if (target_sp && !target_sp->GetEnableSyntheticValue()) { 19690b57cec5SDimitry Andric m_synthetic_value = nullptr; 19700b57cec5SDimitry Andric return; 19710b57cec5SDimitry Andric } 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp); 19740b57cec5SDimitry Andric 19750b57cec5SDimitry Andric if (!UpdateFormatsIfNeeded() && m_synthetic_value) 19760b57cec5SDimitry Andric return; 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric if (m_synthetic_children_sp.get() == nullptr) 19790b57cec5SDimitry Andric return; 19800b57cec5SDimitry Andric 19810b57cec5SDimitry Andric if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value) 19820b57cec5SDimitry Andric return; 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp); 19850b57cec5SDimitry Andric } 19860b57cec5SDimitry Andric 19870b57cec5SDimitry Andric void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) { 19880b57cec5SDimitry Andric if (use_dynamic == eNoDynamicValues) 19890b57cec5SDimitry Andric return; 19900b57cec5SDimitry Andric 19910b57cec5SDimitry Andric if (!m_dynamic_value && !IsDynamic()) { 19920b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 19930b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 19940b57cec5SDimitry Andric if (process && process->IsPossibleDynamicValue(*this)) { 19950b57cec5SDimitry Andric ClearDynamicTypeInformation(); 19960b57cec5SDimitry Andric m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic); 19970b57cec5SDimitry Andric } 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) { 20020b57cec5SDimitry Andric if (use_dynamic == eNoDynamicValues) 20030b57cec5SDimitry Andric return ValueObjectSP(); 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric if (!IsDynamic() && m_dynamic_value == nullptr) { 20060b57cec5SDimitry Andric CalculateDynamicValue(use_dynamic); 20070b57cec5SDimitry Andric } 200806c3fb27SDimitry Andric if (m_dynamic_value && m_dynamic_value->GetError().Success()) 20090b57cec5SDimitry Andric return m_dynamic_value->GetSP(); 20100b57cec5SDimitry Andric else 20110b57cec5SDimitry Andric return ValueObjectSP(); 20120b57cec5SDimitry Andric } 20130b57cec5SDimitry Andric 20145ffd83dbSDimitry Andric ValueObjectSP ValueObject::GetSyntheticValue() { 20155ffd83dbSDimitry Andric CalculateSyntheticValue(); 20160b57cec5SDimitry Andric 20170b57cec5SDimitry Andric if (m_synthetic_value) 20180b57cec5SDimitry Andric return m_synthetic_value->GetSP(); 20190b57cec5SDimitry Andric else 20200b57cec5SDimitry Andric return ValueObjectSP(); 20210b57cec5SDimitry Andric } 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric bool ValueObject::HasSyntheticValue() { 20240b57cec5SDimitry Andric UpdateFormatsIfNeeded(); 20250b57cec5SDimitry Andric 20260b57cec5SDimitry Andric if (m_synthetic_children_sp.get() == nullptr) 20270b57cec5SDimitry Andric return false; 20280b57cec5SDimitry Andric 20295ffd83dbSDimitry Andric CalculateSyntheticValue(); 20300b57cec5SDimitry Andric 20310b57cec5SDimitry Andric return m_synthetic_value != nullptr; 20320b57cec5SDimitry Andric } 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric ValueObject *ValueObject::GetNonBaseClassParent() { 20350b57cec5SDimitry Andric if (GetParent()) { 20360b57cec5SDimitry Andric if (GetParent()->IsBaseClass()) 20370b57cec5SDimitry Andric return GetParent()->GetNonBaseClassParent(); 20380b57cec5SDimitry Andric else 20390b57cec5SDimitry Andric return GetParent(); 20400b57cec5SDimitry Andric } 20410b57cec5SDimitry Andric return nullptr; 20420b57cec5SDimitry Andric } 20430b57cec5SDimitry Andric 20440b57cec5SDimitry Andric bool ValueObject::IsBaseClass(uint32_t &depth) { 20450b57cec5SDimitry Andric if (!IsBaseClass()) { 20460b57cec5SDimitry Andric depth = 0; 20470b57cec5SDimitry Andric return false; 20480b57cec5SDimitry Andric } 20490b57cec5SDimitry Andric if (GetParent()) { 20500b57cec5SDimitry Andric GetParent()->IsBaseClass(depth); 20510b57cec5SDimitry Andric depth = depth + 1; 20520b57cec5SDimitry Andric return true; 20530b57cec5SDimitry Andric } 20540b57cec5SDimitry Andric // TODO: a base of no parent? weird.. 20550b57cec5SDimitry Andric depth = 1; 20560b57cec5SDimitry Andric return true; 20570b57cec5SDimitry Andric } 20580b57cec5SDimitry Andric 20595ffd83dbSDimitry Andric void ValueObject::GetExpressionPath(Stream &s, 20600b57cec5SDimitry Andric GetExpressionPathFormat epformat) { 20610b57cec5SDimitry Andric // synthetic children do not actually "exist" as part of the hierarchy, and 20620b57cec5SDimitry Andric // sometimes they are consed up in ways that don't make sense from an 20630b57cec5SDimitry Andric // underlying language/API standpoint. So, use a special code path here to 20640b57cec5SDimitry Andric // return something that can hopefully be used in expression 2065fe6060f1SDimitry Andric if (m_flags.m_is_synthetic_children_generated) { 20660b57cec5SDimitry Andric UpdateValueIfNeeded(); 20670b57cec5SDimitry Andric 2068fe6060f1SDimitry Andric if (m_value.GetValueType() == Value::ValueType::LoadAddress) { 20690b57cec5SDimitry Andric if (IsPointerOrReferenceType()) { 20700b57cec5SDimitry Andric s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"), 20710b57cec5SDimitry Andric GetValueAsUnsigned(0)); 20720b57cec5SDimitry Andric return; 20730b57cec5SDimitry Andric } else { 20740b57cec5SDimitry Andric uint64_t load_addr = 20750b57cec5SDimitry Andric m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 20760b57cec5SDimitry Andric if (load_addr != LLDB_INVALID_ADDRESS) { 20770b57cec5SDimitry Andric s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"), 20780b57cec5SDimitry Andric load_addr); 20790b57cec5SDimitry Andric return; 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric } 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric if (CanProvideValue()) { 20850b57cec5SDimitry Andric s.Printf("((%s)%s)", GetTypeName().AsCString("void"), 20860b57cec5SDimitry Andric GetValueAsCString()); 20870b57cec5SDimitry Andric return; 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric return; 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric const bool is_deref_of_parent = IsDereferenceOfParent(); 20940b57cec5SDimitry Andric 20950b57cec5SDimitry Andric if (is_deref_of_parent && 20960b57cec5SDimitry Andric epformat == eGetExpressionPathFormatDereferencePointers) { 20970b57cec5SDimitry Andric // this is the original format of GetExpressionPath() producing code like 20980b57cec5SDimitry Andric // *(a_ptr).memberName, which is entirely fine, until you put this into 20990b57cec5SDimitry Andric // StackFrame::GetValueForVariableExpressionPath() which prefers to see 21000b57cec5SDimitry Andric // a_ptr->memberName. the eHonorPointers mode is meant to produce strings 21010b57cec5SDimitry Andric // in this latter format 21020b57cec5SDimitry Andric s.PutCString("*("); 21030b57cec5SDimitry Andric } 21040b57cec5SDimitry Andric 21050b57cec5SDimitry Andric ValueObject *parent = GetParent(); 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric if (parent) 21085ffd83dbSDimitry Andric parent->GetExpressionPath(s, epformat); 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric // if we are a deref_of_parent just because we are synthetic array members 21110b57cec5SDimitry Andric // made up to allow ptr[%d] syntax to work in variable printing, then add our 21120b57cec5SDimitry Andric // name ([%d]) to the expression path 2113fe6060f1SDimitry Andric if (m_flags.m_is_array_item_for_pointer && 21140b57cec5SDimitry Andric epformat == eGetExpressionPathFormatHonorPointers) 21155ffd83dbSDimitry Andric s.PutCString(m_name.GetStringRef()); 21160b57cec5SDimitry Andric 21170b57cec5SDimitry Andric if (!IsBaseClass()) { 21180b57cec5SDimitry Andric if (!is_deref_of_parent) { 21190b57cec5SDimitry Andric ValueObject *non_base_class_parent = GetNonBaseClassParent(); 21200b57cec5SDimitry Andric if (non_base_class_parent && 21210b57cec5SDimitry Andric !non_base_class_parent->GetName().IsEmpty()) { 21220b57cec5SDimitry Andric CompilerType non_base_class_parent_compiler_type = 21230b57cec5SDimitry Andric non_base_class_parent->GetCompilerType(); 21240b57cec5SDimitry Andric if (non_base_class_parent_compiler_type) { 21250b57cec5SDimitry Andric if (parent && parent->IsDereferenceOfParent() && 21260b57cec5SDimitry Andric epformat == eGetExpressionPathFormatHonorPointers) { 21270b57cec5SDimitry Andric s.PutCString("->"); 21280b57cec5SDimitry Andric } else { 21290b57cec5SDimitry Andric const uint32_t non_base_class_parent_type_info = 21300b57cec5SDimitry Andric non_base_class_parent_compiler_type.GetTypeInfo(); 21310b57cec5SDimitry Andric 21320b57cec5SDimitry Andric if (non_base_class_parent_type_info & eTypeIsPointer) { 21330b57cec5SDimitry Andric s.PutCString("->"); 21340b57cec5SDimitry Andric } else if ((non_base_class_parent_type_info & eTypeHasChildren) && 21350b57cec5SDimitry Andric !(non_base_class_parent_type_info & eTypeIsArray)) { 21360b57cec5SDimitry Andric s.PutChar('.'); 21370b57cec5SDimitry Andric } 21380b57cec5SDimitry Andric } 21390b57cec5SDimitry Andric } 21400b57cec5SDimitry Andric } 21410b57cec5SDimitry Andric 21420b57cec5SDimitry Andric const char *name = GetName().GetCString(); 21435ffd83dbSDimitry Andric if (name) 21440b57cec5SDimitry Andric s.PutCString(name); 21450b57cec5SDimitry Andric } 21460b57cec5SDimitry Andric } 21470b57cec5SDimitry Andric 21480b57cec5SDimitry Andric if (is_deref_of_parent && 21490b57cec5SDimitry Andric epformat == eGetExpressionPathFormatDereferencePointers) { 21500b57cec5SDimitry Andric s.PutChar(')'); 21510b57cec5SDimitry Andric } 21520b57cec5SDimitry Andric } 21530b57cec5SDimitry Andric 21540b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath( 21550b57cec5SDimitry Andric llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, 21560b57cec5SDimitry Andric ExpressionPathEndResultType *final_value_type, 21570b57cec5SDimitry Andric const GetValueForExpressionPathOptions &options, 21580b57cec5SDimitry Andric ExpressionPathAftermath *final_task_on_target) { 21590b57cec5SDimitry Andric 2160*0fca6ea1SDimitry Andric ExpressionPathScanEndReason dummy_reason_to_stop = 2161*0fca6ea1SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnknown; 2162*0fca6ea1SDimitry Andric ExpressionPathEndResultType dummy_final_value_type = 2163*0fca6ea1SDimitry Andric ValueObject::eExpressionPathEndResultTypeInvalid; 2164*0fca6ea1SDimitry Andric ExpressionPathAftermath dummy_final_task_on_target = 2165*0fca6ea1SDimitry Andric ValueObject::eExpressionPathAftermathNothing; 21660b57cec5SDimitry Andric 2167*0fca6ea1SDimitry Andric ValueObjectSP ret_val = GetValueForExpressionPath_Impl( 2168*0fca6ea1SDimitry Andric expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, 2169*0fca6ea1SDimitry Andric final_value_type ? final_value_type : &dummy_final_value_type, options, 2170*0fca6ea1SDimitry Andric final_task_on_target ? final_task_on_target 2171*0fca6ea1SDimitry Andric : &dummy_final_task_on_target); 21720b57cec5SDimitry Andric 2173*0fca6ea1SDimitry Andric if (!final_task_on_target || 2174*0fca6ea1SDimitry Andric *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) 2175*0fca6ea1SDimitry Andric return ret_val; 21760b57cec5SDimitry Andric 2177*0fca6ea1SDimitry Andric if (ret_val.get() && 2178*0fca6ea1SDimitry Andric ((final_value_type ? *final_value_type : dummy_final_value_type) == 2179*0fca6ea1SDimitry Andric eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress 2180*0fca6ea1SDimitry Andric // of plain objects 2181*0fca6ea1SDimitry Andric { 2182*0fca6ea1SDimitry Andric if ((final_task_on_target ? *final_task_on_target 2183*0fca6ea1SDimitry Andric : dummy_final_task_on_target) == 2184*0fca6ea1SDimitry Andric ValueObject::eExpressionPathAftermathDereference) { 21850b57cec5SDimitry Andric Status error; 2186*0fca6ea1SDimitry Andric ValueObjectSP final_value = ret_val->Dereference(error); 2187*0fca6ea1SDimitry Andric if (error.Fail() || !final_value.get()) { 21880b57cec5SDimitry Andric if (reason_to_stop) 2189*0fca6ea1SDimitry Andric *reason_to_stop = 2190*0fca6ea1SDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed; 21910b57cec5SDimitry Andric if (final_value_type) 2192*0fca6ea1SDimitry Andric *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; 21930b57cec5SDimitry Andric return ValueObjectSP(); 2194*0fca6ea1SDimitry Andric } else { 2195*0fca6ea1SDimitry Andric if (final_task_on_target) 2196*0fca6ea1SDimitry Andric *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; 2197*0fca6ea1SDimitry Andric return final_value; 2198*0fca6ea1SDimitry Andric } 2199*0fca6ea1SDimitry Andric } 2200*0fca6ea1SDimitry Andric if (*final_task_on_target == 2201*0fca6ea1SDimitry Andric ValueObject::eExpressionPathAftermathTakeAddress) { 2202*0fca6ea1SDimitry Andric Status error; 2203*0fca6ea1SDimitry Andric ValueObjectSP final_value = ret_val->AddressOf(error); 2204*0fca6ea1SDimitry Andric if (error.Fail() || !final_value.get()) { 2205*0fca6ea1SDimitry Andric if (reason_to_stop) 2206*0fca6ea1SDimitry Andric *reason_to_stop = 2207*0fca6ea1SDimitry Andric ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; 2208*0fca6ea1SDimitry Andric if (final_value_type) 2209*0fca6ea1SDimitry Andric *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; 2210*0fca6ea1SDimitry Andric return ValueObjectSP(); 2211*0fca6ea1SDimitry Andric } else { 2212*0fca6ea1SDimitry Andric if (final_task_on_target) 2213*0fca6ea1SDimitry Andric *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; 2214*0fca6ea1SDimitry Andric return final_value; 2215*0fca6ea1SDimitry Andric } 2216*0fca6ea1SDimitry Andric } 2217*0fca6ea1SDimitry Andric } 2218*0fca6ea1SDimitry Andric return ret_val; // final_task_on_target will still have its original value, so 2219*0fca6ea1SDimitry Andric // you know I did not do it 22200b57cec5SDimitry Andric } 22210b57cec5SDimitry Andric 22220b57cec5SDimitry Andric ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( 22230b57cec5SDimitry Andric llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, 22240b57cec5SDimitry Andric ExpressionPathEndResultType *final_result, 22250b57cec5SDimitry Andric const GetValueForExpressionPathOptions &options, 22260b57cec5SDimitry Andric ExpressionPathAftermath *what_next) { 22270b57cec5SDimitry Andric ValueObjectSP root = GetSP(); 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric if (!root) 22300b57cec5SDimitry Andric return nullptr; 22310b57cec5SDimitry Andric 22320b57cec5SDimitry Andric llvm::StringRef remainder = expression; 22330b57cec5SDimitry Andric 22340b57cec5SDimitry Andric while (true) { 22350b57cec5SDimitry Andric llvm::StringRef temp_expression = remainder; 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric CompilerType root_compiler_type = root->GetCompilerType(); 22380b57cec5SDimitry Andric CompilerType pointee_compiler_type; 22390b57cec5SDimitry Andric Flags pointee_compiler_type_info; 22400b57cec5SDimitry Andric 22410b57cec5SDimitry Andric Flags root_compiler_type_info( 22420b57cec5SDimitry Andric root_compiler_type.GetTypeInfo(&pointee_compiler_type)); 22430b57cec5SDimitry Andric if (pointee_compiler_type) 22440b57cec5SDimitry Andric pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); 22450b57cec5SDimitry Andric 22460b57cec5SDimitry Andric if (temp_expression.empty()) { 22470b57cec5SDimitry Andric *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; 22480b57cec5SDimitry Andric return root; 22490b57cec5SDimitry Andric } 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric switch (temp_expression.front()) { 22520b57cec5SDimitry Andric case '-': { 22530b57cec5SDimitry Andric temp_expression = temp_expression.drop_front(); 22540b57cec5SDimitry Andric if (options.m_check_dot_vs_arrow_syntax && 22550b57cec5SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to 22560b57cec5SDimitry Andric // use -> on a 22570b57cec5SDimitry Andric // non-pointer and I 22580b57cec5SDimitry Andric // must catch the error 22590b57cec5SDimitry Andric { 22600b57cec5SDimitry Andric *reason_to_stop = 22610b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; 22620b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 22630b57cec5SDimitry Andric return ValueObjectSP(); 22640b57cec5SDimitry Andric } 22650b57cec5SDimitry Andric if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to 22660b57cec5SDimitry Andric // extract an ObjC IVar 22670b57cec5SDimitry Andric // when this is forbidden 22680b57cec5SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer) && 22690b57cec5SDimitry Andric options.m_no_fragile_ivar) { 22700b57cec5SDimitry Andric *reason_to_stop = 22710b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed; 22720b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 22730b57cec5SDimitry Andric return ValueObjectSP(); 22740b57cec5SDimitry Andric } 22755f757f3fSDimitry Andric if (!temp_expression.starts_with(">")) { 22760b57cec5SDimitry Andric *reason_to_stop = 22770b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; 22780b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 22790b57cec5SDimitry Andric return ValueObjectSP(); 22800b57cec5SDimitry Andric } 22810b57cec5SDimitry Andric } 2282bdd1243dSDimitry Andric [[fallthrough]]; 22830b57cec5SDimitry Andric case '.': // or fallthrough from -> 22840b57cec5SDimitry Andric { 22850b57cec5SDimitry Andric if (options.m_check_dot_vs_arrow_syntax && 22860b57cec5SDimitry Andric temp_expression.front() == '.' && 22870b57cec5SDimitry Andric root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to 22880b57cec5SDimitry Andric // use . on a pointer 22890b57cec5SDimitry Andric // and I must catch the 22900b57cec5SDimitry Andric // error 22910b57cec5SDimitry Andric { 22920b57cec5SDimitry Andric *reason_to_stop = 22930b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; 22940b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 22950b57cec5SDimitry Andric return nullptr; 22960b57cec5SDimitry Andric } 22970b57cec5SDimitry Andric temp_expression = temp_expression.drop_front(); // skip . or > 22980b57cec5SDimitry Andric 22990b57cec5SDimitry Andric size_t next_sep_pos = temp_expression.find_first_of("-.[", 1); 23000b57cec5SDimitry Andric if (next_sep_pos == llvm::StringRef::npos) // if no other separator just 23010b57cec5SDimitry Andric // expand this last layer 23020b57cec5SDimitry Andric { 23035f757f3fSDimitry Andric llvm::StringRef child_name = temp_expression; 23040b57cec5SDimitry Andric ValueObjectSP child_valobj_sp = 230506c3fb27SDimitry Andric root->GetChildMemberWithName(child_name); 23060b57cec5SDimitry Andric 23070b57cec5SDimitry Andric if (child_valobj_sp.get()) // we know we are done, so just return 23080b57cec5SDimitry Andric { 23090b57cec5SDimitry Andric *reason_to_stop = 23100b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString; 23110b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 23120b57cec5SDimitry Andric return child_valobj_sp; 23130b57cec5SDimitry Andric } else { 23140b57cec5SDimitry Andric switch (options.m_synthetic_children_traversal) { 23150b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23160b57cec5SDimitry Andric None: 23170b57cec5SDimitry Andric break; 23180b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23190b57cec5SDimitry Andric FromSynthetic: 23200b57cec5SDimitry Andric if (root->IsSynthetic()) { 23210b57cec5SDimitry Andric child_valobj_sp = root->GetNonSyntheticValue(); 23220b57cec5SDimitry Andric if (child_valobj_sp.get()) 23230b57cec5SDimitry Andric child_valobj_sp = 232406c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 23250b57cec5SDimitry Andric } 23260b57cec5SDimitry Andric break; 23270b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23280b57cec5SDimitry Andric ToSynthetic: 23290b57cec5SDimitry Andric if (!root->IsSynthetic()) { 23300b57cec5SDimitry Andric child_valobj_sp = root->GetSyntheticValue(); 23310b57cec5SDimitry Andric if (child_valobj_sp.get()) 23320b57cec5SDimitry Andric child_valobj_sp = 233306c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric break; 23360b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23370b57cec5SDimitry Andric Both: 23380b57cec5SDimitry Andric if (root->IsSynthetic()) { 23390b57cec5SDimitry Andric child_valobj_sp = root->GetNonSyntheticValue(); 23400b57cec5SDimitry Andric if (child_valobj_sp.get()) 23410b57cec5SDimitry Andric child_valobj_sp = 234206c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 23430b57cec5SDimitry Andric } else { 23440b57cec5SDimitry Andric child_valobj_sp = root->GetSyntheticValue(); 23450b57cec5SDimitry Andric if (child_valobj_sp.get()) 23460b57cec5SDimitry Andric child_valobj_sp = 234706c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 23480b57cec5SDimitry Andric } 23490b57cec5SDimitry Andric break; 23500b57cec5SDimitry Andric } 23510b57cec5SDimitry Andric } 23520b57cec5SDimitry Andric 23530b57cec5SDimitry Andric // if we are here and options.m_no_synthetic_children is true, 23540b57cec5SDimitry Andric // child_valobj_sp is going to be a NULL SP, so we hit the "else" 23550b57cec5SDimitry Andric // branch, and return an error 23560b57cec5SDimitry Andric if (child_valobj_sp.get()) // if it worked, just return 23570b57cec5SDimitry Andric { 23580b57cec5SDimitry Andric *reason_to_stop = 23590b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonEndOfString; 23600b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 23610b57cec5SDimitry Andric return child_valobj_sp; 23620b57cec5SDimitry Andric } else { 23630b57cec5SDimitry Andric *reason_to_stop = 23640b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 23650b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 23660b57cec5SDimitry Andric return nullptr; 23670b57cec5SDimitry Andric } 23680b57cec5SDimitry Andric } else // other layers do expand 23690b57cec5SDimitry Andric { 23700b57cec5SDimitry Andric llvm::StringRef next_separator = temp_expression.substr(next_sep_pos); 23715f757f3fSDimitry Andric llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos); 23720b57cec5SDimitry Andric 23730b57cec5SDimitry Andric ValueObjectSP child_valobj_sp = 237406c3fb27SDimitry Andric root->GetChildMemberWithName(child_name); 23750b57cec5SDimitry Andric if (child_valobj_sp.get()) // store the new root and move on 23760b57cec5SDimitry Andric { 23770b57cec5SDimitry Andric root = child_valobj_sp; 23780b57cec5SDimitry Andric remainder = next_separator; 23790b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 23800b57cec5SDimitry Andric continue; 23810b57cec5SDimitry Andric } else { 23820b57cec5SDimitry Andric switch (options.m_synthetic_children_traversal) { 23830b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23840b57cec5SDimitry Andric None: 23850b57cec5SDimitry Andric break; 23860b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23870b57cec5SDimitry Andric FromSynthetic: 23880b57cec5SDimitry Andric if (root->IsSynthetic()) { 23890b57cec5SDimitry Andric child_valobj_sp = root->GetNonSyntheticValue(); 23900b57cec5SDimitry Andric if (child_valobj_sp.get()) 23910b57cec5SDimitry Andric child_valobj_sp = 239206c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 23930b57cec5SDimitry Andric } 23940b57cec5SDimitry Andric break; 23950b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 23960b57cec5SDimitry Andric ToSynthetic: 23970b57cec5SDimitry Andric if (!root->IsSynthetic()) { 23980b57cec5SDimitry Andric child_valobj_sp = root->GetSyntheticValue(); 23990b57cec5SDimitry Andric if (child_valobj_sp.get()) 24000b57cec5SDimitry Andric child_valobj_sp = 240106c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 24020b57cec5SDimitry Andric } 24030b57cec5SDimitry Andric break; 24040b57cec5SDimitry Andric case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 24050b57cec5SDimitry Andric Both: 24060b57cec5SDimitry Andric if (root->IsSynthetic()) { 24070b57cec5SDimitry Andric child_valobj_sp = root->GetNonSyntheticValue(); 24080b57cec5SDimitry Andric if (child_valobj_sp.get()) 24090b57cec5SDimitry Andric child_valobj_sp = 241006c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 24110b57cec5SDimitry Andric } else { 24120b57cec5SDimitry Andric child_valobj_sp = root->GetSyntheticValue(); 24130b57cec5SDimitry Andric if (child_valobj_sp.get()) 24140b57cec5SDimitry Andric child_valobj_sp = 241506c3fb27SDimitry Andric child_valobj_sp->GetChildMemberWithName(child_name); 24160b57cec5SDimitry Andric } 24170b57cec5SDimitry Andric break; 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric 24210b57cec5SDimitry Andric // if we are here and options.m_no_synthetic_children is true, 24220b57cec5SDimitry Andric // child_valobj_sp is going to be a NULL SP, so we hit the "else" 24230b57cec5SDimitry Andric // branch, and return an error 24240b57cec5SDimitry Andric if (child_valobj_sp.get()) // if it worked, move on 24250b57cec5SDimitry Andric { 24260b57cec5SDimitry Andric root = child_valobj_sp; 24270b57cec5SDimitry Andric remainder = next_separator; 24280b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 24290b57cec5SDimitry Andric continue; 24300b57cec5SDimitry Andric } else { 24310b57cec5SDimitry Andric *reason_to_stop = 24320b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 24330b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 24340b57cec5SDimitry Andric return nullptr; 24350b57cec5SDimitry Andric } 24360b57cec5SDimitry Andric } 24370b57cec5SDimitry Andric break; 24380b57cec5SDimitry Andric } 24390b57cec5SDimitry Andric case '[': { 24400b57cec5SDimitry Andric if (!root_compiler_type_info.Test(eTypeIsArray) && 24410b57cec5SDimitry Andric !root_compiler_type_info.Test(eTypeIsPointer) && 24420b57cec5SDimitry Andric !root_compiler_type_info.Test( 24430b57cec5SDimitry Andric eTypeIsVector)) // if this is not a T[] nor a T* 24440b57cec5SDimitry Andric { 24450b57cec5SDimitry Andric if (!root_compiler_type_info.Test( 24460b57cec5SDimitry Andric eTypeIsScalar)) // if this is not even a scalar... 24470b57cec5SDimitry Andric { 24480b57cec5SDimitry Andric if (options.m_synthetic_children_traversal == 24490b57cec5SDimitry Andric GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: 24500b57cec5SDimitry Andric None) // ...only chance left is synthetic 24510b57cec5SDimitry Andric { 24520b57cec5SDimitry Andric *reason_to_stop = 24530b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; 24540b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 24550b57cec5SDimitry Andric return ValueObjectSP(); 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, 24580b57cec5SDimitry Andric // check that we can 24590b57cec5SDimitry Andric // expand bitfields 24600b57cec5SDimitry Andric { 24610b57cec5SDimitry Andric *reason_to_stop = 24620b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; 24630b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 24640b57cec5SDimitry Andric return ValueObjectSP(); 24650b57cec5SDimitry Andric } 24660b57cec5SDimitry Andric } 24670b57cec5SDimitry Andric if (temp_expression[1] == 24680b57cec5SDimitry Andric ']') // if this is an unbounded range it only works for arrays 24690b57cec5SDimitry Andric { 24700b57cec5SDimitry Andric if (!root_compiler_type_info.Test(eTypeIsArray)) { 24710b57cec5SDimitry Andric *reason_to_stop = 24720b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; 24730b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 24740b57cec5SDimitry Andric return nullptr; 24750b57cec5SDimitry Andric } else // even if something follows, we cannot expand unbounded ranges, 24760b57cec5SDimitry Andric // just let the caller do it 24770b57cec5SDimitry Andric { 24780b57cec5SDimitry Andric *reason_to_stop = 24790b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; 24800b57cec5SDimitry Andric *final_result = 24810b57cec5SDimitry Andric ValueObject::eExpressionPathEndResultTypeUnboundedRange; 24820b57cec5SDimitry Andric return root; 24830b57cec5SDimitry Andric } 24840b57cec5SDimitry Andric } 24850b57cec5SDimitry Andric 24860b57cec5SDimitry Andric size_t close_bracket_position = temp_expression.find(']', 1); 24870b57cec5SDimitry Andric if (close_bracket_position == 24880b57cec5SDimitry Andric llvm::StringRef::npos) // if there is no ], this is a syntax error 24890b57cec5SDimitry Andric { 24900b57cec5SDimitry Andric *reason_to_stop = 24910b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; 24920b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 24930b57cec5SDimitry Andric return nullptr; 24940b57cec5SDimitry Andric } 24950b57cec5SDimitry Andric 24960b57cec5SDimitry Andric llvm::StringRef bracket_expr = 24970b57cec5SDimitry Andric temp_expression.slice(1, close_bracket_position); 24980b57cec5SDimitry Andric 24990b57cec5SDimitry Andric // If this was an empty expression it would have been caught by the if 25000b57cec5SDimitry Andric // above. 25010b57cec5SDimitry Andric assert(!bracket_expr.empty()); 25020b57cec5SDimitry Andric 25030b57cec5SDimitry Andric if (!bracket_expr.contains('-')) { 25040b57cec5SDimitry Andric // if no separator, this is of the form [N]. Note that this cannot be 25050b57cec5SDimitry Andric // an unbounded range of the form [], because that case was handled 25060b57cec5SDimitry Andric // above with an unconditional return. 25070b57cec5SDimitry Andric unsigned long index = 0; 25080b57cec5SDimitry Andric if (bracket_expr.getAsInteger(0, index)) { 25090b57cec5SDimitry Andric *reason_to_stop = 25100b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; 25110b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 25120b57cec5SDimitry Andric return nullptr; 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric // from here on we do have a valid index 25160b57cec5SDimitry Andric if (root_compiler_type_info.Test(eTypeIsArray)) { 251706c3fb27SDimitry Andric ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index); 25180b57cec5SDimitry Andric if (!child_valobj_sp) 25190b57cec5SDimitry Andric child_valobj_sp = root->GetSyntheticArrayMember(index, true); 25200b57cec5SDimitry Andric if (!child_valobj_sp) 25210b57cec5SDimitry Andric if (root->HasSyntheticValue() && 2522*0fca6ea1SDimitry Andric llvm::expectedToStdOptional( 2523*0fca6ea1SDimitry Andric root->GetSyntheticValue()->GetNumChildren()) 2524*0fca6ea1SDimitry Andric .value_or(0) > index) 25250b57cec5SDimitry Andric child_valobj_sp = 252606c3fb27SDimitry Andric root->GetSyntheticValue()->GetChildAtIndex(index); 25270b57cec5SDimitry Andric if (child_valobj_sp) { 25280b57cec5SDimitry Andric root = child_valobj_sp; 25290b57cec5SDimitry Andric remainder = 25300b57cec5SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ] 25310b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 25320b57cec5SDimitry Andric continue; 25330b57cec5SDimitry Andric } else { 25340b57cec5SDimitry Andric *reason_to_stop = 25350b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 25360b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 25370b57cec5SDimitry Andric return nullptr; 25380b57cec5SDimitry Andric } 25390b57cec5SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsPointer)) { 25400b57cec5SDimitry Andric if (*what_next == 25410b57cec5SDimitry Andric ValueObject:: 25420b57cec5SDimitry Andric eExpressionPathAftermathDereference && // if this is a 25430b57cec5SDimitry Andric // ptr-to-scalar, I 25440b57cec5SDimitry Andric // am accessing it 25450b57cec5SDimitry Andric // by index and I 25460b57cec5SDimitry Andric // would have 25470b57cec5SDimitry Andric // deref'ed anyway, 25480b57cec5SDimitry Andric // then do it now 25490b57cec5SDimitry Andric // and use this as 25500b57cec5SDimitry Andric // a bitfield 25510b57cec5SDimitry Andric pointee_compiler_type_info.Test(eTypeIsScalar)) { 25520b57cec5SDimitry Andric Status error; 25530b57cec5SDimitry Andric root = root->Dereference(error); 25540b57cec5SDimitry Andric if (error.Fail() || !root) { 25550b57cec5SDimitry Andric *reason_to_stop = 25560b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed; 25570b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 25580b57cec5SDimitry Andric return nullptr; 25590b57cec5SDimitry Andric } else { 25600b57cec5SDimitry Andric *what_next = eExpressionPathAftermathNothing; 25610b57cec5SDimitry Andric continue; 25620b57cec5SDimitry Andric } 25630b57cec5SDimitry Andric } else { 25640b57cec5SDimitry Andric if (root->GetCompilerType().GetMinimumLanguage() == 25650b57cec5SDimitry Andric eLanguageTypeObjC && 25660b57cec5SDimitry Andric pointee_compiler_type_info.AllClear(eTypeIsPointer) && 25670b57cec5SDimitry Andric root->HasSyntheticValue() && 25680b57cec5SDimitry Andric (options.m_synthetic_children_traversal == 25690b57cec5SDimitry Andric GetValueForExpressionPathOptions:: 25700b57cec5SDimitry Andric SyntheticChildrenTraversal::ToSynthetic || 25710b57cec5SDimitry Andric options.m_synthetic_children_traversal == 25720b57cec5SDimitry Andric GetValueForExpressionPathOptions:: 25730b57cec5SDimitry Andric SyntheticChildrenTraversal::Both)) { 257406c3fb27SDimitry Andric root = root->GetSyntheticValue()->GetChildAtIndex(index); 25750b57cec5SDimitry Andric } else 25760b57cec5SDimitry Andric root = root->GetSyntheticArrayMember(index, true); 25770b57cec5SDimitry Andric if (!root) { 25780b57cec5SDimitry Andric *reason_to_stop = 25790b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 25800b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 25810b57cec5SDimitry Andric return nullptr; 25820b57cec5SDimitry Andric } else { 25830b57cec5SDimitry Andric remainder = 25840b57cec5SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ] 25850b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 25860b57cec5SDimitry Andric continue; 25870b57cec5SDimitry Andric } 25880b57cec5SDimitry Andric } 25890b57cec5SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsScalar)) { 25900b57cec5SDimitry Andric root = root->GetSyntheticBitFieldChild(index, index, true); 25910b57cec5SDimitry Andric if (!root) { 25920b57cec5SDimitry Andric *reason_to_stop = 25930b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 25940b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 25950b57cec5SDimitry Andric return nullptr; 25960b57cec5SDimitry Andric } else // we do not know how to expand members of bitfields, so we 25970b57cec5SDimitry Andric // just return and let the caller do any further processing 25980b57cec5SDimitry Andric { 25990b57cec5SDimitry Andric *reason_to_stop = ValueObject:: 26000b57cec5SDimitry Andric eExpressionPathScanEndReasonBitfieldRangeOperatorMet; 26010b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; 26020b57cec5SDimitry Andric return root; 26030b57cec5SDimitry Andric } 26040b57cec5SDimitry Andric } else if (root_compiler_type_info.Test(eTypeIsVector)) { 260506c3fb27SDimitry Andric root = root->GetChildAtIndex(index); 26060b57cec5SDimitry Andric if (!root) { 26070b57cec5SDimitry Andric *reason_to_stop = 26080b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 26090b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26100b57cec5SDimitry Andric return ValueObjectSP(); 26110b57cec5SDimitry Andric } else { 26120b57cec5SDimitry Andric remainder = 26130b57cec5SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ] 26140b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 26150b57cec5SDimitry Andric continue; 26160b57cec5SDimitry Andric } 26170b57cec5SDimitry Andric } else if (options.m_synthetic_children_traversal == 26180b57cec5SDimitry Andric GetValueForExpressionPathOptions:: 26190b57cec5SDimitry Andric SyntheticChildrenTraversal::ToSynthetic || 26200b57cec5SDimitry Andric options.m_synthetic_children_traversal == 26210b57cec5SDimitry Andric GetValueForExpressionPathOptions:: 26220b57cec5SDimitry Andric SyntheticChildrenTraversal::Both) { 26230b57cec5SDimitry Andric if (root->HasSyntheticValue()) 26240b57cec5SDimitry Andric root = root->GetSyntheticValue(); 26250b57cec5SDimitry Andric else if (!root->IsSynthetic()) { 26260b57cec5SDimitry Andric *reason_to_stop = 26270b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; 26280b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26290b57cec5SDimitry Andric return nullptr; 26300b57cec5SDimitry Andric } 26310b57cec5SDimitry Andric // if we are here, then root itself is a synthetic VO.. should be 26320b57cec5SDimitry Andric // good to go 26330b57cec5SDimitry Andric 26340b57cec5SDimitry Andric if (!root) { 26350b57cec5SDimitry Andric *reason_to_stop = 26360b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; 26370b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26380b57cec5SDimitry Andric return nullptr; 26390b57cec5SDimitry Andric } 264006c3fb27SDimitry Andric root = root->GetChildAtIndex(index); 26410b57cec5SDimitry Andric if (!root) { 26420b57cec5SDimitry Andric *reason_to_stop = 26430b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 26440b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26450b57cec5SDimitry Andric return nullptr; 26460b57cec5SDimitry Andric } else { 26470b57cec5SDimitry Andric remainder = 26480b57cec5SDimitry Andric temp_expression.substr(close_bracket_position + 1); // skip ] 26490b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypePlain; 26500b57cec5SDimitry Andric continue; 26510b57cec5SDimitry Andric } 26520b57cec5SDimitry Andric } else { 26530b57cec5SDimitry Andric *reason_to_stop = 26540b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 26550b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26560b57cec5SDimitry Andric return nullptr; 26570b57cec5SDimitry Andric } 26580b57cec5SDimitry Andric } else { 26590b57cec5SDimitry Andric // we have a low and a high index 26600b57cec5SDimitry Andric llvm::StringRef sleft, sright; 26610b57cec5SDimitry Andric unsigned long low_index, high_index; 26620b57cec5SDimitry Andric std::tie(sleft, sright) = bracket_expr.split('-'); 26630b57cec5SDimitry Andric if (sleft.getAsInteger(0, low_index) || 26640b57cec5SDimitry Andric sright.getAsInteger(0, high_index)) { 26650b57cec5SDimitry Andric *reason_to_stop = 26660b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; 26670b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26680b57cec5SDimitry Andric return nullptr; 26690b57cec5SDimitry Andric } 26700b57cec5SDimitry Andric 26710b57cec5SDimitry Andric if (low_index > high_index) // swap indices if required 26720b57cec5SDimitry Andric std::swap(low_index, high_index); 26730b57cec5SDimitry Andric 26740b57cec5SDimitry Andric if (root_compiler_type_info.Test( 26750b57cec5SDimitry Andric eTypeIsScalar)) // expansion only works for scalars 26760b57cec5SDimitry Andric { 26770b57cec5SDimitry Andric root = root->GetSyntheticBitFieldChild(low_index, high_index, true); 26780b57cec5SDimitry Andric if (!root) { 26790b57cec5SDimitry Andric *reason_to_stop = 26800b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonNoSuchChild; 26810b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 26820b57cec5SDimitry Andric return nullptr; 26830b57cec5SDimitry Andric } else { 26840b57cec5SDimitry Andric *reason_to_stop = ValueObject:: 26850b57cec5SDimitry Andric eExpressionPathScanEndReasonBitfieldRangeOperatorMet; 26860b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; 26870b57cec5SDimitry Andric return root; 26880b57cec5SDimitry Andric } 26890b57cec5SDimitry Andric } else if (root_compiler_type_info.Test( 26900b57cec5SDimitry Andric eTypeIsPointer) && // if this is a ptr-to-scalar, I am 26910b57cec5SDimitry Andric // accessing it by index and I would 26920b57cec5SDimitry Andric // have deref'ed anyway, then do it 26930b57cec5SDimitry Andric // now and use this as a bitfield 26940b57cec5SDimitry Andric *what_next == 26950b57cec5SDimitry Andric ValueObject::eExpressionPathAftermathDereference && 26960b57cec5SDimitry Andric pointee_compiler_type_info.Test(eTypeIsScalar)) { 26970b57cec5SDimitry Andric Status error; 26980b57cec5SDimitry Andric root = root->Dereference(error); 26990b57cec5SDimitry Andric if (error.Fail() || !root) { 27000b57cec5SDimitry Andric *reason_to_stop = 27010b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonDereferencingFailed; 27020b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 27030b57cec5SDimitry Andric return nullptr; 27040b57cec5SDimitry Andric } else { 27050b57cec5SDimitry Andric *what_next = ValueObject::eExpressionPathAftermathNothing; 27060b57cec5SDimitry Andric continue; 27070b57cec5SDimitry Andric } 27080b57cec5SDimitry Andric } else { 27090b57cec5SDimitry Andric *reason_to_stop = 27100b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; 27110b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange; 27120b57cec5SDimitry Andric return root; 27130b57cec5SDimitry Andric } 27140b57cec5SDimitry Andric } 27150b57cec5SDimitry Andric break; 27160b57cec5SDimitry Andric } 27170b57cec5SDimitry Andric default: // some non-separator is in the way 27180b57cec5SDimitry Andric { 27190b57cec5SDimitry Andric *reason_to_stop = 27200b57cec5SDimitry Andric ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; 27210b57cec5SDimitry Andric *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; 27220b57cec5SDimitry Andric return nullptr; 27230b57cec5SDimitry Andric } 27240b57cec5SDimitry Andric } 27250b57cec5SDimitry Andric } 27260b57cec5SDimitry Andric } 27270b57cec5SDimitry Andric 2728*0fca6ea1SDimitry Andric llvm::Error ValueObject::Dump(Stream &s) { 2729*0fca6ea1SDimitry Andric return Dump(s, DumpValueObjectOptions(*this)); 2730*0fca6ea1SDimitry Andric } 27310b57cec5SDimitry Andric 2732*0fca6ea1SDimitry Andric llvm::Error ValueObject::Dump(Stream &s, 2733*0fca6ea1SDimitry Andric const DumpValueObjectOptions &options) { 2734*0fca6ea1SDimitry Andric ValueObjectPrinter printer(*this, &s, options); 2735*0fca6ea1SDimitry Andric return printer.PrintValueObject(); 27360b57cec5SDimitry Andric } 27370b57cec5SDimitry Andric 27380b57cec5SDimitry Andric ValueObjectSP ValueObject::CreateConstantValue(ConstString name) { 27390b57cec5SDimitry Andric ValueObjectSP valobj_sp; 27400b57cec5SDimitry Andric 27410b57cec5SDimitry Andric if (UpdateValueIfNeeded(false) && m_error.Success()) { 27420b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 27430b57cec5SDimitry Andric 27440b57cec5SDimitry Andric DataExtractor data; 27450b57cec5SDimitry Andric data.SetByteOrder(m_data.GetByteOrder()); 27460b57cec5SDimitry Andric data.SetAddressByteSize(m_data.GetAddressByteSize()); 27470b57cec5SDimitry Andric 27480b57cec5SDimitry Andric if (IsBitfield()) { 27490b57cec5SDimitry Andric Value v(Scalar(GetValueAsUnsigned(UINT64_MAX))); 27509dba64beSDimitry Andric m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get()); 27510b57cec5SDimitry Andric } else 27529dba64beSDimitry Andric m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get()); 27530b57cec5SDimitry Andric 27540b57cec5SDimitry Andric valobj_sp = ValueObjectConstResult::Create( 27550b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data, 27560b57cec5SDimitry Andric GetAddressOf()); 27570b57cec5SDimitry Andric } 27580b57cec5SDimitry Andric 27590b57cec5SDimitry Andric if (!valobj_sp) { 27600b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 27610b57cec5SDimitry Andric valobj_sp = ValueObjectConstResult::Create( 27620b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), m_error); 27630b57cec5SDimitry Andric } 27640b57cec5SDimitry Andric return valobj_sp; 27650b57cec5SDimitry Andric } 27660b57cec5SDimitry Andric 27670b57cec5SDimitry Andric ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable( 27680b57cec5SDimitry Andric lldb::DynamicValueType dynValue, bool synthValue) { 27695f757f3fSDimitry Andric ValueObjectSP result_sp; 27700b57cec5SDimitry Andric switch (dynValue) { 27710b57cec5SDimitry Andric case lldb::eDynamicCanRunTarget: 27720b57cec5SDimitry Andric case lldb::eDynamicDontRunTarget: { 27735f757f3fSDimitry Andric if (!IsDynamic()) 27745f757f3fSDimitry Andric result_sp = GetDynamicValue(dynValue); 27750b57cec5SDimitry Andric } break; 27760b57cec5SDimitry Andric case lldb::eNoDynamicValues: { 27775f757f3fSDimitry Andric if (IsDynamic()) 27785f757f3fSDimitry Andric result_sp = GetStaticValue(); 27790b57cec5SDimitry Andric } break; 27800b57cec5SDimitry Andric } 27815f757f3fSDimitry Andric if (!result_sp) 27825f757f3fSDimitry Andric result_sp = GetSP(); 27835f757f3fSDimitry Andric assert(result_sp); 27840b57cec5SDimitry Andric 27855f757f3fSDimitry Andric bool is_synthetic = result_sp->IsSynthetic(); 27865f757f3fSDimitry Andric if (synthValue && !is_synthetic) { 27875f757f3fSDimitry Andric if (auto synth_sp = result_sp->GetSyntheticValue()) 27885f757f3fSDimitry Andric return synth_sp; 27890b57cec5SDimitry Andric } 27905f757f3fSDimitry Andric if (!synthValue && is_synthetic) { 27915f757f3fSDimitry Andric if (auto non_synth_sp = result_sp->GetNonSyntheticValue()) 27925f757f3fSDimitry Andric return non_synth_sp; 27930b57cec5SDimitry Andric } 27940b57cec5SDimitry Andric 27950b57cec5SDimitry Andric return result_sp; 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric 27980b57cec5SDimitry Andric ValueObjectSP ValueObject::Dereference(Status &error) { 27990b57cec5SDimitry Andric if (m_deref_valobj) 28000b57cec5SDimitry Andric return m_deref_valobj->GetSP(); 28010b57cec5SDimitry Andric 28020b57cec5SDimitry Andric const bool is_pointer_or_reference_type = IsPointerOrReferenceType(); 28030b57cec5SDimitry Andric if (is_pointer_or_reference_type) { 28040b57cec5SDimitry Andric bool omit_empty_base_classes = true; 28050b57cec5SDimitry Andric bool ignore_array_bounds = false; 28060b57cec5SDimitry Andric 28070b57cec5SDimitry Andric std::string child_name_str; 28080b57cec5SDimitry Andric uint32_t child_byte_size = 0; 28090b57cec5SDimitry Andric int32_t child_byte_offset = 0; 28100b57cec5SDimitry Andric uint32_t child_bitfield_bit_size = 0; 28110b57cec5SDimitry Andric uint32_t child_bitfield_bit_offset = 0; 28120b57cec5SDimitry Andric bool child_is_base_class = false; 28130b57cec5SDimitry Andric bool child_is_deref_of_parent = false; 28140b57cec5SDimitry Andric const bool transparent_pointers = false; 28150b57cec5SDimitry Andric CompilerType compiler_type = GetCompilerType(); 28165ffd83dbSDimitry Andric uint64_t language_flags = 0; 28170b57cec5SDimitry Andric 28180b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 28190b57cec5SDimitry Andric 2820*0fca6ea1SDimitry Andric CompilerType child_compiler_type; 2821*0fca6ea1SDimitry Andric auto child_compiler_type_or_err = compiler_type.GetChildCompilerTypeAtIndex( 28220b57cec5SDimitry Andric &exe_ctx, 0, transparent_pointers, omit_empty_base_classes, 28230b57cec5SDimitry Andric ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, 28240b57cec5SDimitry Andric child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, 28250b57cec5SDimitry Andric child_is_deref_of_parent, this, language_flags); 2826*0fca6ea1SDimitry Andric if (!child_compiler_type_or_err) 2827*0fca6ea1SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Types), 2828*0fca6ea1SDimitry Andric child_compiler_type_or_err.takeError(), 2829*0fca6ea1SDimitry Andric "could not find child: {0}"); 2830*0fca6ea1SDimitry Andric else 2831*0fca6ea1SDimitry Andric child_compiler_type = *child_compiler_type_or_err; 2832*0fca6ea1SDimitry Andric 28330b57cec5SDimitry Andric if (child_compiler_type && child_byte_size) { 28340b57cec5SDimitry Andric ConstString child_name; 28350b57cec5SDimitry Andric if (!child_name_str.empty()) 28360b57cec5SDimitry Andric child_name.SetCString(child_name_str.c_str()); 28370b57cec5SDimitry Andric 28380b57cec5SDimitry Andric m_deref_valobj = new ValueObjectChild( 28390b57cec5SDimitry Andric *this, child_compiler_type, child_name, child_byte_size, 28400b57cec5SDimitry Andric child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, 28410b57cec5SDimitry Andric child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid, 28420b57cec5SDimitry Andric language_flags); 28430b57cec5SDimitry Andric } 28445ffd83dbSDimitry Andric 28455ffd83dbSDimitry Andric // In case of incomplete child compiler type, use the pointee type and try 28465ffd83dbSDimitry Andric // to recreate a new ValueObjectChild using it. 28475ffd83dbSDimitry Andric if (!m_deref_valobj) { 2848bdd1243dSDimitry Andric // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g. 2849bdd1243dSDimitry Andric // `std::vector<int> &`). Remove ObjC restriction once that's resolved. 2850bdd1243dSDimitry Andric if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) && 2851bdd1243dSDimitry Andric HasSyntheticValue()) { 28525ffd83dbSDimitry Andric child_compiler_type = compiler_type.GetPointeeType(); 28535ffd83dbSDimitry Andric 28545ffd83dbSDimitry Andric if (child_compiler_type) { 28555ffd83dbSDimitry Andric ConstString child_name; 28565ffd83dbSDimitry Andric if (!child_name_str.empty()) 28575ffd83dbSDimitry Andric child_name.SetCString(child_name_str.c_str()); 28585ffd83dbSDimitry Andric 28595ffd83dbSDimitry Andric m_deref_valobj = new ValueObjectChild( 28605ffd83dbSDimitry Andric *this, child_compiler_type, child_name, child_byte_size, 28615ffd83dbSDimitry Andric child_byte_offset, child_bitfield_bit_size, 28625ffd83dbSDimitry Andric child_bitfield_bit_offset, child_is_base_class, 28635ffd83dbSDimitry Andric child_is_deref_of_parent, eAddressTypeInvalid, language_flags); 28645ffd83dbSDimitry Andric } 28655ffd83dbSDimitry Andric } 28665ffd83dbSDimitry Andric } 28675ffd83dbSDimitry Andric 28680b57cec5SDimitry Andric } else if (HasSyntheticValue()) { 28690b57cec5SDimitry Andric m_deref_valobj = 287006c3fb27SDimitry Andric GetSyntheticValue()->GetChildMemberWithName("$$dereference$$").get(); 28715ffd83dbSDimitry Andric } else if (IsSynthetic()) { 287206c3fb27SDimitry Andric m_deref_valobj = GetChildMemberWithName("$$dereference$$").get(); 28730b57cec5SDimitry Andric } 28740b57cec5SDimitry Andric 28750b57cec5SDimitry Andric if (m_deref_valobj) { 28760b57cec5SDimitry Andric error.Clear(); 28770b57cec5SDimitry Andric return m_deref_valobj->GetSP(); 28780b57cec5SDimitry Andric } else { 28790b57cec5SDimitry Andric StreamString strm; 28805ffd83dbSDimitry Andric GetExpressionPath(strm); 28810b57cec5SDimitry Andric 28820b57cec5SDimitry Andric if (is_pointer_or_reference_type) 28830b57cec5SDimitry Andric error.SetErrorStringWithFormat("dereference failed: (%s) %s", 28840b57cec5SDimitry Andric GetTypeName().AsCString("<invalid type>"), 28850b57cec5SDimitry Andric strm.GetData()); 28860b57cec5SDimitry Andric else 28870b57cec5SDimitry Andric error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s", 28880b57cec5SDimitry Andric GetTypeName().AsCString("<invalid type>"), 28890b57cec5SDimitry Andric strm.GetData()); 28900b57cec5SDimitry Andric return ValueObjectSP(); 28910b57cec5SDimitry Andric } 28920b57cec5SDimitry Andric } 28930b57cec5SDimitry Andric 28940b57cec5SDimitry Andric ValueObjectSP ValueObject::AddressOf(Status &error) { 28950b57cec5SDimitry Andric if (m_addr_of_valobj_sp) 28960b57cec5SDimitry Andric return m_addr_of_valobj_sp; 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric AddressType address_type = eAddressTypeInvalid; 28990b57cec5SDimitry Andric const bool scalar_is_load_address = false; 29000b57cec5SDimitry Andric addr_t addr = GetAddressOf(scalar_is_load_address, &address_type); 29010b57cec5SDimitry Andric error.Clear(); 2902*0fca6ea1SDimitry Andric if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) { 2903*0fca6ea1SDimitry Andric switch (address_type) { 2904*0fca6ea1SDimitry Andric case eAddressTypeInvalid: { 29050b57cec5SDimitry Andric StreamString expr_path_strm; 29065ffd83dbSDimitry Andric GetExpressionPath(expr_path_strm); 2907*0fca6ea1SDimitry Andric error.SetErrorStringWithFormat("'%s' is not in memory", 2908*0fca6ea1SDimitry Andric expr_path_strm.GetData()); 2909*0fca6ea1SDimitry Andric } break; 29100b57cec5SDimitry Andric 29110b57cec5SDimitry Andric case eAddressTypeFile: 29120b57cec5SDimitry Andric case eAddressTypeLoad: { 29130b57cec5SDimitry Andric CompilerType compiler_type = GetCompilerType(); 2914*0fca6ea1SDimitry Andric if (compiler_type) { 29157a6dacacSDimitry Andric std::string name(1, '&'); 29167a6dacacSDimitry Andric name.append(m_name.AsCString("")); 2917*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 29187a6dacacSDimitry Andric m_addr_of_valobj_sp = ValueObjectConstResult::Create( 2919*0fca6ea1SDimitry Andric exe_ctx.GetBestExecutionContextScope(), 2920*0fca6ea1SDimitry Andric compiler_type.GetPointerType(), ConstString(name.c_str()), addr, 29217a6dacacSDimitry Andric eAddressTypeInvalid, m_data.GetAddressByteSize()); 2922*0fca6ea1SDimitry Andric } 2923*0fca6ea1SDimitry Andric } break; 2924*0fca6ea1SDimitry Andric default: 2925*0fca6ea1SDimitry Andric break; 2926*0fca6ea1SDimitry Andric } 2927*0fca6ea1SDimitry Andric } else { 2928*0fca6ea1SDimitry Andric StreamString expr_path_strm; 2929*0fca6ea1SDimitry Andric GetExpressionPath(expr_path_strm); 2930*0fca6ea1SDimitry Andric error.SetErrorStringWithFormat("'%s' doesn't have a valid address", 2931*0fca6ea1SDimitry Andric expr_path_strm.GetData()); 2932*0fca6ea1SDimitry Andric } 2933*0fca6ea1SDimitry Andric 29340b57cec5SDimitry Andric return m_addr_of_valobj_sp; 29350b57cec5SDimitry Andric } 29360b57cec5SDimitry Andric 293706c3fb27SDimitry Andric ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) { 29380b57cec5SDimitry Andric return ValueObjectCast::Create(*this, GetName(), compiler_type); 29390b57cec5SDimitry Andric } 29400b57cec5SDimitry Andric 294106c3fb27SDimitry Andric ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) { 294206c3fb27SDimitry Andric // Only allow casts if the original type is equal or larger than the cast 2943*0fca6ea1SDimitry Andric // type, unless we know this is a load address. Getting the size wrong for 2944*0fca6ea1SDimitry Andric // a host side storage could leak lldb memory, so we absolutely want to 2945*0fca6ea1SDimitry Andric // prevent that. We may not always get the right value, for instance if we 2946*0fca6ea1SDimitry Andric // have an expression result value that's copied into a storage location in 2947*0fca6ea1SDimitry Andric // the target may not have copied enough memory. I'm not trying to fix that 2948*0fca6ea1SDimitry Andric // here, I'm just making Cast from a smaller to a larger possible in all the 2949*0fca6ea1SDimitry Andric // cases where that doesn't risk making a Value out of random lldb memory. 2950*0fca6ea1SDimitry Andric // You have to check the ValueObject's Value for the address types, since 2951*0fca6ea1SDimitry Andric // ValueObjects that use live addresses will tell you they fetch data from the 2952*0fca6ea1SDimitry Andric // live address, but once they are made, they actually don't. 2953*0fca6ea1SDimitry Andric // FIXME: Can we make ValueObject's with a live address fetch "more data" from 2954*0fca6ea1SDimitry Andric // the live address if it is still valid? 2955*0fca6ea1SDimitry Andric 295606c3fb27SDimitry Andric Status error; 295706c3fb27SDimitry Andric CompilerType my_type = GetCompilerType(); 295806c3fb27SDimitry Andric 295906c3fb27SDimitry Andric ExecutionContextScope *exe_scope 296006c3fb27SDimitry Andric = ExecutionContext(GetExecutionContextRef()) 296106c3fb27SDimitry Andric .GetBestExecutionContextScope(); 296206c3fb27SDimitry Andric if (compiler_type.GetByteSize(exe_scope) 2963*0fca6ea1SDimitry Andric <= GetCompilerType().GetByteSize(exe_scope) 2964*0fca6ea1SDimitry Andric || m_value.GetValueType() == Value::ValueType::LoadAddress) 296506c3fb27SDimitry Andric return DoCast(compiler_type); 2966*0fca6ea1SDimitry Andric 296706c3fb27SDimitry Andric error.SetErrorString("Can only cast to a type that is equal to or smaller " 296806c3fb27SDimitry Andric "than the orignal type."); 296906c3fb27SDimitry Andric 297006c3fb27SDimitry Andric return ValueObjectConstResult::Create( 297106c3fb27SDimitry Andric ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(), 297206c3fb27SDimitry Andric error); 297306c3fb27SDimitry Andric } 297406c3fb27SDimitry Andric 29750b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) { 29760b57cec5SDimitry Andric return ValueObjectCast::Create(*this, new_name, GetCompilerType()); 29770b57cec5SDimitry Andric } 29780b57cec5SDimitry Andric 29790b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, 29800b57cec5SDimitry Andric CompilerType &compiler_type) { 29810b57cec5SDimitry Andric ValueObjectSP valobj_sp; 29820b57cec5SDimitry Andric AddressType address_type; 29830b57cec5SDimitry Andric addr_t ptr_value = GetPointerValue(&address_type); 29840b57cec5SDimitry Andric 29850b57cec5SDimitry Andric if (ptr_value != LLDB_INVALID_ADDRESS) { 29860b57cec5SDimitry Andric Address ptr_addr(ptr_value); 29870b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 29880b57cec5SDimitry Andric valobj_sp = ValueObjectMemory::Create( 29890b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type); 29900b57cec5SDimitry Andric } 29910b57cec5SDimitry Andric return valobj_sp; 29920b57cec5SDimitry Andric } 29930b57cec5SDimitry Andric 29940b57cec5SDimitry Andric ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) { 29950b57cec5SDimitry Andric ValueObjectSP valobj_sp; 29960b57cec5SDimitry Andric AddressType address_type; 29970b57cec5SDimitry Andric addr_t ptr_value = GetPointerValue(&address_type); 29980b57cec5SDimitry Andric 29990b57cec5SDimitry Andric if (ptr_value != LLDB_INVALID_ADDRESS) { 30000b57cec5SDimitry Andric Address ptr_addr(ptr_value); 30010b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 30020b57cec5SDimitry Andric valobj_sp = ValueObjectMemory::Create( 30030b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric return valobj_sp; 30060b57cec5SDimitry Andric } 30070b57cec5SDimitry Andric 3008*0fca6ea1SDimitry Andric lldb::addr_t ValueObject::GetLoadAddress() { 3009*0fca6ea1SDimitry Andric lldb::addr_t addr_value = LLDB_INVALID_ADDRESS; 3010*0fca6ea1SDimitry Andric if (auto target_sp = GetTargetSP()) { 3011*0fca6ea1SDimitry Andric const bool scalar_is_load_address = true; 3012*0fca6ea1SDimitry Andric AddressType addr_type; 3013*0fca6ea1SDimitry Andric addr_value = GetAddressOf(scalar_is_load_address, &addr_type); 3014*0fca6ea1SDimitry Andric if (addr_type == eAddressTypeFile) { 3015*0fca6ea1SDimitry Andric lldb::ModuleSP module_sp(GetModule()); 3016*0fca6ea1SDimitry Andric if (!module_sp) 3017*0fca6ea1SDimitry Andric addr_value = LLDB_INVALID_ADDRESS; 3018*0fca6ea1SDimitry Andric else { 3019*0fca6ea1SDimitry Andric Address tmp_addr; 3020*0fca6ea1SDimitry Andric module_sp->ResolveFileAddress(addr_value, tmp_addr); 3021*0fca6ea1SDimitry Andric addr_value = tmp_addr.GetLoadAddress(target_sp.get()); 3022*0fca6ea1SDimitry Andric } 3023*0fca6ea1SDimitry Andric } else if (addr_type == eAddressTypeHost || 3024*0fca6ea1SDimitry Andric addr_type == eAddressTypeInvalid) 3025*0fca6ea1SDimitry Andric addr_value = LLDB_INVALID_ADDRESS; 3026*0fca6ea1SDimitry Andric } 3027*0fca6ea1SDimitry Andric return addr_value; 3028*0fca6ea1SDimitry Andric } 3029*0fca6ea1SDimitry Andric 3030*0fca6ea1SDimitry Andric llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType( 3031*0fca6ea1SDimitry Andric CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) { 3032*0fca6ea1SDimitry Andric // Make sure the starting type and the target type are both valid for this 3033*0fca6ea1SDimitry Andric // type of cast; otherwise return the shared pointer to the original 3034*0fca6ea1SDimitry Andric // (unchanged) ValueObject. 3035*0fca6ea1SDimitry Andric if (!type.IsPointerType() && !type.IsReferenceType()) 3036*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3037*0fca6ea1SDimitry Andric "Invalid target type: should be a pointer or a reference", 3038*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3039*0fca6ea1SDimitry Andric 3040*0fca6ea1SDimitry Andric CompilerType start_type = GetCompilerType(); 3041*0fca6ea1SDimitry Andric if (start_type.IsReferenceType()) 3042*0fca6ea1SDimitry Andric start_type = start_type.GetNonReferenceType(); 3043*0fca6ea1SDimitry Andric 3044*0fca6ea1SDimitry Andric auto target_record_type = 3045*0fca6ea1SDimitry Andric type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType(); 3046*0fca6ea1SDimitry Andric auto start_record_type = 3047*0fca6ea1SDimitry Andric start_type.IsPointerType() ? start_type.GetPointeeType() : start_type; 3048*0fca6ea1SDimitry Andric 3049*0fca6ea1SDimitry Andric if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType()) 3050*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3051*0fca6ea1SDimitry Andric "Underlying start & target types should be record types", 3052*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3053*0fca6ea1SDimitry Andric 3054*0fca6ea1SDimitry Andric if (target_record_type.CompareTypes(start_record_type)) 3055*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3056*0fca6ea1SDimitry Andric "Underlying start & target types should be different", 3057*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3058*0fca6ea1SDimitry Andric 3059*0fca6ea1SDimitry Andric if (base_type_indices.empty()) 3060*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3061*0fca6ea1SDimitry Andric "Children sequence must be non-empty", llvm::inconvertibleErrorCode()); 3062*0fca6ea1SDimitry Andric 3063*0fca6ea1SDimitry Andric // Both the starting & target types are valid for the cast, and the list of 3064*0fca6ea1SDimitry Andric // base class indices is non-empty, so we can proceed with the cast. 3065*0fca6ea1SDimitry Andric 3066*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 3067*0fca6ea1SDimitry Andric // The `value` can be a pointer, but GetChildAtIndex works for pointers too. 3068*0fca6ea1SDimitry Andric lldb::ValueObjectSP inner_value = GetSP(); 3069*0fca6ea1SDimitry Andric 3070*0fca6ea1SDimitry Andric for (const uint32_t i : base_type_indices) 3071*0fca6ea1SDimitry Andric // Create synthetic value if needed. 3072*0fca6ea1SDimitry Andric inner_value = 3073*0fca6ea1SDimitry Andric inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true); 3074*0fca6ea1SDimitry Andric 3075*0fca6ea1SDimitry Andric // At this point type of `inner_value` should be the dereferenced target 3076*0fca6ea1SDimitry Andric // type. 3077*0fca6ea1SDimitry Andric CompilerType inner_value_type = inner_value->GetCompilerType(); 3078*0fca6ea1SDimitry Andric if (type.IsPointerType()) { 3079*0fca6ea1SDimitry Andric if (!inner_value_type.CompareTypes(type.GetPointeeType())) 3080*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3081*0fca6ea1SDimitry Andric "casted value doesn't match the desired type", 3082*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3083*0fca6ea1SDimitry Andric 3084*0fca6ea1SDimitry Andric uintptr_t addr = inner_value->GetLoadAddress(); 3085*0fca6ea1SDimitry Andric llvm::StringRef name = ""; 3086*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(target.get(), false); 3087*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type, 3088*0fca6ea1SDimitry Andric /* do deref */ false); 3089*0fca6ea1SDimitry Andric } 3090*0fca6ea1SDimitry Andric 3091*0fca6ea1SDimitry Andric // At this point the target type should be a reference. 3092*0fca6ea1SDimitry Andric if (!inner_value_type.CompareTypes(type.GetNonReferenceType())) 3093*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3094*0fca6ea1SDimitry Andric "casted value doesn't match the desired type", 3095*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3096*0fca6ea1SDimitry Andric 3097*0fca6ea1SDimitry Andric return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType())); 3098*0fca6ea1SDimitry Andric } 3099*0fca6ea1SDimitry Andric 3100*0fca6ea1SDimitry Andric llvm::Expected<lldb::ValueObjectSP> 3101*0fca6ea1SDimitry Andric ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) { 3102*0fca6ea1SDimitry Andric // Make sure the starting type and the target type are both valid for this 3103*0fca6ea1SDimitry Andric // type of cast; otherwise return the shared pointer to the original 3104*0fca6ea1SDimitry Andric // (unchanged) ValueObject. 3105*0fca6ea1SDimitry Andric if (!type.IsPointerType() && !type.IsReferenceType()) 3106*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3107*0fca6ea1SDimitry Andric "Invalid target type: should be a pointer or a reference", 3108*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3109*0fca6ea1SDimitry Andric 3110*0fca6ea1SDimitry Andric CompilerType start_type = GetCompilerType(); 3111*0fca6ea1SDimitry Andric if (start_type.IsReferenceType()) 3112*0fca6ea1SDimitry Andric start_type = start_type.GetNonReferenceType(); 3113*0fca6ea1SDimitry Andric 3114*0fca6ea1SDimitry Andric auto target_record_type = 3115*0fca6ea1SDimitry Andric type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType(); 3116*0fca6ea1SDimitry Andric auto start_record_type = 3117*0fca6ea1SDimitry Andric start_type.IsPointerType() ? start_type.GetPointeeType() : start_type; 3118*0fca6ea1SDimitry Andric 3119*0fca6ea1SDimitry Andric if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType()) 3120*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3121*0fca6ea1SDimitry Andric "Underlying start & target types should be record types", 3122*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3123*0fca6ea1SDimitry Andric 3124*0fca6ea1SDimitry Andric if (target_record_type.CompareTypes(start_record_type)) 3125*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3126*0fca6ea1SDimitry Andric "Underlying start & target types should be different", 3127*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3128*0fca6ea1SDimitry Andric 3129*0fca6ea1SDimitry Andric CompilerType virtual_base; 3130*0fca6ea1SDimitry Andric if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) { 3131*0fca6ea1SDimitry Andric if (!virtual_base.IsValid()) 3132*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3133*0fca6ea1SDimitry Andric "virtual base should be valid", llvm::inconvertibleErrorCode()); 3134*0fca6ea1SDimitry Andric return llvm::make_error<llvm::StringError>( 3135*0fca6ea1SDimitry Andric llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " + 3136*0fca6ea1SDimitry Andric type.TypeDescription() + " via virtual base " + 3137*0fca6ea1SDimitry Andric virtual_base.TypeDescription()), 3138*0fca6ea1SDimitry Andric llvm::inconvertibleErrorCode()); 3139*0fca6ea1SDimitry Andric } 3140*0fca6ea1SDimitry Andric 3141*0fca6ea1SDimitry Andric // Both the starting & target types are valid for the cast, so we can 3142*0fca6ea1SDimitry Andric // proceed with the cast. 3143*0fca6ea1SDimitry Andric 3144*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 3145*0fca6ea1SDimitry Andric auto pointer_type = 3146*0fca6ea1SDimitry Andric type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType(); 3147*0fca6ea1SDimitry Andric 3148*0fca6ea1SDimitry Andric uintptr_t addr = 3149*0fca6ea1SDimitry Andric type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress(); 3150*0fca6ea1SDimitry Andric 3151*0fca6ea1SDimitry Andric llvm::StringRef name = ""; 3152*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(target.get(), false); 3153*0fca6ea1SDimitry Andric lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress( 3154*0fca6ea1SDimitry Andric name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false); 3155*0fca6ea1SDimitry Andric 3156*0fca6ea1SDimitry Andric if (type.IsPointerType()) 3157*0fca6ea1SDimitry Andric return value; 3158*0fca6ea1SDimitry Andric 3159*0fca6ea1SDimitry Andric // At this point the target type is a reference. Since `value` is a pointer, 3160*0fca6ea1SDimitry Andric // it has to be dereferenced. 3161*0fca6ea1SDimitry Andric Status error; 3162*0fca6ea1SDimitry Andric return value->Dereference(error); 3163*0fca6ea1SDimitry Andric } 3164*0fca6ea1SDimitry Andric 3165*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) { 3166*0fca6ea1SDimitry Andric bool is_scalar = GetCompilerType().IsScalarType(); 3167*0fca6ea1SDimitry Andric bool is_enum = GetCompilerType().IsEnumerationType(); 3168*0fca6ea1SDimitry Andric bool is_pointer = 3169*0fca6ea1SDimitry Andric GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType(); 3170*0fca6ea1SDimitry Andric bool is_float = GetCompilerType().IsFloat(); 3171*0fca6ea1SDimitry Andric bool is_integer = GetCompilerType().IsInteger(); 3172*0fca6ea1SDimitry Andric 3173*0fca6ea1SDimitry Andric if (!type.IsScalarType()) { 3174*0fca6ea1SDimitry Andric m_error.SetErrorString("target type must be a scalar"); 3175*0fca6ea1SDimitry Andric return GetSP(); 3176*0fca6ea1SDimitry Andric } 3177*0fca6ea1SDimitry Andric 3178*0fca6ea1SDimitry Andric if (!is_scalar && !is_enum && !is_pointer) { 3179*0fca6ea1SDimitry Andric m_error.SetErrorString("argument must be a scalar, enum, or pointer"); 3180*0fca6ea1SDimitry Andric return GetSP(); 3181*0fca6ea1SDimitry Andric } 3182*0fca6ea1SDimitry Andric 3183*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 3184*0fca6ea1SDimitry Andric uint64_t type_byte_size = 0; 3185*0fca6ea1SDimitry Andric uint64_t val_byte_size = 0; 3186*0fca6ea1SDimitry Andric if (auto temp = type.GetByteSize(target.get())) 3187*0fca6ea1SDimitry Andric type_byte_size = temp.value(); 3188*0fca6ea1SDimitry Andric if (auto temp = GetCompilerType().GetByteSize(target.get())) 3189*0fca6ea1SDimitry Andric val_byte_size = temp.value(); 3190*0fca6ea1SDimitry Andric 3191*0fca6ea1SDimitry Andric if (is_pointer) { 3192*0fca6ea1SDimitry Andric if (!type.IsInteger() && !type.IsBoolean()) { 3193*0fca6ea1SDimitry Andric m_error.SetErrorString("target type must be an integer or boolean"); 3194*0fca6ea1SDimitry Andric return GetSP(); 3195*0fca6ea1SDimitry Andric } 3196*0fca6ea1SDimitry Andric if (!type.IsBoolean() && type_byte_size < val_byte_size) { 3197*0fca6ea1SDimitry Andric m_error.SetErrorString( 3198*0fca6ea1SDimitry Andric "target type cannot be smaller than the pointer type"); 3199*0fca6ea1SDimitry Andric return GetSP(); 3200*0fca6ea1SDimitry Andric } 3201*0fca6ea1SDimitry Andric } 3202*0fca6ea1SDimitry Andric 3203*0fca6ea1SDimitry Andric if (type.IsBoolean()) { 3204*0fca6ea1SDimitry Andric if (!is_scalar || is_integer) 3205*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromBool( 3206*0fca6ea1SDimitry Andric target, GetValueAsUnsigned(0) != 0, "result"); 3207*0fca6ea1SDimitry Andric else if (is_scalar && is_float) { 3208*0fca6ea1SDimitry Andric auto float_value_or_err = GetValueAsAPFloat(); 3209*0fca6ea1SDimitry Andric if (float_value_or_err) 3210*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromBool( 3211*0fca6ea1SDimitry Andric target, !float_value_or_err->isZero(), "result"); 3212*0fca6ea1SDimitry Andric else { 3213*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3214*0fca6ea1SDimitry Andric "cannot get value as APFloat: %s", 3215*0fca6ea1SDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str()); 3216*0fca6ea1SDimitry Andric return GetSP(); 3217*0fca6ea1SDimitry Andric } 3218*0fca6ea1SDimitry Andric } 3219*0fca6ea1SDimitry Andric } 3220*0fca6ea1SDimitry Andric 3221*0fca6ea1SDimitry Andric if (type.IsInteger()) { 3222*0fca6ea1SDimitry Andric if (!is_scalar || is_integer) { 3223*0fca6ea1SDimitry Andric auto int_value_or_err = GetValueAsAPSInt(); 3224*0fca6ea1SDimitry Andric if (int_value_or_err) { 3225*0fca6ea1SDimitry Andric // Get the value as APSInt and extend or truncate it to the requested 3226*0fca6ea1SDimitry Andric // size. 3227*0fca6ea1SDimitry Andric llvm::APSInt ext = 3228*0fca6ea1SDimitry Andric int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT); 3229*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, ext, type, 3230*0fca6ea1SDimitry Andric "result"); 3231*0fca6ea1SDimitry Andric } else { 3232*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3233*0fca6ea1SDimitry Andric "cannot get value as APSInt: %s", 3234*0fca6ea1SDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str()); 3235*0fca6ea1SDimitry Andric ; 3236*0fca6ea1SDimitry Andric return GetSP(); 3237*0fca6ea1SDimitry Andric } 3238*0fca6ea1SDimitry Andric } else if (is_scalar && is_float) { 3239*0fca6ea1SDimitry Andric llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned()); 3240*0fca6ea1SDimitry Andric bool is_exact; 3241*0fca6ea1SDimitry Andric auto float_value_or_err = GetValueAsAPFloat(); 3242*0fca6ea1SDimitry Andric if (float_value_or_err) { 3243*0fca6ea1SDimitry Andric llvm::APFloatBase::opStatus status = 3244*0fca6ea1SDimitry Andric float_value_or_err->convertToInteger( 3245*0fca6ea1SDimitry Andric integer, llvm::APFloat::rmTowardZero, &is_exact); 3246*0fca6ea1SDimitry Andric 3247*0fca6ea1SDimitry Andric // Casting floating point values that are out of bounds of the target 3248*0fca6ea1SDimitry Andric // type is undefined behaviour. 3249*0fca6ea1SDimitry Andric if (status & llvm::APFloatBase::opInvalidOp) { 3250*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3251*0fca6ea1SDimitry Andric "invalid type cast detected: %s", 3252*0fca6ea1SDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str()); 3253*0fca6ea1SDimitry Andric return GetSP(); 3254*0fca6ea1SDimitry Andric } 3255*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, integer, type, 3256*0fca6ea1SDimitry Andric "result"); 3257*0fca6ea1SDimitry Andric } 3258*0fca6ea1SDimitry Andric } 3259*0fca6ea1SDimitry Andric } 3260*0fca6ea1SDimitry Andric 3261*0fca6ea1SDimitry Andric if (type.IsFloat()) { 3262*0fca6ea1SDimitry Andric if (!is_scalar) { 3263*0fca6ea1SDimitry Andric auto int_value_or_err = GetValueAsAPSInt(); 3264*0fca6ea1SDimitry Andric if (int_value_or_err) { 3265*0fca6ea1SDimitry Andric llvm::APSInt ext = 3266*0fca6ea1SDimitry Andric int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT); 3267*0fca6ea1SDimitry Andric Scalar scalar_int(ext); 3268*0fca6ea1SDimitry Andric llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt( 3269*0fca6ea1SDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration()); 3270*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type, 3271*0fca6ea1SDimitry Andric "result"); 3272*0fca6ea1SDimitry Andric } else { 3273*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3274*0fca6ea1SDimitry Andric "cannot get value as APSInt: %s", 3275*0fca6ea1SDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str()); 3276*0fca6ea1SDimitry Andric return GetSP(); 3277*0fca6ea1SDimitry Andric } 3278*0fca6ea1SDimitry Andric } else { 3279*0fca6ea1SDimitry Andric if (is_integer) { 3280*0fca6ea1SDimitry Andric auto int_value_or_err = GetValueAsAPSInt(); 3281*0fca6ea1SDimitry Andric if (int_value_or_err) { 3282*0fca6ea1SDimitry Andric Scalar scalar_int(*int_value_or_err); 3283*0fca6ea1SDimitry Andric llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt( 3284*0fca6ea1SDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration()); 3285*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type, 3286*0fca6ea1SDimitry Andric "result"); 3287*0fca6ea1SDimitry Andric } else { 3288*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3289*0fca6ea1SDimitry Andric "cannot get value as APSInt: %s", 3290*0fca6ea1SDimitry Andric llvm::toString(int_value_or_err.takeError()).c_str()); 3291*0fca6ea1SDimitry Andric return GetSP(); 3292*0fca6ea1SDimitry Andric } 3293*0fca6ea1SDimitry Andric } 3294*0fca6ea1SDimitry Andric if (is_float) { 3295*0fca6ea1SDimitry Andric auto float_value_or_err = GetValueAsAPFloat(); 3296*0fca6ea1SDimitry Andric if (float_value_or_err) { 3297*0fca6ea1SDimitry Andric Scalar scalar_float(*float_value_or_err); 3298*0fca6ea1SDimitry Andric llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat( 3299*0fca6ea1SDimitry Andric type.GetCanonicalType().GetBasicTypeEnumeration()); 3300*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPFloat(target, f, type, 3301*0fca6ea1SDimitry Andric "result"); 3302*0fca6ea1SDimitry Andric } else { 3303*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3304*0fca6ea1SDimitry Andric "cannot get value as APFloat: %s", 3305*0fca6ea1SDimitry Andric llvm::toString(float_value_or_err.takeError()).c_str()); 3306*0fca6ea1SDimitry Andric return GetSP(); 3307*0fca6ea1SDimitry Andric } 3308*0fca6ea1SDimitry Andric } 3309*0fca6ea1SDimitry Andric } 3310*0fca6ea1SDimitry Andric } 3311*0fca6ea1SDimitry Andric 3312*0fca6ea1SDimitry Andric m_error.SetErrorString("Unable to perform requested cast"); 3313*0fca6ea1SDimitry Andric return GetSP(); 3314*0fca6ea1SDimitry Andric } 3315*0fca6ea1SDimitry Andric 3316*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) { 3317*0fca6ea1SDimitry Andric bool is_enum = GetCompilerType().IsEnumerationType(); 3318*0fca6ea1SDimitry Andric bool is_integer = GetCompilerType().IsInteger(); 3319*0fca6ea1SDimitry Andric bool is_float = GetCompilerType().IsFloat(); 3320*0fca6ea1SDimitry Andric 3321*0fca6ea1SDimitry Andric if (!is_enum && !is_integer && !is_float) { 3322*0fca6ea1SDimitry Andric m_error.SetErrorString("argument must be an integer, a float, or an enum"); 3323*0fca6ea1SDimitry Andric return GetSP(); 3324*0fca6ea1SDimitry Andric } 3325*0fca6ea1SDimitry Andric 3326*0fca6ea1SDimitry Andric if (!type.IsEnumerationType()) { 3327*0fca6ea1SDimitry Andric m_error.SetErrorString("target type must be an enum"); 3328*0fca6ea1SDimitry Andric return GetSP(); 3329*0fca6ea1SDimitry Andric } 3330*0fca6ea1SDimitry Andric 3331*0fca6ea1SDimitry Andric lldb::TargetSP target = GetTargetSP(); 3332*0fca6ea1SDimitry Andric uint64_t byte_size = 0; 3333*0fca6ea1SDimitry Andric if (auto temp = type.GetByteSize(target.get())) 3334*0fca6ea1SDimitry Andric byte_size = temp.value(); 3335*0fca6ea1SDimitry Andric 3336*0fca6ea1SDimitry Andric if (is_float) { 3337*0fca6ea1SDimitry Andric llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned()); 3338*0fca6ea1SDimitry Andric bool is_exact; 3339*0fca6ea1SDimitry Andric auto value_or_err = GetValueAsAPFloat(); 3340*0fca6ea1SDimitry Andric if (value_or_err) { 3341*0fca6ea1SDimitry Andric llvm::APFloatBase::opStatus status = value_or_err->convertToInteger( 3342*0fca6ea1SDimitry Andric integer, llvm::APFloat::rmTowardZero, &is_exact); 3343*0fca6ea1SDimitry Andric 3344*0fca6ea1SDimitry Andric // Casting floating point values that are out of bounds of the target 3345*0fca6ea1SDimitry Andric // type is undefined behaviour. 3346*0fca6ea1SDimitry Andric if (status & llvm::APFloatBase::opInvalidOp) { 3347*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3348*0fca6ea1SDimitry Andric "invalid type cast detected: %s", 3349*0fca6ea1SDimitry Andric llvm::toString(value_or_err.takeError()).c_str()); 3350*0fca6ea1SDimitry Andric return GetSP(); 3351*0fca6ea1SDimitry Andric } 3352*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, integer, type, 3353*0fca6ea1SDimitry Andric "result"); 3354*0fca6ea1SDimitry Andric } else { 3355*0fca6ea1SDimitry Andric m_error.SetErrorString("cannot get value as APFloat"); 3356*0fca6ea1SDimitry Andric return GetSP(); 3357*0fca6ea1SDimitry Andric } 3358*0fca6ea1SDimitry Andric } else { 3359*0fca6ea1SDimitry Andric // Get the value as APSInt and extend or truncate it to the requested size. 3360*0fca6ea1SDimitry Andric auto value_or_err = GetValueAsAPSInt(); 3361*0fca6ea1SDimitry Andric if (value_or_err) { 3362*0fca6ea1SDimitry Andric llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT); 3363*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromAPInt(target, ext, type, 3364*0fca6ea1SDimitry Andric "result"); 3365*0fca6ea1SDimitry Andric } else { 3366*0fca6ea1SDimitry Andric m_error.SetErrorStringWithFormat( 3367*0fca6ea1SDimitry Andric "cannot get value as APSInt: %s", 3368*0fca6ea1SDimitry Andric llvm::toString(value_or_err.takeError()).c_str()); 3369*0fca6ea1SDimitry Andric return GetSP(); 3370*0fca6ea1SDimitry Andric } 3371*0fca6ea1SDimitry Andric } 3372*0fca6ea1SDimitry Andric m_error.SetErrorString("Cannot perform requested cast"); 3373*0fca6ea1SDimitry Andric return GetSP(); 3374*0fca6ea1SDimitry Andric } 3375*0fca6ea1SDimitry Andric 3376fe6060f1SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {} 33770b57cec5SDimitry Andric 33780b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope, 33790b57cec5SDimitry Andric bool use_selected) 338081ad6265SDimitry Andric : m_mod_id(), m_exe_ctx_ref() { 33810b57cec5SDimitry Andric ExecutionContext exe_ctx(exe_scope); 33820b57cec5SDimitry Andric TargetSP target_sp(exe_ctx.GetTargetSP()); 33830b57cec5SDimitry Andric if (target_sp) { 33840b57cec5SDimitry Andric m_exe_ctx_ref.SetTargetSP(target_sp); 33850b57cec5SDimitry Andric ProcessSP process_sp(exe_ctx.GetProcessSP()); 33860b57cec5SDimitry Andric if (!process_sp) 33870b57cec5SDimitry Andric process_sp = target_sp->GetProcessSP(); 33880b57cec5SDimitry Andric 33890b57cec5SDimitry Andric if (process_sp) { 33900b57cec5SDimitry Andric m_mod_id = process_sp->GetModID(); 33910b57cec5SDimitry Andric m_exe_ctx_ref.SetProcessSP(process_sp); 33920b57cec5SDimitry Andric 33930b57cec5SDimitry Andric ThreadSP thread_sp(exe_ctx.GetThreadSP()); 33940b57cec5SDimitry Andric 33950b57cec5SDimitry Andric if (!thread_sp) { 33960b57cec5SDimitry Andric if (use_selected) 33970b57cec5SDimitry Andric thread_sp = process_sp->GetThreadList().GetSelectedThread(); 33980b57cec5SDimitry Andric } 33990b57cec5SDimitry Andric 34000b57cec5SDimitry Andric if (thread_sp) { 34010b57cec5SDimitry Andric m_exe_ctx_ref.SetThreadSP(thread_sp); 34020b57cec5SDimitry Andric 34030b57cec5SDimitry Andric StackFrameSP frame_sp(exe_ctx.GetFrameSP()); 34040b57cec5SDimitry Andric if (!frame_sp) { 34050b57cec5SDimitry Andric if (use_selected) 340606c3fb27SDimitry Andric frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); 34070b57cec5SDimitry Andric } 34080b57cec5SDimitry Andric if (frame_sp) 34090b57cec5SDimitry Andric m_exe_ctx_ref.SetFrameSP(frame_sp); 34100b57cec5SDimitry Andric } 34110b57cec5SDimitry Andric } 34120b57cec5SDimitry Andric } 34130b57cec5SDimitry Andric } 34140b57cec5SDimitry Andric 34150b57cec5SDimitry Andric ValueObject::EvaluationPoint::EvaluationPoint( 34160b57cec5SDimitry Andric const ValueObject::EvaluationPoint &rhs) 341781ad6265SDimitry Andric : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {} 34180b57cec5SDimitry Andric 3419fe6060f1SDimitry Andric ValueObject::EvaluationPoint::~EvaluationPoint() = default; 34200b57cec5SDimitry Andric 34210b57cec5SDimitry Andric // This function checks the EvaluationPoint against the current process state. 34220b57cec5SDimitry Andric // If the current state matches the evaluation point, or the evaluation point 34230b57cec5SDimitry Andric // is already invalid, then we return false, meaning "no change". If the 34240b57cec5SDimitry Andric // current state is different, we update our state, and return true meaning 34250b57cec5SDimitry Andric // "yes, change". If we did see a change, we also set m_needs_update to true, 34260b57cec5SDimitry Andric // so future calls to NeedsUpdate will return true. exe_scope will be set to 34270b57cec5SDimitry Andric // the current execution context scope. 34280b57cec5SDimitry Andric 34290b57cec5SDimitry Andric bool ValueObject::EvaluationPoint::SyncWithProcessState( 34300b57cec5SDimitry Andric bool accept_invalid_exe_ctx) { 34310b57cec5SDimitry Andric // Start with the target, if it is NULL, then we're obviously not going to 34320b57cec5SDimitry Andric // get any further: 34330b57cec5SDimitry Andric const bool thread_and_frame_only_if_stopped = true; 34340b57cec5SDimitry Andric ExecutionContext exe_ctx( 34350b57cec5SDimitry Andric m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped)); 34360b57cec5SDimitry Andric 34370b57cec5SDimitry Andric if (exe_ctx.GetTargetPtr() == nullptr) 34380b57cec5SDimitry Andric return false; 34390b57cec5SDimitry Andric 34400b57cec5SDimitry Andric // If we don't have a process nothing can change. 34410b57cec5SDimitry Andric Process *process = exe_ctx.GetProcessPtr(); 34420b57cec5SDimitry Andric if (process == nullptr) 34430b57cec5SDimitry Andric return false; 34440b57cec5SDimitry Andric 34450b57cec5SDimitry Andric // If our stop id is the current stop ID, nothing has changed: 34460b57cec5SDimitry Andric ProcessModID current_mod_id = process->GetModID(); 34470b57cec5SDimitry Andric 34480b57cec5SDimitry Andric // If the current stop id is 0, either we haven't run yet, or the process 34490b57cec5SDimitry Andric // state has been cleared. In either case, we aren't going to be able to sync 34500b57cec5SDimitry Andric // with the process state. 34510b57cec5SDimitry Andric if (current_mod_id.GetStopID() == 0) 34520b57cec5SDimitry Andric return false; 34530b57cec5SDimitry Andric 34540b57cec5SDimitry Andric bool changed = false; 34550b57cec5SDimitry Andric const bool was_valid = m_mod_id.IsValid(); 34560b57cec5SDimitry Andric if (was_valid) { 34570b57cec5SDimitry Andric if (m_mod_id == current_mod_id) { 34580b57cec5SDimitry Andric // Everything is already up to date in this object, no need to update the 34590b57cec5SDimitry Andric // execution context scope. 34600b57cec5SDimitry Andric changed = false; 34610b57cec5SDimitry Andric } else { 34620b57cec5SDimitry Andric m_mod_id = current_mod_id; 34630b57cec5SDimitry Andric m_needs_update = true; 34640b57cec5SDimitry Andric changed = true; 34650b57cec5SDimitry Andric } 34660b57cec5SDimitry Andric } 34670b57cec5SDimitry Andric 34680b57cec5SDimitry Andric // Now re-look up the thread and frame in case the underlying objects have 34690b57cec5SDimitry Andric // gone away & been recreated. That way we'll be sure to return a valid 34700b57cec5SDimitry Andric // exe_scope. If we used to have a thread or a frame but can't find it 34710b57cec5SDimitry Andric // anymore, then mark ourselves as invalid. 34720b57cec5SDimitry Andric 34730b57cec5SDimitry Andric if (!accept_invalid_exe_ctx) { 34740b57cec5SDimitry Andric if (m_exe_ctx_ref.HasThreadRef()) { 34750b57cec5SDimitry Andric ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP()); 34760b57cec5SDimitry Andric if (thread_sp) { 34770b57cec5SDimitry Andric if (m_exe_ctx_ref.HasFrameRef()) { 34780b57cec5SDimitry Andric StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP()); 34790b57cec5SDimitry Andric if (!frame_sp) { 34800b57cec5SDimitry Andric // We used to have a frame, but now it is gone 34810b57cec5SDimitry Andric SetInvalid(); 34820b57cec5SDimitry Andric changed = was_valid; 34830b57cec5SDimitry Andric } 34840b57cec5SDimitry Andric } 34850b57cec5SDimitry Andric } else { 34860b57cec5SDimitry Andric // We used to have a thread, but now it is gone 34870b57cec5SDimitry Andric SetInvalid(); 34880b57cec5SDimitry Andric changed = was_valid; 34890b57cec5SDimitry Andric } 34900b57cec5SDimitry Andric } 34910b57cec5SDimitry Andric } 34920b57cec5SDimitry Andric 34930b57cec5SDimitry Andric return changed; 34940b57cec5SDimitry Andric } 34950b57cec5SDimitry Andric 34960b57cec5SDimitry Andric void ValueObject::EvaluationPoint::SetUpdated() { 34970b57cec5SDimitry Andric ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); 34980b57cec5SDimitry Andric if (process_sp) 34990b57cec5SDimitry Andric m_mod_id = process_sp->GetModID(); 35000b57cec5SDimitry Andric m_needs_update = false; 35010b57cec5SDimitry Andric } 35020b57cec5SDimitry Andric 35030b57cec5SDimitry Andric void ValueObject::ClearUserVisibleData(uint32_t clear_mask) { 35040b57cec5SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsValue) == 35050b57cec5SDimitry Andric eClearUserVisibleDataItemsValue) 35060b57cec5SDimitry Andric m_value_str.clear(); 35070b57cec5SDimitry Andric 35080b57cec5SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsLocation) == 35090b57cec5SDimitry Andric eClearUserVisibleDataItemsLocation) 35100b57cec5SDimitry Andric m_location_str.clear(); 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsSummary) == 35130b57cec5SDimitry Andric eClearUserVisibleDataItemsSummary) 35140b57cec5SDimitry Andric m_summary_str.clear(); 35150b57cec5SDimitry Andric 35160b57cec5SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsDescription) == 35170b57cec5SDimitry Andric eClearUserVisibleDataItemsDescription) 35180b57cec5SDimitry Andric m_object_desc_str.clear(); 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == 35210b57cec5SDimitry Andric eClearUserVisibleDataItemsSyntheticChildren) { 35220b57cec5SDimitry Andric if (m_synthetic_value) 35230b57cec5SDimitry Andric m_synthetic_value = nullptr; 35240b57cec5SDimitry Andric } 35250b57cec5SDimitry Andric } 35260b57cec5SDimitry Andric 35270b57cec5SDimitry Andric SymbolContextScope *ValueObject::GetSymbolContextScope() { 35280b57cec5SDimitry Andric if (m_parent) { 35290b57cec5SDimitry Andric if (!m_parent->IsPointerOrReferenceType()) 35300b57cec5SDimitry Andric return m_parent->GetSymbolContextScope(); 35310b57cec5SDimitry Andric } 35320b57cec5SDimitry Andric return nullptr; 35330b57cec5SDimitry Andric } 35340b57cec5SDimitry Andric 35350b57cec5SDimitry Andric lldb::ValueObjectSP 35360b57cec5SDimitry Andric ValueObject::CreateValueObjectFromExpression(llvm::StringRef name, 35370b57cec5SDimitry Andric llvm::StringRef expression, 35380b57cec5SDimitry Andric const ExecutionContext &exe_ctx) { 35390b57cec5SDimitry Andric return CreateValueObjectFromExpression(name, expression, exe_ctx, 35400b57cec5SDimitry Andric EvaluateExpressionOptions()); 35410b57cec5SDimitry Andric } 35420b57cec5SDimitry Andric 35430b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression( 35440b57cec5SDimitry Andric llvm::StringRef name, llvm::StringRef expression, 35450b57cec5SDimitry Andric const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) { 35460b57cec5SDimitry Andric lldb::ValueObjectSP retval_sp; 35470b57cec5SDimitry Andric lldb::TargetSP target_sp(exe_ctx.GetTargetSP()); 35480b57cec5SDimitry Andric if (!target_sp) 35490b57cec5SDimitry Andric return retval_sp; 35500b57cec5SDimitry Andric if (expression.empty()) 35510b57cec5SDimitry Andric return retval_sp; 35520b57cec5SDimitry Andric target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(), 35530b57cec5SDimitry Andric retval_sp, options); 35540b57cec5SDimitry Andric if (retval_sp && !name.empty()) 35550b57cec5SDimitry Andric retval_sp->SetName(ConstString(name)); 35560b57cec5SDimitry Andric return retval_sp; 35570b57cec5SDimitry Andric } 35580b57cec5SDimitry Andric 35590b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress( 35600b57cec5SDimitry Andric llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, 3561*0fca6ea1SDimitry Andric CompilerType type, bool do_deref) { 35620b57cec5SDimitry Andric if (type) { 35630b57cec5SDimitry Andric CompilerType pointer_type(type.GetPointerType()); 3564*0fca6ea1SDimitry Andric if (!do_deref) 3565*0fca6ea1SDimitry Andric pointer_type = type; 35660b57cec5SDimitry Andric if (pointer_type) { 35670b57cec5SDimitry Andric lldb::DataBufferSP buffer( 35680b57cec5SDimitry Andric new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t))); 35690b57cec5SDimitry Andric lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create( 35700b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), pointer_type, 35710b57cec5SDimitry Andric ConstString(name), buffer, exe_ctx.GetByteOrder(), 35720b57cec5SDimitry Andric exe_ctx.GetAddressByteSize())); 35730b57cec5SDimitry Andric if (ptr_result_valobj_sp) { 3574*0fca6ea1SDimitry Andric if (do_deref) 35750b57cec5SDimitry Andric ptr_result_valobj_sp->GetValue().SetValueType( 3576fe6060f1SDimitry Andric Value::ValueType::LoadAddress); 35770b57cec5SDimitry Andric Status err; 3578*0fca6ea1SDimitry Andric if (do_deref) 35790b57cec5SDimitry Andric ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err); 35800b57cec5SDimitry Andric if (ptr_result_valobj_sp && !name.empty()) 35810b57cec5SDimitry Andric ptr_result_valobj_sp->SetName(ConstString(name)); 35820b57cec5SDimitry Andric } 35830b57cec5SDimitry Andric return ptr_result_valobj_sp; 35840b57cec5SDimitry Andric } 35850b57cec5SDimitry Andric } 35860b57cec5SDimitry Andric return lldb::ValueObjectSP(); 35870b57cec5SDimitry Andric } 35880b57cec5SDimitry Andric 35890b57cec5SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromData( 35900b57cec5SDimitry Andric llvm::StringRef name, const DataExtractor &data, 35910b57cec5SDimitry Andric const ExecutionContext &exe_ctx, CompilerType type) { 35920b57cec5SDimitry Andric lldb::ValueObjectSP new_value_sp; 35930b57cec5SDimitry Andric new_value_sp = ValueObjectConstResult::Create( 35940b57cec5SDimitry Andric exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data, 35950b57cec5SDimitry Andric LLDB_INVALID_ADDRESS); 35960b57cec5SDimitry Andric new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); 35970b57cec5SDimitry Andric if (new_value_sp && !name.empty()) 35980b57cec5SDimitry Andric new_value_sp->SetName(ConstString(name)); 35990b57cec5SDimitry Andric return new_value_sp; 36000b57cec5SDimitry Andric } 36010b57cec5SDimitry Andric 3602*0fca6ea1SDimitry Andric lldb::ValueObjectSP 3603*0fca6ea1SDimitry Andric ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target, 3604*0fca6ea1SDimitry Andric const llvm::APInt &v, CompilerType type, 3605*0fca6ea1SDimitry Andric llvm::StringRef name) { 3606*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(target.get(), false); 3607*0fca6ea1SDimitry Andric uint64_t byte_size = 0; 3608*0fca6ea1SDimitry Andric if (auto temp = type.GetByteSize(target.get())) 3609*0fca6ea1SDimitry Andric byte_size = temp.value(); 3610*0fca6ea1SDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>( 3611*0fca6ea1SDimitry Andric reinterpret_cast<const void *>(v.getRawData()), byte_size, 3612*0fca6ea1SDimitry Andric exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize()); 3613*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type); 3614*0fca6ea1SDimitry Andric } 3615*0fca6ea1SDimitry Andric 3616*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat( 3617*0fca6ea1SDimitry Andric lldb::TargetSP target, const llvm::APFloat &v, CompilerType type, 3618*0fca6ea1SDimitry Andric llvm::StringRef name) { 3619*0fca6ea1SDimitry Andric return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name); 3620*0fca6ea1SDimitry Andric } 3621*0fca6ea1SDimitry Andric 3622*0fca6ea1SDimitry Andric lldb::ValueObjectSP 3623*0fca6ea1SDimitry Andric ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value, 3624*0fca6ea1SDimitry Andric llvm::StringRef name) { 3625*0fca6ea1SDimitry Andric CompilerType target_type; 3626*0fca6ea1SDimitry Andric if (target) { 3627*0fca6ea1SDimitry Andric for (auto type_system_sp : target->GetScratchTypeSystems()) 3628*0fca6ea1SDimitry Andric if (auto compiler_type = 3629*0fca6ea1SDimitry Andric type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) { 3630*0fca6ea1SDimitry Andric target_type = compiler_type; 3631*0fca6ea1SDimitry Andric break; 3632*0fca6ea1SDimitry Andric } 3633*0fca6ea1SDimitry Andric } 3634*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(target.get(), false); 3635*0fca6ea1SDimitry Andric uint64_t byte_size = 0; 3636*0fca6ea1SDimitry Andric if (auto temp = target_type.GetByteSize(target.get())) 3637*0fca6ea1SDimitry Andric byte_size = temp.value(); 3638*0fca6ea1SDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>( 3639*0fca6ea1SDimitry Andric reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(), 3640*0fca6ea1SDimitry Andric exe_ctx.GetAddressByteSize()); 3641*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, 3642*0fca6ea1SDimitry Andric target_type); 3643*0fca6ea1SDimitry Andric } 3644*0fca6ea1SDimitry Andric 3645*0fca6ea1SDimitry Andric lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr( 3646*0fca6ea1SDimitry Andric lldb::TargetSP target, CompilerType type, llvm::StringRef name) { 3647*0fca6ea1SDimitry Andric if (!type.IsNullPtrType()) { 3648*0fca6ea1SDimitry Andric lldb::ValueObjectSP ret_val; 3649*0fca6ea1SDimitry Andric return ret_val; 3650*0fca6ea1SDimitry Andric } 3651*0fca6ea1SDimitry Andric uintptr_t zero = 0; 3652*0fca6ea1SDimitry Andric ExecutionContext exe_ctx(target.get(), false); 3653*0fca6ea1SDimitry Andric uint64_t byte_size = 0; 3654*0fca6ea1SDimitry Andric if (auto temp = type.GetByteSize(target.get())) 3655*0fca6ea1SDimitry Andric byte_size = temp.value(); 3656*0fca6ea1SDimitry Andric lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>( 3657*0fca6ea1SDimitry Andric reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(), 3658*0fca6ea1SDimitry Andric exe_ctx.GetAddressByteSize()); 3659*0fca6ea1SDimitry Andric return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type); 3660*0fca6ea1SDimitry Andric } 3661*0fca6ea1SDimitry Andric 36620b57cec5SDimitry Andric ModuleSP ValueObject::GetModule() { 36630b57cec5SDimitry Andric ValueObject *root(GetRoot()); 36640b57cec5SDimitry Andric if (root != this) 36650b57cec5SDimitry Andric return root->GetModule(); 36660b57cec5SDimitry Andric return lldb::ModuleSP(); 36670b57cec5SDimitry Andric } 36680b57cec5SDimitry Andric 36690b57cec5SDimitry Andric ValueObject *ValueObject::GetRoot() { 36700b57cec5SDimitry Andric if (m_root) 36710b57cec5SDimitry Andric return m_root; 36720b57cec5SDimitry Andric return (m_root = FollowParentChain([](ValueObject *vo) -> bool { 36730b57cec5SDimitry Andric return (vo->m_parent != nullptr); 36740b57cec5SDimitry Andric })); 36750b57cec5SDimitry Andric } 36760b57cec5SDimitry Andric 36770b57cec5SDimitry Andric ValueObject * 36780b57cec5SDimitry Andric ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) { 36790b57cec5SDimitry Andric ValueObject *vo = this; 36800b57cec5SDimitry Andric while (vo) { 36810b57cec5SDimitry Andric if (!f(vo)) 36820b57cec5SDimitry Andric break; 36830b57cec5SDimitry Andric vo = vo->m_parent; 36840b57cec5SDimitry Andric } 36850b57cec5SDimitry Andric return vo; 36860b57cec5SDimitry Andric } 36870b57cec5SDimitry Andric 36880b57cec5SDimitry Andric AddressType ValueObject::GetAddressTypeOfChildren() { 36890b57cec5SDimitry Andric if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) { 36900b57cec5SDimitry Andric ValueObject *root(GetRoot()); 36910b57cec5SDimitry Andric if (root != this) 36920b57cec5SDimitry Andric return root->GetAddressTypeOfChildren(); 36930b57cec5SDimitry Andric } 36940b57cec5SDimitry Andric return m_address_type_of_ptr_or_ref_children; 36950b57cec5SDimitry Andric } 36960b57cec5SDimitry Andric 36970b57cec5SDimitry Andric lldb::DynamicValueType ValueObject::GetDynamicValueType() { 36980b57cec5SDimitry Andric ValueObject *with_dv_info = this; 36990b57cec5SDimitry Andric while (with_dv_info) { 37000b57cec5SDimitry Andric if (with_dv_info->HasDynamicValueTypeInfo()) 37010b57cec5SDimitry Andric return with_dv_info->GetDynamicValueTypeImpl(); 37020b57cec5SDimitry Andric with_dv_info = with_dv_info->m_parent; 37030b57cec5SDimitry Andric } 37040b57cec5SDimitry Andric return lldb::eNoDynamicValues; 37050b57cec5SDimitry Andric } 37060b57cec5SDimitry Andric 37070b57cec5SDimitry Andric lldb::Format ValueObject::GetFormat() const { 37080b57cec5SDimitry Andric const ValueObject *with_fmt_info = this; 37090b57cec5SDimitry Andric while (with_fmt_info) { 37100b57cec5SDimitry Andric if (with_fmt_info->m_format != lldb::eFormatDefault) 37110b57cec5SDimitry Andric return with_fmt_info->m_format; 37120b57cec5SDimitry Andric with_fmt_info = with_fmt_info->m_parent; 37130b57cec5SDimitry Andric } 37140b57cec5SDimitry Andric return m_format; 37150b57cec5SDimitry Andric } 37160b57cec5SDimitry Andric 37170b57cec5SDimitry Andric lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() { 37180b57cec5SDimitry Andric lldb::LanguageType type = m_preferred_display_language; 37190b57cec5SDimitry Andric if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { 37200b57cec5SDimitry Andric if (GetRoot()) { 37210b57cec5SDimitry Andric if (GetRoot() == this) { 37220b57cec5SDimitry Andric if (StackFrameSP frame_sp = GetFrameSP()) { 37230b57cec5SDimitry Andric const SymbolContext &sc( 37240b57cec5SDimitry Andric frame_sp->GetSymbolContext(eSymbolContextCompUnit)); 37250b57cec5SDimitry Andric if (CompileUnit *cu = sc.comp_unit) 37260b57cec5SDimitry Andric type = cu->GetLanguage(); 37270b57cec5SDimitry Andric } 37280b57cec5SDimitry Andric } else { 37290b57cec5SDimitry Andric type = GetRoot()->GetPreferredDisplayLanguage(); 37300b57cec5SDimitry Andric } 37310b57cec5SDimitry Andric } 37320b57cec5SDimitry Andric } 37330b57cec5SDimitry Andric return (m_preferred_display_language = type); // only compute it once 37340b57cec5SDimitry Andric } 37350b57cec5SDimitry Andric 37360b57cec5SDimitry Andric void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) { 37370b57cec5SDimitry Andric if (m_preferred_display_language == lldb::eLanguageTypeUnknown) 37380b57cec5SDimitry Andric SetPreferredDisplayLanguage(lt); 37390b57cec5SDimitry Andric } 37400b57cec5SDimitry Andric 37410b57cec5SDimitry Andric bool ValueObject::CanProvideValue() { 37420b57cec5SDimitry Andric // we need to support invalid types as providers of values because some bare- 37430b57cec5SDimitry Andric // board debugging scenarios have no notion of types, but still manage to 37440b57cec5SDimitry Andric // have raw numeric values for things like registers. sigh. 3745e8d8bef9SDimitry Andric CompilerType type = GetCompilerType(); 37460b57cec5SDimitry Andric return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue)); 37470b57cec5SDimitry Andric } 37480b57cec5SDimitry Andric 3749fe6060f1SDimitry Andric 37500b57cec5SDimitry Andric 37510b57cec5SDimitry Andric ValueObjectSP ValueObject::Persist() { 37520b57cec5SDimitry Andric if (!UpdateValueIfNeeded()) 37530b57cec5SDimitry Andric return nullptr; 37540b57cec5SDimitry Andric 37550b57cec5SDimitry Andric TargetSP target_sp(GetTargetSP()); 37560b57cec5SDimitry Andric if (!target_sp) 37570b57cec5SDimitry Andric return nullptr; 37580b57cec5SDimitry Andric 37590b57cec5SDimitry Andric PersistentExpressionState *persistent_state = 37600b57cec5SDimitry Andric target_sp->GetPersistentExpressionStateForLanguage( 37610b57cec5SDimitry Andric GetPreferredDisplayLanguage()); 37620b57cec5SDimitry Andric 37630b57cec5SDimitry Andric if (!persistent_state) 37640b57cec5SDimitry Andric return nullptr; 37650b57cec5SDimitry Andric 37665ffd83dbSDimitry Andric ConstString name = persistent_state->GetNextPersistentVariableName(); 37670b57cec5SDimitry Andric 37680b57cec5SDimitry Andric ValueObjectSP const_result_sp = 37690b57cec5SDimitry Andric ValueObjectConstResult::Create(target_sp.get(), GetValue(), name); 37700b57cec5SDimitry Andric 37715ffd83dbSDimitry Andric ExpressionVariableSP persistent_var_sp = 37720b57cec5SDimitry Andric persistent_state->CreatePersistentVariable(const_result_sp); 37735ffd83dbSDimitry Andric persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp; 37745ffd83dbSDimitry Andric persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference; 37750b57cec5SDimitry Andric 37765ffd83dbSDimitry Andric return persistent_var_sp->GetValueObject(); 37770b57cec5SDimitry Andric } 37785f757f3fSDimitry Andric 37795f757f3fSDimitry Andric lldb::ValueObjectSP ValueObject::GetVTable() { 37805f757f3fSDimitry Andric return ValueObjectVTable::Create(*this); 37815f757f3fSDimitry Andric } 3782