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/Symbol/Block.h" 18 #include "lldb/Symbol/Function.h" 19 #include "lldb/Symbol/SymbolContext.h" 20 #include "lldb/Symbol/VariableList.h" 21 #include "lldb/Target/StackFrame.h" 22 #include "lldb/Target/Target.h" 23 #include "lldb/Utility/Instrumentation.h" 24 #include "lldb/ValueObject/ValueObjectVariable.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, sc.function->GetAddress().GetFileAddress()); 180 } 181 } else 182 strm.PutCString("No value"); 183 184 return true; 185 } 186 187 uint32_t SBBlock::GetNumRanges() { 188 LLDB_INSTRUMENT_VA(this); 189 190 if (m_opaque_ptr) 191 return m_opaque_ptr->GetNumRanges(); 192 return 0; 193 } 194 195 lldb::SBAddress SBBlock::GetRangeStartAddress(uint32_t idx) { 196 LLDB_INSTRUMENT_VA(this, idx); 197 198 lldb::SBAddress sb_addr; 199 if (m_opaque_ptr) { 200 AddressRange range; 201 if (m_opaque_ptr->GetRangeAtIndex(idx, range)) { 202 sb_addr.ref() = range.GetBaseAddress(); 203 } 204 } 205 return sb_addr; 206 } 207 208 lldb::SBAddress SBBlock::GetRangeEndAddress(uint32_t idx) { 209 LLDB_INSTRUMENT_VA(this, idx); 210 211 lldb::SBAddress sb_addr; 212 if (m_opaque_ptr) { 213 AddressRange range; 214 if (m_opaque_ptr->GetRangeAtIndex(idx, range)) { 215 sb_addr.ref() = range.GetBaseAddress(); 216 sb_addr.ref().Slide(range.GetByteSize()); 217 } 218 } 219 return sb_addr; 220 } 221 222 lldb::SBAddressRangeList SBBlock::GetRanges() { 223 LLDB_INSTRUMENT_VA(this); 224 225 lldb::SBAddressRangeList sb_ranges; 226 if (m_opaque_ptr) 227 sb_ranges.m_opaque_up->ref() = m_opaque_ptr->GetRanges(); 228 return sb_ranges; 229 } 230 231 uint32_t SBBlock::GetRangeIndexForBlockAddress(lldb::SBAddress block_addr) { 232 LLDB_INSTRUMENT_VA(this, block_addr); 233 234 if (m_opaque_ptr && block_addr.IsValid()) { 235 return m_opaque_ptr->GetRangeIndexContainingAddress(block_addr.ref()); 236 } 237 238 return UINT32_MAX; 239 } 240 241 lldb::SBValueList SBBlock::GetVariables(lldb::SBFrame &frame, bool arguments, 242 bool locals, bool statics, 243 lldb::DynamicValueType use_dynamic) { 244 LLDB_INSTRUMENT_VA(this, frame, 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 value_list; 293 } 294 295 lldb::SBValueList SBBlock::GetVariables(lldb::SBTarget &target, bool arguments, 296 bool locals, bool statics) { 297 LLDB_INSTRUMENT_VA(this, target, arguments, locals, statics); 298 299 Block *block = GetPtr(); 300 301 SBValueList value_list; 302 if (block) { 303 TargetSP target_sp(target.GetSP()); 304 305 VariableListSP variable_list_sp(block->GetBlockVariableList(true)); 306 307 if (variable_list_sp) { 308 const size_t num_variables = variable_list_sp->GetSize(); 309 if (num_variables) { 310 for (size_t i = 0; i < num_variables; ++i) { 311 VariableSP variable_sp(variable_list_sp->GetVariableAtIndex(i)); 312 if (variable_sp) { 313 bool add_variable = false; 314 switch (variable_sp->GetScope()) { 315 case eValueTypeVariableGlobal: 316 case eValueTypeVariableStatic: 317 case eValueTypeVariableThreadLocal: 318 add_variable = statics; 319 break; 320 321 case eValueTypeVariableArgument: 322 add_variable = arguments; 323 break; 324 325 case eValueTypeVariableLocal: 326 add_variable = locals; 327 break; 328 329 default: 330 break; 331 } 332 if (add_variable) { 333 if (target_sp) 334 value_list.Append( 335 ValueObjectVariable::Create(target_sp.get(), variable_sp)); 336 } 337 } 338 } 339 } 340 } 341 } 342 return value_list; 343 } 344