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