1 //===-- SBBlock.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/API/SBBlock.h"
11 #include "lldb/API/SBAddress.h"
12 #include "lldb/API/SBFileSpec.h"
13 #include "lldb/API/SBFrame.h"
14 #include "lldb/API/SBStream.h"
15 #include "lldb/API/SBValue.h"
16 #include "lldb/Core/AddressRange.h"
17 #include "lldb/Core/Log.h"
18 #include "lldb/Core/ValueObjectVariable.h"
19 #include "lldb/Symbol/Block.h"
20 #include "lldb/Symbol/Function.h"
21 #include "lldb/Symbol/SymbolContext.h"
22 #include "lldb/Symbol/VariableList.h"
23 #include "lldb/Target/StackFrame.h"
24 #include "lldb/Target/Target.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 
30 SBBlock::SBBlock () :
31     m_opaque_ptr (NULL)
32 {
33 }
34 
35 SBBlock::SBBlock (lldb_private::Block *lldb_object_ptr) :
36     m_opaque_ptr (lldb_object_ptr)
37 {
38 }
39 
40 SBBlock::SBBlock(const SBBlock &rhs) :
41     m_opaque_ptr (rhs.m_opaque_ptr)
42 {
43 }
44 
45 const SBBlock &
46 SBBlock::operator = (const SBBlock &rhs)
47 {
48     m_opaque_ptr = rhs.m_opaque_ptr;
49     return *this;
50 }
51 
52 SBBlock::~SBBlock ()
53 {
54     m_opaque_ptr = NULL;
55 }
56 
57 bool
58 SBBlock::IsValid () const
59 {
60     return m_opaque_ptr != NULL;
61 }
62 
63 bool
64 SBBlock::IsInlined () const
65 {
66     if (m_opaque_ptr)
67         return m_opaque_ptr->GetInlinedFunctionInfo () != NULL;
68     return false;
69 }
70 
71 const char *
72 SBBlock::GetInlinedName () const
73 {
74     if (m_opaque_ptr)
75     {
76         const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
77         if (inlined_info)
78         {
79             Function *function = m_opaque_ptr->CalculateSymbolContextFunction();
80             LanguageType language;
81             if (function)
82                 language = function->GetLanguage();
83             else
84                 language = lldb::eLanguageTypeUnknown;
85             return inlined_info->GetName(language).AsCString (NULL);
86         }
87     }
88     return NULL;
89 }
90 
91 SBFileSpec
92 SBBlock::GetInlinedCallSiteFile () const
93 {
94     SBFileSpec sb_file;
95     if (m_opaque_ptr)
96     {
97         const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
98         if (inlined_info)
99             sb_file.SetFileSpec (inlined_info->GetCallSite().GetFile());
100     }
101     return sb_file;
102 }
103 
104 uint32_t
105 SBBlock::GetInlinedCallSiteLine () const
106 {
107     if (m_opaque_ptr)
108     {
109         const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
110         if (inlined_info)
111             return inlined_info->GetCallSite().GetLine();
112     }
113     return 0;
114 }
115 
116 uint32_t
117 SBBlock::GetInlinedCallSiteColumn () const
118 {
119     if (m_opaque_ptr)
120     {
121         const InlineFunctionInfo* inlined_info = m_opaque_ptr->GetInlinedFunctionInfo ();
122         if (inlined_info)
123             return inlined_info->GetCallSite().GetColumn();
124     }
125     return 0;
126 }
127 
128 void
129 SBBlock::AppendVariables (bool can_create, bool get_parent_variables, lldb_private::VariableList *var_list)
130 {
131     if (IsValid())
132     {
133         bool show_inline = true;
134         m_opaque_ptr->AppendVariables (can_create,
135                                        get_parent_variables,
136                                        show_inline,
137                                        [](Variable*) { return true; },
138                                        var_list);
139     }
140 }
141 
142 SBBlock
143 SBBlock::GetParent ()
144 {
145     SBBlock sb_block;
146     if (m_opaque_ptr)
147         sb_block.m_opaque_ptr = m_opaque_ptr->GetParent();
148     return sb_block;
149 }
150 
151 lldb::SBBlock
152 SBBlock::GetContainingInlinedBlock  ()
153 {
154     SBBlock sb_block;
155     if (m_opaque_ptr)
156         sb_block.m_opaque_ptr = m_opaque_ptr->GetContainingInlinedBlock ();
157     return sb_block;
158 }
159 
160 SBBlock
161 SBBlock::GetSibling ()
162 {
163     SBBlock sb_block;
164     if (m_opaque_ptr)
165         sb_block.m_opaque_ptr = m_opaque_ptr->GetSibling();
166     return sb_block;
167 }
168 
169 SBBlock
170 SBBlock::GetFirstChild ()
171 {
172     SBBlock sb_block;
173     if (m_opaque_ptr)
174         sb_block.m_opaque_ptr = m_opaque_ptr->GetFirstChild();
175     return sb_block;
176 }
177 
178 lldb_private::Block *
179 SBBlock::GetPtr ()
180 {
181     return m_opaque_ptr;
182 }
183 
184 void
185 SBBlock::SetPtr (lldb_private::Block *block)
186 {
187     m_opaque_ptr = block;
188 }
189 
190 bool
191 SBBlock::GetDescription (SBStream &description)
192 {
193     Stream &strm = description.ref();
194 
195     if (m_opaque_ptr)
196     {
197         lldb::user_id_t id = m_opaque_ptr->GetID();
198         strm.Printf ("Block: {id: %" PRIu64 "} ", id);
199         if (IsInlined())
200         {
201             strm.Printf (" (inlined, '%s') ", GetInlinedName());
202         }
203         lldb_private::SymbolContext sc;
204         m_opaque_ptr->CalculateSymbolContext (&sc);
205         if (sc.function)
206         {
207             m_opaque_ptr->DumpAddressRanges (&strm,
208                                              sc.function->GetAddressRange().GetBaseAddress().GetFileAddress());
209         }
210     }
211     else
212         strm.PutCString ("No value");
213 
214     return true;
215 }
216 
217 uint32_t
218 SBBlock::GetNumRanges ()
219 {
220     if (m_opaque_ptr)
221         return m_opaque_ptr->GetNumRanges();
222     return 0;
223 }
224 
225 lldb::SBAddress
226 SBBlock::GetRangeStartAddress (uint32_t idx)
227 {
228     lldb::SBAddress sb_addr;
229     if (m_opaque_ptr)
230     {
231         AddressRange range;
232         if (m_opaque_ptr->GetRangeAtIndex(idx, range))
233         {
234             sb_addr.ref() = range.GetBaseAddress();
235         }
236     }
237     return sb_addr;
238 }
239 
240 lldb::SBAddress
241 SBBlock::GetRangeEndAddress (uint32_t idx)
242 {
243     lldb::SBAddress sb_addr;
244     if (m_opaque_ptr)
245     {
246         AddressRange range;
247         if (m_opaque_ptr->GetRangeAtIndex(idx, range))
248         {
249             sb_addr.ref() = range.GetBaseAddress();
250             sb_addr.ref().Slide(range.GetByteSize());
251         }
252     }
253     return sb_addr;
254 }
255 
256 uint32_t
257 SBBlock::GetRangeIndexForBlockAddress (lldb::SBAddress block_addr)
258 {
259     if (m_opaque_ptr && block_addr.IsValid())
260     {
261         return m_opaque_ptr->GetRangeIndexContainingAddress (block_addr.ref());
262     }
263 
264     return UINT32_MAX;
265 }
266 
267 
268 lldb::SBValueList
269 SBBlock::GetVariables (lldb::SBFrame& frame,
270                        bool arguments,
271                        bool locals,
272                        bool statics,
273                        lldb::DynamicValueType use_dynamic)
274 {
275     Block *block = GetPtr();
276     SBValueList value_list;
277     if (block)
278     {
279         StackFrameSP frame_sp(frame.GetFrameSP());
280         VariableListSP variable_list_sp (block->GetBlockVariableList (true));
281 
282         if (variable_list_sp)
283         {
284             const size_t num_variables = variable_list_sp->GetSize();
285             if (num_variables)
286             {
287                 for (size_t i = 0; i < num_variables; ++i)
288                 {
289                     VariableSP variable_sp (variable_list_sp->GetVariableAtIndex(i));
290                     if (variable_sp)
291                     {
292                         bool add_variable = false;
293                         switch (variable_sp->GetScope())
294                         {
295                             case eValueTypeVariableGlobal:
296                             case eValueTypeVariableStatic:
297                             case eValueTypeVariableThreadLocal:
298                                 add_variable = statics;
299                                 break;
300 
301                             case eValueTypeVariableArgument:
302                                 add_variable = arguments;
303                                 break;
304 
305                             case eValueTypeVariableLocal:
306                                 add_variable = locals;
307                                 break;
308 
309                             default:
310                                 break;
311                         }
312                         if (add_variable)
313                         {
314                             if (frame_sp)
315                             {
316                                 lldb::ValueObjectSP valobj_sp(frame_sp->GetValueObjectForFrameVariable (variable_sp,eNoDynamicValues));
317                                 SBValue value_sb;
318                                 value_sb.SetSP(valobj_sp, use_dynamic);
319                                 value_list.Append (value_sb);
320                             }
321                         }
322                     }
323                 }
324             }
325         }
326     }
327     return value_list;
328 }
329 
330 lldb::SBValueList
331 SBBlock::GetVariables (lldb::SBTarget& target,
332                        bool arguments,
333                        bool locals,
334                        bool statics)
335 {
336     Block *block = GetPtr();
337 
338     SBValueList value_list;
339     if (block)
340     {
341         TargetSP target_sp(target.GetSP());
342 
343         VariableListSP variable_list_sp (block->GetBlockVariableList (true));
344 
345         if (variable_list_sp)
346         {
347             const size_t num_variables = variable_list_sp->GetSize();
348             if (num_variables)
349             {
350                 for (size_t i = 0; i < num_variables; ++i)
351                 {
352                     VariableSP variable_sp (variable_list_sp->GetVariableAtIndex(i));
353                     if (variable_sp)
354                     {
355                         bool add_variable = false;
356                         switch (variable_sp->GetScope())
357                         {
358                             case eValueTypeVariableGlobal:
359                             case eValueTypeVariableStatic:
360                             case eValueTypeVariableThreadLocal:
361                                 add_variable = statics;
362                                 break;
363 
364                             case eValueTypeVariableArgument:
365                                 add_variable = arguments;
366                                 break;
367 
368                             case eValueTypeVariableLocal:
369                                 add_variable = locals;
370                                 break;
371 
372                             default:
373                                 break;
374                         }
375                         if (add_variable)
376                         {
377                             if (target_sp)
378                                 value_list.Append (ValueObjectVariable::Create (target_sp.get(), variable_sp));
379                         }
380                     }
381                 }
382             }
383         }
384     }
385     return value_list;
386 }
387 
388