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     uint32_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 ) :
39     ValueObject (parent),
40     m_clang_ast (clang_ast),
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 {
48     m_name = name;
49 }
50 
51 ValueObjectChild::~ValueObjectChild()
52 {
53 }
54 
55 void *
56 ValueObjectChild::GetClangType()
57 {
58     return m_clang_type;
59 }
60 
61 lldb::ValueType
62 ValueObjectChild::GetValueType() const
63 {
64     return m_parent->GetValueType();
65 }
66 
67 uint32_t
68 ValueObjectChild::CalculateNumChildren()
69 {
70     return ClangASTContext::GetNumChildren (m_clang_type, true);
71 }
72 
73 clang::ASTContext *
74 ValueObjectChild::GetClangAST ()
75 {
76     return m_clang_ast;
77 }
78 
79 size_t
80 ValueObjectChild::GetByteSize()
81 {
82     return m_byte_size;
83 }
84 
85 off_t
86 ValueObjectChild::GetByteOffset()
87 {
88     return m_byte_offset;
89 }
90 
91 uint32_t
92 ValueObjectChild::GetBitfieldBitSize()
93 {
94     return m_bitfield_bit_size;
95 }
96 
97 uint32_t
98 ValueObjectChild::GetBitfieldBitOffset()
99 {
100     return m_bitfield_bit_offset;
101 }
102 
103 ConstString
104 ValueObjectChild::GetTypeName()
105 {
106     if (m_type_name.IsEmpty())
107     {
108         m_type_name = ClangASTType::GetClangTypeName (GetClangType());
109         if (m_type_name)
110         {
111             if (m_bitfield_bit_size > 0)
112             {
113                 const char *clang_type_name = m_type_name.AsCString();
114                 if (clang_type_name)
115                 {
116                     std::vector<char> bitfield_type_name (strlen(clang_type_name) + 32, 0);
117                     ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", clang_type_name, m_bitfield_bit_size);
118                     m_type_name.SetCString(&bitfield_type_name.front());
119                 }
120             }
121         }
122     }
123     return m_type_name;
124 }
125 
126 void
127 ValueObjectChild::UpdateValue (ExecutionContextScope *exe_scope)
128 {
129     m_error.Clear();
130     SetValueIsValid (false);
131     ValueObject* parent = m_parent;
132     if (parent)
133     {
134         if (parent->UpdateValueIfNeeded(exe_scope))
135         {
136             m_value.SetContext(Value::eContextTypeOpaqueClangQualType, m_clang_type);
137 
138             // Copy the parent scalar value and the scalar value type
139             m_value.GetScalar() = parent->GetValue().GetScalar();
140             Value::ValueType value_type = parent->GetValue().GetValueType();
141             m_value.SetValueType (value_type);
142 
143             if (ClangASTContext::IsPointerOrReferenceType (parent->GetClangType()))
144             {
145                 uint32_t offset = 0;
146                 m_value.GetScalar() = parent->GetDataExtractor().GetPointer(&offset);
147                 // For pointers, m_byte_offset should only ever be set if we
148                 // ValueObject::GetSyntheticArrayMemberFromPointer() was called
149                 if (ClangASTContext::IsPointerType (parent->GetClangType()) && m_byte_offset)
150                     m_value.GetScalar() += m_byte_offset;
151                 if (value_type == Value::eValueTypeScalar ||
152                     value_type == Value::eValueTypeFileAddress)
153                     m_value.SetValueType (Value::eValueTypeLoadAddress);
154             }
155             else
156             {
157                 switch (value_type)
158                 {
159                 case Value::eValueTypeLoadAddress:
160                 case Value::eValueTypeFileAddress:
161                 case Value::eValueTypeHostAddress:
162                     {
163                         lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
164                         if (addr == LLDB_INVALID_ADDRESS || addr == 0)
165                         {
166                             m_error.SetErrorStringWithFormat("Parent address is invalid: 0x%llx.\n", addr);
167                             break;
168                         }
169                         // Set this object's scalar value to the address of its
170                         // value be adding its byte offset to the parent address
171                         m_value.GetScalar() += GetByteOffset();
172                     }
173                     break;
174 
175                 case Value::eValueTypeScalar:
176                     // TODO: What if this is a register value? Do we try and
177                     // extract the child value from within the parent data?
178                     // Probably...
179                 default:
180                     m_error.SetErrorString ("Parent has invalid value.");
181                     break;
182                 }
183             }
184 
185             if (m_error.Success())
186             {
187                 ExecutionContext exe_ctx (exe_scope);
188                 m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST (), m_data, 0);
189             }
190         }
191         else
192         {
193             m_error.SetErrorStringWithFormat("Parent failed to evaluate: %s.\n", parent->GetError().AsCString());
194         }
195     }
196     else
197     {
198         m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject.");
199     }
200 }
201 
202 
203 bool
204 ValueObjectChild::IsInScope (StackFrame *frame)
205 {
206     return m_parent->IsInScope (frame);
207 }
208