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                                 add_variable = statics;
298                                 break;
299 
300                             case eValueTypeVariableArgument:
301                                 add_variable = arguments;
302                                 break;
303 
304                             case eValueTypeVariableLocal:
305                                 add_variable = locals;
306                                 break;
307 
308                             default:
309                                 break;
310                         }
311                         if (add_variable)
312                         {
313                             if (frame_sp)
314                             {
315                                 lldb::ValueObjectSP valobj_sp(frame_sp->GetValueObjectForFrameVariable (variable_sp,eNoDynamicValues));
316                                 SBValue value_sb;
317                                 value_sb.SetSP(valobj_sp, use_dynamic);
318                                 value_list.Append (value_sb);
319                             }
320                         }
321                     }
322                 }
323             }
324         }
325     }
326     return value_list;
327 }
328 
329 lldb::SBValueList
330 SBBlock::GetVariables (lldb::SBTarget& target,
331                        bool arguments,
332                        bool locals,
333                        bool statics)
334 {
335     Block *block = GetPtr();
336 
337     SBValueList value_list;
338     if (block)
339     {
340         TargetSP target_sp(target.GetSP());
341 
342         VariableListSP variable_list_sp (block->GetBlockVariableList (true));
343 
344         if (variable_list_sp)
345         {
346             const size_t num_variables = variable_list_sp->GetSize();
347             if (num_variables)
348             {
349                 for (size_t i = 0; i < num_variables; ++i)
350                 {
351                     VariableSP variable_sp (variable_list_sp->GetVariableAtIndex(i));
352                     if (variable_sp)
353                     {
354                         bool add_variable = false;
355                         switch (variable_sp->GetScope())
356                         {
357                             case eValueTypeVariableGlobal:
358                             case eValueTypeVariableStatic:
359                                 add_variable = statics;
360                                 break;
361 
362                             case eValueTypeVariableArgument:
363                                 add_variable = arguments;
364                                 break;
365 
366                             case eValueTypeVariableLocal:
367                                 add_variable = locals;
368                                 break;
369 
370                             default:
371                                 break;
372                         }
373                         if (add_variable)
374                         {
375                             if (target_sp)
376                                 value_list.Append (ValueObjectVariable::Create (target_sp.get(), variable_sp));
377                         }
378                     }
379                 }
380             }
381         }
382     }
383     return value_list;
384 }
385 
386