blob: c47307c733a89e21ce267fcac2350a69623fd669 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Greg Clayton1d273162010-10-06 03:09:58 +000012#include "lldb/API/SBAddress.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000013#include "lldb/API/SBFrame.h"
Greg Clayton1d273162010-10-06 03:09:58 +000014#include "lldb/API/SBInstruction.h"
15#include "lldb/API/SBStream.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000016#include "lldb/API/SBTarget.h"
Greg Clayton1d273162010-10-06 03:09:58 +000017
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000018#include "lldb/Core/ArchSpec.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/Disassembler.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000020#include "lldb/Core/EmulateInstruction.h"
Jason Molendaaff1b352014-10-10 23:07:36 +000021#include "lldb/Core/Module.h"
Greg Clayton1d273162010-10-06 03:09:58 +000022#include "lldb/Core/StreamFile.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000023#include "lldb/Target/ExecutionContext.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000024#include "lldb/Target/StackFrame.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000025#include "lldb/Target/Target.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000026#include "lldb/Utility/DataBufferHeap.h"
27#include "lldb/Utility/DataExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000028
Greg Clayton4a9d83a2016-06-07 22:56:40 +000029//----------------------------------------------------------------------
30// We recently fixed a leak in one of the Instruction subclasses where
31// the instruction will only hold a weak reference to the disassembler
32// to avoid a cycle that was keeping both objects alive (leak) and we
33// need the InstructionImpl class to make sure our public API behaves
34// as users would expect. Calls in our public API allow clients to do
35// things like:
36//
37// 1 lldb::SBInstruction inst;
38// 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0)
39// 3 if (inst.DoesBranch())
40// 4 ...
41//
42// There was a temporary lldb::DisassemblerSP object created in the
43// SBInstructionList that was returned by lldb.target.ReadInstructions()
44// that will go away after line 2 but the "inst" object should be able
45// to still answer questions about itself. So we make sure that any
46// SBInstruction objects that are given out have a strong reference to
47// the disassembler and the instruction so that the object can live and
48// successfully respond to all queries.
49//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000050class InstructionImpl {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000051public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 InstructionImpl(const lldb::DisassemblerSP &disasm_sp,
53 const lldb::InstructionSP &inst_sp)
54 : m_disasm_sp(disasm_sp), m_inst_sp(inst_sp) {}
Greg Clayton4a9d83a2016-06-07 22:56:40 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 lldb::InstructionSP GetSP() const { return m_inst_sp; }
Greg Clayton4a9d83a2016-06-07 22:56:40 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 bool IsValid() const { return (bool)m_inst_sp; }
Greg Clayton4a9d83a2016-06-07 22:56:40 +000059
60protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid
62 lldb::InstructionSP m_inst_sp;
Greg Clayton4a9d83a2016-06-07 22:56:40 +000063};
64
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065using namespace lldb;
66using namespace lldb_private;
67
Kate Stoneb9c1b512016-09-06 20:57:50 +000068SBInstruction::SBInstruction() : m_opaque_sp() {}
69
70SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp,
71 const lldb::InstructionSP &inst_sp)
72 : m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) {}
73
74SBInstruction::SBInstruction(const SBInstruction &rhs)
75 : m_opaque_sp(rhs.m_opaque_sp) {}
76
77const SBInstruction &SBInstruction::operator=(const SBInstruction &rhs) {
78 if (this != &rhs)
79 m_opaque_sp = rhs.m_opaque_sp;
80 return *this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081}
82
Kate Stoneb9c1b512016-09-06 20:57:50 +000083SBInstruction::~SBInstruction() {}
84
85bool SBInstruction::IsValid() { return m_opaque_sp && m_opaque_sp->IsValid(); }
86
87SBAddress SBInstruction::GetAddress() {
88 SBAddress sb_addr;
89 lldb::InstructionSP inst_sp(GetOpaque());
90 if (inst_sp && inst_sp->GetAddress().IsValid())
91 sb_addr.SetAddress(&inst_sp->GetAddress());
92 return sb_addr;
Greg Clayton1d273162010-10-06 03:09:58 +000093}
94
Kate Stoneb9c1b512016-09-06 20:57:50 +000095const char *SBInstruction::GetMnemonic(SBTarget target) {
96 lldb::InstructionSP inst_sp(GetOpaque());
97 if (inst_sp) {
98 ExecutionContext exe_ctx;
99 TargetSP target_sp(target.GetSP());
100 std::unique_lock<std::recursive_mutex> lock;
101 if (target_sp) {
102 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Greg Claytonefabb122010-11-05 23:17:00 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 target_sp->CalculateExecutionContext(exe_ctx);
105 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000106 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 return inst_sp->GetMnemonic(&exe_ctx);
108 }
109 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000110}
111
Kate Stoneb9c1b512016-09-06 20:57:50 +0000112const char *SBInstruction::GetOperands(SBTarget target) {
113 lldb::InstructionSP inst_sp(GetOpaque());
114 if (inst_sp) {
115 ExecutionContext exe_ctx;
116 TargetSP target_sp(target.GetSP());
117 std::unique_lock<std::recursive_mutex> lock;
118 if (target_sp) {
119 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121 target_sp->CalculateExecutionContext(exe_ctx);
122 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000123 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124 return inst_sp->GetOperands(&exe_ctx);
125 }
126 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000127}
128
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129const char *SBInstruction::GetComment(SBTarget target) {
130 lldb::InstructionSP inst_sp(GetOpaque());
131 if (inst_sp) {
132 ExecutionContext exe_ctx;
133 TargetSP target_sp(target.GetSP());
134 std::unique_lock<std::recursive_mutex> lock;
135 if (target_sp) {
136 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000137
Kate Stoneb9c1b512016-09-06 20:57:50 +0000138 target_sp->CalculateExecutionContext(exe_ctx);
139 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000140 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 return inst_sp->GetComment(&exe_ctx);
142 }
143 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000144}
145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146size_t SBInstruction::GetByteSize() {
147 lldb::InstructionSP inst_sp(GetOpaque());
148 if (inst_sp)
149 return inst_sp->GetOpcode().GetByteSize();
150 return 0;
Greg Clayton1d273162010-10-06 03:09:58 +0000151}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152
Kate Stoneb9c1b512016-09-06 20:57:50 +0000153SBData SBInstruction::GetData(SBTarget target) {
154 lldb::SBData sb_data;
155 lldb::InstructionSP inst_sp(GetOpaque());
156 if (inst_sp) {
157 DataExtractorSP data_extractor_sp(new DataExtractor());
158 if (inst_sp->GetData(*data_extractor_sp)) {
159 sb_data.SetOpaque(data_extractor_sp);
Greg Clayton8f7180b2011-09-26 07:11:27 +0000160 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161 }
162 return sb_data;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000163}
164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165bool SBInstruction::DoesBranch() {
166 lldb::InstructionSP inst_sp(GetOpaque());
167 if (inst_sp)
168 return inst_sp->DoesBranch();
169 return false;
Greg Clayton1d273162010-10-06 03:09:58 +0000170}
171
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172bool SBInstruction::HasDelaySlot() {
173 lldb::InstructionSP inst_sp(GetOpaque());
174 if (inst_sp)
175 return inst_sp->HasDelaySlot();
176 return false;
Bhushan D. Attardedf5f0b42016-01-27 10:16:30 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179lldb::InstructionSP SBInstruction::GetOpaque() {
180 if (m_opaque_sp)
181 return m_opaque_sp->GetSP();
182 else
183 return lldb::InstructionSP();
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000184}
185
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp,
187 const lldb::InstructionSP &inst_sp) {
188 m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp));
Greg Clayton1d273162010-10-06 03:09:58 +0000189}
190
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191bool SBInstruction::GetDescription(lldb::SBStream &s) {
192 lldb::InstructionSP inst_sp(GetOpaque());
193 if (inst_sp) {
194 SymbolContext sc;
195 const Address &addr = inst_sp->GetAddress();
196 ModuleSP module_sp(addr.GetModule());
197 if (module_sp)
198 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
199 sc);
200 // Use the "ref()" instead of the "get()" accessor in case the SBStream
201 // didn't have a stream already created, one will get created...
202 FormatEntity::Entry format;
203 FormatEntity::Parse("${addr}: ", format);
204 inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0);
205 return true;
206 }
207 return false;
208}
209
210void SBInstruction::Print(FILE *out) {
211 if (out == NULL)
212 return;
213
214 lldb::InstructionSP inst_sp(GetOpaque());
215 if (inst_sp) {
216 SymbolContext sc;
217 const Address &addr = inst_sp->GetAddress();
218 ModuleSP module_sp(addr.GetModule());
219 if (module_sp)
220 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
221 sc);
222 StreamFile out_stream(out, false);
223 FormatEntity::Entry format;
224 FormatEntity::Parse("${addr}: ", format);
225 inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0);
226 }
227}
228
229bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame,
230 uint32_t evaluate_options) {
231 lldb::InstructionSP inst_sp(GetOpaque());
232 if (inst_sp) {
233 lldb::StackFrameSP frame_sp(frame.GetFrameSP());
234
235 if (frame_sp) {
236 lldb_private::ExecutionContext exe_ctx;
237 frame_sp->CalculateExecutionContext(exe_ctx);
238 lldb_private::Target *target = exe_ctx.GetTargetPtr();
239 lldb_private::ArchSpec arch = target->GetArchitecture();
240
241 return inst_sp->Emulate(
242 arch, evaluate_options, (void *)frame_sp.get(),
243 &lldb_private::EmulateInstruction::ReadMemoryFrame,
244 &lldb_private::EmulateInstruction::WriteMemoryFrame,
245 &lldb_private::EmulateInstruction::ReadRegisterFrame,
246 &lldb_private::EmulateInstruction::WriteRegisterFrame);
Greg Clayton1d273162010-10-06 03:09:58 +0000247 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000248 }
249 return false;
Greg Clayton1d273162010-10-06 03:09:58 +0000250}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000251
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252bool SBInstruction::DumpEmulation(const char *triple) {
253 lldb::InstructionSP inst_sp(GetOpaque());
254 if (inst_sp && triple) {
255 lldb_private::ArchSpec arch(triple, NULL);
256 return inst_sp->DumpEmulation(arch);
257 }
258 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259}
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000260
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261bool SBInstruction::TestEmulation(lldb::SBStream &output_stream,
262 const char *test_file) {
263 if (!m_opaque_sp)
264 SetOpaque(lldb::DisassemblerSP(),
265 lldb::InstructionSP(new PseudoInstruction()));
Greg Claytonb9556ac2012-01-30 07:41:31 +0000266
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 lldb::InstructionSP inst_sp(GetOpaque());
268 if (inst_sp)
269 return inst_sp->TestEmulation(output_stream.get(), test_file);
270 return false;
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000271}
272
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273lldb::AddressClass SBInstruction::GetAddressClass() {
274 lldb::InstructionSP inst_sp(GetOpaque());
275 if (inst_sp)
276 return inst_sp->GetAddressClass();
277 return eAddressClassInvalid;
Greg Claytonc8e0c242012-04-13 00:07:34 +0000278}