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 
25 using namespace lldb_private;
26 
27 ValueObjectChild::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 
53 ValueObjectChild::~ValueObjectChild()
54 {
55 }
56 
57 lldb::ValueType
58 ValueObjectChild::GetValueType() const
59 {
60     return m_parent->GetValueType();
61 }
62 
63 uint32_t
64 ValueObjectChild::CalculateNumChildren()
65 {
66     return ClangASTContext::GetNumChildren (GetClangAST (), m_clang_type, true);
67 }
68 
69 ConstString
70 ValueObjectChild::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 
92 void
93 ValueObjectChild::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 
187 bool
188 ValueObjectChild::IsInScope (StackFrame *frame)
189 {
190     return m_parent->IsInScope (frame);
191 }
192