ValueObjectChild.cpp revision 9db023bd392ede8fc4c92d7dfee64382e08bbd78
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/ClangASTType.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
25using namespace lldb_private;
26
27ValueObjectChild::ValueObjectChild
28(
29    ValueObject* parent,
30    clang::ASTContext *clang_ast,
31    void *clang_type,
32    const ConstString &name,
33    uint32_t byte_size,
34    int32_t byte_offset,
35    uint32_t bitfield_bit_size,
36    uint32_t bitfield_bit_offset,
37    bool is_base_class
38) :
39    ValueObject (parent),
40    m_clang_ast (clang_ast),
41    m_clang_type (clang_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{
48    assert (bitfield_bit_size   < (sizeof(m_bitfield_bit_size  ) * CHAR_BIT));
49    assert (bitfield_bit_offset < (sizeof(m_bitfield_bit_offset) * CHAR_BIT));
50    m_name = name;
51}
52
53ValueObjectChild::~ValueObjectChild()
54{
55}
56
57lldb::ValueType
58ValueObjectChild::GetValueType() const
59{
60    return m_parent->GetValueType();
61}
62
63uint32_t
64ValueObjectChild::CalculateNumChildren()
65{
66    return ClangASTContext::GetNumChildren (m_clang_type, true);
67}
68
69ConstString
70ValueObjectChild::GetTypeName()
71{
72    if (m_type_name.IsEmpty())
73    {
74        m_type_name = ClangASTType::GetClangTypeName (GetClangType());
75        if (m_type_name)
76        {
77            if (m_bitfield_bit_size > 0)
78            {
79                const char *clang_type_name = m_type_name.AsCString();
80                if (clang_type_name)
81                {
82                    std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
83                    ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
84                    m_type_name.SetCString(&bitfield_type_name.front());
85                }
86            }
87        }
88    }
89    return m_type_name;
90}
91
92void
93ValueObjectChild::UpdateValue (ExecutionContextScope *exe_scope)
94{
95    m_error.Clear();
96    SetValueIsValid (false);
97    ValueObject* parent = m_parent;
98    if (parent)
99    {
100        if (parent->UpdateValueIfNeeded(exe_scope))
101        {
102            m_value.SetContext(Value::eContextTypeClangType, m_clang_type);
103
104            // Copy the parent scalar value and the scalar value type
105            m_value.GetScalar() = parent->GetValue().GetScalar();
106            Value::ValueType value_type = parent->GetValue().GetValueType();
107            m_value.SetValueType (value_type);
108
109            if (ClangASTContext::IsPointerOrReferenceType (parent->GetClangType()))
110            {
111                uint32_t offset = 0;
112                m_value.GetScalar() = parent->GetDataExtractor().GetPointer(&offset);
113
114                lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
115
116                if (addr == LLDB_INVALID_ADDRESS)
117                {
118                    m_error.SetErrorString ("parent address is invalid.");
119                }
120                else if (addr == 0)
121                {
122                    m_error.SetErrorString ("parent is NULL");
123                }
124                else
125                {
126                    m_value.GetScalar() += m_byte_offset;
127                    if (m_pointers_point_to_load_addrs ||
128                        value_type == Value::eValueTypeScalar ||
129                        value_type == Value::eValueTypeFileAddress)
130                        m_value.SetValueType (Value::eValueTypeLoadAddress);
131                }
132            }
133            else
134            {
135                switch (value_type)
136                {
137                case Value::eValueTypeLoadAddress:
138                case Value::eValueTypeFileAddress:
139                case Value::eValueTypeHostAddress:
140                    {
141                        lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
142                        if (addr == LLDB_INVALID_ADDRESS)
143                        {
144                            m_error.SetErrorString ("parent address is invalid.");
145                        }
146                        else if (addr == 0)
147                        {
148                            m_error.SetErrorString ("parent is NULL");
149                        }
150                        else
151                        {
152                            // Set this object's scalar value to the address of its
153                            // value be adding its byte offset to the parent address
154                            m_value.GetScalar() += GetByteOffset();
155                        }
156                    }
157                    break;
158
159                case Value::eValueTypeScalar:
160                    // TODO: What if this is a register value? Do we try and
161                    // extract the child value from within the parent data?
162                    // Probably...
163                default:
164                    m_error.SetErrorString ("Parent has invalid value.");
165                    break;
166                }
167            }
168
169            if (m_error.Success())
170            {
171                ExecutionContext exe_ctx (exe_scope);
172                m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0);
173            }
174        }
175        else
176        {
177            m_error.SetErrorStringWithFormat("Parent failed to evaluate: %s.\n", parent->GetError().AsCString());
178        }
179    }
180    else
181    {
182        m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
183    }
184}
185
186
187bool
188ValueObjectChild::IsInScope (StackFrame *frame)
189{
190    return m_parent->IsInScope (frame);
191}
192