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