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