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