forked from OSchip/llvm-project
169 lines
4.7 KiB
C++
169 lines
4.7 KiB
C++
//===-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
|