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