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