blob: 181ce362ea7323b3174a644d164c5396d6af1245 [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"
Pavel Labath7263f1b2017-10-31 10:56:03 +000023#include "lldb/Host/HostInfo.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000024#include "lldb/Target/ExecutionContext.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000025#include "lldb/Target/StackFrame.h"
Caroline Tice7c9dd3c2011-04-05 23:22:54 +000026#include "lldb/Target/Target.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000027#include "lldb/Utility/DataBufferHeap.h"
28#include "lldb/Utility/DataExtractor.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029
Greg Clayton4a9d83a2016-06-07 22:56:40 +000030//----------------------------------------------------------------------
31// We recently fixed a leak in one of the Instruction subclasses where
32// the instruction will only hold a weak reference to the disassembler
33// to avoid a cycle that was keeping both objects alive (leak) and we
34// need the InstructionImpl class to make sure our public API behaves
35// as users would expect. Calls in our public API allow clients to do
36// things like:
37//
38// 1 lldb::SBInstruction inst;
39// 2 inst = target.ReadInstructions(pc, 1).GetInstructionAtIndex(0)
40// 3 if (inst.DoesBranch())
41// 4 ...
42//
43// There was a temporary lldb::DisassemblerSP object created in the
44// SBInstructionList that was returned by lldb.target.ReadInstructions()
45// that will go away after line 2 but the "inst" object should be able
46// to still answer questions about itself. So we make sure that any
47// SBInstruction objects that are given out have a strong reference to
48// the disassembler and the instruction so that the object can live and
49// successfully respond to all queries.
50//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000051class InstructionImpl {
Greg Clayton4a9d83a2016-06-07 22:56:40 +000052public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 InstructionImpl(const lldb::DisassemblerSP &disasm_sp,
54 const lldb::InstructionSP &inst_sp)
55 : m_disasm_sp(disasm_sp), m_inst_sp(inst_sp) {}
Greg Clayton4a9d83a2016-06-07 22:56:40 +000056
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 lldb::InstructionSP GetSP() const { return m_inst_sp; }
Greg Clayton4a9d83a2016-06-07 22:56:40 +000058
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 bool IsValid() const { return (bool)m_inst_sp; }
Greg Clayton4a9d83a2016-06-07 22:56:40 +000060
61protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid
63 lldb::InstructionSP m_inst_sp;
Greg Clayton4a9d83a2016-06-07 22:56:40 +000064};
65
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066using namespace lldb;
67using namespace lldb_private;
68
Kate Stoneb9c1b512016-09-06 20:57:50 +000069SBInstruction::SBInstruction() : m_opaque_sp() {}
70
71SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp,
72 const lldb::InstructionSP &inst_sp)
73 : m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) {}
74
75SBInstruction::SBInstruction(const SBInstruction &rhs)
76 : m_opaque_sp(rhs.m_opaque_sp) {}
77
78const SBInstruction &SBInstruction::operator=(const SBInstruction &rhs) {
79 if (this != &rhs)
80 m_opaque_sp = rhs.m_opaque_sp;
81 return *this;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082}
83
Kate Stoneb9c1b512016-09-06 20:57:50 +000084SBInstruction::~SBInstruction() {}
85
86bool SBInstruction::IsValid() { return m_opaque_sp && m_opaque_sp->IsValid(); }
87
88SBAddress SBInstruction::GetAddress() {
89 SBAddress sb_addr;
90 lldb::InstructionSP inst_sp(GetOpaque());
91 if (inst_sp && inst_sp->GetAddress().IsValid())
92 sb_addr.SetAddress(&inst_sp->GetAddress());
93 return sb_addr;
Greg Clayton1d273162010-10-06 03:09:58 +000094}
95
Kate Stoneb9c1b512016-09-06 20:57:50 +000096const char *SBInstruction::GetMnemonic(SBTarget target) {
97 lldb::InstructionSP inst_sp(GetOpaque());
98 if (inst_sp) {
99 ExecutionContext exe_ctx;
100 TargetSP target_sp(target.GetSP());
101 std::unique_lock<std::recursive_mutex> lock;
102 if (target_sp) {
103 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Greg Claytonefabb122010-11-05 23:17:00 +0000104
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105 target_sp->CalculateExecutionContext(exe_ctx);
106 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000107 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000108 return inst_sp->GetMnemonic(&exe_ctx);
109 }
110 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000111}
112
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113const char *SBInstruction::GetOperands(SBTarget target) {
114 lldb::InstructionSP inst_sp(GetOpaque());
115 if (inst_sp) {
116 ExecutionContext exe_ctx;
117 TargetSP target_sp(target.GetSP());
118 std::unique_lock<std::recursive_mutex> lock;
119 if (target_sp) {
120 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000121
Kate Stoneb9c1b512016-09-06 20:57:50 +0000122 target_sp->CalculateExecutionContext(exe_ctx);
123 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000124 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000125 return inst_sp->GetOperands(&exe_ctx);
126 }
127 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000128}
129
Kate Stoneb9c1b512016-09-06 20:57:50 +0000130const char *SBInstruction::GetComment(SBTarget target) {
131 lldb::InstructionSP inst_sp(GetOpaque());
132 if (inst_sp) {
133 ExecutionContext exe_ctx;
134 TargetSP target_sp(target.GetSP());
135 std::unique_lock<std::recursive_mutex> lock;
136 if (target_sp) {
137 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
Saleem Abdulrasoolbb19a132016-05-19 05:13:57 +0000138
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 target_sp->CalculateExecutionContext(exe_ctx);
140 exe_ctx.SetProcessSP(target_sp->GetProcessSP());
Greg Clayton8f7180b2011-09-26 07:11:27 +0000141 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 return inst_sp->GetComment(&exe_ctx);
143 }
144 return NULL;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000145}
146
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147size_t SBInstruction::GetByteSize() {
148 lldb::InstructionSP inst_sp(GetOpaque());
149 if (inst_sp)
150 return inst_sp->GetOpcode().GetByteSize();
151 return 0;
Greg Clayton1d273162010-10-06 03:09:58 +0000152}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154SBData SBInstruction::GetData(SBTarget target) {
155 lldb::SBData sb_data;
156 lldb::InstructionSP inst_sp(GetOpaque());
157 if (inst_sp) {
158 DataExtractorSP data_extractor_sp(new DataExtractor());
159 if (inst_sp->GetData(*data_extractor_sp)) {
160 sb_data.SetOpaque(data_extractor_sp);
Greg Clayton8f7180b2011-09-26 07:11:27 +0000161 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 }
163 return sb_data;
Greg Clayton8f7180b2011-09-26 07:11:27 +0000164}
165
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166bool SBInstruction::DoesBranch() {
167 lldb::InstructionSP inst_sp(GetOpaque());
168 if (inst_sp)
169 return inst_sp->DoesBranch();
170 return false;
Greg Clayton1d273162010-10-06 03:09:58 +0000171}
172
Kate Stoneb9c1b512016-09-06 20:57:50 +0000173bool SBInstruction::HasDelaySlot() {
174 lldb::InstructionSP inst_sp(GetOpaque());
175 if (inst_sp)
176 return inst_sp->HasDelaySlot();
177 return false;
Bhushan D. Attardedf5f0b42016-01-27 10:16:30 +0000178}
179
Nitesh Jaindd125942017-05-04 11:34:42 +0000180bool SBInstruction::CanSetBreakpoint () {
181 lldb::InstructionSP inst_sp(GetOpaque());
182 if (inst_sp)
183 return inst_sp->CanSetBreakpoint();
184 return false;
185}
186
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187lldb::InstructionSP SBInstruction::GetOpaque() {
188 if (m_opaque_sp)
189 return m_opaque_sp->GetSP();
190 else
191 return lldb::InstructionSP();
Greg Clayton4a9d83a2016-06-07 22:56:40 +0000192}
193
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp,
195 const lldb::InstructionSP &inst_sp) {
196 m_opaque_sp.reset(new InstructionImpl(disasm_sp, inst_sp));
Greg Clayton1d273162010-10-06 03:09:58 +0000197}
198
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199bool SBInstruction::GetDescription(lldb::SBStream &s) {
200 lldb::InstructionSP inst_sp(GetOpaque());
201 if (inst_sp) {
202 SymbolContext sc;
203 const Address &addr = inst_sp->GetAddress();
204 ModuleSP module_sp(addr.GetModule());
205 if (module_sp)
206 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
207 sc);
208 // Use the "ref()" instead of the "get()" accessor in case the SBStream
209 // didn't have a stream already created, one will get created...
210 FormatEntity::Entry format;
211 FormatEntity::Parse("${addr}: ", format);
212 inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0);
213 return true;
214 }
215 return false;
216}
217
218void SBInstruction::Print(FILE *out) {
219 if (out == NULL)
220 return;
221
222 lldb::InstructionSP inst_sp(GetOpaque());
223 if (inst_sp) {
224 SymbolContext sc;
225 const Address &addr = inst_sp->GetAddress();
226 ModuleSP module_sp(addr.GetModule());
227 if (module_sp)
228 module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
229 sc);
230 StreamFile out_stream(out, false);
231 FormatEntity::Entry format;
232 FormatEntity::Parse("${addr}: ", format);
233 inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0);
234 }
235}
236
237bool SBInstruction::EmulateWithFrame(lldb::SBFrame &frame,
238 uint32_t evaluate_options) {
239 lldb::InstructionSP inst_sp(GetOpaque());
240 if (inst_sp) {
241 lldb::StackFrameSP frame_sp(frame.GetFrameSP());
242
243 if (frame_sp) {
244 lldb_private::ExecutionContext exe_ctx;
245 frame_sp->CalculateExecutionContext(exe_ctx);
246 lldb_private::Target *target = exe_ctx.GetTargetPtr();
247 lldb_private::ArchSpec arch = target->GetArchitecture();
248
249 return inst_sp->Emulate(
250 arch, evaluate_options, (void *)frame_sp.get(),
251 &lldb_private::EmulateInstruction::ReadMemoryFrame,
252 &lldb_private::EmulateInstruction::WriteMemoryFrame,
253 &lldb_private::EmulateInstruction::ReadRegisterFrame,
254 &lldb_private::EmulateInstruction::WriteRegisterFrame);
Greg Clayton1d273162010-10-06 03:09:58 +0000255 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 }
257 return false;
Greg Clayton1d273162010-10-06 03:09:58 +0000258}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260bool SBInstruction::DumpEmulation(const char *triple) {
261 lldb::InstructionSP inst_sp(GetOpaque());
262 if (inst_sp && triple) {
Pavel Labath7263f1b2017-10-31 10:56:03 +0000263 return inst_sp->DumpEmulation(HostInfo::GetAugmentedArchSpec(triple));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 }
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}