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