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
21using namespace lldb;
22using namespace lldb_private;
23
24
25SBAddress::SBAddress () :
26    m_opaque_ap ()
27{
28}
29
30SBAddress::SBAddress (const Address *lldb_object_ptr) :
31    m_opaque_ap ()
32{
33    if (lldb_object_ptr)
34        ref() = *lldb_object_ptr;
35}
36
37SBAddress::SBAddress (const SBAddress &rhs) :
38    m_opaque_ap ()
39{
40    if (rhs.IsValid())
41        ref() = rhs.ref();
42}
43
44
45SBAddress::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
51SBAddress::SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target) :
52    m_opaque_ap()
53{
54    SetLoadAddress (load_addr, target);
55}
56
57
58
59SBAddress::~SBAddress ()
60{
61}
62
63const SBAddress &
64SBAddress::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
76bool
77SBAddress::IsValid () const
78{
79    return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
80}
81
82void
83SBAddress::Clear ()
84{
85    m_opaque_ap.reset();
86}
87
88void
89SBAddress::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
97void
98SBAddress::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
106lldb::addr_t
107SBAddress::GetFileAddress () const
108{
109    if (m_opaque_ap.get())
110        return m_opaque_ap->GetFileAddress();
111    else
112        return LLDB_INVALID_ADDRESS;
113}
114
115lldb::addr_t
116SBAddress::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
142void
143SBAddress::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
160bool
161SBAddress::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
175lldb::SBSection
176SBAddress::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
184lldb::addr_t
185SBAddress::GetOffset ()
186{
187    if (m_opaque_ap.get())
188        return m_opaque_ap->GetOffset();
189    return 0;
190}
191
192Address *
193SBAddress::operator->()
194{
195    return m_opaque_ap.get();
196}
197
198const Address *
199SBAddress::operator->() const
200{
201    return m_opaque_ap.get();
202}
203
204Address &
205SBAddress::ref ()
206{
207    if (m_opaque_ap.get() == NULL)
208        m_opaque_ap.reset (new Address());
209    return *m_opaque_ap;
210}
211
212const Address &
213SBAddress::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
222Address *
223SBAddress::get ()
224{
225    return m_opaque_ap.get();
226}
227
228bool
229SBAddress::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
252SBModule
253SBAddress::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
261SBSymbolContext
262SBAddress::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
270SBCompileUnit
271SBAddress::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
279SBFunction
280SBAddress::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
288SBBlock
289SBAddress::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
297SBSymbol
298SBAddress::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
306SBLineEntry
307SBAddress::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
319AddressClass
320SBAddress::GetAddressClass ()
321{
322    if (m_opaque_ap.get())
323        return m_opaque_ap->GetAddressClass();
324    return eAddressClassInvalid;
325}
326
327