LLDB  mainline
SBInstruction.cpp
Go to the documentation of this file.
1 //===-- SBInstruction.cpp ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "SBReproducerPrivate.h"
11 
12 #include "lldb/API/SBAddress.h"
13 #include "lldb/API/SBFrame.h"
14 
15 #include "lldb/API/SBInstruction.h"
16 #include "lldb/API/SBStream.h"
17 #include "lldb/API/SBTarget.h"
18 #include "lldb/Core/Disassembler.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/StreamFile.h"
22 #include "lldb/Host/HostInfo.h"
24 #include "lldb/Target/StackFrame.h"
25 #include "lldb/Target/Target.h"
26 #include "lldb/Utility/ArchSpec.h"
29 
30 #include <memory>
31 
32 // We recently fixed a leak in one of the Instruction subclasses where the
33 // instruction will only hold a weak reference to the disassembler to avoid a
34 // cycle that was keeping both objects alive (leak) and we need the
35 // InstructionImpl class to make sure our public API behaves as users would
36 // expect. Calls in our public API allow clients to do 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() that
45 // will go away after line 2 but the "inst" object should be able to still
46 // answer questions about itself. So we make sure that any SBInstruction
47 // objects that are given out have a strong reference to the disassembler and
48 // the instruction so that the object can live and successfully respond to all
49 // queries.
51 public:
52  InstructionImpl(const lldb::DisassemblerSP &disasm_sp,
53  const lldb::InstructionSP &inst_sp)
54  : m_disasm_sp(disasm_sp), m_inst_sp(inst_sp) {}
55 
56  lldb::InstructionSP GetSP() const { return m_inst_sp; }
57 
58  bool IsValid() const { return (bool)m_inst_sp; }
59 
60 protected:
61  lldb::DisassemblerSP m_disasm_sp; // Can be empty/invalid
62  lldb::InstructionSP m_inst_sp;
63 };
64 
65 using namespace lldb;
66 using namespace lldb_private;
67 
68 SBInstruction::SBInstruction() : m_opaque_sp() {
70 }
71 
72 SBInstruction::SBInstruction(const lldb::DisassemblerSP &disasm_sp,
73  const lldb::InstructionSP &inst_sp)
74  : m_opaque_sp(new InstructionImpl(disasm_sp, inst_sp)) {}
75 
77  : m_opaque_sp(rhs.m_opaque_sp) {
79 }
80 
83  SBInstruction, operator=,(const lldb::SBInstruction &),
84  rhs);
85 
86  if (this != &rhs)
87  m_opaque_sp = rhs.m_opaque_sp;
88  return LLDB_RECORD_RESULT(*this);
89 }
90 
92 
95  return this->operator bool();
96 }
97 SBInstruction::operator bool() const {
98  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBInstruction, operator bool);
99 
100  return m_opaque_sp && m_opaque_sp->IsValid();
101 }
102 
105 
106  SBAddress sb_addr;
107  lldb::InstructionSP inst_sp(GetOpaque());
108  if (inst_sp && inst_sp->GetAddress().IsValid())
109  sb_addr.SetAddress(&inst_sp->GetAddress());
110  return LLDB_RECORD_RESULT(sb_addr);
111 }
112 
115  target);
116 
117  lldb::InstructionSP inst_sp(GetOpaque());
118  if (inst_sp) {
119  ExecutionContext exe_ctx;
120  TargetSP target_sp(target.GetSP());
121  std::unique_lock<std::recursive_mutex> lock;
122  if (target_sp) {
123  lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
124 
125  target_sp->CalculateExecutionContext(exe_ctx);
126  exe_ctx.SetProcessSP(target_sp->GetProcessSP());
127  }
128  return inst_sp->GetMnemonic(&exe_ctx);
129  }
130  return NULL;
131 }
132 
135  target);
136 
137  lldb::InstructionSP inst_sp(GetOpaque());
138  if (inst_sp) {
139  ExecutionContext exe_ctx;
140  TargetSP target_sp(target.GetSP());
141  std::unique_lock<std::recursive_mutex> lock;
142  if (target_sp) {
143  lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
144 
145  target_sp->CalculateExecutionContext(exe_ctx);
146  exe_ctx.SetProcessSP(target_sp->GetProcessSP());
147  }
148  return inst_sp->GetOperands(&exe_ctx);
149  }
150  return NULL;
151 }
152 
153 const char *SBInstruction::GetComment(SBTarget target) {
155  target);
156 
157  lldb::InstructionSP inst_sp(GetOpaque());
158  if (inst_sp) {
159  ExecutionContext exe_ctx;
160  TargetSP target_sp(target.GetSP());
161  std::unique_lock<std::recursive_mutex> lock;
162  if (target_sp) {
163  lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
164 
165  target_sp->CalculateExecutionContext(exe_ctx);
166  exe_ctx.SetProcessSP(target_sp->GetProcessSP());
167  }
168  return inst_sp->GetComment(&exe_ctx);
169  }
170  return NULL;
171 }
172 
175 
176  lldb::InstructionSP inst_sp(GetOpaque());
177  if (inst_sp)
178  return inst_sp->GetOpcode().GetByteSize();
179  return 0;
180 }
181 
184  target);
185 
186  lldb::SBData sb_data;
187  lldb::InstructionSP inst_sp(GetOpaque());
188  if (inst_sp) {
189  DataExtractorSP data_extractor_sp(new DataExtractor());
190  if (inst_sp->GetData(*data_extractor_sp)) {
191  sb_data.SetOpaque(data_extractor_sp);
192  }
193  }
194  return LLDB_RECORD_RESULT(sb_data);
195 }
196 
199 
200  lldb::InstructionSP inst_sp(GetOpaque());
201  if (inst_sp)
202  return inst_sp->DoesBranch();
203  return false;
204 }
205 
208 
209  lldb::InstructionSP inst_sp(GetOpaque());
210  if (inst_sp)
211  return inst_sp->HasDelaySlot();
212  return false;
213 }
214 
217 
218  lldb::InstructionSP inst_sp(GetOpaque());
219  if (inst_sp)
220  return inst_sp->CanSetBreakpoint();
221  return false;
222 }
223 
224 lldb::InstructionSP SBInstruction::GetOpaque() {
225  if (m_opaque_sp)
226  return m_opaque_sp->GetSP();
227  else
228  return lldb::InstructionSP();
229 }
230 
231 void SBInstruction::SetOpaque(const lldb::DisassemblerSP &disasm_sp,
232  const lldb::InstructionSP &inst_sp) {
233  m_opaque_sp = std::make_shared<InstructionImpl>(disasm_sp, inst_sp);
234 }
235 
238  s);
239 
240  lldb::InstructionSP inst_sp(GetOpaque());
241  if (inst_sp) {
242  SymbolContext sc;
243  const Address &addr = inst_sp->GetAddress();
244  ModuleSP module_sp(addr.GetModule());
245  if (module_sp)
246  module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
247  sc);
248  // Use the "ref()" instead of the "get()" accessor in case the SBStream
249  // didn't have a stream already created, one will get created...
250  FormatEntity::Entry format;
251  FormatEntity::Parse("${addr}: ", format);
252  inst_sp->Dump(&s.ref(), 0, true, false, NULL, &sc, NULL, &format, 0);
253  return true;
254  }
255  return false;
256 }
257 
258 void SBInstruction::Print(FILE *out) {
259  LLDB_RECORD_METHOD(void, SBInstruction, Print, (FILE *), out);
260 
261  if (out == NULL)
262  return;
263 
264  lldb::InstructionSP inst_sp(GetOpaque());
265  if (inst_sp) {
266  SymbolContext sc;
267  const Address &addr = inst_sp->GetAddress();
268  ModuleSP module_sp(addr.GetModule());
269  if (module_sp)
270  module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything,
271  sc);
272  StreamFile out_stream(out, false);
273  FormatEntity::Entry format;
274  FormatEntity::Parse("${addr}: ", format);
275  inst_sp->Dump(&out_stream, 0, true, false, NULL, &sc, NULL, &format, 0);
276  }
277 }
278 
280  uint32_t evaluate_options) {
282  (lldb::SBFrame &, uint32_t), frame, evaluate_options);
283 
284  lldb::InstructionSP inst_sp(GetOpaque());
285  if (inst_sp) {
286  lldb::StackFrameSP frame_sp(frame.GetFrameSP());
287 
288  if (frame_sp) {
290  frame_sp->CalculateExecutionContext(exe_ctx);
291  lldb_private::Target *target = exe_ctx.GetTargetPtr();
292  lldb_private::ArchSpec arch = target->GetArchitecture();
293 
294  return inst_sp->Emulate(
295  arch, evaluate_options, (void *)frame_sp.get(),
300  }
301  }
302  return false;
303 }
304 
305 bool SBInstruction::DumpEmulation(const char *triple) {
306  LLDB_RECORD_METHOD(bool, SBInstruction, DumpEmulation, (const char *),
307  triple);
308 
309  lldb::InstructionSP inst_sp(GetOpaque());
310  if (inst_sp && triple) {
311  return inst_sp->DumpEmulation(HostInfo::GetAugmentedArchSpec(triple));
312  }
313  return false;
314 }
315 
317  const char *test_file) {
319  (lldb::SBStream &, const char *), output_stream,
320  test_file);
321 
322  if (!m_opaque_sp)
323  SetOpaque(lldb::DisassemblerSP(),
324  lldb::InstructionSP(new PseudoInstruction()));
325 
326  lldb::InstructionSP inst_sp(GetOpaque());
327  if (inst_sp)
328  return inst_sp->TestEmulation(output_stream.get(), test_file);
329  return false;
330 }
331 
332 namespace lldb_private {
333 namespace repro {
334 
335 template <>
340  const lldb::SBInstruction &,
341  SBInstruction, operator=,(const lldb::SBInstruction &));
343  LLDB_REGISTER_METHOD_CONST(bool, SBInstruction, operator bool, ());
346  (lldb::SBTarget));
348  (lldb::SBTarget));
350  (lldb::SBTarget));
353  (lldb::SBTarget));
358  (lldb::SBStream &));
359  LLDB_REGISTER_METHOD(void, SBInstruction, Print, (FILE *));
361  (lldb::SBFrame &, uint32_t));
362  LLDB_REGISTER_METHOD(bool, SBInstruction, DumpEmulation, (const char *));
364  (lldb::SBStream &, const char *));
365 }
366 
367 }
368 }
The registry contains a unique mapping between functions and their ID.
An data extractor class.
Definition: DataExtractor.h:47
void Print(FILE *out)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
#define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class)
void SetOpaque(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP &inst_sp)
const ArchSpec & GetArchitecture() const
Definition: Target.h:941
Defines a symbol context baton that can be handed other debug core functions.
Definition: SymbolContext.h:33
bool TestEmulation(lldb::SBStream &output_stream, const char *test_file)
An architecture specification class.
Definition: ArchSpec.h:32
void SetOpaque(const lldb::DataExtractorSP &data_sp)
Definition: SBData.cpp:46
InstructionImpl(const lldb::DisassemblerSP &disasm_sp, const lldb::InstructionSP &inst_sp)
void SetAddress(lldb::SBSection section, lldb::addr_t offset)
Definition: SBAddress.cpp:95
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const char * GetOperands(lldb::SBTarget target)
const SBInstruction & operator=(const SBInstruction &rhs)
bool IsValid() const
Target * GetTargetPtr() const
Returns a pointer to the target object.
#define LLDB_REGISTER_CONSTRUCTOR(Class, Signature)
#define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method)
lldb::TargetSP GetSP() const
Definition: SBTarget.cpp:600
Node * Parse(llvm::StringRef expr, llvm::BumpPtrAllocator &alloc)
Parse the given postfix expression.
lldb::SBData GetData(lldb::SBTarget target)
const char * GetMnemonic(lldb::SBTarget target)
#define LLDB_RECORD_CONSTRUCTOR(Class, Signature,...)
lldb::InstructionSP GetOpaque()
static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
#define LLDB_RECORD_METHOD(Result, Class, Method, Signature,...)
static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
lldb::InstructionSP GetSP() const
A section + offset based address class.
Definition: Address.h:80
void SetProcessSP(const lldb::ProcessSP &process_sp)
Set accessor to set only the process shared pointer.
static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
lldb_private::Stream & ref()
Definition: SBStream.cpp:162
lldb::InstructionSP m_inst_sp
void RegisterMethods< SBInstruction >(Registry &R)
static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
lldb::DisassemblerSP m_disasm_sp
lldb::StackFrameSP GetFrameSP() const
Definition: SBFrame.cpp:84
lldb::ModuleSP GetModule() const
Get accessor for the module for this address.
Definition: Address.cpp:264
bool DumpEmulation(const char *triple)
Definition: SBAddress.h:15
lldb_private::Stream * get()
Definition: SBStream.cpp:160
bool GetDescription(lldb::SBStream &description)
#define LLDB_REGISTER_METHOD(Result, Class, Method, Signature)
#define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method)
const char * GetComment(lldb::SBTarget target)
#define LLDB_RECORD_RESULT(Result)
#define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature)
class LLDB_API SBInstruction
Definition: SBDefines.h:49
bool EmulateWithFrame(lldb::SBFrame &frame, uint32_t evaluate_options)