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