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