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