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 void
164 SBInstruction::SetOpaque (const lldb::InstructionSP &inst_sp)
165 {
166     m_opaque_sp = inst_sp;
167 }
168 
169 bool
170 SBInstruction::GetDescription (lldb::SBStream &s)
171 {
172     if (m_opaque_sp)
173     {
174         SymbolContext sc;
175         const Address &addr = m_opaque_sp->GetAddress();
176         ModuleSP module_sp (addr.GetModule());
177         if (module_sp)
178             module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
179         // Use the "ref()" instead of the "get()" accessor in case the SBStream
180         // didn't have a stream already created, one will get created...
181         FormatEntity::Entry format;
182         FormatEntity::Parse("${addr}: ", format);
183         m_opaque_sp->Dump (&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0);
184         return true;
185     }
186     return false;
187 }
188 
189 void
190 SBInstruction::Print (FILE *out)
191 {
192     if (out == NULL)
193         return;
194 
195     if (m_opaque_sp)
196     {
197         SymbolContext sc;
198         const Address &addr = m_opaque_sp->GetAddress();
199         ModuleSP module_sp (addr.GetModule());
200         if (module_sp)
201             module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
202         StreamFile out_stream (out, false);
203         FormatEntity::Entry format;
204         FormatEntity::Parse("${addr}: ", format);
205         m_opaque_sp->Dump (&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0);
206     }
207 }
208 
209 bool
210 SBInstruction::EmulateWithFrame (lldb::SBFrame &frame, uint32_t evaluate_options)
211 {
212     if (m_opaque_sp)
213     {
214         lldb::StackFrameSP frame_sp (frame.GetFrameSP());
215 
216         if (frame_sp)
217         {
218             lldb_private::ExecutionContext exe_ctx;
219             frame_sp->CalculateExecutionContext (exe_ctx);
220             lldb_private::Target *target = exe_ctx.GetTargetPtr();
221             lldb_private::ArchSpec arch = target->GetArchitecture();
222 
223             return m_opaque_sp->Emulate (arch,
224                                          evaluate_options,
225                                          (void *) frame_sp.get(),
226                                          &lldb_private::EmulateInstruction::ReadMemoryFrame,
227                                          &lldb_private::EmulateInstruction::WriteMemoryFrame,
228                                          &lldb_private::EmulateInstruction::ReadRegisterFrame,
229                                          &lldb_private::EmulateInstruction::WriteRegisterFrame);
230         }
231     }
232     return false;
233 }
234 
235 bool
236 SBInstruction::DumpEmulation (const char *triple)
237 {
238     if (m_opaque_sp && triple)
239     {
240         lldb_private::ArchSpec arch (triple, NULL);
241 
242         return m_opaque_sp->DumpEmulation (arch);
243 
244     }
245     return false;
246 }
247 
248 bool
249 SBInstruction::TestEmulation (lldb::SBStream &output_stream,  const char *test_file)
250 {
251     if (!m_opaque_sp.get())
252         m_opaque_sp.reset (new PseudoInstruction());
253 
254     return m_opaque_sp->TestEmulation (output_stream.get(), test_file);
255 }
256 
257 lldb::AddressClass
258 SBInstruction::GetAddressClass ()
259 {
260     if (m_opaque_sp.get())
261         return m_opaque_sp->GetAddressClass();
262     return eAddressClassInvalid;
263 }
264