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