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