Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
x86_disasm(3)			   libdisasm			 x86_disasm(3)

NAME
       x86_disasm,   x86_disasm_forward,   x86_disasm_range  -	disassemble  a
       bytestream to x86 assembly language instructions

SYNOPSIS
       #include	<libdis.h>

       typedef void (*DISASM_CALLBACK)(	x86_insn_t *, void * );
       typedef long (*DISASM_RESOLVER)(	x86_op_t *, x86_insn_t *, void * );

       int x86_disasm( unsigned	char *buf, unsigned int	buf_len,
		 unsigned long buf_rva,	unsigned int offset,
		 x86_insn_t * insn );
       int x86_disasm_range( unsigned char *buf, unsigned long buf_rva,
		       unsigned	int offset, unsigned int len,
		       DISASM_CALLBACK func, void *arg );
       int x86_disasm_forward( unsigned	char *buf, unsigned int	buf_len,
		      unsigned long buf_rva, unsigned int offset,
		      DISASM_CALLBACK func, void *arg,
		      DISASM_RESOLVER resolver,	void *r_arg );

DESCRIPTION
       #define MAX_REGNAME 8
       #define MAX_PREFIX_STR 32
       #define MAX_MNEM_STR 16
       #define MAX_INSN_SIZE 20	/* same	as in i386.h */
       #define MAX_OP_STRING 32	/* max possible	operand	size in	string form */
       #define MAX_OP_RAW_STRING 64    /* max possible	operand	 size  in  raw
       form */
       #define	MAX_OP_XML_STRING  256	  /*  max possible operand size	in xml
       form */
       #define MAX_NUM_OPERANDS	8    /*	max # implicit and  explicit  operands
       */
       #define MAX_INSN_STRING 512	  /* 2 * 8 * MAX_OP_STRING */
       #define MAX_INSN_RAW_STRING 1024	  /* 2 * 8 * MAX_OP_RAW_STRING */
       #define MAX_INSN_XML_STRING 4096	  /* 2 * 8 * MAX_OP_XML_STRING */

       enum x86_reg_type {	/* NOTE: these may be ORed together */
	    reg_gen	= 0x00001,   /*	general	purpose	*/
	    reg_in	= 0x00002,   /*	incoming args, ala RISC	*/
	    reg_out	= 0x00004,   /*	args to	calls, ala RISC	*/
	    reg_local	= 0x00008,   /*	local vars, ala	RISC */
	    reg_fpu	= 0x00010,   /*	FPU data register */
	    reg_seg	= 0x00020,   /*	segment	register */
	    reg_simd	= 0x00040,   /*	SIMD/MMX reg */
	    reg_sys	= 0x00080,   /*	restricted/system register */
	    reg_sp	= 0x00100,   /*	stack pointer */
	    reg_fp	= 0x00200,   /*	frame pointer */
	    reg_pc	= 0x00400,   /*	program	counter	*/
	    reg_retaddr	= 0x00800,   /*	return addr for	func */
	    reg_cond	= 0x01000,   /*	condition code / flags */
	    reg_zero	= 0x02000,   /*	zero register, ala RISC	*/
	    reg_ret	= 0x04000,   /*	return value */
	    reg_src	= 0x10000,   /*	array/rep source */
	    reg_dest	= 0x20000,   /*	array/rep destination */
	    reg_count	= 0x40000    /*	array/rep/loop counter */
       };

       typedef struct {
	    char name[MAX_REGNAME];
	    enum x86_reg_type type;	       /* what register	is used	for */
	    unsigned int size;		  /* size of register in bytes */
	    unsigned  int  id;			 /*  register  ID #, for quick
       compares	*/
	    unsigned int alias;		  /* ID	of reg this is an alias	of */
	    unsigned int shift;		  /* amount to shift aliased reg by */
       } x86_reg_t;

       typedef struct {
	    unsigned int     scale;	  /* scale factor */
	    x86_reg_t	     index, base; /* index, base registers */
	    long	     disp;	  /* displacement */
	    char	     disp_sign;	  /* is	negative? 1/0 */
	    char	     disp_size;	  /* 0,	1, 2, 4	*/
       } x86_ea_t;

       enum x86_op_type	{  /* mutually exclusive */
	    op_unused =	0,	/* empty/unused	operand	*/
	    op_register	= 1,	/* CPU register	*/
	    op_immediate = 2,	/* Immediate Value */
	    op_relative_near = 3,    /*	Relative offset	from IP	*/
	    op_relative_far = 4,
	    op_absolute	= 5,	/* Absolute address (ptr16:32) */
	    op_expression = 6,	/* Address expression  (scale/index/base/disp)
       */
	    op_offset =	7,	/* Offset from start of	segment	(m32) */
	    op_unknown
       };

       enum x86_op_datatype {	     /*	these use Intel's lame terminology */
	    op_byte = 1,	/* 1 byte integer */
	    op_word = 2,	/* 2 byte integer */
	    op_dword = 3,	/* 4 byte integer */
	    op_qword = 4,	/* 8 byte integer */
	    op_dqword =	5,	/* 16 byte integer */
	    op_sreal = 6,	/* 4 byte real (single real) */
	    op_dreal = 7,	/* 8 byte real (double real) */
	    op_extreal = 8,	     /*	10 byte	real (extended real) */
	    op_bcd = 9,		/* 10 byte binary-coded	decimal	*/
	    op_simd = 10,	/* 16 byte packed (SIMD, MMX) */
	       op_ssimd	 = 10,		/* 16 byte : 4 packed single FP	(SIMD,
       MMX) */
	       op_dsimd	= 11,	       /* 16 byte : 2 packed double FP	(SIMD,
       MMX) */
	       op_sssimd  =  12,	  /*  4	byte : scalar single FP	(SIMD,
       MMX) */
	       op_sdsimd = 13,	       /* 8 byte :  scalar  double  FP	(SIMD,
       MMX) */
	    op_descr32 = 14,	/* 6 byte Intel	descriptor 2:4 */
	    op_descr16 = 15,	/* 4 byte Intel	descriptor 2:2 */
	    op_pdescr32	= 16,	/* 6 byte Intel	pseudo-descriptor 32:16	*/
	    op_pdescr16	= 17,	/* 6 byte Intel	pseudo-descriptor 8:24:16 */
	    op_fpuenv =	11	/* 28 byte FPU control/environment data	*/
       };

       enum x86_op_access {	/* ORed	together */
	    op_read = 1,
	    op_write = 2,
	    op_execute = 4
       };

       enum  x86_op_flags  { /*	ORed together, but segs	are mutually exclusive
       */
	    op_signed =	1,	/* signed integer */
	    op_string =	2,	/* possible string or array */
	    op_constant	= 4,	/* symbolic constant */
	    op_pointer = 8,	     /*	operand	points to a memory address */
	    op_sysref =	0x010,	/* operand is a	syscall	number */
	    op_implied = 0x020,	/* operand is implicit in insn */
	    op_hardcode	= 0x040, /* operans is hardcoded in insn */
	    op_es_seg =	0x100,	/* ES segment override */
	    op_cs_seg =	0x200,	/* CS segment override */
	    op_ss_seg =	0x300,	/* SS segment override */
	    op_ds_seg =	0x400,	/* DS segment override */
	    op_fs_seg =	0x500,	/* FS segment override */
	    op_gs_seg =	0x600	/* GS segment override */
       };

       typedef struct {
	    enum x86_op_type	type;	       /* operand type */
	    enum x86_op_datatype     datatype; /* operand size */
	    enum x86_op_access	access;	       /* operand access [RWX] */
	    enum x86_op_flags	flags;	       /* misc flags */
	    union {
		 /* immediate values */
		 char		sbyte;
		 short		sword;
		 long		sdword;
		 qword		sqword;
		 unsigned char	byte;
		 unsigned short	     word;
		 unsigned long	dword;
		 qword		     qword;
		 float		   sreal;
		 double		   dreal;
		 /* misc large/non-native types	*/
		 unsigned char	extreal[10];
		 unsigned char	bcd[10];
		 qword		dqword[2];
		 unsigned char	simd[16];
		 unsigned char	fpuenv[28];
		 /* absolute address */
		 void		* address;
		 /* offset from	segment	*/
		 unsigned long	offset;
		 /* ID of CPU register */
		 x86_reg_t reg;
		 /* offsets from current insn */
		 char		relative_near;
		 long		relative_far;
		 /* effective address [expression] */
		 x86_ea_t  expression;
	    } data;
	    void * insn;
       } x86_op_t;

       typedef struct x86_operand_list {
	    x86_op_t op;
	    struct x86_operand_list *next;
       } x86_oplist_t;

       enum x86_insn_group {
	    insn_none =	0,
	    insn_controlflow = 1,
	    insn_arithmetic = 2,
	    insn_logic = 3,
	    insn_stack = 4,
	    insn_comparison = 5,
	    insn_move =	6,
	    insn_string	= 7,
	    insn_bit_manip = 8,
	    insn_flag_manip = 9,
	    insn_fpu = 10,
	    insn_interrupt = 13,
	    insn_system	= 14,
	    insn_other = 15
       };

       enum x86_insn_type {
	    insn_invalid = 0,
	    /* insn_controlflow	*/
	    insn_jmp = 0x1001,
	    insn_jcc = 0x1002,
	    insn_call =	0x1003,
	    insn_callcc	= 0x1004,
	    insn_return	= 0x1005,
	    insn_loop =	0x1006,
	    /* insn_arithmetic */
	    insn_add = 0x2001,
	    insn_sub = 0x2002,
	    insn_mul = 0x2003,
	    insn_div = 0x2004,
	    insn_inc = 0x2005,
	    insn_dec = 0x2006,
	    insn_shl = 0x2007,
	    insn_shr = 0x2008,
	    insn_rol = 0x2009,
	    insn_ror = 0x200A,
	    /* insn_logic */
	    insn_and = 0x3001,
	    insn_or = 0x3002,
	    insn_xor = 0x3003,
	    insn_not = 0x3004,
	    insn_neg = 0x3005,
	    /* insn_stack */
	    insn_push =	0x4001,
	    insn_pop = 0x4002,
	    insn_pushregs = 0x4003,
	    insn_popregs = 0x4004,
	    insn_pushflags = 0x4005,
	    insn_popflags = 0x4006,
	    insn_enter = 0x4007,
	    insn_leave = 0x4008,
	    /* insn_comparison */
	    insn_test =	0x5001,
	    insn_cmp = 0x5002,
	    /* insn_move */
	    insn_mov = 0x6001,	/* move	*/
	    insn_movcc = 0x6002,     /*	conditional move */
	    insn_xchg =	0x6003,	/* exchange */
	    insn_xchgcc	= 0x6004,    /*	conditional exchange */
	    /* insn_string */
	    insn_strcmp	= 0x7001,
	    insn_strload = 0x7002,
	    insn_strmov	= 0x7003,
	    insn_strstore = 0x7004,
	    insn_translate = 0x7005, /*	xlat */
	    /* insn_bit_manip */
	    insn_bittest = 0x8001,
	    insn_bitset	= 0x8002,
	    insn_bitclear = 0x8003,
	    /* insn_flag_manip */
	    insn_clear_carry = 0x9001,
	    insn_clear_zero = 0x9002,
	    insn_clear_oflow = 0x9003,
	    insn_clear_dir = 0x9004,
	    insn_clear_sign = 0x9005,
	    insn_clear_parity =	0x9006,
	    insn_set_carry = 0x9007,
	    insn_set_zero = 0x9008,
	    insn_set_oflow = 0x9009,
	    insn_set_dir = 0x900A,
	    insn_set_sign = 0x900B,
	    insn_set_parity = 0x900C,
	    insn_tog_carry = 0x9010,
	    insn_tog_zero = 0x9020,
	    insn_tog_oflow = 0x9030,
	    insn_tog_dir = 0x9040,
	    insn_tog_sign = 0x9050,
	    insn_tog_parity = 0x9060,
	    /* insn_fpu	*/
	    insn_fmov =	0xA001,
	    insn_fmovcc	= 0xA002,
	    insn_fneg =	0xA003,
	    insn_fabs =	0xA004,
	    insn_fadd =	0xA005,
	    insn_fsub =	0xA006,
	    insn_fmul =	0xA007,
	    insn_fdiv =	0xA008,
	    insn_fsqrt = 0xA009,
	    insn_fcmp =	0xA00A,
	    insn_fcos =	0xA00C,
	    insn_fldpi = 0xA00D,
	    insn_fldz =	0xA00E,
	    insn_ftan =	0xA00F,
	    insn_fsine = 0xA010,
	    insn_fsys =	0xA020,
	    /* insn_interrupt */
	    insn_int = 0xD001,
	    insn_intcc = 0xD002,     /*	not present in x86 ISA */
	    insn_iret =	0xD003,
	    insn_bound = 0xD004,
	    insn_debug = 0xD005,
	    insn_trace = 0xD006,
	    insn_invalid_op = 0xD007,
	    insn_oflow = 0xD008,
	    /* insn_system */
	    insn_halt =	0xE001,
	    insn_in = 0xE002,	/* input from port/bus */
	    insn_out = 0xE003,	/* output to port/bus */
	    insn_cpuid = 0xE004,
	    /* insn_other */
	    insn_nop = 0xF001,
	    insn_bcdconv = 0xF002,   /*	convert	to or from BCD */
	    insn_szconv	= 0xF003     /*	change size of operand */
       };

       enum x86_insn_note {
	    insn_note_ring0	     = 1, /* Only available in ring 0 */
	    insn_note_smm	= 2, /*	"" in System Management	Mode */
	    insn_note_serial	= 4  /*	Serializing instruction	*/
       };

       enum x86_flag_status {
	    insn_carry_set = 0x1,
	    insn_zero_set = 0x2,
	    insn_oflow_set = 0x4,
	    insn_dir_set = 0x8,
	    insn_sign_set = 0x10,
	    insn_parity_set = 0x20,
	    insn_carry_or_zero_set = 0x40,
	    insn_zero_set_or_sign_ne_oflow = 0x80,
	    insn_carry_clear = 0x100,
	    insn_zero_clear = 0x200,
	    insn_oflow_clear = 0x400,
	    insn_dir_clear = 0x800,
	    insn_sign_clear = 0x1000,
	    insn_parity_clear =	0x2000,
	    insn_sign_eq_oflow = 0x4000,
	    insn_sign_ne_oflow = 0x8000
       };

       enum x86_insn_cpu {
	    cpu_8086  =	1, /* Intel */
	    cpu_80286 =	2,
	    cpu_80386 =	3,
	    cpu_80387 =	4,
	    cpu_80486 =	5,
	    cpu_pentium	   = 6,
	    cpu_pentiumpro = 7,
	    cpu_pentium2   = 8,
	    cpu_pentium3   = 9,	>br>	  cpu_pentium4	 = 10,
	    cpu_k6	   = 16,     /*	AMD */
	    cpu_k7	   = 32,
	    cpu_athlon	   = 48
       };

       enum x86_insn_isa {
	    isa_gp	   = 1,	/* general purpose */
	    isa_fp	   = 2,	/* floating point */
	    isa_fpumgt	   = 3,	/* FPU/SIMD management */
	    isa_mmx	   = 4,	/* Intel MMX */
	    isa_sse1  =	5, /* Intel SSE	SIMD */
	    isa_sse2  =	6, /* Intel SSE2 SIMD */
	    isa_sse3  =	7, /* Intel SSE3 SIMD */
	    isa_3dnow =	8, /* AMD 3DNow! SIMD */
	    isa_sys	   = 9	/* system instructions */
       };

       enum x86_insn_prefix {
	    insn_no_prefix = 0,
	    insn_rep_zero = 1,
	    insn_rep_notzero = 2,
	    insn_lock =	4,
	    insn_delay = 8
       };

       typedef struct {
	    /* information about the instruction */
	    unsigned long addr;	     /*	load address */
	    unsigned long offset;	  /* offset into file/buffer */
	    enum x86_insn_group	group;	  /* meta-type,	e.g. INSN_EXEC */
	    enum x86_insn_type type; /*	type, e.g. INSN_BRANCH */
	    unsigned char bytes[MAX_INSN_SIZE];
	    unsigned char size;	     /*	size of	insn in	bytes */
	    enum x86_insn_prefix prefix;
	    enum x86_flag_status flags_set; /* flags set or tested by insn */
	    enum x86_flag_status flags_tested;
	    /* the instruction proper */
	    char prefix_string[32];	  /* prefixes [might be	truncated] */
	    char mnemonic[8];
	    x86_op_t operands[3];
	    /* convenience fields for user */
	    void *block;	     /*	code block containing this insn	*/
	    void *function;		  /* function containing this insn */
	    void *tag;		     /*	tag the	insn as	seen/processed */
       } x86_insn_t;
       #define X86_WILDCARD_BYTE 0xF4

       typedef struct {
	       enum x86_op_type	       type;	       /* operand type */
	       enum x86_op_datatype    datatype;       /* operand size */
	       enum x86_op_access      access;	       /* operand access [RWX]
       */
	       enum x86_op_flags       flags;	       /* misc flags */
       } x86_invariant_op_t;

       typedef struct {
	    unsigned char bytes[64]; /*	invariant representation */
	    unsigned int  size;	     /*	number of bytes	in insn	*/
	       enum x86_insn_group group;      /* meta-type, e.g. INSN_EXEC */
	       enum x86_insn_type type;	       /* type,	e.g. INSN_BRANCH */
	    x86_invariant_op_t	 operands[3];	 /*   use   same  ordering  as
       x86_insn_t */
       } x86_invariant_t;

