1cfca06d7SDimitry Andric //===-- SBInstruction.cpp -------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
9f034231aSEd Maste #include "lldb/API/SBInstruction.h"
106f8fc217SDimitry Andric #include "lldb/Utility/Instrumentation.h"
11f034231aSEd Maste
12f034231aSEd Maste #include "lldb/API/SBAddress.h"
13f034231aSEd Maste #include "lldb/API/SBFrame.h"
14ead24645SDimitry Andric #include "lldb/API/SBFile.h"
155f29bb8aSDimitry Andric
16f034231aSEd Maste #include "lldb/API/SBInstruction.h"
17f034231aSEd Maste #include "lldb/API/SBStream.h"
18f034231aSEd Maste #include "lldb/API/SBTarget.h"
19f034231aSEd Maste #include "lldb/Core/Disassembler.h"
20f034231aSEd Maste #include "lldb/Core/EmulateInstruction.h"
21205afe67SEd Maste #include "lldb/Core/Module.h"
22ef5d0b5eSDimitry Andric #include "lldb/Host/HostInfo.h"
23b1c73532SDimitry Andric #include "lldb/Host/StreamFile.h"
24f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
25f034231aSEd Maste #include "lldb/Target/StackFrame.h"
26f034231aSEd Maste #include "lldb/Target/Target.h"
27ef5d0b5eSDimitry Andric #include "lldb/Utility/ArchSpec.h"
2874a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
2974a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
30f034231aSEd Maste
315f29bb8aSDimitry Andric #include <memory>
325f29bb8aSDimitry Andric
33f73363f1SDimitry Andric // We recently fixed a leak in one of the Instruction subclasses where the
34f73363f1SDimitry Andric // instruction will only hold a weak reference to the disassembler to avoid a
35f73363f1SDimitry Andric // cycle that was keeping both objects alive (leak) and we need the
36f73363f1SDimitry Andric // InstructionImpl class to make sure our public API behaves as users would
37f73363f1SDimitry Andric // expect. Calls in our public API allow clients to do things like:
38f3fbd1c0SDimitry Andric //
39f3fbd1c0SDimitry Andric // 1 lldb::SBInstruction inst;
40f3fbd1c0SDimitry Andric // 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0)
41f3fbd1c0SDimitry Andric // 3 if (inst.DoesBranch())
42f3fbd1c0SDimitry Andric // 4 ...
43f3fbd1c0SDimitry Andric //
44f3fbd1c0SDimitry Andric // There was a temporary lldb::DisassemblerSP object created in the
45f73363f1SDimitry Andric // SBInstructionList that was returned by lldb.target.ReadInstructions() that
46f73363f1SDimitry Andric // will go away after line 2 but the "inst" object should be able to still
47f73363f1SDimitry Andric // answer questions about itself. So we make sure that any SBInstruction
48f73363f1SDimitry Andric // objects that are given out have a strong reference to the disassembler and
49f73363f1SDimitry Andric // the instruction so that the object can live and successfully respond to all
50f73363f1SDimitry Andric // queries.
5114f1b3e8SDimitry Andric class InstructionImpl {
52f3fbd1c0SDimitry Andric public:
InstructionImpl(const lldb::DisassemblerSP & disasm_sp,const lldb::InstructionSP & inst_sp)5314f1b3e8SDimitry Andric InstructionImpl(const lldb::DisassemblerSP &disasm_sp,
5414f1b3e8SDimitry Andric const lldb::InstructionSP &inst_sp)
5514f1b3e8SDimitry Andric : m_disasm_sp(disasm_sp), m_inst_sp(inst_sp) {}
56f034231aSEd Maste
GetSP() const5714f1b3e8SDimitry Andric lldb::InstructionSP GetSP() const { return m_inst_sp; }
58f3fbd1c0SDimitry Andric
IsValid() const5914f1b3e8SDimitry Andric bool IsValid() const { return (bool)m_inst_sp; }
60f3fbd1c0SDimitry Andric
61f3fbd1c0SDimitry Andric protected:
62f3fbd1c0SDimitry Andric lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid
63f3fbd1c0SDimitry Andric lldb::InstructionSP m_inst_sp;
64f3fbd1c0SDimitry Andric };
65f3fbd1c0SDimitry Andric
66f3fbd1c0SDimitry Andric using namespace lldb;
67f3fbd1c0SDimitry Andric using namespace lldb_private;
68f3fbd1c0SDimitry Andric
SBInstruction()696f8fc217SDimitry Andric SBInstruction::SBInstruction() { LLDB_INSTRUMENT_VA(this); }
70f3fbd1c0SDimitry Andric
SBInstruction(const lldb::DisassemblerSP & disasm_sp,const lldb::InstructionSP & inst_sp)7114f1b3e8SDimitry Andric SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp,
7214f1b3e8SDimitry Andric const lldb::InstructionSP &inst_sp)
7314f1b3e8SDimitry Andric : m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) {}
74f034231aSEd Maste
SBInstruction(const SBInstruction & rhs)7514f1b3e8SDimitry Andric SBInstruction::SBInstruction(const SBInstruction &rhs)
765f29bb8aSDimitry Andric : m_opaque_sp(rhs.m_opaque_sp) {
776f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
785f29bb8aSDimitry Andric }
79f034231aSEd Maste
operator =(const SBInstruction & rhs)8014f1b3e8SDimitry Andric const SBInstruction &SBInstruction::operator=(const SBInstruction &rhs) {
816f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, rhs);
825f29bb8aSDimitry Andric
83f034231aSEd Maste if (this != &rhs)
84f034231aSEd Maste m_opaque_sp = rhs.m_opaque_sp;
856f8fc217SDimitry Andric return *this;
86f034231aSEd Maste }
87f034231aSEd Maste
88cfca06d7SDimitry Andric SBInstruction::~SBInstruction() = default;
89f034231aSEd Maste
IsValid()905f29bb8aSDimitry Andric bool SBInstruction::IsValid() {
916f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
925f29bb8aSDimitry Andric return this->operator bool();
935f29bb8aSDimitry Andric }
operator bool() const945f29bb8aSDimitry Andric SBInstruction::operator bool() const {
956f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
965f29bb8aSDimitry Andric
975f29bb8aSDimitry Andric return m_opaque_sp && m_opaque_sp->IsValid();
985f29bb8aSDimitry Andric }
99f034231aSEd Maste
GetAddress()10014f1b3e8SDimitry Andric SBAddress SBInstruction::GetAddress() {
1016f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1025f29bb8aSDimitry Andric
103f034231aSEd Maste SBAddress sb_addr;
104f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
105f3fbd1c0SDimitry Andric if (inst_sp && inst_sp->GetAddress().IsValid())
106b60736ecSDimitry Andric sb_addr.SetAddress(inst_sp->GetAddress());
1076f8fc217SDimitry Andric return sb_addr;
108f034231aSEd Maste }
109f034231aSEd Maste
GetMnemonic(SBTarget target)11014f1b3e8SDimitry Andric const char *SBInstruction::GetMnemonic(SBTarget target) {
1116f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target);
1125f29bb8aSDimitry Andric
113f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
1147fa27ce4SDimitry Andric if (!inst_sp)
1157fa27ce4SDimitry Andric return nullptr;
1167fa27ce4SDimitry Andric
117f034231aSEd Maste ExecutionContext exe_ctx;
118f034231aSEd Maste TargetSP target_sp(target.GetSP());
119f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
12014f1b3e8SDimitry Andric if (target_sp) {
121f3fbd1c0SDimitry Andric lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
122f3fbd1c0SDimitry Andric
123f034231aSEd Maste target_sp->CalculateExecutionContext(exe_ctx);
124f034231aSEd Maste exe_ctx.SetProcessSP(target_sp->GetProcessSP());
125f034231aSEd Maste }
1267fa27ce4SDimitry Andric return ConstString(inst_sp->GetMnemonic(&exe_ctx)).GetCString();
127f034231aSEd Maste }
128f034231aSEd Maste
GetOperands(SBTarget target)12914f1b3e8SDimitry Andric const char *SBInstruction::GetOperands(SBTarget target) {
1306f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target);
1315f29bb8aSDimitry Andric
132f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
1337fa27ce4SDimitry Andric if (!inst_sp)
1347fa27ce4SDimitry Andric return nullptr;
1357fa27ce4SDimitry Andric
136f034231aSEd Maste ExecutionContext exe_ctx;
137f034231aSEd Maste TargetSP target_sp(target.GetSP());
138f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
13914f1b3e8SDimitry Andric if (target_sp) {
140f3fbd1c0SDimitry Andric lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
141f3fbd1c0SDimitry Andric
142f034231aSEd Maste target_sp->CalculateExecutionContext(exe_ctx);
143f034231aSEd Maste exe_ctx.SetProcessSP(target_sp->GetProcessSP());
144f034231aSEd Maste }
1457fa27ce4SDimitry Andric return ConstString(inst_sp->GetOperands(&exe_ctx)).GetCString();
146f034231aSEd Maste }
147f034231aSEd Maste
GetComment(SBTarget target)14814f1b3e8SDimitry Andric const char *SBInstruction::GetComment(SBTarget target) {
1496f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target);
1505f29bb8aSDimitry Andric
151f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
1527fa27ce4SDimitry Andric if (!inst_sp)
1537fa27ce4SDimitry Andric return nullptr;
1547fa27ce4SDimitry Andric
155f034231aSEd Maste ExecutionContext exe_ctx;
156f034231aSEd Maste TargetSP target_sp(target.GetSP());
157f3fbd1c0SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
15814f1b3e8SDimitry Andric if (target_sp) {
159f3fbd1c0SDimitry Andric lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
160f3fbd1c0SDimitry Andric
161f034231aSEd Maste target_sp->CalculateExecutionContext(exe_ctx);
162f034231aSEd Maste exe_ctx.SetProcessSP(target_sp->GetProcessSP());
163f034231aSEd Maste }
1647fa27ce4SDimitry Andric return ConstString(inst_sp->GetComment(&exe_ctx)).GetCString();
165f034231aSEd Maste }
166f034231aSEd Maste
GetControlFlowKind(lldb::SBTarget target)167e3b55780SDimitry Andric lldb::InstructionControlFlowKind SBInstruction::GetControlFlowKind(lldb::SBTarget target) {
168e3b55780SDimitry Andric LLDB_INSTRUMENT_VA(this, target);
169e3b55780SDimitry Andric
170e3b55780SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
171e3b55780SDimitry Andric if (inst_sp) {
172e3b55780SDimitry Andric ExecutionContext exe_ctx;
173e3b55780SDimitry Andric TargetSP target_sp(target.GetSP());
174e3b55780SDimitry Andric std::unique_lock<std::recursive_mutex> lock;
175e3b55780SDimitry Andric if (target_sp) {
176e3b55780SDimitry Andric lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
177e3b55780SDimitry Andric
178e3b55780SDimitry Andric target_sp->CalculateExecutionContext(exe_ctx);
179e3b55780SDimitry Andric exe_ctx.SetProcessSP(target_sp->GetProcessSP());
180e3b55780SDimitry Andric }
181e3b55780SDimitry Andric return inst_sp->GetControlFlowKind(&exe_ctx);
182e3b55780SDimitry Andric }
183e3b55780SDimitry Andric return lldb::eInstructionControlFlowKindUnknown;
184e3b55780SDimitry Andric }
185e3b55780SDimitry Andric
GetByteSize()18614f1b3e8SDimitry Andric size_t SBInstruction::GetByteSize() {
1876f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
1885f29bb8aSDimitry Andric
189f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
190f3fbd1c0SDimitry Andric if (inst_sp)
191f3fbd1c0SDimitry Andric return inst_sp->GetOpcode().GetByteSize();
192f034231aSEd Maste return 0;
193f034231aSEd Maste }
194f034231aSEd Maste
GetData(SBTarget target)19514f1b3e8SDimitry Andric SBData SBInstruction::GetData(SBTarget target) {
1966f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, target);
1975f29bb8aSDimitry Andric
198f034231aSEd Maste lldb::SBData sb_data;
199f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
20014f1b3e8SDimitry Andric if (inst_sp) {
201f034231aSEd Maste DataExtractorSP data_extractor_sp(new DataExtractor());
20214f1b3e8SDimitry Andric if (inst_sp->GetData(*data_extractor_sp)) {
203f034231aSEd Maste sb_data.SetOpaque(data_extractor_sp);
204f034231aSEd Maste }
205f034231aSEd Maste }
2066f8fc217SDimitry Andric return sb_data;
207f034231aSEd Maste }
208f034231aSEd Maste
DoesBranch()20914f1b3e8SDimitry Andric bool SBInstruction::DoesBranch() {
2106f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
2115f29bb8aSDimitry Andric
212f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
213f3fbd1c0SDimitry Andric if (inst_sp)
214f3fbd1c0SDimitry Andric return inst_sp->DoesBranch();
215f034231aSEd Maste return false;
216f034231aSEd Maste }
217f034231aSEd Maste
HasDelaySlot()21814f1b3e8SDimitry Andric bool SBInstruction::HasDelaySlot() {
2196f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
2205f29bb8aSDimitry Andric
221f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
222f3fbd1c0SDimitry Andric if (inst_sp)
223f3fbd1c0SDimitry Andric return inst_sp->HasDelaySlot();
2242fc5d2d1SDimitry Andric return false;
2252fc5d2d1SDimitry Andric }
2262fc5d2d1SDimitry Andric
CanSetBreakpoint()2278b4000f1SDimitry Andric bool SBInstruction::CanSetBreakpoint() {
2286f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this);
2295f29bb8aSDimitry Andric
2308b4000f1SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
2318b4000f1SDimitry Andric if (inst_sp)
2328b4000f1SDimitry Andric return inst_sp->CanSetBreakpoint();
2338b4000f1SDimitry Andric return false;
2348b4000f1SDimitry Andric }
2358b4000f1SDimitry Andric
GetOpaque()23614f1b3e8SDimitry Andric lldb::InstructionSP SBInstruction::GetOpaque() {
237f3fbd1c0SDimitry Andric if (m_opaque_sp)
238f3fbd1c0SDimitry Andric return m_opaque_sp->GetSP();
239f3fbd1c0SDimitry Andric else
240f3fbd1c0SDimitry Andric return lldb::InstructionSP();
241f3fbd1c0SDimitry Andric }
242f3fbd1c0SDimitry Andric
SetOpaque(const lldb::DisassemblerSP & disasm_sp,const lldb::InstructionSP & inst_sp)24314f1b3e8SDimitry Andric void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp,
24414f1b3e8SDimitry Andric const lldb::InstructionSP &inst_sp) {
2455f29bb8aSDimitry Andric m_opaque_sp = std::make_shared<InstructionImpl>(disasm_sp, inst_sp);
246f034231aSEd Maste }
247f034231aSEd Maste
GetDescription(lldb::SBStream & s)24814f1b3e8SDimitry Andric bool SBInstruction::GetDescription(lldb::SBStream &s) {
2496f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, s);
2505f29bb8aSDimitry Andric
251f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
25214f1b3e8SDimitry Andric if (inst_sp) {
253205afe67SEd Maste SymbolContext sc;
254f3fbd1c0SDimitry Andric const Address &addr = inst_sp->GetAddress();
255205afe67SEd Maste ModuleSP module_sp(addr.GetModule());
256205afe67SEd Maste if (module_sp)
25714f1b3e8SDimitry Andric module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
25814f1b3e8SDimitry Andric sc);
259f034231aSEd Maste // Use the "ref()" instead of the "get()" accessor in case the SBStream
260f034231aSEd Maste // didn't have a stream already created, one will get created...
26112bd4897SEd Maste FormatEntity::Entry format;
26212bd4897SEd Maste FormatEntity::Parse("${addr}: ", format);
2631f917f69SDimitry Andric inst_sp->Dump(&s.ref(), 0, true, false, /*show_control_flow_kind=*/false,
2641f917f69SDimitry Andric nullptr, &sc, nullptr, &format, 0);
265f034231aSEd Maste return true;
266f034231aSEd Maste }
267f034231aSEd Maste return false;
268f034231aSEd Maste }
269f034231aSEd Maste
Print(FILE * outp)270ead24645SDimitry Andric void SBInstruction::Print(FILE *outp) {
2716f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, outp);
272ead24645SDimitry Andric FileSP out = std::make_shared<NativeFile>(outp, /*take_ownership=*/false);
273ead24645SDimitry Andric Print(out);
274ead24645SDimitry Andric }
2755f29bb8aSDimitry Andric
Print(SBFile out)276ead24645SDimitry Andric void SBInstruction::Print(SBFile out) {
2776f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, out);
278ead24645SDimitry Andric Print(out.m_opaque_sp);
279ead24645SDimitry Andric }
280ead24645SDimitry Andric
Print(FileSP out_sp)281ead24645SDimitry Andric void SBInstruction::Print(FileSP out_sp) {
2826f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, out_sp);
283ead24645SDimitry Andric
284ead24645SDimitry Andric if (!out_sp || !out_sp->IsValid())
285f034231aSEd Maste return;
286f034231aSEd Maste
287f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
28814f1b3e8SDimitry Andric if (inst_sp) {
289205afe67SEd Maste SymbolContext sc;
290f3fbd1c0SDimitry Andric const Address &addr = inst_sp->GetAddress();
291205afe67SEd Maste ModuleSP module_sp(addr.GetModule());
292205afe67SEd Maste if (module_sp)
29314f1b3e8SDimitry Andric module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
29414f1b3e8SDimitry Andric sc);
295ead24645SDimitry Andric StreamFile out_stream(out_sp);
29612bd4897SEd Maste FormatEntity::Entry format;
29712bd4897SEd Maste FormatEntity::Parse("${addr}: ", format);
2981f917f69SDimitry Andric inst_sp->Dump(&out_stream, 0, true, false, /*show_control_flow_kind=*/false,
2991f917f69SDimitry Andric nullptr, &sc, nullptr, &format, 0);
300f034231aSEd Maste }
301f034231aSEd Maste }
302f034231aSEd Maste
EmulateWithFrame(lldb::SBFrame & frame,uint32_t evaluate_options)30314f1b3e8SDimitry Andric bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame,
30414f1b3e8SDimitry Andric uint32_t evaluate_options) {
3056f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, frame, evaluate_options);
3065f29bb8aSDimitry Andric
307f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
30814f1b3e8SDimitry Andric if (inst_sp) {
309f034231aSEd Maste lldb::StackFrameSP frame_sp(frame.GetFrameSP());
310f034231aSEd Maste
31114f1b3e8SDimitry Andric if (frame_sp) {
312f034231aSEd Maste lldb_private::ExecutionContext exe_ctx;
313f034231aSEd Maste frame_sp->CalculateExecutionContext(exe_ctx);
314f034231aSEd Maste lldb_private::Target *target = exe_ctx.GetTargetPtr();
315f034231aSEd Maste lldb_private::ArchSpec arch = target->GetArchitecture();
316f034231aSEd Maste
31714f1b3e8SDimitry Andric return inst_sp->Emulate(
31814f1b3e8SDimitry Andric arch, evaluate_options, (void *)frame_sp.get(),
319f034231aSEd Maste &lldb_private::EmulateInstruction::ReadMemoryFrame,
320f034231aSEd Maste &lldb_private::EmulateInstruction::WriteMemoryFrame,
321f034231aSEd Maste &lldb_private::EmulateInstruction::ReadRegisterFrame,
322f034231aSEd Maste &lldb_private::EmulateInstruction::WriteRegisterFrame);
323f034231aSEd Maste }
324f034231aSEd Maste }
325f034231aSEd Maste return false;
326f034231aSEd Maste }
327f034231aSEd Maste
DumpEmulation(const char * triple)32814f1b3e8SDimitry Andric bool SBInstruction::DumpEmulation(const char *triple) {
3296f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, triple);
3305f29bb8aSDimitry Andric
331f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
33214f1b3e8SDimitry Andric if (inst_sp && triple) {
333ef5d0b5eSDimitry Andric return inst_sp->DumpEmulation(HostInfo::GetAugmentedArchSpec(triple));
334f034231aSEd Maste }
335f034231aSEd Maste return false;
336f034231aSEd Maste }
337f034231aSEd Maste
TestEmulation(lldb::SBStream & output_stream,const char * test_file)33814f1b3e8SDimitry Andric bool SBInstruction::TestEmulation(lldb::SBStream &output_stream,
33914f1b3e8SDimitry Andric const char *test_file) {
3406f8fc217SDimitry Andric LLDB_INSTRUMENT_VA(this, output_stream, test_file);
3415f29bb8aSDimitry Andric
342f3fbd1c0SDimitry Andric if (!m_opaque_sp)
34314f1b3e8SDimitry Andric SetOpaque(lldb::DisassemblerSP(),
34414f1b3e8SDimitry Andric lldb::InstructionSP(new PseudoInstruction()));
345f034231aSEd Maste
346f3fbd1c0SDimitry Andric lldb::InstructionSP inst_sp(GetOpaque());
347f3fbd1c0SDimitry Andric if (inst_sp)
3487fa27ce4SDimitry Andric return inst_sp->TestEmulation(output_stream.ref(), test_file);
349f3fbd1c0SDimitry Andric return false;
350f034231aSEd Maste }
351