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