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