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 ConstString
GetTypeName()70 ValueObjectChild::GetTypeName()
71 {
72     if (m_type_name.IsEmpty())
73     {
74         m_type_name = GetClangType().GetConstTypeName ();
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 ConstString
GetQualifiedTypeName()93 ValueObjectChild::GetQualifiedTypeName()
94 {
95     ConstString qualified_name = GetClangType().GetConstTypeName();
96     if (qualified_name)
97     {
98         if (m_bitfield_bit_size > 0)
99         {
100             const char *clang_type_name = qualified_name.AsCString();
101             if (clang_type_name)
102             {
103                 std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
104                 ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
105                 qualified_name.SetCString(&bitfield_type_name.front());
106             }
107         }
108     }
109     return qualified_name;
110 }
111 
112 bool
UpdateValue()113 ValueObjectChild::UpdateValue ()
114 {
115     m_error.Clear();
116     SetValueIsValid (false);
117     ValueObject* parent = m_parent;
118     if (parent)
119     {
120         if (parent->UpdateValueIfNeeded(false))
121         {
122             m_value.SetClangType(GetClangType());
123 
124             // Copy the parent scalar value and the scalar value type
125             m_value.GetScalar() = parent->GetValue().GetScalar();
126             Value::ValueType value_type = parent->GetValue().GetValueType();
127             m_value.SetValueType (value_type);
128 
129             if (parent->GetClangType().IsPointerOrReferenceType ())
130             {
131                 lldb::addr_t addr = parent->GetPointerValue ();
132                 m_value.GetScalar() = addr;
133 
134                 if (addr == LLDB_INVALID_ADDRESS)
135                 {
136                     m_error.SetErrorString ("parent address is invalid.");
137                 }
138                 else if (addr == 0)
139                 {
140                     m_error.SetErrorString ("parent is NULL");
141                 }
142                 else
143                 {
144                     m_value.GetScalar() += m_byte_offset;
145                     AddressType addr_type = parent->GetAddressTypeOfChildren();
146 
147                     switch (addr_type)
148                     {
149                         case eAddressTypeFile:
150                             {
151                                 lldb::ProcessSP process_sp (GetProcessSP());
152                                 if (process_sp && process_sp->IsAlive() == true)
153                                     m_value.SetValueType (Value::eValueTypeLoadAddress);
154                                 else
155                                     m_value.SetValueType(Value::eValueTypeFileAddress);
156                             }
157                             break;
158                         case eAddressTypeLoad:
159                             m_value.SetValueType (Value::eValueTypeLoadAddress);
160                             break;
161                         case eAddressTypeHost:
162                             m_value.SetValueType(Value::eValueTypeHostAddress);
163                             break;
164                         case eAddressTypeInvalid:
165                             // TODO: does this make sense?
166                             m_value.SetValueType(Value::eValueTypeScalar);
167                             break;
168                     }
169                 }
170             }
171             else
172             {
173                 switch (value_type)
174                 {
175                 case Value::eValueTypeLoadAddress:
176                 case Value::eValueTypeFileAddress:
177                 case Value::eValueTypeHostAddress:
178                     {
179                         lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
180                         if (addr == LLDB_INVALID_ADDRESS)
181                         {
182                             m_error.SetErrorString ("parent address is invalid.");
183                         }
184                         else if (addr == 0)
185                         {
186                             m_error.SetErrorString ("parent is NULL");
187                         }
188                         else
189                         {
190                             // Set this object's scalar value to the address of its
191                             // value by adding its byte offset to the parent address
192                             m_value.GetScalar() += GetByteOffset();
193                         }
194                     }
195                     break;
196 
197                 case Value::eValueTypeScalar:
198                     // TODO: What if this is a register value? Do we try and
199                     // extract the child value from within the parent data?
200                     // Probably...
201                 default:
202                     m_error.SetErrorString ("parent has invalid value.");
203                     break;
204                 }
205             }
206 
207             if (m_error.Success())
208             {
209                 ExecutionContext exe_ctx (GetExecutionContextRef().Lock());
210                 m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
211             }
212         }
213         else
214         {
215             m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", parent->GetError().AsCString());
216         }
217     }
218     else
219     {
220         m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
221     }
222 
223     return m_error.Success();
224 }
225 
226 
227 bool
IsInScope()228 ValueObjectChild::IsInScope ()
229 {
230     ValueObject* root(GetRoot());
231     if (root)
232         return root->IsInScope ();
233     return false;
234 }
235