SBAddress.cpp revision 0416bdf783a7dc2544b9ab034e225391f8f47343
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
20namespace 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
83using namespace lldb;
84using namespace lldb_private;
85
86
87SBAddress::SBAddress () :
88    m_opaque_ap ()
89{
90}
91
92SBAddress::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
99SBAddress::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
107SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
108    m_opaque_ap()
109{
110    SetLoadAddress (load_addr, target);
111}
112
113
114
115SBAddress::~SBAddress ()
116{
117}
118
119const SBAddress &
120SBAddress::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
132bool
133SBAddress::IsValid () const
134{
135    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
136}
137
138void
139SBAddress::Clear ()
140{
141    m_opaque_ap.reset();
142}
143
144void
145SBAddress::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
158lldb::addr_t
159SBAddress::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
167lldb::addr_t
168SBAddress::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
191void
192SBAddress::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
209bool
210SBAddress::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
224lldb::SBSection
225SBAddress::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
233lldb::addr_t
234SBAddress::GetOffset ()
235{
236    if (m_opaque_ap.get())
237        m_opaque_ap->GetAddress().GetOffset();
238    return 0;
239}
240
241Address *
242SBAddress::operator->()
243{
244    if (m_opaque_ap.get())
245        return &m_opaque_ap->GetAddress();
246    return NULL;
247}
248
249const Address *
250SBAddress::operator->() const
251{
252    if (m_opaque_ap.get())
253        return &m_opaque_ap->GetAddress();
254    return NULL;
255}
256
257Address &
258SBAddress::ref ()
259{
260    if (m_opaque_ap.get() == NULL)
261        m_opaque_ap.reset (new AddressImpl());
262    return m_opaque_ap->GetAddress();
263}
264
265const Address &
266SBAddress::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
275Address *
276SBAddress::get ()
277{
278    if (m_opaque_ap.get())
279        return &m_opaque_ap->GetAddress();
280    return NULL;
281}
282
283bool
284SBAddress::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
297SBModule
298SBAddress::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
308SBSymbolContext
309SBAddress::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
317SBCompileUnit
318SBAddress::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
326SBFunction
327SBAddress::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
335SBBlock
336SBAddress::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
344SBSymbol
345SBAddress::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
353SBLineEntry
354SBAddress::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