EXAMPLES
       The following sample callback outputs instructions in raw syntax:

       void raw_print( x86_insn_t *insn, void *arg ) {
	       char line[1024];
	       x86_format_insn(insn, line, 1024, raw_syntax);
	       printf( "%s0, line);
       }

       The following sample resolver performs very limited checking on the op-
       erand  of  a jump or call to determine what program address the operand
       refers to:

       long resolver( x86_op_t *op, x86_insn_t *insn ) {
	       long retval = -1;
	       /* this is a flat ripoff	of internal_resolver in	libdis.c --
		  we don't do any register or stack resolving, or check
		  to see if we have already encountered	this RVA */
	       if ( op->type ==	op_absolute || op->type	== op_offset ) {
		       retval =	op->data.sdword;
	       } else if (op->type == op_relative ){
		       if ( op->datatype == op_byte ) {
			       retval	=   insn->addr	  +    insn->size    +
       op->data.sbyte;
		       } else if ( op->datatype	== op_word ) {
			       retval	 =    insn->addr    +	insn->size   +
       op->data.sword;
		       } else if ( op->datatype	== op_dword ) {
			       retval =	insn->addr + insn->size	+ op->data.sd-
       word;
		       }
	       }
	       return( retval );
       }

       The  following  code snippets demonstrate how to	use the	various	disas-
       sembly routines:

	       unsigned	char *buf;  /* buffer of bytes to disassemble */
	       unsigned	int buf_len;/* length of buffer	*/
	       unsigned	long rva;   /* load address of start of	buffer */
	       unsigned	int pos;    /* position	in buffer */
	       x86_insn_t insn;	    /* disassembled instruction	*/

	       /* disassemble entire buffer, printing automatically */
	       x86_disasm_range( buf, buf_rva, pos, buf_len,
				 raw_print, NULL );

	       /* disassemble a	single instruction, then print it */
	       if (x86_disasm( buf, buf_len, buf_rva, pos, &insn ) ) {
		       raw_print( &insn, NULL );
	       }

	       /* disassemble forward in 'buf' starting	at 'pos' */
	       x86_disasm_forward( buf,	buf_len, buf_rva, pos,
				   raw_print, NULL, resolver );

SEE ALSO
       libdisasm(7), x86_format_insn(3), x86_init(3), x86dis(1)

mammon_				     0.21			 x86_disasm(3)

NAME | SYNOPSIS | DESCRIPTION | EXAMPLES | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=x86_disasm&sektion=3&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help