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