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