1 //===-- SBAddress.cpp -------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/API/SBAddress.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/Log.h"
16 #include "lldb/Core/Module.h"
17 #include "lldb/Host/Mutex.h"
18 #include "lldb/Target/Target.h"
19 
20 namespace lldb_private
21 {
22     // We need a address implementation to hold onto a reference to the module
23     // since if the module goes away and we have anyone still holding onto a
24     // SBAddress object, we could crash.
25     class AddressImpl
26     {
27     public:
28         AddressImpl () :
29             m_module_sp(),
30             m_address()
31         {
32         }
33 
34         AddressImpl (const Address &addr) :
35             m_module_sp (addr.GetModule()),
36             m_address (addr)
37         {
38         }
39 
40         AddressImpl (const AddressImpl &rhs) :
41             m_module_sp (rhs.m_module_sp),
42             m_address   (rhs.m_address)
43         {
44         }
45 
46         bool
47         IsValid () const
48         {
49             return m_address.IsValid();
50         }
51 
52         void
53         operator = (const AddressImpl &rhs)
54         {
55             m_module_sp = rhs.m_module_sp;
56             m_address = rhs.m_address;
57         }
58 
59         Address &
60         GetAddress ()
61         {
62             return m_address;
63         }
64 
65         Module *
66         GetModule()
67         {
68             return m_module_sp.get();
69         }
70 
71         const lldb::ModuleSP &
72         GetModuleSP() const
73         {
74             return m_module_sp;
75         }
76     protected:
77         lldb::ModuleSP m_module_sp;
78         Address m_address;
79     };
80 }
81 
82 
83 using namespace lldb;
84 using namespace lldb_private;
85 
86 
87 SBAddress::SBAddress () :
88     m_opaque_ap ()
89 {
90 }
91 
92 SBAddress::SBAddress (const Address *lldb_object_ptr) :
93     m_opaque_ap ()
94 {
95     if (lldb_object_ptr)
96         m_opaque_ap.reset (new AddressImpl(*lldb_object_ptr));
97 }
98 
99 SBAddress::SBAddress (const SBAddress &rhs) :
100     m_opaque_ap ()
101 {
102     if (rhs.IsValid())
103         m_opaque_ap.reset (new AddressImpl(*rhs.m_opaque_ap.get()));
104 }
105 
106 // Create an address by resolving a load address using the supplied target
107 SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
108     m_opaque_ap()
109 {
110     SetLoadAddress (load_addr, target);
111 }
112 
113 
114 
115 SBAddress::~SBAddress ()
116 {
117 }
118 
119 const SBAddress &
120 SBAddress::operator = (const SBAddress &rhs)
121 {
122     if (this != &rhs)
123     {
124         if (rhs.IsValid())
125             m_opaque_ap.reset(new AddressImpl(*rhs.m_opaque_ap.get()));
126         else
127             m_opaque_ap.reset();
128     }
129     return *this;
130 }
131 
132 bool
133 SBAddress::IsValid () const
134 {
135     return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
136 }
137 
138 void
139 SBAddress::Clear ()
140 {
141     m_opaque_ap.reset();
142 }
143 
144 void
145 SBAddress::SetAddress (const Address *lldb_object_ptr)
146 {
147     if (lldb_object_ptr)
148     {
149         if (m_opaque_ap.get())
150             *m_opaque_ap = *lldb_object_ptr;
151         else
152             m_opaque_ap.reset (new AddressImpl(*lldb_object_ptr));
153     }
154     else
155         m_opaque_ap.reset();
156 }
157 
158 lldb::addr_t
159 SBAddress::GetFileAddress () const
160 {
161     if (m_opaque_ap.get())
162         return m_opaque_ap->GetAddress().GetFileAddress();
163     else
164         return LLDB_INVALID_ADDRESS;
165 }
166 
167 lldb::addr_t
168 SBAddress::GetLoadAddress (const SBTarget &target) const
169 {
170     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
171 
172     lldb::addr_t addr = LLDB_INVALID_ADDRESS;
173     if (m_opaque_ap.get())
174     {
175         Mutex::Locker api_locker (target->GetAPIMutex());
176         addr = m_opaque_ap->GetAddress().GetLoadAddress (target.get());
177     }
178 
179     if (log)
180     {
181         if (addr == LLDB_INVALID_ADDRESS)
182             log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS", target.get());
183         else
184             log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%llx", target.get(), addr);
185     }
186 
187     return addr;
188 }
189 
190 void
191 SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
192 {
193     // Create the address object if we don't already have one
194     ref();
195     if (target.IsValid())
196         *this = target.ResolveLoadAddress(load_addr);
197     else
198         m_opaque_ap->GetAddress().Clear();
199 
200     // Check if we weren't were able to resolve a section offset address.
201     // If we weren't it is ok, the load address might be a location on the
202     // stack or heap, so we should just have an address with no section and
203     // a valid offset
204     if (!m_opaque_ap->IsValid())
205         m_opaque_ap->GetAddress().SetOffset(load_addr);
206 }
207 
208 bool
209 SBAddress::OffsetAddress (addr_t offset)
210 {
211     if (m_opaque_ap.get())
212     {
213         addr_t addr_offset = m_opaque_ap->GetAddress().GetOffset();
214         if (addr_offset != LLDB_INVALID_ADDRESS)
215         {
216             m_opaque_ap->GetAddress().SetOffset(addr_offset + offset);
217             return true;
218         }
219     }
220     return false;
221 }
222 
223 lldb::SBSection
224 SBAddress::GetSection ()
225 {
226     lldb::SBSection sb_section;
227     if (m_opaque_ap.get())
228         sb_section.SetSection(m_opaque_ap->GetAddress().GetSection());
229     return sb_section;
230 }
231 
232 
233 Address *
234 SBAddress::operator->()
235 {
236     if (m_opaque_ap.get())
237         return &m_opaque_ap->GetAddress();
238     return NULL;
239 }
240 
241 const Address *
242 SBAddress::operator->() const
243 {
244     if (m_opaque_ap.get())
245         return &m_opaque_ap->GetAddress();
246     return NULL;
247 }
248 
249 Address &
250 SBAddress::ref ()
251 {
252     if (m_opaque_ap.get() == NULL)
253         m_opaque_ap.reset (new AddressImpl());
254     return m_opaque_ap->GetAddress();
255 }
256 
257 const Address &
258 SBAddress::ref () const
259 {
260     // "const SBAddress &addr" should already have checked "addr.IsValid()"
261     // prior to calling this function. In case you didn't we will assert
262     // and die to let you know.
263     assert (m_opaque_ap.get());
264     return m_opaque_ap->GetAddress();
265 }
266 
267 Address *
268 SBAddress::get ()
269 {
270     if (m_opaque_ap.get())
271         return &m_opaque_ap->GetAddress();
272     return NULL;
273 }
274 
275 bool
276 SBAddress::GetDescription (SBStream &description)
277 {
278     // Call "ref()" on the stream to make sure it creates a backing stream in
279     // case there isn't one already...
280     description.ref();
281     if (m_opaque_ap.get())
282         m_opaque_ap->GetAddress().Dump (description.get(), NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
283     else
284         description.Printf ("No value");
285 
286     return true;
287 }
288 
289 SBModule
290 SBAddress::GetModule ()
291 {
292     SBModule sb_module;
293     if (m_opaque_ap.get())
294     {
295         Module *module = m_opaque_ap->GetModule();
296         if (module)
297             *sb_module = module;
298     }
299     return sb_module;
300 }
301 
302 SBSymbolContext
303 SBAddress::GetSymbolContext (uint32_t resolve_scope)
304 {
305     SBSymbolContext sb_sc;
306     if (m_opaque_ap.get())
307         m_opaque_ap->GetAddress().CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
308     return sb_sc;
309 }
310 
311 SBCompileUnit
312 SBAddress::GetCompileUnit ()
313 {
314     SBCompileUnit sb_comp_unit;
315     if (m_opaque_ap.get())
316         sb_comp_unit.reset(m_opaque_ap->GetAddress().CalculateSymbolContextCompileUnit());
317     return sb_comp_unit;
318 }
319 
320 SBFunction
321 SBAddress::GetFunction ()
322 {
323     SBFunction sb_function;
324     if (m_opaque_ap.get())
325         sb_function.reset(m_opaque_ap->GetAddress().CalculateSymbolContextFunction());
326     return sb_function;
327 }
328 
329 SBBlock
330 SBAddress::GetBlock ()
331 {
332     SBBlock sb_block;
333     if (m_opaque_ap.get())
334         sb_block.reset(m_opaque_ap->GetAddress().CalculateSymbolContextBlock());
335     return sb_block;
336 }
337 
338 SBSymbol
339 SBAddress::GetSymbol ()
340 {
341     SBSymbol sb_symbol;
342     if (m_opaque_ap.get())
343         sb_symbol.reset(m_opaque_ap->GetAddress().CalculateSymbolContextSymbol());
344     return sb_symbol;
345 }
346 
347 SBLineEntry
348 SBAddress::GetLineEntry ()
349 {
350     SBLineEntry sb_line_entry;
351     if (m_opaque_ap.get())
352     {
353         LineEntry line_entry;
354         if (m_opaque_ap->GetAddress().CalculateSymbolContextLineEntry (line_entry))
355             sb_line_entry.SetLineEntry (line_entry);
356     }
357     return sb_line_entry;
358 }
359 
360 
361