1 //===-- ValueObjectMemory.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 11 #include "lldb/Core/ValueObjectMemory.h" 12 13 // C Includes 14 // C++ Includes 15 // Other libraries and framework includes 16 // Project includes 17 #include "lldb/Core/Module.h" 18 #include "lldb/Core/ValueObjectList.h" 19 #include "lldb/Core/Value.h" 20 #include "lldb/Core/ValueObject.h" 21 22 #include "lldb/Symbol/ObjectFile.h" 23 #include "lldb/Symbol/SymbolContext.h" 24 #include "lldb/Symbol/Type.h" 25 #include "lldb/Symbol/Variable.h" 26 27 #include "lldb/Target/ExecutionContext.h" 28 #include "lldb/Target/Process.h" 29 #include "lldb/Target/RegisterContext.h" 30 #include "lldb/Target/Target.h" 31 #include "lldb/Target/Thread.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 ValueObjectSP 37 ValueObjectMemory::Create (ExecutionContextScope *exe_scope, 38 const char *name, 39 const Address &address, 40 lldb::TypeSP &type_sp) 41 { 42 return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP(); 43 } 44 45 ValueObjectSP 46 ValueObjectMemory::Create (ExecutionContextScope *exe_scope, 47 const char *name, 48 const Address &address, 49 const ClangASTType &ast_type) 50 { 51 return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP(); 52 } 53 54 ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, 55 const char *name, 56 const Address &address, 57 lldb::TypeSP &type_sp) : 58 ValueObject(exe_scope), 59 m_address (address), 60 m_type_sp(type_sp), 61 m_clang_type() 62 { 63 // Do not attempt to construct one of these objects with no variable! 64 assert (m_type_sp.get() != NULL); 65 SetName (ConstString(name)); 66 m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 67 lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get()); 68 if (load_address != LLDB_INVALID_ADDRESS) 69 { 70 m_value.SetValueType(Value::eValueTypeLoadAddress); 71 m_value.GetScalar() = load_address; 72 } 73 else 74 { 75 lldb::addr_t file_address = m_address.GetFileAddress(); 76 if (file_address != LLDB_INVALID_ADDRESS) 77 { 78 m_value.SetValueType(Value::eValueTypeFileAddress); 79 m_value.GetScalar() = file_address; 80 } 81 else 82 { 83 m_value.GetScalar() = m_address.GetOffset(); 84 m_value.SetValueType (Value::eValueTypeScalar); 85 } 86 } 87 } 88 89 ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, 90 const char *name, 91 const Address &address, 92 const ClangASTType &ast_type) : 93 ValueObject(exe_scope), 94 m_address (address), 95 m_type_sp(), 96 m_clang_type(ast_type) 97 { 98 // Do not attempt to construct one of these objects with no variable! 99 assert (m_clang_type.GetASTContext()); 100 assert (m_clang_type.GetOpaqueQualType()); 101 102 SetName (ConstString(name)); 103 m_value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); 104 lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTargetSP().get()); 105 if (load_address != LLDB_INVALID_ADDRESS) 106 { 107 m_value.SetValueType(Value::eValueTypeLoadAddress); 108 m_value.GetScalar() = load_address; 109 } 110 else 111 { 112 lldb::addr_t file_address = m_address.GetFileAddress(); 113 if (file_address != LLDB_INVALID_ADDRESS) 114 { 115 m_value.SetValueType(Value::eValueTypeFileAddress); 116 m_value.GetScalar() = file_address; 117 } 118 else 119 { 120 m_value.GetScalar() = m_address.GetOffset(); 121 m_value.SetValueType (Value::eValueTypeScalar); 122 } 123 } 124 } 125 126 ValueObjectMemory::~ValueObjectMemory() 127 { 128 } 129 130 lldb::clang_type_t 131 ValueObjectMemory::GetClangType () 132 { 133 if (m_type_sp) 134 return m_type_sp->GetClangForwardType(); 135 return m_clang_type.GetOpaqueQualType(); 136 } 137 138 ConstString 139 ValueObjectMemory::GetTypeName() 140 { 141 if (m_type_sp) 142 return m_type_sp->GetName(); 143 return ClangASTType::GetConstTypeName (m_clang_type.GetOpaqueQualType()); 144 } 145 146 uint32_t 147 ValueObjectMemory::CalculateNumChildren() 148 { 149 if (m_type_sp) 150 return m_type_sp->GetNumChildren(true); 151 const bool omit_empty_base_classes = true; 152 return ClangASTContext::GetNumChildren (m_clang_type.GetASTContext(), 153 m_clang_type.GetOpaqueQualType(), 154 omit_empty_base_classes); 155 } 156 157 clang::ASTContext * 158 ValueObjectMemory::GetClangAST () 159 { 160 if (m_type_sp) 161 return m_type_sp->GetClangAST(); 162 return m_clang_type.GetASTContext(); 163 } 164 165 size_t 166 ValueObjectMemory::GetByteSize() 167 { 168 if (m_type_sp) 169 return m_type_sp->GetByteSize(); 170 return (m_clang_type.GetClangTypeBitWidth () + 7) / 8; 171 } 172 173 lldb::ValueType 174 ValueObjectMemory::GetValueType() const 175 { 176 // RETHINK: Should this be inherited from somewhere? 177 return lldb::eValueTypeVariableGlobal; 178 } 179 180 bool 181 ValueObjectMemory::UpdateValue () 182 { 183 SetValueIsValid (false); 184 m_error.Clear(); 185 186 ExecutionContext exe_ctx (GetExecutionContextScope()); 187 188 Target *target = exe_ctx.GetTargetPtr(); 189 if (target) 190 { 191 m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); 192 m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); 193 } 194 195 Value old_value(m_value); 196 if (m_address.IsValid()) 197 { 198 Value::ValueType value_type = m_value.GetValueType(); 199 200 switch (value_type) 201 { 202 default: 203 assert(!"Unhandled expression result value kind..."); 204 break; 205 206 case Value::eValueTypeScalar: 207 // The variable value is in the Scalar value inside the m_value. 208 // We can point our m_data right to it. 209 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule()); 210 break; 211 212 case Value::eValueTypeFileAddress: 213 case Value::eValueTypeLoadAddress: 214 case Value::eValueTypeHostAddress: 215 // The DWARF expression result was an address in the inferior 216 // process. If this variable is an aggregate type, we just need 217 // the address as the main value as all child variable objects 218 // will rely upon this location and add an offset and then read 219 // their own values as needed. If this variable is a simple 220 // type, we read all data for it into m_data. 221 // Make sure this type has a value before we try and read it 222 223 // If we have a file address, convert it to a load address if we can. 224 if (value_type == Value::eValueTypeFileAddress && exe_ctx.GetProcessPtr()) 225 { 226 lldb::addr_t load_addr = m_address.GetLoadAddress(target); 227 if (load_addr != LLDB_INVALID_ADDRESS) 228 { 229 m_value.SetValueType(Value::eValueTypeLoadAddress); 230 m_value.GetScalar() = load_addr; 231 } 232 } 233 234 if (ClangASTContext::IsAggregateType (GetClangType())) 235 { 236 // this value object represents an aggregate type whose 237 // children have values, but this object does not. So we 238 // say we are changed if our location has changed. 239 SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); 240 } 241 else 242 { 243 // Copy the Value and set the context to use our Variable 244 // so it can extract read its value into m_data appropriately 245 Value value(m_value); 246 if (m_type_sp) 247 value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); 248 else 249 value.SetContext(Value::eContextTypeClangType, m_clang_type.GetOpaqueQualType()); 250 251 m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0, GetModule()); 252 } 253 break; 254 } 255 256 SetValueIsValid (m_error.Success()); 257 } 258 return m_error.Success(); 259 } 260 261 262 263 bool 264 ValueObjectMemory::IsInScope () 265 { 266 // FIXME: Maybe try to read the memory address, and if that works, then 267 // we are in scope? 268 return true; 269 } 270 271 272 Module * 273 ValueObjectMemory::GetModule() 274 { 275 return m_address.GetModule(); 276 } 277 278 279