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