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 21 using namespace lldb; 22 using namespace lldb_private; 23 24 SBAddress::SBAddress() : m_opaque_up(new Address()) { 25 LLDB_INSTRUMENT_VA(this); 26 } 27 28 SBAddress::SBAddress(const Address &address) 29 : m_opaque_up(std::make_unique<Address>(address)) {} 30 31 SBAddress::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 37 SBAddress::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 43 SBAddress::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 50 SBAddress::~SBAddress() = default; 51 52 const 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 60 bool 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 66 bool SBAddress::operator!=(const SBAddress &rhs) const { 67 LLDB_INSTRUMENT_VA(this, rhs); 68 69 return !(*this == rhs); 70 } 71 72 bool SBAddress::IsValid() const { 73 LLDB_INSTRUMENT_VA(this); 74 return this->operator bool(); 75 } 76 SBAddress::operator bool() const { 77 LLDB_INSTRUMENT_VA(this); 78 79 return m_opaque_up != nullptr && m_opaque_up->IsValid(); 80 } 81 82 void SBAddress::Clear() { 83 LLDB_INSTRUMENT_VA(this); 84 85 m_opaque_up = std::make_unique<Address>(); 86 } 87 88 void 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 96 void SBAddress::SetAddress(const Address &address) { ref() = address; } 97 98 lldb::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 107 lldb::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 122 void 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 139 bool 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 152 lldb::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 161 lldb::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 169 Address *SBAddress::operator->() { return m_opaque_up.get(); } 170 171 const Address *SBAddress::operator->() const { return m_opaque_up.get(); } 172 173 Address &SBAddress::ref() { 174 if (m_opaque_up == nullptr) 175 m_opaque_up = std::make_unique<Address>(); 176 return *m_opaque_up; 177 } 178 179 const 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 186 Address *SBAddress::get() { return m_opaque_up.get(); } 187 188 bool 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 203 SBModule 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 212 SBSymbolContext 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 222 SBCompileUnit 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 231 SBFunction 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 240 SBBlock 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 249 SBSymbol 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 258 SBLineEntry 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