3757 lines · cpp
1//===-- ValueObject.cpp ---------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/ValueObject/ValueObject.h"10 11#include "lldb/Core/Address.h"12#include "lldb/Core/Declaration.h"13#include "lldb/Core/Module.h"14#include "lldb/DataFormatters/DataVisualization.h"15#include "lldb/DataFormatters/DumpValueObjectOptions.h"16#include "lldb/DataFormatters/FormatManager.h"17#include "lldb/DataFormatters/StringPrinter.h"18#include "lldb/DataFormatters/TypeFormat.h"19#include "lldb/DataFormatters/TypeSummary.h"20#include "lldb/DataFormatters/ValueObjectPrinter.h"21#include "lldb/Expression/ExpressionVariable.h"22#include "lldb/Host/Config.h"23#include "lldb/Symbol/CompileUnit.h"24#include "lldb/Symbol/CompilerType.h"25#include "lldb/Symbol/SymbolContext.h"26#include "lldb/Symbol/Type.h"27#include "lldb/Symbol/Variable.h"28#include "lldb/Target/ExecutionContext.h"29#include "lldb/Target/Language.h"30#include "lldb/Target/LanguageRuntime.h"31#include "lldb/Target/Process.h"32#include "lldb/Target/StackFrame.h"33#include "lldb/Target/Target.h"34#include "lldb/Target/Thread.h"35#include "lldb/Target/ThreadList.h"36#include "lldb/Utility/DataBuffer.h"37#include "lldb/Utility/DataBufferHeap.h"38#include "lldb/Utility/Flags.h"39#include "lldb/Utility/LLDBLog.h"40#include "lldb/Utility/Log.h"41#include "lldb/Utility/Scalar.h"42#include "lldb/Utility/Stream.h"43#include "lldb/Utility/StreamString.h"44#include "lldb/ValueObject/ValueObjectCast.h"45#include "lldb/ValueObject/ValueObjectChild.h"46#include "lldb/ValueObject/ValueObjectConstResult.h"47#include "lldb/ValueObject/ValueObjectDynamicValue.h"48#include "lldb/ValueObject/ValueObjectMemory.h"49#include "lldb/ValueObject/ValueObjectSynthetic.h"50#include "lldb/ValueObject/ValueObjectVTable.h"51#include "lldb/lldb-private-types.h"52 53#include "llvm/Support/Compiler.h"54 55#include <algorithm>56#include <cstdint>57#include <cstdlib>58#include <memory>59#include <optional>60#include <tuple>61 62#include <cassert>63#include <cinttypes>64#include <cstdio>65#include <cstring>66 67namespace lldb_private {68class ExecutionContextScope;69}70namespace lldb_private {71class SymbolContextScope;72}73 74using namespace lldb;75using namespace lldb_private;76 77static user_id_t g_value_obj_uid = 0;78 79// ValueObject constructor80ValueObject::ValueObject(ValueObject &parent)81 : m_parent(&parent), m_update_point(parent.GetUpdatePoint()),82 m_manager(parent.GetManager()), m_id(++g_value_obj_uid) {83 m_flags.m_is_synthetic_children_generated =84 parent.m_flags.m_is_synthetic_children_generated;85 m_data.SetByteOrder(parent.GetDataExtractor().GetByteOrder());86 m_data.SetAddressByteSize(parent.GetDataExtractor().GetAddressByteSize());87 m_manager->ManageObject(this);88}89 90// ValueObject constructor91ValueObject::ValueObject(ExecutionContextScope *exe_scope,92 ValueObjectManager &manager,93 AddressType child_ptr_or_ref_addr_type)94 : m_update_point(exe_scope), m_manager(&manager),95 m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),96 m_id(++g_value_obj_uid) {97 if (exe_scope) {98 TargetSP target_sp(exe_scope->CalculateTarget());99 if (target_sp) {100 const ArchSpec &arch = target_sp->GetArchitecture();101 m_data.SetByteOrder(arch.GetByteOrder());102 m_data.SetAddressByteSize(arch.GetAddressByteSize());103 }104 }105 m_manager->ManageObject(this);106}107 108// Destructor109ValueObject::~ValueObject() = default;110 111bool ValueObject::UpdateValueIfNeeded(bool update_format) {112 113 bool did_change_formats = false;114 115 if (update_format)116 did_change_formats = UpdateFormatsIfNeeded();117 118 // If this is a constant value, then our success is predicated on whether we119 // have an error or not120 if (GetIsConstant()) {121 // if you are constant, things might still have changed behind your back122 // (e.g. you are a frozen object and things have changed deeper than you123 // cared to freeze-dry yourself) in this case, your value has not changed,124 // but "computed" entries might have, so you might now have a different125 // summary, or a different object description. clear these so we will126 // recompute them127 if (update_format && !did_change_formats)128 ClearUserVisibleData(eClearUserVisibleDataItemsSummary |129 eClearUserVisibleDataItemsDescription);130 return m_error.Success();131 }132 133 bool first_update = IsChecksumEmpty();134 135 if (NeedsUpdating()) {136 m_update_point.SetUpdated();137 138 // Save the old value using swap to avoid a string copy which also will139 // clear our m_value_str140 if (m_value_str.empty()) {141 m_flags.m_old_value_valid = false;142 } else {143 m_flags.m_old_value_valid = true;144 m_old_value_str.swap(m_value_str);145 ClearUserVisibleData(eClearUserVisibleDataItemsValue);146 }147 148 ClearUserVisibleData();149 150 if (IsInScope()) {151 const bool value_was_valid = GetValueIsValid();152 SetValueDidChange(false);153 154 m_error.Clear();155 156 // Call the pure virtual function to update the value157 158 bool need_compare_checksums = false;159 llvm::SmallVector<uint8_t, 16> old_checksum;160 161 if (!first_update && CanProvideValue()) {162 need_compare_checksums = true;163 old_checksum.resize(m_value_checksum.size());164 std::copy(m_value_checksum.begin(), m_value_checksum.end(),165 old_checksum.begin());166 }167 168 bool success = UpdateValue();169 170 SetValueIsValid(success);171 172 if (success) {173 UpdateChildrenAddressType();174 const uint64_t max_checksum_size = 128;175 m_data.Checksum(m_value_checksum, max_checksum_size);176 } else {177 need_compare_checksums = false;178 m_value_checksum.clear();179 }180 181 assert(!need_compare_checksums ||182 (!old_checksum.empty() && !m_value_checksum.empty()));183 184 if (first_update)185 SetValueDidChange(false);186 else if (!m_flags.m_value_did_change && !success) {187 // The value wasn't gotten successfully, so we mark this as changed if188 // the value used to be valid and now isn't189 SetValueDidChange(value_was_valid);190 } else if (need_compare_checksums) {191 SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0],192 m_value_checksum.size()));193 }194 195 } else {196 m_error = Status::FromErrorString("out of scope");197 }198 }199 return m_error.Success();200}201 202bool ValueObject::UpdateFormatsIfNeeded() {203 Log *log = GetLog(LLDBLog::DataFormatters);204 LLDB_LOGF(log,205 "[%s %p] checking for FormatManager revisions. ValueObject "206 "rev: %d - Global rev: %d",207 GetName().GetCString(), static_cast<void *>(this),208 m_last_format_mgr_revision,209 DataVisualization::GetCurrentRevision());210 211 bool any_change = false;212 213 if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) {214 m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();215 any_change = true;216 217 SetValueFormat(DataVisualization::GetFormat(*this, GetDynamicValueType()));218 SetSummaryFormat(219 DataVisualization::GetSummaryFormat(*this, GetDynamicValueType()));220 SetSyntheticChildren(221 DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType()));222 }223 224 return any_change;225}226 227void ValueObject::SetNeedsUpdate() {228 m_update_point.SetNeedsUpdate();229 // We have to clear the value string here so ConstResult children will notice230 // if their values are changed by hand (i.e. with SetValueAsCString).231 ClearUserVisibleData(eClearUserVisibleDataItemsValue);232}233 234void ValueObject::ClearDynamicTypeInformation() {235 m_flags.m_children_count_valid = false;236 m_flags.m_did_calculate_complete_objc_class_type = false;237 m_last_format_mgr_revision = 0;238 m_override_type = CompilerType();239 SetValueFormat(lldb::TypeFormatImplSP());240 SetSummaryFormat(lldb::TypeSummaryImplSP());241 SetSyntheticChildren(lldb::SyntheticChildrenSP());242}243 244CompilerType ValueObject::MaybeCalculateCompleteType() {245 CompilerType compiler_type(GetCompilerTypeImpl());246 247 if (m_flags.m_did_calculate_complete_objc_class_type) {248 if (m_override_type.IsValid())249 return m_override_type;250 else251 return compiler_type;252 }253 254 m_flags.m_did_calculate_complete_objc_class_type = true;255 256 ProcessSP process_sp(257 GetUpdatePoint().GetExecutionContextRef().GetProcessSP());258 259 if (!process_sp)260 return compiler_type;261 262 if (auto *runtime =263 process_sp->GetLanguageRuntime(GetObjectRuntimeLanguage())) {264 if (std::optional<CompilerType> complete_type =265 runtime->GetRuntimeType(compiler_type)) {266 m_override_type = *complete_type;267 if (m_override_type.IsValid())268 return m_override_type;269 }270 }271 return compiler_type;272}273 274DataExtractor &ValueObject::GetDataExtractor() {275 UpdateValueIfNeeded(false);276 return m_data;277}278 279const Status &ValueObject::GetError() {280 UpdateValueIfNeeded(false);281 return m_error;282}283 284const char *ValueObject::GetLocationAsCStringImpl(const Value &value,285 const DataExtractor &data) {286 if (UpdateValueIfNeeded(false)) {287 if (m_location_str.empty()) {288 StreamString sstr;289 290 Value::ValueType value_type = value.GetValueType();291 292 switch (value_type) {293 case Value::ValueType::Invalid:294 m_location_str = "invalid";295 break;296 case Value::ValueType::Scalar:297 if (value.GetContextType() == Value::ContextType::RegisterInfo) {298 RegisterInfo *reg_info = value.GetRegisterInfo();299 if (reg_info) {300 if (reg_info->name)301 m_location_str = reg_info->name;302 else if (reg_info->alt_name)303 m_location_str = reg_info->alt_name;304 if (m_location_str.empty())305 m_location_str = (reg_info->encoding == lldb::eEncodingVector)306 ? "vector"307 : "scalar";308 }309 }310 if (m_location_str.empty())311 m_location_str = "scalar";312 break;313 314 case Value::ValueType::LoadAddress:315 case Value::ValueType::FileAddress:316 case Value::ValueType::HostAddress: {317 uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;318 sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size,319 value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));320 m_location_str = std::string(sstr.GetString());321 } break;322 }323 }324 }325 return m_location_str.c_str();326}327 328bool ValueObject::ResolveValue(Scalar &scalar) {329 if (UpdateValueIfNeeded(330 false)) // make sure that you are up to date before returning anything331 {332 ExecutionContext exe_ctx(GetExecutionContextRef());333 Value tmp_value(m_value);334 scalar = tmp_value.ResolveValue(&exe_ctx, GetModule().get());335 if (scalar.IsValid()) {336 const uint32_t bitfield_bit_size = GetBitfieldBitSize();337 if (bitfield_bit_size)338 return scalar.ExtractBitfield(bitfield_bit_size,339 GetBitfieldBitOffset());340 return true;341 }342 }343 return false;344}345 346bool ValueObject::IsLogicalTrue(Status &error) {347 if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {348 LazyBool is_logical_true = language->IsLogicalTrue(*this, error);349 switch (is_logical_true) {350 case eLazyBoolYes:351 case eLazyBoolNo:352 return (is_logical_true == true);353 case eLazyBoolCalculate:354 break;355 }356 }357 358 Scalar scalar_value;359 360 if (!ResolveValue(scalar_value)) {361 error = Status::FromErrorString("failed to get a scalar result");362 return false;363 }364 365 bool ret;366 ret = scalar_value.ULongLong(1) != 0;367 error.Clear();368 return ret;369}370 371ValueObjectSP ValueObject::GetChildAtIndex(uint32_t idx, bool can_create) {372 ValueObjectSP child_sp;373 // We may need to update our value if we are dynamic374 if (IsPossibleDynamicType())375 UpdateValueIfNeeded(false);376 if (idx < GetNumChildrenIgnoringErrors()) {377 // Check if we have already made the child value object?378 if (can_create && !m_children.HasChildAtIndex(idx)) {379 // No we haven't created the child at this index, so lets have our380 // subclass do it and cache the result for quick future access.381 m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx));382 }383 384 ValueObject *child = m_children.GetChildAtIndex(idx);385 if (child != nullptr)386 return child->GetSP();387 }388 return child_sp;389}390 391lldb::ValueObjectSP392ValueObject::GetChildAtNamePath(llvm::ArrayRef<llvm::StringRef> names) {393 if (names.size() == 0)394 return GetSP();395 ValueObjectSP root(GetSP());396 for (llvm::StringRef name : names) {397 root = root->GetChildMemberWithName(name);398 if (!root) {399 return root;400 }401 }402 return root;403}404 405llvm::Expected<size_t>406ValueObject::GetIndexOfChildWithName(llvm::StringRef name) {407 bool omit_empty_base_classes = true;408 return GetCompilerType().GetIndexOfChildWithName(name,409 omit_empty_base_classes);410}411 412ValueObjectSP ValueObject::GetChildMemberWithName(llvm::StringRef name,413 bool can_create) {414 // We may need to update our value if we are dynamic.415 if (IsPossibleDynamicType())416 UpdateValueIfNeeded(false);417 418 // When getting a child by name, it could be buried inside some base classes419 // (which really aren't part of the expression path), so we need a vector of420 // indexes that can get us down to the correct child.421 std::vector<uint32_t> child_indexes;422 bool omit_empty_base_classes = true;423 424 if (!GetCompilerType().IsValid())425 return ValueObjectSP();426 427 const size_t num_child_indexes =428 GetCompilerType().GetIndexOfChildMemberWithName(429 name, omit_empty_base_classes, child_indexes);430 if (num_child_indexes == 0)431 return nullptr;432 433 ValueObjectSP child_sp = GetSP();434 for (uint32_t idx : child_indexes)435 if (child_sp)436 child_sp = child_sp->GetChildAtIndex(idx, can_create);437 return child_sp;438}439 440llvm::Expected<uint32_t> ValueObject::GetNumChildren(uint32_t max) {441 UpdateValueIfNeeded();442 443 if (max < UINT32_MAX) {444 if (m_flags.m_children_count_valid) {445 size_t children_count = m_children.GetChildrenCount();446 return children_count <= max ? children_count : max;447 } else448 return CalculateNumChildren(max);449 }450 451 if (!m_flags.m_children_count_valid) {452 auto num_children_or_err = CalculateNumChildren();453 if (num_children_or_err)454 SetNumChildren(*num_children_or_err);455 else456 return num_children_or_err;457 }458 return m_children.GetChildrenCount();459}460 461uint32_t ValueObject::GetNumChildrenIgnoringErrors(uint32_t max) {462 auto value_or_err = GetNumChildren(max);463 if (value_or_err)464 return *value_or_err;465 LLDB_LOG_ERRORV(GetLog(LLDBLog::DataFormatters), value_or_err.takeError(),466 "{0}");467 return 0;468}469 470bool ValueObject::MightHaveChildren() {471 bool has_children = false;472 const uint32_t type_info = GetTypeInfo();473 if (type_info) {474 if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference))475 has_children = true;476 } else {477 has_children = GetNumChildrenIgnoringErrors() > 0;478 }479 return has_children;480}481 482// Should only be called by ValueObject::GetNumChildren()483void ValueObject::SetNumChildren(uint32_t num_children) {484 m_flags.m_children_count_valid = true;485 m_children.SetChildrenCount(num_children);486}487 488ValueObject *ValueObject::CreateChildAtIndex(size_t idx) {489 bool omit_empty_base_classes = true;490 bool ignore_array_bounds = false;491 std::string child_name;492 uint32_t child_byte_size = 0;493 int32_t child_byte_offset = 0;494 uint32_t child_bitfield_bit_size = 0;495 uint32_t child_bitfield_bit_offset = 0;496 bool child_is_base_class = false;497 bool child_is_deref_of_parent = false;498 uint64_t language_flags = 0;499 const bool transparent_pointers = true;500 501 ExecutionContext exe_ctx(GetExecutionContextRef());502 503 auto child_compiler_type_or_err =504 GetCompilerType().GetChildCompilerTypeAtIndex(505 &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,506 ignore_array_bounds, child_name, child_byte_size, child_byte_offset,507 child_bitfield_bit_size, child_bitfield_bit_offset,508 child_is_base_class, child_is_deref_of_parent, this, language_flags);509 if (!child_compiler_type_or_err || !child_compiler_type_or_err->IsValid()) {510 LLDB_LOG_ERROR(GetLog(LLDBLog::Types),511 child_compiler_type_or_err.takeError(),512 "could not find child: {0}");513 return nullptr;514 }515 516 return new ValueObjectChild(517 *this, *child_compiler_type_or_err, ConstString(child_name),518 child_byte_size, child_byte_offset, child_bitfield_bit_size,519 child_bitfield_bit_offset, child_is_base_class, child_is_deref_of_parent,520 eAddressTypeInvalid, language_flags);521}522 523ValueObject *ValueObject::CreateSyntheticArrayMember(size_t idx) {524 bool omit_empty_base_classes = true;525 bool ignore_array_bounds = true;526 std::string child_name;527 uint32_t child_byte_size = 0;528 int32_t child_byte_offset = 0;529 uint32_t child_bitfield_bit_size = 0;530 uint32_t child_bitfield_bit_offset = 0;531 bool child_is_base_class = false;532 bool child_is_deref_of_parent = false;533 uint64_t language_flags = 0;534 const bool transparent_pointers = false;535 536 ExecutionContext exe_ctx(GetExecutionContextRef());537 538 auto child_compiler_type_or_err =539 GetCompilerType().GetChildCompilerTypeAtIndex(540 &exe_ctx, 0, transparent_pointers, omit_empty_base_classes,541 ignore_array_bounds, child_name, child_byte_size, child_byte_offset,542 child_bitfield_bit_size, child_bitfield_bit_offset,543 child_is_base_class, child_is_deref_of_parent, this, language_flags);544 if (!child_compiler_type_or_err) {545 LLDB_LOG_ERROR(GetLog(LLDBLog::Types),546 child_compiler_type_or_err.takeError(),547 "could not find child: {0}");548 return nullptr;549 }550 551 if (child_compiler_type_or_err->IsValid()) {552 child_byte_offset += child_byte_size * idx;553 554 return new ValueObjectChild(555 *this, *child_compiler_type_or_err, ConstString(child_name),556 child_byte_size, child_byte_offset, child_bitfield_bit_size,557 child_bitfield_bit_offset, child_is_base_class,558 child_is_deref_of_parent, eAddressTypeInvalid, language_flags);559 }560 561 // In case of an incomplete type, try to use the ValueObject's562 // synthetic value to create the child ValueObject.563 if (ValueObjectSP synth_valobj_sp = GetSyntheticValue())564 return synth_valobj_sp->GetChildAtIndex(idx, /*can_create=*/true).get();565 566 return nullptr;567}568 569bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,570 std::string &destination,571 lldb::LanguageType lang) {572 return GetSummaryAsCString(summary_ptr, destination,573 TypeSummaryOptions().SetLanguage(lang));574}575 576bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr,577 std::string &destination,578 const TypeSummaryOptions &options) {579 destination.clear();580 581 // If we have a forcefully completed type, don't try and show a summary from582 // a valid summary string or function because the type is not complete and583 // no member variables or member functions will be available.584 if (GetCompilerType().IsForcefullyCompleted()) {585 destination = "<incomplete type>";586 return true;587 }588 589 // ideally we would like to bail out if passing NULL, but if we do so we end590 // up not providing the summary for function pointers anymore591 if (/*summary_ptr == NULL ||*/ m_flags.m_is_getting_summary)592 return false;593 594 m_flags.m_is_getting_summary = true;595 596 TypeSummaryOptions actual_options(options);597 598 if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)599 actual_options.SetLanguage(GetPreferredDisplayLanguage());600 601 // this is a hot path in code and we prefer to avoid setting this string all602 // too often also clearing out other information that we might care to see in603 // a crash log. might be useful in very specific situations though.604 /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s.605 Summary provider's description is %s",606 GetTypeName().GetCString(),607 GetName().GetCString(),608 summary_ptr->GetDescription().c_str());*/609 610 if (UpdateValueIfNeeded(false) && summary_ptr) {611 if (HasSyntheticValue())612 m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on613 // the synthetic children being614 // up-to-date (e.g. ${svar%#})615 616 if (TargetSP target_sp = GetExecutionContextRef().GetTargetSP()) {617 SummaryStatisticsSP stats_sp =618 target_sp->GetSummaryStatisticsCache()619 .GetSummaryStatisticsForProvider(*summary_ptr);620 621 // Construct RAII types to time and collect data on summary creation.622 SummaryStatistics::SummaryInvocation invocation(stats_sp);623 summary_ptr->FormatObject(this, destination, actual_options);624 } else625 summary_ptr->FormatObject(this, destination, actual_options);626 }627 m_flags.m_is_getting_summary = false;628 return !destination.empty();629}630 631const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) {632 if (UpdateValueIfNeeded(true) && m_summary_str.empty()) {633 TypeSummaryOptions summary_options;634 summary_options.SetLanguage(lang);635 GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str,636 summary_options);637 }638 if (m_summary_str.empty())639 return nullptr;640 return m_summary_str.c_str();641}642 643bool ValueObject::GetSummaryAsCString(std::string &destination,644 const TypeSummaryOptions &options) {645 return GetSummaryAsCString(GetSummaryFormat().get(), destination, options);646}647 648bool ValueObject::IsCStringContainer(bool check_pointer) {649 CompilerType pointee_or_element_compiler_type;650 const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type));651 bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&652 pointee_or_element_compiler_type.IsCharType());653 if (!is_char_arr_ptr)654 return false;655 if (!check_pointer)656 return true;657 if (type_flags.Test(eTypeIsArray))658 return true;659 addr_t cstr_address = GetPointerValue().address;660 return (cstr_address != LLDB_INVALID_ADDRESS);661}662 663size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,664 uint32_t item_count) {665 CompilerType pointee_or_element_compiler_type;666 const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type);667 const bool is_pointer_type = type_info & eTypeIsPointer;668 const bool is_array_type = type_info & eTypeIsArray;669 if (!(is_pointer_type || is_array_type))670 return 0;671 672 if (item_count == 0)673 return 0;674 675 ExecutionContext exe_ctx(GetExecutionContextRef());676 677 std::optional<uint64_t> item_type_size =678 llvm::expectedToOptional(pointee_or_element_compiler_type.GetByteSize(679 exe_ctx.GetBestExecutionContextScope()));680 if (!item_type_size)681 return 0;682 const uint64_t bytes = item_count * *item_type_size;683 const uint64_t offset = item_idx * *item_type_size;684 685 if (item_idx == 0 && item_count == 1) // simply a deref686 {687 if (is_pointer_type) {688 Status error;689 ValueObjectSP pointee_sp = Dereference(error);690 if (error.Fail() || pointee_sp.get() == nullptr)691 return 0;692 return pointee_sp->GetData(data, error);693 } else {694 ValueObjectSP child_sp = GetChildAtIndex(0);695 if (child_sp.get() == nullptr)696 return 0;697 Status error;698 return child_sp->GetData(data, error);699 }700 return true;701 } else /* (items > 1) */702 {703 Status error;704 lldb_private::DataBufferHeap *heap_buf_ptr = nullptr;705 lldb::DataBufferSP data_sp(heap_buf_ptr =706 new lldb_private::DataBufferHeap());707 708 auto [addr, addr_type] =709 is_pointer_type ? GetPointerValue() : GetAddressOf(true);710 711 switch (addr_type) {712 case eAddressTypeFile: {713 ModuleSP module_sp(GetModule());714 if (module_sp) {715 addr = addr + offset;716 Address so_addr;717 module_sp->ResolveFileAddress(addr, so_addr);718 ExecutionContext exe_ctx(GetExecutionContextRef());719 Target *target = exe_ctx.GetTargetPtr();720 if (target) {721 heap_buf_ptr->SetByteSize(bytes);722 size_t bytes_read = target->ReadMemory(723 so_addr, heap_buf_ptr->GetBytes(), bytes, error, true);724 if (error.Success()) {725 data.SetData(data_sp);726 return bytes_read;727 }728 }729 }730 } break;731 case eAddressTypeLoad: {732 ExecutionContext exe_ctx(GetExecutionContextRef());733 if (Target *target = exe_ctx.GetTargetPtr()) {734 heap_buf_ptr->SetByteSize(bytes);735 Address target_addr;736 target_addr.SetLoadAddress(addr + offset, target);737 size_t bytes_read =738 target->ReadMemory(target_addr, heap_buf_ptr->GetBytes(), bytes,739 error, /*force_live_memory=*/true);740 if (error.Success() || bytes_read > 0) {741 data.SetData(data_sp);742 return bytes_read;743 }744 }745 } break;746 case eAddressTypeHost: {747 auto max_bytes =748 GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());749 if (max_bytes && *max_bytes > offset) {750 size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);751 addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);752 if (addr == 0 || addr == LLDB_INVALID_ADDRESS)753 break;754 heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read);755 data.SetData(data_sp);756 return bytes_read;757 }758 } break;759 case eAddressTypeInvalid:760 break;761 }762 }763 return 0;764}765 766uint64_t ValueObject::GetData(DataExtractor &data, Status &error) {767 UpdateValueIfNeeded(false);768 ExecutionContext exe_ctx(GetExecutionContextRef());769 error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());770 if (error.Fail()) {771 if (m_data.GetByteSize()) {772 data = m_data;773 error.Clear();774 return data.GetByteSize();775 } else {776 return 0;777 }778 }779 data.SetAddressByteSize(m_data.GetAddressByteSize());780 data.SetByteOrder(m_data.GetByteOrder());781 return data.GetByteSize();782}783 784bool ValueObject::SetData(DataExtractor &data, Status &error) {785 error.Clear();786 // Make sure our value is up to date first so that our location and location787 // type is valid.788 if (!UpdateValueIfNeeded(false)) {789 error = Status::FromErrorString("unable to read value");790 return false;791 }792 793 const Encoding encoding = GetCompilerType().GetEncoding();794 795 const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);796 797 Value::ValueType value_type = m_value.GetValueType();798 799 switch (value_type) {800 case Value::ValueType::Invalid:801 error = Status::FromErrorString("invalid location");802 return false;803 case Value::ValueType::Scalar: {804 Status set_error =805 m_value.GetScalar().SetValueFromData(data, encoding, byte_size);806 807 if (!set_error.Success()) {808 error = Status::FromErrorStringWithFormat(809 "unable to set scalar value: %s", set_error.AsCString());810 return false;811 }812 } break;813 case Value::ValueType::LoadAddress: {814 // If it is a load address, then the scalar value is the storage location815 // of the data, and we have to shove this value down to that load location.816 ExecutionContext exe_ctx(GetExecutionContextRef());817 Process *process = exe_ctx.GetProcessPtr();818 if (process) {819 addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);820 size_t bytes_written = process->WriteMemory(821 target_addr, data.GetDataStart(), byte_size, error);822 if (!error.Success())823 return false;824 if (bytes_written != byte_size) {825 error = Status::FromErrorString("unable to write value to memory");826 return false;827 }828 }829 } break;830 case Value::ValueType::HostAddress: {831 // If it is a host address, then we stuff the scalar as a DataBuffer into832 // the Value's data.833 DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));834 m_data.SetData(buffer_sp, 0);835 data.CopyByteOrderedData(0, byte_size,836 const_cast<uint8_t *>(m_data.GetDataStart()),837 byte_size, m_data.GetByteOrder());838 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();839 } break;840 case Value::ValueType::FileAddress:841 break;842 }843 844 // If we have reached this point, then we have successfully changed the845 // value.846 SetNeedsUpdate();847 return true;848}849 850llvm::ArrayRef<uint8_t> ValueObject::GetLocalBuffer() const {851 if (m_value.GetValueType() != Value::ValueType::HostAddress)852 return {};853 auto start = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);854 if (start == LLDB_INVALID_ADDRESS)855 return {};856 // Does our pointer point to this value object's m_data buffer?857 if ((uint64_t)m_data.GetDataStart() == start)858 return m_data.GetData();859 // Does our pointer point to the value's buffer?860 if ((uint64_t)m_value.GetBuffer().GetBytes() == start)861 return m_value.GetBuffer().GetData();862 // Our pointer points to something else. We can't know what the size is.863 return {};864}865 866static bool CopyStringDataToBufferSP(const StreamString &source,867 lldb::WritableDataBufferSP &destination) {868 llvm::StringRef src = source.GetString();869 src = src.rtrim('\0');870 destination = std::make_shared<DataBufferHeap>(src.size(), 0);871 memcpy(destination->GetBytes(), src.data(), src.size());872 return true;873}874 875std::pair<size_t, bool>876ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,877 Status &error, bool honor_array) {878 bool was_capped = false;879 StreamString s;880 ExecutionContext exe_ctx(GetExecutionContextRef());881 Target *target = exe_ctx.GetTargetPtr();882 883 if (!target) {884 s << "<no target to read from>";885 error = Status::FromErrorString("no target to read from");886 CopyStringDataToBufferSP(s, buffer_sp);887 return {0, was_capped};888 }889 890 const auto max_length = target->GetMaximumSizeOfStringSummary();891 892 size_t bytes_read = 0;893 size_t total_bytes_read = 0;894 895 CompilerType compiler_type = GetCompilerType();896 CompilerType elem_or_pointee_compiler_type;897 const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type));898 if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) &&899 elem_or_pointee_compiler_type.IsCharType()) {900 AddrAndType cstr_address;901 902 size_t cstr_len = 0;903 bool capped_data = false;904 const bool is_array = type_flags.Test(eTypeIsArray);905 if (is_array) {906 // We have an array907 uint64_t array_size = 0;908 if (compiler_type.IsArrayType(nullptr, &array_size)) {909 cstr_len = array_size;910 if (cstr_len > max_length) {911 capped_data = true;912 cstr_len = max_length;913 }914 }915 cstr_address = GetAddressOf(true);916 } else {917 // We have a pointer918 cstr_address = GetPointerValue();919 }920 921 if (cstr_address.address == 0 ||922 cstr_address.address == LLDB_INVALID_ADDRESS) {923 if (cstr_address.type == eAddressTypeHost && is_array) {924 const char *cstr = GetDataExtractor().PeekCStr(0);925 if (cstr == nullptr) {926 s << "<invalid address>";927 error = Status::FromErrorString("invalid address");928 CopyStringDataToBufferSP(s, buffer_sp);929 return {0, was_capped};930 }931 s << llvm::StringRef(cstr, cstr_len);932 CopyStringDataToBufferSP(s, buffer_sp);933 return {cstr_len, was_capped};934 } else {935 s << "<invalid address>";936 error = Status::FromErrorString("invalid address");937 CopyStringDataToBufferSP(s, buffer_sp);938 return {0, was_capped};939 }940 }941 942 Address cstr_so_addr(cstr_address.address);943 DataExtractor data;944 if (cstr_len > 0 && honor_array) {945 // I am using GetPointeeData() here to abstract the fact that some946 // ValueObjects are actually frozen pointers in the host but the pointed-947 // to data lives in the debuggee, and GetPointeeData() automatically948 // takes care of this949 GetPointeeData(data, 0, cstr_len);950 951 if ((bytes_read = data.GetByteSize()) > 0) {952 total_bytes_read = bytes_read;953 for (size_t offset = 0; offset < bytes_read; offset++)954 s.Printf("%c", *data.PeekData(offset, 1));955 if (capped_data)956 was_capped = true;957 }958 } else {959 cstr_len = max_length;960 const size_t k_max_buf_size = 64;961 962 size_t offset = 0;963 964 int cstr_len_displayed = -1;965 bool capped_cstr = false;966 // I am using GetPointeeData() here to abstract the fact that some967 // ValueObjects are actually frozen pointers in the host but the pointed-968 // to data lives in the debuggee, and GetPointeeData() automatically969 // takes care of this970 while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) {971 total_bytes_read += bytes_read;972 const char *cstr = data.PeekCStr(0);973 size_t len = strnlen(cstr, k_max_buf_size);974 if (cstr_len_displayed < 0)975 cstr_len_displayed = len;976 977 if (len == 0)978 break;979 cstr_len_displayed += len;980 if (len > bytes_read)981 len = bytes_read;982 if (len > cstr_len)983 len = cstr_len;984 985 for (size_t offset = 0; offset < bytes_read; offset++)986 s.Printf("%c", *data.PeekData(offset, 1));987 988 if (len < k_max_buf_size)989 break;990 991 if (len >= cstr_len) {992 capped_cstr = true;993 break;994 }995 996 cstr_len -= len;997 offset += len;998 }999 1000 if (cstr_len_displayed >= 0) {1001 if (capped_cstr)1002 was_capped = true;1003 }1004 }1005 } else {1006 error = Status::FromErrorString("not a string object");1007 s << "<not a string object>";1008 }1009 CopyStringDataToBufferSP(s, buffer_sp);1010 return {total_bytes_read, was_capped};1011}1012 1013llvm::Expected<std::string> ValueObject::GetObjectDescription() {1014 if (!UpdateValueIfNeeded(true))1015 return llvm::createStringError("could not update value");1016 1017 // Return cached value.1018 if (!m_object_desc_str.empty())1019 return m_object_desc_str;1020 1021 ExecutionContext exe_ctx(GetExecutionContextRef());1022 Process *process = exe_ctx.GetProcessPtr();1023 if (!process)1024 return llvm::createStringError("no process");1025 1026 // Returns the object description produced by one language runtime.1027 auto get_object_description =1028 [&](LanguageType language) -> llvm::Expected<std::string> {1029 if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {1030 StreamString s;1031 if (llvm::Error error = runtime->GetObjectDescription(s, *this))1032 return error;1033 m_object_desc_str = s.GetString();1034 return m_object_desc_str;1035 }1036 return llvm::createStringError("no native language runtime");1037 };1038 1039 // Try the native language runtime first.1040 LanguageType native_language = GetObjectRuntimeLanguage();1041 llvm::Expected<std::string> desc = get_object_description(native_language);1042 if (desc)1043 return desc;1044 1045 // Try the Objective-C language runtime. This fallback is necessary1046 // for Objective-C++ and mixed Objective-C / C++ programs.1047 if (Language::LanguageIsCFamily(native_language)) {1048 // We're going to try again, so let's drop the first error.1049 llvm::consumeError(desc.takeError());1050 return get_object_description(eLanguageTypeObjC);1051 }1052 return desc;1053}1054 1055bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,1056 std::string &destination) {1057 if (UpdateValueIfNeeded(false))1058 return format.FormatObject(this, destination);1059 else1060 return false;1061}1062 1063bool ValueObject::GetValueAsCString(lldb::Format format,1064 std::string &destination) {1065 return GetValueAsCString(TypeFormatImpl_Format(format), destination);1066}1067 1068const char *ValueObject::GetValueAsCString() {1069 if (UpdateValueIfNeeded(true)) {1070 lldb::TypeFormatImplSP format_sp;1071 lldb::Format my_format = GetFormat();1072 if (my_format == lldb::eFormatDefault) {1073 if (m_type_format_sp)1074 format_sp = m_type_format_sp;1075 else {1076 if (m_flags.m_is_bitfield_for_scalar)1077 my_format = eFormatUnsigned;1078 else {1079 if (m_value.GetContextType() == Value::ContextType::RegisterInfo) {1080 const RegisterInfo *reg_info = m_value.GetRegisterInfo();1081 if (reg_info)1082 my_format = reg_info->format;1083 } else {1084 my_format = GetValue().GetCompilerType().GetFormat();1085 }1086 }1087 }1088 }1089 if (my_format != m_last_format || m_value_str.empty()) {1090 m_last_format = my_format;1091 if (!format_sp)1092 format_sp = std::make_shared<TypeFormatImpl_Format>(my_format);1093 if (GetValueAsCString(*format_sp.get(), m_value_str)) {1094 if (!m_flags.m_value_did_change && m_flags.m_old_value_valid) {1095 // The value was gotten successfully, so we consider the value as1096 // changed if the value string differs1097 SetValueDidChange(m_old_value_str != m_value_str);1098 }1099 }1100 }1101 }1102 if (m_value_str.empty())1103 return nullptr;1104 return m_value_str.c_str();1105}1106 1107// if > 8bytes, 0 is returned. this method should mostly be used to read1108// address values out of pointers1109uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) {1110 // If our byte size is zero this is an aggregate type that has children1111 if (CanProvideValue()) {1112 Scalar scalar;1113 if (ResolveValue(scalar)) {1114 if (success)1115 *success = true;1116 scalar.MakeUnsigned();1117 return scalar.ULongLong(fail_value);1118 }1119 // fallthrough, otherwise...1120 }1121 1122 if (success)1123 *success = false;1124 return fail_value;1125}1126 1127int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {1128 // If our byte size is zero this is an aggregate type that has children1129 if (CanProvideValue()) {1130 Scalar scalar;1131 if (ResolveValue(scalar)) {1132 if (success)1133 *success = true;1134 scalar.MakeSigned();1135 return scalar.SLongLong(fail_value);1136 }1137 // fallthrough, otherwise...1138 }1139 1140 if (success)1141 *success = false;1142 return fail_value;1143}1144 1145llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {1146 // Make sure the type can be converted to an APSInt.1147 if (!GetCompilerType().IsInteger() &&1148 !GetCompilerType().IsScopedEnumerationType() &&1149 !GetCompilerType().IsEnumerationType() &&1150 !GetCompilerType().IsPointerType() &&1151 !GetCompilerType().IsNullPtrType() &&1152 !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())1153 return llvm::make_error<llvm::StringError>(1154 "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());1155 1156 if (CanProvideValue()) {1157 Scalar scalar;1158 if (ResolveValue(scalar))1159 return scalar.GetAPSInt();1160 }1161 1162 return llvm::make_error<llvm::StringError>(1163 "error occurred; unable to convert to APSInt",1164 llvm::inconvertibleErrorCode());1165}1166 1167llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {1168 if (!GetCompilerType().IsFloat())1169 return llvm::make_error<llvm::StringError>(1170 "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());1171 1172 if (CanProvideValue()) {1173 Scalar scalar;1174 if (ResolveValue(scalar))1175 return scalar.GetAPFloat();1176 }1177 1178 return llvm::make_error<llvm::StringError>(1179 "error occurred; unable to convert to APFloat",1180 llvm::inconvertibleErrorCode());1181}1182 1183llvm::Expected<bool> ValueObject::GetValueAsBool() {1184 CompilerType val_type = GetCompilerType();1185 if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||1186 val_type.IsPointerType()) {1187 auto value_or_err = GetValueAsAPSInt();1188 if (value_or_err)1189 return value_or_err->getBoolValue();1190 }1191 if (val_type.IsFloat()) {1192 auto value_or_err = GetValueAsAPFloat();1193 if (value_or_err)1194 return value_or_err->isNonZero();1195 }1196 if (val_type.IsArrayType())1197 return GetAddressOf().address != 0;1198 1199 return llvm::make_error<llvm::StringError>("type cannot be converted to bool",1200 llvm::inconvertibleErrorCode());1201}1202 1203void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {1204 // Verify the current object is an integer object1205 CompilerType val_type = GetCompilerType();1206 if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1207 !val_type.IsFloat() && !val_type.IsPointerType() &&1208 !val_type.IsScalarType()) {1209 error =1210 Status::FromErrorString("current value object is not an integer objet");1211 return;1212 }1213 1214 // Verify the current object is not actually associated with any program1215 // variable.1216 if (GetVariable()) {1217 error = Status::FromErrorString(1218 "current value object is not a temporary object");1219 return;1220 }1221 1222 // Verify the proposed new value is the right size.1223 lldb::TargetSP target = GetTargetSP();1224 uint64_t byte_size = 0;1225 if (auto temp =1226 llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))1227 byte_size = temp.value();1228 if (value.getBitWidth() != byte_size * CHAR_BIT) {1229 error = Status::FromErrorString(1230 "illegal argument: new value should be of the same size");1231 return;1232 }1233 1234 lldb::DataExtractorSP data_sp;1235 data_sp->SetData(value.getRawData(), byte_size,1236 target->GetArchitecture().GetByteOrder());1237 data_sp->SetAddressByteSize(1238 static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));1239 SetData(*data_sp, error);1240}1241 1242void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,1243 Status &error) {1244 // Verify the current object is an integer object1245 CompilerType val_type = GetCompilerType();1246 if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&1247 !val_type.IsFloat() && !val_type.IsPointerType() &&1248 !val_type.IsScalarType()) {1249 error =1250 Status::FromErrorString("current value object is not an integer objet");1251 return;1252 }1253 1254 // Verify the current object is not actually associated with any program1255 // variable.1256 if (GetVariable()) {1257 error = Status::FromErrorString(1258 "current value object is not a temporary object");1259 return;1260 }1261 1262 // Verify the proposed new value is the right type.1263 CompilerType new_val_type = new_val_sp->GetCompilerType();1264 if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&1265 !new_val_type.IsPointerType()) {1266 error = Status::FromErrorString(1267 "illegal argument: new value should be of the same size");1268 return;1269 }1270 1271 if (new_val_type.IsInteger()) {1272 auto value_or_err = new_val_sp->GetValueAsAPSInt();1273 if (value_or_err)1274 SetValueFromInteger(*value_or_err, error);1275 else1276 error = Status::FromErrorString("error getting APSInt from new_val_sp");1277 } else if (new_val_type.IsFloat()) {1278 auto value_or_err = new_val_sp->GetValueAsAPFloat();1279 if (value_or_err)1280 SetValueFromInteger(value_or_err->bitcastToAPInt(), error);1281 else1282 error = Status::FromErrorString("error getting APFloat from new_val_sp");1283 } else if (new_val_type.IsPointerType()) {1284 bool success = true;1285 uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);1286 if (success) {1287 lldb::TargetSP target = GetTargetSP();1288 uint64_t num_bits = 0;1289 if (auto temp = llvm::expectedToOptional(1290 new_val_sp->GetCompilerType().GetBitSize(target.get())))1291 num_bits = temp.value();1292 SetValueFromInteger(llvm::APInt(num_bits, int_val), error);1293 } else1294 error = Status::FromErrorString("error converting new_val_sp to integer");1295 }1296}1297 1298// if any more "special cases" are added to1299// ValueObject::DumpPrintableRepresentation() please keep this call up to date1300// by returning true for your new special cases. We will eventually move to1301// checking this call result before trying to display special cases1302bool ValueObject::HasSpecialPrintableRepresentation(1303 ValueObjectRepresentationStyle val_obj_display, Format custom_format) {1304 Flags flags(GetTypeInfo());1305 if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1306 val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1307 if (IsCStringContainer(true) &&1308 (custom_format == eFormatCString || custom_format == eFormatCharArray ||1309 custom_format == eFormatChar || custom_format == eFormatVectorOfChar))1310 return true;1311 1312 if (flags.Test(eTypeIsArray)) {1313 if ((custom_format == eFormatBytes) ||1314 (custom_format == eFormatBytesWithASCII))1315 return true;1316 1317 if ((custom_format == eFormatVectorOfChar) ||1318 (custom_format == eFormatVectorOfFloat32) ||1319 (custom_format == eFormatVectorOfFloat64) ||1320 (custom_format == eFormatVectorOfSInt16) ||1321 (custom_format == eFormatVectorOfSInt32) ||1322 (custom_format == eFormatVectorOfSInt64) ||1323 (custom_format == eFormatVectorOfSInt8) ||1324 (custom_format == eFormatVectorOfUInt128) ||1325 (custom_format == eFormatVectorOfUInt16) ||1326 (custom_format == eFormatVectorOfUInt32) ||1327 (custom_format == eFormatVectorOfUInt64) ||1328 (custom_format == eFormatVectorOfUInt8))1329 return true;1330 }1331 }1332 return false;1333}1334 1335bool ValueObject::DumpPrintableRepresentation(1336 Stream &s, ValueObjectRepresentationStyle val_obj_display,1337 Format custom_format, PrintableRepresentationSpecialCases special,1338 bool do_dump_error) {1339 1340 // If the ValueObject has an error, we might end up dumping the type, which1341 // is useful, but if we don't even have a type, then don't examine the object1342 // further as that's not meaningful, only the error is.1343 if (m_error.Fail() && !GetCompilerType().IsValid()) {1344 if (do_dump_error)1345 s.Printf("<%s>", m_error.AsCString());1346 return false;1347 }1348 1349 Flags flags(GetTypeInfo());1350 1351 bool allow_special =1352 (special == ValueObject::PrintableRepresentationSpecialCases::eAllow);1353 const bool only_special = false;1354 1355 if (allow_special) {1356 if (flags.AnySet(eTypeIsArray | eTypeIsPointer) &&1357 val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) {1358 // when being asked to get a printable display an array or pointer type1359 // directly, try to "do the right thing"1360 1361 if (IsCStringContainer(true) &&1362 (custom_format == eFormatCString ||1363 custom_format == eFormatCharArray || custom_format == eFormatChar ||1364 custom_format ==1365 eFormatVectorOfChar)) // print char[] & char* directly1366 {1367 Status error;1368 lldb::WritableDataBufferSP buffer_sp;1369 std::pair<size_t, bool> read_string =1370 ReadPointedString(buffer_sp, error,1371 (custom_format == eFormatVectorOfChar) ||1372 (custom_format == eFormatCharArray));1373 lldb_private::formatters::StringPrinter::1374 ReadBufferAndDumpToStreamOptions options(*this);1375 options.SetData(DataExtractor(1376 buffer_sp, lldb::eByteOrderInvalid,1377 8)); // none of this matters for a string - pass some defaults1378 options.SetStream(&s);1379 options.SetPrefixToken(nullptr);1380 options.SetQuote('"');1381 options.SetSourceSize(buffer_sp->GetByteSize());1382 options.SetIsTruncated(read_string.second);1383 options.SetBinaryZeroIsTerminator(custom_format != eFormatVectorOfChar);1384 formatters::StringPrinter::ReadBufferAndDumpToStream<1385 lldb_private::formatters::StringPrinter::StringElementType::ASCII>(1386 options);1387 return !error.Fail();1388 }1389 1390 if (custom_format == eFormatEnum)1391 return false;1392 1393 // this only works for arrays, because I have no way to know when the1394 // pointed memory ends, and no special \0 end of data marker1395 if (flags.Test(eTypeIsArray)) {1396 if ((custom_format == eFormatBytes) ||1397 (custom_format == eFormatBytesWithASCII)) {1398 const size_t count = GetNumChildrenIgnoringErrors();1399 1400 s << '[';1401 for (size_t low = 0; low < count; low++) {1402 1403 if (low)1404 s << ',';1405 1406 ValueObjectSP child = GetChildAtIndex(low);1407 if (!child.get()) {1408 s << "<invalid child>";1409 continue;1410 }1411 child->DumpPrintableRepresentation(1412 s, ValueObject::eValueObjectRepresentationStyleValue,1413 custom_format);1414 }1415 1416 s << ']';1417 1418 return true;1419 }1420 1421 if ((custom_format == eFormatVectorOfChar) ||1422 (custom_format == eFormatVectorOfFloat32) ||1423 (custom_format == eFormatVectorOfFloat64) ||1424 (custom_format == eFormatVectorOfSInt16) ||1425 (custom_format == eFormatVectorOfSInt32) ||1426 (custom_format == eFormatVectorOfSInt64) ||1427 (custom_format == eFormatVectorOfSInt8) ||1428 (custom_format == eFormatVectorOfUInt128) ||1429 (custom_format == eFormatVectorOfUInt16) ||1430 (custom_format == eFormatVectorOfUInt32) ||1431 (custom_format == eFormatVectorOfUInt64) ||1432 (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes1433 // with ASCII or any vector1434 // format should be printed1435 // directly1436 {1437 const size_t count = GetNumChildrenIgnoringErrors();1438 1439 Format format = FormatManager::GetSingleItemFormat(custom_format);1440 1441 s << '[';1442 for (size_t low = 0; low < count; low++) {1443 1444 if (low)1445 s << ',';1446 1447 ValueObjectSP child = GetChildAtIndex(low);1448 if (!child.get()) {1449 s << "<invalid child>";1450 continue;1451 }1452 child->DumpPrintableRepresentation(1453 s, ValueObject::eValueObjectRepresentationStyleValue, format);1454 }1455 1456 s << ']';1457 1458 return true;1459 }1460 }1461 1462 if ((custom_format == eFormatBoolean) ||1463 (custom_format == eFormatBinary) || (custom_format == eFormatChar) ||1464 (custom_format == eFormatCharPrintable) ||1465 (custom_format == eFormatComplexFloat) ||1466 (custom_format == eFormatDecimal) || (custom_format == eFormatHex) ||1467 (custom_format == eFormatHexUppercase) ||1468 (custom_format == eFormatFloat) ||1469 (custom_format == eFormatFloat128) ||1470 (custom_format == eFormatOctal) || (custom_format == eFormatOSType) ||1471 (custom_format == eFormatUnicode16) ||1472 (custom_format == eFormatUnicode32) ||1473 (custom_format == eFormatUnsigned) ||1474 (custom_format == eFormatPointer) ||1475 (custom_format == eFormatComplexInteger) ||1476 (custom_format == eFormatComplex) ||1477 (custom_format == eFormatDefault)) // use the [] operator1478 return false;1479 }1480 }1481 1482 if (only_special)1483 return false;1484 1485 bool var_success = false;1486 1487 {1488 llvm::StringRef str;1489 1490 // this is a local stream that we are using to ensure that the data pointed1491 // to by cstr survives long enough for us to copy it to its destination -1492 // it is necessary to have this temporary storage area for cases where our1493 // desired output is not backed by some other longer-term storage1494 StreamString strm;1495 1496 if (custom_format != eFormatInvalid)1497 SetFormat(custom_format);1498 1499 switch (val_obj_display) {1500 case eValueObjectRepresentationStyleValue:1501 str = GetValueAsCString();1502 break;1503 1504 case eValueObjectRepresentationStyleSummary:1505 str = GetSummaryAsCString();1506 break;1507 1508 case eValueObjectRepresentationStyleLanguageSpecific: {1509 llvm::Expected<std::string> desc = GetObjectDescription();1510 if (!desc) {1511 strm << "error: " << toString(desc.takeError());1512 str = strm.GetString();1513 } else {1514 strm << *desc;1515 str = strm.GetString();1516 }1517 } break;1518 1519 case eValueObjectRepresentationStyleLocation:1520 str = GetLocationAsCString();1521 break;1522 1523 case eValueObjectRepresentationStyleChildrenCount: {1524 if (auto err = GetNumChildren()) {1525 strm.Printf("%" PRIu32, *err);1526 str = strm.GetString();1527 } else {1528 strm << "error: " << toString(err.takeError());1529 str = strm.GetString();1530 }1531 break;1532 }1533 1534 case eValueObjectRepresentationStyleType:1535 str = GetTypeName().GetStringRef();1536 break;1537 1538 case eValueObjectRepresentationStyleName:1539 str = GetName().GetStringRef();1540 break;1541 1542 case eValueObjectRepresentationStyleExpressionPath:1543 GetExpressionPath(strm);1544 str = strm.GetString();1545 break;1546 }1547 1548 // If the requested display style produced no output, try falling back to1549 // alternative presentations.1550 if (str.empty()) {1551 if (val_obj_display == eValueObjectRepresentationStyleValue)1552 str = GetSummaryAsCString();1553 else if (val_obj_display == eValueObjectRepresentationStyleSummary) {1554 if (!CanProvideValue()) {1555 strm.Printf("%s @ %s", GetTypeName().AsCString(),1556 GetLocationAsCString());1557 str = strm.GetString();1558 } else1559 str = GetValueAsCString();1560 }1561 }1562 1563 if (!str.empty())1564 s << str;1565 else {1566 // We checked for errors at the start, but do it again here in case1567 // realizing the value for dumping produced an error.1568 if (m_error.Fail()) {1569 if (do_dump_error)1570 s.Printf("<%s>", m_error.AsCString());1571 else1572 return false;1573 } else if (val_obj_display == eValueObjectRepresentationStyleSummary)1574 s.PutCString("<no summary available>");1575 else if (val_obj_display == eValueObjectRepresentationStyleValue)1576 s.PutCString("<no value available>");1577 else if (val_obj_display ==1578 eValueObjectRepresentationStyleLanguageSpecific)1579 s.PutCString("<not a valid Objective-C object>"); // edit this if we1580 // have other runtimes1581 // that support a1582 // description1583 else1584 s.PutCString("<no printable representation>");1585 }1586 1587 // we should only return false here if we could not do *anything* even if1588 // we have an error message as output, that's a success from our callers'1589 // perspective, so return true1590 var_success = true;1591 1592 if (custom_format != eFormatInvalid)1593 SetFormat(eFormatDefault);1594 }1595 1596 return var_success;1597}1598 1599ValueObject::AddrAndType1600ValueObject::GetAddressOf(bool scalar_is_load_address) {1601 // Can't take address of a bitfield1602 if (IsBitfield())1603 return {};1604 1605 if (!UpdateValueIfNeeded(false))1606 return {};1607 1608 switch (m_value.GetValueType()) {1609 case Value::ValueType::Invalid:1610 return {};1611 case Value::ValueType::Scalar:1612 if (scalar_is_load_address) {1613 return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1614 eAddressTypeLoad};1615 }1616 return {};1617 1618 case Value::ValueType::LoadAddress:1619 case Value::ValueType::FileAddress:1620 return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1621 m_value.GetValueAddressType()};1622 case Value::ValueType::HostAddress:1623 return {LLDB_INVALID_ADDRESS, m_value.GetValueAddressType()};1624 }1625 llvm_unreachable("Unhandled value type!");1626}1627 1628ValueObject::AddrAndType ValueObject::GetPointerValue() {1629 if (!UpdateValueIfNeeded(false))1630 return {};1631 1632 switch (m_value.GetValueType()) {1633 case Value::ValueType::Invalid:1634 return {};1635 case Value::ValueType::Scalar:1636 return {m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS),1637 GetAddressTypeOfChildren()};1638 1639 case Value::ValueType::HostAddress:1640 case Value::ValueType::LoadAddress:1641 case Value::ValueType::FileAddress: {1642 lldb::offset_t data_offset = 0;1643 return {m_data.GetAddress(&data_offset), GetAddressTypeOfChildren()};1644 }1645 }1646 1647 llvm_unreachable("Unhandled value type!");1648}1649 1650static const char *ConvertBoolean(lldb::LanguageType language_type,1651 const char *value_str) {1652 if (Language *language = Language::FindPlugin(language_type))1653 if (auto boolean = language->GetBooleanFromString(value_str))1654 return *boolean ? "1" : "0";1655 1656 return llvm::StringSwitch<const char *>(value_str)1657 .Case("true", "1")1658 .Case("false", "0")1659 .Default(value_str);1660}1661 1662bool ValueObject::SetValueFromCString(const char *value_str, Status &error) {1663 error.Clear();1664 // Make sure our value is up to date first so that our location and location1665 // type is valid.1666 if (!UpdateValueIfNeeded(false)) {1667 error = Status::FromErrorString("unable to read value");1668 return false;1669 }1670 1671 const Encoding encoding = GetCompilerType().GetEncoding();1672 1673 const size_t byte_size = llvm::expectedToOptional(GetByteSize()).value_or(0);1674 1675 Value::ValueType value_type = m_value.GetValueType();1676 1677 if (value_type == Value::ValueType::Scalar) {1678 // If the value is already a scalar, then let the scalar change itself:1679 m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size);1680 } else if (byte_size <= 16) {1681 if (GetCompilerType().IsBoolean())1682 value_str = ConvertBoolean(GetObjectRuntimeLanguage(), value_str);1683 1684 // If the value fits in a scalar, then make a new scalar and again let the1685 // scalar code do the conversion, then figure out where to put the new1686 // value.1687 Scalar new_scalar;1688 error = new_scalar.SetValueFromCString(value_str, encoding, byte_size);1689 if (error.Success()) {1690 switch (value_type) {1691 case Value::ValueType::LoadAddress: {1692 // If it is a load address, then the scalar value is the storage1693 // location of the data, and we have to shove this value down to that1694 // load location.1695 ExecutionContext exe_ctx(GetExecutionContextRef());1696 Process *process = exe_ctx.GetProcessPtr();1697 if (process) {1698 addr_t target_addr =1699 m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);1700 size_t bytes_written = process->WriteScalarToMemory(1701 target_addr, new_scalar, byte_size, error);1702 if (!error.Success())1703 return false;1704 if (bytes_written != byte_size) {1705 error = Status::FromErrorString("unable to write value to memory");1706 return false;1707 }1708 }1709 } break;1710 case Value::ValueType::HostAddress: {1711 // If it is a host address, then we stuff the scalar as a DataBuffer1712 // into the Value's data.1713 DataExtractor new_data;1714 new_data.SetByteOrder(m_data.GetByteOrder());1715 1716 DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));1717 m_data.SetData(buffer_sp, 0);1718 bool success = new_scalar.GetData(new_data);1719 if (success) {1720 new_data.CopyByteOrderedData(1721 0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()),1722 byte_size, m_data.GetByteOrder());1723 }1724 m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();1725 1726 } break;1727 case Value::ValueType::Invalid:1728 error = Status::FromErrorString("invalid location");1729 return false;1730 case Value::ValueType::FileAddress:1731 case Value::ValueType::Scalar:1732 break;1733 }1734 } else {1735 return false;1736 }1737 } else {1738 // We don't support setting things bigger than a scalar at present.1739 error = Status::FromErrorString("unable to write aggregate data type");1740 return false;1741 }1742 1743 // If we have reached this point, then we have successfully changed the1744 // value.1745 SetNeedsUpdate();1746 return true;1747}1748 1749bool ValueObject::GetDeclaration(Declaration &decl) {1750 decl.Clear();1751 return false;1752}1753 1754void ValueObject::AddSyntheticChild(ConstString key, ValueObject *valobj) {1755 m_synthetic_children[key] = valobj;1756}1757 1758ValueObjectSP ValueObject::GetSyntheticChild(ConstString key) const {1759 ValueObjectSP synthetic_child_sp;1760 std::map<ConstString, ValueObject *>::const_iterator pos =1761 m_synthetic_children.find(key);1762 if (pos != m_synthetic_children.end())1763 synthetic_child_sp = pos->second->GetSP();1764 return synthetic_child_sp;1765}1766 1767bool ValueObject::IsPossibleDynamicType() {1768 ExecutionContext exe_ctx(GetExecutionContextRef());1769 Process *process = exe_ctx.GetProcessPtr();1770 if (process)1771 return process->IsPossibleDynamicValue(*this);1772 else1773 return GetCompilerType().IsPossibleDynamicType(nullptr, true, true);1774}1775 1776bool ValueObject::IsRuntimeSupportValue() {1777 Process *process(GetProcessSP().get());1778 if (!process)1779 return false;1780 1781 // We trust that the compiler did the right thing and marked runtime support1782 // values as artificial.1783 if (!GetVariable() || !GetVariable()->IsArtificial())1784 return false;1785 1786 if (auto *runtime = process->GetLanguageRuntime(GetVariable()->GetLanguage()))1787 if (runtime->IsAllowedRuntimeValue(GetName()))1788 return false;1789 1790 return true;1791}1792 1793bool ValueObject::IsNilReference() {1794 if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1795 return language->IsNilReference(*this);1796 }1797 return false;1798}1799 1800bool ValueObject::IsUninitializedReference() {1801 if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) {1802 return language->IsUninitializedReference(*this);1803 }1804 return false;1805}1806 1807// This allows you to create an array member using and index that doesn't not1808// fall in the normal bounds of the array. Many times structure can be defined1809// as: struct Collection {1810// uint32_t item_count;1811// Item item_array[0];1812// };1813// The size of the "item_array" is 1, but many times in practice there are more1814// items in "item_array".1815 1816ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index,1817 bool can_create) {1818 ValueObjectSP synthetic_child_sp;1819 if (IsPointerType() || IsArrayType()) {1820 std::string index_str = llvm::formatv("[{0}]", index);1821 ConstString index_const_str(index_str);1822 // Check if we have already created a synthetic array member in this valid1823 // object. If we have we will re-use it.1824 synthetic_child_sp = GetSyntheticChild(index_const_str);1825 if (!synthetic_child_sp) {1826 ValueObject *synthetic_child;1827 // We haven't made a synthetic array member for INDEX yet, so lets make1828 // one and cache it for any future reference.1829 synthetic_child = CreateSyntheticArrayMember(index);1830 1831 // Cache the value if we got one back...1832 if (synthetic_child) {1833 AddSyntheticChild(index_const_str, synthetic_child);1834 synthetic_child_sp = synthetic_child->GetSP();1835 synthetic_child_sp->SetName(ConstString(index_str));1836 synthetic_child_sp->m_flags.m_is_array_item_for_pointer = true;1837 }1838 }1839 }1840 return synthetic_child_sp;1841}1842 1843ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to,1844 bool can_create) {1845 ValueObjectSP synthetic_child_sp;1846 if (IsScalarType()) {1847 std::string index_str = llvm::formatv("[{0}-{1}]", from, to);1848 ConstString index_const_str(index_str);1849 // Check if we have already created a synthetic array member in this valid1850 // object. If we have we will re-use it.1851 synthetic_child_sp = GetSyntheticChild(index_const_str);1852 if (!synthetic_child_sp) {1853 uint32_t bit_field_size = to - from + 1;1854 uint32_t bit_field_offset = from;1855 if (GetDataExtractor().GetByteOrder() == eByteOrderBig)1856 bit_field_offset =1857 llvm::expectedToOptional(GetByteSize()).value_or(0) * 8 -1858 bit_field_size - bit_field_offset;1859 // We haven't made a synthetic array member for INDEX yet, so lets make1860 // one and cache it for any future reference.1861 ValueObjectChild *synthetic_child = new ValueObjectChild(1862 *this, GetCompilerType(), index_const_str,1863 llvm::expectedToOptional(GetByteSize()).value_or(0), 0,1864 bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid,1865 0);1866 1867 // Cache the value if we got one back...1868 if (synthetic_child) {1869 AddSyntheticChild(index_const_str, synthetic_child);1870 synthetic_child_sp = synthetic_child->GetSP();1871 synthetic_child_sp->SetName(ConstString(index_str));1872 synthetic_child_sp->m_flags.m_is_bitfield_for_scalar = true;1873 }1874 }1875 }1876 return synthetic_child_sp;1877}1878 1879ValueObjectSP ValueObject::GetSyntheticChildAtOffset(1880 uint32_t offset, const CompilerType &type, bool can_create,1881 ConstString name_const_str) {1882 1883 ValueObjectSP synthetic_child_sp;1884 1885 if (name_const_str.IsEmpty()) {1886 name_const_str.SetString("@" + std::to_string(offset));1887 }1888 1889 // Check if we have already created a synthetic array member in this valid1890 // object. If we have we will re-use it.1891 synthetic_child_sp = GetSyntheticChild(name_const_str);1892 1893 if (synthetic_child_sp.get())1894 return synthetic_child_sp;1895 1896 if (!can_create)1897 return {};1898 1899 ExecutionContext exe_ctx(GetExecutionContextRef());1900 std::optional<uint64_t> size = llvm::expectedToOptional(1901 type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));1902 if (!size)1903 return {};1904 ValueObjectChild *synthetic_child =1905 new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1906 false, false, eAddressTypeInvalid, 0);1907 if (synthetic_child) {1908 AddSyntheticChild(name_const_str, synthetic_child);1909 synthetic_child_sp = synthetic_child->GetSP();1910 synthetic_child_sp->SetName(name_const_str);1911 synthetic_child_sp->m_flags.m_is_child_at_offset = true;1912 }1913 return synthetic_child_sp;1914}1915 1916ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,1917 const CompilerType &type,1918 bool can_create,1919 ConstString name_const_str) {1920 ValueObjectSP synthetic_child_sp;1921 1922 if (name_const_str.IsEmpty()) {1923 char name_str[128];1924 snprintf(name_str, sizeof(name_str), "base%s@%i",1925 type.GetTypeName().AsCString("<unknown>"), offset);1926 name_const_str.SetCString(name_str);1927 }1928 1929 // Check if we have already created a synthetic array member in this valid1930 // object. If we have we will re-use it.1931 synthetic_child_sp = GetSyntheticChild(name_const_str);1932 1933 if (synthetic_child_sp.get())1934 return synthetic_child_sp;1935 1936 if (!can_create)1937 return {};1938 1939 const bool is_base_class = true;1940 1941 ExecutionContext exe_ctx(GetExecutionContextRef());1942 std::optional<uint64_t> size = llvm::expectedToOptional(1943 type.GetByteSize(exe_ctx.GetBestExecutionContextScope()));1944 if (!size)1945 return {};1946 ValueObjectChild *synthetic_child =1947 new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,1948 is_base_class, false, eAddressTypeInvalid, 0);1949 if (synthetic_child) {1950 AddSyntheticChild(name_const_str, synthetic_child);1951 synthetic_child_sp = synthetic_child->GetSP();1952 synthetic_child_sp->SetName(name_const_str);1953 }1954 return synthetic_child_sp;1955}1956 1957// your expression path needs to have a leading . or -> (unless it somehow1958// "looks like" an array, in which case it has a leading [ symbol). while the [1959// is meaningful and should be shown to the user, . and -> are just parser1960// design, but by no means added information for the user.. strip them off1961static const char *SkipLeadingExpressionPathSeparators(const char *expression) {1962 if (!expression || !expression[0])1963 return expression;1964 if (expression[0] == '.')1965 return expression + 1;1966 if (expression[0] == '-' && expression[1] == '>')1967 return expression + 2;1968 return expression;1969}1970 1971ValueObjectSP1972ValueObject::GetSyntheticExpressionPathChild(const char *expression,1973 bool can_create) {1974 ValueObjectSP synthetic_child_sp;1975 ConstString name_const_string(expression);1976 // Check if we have already created a synthetic array member in this valid1977 // object. If we have we will re-use it.1978 synthetic_child_sp = GetSyntheticChild(name_const_string);1979 if (!synthetic_child_sp) {1980 // We haven't made a synthetic array member for expression yet, so lets1981 // make one and cache it for any future reference.1982 synthetic_child_sp = GetValueForExpressionPath(1983 expression, nullptr, nullptr,1984 GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(1985 GetValueForExpressionPathOptions::SyntheticChildrenTraversal::1986 None));1987 1988 // Cache the value if we got one back...1989 if (synthetic_child_sp.get()) {1990 // FIXME: this causes a "real" child to end up with its name changed to1991 // the contents of expression1992 AddSyntheticChild(name_const_string, synthetic_child_sp.get());1993 synthetic_child_sp->SetName(1994 ConstString(SkipLeadingExpressionPathSeparators(expression)));1995 }1996 }1997 return synthetic_child_sp;1998}1999 2000void ValueObject::CalculateSyntheticValue() {2001 TargetSP target_sp(GetTargetSP());2002 if (target_sp && !target_sp->GetEnableSyntheticValue()) {2003 m_synthetic_value = nullptr;2004 return;2005 }2006 2007 lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);2008 2009 if (!UpdateFormatsIfNeeded() && m_synthetic_value)2010 return;2011 2012 if (m_synthetic_children_sp.get() == nullptr)2013 return;2014 2015 if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)2016 return;2017 2018 m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);2019}2020 2021void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) {2022 if (use_dynamic == eNoDynamicValues)2023 return;2024 2025 if (!m_dynamic_value && !IsDynamic()) {2026 ExecutionContext exe_ctx(GetExecutionContextRef());2027 Process *process = exe_ctx.GetProcessPtr();2028 if (process && process->IsPossibleDynamicValue(*this)) {2029 ClearDynamicTypeInformation();2030 m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic);2031 }2032 }2033}2034 2035ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) {2036 if (use_dynamic == eNoDynamicValues)2037 return ValueObjectSP();2038 2039 if (!IsDynamic() && m_dynamic_value == nullptr) {2040 CalculateDynamicValue(use_dynamic);2041 }2042 if (m_dynamic_value && m_dynamic_value->GetError().Success())2043 return m_dynamic_value->GetSP();2044 else2045 return ValueObjectSP();2046}2047 2048ValueObjectSP ValueObject::GetSyntheticValue() {2049 CalculateSyntheticValue();2050 2051 if (m_synthetic_value)2052 return m_synthetic_value->GetSP();2053 else2054 return ValueObjectSP();2055}2056 2057bool ValueObject::HasSyntheticValue() {2058 UpdateFormatsIfNeeded();2059 2060 if (m_synthetic_children_sp.get() == nullptr)2061 return false;2062 2063 CalculateSyntheticValue();2064 2065 return m_synthetic_value != nullptr;2066}2067 2068ValueObject *ValueObject::GetNonBaseClassParent() {2069 if (GetParent()) {2070 if (GetParent()->IsBaseClass())2071 return GetParent()->GetNonBaseClassParent();2072 else2073 return GetParent();2074 }2075 return nullptr;2076}2077 2078bool ValueObject::IsBaseClass(uint32_t &depth) {2079 if (!IsBaseClass()) {2080 depth = 0;2081 return false;2082 }2083 if (GetParent()) {2084 GetParent()->IsBaseClass(depth);2085 depth = depth + 1;2086 return true;2087 }2088 // TODO: a base of no parent? weird..2089 depth = 1;2090 return true;2091}2092 2093void ValueObject::GetExpressionPath(Stream &s,2094 GetExpressionPathFormat epformat) {2095 // synthetic children do not actually "exist" as part of the hierarchy, and2096 // sometimes they are consed up in ways that don't make sense from an2097 // underlying language/API standpoint. So, use a special code path here to2098 // return something that can hopefully be used in expression2099 if (m_flags.m_is_synthetic_children_generated) {2100 UpdateValueIfNeeded();2101 2102 if (m_value.GetValueType() == Value::ValueType::LoadAddress) {2103 if (IsPointerOrReferenceType()) {2104 s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"),2105 GetValueAsUnsigned(0));2106 return;2107 } else {2108 uint64_t load_addr =2109 m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);2110 if (load_addr != LLDB_INVALID_ADDRESS) {2111 s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"),2112 load_addr);2113 return;2114 }2115 }2116 }2117 2118 if (CanProvideValue()) {2119 s.Printf("((%s)%s)", GetTypeName().AsCString("void"),2120 GetValueAsCString());2121 return;2122 }2123 2124 return;2125 }2126 2127 const bool is_deref_of_parent = IsDereferenceOfParent();2128 2129 if (is_deref_of_parent &&2130 epformat == eGetExpressionPathFormatDereferencePointers) {2131 // this is the original format of GetExpressionPath() producing code like2132 // *(a_ptr).memberName, which is entirely fine, until you put this into2133 // StackFrame::GetValueForVariableExpressionPath() which prefers to see2134 // a_ptr->memberName. the eHonorPointers mode is meant to produce strings2135 // in this latter format2136 s.PutCString("*(");2137 }2138 2139 ValueObject *parent = GetParent();2140 2141 if (parent)2142 parent->GetExpressionPath(s, epformat);2143 2144 // if we are a deref_of_parent just because we are synthetic array members2145 // made up to allow ptr[%d] syntax to work in variable printing, then add our2146 // name ([%d]) to the expression path2147 if (m_flags.m_is_array_item_for_pointer &&2148 epformat == eGetExpressionPathFormatHonorPointers)2149 s.PutCString(m_name.GetStringRef());2150 2151 if (!IsBaseClass()) {2152 if (!is_deref_of_parent) {2153 ValueObject *non_base_class_parent = GetNonBaseClassParent();2154 if (non_base_class_parent &&2155 !non_base_class_parent->GetName().IsEmpty()) {2156 CompilerType non_base_class_parent_compiler_type =2157 non_base_class_parent->GetCompilerType();2158 if (non_base_class_parent_compiler_type) {2159 if (parent && parent->IsDereferenceOfParent() &&2160 epformat == eGetExpressionPathFormatHonorPointers) {2161 s.PutCString("->");2162 } else {2163 const uint32_t non_base_class_parent_type_info =2164 non_base_class_parent_compiler_type.GetTypeInfo();2165 2166 if (non_base_class_parent_type_info & eTypeIsPointer) {2167 s.PutCString("->");2168 } else if ((non_base_class_parent_type_info & eTypeHasChildren) &&2169 !(non_base_class_parent_type_info & eTypeIsArray)) {2170 s.PutChar('.');2171 }2172 }2173 }2174 }2175 2176 const char *name = GetName().GetCString();2177 if (name)2178 s.PutCString(name);2179 }2180 }2181 2182 if (is_deref_of_parent &&2183 epformat == eGetExpressionPathFormatDereferencePointers) {2184 s.PutChar(')');2185 }2186}2187 2188// Return the alternate value (synthetic if the input object is non-synthetic2189// and otherwise) this is permitted by the expression path options.2190static ValueObjectSP GetAlternateValue(2191 ValueObject &valobj,2192 ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal2193 synth_traversal) {2194 using SynthTraversal =2195 ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal;2196 2197 if (valobj.IsSynthetic()) {2198 if (synth_traversal == SynthTraversal::FromSynthetic ||2199 synth_traversal == SynthTraversal::Both)2200 return valobj.GetNonSyntheticValue();2201 } else {2202 if (synth_traversal == SynthTraversal::ToSynthetic ||2203 synth_traversal == SynthTraversal::Both)2204 return valobj.GetSyntheticValue();2205 }2206 return nullptr;2207}2208 2209// Dereference the provided object or the alternate value, if permitted by the2210// expression path options.2211static ValueObjectSP DereferenceValueOrAlternate(2212 ValueObject &valobj,2213 ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal2214 synth_traversal,2215 Status &error) {2216 error.Clear();2217 ValueObjectSP result = valobj.Dereference(error);2218 if (!result || error.Fail()) {2219 if (ValueObjectSP alt_obj = GetAlternateValue(valobj, synth_traversal)) {2220 error.Clear();2221 result = alt_obj->Dereference(error);2222 }2223 }2224 return result;2225}2226 2227ValueObjectSP ValueObject::GetValueForExpressionPath(2228 llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2229 ExpressionPathEndResultType *final_value_type,2230 const GetValueForExpressionPathOptions &options,2231 ExpressionPathAftermath *final_task_on_target) {2232 2233 ExpressionPathScanEndReason dummy_reason_to_stop =2234 ValueObject::eExpressionPathScanEndReasonUnknown;2235 ExpressionPathEndResultType dummy_final_value_type =2236 ValueObject::eExpressionPathEndResultTypeInvalid;2237 ExpressionPathAftermath dummy_final_task_on_target =2238 ValueObject::eExpressionPathAftermathNothing;2239 2240 ValueObjectSP ret_val = GetValueForExpressionPath_Impl(2241 expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,2242 final_value_type ? final_value_type : &dummy_final_value_type, options,2243 final_task_on_target ? final_task_on_target2244 : &dummy_final_task_on_target);2245 2246 if (!final_task_on_target ||2247 *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)2248 return ret_val;2249 2250 if (ret_val.get() &&2251 ((final_value_type ? *final_value_type : dummy_final_value_type) ==2252 eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress2253 // of plain objects2254 {2255 if ((final_task_on_target ? *final_task_on_target2256 : dummy_final_task_on_target) ==2257 ValueObject::eExpressionPathAftermathDereference) {2258 Status error;2259 ValueObjectSP final_value = DereferenceValueOrAlternate(2260 *ret_val, options.m_synthetic_children_traversal, error);2261 if (error.Fail() || !final_value.get()) {2262 if (reason_to_stop)2263 *reason_to_stop =2264 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2265 if (final_value_type)2266 *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2267 return ValueObjectSP();2268 } else {2269 if (final_task_on_target)2270 *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2271 return final_value;2272 }2273 }2274 if (*final_task_on_target ==2275 ValueObject::eExpressionPathAftermathTakeAddress) {2276 Status error;2277 ValueObjectSP final_value = ret_val->AddressOf(error);2278 if (error.Fail() || !final_value.get()) {2279 if (reason_to_stop)2280 *reason_to_stop =2281 ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;2282 if (final_value_type)2283 *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;2284 return ValueObjectSP();2285 } else {2286 if (final_task_on_target)2287 *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;2288 return final_value;2289 }2290 }2291 }2292 return ret_val; // final_task_on_target will still have its original value, so2293 // you know I did not do it2294}2295 2296ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(2297 llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop,2298 ExpressionPathEndResultType *final_result,2299 const GetValueForExpressionPathOptions &options,2300 ExpressionPathAftermath *what_next) {2301 ValueObjectSP root = GetSP();2302 2303 if (!root)2304 return nullptr;2305 2306 llvm::StringRef remainder = expression;2307 2308 while (true) {2309 llvm::StringRef temp_expression = remainder;2310 2311 CompilerType root_compiler_type = root->GetCompilerType();2312 CompilerType pointee_compiler_type;2313 Flags pointee_compiler_type_info;2314 2315 Flags root_compiler_type_info(2316 root_compiler_type.GetTypeInfo(&pointee_compiler_type));2317 if (pointee_compiler_type)2318 pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());2319 2320 if (temp_expression.empty()) {2321 *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;2322 return root;2323 }2324 2325 switch (temp_expression.front()) {2326 case '-': {2327 temp_expression = temp_expression.drop_front();2328 if (options.m_check_dot_vs_arrow_syntax &&2329 root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2330 // use -> on a2331 // non-pointer and I2332 // must catch the error2333 {2334 *reason_to_stop =2335 ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;2336 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2337 return ValueObjectSP();2338 }2339 if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to2340 // extract an ObjC IVar2341 // when this is forbidden2342 root_compiler_type_info.Test(eTypeIsPointer) &&2343 options.m_no_fragile_ivar) {2344 *reason_to_stop =2345 ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;2346 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2347 return ValueObjectSP();2348 }2349 if (!temp_expression.starts_with(">")) {2350 *reason_to_stop =2351 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2352 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2353 return ValueObjectSP();2354 }2355 }2356 [[fallthrough]];2357 case '.': // or fallthrough from ->2358 {2359 if (options.m_check_dot_vs_arrow_syntax &&2360 temp_expression.front() == '.' &&2361 root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to2362 // use . on a pointer2363 // and I must catch the2364 // error2365 {2366 *reason_to_stop =2367 ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;2368 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2369 return nullptr;2370 }2371 temp_expression = temp_expression.drop_front(); // skip . or >2372 2373 size_t next_sep_pos = temp_expression.find_first_of("-.[", 1);2374 if (next_sep_pos == llvm::StringRef::npos) {2375 // if no other separator just expand this last layer2376 llvm::StringRef child_name = temp_expression;2377 ValueObjectSP child_valobj_sp =2378 root->GetChildMemberWithName(child_name);2379 if (!child_valobj_sp) {2380 if (ValueObjectSP altroot = GetAlternateValue(2381 *root, options.m_synthetic_children_traversal))2382 child_valobj_sp = altroot->GetChildMemberWithName(child_name);2383 }2384 if (child_valobj_sp) {2385 *reason_to_stop =2386 ValueObject::eExpressionPathScanEndReasonEndOfString;2387 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2388 return child_valobj_sp;2389 }2390 *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;2391 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2392 return nullptr;2393 }2394 2395 llvm::StringRef next_separator = temp_expression.substr(next_sep_pos);2396 llvm::StringRef child_name = temp_expression.slice(0, next_sep_pos);2397 2398 ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name);2399 if (!child_valobj_sp) {2400 if (ValueObjectSP altroot = GetAlternateValue(2401 *root, options.m_synthetic_children_traversal))2402 child_valobj_sp = altroot->GetChildMemberWithName(child_name);2403 }2404 if (child_valobj_sp) {2405 root = child_valobj_sp;2406 remainder = next_separator;2407 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2408 continue;2409 }2410 *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;2411 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2412 return nullptr;2413 }2414 case '[': {2415 if (!root_compiler_type_info.Test(eTypeIsArray) &&2416 !root_compiler_type_info.Test(eTypeIsPointer) &&2417 !root_compiler_type_info.Test(2418 eTypeIsVector)) // if this is not a T[] nor a T*2419 {2420 if (!root_compiler_type_info.Test(2421 eTypeIsScalar)) // if this is not even a scalar...2422 {2423 if (options.m_synthetic_children_traversal ==2424 GetValueForExpressionPathOptions::SyntheticChildrenTraversal::2425 None) // ...only chance left is synthetic2426 {2427 *reason_to_stop =2428 ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;2429 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2430 return ValueObjectSP();2431 }2432 } else if (!options.m_allow_bitfields_syntax) // if this is a scalar,2433 // check that we can2434 // expand bitfields2435 {2436 *reason_to_stop =2437 ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;2438 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2439 return ValueObjectSP();2440 }2441 }2442 if (temp_expression[1] ==2443 ']') // if this is an unbounded range it only works for arrays2444 {2445 if (!root_compiler_type_info.Test(eTypeIsArray)) {2446 *reason_to_stop =2447 ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;2448 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2449 return nullptr;2450 } else // even if something follows, we cannot expand unbounded ranges,2451 // just let the caller do it2452 {2453 *reason_to_stop =2454 ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2455 *final_result =2456 ValueObject::eExpressionPathEndResultTypeUnboundedRange;2457 return root;2458 }2459 }2460 2461 size_t close_bracket_position = temp_expression.find(']', 1);2462 if (close_bracket_position ==2463 llvm::StringRef::npos) // if there is no ], this is a syntax error2464 {2465 *reason_to_stop =2466 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2467 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2468 return nullptr;2469 }2470 2471 llvm::StringRef bracket_expr =2472 temp_expression.slice(1, close_bracket_position);2473 2474 // If this was an empty expression it would have been caught by the if2475 // above.2476 assert(!bracket_expr.empty());2477 2478 if (!bracket_expr.contains('-')) {2479 // if no separator, this is of the form [N]. Note that this cannot be2480 // an unbounded range of the form [], because that case was handled2481 // above with an unconditional return.2482 unsigned long index = 0;2483 if (bracket_expr.getAsInteger(0, index)) {2484 *reason_to_stop =2485 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2486 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2487 return nullptr;2488 }2489 2490 // from here on we do have a valid index2491 if (root_compiler_type_info.Test(eTypeIsArray)) {2492 ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index);2493 if (!child_valobj_sp)2494 child_valobj_sp = root->GetSyntheticArrayMember(index, true);2495 if (!child_valobj_sp)2496 if (root->HasSyntheticValue() &&2497 llvm::expectedToStdOptional(2498 root->GetSyntheticValue()->GetNumChildren())2499 .value_or(0) > index)2500 child_valobj_sp =2501 root->GetSyntheticValue()->GetChildAtIndex(index);2502 if (child_valobj_sp) {2503 root = child_valobj_sp;2504 remainder =2505 temp_expression.substr(close_bracket_position + 1); // skip ]2506 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2507 continue;2508 } else {2509 *reason_to_stop =2510 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2511 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2512 return nullptr;2513 }2514 } else if (root_compiler_type_info.Test(eTypeIsPointer)) {2515 if (*what_next ==2516 ValueObject::2517 eExpressionPathAftermathDereference && // if this is a2518 // ptr-to-scalar, I2519 // am accessing it2520 // by index and I2521 // would have2522 // deref'ed anyway,2523 // then do it now2524 // and use this as2525 // a bitfield2526 pointee_compiler_type_info.Test(eTypeIsScalar)) {2527 Status error;2528 root = DereferenceValueOrAlternate(2529 *root, options.m_synthetic_children_traversal, error);2530 if (error.Fail() || !root) {2531 *reason_to_stop =2532 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2533 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2534 return nullptr;2535 } else {2536 *what_next = eExpressionPathAftermathNothing;2537 continue;2538 }2539 } else {2540 if (root->GetCompilerType().GetMinimumLanguage() ==2541 eLanguageTypeObjC &&2542 pointee_compiler_type_info.AllClear(eTypeIsPointer) &&2543 root->HasSyntheticValue() &&2544 (options.m_synthetic_children_traversal ==2545 GetValueForExpressionPathOptions::2546 SyntheticChildrenTraversal::ToSynthetic ||2547 options.m_synthetic_children_traversal ==2548 GetValueForExpressionPathOptions::2549 SyntheticChildrenTraversal::Both)) {2550 root = root->GetSyntheticValue()->GetChildAtIndex(index);2551 } else2552 root = root->GetSyntheticArrayMember(index, true);2553 if (!root) {2554 *reason_to_stop =2555 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2556 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2557 return nullptr;2558 } else {2559 remainder =2560 temp_expression.substr(close_bracket_position + 1); // skip ]2561 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2562 continue;2563 }2564 }2565 } else if (root_compiler_type_info.Test(eTypeIsScalar)) {2566 root = root->GetSyntheticBitFieldChild(index, index, true);2567 if (!root) {2568 *reason_to_stop =2569 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2570 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2571 return nullptr;2572 } else // we do not know how to expand members of bitfields, so we2573 // just return and let the caller do any further processing2574 {2575 *reason_to_stop = ValueObject::2576 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2577 *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2578 return root;2579 }2580 } else if (root_compiler_type_info.Test(eTypeIsVector)) {2581 root = root->GetChildAtIndex(index);2582 if (!root) {2583 *reason_to_stop =2584 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2585 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2586 return ValueObjectSP();2587 } else {2588 remainder =2589 temp_expression.substr(close_bracket_position + 1); // skip ]2590 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2591 continue;2592 }2593 } else if (options.m_synthetic_children_traversal ==2594 GetValueForExpressionPathOptions::2595 SyntheticChildrenTraversal::ToSynthetic ||2596 options.m_synthetic_children_traversal ==2597 GetValueForExpressionPathOptions::2598 SyntheticChildrenTraversal::Both) {2599 if (root->HasSyntheticValue())2600 root = root->GetSyntheticValue();2601 else if (!root->IsSynthetic()) {2602 *reason_to_stop =2603 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2604 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2605 return nullptr;2606 }2607 // if we are here, then root itself is a synthetic VO.. should be2608 // good to go2609 2610 if (!root) {2611 *reason_to_stop =2612 ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;2613 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2614 return nullptr;2615 }2616 root = root->GetChildAtIndex(index);2617 if (!root) {2618 *reason_to_stop =2619 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2620 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2621 return nullptr;2622 } else {2623 remainder =2624 temp_expression.substr(close_bracket_position + 1); // skip ]2625 *final_result = ValueObject::eExpressionPathEndResultTypePlain;2626 continue;2627 }2628 } else {2629 *reason_to_stop =2630 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2631 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2632 return nullptr;2633 }2634 } else {2635 // we have a low and a high index2636 llvm::StringRef sleft, sright;2637 unsigned long low_index, high_index;2638 std::tie(sleft, sright) = bracket_expr.split('-');2639 if (sleft.getAsInteger(0, low_index) ||2640 sright.getAsInteger(0, high_index)) {2641 *reason_to_stop =2642 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2643 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2644 return nullptr;2645 }2646 2647 if (low_index > high_index) // swap indices if required2648 std::swap(low_index, high_index);2649 2650 if (root_compiler_type_info.Test(2651 eTypeIsScalar)) // expansion only works for scalars2652 {2653 root = root->GetSyntheticBitFieldChild(low_index, high_index, true);2654 if (!root) {2655 *reason_to_stop =2656 ValueObject::eExpressionPathScanEndReasonNoSuchChild;2657 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2658 return nullptr;2659 } else {2660 *reason_to_stop = ValueObject::2661 eExpressionPathScanEndReasonBitfieldRangeOperatorMet;2662 *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;2663 return root;2664 }2665 } else if (root_compiler_type_info.Test(2666 eTypeIsPointer) && // if this is a ptr-to-scalar, I am2667 // accessing it by index and I would2668 // have deref'ed anyway, then do it2669 // now and use this as a bitfield2670 *what_next ==2671 ValueObject::eExpressionPathAftermathDereference &&2672 pointee_compiler_type_info.Test(eTypeIsScalar)) {2673 Status error;2674 root = DereferenceValueOrAlternate(2675 *root, options.m_synthetic_children_traversal, error);2676 if (error.Fail() || !root) {2677 *reason_to_stop =2678 ValueObject::eExpressionPathScanEndReasonDereferencingFailed;2679 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2680 return nullptr;2681 } else {2682 *what_next = ValueObject::eExpressionPathAftermathNothing;2683 continue;2684 }2685 } else {2686 *reason_to_stop =2687 ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;2688 *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;2689 return root;2690 }2691 }2692 break;2693 }2694 default: // some non-separator is in the way2695 {2696 *reason_to_stop =2697 ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;2698 *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;2699 return nullptr;2700 }2701 }2702 }2703}2704 2705llvm::Error ValueObject::Dump(Stream &s) {2706 return Dump(s, DumpValueObjectOptions(*this));2707}2708 2709llvm::Error ValueObject::Dump(Stream &s,2710 const DumpValueObjectOptions &options) {2711 ValueObjectPrinter printer(*this, &s, options);2712 return printer.PrintValueObject();2713}2714 2715ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {2716 ValueObjectSP valobj_sp;2717 2718 if (UpdateValueIfNeeded(false) && m_error.Success()) {2719 ExecutionContext exe_ctx(GetExecutionContextRef());2720 2721 DataExtractor data;2722 data.SetByteOrder(m_data.GetByteOrder());2723 data.SetAddressByteSize(m_data.GetAddressByteSize());2724 2725 if (IsBitfield()) {2726 Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));2727 m_error = v.GetValueAsData(&exe_ctx, data, GetModule().get());2728 } else2729 m_error = m_value.GetValueAsData(&exe_ctx, data, GetModule().get());2730 2731 valobj_sp = ValueObjectConstResult::Create(2732 exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data,2733 GetAddressOf().address);2734 }2735 2736 if (!valobj_sp) {2737 ExecutionContext exe_ctx(GetExecutionContextRef());2738 valobj_sp = ValueObjectConstResult::Create(2739 exe_ctx.GetBestExecutionContextScope(), m_error.Clone());2740 }2741 return valobj_sp;2742}2743 2744ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(2745 lldb::DynamicValueType dynValue, bool synthValue) {2746 ValueObjectSP result_sp;2747 switch (dynValue) {2748 case lldb::eDynamicCanRunTarget:2749 case lldb::eDynamicDontRunTarget: {2750 if (!IsDynamic())2751 result_sp = GetDynamicValue(dynValue);2752 } break;2753 case lldb::eNoDynamicValues: {2754 if (IsDynamic())2755 result_sp = GetStaticValue();2756 } break;2757 }2758 if (!result_sp)2759 result_sp = GetSP();2760 assert(result_sp);2761 2762 bool is_synthetic = result_sp->IsSynthetic();2763 if (synthValue && !is_synthetic) {2764 if (auto synth_sp = result_sp->GetSyntheticValue())2765 return synth_sp;2766 }2767 if (!synthValue && is_synthetic) {2768 if (auto non_synth_sp = result_sp->GetNonSyntheticValue())2769 return non_synth_sp;2770 }2771 2772 return result_sp;2773}2774 2775ValueObjectSP ValueObject::Dereference(Status &error) {2776 if (m_deref_valobj)2777 return m_deref_valobj->GetSP();2778 2779 std::string deref_name_str;2780 uint32_t deref_byte_size = 0;2781 int32_t deref_byte_offset = 0;2782 CompilerType compiler_type = GetCompilerType();2783 uint64_t language_flags = 0;2784 2785 ExecutionContext exe_ctx(GetExecutionContextRef());2786 2787 CompilerType deref_compiler_type;2788 auto deref_compiler_type_or_err = compiler_type.GetDereferencedType(2789 &exe_ctx, deref_name_str, deref_byte_size, deref_byte_offset, this,2790 language_flags);2791 2792 std::string deref_error;2793 if (deref_compiler_type_or_err) {2794 deref_compiler_type = *deref_compiler_type_or_err;2795 } else {2796 deref_error = llvm::toString(deref_compiler_type_or_err.takeError());2797 LLDB_LOG(GetLog(LLDBLog::Types), "could not find child: {0}", deref_error);2798 }2799 2800 if (deref_compiler_type && deref_byte_size) {2801 ConstString deref_name;2802 if (!deref_name_str.empty())2803 deref_name.SetCString(deref_name_str.c_str());2804 2805 m_deref_valobj =2806 new ValueObjectChild(*this, deref_compiler_type, deref_name,2807 deref_byte_size, deref_byte_offset, 0, 0, false,2808 true, eAddressTypeInvalid, language_flags);2809 }2810 2811 // In case of incomplete deref compiler type, use the pointee type and try2812 // to recreate a new ValueObjectChild using it.2813 if (!m_deref_valobj) {2814 // FIXME(#59012): C++ stdlib formatters break with incomplete types (e.g.2815 // `std::vector<int> &`). Remove ObjC restriction once that's resolved.2816 if (Language::LanguageIsObjC(GetPreferredDisplayLanguage()) &&2817 HasSyntheticValue()) {2818 deref_compiler_type = compiler_type.GetPointeeType();2819 2820 if (deref_compiler_type) {2821 ConstString deref_name;2822 if (!deref_name_str.empty())2823 deref_name.SetCString(deref_name_str.c_str());2824 2825 m_deref_valobj = new ValueObjectChild(2826 *this, deref_compiler_type, deref_name, deref_byte_size,2827 deref_byte_offset, 0, 0, false, true, eAddressTypeInvalid,2828 language_flags);2829 }2830 }2831 }2832 2833 if (!m_deref_valobj && IsSynthetic())2834 m_deref_valobj = GetChildMemberWithName("$$dereference$$").get();2835 2836 if (m_deref_valobj) {2837 error.Clear();2838 return m_deref_valobj->GetSP();2839 } else {2840 StreamString strm;2841 GetExpressionPath(strm);2842 2843 if (deref_error.empty())2844 error = Status::FromErrorStringWithFormat(2845 "dereference failed: (%s) %s",2846 GetTypeName().AsCString("<invalid type>"), strm.GetData());2847 else2848 error = Status::FromErrorStringWithFormat(2849 "dereference failed: %s: (%s) %s", deref_error.c_str(),2850 GetTypeName().AsCString("<invalid type>"), strm.GetData());2851 return ValueObjectSP();2852 }2853}2854 2855ValueObjectSP ValueObject::AddressOf(Status &error) {2856 if (m_addr_of_valobj_sp)2857 return m_addr_of_valobj_sp;2858 2859 auto [addr, address_type] = GetAddressOf(/*scalar_is_load_address=*/false);2860 error.Clear();2861 if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) {2862 switch (address_type) {2863 case eAddressTypeInvalid: {2864 StreamString expr_path_strm;2865 GetExpressionPath(expr_path_strm);2866 error = Status::FromErrorStringWithFormat("'%s' is not in memory",2867 expr_path_strm.GetData());2868 } break;2869 2870 case eAddressTypeFile:2871 case eAddressTypeLoad: {2872 CompilerType compiler_type = GetCompilerType();2873 if (compiler_type) {2874 std::string name(1, '&');2875 name.append(m_name.AsCString(""));2876 ExecutionContext exe_ctx(GetExecutionContextRef());2877 2878 lldb::DataBufferSP buffer(2879 new lldb_private::DataBufferHeap(&addr, sizeof(lldb::addr_t)));2880 m_addr_of_valobj_sp = ValueObjectConstResult::Create(2881 exe_ctx.GetBestExecutionContextScope(),2882 compiler_type.GetPointerType(), ConstString(name.c_str()), buffer,2883 endian::InlHostByteOrder(), exe_ctx.GetAddressByteSize());2884 }2885 } break;2886 default:2887 break;2888 }2889 } else {2890 StreamString expr_path_strm;2891 GetExpressionPath(expr_path_strm);2892 error = Status::FromErrorStringWithFormat(2893 "'%s' doesn't have a valid address", expr_path_strm.GetData());2894 }2895 2896 return m_addr_of_valobj_sp;2897}2898 2899ValueObjectSP ValueObject::DoCast(const CompilerType &compiler_type) {2900 return ValueObjectCast::Create(*this, GetName(), compiler_type);2901}2902 2903ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) {2904 // Only allow casts if the original type is equal or larger than the cast2905 // type, unless we know this is a load address. Getting the size wrong for2906 // a host side storage could leak lldb memory, so we absolutely want to2907 // prevent that. We may not always get the right value, for instance if we2908 // have an expression result value that's copied into a storage location in2909 // the target may not have copied enough memory. I'm not trying to fix that2910 // here, I'm just making Cast from a smaller to a larger possible in all the2911 // cases where that doesn't risk making a Value out of random lldb memory.2912 // You have to check the ValueObject's Value for the address types, since2913 // ValueObjects that use live addresses will tell you they fetch data from the2914 // live address, but once they are made, they actually don't.2915 // FIXME: Can we make ValueObject's with a live address fetch "more data" from2916 // the live address if it is still valid?2917 2918 Status error;2919 CompilerType my_type = GetCompilerType();2920 2921 ExecutionContextScope *exe_scope =2922 ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope();2923 if (llvm::expectedToOptional(compiler_type.GetByteSize(exe_scope))2924 .value_or(0) <=2925 llvm::expectedToOptional(GetCompilerType().GetByteSize(exe_scope))2926 .value_or(0) ||2927 m_value.GetValueType() == Value::ValueType::LoadAddress)2928 return DoCast(compiler_type);2929 2930 error = Status::FromErrorString(2931 "Can only cast to a type that is equal to or smaller "2932 "than the orignal type.");2933 2934 return ValueObjectConstResult::Create(2935 ExecutionContext(GetExecutionContextRef()).GetBestExecutionContextScope(),2936 std::move(error));2937}2938 2939lldb::ValueObjectSP ValueObject::Clone(ConstString new_name) {2940 return ValueObjectCast::Create(*this, new_name, GetCompilerType());2941}2942 2943ValueObjectSP ValueObject::CastPointerType(const char *name,2944 CompilerType &compiler_type) {2945 ValueObjectSP valobj_sp;2946 addr_t ptr_value = GetPointerValue().address;2947 2948 if (ptr_value != LLDB_INVALID_ADDRESS) {2949 Address ptr_addr(ptr_value);2950 ExecutionContext exe_ctx(GetExecutionContextRef());2951 valobj_sp = ValueObjectMemory::Create(2952 exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type);2953 }2954 return valobj_sp;2955}2956 2957ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {2958 ValueObjectSP valobj_sp;2959 addr_t ptr_value = GetPointerValue().address;2960 2961 if (ptr_value != LLDB_INVALID_ADDRESS) {2962 Address ptr_addr(ptr_value);2963 ExecutionContext exe_ctx(GetExecutionContextRef());2964 valobj_sp = ValueObjectMemory::Create(2965 exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp);2966 }2967 return valobj_sp;2968}2969 2970lldb::addr_t ValueObject::GetLoadAddress() {2971 if (auto target_sp = GetTargetSP()) {2972 const bool scalar_is_load_address = true;2973 auto [addr_value, addr_type] = GetAddressOf(scalar_is_load_address);2974 if (addr_type == eAddressTypeFile) {2975 lldb::ModuleSP module_sp(GetModule());2976 if (!module_sp)2977 addr_value = LLDB_INVALID_ADDRESS;2978 else {2979 Address tmp_addr;2980 module_sp->ResolveFileAddress(addr_value, tmp_addr);2981 addr_value = tmp_addr.GetLoadAddress(target_sp.get());2982 }2983 } else if (addr_type == eAddressTypeHost ||2984 addr_type == eAddressTypeInvalid)2985 addr_value = LLDB_INVALID_ADDRESS;2986 return addr_value;2987 }2988 return LLDB_INVALID_ADDRESS;2989}2990 2991llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(2992 CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {2993 // Make sure the starting type and the target type are both valid for this2994 // type of cast; otherwise return the shared pointer to the original2995 // (unchanged) ValueObject.2996 if (!type.IsPointerType() && !type.IsReferenceType())2997 return llvm::make_error<llvm::StringError>(2998 "Invalid target type: should be a pointer or a reference",2999 llvm::inconvertibleErrorCode());3000 3001 CompilerType start_type = GetCompilerType();3002 if (start_type.IsReferenceType())3003 start_type = start_type.GetNonReferenceType();3004 3005 auto target_record_type =3006 type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3007 auto start_record_type =3008 start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;3009 3010 if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3011 return llvm::make_error<llvm::StringError>(3012 "Underlying start & target types should be record types",3013 llvm::inconvertibleErrorCode());3014 3015 if (target_record_type.CompareTypes(start_record_type))3016 return llvm::make_error<llvm::StringError>(3017 "Underlying start & target types should be different",3018 llvm::inconvertibleErrorCode());3019 3020 if (base_type_indices.empty())3021 return llvm::make_error<llvm::StringError>(3022 "Children sequence must be non-empty", llvm::inconvertibleErrorCode());3023 3024 // Both the starting & target types are valid for the cast, and the list of3025 // base class indices is non-empty, so we can proceed with the cast.3026 3027 lldb::TargetSP target = GetTargetSP();3028 // The `value` can be a pointer, but GetChildAtIndex works for pointers too.3029 lldb::ValueObjectSP inner_value = GetSP();3030 3031 for (const uint32_t i : base_type_indices)3032 // Create synthetic value if needed.3033 inner_value =3034 inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);3035 3036 // At this point type of `inner_value` should be the dereferenced target3037 // type.3038 CompilerType inner_value_type = inner_value->GetCompilerType();3039 if (type.IsPointerType()) {3040 if (!inner_value_type.CompareTypes(type.GetPointeeType()))3041 return llvm::make_error<llvm::StringError>(3042 "casted value doesn't match the desired type",3043 llvm::inconvertibleErrorCode());3044 3045 uintptr_t addr = inner_value->GetLoadAddress();3046 llvm::StringRef name = "";3047 ExecutionContext exe_ctx(target.get(), false);3048 return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,3049 /* do deref */ false);3050 }3051 3052 // At this point the target type should be a reference.3053 if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))3054 return llvm::make_error<llvm::StringError>(3055 "casted value doesn't match the desired type",3056 llvm::inconvertibleErrorCode());3057 3058 return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));3059}3060 3061llvm::Expected<lldb::ValueObjectSP>3062ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {3063 // Make sure the starting type and the target type are both valid for this3064 // type of cast; otherwise return the shared pointer to the original3065 // (unchanged) ValueObject.3066 if (!type.IsPointerType() && !type.IsReferenceType())3067 return llvm::make_error<llvm::StringError>(3068 "Invalid target type: should be a pointer or a reference",3069 llvm::inconvertibleErrorCode());3070 3071 CompilerType start_type = GetCompilerType();3072 if (start_type.IsReferenceType())3073 start_type = start_type.GetNonReferenceType();3074 3075 auto target_record_type =3076 type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();3077 auto start_record_type =3078 start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;3079 3080 if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())3081 return llvm::make_error<llvm::StringError>(3082 "Underlying start & target types should be record types",3083 llvm::inconvertibleErrorCode());3084 3085 if (target_record_type.CompareTypes(start_record_type))3086 return llvm::make_error<llvm::StringError>(3087 "Underlying start & target types should be different",3088 llvm::inconvertibleErrorCode());3089 3090 CompilerType virtual_base;3091 if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {3092 if (!virtual_base.IsValid())3093 return llvm::make_error<llvm::StringError>(3094 "virtual base should be valid", llvm::inconvertibleErrorCode());3095 return llvm::make_error<llvm::StringError>(3096 llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +3097 type.TypeDescription() + " via virtual base " +3098 virtual_base.TypeDescription()),3099 llvm::inconvertibleErrorCode());3100 }3101 3102 // Both the starting & target types are valid for the cast, so we can3103 // proceed with the cast.3104 3105 lldb::TargetSP target = GetTargetSP();3106 auto pointer_type =3107 type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();3108 3109 uintptr_t addr =3110 type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();3111 3112 llvm::StringRef name = "";3113 ExecutionContext exe_ctx(target.get(), false);3114 lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(3115 name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);3116 3117 if (type.IsPointerType())3118 return value;3119 3120 // At this point the target type is a reference. Since `value` is a pointer,3121 // it has to be dereferenced.3122 Status error;3123 return value->Dereference(error);3124}3125 3126lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {3127 bool is_scalar = GetCompilerType().IsScalarType();3128 bool is_enum = GetCompilerType().IsEnumerationType();3129 bool is_pointer =3130 GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();3131 bool is_float = GetCompilerType().IsFloat();3132 bool is_integer = GetCompilerType().IsInteger();3133 ExecutionContext exe_ctx(GetExecutionContextRef());3134 3135 if (!type.IsScalarType())3136 return ValueObjectConstResult::Create(3137 exe_ctx.GetBestExecutionContextScope(),3138 Status::FromErrorString("target type must be a scalar"));3139 3140 if (!is_scalar && !is_enum && !is_pointer)3141 return ValueObjectConstResult::Create(3142 exe_ctx.GetBestExecutionContextScope(),3143 Status::FromErrorString("argument must be a scalar, enum, or pointer"));3144 3145 lldb::TargetSP target = GetTargetSP();3146 uint64_t type_byte_size = 0;3147 uint64_t val_byte_size = 0;3148 if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3149 type_byte_size = temp.value();3150 if (auto temp =3151 llvm::expectedToOptional(GetCompilerType().GetByteSize(target.get())))3152 val_byte_size = temp.value();3153 3154 if (is_pointer) {3155 if (!type.IsInteger() && !type.IsBoolean())3156 return ValueObjectConstResult::Create(3157 exe_ctx.GetBestExecutionContextScope(),3158 Status::FromErrorString("target type must be an integer or boolean"));3159 if (!type.IsBoolean() && type_byte_size < val_byte_size)3160 return ValueObjectConstResult::Create(3161 exe_ctx.GetBestExecutionContextScope(),3162 Status::FromErrorString(3163 "target type cannot be smaller than the pointer type"));3164 }3165 3166 if (type.IsBoolean()) {3167 if (!is_scalar || is_integer)3168 return ValueObject::CreateValueObjectFromBool(3169 target, GetValueAsUnsigned(0) != 0, "result");3170 else if (is_scalar && is_float) {3171 auto float_value_or_err = GetValueAsAPFloat();3172 if (float_value_or_err)3173 return ValueObject::CreateValueObjectFromBool(3174 target, !float_value_or_err->isZero(), "result");3175 else3176 return ValueObjectConstResult::Create(3177 exe_ctx.GetBestExecutionContextScope(),3178 Status::FromErrorStringWithFormat(3179 "cannot get value as APFloat: %s",3180 llvm::toString(float_value_or_err.takeError()).c_str()));3181 }3182 }3183 3184 if (type.IsInteger()) {3185 if (!is_scalar || is_integer) {3186 auto int_value_or_err = GetValueAsAPSInt();3187 if (int_value_or_err) {3188 // Get the value as APSInt and extend or truncate it to the requested3189 // size.3190 llvm::APSInt ext =3191 int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3192 return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3193 "result");3194 } else3195 return ValueObjectConstResult::Create(3196 exe_ctx.GetBestExecutionContextScope(),3197 Status::FromErrorStringWithFormat(3198 "cannot get value as APSInt: %s",3199 llvm::toString(int_value_or_err.takeError()).c_str()));3200 } else if (is_scalar && is_float) {3201 llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());3202 bool is_exact;3203 auto float_value_or_err = GetValueAsAPFloat();3204 if (float_value_or_err) {3205 llvm::APFloatBase::opStatus status =3206 float_value_or_err->convertToInteger(3207 integer, llvm::APFloat::rmTowardZero, &is_exact);3208 3209 // Casting floating point values that are out of bounds of the target3210 // type is undefined behaviour.3211 if (status & llvm::APFloatBase::opInvalidOp)3212 return ValueObjectConstResult::Create(3213 exe_ctx.GetBestExecutionContextScope(),3214 Status::FromErrorStringWithFormat(3215 "invalid type cast detected: %s",3216 llvm::toString(float_value_or_err.takeError()).c_str()));3217 return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3218 "result");3219 }3220 }3221 }3222 3223 if (type.IsFloat()) {3224 if (!is_scalar) {3225 auto int_value_or_err = GetValueAsAPSInt();3226 if (int_value_or_err) {3227 llvm::APSInt ext =3228 int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);3229 Scalar scalar_int(ext);3230 llvm::APFloat f =3231 scalar_int.CreateAPFloatFromAPSInt(type.GetBasicTypeEnumeration());3232 return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3233 "result");3234 } else {3235 return ValueObjectConstResult::Create(3236 exe_ctx.GetBestExecutionContextScope(),3237 Status::FromErrorStringWithFormat(3238 "cannot get value as APSInt: %s",3239 llvm::toString(int_value_or_err.takeError()).c_str()));3240 }3241 } else {3242 if (is_integer) {3243 auto int_value_or_err = GetValueAsAPSInt();3244 if (int_value_or_err) {3245 Scalar scalar_int(*int_value_or_err);3246 llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(3247 type.GetBasicTypeEnumeration());3248 return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3249 "result");3250 } else {3251 return ValueObjectConstResult::Create(3252 exe_ctx.GetBestExecutionContextScope(),3253 Status::FromErrorStringWithFormat(3254 "cannot get value as APSInt: %s",3255 llvm::toString(int_value_or_err.takeError()).c_str()));3256 }3257 }3258 if (is_float) {3259 auto float_value_or_err = GetValueAsAPFloat();3260 if (float_value_or_err) {3261 Scalar scalar_float(*float_value_or_err);3262 llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(3263 type.GetBasicTypeEnumeration());3264 return ValueObject::CreateValueObjectFromAPFloat(target, f, type,3265 "result");3266 } else {3267 return ValueObjectConstResult::Create(3268 exe_ctx.GetBestExecutionContextScope(),3269 Status::FromErrorStringWithFormat(3270 "cannot get value as APFloat: %s",3271 llvm::toString(float_value_or_err.takeError()).c_str()));3272 }3273 }3274 }3275 }3276 3277 return ValueObjectConstResult::Create(3278 exe_ctx.GetBestExecutionContextScope(),3279 Status::FromErrorString("Unable to perform requested cast"));3280}3281 3282lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {3283 bool is_enum = GetCompilerType().IsEnumerationType();3284 bool is_integer = GetCompilerType().IsInteger();3285 bool is_float = GetCompilerType().IsFloat();3286 ExecutionContext exe_ctx(GetExecutionContextRef());3287 3288 if (!is_enum && !is_integer && !is_float)3289 return ValueObjectConstResult::Create(3290 exe_ctx.GetBestExecutionContextScope(),3291 Status::FromErrorString(3292 "argument must be an integer, a float, or an enum"));3293 3294 if (!type.IsEnumerationType())3295 return ValueObjectConstResult::Create(3296 exe_ctx.GetBestExecutionContextScope(),3297 Status::FromErrorString("target type must be an enum"));3298 3299 lldb::TargetSP target = GetTargetSP();3300 uint64_t byte_size = 0;3301 if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3302 byte_size = temp.value();3303 3304 if (is_float) {3305 llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());3306 bool is_exact;3307 auto value_or_err = GetValueAsAPFloat();3308 if (value_or_err) {3309 llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(3310 integer, llvm::APFloat::rmTowardZero, &is_exact);3311 3312 // Casting floating point values that are out of bounds of the target3313 // type is undefined behaviour.3314 if (status & llvm::APFloatBase::opInvalidOp)3315 return ValueObjectConstResult::Create(3316 exe_ctx.GetBestExecutionContextScope(),3317 Status::FromErrorStringWithFormat(3318 "invalid type cast detected: %s",3319 llvm::toString(value_or_err.takeError()).c_str()));3320 return ValueObject::CreateValueObjectFromAPInt(target, integer, type,3321 "result");3322 } else3323 return ValueObjectConstResult::Create(3324 exe_ctx.GetBestExecutionContextScope(),3325 Status::FromErrorString("cannot get value as APFloat"));3326 } else {3327 // Get the value as APSInt and extend or truncate it to the requested size.3328 auto value_or_err = GetValueAsAPSInt();3329 if (value_or_err) {3330 llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);3331 return ValueObject::CreateValueObjectFromAPInt(target, ext, type,3332 "result");3333 } else3334 return ValueObjectConstResult::Create(3335 exe_ctx.GetBestExecutionContextScope(),3336 Status::FromErrorStringWithFormat(3337 "cannot get value as APSInt: %s",3338 llvm::toString(value_or_err.takeError()).c_str()));3339 }3340 return ValueObjectConstResult::Create(3341 exe_ctx.GetBestExecutionContextScope(),3342 Status::FromErrorString("Cannot perform requested cast"));3343}3344 3345ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}3346 3347ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,3348 bool use_selected)3349 : m_mod_id(), m_exe_ctx_ref() {3350 ExecutionContext exe_ctx(exe_scope);3351 TargetSP target_sp(exe_ctx.GetTargetSP());3352 if (target_sp) {3353 m_exe_ctx_ref.SetTargetSP(target_sp);3354 ProcessSP process_sp(exe_ctx.GetProcessSP());3355 if (!process_sp)3356 process_sp = target_sp->GetProcessSP();3357 3358 if (process_sp) {3359 m_mod_id = process_sp->GetModID();3360 m_exe_ctx_ref.SetProcessSP(process_sp);3361 3362 ThreadSP thread_sp(exe_ctx.GetThreadSP());3363 3364 if (!thread_sp) {3365 if (use_selected)3366 thread_sp = process_sp->GetThreadList().GetSelectedThread();3367 }3368 3369 if (thread_sp) {3370 m_exe_ctx_ref.SetThreadSP(thread_sp);3371 3372 StackFrameSP frame_sp(exe_ctx.GetFrameSP());3373 if (!frame_sp) {3374 if (use_selected)3375 frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame);3376 }3377 if (frame_sp)3378 m_exe_ctx_ref.SetFrameSP(frame_sp);3379 }3380 }3381 }3382}3383 3384ValueObject::EvaluationPoint::EvaluationPoint(3385 const ValueObject::EvaluationPoint &rhs)3386 : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref) {}3387 3388ValueObject::EvaluationPoint::~EvaluationPoint() = default;3389 3390// This function checks the EvaluationPoint against the current process state.3391// If the current state matches the evaluation point, or the evaluation point3392// is already invalid, then we return false, meaning "no change". If the3393// current state is different, we update our state, and return true meaning3394// "yes, change". If we did see a change, we also set m_needs_update to true,3395// so future calls to NeedsUpdate will return true. exe_scope will be set to3396// the current execution context scope.3397 3398bool ValueObject::EvaluationPoint::SyncWithProcessState(3399 bool accept_invalid_exe_ctx) {3400 // Start with the target, if it is NULL, then we're obviously not going to3401 // get any further:3402 const bool thread_and_frame_only_if_stopped = true;3403 ExecutionContext exe_ctx(3404 m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));3405 3406 if (exe_ctx.GetTargetPtr() == nullptr)3407 return false;3408 3409 // If we don't have a process nothing can change.3410 Process *process = exe_ctx.GetProcessPtr();3411 if (process == nullptr)3412 return false;3413 3414 // If our stop id is the current stop ID, nothing has changed:3415 ProcessModID current_mod_id = process->GetModID();3416 3417 // If the current stop id is 0, either we haven't run yet, or the process3418 // state has been cleared. In either case, we aren't going to be able to sync3419 // with the process state.3420 if (current_mod_id.GetStopID() == 0)3421 return false;3422 3423 bool changed = false;3424 const bool was_valid = m_mod_id.IsValid();3425 if (was_valid) {3426 if (m_mod_id == current_mod_id) {3427 // Everything is already up to date in this object, no need to update the3428 // execution context scope.3429 changed = false;3430 } else {3431 m_mod_id = current_mod_id;3432 m_needs_update = true;3433 changed = true;3434 }3435 }3436 3437 // Now re-look up the thread and frame in case the underlying objects have3438 // gone away & been recreated. That way we'll be sure to return a valid3439 // exe_scope. If we used to have a thread or a frame but can't find it3440 // anymore, then mark ourselves as invalid.3441 3442 if (!accept_invalid_exe_ctx) {3443 if (m_exe_ctx_ref.HasThreadRef()) {3444 ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP());3445 if (thread_sp) {3446 if (m_exe_ctx_ref.HasFrameRef()) {3447 StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP());3448 if (!frame_sp) {3449 // We used to have a frame, but now it is gone3450 SetInvalid();3451 changed = was_valid;3452 }3453 }3454 } else {3455 // We used to have a thread, but now it is gone3456 SetInvalid();3457 changed = was_valid;3458 }3459 }3460 }3461 3462 return changed;3463}3464 3465void ValueObject::EvaluationPoint::SetUpdated() {3466 ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());3467 if (process_sp)3468 m_mod_id = process_sp->GetModID();3469 m_needs_update = false;3470}3471 3472void ValueObject::ClearUserVisibleData(uint32_t clear_mask) {3473 if ((clear_mask & eClearUserVisibleDataItemsValue) ==3474 eClearUserVisibleDataItemsValue)3475 m_value_str.clear();3476 3477 if ((clear_mask & eClearUserVisibleDataItemsLocation) ==3478 eClearUserVisibleDataItemsLocation)3479 m_location_str.clear();3480 3481 if ((clear_mask & eClearUserVisibleDataItemsSummary) ==3482 eClearUserVisibleDataItemsSummary)3483 m_summary_str.clear();3484 3485 if ((clear_mask & eClearUserVisibleDataItemsDescription) ==3486 eClearUserVisibleDataItemsDescription)3487 m_object_desc_str.clear();3488 3489 if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) ==3490 eClearUserVisibleDataItemsSyntheticChildren) {3491 if (m_synthetic_value)3492 m_synthetic_value = nullptr;3493 }3494}3495 3496SymbolContextScope *ValueObject::GetSymbolContextScope() {3497 if (m_parent) {3498 if (!m_parent->IsPointerOrReferenceType())3499 return m_parent->GetSymbolContextScope();3500 }3501 return nullptr;3502}3503 3504lldb::ValueObjectSP3505ValueObject::CreateValueObjectFromExpression(llvm::StringRef name,3506 llvm::StringRef expression,3507 const ExecutionContext &exe_ctx) {3508 return CreateValueObjectFromExpression(name, expression, exe_ctx,3509 EvaluateExpressionOptions());3510}3511 3512lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(3513 llvm::StringRef name, llvm::StringRef expression,3514 const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) {3515 lldb::ValueObjectSP retval_sp;3516 lldb::TargetSP target_sp(exe_ctx.GetTargetSP());3517 if (!target_sp)3518 return retval_sp;3519 if (expression.empty())3520 return retval_sp;3521 target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(),3522 retval_sp, options);3523 if (retval_sp && !name.empty())3524 retval_sp->SetName(ConstString(name));3525 return retval_sp;3526}3527 3528lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(3529 llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,3530 CompilerType type, bool do_deref) {3531 if (type) {3532 CompilerType pointer_type(type.GetPointerType());3533 if (!do_deref)3534 pointer_type = type;3535 if (pointer_type) {3536 lldb::DataBufferSP buffer(3537 new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));3538 lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create(3539 exe_ctx.GetBestExecutionContextScope(), pointer_type,3540 ConstString(name), buffer, exe_ctx.GetByteOrder(),3541 exe_ctx.GetAddressByteSize()));3542 if (ptr_result_valobj_sp) {3543 if (do_deref)3544 ptr_result_valobj_sp->GetValue().SetValueType(3545 Value::ValueType::LoadAddress);3546 Status err;3547 if (do_deref)3548 ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);3549 if (ptr_result_valobj_sp && !name.empty())3550 ptr_result_valobj_sp->SetName(ConstString(name));3551 }3552 return ptr_result_valobj_sp;3553 }3554 }3555 return lldb::ValueObjectSP();3556}3557 3558lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(3559 llvm::StringRef name, const DataExtractor &data,3560 const ExecutionContext &exe_ctx, CompilerType type) {3561 lldb::ValueObjectSP new_value_sp;3562 new_value_sp = ValueObjectConstResult::Create(3563 exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data,3564 LLDB_INVALID_ADDRESS);3565 new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);3566 if (new_value_sp && !name.empty())3567 new_value_sp->SetName(ConstString(name));3568 return new_value_sp;3569}3570 3571lldb::ValueObjectSP3572ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,3573 const llvm::APInt &v, CompilerType type,3574 llvm::StringRef name) {3575 ExecutionContext exe_ctx(target.get(), false);3576 uint64_t byte_size = 0;3577 if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3578 byte_size = temp.value();3579 lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3580 reinterpret_cast<const void *>(v.getRawData()), byte_size,3581 exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());3582 return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3583}3584 3585lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(3586 lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,3587 llvm::StringRef name) {3588 return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);3589}3590 3591lldb::ValueObjectSP ValueObject::CreateValueObjectFromScalar(3592 lldb::TargetSP target, Scalar &s, CompilerType type, llvm::StringRef name) {3593 ExecutionContext exe_ctx(target.get(), false);3594 return ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(),3595 type, s, ConstString(name));3596}3597 3598lldb::ValueObjectSP3599ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,3600 llvm::StringRef name) {3601 CompilerType target_type;3602 if (target) {3603 for (auto type_system_sp : target->GetScratchTypeSystems())3604 if (auto compiler_type =3605 type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {3606 target_type = compiler_type;3607 break;3608 }3609 }3610 ExecutionContext exe_ctx(target.get(), false);3611 uint64_t byte_size = 0;3612 if (auto temp =3613 llvm::expectedToOptional(target_type.GetByteSize(target.get())))3614 byte_size = temp.value();3615 lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3616 reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),3617 exe_ctx.GetAddressByteSize());3618 return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,3619 target_type);3620}3621 3622lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(3623 lldb::TargetSP target, CompilerType type, llvm::StringRef name) {3624 if (!type.IsNullPtrType()) {3625 lldb::ValueObjectSP ret_val;3626 return ret_val;3627 }3628 uintptr_t zero = 0;3629 ExecutionContext exe_ctx(target.get(), false);3630 uint64_t byte_size = 0;3631 if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))3632 byte_size = temp.value();3633 lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(3634 reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),3635 exe_ctx.GetAddressByteSize());3636 return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);3637}3638 3639ModuleSP ValueObject::GetModule() {3640 ValueObject *root(GetRoot());3641 if (root != this)3642 return root->GetModule();3643 return lldb::ModuleSP();3644}3645 3646ValueObject *ValueObject::GetRoot() {3647 if (m_root)3648 return m_root;3649 return (m_root = FollowParentChain([](ValueObject *vo) -> bool {3650 return (vo->m_parent != nullptr);3651 }));3652}3653 3654ValueObject *3655ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {3656 ValueObject *vo = this;3657 while (vo) {3658 if (!f(vo))3659 break;3660 vo = vo->m_parent;3661 }3662 return vo;3663}3664 3665AddressType ValueObject::GetAddressTypeOfChildren() {3666 if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) {3667 ValueObject *root(GetRoot());3668 if (root != this)3669 return root->GetAddressTypeOfChildren();3670 }3671 return m_address_type_of_ptr_or_ref_children;3672}3673 3674lldb::DynamicValueType ValueObject::GetDynamicValueType() {3675 ValueObject *with_dv_info = this;3676 while (with_dv_info) {3677 if (with_dv_info->HasDynamicValueTypeInfo())3678 return with_dv_info->GetDynamicValueTypeImpl();3679 with_dv_info = with_dv_info->m_parent;3680 }3681 return lldb::eNoDynamicValues;3682}3683 3684lldb::Format ValueObject::GetFormat() const {3685 const ValueObject *with_fmt_info = this;3686 while (with_fmt_info) {3687 if (with_fmt_info->m_format != lldb::eFormatDefault)3688 return with_fmt_info->m_format;3689 with_fmt_info = with_fmt_info->m_parent;3690 }3691 return m_format;3692}3693 3694lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() {3695 lldb::LanguageType type = m_preferred_display_language;3696 if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {3697 if (GetRoot()) {3698 if (GetRoot() == this) {3699 if (StackFrameSP frame_sp = GetFrameSP()) {3700 const SymbolContext &sc(3701 frame_sp->GetSymbolContext(eSymbolContextCompUnit));3702 if (CompileUnit *cu = sc.comp_unit)3703 type = cu->GetLanguage();3704 }3705 } else {3706 type = GetRoot()->GetPreferredDisplayLanguage();3707 }3708 }3709 }3710 return (m_preferred_display_language = type); // only compute it once3711}3712 3713void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) {3714 if (m_preferred_display_language == lldb::eLanguageTypeUnknown)3715 SetPreferredDisplayLanguage(lt);3716}3717 3718bool ValueObject::CanProvideValue() {3719 // we need to support invalid types as providers of values because some bare-3720 // board debugging scenarios have no notion of types, but still manage to3721 // have raw numeric values for things like registers. sigh.3722 CompilerType type = GetCompilerType();3723 return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));3724}3725 3726ValueObjectSP ValueObject::Persist() {3727 if (!UpdateValueIfNeeded())3728 return nullptr;3729 3730 TargetSP target_sp(GetTargetSP());3731 if (!target_sp)3732 return nullptr;3733 3734 PersistentExpressionState *persistent_state =3735 target_sp->GetPersistentExpressionStateForLanguage(3736 GetPreferredDisplayLanguage());3737 3738 if (!persistent_state)3739 return nullptr;3740 3741 ConstString name = persistent_state->GetNextPersistentVariableName();3742 3743 ValueObjectSP const_result_sp =3744 ValueObjectConstResult::Create(target_sp.get(), GetValue(), name);3745 3746 ExpressionVariableSP persistent_var_sp =3747 persistent_state->CreatePersistentVariable(const_result_sp);3748 persistent_var_sp->m_live_sp = persistent_var_sp->m_frozen_sp;3749 persistent_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;3750 3751 return persistent_var_sp->GetValueObject();3752}3753 3754lldb::ValueObjectSP ValueObject::GetVTable() {3755 return ValueObjectVTable::Create(*this);3756}3757