#pragma once #pragma warning(disable:4141) #pragma warning(disable:4146) #pragma warning(disable:4624) #pragma warning(disable:4996) #pragma warning(disable:4267) #pragma warning(disable:4244) #include "DebugCommon.h" #include "BeefySysLib/Common.h" #include #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 X86CPU; enum X86CPURegister { // integer general registers (DO NOT REORDER THESE; must exactly match DbgModule x86 register mappings) X86Reg_EAX = 0, X86Reg_ECX, X86Reg_EDX, X86Reg_EBX, X86Reg_ESP, X86Reg_EBP, X86Reg_ESI, X86Reg_EDI, X86Reg_EIP, X86Reg_EFL, // fpu registers (80-bit st(#) reg stack) X86Reg_FPST0, X86Reg_FPST1, X86Reg_FPST2, X86Reg_FPST3, X86Reg_FPST4, X86Reg_FPST5, X86Reg_FPST6, X86Reg_FPST7, // mmx registers (alias to the low 64 bits of the matching st(#) register) X86Reg_MM0, X86Reg_MM1, X86Reg_MM2, X86Reg_MM3, X86Reg_MM4, X86Reg_MM5, X86Reg_MM6, X86Reg_MM7, // xmm registers X86Reg_XMM00, X86Reg_XMM01, X86Reg_XMM02, X86Reg_XMM03, X86Reg_XMM10, X86Reg_XMM11, X86Reg_XMM12, X86Reg_XMM13, X86Reg_XMM20, X86Reg_XMM21, X86Reg_XMM22, X86Reg_XMM23, X86Reg_XMM30, X86Reg_XMM31, X86Reg_XMM32, X86Reg_XMM33, X86Reg_XMM40, X86Reg_XMM41, X86Reg_XMM42, X86Reg_XMM43, X86Reg_XMM50, X86Reg_XMM51, X86Reg_XMM52, X86Reg_XMM53, X86Reg_XMM60, X86Reg_XMM61, X86Reg_XMM62, X86Reg_XMM63, X86Reg_XMM70, X86Reg_XMM71, X86Reg_XMM72, X86Reg_XMM73, // 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) X86Reg_M128_XMM0, X86Reg_M128_XMM1, X86Reg_M128_XMM2, X86Reg_M128_XMM3, X86Reg_M128_XMM4, X86Reg_M128_XMM5, X86Reg_M128_XMM6, X86Reg_M128_XMM7, // flags boolean pseudo-registers (aliases to individual flags in EFL) X86Reg_FLAG_CF_CARRY, X86Reg_FLAG_PF_PARITY, X86Reg_FLAG_AF_ADJUST, X86Reg_FLAG_ZF_ZERO, X86Reg_FLAG_SF_SIGN, X86Reg_FLAG_IF_INTERRUPT, X86Reg_FLAG_DF_DIRECTION, X86Reg_FLAG_OF_OVERFLOW, // category macro-registers X86Reg_CAT_ALLREGS, X86Reg_CAT_IREGS, X86Reg_CAT_FPREGS, X86Reg_CAT_MMREGS, X86Reg_CAT_XMMREGS, X86Reg_CAT_FLAGS, X86Reg_COUNT, X86Reg_INTREG_FIRST = X86Reg_EAX, X86Reg_INTREG_LAST = X86Reg_EFL, X86Reg_INTREG_COUNT = (X86Reg_INTREG_LAST - X86Reg_INTREG_FIRST) + 1, X86Reg_FPSTREG_FIRST = X86Reg_FPST0, X86Reg_FPSTREG_LAST = X86Reg_FPST7, X86Reg_FPSTREG_COUNT = (X86Reg_FPSTREG_LAST - X86Reg_FPSTREG_FIRST) + 1, X86Reg_MMREG_FIRST = X86Reg_MM0, X86Reg_MMREG_LAST = X86Reg_MM7, X86Reg_MMREG_COUNT = (X86Reg_MMREG_LAST - X86Reg_MMREG_FIRST) + 1, X86Reg_XMMREG_FIRST = X86Reg_XMM00, X86Reg_XMMREG_LAST = X86Reg_XMM73, X86Reg_XMMREG_SINGLE_COUNT = (X86Reg_XMMREG_LAST - X86Reg_XMMREG_FIRST) + 1, X86Reg_M128_XMMREG_FIRST = X86Reg_M128_XMM0, X86Reg_M128_XMMREG_LAST = X86Reg_M128_XMM7, X86Reg_M128_XMMREG_COUNT = (X86Reg_M128_XMMREG_LAST - X86Reg_M128_XMMREG_FIRST) + 1, X86Reg_FLAG_FIRST = X86Reg_FLAG_CF_CARRY, X86Reg_FLAG_LAST = X86Reg_FLAG_OF_OVERFLOW, X86Reg_FLAG_COUNT = (X86Reg_FLAG_LAST - X86Reg_FLAG_FIRST) + 1, X86Reg_CAT_FIRST = X86Reg_CAT_ALLREGS, X86Reg_CAT_LAST = X86Reg_CAT_FLAGS, X86Reg_CAT_COUNT = (X86Reg_CAT_LAST - X86Reg_CAT_FIRST) + 1, }; #pragma pack(push, 1) class X86CPURegisters { public: static const int kNumIntRegs = 10; static const int kNumFpMmRegs = 8; static const int kNumXmmRegs = 8; struct IntRegs { int32 eax; int32 ecx; int32 edx; int32 ebx; uint32 esp; uint32 ebp; int32 esi; int32 edi; uint32 eip; int32 efl; }; 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 XmmIReg { int32 i[4]; }; union { IntRegs mIntRegs; int32 mIntRegsArray[kNumIntRegs]; }; FpMmReg mFpMmRegsArray[kNumFpMmRegs]; union { XmmReg mXmmRegsArray[kNumXmmRegs]; XmmDReg mXmmDRegsArray[kNumXmmRegs]; XmmIReg mXmmIRegsARray[kNumXmmRegs]; }; X86CPURegisters() { memset(&mIntRegs, 0, sizeof(mIntRegs)); memset(mFpMmRegsArray, 0, sizeof(mFpMmRegsArray)); memset(mXmmRegsArray, 0, sizeof(mXmmRegsArray)); } inline uint32 GetPC() { return mIntRegs.eip; } inline uint32* GetPCRegisterRef() { return &mIntRegs.eip; } inline uint32 GetSP() { return mIntRegs.esp; } inline uint32* GetSPRegisterRef() { return &mIntRegs.esp; } inline uint32 GetBP() { return mIntRegs.ebp; } inline uint32* GetBPRegisterRef() { return &mIntRegs.ebp; } inline XmmReg* GetXMMRegRef(int regNum) { return &mXmmRegsArray[regNum]; } inline int32* GetExceptionRegisterRef(int regNum) { return NULL; } static int GetFlagBitForRegister(int flagRegister) { int flagBit = -1; switch (flagRegister) { case X86Reg_FLAG_CF_CARRY: flagBit = 0; break; case X86Reg_FLAG_PF_PARITY: flagBit = 2; break; case X86Reg_FLAG_AF_ADJUST: flagBit = 4; break; case X86Reg_FLAG_ZF_ZERO: flagBit = 6; break; case X86Reg_FLAG_SF_SIGN: flagBit = 7; break; case X86Reg_FLAG_IF_INTERRUPT: flagBit = 9; break; case X86Reg_FLAG_DF_DIRECTION: flagBit = 10; break; case X86Reg_FLAG_OF_OVERFLOW: flagBit = 11; break; default: break; } return flagBit; } static int GetCompositeRegister(int regNum) { if ((regNum >= X86Reg_XMMREG_FIRST) && (regNum <= X86Reg_XMMREG_LAST)) return X86Reg_M128_XMMREG_FIRST + ((regNum - X86Reg_XMM00) / 4); return regNum; } static const char* sCPURegisterNames[]; static const char* GetRegisterName(int regNum) { return sCPURegisterNames[regNum]; } }; #pragma pack(pop) class X86Instr { public: X86CPU* mX86; llvm::MCInst mMCInst; uint32 mAddress; int mSize; llvm::SmallVector mAnnotationStr; llvm::raw_svector_ostream mAnnotationStream; static uint8 sRegForm[]; X86Instr() : mAnnotationStream(mAnnotationStr) { mX86 = NULL; mAddress = 0; mSize = 0; } int GetLength(); bool IsStackAdjust(); bool IsBranch(); bool IsCall(); bool IsRep(bool& isPrefixOnly); bool IsReturn(); bool IsLoadAddress(); bool GetIndexRegisterAndOffset(int* outRegister, int* outOffset); // IE: [ebp + 0x4] bool GetImmediate(uint32* outImm); int GetJmpState(int flags); void MarkRegsUsed(Array& regsUsed, bool overrideForm); uint32 GetTarget(X86CPURegisters* registers = NULL); }; class X86CPU { public: typedef std::multimap 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: X86CPU(); ~X86CPU(); bool Decode(uint32 address, DbgModuleMemoryCache* memoryCache, X86Instr* inst); bool Decode(uint32 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, X86Instr* inst); uint32 DecodeThunk(uint32 address, DbgModuleMemoryCache* memoryCache) { return 0; } bool IsReturnInstruction(X86Instr* inst); String InstructionToString(X86Instr* inst, uint32 addr); void GetNextPC(uint32 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, uint32* regs, uint32 nextPCs[2]); bool IsObjectAccessBreak(uint32 address, DbgModuleMemoryCache* memoryCache, int32* regs, int32* outObjectPtr); int GetOpcodesForMnemonic(const StringImpl& mnemonic, Array& outOpcodes); void GetClobbersForMnemonic(const StringImpl& mnemonic, int argCount, Array& outImplicitClobberRegNums, int& outClobberArgCount, bool& outMayClobberMem); bool ParseInlineAsmInstructionLLVM(const StringImpl&asmInst, String& outError); }; #ifdef BF_DBG_32 #define CPURegisters X86CPURegisters #define CPU X86CPU typedef X86Instr CPUInst; #define DwarfReg_SP X86Reg_ESP #define CPUReg_CAT_ALLREGS X86Reg_CAT_ALLREGS #define CPUReg_CAT_IREGS X86Reg_CAT_IREGS #define CPUReg_CAT_FPREGS X86Reg_CAT_FPREGS #define CPUReg_CAT_MMREGS X86Reg_CAT_MMREGS #define CPUReg_CAT_XMMREGS X86Reg_CAT_XMMREGS #define CPUReg_CAT_FLAGS X86Reg_CAT_FLAGS #define CPUReg_FLAG_CF_CARRY X86Reg_FLAG_CF_CARRY #define CPUReg_FLAG_PF_PARITY X86Reg_FLAG_PF_PARITY #define CPUReg_FLAG_AF_ADJUST X86Reg_FLAG_AF_ADJUST #define CPUReg_FLAG_ZF_ZERO X86Reg_FLAG_ZF_ZERO #define CPUReg_FLAG_SF_SIGN X86Reg_FLAG_SF_SIGN #define CPUReg_FLAG_IF_INTERRUPT X86Reg_FLAG_IF_INTERRUPT #define CPUReg_FLAG_DF_DIRECTION X86Reg_FLAG_DF_DIRECTION #define CPUReg_FLAG_OF_OVERFLOW X86Reg_FLAG_OF_OVERFLOW #define CPUReg_XMMREG_FIRST X86Reg_XMMREG_FIRST #define CPUReg_XMMREG_LAST X86Reg_XMMREG_LAST #define CPUReg_M128_XMMREG_FIRST X86Reg_M128_XMMREG_FIRST #define CPUReg_M128_XMMREG_LAST X86Reg_M128_XMMREG_LAST #define CPUReg_MMREG_FIRST X86Reg_MMREG_FIRST #define CPUReg_FPSTREG_FIRST X86Reg_FPSTREG_FIRST #endif static_assert(X86Reg_FPSTREG_COUNT == X86Reg_MMREG_COUNT, "CPUReg register count mismatch"); // these alias to the same regs static_assert(sizeof(X86CPURegisters::IntRegs) == X86CPURegisters::kNumIntRegs*sizeof(int32), "X86CPURegisters size mismatch"); static_assert(sizeof(X86CPURegisters) == (X86Reg_INTREG_COUNT*sizeof(int32) + X86Reg_MMREG_COUNT*sizeof(X86CPURegisters::FpMmReg) + (X86Reg_XMMREG_SINGLE_COUNT / 4)*sizeof(X86CPURegisters::XmmReg)), "X86CPURegisters size mismatch"); static_assert(offsetof(X86CPURegisters, mIntRegs) == 0, "X86CPURegisters layout mismatch"); static_assert(offsetof(X86CPURegisters::IntRegs, eax) == 0, "X86CPURegisters layout mismatch"); NS_BF_END