1 //===-- ValueObjectChild.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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Core/ValueObjectChild.h" 10 11 #include "lldb/Core/Value.h" 12 #include "lldb/Symbol/CompilerType.h" 13 #include "lldb/Target/ExecutionContext.h" 14 #include "lldb/Target/Process.h" 15 #include "lldb/Utility/Flags.h" 16 #include "lldb/Utility/Scalar.h" 17 #include "lldb/Utility/Status.h" 18 #include "lldb/lldb-forward.h" 19 20 #include <functional> 21 #include <memory> 22 #include <vector> 23 24 #include <stdio.h> 25 #include <string.h> 26 27 using namespace lldb_private; 28 29 ValueObjectChild::ValueObjectChild( 30 ValueObject &parent, const CompilerType &compiler_type, 31 ConstString name, uint64_t byte_size, int32_t byte_offset, 32 uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, 33 bool is_base_class, bool is_deref_of_parent, 34 AddressType child_ptr_or_ref_addr_type, uint64_t language_flags) 35 : ValueObject(parent), m_compiler_type(compiler_type), 36 m_byte_size(byte_size), m_byte_offset(byte_offset), 37 m_bitfield_bit_size(bitfield_bit_size), 38 m_bitfield_bit_offset(bitfield_bit_offset), 39 m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent), 40 m_can_update_with_invalid_exe_ctx() { 41 m_name = name; 42 SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); 43 SetLanguageFlags(language_flags); 44 } 45 46 ValueObjectChild::~ValueObjectChild() {} 47 48 lldb::ValueType ValueObjectChild::GetValueType() const { 49 return m_parent->GetValueType(); 50 } 51 52 size_t ValueObjectChild::CalculateNumChildren(uint32_t max) { 53 ExecutionContext exe_ctx(GetExecutionContextRef()); 54 auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 55 return children_count <= max ? children_count : max; 56 } 57 58 static void AdjustForBitfieldness(ConstString &name, 59 uint8_t bitfield_bit_size) { 60 if (name && bitfield_bit_size) 61 name.SetString(llvm::formatv("{0}:{1}", name, bitfield_bit_size).str()); 62 } 63 64 ConstString ValueObjectChild::GetTypeName() { 65 if (m_type_name.IsEmpty()) { 66 m_type_name = GetCompilerType().GetTypeName(); 67 AdjustForBitfieldness(m_type_name, m_bitfield_bit_size); 68 } 69 return m_type_name; 70 } 71 72 ConstString ValueObjectChild::GetQualifiedTypeName() { 73 ConstString qualified_name = GetCompilerType().GetTypeName(); 74 AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); 75 return qualified_name; 76 } 77 78 ConstString ValueObjectChild::GetDisplayTypeName() { 79 ConstString display_name = GetCompilerType().GetDisplayTypeName(); 80 AdjustForBitfieldness(display_name, m_bitfield_bit_size); 81 return display_name; 82 } 83 84 LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { 85 if (m_can_update_with_invalid_exe_ctx.hasValue()) 86 return m_can_update_with_invalid_exe_ctx.getValue(); 87 if (m_parent) { 88 ValueObject *opinionated_parent = 89 m_parent->FollowParentChain([](ValueObject *valobj) -> bool { 90 return (valobj->CanUpdateWithInvalidExecutionContext() == 91 eLazyBoolCalculate); 92 }); 93 if (opinionated_parent) 94 return (m_can_update_with_invalid_exe_ctx = 95 opinionated_parent->CanUpdateWithInvalidExecutionContext()) 96 .getValue(); 97 } 98 return (m_can_update_with_invalid_exe_ctx = 99 this->ValueObject::CanUpdateWithInvalidExecutionContext()) 100 .getValue(); 101 } 102 103 bool ValueObjectChild::UpdateValue() { 104 m_error.Clear(); 105 SetValueIsValid(false); 106 ValueObject *parent = m_parent; 107 if (parent) { 108 if (parent->UpdateValueIfNeeded(false)) { 109 m_value.SetCompilerType(GetCompilerType()); 110 111 CompilerType parent_type(parent->GetCompilerType()); 112 // Copy the parent scalar value and the scalar value type 113 m_value.GetScalar() = parent->GetValue().GetScalar(); 114 Value::ValueType value_type = parent->GetValue().GetValueType(); 115 m_value.SetValueType(value_type); 116 117 Flags parent_type_flags(parent_type.GetTypeInfo()); 118 const bool is_instance_ptr_base = 119 ((m_is_base_class) && 120 (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer))); 121 122 if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) { 123 lldb::addr_t addr = parent->GetPointerValue(); 124 m_value.GetScalar() = addr; 125 126 if (addr == LLDB_INVALID_ADDRESS) { 127 m_error.SetErrorString("parent address is invalid."); 128 } else if (addr == 0) { 129 m_error.SetErrorString("parent is NULL"); 130 } else { 131 m_value.GetScalar() += m_byte_offset; 132 AddressType addr_type = parent->GetAddressTypeOfChildren(); 133 134 switch (addr_type) { 135 case eAddressTypeFile: { 136 lldb::ProcessSP process_sp(GetProcessSP()); 137 if (process_sp && process_sp->IsAlive()) 138 m_value.SetValueType(Value::eValueTypeLoadAddress); 139 else 140 m_value.SetValueType(Value::eValueTypeFileAddress); 141 } break; 142 case eAddressTypeLoad: 143 m_value.SetValueType(is_instance_ptr_base 144 ? Value::eValueTypeScalar 145 : Value::eValueTypeLoadAddress); 146 break; 147 case eAddressTypeHost: 148 m_value.SetValueType(Value::eValueTypeHostAddress); 149 break; 150 case eAddressTypeInvalid: 151 // TODO: does this make sense? 152 m_value.SetValueType(Value::eValueTypeScalar); 153 break; 154 } 155 } 156 } else { 157 switch (value_type) { 158 case Value::eValueTypeLoadAddress: 159 case Value::eValueTypeFileAddress: 160 case Value::eValueTypeHostAddress: { 161 lldb::addr_t addr = 162 m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); 163 if (addr == LLDB_INVALID_ADDRESS) { 164 m_error.SetErrorString("parent address is invalid."); 165 } else if (addr == 0) { 166 m_error.SetErrorString("parent is NULL"); 167 } else { 168 // Set this object's scalar value to the address of its value by 169 // adding its byte offset to the parent address 170 m_value.GetScalar() += GetByteOffset(); 171 172 // If a bitfield doesn't fit into the child_byte_size'd 173 // window at child_byte_offset, move the window forward 174 // until it fits. The problem here is that Value has no 175 // notion of bitfields and thus the Value's DataExtractor 176 // is sized like the bitfields CompilerType; a sequence of 177 // bitfields, however, can be larger than their underlying 178 // type. 179 if (m_bitfield_bit_offset) { 180 const bool thread_and_frame_only_if_stopped = true; 181 ExecutionContext exe_ctx(GetExecutionContextRef().Lock( 182 thread_and_frame_only_if_stopped)); 183 if (auto type_bit_size = GetCompilerType().GetBitSize( 184 exe_ctx.GetBestExecutionContextScope())) { 185 uint64_t bitfield_end = 186 m_bitfield_bit_size + m_bitfield_bit_offset; 187 if (bitfield_end > *type_bit_size) { 188 uint64_t overhang_bytes = 189 (bitfield_end - *type_bit_size + 7) / 8; 190 m_value.GetScalar() += overhang_bytes; 191 m_bitfield_bit_offset -= overhang_bytes * 8; 192 } 193 } 194 } 195 } 196 } break; 197 198 case Value::eValueTypeScalar: 199 // try to extract the child value from the parent's scalar value 200 { 201 Scalar scalar(m_value.GetScalar()); 202 scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset); 203 m_value.GetScalar() = scalar; 204 } 205 break; 206 default: 207 m_error.SetErrorString("parent has invalid value."); 208 break; 209 } 210 } 211 212 if (m_error.Success()) { 213 const bool thread_and_frame_only_if_stopped = true; 214 ExecutionContext exe_ctx( 215 GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); 216 if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) { 217 Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value; 218 m_error = 219 value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 220 } else { 221 m_error.Clear(); // No value so nothing to read... 222 } 223 } 224 225 } else { 226 m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", 227 parent->GetError().AsCString()); 228 } 229 } else { 230 m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); 231 } 232 233 return m_error.Success(); 234 } 235 236 bool ValueObjectChild::IsInScope() { 237 ValueObject *root(GetRoot()); 238 if (root) 239 return root->IsInScope(); 240 return false; 241 } 242