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
ValueObjectChild(ValueObject & parent,const ClangASTType & clang_type,const ConstString & name,uint64_t byte_size,int32_t byte_offset,uint32_t bitfield_bit_size,uint32_t bitfield_bit_offset,bool is_base_class,bool is_deref_of_parent,AddressType child_ptr_or_ref_addr_type)27 ValueObjectChild::ValueObjectChild
28 (
29 ValueObject &parent,
30 const ClangASTType &clang_type,
31 const ConstString &name,
32 uint64_t byte_size,
33 int32_t byte_offset,
34 uint32_t bitfield_bit_size,
35 uint32_t bitfield_bit_offset,
36 bool is_base_class,
37 bool is_deref_of_parent,
38 AddressType child_ptr_or_ref_addr_type
39 ) :
40 ValueObject (parent),
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 m_is_deref_of_parent (is_deref_of_parent)
48 {
49 m_name = name;
50 SetAddressTypeOfChildren(child_ptr_or_ref_addr_type);
51 }
52
~ValueObjectChild()53 ValueObjectChild::~ValueObjectChild()
54 {
55 }
56
57 lldb::ValueType
GetValueType() const58 ValueObjectChild::GetValueType() const
59 {
60 return m_parent->GetValueType();
61 }
62
63 size_t
CalculateNumChildren()64 ValueObjectChild::CalculateNumChildren()
65 {
66 return GetClangType().GetNumChildren (true);
67 }
68
69 static void
AdjustForBitfieldness(ConstString & name,uint8_t bitfield_bit_size)70 AdjustForBitfieldness(ConstString& name,
71 uint8_t bitfield_bit_size)
72 {
73 if (name && bitfield_bit_size)
74 {
75 const char *clang_type_name = name.AsCString();
76 if (clang_type_name)
77 {
78 std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
79 ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, bitfield_bit_size);
80 name.SetCString(&bitfield_type_name.front());
81 }
82 }
83 }
84
85 ConstString
GetTypeName()86 ValueObjectChild::GetTypeName()
87 {
88 if (m_type_name.IsEmpty())
89 {
90 m_type_name = GetClangType().GetConstTypeName ();
91 AdjustForBitfieldness(m_type_name, m_bitfield_bit_size);
92 }
93 return m_type_name;
94 }
95
96 ConstString
GetQualifiedTypeName()97 ValueObjectChild::GetQualifiedTypeName()
98 {
99 ConstString qualified_name = GetClangType().GetConstTypeName();
100 AdjustForBitfieldness(qualified_name, m_bitfield_bit_size);
101 return qualified_name;
102 }
103
104 ConstString
GetDisplayTypeName()105 ValueObjectChild::GetDisplayTypeName()
106 {
107 ConstString display_name = GetClangType().GetDisplayTypeName();
108 AdjustForBitfieldness(display_name, m_bitfield_bit_size);
109 return display_name;
110 }
111
112 bool
CanUpdateWithInvalidExecutionContext()113 ValueObjectChild::CanUpdateWithInvalidExecutionContext ()
114 {
115 if (m_parent)
116 return m_parent->CanUpdateWithInvalidExecutionContext();
117 return this->ValueObject::CanUpdateWithInvalidExecutionContext();
118 }
119
120 bool
UpdateValue()121 ValueObjectChild::UpdateValue ()
122 {
123 m_error.Clear();
124 SetValueIsValid (false);
125 ValueObject* parent = m_parent;
126 if (parent)
127 {
128 if (parent->UpdateValueIfNeeded(false))
129 {
130 m_value.SetClangType(GetClangType());
131
132 // Copy the parent scalar value and the scalar value type
133 m_value.GetScalar() = parent->GetValue().GetScalar();
134 Value::ValueType value_type = parent->GetValue().GetValueType();
135 m_value.SetValueType (value_type);
136
137 if (parent->GetClangType().IsPointerOrReferenceType ())
138 {
139 lldb::addr_t addr = parent->GetPointerValue ();
140 m_value.GetScalar() = addr;
141
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 m_value.GetScalar() += m_byte_offset;
153 AddressType addr_type = parent->GetAddressTypeOfChildren();
154
155 switch (addr_type)
156 {
157 case eAddressTypeFile:
158 {
159 lldb::ProcessSP process_sp (GetProcessSP());
160 if (process_sp && process_sp->IsAlive() == true)
161 m_value.SetValueType (Value::eValueTypeLoadAddress);
162 else
163 m_value.SetValueType(Value::eValueTypeFileAddress);
164 }
165 break;
166 case eAddressTypeLoad:
167 m_value.SetValueType (Value::eValueTypeLoadAddress);
168 break;
169 case eAddressTypeHost:
170 m_value.SetValueType(Value::eValueTypeHostAddress);
171 break;
172 case eAddressTypeInvalid:
173 // TODO: does this make sense?
174 m_value.SetValueType(Value::eValueTypeScalar);
175 break;
176 }
177 }
178 }
179 else
180 {
181 switch (value_type)
182 {
183 case Value::eValueTypeLoadAddress:
184 case Value::eValueTypeFileAddress:
185 case Value::eValueTypeHostAddress:
186 {
187 lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
188 if (addr == LLDB_INVALID_ADDRESS)
189 {
190 m_error.SetErrorString ("parent address is invalid.");
191 }
192 else if (addr == 0)
193 {
194 m_error.SetErrorString ("parent is NULL");
195 }
196 else
197 {
198 // Set this object's scalar value to the address of its
199 // value by adding its byte offset to the parent address
200 m_value.GetScalar() += GetByteOffset();
201 }
202 }
203 break;
204
205 case Value::eValueTypeScalar:
206 // TODO: What if this is a register value? Do we try and
207 // extract the child value from within the parent data?
208 // Probably...
209 default:
210 m_error.SetErrorString ("parent has invalid value.");
211 break;
212 }
213 }
214
215 if (m_error.Success())
216 {
217 const bool thread_and_frame_only_if_stopped = true;
218 ExecutionContext exe_ctx (GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
219 if (GetClangType().GetTypeInfo() & lldb::eTypeHasValue)
220 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
221 else
222 m_error.Clear(); // No value so nothing to read...
223 }
224 }
225 else
226 {
227 m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", parent->GetError().AsCString());
228 }
229 }
230 else
231 {
232 m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
233 }
234
235 return m_error.Success();
236 }
237
238
239 bool
IsInScope()240 ValueObjectChild::IsInScope ()
241 {
242 ValueObject* root(GetRoot());
243 if (root)
244 return root->IsInScope ();
245 return false;
246 }
247