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