File indexing completed on 2026-05-10 08:42:45
0001
0002
0003
0004
0005
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
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
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
0103 eContextReadOpcode,
0104
0105
0106
0107 eContextImmediate,
0108
0109
0110
0111 eContextPushRegisterOnStack,
0112
0113
0114
0115 eContextPopRegisterOffStack,
0116
0117
0118 eContextAdjustStackPointer,
0119
0120
0121 eContextSetFramePointer,
0122
0123
0124
0125 eContextRestoreStackPointer,
0126
0127
0128 eContextAdjustBaseRegister,
0129
0130
0131 eContextAdjustPC,
0132
0133
0134 eContextRegisterPlusOffset,
0135
0136
0137 eContextRegisterStore,
0138
0139 eContextRegisterLoad,
0140
0141
0142 eContextRelativeBranchImmediate,
0143
0144
0145 eContextAbsoluteBranchRegister,
0146
0147
0148
0149 eContextSupervisorCall,
0150
0151
0152
0153 eContextTableBranchReadMemory,
0154
0155
0156 eContextWriteRegisterRandomBits,
0157
0158
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;
0196 int64_t signed_offset;
0197 } RegisterPlusOffset;
0198
0199 struct RegisterPlusIndirectOffset {
0200 RegisterInfo base_reg;
0201 RegisterInfo offset_reg;
0202 } RegisterPlusIndirectOffset;
0203
0204 struct RegisterToRegisterPlusOffset {
0205 RegisterInfo data_reg;
0206 RegisterInfo base_reg;
0207 int64_t offset;
0208 } RegisterToRegisterPlusOffset;
0209
0210 struct RegisterToRegisterPlusIndirectOffset {
0211 RegisterInfo base_reg;
0212 RegisterInfo offset_reg;
0213 RegisterInfo data_reg;
0214 } RegisterToRegisterPlusIndirectOffset;
0215
0216 struct RegisterRegisterOperands {
0217 RegisterInfo
0218 operand1;
0219 RegisterInfo
0220 operand2;
0221 } RegisterRegisterOperands;
0222
0223 int64_t signed_offset;
0224
0225
0226 RegisterInfo reg;
0227
0228 uint64_t unsigned_immediate;
0229 int64_t signed_immediate;
0230
0231 lldb::addr_t address;
0232
0233 struct ISAAndImmediate {
0234 uint32_t isa;
0235 uint32_t unsigned_data32;
0236 } ISAAndImmediate;
0237
0238 struct ISAAndImmediateSigned {
0239 uint32_t isa;
0240 int32_t signed_data32;
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 ®_value);
0348
0349 typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction,
0350 void *baton, const Context &context,
0351 const RegisterInfo *reg_info,
0352 const RegisterValue ®_value);
0353
0354
0355
0356
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
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
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 ®_name);
0394
0395
0396 std::optional<RegisterValue> ReadRegister(const RegisterInfo ®_info);
0397
0398 uint64_t ReadRegisterUnsigned(const RegisterInfo ®_info,
0399 uint64_t fail_value, bool *success_ptr);
0400
0401 bool WriteRegister(const Context &context, const RegisterInfo &ref_info,
0402 const RegisterValue ®_value);
0403
0404 bool WriteRegisterUnsigned(const Context &context,
0405 const RegisterInfo ®_info, uint64_t reg_value);
0406
0407
0408 bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num,
0409 RegisterValue ®_value);
0410
0411 bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind,
0412 uint32_t reg_num, const RegisterValue ®_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 ®_value);
0455
0456 static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton,
0457 const Context &context,
0458 const RegisterInfo *reg_info,
0459 const RegisterValue ®_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 ®_value);
0472
0473 static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton,
0474 const Context &context,
0475 const RegisterInfo *reg_info,
0476 const RegisterValue ®_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 ®_kind,
0495 uint32_t ®_num);
0496
0497 static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx,
0498 const RegisterInfo ®_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
0512 EmulateInstruction(const EmulateInstruction &) = delete;
0513 const EmulateInstruction &operator=(const EmulateInstruction &) = delete;
0514 };
0515
0516 }
0517
0518 #endif