xref: /llvm-project/lldb/source/API/SBBlock.cpp (revision 66a88f62cd56e55b5fa0ddb1bdffa549f7565f8f)
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 "lldb/API/SBAddress.h"
11 #include "lldb/API/SBFileSpec.h"
12 #include "lldb/API/SBFrame.h"
13 #include "lldb/API/SBStream.h"
14 #include "lldb/API/SBValue.h"
15 #include "lldb/Core/AddressRange.h"
16 #include "lldb/Core/AddressRangeListImpl.h"
17 #include "lldb/Symbol/Block.h"
18 #include "lldb/Symbol/Function.h"
19 #include "lldb/Symbol/SymbolContext.h"
20 #include "lldb/Symbol/VariableList.h"
21 #include "lldb/Target/StackFrame.h"
22 #include "lldb/Target/Target.h"
23 #include "lldb/Utility/Instrumentation.h"
24 #include "lldb/ValueObject/ValueObjectVariable.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 SBBlock::SBBlock() { LLDB_INSTRUMENT_VA(this); }
30 
31 SBBlock::SBBlock(lldb_private::Block *lldb_object_ptr)
32     : m_opaque_ptr(lldb_object_ptr) {}
33 
34 SBBlock::SBBlock(const SBBlock &rhs) : m_opaque_ptr(rhs.m_opaque_ptr) {
35   LLDB_INSTRUMENT_VA(this, rhs);
36 }
37 
38 const SBBlock &SBBlock::operator=(const SBBlock &rhs) {
39   LLDB_INSTRUMENT_VA(this, rhs);
40 
41   m_opaque_ptr = rhs.m_opaque_ptr;
42   return *this;
43 }
44 
45 SBBlock::~SBBlock() { m_opaque_ptr = nullptr; }
46 
47 bool SBBlock::IsValid() const {
48   LLDB_INSTRUMENT_VA(this);
49   return this->operator bool();
50 }
51 SBBlock::operator bool() const {
52   LLDB_INSTRUMENT_VA(this);
53 
54   return m_opaque_ptr != nullptr;
55 }
56 
57 bool SBBlock::IsInlined() const {
58   LLDB_INSTRUMENT_VA(this);
59 
60   if (m_opaque_ptr)
61     return m_opaque_ptr->GetInlinedFunctionInfo() != nullptr;
62   return false;
63 }
64 
65 const char *SBBlock::GetInlinedName() const {
66   LLDB_INSTRUMENT_VA(this);
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 
78 SBFileSpec SBBlock::GetInlinedCallSiteFile() const {
79   LLDB_INSTRUMENT_VA(this);
80 
81   SBFileSpec sb_file;
82   if (m_opaque_ptr) {
83     const InlineFunctionInfo *inlined_info =
84         m_opaque_ptr->GetInlinedFunctionInfo();
85     if (inlined_info)
86       sb_file.SetFileSpec(inlined_info->GetCallSite().GetFile());
87   }
88   return sb_file;
89 }
90 
91 uint32_t SBBlock::GetInlinedCallSiteLine() const {
92   LLDB_INSTRUMENT_VA(this);
93 
94   if (m_opaque_ptr) {
95     const InlineFunctionInfo *inlined_info =
96         m_opaque_ptr->GetInlinedFunctionInfo();
97     if (inlined_info)
98       return inlined_info->GetCallSite().GetLine();
99   }
100   return 0;
101 }
102 
103 uint32_t SBBlock::GetInlinedCallSiteColumn() const {
104   LLDB_INSTRUMENT_VA(this);
105 
106   if (m_opaque_ptr) {
107     const InlineFunctionInfo *inlined_info =
108         m_opaque_ptr->GetInlinedFunctionInfo();
109     if (inlined_info)
110       return inlined_info->GetCallSite().GetColumn();
111   }
112   return 0;
113 }
114 
115 void SBBlock::AppendVariables(bool can_create, bool get_parent_variables,
116                               lldb_private::VariableList *var_list) {
117   if (IsValid()) {
118     bool show_inline = true;
119     m_opaque_ptr->AppendVariables(can_create, get_parent_variables, show_inline,
120                                   [](Variable *) { return true; }, var_list);
121   }
122 }
123 
124 SBBlock SBBlock::GetParent() {
125   LLDB_INSTRUMENT_VA(this);
126 
127   SBBlock sb_block;
128   if (m_opaque_ptr)
129     sb_block.m_opaque_ptr = m_opaque_ptr->GetParent();
130   return sb_block;
131 }
132 
133 lldb::SBBlock SBBlock::GetContainingInlinedBlock() {
134   LLDB_INSTRUMENT_VA(this);
135 
136   SBBlock sb_block;
137   if (m_opaque_ptr)
138     sb_block.m_opaque_ptr = m_opaque_ptr->GetContainingInlinedBlock();
139   return sb_block;
140 }
141 
142 SBBlock SBBlock::GetSibling() {
143   LLDB_INSTRUMENT_VA(this);
144 
145   SBBlock sb_block;
146   if (m_opaque_ptr)
147     sb_block.m_opaque_ptr = m_opaque_ptr->GetSibling();
148   return sb_block;
149 }
150 
151 SBBlock SBBlock::GetFirstChild() {
152   LLDB_INSTRUMENT_VA(this);
153 
154   SBBlock sb_block;
155   if (m_opaque_ptr)
156     sb_block.m_opaque_ptr = m_opaque_ptr->GetFirstChild();
157   return sb_block;
158 }
159 
160 lldb_private::Block *SBBlock::GetPtr() { return m_opaque_ptr; }
161 
162 void SBBlock::SetPtr(lldb_private::Block *block) { m_opaque_ptr = block; }
163 
164 bool SBBlock::GetDescription(SBStream &description) {
165   LLDB_INSTRUMENT_VA(this, description);
166 
167   Stream &strm = description.ref();
168 
169   if (m_opaque_ptr) {
170     lldb::user_id_t id = m_opaque_ptr->GetID();
171     strm.Printf("Block: {id: %" PRIu64 "} ", id);
172     if (IsInlined()) {
173       strm.Printf(" (inlined, '%s') ", GetInlinedName());
174     }
175     lldb_private::SymbolContext sc;
176     m_opaque_ptr->CalculateSymbolContext(&sc);
177     if (sc.function) {
178       m_opaque_ptr->DumpAddressRanges(
179           &strm, sc.function->GetAddress().GetFileAddress());
180     }
181   } else
182     strm.PutCString("No value");
183 
184   return true;
185 }
186 
187 uint32_t SBBlock::GetNumRanges() {
188   LLDB_INSTRUMENT_VA(this);
189 
190   if (m_opaque_ptr)
191     return m_opaque_ptr->GetNumRanges();
192   return 0;
193 }
194 
195 lldb::SBAddress SBBlock::GetRangeStartAddress(uint32_t idx) {
196   LLDB_INSTRUMENT_VA(this, idx);
197 
198   lldb::SBAddress sb_addr;
199   if (m_opaque_ptr) {
200     AddressRange range;
201     if (m_opaque_ptr->GetRangeAtIndex(idx, range)) {
202       sb_addr.ref() = range.GetBaseAddress();
203     }
204   }
205   return sb_addr;
206 }
207 
208 lldb::SBAddress SBBlock::GetRangeEndAddress(uint32_t idx) {
209   LLDB_INSTRUMENT_VA(this, idx);
210 
211   lldb::SBAddress sb_addr;
212   if (m_opaque_ptr) {
213     AddressRange range;
214     if (m_opaque_ptr->GetRangeAtIndex(idx, range)) {
215       sb_addr.ref() = range.GetBaseAddress();
216       sb_addr.ref().Slide(range.GetByteSize());
217     }
218   }
219   return sb_addr;
220 }
221 
222 lldb::SBAddressRangeList SBBlock::GetRanges() {
223   LLDB_INSTRUMENT_VA(this);
224 
225   lldb::SBAddressRangeList sb_ranges;
226   if (m_opaque_ptr)
227     sb_ranges.m_opaque_up->ref() = m_opaque_ptr->GetRanges();
228   return sb_ranges;
229 }
230 
231 uint32_t SBBlock::GetRangeIndexForBlockAddress(lldb::SBAddress block_addr) {
232   LLDB_INSTRUMENT_VA(this, block_addr);
233 
234   if (m_opaque_ptr && block_addr.IsValid()) {
235     return m_opaque_ptr->GetRangeIndexContainingAddress(block_addr.ref());
236   }
237 
238   return UINT32_MAX;
239 }
240 
241 lldb::SBValueList SBBlock::GetVariables(lldb::SBFrame &frame, bool arguments,
242                                         bool locals, bool statics,
243                                         lldb::DynamicValueType use_dynamic) {
244   LLDB_INSTRUMENT_VA(this, frame, 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 value_list;
293 }
294 
295 lldb::SBValueList SBBlock::GetVariables(lldb::SBTarget &target, bool arguments,
296                                         bool locals, bool statics) {
297   LLDB_INSTRUMENT_VA(this, target, arguments, locals, statics);
298 
299   Block *block = GetPtr();
300 
301   SBValueList value_list;
302   if (block) {
303     TargetSP target_sp(target.GetSP());
304 
305     VariableListSP variable_list_sp(block->GetBlockVariableList(true));
306 
307     if (variable_list_sp) {
308       const size_t num_variables = variable_list_sp->GetSize();
309       if (num_variables) {
310         for (size_t i = 0; i < num_variables; ++i) {
311           VariableSP variable_sp(variable_list_sp->GetVariableAtIndex(i));
312           if (variable_sp) {
313             bool add_variable = false;
314             switch (variable_sp->GetScope()) {
315             case eValueTypeVariableGlobal:
316             case eValueTypeVariableStatic:
317             case eValueTypeVariableThreadLocal:
318               add_variable = statics;
319               break;
320 
321             case eValueTypeVariableArgument:
322               add_variable = arguments;
323               break;
324 
325             case eValueTypeVariableLocal:
326               add_variable = locals;
327               break;
328 
329             default:
330               break;
331             }
332             if (add_variable) {
333               if (target_sp)
334                 value_list.Append(
335                     ValueObjectVariable::Create(target_sp.get(), variable_sp));
336             }
337           }
338         }
339       }
340     }
341   }
342   return value_list;
343 }
344