Home | History | Annotate | Download | only in libdisasm
      1 #ifndef LIBDISASM_H
      2 #define LIBDISASM_H
      3 
      4 #ifdef WIN32
      5 #include <windows.h>
      6 #endif
      7 
      8 #include <stdint.h>
      9 
     10 /* 'NEW" types
     11  * __________________________________________________________________________*/
     12 #ifndef LIBDISASM_QWORD_H       /* do not interfere with qword.h */
     13         #define LIBDISASM_QWORD_H
     14         #ifdef _MSC_VER
     15                 typedef __int64         qword_t;
     16         #else
     17                 typedef int64_t         qword_t;
     18         #endif
     19 #endif
     20 
     21 #include <sys/types.h>
     22 
     23 #ifdef __cplusplus
     24 extern "C" {
     25 #endif
     26 
     27 /* 'NEW" x86 API
     28  * __________________________________________________________________________*/
     29 
     30 
     31 /* ========================================= Error Reporting */
     32 /* REPORT CODES
     33  *      These are passed to a reporter function passed at initialization.
     34  *      Each code determines the type of the argument passed to the reporter;
     35  *      this allows the report to recover from errors, or just log them.
     36  */
     37 enum x86_report_codes {
     38         report_disasm_bounds,   /* RVA OUT OF BOUNDS : The disassembler could
     39                                    not disassemble the supplied RVA as it is
     40                                    out of the range of the buffer. The
     41                                    application should store the address and
     42                                    attempt to determine what section of the
     43                                    binary it is in, then disassemble the
     44                                    address from the bytes in that section.
     45                                         data: uint32_t rva */
     46         report_insn_bounds,     /* INSTRUCTION OUT OF BOUNDS: The disassembler
     47                                    could not disassemble the instruction as
     48                                    the instruction would require bytes beyond
     49                                    the end of the current buffer. This usually
     50                                    indicated garbage bytes at the end of a
     51                                    buffer, or an incorrectly-sized buffer.
     52                                         data: uint32_t rva */
     53         report_invalid_insn,    /* INVALID INSTRUCTION: The disassembler could
     54                                    not disassemble the instruction as it has an
     55                                    invalid combination of opcodes and operands.
     56                                    This will stop automated disassembly; the
     57                                    application can restart the disassembly
     58                                    after the invalid instruction.
     59                                         data: uint32_t rva */
     60         report_unknown
     61 };
     62 
     63 /* 'arg' is optional arbitrary data provided by the code passing the
     64  *       callback -- for example, it could be 'this' or 'self' in OOP code.
     65  * 'code' is provided by libdisasm, it is one of the above
     66  * 'data' is provided by libdisasm and is context-specific, per the enums */
     67 typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
     68 				 void *data, void *arg );
     69 
     70 
     71 /* x86_report_error : Call the register reporter to report an error */
     72 void x86_report_error( enum x86_report_codes code, void *data );
     73 
     74 /* ========================================= Libdisasm Management Routines */
     75 enum x86_options {		/* these can be ORed together */
     76         opt_none= 0,
     77         opt_ignore_nulls=1,     /* ignore sequences of > 4 NULL bytes */
     78         opt_16_bit=2,           /* 16-bit/DOS disassembly */
     79         opt_att_mnemonics=4,    /* use AT&T syntax names for alternate opcode mnemonics */
     80 };
     81 
     82 /* management routines */
     83 /* 'arg' is caller-specific data which is passed as the first argument
     84  * to the reporter callback routine */
     85 int x86_init( enum x86_options options, DISASM_REPORTER reporter, void *arg);
     86 void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
     87 void x86_set_options( enum x86_options options );
     88 enum x86_options x86_get_options( void );
     89 int x86_cleanup(void);
     90 
     91 
     92 /* ========================================= Instruction Representation */
     93 /* these defines are only intended for use in the array decl's */
     94 #define MAX_REGNAME 8
     95 
     96 #define MAX_PREFIX_STR 32
     97 #define MAX_MNEM_STR 16
     98 #define MAX_INSN_SIZE 20        /* same as in i386.h */
     99 #define MAX_OP_STRING 32        /* max possible operand size in string form */
    100 #define MAX_OP_RAW_STRING 64    /* max possible operand size in raw form */
    101 #define MAX_OP_XML_STRING 256   /* max possible operand size in xml form */
    102 #define MAX_NUM_OPERANDS 8	/* max # implicit and explicit operands */
    103 /* in these, the '2 *' is arbitrary: the max # of operands should require
    104  * more space than the rest of the insn */
    105 #define MAX_INSN_STRING 512        /* 2 * 8 * MAX_OP_STRING */
    106 #define MAX_INSN_RAW_STRING 1024   /* 2 * 8 * MAX_OP_RAW_STRING */
    107 #define MAX_INSN_XML_STRING 4096   /* 2 * 8 * MAX_OP_XML_STRING */
    108 
    109 enum x86_reg_type {     /* NOTE: these may be ORed together */
    110         reg_gen         = 0x00001,      /* general purpose */
    111         reg_in          = 0x00002,      /* incoming args, ala RISC */
    112         reg_out         = 0x00004,      /* args to calls, ala RISC */
    113         reg_local       = 0x00008,      /* local vars, ala RISC */
    114         reg_fpu         = 0x00010,      /* FPU data register */
    115         reg_seg         = 0x00020,      /* segment register */
    116         reg_simd        = 0x00040,      /* SIMD/MMX reg */
    117         reg_sys         = 0x00080,      /* restricted/system register */
    118         reg_sp          = 0x00100,      /* stack pointer */
    119         reg_fp          = 0x00200,      /* frame pointer */
    120         reg_pc          = 0x00400,      /* program counter */
    121         reg_retaddr     = 0x00800,      /* return addr for func */
    122         reg_cond        = 0x01000,      /* condition code / flags */
    123         reg_zero        = 0x02000,      /* zero register, ala RISC */
    124         reg_ret         = 0x04000,      /* return value */
    125         reg_src         = 0x10000,      /* array/rep source */
    126         reg_dest        = 0x20000,      /* array/rep destination */
    127         reg_count       = 0x40000       /* array/rep/loop counter */
    128 };
    129 
    130 /* x86_reg_t : an X86 CPU register */
    131 typedef struct {
    132         char name[MAX_REGNAME];
    133         enum x86_reg_type type;         /* what register is used for */
    134         unsigned int size;              /* size of register in bytes */
    135         unsigned int id;                /* register ID #, for quick compares */
    136 	unsigned int alias;		/* ID of reg this is an alias for */
    137 	unsigned int shift;		/* amount to shift aliased reg by */
    138 } x86_reg_t;
    139 
    140 /* x86_ea_t : an X86 effective address (address expression) */
    141 typedef struct {
    142         unsigned int     scale;         /* scale factor */
    143         x86_reg_t        index, base;   /* index, base registers */
    144         int32_t          disp;          /* displacement */
    145         char             disp_sign;     /* is negative? 1/0 */
    146         char             disp_size;     /* 0, 1, 2, 4 */
    147 } x86_ea_t;
    148 
    149 /* x86_absolute_t : an X86 segment:offset address (descriptor) */
    150 typedef struct {
    151 	unsigned short	segment;	/* loaded directly into CS */
    152 	union {
    153 		unsigned short	off16;	/* loaded directly into IP */
    154 		uint32_t		off32;	/* loaded directly into EIP */
    155 	} offset;
    156 } x86_absolute_t;
    157 
    158 enum x86_op_type {      /* mutually exclusive */
    159         op_unused = 0,          /* empty/unused operand: should never occur */
    160         op_register = 1,        /* CPU register */
    161         op_immediate = 2,       /* Immediate Value */
    162         op_relative_near = 3,   /* Relative offset from IP */
    163         op_relative_far = 4,    /* Relative offset from IP */
    164         op_absolute = 5,        /* Absolute address (ptr16:32) */
    165         op_expression = 6,      /* Address expression (scale/index/base/disp) */
    166         op_offset = 7,          /* Offset from start of segment (m32) */
    167         op_unknown
    168 };
    169 
    170 #define x86_optype_is_address( optype ) \
    171 	( optype == op_absolute || optype == op_offset )
    172 #define x86_optype_is_relative( optype ) \
    173 	( optype == op_relative_near || optype == op_relative_far )
    174 #define x86_optype_is_memory( optype ) \
    175 	( optype > op_immediate && optype < op_unknown )
    176 
    177 enum x86_op_datatype {          /* these use Intel's lame terminology */
    178         op_byte = 1,            /* 1 byte integer */
    179         op_word = 2,            /* 2 byte integer */
    180         op_dword = 3,           /* 4 byte integer */
    181         op_qword = 4,           /* 8 byte integer */
    182         op_dqword = 5,          /* 16 byte integer */
    183         op_sreal = 6,           /* 4 byte real (single real) */
    184         op_dreal = 7,           /* 8 byte real (double real) */
    185         op_extreal = 8,         /* 10 byte real (extended real) */
    186         op_bcd = 9,             /* 10 byte binary-coded decimal */
    187         op_ssimd = 10,          /* 16 byte : 4 packed single FP (SIMD, MMX) */
    188         op_dsimd = 11,          /* 16 byte : 2 packed double FP (SIMD, MMX) */
    189         op_sssimd = 12,         /* 4 byte : scalar single FP (SIMD, MMX) */
    190         op_sdsimd = 13,         /* 8 byte : scalar double FP (SIMD, MMX) */
    191 	op_descr32 = 14,	/* 6 byte Intel descriptor 2:4 */
    192 	op_descr16 = 15,	/* 4 byte Intel descriptor 2:2 */
    193 	op_pdescr32 = 16,	/* 6 byte Intel pseudo-descriptor 32:16 */
    194 	op_pdescr16 = 17,	/* 6 byte Intel pseudo-descriptor 8:24:16 */
    195 	op_bounds16 = 18,	/* signed 16:16 lower:upper bounds */
    196 	op_bounds32 = 19,	/* signed 32:32 lower:upper bounds */
    197         op_fpuenv16 = 20,	/* 14 byte FPU control/environment data */
    198         op_fpuenv32 = 21,	/* 28 byte FPU control/environment data */
    199 	op_fpustate16 = 22,	/* 94 byte FPU state (env & reg stack) */
    200 	op_fpustate32 = 23,	/* 108 byte FPU state (env & reg stack) */
    201 	op_fpregset = 24,	/* 512 bytes: register set */
    202 	op_fpreg = 25,		/* FPU register */
    203     op_none = 0xFF,     /* operand without a datatype (INVLPG) */
    204 };
    205 
    206 enum x86_op_access {    /* ORed together */
    207         op_read = 1,
    208         op_write = 2,
    209         op_execute = 4
    210 };
    211 
    212 enum x86_op_flags {     /* ORed together, but segs are mutually exclusive */
    213         op_signed = 1,          /* signed integer */
    214         op_string = 2,          /* possible string or array */
    215         op_constant = 4,        /* symbolic constant */
    216         op_pointer = 8,         /* operand points to a memory address */
    217 	op_sysref = 0x010,	/* operand is a syscall number */
    218 	op_implied = 0x020,	/* operand is implicit in the insn */
    219 	op_hardcode = 0x40,	/* operand is hardcoded in insn definition */
    220 	/* NOTE: an 'implied' operand is one which can be considered a side
    221 	 * effect of the insn, e.g. %esp being modified by PUSH or POP. A
    222 	 * 'hard-coded' operand is one which is specified in the instruction
    223 	 * definition, e.g. %es:%edi in MOVSB or 1 in ROL Eb, 1. The difference
    224 	 * is that hard-coded operands are printed by disassemblers and are
    225 	 * required to re-assemble, while implicit operands are invisible. */
    226         op_es_seg = 0x100,      /* ES segment override */
    227         op_cs_seg = 0x200,      /* CS segment override */
    228         op_ss_seg = 0x300,      /* SS segment override */
    229         op_ds_seg = 0x400,      /* DS segment override */
    230         op_fs_seg = 0x500,      /* FS segment override */
    231         op_gs_seg = 0x600       /* GS segment override */
    232 };
    233 
    234 /* x86_op_t : an X86 instruction operand */
    235 typedef struct {
    236         enum x86_op_type        type;           /* operand type */
    237         enum x86_op_datatype    datatype;       /* operand size */
    238         enum x86_op_access      access;         /* operand access [RWX] */
    239         enum x86_op_flags       flags;          /* misc flags */
    240         union {
    241 		/* sizeof will have to work on these union members! */
    242                 /* immediate values */
    243                 char            sbyte;
    244                 short           sword;
    245                 int32_t         sdword;
    246                 qword_t         sqword;
    247                 unsigned char   byte;
    248                 unsigned short  word;
    249                 uint32_t        dword;
    250                 qword_t         qword;
    251                 float           sreal;
    252                 double          dreal;
    253                 /* misc large/non-native types */
    254                 unsigned char   extreal[10];
    255                 unsigned char   bcd[10];
    256                 qword_t         dqword[2];
    257                 unsigned char   simd[16];
    258                 unsigned char   fpuenv[28];
    259                 /* offset from segment */
    260                 uint32_t        offset;
    261                 /* ID of CPU register */
    262                 x86_reg_t       reg;
    263                 /* offsets from current insn */
    264                 char            relative_near;
    265                 int32_t         relative_far;
    266 		/* segment:offset */
    267 		x86_absolute_t	absolute;
    268                 /* effective address [expression] */
    269                 x86_ea_t        expression;
    270         } data;
    271 	/* this is needed to make formatting operands more sane */
    272 	void * insn;		/* pointer to x86_insn_t owning operand */
    273 } x86_op_t;
    274 
    275 /* Linked list of x86_op_t; provided for manual traversal of the operand
    276  * list in an insn. Users wishing to add operands to this list, e.g. to add
    277  * implicit operands, should use x86_operand_new in x86_operand_list.h */
    278 typedef struct x86_operand_list {
    279 	x86_op_t op;
    280 	struct x86_operand_list *next;
    281 } x86_oplist_t;
    282 
    283 enum x86_insn_group {
    284 	insn_none = 0,		/* invalid instruction */
    285         insn_controlflow = 1,
    286         insn_arithmetic = 2,
    287         insn_logic = 3,
    288         insn_stack = 4,
    289         insn_comparison = 5,
    290         insn_move = 6,
    291         insn_string = 7,
    292         insn_bit_manip = 8,
    293         insn_flag_manip = 9,
    294         insn_fpu = 10,
    295         insn_interrupt = 13,
    296         insn_system = 14,
    297         insn_other = 15
    298 };
    299 
    300 enum x86_insn_type {
    301 	insn_invalid = 0,	/* invalid instruction */
    302         /* insn_controlflow */
    303         insn_jmp = 0x1001,
    304         insn_jcc = 0x1002,
    305         insn_call = 0x1003,
    306         insn_callcc = 0x1004,
    307         insn_return = 0x1005,
    308         /* insn_arithmetic */
    309         insn_add = 0x2001,
    310         insn_sub = 0x2002,
    311         insn_mul = 0x2003,
    312         insn_div = 0x2004,
    313         insn_inc = 0x2005,
    314         insn_dec = 0x2006,
    315         insn_shl = 0x2007,
    316         insn_shr = 0x2008,
    317         insn_rol = 0x2009,
    318         insn_ror = 0x200A,
    319         /* insn_logic */
    320         insn_and = 0x3001,
    321         insn_or = 0x3002,
    322         insn_xor = 0x3003,
    323         insn_not = 0x3004,
    324         insn_neg = 0x3005,
    325         /* insn_stack */
    326         insn_push = 0x4001,
    327         insn_pop = 0x4002,
    328         insn_pushregs = 0x4003,
    329         insn_popregs = 0x4004,
    330         insn_pushflags = 0x4005,
    331         insn_popflags = 0x4006,
    332         insn_enter = 0x4007,
    333         insn_leave = 0x4008,
    334         /* insn_comparison */
    335         insn_test = 0x5001,
    336         insn_cmp = 0x5002,
    337         /* insn_move */
    338         insn_mov = 0x6001,      /* move */
    339         insn_movcc = 0x6002,    /* conditional move */
    340         insn_xchg = 0x6003,     /* exchange */
    341         insn_xchgcc = 0x6004,   /* conditional exchange */
    342         /* insn_string */
    343         insn_strcmp = 0x7001,
    344         insn_strload = 0x7002,
    345         insn_strmov = 0x7003,
    346         insn_strstore = 0x7004,
    347         insn_translate = 0x7005,        /* xlat */
    348         /* insn_bit_manip */
    349         insn_bittest = 0x8001,
    350         insn_bitset = 0x8002,
    351         insn_bitclear = 0x8003,
    352         /* insn_flag_manip */
    353         insn_clear_carry = 0x9001,
    354         insn_clear_zero = 0x9002,
    355         insn_clear_oflow = 0x9003,
    356         insn_clear_dir = 0x9004,
    357         insn_clear_sign = 0x9005,
    358         insn_clear_parity = 0x9006,
    359         insn_set_carry = 0x9007,
    360         insn_set_zero = 0x9008,
    361         insn_set_oflow = 0x9009,
    362         insn_set_dir = 0x900A,
    363         insn_set_sign = 0x900B,
    364         insn_set_parity = 0x900C,
    365         insn_tog_carry = 0x9010,
    366         insn_tog_zero = 0x9020,
    367         insn_tog_oflow = 0x9030,
    368         insn_tog_dir = 0x9040,
    369         insn_tog_sign = 0x9050,
    370         insn_tog_parity = 0x9060,
    371         /* insn_fpu */
    372         insn_fmov = 0xA001,
    373         insn_fmovcc = 0xA002,
    374         insn_fneg = 0xA003,
    375         insn_fabs = 0xA004,
    376         insn_fadd = 0xA005,
    377         insn_fsub = 0xA006,
    378         insn_fmul = 0xA007,
    379         insn_fdiv = 0xA008,
    380         insn_fsqrt = 0xA009,
    381         insn_fcmp = 0xA00A,
    382         insn_fcos = 0xA00C,
    383         insn_fldpi = 0xA00D,
    384         insn_fldz = 0xA00E,
    385         insn_ftan = 0xA00F,
    386         insn_fsine = 0xA010,
    387         insn_fsys = 0xA020,
    388         /* insn_interrupt */
    389         insn_int = 0xD001,
    390         insn_intcc = 0xD002,    /* not present in x86 ISA */
    391         insn_iret = 0xD003,
    392         insn_bound = 0xD004,
    393         insn_debug = 0xD005,
    394         insn_trace = 0xD006,
    395         insn_invalid_op = 0xD007,
    396         insn_oflow = 0xD008,
    397         /* insn_system */
    398         insn_halt = 0xE001,
    399         insn_in = 0xE002,       /* input from port/bus */
    400         insn_out = 0xE003,      /* output to port/bus */
    401         insn_cpuid = 0xE004,
    402         /* insn_other */
    403         insn_nop = 0xF001,
    404         insn_bcdconv = 0xF002,  /* convert to or from BCD */
    405         insn_szconv = 0xF003    /* change size of operand */
    406 };
    407 
    408 /* These flags specify special characteristics of the instruction, such as
    409  * whether the inatruction is privileged or whether it serializes the
    410  * pipeline.
    411  * NOTE : These may not be accurate for all instructions; updates to the
    412  * opcode tables have not been completed. */
    413 enum x86_insn_note {
    414 	insn_note_ring0		= 1,	/* Only available in ring 0 */
    415 	insn_note_smm		= 2,	/* "" in System Management Mode */
    416 	insn_note_serial	= 4,	/* Serializing instruction */
    417 	insn_note_nonswap	= 8,	/* Does not swap arguments in att-style formatting */
    418 	insn_note_nosuffix  = 16,	/* Does not have size suffix in att-style formatting */
    419 };
    420 
    421 /* This specifies what effects the instruction has on the %eflags register */
    422 enum x86_flag_status {
    423         insn_carry_set = 0x1,			/* CF */
    424         insn_zero_set = 0x2,			/* ZF */
    425         insn_oflow_set = 0x4,			/* OF */
    426         insn_dir_set = 0x8,			/* DF */
    427         insn_sign_set = 0x10,			/* SF */
    428         insn_parity_set = 0x20,			/* PF */
    429         insn_carry_or_zero_set = 0x40,
    430         insn_zero_set_or_sign_ne_oflow = 0x80,
    431         insn_carry_clear = 0x100,
    432         insn_zero_clear = 0x200,
    433         insn_oflow_clear = 0x400,
    434         insn_dir_clear = 0x800,
    435         insn_sign_clear = 0x1000,
    436         insn_parity_clear = 0x2000,
    437         insn_sign_eq_oflow = 0x4000,
    438         insn_sign_ne_oflow = 0x8000
    439 };
    440 
    441 /* The CPU model in which the insturction first appeared; this can be used
    442  * to mask out instructions appearing in earlier or later models or to
    443  * check the portability of a binary.
    444  * NOTE : These may not be accurate for all instructions; updates to the
    445  * opcode tables have not been completed. */
    446 enum x86_insn_cpu {
    447 	cpu_8086 	= 1,	/* Intel */
    448 	cpu_80286	= 2,
    449 	cpu_80386	= 3,
    450 	cpu_80387	= 4,
    451 	cpu_80486	= 5,
    452 	cpu_pentium	= 6,
    453 	cpu_pentiumpro	= 7,
    454 	cpu_pentium2	= 8,
    455 	cpu_pentium3	= 9,
    456 	cpu_pentium4	= 10,
    457 	cpu_k6		= 16,	/* AMD */
    458 	cpu_k7		= 32,
    459 	cpu_athlon	= 48
    460 };
    461 
    462 /* CPU ISA subsets: These are derived from the Instruction Groups in
    463  * Intel Vol 1 Chapter 5; they represent subsets of the IA32 ISA but
    464  * do not reflect the 'type' of the instruction in the same way that
    465  * x86_insn_group does. In short, these are AMD/Intel's somewhat useless
    466  * designations.
    467  * NOTE : These may not be accurate for all instructions; updates to the
    468  * opcode tables have not been completed. */
    469 enum x86_insn_isa {
    470 	isa_gp		= 1,	/* general purpose */
    471 	isa_fp		= 2,	/* floating point */
    472 	isa_fpumgt	= 3,	/* FPU/SIMD management */
    473 	isa_mmx		= 4,	/* Intel MMX */
    474 	isa_sse1	= 5,	/* Intel SSE SIMD */
    475 	isa_sse2	= 6,	/* Intel SSE2 SIMD */
    476 	isa_sse3	= 7,	/* Intel SSE3 SIMD */
    477 	isa_3dnow	= 8,	/* AMD 3DNow! SIMD */
    478 	isa_sys		= 9	/* system instructions */
    479 };
    480 
    481 enum x86_insn_prefix {
    482         insn_no_prefix = 0,
    483         insn_rep_zero = 1,	/* REPZ and REPE */
    484         insn_rep_notzero = 2,	/* REPNZ and REPNZ */
    485         insn_lock = 4		/* LOCK: */
    486 };
    487 
    488 /* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
    489 /* x86_insn_t : an X86 instruction */
    490 typedef struct {
    491         /* information about the instruction */
    492         uint32_t addr;             /* load address */
    493         uint32_t offset;           /* offset into file/buffer */
    494         enum x86_insn_group group;      /* meta-type, e.g. INS_EXEC */
    495         enum x86_insn_type type;        /* type, e.g. INS_BRANCH */
    496 	enum x86_insn_note note;	/* note, e.g. RING0 */
    497         unsigned char bytes[MAX_INSN_SIZE];
    498         unsigned char size;             /* size of insn in bytes */
    499 	/* 16/32-bit mode settings */
    500 	unsigned char addr_size;	/* default address size : 2 or 4 */
    501 	unsigned char op_size;		/* default operand size : 2 or 4 */
    502 	/* CPU/instruction set */
    503 	enum x86_insn_cpu cpu;
    504 	enum x86_insn_isa isa;
    505 	/* flags */
    506         enum x86_flag_status flags_set; /* flags set or tested by insn */
    507         enum x86_flag_status flags_tested;
    508 	/* stack */
    509 	unsigned char stack_mod;	/* 0 or 1 : is the stack modified? */
    510 	int32_t stack_mod_val;		/* val stack is modified by if known */
    511 
    512         /* the instruction proper */
    513         enum x86_insn_prefix prefix;	/* prefixes ORed together */
    514         char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
    515         char mnemonic[MAX_MNEM_STR];
    516         x86_oplist_t *operands;		/* list of explicit/implicit operands */
    517 	size_t operand_count;		/* total number of operands */
    518 	size_t explicit_count;		/* number of explicit operands */
    519         /* convenience fields for user */
    520         void *block;                    /* code block containing this insn */
    521         void *function;                 /* function containing this insn */
    522         int tag;			/* tag the insn as seen/processed */
    523 } x86_insn_t;
    524 
    525 
    526 /* returns 0 if an instruction is invalid, 1 if valid */
    527 int x86_insn_is_valid( x86_insn_t *insn );
    528 
    529 /* DISASSEMBLY ROUTINES
    530  *      Canonical order of arguments is
    531  *        (buf, buf_len, buf_rva, offset, len, insn, func, arg, resolve_func)
    532  *      ...but of course all of these are not used at the same time.
    533  */
    534 
    535 
    536 /* Function prototype for caller-supplied callback routine
    537  *      These callbacks are intended to process 'insn' further, e.g. by
    538  *      adding it to a linked list, database, etc */
    539 typedef void (*DISASM_CALLBACK)( x86_insn_t *insn, void * arg );
    540 
    541 /* Function prototype for caller-supplied address resolver.
    542  *      This routine is used to determine the rva to disassemble next, given
    543  *      the 'dest' operand of a jump/call. This allows the caller to resolve
    544  *      jump/call targets stored in a register or on the stack, and also allows
    545  *      the caller to prevent endless loops by checking if an address has
    546  *      already been disassembled. If an address cannot be resolved from the
    547  *      operand, or if the address has already been disassembled, this routine
    548  *      should return -1; in all other cases the RVA to be disassembled next
    549  *      should be returned. */
    550 typedef int32_t (*DISASM_RESOLVER)( x86_op_t *op, x86_insn_t * current_insn,
    551 				 void *arg );
    552 
    553 
    554 /* x86_disasm: Disassemble a single instruction from a buffer of bytes.
    555  *             Returns size of instruction in bytes.
    556  *             Caller is responsible for calling x86_oplist_free() on
    557  *             a reused "insn" to avoid leaking memory when calling this
    558  *             function repeatedly.
    559  *      buf     : Buffer of bytes to disassemble
    560  *      buf_len : Length of the buffer
    561  *      buf_rva : Load address of the start of the buffer
    562  *      offset  : Offset in buffer to disassemble
    563  *      insn    : Structure to fill with disassembled instruction
    564  */
    565 unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
    566                 	 uint32_t buf_rva, unsigned int offset,
    567                 	 x86_insn_t * insn );
    568 
    569 /* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
    570  *                   invoking a callback function each time an instruction
    571  *                   is successfully disassembled. The 'range' refers to the
    572  *                   bytes between 'offset' and 'offset + len' in the buffer;
    573  *                   'len' is assumed to be less than the length of the buffer.
    574  *                   Returns number of instructions processed.
    575  *      buf     : Buffer of bytes to disassemble (e.g. .text section)
    576  *      buf_rva : Load address of buffer (e.g. ELF Virtual Address)
    577  *      offset  : Offset in buffer to start disassembly at
    578  *      len     : Number of bytes to disassemble
    579  *      func    : Callback function to invoke (may be NULL)
    580  *      arg     : Arbitrary data to pass to callback (may be NULL)
    581  */
    582 unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
    583 	                       unsigned int offset, unsigned int len,
    584 	                       DISASM_CALLBACK func, void *arg );
    585 
    586 /* x86_disasm_forward: Flow-of-execution disassembly of the bytes in a buffer,
    587  *                     invoking a callback function each time an instruction
    588  *                     is successfully disassembled.
    589  *      buf     : Buffer to disassemble (e.g. .text section)
    590  *      buf_len : Number of bytes in buffer
    591  *      buf_rva : Load address of buffer (e.g. ELF Virtual Address)
    592  *      offset  : Offset in buffer to start disassembly at (e.g. entry point)
    593  *      func    : Callback function to invoke (may be NULL)
    594  *      arg     : Arbitrary data to pass to callback (may be NULL)
    595  *      resolver: Caller-supplied address resolver. If no resolver is
    596  *                supplied, a default internal one is used -- however the
    597  *                internal resolver does NOT catch loops and could end up
    598  *                disassembling forever..
    599  *      r_arg	: Arbitrary data to pass to resolver (may be NULL)
    600  */
    601 unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
    602 	                         uint32_t buf_rva, unsigned int offset,
    603 	                         DISASM_CALLBACK func, void *arg,
    604 	                         DISASM_RESOLVER resolver, void *r_arg );
    605 
    606 /* Instruction operands: these are stored as a list of explicit and
    607  * implicit operands. It is recommended that the 'foreach' routines
    608  * be used to when examining operands for purposes of data flow analysis */
    609 
    610 /* Operand FOREACH callback: 'arg' is an abritrary parameter passed to the
    611  * foreach routine, 'insn' is the x86_insn_t whose operands are being
    612  * iterated over, and 'op' is the current x86_op_t */
    613 typedef void (*x86_operand_fn)(x86_op_t *op, x86_insn_t *insn, void *arg);
    614 
    615 /* FOREACH types: these are used to limit the foreach results to
    616  * operands which match a certain "type" (implicit or explicit)
    617  * or which are accessed in certain ways (e.g. read or write). Note
    618  * that this operates on the operand list of single instruction, so
    619  * specifying the 'real' operand type (register, memory, etc) is not
    620  * useful. Note also that by definition Execute Access implies Read
    621  * Access and implies Not Write Access.
    622  * The "type" (implicit or explicit) and the access method can
    623  * be ORed together, e.g. op_wo | op_explicit */
    624 enum x86_op_foreach_type {
    625 	op_any 	= 0,		/* ALL operands (explicit, implicit, rwx) */
    626 	op_dest = 1,		/* operands with Write access */
    627 	op_src 	= 2,		/* operands with Read access */
    628 	op_ro 	= 3,		/* operands with Read but not Write access */
    629 	op_wo 	= 4,		/* operands with Write but not Read access */
    630 	op_xo 	= 5,		/* operands with Execute access */
    631 	op_rw 	= 6,		/* operands with Read AND Write access */
    632 	op_implicit = 0x10,	/* operands that are implied by the opcode */
    633 	op_explicit = 0x20	/* operands that are not side-effects */
    634 };
    635 
    636 
    637 /* free the operand list associated with an instruction -- useful for
    638  * preventing memory leaks when free()ing an x86_insn_t */
    639 void x86_oplist_free( x86_insn_t *insn );
    640 
    641 /* Operand foreach: invokes 'func' with 'insn' and 'arg' as arguments. The
    642  * 'type' parameter is used to select only operands matching specific
    643  * criteria. */
    644 int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg,
    645 	       	  	 enum x86_op_foreach_type type);
    646 
    647 /* convenience routine: returns count of operands matching 'type' */
    648 size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type );
    649 
    650 /* accessor functions for the operands */
    651 x86_op_t * x86_operand_1st( x86_insn_t *insn );
    652 x86_op_t * x86_operand_2nd( x86_insn_t *insn );
    653 x86_op_t * x86_operand_3rd( x86_insn_t *insn );
    654 
    655 /* these allow libdisasm 2.0 accessor functions to still be used */
    656 #define x86_get_dest_operand( insn ) x86_operand_1st( insn )
    657 #define x86_get_src_operand( insn ) x86_operand_2nd( insn )
    658 #define x86_get_imm_operand( insn ) x86_operand_3rd( insn )
    659 
    660 /* get size of operand data in bytes */
    661 unsigned int x86_operand_size( x86_op_t *op );
    662 
    663 /* Operand Convenience Routines: the following three routines are common
    664  * operations on operands, intended to ease the burden of the programmer. */
    665 
    666 /* Get Address: return the value of an offset operand, or the offset of
    667  * a segment:offset absolute address */
    668 uint32_t x86_get_address( x86_insn_t *insn );
    669 
    670 /* Get Relative Offset: return as a sign-extended int32_t the near or far
    671  * relative offset operand, or 0 if there is none. There can be only one
    672  * relaive offset operand in an instruction. */
    673 int32_t x86_get_rel_offset( x86_insn_t *insn );
    674 
    675 /* Get Branch Target: return the x86_op_t containing the target of
    676  * a jump or call operand, or NULL if there is no branch target.
    677  * Internally, a 'branch target' is defined as any operand with
    678  * Execute Access set. There can be only one branch target per instruction. */
    679 x86_op_t * x86_get_branch_target( x86_insn_t *insn );
    680 
    681 /* Get Immediate: return the x86_op_t containing the immediate operand
    682  * for this instruction, or NULL if there is no immediate operand. There
    683  * can be only one immediate operand per instruction */
    684 x86_op_t * x86_get_imm( x86_insn_t *insn );
    685 
    686 /* Get Raw Immediate Data: returns a pointer to the immediate data encoded
    687  * in the instruction. This is useful for large data types [>32 bits] currently
    688  * not supported by libdisasm, or for determining if the disassembler
    689  * screwed up the conversion of the immediate data. Note that 'imm' in this
    690  * context refers to immediate data encoded at the end of an instruction as
    691  * detailed in the Intel Manual Vol II Chapter 2; it does not refer to the
    692  * 'op_imm' operand (the third operand in instructions like 'mul' */
    693 unsigned char * x86_get_raw_imm( x86_insn_t *insn );
    694 
    695 
    696 /* More accessor fuctions, this time for user-defined info... */
    697 /* set the address (usually RVA) of the insn */
    698 void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr );
    699 
    700 /* set the offset (usually offset into file) of the insn */
    701 void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset );
    702 
    703 /* set a pointer to the function owning the instruction. The
    704  * type of 'func' is user-defined; libdisasm does not use the func field. */
    705 void x86_set_insn_function( x86_insn_t *insn, void * func );
    706 
    707 /* set a pointer to the block of code owning the instruction. The
    708  * type of 'block' is user-defined; libdisasm does not use the block field. */
    709 void x86_set_insn_block( x86_insn_t *insn, void * block );
    710 
    711 /* instruction tagging: these routines allow the programmer to mark
    712  * instructions as "seen" in a DFS, for example. libdisasm does not use
    713  * the tag field.*/
    714 /* set insn->tag to 1 */
    715 void x86_tag_insn( x86_insn_t *insn );
    716 /* set insn->tag to 0 */
    717 void x86_untag_insn( x86_insn_t *insn );
    718 /* return insn->tag */
    719 int x86_insn_is_tagged( x86_insn_t *insn );
    720 
    721 
    722 /* Disassembly formats:
    723  *      AT&T is standard AS/GAS-style: "mnemonic\tsrc, dest, imm"
    724  *      Intel is standard MASM/NASM/TASM: "mnemonic\tdest,src, imm"
    725  *      Native is tab-delimited: "RVA\tbytes\tmnemonic\tdest\tsrc\timm"
    726  *      XML is your typical <insn> ... </insn>
    727  *      Raw is addr|offset|size|bytes|prefix... see libdisasm_formats.7
    728  */
    729 enum x86_asm_format {
    730 	unknown_syntax = 0,		/* never use! */
    731 	native_syntax, 			/* header: 35 bytes */
    732 	intel_syntax, 			/* header: 23 bytes */
    733 	att_syntax,  			/* header: 23 bytes */
    734 	xml_syntax,			/* header: 679 bytes */
    735 	raw_syntax			/* header: 172 bytes */
    736 };
    737 
    738 /* format (sprintf) an operand into 'buf' using specified syntax */
    739 int x86_format_operand(x86_op_t *op, char *buf, int len,
    740                   enum x86_asm_format format);
    741 
    742 /* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
    743 int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
    744                         enum x86_asm_format format);
    745 
    746 /* format (sprintf) an instruction into 'buf' using specified syntax;
    747  * this includes formatting all operands */
    748 int x86_format_insn(x86_insn_t *insn, char *buf, int len, enum x86_asm_format);
    749 
    750 /* fill 'buf' with a description of the format's syntax */
    751 int x86_format_header( char *buf, int len, enum x86_asm_format format);
    752 
    753 /* Endianness of an x86 CPU : 0 is big, 1 is little; always returns 1 */
    754 unsigned int x86_endian(void);
    755 
    756 /* Default address and operand size in bytes */
    757 unsigned int x86_addr_size(void);
    758 unsigned int x86_op_size(void);
    759 
    760 /* Size of a machine word in bytes */
    761 unsigned int x86_word_size(void);
    762 
    763 /* maximum size of a code instruction */
    764 #define x86_max_inst_size(x) x86_max_insn_size(x)
    765 unsigned int x86_max_insn_size(void);
    766 
    767 /* register IDs of Stack, Frame, Instruction pointer and Flags register */
    768 unsigned int x86_sp_reg(void);
    769 unsigned int x86_fp_reg(void);
    770 unsigned int x86_ip_reg(void);
    771 unsigned int x86_flag_reg(void);
    772 
    773 /* fill 'reg' struct with details of register 'id' */
    774 void x86_reg_from_id( unsigned int id, x86_reg_t * reg );
    775 
    776 /* convenience macro demonstrating how to get an aliased register; proto is
    777  *   void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
    778  * where 'alias_reg' is a reg operand and 'output_reg' is filled with the
    779  * register that the operand is an alias for */
    780 #define x86_get_aliased_reg( alias_reg, output_reg )			\
    781 	x86_reg_from_id( alias_reg->alias, output_reg )
    782 
    783 
    784 /* ================================== Invariant Instruction Representation */
    785 /* Invariant instructions are used for generating binary signatures;
    786  * the instruction is modified so that all variant bytes in an instruction
    787  * are replaced with a wildcard byte.
    788  *
    789  * A 'variant byte' is one that is expected to be modified by either the
    790  * static or the dynamic linker: for example, an address encoded in an
    791  * instruction.
    792  *
    793  * By comparing the invariant representation of one instruction [or of a
    794  * sequence of instructions] with the invariant representation of another,
    795  * one determine whether the two invariant representations are from the same
    796  * relocatable object [.o] file. Thus one can use binary signatures [which
    797  * are just sequences of invariant instruction representations] to look for
    798  * library routines which have been statically-linked into a binary.
    799  *
    800  * The invariant routines are faster and smaller than the disassembly
    801  * routines; they can be used to determine the size of an instruction
    802  * without all of the overhead of a full instruction disassembly.
    803  */
    804 
    805 /* This byte is used to replace variant bytes */
    806 #define X86_WILDCARD_BYTE 0xF4
    807 
    808 typedef struct {
    809         enum x86_op_type        type;           /* operand type */
    810         enum x86_op_datatype    datatype;       /* operand size */
    811         enum x86_op_access      access;         /* operand access [RWX] */
    812         enum x86_op_flags       flags;          /* misc flags */
    813 } x86_invariant_op_t;
    814 
    815 typedef struct {
    816 	unsigned char bytes[64];	/* invariant representation */
    817 	unsigned int  size;		/* number of bytes in insn */
    818         enum x86_insn_group group;      /* meta-type, e.g. INS_EXEC */
    819         enum x86_insn_type type;        /* type, e.g. INS_BRANCH */
    820 	x86_invariant_op_t operands[3];	/* operands: dest, src, imm */
    821 } x86_invariant_t;
    822 
    823 
    824 /* return a version of the instruction with the variant bytes masked out */
    825 size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
    826 			  x86_invariant_t *inv );
    827 /* return the size in bytes of the intruction pointed to by 'buf';
    828  * this used x86_invariant_disasm since it faster than x86_disasm */
    829 size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );
    830 
    831 #ifdef __cplusplus
    832 }
    833 #endif
    834 
    835 
    836 #endif
    837