ValueObjectChild.cpp revision b2fbdad3f48f40932d7d839b2ac7e3363846a9c3
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    bool is_deref_of_parent
39) :
40    ValueObject (parent),
41    m_clang_ast (clang_ast),
42    m_clang_type (clang_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{
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 (GetClangAST (), m_clang_type, true);
67}
68
69ConstString
70ValueObjectChild::GetTypeName()
71{
72    if (m_type_name.IsEmpty())
73    {
74        m_type_name = ClangASTType::GetConstTypeName (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
92bool
93ValueObjectChild::UpdateValue ()
94{
95    m_error.Clear();
96    SetValueIsValid (false);
97    ValueObject* parent = m_parent;
98    if (parent)
99    {
100        if (parent->UpdateValueIfNeeded(false))
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                const bool scalar_is_load_address = true;
112                AddressType address_type;
113
114                lldb::addr_t addr = parent->GetPointerValue (address_type, scalar_is_load_address);
115                m_value.GetScalar() = addr;
116
117                if (addr == LLDB_INVALID_ADDRESS)
118                {
119                    m_error.SetErrorString ("parent address is invalid.");
120                }
121                else if (addr == 0)
122                {
123                    m_error.SetErrorString ("parent is NULL");
124                }
125                else
126                {
127                    m_value.GetScalar() += m_byte_offset;
128                    if (m_pointers_point_to_load_addrs ||
129                        value_type == Value::eValueTypeScalar ||
130                        value_type == Value::eValueTypeFileAddress)
131                        m_value.SetValueType (Value::eValueTypeLoadAddress);
132                }
133            }
134            else
135            {
136                switch (value_type)
137                {
138                case Value::eValueTypeLoadAddress:
139                case Value::eValueTypeFileAddress:
140                case Value::eValueTypeHostAddress:
141                    {
142                        lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
143                        if (addr == LLDB_INVALID_ADDRESS)
144                        {
145                            m_error.SetErrorString ("parent address is invalid.");
146                        }
147                        else if (addr == 0)
148                        {
149                            m_error.SetErrorString ("parent is NULL");
150                        }
151                        else
152                        {
153                            // Set this object's scalar value to the address of its
154                            // value by adding its byte offset to the parent address
155                            m_value.GetScalar() += GetByteOffset();
156                        }
157                    }
158                    break;
159
160                case Value::eValueTypeScalar:
161                    // TODO: What if this is a register value? Do we try and
162                    // extract the child value from within the parent data?
163                    // Probably...
164                default:
165                    m_error.SetErrorString ("Parent has invalid value.");
166                    break;
167                }
168            }
169
170            if (m_error.Success())
171            {
172                ExecutionContext exe_ctx (GetExecutionContextScope());
173                m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0, GetModule());
174            }
175        }
176        else
177        {
178            m_error.SetErrorStringWithFormat("Parent failed to evaluate: %s.\n", parent->GetError().AsCString());
179        }
180    }
181    else
182    {
183        m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
184    }
185
186    return m_error.Success();
187}
188
189
190bool
191ValueObjectChild::IsInScope ()
192{
193    return m_parent->IsInScope ();
194}
195