SBAddress.cpp revision 7dd5c51fbab8384b18f20ecc125f9a1bb3c9bcb2
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
107SBAddress::SBAddress (lldb::SBSection section, lldb::addr_t offset) :
108    m_opaque_ap(new AddressImpl (Address(section.GetSection(), offset)))
109{
110}
111
112// Create an address by resolving a load address using the supplied target
113SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
114    m_opaque_ap()
115{
116    SetLoadAddress (load_addr, target);
117}
118
119
120
121SBAddress::~SBAddress ()
122{
123}
124
125const SBAddress &
126SBAddress::operator = (const SBAddress &rhs)
127{
128    if (this != &rhs)
129    {
130        if (rhs.IsValid())
131            m_opaque_ap.reset(new AddressImpl(*rhs.m_opaque_ap.get()));
132        else
133            m_opaque_ap.reset();
134    }
135    return *this;
136}
137
138bool
139SBAddress::IsValid () const
140{
141    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
142}
143
144void
145SBAddress::Clear ()
146{
147    m_opaque_ap.reset();
148}
149
150void
151SBAddress::SetAddress (lldb::SBSection section, lldb::addr_t offset)
152{
153    Address &addr = ref();
154    addr.SetSection (section.GetSection());
155    addr.SetOffset (offset);
156}
157
158
159void
160SBAddress::SetAddress (const Address *lldb_object_ptr)
161{
162    if (lldb_object_ptr)
163    {
164        if (m_opaque_ap.get())
165            *m_opaque_ap = *lldb_object_ptr;
166        else
167            m_opaque_ap.reset (new AddressImpl(*lldb_object_ptr));
168    }
169    else
170        m_opaque_ap.reset();
171}
172
173lldb::addr_t
174SBAddress::GetFileAddress () const
175{
176    if (m_opaque_ap.get())
177        return m_opaque_ap->GetAddress().GetFileAddress();
178    else
179        return LLDB_INVALID_ADDRESS;
180}
181
182lldb::addr_t
183SBAddress::GetLoadAddress (const SBTarget &target) const
184{
185    LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
186
187    lldb::addr_t addr = LLDB_INVALID_ADDRESS;
188    TargetSP target_sp (target.GetSP());
189    if (m_opaque_ap.get())
190    {
191        Mutex::Locker api_locker (target_sp->GetAPIMutex());
192        addr = m_opaque_ap->GetAddress().GetLoadAddress (target_sp.get());
193    }
194
195    if (log)
196    {
197        if (addr == LLDB_INVALID_ADDRESS)
198            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => LLDB_INVALID_ADDRESS", target_sp.get());
199        else
200            log->Printf ("SBAddress::GetLoadAddress (SBTarget(%p)) => 0x%llx", target_sp.get(), addr);
201    }
202
203    return addr;
204}
205
206void
207SBAddress::SetLoadAddress (lldb::addr_t load_addr, lldb::SBTarget &target)
208{
209    // Create the address object if we don't already have one
210    ref();
211    if (target.IsValid())
212        *this = target.ResolveLoadAddress(load_addr);
213    else
214        m_opaque_ap->GetAddress().Clear();
215
216    // Check if we weren't were able to resolve a section offset address.
217    // If we weren't it is ok, the load address might be a location on the
218    // stack or heap, so we should just have an address with no section and
219    // a valid offset
220    if (!m_opaque_ap->IsValid())
221        m_opaque_ap->GetAddress().SetOffset(load_addr);
222}
223
224bool
225SBAddress::OffsetAddress (addr_t offset)
226{
227    if (m_opaque_ap.get())
228    {
229        addr_t addr_offset = m_opaque_ap->GetAddress().GetOffset();
230        if (addr_offset != LLDB_INVALID_ADDRESS)
231        {
232            m_opaque_ap->GetAddress().SetOffset(addr_offset + offset);
233            return true;
234        }
235    }
236    return false;
237}
238
239lldb::SBSection
240SBAddress::GetSection ()
241{
242    lldb::SBSection sb_section;
243    if (m_opaque_ap.get())
244        sb_section.SetSection(m_opaque_ap->GetAddress().GetSection());
245    return sb_section;
246}
247
248lldb::addr_t
249SBAddress::GetOffset ()
250{
251    if (m_opaque_ap.get())
252        m_opaque_ap->GetAddress().GetOffset();
253    return 0;
254}
255
256Address *
257SBAddress::operator->()
258{
259    if (m_opaque_ap.get())
260        return &m_opaque_ap->GetAddress();
261    return NULL;
262}
263
264const Address *
265SBAddress::operator->() const
266{
267    if (m_opaque_ap.get())
268        return &m_opaque_ap->GetAddress();
269    return NULL;
270}
271
272Address &
273SBAddress::ref ()
274{
275    if (m_opaque_ap.get() == NULL)
276        m_opaque_ap.reset (new AddressImpl());
277    return m_opaque_ap->GetAddress();
278}
279
280const Address &
281SBAddress::ref () const
282{
283    // "const SBAddress &addr" should already have checked "addr.IsValid()"
284    // prior to calling this function. In case you didn't we will assert
285    // and die to let you know.
286    assert (m_opaque_ap.get());
287    return m_opaque_ap->GetAddress();
288}
289
290Address *
291SBAddress::get ()
292{
293    if (m_opaque_ap.get())
294        return &m_opaque_ap->GetAddress();
295    return NULL;
296}
297
298bool
299SBAddress::GetDescription (SBStream &description)
300{
301    // Call "ref()" on the stream to make sure it creates a backing stream in
302    // case there isn't one already...
303    Stream &strm = description.ref();
304    if (m_opaque_ap.get())
305        m_opaque_ap->GetAddress().Dump (&strm, NULL, Address::DumpStyleModuleWithFileAddress, Address::DumpStyleInvalid, 4);
306    else
307        strm.PutCString ("No value");
308
309    return true;
310}
311
312SBModule
313SBAddress::GetModule ()
314{
315    SBModule sb_module;
316    if (m_opaque_ap.get())
317    {
318        sb_module.SetSP (m_opaque_ap->GetModuleSP());
319    }
320    return sb_module;
321}
322
323SBSymbolContext
324SBAddress::GetSymbolContext (uint32_t resolve_scope)
325{
326    SBSymbolContext sb_sc;
327    if (m_opaque_ap.get())
328        m_opaque_ap->GetAddress().CalculateSymbolContext (&sb_sc.ref(), resolve_scope);
329    return sb_sc;
330}
331
332SBCompileUnit
333SBAddress::GetCompileUnit ()
334{
335    SBCompileUnit sb_comp_unit;
336    if (m_opaque_ap.get())
337        sb_comp_unit.reset(m_opaque_ap->GetAddress().CalculateSymbolContextCompileUnit());
338    return sb_comp_unit;
339}
340
341SBFunction
342SBAddress::GetFunction ()
343{
344    SBFunction sb_function;
345    if (m_opaque_ap.get())
346        sb_function.reset(m_opaque_ap->GetAddress().CalculateSymbolContextFunction());
347    return sb_function;
348}
349
350SBBlock
351SBAddress::GetBlock ()
352{
353    SBBlock sb_block;
354    if (m_opaque_ap.get())
355        sb_block.SetPtr(m_opaque_ap->GetAddress().CalculateSymbolContextBlock());
356    return sb_block;
357}
358
359SBSymbol
360SBAddress::GetSymbol ()
361{
362    SBSymbol sb_symbol;
363    if (m_opaque_ap.get())
364        sb_symbol.reset(m_opaque_ap->GetAddress().CalculateSymbolContextSymbol());
365    return sb_symbol;
366}
367
368SBLineEntry
369SBAddress::GetLineEntry ()
370{
371    SBLineEntry sb_line_entry;
372    if (m_opaque_ap.get())
373    {
374        LineEntry line_entry;
375        if (m_opaque_ap->GetAddress().CalculateSymbolContextLineEntry (line_entry))
376            sb_line_entry.SetLineEntry (line_entry);
377    }
378    return sb_line_entry;
379}
380
381
382