//===-EDOperand.cpp - LLVM Enhanced Disassembler --------------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the Enhanced Disassembly library's operand class. The // operand is responsible for allowing evaluation given a particular register // context. // //===----------------------------------------------------------------------===// #include "EDDisassembler.h" #include "EDInst.h" #include "EDOperand.h" #include "llvm/MC/MCInst.h" using namespace llvm; EDOperand::EDOperand(const EDDisassembler &disassembler, const EDInst &inst, unsigned int opIndex, unsigned int &mcOpIndex) : Disassembler(disassembler), Inst(inst), OpIndex(opIndex), MCOpIndex(mcOpIndex) { unsigned int numMCOperands = 0; if(Disassembler.Key.Arch == Triple::x86 || Disassembler.Key.Arch == Triple::x86_64) { uint8_t operandFlags = inst.ThisInstInfo->operandFlags[opIndex]; if (operandFlags & kOperandFlagImmediate) { numMCOperands = 1; } else if (operandFlags & kOperandFlagRegister) { numMCOperands = 1; } else if (operandFlags & kOperandFlagMemory) { if (operandFlags & kOperandFlagPCRelative) { numMCOperands = 1; } else { numMCOperands = 5; } } else if (operandFlags & kOperandFlagEffectiveAddress) { numMCOperands = 4; } } mcOpIndex += numMCOperands; } EDOperand::~EDOperand() { } int EDOperand::evaluate(uint64_t &result, EDRegisterReaderCallback callback, void *arg) { if (Disassembler.Key.Arch == Triple::x86 || Disassembler.Key.Arch == Triple::x86_64) { uint8_t operandFlags = Inst.ThisInstInfo->operandFlags[OpIndex]; if (operandFlags & kOperandFlagImmediate) { result = Inst.Inst->getOperand(MCOpIndex).getImm(); return 0; } if (operandFlags & kOperandFlagRegister) { unsigned reg = Inst.Inst->getOperand(MCOpIndex).getReg(); return callback(&result, reg, arg); } if (operandFlags & kOperandFlagMemory || operandFlags & kOperandFlagEffectiveAddress){ if(operandFlags & kOperandFlagPCRelative) { int64_t displacement = Inst.Inst->getOperand(MCOpIndex).getImm(); uint64_t ripVal; // TODO fix how we do this if (callback(&ripVal, Disassembler.registerIDWithName("RIP"), arg)) return -1; result = ripVal + displacement; return 0; } else { unsigned baseReg = Inst.Inst->getOperand(MCOpIndex).getReg(); uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm(); unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg(); int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm(); //unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg(); uint64_t addr = 0; if(baseReg) { uint64_t baseVal; if (callback(&baseVal, baseReg, arg)) return -1; addr += baseVal; } if(indexReg) { uint64_t indexVal; if (callback(&indexVal, indexReg, arg)) return -1; addr += (scaleAmount * indexVal); } addr += displacement; result = addr; return 0; } } return -1; } return -1; } int EDOperand::isRegister() { return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagRegister); } unsigned EDOperand::regVal() { return Inst.Inst->getOperand(MCOpIndex).getReg(); } int EDOperand::isImmediate() { return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagImmediate); } uint64_t EDOperand::immediateVal() { return Inst.Inst->getOperand(MCOpIndex).getImm(); } int EDOperand::isMemory() { return(Inst.ThisInstInfo->operandFlags[OpIndex] & kOperandFlagMemory); } #ifdef __BLOCKS__ struct RegisterReaderWrapper { EDRegisterBlock_t regBlock; }; int readerWrapperCallback(uint64_t *value, unsigned regID, void *arg) { struct RegisterReaderWrapper *wrapper = (struct RegisterReaderWrapper *)arg; return wrapper->regBlock(value, regID); } int EDOperand::evaluate(uint64_t &result, EDRegisterBlock_t regBlock) { struct RegisterReaderWrapper wrapper; wrapper.regBlock = regBlock; return evaluate(result, readerWrapperCallback, (void*)&wrapper); } #endif