1 //===-- ValueObjectConstResultImpl.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/ValueObjectConstResultImpl.h"
11 
12 #include "lldb/Core/ValueObjectChild.h"
13 #include "lldb/Core/ValueObjectConstResult.h"
14 #include "lldb/Core/ValueObjectConstResultChild.h"
15 #include "lldb/Core/ValueObjectMemory.h"
16 #include "lldb/Core/DataExtractor.h"
17 #include "lldb/Core/Module.h"
18 #include "lldb/Core/ValueObjectList.h"
19 
20 #include "lldb/Symbol/ClangASTType.h"
21 #include "lldb/Symbol/ObjectFile.h"
22 #include "lldb/Symbol/SymbolContext.h"
23 #include "lldb/Symbol/Type.h"
24 #include "lldb/Symbol/Variable.h"
25 
26 #include "lldb/Target/ExecutionContext.h"
27 #include "lldb/Target/Process.h"
28 #include "lldb/Target/Target.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 // this macro enables a simpler implementation for some method calls in this object that relies only upon
34 // ValueObject knowning how to set the address type of its children correctly. the alternative implementation
35 // relies on being able to create a target copy of the frozen object, which makes it less bug-prone but less
36 // efficient as well. once we are confident the faster implementation is bug-free, this macro (and the slower
37 // implementations) can go
38 #define TRIVIAL_IMPL 1
39 
40 ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj,
41                                                         lldb::addr_t live_address) :
42     m_impl_backend(valobj),
43     m_live_address(live_address),
44     m_live_address_type(eAddressTypeLoad),
45     m_load_addr_backend(),
46     m_address_of_backend()
47 {
48 }
49 
50 lldb::ValueObjectSP
51 ValueObjectConstResultImpl::DerefOnTarget()
52 {
53     if (m_load_addr_backend.get() == NULL)
54     {
55         lldb::addr_t tgt_address = m_impl_backend->GetPointerValue();
56         ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
57         m_load_addr_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
58                                                               m_impl_backend->GetClangAST(),
59                                                               m_impl_backend->GetClangType(),
60                                                               m_impl_backend->GetName(),
61                                                               tgt_address,
62                                                               eAddressTypeLoad,
63                                                               exe_ctx.GetAddressByteSize());
64     }
65     return m_load_addr_backend;
66 }
67 
68 lldb::ValueObjectSP
69 ValueObjectConstResultImpl::Dereference (Error &error)
70 {
71     if (m_impl_backend == NULL)
72         return lldb::ValueObjectSP();
73 
74 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
75     return m_impl_backend->ValueObject::Dereference(error);
76 #else
77     m_impl_backend->UpdateValueIfNeeded(false);
78 
79     if (NeedsDerefOnTarget())
80         return DerefOnTarget()->Dereference(error);
81     else
82         return m_impl_backend->ValueObject::Dereference(error);
83 #endif
84 }
85 
86 ValueObject *
87 ValueObjectConstResultImpl::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
88 {
89     if (m_impl_backend == NULL)
90         return NULL;
91 
92     m_impl_backend->UpdateValueIfNeeded(false);
93 
94     ValueObjectConstResultChild *valobj = NULL;
95 
96     bool omit_empty_base_classes = true;
97     bool ignore_array_bounds = synthetic_array_member;
98     std::string child_name_str;
99     uint32_t child_byte_size = 0;
100     int32_t child_byte_offset = 0;
101     uint32_t child_bitfield_bit_size = 0;
102     uint32_t child_bitfield_bit_offset = 0;
103     bool child_is_base_class = false;
104     bool child_is_deref_of_parent = false;
105 
106     const bool transparent_pointers = synthetic_array_member == false;
107     clang::ASTContext *clang_ast = m_impl_backend->GetClangAST();
108     lldb::clang_type_t clang_type = m_impl_backend->GetClangType();
109     lldb::clang_type_t child_clang_type;
110 
111     ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
112 
113     child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
114                                                                   clang_ast,
115                                                                   m_impl_backend->GetName().GetCString(),
116                                                                   clang_type,
117                                                                   idx,
118                                                                   transparent_pointers,
119                                                                   omit_empty_base_classes,
120                                                                   ignore_array_bounds,
121                                                                   child_name_str,
122                                                                   child_byte_size,
123                                                                   child_byte_offset,
124                                                                   child_bitfield_bit_size,
125                                                                   child_bitfield_bit_offset,
126                                                                   child_is_base_class,
127                                                                   child_is_deref_of_parent);
128     if (child_clang_type && child_byte_size)
129     {
130         if (synthetic_index)
131             child_byte_offset += child_byte_size * synthetic_index;
132 
133         ConstString child_name;
134         if (!child_name_str.empty())
135             child_name.SetCString (child_name_str.c_str());
136 
137         valobj = new ValueObjectConstResultChild (*m_impl_backend,
138                                                   clang_ast,
139                                                   child_clang_type,
140                                                   child_name,
141                                                   child_byte_size,
142                                                   child_byte_offset,
143                                                   child_bitfield_bit_size,
144                                                   child_bitfield_bit_offset,
145                                                   child_is_base_class,
146                                                   child_is_deref_of_parent);
147         valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset);
148     }
149 
150     return valobj;
151 }
152 
153 lldb::ValueObjectSP
154 ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create)
155 {
156     if (m_impl_backend == NULL)
157         return lldb::ValueObjectSP();
158 
159 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
160     return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
161 #else
162     m_impl_backend->UpdateValueIfNeeded(false);
163 
164     if (NeedsDerefOnTarget())
165         return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create);
166     else
167         return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
168 #endif
169 }
170 
171 lldb::ValueObjectSP
172 ValueObjectConstResultImpl::AddressOf (Error &error)
173 {
174     if (m_address_of_backend.get() != NULL)
175         return m_address_of_backend;
176 
177     if (m_impl_backend == NULL)
178         return lldb::ValueObjectSP();
179     if (m_live_address != LLDB_INVALID_ADDRESS)
180     {
181         ClangASTType type(m_impl_backend->GetClangAST(), m_impl_backend->GetClangType());
182 
183         lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t)));
184 
185         std::string new_name("&");
186         new_name.append(m_impl_backend->GetName().AsCString(""));
187         ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef());
188         m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
189                                                                type.GetASTContext(),
190                                                                type.GetPointerType(),
191                                                                ConstString(new_name.c_str()),
192                                                                buffer,
193                                                                lldb::endian::InlHostByteOrder(),
194                                                                exe_ctx.GetAddressByteSize());
195 
196         m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
197         m_address_of_backend->GetValue().GetScalar() = m_live_address;
198 
199         return m_address_of_backend;
200     }
201     else
202         return lldb::ValueObjectSP();
203 }
204 
205 lldb::addr_t
206 ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address,
207                                           AddressType *address_type)
208 {
209 
210     if (m_impl_backend == NULL)
211         return 0;
212 
213     if (m_live_address == LLDB_INVALID_ADDRESS)
214     {
215         return m_impl_backend->ValueObject::GetAddressOf (scalar_is_load_address,
216                                                           address_type);
217     }
218 
219     if (address_type)
220         *address_type = m_live_address_type;
221 
222     return m_live_address;
223 }
224 
225 size_t
226 ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data,
227                                             uint32_t item_idx,
228                                             uint32_t item_count)
229 {
230     if (m_impl_backend == NULL)
231         return 0;
232 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
233     return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
234 #else
235     m_impl_backend->UpdateValueIfNeeded(false);
236 
237     if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType())
238         return DerefOnTarget()->GetPointeeData(data, item_idx, item_count);
239     else
240         return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
241 #endif
242 }
243