mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
379
IDEHelper/X86.h
Normal file
379
IDEHelper/X86.h
Normal file
|
@ -0,0 +1,379 @@
|
|||
#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 <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 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<char, 64> mAnnotationStr;
|
||||
llvm::raw_svector_ostream mAnnotationStream;
|
||||
static uint8 sRegForm[];
|
||||
|
||||
X86Instr() :
|
||||
mAnnotationStream(mAnnotationStr)
|
||||
{
|
||||
mX86 = 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(uint32* outImm);
|
||||
int GetJmpState(int flags);
|
||||
void MarkRegsUsed(Array<RegForm>& regsUsed, bool overrideForm);
|
||||
|
||||
uint32 GetTarget(X86CPURegisters* registers = NULL);
|
||||
};
|
||||
|
||||
class X86CPU
|
||||
{
|
||||
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:
|
||||
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<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_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
|
Loading…
Add table
Add a link
Reference in a new issue