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