diff options
Diffstat (limited to 'include/lldb/Core/EmulateInstruction.h')
-rw-r--r-- | include/lldb/Core/EmulateInstruction.h | 981 |
1 files changed, 423 insertions, 558 deletions
diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h index 36fff43bf6bc..90e66d668ca4 100644 --- a/include/lldb/Core/EmulateInstruction.h +++ b/include/lldb/Core/EmulateInstruction.h @@ -12,24 +12,25 @@ #include <string> -#include "lldb/lldb-private.h" -#include "lldb/lldb-public.h" #include "lldb/Core/ArchSpec.h" -#include "lldb/Core/PluginInterface.h" #include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginInterface.h" #include "lldb/Core/RegisterValue.h" +#include "lldb/lldb-private.h" +#include "lldb/lldb-public.h" namespace lldb_private { //---------------------------------------------------------------------- -/// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h" +/// @class EmulateInstruction EmulateInstruction.h +/// "lldb/Core/EmulateInstruction.h" /// @brief A class that allows emulation of CPU opcodes. /// -/// This class is a plug-in interface that is accessed through the +/// This class is a plug-in interface that is accessed through the /// standard static FindPlugin function call in the EmulateInstruction /// class. The FindPlugin takes a target triple and returns a new object /// if there is a plug-in that supports the architecture and OS. Four -/// callbacks and a baton are provided. The four callbacks are read +/// callbacks and a baton are provided. The four callbacks are read /// register, write register, read memory and write memory. /// /// This class is currently designed for these main use cases: @@ -38,13 +39,13 @@ namespace lldb_private { /// - Emulating instructions for breakpoint traps /// /// Objects can be asked to read an instruction which will cause a call -/// to the read register callback to get the PC, followed by a read -/// memory call to read the opcode. If ReadInstruction () returns true, -/// then a call to EmulateInstruction::EvaluateInstruction () can be +/// to the read register callback to get the PC, followed by a read +/// memory call to read the opcode. If ReadInstruction () returns true, +/// then a call to EmulateInstruction::EvaluateInstruction () can be /// made. At this point the EmulateInstruction subclass will use all of /// the callbacks to emulate an instruction. /// -/// Clients that provide the callbacks can either do the read/write +/// Clients that provide the callbacks can either do the read/write /// registers/memory to actually emulate the instruction on a real or /// virtual CPU, or watch for the EmulateInstruction::Context which /// is context for the read/write register/memory which explains why @@ -54,15 +55,15 @@ namespace lldb_private { /// CFI information from assembly code without having to actually do /// the read/write register/memory. /// -/// Clients must be prepared that not all instructions for an -/// Instruction Set Architecture (ISA) will be emulated. +/// Clients must be prepared that not all instructions for an +/// Instruction Set Architecture (ISA) will be emulated. /// /// Subclasses at the very least should implement the instructions that /// save and restore registers onto the stack and adjustment to the stack /// pointer. By just implementing a few instructions for an ISA that are -/// the typical prologue opcodes, you can then generate CFI using a +/// the typical prologue opcodes, you can then generate CFI using a /// class that will soon be available. -/// +/// /// Implementing all of the instructions that affect the PC can then /// allow single step prediction support. /// @@ -73,571 +74,435 @@ namespace lldb_private { /// hitting software breakpoints we must disable the breakpoint by /// restoring the original breakpoint opcode, single stepping and /// restoring the breakpoint trap. If all threads were allowed to run -/// then other threads could miss the breakpoint. +/// then other threads could miss the breakpoint. /// -/// This class centralizes the code that usually is done in separate +/// This class centralizes the code that usually is done in separate /// code paths in a debugger (single step prediction, finding save /// restore locations of registers for unwinding stack frame variables) /// and emulating the instruction is just a bonus. //---------------------------------------------------------------------- -class EmulateInstruction : - public PluginInterface -{ +class EmulateInstruction : public PluginInterface { public: + static EmulateInstruction *FindPlugin(const ArchSpec &arch, + InstructionType supported_inst_type, + const char *plugin_name); + + enum ContextType { + eContextInvalid = 0, + // Read an instruction opcode from memory + eContextReadOpcode, + + // Usually used for writing a register value whose source value is an + // immediate + eContextImmediate, + + // Exclusively used when saving a register to the stack as part of the + // prologue + eContextPushRegisterOnStack, + + // Exclusively used when restoring a register off the stack as part of + // the epilogue + eContextPopRegisterOffStack, + + // Add or subtract a value from the stack + eContextAdjustStackPointer, + + // Adjust the frame pointer for the current frame + eContextSetFramePointer, + + // Typically in an epilogue sequence. Copy the frame pointer back + // into the stack pointer, use SP for CFA calculations again. + eContextRestoreStackPointer, + + // Add or subtract a value from a base address register (other than SP) + eContextAdjustBaseRegister, + + // Add or subtract a value from the PC or store a value to the PC. + eContextAdjustPC, + + // Used in WriteRegister callbacks to indicate where the + eContextRegisterPlusOffset, + + // Used in WriteMemory callback to indicate where the data came from + eContextRegisterStore, + + eContextRegisterLoad, + + // Used when performing a PC-relative branch where the + eContextRelativeBranchImmediate, + + // Used when performing an absolute branch where the + eContextAbsoluteBranchRegister, + + // Used when performing a supervisor call to an operating system to + // provide a service: + eContextSupervisorCall, + + // Used when performing a MemU operation to read the PC-relative offset + // from an address. + eContextTableBranchReadMemory, + + // Used when random bits are written into a register + eContextWriteRegisterRandomBits, + + // Used when random bits are written to memory + eContextWriteMemoryRandomBits, + + eContextArithmetic, + + eContextAdvancePC, + + eContextReturnFromException + }; + + enum InfoType { + eInfoTypeRegisterPlusOffset, + eInfoTypeRegisterPlusIndirectOffset, + eInfoTypeRegisterToRegisterPlusOffset, + eInfoTypeRegisterToRegisterPlusIndirectOffset, + eInfoTypeRegisterRegisterOperands, + eInfoTypeOffset, + eInfoTypeRegister, + eInfoTypeImmediate, + eInfoTypeImmediateSigned, + eInfoTypeAddress, + eInfoTypeISAAndImmediate, + eInfoTypeISAAndImmediateSigned, + eInfoTypeISA, + eInfoTypeNoArgs + } InfoType; + + struct Context { + ContextType type; + enum InfoType info_type; + union { + struct RegisterPlusOffset { + RegisterInfo reg; // base register + int64_t signed_offset; // signed offset added to base register + } RegisterPlusOffset; + + struct RegisterPlusIndirectOffset { + RegisterInfo base_reg; // base register number + RegisterInfo offset_reg; // offset register kind + } RegisterPlusIndirectOffset; + + struct RegisterToRegisterPlusOffset { + RegisterInfo data_reg; // source/target register for data + RegisterInfo base_reg; // base register for address calculation + int64_t offset; // offset for address calculation + } RegisterToRegisterPlusOffset; - static EmulateInstruction* - FindPlugin (const ArchSpec &arch, - InstructionType supported_inst_type, - const char *plugin_name); - - enum ContextType - { - eContextInvalid = 0, - // Read an instruction opcode from memory - eContextReadOpcode, - - // Usually used for writing a register value whose source value is an - // immediate - eContextImmediate, - - // Exclusively used when saving a register to the stack as part of the - // prologue - eContextPushRegisterOnStack, - - // Exclusively used when restoring a register off the stack as part of - // the epilogue - eContextPopRegisterOffStack, - - // Add or subtract a value from the stack - eContextAdjustStackPointer, - - // Adjust the frame pointer for the current frame - eContextSetFramePointer, - - // Add or subtract a value from a base address register (other than SP) - eContextAdjustBaseRegister, - - // Add or subtract a value from the PC or store a value to the PC. - eContextAdjustPC, - - // Used in WriteRegister callbacks to indicate where the - eContextRegisterPlusOffset, - - // Used in WriteMemory callback to indicate where the data came from - eContextRegisterStore, - - eContextRegisterLoad, - - // Used when performing a PC-relative branch where the - eContextRelativeBranchImmediate, - - // Used when performing an absolute branch where the - eContextAbsoluteBranchRegister, - - // Used when performing a supervisor call to an operating system to - // provide a service: - eContextSupervisorCall, - - // Used when performing a MemU operation to read the PC-relative offset - // from an address. - eContextTableBranchReadMemory, - - // Used when random bits are written into a register - eContextWriteRegisterRandomBits, - - // Used when random bits are written to memory - eContextWriteMemoryRandomBits, - - eContextArithmetic, - - eContextAdvancePC, - - eContextReturnFromException - }; - - enum InfoType { - eInfoTypeRegisterPlusOffset, - eInfoTypeRegisterPlusIndirectOffset, - eInfoTypeRegisterToRegisterPlusOffset, - eInfoTypeRegisterToRegisterPlusIndirectOffset, - eInfoTypeRegisterRegisterOperands, - eInfoTypeOffset, - eInfoTypeRegister, - eInfoTypeImmediate, - eInfoTypeImmediateSigned, - eInfoTypeAddress, - eInfoTypeISAAndImmediate, - eInfoTypeISAAndImmediateSigned, - eInfoTypeISA, - eInfoTypeNoArgs - } InfoType; - - struct Context - { - ContextType type; - enum InfoType info_type; - union - { - struct RegisterPlusOffset - { - RegisterInfo reg; // base register - int64_t signed_offset; // signed offset added to base register - } RegisterPlusOffset; - - struct RegisterPlusIndirectOffset - { - RegisterInfo base_reg; // base register number - RegisterInfo offset_reg; // offset register kind - } RegisterPlusIndirectOffset; - - struct RegisterToRegisterPlusOffset - { - RegisterInfo data_reg; // source/target register for data - RegisterInfo base_reg; // base register for address calculation - int64_t offset; // offset for address calculation - } RegisterToRegisterPlusOffset; - - struct RegisterToRegisterPlusIndirectOffset - { - RegisterInfo base_reg; // base register for address calculation - RegisterInfo offset_reg; // offset register for address calculation - RegisterInfo data_reg; // source/target register for data - } RegisterToRegisterPlusIndirectOffset; - - struct RegisterRegisterOperands - { - RegisterInfo operand1; // register containing first operand for binary op - RegisterInfo operand2; // register containing second operand for binary op - } RegisterRegisterOperands; - - int64_t signed_offset; // signed offset by which to adjust self (for registers only) - - RegisterInfo reg; // plain register - - uint64_t unsigned_immediate;// unsigned immediate value - int64_t signed_immediate; // signed immediate value - - lldb::addr_t address; // direct address - - struct ISAAndImmediate - { - uint32_t isa; - uint32_t unsigned_data32; // immediate data - } ISAAndImmediate; - - struct ISAAndImmediateSigned - { - uint32_t isa; - int32_t signed_data32; // signed immediate data - } ISAAndImmediateSigned; - - uint32_t isa; - } info; - - Context () : - type (eContextInvalid), - info_type (eInfoTypeNoArgs) - { - } - - void - SetRegisterPlusOffset (RegisterInfo base_reg, - int64_t signed_offset) - { - info_type = eInfoTypeRegisterPlusOffset; - info.RegisterPlusOffset.reg = base_reg; - info.RegisterPlusOffset.signed_offset = signed_offset; - } - - void - SetRegisterPlusIndirectOffset (RegisterInfo base_reg, - RegisterInfo offset_reg) - { - info_type = eInfoTypeRegisterPlusIndirectOffset; - info.RegisterPlusIndirectOffset.base_reg = base_reg; - info.RegisterPlusIndirectOffset.offset_reg = offset_reg; - } - - void - SetRegisterToRegisterPlusOffset (RegisterInfo data_reg, + struct RegisterToRegisterPlusIndirectOffset { + RegisterInfo base_reg; // base register for address calculation + RegisterInfo offset_reg; // offset register for address calculation + RegisterInfo data_reg; // source/target register for data + } RegisterToRegisterPlusIndirectOffset; + + struct RegisterRegisterOperands { + RegisterInfo + operand1; // register containing first operand for binary op + RegisterInfo + operand2; // register containing second operand for binary op + } RegisterRegisterOperands; + + int64_t signed_offset; // signed offset by which to adjust self (for + // registers only) + + RegisterInfo reg; // plain register + + uint64_t unsigned_immediate; // unsigned immediate value + int64_t signed_immediate; // signed immediate value + + lldb::addr_t address; // direct address + + struct ISAAndImmediate { + uint32_t isa; + uint32_t unsigned_data32; // immediate data + } ISAAndImmediate; + + struct ISAAndImmediateSigned { + uint32_t isa; + int32_t signed_data32; // signed immediate data + } ISAAndImmediateSigned; + + uint32_t isa; + } info; + + Context() : type(eContextInvalid), info_type(eInfoTypeNoArgs) {} + + void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset) { + info_type = eInfoTypeRegisterPlusOffset; + info.RegisterPlusOffset.reg = base_reg; + info.RegisterPlusOffset.signed_offset = signed_offset; + } + + void SetRegisterPlusIndirectOffset(RegisterInfo base_reg, + RegisterInfo offset_reg) { + info_type = eInfoTypeRegisterPlusIndirectOffset; + info.RegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterPlusIndirectOffset.offset_reg = offset_reg; + } + + void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, RegisterInfo base_reg, - int64_t offset) - { - info_type = eInfoTypeRegisterToRegisterPlusOffset; - info.RegisterToRegisterPlusOffset.data_reg = data_reg; - info.RegisterToRegisterPlusOffset.base_reg = base_reg; - info.RegisterToRegisterPlusOffset.offset = offset; - } - - void - SetRegisterToRegisterPlusIndirectOffset (RegisterInfo base_reg, + int64_t offset) { + info_type = eInfoTypeRegisterToRegisterPlusOffset; + info.RegisterToRegisterPlusOffset.data_reg = data_reg; + info.RegisterToRegisterPlusOffset.base_reg = base_reg; + info.RegisterToRegisterPlusOffset.offset = offset; + } + + void SetRegisterToRegisterPlusIndirectOffset(RegisterInfo base_reg, RegisterInfo offset_reg, - RegisterInfo data_reg) - { - info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset; - info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg; - info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg; - info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg; - } - - void - SetRegisterRegisterOperands (RegisterInfo op1_reg, - RegisterInfo op2_reg) - { - info_type = eInfoTypeRegisterRegisterOperands; - info.RegisterRegisterOperands.operand1 = op1_reg; - info.RegisterRegisterOperands.operand2 = op2_reg; - } - - void - SetOffset (int64_t signed_offset) - { - info_type = eInfoTypeOffset; - info.signed_offset = signed_offset; - } - - void - SetRegister (RegisterInfo reg) - { - info_type = eInfoTypeRegister; - info.reg = reg; - } - - void - SetImmediate (uint64_t immediate) - { - info_type = eInfoTypeImmediate; - info.unsigned_immediate = immediate; - } - - void - SetImmediateSigned (int64_t signed_immediate) - { - info_type = eInfoTypeImmediateSigned; - info.signed_immediate = signed_immediate; - } - - void - SetAddress (lldb::addr_t address) - { - info_type = eInfoTypeAddress; - info.address = address; - } - void - SetISAAndImmediate (uint32_t isa, uint32_t data) - { - info_type = eInfoTypeISAAndImmediate; - info.ISAAndImmediate.isa = isa; - info.ISAAndImmediate.unsigned_data32 = data; - } - - void - SetISAAndImmediateSigned (uint32_t isa, int32_t data) - { - info_type = eInfoTypeISAAndImmediateSigned; - info.ISAAndImmediateSigned.isa = isa; - info.ISAAndImmediateSigned.signed_data32 = data; - } - - void - SetISA (uint32_t isa) - { - info_type = eInfoTypeISA; - info.isa = isa; - } - - void - SetNoArgs () - { - info_type = eInfoTypeNoArgs; - } - - void - Dump (Stream &s, - EmulateInstruction *instruction) const; - - }; - - typedef size_t (*ReadMemoryCallback) (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - void *dst, - size_t length); - - typedef size_t (*WriteMemoryCallback) (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - const void *dst, - size_t length); - - typedef bool (*ReadRegisterCallback) (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value); - - typedef bool (*WriteRegisterCallback) (EmulateInstruction *instruction, - void *baton, - const Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value); - - // Type to represent the condition of an instruction. The UINT32 value is reserved for the - // unconditional case and all other value can be used in an architecture dependent way. - typedef uint32_t InstructionCondition; - static const InstructionCondition UnconditionalCondition = UINT32_MAX; - - EmulateInstruction (const ArchSpec &arch); - - ~EmulateInstruction() override = default; - - //---------------------------------------------------------------------- - // Mandatory overrides - //---------------------------------------------------------------------- - virtual bool - SupportsEmulatingInstructionsOfType (InstructionType inst_type) = 0; - - virtual bool - SetTargetTriple (const ArchSpec &arch) = 0; - - virtual bool - ReadInstruction () = 0; - - virtual bool - EvaluateInstruction (uint32_t evaluate_options) = 0; - - virtual InstructionCondition - GetInstructionCondition() { return UnconditionalCondition; } - - virtual bool - TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; - - virtual bool - GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) = 0; - - //---------------------------------------------------------------------- - // Optional overrides - //---------------------------------------------------------------------- - virtual bool - SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target); - - virtual bool - CreateFunctionEntryUnwind (UnwindPlan &unwind_plan); - - static const char * - TranslateRegister (lldb::RegisterKind reg_kind, uint32_t reg_num, std::string ®_name); - - //---------------------------------------------------------------------- - // RegisterInfo variants - //---------------------------------------------------------------------- - bool - ReadRegister (const RegisterInfo *reg_info, - RegisterValue& reg_value); - - uint64_t - ReadRegisterUnsigned (const RegisterInfo *reg_info, - uint64_t fail_value, - bool *success_ptr); - - bool - WriteRegister (const Context &context, - const RegisterInfo *ref_info, - const RegisterValue& reg_value); - - bool - WriteRegisterUnsigned (const Context &context, - const RegisterInfo *reg_info, - uint64_t reg_value); - - //---------------------------------------------------------------------- - // Register kind and number variants - //---------------------------------------------------------------------- - bool - ReadRegister (lldb::RegisterKind reg_kind, - uint32_t reg_num, - RegisterValue& reg_value); - - bool - WriteRegister (const Context &context, - lldb::RegisterKind reg_kind, - uint32_t reg_num, - const RegisterValue& reg_value); - - uint64_t - ReadRegisterUnsigned (lldb::RegisterKind reg_kind, - uint32_t reg_num, - uint64_t fail_value, - bool *success_ptr); - - bool - WriteRegisterUnsigned (const Context &context, - lldb::RegisterKind reg_kind, - uint32_t reg_num, - uint64_t reg_value); - - - size_t - ReadMemory (const Context &context, - lldb::addr_t addr, - void *dst, - size_t dst_len); - - 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); - - bool - WriteMemoryUnsigned (const Context &context, - lldb::addr_t addr, - uint64_t uval, - size_t uval_byte_size); - - uint32_t - GetAddressByteSize () const - { - return m_arch.GetAddressByteSize(); + RegisterInfo data_reg) { + info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset; + info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg; + info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg; + } + + void SetRegisterRegisterOperands(RegisterInfo op1_reg, + RegisterInfo op2_reg) { + info_type = eInfoTypeRegisterRegisterOperands; + info.RegisterRegisterOperands.operand1 = op1_reg; + info.RegisterRegisterOperands.operand2 = op2_reg; + } + + void SetOffset(int64_t signed_offset) { + info_type = eInfoTypeOffset; + info.signed_offset = signed_offset; + } + + void SetRegister(RegisterInfo reg) { + info_type = eInfoTypeRegister; + info.reg = reg; } - lldb::ByteOrder - GetByteOrder () const - { - return m_arch.GetByteOrder(); + void SetImmediate(uint64_t immediate) { + info_type = eInfoTypeImmediate; + info.unsigned_immediate = immediate; } - const Opcode & - GetOpcode () const - { - return m_opcode; + void SetImmediateSigned(int64_t signed_immediate) { + info_type = eInfoTypeImmediateSigned; + info.signed_immediate = signed_immediate; } - - lldb::addr_t - GetAddress () const - { - return m_addr; + + void SetAddress(lldb::addr_t address) { + info_type = eInfoTypeAddress; + info.address = address; + } + void SetISAAndImmediate(uint32_t isa, uint32_t data) { + info_type = eInfoTypeISAAndImmediate; + info.ISAAndImmediate.isa = isa; + info.ISAAndImmediate.unsigned_data32 = data; } - - const ArchSpec & - GetArchitecture () const - { - return m_arch; + + void SetISAAndImmediateSigned(uint32_t isa, int32_t data) { + info_type = eInfoTypeISAAndImmediateSigned; + info.ISAAndImmediateSigned.isa = isa; + info.ISAAndImmediateSigned.signed_data32 = data; + } + + void SetISA(uint32_t isa) { + info_type = eInfoTypeISA; + info.isa = isa; } - static size_t - ReadMemoryFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - void *dst, - size_t length); - - static size_t - WriteMemoryFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - const void *dst, - size_t length); - - static bool - ReadRegisterFrame (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value); - - - static bool - WriteRegisterFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value); - - static size_t - ReadMemoryDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - void *dst, - size_t length); - - static size_t - WriteMemoryDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - const void *dst, - size_t length); - - static bool - ReadRegisterDefault (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value); - - - static bool - WriteRegisterDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value); - - void - SetBaton (void *baton); - - void - SetCallbacks (ReadMemoryCallback read_mem_callback, - WriteMemoryCallback write_mem_callback, - ReadRegisterCallback read_reg_callback, - WriteRegisterCallback write_reg_callback); - - void - SetReadMemCallback (ReadMemoryCallback read_mem_callback); - - void - SetWriteMemCallback (WriteMemoryCallback write_mem_callback); - - void - SetReadRegCallback (ReadRegisterCallback read_reg_callback); - - void - SetWriteRegCallback (WriteRegisterCallback write_reg_callback); - - static bool - GetBestRegisterKindAndNumber (const RegisterInfo *reg_info, - lldb::RegisterKind ®_kind, - uint32_t ®_num); - - static uint32_t - GetInternalRegisterNumber (RegisterContext *reg_ctx, - const RegisterInfo ®_info); + void SetNoArgs() { info_type = eInfoTypeNoArgs; } + + void Dump(Stream &s, EmulateInstruction *instruction) const; + }; + + typedef size_t (*ReadMemoryCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, void *dst, + size_t length); + + typedef size_t (*WriteMemoryCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, const void *dst, + size_t length); + + typedef bool (*ReadRegisterCallback)(EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + // Type to represent the condition of an instruction. The UINT32 value is + // reserved for the + // unconditional case and all other value can be used in an architecture + // dependent way. + typedef uint32_t InstructionCondition; + static const InstructionCondition UnconditionalCondition = UINT32_MAX; + + EmulateInstruction(const ArchSpec &arch); + + ~EmulateInstruction() override = default; + + //---------------------------------------------------------------------- + // Mandatory overrides + //---------------------------------------------------------------------- + virtual bool + SupportsEmulatingInstructionsOfType(InstructionType inst_type) = 0; + + virtual bool SetTargetTriple(const ArchSpec &arch) = 0; + + virtual bool ReadInstruction() = 0; + + virtual bool EvaluateInstruction(uint32_t evaluate_options) = 0; + + virtual InstructionCondition GetInstructionCondition() { + return UnconditionalCondition; + } + + virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) = 0; + + virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + RegisterInfo ®_info) = 0; + + //---------------------------------------------------------------------- + // Optional overrides + //---------------------------------------------------------------------- + virtual bool SetInstruction(const Opcode &insn_opcode, + const Address &inst_addr, Target *target); + + virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan); + + static const char *TranslateRegister(lldb::RegisterKind reg_kind, + uint32_t reg_num, std::string ®_name); + + //---------------------------------------------------------------------- + // RegisterInfo variants + //---------------------------------------------------------------------- + bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value); + + uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, + uint64_t fail_value, bool *success_ptr); + + bool WriteRegister(const Context &context, const RegisterInfo *ref_info, + const RegisterValue ®_value); + + bool WriteRegisterUnsigned(const Context &context, + const RegisterInfo *reg_info, uint64_t reg_value); + + //---------------------------------------------------------------------- + // Register kind and number variants + //---------------------------------------------------------------------- + bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, + RegisterValue ®_value); + + bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind, + uint32_t reg_num, const RegisterValue ®_value); + + uint64_t ReadRegisterUnsigned(lldb::RegisterKind reg_kind, uint32_t reg_num, + uint64_t fail_value, bool *success_ptr); + + bool WriteRegisterUnsigned(const Context &context, + lldb::RegisterKind reg_kind, uint32_t reg_num, + uint64_t reg_value); + + size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst, + size_t dst_len); + + 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); + + bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr, + uint64_t uval, size_t uval_byte_size); + + uint32_t GetAddressByteSize() const { return m_arch.GetAddressByteSize(); } + + lldb::ByteOrder GetByteOrder() const { return m_arch.GetByteOrder(); } + + const Opcode &GetOpcode() const { return m_opcode; } + + lldb::addr_t GetAddress() const { return m_addr; } + + const ArchSpec &GetArchitecture() const { return m_arch; } + + static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + void *dst, size_t length); + + static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + const void *dst, size_t length); + + static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + void *dst, size_t length); + + static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + const void *dst, size_t length); + + static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + void SetBaton(void *baton); + + void SetCallbacks(ReadMemoryCallback read_mem_callback, + WriteMemoryCallback write_mem_callback, + ReadRegisterCallback read_reg_callback, + WriteRegisterCallback write_reg_callback); + + void SetReadMemCallback(ReadMemoryCallback read_mem_callback); + + void SetWriteMemCallback(WriteMemoryCallback write_mem_callback); + + void SetReadRegCallback(ReadRegisterCallback read_reg_callback); + + void SetWriteRegCallback(WriteRegisterCallback write_reg_callback); + + static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, + lldb::RegisterKind ®_kind, + uint32_t ®_num); + + static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx, + const RegisterInfo ®_info); protected: - ArchSpec m_arch; - void * m_baton; - ReadMemoryCallback m_read_mem_callback; - WriteMemoryCallback m_write_mem_callback; - ReadRegisterCallback m_read_reg_callback; - WriteRegisterCallback m_write_reg_callback; - lldb::addr_t m_addr; - Opcode m_opcode; - + ArchSpec m_arch; + void *m_baton; + ReadMemoryCallback m_read_mem_callback; + WriteMemoryCallback m_write_mem_callback; + ReadRegisterCallback m_read_reg_callback; + WriteRegisterCallback m_write_reg_callback; + lldb::addr_t m_addr; + Opcode m_opcode; + private: - //------------------------------------------------------------------ - // For EmulateInstruction only - //------------------------------------------------------------------ - DISALLOW_COPY_AND_ASSIGN (EmulateInstruction); + //------------------------------------------------------------------ + // For EmulateInstruction only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN(EmulateInstruction); }; } // namespace lldb_private |