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_load_addr_backend(),
45     m_address_of_backend()
46 {
47 }
48 
49 lldb::ValueObjectSP
50 ValueObjectConstResultImpl::DerefOnTarget()
51 {
52     if (m_load_addr_backend.get() == NULL)
53     {
54         lldb::addr_t tgt_address = m_impl_backend->GetPointerValue();
55         m_load_addr_backend = ValueObjectConstResult::Create (m_impl_backend->GetExecutionContextScope(),
56                                                               m_impl_backend->GetClangAST(),
57                                                               m_impl_backend->GetClangType(),
58                                                               m_impl_backend->GetName(),
59                                                               tgt_address,
60                                                               eAddressTypeLoad,
61                                                               m_impl_backend->GetUpdatePoint().GetProcessSP()->GetAddressByteSize());
62     }
63     return m_load_addr_backend;
64 }
65 
66 lldb::ValueObjectSP
67 ValueObjectConstResultImpl::Dereference (Error &error)
68 {
69     if (m_impl_backend == NULL)
70         return lldb::ValueObjectSP();
71 
72 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
73     return m_impl_backend->ValueObject::Dereference(error);
74 #else
75     m_impl_backend->UpdateValueIfNeeded(false);
76 
77     if (NeedsDerefOnTarget())
78         return DerefOnTarget()->Dereference(error);
79     else
80         return m_impl_backend->ValueObject::Dereference(error);
81 #endif
82 }
83 
84 ValueObject *
85 ValueObjectConstResultImpl::CreateChildAtIndex (uint32_t idx, bool synthetic_array_member, int32_t synthetic_index)
86 {
87     if (m_impl_backend == NULL)
88         return NULL;
89 
90     m_impl_backend->UpdateValueIfNeeded(false);
91 
92     ValueObjectConstResultChild *valobj = NULL;
93 
94     bool omit_empty_base_classes = true;
95     bool ignore_array_bounds = synthetic_array_member;
96     std::string child_name_str;
97     uint32_t child_byte_size = 0;
98     int32_t child_byte_offset = 0;
99     uint32_t child_bitfield_bit_size = 0;
100     uint32_t child_bitfield_bit_offset = 0;
101     bool child_is_base_class = false;
102     bool child_is_deref_of_parent = false;
103 
104     const bool transparent_pointers = synthetic_array_member == false;
105     clang::ASTContext *clang_ast = m_impl_backend->GetClangAST();
106     lldb::clang_type_t clang_type = m_impl_backend->GetClangType();
107     lldb::clang_type_t child_clang_type;
108 
109     ExecutionContext exe_ctx;
110     m_impl_backend->GetExecutionContextScope()->CalculateExecutionContext (exe_ctx);
111 
112     child_clang_type = ClangASTContext::GetChildClangTypeAtIndex (&exe_ctx,
113                                                                   clang_ast,
114                                                                   m_impl_backend->GetName().GetCString(),
115                                                                   clang_type,
116                                                                   idx,
117                                                                   transparent_pointers,
118                                                                   omit_empty_base_classes,
119                                                                   ignore_array_bounds,
120                                                                   child_name_str,
121                                                                   child_byte_size,
122                                                                   child_byte_offset,
123                                                                   child_bitfield_bit_size,
124                                                                   child_bitfield_bit_offset,
125                                                                   child_is_base_class,
126                                                                   child_is_deref_of_parent);
127     if (child_clang_type && child_byte_size)
128     {
129         if (synthetic_index)
130             child_byte_offset += child_byte_size * synthetic_index;
131 
132         ConstString child_name;
133         if (!child_name_str.empty())
134             child_name.SetCString (child_name_str.c_str());
135 
136         valobj = new ValueObjectConstResultChild (*m_impl_backend,
137                                                   clang_ast,
138                                                   child_clang_type,
139                                                   child_name,
140                                                   child_byte_size,
141                                                   child_byte_offset,
142                                                   child_bitfield_bit_size,
143                                                   child_bitfield_bit_offset,
144                                                   child_is_base_class,
145                                                   child_is_deref_of_parent);
146         valobj->m_impl.SetLiveAddress(m_live_address+child_byte_offset);
147     }
148 
149     return valobj;
150 }
151 
152 lldb::ValueObjectSP
153 ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, const ClangASTType& type, bool can_create)
154 {
155     if (m_impl_backend == NULL)
156         return lldb::ValueObjectSP();
157 
158 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
159     return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
160 #else
161     m_impl_backend->UpdateValueIfNeeded(false);
162 
163     if (NeedsDerefOnTarget())
164         return DerefOnTarget()->GetSyntheticChildAtOffset(offset, type, can_create);
165     else
166         return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, type, can_create);
167 #endif
168 }
169 
170 lldb::ValueObjectSP
171 ValueObjectConstResultImpl::AddressOf (Error &error)
172 {
173     if (m_address_of_backend.get() != NULL)
174         return m_address_of_backend;
175 
176     if (m_impl_backend == NULL)
177         return lldb::ValueObjectSP();
178     if (m_live_address != LLDB_INVALID_ADDRESS)
179     {
180         ClangASTType type(m_impl_backend->GetClangAST(), m_impl_backend->GetClangType());
181 
182         lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t)));
183 
184         std::string new_name("&");
185         new_name.append(m_impl_backend->GetName().AsCString(""));
186 
187         m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetUpdatePoint().GetExecutionContextScope(),
188                                                               type.GetASTContext(),
189                                                               type.GetPointerType(),
190                                                               ConstString(new_name.c_str()),
191                                                               buffer,
192                                                               lldb::endian::InlHostByteOrder(),
193                                                               m_impl_backend->GetExecutionContextScope()->CalculateProcess()->GetAddressByteSize());
194 
195         m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar);
196         m_address_of_backend->GetValue().GetScalar() = m_live_address;
197 
198         return m_address_of_backend;
199     }
200     else
201         return lldb::ValueObjectSP();
202 }
203 
204 size_t
205 ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data,
206                                             uint32_t item_idx,
207                                             uint32_t item_count)
208 {
209     if (m_impl_backend == NULL)
210         return 0;
211 #if defined (TRIVIAL_IMPL) && TRIVIAL_IMPL == 1
212     return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
213 #else
214     m_impl_backend->UpdateValueIfNeeded(false);
215 
216     if (NeedsDerefOnTarget() && m_impl_backend->IsPointerType())
217         return DerefOnTarget()->GetPointeeData(data, item_idx, item_count);
218     else
219         return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count);
220 #endif
221 }
222