1//===-- SBInstruction.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/SBInstruction.h"
11
12#include "lldb/API/SBAddress.h"
13#include "lldb/API/SBFrame.h"
14#include "lldb/API/SBInstruction.h"
15#include "lldb/API/SBStream.h"
16#include "lldb/API/SBTarget.h"
17
18#include "lldb/Core/ArchSpec.h"
19#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/DataExtractor.h"
21#include "lldb/Core/Disassembler.h"
22#include "lldb/Core/EmulateInstruction.h"
23#include "lldb/Core/StreamFile.h"
24#include "lldb/Target/ExecutionContext.h"
25#include "lldb/Target/StackFrame.h"
26#include "lldb/Target/Target.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31SBInstruction::SBInstruction ()
32{
33}
34
35SBInstruction::SBInstruction (const lldb::InstructionSP& inst_sp) :
36    m_opaque_sp (inst_sp)
37{
38}
39
40SBInstruction::SBInstruction(const SBInstruction &rhs) :
41    m_opaque_sp (rhs.m_opaque_sp)
42{
43}
44
45const SBInstruction &
46SBInstruction::operator = (const SBInstruction &rhs)
47{
48    if (this != &rhs)
49        m_opaque_sp = rhs.m_opaque_sp;
50    return *this;
51}
52
53SBInstruction::~SBInstruction ()
54{
55}
56
57bool
58SBInstruction::IsValid()
59{
60    return (m_opaque_sp.get() != NULL);
61}
62
63SBAddress
64SBInstruction::GetAddress()
65{
66    SBAddress sb_addr;
67    if (m_opaque_sp && m_opaque_sp->GetAddress().IsValid())
68        sb_addr.SetAddress(&m_opaque_sp->GetAddress());
69    return sb_addr;
70}
71
72const char *
73SBInstruction::GetMnemonic(SBTarget target)
74{
75    if (m_opaque_sp)
76    {
77        Mutex::Locker api_locker;
78        ExecutionContext exe_ctx;
79        TargetSP target_sp (target.GetSP());
80        if (target_sp)
81        {
82            api_locker.Lock (target_sp->GetAPIMutex());
83            target_sp->CalculateExecutionContext (exe_ctx);
84            exe_ctx.SetProcessSP(target_sp->GetProcessSP());
85        }
86        return m_opaque_sp->GetMnemonic(&exe_ctx);
87    }
88    return NULL;
89}
90
91const char *
92SBInstruction::GetOperands(SBTarget target)
93{
94    if (m_opaque_sp)
95    {
96        Mutex::Locker api_locker;
97        ExecutionContext exe_ctx;
98        TargetSP target_sp (target.GetSP());
99        if (target_sp)
100        {
101            api_locker.Lock (target_sp->GetAPIMutex());
102            target_sp->CalculateExecutionContext (exe_ctx);
103            exe_ctx.SetProcessSP(target_sp->GetProcessSP());
104        }
105        return m_opaque_sp->GetOperands(&exe_ctx);
106    }
107    return NULL;
108}
109
110const char *
111SBInstruction::GetComment(SBTarget target)
112{
113    if (m_opaque_sp)
114    {
115        Mutex::Locker api_locker;
116        ExecutionContext exe_ctx;
117        TargetSP target_sp (target.GetSP());
118        if (target_sp)
119        {
120            api_locker.Lock (target_sp->GetAPIMutex());
121            target_sp->CalculateExecutionContext (exe_ctx);
122            exe_ctx.SetProcessSP(target_sp->GetProcessSP());
123        }
124        return m_opaque_sp->GetComment(&exe_ctx);
125    }
126    return NULL;
127}
128
129size_t
130SBInstruction::GetByteSize ()
131{
132    if (m_opaque_sp)
133        return m_opaque_sp->GetOpcode().GetByteSize();
134    return 0;
135}
136
137SBData
138SBInstruction::GetData (SBTarget target)
139{
140    lldb::SBData sb_data;
141    if (m_opaque_sp)
142    {
143        DataExtractorSP data_extractor_sp (new DataExtractor());
144        if (m_opaque_sp->GetData (*data_extractor_sp))
145        {
146            sb_data.SetOpaque (data_extractor_sp);
147        }
148    }
149    return sb_data;
150}
151
152
153
154bool
155SBInstruction::DoesBranch ()
156{
157    if (m_opaque_sp)
158        return m_opaque_sp->DoesBranch ();
159    return false;
160}
161
162void
163SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp)
164{
165    m_opaque_sp = inst_sp;
166}
167
168bool
169SBInstruction::GetDescription (lldb::SBStream &s)
170{
171    if (m_opaque_sp)
172    {
173        // Use the "ref()" instead of the "get()" accessor in case the SBStream
174        // didn't have a stream already created, one will get created...
175        m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL);
176        return true;
177    }
178    return false;
179}
180
181void
182SBInstruction::Print (FILE *out)
183{
184    if (out == NULL)
185        return;
186
187    if (m_opaque_sp)
188    {
189        StreamFile out_stream (out, false);
190        m_opaque_sp->Dump (&out_stream, 0, true, false, NULL);
191    }
192}
193
194bool
195SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options)
196{
197    if (m_opaque_sp)
198    {
199        lldb::StackFrameSP frame_sp (frame.GetFrameSP());
200
201        if (frame_sp)
202        {
203            lldb_private::ExecutionContext exe_ctx;
204            frame_sp->CalculateExecutionContext (exe_ctx);
205            lldb_private::Target *target = exe_ctx.GetTargetPtr();
206            lldb_private::ArchSpec arch = target->GetArchitecture();
207
208            return m_opaque_sp->Emulate (arch,
209                                         evaluate_options,
210                                         (void *) frame_sp.get(),
211                                         &lldb_private::EmulateInstruction::ReadMemoryFrame,
212                                         &lldb_private::EmulateInstruction::WriteMemoryFrame,
213                                         &lldb_private::EmulateInstruction::ReadRegisterFrame,
214                                         &lldb_private::EmulateInstruction::WriteRegisterFrame);
215        }
216    }
217    return false;
218}
219
220bool
221SBInstruction::DumpEmulation (const char *triple)
222{
223    if (m_opaque_sp && triple)
224    {
225        lldb_private::ArchSpec arch (triple, NULL);
226
227        return m_opaque_sp->DumpEmulation (arch);
228
229    }
230    return false;
231}
232
233bool
234SBInstruction::TestEmulation (lldb::SBStream &output_stream,  const char *test_file)
235{
236    if (!m_opaque_sp.get())
237        m_opaque_sp.reset (new PseudoInstruction());
238
239    return m_opaque_sp->TestEmulation (output_stream.get(), test_file);
240}
241
242lldb::AddressClass
243SBInstruction::GetAddressClass ()
244{
245    if (m_opaque_sp.get())
246        return m_opaque_sp->GetAddressClass();
247    return eAddressClassInvalid;
248}
249