178a685aaSJim Ingham //===-- ValueObjectMemory.cpp ---------------------------------*- C++ -*-===//
278a685aaSJim Ingham //
378a685aaSJim Ingham //                     The LLVM Compiler Infrastructure
478a685aaSJim Ingham //
578a685aaSJim Ingham // This file is distributed under the University of Illinois Open Source
678a685aaSJim Ingham // License. See LICENSE.TXT for details.
778a685aaSJim Ingham //
878a685aaSJim Ingham //===----------------------------------------------------------------------===//
978a685aaSJim Ingham 
1078a685aaSJim Ingham 
1178a685aaSJim Ingham #include "lldb/Core/ValueObjectMemory.h"
1278a685aaSJim Ingham 
1378a685aaSJim Ingham // C Includes
1478a685aaSJim Ingham // C++ Includes
1578a685aaSJim Ingham // Other libraries and framework includes
1678a685aaSJim Ingham // Project includes
1778a685aaSJim Ingham #include "lldb/Core/Module.h"
1878a685aaSJim Ingham #include "lldb/Core/ValueObjectList.h"
1978a685aaSJim Ingham #include "lldb/Core/Value.h"
2078a685aaSJim Ingham #include "lldb/Core/ValueObject.h"
2178a685aaSJim Ingham 
2278a685aaSJim Ingham #include "lldb/Symbol/ObjectFile.h"
2378a685aaSJim Ingham #include "lldb/Symbol/SymbolContext.h"
2478a685aaSJim Ingham #include "lldb/Symbol/Type.h"
2578a685aaSJim Ingham #include "lldb/Symbol/Variable.h"
2678a685aaSJim Ingham 
2778a685aaSJim Ingham #include "lldb/Target/ExecutionContext.h"
2878a685aaSJim Ingham #include "lldb/Target/Process.h"
2978a685aaSJim Ingham #include "lldb/Target/RegisterContext.h"
3078a685aaSJim Ingham #include "lldb/Target/Target.h"
3178a685aaSJim Ingham #include "lldb/Target/Thread.h"
3278a685aaSJim Ingham 
33*58b59f95SJim Ingham using namespace lldb;
3478a685aaSJim Ingham using namespace lldb_private;
3578a685aaSJim Ingham 
36*58b59f95SJim Ingham ValueObjectSP
37*58b59f95SJim Ingham ValueObjectMemory::Create (ExecutionContextScope *exe_scope,
38*58b59f95SJim Ingham                            const char *name,
39*58b59f95SJim Ingham                            const Address &address,
40*58b59f95SJim Ingham                            lldb::TypeSP &type_sp)
41*58b59f95SJim Ingham {
42*58b59f95SJim Ingham     return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP();
43*58b59f95SJim Ingham }
44*58b59f95SJim Ingham 
4578a685aaSJim Ingham ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope,
4678a685aaSJim Ingham                                       const char *name,
4778a685aaSJim Ingham                                       const Address &address,
4878a685aaSJim Ingham                                       lldb::TypeSP &type_sp) :
4978a685aaSJim Ingham     ValueObject(exe_scope),
5078a685aaSJim Ingham     m_address (address),
5178a685aaSJim Ingham     m_type_sp(type_sp)
5278a685aaSJim Ingham {
5378a685aaSJim Ingham     // Do not attempt to construct one of these objects with no variable!
5478a685aaSJim Ingham     assert (m_type_sp.get() != NULL);
5578a685aaSJim Ingham     SetName (name);
5678a685aaSJim Ingham     m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
5778a685aaSJim Ingham     lldb::addr_t load_address = m_address.GetLoadAddress(m_update_point.GetTarget());
5878a685aaSJim Ingham     if (load_address != LLDB_INVALID_ADDRESS)
5978a685aaSJim Ingham     {
6078a685aaSJim Ingham         m_value.SetValueType(Value::eValueTypeLoadAddress);
6178a685aaSJim Ingham         m_value.GetScalar() = load_address;
6278a685aaSJim Ingham     }
6378a685aaSJim Ingham     else
6478a685aaSJim Ingham     {
6578a685aaSJim Ingham         lldb::addr_t file_address = m_address.GetFileAddress();
6678a685aaSJim Ingham         if (file_address != LLDB_INVALID_ADDRESS)
6778a685aaSJim Ingham         {
6878a685aaSJim Ingham             m_value.SetValueType(Value::eValueTypeFileAddress);
6978a685aaSJim Ingham             m_value.GetScalar() = file_address;
7078a685aaSJim Ingham         }
7178a685aaSJim Ingham         else
7278a685aaSJim Ingham         {
7378a685aaSJim Ingham             m_value.GetScalar() = m_address.GetOffset();
7478a685aaSJim Ingham             m_value.SetValueType (Value::eValueTypeScalar);
7578a685aaSJim Ingham         }
7678a685aaSJim Ingham     }
7778a685aaSJim Ingham }
7878a685aaSJim Ingham 
7978a685aaSJim Ingham ValueObjectMemory::~ValueObjectMemory()
8078a685aaSJim Ingham {
8178a685aaSJim Ingham }
8278a685aaSJim Ingham 
8378a685aaSJim Ingham lldb::clang_type_t
8478a685aaSJim Ingham ValueObjectMemory::GetClangType ()
8578a685aaSJim Ingham {
8678a685aaSJim Ingham     return m_type_sp->GetClangForwardType();
8778a685aaSJim Ingham }
8878a685aaSJim Ingham 
8978a685aaSJim Ingham ConstString
9078a685aaSJim Ingham ValueObjectMemory::GetTypeName()
9178a685aaSJim Ingham {
9278a685aaSJim Ingham     return m_type_sp->GetName();
9378a685aaSJim Ingham }
9478a685aaSJim Ingham 
9578a685aaSJim Ingham uint32_t
9678a685aaSJim Ingham ValueObjectMemory::CalculateNumChildren()
9778a685aaSJim Ingham {
9878a685aaSJim Ingham     return m_type_sp->GetNumChildren(true);
9978a685aaSJim Ingham }
10078a685aaSJim Ingham 
10178a685aaSJim Ingham clang::ASTContext *
10278a685aaSJim Ingham ValueObjectMemory::GetClangAST ()
10378a685aaSJim Ingham {
10478a685aaSJim Ingham     return m_type_sp->GetClangAST();
10578a685aaSJim Ingham }
10678a685aaSJim Ingham 
10778a685aaSJim Ingham size_t
10878a685aaSJim Ingham ValueObjectMemory::GetByteSize()
10978a685aaSJim Ingham {
11078a685aaSJim Ingham     return m_type_sp->GetByteSize();
11178a685aaSJim Ingham }
11278a685aaSJim Ingham 
11378a685aaSJim Ingham lldb::ValueType
11478a685aaSJim Ingham ValueObjectMemory::GetValueType() const
11578a685aaSJim Ingham {
11678a685aaSJim Ingham     // RETHINK: Should this be inherited from somewhere?
11778a685aaSJim Ingham     return lldb::eValueTypeVariableGlobal;
11878a685aaSJim Ingham }
11978a685aaSJim Ingham 
12078a685aaSJim Ingham bool
12178a685aaSJim Ingham ValueObjectMemory::UpdateValue ()
12278a685aaSJim Ingham {
12378a685aaSJim Ingham     SetValueIsValid (false);
12478a685aaSJim Ingham     m_error.Clear();
12578a685aaSJim Ingham 
12678a685aaSJim Ingham     ExecutionContext exe_ctx (GetExecutionContextScope());
12778a685aaSJim Ingham 
12878a685aaSJim Ingham     if (exe_ctx.target)
12978a685aaSJim Ingham     {
13078a685aaSJim Ingham         m_data.SetByteOrder(exe_ctx.target->GetArchitecture().GetByteOrder());
13178a685aaSJim Ingham         m_data.SetAddressByteSize(exe_ctx.target->GetArchitecture().GetAddressByteSize());
13278a685aaSJim Ingham     }
13378a685aaSJim Ingham 
13478a685aaSJim Ingham     Value old_value(m_value);
13578a685aaSJim Ingham     if (m_address.IsValid())
13678a685aaSJim Ingham     {
13778a685aaSJim Ingham         Value::ValueType value_type = m_value.GetValueType();
13878a685aaSJim Ingham 
13978a685aaSJim Ingham         switch (value_type)
14078a685aaSJim Ingham         {
14178a685aaSJim Ingham         default:
14278a685aaSJim Ingham             assert(!"Unhandled expression result value kind...");
14378a685aaSJim Ingham             break;
14478a685aaSJim Ingham 
14578a685aaSJim Ingham         case Value::eValueTypeScalar:
14678a685aaSJim Ingham             // The variable value is in the Scalar value inside the m_value.
14778a685aaSJim Ingham             // We can point our m_data right to it.
14878a685aaSJim Ingham             m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0);
14978a685aaSJim Ingham             break;
15078a685aaSJim Ingham 
15178a685aaSJim Ingham         case Value::eValueTypeFileAddress:
15278a685aaSJim Ingham         case Value::eValueTypeLoadAddress:
15378a685aaSJim Ingham         case Value::eValueTypeHostAddress:
15478a685aaSJim Ingham             // The DWARF expression result was an address in the inferior
15578a685aaSJim Ingham             // process. If this variable is an aggregate type, we just need
15678a685aaSJim Ingham             // the address as the main value as all child variable objects
15778a685aaSJim Ingham             // will rely upon this location and add an offset and then read
15878a685aaSJim Ingham             // their own values as needed. If this variable is a simple
15978a685aaSJim Ingham             // type, we read all data for it into m_data.
16078a685aaSJim Ingham             // Make sure this type has a value before we try and read it
16178a685aaSJim Ingham 
16278a685aaSJim Ingham             // If we have a file address, convert it to a load address if we can.
16378a685aaSJim Ingham             if (value_type == Value::eValueTypeFileAddress && exe_ctx.process)
16478a685aaSJim Ingham             {
16578a685aaSJim Ingham                 lldb::addr_t load_addr = m_address.GetLoadAddress(exe_ctx.target);
16678a685aaSJim Ingham                 if (load_addr != LLDB_INVALID_ADDRESS)
16778a685aaSJim Ingham                 {
16878a685aaSJim Ingham                     m_value.SetValueType(Value::eValueTypeLoadAddress);
16978a685aaSJim Ingham                     m_value.GetScalar() = load_addr;
17078a685aaSJim Ingham                 }
17178a685aaSJim Ingham             }
17278a685aaSJim Ingham 
17378a685aaSJim Ingham             if (ClangASTContext::IsAggregateType (GetClangType()))
17478a685aaSJim Ingham             {
17578a685aaSJim Ingham                 // this value object represents an aggregate type whose
17678a685aaSJim Ingham                 // children have values, but this object does not. So we
17778a685aaSJim Ingham                 // say we are changed if our location has changed.
17878a685aaSJim Ingham                 SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
17978a685aaSJim Ingham             }
18078a685aaSJim Ingham             else
18178a685aaSJim Ingham             {
18278a685aaSJim Ingham                 // Copy the Value and set the context to use our Variable
18378a685aaSJim Ingham                 // so it can extract read its value into m_data appropriately
18478a685aaSJim Ingham                 Value value(m_value);
18578a685aaSJim Ingham                 value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get());
18678a685aaSJim Ingham                 m_error = value.GetValueAsData(&exe_ctx, GetClangAST(), m_data, 0);
18778a685aaSJim Ingham             }
18878a685aaSJim Ingham             break;
18978a685aaSJim Ingham         }
19078a685aaSJim Ingham 
19178a685aaSJim Ingham         SetValueIsValid (m_error.Success());
19278a685aaSJim Ingham     }
19378a685aaSJim Ingham     return m_error.Success();
19478a685aaSJim Ingham }
19578a685aaSJim Ingham 
19678a685aaSJim Ingham 
19778a685aaSJim Ingham 
19878a685aaSJim Ingham bool
19978a685aaSJim Ingham ValueObjectMemory::IsInScope ()
20078a685aaSJim Ingham {
20178a685aaSJim Ingham     // FIXME: Maybe try to read the memory address, and if that works, then
20278a685aaSJim Ingham     // we are in scope?
20378a685aaSJim Ingham     return true;
20478a685aaSJim Ingham }
20578a685aaSJim Ingham 
206