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.GetModuleSP()),
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 
107 SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) :
108     m_opaque_ap(new AddressImpl (Address(section.GetSection(), offset)))
109 {
110 }
111 
112 // Create an address by resolving a load address using the supplied target
113 SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
114     m_opaque_ap()
115 {
116     SetLoadAddress (load_addr, target);
117 }
118 
119 
120 
121 SBAddress::~SBAddress ()
122 {
123 }
124 
125 const SBAddress &
126 SBAddress::operator = (const SBAddress &rhs)
127 {
128     if (this != &rhs)
129     {
130         if (rhs.IsValid())
131             m_opaque_ap.reset(new AddressImpl(*rhs.m_opaque_ap.get()));
132         else
133             m_opaque_ap.reset();
134     }
135     return *this;
136 }
137 
138 bool
139 SBAddress::IsValid () const
140 {
141     return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
142 }
143 
144 void
145 SBAddress::Clear ()
146 {
147     m_opaque_ap.reset();
148 }
149 
150 void
151 SBAddress::SetAddress (lldb::SBSection section, lldb::addr_t offset)
152 {
153     Address &addr = ref();
154     addr.SetSection (section.GetSection());
155     addr.SetOffset (offset);
156 }
157 
158 
159 void
160 SBAddress::SetAddress (const Address *lldb_object_ptr)
161 {
162     if (lldb_object_ptr)
163     {
164         if (m_opaque_ap.get())
165             *m_opaque_ap = *lldb_object_ptr;
166         else
167             m_opaque_ap.reset (new AddressImpl(*lldb_object_ptr));
168     }
169     else
170         m_opaque_ap.reset();
171 }
172 
173 lldb::addr_t
174 SBAddress::GetFileAddress () const
175 {
176     if (m_opaque_ap.get())
177         return m_opaque_ap->GetAddress().GetFileAddress();
178     else
179         return LLDB_INVALID_ADDRESS;
180 }
181 
182 lldb::addr_t
183 SBAddress::GetLoadAddress (const SBTarget &target) const
184 {
185     LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
186 
187     lldb::addr_t addr = LLDB_INVALID_ADDRESS;
188     TargetSP target_sp (target.GetSP());
189     if (m_opaque_ap.get())
190     {
191         Mutex::Locker api_locker (target_sp->GetAPIMutex());
192         addr = m_opaque_ap->GetAddress().GetLoadAddress (target_sp.get());
193     }
194 
195     if (log)
196     {
197         if (addr == LLDB_INVALID_ADDRESS)
198             log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS", target_sp.get());
199         else
200             log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%llx", target_sp.get(), addr);
201     }
202 
203     return addr;
204 }
205 
206 void
207 SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
208 {
209     // Create the address object if we don't already have one
210     ref();
211     if (target.IsValid())
212         *this = target.ResolveLoadAddress(load_addr);
213     else
214         m_opaque_ap->GetAddress().Clear();
215 
216     // Check if we weren't were able to resolve a section offset address.
217     // If we weren't it is ok, the load address might be a location on the
218     // stack or heap, so we should just have an address with no section and
219     // a valid offset
220     if (!m_opaque_ap->IsValid())
221         m_opaque_ap->GetAddress().SetOffset(load_addr);
222 }
223 
224 bool
225 SBAddress::OffsetAddress (addr_t offset)
226 {
227     if (m_opaque_ap.get())
228     {
229         addr_t addr_offset = m_opaque_ap->GetAddress().GetOffset();
230         if (addr_offset != LLDB_INVALID_ADDRESS)
231         {
232             m_opaque_ap->GetAddress().SetOffset(addr_offset + offset);
233             return true;
234         }
235     }
236     return false;
237 }
238 
239 lldb::SBSection
240 SBAddress::GetSection ()
241 {
242     lldb::SBSection sb_section;
243     if (m_opaque_ap.get())
244         sb_section.SetSection(m_opaque_ap->GetAddress().GetSection());
245     return sb_section;
246 }
247 
248 lldb::addr_t
249 SBAddress::GetOffset ()
250 {
251     if (m_opaque_ap.get())
252         m_opaque_ap->GetAddress().GetOffset();
253     return 0;
254 }
255 
256 Address *
257 SBAddress::operator->()
258 {
259     if (m_opaque_ap.get())
260         return &m_opaque_ap->GetAddress();
261     return NULL;
262 }
263 
264 const Address *
265 SBAddress::operator->() const
266 {
267     if (m_opaque_ap.get())
268         return &m_opaque_ap->GetAddress();
269     return NULL;
270 }
271 
272 Address &
273 SBAddress::ref ()
274 {
275     if (m_opaque_ap.get() == NULL)
276         m_opaque_ap.reset (new AddressImpl());
277     return m_opaque_ap->GetAddress();
278 }
279 
280 const Address &
281 SBAddress::ref () const
282 {
283     // "const SBAddress &addr" should already have checked "addr.IsValid()"
284     // prior to calling this function. In case you didn't we will assert
285     // and die to let you know.
286     assert (m_opaque_ap.get());
287     return m_opaque_ap->GetAddress();
288 }
289 
290 Address *
291 SBAddress::get ()
292 {
293     if (m_opaque_ap.get())
294         return &m_opaque_ap->GetAddress();
295     return NULL;
296 }
297 
298 bool
299 SBAddress::GetDescription (SBStream &description)
300 {
301     // Call "ref()" on the stream to make sure it creates a backing stream in
302     // case there isn't one already...
303     Stream &strm = description.ref();
304     if (m_opaque_ap.get())
305         m_opaque_ap->GetAddress().Dump (&strm, NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
306     else
307         strm.PutCString ("No value");
308 
309     return true;
310 }
311 
312 SBModule
313 SBAddress::GetModule ()
314 {
315     SBModule sb_module;
316     if (m_opaque_ap.get())
317     {
318         sb_module.SetSP (m_opaque_ap->GetModuleSP());
319     }
320     return sb_module;
321 }
322 
323 SBSymbolContext
324 SBAddress::GetSymbolContext (uint32_t resolve_scope)
325 {
326     SBSymbolContext sb_sc;
327     if (m_opaque_ap.get())
328         m_opaque_ap->GetAddress().CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
329     return sb_sc;
330 }
331 
332 SBCompileUnit
333 SBAddress::GetCompileUnit ()
334 {
335     SBCompileUnit sb_comp_unit;
336     if (m_opaque_ap.get())
337         sb_comp_unit.reset(m_opaque_ap->GetAddress().CalculateSymbolContextCompileUnit());
338     return sb_comp_unit;
339 }
340 
341 SBFunction
342 SBAddress::GetFunction ()
343 {
344     SBFunction sb_function;
345     if (m_opaque_ap.get())
346         sb_function.reset(m_opaque_ap->GetAddress().CalculateSymbolContextFunction());
347     return sb_function;
348 }
349 
350 SBBlock
351 SBAddress::GetBlock ()
352 {
353     SBBlock sb_block;
354     if (m_opaque_ap.get())
355         sb_block.reset(m_opaque_ap->GetAddress().CalculateSymbolContextBlock());
356     return sb_block;
357 }
358 
359 SBSymbol
360 SBAddress::GetSymbol ()
361 {
362     SBSymbol sb_symbol;
363     if (m_opaque_ap.get())
364         sb_symbol.reset(m_opaque_ap->GetAddress().CalculateSymbolContextSymbol());
365     return sb_symbol;
366 }
367 
368 SBLineEntry
369 SBAddress::GetLineEntry ()
370 {
371     SBLineEntry sb_line_entry;
372     if (m_opaque_ap.get())
373     {
374         LineEntry line_entry;
375         if (m_opaque_ap->GetAddress().CalculateSymbolContextLineEntry (line_entry))
376             sb_line_entry.SetLineEntry (line_entry);
377     }
378     return sb_line_entry;
379 }
380 
381 
382