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