1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183 |
- #pragma warning(push)
- #pragma warning(disable:4996)
- #pragma warning(disable:4800)
- #pragma warning(disable:4244)
- #pragma warning(disable:4005)
- #pragma warning(disable:4267)
- #pragma warning(disable:4146)
- #include "X64.h"
- #include "X86.h"
- #include <assert.h>
- #include "llvm/Support/AlignOf.h"
- #include "llvm/Support/FormattedStream.h"
- #include "llvm/Support/SourceMgr.h"
- #include "llvm/MC/MCContext.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Support/TargetRegistry.h"
- #include "llvm/IR/InlineAsm.h"
- //#include "llvm/Support/MemoryObject.h"
- #include "llvm/Target/TargetOptions.h"
- #include "llvm/Target/TargetMachine.h"
- //#include "llvm/Target/TargetSubtargetInfo.h"
- //#include "llvm/Target/TargetInstrInfo.h"
- #include "llvm/MC/MCAsmInfo.h"
- #include "llvm/MC/MCStreamer.h"
- #include "llvm/MC/MCParser/MCAsmParser.h"
- #include "llvm/MC/MCParser/MCTargetAsmParser.h"
- #include "llvm/MC/MCObjectFileInfo.h"
- #include "llvm/MC/MCDisassembler/MCDisassembler.h"
- #include "X86/Disassembler/X86DisassemblerDecoder.h"
- #include "X86/MCTargetDesc/X86MCTargetDesc.h"
- #include "X86/MCTargetDesc/X86BaseInfo.h"
- #include "X86InstrInfo.h"
- #include "BeefySysLib/util/HashSet.h"
- #include "../../llvm/lib/Target/X86/TargetInfo/X86TargetInfo.h"
- #pragma warning(pop)
- #include "BeefySysLib/util/AllocDebug.h"
- //#include "Support/TargetSelect.h"
- //int arch_8086_disasm_instr(struct x86_instr *instr, addr_t pc, char *line, unsigned int max_line);
- extern "C" void LLVMInitializeX86TargetMC();
- extern "C" void LLVMInitializeX86Disassembler();
- extern "C" void LLVMInitializeAArch64TargetMC();
- USING_NS_BF;
- const char* X64CPURegisters::sCPURegisterNames[] =
- {
- "NONE",
- // integer general registers (DO NOT REORDER THESE; must exactly match DbgModule x86 register mappings)
- "RAX",
- "RDX",
- "RCX",
- "RBX",
- "RSI",
- "RDI",
- "RBP",
- "RSP",
- "R8",
- "R9",
- "R10",
- "R11",
- "R12",
- "R13",
- "R14",
- "R15",
- "RIP",
- "EFL",
- "GS",
- "EAX",
- "EDX",
- "ECX",
- "EBX",
- "ESI",
- "EDI",
- "R8D",
- "R9D",
- "R10D",
- "R11D",
- "R12D",
- "R13D",
- "R14D",
- "R15D",
- "AX",
- "DX",
- "CX",
- "BX",
- "SI",
- "DI",
- "R8W",
- "R9W",
- "R10W",
- "R11W",
- "R12W",
- "R13W",
- "R14W",
- "R15W",
- "AL",
- "DL",
- "CL",
- "BL",
- "AH",
- "DH",
- "CH",
- "BH",
- "SIL",
- "DIL",
- "R8B",
- "R9B",
- "R10B",
- "R11B",
- "R12B",
- "R13B",
- "R14B",
- "R15B",
- // fpu registers (80-bit st(#) reg stack)
- "FPST0",
- "FPST1",
- "FPST2",
- "FPST3",
- "FPST4",
- "FPST5",
- "FPST6",
- "FPST7",
- // mmx registers (alias to the low 64 bits of the matching st(#) register)
- "MM0",
- "MM1",
- "MM2",
- "MM3",
- "MM4",
- "MM5",
- "MM6",
- "MM7",
- "XMM0_f64",
- "XMM1_f64",
- "XMM2_f64",
- "XMM3_f64",
- "XMM4_f64",
- "XMM5_f64",
- "XMM6_f64",
- "XMM7_f64",
- "XMM8_f64",
- "XMM9_f64",
- "XMM10_f64",
- "XMM11_f64",
- "XMM12_f64",
- "XMM13_f64",
- "XMM14_f64",
- "XMM15_f64",
- "XMM0_f32",
- "XMM1_f32",
- "XMM2_f32",
- "XMM3_f32",
- "XMM4_f32",
- "XMM5_f32",
- "XMM6_f32",
- "XMM7_f32",
- "XMM8_f32",
- "XMM9_f32",
- "XMM10_f32",
- "XMM11_f32",
- "XMM12_f32",
- "XMM13_f32",
- "XMM14_f32",
- "XMM15_f32",
- // xmm registers
- "XMM00",
- "XMM01",
- "XMM02",
- "XMM03",
- "XMM10",
- "XMM11",
- "XMM12",
- "XMM13",
- "XMM20",
- "XMM21",
- "XMM22",
- "XMM23",
- "XMM30",
- "XMM31",
- "XMM32",
- "XMM33",
- "XMM40",
- "XMM41",
- "XMM42",
- "XMM43",
- "XMM50",
- "XMM51",
- "XMM52",
- "XMM53",
- "XMM60",
- "XMM61",
- "XMM62",
- "XMM63",
- "XMM70",
- "XMM71",
- "XMM72",
- "XMM73",
- "XMM80",
- "XMM81",
- "XMM82",
- "XMM83",
- "XMM90",
- "XMM91",
- "XMM92",
- "XMM93",
- "XMM100",
- "XMM101",
- "XMM102",
- "XMM103",
- "XMM110",
- "XMM111",
- "XMM112",
- "XMM13",
- "XMM120",
- "XMM121",
- "XMM122",
- "XMM123",
- "XMM130",
- "XMM131",
- "XMM132",
- "XMM133",
- "XMM140",
- "XMM141",
- "XMM142",
- "XMM143",
- "XMM150",
- "XMM151",
- "XMM152",
- "XMM153",
- // 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)
- "XMM0",
- "XMM1",
- "XMM2",
- "XMM3",
- "XMM4",
- "XMM5",
- "XMM6",
- "XMM7",
- "XMM8",
- "XMM9",
- "XMM10",
- "XMM11",
- "XMM12",
- "XMM13",
- "XMM14",
- "XMM15",
- "CF_CARRY",
- "PF_PARITY",
- "AF_ADJUST",
- "ZF_ZERO",
- "SF_SIGN",
- "IF_INTERRUPT",
- "DF_DIRECTION",
- "OF_OVERFLOW",
- // category macro-registers
- "ALLREGS",
- "IREGS",
- "FPREGS",
- "MMREGS",
- "XMMREGS",
- "FLAGS",
- };
- using namespace Beefy;
- using namespace llvm;
- namespace Beefy
- {
- //
- // The memory object created by LLVMDisasmInstruction().
- //
- //class DisasmMemoryObject : public MemoryObject
- //{
- // uint8_t *Bytes;
- // uint64_t Size;
- // uint64_t BasePC;
- //public:
- // DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
- // Bytes(bytes), Size(size), BasePC(basePC) {}
- // bool isValidAddress(uint64_t address) const override { return address >= BasePC && address < BasePC + Size; }
- // uint64_t getExtent() const override { return Size; }
- // uint64_t readBytes(uint8_t *Buf, uint64_t Size,
- // uint64_t Address) const override {
- // /*if (Addr - BasePC >= Size)
- // return -1;
- // *Byte = Bytes[Addr - BasePC];
- // return 0;*/
- // memcpy(Buf, Bytes + (Address - BasePC), Size);
- // return Size;
- // }
- // virtual const uint8_t *getPointer(uint64_t address, uint64_t size) const override
- // {
- // return Bytes + (address - BasePC);
- // }
- //};
- } // end anonymous namespace
- //using namespace X86Disassembler;
- int X64Instr::GetLength()
- {
- return mSize;
- }
- bool X64Instr::IsBranch()
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- return (instDesc.getFlags() & (1 << MCID::Branch)) != 0;
- }
- bool X64Instr::IsCall()
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- return (instDesc.getFlags() & (1 << MCID::Call)) != 0;
- }
- bool X64Instr::IsRep(bool& isPrefixOnly)
- {
- auto instFlags = mMCInst.getFlags();
- if ((instFlags & (X86::IP_HAS_REPEAT_NE | X86::IP_HAS_REPEAT)) != 0)
- {
- isPrefixOnly = false;
- return true;
- }
- auto opCode = mMCInst.getOpcode();
- if ((opCode >= X86::REPNE_PREFIX) && (opCode <= X86::REP_MOVSW_64))
- {
- isPrefixOnly = true;
- return true;
- }
- return false;
- }
- bool X64Instr::IsReturn()
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- return (instDesc.getFlags() & (1 << MCID::Return)) != 0;
- }
- bool X64Instr::IsLoadAddress()
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- if (instDesc.NumOperands >= 6)
- {
- if ((instDesc.OpInfo[0].OperandType == MCOI::OPERAND_REGISTER) &&
- (instDesc.OpInfo[4].OperandType == MCOI::OPERAND_MEMORY))
- return true;
- }
- return false;
- }
- static int ConvertRegNum(const MCOperand& operand)
- {
- if (!operand.isReg())
- return -1;
- switch (operand.getReg())
- {
- case llvm::X86::AL:
- case llvm::X86::AH:
- case llvm::X86::EAX:
- case llvm::X86::RAX:
- return X64Reg_RAX;
- case llvm::X86::CL:
- case llvm::X86::CH:
- case llvm::X86::ECX:
- case llvm::X86::RCX:
- return X64Reg_RCX;
- case llvm::X86::DL:
- case llvm::X86::DH:
- case llvm::X86::EDX:
- case llvm::X86::RDX:
- return X64Reg_RDX;
- case llvm::X86::BL:
- case llvm::X86::BH:
- case llvm::X86::EBX:
- case llvm::X86::RBX:
- return X64Reg_RBX;
- case llvm::X86::RBP:
- return X64Reg_RBP;
- case llvm::X86::RSP:
- return X64Reg_RSP;
- case llvm::X86::R8:
- case llvm::X86::R8D:
- case llvm::X86::R8W:
- case llvm::X86::R8B:
- return X64Reg_R8;
- case llvm::X86::R9:
- case llvm::X86::R9D:
- case llvm::X86::R9W:
- case llvm::X86::R9B:
- return X64Reg_R9;
- case llvm::X86::R10:
- case llvm::X86::R10D:
- case llvm::X86::R10W:
- case llvm::X86::R10B:
- return X64Reg_R10;
- case llvm::X86::R11:
- case llvm::X86::R11D:
- case llvm::X86::R11W:
- case llvm::X86::R11B:
- return X64Reg_R11;
- case llvm::X86::R12:
- case llvm::X86::R12D:
- case llvm::X86::R12W:
- case llvm::X86::R12B:
- return X64Reg_R12;
- case llvm::X86::R13:
- case llvm::X86::R13D:
- case llvm::X86::R13W:
- case llvm::X86::R13B:
- return X64Reg_R13;
- case llvm::X86::R14:
- case llvm::X86::R14D:
- case llvm::X86::R14W:
- case llvm::X86::R14B:
- return X64Reg_R14;
- case llvm::X86::R15:
- case llvm::X86::R15D:
- case llvm::X86::R15W:
- case llvm::X86::R15B:
- return X64Reg_R15;
- case llvm::X86::RSI:
- case llvm::X86::ESI:
- case llvm::X86::SI:
- case llvm::X86::SIL:
- return X64Reg_RSI;
- case llvm::X86::RDI:
- case llvm::X86::EDI:
- case llvm::X86::DI:
- case llvm::X86::DIL:
- return X64Reg_RDI;
- case llvm::X86::RIP:
- return X64Reg_RIP;
- case llvm::X86::EFLAGS:
- return X64Reg_EFL;
- case llvm::X86::ST0:
- return X64Reg_FPST0;
- case llvm::X86::ST1:
- return X64Reg_FPST1;
- case llvm::X86::ST2:
- return X64Reg_FPST2;
- case llvm::X86::ST3:
- return X64Reg_FPST3;
- case llvm::X86::ST4:
- return X64Reg_FPST4;
- case llvm::X86::ST5:
- return X64Reg_FPST5;
- case llvm::X86::ST6:
- return X64Reg_FPST6;
- case llvm::X86::ST7:
- return X64Reg_FPST7;
- case llvm::X86::XMM0:
- return X64Reg_M128_XMM0;
- case llvm::X86::XMM1:
- return X64Reg_M128_XMM1;
- case llvm::X86::XMM2:
- return X64Reg_M128_XMM2;
- case llvm::X86::XMM3:
- return X64Reg_M128_XMM3;
- case llvm::X86::XMM4:
- return X64Reg_M128_XMM4;
- case llvm::X86::XMM5:
- return X64Reg_M128_XMM5;
- case llvm::X86::XMM6:
- return X64Reg_M128_XMM6;
- case llvm::X86::XMM7:
- return X64Reg_M128_XMM7;
- case llvm::X86::XMM8:
- return X64Reg_M128_XMM8;
- case llvm::X86::XMM9:
- return X64Reg_M128_XMM9;
- case llvm::X86::XMM10:
- return X64Reg_M128_XMM10;
- case llvm::X86::XMM11:
- return X64Reg_M128_XMM11;
- case llvm::X86::XMM12:
- return X64Reg_M128_XMM12;
- case llvm::X86::XMM13:
- return X64Reg_M128_XMM13;
- case llvm::X86::XMM14:
- return X64Reg_M128_XMM14;
- case llvm::X86::XMM15:
- return X64Reg_M128_XMM15;
- }
- return -1;
- }
- bool X64Instr::GetIndexRegisterAndOffset(int* outRegister, int* outOffset)
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- auto form = (instDesc.TSFlags & llvm::X86II::FormMask);
- if ((form == llvm::X86II::MRMDestMem) || (form == llvm::X86II::MRMSrcMem) ||
- ((form >= llvm::X86II::MRM0m) && (form <= llvm::X86II::MRM7m)))
- {
- int regOffset = 0;
- if (form == llvm::X86II::MRMSrcMem)
- regOffset = 1;
- auto baseReg = mMCInst.getOperand(regOffset + llvm::X86::AddrBaseReg);
- auto scaleAmt = mMCInst.getOperand(regOffset + llvm::X86::AddrScaleAmt);
- auto indexReg = mMCInst.getOperand(regOffset + llvm::X86::AddrIndexReg);
- auto addrDisp = mMCInst.getOperand(regOffset + llvm::X86::AddrDisp);
- /*bool a = baseReg.isReg();
- bool b = scaleAmt.isImm();
- int c = scaleAmt.getImm();
- bool d = indexReg.isReg();
- int e = indexReg.getReg();
- bool f = addrDisp.isImm();*/
- bool isValid = false;
- // Look for [reg+offset] form
- if ((baseReg.isReg()) &&
- (scaleAmt.isImm()) && (scaleAmt.getImm() == 1) &&
- (indexReg.isReg()) && (indexReg.getReg() == llvm::X86::NoRegister) &&
- (addrDisp.isImm()))
- {
- int regNum = ConvertRegNum(baseReg);
- if (regNum == -1)
- return false;
- *outRegister = regNum;
- *outOffset = (int)addrDisp.getImm();
- return true;
- }
- }
- return false;
- }
- bool X64Instr::GetImmediate(uint64* outImm)
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- auto immediateType = (instDesc.TSFlags & llvm::X86II::ImmMask);
- if ((immediateType == 0) && (mMCInst.getNumOperands() < 6))
- return false;
- auto immOp = mMCInst.getOperand(5);
- if (!immOp.isImm())
- return false;
- *outImm = immOp.getImm();
- return true;
- }
- int X64Instr::GetJmpState(int flags)
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- if ((instDesc.getFlags() & (1 << MCID::Branch)) == 0)
- return -1;
- if (mMCInst.getNumOperands() < 1)
- return 0;
- #define FLAGVAR(abbr, name) int flag##abbr = ((flags & ((uint64)1 << X64CPURegisters::GetFlagBitForRegister(X64Reg_FLAG_##abbr##_##name))) != 0) ? 1 : 0
- FLAGVAR(CF, CARRY);
- FLAGVAR(PF, PARITY);
- FLAGVAR(AF, ADJUST);
- FLAGVAR(ZF, ZERO);
- FLAGVAR(SF, SIGN);
- FLAGVAR(IF, INTERRUPT);
- FLAGVAR(DF, DIRECTION);
- FLAGVAR(OF, OVERFLOW);
- #undef FLAGVAR
- int baseOpCode = llvm::X86II::getBaseOpcodeFor(instDesc.TSFlags);
- switch (baseOpCode)
- {
- case 0x70: // JO
- return (!flagOF) ? 1 : 0;
- case 0x71: // JNO
- return (!flagOF) ? 1 : 0;
- case 0x72: // JB
- return (flagCF) ? 1 : 0;
- case 0x73: // JAE
- return (!flagCF) ? 1 : 0;
- case 0x74: // JE
- return (flagZF) ? 1 : 0;
- case 0x75: // JNE
- return (!flagZF) ? 1 : 0;
- case 0x76: // JBE
- return ((flagCF) || (flagZF)) ? 1 : 0;
- case 0x77: // JA
- return ((!flagCF) && (!flagZF)) ? 1 : 0;
- case 0x78: // JNP
- return (flagSF) ? 1 : 0;
- case 0x79: // JNS
- return (!flagSF) ? 1 : 0;
- case 0x7A: // JP
- return (flagPF) ? 1 : 0;
- case 0x7B: // JPO
- return (!flagPF) ? 1 : 0;
- case 0x7C: // JL
- return (flagSF != flagOF) ? 1 : 0;
- case 0x7D: // JGE
- return (flagSF == flagOF) ? 1 : 0;
- case 0x7E: // JLE
- return ((flagZF) || (flagSF != flagOF)) ? 1 : 0;
- case 0x7F: // JG
- return ((!flagZF) && (flagSF == flagOF)) ? 1 : 0;
- case 0xEB: // JMP
- return 1;
- }
- return -1;
- }
- void X64Instr::MarkRegsUsed(Array<RegForm>& regsUsed, bool overrideForm)
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- //String dbgStr = mX64->InstructionToString(this, 0);
- int opCode = instDesc.getOpcode();
- auto form = (instDesc.TSFlags & llvm::X86II::FormMask);
- /*if (opCode == 1724)
- {
- // MOVAPSrr is emitted for all moves between XMM registers, regardless of
- // their actual format, so we just copy the actual RegForm form here
- if (instDesc.getNumOperands() != 2)
- return;
- auto operand = mMCInst.getOperand(0);
- int regNumTo = ConvertRegNum(operand);
- operand = mMCInst.getOperand(1);
- int regNumFrom = ConvertRegNum(operand);
- if (regNumFrom == -1) // ??
- return;
- while (std::max(regNumFrom, regNumTo) >= (int)regsUsed.size())
- regsUsed.push_back(RegForm_Invalid);
- if ((regsUsed[regNumTo] <= RegForm_Unknown) || (overrideForm))
- regsUsed[regNumTo] = regsUsed[regNumFrom];
- return;
- }
- else if (opCode == 1722)
- {
- // MOVAPSmr is actually emitted for all moves from XMM reg to memory
- // So ignore the format
- return;
- }
- else if (opCode == 1723)
- {
- // MOVAPSrm is actually emitted for all moves from XMM reg to memory
- // So ignore the format
- return;
- }*/
- int checkIdx = opCode * 3;
- //const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- //auto form = (instDesc.TSFlags & llvm::X86II::FormMask);
- for (int opIdx = 0; opIdx < std::min((int)instDesc.getNumOperands(), 3); opIdx++)
- {
- auto operand = mMCInst.getOperand(opIdx);
- int regNum = ConvertRegNum(operand);
- if (regNum != -1)
- {
- while (regNum >= (int)regsUsed.size())
- regsUsed.push_back(RegForm_Invalid);
- RegForm regForm = (RegForm)X86Instr::sRegForm[checkIdx];
- if ((regsUsed[regNum] <= RegForm_Unknown) || (overrideForm))
- regsUsed[regNum] = regForm;
- checkIdx++;
- }
- }
- }
- uint64 X64Instr::GetTarget(Debugger* debugger, X64CPURegisters* registers)
- {
- const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- if (mMCInst.getNumOperands() < 1)
- return 0;
- /*if ((debugger != NULL) && (registers != NULL))
- {
- int regNum = 0;
- int offset = 0;
- if (GetIndexRegisterAndOffset(®Num, &offset))
- {
- uint64 addr = registers->mIntRegsArray[regNum] + offset;
- uint64 val = 0;
- debugger->ReadMemory(addr, 8, &val);
- return val;
- }
- }*/
- int opIdx = 0;
- auto operand = mMCInst.getOperand(0);
- if (mMCInst.getNumOperands() > 4)
- {
- if ((instDesc.OpInfo[0].OperandType == MCOI::OPERAND_REGISTER) && (instDesc.OpInfo[4].OperandType == MCOI::OPERAND_MEMORY))
- {
- opIdx = 4;
- operand = mMCInst.getOperand(opIdx);
- }
- }
- if (operand.isImm())
- {
- auto targetAddr = (uint64)operand.getImm();
- if (instDesc.OpInfo[opIdx].OperandType == MCOI::OPERAND_PCREL)
- targetAddr += mAddress + mSize;
- return targetAddr;
- }
- return 0;
- }
- bool X64Instr::PartialSimulate(Debugger* debugger, X64CPURegisters* registers)
- {
- // const MCInstrDesc &instDesc = mX64->mInstrInfo->get(mMCInst.getOpcode());
- //
- // for (int i = 0; i < instDesc.NumOperands; i++)
- // {
- // auto regInfo = mMCInst.getOperand(i);
- // NOP;
- // }
- //
- // if (instDesc.getOpcode() == X86::MOV64rm)
- // {
- // auto form = (instDesc.TSFlags & llvm::X86II::FormMask);
- //
- // if ((form == llvm::X86II::MRMSrcMem) && (instDesc.NumOperands == 6))
- // {
- // auto destReg = mMCInst.getOperand(llvm::X86::AddrBaseReg);
- // if (destReg.isReg())
- // {
- // int regNum = 0;
- // int offset = 0;
- // if (GetIndexRegisterAndOffset(®Num, &offset))
- // {
- // uint64 addr = registers->mIntRegsArray[regNum] + offset;
- // uint64 val = 0;
- // debugger->ReadMemory(addr, 8, &val);
- //
- // switch (destReg.getReg())
- // {
- //
- // }
- // }
- // }
- // }
- //
- //// if ((form == llvm::X86II::MRMDestMem) || (form == llvm::X86II::MRMSrcMem) ||
- //// ((form >= llvm::X86II::MRM0m) && (form <= llvm::X86II::MRM7m)))
- //// {
- //// }
- // }
- //
- // if (instDesc.getOpcode() == X86::XOR8rr)
- // {
- // if (instDesc.NumOperands == 3)
- // {
- // auto destReg = mMCInst.getOperand(0);
- // auto srcReg = mMCInst.getOperand(1);
- //
- // if ((destReg.isReg()) && (srcReg.isReg()))
- // {
- // if (destReg.getReg() == srcReg.getReg())
- // {
- // switch (destReg.getReg())
- // {
- // case X86::AL:
- // ((uint8*)®isters->mIntRegs.rax)[0] = 0;
- // break;
- // }
- // }
- // }
- // }
- // }
- return false;
- }
- X64CPU::X64CPU() :
- mWarningStream(mWarningString),
- mCommentStream(mCommentString)
- {
- mDisAsm = NULL;
- mRegisterInfo = NULL;
- mAsmInfo = NULL;
- mInstrInfo = NULL;
- mInstPrinter = NULL;
- //InitializeAllTargets();
- auto& TheX86_64Target = llvm::getTheX86_64Target();
- const char* triple = "x86_64-pc-mingw32";
- mSubtargetInfo = TheX86_64Target.createMCSubtargetInfo(triple, "x86-64", "");
- mRegisterInfo = TheX86_64Target.createMCRegInfo(triple);
- if (!mRegisterInfo)
- return;
- MCTargetOptions options;
- // Get the assembler info needed to setup the MCContext.
- mAsmInfo = TheX86_64Target.createMCAsmInfo(*mRegisterInfo, triple, options);
- if (!mAsmInfo)
- return;
- mInstrInfo = TheX86_64Target.createMCInstrInfo();
- mMCContext = new MCContext(Triple(triple), mAsmInfo, mRegisterInfo, mSubtargetInfo);
- mMCObjectFileInfo = TheX86_64Target.createMCObjectFileInfo(*mMCContext, false);
- if (!mMCObjectFileInfo)
- return;
- mMCContext->setObjectFileInfo(mMCObjectFileInfo);
- MCDisassembler *disAsm = TheX86_64Target.createMCDisassembler(*mSubtargetInfo, *mMCContext);
- mDisAsm = disAsm;
- mInstPrinter = TheX86_64Target.createMCInstPrinter(Triple(triple), 1, *mAsmInfo,
- *mInstrInfo, *mRegisterInfo);
- mInstPrinter->setPrintImmHex(true);
- for (const X86StringToOpcodeEntry* entry = &gX86StringToOpcodeTable[0]; entry->Name != nullptr; ++entry)
- {
- mStringToOpcodeMap.insert(StringToOpcodeMap::value_type(entry->Name, entry->Opcode));
- }
- }
- extern "C" void LLVMShutdown();
- X64CPU::~X64CPU()
- {
- delete mInstPrinter;
- delete mDisAsm;
- delete mMCContext;
- delete mMCObjectFileInfo;
- delete mInstrInfo;
- delete mAsmInfo;
- delete mRegisterInfo;
- delete mSubtargetInfo;
- LLVMShutdown();
- }
- bool X64CPU::Decode(uint64 address, DbgModuleMemoryCache* memoryCache, X64Instr* inst)
- {
- inst->mAddress = address;
- inst->mX64 = this;
- uint64 size = 0;
- uint8 data[15];
- memoryCache->Read(address, data, 15);
- mDisAsm->CommentStream = &inst->mAnnotationStream;
- ArrayRef<uint8_t> dataArrayRef(data, data + 15);
- MCDisassembler::DecodeStatus S = mDisAsm->getInstruction(inst->mMCInst, size, dataArrayRef, address, nulls());
- inst->mSize = (int)size;
- return S == MCDisassembler::Success;
- }
- bool X64CPU::Decode(uint64 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, X64Instr* inst)
- {
- //X86GenericDisassembler assembler;
- //DisasmMemoryObject region((uint8*)dataBase, dataLength, baseAddress);
- //std::memorystream
- uint64 address = baseAddress + (dataPtr - dataBase);
- inst->mAddress = address;
- inst->mX64 = this;
- uint64 size = 0;
- //TODO: LLVM3.8
- //MCDisassembler::DecodeStatus S = mDisAsm->getInstruction(inst->mMCInst, size, region, address, nulls(), inst->mAnnotationStream);
- mDisAsm->CommentStream = &inst->mAnnotationStream;
- ArrayRef<uint8_t> dataArrayRef(dataPtr, dataLength - (dataPtr - dataBase));
- MCDisassembler::DecodeStatus S = mDisAsm->getInstruction(inst->mMCInst, size, dataArrayRef, address, nulls());
- inst->mSize = (int)size;
- return S == MCDisassembler::Success;
- }
- uint64 X64CPU::DecodeThunk(uint64 address, DbgModuleMemoryCache* memoryCache)
- {
- uint8 inst = 0;
- memoryCache->Read(address, &inst, 1);
- if (inst == 0xE9)
- {
- int32 offset = 0;
- memoryCache->Read(address + 1, (uint8*)&offset, sizeof(int32));
- return address + offset + 5;
- }
- return 0;
- }
- void X64CPU::GetNextPC(uint64 baseAddress, const uint8* dataBase, int dataLength, const uint8* dataPtr, uint32* regs, uint64 nextPCs[2])
- {
- //DisasmMemoryObject region((uint8*)dataBase, dataLength, baseAddress);
- uint64 address = baseAddress + (dataPtr - dataBase);
- uint64 size = 0;
- MCInst mcInst;
- //MCDisassembler::DecodeStatus S = mDisAsm->getInstruction(mcInst, size, region, address, nulls(), nulls());
- mDisAsm->CommentStream = &nulls();
- ArrayRef<uint8_t> dataArrayRef(dataPtr, dataLength - (dataPtr - dataBase));
- MCDisassembler::DecodeStatus S = mDisAsm->getInstruction(mcInst, size, dataArrayRef, address, nulls());
- }
- bool X64CPU::IsReturnInstruction(X64Instr* inst)
- {
- const MCInstrDesc &instDesc = mInstrInfo->get(inst->mMCInst.getOpcode());
- return (instDesc.getFlags() & (1 << MCID::Return)) != 0;
- }
- String X64CPU::InstructionToString(X64Instr* inst, uint64 addr)
- {
- StringRef annotationsStr;
- SmallVector<char, 256> insnStr;
- raw_svector_ostream OS(insnStr);
- //mInstPrinter->CurPCRelImmOffset = addr + inst->GetLength();
- mInstPrinter->printInst(&inst->mMCInst, addr, annotationsStr, *mSubtargetInfo, OS);
- //OS.flush();
- //llvm::StringRef str = OS.str();
- String result;
- for (int idx = 0; idx < (int)insnStr.size(); idx++)
- {
- char c = insnStr[idx];
- if (c == '\t')
- {
- if (idx != 0)
- {
- int numSpaces = 10 - ((int)result.length() % 10);
- result.Append(' ', numSpaces);
- }
- }
- else
- result.Append(c);
- }
- if (result.StartsWith("rep "))
- {
- while ((result.length() > 10) && (result[10] == ' '))
- result.Remove(10);
- }
- /*String result = String(insnStr.data(), insnStr.size());
- for (int i = 0; i < (int)result.length(); i++)
- {
- if (result[i] == '\t')
- result[i] = ' ';
- }*/
- return result;
- }
- DbgBreakKind X64CPU::GetDbgBreakKind(uint64 address, DbgModuleMemoryCache* memoryCache, int64* regs, int64* outObjectPtr)
- {
- // We've looking for a CMP BYTE PTR [<reg>], -0x80
- // if <reg> is R12 then encoding takes an extra 2 bytes
- X64Instr inst;
- for (int checkLen = 5; checkLen >= 3; checkLen--)
- {
- int offset = -3 - checkLen;
- if (!Decode(address + offset, memoryCache, &inst))
- continue;
- if (inst.GetLength() != checkLen)
- continue;
- const MCInstrDesc &instDesc = mInstrInfo->get(inst.mMCInst.getOpcode());
- if (!instDesc.isCompare())
- continue;
- auto immediateType = (instDesc.TSFlags & llvm::X86II::ImmMask);
- if ((immediateType == llvm::X86II::Imm8) && (inst.mMCInst.getNumOperands() == 2))
- {
- // We're checking for a TEST [<reg>], 1
- if (inst.mMCInst.getOpcode() != llvm::X86::TEST8ri)
- continue;
- auto immOp = inst.mMCInst.getOperand(1);
- if (!immOp.isImm())
- continue;
- if (immOp.getImm() != 1)
- continue;
- return DbgBreakKind_ArithmeticOverflow;
- }
- if ((immediateType == 0) || (inst.mMCInst.getNumOperands() < 6))
- continue;
- auto form = (instDesc.TSFlags & llvm::X86II::FormMask);
- auto baseReg = inst.mMCInst.getOperand(llvm::X86::AddrBaseReg);
- /*auto scaleAmt = inst.mMCInst.getOperand(llvm::X86::AddrScaleAmt);
- auto indexReg = inst.mMCInst.getOperand(llvm::X86::AddrIndexReg);
- auto addrDisp = inst.mMCInst.getOperand(llvm::X86::AddrDisp);*/
- auto immOp = inst.mMCInst.getOperand(5);
- if (!immOp.isImm())
- continue;
- if (immOp.getImm() != -0x80)
- continue;
- int regNum = ConvertRegNum(baseReg);
- if (regNum == -1)
- continue;
- *outObjectPtr = (uint64)regs[regNum];
- return DbgBreakKind_ObjectAccess;
- }
- // check jno/jnb
- for (int offset = 3; offset <= 3; offset++)
- {
- if (!Decode(address - offset, memoryCache, &inst))
- continue;
- if (inst.GetLength() != 2)
- continue;
- const MCInstrDesc &instDesc = mInstrInfo->get(inst.mMCInst.getOpcode());
- if (!instDesc.isBranch())
- continue;
- auto immediateType = (instDesc.TSFlags & llvm::X86II::ImmMask);
- if ((immediateType == llvm::X86II::Imm8PCRel) && (inst.mMCInst.getNumOperands() == 2))
- {
- auto immOp = inst.mMCInst.getOperand(1);
- if (!immOp.isImm())
- continue;
- if ((immOp.getImm() != 1) && (immOp.getImm() != 3))
- continue;
- return DbgBreakKind_ArithmeticOverflow;
- }
- }
- return DbgBreakKind_None;
- }
- int X64CPU::GetOpcodesForMnemonic(const StringImpl& mnemonic, Array<int>& outOpcodes)
- {
- String s(mnemonic);
- std::transform(s.begin(), s.end(), s.begin(), ::tolower);
- std::pair<StringToOpcodeMap::iterator, StringToOpcodeMap::iterator> range = mStringToOpcodeMap.equal_range(s);
- outOpcodes.Clear();
- for (StringToOpcodeMap::iterator it = range.first; it != range.second; ++it)
- outOpcodes.push_back(it->second);
- return (int)outOpcodes.size();
- }
- void X64CPU::GetClobbersForMnemonic(const StringImpl& mnemonic, int argCount, Array<int>& outImplicitClobberRegNums, int& outClobberArgCount, bool& outMayClobberMem)
- {
- outImplicitClobberRegNums.Clear();
- outClobberArgCount = 0;
- outMayClobberMem = false;
- Array<int> opcodes;
- if (!GetOpcodesForMnemonic(mnemonic, opcodes))
- return;
- HashSet<int> impRegs;
- for (int op : opcodes)
- {
- const MCInstrDesc& desc = mInstrInfo->get(op);
- //if ((desc.getNumOperands() != argCount) && !desc.isVariadic())
- //continue; // not an operand form that we care about
- outClobberArgCount = std::max(outClobberArgCount, (int)desc.getNumDefs());
- if (!outMayClobberMem && desc.mayStore())
- outMayClobberMem = true;
- int numImplicits = desc.getNumImplicitDefs();
- auto impPtr = desc.getImplicitDefs();
- for (int iImp = 0; iImp<numImplicits; ++iImp)
- impRegs.Add(impPtr[iImp]);
- }
- for (auto const& r : impRegs)
- {
- int regNum = ConvertRegNum(MCOperand::createReg(r));
- if (regNum != -1)
- outImplicitClobberRegNums.push_back(regNum);
- }
- }
- bool X64CPU::ParseInlineAsmInstructionLLVM(const StringImpl&asmInst, String& outError)
- {
- struct LocalThunk
- {
- std::function<void(const SMDiagnostic &)> mFunc;
- void Thunk(const SMDiagnostic& diag)
- {
- mFunc(diag);
- }
- static void StaticThunk(const SMDiagnostic& diag, void* diagInfo)
- {
- ((LocalThunk*)diagInfo)->Thunk(diag);
- }
- };
- String diagMessage, diagLineContents;
- std::function<void(const SMDiagnostic &)> diagHandler = [&](const SMDiagnostic &diag)
- {
- if (diag.getKind() == SourceMgr::DK_Error)
- {
- diagMessage = diag.getMessage().data();
- diagLineContents = diag.getLineContents().data();
- }
- };
- LocalThunk localThunk;
- localThunk.mFunc = diagHandler;
- auto& TheX86_64Target = getTheX86_64Target();
- llvm::SourceMgr srcMgr;
- srcMgr.setDiagHandler(LocalThunk::StaticThunk, &localThunk);
- SmallString<512> asmString;
- asmString.assign(asmInst.c_str());
- //asmString.push_back('\n');
- asmString.push_back('\0');
- asmString.pop_back();
- std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBuffer(asmString, "inline asm");
- srcMgr.AddNewSourceBuffer(std::move(buffer), llvm::SMLoc());
- llvm::MCTargetOptions options;
- std::unique_ptr<llvm::MCStreamer> streamer(createNullStreamer(*mMCContext));
- std::unique_ptr<llvm::MCAsmParser> parser(createMCAsmParser(srcMgr, *mMCContext, *streamer.get(), *mAsmInfo));
- std::unique_ptr<llvm::MCTargetAsmParser> asmParser(TheX86_64Target.createMCAsmParser(*mSubtargetInfo, *parser.get(), *mInstrInfo, options));
- parser->setAssemblerDialect(llvm::InlineAsm::AD_Intel);
- parser->setTargetParser(*asmParser);
- bool result = parser->Run(false, true) == 0;
- if (result)
- outError.clear();
- else
- outError = diagMessage.c_str(); // we can ignore diagLineContents in this situation since we're only doing one line at a time anyway
- //outError = StrFormat("%s: \"%s\"", diagMessage.c_str(), diagLineContents.c_str());
- return result;
- }
|