blob: 8b7deb7011be70bbe186759dd83a6db330607316 [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
Nitesh Jaindd125942017-05-04 11:34:42 +0000179bool SBInstruction::CanSetBreakpoint () {
180 lldb::InstructionSP inst_sp(GetOpaque());
181 if (inst_sp)
182 return inst_sp->CanSetBreakpoint();
183 return false;
184}
185
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186lldb::InstructionSP SBInstruction::GetOpaque() {
187 if (m_opaque_sp)
188 return m_opaque_sp->GetSP();
189 else
190 return lldb::InstructionSP();
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000191}
192
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp,
194 const lldb::InstructionSP &inst_sp) {
195 m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp));
Greg Clayton1d273162010-10-06 03:09:58 +0000196}
197
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198bool SBInstruction::GetDescription(lldb::SBStream &s) {
199 lldb::InstructionSP inst_sp(GetOpaque());
200 if (inst_sp) {
201 SymbolContext sc;
202 const Address &addr = inst_sp->GetAddress();
203 ModuleSP module_sp(addr.GetModule());
204 if (module_sp)
205 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
206 sc);
207 // Use the "ref()" instead of the "get()" accessor in case the SBStream
208 // didn't have a stream already created, one will get created...
209 FormatEntity::Entry format;
210 FormatEntity::Parse("${addr}: ", format);
211 inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0);
212 return true;
213 }
214 return false;
215}
216
217void SBInstruction::Print(FILE *out) {
218 if (out == NULL)
219 return;
220
221 lldb::InstructionSP inst_sp(GetOpaque());
222 if (inst_sp) {
223 SymbolContext sc;
224 const Address &addr = inst_sp->GetAddress();
225 ModuleSP module_sp(addr.GetModule());
226 if (module_sp)
227 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
228 sc);
229 StreamFile out_stream(out, false);
230 FormatEntity::Entry format;
231 FormatEntity::Parse("${addr}: ", format);
232 inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0);
233 }
234}
235
236bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame,
237 uint32_t evaluate_options) {
238 lldb::InstructionSP inst_sp(GetOpaque());
239 if (inst_sp) {
240 lldb::StackFrameSP frame_sp(frame.GetFrameSP());
241
242 if (frame_sp) {
243 lldb_private::ExecutionContext exe_ctx;
244 frame_sp->CalculateExecutionContext(exe_ctx);
245 lldb_private::Target *target = exe_ctx.GetTargetPtr();
246 lldb_private::ArchSpec arch = target->GetArchitecture();
247
248 return inst_sp->Emulate(
249 arch, evaluate_options, (void *)frame_sp.get(),
250 &lldb_private::EmulateInstruction::ReadMemoryFrame,
251 &lldb_private::EmulateInstruction::WriteMemoryFrame,
252 &lldb_private::EmulateInstruction::ReadRegisterFrame,
253 &lldb_private::EmulateInstruction::WriteRegisterFrame);
Greg Clayton1d273162010-10-06 03:09:58 +0000254 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255 }
256 return false;
Greg Clayton1d273162010-10-06 03:09:58 +0000257}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259bool SBInstruction::DumpEmulation(const char *triple) {
260 lldb::InstructionSP inst_sp(GetOpaque());
261 if (inst_sp && triple) {
262 lldb_private::ArchSpec arch(triple, NULL);
263 return inst_sp->DumpEmulation(arch);
264 }
265 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000266}
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000267
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268bool SBInstruction::TestEmulation(lldb::SBStream &output_stream,
269 const char *test_file) {
270 if (!m_opaque_sp)
271 SetOpaque(lldb::DisassemblerSP(),
272 lldb::InstructionSP(new PseudoInstruction()));
Greg Claytonb9556ac2012-01-30 07:41:31 +0000273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 lldb::InstructionSP inst_sp(GetOpaque());
275 if (inst_sp)
276 return inst_sp->TestEmulation(output_stream.get(), test_file);
277 return false;
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000278}
279
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280lldb::AddressClass SBInstruction::GetAddressClass() {
281 lldb::InstructionSP inst_sp(GetOpaque());
282 if (inst_sp)
283 return inst_sp->GetAddressClass();
284 return eAddressClassInvalid;
Greg Claytonc8e0c242012-04-13 00:07:34 +0000285}