Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:45

0001 //===-- EmulateInstruction.h ------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_CORE_EMULATEINSTRUCTION_H
0010 #define LLDB_CORE_EMULATEINSTRUCTION_H
0011 
0012 #include <optional>
0013 #include <string>
0014 
0015 #include "lldb/Core/Address.h"
0016 #include "lldb/Core/Opcode.h"
0017 #include "lldb/Core/PluginInterface.h"
0018 #include "lldb/Utility/ArchSpec.h"
0019 #include "lldb/lldb-defines.h"
0020 #include "lldb/lldb-enumerations.h"
0021 #include "lldb/lldb-private-enumerations.h"
0022 #include "lldb/lldb-private-types.h"
0023 #include "lldb/lldb-types.h"
0024 
0025 #include <cstddef>
0026 #include <cstdint>
0027 
0028 namespace lldb_private {
0029 class OptionValueDictionary;
0030 class RegisterContext;
0031 class RegisterValue;
0032 class Stream;
0033 class Target;
0034 class UnwindPlan;
0035 
0036 /// \class EmulateInstruction EmulateInstruction.h
0037 /// "lldb/Core/EmulateInstruction.h"
0038 /// A class that allows emulation of CPU opcodes.
0039 ///
0040 /// This class is a plug-in interface that is accessed through the standard
0041 /// static FindPlugin function call in the EmulateInstruction class. The
0042 /// FindPlugin takes a target triple and returns a new object if there is a
0043 /// plug-in that supports the architecture and OS. Four callbacks and a baton
0044 /// are provided. The four callbacks are read register, write register, read
0045 /// memory and write memory.
0046 ///
0047 /// This class is currently designed for these main use cases: - Auto
0048 /// generation of Call Frame Information (CFI) from assembly code - Predicting
0049 /// single step breakpoint locations - Emulating instructions for breakpoint
0050 /// traps
0051 ///
0052 /// Objects can be asked to read an instruction which will cause a call to the
0053 /// read register callback to get the PC, followed by a read memory call to
0054 /// read the opcode. If ReadInstruction () returns true, then a call to
0055 /// EmulateInstruction::EvaluateInstruction () can be made. At this point the
0056 /// EmulateInstruction subclass will use all of the callbacks to emulate an
0057 /// instruction.
0058 ///
0059 /// Clients that provide the callbacks can either do the read/write
0060 /// registers/memory to actually emulate the instruction on a real or virtual
0061 /// CPU, or watch for the EmulateInstruction::Context which is context for the
0062 /// read/write register/memory which explains why the callback is being
0063 /// called. Examples of a context are: "pushing register 3 onto the stack at
0064 /// offset -12", or "adjusting stack pointer by -16". This extra context
0065 /// allows the generation of
0066 /// CFI information from assembly code without having to actually do
0067 /// the read/write register/memory.
0068 ///
0069 /// Clients must be prepared that not all instructions for an Instruction Set
0070 /// Architecture (ISA) will be emulated.
0071 ///
0072 /// Subclasses at the very least should implement the instructions that save
0073 /// and restore registers onto the stack and adjustment to the stack pointer.
0074 /// By just implementing a few instructions for an ISA that are the typical
0075 /// prologue opcodes, you can then generate CFI using a class that will soon
0076 /// be available.
0077 ///
0078 /// Implementing all of the instructions that affect the PC can then allow
0079 /// single step prediction support.
0080 ///
0081 /// Implementing all of the instructions allows for emulation of opcodes for
0082 /// breakpoint traps and will pave the way for "thread centric" debugging. The
0083 /// current debugging model is "process centric" where all threads must be
0084 /// stopped when any thread is stopped; when hitting software breakpoints we
0085 /// must disable the breakpoint by restoring the original breakpoint opcode,
0086 /// single stepping and restoring the breakpoint trap. If all threads were
0087 /// allowed to run then other threads could miss the breakpoint.
0088 ///
0089 /// This class centralizes the code that usually is done in separate code
0090 /// paths in a debugger (single step prediction, finding save restore
0091 /// locations of registers for unwinding stack frame variables) and emulating
0092 /// the instruction is just a bonus.
0093 
0094 class EmulateInstruction : public PluginInterface {
0095 public:
0096   static EmulateInstruction *FindPlugin(const ArchSpec &arch,
0097                                         InstructionType supported_inst_type,
0098                                         const char *plugin_name);
0099 
0100   enum ContextType {
0101     eContextInvalid = 0,
0102     // Read an instruction opcode from memory
0103     eContextReadOpcode,
0104 
0105     // Usually used for writing a register value whose source value is an
0106     // immediate
0107     eContextImmediate,
0108 
0109     // Exclusively used when saving a register to the stack as part of the
0110     // prologue
0111     eContextPushRegisterOnStack,
0112 
0113     // Exclusively used when restoring a register off the stack as part of the
0114     // epilogue
0115     eContextPopRegisterOffStack,
0116 
0117     // Add or subtract a value from the stack
0118     eContextAdjustStackPointer,
0119 
0120     // Adjust the frame pointer for the current frame
0121     eContextSetFramePointer,
0122 
0123     // Typically in an epilogue sequence.  Copy the frame pointer back into the
0124     // stack pointer, use SP for CFA calculations again.
0125     eContextRestoreStackPointer,
0126 
0127     // Add or subtract a value from a base address register (other than SP)
0128     eContextAdjustBaseRegister,
0129 
0130     // Add or subtract a value from the PC or store a value to the PC.
0131     eContextAdjustPC,
0132 
0133     // Used in WriteRegister callbacks to indicate where the
0134     eContextRegisterPlusOffset,
0135 
0136     // Used in WriteMemory callback to indicate where the data came from
0137     eContextRegisterStore,
0138 
0139     eContextRegisterLoad,
0140 
0141     // Used when performing a PC-relative branch where the
0142     eContextRelativeBranchImmediate,
0143 
0144     // Used when performing an absolute branch where the
0145     eContextAbsoluteBranchRegister,
0146 
0147     // Used when performing a supervisor call to an operating system to provide
0148     // a service:
0149     eContextSupervisorCall,
0150 
0151     // Used when performing a MemU operation to read the PC-relative offset
0152     // from an address.
0153     eContextTableBranchReadMemory,
0154 
0155     // Used when random bits are written into a register
0156     eContextWriteRegisterRandomBits,
0157 
0158     // Used when random bits are written to memory
0159     eContextWriteMemoryRandomBits,
0160 
0161     eContextArithmetic,
0162 
0163     eContextAdvancePC,
0164 
0165     eContextReturnFromException
0166   };
0167 
0168   enum InfoType {
0169     eInfoTypeRegisterPlusOffset,
0170     eInfoTypeRegisterPlusIndirectOffset,
0171     eInfoTypeRegisterToRegisterPlusOffset,
0172     eInfoTypeRegisterToRegisterPlusIndirectOffset,
0173     eInfoTypeRegisterRegisterOperands,
0174     eInfoTypeOffset,
0175     eInfoTypeRegister,
0176     eInfoTypeImmediate,
0177     eInfoTypeImmediateSigned,
0178     eInfoTypeAddress,
0179     eInfoTypeISAAndImmediate,
0180     eInfoTypeISAAndImmediateSigned,
0181     eInfoTypeISA,
0182     eInfoTypeNoArgs
0183   };
0184 
0185   struct Context {
0186     ContextType type = eContextInvalid;
0187 
0188   private:
0189     enum InfoType info_type = eInfoTypeNoArgs;
0190 
0191   public:
0192     enum InfoType GetInfoType() const { return info_type; }
0193     union ContextInfo {
0194       struct RegisterPlusOffset {
0195         RegisterInfo reg;      // base register
0196         int64_t signed_offset; // signed offset added to base register
0197       } RegisterPlusOffset;
0198 
0199       struct RegisterPlusIndirectOffset {
0200         RegisterInfo base_reg;   // base register number
0201         RegisterInfo offset_reg; // offset register kind
0202       } RegisterPlusIndirectOffset;
0203 
0204       struct RegisterToRegisterPlusOffset {
0205         RegisterInfo data_reg; // source/target register for data
0206         RegisterInfo base_reg; // base register for address calculation
0207         int64_t offset;        // offset for address calculation
0208       } RegisterToRegisterPlusOffset;
0209 
0210       struct RegisterToRegisterPlusIndirectOffset {
0211         RegisterInfo base_reg;   // base register for address calculation
0212         RegisterInfo offset_reg; // offset register for address calculation
0213         RegisterInfo data_reg;   // source/target register for data
0214       } RegisterToRegisterPlusIndirectOffset;
0215 
0216       struct RegisterRegisterOperands {
0217         RegisterInfo
0218             operand1; // register containing first operand for binary op
0219         RegisterInfo
0220             operand2; // register containing second operand for binary op
0221       } RegisterRegisterOperands;
0222 
0223       int64_t signed_offset; // signed offset by which to adjust self (for
0224                              // registers only)
0225 
0226       RegisterInfo reg; // plain register
0227 
0228       uint64_t unsigned_immediate; // unsigned immediate value
0229       int64_t signed_immediate;    // signed immediate value
0230 
0231       lldb::addr_t address; // direct address
0232 
0233       struct ISAAndImmediate {
0234         uint32_t isa;
0235         uint32_t unsigned_data32; // immediate data
0236       } ISAAndImmediate;
0237 
0238       struct ISAAndImmediateSigned {
0239         uint32_t isa;
0240         int32_t signed_data32; // signed immediate data
0241       } ISAAndImmediateSigned;
0242 
0243       uint32_t isa;
0244     } info;
0245     static_assert(std::is_trivial<ContextInfo>::value,
0246                   "ContextInfo must be trivial.");
0247 
0248     Context() = default;
0249 
0250     void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset) {
0251       info_type = eInfoTypeRegisterPlusOffset;
0252       info.RegisterPlusOffset.reg = base_reg;
0253       info.RegisterPlusOffset.signed_offset = signed_offset;
0254     }
0255 
0256     void SetRegisterPlusIndirectOffset(RegisterInfo base_reg,
0257                                        RegisterInfo offset_reg) {
0258       info_type = eInfoTypeRegisterPlusIndirectOffset;
0259       info.RegisterPlusIndirectOffset.base_reg = base_reg;
0260       info.RegisterPlusIndirectOffset.offset_reg = offset_reg;
0261     }
0262 
0263     void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg,
0264                                          RegisterInfo base_reg,
0265                                          int64_t offset) {
0266       info_type = eInfoTypeRegisterToRegisterPlusOffset;
0267       info.RegisterToRegisterPlusOffset.data_reg = data_reg;
0268       info.RegisterToRegisterPlusOffset.base_reg = base_reg;
0269       info.RegisterToRegisterPlusOffset.offset = offset;
0270     }
0271 
0272     void SetRegisterToRegisterPlusIndirectOffset(RegisterInfo base_reg,
0273                                                  RegisterInfo offset_reg,
0274                                                  RegisterInfo data_reg) {
0275       info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset;
0276       info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg;
0277       info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg;
0278       info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg;
0279     }
0280 
0281     void SetRegisterRegisterOperands(RegisterInfo op1_reg,
0282                                      RegisterInfo op2_reg) {
0283       info_type = eInfoTypeRegisterRegisterOperands;
0284       info.RegisterRegisterOperands.operand1 = op1_reg;
0285       info.RegisterRegisterOperands.operand2 = op2_reg;
0286     }
0287 
0288     void SetOffset(int64_t signed_offset) {
0289       info_type = eInfoTypeOffset;
0290       info.signed_offset = signed_offset;
0291     }
0292 
0293     void SetRegister(RegisterInfo reg) {
0294       info_type = eInfoTypeRegister;
0295       info.reg = reg;
0296     }
0297 
0298     void SetImmediate(uint64_t immediate) {
0299       info_type = eInfoTypeImmediate;
0300       info.unsigned_immediate = immediate;
0301     }
0302 
0303     void SetImmediateSigned(int64_t signed_immediate) {
0304       info_type = eInfoTypeImmediateSigned;
0305       info.signed_immediate = signed_immediate;
0306     }
0307 
0308     void SetAddress(lldb::addr_t address) {
0309       info_type = eInfoTypeAddress;
0310       info.address = address;
0311     }
0312     void SetISAAndImmediate(uint32_t isa, uint32_t data) {
0313       info_type = eInfoTypeISAAndImmediate;
0314       info.ISAAndImmediate.isa = isa;
0315       info.ISAAndImmediate.unsigned_data32 = data;
0316     }
0317 
0318     void SetISAAndImmediateSigned(uint32_t isa, int32_t data) {
0319       info_type = eInfoTypeISAAndImmediateSigned;
0320       info.ISAAndImmediateSigned.isa = isa;
0321       info.ISAAndImmediateSigned.signed_data32 = data;
0322     }
0323 
0324     void SetISA(uint32_t isa) {
0325       info_type = eInfoTypeISA;
0326       info.isa = isa;
0327     }
0328 
0329     void SetNoArgs() { info_type = eInfoTypeNoArgs; }
0330 
0331     void Dump(Stream &s, EmulateInstruction *instruction) const;
0332   };
0333 
0334   typedef size_t (*ReadMemoryCallback)(EmulateInstruction *instruction,
0335                                        void *baton, const Context &context,
0336                                        lldb::addr_t addr, void *dst,
0337                                        size_t length);
0338 
0339   typedef size_t (*WriteMemoryCallback)(EmulateInstruction *instruction,
0340                                         void *baton, const Context &context,
0341                                         lldb::addr_t addr, const void *dst,
0342                                         size_t length);
0343 
0344   typedef bool (*ReadRegisterCallback)(EmulateInstruction *instruction,
0345                                        void *baton,
0346                                        const RegisterInfo *reg_info,
0347                                        RegisterValue &reg_value);
0348 
0349   typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction,
0350                                         void *baton, const Context &context,
0351                                         const RegisterInfo *reg_info,
0352                                         const RegisterValue &reg_value);
0353 
0354   // Type to represent the condition of an instruction. The UINT32 value is
0355   // reserved for the unconditional case and all other value can be used in an
0356   // architecture dependent way.
0357   typedef uint32_t InstructionCondition;
0358   static const InstructionCondition UnconditionalCondition = UINT32_MAX;
0359 
0360   EmulateInstruction(const ArchSpec &arch);
0361 
0362   ~EmulateInstruction() override = default;
0363 
0364   // Mandatory overrides
0365   virtual bool
0366   SupportsEmulatingInstructionsOfType(InstructionType inst_type) = 0;
0367 
0368   virtual bool SetTargetTriple(const ArchSpec &arch) = 0;
0369 
0370   virtual bool ReadInstruction() = 0;
0371 
0372   virtual std::optional<uint32_t> GetLastInstrSize() { return std::nullopt; }
0373 
0374   virtual bool EvaluateInstruction(uint32_t evaluate_options) = 0;
0375 
0376   virtual InstructionCondition GetInstructionCondition() {
0377     return UnconditionalCondition;
0378   }
0379 
0380   virtual bool TestEmulation(Stream &out_stream, ArchSpec &arch,
0381                              OptionValueDictionary *test_data) = 0;
0382 
0383   virtual std::optional<RegisterInfo>
0384   GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) = 0;
0385 
0386   // Optional overrides
0387   virtual bool SetInstruction(const Opcode &insn_opcode,
0388                               const Address &inst_addr, Target *target);
0389 
0390   virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan);
0391 
0392   static const char *TranslateRegister(lldb::RegisterKind reg_kind,
0393                                        uint32_t reg_num, std::string &reg_name);
0394 
0395   // RegisterInfo variants
0396   std::optional<RegisterValue> ReadRegister(const RegisterInfo &reg_info);
0397 
0398   uint64_t ReadRegisterUnsigned(const RegisterInfo &reg_info,
0399                                 uint64_t fail_value, bool *success_ptr);
0400 
0401   bool WriteRegister(const Context &context, const RegisterInfo &ref_info,
0402                      const RegisterValue &reg_value);
0403 
0404   bool WriteRegisterUnsigned(const Context &context,
0405                              const RegisterInfo &reg_info, uint64_t reg_value);
0406 
0407   // Register kind and number variants
0408   bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num,
0409                     RegisterValue &reg_value);
0410 
0411   bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind,
0412                      uint32_t reg_num, const RegisterValue &reg_value);
0413 
0414   uint64_t ReadRegisterUnsigned(lldb::RegisterKind reg_kind, uint32_t reg_num,
0415                                 uint64_t fail_value, bool *success_ptr);
0416 
0417   bool WriteRegisterUnsigned(const Context &context,
0418                              lldb::RegisterKind reg_kind, uint32_t reg_num,
0419                              uint64_t reg_value);
0420 
0421   size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst,
0422                     size_t dst_len);
0423 
0424   uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr,
0425                               size_t byte_size, uint64_t fail_value,
0426                               bool *success_ptr);
0427 
0428   bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src,
0429                    size_t src_len);
0430 
0431   bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr,
0432                            uint64_t uval, size_t uval_byte_size);
0433 
0434   uint32_t GetAddressByteSize() const { return m_arch.GetAddressByteSize(); }
0435 
0436   lldb::ByteOrder GetByteOrder() const { return m_arch.GetByteOrder(); }
0437 
0438   const Opcode &GetOpcode() const { return m_opcode; }
0439 
0440   lldb::addr_t GetAddress() const { return m_addr; }
0441 
0442   const ArchSpec &GetArchitecture() const { return m_arch; }
0443 
0444   static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton,
0445                                 const Context &context, lldb::addr_t addr,
0446                                 void *dst, size_t length);
0447 
0448   static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton,
0449                                  const Context &context, lldb::addr_t addr,
0450                                  const void *dst, size_t length);
0451 
0452   static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton,
0453                                 const RegisterInfo *reg_info,
0454                                 RegisterValue &reg_value);
0455 
0456   static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton,
0457                                  const Context &context,
0458                                  const RegisterInfo *reg_info,
0459                                  const RegisterValue &reg_value);
0460 
0461   static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton,
0462                                   const Context &context, lldb::addr_t addr,
0463                                   void *dst, size_t length);
0464 
0465   static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton,
0466                                    const Context &context, lldb::addr_t addr,
0467                                    const void *dst, size_t length);
0468 
0469   static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton,
0470                                   const RegisterInfo *reg_info,
0471                                   RegisterValue &reg_value);
0472 
0473   static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton,
0474                                    const Context &context,
0475                                    const RegisterInfo *reg_info,
0476                                    const RegisterValue &reg_value);
0477 
0478   void SetBaton(void *baton);
0479 
0480   void SetCallbacks(ReadMemoryCallback read_mem_callback,
0481                     WriteMemoryCallback write_mem_callback,
0482                     ReadRegisterCallback read_reg_callback,
0483                     WriteRegisterCallback write_reg_callback);
0484 
0485   void SetReadMemCallback(ReadMemoryCallback read_mem_callback);
0486 
0487   void SetWriteMemCallback(WriteMemoryCallback write_mem_callback);
0488 
0489   void SetReadRegCallback(ReadRegisterCallback read_reg_callback);
0490 
0491   void SetWriteRegCallback(WriteRegisterCallback write_reg_callback);
0492 
0493   static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info,
0494                                            lldb::RegisterKind &reg_kind,
0495                                            uint32_t &reg_num);
0496 
0497   static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx,
0498                                             const RegisterInfo &reg_info);
0499 
0500 protected:
0501   ArchSpec m_arch;
0502   void *m_baton = nullptr;
0503   ReadMemoryCallback m_read_mem_callback = &ReadMemoryDefault;
0504   WriteMemoryCallback m_write_mem_callback = &WriteMemoryDefault;
0505   ReadRegisterCallback m_read_reg_callback = &ReadRegisterDefault;
0506   WriteRegisterCallback m_write_reg_callback = &WriteRegisterDefault;
0507   lldb::addr_t m_addr = LLDB_INVALID_ADDRESS;
0508   Opcode m_opcode;
0509 
0510 private:
0511   // For EmulateInstruction only
0512   EmulateInstruction(const EmulateInstruction &) = delete;
0513   const EmulateInstruction &operator=(const EmulateInstruction &) = delete;
0514 };
0515 
0516 } // namespace lldb_private
0517 
0518 #endif // LLDB_CORE_EMULATEINSTRUCTION_H