libdasm import
git-svn-id: file:///home/svn/incoming/trunk@3358 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
eccdce049c
commit
fd0d349eb7
|
@ -0,0 +1,44 @@
|
|||
module Ext
|
||||
module Disassembler
|
||||
module X86
|
||||
|
||||
require 'ext/disassembler/x86/dasm/dasm'
|
||||
|
||||
module Register
|
||||
#
|
||||
# Register number constants
|
||||
#
|
||||
EAX = AL = AX = ES = 0
|
||||
ECX = CL = CX = CS = 1
|
||||
EDX = DL = DX = SS = 2
|
||||
EBX = BL = BX = DS = 3
|
||||
ESP = AH = SP = FS = 4
|
||||
EBP = CH = BP = GS = 5
|
||||
ESI = DH = SI = 6
|
||||
EDI = BH = DI = 7
|
||||
|
||||
module Type
|
||||
General = 1
|
||||
Segment = 2
|
||||
Debug = 3
|
||||
Control = 4
|
||||
Test = 5
|
||||
XMM = 6
|
||||
MMX = 7
|
||||
FPU = 8
|
||||
end
|
||||
end
|
||||
|
||||
module Operand
|
||||
|
||||
module Type
|
||||
Memory = 1
|
||||
Register = 2
|
||||
Immediate = 3
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,862 @@
|
|||
//
|
||||
// Wraps jt's libdasm in ruby classes that can be accessed through:
|
||||
//
|
||||
// Ext::Disassembler::X86::Dasm
|
||||
// Ext::Disassembler::X86::Dasm::Instruction
|
||||
// Ext::Disassembler::X86::Dasm::Operand
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// dasm = Ext::Disassembler::X86::Dasm.new
|
||||
//
|
||||
// dasm.disassemble(buf).each { |instruction|
|
||||
// puts instruction.to_s
|
||||
// }
|
||||
//
|
||||
// All credits for the disassembler to go jt <jt at klake.org> :)
|
||||
//
|
||||
// skape
|
||||
// 01/2006
|
||||
//
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ruby.h>
|
||||
#include "libdasm.h"
|
||||
|
||||
#define min(x, y) (x < y) ? x : y
|
||||
|
||||
static VALUE dasm_klass;
|
||||
static VALUE instr_klass;
|
||||
static VALUE instr_type_klass;
|
||||
static VALUE oper_klass;
|
||||
static VALUE oper_type_klass;
|
||||
|
||||
typedef struct _DASM_OBJECT
|
||||
{
|
||||
enum Mode mode;
|
||||
enum Format format;
|
||||
} DASM_OBJECT, *PDASM_OBJECT;
|
||||
|
||||
#define rb_dasm_cast(x, y) \
|
||||
Data_Get_Struct(x, DASM_OBJECT, y)
|
||||
|
||||
////
|
||||
//
|
||||
// Operand class
|
||||
//
|
||||
////
|
||||
|
||||
typedef struct _OPERAND_OBJECT
|
||||
{
|
||||
OPERAND *op;
|
||||
} OPERAND_OBJECT, *POPERAND_OBJECT;
|
||||
|
||||
#define rb_operand_cast(x, y) \
|
||||
Data_Get_Struct(x, OPERAND_OBJECT, y)
|
||||
|
||||
//
|
||||
// Deallocates the memory used by an instance of the operand class.
|
||||
//
|
||||
static void operand_free(void *oper)
|
||||
{
|
||||
if (oper)
|
||||
free(oper);
|
||||
}
|
||||
|
||||
//
|
||||
// Allocates storage for the operand instance structure.
|
||||
//
|
||||
static VALUE operand_alloc(VALUE klass)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
VALUE obj;
|
||||
|
||||
obj = Data_Make_Struct(klass, OPERAND_OBJECT, 0, operand_free, oper);
|
||||
|
||||
oper->op = NULL;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocates and initializes an instance of the Operand class.
|
||||
//
|
||||
static VALUE operand_new(VALUE klass, OPERAND *op)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
VALUE obj = operand_alloc(klass);
|
||||
|
||||
rb_operand_cast(obj, oper);
|
||||
|
||||
oper->op = op;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the operands type as one of the Ext::Disassembler::X86::Operand::Type
|
||||
// constants.
|
||||
//
|
||||
static VALUE operand_type(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(get_operand_type(oper->op));
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the register used by the operand, if any, as one of the
|
||||
// Ext::Disassembler::X86::Register constants.
|
||||
//
|
||||
static VALUE operand_reg(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
VALUE rv;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
if (get_operand_register(oper->op) == REGISTER_NOP)
|
||||
rv = Qnil;
|
||||
else
|
||||
rv = INT2FIX(get_operand_register(oper->op));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the register type being used by the operand, if any, as one of the
|
||||
// Ext::Disassembler::X86::Register::Type constants.
|
||||
//
|
||||
static VALUE operand_regtype(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(get_register_type(oper->op));
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the base register that is used when the operand is a memory operand.
|
||||
//
|
||||
static VALUE operand_basereg(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
VALUE rv;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return (oper->op->basereg == REGISTER_NOP) ? Qnil : INT2FIX(oper->op->basereg);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the index register that is used when the operand is a memory operand.
|
||||
//
|
||||
static VALUE operand_indexreg(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
VALUE rv;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return (oper->op->indexreg == REGISTER_NOP) ? Qnil : INT2FIX(oper->op->indexreg);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the scale used.
|
||||
//
|
||||
static VALUE operand_scale(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(get_operand_scale(oper->op));
|
||||
}
|
||||
|
||||
//
|
||||
// The number of bytes used for displacement.
|
||||
//
|
||||
static VALUE operand_dispbytes(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->dispbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// The offset from the start of the instruction for the displacement bytes.
|
||||
//
|
||||
static VALUE operand_dispoffset(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->dispoffset);
|
||||
}
|
||||
|
||||
//
|
||||
// The number of bytes used for immediate data.
|
||||
//
|
||||
static VALUE operand_immbytes(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->immbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// The offset from the start of the instruction to the immediate bytes.
|
||||
//
|
||||
static VALUE operand_immoffset(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->immoffset);
|
||||
}
|
||||
|
||||
//
|
||||
// The number of bytes used for section.
|
||||
//
|
||||
static VALUE operand_sectionbytes(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->sectionbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// The section being used.
|
||||
//
|
||||
static VALUE operand_section(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->section);
|
||||
}
|
||||
|
||||
//
|
||||
// The displacement value of the operand, if any.
|
||||
//
|
||||
static VALUE operand_displacement(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->displacement);
|
||||
}
|
||||
|
||||
//
|
||||
// The immediate value of the operand, if any.
|
||||
//
|
||||
static VALUE operand_immediate(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->immediate);
|
||||
}
|
||||
|
||||
//
|
||||
// Internal flags for the operand.
|
||||
//
|
||||
static VALUE operand_flags(VALUE self)
|
||||
{
|
||||
POPERAND_OBJECT oper;
|
||||
|
||||
rb_operand_cast(self, oper);
|
||||
|
||||
return INT2FIX(oper->op->flags);
|
||||
}
|
||||
|
||||
////
|
||||
//
|
||||
// Instruction class
|
||||
//
|
||||
////
|
||||
|
||||
typedef struct _INSTRUCTION_OBJECT
|
||||
{
|
||||
INSTRUCTION inst;
|
||||
BYTE raw[16];
|
||||
VALUE dasm;
|
||||
VALUE op1;
|
||||
VALUE op2;
|
||||
VALUE op3;
|
||||
} INSTRUCTION_OBJECT, *PINSTRUCTION_OBJECT;
|
||||
|
||||
#define rb_instruction_cast(x, y) \
|
||||
Data_Get_Struct(x, INSTRUCTION_OBJECT, y)
|
||||
|
||||
//
|
||||
// Deallocates the memory used by an instance of the Instruction class.
|
||||
//
|
||||
static void instruction_free(void *inst)
|
||||
{
|
||||
if (inst)
|
||||
free(inst);
|
||||
}
|
||||
|
||||
//
|
||||
// Allocates storage for the Instruction class.
|
||||
//
|
||||
static VALUE instruction_alloc(VALUE klass)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
VALUE obj;
|
||||
|
||||
obj = Data_Make_Struct(klass, INSTRUCTION_OBJECT, 0,
|
||||
instruction_free, inst);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// Creates and initializes an instance of the Instruction class based on the
|
||||
// supplied INSTRUCTION instance passed from libdasm.
|
||||
//
|
||||
static VALUE instruction_new(VALUE klass, VALUE dasm, INSTRUCTION *raw_inst, BYTE *raw)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
VALUE obj = instruction_alloc(klass);
|
||||
|
||||
rb_instruction_cast(obj, inst);
|
||||
|
||||
inst->dasm = dasm;
|
||||
|
||||
memcpy(&inst->inst, raw_inst, sizeof(INSTRUCTION));
|
||||
memcpy(inst->raw, raw, min(raw_inst->length, sizeof(inst->raw)));
|
||||
|
||||
inst->op1 = (raw_inst->op1.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op1);
|
||||
inst->op2 = (raw_inst->op2.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op2);
|
||||
inst->op3 = (raw_inst->op3.type == OPERAND_TYPE_NONE) ? Qnil : operand_new(oper_klass, &inst->inst.op3);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the length of the instruction in terms of bytes.
|
||||
//
|
||||
static VALUE instruction_length(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.length);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the type of instruction as represented by a constant that can be
|
||||
// found under the Instruction::Type module.
|
||||
//
|
||||
static VALUE instruction_type(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.type);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the addressing mode used when disassembling this instruction.
|
||||
//
|
||||
static VALUE instruction_mode(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
VALUE rv;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
switch (inst->inst.mode)
|
||||
{
|
||||
case MODE_32: rv = INT2FIX(32); break;
|
||||
case MODE_16: rv = INT2FIX(16); break;
|
||||
default: rv = Qnil; break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the one-byte opcode associated with this instruction.
|
||||
//
|
||||
static VALUE instruction_opcode(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return (inst->inst.opcode) ? CHR2FIX(inst->inst.opcode) : Qnil;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the Mod R/M byte of the instruction, if any.
|
||||
//
|
||||
static VALUE instruction_modrm(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return (inst->inst.modrm) ? CHR2FIX(inst->inst.modrm) : Qnil;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the SIB byte of the instruction, if any.
|
||||
//
|
||||
static VALUE instruction_sib(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return (inst->inst.sib) ? CHR2FIX(inst->inst.sib) : Qnil;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the number of displacement bytes used in the instruction.
|
||||
//
|
||||
static VALUE instruction_dispbytes(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.dispbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the number of immediate bytes used by the instruction.
|
||||
//
|
||||
static VALUE instruction_immbytes(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.immbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the number of section bytes used by the instruction.
|
||||
//
|
||||
static VALUE instruction_sectionbytes(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.sectionbytes);
|
||||
}
|
||||
|
||||
//
|
||||
// Arbitrary flags used by the disassembler.
|
||||
//
|
||||
static VALUE instruction_flags(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return INT2FIX(inst->inst.flags);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the raw string associated with the instruction.
|
||||
//
|
||||
static VALUE instruction_raw(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return rb_str_new(inst->raw, min(inst->inst.length, sizeof(inst->raw)));
|
||||
}
|
||||
|
||||
//
|
||||
// Converts the instruction to a printable disassembled string using the format
|
||||
// that the Dasm instance the instruction came from is using.
|
||||
//
|
||||
static VALUE instruction_to_s(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
PDASM_OBJECT dasm;
|
||||
char buf[32] = { 0 };
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
rb_dasm_cast(inst->dasm, dasm);
|
||||
|
||||
get_instruction_string(&inst->inst, dasm->format, 0, (BYTE *)buf, sizeof(buf) - 1);
|
||||
|
||||
return rb_str_new2(buf);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the first operand of the instruction, if any.
|
||||
//
|
||||
static VALUE instruction_op1(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return inst->op1;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the second operand of the instruction, if any.
|
||||
//
|
||||
static VALUE instruction_op2(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return inst->op2;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the third operand of the instruction, if any.
|
||||
//
|
||||
static VALUE instruction_op3(VALUE self)
|
||||
{
|
||||
PINSTRUCTION_OBJECT inst;
|
||||
|
||||
rb_instruction_cast(self, inst);
|
||||
|
||||
return inst->op3;
|
||||
}
|
||||
|
||||
////
|
||||
//
|
||||
// Dasm class
|
||||
//
|
||||
////
|
||||
|
||||
//
|
||||
// Deallocates the memory used by an instance of the Dasm class.
|
||||
//
|
||||
static void dasm_free(void *dasm)
|
||||
{
|
||||
if (dasm)
|
||||
free(dasm);
|
||||
}
|
||||
|
||||
//
|
||||
// Initializes the underlying datastructure for an instance of the Dasm class.
|
||||
//
|
||||
static VALUE dasm_alloc(VALUE klass)
|
||||
{
|
||||
PDASM_OBJECT dasm;
|
||||
VALUE obj;
|
||||
|
||||
obj = Data_Make_Struct(klass, DASM_OBJECT, 0, dasm_free, dasm);
|
||||
dasm->mode = MODE_32;
|
||||
dasm->format = FORMAT_INTEL;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
//
|
||||
// Performs a disassembly on the supplied buffer and returns an array of
|
||||
// Instruction instances.
|
||||
//
|
||||
static VALUE dasm_disassemble(VALUE self, VALUE buf)
|
||||
{
|
||||
PDASM_OBJECT obj;
|
||||
INSTRUCTION inst;
|
||||
VALUE instructions = rb_ary_new();
|
||||
int offset = 0, len;
|
||||
|
||||
buf = StringValue(buf);
|
||||
len = RSTRING(buf)->len;
|
||||
|
||||
rb_dasm_cast(self, obj);
|
||||
|
||||
while (offset < len)
|
||||
{
|
||||
VALUE rb_inst;
|
||||
BYTE *current = (BYTE *)(RSTRING(buf)->ptr + offset);
|
||||
|
||||
if (!get_instruction(&inst, current, obj->mode))
|
||||
break;
|
||||
|
||||
rb_inst = instruction_new(instr_klass, self, &inst, current);
|
||||
|
||||
rb_ary_push(instructions, rb_inst);
|
||||
|
||||
offset += inst.length;
|
||||
}
|
||||
|
||||
return instructions;
|
||||
}
|
||||
|
||||
//
|
||||
// Sets the disassembler mode, either 16 or 32 bits.
|
||||
//
|
||||
static VALUE dasm_set_mode(VALUE self, VALUE bits)
|
||||
{
|
||||
PDASM_OBJECT obj;
|
||||
int val = FIX2INT(bits);
|
||||
|
||||
rb_dasm_cast(self, obj);
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case 32: obj->mode = MODE_32; break;
|
||||
case 16: obj->mode = MODE_16; break;
|
||||
default: rb_raise(rb_eArgError, "Invalid disassembler mode (must be 16 or 32)"); break;
|
||||
}
|
||||
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the current disassembler mode that is being operated under.
|
||||
//
|
||||
static VALUE dasm_mode(VALUE self)
|
||||
{
|
||||
PDASM_OBJECT obj;
|
||||
VALUE rv;
|
||||
|
||||
rb_dasm_cast(self, obj);
|
||||
|
||||
switch (obj->mode)
|
||||
{
|
||||
case MODE_32: rv = INT2FIX(32); break;
|
||||
case MODE_16: rv = INT2FIX(16); break;
|
||||
default: rv = Qnil; break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Changes the format that should be used when displaying disassembly strings.
|
||||
//
|
||||
static VALUE dasm_set_format(VALUE self, VALUE format)
|
||||
{
|
||||
PDASM_OBJECT obj;
|
||||
|
||||
format = StringValue(format);
|
||||
|
||||
rb_dasm_cast(self, obj);
|
||||
|
||||
if (!strncasecmp(RSTRING(format)->ptr, "intel", 5))
|
||||
obj->format = FORMAT_INTEL;
|
||||
else if (!strncasecmp(RSTRING(format)->ptr, "att", 3))
|
||||
obj->format = FORMAT_ATT;
|
||||
else
|
||||
rb_raise(rb_eArgError, "Invalid output format (must be intel or att)");
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
//
|
||||
// Returns the format currently being used when displaying string versions of
|
||||
// instructions.
|
||||
//
|
||||
static VALUE dasm_format(VALUE self)
|
||||
{
|
||||
PDASM_OBJECT obj;
|
||||
VALUE rv;
|
||||
|
||||
rb_dasm_cast(self, obj);
|
||||
|
||||
switch (obj->format)
|
||||
{
|
||||
case FORMAT_INTEL: rv = rb_str_new2("intel"); break;
|
||||
case FORMAT_ATT: rv = rb_str_new2("att"); break;
|
||||
default: rv = Qnil; break;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//
|
||||
// Initializes the dasm classes.
|
||||
//
|
||||
void Init_dasm()
|
||||
{
|
||||
// Dasm
|
||||
dasm_klass = rb_define_class_under(
|
||||
rb_define_module_under(
|
||||
rb_define_module_under(
|
||||
rb_define_module("Ext"),
|
||||
"Disassembler"),
|
||||
"X86"),
|
||||
"Dasm",
|
||||
rb_define_class("Dasm", rb_cObject));
|
||||
|
||||
rb_define_alloc_func(dasm_klass, dasm_alloc);
|
||||
|
||||
rb_define_method(dasm_klass, "disassemble", dasm_disassemble, 1);
|
||||
rb_define_method(dasm_klass, "set_mode", dasm_set_mode, 1);
|
||||
rb_define_method(dasm_klass, "mode", dasm_mode, 0);
|
||||
rb_define_method(dasm_klass, "set_format", dasm_set_format, 1);
|
||||
rb_define_method(dasm_klass, "format", dasm_format, 0);
|
||||
|
||||
// Instruction
|
||||
instr_klass = rb_define_class_under(dasm_klass, "Instruction",
|
||||
rb_define_class("Instruction", rb_cObject));
|
||||
instr_type_klass = rb_define_module_under(instr_klass, "Type");
|
||||
|
||||
rb_define_const(instr_type_klass, "ASC", INT2FIX(INSTRUCTION_TYPE_ASC));
|
||||
rb_define_const(instr_type_klass, "DCL", INT2FIX(INSTRUCTION_TYPE_DCL));
|
||||
rb_define_const(instr_type_klass, "MOV", INT2FIX(INSTRUCTION_TYPE_MOV));
|
||||
rb_define_const(instr_type_klass, "MOVSR", INT2FIX(INSTRUCTION_TYPE_MOVSR));
|
||||
rb_define_const(instr_type_klass, "ADD", INT2FIX(INSTRUCTION_TYPE_ADD));
|
||||
rb_define_const(instr_type_klass, "XADD", INT2FIX(INSTRUCTION_TYPE_XADD));
|
||||
rb_define_const(instr_type_klass, "ADC", INT2FIX(INSTRUCTION_TYPE_ADC));
|
||||
rb_define_const(instr_type_klass, "SUB", INT2FIX(INSTRUCTION_TYPE_SUB));
|
||||
rb_define_const(instr_type_klass, "SBB", INT2FIX(INSTRUCTION_TYPE_SBB));
|
||||
rb_define_const(instr_type_klass, "INC", INT2FIX(INSTRUCTION_TYPE_INC));
|
||||
rb_define_const(instr_type_klass, "DEC", INT2FIX(INSTRUCTION_TYPE_DEC));
|
||||
rb_define_const(instr_type_klass, "DIV", INT2FIX(INSTRUCTION_TYPE_DIV));
|
||||
rb_define_const(instr_type_klass, "IDIV", INT2FIX(INSTRUCTION_TYPE_IDIV));
|
||||
rb_define_const(instr_type_klass, "NOT", INT2FIX(INSTRUCTION_TYPE_NOT));
|
||||
rb_define_const(instr_type_klass, "NEG", INT2FIX(INSTRUCTION_TYPE_NEG));
|
||||
rb_define_const(instr_type_klass, "STOS", INT2FIX(INSTRUCTION_TYPE_STOS));
|
||||
rb_define_const(instr_type_klass, "LODS", INT2FIX(INSTRUCTION_TYPE_LODS));
|
||||
rb_define_const(instr_type_klass, "SCAS", INT2FIX(INSTRUCTION_TYPE_SCAS));
|
||||
rb_define_const(instr_type_klass, "MOVS", INT2FIX(INSTRUCTION_TYPE_MOVS));
|
||||
rb_define_const(instr_type_klass, "MOVSX", INT2FIX(INSTRUCTION_TYPE_MOVSX));
|
||||
rb_define_const(instr_type_klass, "MOVZX", INT2FIX(INSTRUCTION_TYPE_MOVZX));
|
||||
rb_define_const(instr_type_klass, "CMPS", INT2FIX(INSTRUCTION_TYPE_CMPS));
|
||||
rb_define_const(instr_type_klass, "SHX", INT2FIX(INSTRUCTION_TYPE_SHX));
|
||||
rb_define_const(instr_type_klass, "ROX", INT2FIX(INSTRUCTION_TYPE_ROX));
|
||||
rb_define_const(instr_type_klass, "MUL", INT2FIX(INSTRUCTION_TYPE_MUL));
|
||||
rb_define_const(instr_type_klass, "IMUL", INT2FIX(INSTRUCTION_TYPE_IMUL));
|
||||
rb_define_const(instr_type_klass, "EIMUL", INT2FIX(INSTRUCTION_TYPE_EIMUL));
|
||||
rb_define_const(instr_type_klass, "XOR", INT2FIX(INSTRUCTION_TYPE_XOR));
|
||||
rb_define_const(instr_type_klass, "LEA", INT2FIX(INSTRUCTION_TYPE_LEA));
|
||||
rb_define_const(instr_type_klass, "XCHG", INT2FIX(INSTRUCTION_TYPE_XCHG));
|
||||
rb_define_const(instr_type_klass, "CMP", INT2FIX(INSTRUCTION_TYPE_CMP));
|
||||
rb_define_const(instr_type_klass, "TEST", INT2FIX(INSTRUCTION_TYPE_TEST));
|
||||
rb_define_const(instr_type_klass, "PUSH", INT2FIX(INSTRUCTION_TYPE_PUSH));
|
||||
rb_define_const(instr_type_klass, "AND", INT2FIX(INSTRUCTION_TYPE_AND));
|
||||
rb_define_const(instr_type_klass, "OR", INT2FIX(INSTRUCTION_TYPE_OR));
|
||||
rb_define_const(instr_type_klass, "POP", INT2FIX(INSTRUCTION_TYPE_POP));
|
||||
rb_define_const(instr_type_klass, "JMP", INT2FIX(INSTRUCTION_TYPE_JMP));
|
||||
rb_define_const(instr_type_klass, "JMPC", INT2FIX(INSTRUCTION_TYPE_JMPC));
|
||||
rb_define_const(instr_type_klass, "SETC", INT2FIX(INSTRUCTION_TYPE_SETC));
|
||||
rb_define_const(instr_type_klass, "MOVC", INT2FIX(INSTRUCTION_TYPE_MOVC));
|
||||
rb_define_const(instr_type_klass, "LOOP", INT2FIX(INSTRUCTION_TYPE_LOOP));
|
||||
rb_define_const(instr_type_klass, "CALL", INT2FIX(INSTRUCTION_TYPE_CALL));
|
||||
rb_define_const(instr_type_klass, "RET", INT2FIX(INSTRUCTION_TYPE_RET));
|
||||
rb_define_const(instr_type_klass, "INT", INT2FIX(INSTRUCTION_TYPE_INT));
|
||||
rb_define_const(instr_type_klass, "BT", INT2FIX(INSTRUCTION_TYPE_BT));
|
||||
rb_define_const(instr_type_klass, "BTS", INT2FIX(INSTRUCTION_TYPE_BTS));
|
||||
rb_define_const(instr_type_klass, "BTR", INT2FIX(INSTRUCTION_TYPE_BTR));
|
||||
rb_define_const(instr_type_klass, "BTC", INT2FIX(INSTRUCTION_TYPE_BTC));
|
||||
rb_define_const(instr_type_klass, "BSF", INT2FIX(INSTRUCTION_TYPE_BSF));
|
||||
rb_define_const(instr_type_klass, "BSR", INT2FIX(INSTRUCTION_TYPE_BSR));
|
||||
rb_define_const(instr_type_klass, "BSWAP", INT2FIX(INSTRUCTION_TYPE_BSWAP));
|
||||
rb_define_const(instr_type_klass, "SGDT", INT2FIX(INSTRUCTION_TYPE_SGDT));
|
||||
rb_define_const(instr_type_klass, "SIDT", INT2FIX(INSTRUCTION_TYPE_SIDT));
|
||||
rb_define_const(instr_type_klass, "SLDT", INT2FIX(INSTRUCTION_TYPE_SLDT));
|
||||
rb_define_const(instr_type_klass, "LFP", INT2FIX(INSTRUCTION_TYPE_LFP));
|
||||
rb_define_const(instr_type_klass, "FCMOVC", INT2FIX(INSTRUCTION_TYPE_FCMOVC));
|
||||
rb_define_const(instr_type_klass, "FADD", INT2FIX(INSTRUCTION_TYPE_FADD));
|
||||
rb_define_const(instr_type_klass, "FADDP", INT2FIX(INSTRUCTION_TYPE_FADDP));
|
||||
rb_define_const(instr_type_klass, "FIADD", INT2FIX(INSTRUCTION_TYPE_FIADD));
|
||||
rb_define_const(instr_type_klass, "FSUB", INT2FIX(INSTRUCTION_TYPE_FSUB));
|
||||
rb_define_const(instr_type_klass, "FSUBP", INT2FIX(INSTRUCTION_TYPE_FSUBP));
|
||||
rb_define_const(instr_type_klass, "FISUB", INT2FIX(INSTRUCTION_TYPE_FISUB));
|
||||
rb_define_const(instr_type_klass, "FSUBR", INT2FIX(INSTRUCTION_TYPE_FSUBR));
|
||||
rb_define_const(instr_type_klass, "FSUBRP", INT2FIX(INSTRUCTION_TYPE_FSUBRP));
|
||||
rb_define_const(instr_type_klass, "FISUBR", INT2FIX(INSTRUCTION_TYPE_FISUBR));
|
||||
rb_define_const(instr_type_klass, "FMUL", INT2FIX(INSTRUCTION_TYPE_FMUL));
|
||||
rb_define_const(instr_type_klass, "FMULP", INT2FIX(INSTRUCTION_TYPE_FMULP));
|
||||
rb_define_const(instr_type_klass, "FIMUL", INT2FIX(INSTRUCTION_TYPE_FIMUL));
|
||||
rb_define_const(instr_type_klass, "FDIV", INT2FIX(INSTRUCTION_TYPE_FDIV));
|
||||
rb_define_const(instr_type_klass, "FDIVP", INT2FIX(INSTRUCTION_TYPE_FDIVP));
|
||||
rb_define_const(instr_type_klass, "FDIVR", INT2FIX(INSTRUCTION_TYPE_FDIVR));
|
||||
rb_define_const(instr_type_klass, "FDIVRP", INT2FIX(INSTRUCTION_TYPE_FDIVRP));
|
||||
rb_define_const(instr_type_klass, "FIDIV", INT2FIX(INSTRUCTION_TYPE_FIDIV));
|
||||
rb_define_const(instr_type_klass, "FIDIVR", INT2FIX(INSTRUCTION_TYPE_FIDIVR));
|
||||
rb_define_const(instr_type_klass, "FCOM", INT2FIX(INSTRUCTION_TYPE_FCOM));
|
||||
rb_define_const(instr_type_klass, "FCOMP", INT2FIX(INSTRUCTION_TYPE_FCOMP));
|
||||
rb_define_const(instr_type_klass, "FCOMPP", INT2FIX(INSTRUCTION_TYPE_FCOMPP));
|
||||
rb_define_const(instr_type_klass, "FCOMI", INT2FIX(INSTRUCTION_TYPE_FCOMI));
|
||||
rb_define_const(instr_type_klass, "FCOMIP", INT2FIX(INSTRUCTION_TYPE_FCOMIP));
|
||||
rb_define_const(instr_type_klass, "FUCOM", INT2FIX(INSTRUCTION_TYPE_FUCOM));
|
||||
rb_define_const(instr_type_klass, "FUCOMP", INT2FIX(INSTRUCTION_TYPE_FUCOMP));
|
||||
rb_define_const(instr_type_klass, "FUCOMPP", INT2FIX(INSTRUCTION_TYPE_FUCOMPP));
|
||||
rb_define_const(instr_type_klass, "FUCOMI", INT2FIX(INSTRUCTION_TYPE_FUCOMI));
|
||||
rb_define_const(instr_type_klass, "FUCOMIP", INT2FIX(INSTRUCTION_TYPE_FUCOMIP));
|
||||
rb_define_const(instr_type_klass, "FST", INT2FIX(INSTRUCTION_TYPE_FST));
|
||||
rb_define_const(instr_type_klass, "FSTP", INT2FIX(INSTRUCTION_TYPE_FSTP));
|
||||
rb_define_const(instr_type_klass, "FIST", INT2FIX(INSTRUCTION_TYPE_FIST));
|
||||
rb_define_const(instr_type_klass, "FISTP", INT2FIX(INSTRUCTION_TYPE_FISTP));
|
||||
rb_define_const(instr_type_klass, "FISTTP", INT2FIX(INSTRUCTION_TYPE_FISTTP));
|
||||
rb_define_const(instr_type_klass, "FLD", INT2FIX(INSTRUCTION_TYPE_FLD));
|
||||
rb_define_const(instr_type_klass, "FILD", INT2FIX(INSTRUCTION_TYPE_FILD));
|
||||
rb_define_const(instr_type_klass, "FICOM", INT2FIX(INSTRUCTION_TYPE_FICOM));
|
||||
rb_define_const(instr_type_klass, "FICOMP", INT2FIX(INSTRUCTION_TYPE_FICOMP));
|
||||
rb_define_const(instr_type_klass, "FFREE", INT2FIX(INSTRUCTION_TYPE_FFREE));
|
||||
rb_define_const(instr_type_klass, "FFREEP", INT2FIX(INSTRUCTION_TYPE_FFREEP));
|
||||
rb_define_const(instr_type_klass, "FXCH", INT2FIX(INSTRUCTION_TYPE_FXCH));
|
||||
rb_define_const(instr_type_klass, "FPU", INT2FIX(INSTRUCTION_TYPE_FPU));
|
||||
rb_define_const(instr_type_klass, "MMX", INT2FIX(INSTRUCTION_TYPE_MMX));
|
||||
rb_define_const(instr_type_klass, "SSE", INT2FIX(INSTRUCTION_TYPE_SSE));
|
||||
rb_define_const(instr_type_klass, "OTHER", INT2FIX(INSTRUCTION_TYPE_OTHER));
|
||||
rb_define_const(instr_type_klass, "PRIV", INT2FIX(INSTRUCTION_TYPE_PRIV));
|
||||
|
||||
rb_define_alloc_func(instr_klass, instruction_alloc);
|
||||
rb_define_method(instr_klass, "length", instruction_length, 0);
|
||||
rb_define_method(instr_klass, "type", instruction_type, 0);
|
||||
rb_define_method(instr_klass, "mode", instruction_mode, 0);
|
||||
rb_define_method(instr_klass, "opcode", instruction_opcode, 0);
|
||||
rb_define_method(instr_klass, "modrm", instruction_modrm, 0);
|
||||
rb_define_method(instr_klass, "sib", instruction_sib, 0);
|
||||
rb_define_method(instr_klass, "dispbytes", instruction_dispbytes, 0);
|
||||
rb_define_method(instr_klass, "immbytes", instruction_immbytes, 0);
|
||||
rb_define_method(instr_klass, "sectionbytes", instruction_sectionbytes, 0);
|
||||
rb_define_method(instr_klass, "flags", instruction_flags, 0);
|
||||
rb_define_method(instr_klass, "raw", instruction_raw, 0);
|
||||
rb_define_method(instr_klass, "to_s", instruction_to_s, 0);
|
||||
rb_define_method(instr_klass, "op1", instruction_op1, 0);
|
||||
rb_define_method(instr_klass, "op2", instruction_op2, 0);
|
||||
rb_define_method(instr_klass, "op3", instruction_op3, 0);
|
||||
|
||||
// Operand
|
||||
oper_klass = rb_define_class_under(dasm_klass, "Operand",
|
||||
rb_define_class("Operand", rb_cObject));
|
||||
oper_type_klass = rb_define_module_under(oper_klass, "Type");
|
||||
|
||||
rb_define_alloc_func(oper_klass, operand_alloc);
|
||||
rb_define_method(oper_klass, "type", operand_type, 0);
|
||||
rb_define_method(oper_klass, "reg", operand_reg, 0);
|
||||
rb_define_method(oper_klass, "regtype", operand_regtype, 0);
|
||||
rb_define_method(oper_klass, "basereg", operand_basereg, 0);
|
||||
rb_define_method(oper_klass, "indexreg", operand_indexreg, 0);
|
||||
rb_define_method(oper_klass, "scale", operand_scale, 0);
|
||||
rb_define_method(oper_klass, "dispbytes", operand_dispbytes, 0);
|
||||
rb_define_method(oper_klass, "dispoffset", operand_dispoffset, 0);
|
||||
rb_define_method(oper_klass, "immbytes", operand_immbytes, 0);
|
||||
rb_define_method(oper_klass, "immoffset", operand_immoffset, 0);
|
||||
rb_define_method(oper_klass, "sectionbytes", operand_sectionbytes, 0);
|
||||
rb_define_method(oper_klass, "section", operand_section, 0);
|
||||
rb_define_method(oper_klass, "displacement", operand_displacement, 0);
|
||||
rb_define_method(oper_klass, "immediate", operand_immediate, 0);
|
||||
rb_define_method(oper_klass, "flags", operand_flags, 0);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
$:.unshift(File.join(File.dirname(__FILE__), '..', '..', '..'))
|
||||
|
||||
require 'test/unit'
|
||||
require 'ext/disassembler/x86'
|
||||
require 'ext/disassembler/x86/dasm'
|
||||
|
||||
class Ext::Disassembler::X86::Dasm::UnitTest < Test::Unit::TestCase
|
||||
Klass = Ext::Disassembler::X86::Dasm
|
||||
|
||||
def test_mode
|
||||
d = Klass.new
|
||||
|
||||
assert_equal(32, d.mode)
|
||||
assert_equal(true, d.set_mode(16))
|
||||
assert_equal(16, d.mode)
|
||||
assert_equal(true, d.set_mode(32))
|
||||
assert_equal(32, d.mode)
|
||||
end
|
||||
|
||||
def test_disassemble
|
||||
d = Klass.new
|
||||
b1 = "\x41"
|
||||
ary = d.disassemble(b1)
|
||||
|
||||
assert_not_nil(ary)
|
||||
|
||||
inst = ary[0]
|
||||
|
||||
assert_not_nil(inst)
|
||||
assert_kind_of(Ext::Disassembler::X86::Dasm::Instruction, inst)
|
||||
assert_equal(1, inst.length)
|
||||
assert_equal(Klass::Instruction::Type::INC, inst.type)
|
||||
assert_equal(32, inst.mode)
|
||||
assert_equal(0x41, inst.opcode)
|
||||
assert_nil(inst.modrm)
|
||||
assert_nil(inst.sib)
|
||||
assert_equal(0, inst.dispbytes)
|
||||
assert_equal(0, inst.immbytes)
|
||||
assert_equal(0, inst.sectionbytes)
|
||||
assert_equal("\x41", inst.raw)
|
||||
assert_equal("inc ecx", inst.to_s);
|
||||
d.set_format("att")
|
||||
assert_equal("inc %ecx", inst.to_s);
|
||||
end
|
||||
|
||||
def test_operand
|
||||
d = Klass.new
|
||||
b1 = "\xc7\x44\x24\x04\x78\x56\x34\x12\x41"
|
||||
ary = d.disassemble(b1)
|
||||
|
||||
assert_not_nil(ary)
|
||||
|
||||
inst1 = ary[0]
|
||||
inst2 = ary[1]
|
||||
|
||||
# inst1: mov dword [esp+0x4],0x12345678
|
||||
assert_not_nil(inst1.op1)
|
||||
assert_not_nil(inst1.op2)
|
||||
assert_nil(inst1.op3)
|
||||
assert_equal(Ext::Disassembler::X86::Operand::Type::Memory, inst1.op1.type)
|
||||
assert_equal(Ext::Disassembler::X86::Operand::Type::Immediate, inst1.op2.type)
|
||||
assert_equal(Ext::Disassembler::X86::Register::ESP, inst1.op1.basereg)
|
||||
assert_equal(4, inst1.op1.displacement)
|
||||
assert_equal(0x12345678, inst1.op2.immediate)
|
||||
assert_equal("mov dword [esp+0x4],0x12345678", inst1.to_s)
|
||||
|
||||
# inst2: inc ecx
|
||||
assert_not_nil(inst2.op1)
|
||||
assert_nil(inst2.op2)
|
||||
assert_nil(inst2.op3)
|
||||
assert_equal(Ext::Disassembler::X86::Register::ECX, inst2.op1.reg)
|
||||
assert_equal(Ext::Disassembler::X86::Register::Type::General, inst2.op1.regtype)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
require 'mkmf'
|
||||
create_makefile('dasm')
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,537 @@
|
|||
|
||||
/*
|
||||
* libdasm -- simple x86 disassembly library
|
||||
* (c) 2004 - 2005 jt / nologin.org
|
||||
*
|
||||
* libdasm.h:
|
||||
* Definitions for structures, functions and other weird stuff
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _LIBDASM_H
|
||||
#define _LIBDASM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define __LIBDASM_VERSION__ 0x01030000
|
||||
|
||||
#define GET_VERSION_MAJOR \
|
||||
(__LIBDASM_VERSION__ & 0xff000000) >> 24
|
||||
#define GET_VERSION_MINOR1 \
|
||||
(__LIBDASM_VERSION__ & 0x00ff0000) >> 16
|
||||
#define GET_VERSION_MINOR2 \
|
||||
(__LIBDASM_VERSION__ & 0x0000ff00) >> 8
|
||||
#define GET_VERSION_MINOR3 \
|
||||
(__LIBDASM_VERSION__ & 0x000000ff)
|
||||
|
||||
// Data types
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#define __inline__ __inline
|
||||
#define snprintf _snprintf
|
||||
typedef unsigned __int64 QWORD; // for MSVC
|
||||
typedef signed __int8 SBYTE;
|
||||
typedef signed __int16 SWORD;
|
||||
typedef signed __int32 SDWORD;
|
||||
typedef signed __int64 SQWORD;
|
||||
#else
|
||||
#if defined __sun
|
||||
#define BYTE_ORDER 1234
|
||||
#define BIG_ENDIAN 1234
|
||||
#define LITTLE_ENDIAN 4321
|
||||
#define u_int8_t uint8_t
|
||||
#define u_int16_t uint16_t
|
||||
#define u_int32_t uint32_t
|
||||
#define u_int64_t uint64_t
|
||||
|
||||
#endif // other *nix
|
||||
#include <sys/types.h>
|
||||
typedef u_int8_t BYTE;
|
||||
typedef u_int16_t WORD;
|
||||
typedef u_int32_t DWORD;
|
||||
typedef u_int64_t QWORD;
|
||||
typedef int8_t SBYTE;
|
||||
typedef int16_t SWORD;
|
||||
typedef int32_t SDWORD;
|
||||
typedef int64_t SQWORD;
|
||||
#endif
|
||||
|
||||
// Define endianess
|
||||
|
||||
#ifndef __X86__
|
||||
// These should catch x86 with most compilers
|
||||
#if defined _X86_ || defined _i386_ || defined __i386__
|
||||
#define __X86__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __LITTLE_ENDIAN__
|
||||
// These should catch little-endian with most compilers
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN) || defined __X86__ || defined _ALPHA_
|
||||
#define __LITTLE_ENDIAN__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// Registers
|
||||
#define REGISTER_EAX 0
|
||||
#define REGISTER_ECX 1
|
||||
#define REGISTER_EDX 2
|
||||
#define REGISTER_EBX 3
|
||||
#define REGISTER_ESP 4
|
||||
#define REGISTER_EBP 5
|
||||
#define REGISTER_ESI 6
|
||||
#define REGISTER_EDI 7
|
||||
#define REGISTER_NOP 8 // no register defined
|
||||
|
||||
// Registers
|
||||
#define REG_EAX REGISTER_EAX
|
||||
#define REG_AX REG_EAX
|
||||
#define REG_AL REG_EAX
|
||||
#define REG_ES REG_EAX // Just for reg_table consistence
|
||||
#define REG_ST0 REG_EAX // Just for reg_table consistence
|
||||
#define REG_ECX REGISTER_ECX
|
||||
#define REG_CX REG_ECX
|
||||
#define REG_CL REG_ECX
|
||||
#define REG_CS REG_ECX
|
||||
#define REG_ST1 REG_ECX
|
||||
#define REG_EDX REGISTER_EDX
|
||||
#define REG_DX REG_EDX
|
||||
#define REG_DL REG_EDX
|
||||
#define REG_SS REG_EDX
|
||||
#define REG_ST2 REG_EDX
|
||||
#define REG_EBX REGISTER_EBX
|
||||
#define REG_BX REG_EBX
|
||||
#define REG_BL REG_EBX
|
||||
#define REG_DS REG_EBX
|
||||
#define REG_ST3 REG_EBX
|
||||
#define REG_ESP REGISTER_ESP
|
||||
#define REG_SP REG_ESP
|
||||
#define REG_AH REG_ESP // Just for reg_table consistence
|
||||
#define REG_FS REG_ESP
|
||||
#define REG_ST4 REG_ESP
|
||||
#define REG_EBP REGISTER_EBP
|
||||
#define REG_BP REG_EBP
|
||||
#define REG_CH REG_EBP
|
||||
#define REG_GS REG_EBP
|
||||
#define REG_ST5 REG_EBP
|
||||
#define REG_ESI REGISTER_ESI
|
||||
#define REG_SI REG_ESI
|
||||
#define REG_DH REG_ESI
|
||||
#define REG_ST6 REG_ESI
|
||||
#define REG_EDI REGISTER_EDI
|
||||
#define REG_DI REG_EDI
|
||||
#define REG_BH REG_EDI
|
||||
#define REG_ST7 REG_EDI
|
||||
#define REG_NOP REGISTER_NOP
|
||||
|
||||
// Register types
|
||||
#define REGISTER_TYPE_GEN 1
|
||||
#define REGISTER_TYPE_SEGMENT 2
|
||||
#define REGISTER_TYPE_DEBUG 3
|
||||
#define REGISTER_TYPE_CONTROL 4
|
||||
#define REGISTER_TYPE_TEST 5
|
||||
#define REGISTER_TYPE_XMM 6
|
||||
#define REGISTER_TYPE_MMX 7
|
||||
#define REGISTER_TYPE_FPU 8
|
||||
|
||||
// Disassembling mode
|
||||
enum Mode {
|
||||
MODE_32, // 32-bit
|
||||
MODE_16 // 16-bit
|
||||
};
|
||||
|
||||
// Disassembling format
|
||||
enum Format {
|
||||
FORMAT_ATT,
|
||||
FORMAT_INTEL,
|
||||
};
|
||||
|
||||
// Instruction types (just the most common ones atm)
|
||||
enum Instruction {
|
||||
// Integer instructions
|
||||
INSTRUCTION_TYPE_ASC, // aaa, aam, etc.
|
||||
INSTRUCTION_TYPE_DCL, // daa, das
|
||||
INSTRUCTION_TYPE_MOV,
|
||||
INSTRUCTION_TYPE_MOVSR, // segment register
|
||||
INSTRUCTION_TYPE_ADD,
|
||||
INSTRUCTION_TYPE_XADD,
|
||||
INSTRUCTION_TYPE_ADC,
|
||||
INSTRUCTION_TYPE_SUB,
|
||||
INSTRUCTION_TYPE_SBB,
|
||||
INSTRUCTION_TYPE_INC,
|
||||
INSTRUCTION_TYPE_DEC,
|
||||
INSTRUCTION_TYPE_DIV,
|
||||
INSTRUCTION_TYPE_IDIV,
|
||||
INSTRUCTION_TYPE_NOT,
|
||||
INSTRUCTION_TYPE_NEG,
|
||||
INSTRUCTION_TYPE_STOS,
|
||||
INSTRUCTION_TYPE_LODS,
|
||||
INSTRUCTION_TYPE_SCAS,
|
||||
INSTRUCTION_TYPE_MOVS,
|
||||
INSTRUCTION_TYPE_MOVSX,
|
||||
INSTRUCTION_TYPE_MOVZX,
|
||||
INSTRUCTION_TYPE_CMPS,
|
||||
INSTRUCTION_TYPE_SHX, // signed/unsigned shift left/right
|
||||
INSTRUCTION_TYPE_ROX, // signed/unsigned rot left/right
|
||||
INSTRUCTION_TYPE_MUL,
|
||||
INSTRUCTION_TYPE_IMUL,
|
||||
INSTRUCTION_TYPE_EIMUL, // "extended" imul with 2-3 operands
|
||||
INSTRUCTION_TYPE_XOR,
|
||||
INSTRUCTION_TYPE_LEA,
|
||||
INSTRUCTION_TYPE_XCHG,
|
||||
INSTRUCTION_TYPE_CMP,
|
||||
INSTRUCTION_TYPE_TEST,
|
||||
INSTRUCTION_TYPE_PUSH,
|
||||
INSTRUCTION_TYPE_AND,
|
||||
INSTRUCTION_TYPE_OR,
|
||||
INSTRUCTION_TYPE_POP,
|
||||
INSTRUCTION_TYPE_JMP,
|
||||
INSTRUCTION_TYPE_JMPC, // conditional jump
|
||||
INSTRUCTION_TYPE_SETC, // conditional byte set
|
||||
INSTRUCTION_TYPE_MOVC, // conditional mov
|
||||
INSTRUCTION_TYPE_LOOP,
|
||||
INSTRUCTION_TYPE_CALL,
|
||||
INSTRUCTION_TYPE_RET,
|
||||
INSTRUCTION_TYPE_INT, // interrupt
|
||||
INSTRUCTION_TYPE_BT, // bit tests
|
||||
INSTRUCTION_TYPE_BTS,
|
||||
INSTRUCTION_TYPE_BTR,
|
||||
INSTRUCTION_TYPE_BTC,
|
||||
INSTRUCTION_TYPE_BSF,
|
||||
INSTRUCTION_TYPE_BSR,
|
||||
INSTRUCTION_TYPE_BSWAP,
|
||||
INSTRUCTION_TYPE_SGDT,
|
||||
INSTRUCTION_TYPE_SIDT,
|
||||
INSTRUCTION_TYPE_SLDT,
|
||||
INSTRUCTION_TYPE_LFP,
|
||||
// FPU instructions
|
||||
INSTRUCTION_TYPE_FCMOVC, // float conditional mov
|
||||
INSTRUCTION_TYPE_FADD,
|
||||
INSTRUCTION_TYPE_FADDP,
|
||||
INSTRUCTION_TYPE_FIADD,
|
||||
INSTRUCTION_TYPE_FSUB,
|
||||
INSTRUCTION_TYPE_FSUBP,
|
||||
INSTRUCTION_TYPE_FISUB,
|
||||
INSTRUCTION_TYPE_FSUBR,
|
||||
INSTRUCTION_TYPE_FSUBRP,
|
||||
INSTRUCTION_TYPE_FISUBR,
|
||||
INSTRUCTION_TYPE_FMUL,
|
||||
INSTRUCTION_TYPE_FMULP,
|
||||
INSTRUCTION_TYPE_FIMUL,
|
||||
INSTRUCTION_TYPE_FDIV,
|
||||
INSTRUCTION_TYPE_FDIVP,
|
||||
INSTRUCTION_TYPE_FDIVR,
|
||||
INSTRUCTION_TYPE_FDIVRP,
|
||||
INSTRUCTION_TYPE_FIDIV,
|
||||
INSTRUCTION_TYPE_FIDIVR,
|
||||
INSTRUCTION_TYPE_FCOM,
|
||||
INSTRUCTION_TYPE_FCOMP,
|
||||
INSTRUCTION_TYPE_FCOMPP,
|
||||
INSTRUCTION_TYPE_FCOMI,
|
||||
INSTRUCTION_TYPE_FCOMIP,
|
||||
INSTRUCTION_TYPE_FUCOM,
|
||||
INSTRUCTION_TYPE_FUCOMP,
|
||||
INSTRUCTION_TYPE_FUCOMPP,
|
||||
INSTRUCTION_TYPE_FUCOMI,
|
||||
INSTRUCTION_TYPE_FUCOMIP,
|
||||
INSTRUCTION_TYPE_FST,
|
||||
INSTRUCTION_TYPE_FSTP,
|
||||
INSTRUCTION_TYPE_FIST,
|
||||
INSTRUCTION_TYPE_FISTP,
|
||||
INSTRUCTION_TYPE_FISTTP,
|
||||
INSTRUCTION_TYPE_FLD,
|
||||
INSTRUCTION_TYPE_FILD,
|
||||
INSTRUCTION_TYPE_FICOM,
|
||||
INSTRUCTION_TYPE_FICOMP,
|
||||
INSTRUCTION_TYPE_FFREE,
|
||||
INSTRUCTION_TYPE_FFREEP,
|
||||
INSTRUCTION_TYPE_FXCH,
|
||||
INSTRUCTION_TYPE_FPU, // Other FPU instructions
|
||||
|
||||
INSTRUCTION_TYPE_MMX, // Other MMX instructions
|
||||
|
||||
INSTRUCTION_TYPE_SSE, // Other SSE instructions
|
||||
|
||||
INSTRUCTION_TYPE_OTHER, // Other instructions :-)
|
||||
INSTRUCTION_TYPE_PRIV // Privileged instruction
|
||||
};
|
||||
|
||||
// Operand types
|
||||
enum Operand {
|
||||
OPERAND_TYPE_NONE, // operand not present
|
||||
OPERAND_TYPE_MEMORY, // memory operand ([eax], [0], etc.)
|
||||
OPERAND_TYPE_REGISTER, // register operand (eax, mm0, etc.)
|
||||
OPERAND_TYPE_IMMEDIATE, // immediate operand (0x1234)
|
||||
};
|
||||
|
||||
// Structure definitions
|
||||
|
||||
// struct INST is used internally by the library
|
||||
typedef struct _INST {
|
||||
DWORD type; // Instruction type and flags
|
||||
const char *mnemonic; // Instruction mnemonic
|
||||
int flags1; // First operand flags (if any)
|
||||
int flags2; // Second operand flags (if any)
|
||||
int flags3; // Additional operand flags (if any)
|
||||
int modrm; // Is MODRM byte present?
|
||||
} INST, *PINST;
|
||||
|
||||
// Operands for the instruction
|
||||
typedef struct _OPERAND {
|
||||
enum Operand type; // Operand type (register, memory, etc)
|
||||
int reg; // Register (if any)
|
||||
int basereg; // Base register (if any)
|
||||
int indexreg; // Index register (if any)
|
||||
int scale; // Scale (if any)
|
||||
int dispbytes; // Displacement bytes (0 = no displacement)
|
||||
int dispoffset; // Displacement value offset
|
||||
int immbytes; // Immediate bytes (0 = no immediate)
|
||||
int immoffset; // Immediate value offset
|
||||
int sectionbytes; // Section prefix bytes (0 = no section prefix)
|
||||
WORD section; // Section prefix value
|
||||
DWORD displacement; // Displacement value
|
||||
DWORD immediate; // Immediate value
|
||||
int flags; // Operand flags
|
||||
} OPERAND, *POPERAND;
|
||||
|
||||
// struct INSTRUCTION is used to interface the library
|
||||
typedef struct _INSTRUCTION {
|
||||
int length; // Instruction length
|
||||
enum Instruction type; // Instruction type
|
||||
enum Mode mode; // Addressing mode
|
||||
BYTE opcode; // Actual opcode
|
||||
BYTE modrm; // MODRM byte
|
||||
BYTE sib; // SIB byte
|
||||
int extindex; // Extension table index
|
||||
int fpuindex; // FPU table index
|
||||
int dispbytes; // Displacement bytes (0 = no displacement)
|
||||
int immbytes; // Immediate bytes (0 = no immediate)
|
||||
int sectionbytes; // Section prefix bytes (0 = no section prefix)
|
||||
OPERAND op1; // First operand (if any)
|
||||
OPERAND op2; // Second operand (if any)
|
||||
OPERAND op3; // Additional operand (if any)
|
||||
PINST ptr; // Pointer to instruction table
|
||||
int flags; // Instruction flags
|
||||
} INSTRUCTION, *PINSTRUCTION;
|
||||
|
||||
|
||||
// Function definitions
|
||||
|
||||
int get_instruction(
|
||||
INSTRUCTION *inst, // pointer to INSTRUCTION structure
|
||||
BYTE *addr, // code buffer
|
||||
enum Mode mode // mode: MODE_32 or MODE_16
|
||||
);
|
||||
|
||||
// Get complete instruction string
|
||||
int get_instruction_string(
|
||||
INSTRUCTION *inst, // pointer to INSTRUCTION structure
|
||||
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
|
||||
DWORD offset, // instruction absolute address
|
||||
char *string, // string buffer
|
||||
int length // string length
|
||||
);
|
||||
|
||||
// Get mnemonic string
|
||||
int get_mnemonic_string(
|
||||
INSTRUCTION *inst, // pointer to INSTRUCTION structure
|
||||
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
|
||||
char *string, // string buffer
|
||||
int length // string length
|
||||
);
|
||||
|
||||
// Get individual operand string
|
||||
int get_operand_string(
|
||||
INSTRUCTION *inst, // pointer to INSTRUCTION structure
|
||||
POPERAND op, // pointer to OPERAND structure
|
||||
enum Format format, // instruction format: FORMAT_ATT or FORMAT_INTEL
|
||||
DWORD offset, // instruction absolute address
|
||||
char *string, // string buffer
|
||||
int length // string length
|
||||
);
|
||||
|
||||
// Helper functions
|
||||
|
||||
int get_register_type(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_type(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_register(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_basereg(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_indexreg(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_scale(
|
||||
POPERAND op
|
||||
);
|
||||
int get_operand_immediate(
|
||||
POPERAND op,
|
||||
DWORD *imm // returned immediate value
|
||||
);
|
||||
int get_operand_displacement(
|
||||
POPERAND op,
|
||||
DWORD *disp // returned displacement value
|
||||
);
|
||||
POPERAND get_source_operand(
|
||||
PINSTRUCTION inst
|
||||
);
|
||||
POPERAND get_destination_operand(
|
||||
PINSTRUCTION inst
|
||||
);
|
||||
|
||||
|
||||
// Instruction flags (prefixes)
|
||||
|
||||
// Group 1
|
||||
#define MASK_PREFIX_G1(x) ((x) & 0xff000000) >> 24
|
||||
#define PREFIX_LOCK 0x01000000 // 0xf0
|
||||
#define PREFIX_REPNE 0x02000000 // 0xf2
|
||||
#define PREFIX_REP 0x03000000 // 0xf3
|
||||
#define PREFIX_REPE 0x03000000 // 0xf3
|
||||
// Group 2
|
||||
#define MASK_PREFIX_G2(x) ((x) & 0x00ff0000) >> 16
|
||||
#define PREFIX_ES_OVERRIDE 0x00010000 // 0x26
|
||||
#define PREFIX_CS_OVERRIDE 0x00020000 // 0x2e
|
||||
#define PREFIX_SS_OVERRIDE 0x00030000 // 0x36
|
||||
#define PREFIX_DS_OVERRIDE 0x00040000 // 0x3e
|
||||
#define PREFIX_FS_OVERRIDE 0x00050000 // 0x64
|
||||
#define PREFIX_GS_OVERRIDE 0x00060000 // 0x65
|
||||
// Group 3 & 4
|
||||
#define MASK_PREFIX_G3(x) ((x) & 0x0000ff00) >> 8
|
||||
#define MASK_PREFIX_OPERAND(x) ((x) & 0x00000f00) >> 8
|
||||
#define MASK_PREFIX_ADDR(x) ((x) & 0x0000f000) >> 12
|
||||
#define PREFIX_OPERAND_SIZE_OVERRIDE 0x00000100 // 0x66
|
||||
#define PREFIX_ADDR_SIZE_OVERRIDE 0x00001000 // 0x67
|
||||
|
||||
// Extensions
|
||||
|
||||
#define MASK_EXT(x) ((x) & 0x000000ff)
|
||||
#define EXT_G1_1 0x00000001
|
||||
#define EXT_G1_2 0x00000002
|
||||
#define EXT_G1_3 0x00000003
|
||||
#define EXT_G2_1 0x00000004
|
||||
#define EXT_G2_2 0x00000005
|
||||
#define EXT_G2_3 0x00000006
|
||||
#define EXT_G2_4 0x00000007
|
||||
#define EXT_G2_5 0x00000008
|
||||
#define EXT_G2_6 0x00000009
|
||||
#define EXT_G3_1 0x0000000a
|
||||
#define EXT_G3_2 0x0000000b
|
||||
#define EXT_G4 0x0000000c
|
||||
#define EXT_G5 0x0000000d
|
||||
#define EXT_G6 0x0000000e
|
||||
#define EXT_G7 0x0000000f
|
||||
#define EXT_G8 0x00000010
|
||||
#define EXT_G9 0x00000011
|
||||
#define EXT_GA 0x00000012
|
||||
#define EXT_GB 0x00000013
|
||||
#define EXT_GC 0x00000014
|
||||
#define EXT_GD 0x00000015
|
||||
#define EXT_GE 0x00000016
|
||||
#define EXT_GF 0x00000017
|
||||
#define EXT_G0 0x00000018
|
||||
|
||||
// Extra groups for 2 and 3-byte opcodes, and FPU stuff
|
||||
#define EXT_T2 0x00000020 // opcode table 2
|
||||
#define EXT_CP 0x00000030 // co-processor
|
||||
|
||||
// Instruction type flags
|
||||
|
||||
#define TYPE_3 0x80000000
|
||||
#define MASK_TYPE_FLAGS(x) ((x) & 0xff000000)
|
||||
#define MASK_TYPE_VALUE(x) ((x) & 0x00ffffff)
|
||||
|
||||
|
||||
// Operand flags
|
||||
|
||||
#define FLAGS_NONE 0
|
||||
|
||||
// Operand Addressing Methods, from the Intel manual
|
||||
#define MASK_AM(x) ((x) & 0x00ff0000)
|
||||
#define AM_A 0x00010000 // Direct address with segment prefix
|
||||
#define AM_C 0x00020000 // MODRM reg field defines control register
|
||||
#define AM_D 0x00030000 // MODRM reg field defines debug register
|
||||
#define AM_E 0x00040000 // MODRM byte defines reg/memory address
|
||||
#define AM_G 0x00050000 // MODRM byte defines general-purpose reg
|
||||
#define AM_I 0x00060000 // Immediate data follows
|
||||
#define AM_J 0x00070000 // Immediate value is relative to EIP
|
||||
#define AM_M 0x00080000 // MODRM mod field can refer only to memory
|
||||
#define AM_O 0x00090000 // Displacement follows (without modrm/sib)
|
||||
#define AM_P 0x000a0000 // MODRM reg field defines MMX register
|
||||
#define AM_Q 0x000b0000 // MODRM defines MMX register or memory
|
||||
#define AM_R 0x000c0000 // MODRM mod field can only refer to register
|
||||
#define AM_S 0x000d0000 // MODRM reg field defines segment register
|
||||
#define AM_T 0x000e0000 // MODRM reg field defines test register
|
||||
#define AM_V 0x000f0000 // MODRM reg field defines XMM register
|
||||
#define AM_W 0x00100000 // MODRM defines XMM register or memory
|
||||
// Extra addressing modes used in this implementation
|
||||
#define AM_I1 0x00200000 // Immediate byte 1 encoded in instruction
|
||||
#define AM_REG 0x00210000 // Register encoded in instruction
|
||||
#define AM_IND 0x00220000 // Register indirect encoded in instruction
|
||||
|
||||
// Operand Types, from the intel manual
|
||||
#define MASK_OT(x) ((x) & 0xff000000)
|
||||
#define OT_a 0x01000000
|
||||
#define OT_b 0x02000000 // always 1 byte
|
||||
#define OT_c 0x03000000 // byte or word, depending on operand
|
||||
#define OT_d 0x04000000 // double-word
|
||||
#define OT_q 0x05000000 // quad-word
|
||||
#define OT_dq 0x06000000 // double quad-word
|
||||
#define OT_v 0x07000000 // word or double-word, depending on operand
|
||||
#define OT_w 0x08000000 // always word
|
||||
#define OT_p 0x09000000 // 32-bit or 48-bit pointer
|
||||
#define OT_pi 0x0a000000 // quadword MMX register
|
||||
#define OT_pd 0x0b000000 // 128-bit double-precision float
|
||||
#define OT_ps 0x0c000000 // 128-bit single-precision float
|
||||
#define OT_s 0x0d000000 // 6-byte pseudo descriptor
|
||||
#define OT_sd 0x0e000000 // Scalar of 128-bit double-precision float
|
||||
#define OT_ss 0x0f000000 // Scalar of 128-bit single-precision float
|
||||
#define OT_si 0x10000000 // Doubleword integer register
|
||||
#define OT_t 0x11000000 // 80-bit packed FP data
|
||||
|
||||
// Operand permissions
|
||||
#define MASK_PERMS(x) ((x) & 0x0000f000)
|
||||
#define P_r 0x00004000 // Read
|
||||
#define P_w 0x00002000 // Write
|
||||
#define P_x 0x00001000 // Execute
|
||||
|
||||
// Additional operand flags
|
||||
#define MASK_FLAGS(x) ((x) & 0x00000f00)
|
||||
#define F_s 0x00000100 // sign-extend 1-byte immediate
|
||||
#define F_r 0x00000200 // use segment register
|
||||
#define F_f 0x00000400 // use FPU register
|
||||
|
||||
// Mask 0x000000f0 unused atm
|
||||
|
||||
// Operand register mask
|
||||
#define MASK_REG(x) ((x) & 0x0000000f)
|
||||
|
||||
|
||||
|
||||
// MODRM byte
|
||||
#define MASK_MODRM_MOD(x) (((x) & 0xc0) >> 6)
|
||||
#define MASK_MODRM_REG(x) (((x) & 0x38) >> 3)
|
||||
#define MASK_MODRM_RM(x) ((x) & 0x7)
|
||||
|
||||
// SIB byte
|
||||
#define MASK_SIB_SCALE(x) MASK_MODRM_MOD(x)
|
||||
#define MASK_SIB_INDEX(x) MASK_MODRM_REG(x)
|
||||
#define MASK_SIB_BASE(x) MASK_MODRM_RM(x)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue