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