123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179 |
- #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();
- mMCObjectFileInfo = new MCObjectFileInfo();
- mMCContext = new MCContext(mAsmInfo, mRegisterInfo, 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;
- }
|