123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- #pragma once
- #pragma warning(disable:4141)
- #pragma warning(disable:4624)
- #pragma warning(disable:4996)
- #pragma warning(disable:4267)
- #pragma warning(disable:4244)
- #include "DebugCommon.h"
- #include "BeefySysLib/Common.h"
- #include <sstream>
- #include "llvm/MC/MCInst.h"
- #include "llvm/MC/MCInstPrinter.h"
- #include "llvm/Support/raw_ostream.h"
- #include "CPU.h"
- #include "Debugger.h"
- namespace llvm
- {
- class MCSubtargetInfo;
- class MCRegisterInfo;
- class MCDisassembler;
- class MCInst;
- class MCInstrInfo;
- class MCAsmInfo;
- class MCContext;
- class MCObjectFileInfo;
- }
- NS_BF_BEGIN
- class X64CPU;
- enum X64CPURegister
- {
- X64Reg_None = -1,
- // integer general registers (DO NOT REORDER THESE; must exactly match DbgModule X64 register mappings)
- X64Reg_RAX = 0,
- X64Reg_RDX,
- X64Reg_RCX,
- X64Reg_RBX,
- X64Reg_RSI,
- X64Reg_RDI,
- X64Reg_RBP,
- X64Reg_RSP,
- X64Reg_R8,
- X64Reg_R9,
- X64Reg_R10,
- X64Reg_R11,
- X64Reg_R12,
- X64Reg_R13,
- X64Reg_R14,
- X64Reg_R15,
- X64Reg_RIP,
- X64Reg_EFL,
- X64Reg_GS,
- X64Reg_EAX,
- X64Reg_EDX,
- X64Reg_ECX,
- X64Reg_EBX,
- X64Reg_ESI,
- X64Reg_EDI,
- X64Reg_R8D,
- X64Reg_R9D,
- X64Reg_R10D,
- X64Reg_R11D,
- X64Reg_R12D,
- X64Reg_R13D,
- X64Reg_R14D,
- X64Reg_R15D,
- X64Reg_AX,
- X64Reg_DX,
- X64Reg_CX,
- X64Reg_BX,
- X64Reg_SI,
- X64Reg_DI,
- X64Reg_R8W,
- X64Reg_R9W,
- X64Reg_R10W,
- X64Reg_R11W,
- X64Reg_R12W,
- X64Reg_R13W,
- X64Reg_R14W,
- X64Reg_R15W,
- X64Reg_AL,
- X64Reg_DL,
- X64Reg_CL,
- X64Reg_BL,
- X64Reg_AH,
- X64Reg_DH,
- X64Reg_CH,
- X64Reg_BH,
- X64Reg_SIL,
- X64Reg_DIL,
- X64Reg_R8B,
- X64Reg_R9B,
- X64Reg_R10B,
- X64Reg_R11B,
- X64Reg_R12B,
- X64Reg_R13B,
- X64Reg_R14B,
- X64Reg_R15B,
- // fpu registers (80-bit st(#) reg stack)
- X64Reg_FPST0,
- X64Reg_FPST1,
- X64Reg_FPST2,
- X64Reg_FPST3,
- X64Reg_FPST4,
- X64Reg_FPST5,
- X64Reg_FPST6,
- X64Reg_FPST7,
- // mmx registers (alias to the low 64 bits of the matching st(#) register)
- X64Reg_MM0,
- X64Reg_MM1,
- X64Reg_MM2,
- X64Reg_MM3,
- X64Reg_MM4,
- X64Reg_MM5,
- X64Reg_MM6,
- X64Reg_MM7,
- // XMM registers, using first element as a double
- X64Reg_XMM0_f64,
- X64Reg_XMM1_f64,
- X64Reg_XMM2_f64,
- X64Reg_XMM3_f64,
- X64Reg_XMM4_f64,
- X64Reg_XMM5_f64,
- X64Reg_XMM6_f64,
- X64Reg_XMM7_f64,
- X64Reg_XMM8_f64,
- X64Reg_XMM9_f64,
- X64Reg_XMM10_f64,
- X64Reg_XMM11_f64,
- X64Reg_XMM12_f64,
- X64Reg_XMM13_f64,
- X64Reg_XMM14_f64,
- X64Reg_XMM15_f64,
- // XMM registers, using first element as a float
- X64Reg_XMM0_f32,
- X64Reg_XMM1_f32,
- X64Reg_XMM2_f32,
- X64Reg_XMM3_f32,
- X64Reg_XMM4_f32,
- X64Reg_XMM5_f32,
- X64Reg_XMM6_f32,
- X64Reg_XMM7_f32,
- X64Reg_XMM8_f32,
- X64Reg_XMM9_f32,
- X64Reg_XMM10_f32,
- X64Reg_XMM11_f32,
- X64Reg_XMM12_f32,
- X64Reg_XMM13_f32,
- X64Reg_XMM14_f32,
- X64Reg_XMM15_f32,
- // xmm registers
- X64Reg_XMM00,
- X64Reg_XMM01,
- X64Reg_XMM02,
- X64Reg_XMM03,
- X64Reg_XMM10,
- X64Reg_XMM11,
- X64Reg_XMM12,
- X64Reg_XMM13,
- X64Reg_XMM20,
- X64Reg_XMM21,
- X64Reg_XMM22,
- X64Reg_XMM23,
- X64Reg_XMM30,
- X64Reg_XMM31,
- X64Reg_XMM32,
- X64Reg_XMM33,
- X64Reg_XMM40,
- X64Reg_XMM41,
- X64Reg_XMM42,
- X64Reg_XMM43,
- X64Reg_XMM50,
- X64Reg_XMM51,
- X64Reg_XMM52,
- X64Reg_XMM53,
- X64Reg_XMM60,
- X64Reg_XMM61,
- X64Reg_XMM62,
- X64Reg_XMM63,
- X64Reg_XMM70,
- X64Reg_XMM71,
- X64Reg_XMM72,
- X64Reg_XMM73,
- X64Reg_XMM80,
- X64Reg_XMM81,
- X64Reg_XMM82,
- X64Reg_XMM83,
- X64Reg_XMM90,
- X64Reg_XMM91,
- X64Reg_XMM92,
- X64Reg_XMM93,
- X64Reg_XMM10_0,
- X64Reg_XMM10_1,
- X64Reg_XMM10_2,
- X64Reg_XMM10_3,
- X64Reg_XMM11_0,
- X64Reg_XMM11_1,
- X64Reg_XMM11_2,
- X64Reg_XMM11_3,
- X64Reg_XMM12_0,
- X64Reg_XMM12_1,
- X64Reg_XMM12_2,
- X64Reg_XMM12_3,
- X64Reg_XMM13_0,
- X64Reg_XMM13_1,
- X64Reg_XMM13_2,
- X64Reg_XMM13_3,
- X64Reg_XMM14_0,
- X64Reg_XMM14_1,
- X64Reg_XMM14_2,
- X64Reg_XMM14_3,
- X64Reg_XMM15_0,
- X64Reg_XMM15_1,
- X64Reg_XMM15_2,
- X64Reg_XMM15_3,
- // xmm 128-bit macro-registers (no stored data with these, they're symbolic for use as higher-level constructs, aliases to the individual xmm regs above)
- X64Reg_M128_XMM0,
- X64Reg_M128_XMM1,
- X64Reg_M128_XMM2,
- X64Reg_M128_XMM3,
- X64Reg_M128_XMM4,
- X64Reg_M128_XMM5,
- X64Reg_M128_XMM6,
- X64Reg_M128_XMM7,
- X64Reg_M128_XMM8,
- X64Reg_M128_XMM9,
- X64Reg_M128_XMM10,
- X64Reg_M128_XMM11,
- X64Reg_M128_XMM12,
- X64Reg_M128_XMM13,
- X64Reg_M128_XMM14,
- X64Reg_M128_XMM15,
- // flags boolean pseudo-registers (aliases to individual flags in EFL)
- X64Reg_FLAG_CF_CARRY,
- X64Reg_FLAG_PF_PARITY,
- X64Reg_FLAG_AF_ADJUST,
- X64Reg_FLAG_ZF_ZERO,
- X64Reg_FLAG_SF_SIGN,
- X64Reg_FLAG_IF_INTERRUPT,
- X64Reg_FLAG_DF_DIRECTION,
- X64Reg_FLAG_OF_OVERFLOW,
- // category macro-registers
- X64Reg_CAT_ALLREGS,
- X64Reg_CAT_IREGS,
- X64Reg_CAT_FPREGS,
- X64Reg_CAT_MMREGS,
- X64Reg_CAT_XMMREGS,
- X64Reg_CAT_FLAGS,
- X64Reg_COUNT,
- X64Reg_INTREG_FIRST = X64Reg_RAX,
- X64Reg_INTREG_LAST = X64Reg_GS,
- X64Reg_INTREG_COUNT = (X64Reg_INTREG_LAST - X64Reg_INTREG_FIRST) + 1,
- X64Reg_FPSTREG_FIRST = X64Reg_FPST0,
- X64Reg_FPSTREG_LAST = X64Reg_FPST7,
- X64Reg_FPSTREG_COUNT = (X64Reg_FPSTREG_LAST - X64Reg_FPSTREG_FIRST) + 1,
- X64Reg_MMREG_FIRST = X64Reg_MM0,
- X64Reg_MMREG_LAST = X64Reg_MM7,
- X64Reg_MMREG_COUNT = (X64Reg_MMREG_LAST - X64Reg_MMREG_FIRST) + 1,
- X64Reg_XMMREG_FIRST = X64Reg_XMM00,
- X64Reg_XMMREG_LAST = X64Reg_XMM15_3,
- X64Reg_XMMREG_SINGLE_COUNT = (X64Reg_XMMREG_LAST - X64Reg_XMMREG_FIRST) + 1,
- X64Reg_M128_XMMREG_FIRST = X64Reg_M128_XMM0,
- X64Reg_M128_XMMREG_LAST = X64Reg_M128_XMM15,
- X64Reg_M128_XMMREG_COUNT = (X64Reg_M128_XMMREG_LAST - X64Reg_M128_XMMREG_FIRST) + 1,
- X64Reg_FLAG_FIRST = X64Reg_FLAG_CF_CARRY,
- X64Reg_FLAG_LAST = X64Reg_FLAG_OF_OVERFLOW,
- X64Reg_FLAG_COUNT = (X64Reg_FLAG_LAST - X64Reg_FLAG_FIRST) + 1,
- X64Reg_CAT_FIRST = X64Reg_CAT_ALLREGS,
- X64Reg_CAT_LAST = X64Reg_CAT_FLAGS,
- X64Reg_CAT_COUNT = (X64Reg_CAT_LAST - X64Reg_CAT_FIRST) + 1,
- };
- #pragma pack(push, 1)
- class X64CPURegisters
- {
- public:
- static const int kNumIntRegs = 19;
- static const int kNumFpMmRegs = 8;
- static const int kNumXmmRegs = 16;
- struct IntRegs
- {
- int64 rax;
- int64 rdx;
- int64 rcx;
- int64 rbx;
- int64 rsi;
- int64 rdi;
- uint64 rbp;
- uint64 rsp;
- int64 r8;
- int64 r9;
- int64 r10;
- int64 r11;
- int64 r12;
- int64 r13;
- int64 r14;
- int64 r15;
- uint64 rip;
- int64 efl; // Really just int32
- int64 gs; // For TLS
- };
- struct Fp80Reg
- {
- uint8 fp80[10]; // 80-bit FP value, must be down-converted to use as a double
- };
- union FpMmReg
- {
- Fp80Reg fp;
- int64 mm;
- };
- struct XmmReg
- {
- float f[4];
- };
- struct XmmDReg
- {
- double d[2];
- };
- struct XmmI32Reg
- {
- int32 i[4];
- };
- struct XmmI64Reg
- {
- int64 i[2];
- };
- union
- {
- IntRegs mIntRegs;
- int64 mIntRegsArray[kNumIntRegs];
- };
- FpMmReg mFpMmRegsArray[kNumFpMmRegs];
- union
- {
- XmmReg mXmmRegsArray[kNumXmmRegs];
- XmmDReg mXmmDRegsArray[kNumXmmRegs];
- XmmI32Reg mXmmI32RegsARray[kNumXmmRegs];
- XmmI64Reg mXmmI64RegsARray[kNumXmmRegs];
- };
- X64CPURegisters()
- {
- memset(&mIntRegs, 0, sizeof(mIntRegs));
- memset(mFpMmRegsArray, 0, sizeof(mFpMmRegsArray));
- memset(mXmmRegsArray, 0, sizeof(mXmmRegsArray));
- }
- inline uint64 GetPC() { return mIntRegs.rip; }
- inline uint64* GetPCRegisterRef() { return &mIntRegs.rip; }
- inline uint64 GetSP() { return mIntRegs.rsp; }
- inline uint64* GetSPRegisterRef() { return &mIntRegs.rsp; }
- inline uint64 GetBP() { return mIntRegs.rbp; }
- inline uint64* GetBPRegisterRef() { return &mIntRegs.rbp; }
- inline XmmReg* GetXMMRegRef(int regNum)
- {
- return &mXmmRegsArray[regNum];
- }
- inline int64* GetExceptionRegisterRef(int regNum)
- {
- int regRemapping[] =
- { X64Reg_RAX,
- X64Reg_RCX,
- X64Reg_RDX,
- X64Reg_RBX,
- X64Reg_RSP,
- X64Reg_RBP,
- X64Reg_RSI,
- X64Reg_RDI,
- X64Reg_R8,
- X64Reg_R9,
- X64Reg_R10,
- X64Reg_R11,
- X64Reg_R12,
- X64Reg_R13,
- X64Reg_R14,
- X64Reg_R15,
- X64Reg_RIP,
- X64Reg_EFL };
- return &mIntRegsArray[regRemapping[regNum]];
- }
- static int GetFlagBitForRegister(int flagRegister)
- {
- int flagBit = -1;
- switch (flagRegister)
- {
- case X64Reg_FLAG_CF_CARRY: flagBit = 0; break;
- case X64Reg_FLAG_PF_PARITY: flagBit = 2; break;
- case X64Reg_FLAG_AF_ADJUST: flagBit = 4; break;
- case X64Reg_FLAG_ZF_ZERO: flagBit = 6; break;
- case X64Reg_FLAG_SF_SIGN: flagBit = 7; break;
- case X64Reg_FLAG_IF_INTERRUPT: flagBit = 9; break;
- case X64Reg_FLAG_DF_DIRECTION: flagBit = 10; break;
- case X64Reg_FLAG_OF_OVERFLOW: flagBit = 11; break;
- default: break;
- }
- return flagBit;
- }
- static int GetCompositeRegister(int regNum)
- {
- if ((regNum >= X64Reg_XMMREG_FIRST) && (regNum <= X64Reg_XMMREG_LAST))
- return X64Reg_M128_XMMREG_FIRST + ((regNum - X64Reg_XMM00) / 4);
- return regNum;
- }
- static const char* sCPURegisterNames[];
- static const char* GetRegisterName(int regNum)
- {
- return sCPURegisterNames[regNum + 1];
- }
- };
- #pragma pack(pop)
- class X64Instr
- {
- public:
- X64CPU* mX64;
- llvm::MCInst mMCInst;
- uint64 mAddress;
- int mSize;
- llvm::SmallVector<char, 64> mAnnotationStr;
- llvm::raw_svector_ostream mAnnotationStream;
- //static uint8 sRegForm[];
- X64Instr() :
- mAnnotationStream(mAnnotationStr)
- {
- mX64 = NULL;
- mAddress = 0;
- mSize = 0;
- }
- int GetLength();
- bool IsBranch();
- bool IsCall();
- bool IsRep(bool& isPrefixOnly);
- bool IsReturn();
- bool IsLoadAddress();
- bool GetIndexRegisterAndOffset(int* outRegister, int* outOffset); // IE: [ebp + 0x4]
- bool GetImmediate(uint64* outImm);
- int GetJmpState(int flags);
- void MarkRegsUsed(Array<RegForm>& regsUsed, bool overrideForm);
- uint64 GetTarget(Debugger* debugger = NULL, X64CPURegisters* registers = NULL);
- bool PartialSimulate(Debugger* debugger, X64CPURegisters* registers);
- };
- class X64CPU
- {
- public:
- typedef std::multimap<String, int> StringToOpcodeMap;
- llvm::MCContext* mMCContext;
- llvm::MCObjectFileInfo* mMCObjectFileInfo;
- llvm::MCSubtargetInfo* mSubtargetInfo;
- llvm::MCRegisterInfo* mRegisterInfo;
- llvm::MCAsmInfo* mAsmInfo;
- llvm::MCInstPrinter* mInstPrinter;
- llvm::MCDisassembler* mDisAsm;
- llvm::MCInstrInfo* mInstrInfo;
- String mWarningString;
- std::stringstream mWarningStream;
- String mCommentString;
- std::stringstream mCommentStream;
- StringToOpcodeMap mStringToOpcodeMap;
- public:
- X64CPU();
- ~X64CPU();
- bool Decode(uint64 address, DbgModuleMemoryCache* memoryCache, X64Instr* inst);
- bool Decode(uint64 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, X64Instr* inst);
- uint64 DecodeThunk(uint64 address, DbgModuleMemoryCache* memoryCache);
- bool IsReturnInstruction(X64Instr* inst);
- String InstructionToString(X64Instr* inst, uint64 addr);
- void GetNextPC(uint64 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, uint32* regs, uint64 nextPCs[2]);
- DbgBreakKind GetDbgBreakKind(uint64 address, DbgModuleMemoryCache* memoryCache, int64* regs, int64* outObjectPtr);
- int GetOpcodesForMnemonic(const StringImpl& mnemonic, Array<int>& outOpcodes);
- void GetClobbersForMnemonic(const StringImpl& mnemonic, int argCount, Array<int>& outImplicitClobberRegNums, int& outClobberArgCount, bool& outMayClobberMem);
- bool ParseInlineAsmInstructionLLVM(const StringImpl&asmInst, String& outError);
- };
- #ifdef BF_DBG_64
- #define CPURegisters X64CPURegisters
- #define CPU X64CPU
- typedef X64Instr CPUInst;
- #define DwarfReg_SP X64Reg_RSP
- #define CPUReg_CAT_ALLREGS X64Reg_CAT_ALLREGS
- #define CPUReg_CAT_IREGS X64Reg_CAT_IREGS
- #define CPUReg_CAT_FPREGS X64Reg_CAT_FPREGS
- #define CPUReg_CAT_MMREGS X64Reg_CAT_MMREGS
- #define CPUReg_CAT_XMMREGS X64Reg_CAT_XMMREGS
- #define CPUReg_CAT_FLAGS X64Reg_CAT_FLAGS
- #define CPUReg_FLAG_CF_CARRY X64Reg_FLAG_CF_CARRY
- #define CPUReg_FLAG_PF_PARITY X64Reg_FLAG_PF_PARITY
- #define CPUReg_FLAG_AF_ADJUST X64Reg_FLAG_AF_ADJUST
- #define CPUReg_FLAG_ZF_ZERO X64Reg_FLAG_ZF_ZERO
- #define CPUReg_FLAG_SF_SIGN X64Reg_FLAG_SF_SIGN
- #define CPUReg_FLAG_IF_INTERRUPT X64Reg_FLAG_IF_INTERRUPT
- #define CPUReg_FLAG_DF_DIRECTION X64Reg_FLAG_DF_DIRECTION
- #define CPUReg_FLAG_OF_OVERFLOW X64Reg_FLAG_OF_OVERFLOW
- #define CPUReg_XMMREG_FIRST X64Reg_XMMREG_FIRST
- #define CPUReg_XMMREG_LAST X64Reg_XMMREG_LAST
- #define CPUReg_M128_XMMREG_FIRST X64Reg_M128_XMMREG_FIRST
- #define CPUReg_M128_XMMREG_LAST X64Reg_M128_XMMREG_LAST
- #define CPUReg_MMREG_FIRST X64Reg_MMREG_FIRST
- #define CPUReg_FPSTREG_FIRST X64Reg_FPSTREG_FIRST
- #endif
- static_assert(X64Reg_FPSTREG_COUNT == X64Reg_MMREG_COUNT, "CPUReg register count mismatch"); // these alias to the same regs
- static_assert(sizeof(X64CPURegisters::IntRegs) == X64CPURegisters::kNumIntRegs*sizeof(int64), "X64CPURegisters size mismatch");
- static_assert(sizeof(X64CPURegisters) == (X64Reg_INTREG_COUNT*sizeof(int64) + X64Reg_MMREG_COUNT*sizeof(X64CPURegisters::FpMmReg) + (X64Reg_XMMREG_SINGLE_COUNT / 4)*sizeof(X64CPURegisters::XmmReg)), "X64CPURegisters size mismatch");
- static_assert(offsetof(X64CPURegisters, mIntRegs) == 0, "X64CPURegisters layout mismatch");
- static_assert(offsetof(X64CPURegisters::IntRegs, rax) == 0, "X64CPURegisters layout mismatch");
- NS_BF_END
|