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