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