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