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