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