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