LLDB  mainline
EmulateInstruction.h
Go to the documentation of this file.
1 //===-- EmulateInstruction.h ------------------------------------*- 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 
9 #ifndef lldb_EmulateInstruction_h_
10 #define lldb_EmulateInstruction_h_
11 
12 #include <string>
13 
14 #include "lldb/Core/Address.h"
15 #include "lldb/Core/Opcode.h"
17 #include "lldb/Utility/ArchSpec.h"
18 #include "lldb/lldb-defines.h"
19 #include "lldb/lldb-enumerations.h"
22 #include "lldb/lldb-types.h"
23 
24 #include <stddef.h>
25 #include <stdint.h>
26 namespace lldb_private {
27 class OptionValueDictionary;
28 }
29 namespace lldb_private {
30 class RegisterContext;
31 }
32 namespace lldb_private {
33 class RegisterValue;
34 }
35 namespace lldb_private {
36 class Stream;
37 }
38 namespace lldb_private {
39 class Target;
40 }
41 namespace lldb_private {
42 class UnwindPlan;
43 }
44 
45 namespace lldb_private {
46 
47 /// \class EmulateInstruction EmulateInstruction.h
48 /// "lldb/Core/EmulateInstruction.h"
49 /// A class that allows emulation of CPU opcodes.
50 ///
51 /// This class is a plug-in interface that is accessed through the standard
52 /// static FindPlugin function call in the EmulateInstruction class. The
53 /// FindPlugin takes a target triple and returns a new object if there is a
54 /// plug-in that supports the architecture and OS. Four callbacks and a baton
55 /// are provided. The four callbacks are read register, write register, read
56 /// memory and write memory.
57 ///
58 /// This class is currently designed for these main use cases: - Auto
59 /// generation of Call Frame Information (CFI) from assembly code - Predicting
60 /// single step breakpoint locations - Emulating instructions for breakpoint
61 /// traps
62 ///
63 /// Objects can be asked to read an instruction which will cause a call to the
64 /// read register callback to get the PC, followed by a read memory call to
65 /// read the opcode. If ReadInstruction () returns true, then a call to
66 /// EmulateInstruction::EvaluateInstruction () can be made. At this point the
67 /// EmulateInstruction subclass will use all of the callbacks to emulate an
68 /// instruction.
69 ///
70 /// Clients that provide the callbacks can either do the read/write
71 /// registers/memory to actually emulate the instruction on a real or virtual
72 /// CPU, or watch for the EmulateInstruction::Context which is context for the
73 /// read/write register/memory which explains why the callback is being
74 /// called. Examples of a context are: "pushing register 3 onto the stack at
75 /// offset -12", or "adjusting stack pointer by -16". This extra context
76 /// allows the generation of
77 /// CFI information from assembly code without having to actually do
78 /// the read/write register/memory.
79 ///
80 /// Clients must be prepared that not all instructions for an Instruction Set
81 /// Architecture (ISA) will be emulated.
82 ///
83 /// Subclasses at the very least should implement the instructions that save
84 /// and restore registers onto the stack and adjustment to the stack pointer.
85 /// By just implementing a few instructions for an ISA that are the typical
86 /// prologue opcodes, you can then generate CFI using a class that will soon
87 /// be available.
88 ///
89 /// Implementing all of the instructions that affect the PC can then allow
90 /// single step prediction support.
91 ///
92 /// Implementing all of the instructions allows for emulation of opcodes for
93 /// breakpoint traps and will pave the way for "thread centric" debugging. The
94 /// current debugging model is "process centric" where all threads must be
95 /// stopped when any thread is stopped; when hitting software breakpoints we
96 /// must disable the breakpoint by restoring the original breakpoint opcode,
97 /// single stepping and restoring the breakpoint trap. If all threads were
98 /// allowed to run then other threads could miss the breakpoint.
99 ///
100 /// This class centralizes the code that usually is done in separate code
101 /// paths in a debugger (single step prediction, finding save restore
102 /// locations of registers for unwinding stack frame variables) and emulating
103 /// the instruction is just a bonus.
104 
106 public:
107  static EmulateInstruction *FindPlugin(const ArchSpec &arch,
108  InstructionType supported_inst_type,
109  const char *plugin_name);
110 
111  enum ContextType {
113  // Read an instruction opcode from memory
115 
116  // Usually used for writing a register value whose source value is an
117  // immediate
119 
120  // Exclusively used when saving a register to the stack as part of the
121  // prologue
123 
124  // Exclusively used when restoring a register off the stack as part of the
125  // epilogue
127 
128  // Add or subtract a value from the stack
130 
131  // Adjust the frame pointer for the current frame
133 
134  // Typically in an epilogue sequence. Copy the frame pointer back into the
135  // stack pointer, use SP for CFA calculations again.
137 
138  // Add or subtract a value from a base address register (other than SP)
140 
141  // Add or subtract a value from the PC or store a value to the PC.
143 
144  // Used in WriteRegister callbacks to indicate where the
146 
147  // Used in WriteMemory callback to indicate where the data came from
149 
151 
152  // Used when performing a PC-relative branch where the
154 
155  // Used when performing an absolute branch where the
157 
158  // Used when performing a supervisor call to an operating system to provide
159  // a service:
161 
162  // Used when performing a MemU operation to read the PC-relative offset
163  // from an address.
165 
166  // Used when random bits are written into a register
168 
169  // Used when random bits are written to memory
171 
173 
175 
177  };
178 
179  enum InfoType {
194  } InfoType;
195 
196  struct Context {
198  enum InfoType info_type;
199  union {
200  struct RegisterPlusOffset {
201  RegisterInfo reg; // base register
202  int64_t signed_offset; // signed offset added to base register
204 
206  RegisterInfo base_reg; // base register number
207  RegisterInfo offset_reg; // offset register kind
209 
211  RegisterInfo data_reg; // source/target register for data
212  RegisterInfo base_reg; // base register for address calculation
213  int64_t offset; // offset for address calculation
215 
217  RegisterInfo base_reg; // base register for address calculation
218  RegisterInfo offset_reg; // offset register for address calculation
219  RegisterInfo data_reg; // source/target register for data
221 
222  struct RegisterRegisterOperands {
223  RegisterInfo
224  operand1; // register containing first operand for binary op
225  RegisterInfo
226  operand2; // register containing second operand for binary op
228 
229  int64_t signed_offset; // signed offset by which to adjust self (for
230  // registers only)
231 
232  RegisterInfo reg; // plain register
233 
234  uint64_t unsigned_immediate; // unsigned immediate value
235  int64_t signed_immediate; // signed immediate value
236 
237  lldb::addr_t address; // direct address
238 
239  struct ISAAndImmediate {
241  uint32_t unsigned_data32; // immediate data
242  } ISAAndImmediate;
243 
244  struct ISAAndImmediateSigned {
245  uint32_t isa;
246  int32_t signed_data32; // signed immediate data
248 
249  uint32_t isa;
250  } info;
251 
252  Context() : type(eContextInvalid), info_type(eInfoTypeNoArgs) {}
253 
254  void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset) {
255  info_type = eInfoTypeRegisterPlusOffset;
256  info.RegisterPlusOffset.reg = base_reg;
257  info.RegisterPlusOffset.signed_offset = signed_offset;
258  }
259 
261  RegisterInfo offset_reg) {
263  info.RegisterPlusIndirectOffset.base_reg = base_reg;
264  info.RegisterPlusIndirectOffset.offset_reg = offset_reg;
265  }
266 
268  RegisterInfo base_reg,
269  int64_t offset) {
271  info.RegisterToRegisterPlusOffset.data_reg = data_reg;
272  info.RegisterToRegisterPlusOffset.base_reg = base_reg;
273  info.RegisterToRegisterPlusOffset.offset = offset;
274  }
275 
277  RegisterInfo offset_reg,
278  RegisterInfo data_reg) {
280  info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg;
281  info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg;
282  info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg;
283  }
284 
285  void SetRegisterRegisterOperands(RegisterInfo op1_reg,
286  RegisterInfo op2_reg) {
288  info.RegisterRegisterOperands.operand1 = op1_reg;
289  info.RegisterRegisterOperands.operand2 = op2_reg;
290  }
291 
292  void SetOffset(int64_t signed_offset) {
293  info_type = eInfoTypeOffset;
294  info.signed_offset = signed_offset;
295  }
296 
297  void SetRegister(RegisterInfo reg) {
298  info_type = eInfoTypeRegister;
299  info.reg = reg;
300  }
301 
302  void SetImmediate(uint64_t immediate) {
303  info_type = eInfoTypeImmediate;
304  info.unsigned_immediate = immediate;
305  }
306 
308  info_type = eInfoTypeImmediateSigned;
309  info.signed_immediate = signed_immediate;
310  }
311 
313  info_type = eInfoTypeAddress;
314  info.address = address;
315  }
317  info_type = eInfoTypeISAAndImmediate;
318  info.ISAAndImmediate.isa = isa;
319  info.ISAAndImmediate.unsigned_data32 = data;
320  }
321 
322  void SetISAAndImmediateSigned(uint32_t isa, int32_t data) {
323  info_type = eInfoTypeISAAndImmediateSigned;
324  info.ISAAndImmediateSigned.isa = isa;
325  info.ISAAndImmediateSigned.signed_data32 = data;
326  }
327 
329  info_type = eInfoTypeISA;
330  info.isa = isa;
331  }
332 
333  void SetNoArgs() { info_type = eInfoTypeNoArgs; }
334 
335  void Dump(Stream &s, EmulateInstruction *instruction) const;
336  };
337 
338  typedef size_t (*ReadMemoryCallback)(EmulateInstruction *instruction,
339  void *baton, const Context &context,
340  lldb::addr_t addr, void *dst,
341  size_t length);
342 
343  typedef size_t (*WriteMemoryCallback)(EmulateInstruction *instruction,
344  void *baton, const Context &context,
345  lldb::addr_t addr, const void *dst,
346  size_t length);
347 
348  typedef bool (*ReadRegisterCallback)(EmulateInstruction *instruction,
349  void *baton,
350  const RegisterInfo *reg_info,
351  RegisterValue &reg_value);
352 
353  typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction,
354  void *baton, const Context &context,
355  const RegisterInfo *reg_info,
356  const RegisterValue &reg_value);
357 
358  // Type to represent the condition of an instruction. The UINT32 value is
359  // reserved for the unconditional case and all other value can be used in an
360  // architecture dependent way.
362  static const InstructionCondition UnconditionalCondition = UINT32_MAX;
363 
364  EmulateInstruction(const ArchSpec &arch);
365 
366  ~EmulateInstruction() override = default;
367 
368  // Mandatory overrides
369  virtual bool
371 
372  virtual bool SetTargetTriple(const ArchSpec &arch) = 0;
373 
374  virtual bool ReadInstruction() = 0;
375 
376  virtual bool EvaluateInstruction(uint32_t evaluate_options) = 0;
377 
378  virtual InstructionCondition GetInstructionCondition() {
379  return UnconditionalCondition;
380  }
381 
382  virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch,
383  OptionValueDictionary *test_data) = 0;
384 
385  virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num,
386  RegisterInfo &reg_info) = 0;
387 
388  // Optional overrides
389  virtual bool SetInstruction(const Opcode &insn_opcode,
390  const Address &inst_addr, Target *target);
391 
392  virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan);
393 
394  static const char *TranslateRegister(lldb::RegisterKind reg_kind,
395  uint32_t reg_num, std::string &reg_name);
396 
397  // RegisterInfo variants
398  bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value);
399 
400  uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info,
401  uint64_t fail_value, bool *success_ptr);
402 
403  bool WriteRegister(const Context &context, const RegisterInfo *ref_info,
404  const RegisterValue &reg_value);
405 
406  bool WriteRegisterUnsigned(const Context &context,
407  const RegisterInfo *reg_info, uint64_t reg_value);
408 
409  // Register kind and number variants
410  bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num,
411  RegisterValue &reg_value);
412 
413  bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind,
414  uint32_t reg_num, const RegisterValue &reg_value);
415 
416  uint64_t ReadRegisterUnsigned(lldb::RegisterKind reg_kind, uint32_t reg_num,
417  uint64_t fail_value, bool *success_ptr);
418 
419  bool WriteRegisterUnsigned(const Context &context,
420  lldb::RegisterKind reg_kind, uint32_t reg_num,
421  uint64_t reg_value);
422 
423  size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst,
424  size_t dst_len);
425 
426  uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr,
427  size_t byte_size, uint64_t fail_value,
428  bool *success_ptr);
429 
430  bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src,
431  size_t src_len);
432 
433  bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr,
434  uint64_t uval, size_t uval_byte_size);
435 
437 
439 
440  const Opcode &GetOpcode() const { return m_opcode; }
441 
442  lldb::addr_t GetAddress() const { return m_addr; }
443 
444  const ArchSpec &GetArchitecture() const { return m_arch; }
445 
446  static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton,
447  const Context &context, lldb::addr_t addr,
448  void *dst, size_t length);
449 
450  static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton,
451  const Context &context, lldb::addr_t addr,
452  const void *dst, size_t length);
453 
454  static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton,
455  const RegisterInfo *reg_info,
456  RegisterValue &reg_value);
457 
458  static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton,
459  const Context &context,
460  const RegisterInfo *reg_info,
461  const RegisterValue &reg_value);
462 
463  static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton,
464  const Context &context, lldb::addr_t addr,
465  void *dst, size_t length);
466 
467  static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton,
468  const Context &context, lldb::addr_t addr,
469  const void *dst, size_t length);
470 
471  static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton,
472  const RegisterInfo *reg_info,
473  RegisterValue &reg_value);
474 
475  static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton,
476  const Context &context,
477  const RegisterInfo *reg_info,
478  const RegisterValue &reg_value);
479 
480  void SetBaton(void *baton);
481 
482  void SetCallbacks(ReadMemoryCallback read_mem_callback,
483  WriteMemoryCallback write_mem_callback,
484  ReadRegisterCallback read_reg_callback,
485  WriteRegisterCallback write_reg_callback);
486 
487  void SetReadMemCallback(ReadMemoryCallback read_mem_callback);
488 
489  void SetWriteMemCallback(WriteMemoryCallback write_mem_callback);
490 
491  void SetReadRegCallback(ReadRegisterCallback read_reg_callback);
492 
493  void SetWriteRegCallback(WriteRegisterCallback write_reg_callback);
494 
495  static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info,
496  lldb::RegisterKind &reg_kind,
497  uint32_t &reg_num);
498 
500  const RegisterInfo &reg_info);
501 
502 protected:
504  void *m_baton = nullptr;
511 
512 private:
513  // For EmulateInstruction only
514  DISALLOW_COPY_AND_ASSIGN(EmulateInstruction);
515 };
516 
517 } // namespace lldb_private
518 
519 #endif // lldb_EmulateInstruction_h_
void SetReadMemCallback(ReadMemoryCallback read_mem_callback)
bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr, uint64_t uval, size_t uval_byte_size)
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
static const InstructionCondition UnconditionalCondition
EmulateInstruction(const ArchSpec &arch)
static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, uint64_t fail_value, bool *success_ptr)
void Dump(Stream &s, EmulateInstruction *instruction) const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
virtual bool SetTargetTriple(const ArchSpec &arch)=0
struct lldb_private::EmulateInstruction::Context::@5::RegisterPlusIndirectOffset RegisterPlusIndirectOffset
struct lldb_private::EmulateInstruction::Context::@5::RegisterRegisterOperands RegisterRegisterOperands
void SetImmediateSigned(int64_t signed_immediate)
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:742
bool WriteRegister(const Context &context, const RegisterInfo *ref_info, const RegisterValue &reg_value)
virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo &reg_info)=0
size_t(* WriteMemoryCallback)(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
lldb::ByteOrder GetByteOrder() const
void SetISAAndImmediateSigned(uint32_t isa, int32_t data)
static const char * TranslateRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, std::string &reg_name)
An architecture specification class.
Definition: ArchSpec.h:32
~EmulateInstruction() override=default
"lldb/Core/EmulateInstruction.h" A class that allows emulation of CPU opcodes.
uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr)
bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, size_t src_len)
void SetRegisterToRegisterPlusIndirectOffset(RegisterInfo base_reg, RegisterInfo offset_reg, RegisterInfo data_reg)
static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx, const RegisterInfo &reg_info)
struct lldb_private::EmulateInstruction::Context::@5::RegisterToRegisterPlusIndirectOffset RegisterToRegisterPlusIndirectOffset
void SetReadRegCallback(ReadRegisterCallback read_reg_callback)
#define UINT32_MAX
Definition: lldb-defines.h:31
union lldb_private::EmulateInstruction::Context::@5 info
void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset)
#define LLDB_INVALID_ADDRESS
Invalid value definitions.
Definition: lldb-defines.h:85
size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst, size_t dst_len)
size_t(* ReadMemoryCallback)(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
virtual bool SupportsEmulatingInstructionsOfType(InstructionType inst_type)=0
void SetISAAndImmediate(uint32_t isa, uint32_t data)
static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
const ArchSpec & GetArchitecture() const
static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
virtual InstructionCondition GetInstructionCondition()
static EmulateInstruction * FindPlugin(const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name)
void SetRegisterPlusIndirectOffset(RegisterInfo base_reg, RegisterInfo offset_reg)
void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, int64_t offset)
static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, const void *dst, size_t length)
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition: ArchSpec.cpp:788
static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
WriteRegisterCallback m_write_reg_callback
WriteMemoryCallback m_write_mem_callback
struct lldb_private::EmulateInstruction::Context::@5::RegisterToRegisterPlusOffset RegisterToRegisterPlusOffset
A section + offset based address class.
Definition: Address.h:80
virtual bool SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, Target *target)
static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
InstructionType
Instruction types.
bool(* WriteRegisterCallback)(EmulateInstruction *instruction, void *baton, const Context &context, const RegisterInfo *reg_info, const RegisterValue &reg_value)
static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, lldb::RegisterKind &reg_kind, uint32_t &reg_num)
static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, const Context &context, lldb::addr_t addr, void *dst, size_t length)
uint64_t addr_t
Definition: lldb-types.h:83
struct lldb_private::EmulateInstruction::Context::@5::RegisterPlusOffset RegisterPlusOffset
void SetRegisterRegisterOperands(RegisterInfo op1_reg, RegisterInfo op2_reg)
ReadRegisterCallback m_read_reg_callback
void SetWriteMemCallback(WriteMemoryCallback write_mem_callback)
bool WriteRegisterUnsigned(const Context &context, const RegisterInfo *reg_info, uint64_t reg_value)
virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)=0
virtual bool EvaluateInstruction(uint32_t evaluate_options)=0
struct lldb_private::EmulateInstruction::Context::@5::ISAAndImmediateSigned ISAAndImmediateSigned
struct lldb_private::EmulateInstruction::Context::@5::ISAAndImmediate ISAAndImmediate
bool(* ReadRegisterCallback)(EmulateInstruction *instruction, void *baton, const RegisterInfo *reg_info, RegisterValue &reg_value)
void SetWriteRegCallback(WriteRegisterCallback write_reg_callback)
void SetCallbacks(ReadMemoryCallback read_mem_callback, WriteMemoryCallback write_mem_callback, ReadRegisterCallback read_reg_callback, WriteRegisterCallback write_reg_callback)
virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan)