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 25 using namespace lldb; 26 using namespace lldb_private; 27 28 SBBlock::SBBlock() : m_opaque_ptr(nullptr) { 29 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBlock); 30 } 31 32 SBBlock::SBBlock(lldb_private::Block *lldb_object_ptr) 33 : m_opaque_ptr(lldb_object_ptr) {} 34 35 SBBlock::SBBlock(const SBBlock &rhs) : m_opaque_ptr(rhs.m_opaque_ptr) { 36 LLDB_RECORD_CONSTRUCTOR(SBBlock, (const lldb::SBBlock &), rhs); 37 } 38 39 const 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 47 SBBlock::~SBBlock() { m_opaque_ptr = nullptr; } 48 49 bool SBBlock::IsValid() const { 50 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, IsValid); 51 return this->operator bool(); 52 } 53 SBBlock::operator bool() const { 54 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBlock, operator bool); 55 56 return m_opaque_ptr != nullptr; 57 } 58 59 bool 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 67 const 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 80 SBFileSpec 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 94 uint32_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 106 uint32_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 118 void 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 127 SBBlock 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 136 lldb::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 145 SBBlock 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 154 SBBlock 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 163 lldb_private::Block *SBBlock::GetPtr() { return m_opaque_ptr; } 164 165 void SBBlock::SetPtr(lldb_private::Block *block) { m_opaque_ptr = block; } 166 167 bool 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 192 uint32_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 200 lldb::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 214 lldb::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 229 uint32_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 240 lldb::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 297 lldb::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 349 namespace lldb_private { 350 namespace repro { 351 352 template <> 353 void 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