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