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