15ffd83dbSDimitry Andric //===-- ValueObjectChild.cpp ----------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectChild.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "lldb/Core/Value.h" 120b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h" 130b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h" 140b57cec5SDimitry Andric #include "lldb/Target/Process.h" 150b57cec5SDimitry Andric #include "lldb/Utility/Flags.h" 160b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h" 170b57cec5SDimitry Andric #include "lldb/Utility/Status.h" 180b57cec5SDimitry Andric #include "lldb/lldb-forward.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include <functional> 210b57cec5SDimitry Andric #include <memory> 220b57cec5SDimitry Andric #include <vector> 230b57cec5SDimitry Andric 24fe6060f1SDimitry Andric #include <cstdio> 25fe6060f1SDimitry Andric #include <cstring> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace lldb_private; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric ValueObjectChild::ValueObjectChild( 300b57cec5SDimitry Andric ValueObject &parent, const CompilerType &compiler_type, 310b57cec5SDimitry Andric ConstString name, uint64_t byte_size, int32_t byte_offset, 320b57cec5SDimitry Andric uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, 330b57cec5SDimitry Andric bool is_base_class, bool is_deref_of_parent, 340b57cec5SDimitry Andric AddressType child_ptr_or_ref_addr_type, uint64_t language_flags) 350b57cec5SDimitry Andric : ValueObject(parent), m_compiler_type(compiler_type), 360b57cec5SDimitry Andric m_byte_size(byte_size), m_byte_offset(byte_offset), 370b57cec5SDimitry Andric m_bitfield_bit_size(bitfield_bit_size), 380b57cec5SDimitry Andric m_bitfield_bit_offset(bitfield_bit_offset), 390b57cec5SDimitry Andric m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent), 400b57cec5SDimitry Andric m_can_update_with_invalid_exe_ctx() { 410b57cec5SDimitry Andric m_name = name; 420b57cec5SDimitry Andric SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); 430b57cec5SDimitry Andric SetLanguageFlags(language_flags); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 46fe6060f1SDimitry Andric ValueObjectChild::~ValueObjectChild() = default; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric lldb::ValueType ValueObjectChild::GetValueType() const { 490b57cec5SDimitry Andric return m_parent->GetValueType(); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 52*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> ValueObjectChild::CalculateNumChildren(uint32_t max) { 530b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 540b57cec5SDimitry Andric auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 55*0fca6ea1SDimitry Andric if (!children_count) 56*0fca6ea1SDimitry Andric return children_count; 57*0fca6ea1SDimitry Andric return *children_count <= max ? *children_count : max; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static void AdjustForBitfieldness(ConstString &name, 610b57cec5SDimitry Andric uint8_t bitfield_bit_size) { 62e8d8bef9SDimitry Andric if (name && bitfield_bit_size) 63e8d8bef9SDimitry Andric name.SetString(llvm::formatv("{0}:{1}", name, bitfield_bit_size).str()); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric ConstString ValueObjectChild::GetTypeName() { 670b57cec5SDimitry Andric if (m_type_name.IsEmpty()) { 685ffd83dbSDimitry Andric m_type_name = GetCompilerType().GetTypeName(); 690b57cec5SDimitry Andric AdjustForBitfieldness(m_type_name, m_bitfield_bit_size); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric return m_type_name; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric ConstString ValueObjectChild::GetQualifiedTypeName() { 755ffd83dbSDimitry Andric ConstString qualified_name = GetCompilerType().GetTypeName(); 760b57cec5SDimitry Andric AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); 770b57cec5SDimitry Andric return qualified_name; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric ConstString ValueObjectChild::GetDisplayTypeName() { 810b57cec5SDimitry Andric ConstString display_name = GetCompilerType().GetDisplayTypeName(); 820b57cec5SDimitry Andric AdjustForBitfieldness(display_name, m_bitfield_bit_size); 830b57cec5SDimitry Andric return display_name; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { 8781ad6265SDimitry Andric if (m_can_update_with_invalid_exe_ctx) 88bdd1243dSDimitry Andric return *m_can_update_with_invalid_exe_ctx; 890b57cec5SDimitry Andric if (m_parent) { 900b57cec5SDimitry Andric ValueObject *opinionated_parent = 910b57cec5SDimitry Andric m_parent->FollowParentChain([](ValueObject *valobj) -> bool { 920b57cec5SDimitry Andric return (valobj->CanUpdateWithInvalidExecutionContext() == 930b57cec5SDimitry Andric eLazyBoolCalculate); 940b57cec5SDimitry Andric }); 950b57cec5SDimitry Andric if (opinionated_parent) 96bdd1243dSDimitry Andric return *(m_can_update_with_invalid_exe_ctx = 97bdd1243dSDimitry Andric opinionated_parent->CanUpdateWithInvalidExecutionContext()); 980b57cec5SDimitry Andric } 99bdd1243dSDimitry Andric return *(m_can_update_with_invalid_exe_ctx = 100bdd1243dSDimitry Andric this->ValueObject::CanUpdateWithInvalidExecutionContext()); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric bool ValueObjectChild::UpdateValue() { 1040b57cec5SDimitry Andric m_error.Clear(); 1050b57cec5SDimitry Andric SetValueIsValid(false); 1060b57cec5SDimitry Andric ValueObject *parent = m_parent; 1070b57cec5SDimitry Andric if (parent) { 1080b57cec5SDimitry Andric if (parent->UpdateValueIfNeeded(false)) { 1090b57cec5SDimitry Andric m_value.SetCompilerType(GetCompilerType()); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric CompilerType parent_type(parent->GetCompilerType()); 1120b57cec5SDimitry Andric // Copy the parent scalar value and the scalar value type 1130b57cec5SDimitry Andric m_value.GetScalar() = parent->GetValue().GetScalar(); 114e8d8bef9SDimitry Andric m_value.SetValueType(parent->GetValue().GetValueType()); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric Flags parent_type_flags(parent_type.GetTypeInfo()); 1170b57cec5SDimitry Andric const bool is_instance_ptr_base = 1180b57cec5SDimitry Andric ((m_is_base_class) && 1190b57cec5SDimitry Andric (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer))); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) { 122e8d8bef9SDimitry Andric m_value.GetScalar() = parent->GetPointerValue(); 1230b57cec5SDimitry Andric 124e8d8bef9SDimitry Andric switch (parent->GetAddressTypeOfChildren()) { 1250b57cec5SDimitry Andric case eAddressTypeFile: { 1260b57cec5SDimitry Andric lldb::ProcessSP process_sp(GetProcessSP()); 1270b57cec5SDimitry Andric if (process_sp && process_sp->IsAlive()) 128fe6060f1SDimitry Andric m_value.SetValueType(Value::ValueType::LoadAddress); 1290b57cec5SDimitry Andric else 130fe6060f1SDimitry Andric m_value.SetValueType(Value::ValueType::FileAddress); 1310b57cec5SDimitry Andric } break; 1320b57cec5SDimitry Andric case eAddressTypeLoad: 1330b57cec5SDimitry Andric m_value.SetValueType(is_instance_ptr_base 134fe6060f1SDimitry Andric ? Value::ValueType::Scalar 135fe6060f1SDimitry Andric : Value::ValueType::LoadAddress); 1360b57cec5SDimitry Andric break; 1370b57cec5SDimitry Andric case eAddressTypeHost: 138fe6060f1SDimitry Andric m_value.SetValueType(Value::ValueType::HostAddress); 1390b57cec5SDimitry Andric break; 1400b57cec5SDimitry Andric case eAddressTypeInvalid: 1410b57cec5SDimitry Andric // TODO: does this make sense? 142fe6060f1SDimitry Andric m_value.SetValueType(Value::ValueType::Scalar); 1430b57cec5SDimitry Andric break; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric } 146e8d8bef9SDimitry Andric switch (m_value.GetValueType()) { 147fe6060f1SDimitry Andric case Value::ValueType::Invalid: 148fe6060f1SDimitry Andric break; 149fe6060f1SDimitry Andric case Value::ValueType::LoadAddress: 150fe6060f1SDimitry Andric case Value::ValueType::FileAddress: 151fe6060f1SDimitry Andric case Value::ValueType::HostAddress: { 152e8d8bef9SDimitry Andric lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 1530b57cec5SDimitry Andric if (addr == LLDB_INVALID_ADDRESS) { 1540b57cec5SDimitry Andric m_error.SetErrorString("parent address is invalid."); 1550b57cec5SDimitry Andric } else if (addr == 0) { 1560b57cec5SDimitry Andric m_error.SetErrorString("parent is NULL"); 1570b57cec5SDimitry Andric } else { 158e8d8bef9SDimitry Andric // If a bitfield doesn't fit into the child_byte_size'd window at 159e8d8bef9SDimitry Andric // child_byte_offset, move the window forward until it fits. The 160e8d8bef9SDimitry Andric // problem here is that Value has no notion of bitfields and thus the 161e8d8bef9SDimitry Andric // Value's DataExtractor is sized like the bitfields CompilerType; a 162e8d8bef9SDimitry Andric // sequence of bitfields, however, can be larger than their underlying 1639dba64beSDimitry Andric // type. 1649dba64beSDimitry Andric if (m_bitfield_bit_offset) { 1659dba64beSDimitry Andric const bool thread_and_frame_only_if_stopped = true; 1669dba64beSDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef().Lock( 1679dba64beSDimitry Andric thread_and_frame_only_if_stopped)); 1689dba64beSDimitry Andric if (auto type_bit_size = GetCompilerType().GetBitSize( 1699dba64beSDimitry Andric exe_ctx.GetBestExecutionContextScope())) { 1709dba64beSDimitry Andric uint64_t bitfield_end = 1719dba64beSDimitry Andric m_bitfield_bit_size + m_bitfield_bit_offset; 1729dba64beSDimitry Andric if (bitfield_end > *type_bit_size) { 1739dba64beSDimitry Andric uint64_t overhang_bytes = 1749dba64beSDimitry Andric (bitfield_end - *type_bit_size + 7) / 8; 175e8d8bef9SDimitry Andric m_byte_offset += overhang_bytes; 1769dba64beSDimitry Andric m_bitfield_bit_offset -= overhang_bytes * 8; 1779dba64beSDimitry Andric } 1789dba64beSDimitry Andric } 1799dba64beSDimitry Andric } 180e8d8bef9SDimitry Andric 181e8d8bef9SDimitry Andric // Set this object's scalar value to the address of its value by 182e8d8bef9SDimitry Andric // adding its byte offset to the parent address 183e8d8bef9SDimitry Andric m_value.GetScalar() += m_byte_offset; 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric } break; 1860b57cec5SDimitry Andric 187fe6060f1SDimitry Andric case Value::ValueType::Scalar: 1880b57cec5SDimitry Andric // try to extract the child value from the parent's scalar value 1890b57cec5SDimitry Andric { 1900b57cec5SDimitry Andric Scalar scalar(m_value.GetScalar()); 1910b57cec5SDimitry Andric scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset); 1920b57cec5SDimitry Andric m_value.GetScalar() = scalar; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric break; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric if (m_error.Success()) { 1980b57cec5SDimitry Andric const bool thread_and_frame_only_if_stopped = true; 1990b57cec5SDimitry Andric ExecutionContext exe_ctx( 2000b57cec5SDimitry Andric GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); 2010b57cec5SDimitry Andric if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) { 2020b57cec5SDimitry Andric Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value; 2030b57cec5SDimitry Andric m_error = 2049dba64beSDimitry Andric value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 2050b57cec5SDimitry Andric } else { 2060b57cec5SDimitry Andric m_error.Clear(); // No value so nothing to read... 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric } else { 2110b57cec5SDimitry Andric m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", 2120b57cec5SDimitry Andric parent->GetError().AsCString()); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric } else { 2150b57cec5SDimitry Andric m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric return m_error.Success(); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric bool ValueObjectChild::IsInScope() { 2220b57cec5SDimitry Andric ValueObject *root(GetRoot()); 2230b57cec5SDimitry Andric if (root) 2240b57cec5SDimitry Andric return root->IsInScope(); 2250b57cec5SDimitry Andric return false; 2260b57cec5SDimitry Andric } 227