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 
28 using namespace lldb;
29 using namespace lldb_private;
30 
SBInstruction()31 SBInstruction::SBInstruction ()
32 {
33 }
34 
SBInstruction(const lldb::InstructionSP & inst_sp)35 SBInstruction::SBInstruction (const lldb::InstructionSP& inst_sp) :
36     m_opaque_sp (inst_sp)
37 {
38 }
39 
SBInstruction(const SBInstruction & rhs)40 SBInstruction::SBInstruction(const SBInstruction &rhs) :
41     m_opaque_sp (rhs.m_opaque_sp)
42 {
43 }
44 
45 const SBInstruction &
operator =(const SBInstruction & rhs)46 SBInstruction::operator = (const SBInstruction &rhs)
47 {
48     if (this != &rhs)
49         m_opaque_sp = rhs.m_opaque_sp;
50     return *this;
51 }
52 
~SBInstruction()53 SBInstruction::~SBInstruction ()
54 {
55 }
56 
57 bool
IsValid()58 SBInstruction::IsValid()
59 {
60     return (m_opaque_sp.get() != NULL);
61 }
62 
63 SBAddress
GetAddress()64 SBInstruction::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 
72 const char *
GetMnemonic(SBTarget target)73 SBInstruction::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 
91 const char *
GetOperands(SBTarget target)92 SBInstruction::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 
110 const char *
GetComment(SBTarget target)111 SBInstruction::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 
129 size_t
GetByteSize()130 SBInstruction::GetByteSize ()
131 {
132     if (m_opaque_sp)
133         return m_opaque_sp->GetOpcode().GetByteSize();
134     return 0;
135 }
136 
137 SBData
GetData(SBTarget target)138 SBInstruction::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 
154 bool
DoesBranch()155 SBInstruction::DoesBranch ()
156 {
157     if (m_opaque_sp)
158         return m_opaque_sp->DoesBranch ();
159     return false;
160 }
161 
162 void
SetOpaque(const lldb::InstructionSP & inst_sp)163 SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp)
164 {
165     m_opaque_sp = inst_sp;
166 }
167 
168 bool
GetDescription(lldb::SBStream & s)169 SBInstruction::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 
181 void
Print(FILE * out)182 SBInstruction::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 
194 bool
EmulateWithFrame(lldb::SBFrame & frame,uint32_t evaluate_options)195 SBInstruction::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 
220 bool
DumpEmulation(const char * triple)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
TestEmulation(lldb::SBStream & output_stream,const char * test_file)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 
242 lldb::AddressClass
GetAddressClass()243 SBInstruction::GetAddressClass ()
244 {
245     if (m_opaque_sp.get())
246         return m_opaque_sp->GetAddressClass();
247     return eAddressClassInvalid;
248 }
249