1 //===-- SBAddress.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/SBAddress.h" 10 #include "SBReproducerPrivate.h" 11 #include "Utils.h" 12 #include "lldb/API/SBProcess.h" 13 #include "lldb/API/SBSection.h" 14 #include "lldb/API/SBStream.h" 15 #include "lldb/Core/Address.h" 16 #include "lldb/Core/Module.h" 17 #include "lldb/Symbol/LineEntry.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Utility/StreamString.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 SBAddress::SBAddress() : m_opaque_up(new Address()) { 25 LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBAddress); 26 } 27 28 SBAddress::SBAddress(const Address *lldb_object_ptr) 29 : m_opaque_up(new Address()) { 30 if (lldb_object_ptr) 31 m_opaque_up = std::make_unique<Address>(*lldb_object_ptr); 32 } 33 34 SBAddress::SBAddress(const SBAddress &rhs) : m_opaque_up(new Address()) { 35 LLDB_RECORD_CONSTRUCTOR(SBAddress, (const lldb::SBAddress &), rhs); 36 37 m_opaque_up = clone(rhs.m_opaque_up); 38 } 39 40 SBAddress::SBAddress(lldb::SBSection section, lldb::addr_t offset) 41 : m_opaque_up(new Address(section.GetSP(), offset)) { 42 LLDB_RECORD_CONSTRUCTOR(SBAddress, (lldb::SBSection, lldb::addr_t), section, 43 offset); 44 } 45 46 // Create an address by resolving a load address using the supplied target 47 SBAddress::SBAddress(lldb::addr_t load_addr, lldb::SBTarget &target) 48 : m_opaque_up(new Address()) { 49 LLDB_RECORD_CONSTRUCTOR(SBAddress, (lldb::addr_t, lldb::SBTarget &), 50 load_addr, target); 51 52 SetLoadAddress(load_addr, target); 53 } 54 55 SBAddress::~SBAddress() {} 56 57 const SBAddress &SBAddress::operator=(const SBAddress &rhs) { 58 LLDB_RECORD_METHOD(const lldb::SBAddress &, 59 SBAddress, operator=,(const lldb::SBAddress &), rhs); 60 61 if (this != &rhs) 62 m_opaque_up = clone(rhs.m_opaque_up); 63 return LLDB_RECORD_RESULT(*this); 64 } 65 66 bool lldb::operator==(const SBAddress &lhs, const SBAddress &rhs) { 67 if (lhs.IsValid() && rhs.IsValid()) 68 return lhs.ref() == rhs.ref(); 69 return false; 70 } 71 72 bool SBAddress::operator!=(const SBAddress &rhs) const { 73 LLDB_RECORD_METHOD_CONST(bool, SBAddress, operator!=,(const SBAddress &), 74 &rhs); 75 76 return !(*this == rhs); 77 } 78 79 bool SBAddress::IsValid() const { 80 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBAddress, IsValid); 81 return this->operator bool(); 82 } 83 SBAddress::operator bool() const { 84 LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBAddress, operator bool); 85 86 return m_opaque_up != nullptr && m_opaque_up->IsValid(); 87 } 88 89 void SBAddress::Clear() { 90 LLDB_RECORD_METHOD_NO_ARGS(void, SBAddress, Clear); 91 92 m_opaque_up.reset(new Address()); 93 } 94 95 void SBAddress::SetAddress(lldb::SBSection section, lldb::addr_t offset) { 96 LLDB_RECORD_METHOD(void, SBAddress, SetAddress, 97 (lldb::SBSection, lldb::addr_t), section, offset); 98 99 Address &addr = ref(); 100 addr.SetSection(section.GetSP()); 101 addr.SetOffset(offset); 102 } 103 104 void SBAddress::SetAddress(const Address *lldb_object_ptr) { 105 if (lldb_object_ptr) 106 ref() = *lldb_object_ptr; 107 else 108 m_opaque_up.reset(new Address()); 109 } 110 111 lldb::addr_t SBAddress::GetFileAddress() const { 112 LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::addr_t, SBAddress, GetFileAddress); 113 114 if (m_opaque_up->IsValid()) 115 return m_opaque_up->GetFileAddress(); 116 else 117 return LLDB_INVALID_ADDRESS; 118 } 119 120 lldb::addr_t SBAddress::GetLoadAddress(const SBTarget &target) const { 121 LLDB_RECORD_METHOD_CONST(lldb::addr_t, SBAddress, GetLoadAddress, 122 (const lldb::SBTarget &), target); 123 124 lldb::addr_t addr = LLDB_INVALID_ADDRESS; 125 TargetSP target_sp(target.GetSP()); 126 if (target_sp) { 127 if (m_opaque_up->IsValid()) { 128 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 129 addr = m_opaque_up->GetLoadAddress(target_sp.get()); 130 } 131 } 132 133 return addr; 134 } 135 136 void SBAddress::SetLoadAddress(lldb::addr_t load_addr, lldb::SBTarget &target) { 137 LLDB_RECORD_METHOD(void, SBAddress, SetLoadAddress, 138 (lldb::addr_t, lldb::SBTarget &), load_addr, target); 139 140 // Create the address object if we don't already have one 141 ref(); 142 if (target.IsValid()) 143 *this = target.ResolveLoadAddress(load_addr); 144 else 145 m_opaque_up->Clear(); 146 147 // Check if we weren't were able to resolve a section offset address. If we 148 // weren't it is ok, the load address might be a location on the stack or 149 // heap, so we should just have an address with no section and a valid offset 150 if (!m_opaque_up->IsValid()) 151 m_opaque_up->SetOffset(load_addr); 152 } 153 154 bool SBAddress::OffsetAddress(addr_t offset) { 155 LLDB_RECORD_METHOD(bool, SBAddress, OffsetAddress, (lldb::addr_t), offset); 156 157 if (m_opaque_up->IsValid()) { 158 addr_t addr_offset = m_opaque_up->GetOffset(); 159 if (addr_offset != LLDB_INVALID_ADDRESS) { 160 m_opaque_up->SetOffset(addr_offset + offset); 161 return true; 162 } 163 } 164 return false; 165 } 166 167 lldb::SBSection SBAddress::GetSection() { 168 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBSection, SBAddress, GetSection); 169 170 lldb::SBSection sb_section; 171 if (m_opaque_up->IsValid()) 172 sb_section.SetSP(m_opaque_up->GetSection()); 173 return LLDB_RECORD_RESULT(sb_section); 174 } 175 176 lldb::addr_t SBAddress::GetOffset() { 177 LLDB_RECORD_METHOD_NO_ARGS(lldb::addr_t, SBAddress, GetOffset); 178 179 if (m_opaque_up->IsValid()) 180 return m_opaque_up->GetOffset(); 181 return 0; 182 } 183 184 Address *SBAddress::operator->() { return m_opaque_up.get(); } 185 186 const Address *SBAddress::operator->() const { return m_opaque_up.get(); } 187 188 Address &SBAddress::ref() { 189 if (m_opaque_up == nullptr) 190 m_opaque_up.reset(new Address()); 191 return *m_opaque_up; 192 } 193 194 const Address &SBAddress::ref() const { 195 // This object should already have checked with "IsValid()" prior to calling 196 // this function. In case you didn't we will assert and die to let you know. 197 assert(m_opaque_up.get()); 198 return *m_opaque_up; 199 } 200 201 Address *SBAddress::get() { return m_opaque_up.get(); } 202 203 bool SBAddress::GetDescription(SBStream &description) { 204 LLDB_RECORD_METHOD(bool, SBAddress, GetDescription, (lldb::SBStream &), 205 description); 206 207 // Call "ref()" on the stream to make sure it creates a backing stream in 208 // case there isn't one already... 209 Stream &strm = description.ref(); 210 if (m_opaque_up->IsValid()) { 211 m_opaque_up->Dump(&strm, nullptr, Address::DumpStyleResolvedDescription, 212 Address::DumpStyleModuleWithFileAddress, 4); 213 } else 214 strm.PutCString("No value"); 215 216 return true; 217 } 218 219 SBModule SBAddress::GetModule() { 220 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBModule, SBAddress, GetModule); 221 222 SBModule sb_module; 223 if (m_opaque_up->IsValid()) 224 sb_module.SetSP(m_opaque_up->GetModule()); 225 return LLDB_RECORD_RESULT(sb_module); 226 } 227 228 SBSymbolContext SBAddress::GetSymbolContext(uint32_t resolve_scope) { 229 LLDB_RECORD_METHOD(lldb::SBSymbolContext, SBAddress, GetSymbolContext, 230 (uint32_t), resolve_scope); 231 232 SBSymbolContext sb_sc; 233 SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope); 234 if (m_opaque_up->IsValid()) 235 m_opaque_up->CalculateSymbolContext(&sb_sc.ref(), scope); 236 return LLDB_RECORD_RESULT(sb_sc); 237 } 238 239 SBCompileUnit SBAddress::GetCompileUnit() { 240 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBCompileUnit, SBAddress, GetCompileUnit); 241 242 SBCompileUnit sb_comp_unit; 243 if (m_opaque_up->IsValid()) 244 sb_comp_unit.reset(m_opaque_up->CalculateSymbolContextCompileUnit()); 245 return LLDB_RECORD_RESULT(sb_comp_unit); 246 } 247 248 SBFunction SBAddress::GetFunction() { 249 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBFunction, SBAddress, GetFunction); 250 251 SBFunction sb_function; 252 if (m_opaque_up->IsValid()) 253 sb_function.reset(m_opaque_up->CalculateSymbolContextFunction()); 254 return LLDB_RECORD_RESULT(sb_function); 255 } 256 257 SBBlock SBAddress::GetBlock() { 258 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBlock, SBAddress, GetBlock); 259 260 SBBlock sb_block; 261 if (m_opaque_up->IsValid()) 262 sb_block.SetPtr(m_opaque_up->CalculateSymbolContextBlock()); 263 return LLDB_RECORD_RESULT(sb_block); 264 } 265 266 SBSymbol SBAddress::GetSymbol() { 267 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBSymbol, SBAddress, GetSymbol); 268 269 SBSymbol sb_symbol; 270 if (m_opaque_up->IsValid()) 271 sb_symbol.reset(m_opaque_up->CalculateSymbolContextSymbol()); 272 return LLDB_RECORD_RESULT(sb_symbol); 273 } 274 275 SBLineEntry SBAddress::GetLineEntry() { 276 LLDB_RECORD_METHOD_NO_ARGS(lldb::SBLineEntry, SBAddress, GetLineEntry); 277 278 SBLineEntry sb_line_entry; 279 if (m_opaque_up->IsValid()) { 280 LineEntry line_entry; 281 if (m_opaque_up->CalculateSymbolContextLineEntry(line_entry)) 282 sb_line_entry.SetLineEntry(line_entry); 283 } 284 return LLDB_RECORD_RESULT(sb_line_entry); 285 } 286 287 namespace lldb_private { 288 namespace repro { 289 290 template <> 291 void RegisterMethods<SBAddress>(Registry &R) { 292 LLDB_REGISTER_CONSTRUCTOR(SBAddress, ()); 293 LLDB_REGISTER_CONSTRUCTOR(SBAddress, (const lldb::SBAddress &)); 294 LLDB_REGISTER_CONSTRUCTOR(SBAddress, (lldb::SBSection, lldb::addr_t)); 295 LLDB_REGISTER_CONSTRUCTOR(SBAddress, (lldb::addr_t, lldb::SBTarget &)); 296 LLDB_REGISTER_METHOD(const lldb::SBAddress &, 297 SBAddress, operator=,(const lldb::SBAddress &)); 298 LLDB_REGISTER_METHOD_CONST(bool, 299 SBAddress, operator!=,(const lldb::SBAddress &)); 300 LLDB_REGISTER_METHOD_CONST(bool, SBAddress, IsValid, ()); 301 LLDB_REGISTER_METHOD_CONST(bool, SBAddress, operator bool, ()); 302 LLDB_REGISTER_METHOD(void, SBAddress, Clear, ()); 303 LLDB_REGISTER_METHOD(void, SBAddress, SetAddress, 304 (lldb::SBSection, lldb::addr_t)); 305 LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBAddress, GetFileAddress, ()); 306 LLDB_REGISTER_METHOD_CONST(lldb::addr_t, SBAddress, GetLoadAddress, 307 (const lldb::SBTarget &)); 308 LLDB_REGISTER_METHOD(void, SBAddress, SetLoadAddress, 309 (lldb::addr_t, lldb::SBTarget &)); 310 LLDB_REGISTER_METHOD(bool, SBAddress, OffsetAddress, (lldb::addr_t)); 311 LLDB_REGISTER_METHOD(lldb::SBSection, SBAddress, GetSection, ()); 312 LLDB_REGISTER_METHOD(lldb::addr_t, SBAddress, GetOffset, ()); 313 LLDB_REGISTER_METHOD(bool, SBAddress, GetDescription, (lldb::SBStream &)); 314 LLDB_REGISTER_METHOD(lldb::SBModule, SBAddress, GetModule, ()); 315 LLDB_REGISTER_METHOD(lldb::SBSymbolContext, SBAddress, GetSymbolContext, 316 (uint32_t)); 317 LLDB_REGISTER_METHOD(lldb::SBCompileUnit, SBAddress, GetCompileUnit, ()); 318 LLDB_REGISTER_METHOD(lldb::SBFunction, SBAddress, GetFunction, ()); 319 LLDB_REGISTER_METHOD(lldb::SBBlock, SBAddress, GetBlock, ()); 320 LLDB_REGISTER_METHOD(lldb::SBSymbol, SBAddress, GetSymbol, ()); 321 LLDB_REGISTER_METHOD(lldb::SBLineEntry, SBAddress, GetLineEntry, ()); 322 } 323 324 } 325 } 326