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