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     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 
53 ValueObjectChild::~ValueObjectChild()
54 {
55 }
56 
57 lldb::ValueType
58 ValueObjectChild::GetValueType() const
59 {
60     return m_parent->GetValueType();
61 }
62 
63 size_t
64 ValueObjectChild::CalculateNumChildren()
65 {
66     return GetClangType().GetNumChildren (true);
67 }
68 
69 static void
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
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
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
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
113 ValueObjectChild::CanUpdateWithInvalidExecutionContext ()
114 {
115     if (m_parent)
116         return m_parent->CanUpdateWithInvalidExecutionContext();
117     return this->ValueObject::CanUpdateWithInvalidExecutionContext();
118 }
119 
120 bool
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
240 ValueObjectChild::IsInScope ()
241 {
242     ValueObject* root(GetRoot());
243     if (root)
244         return root->IsInScope ();
245     return false;
246 }
247