1%module x86disasm
2%{
3#ifdef _MSC_VER
4	typedef __int64         qword;
5#else
6	typedef long long       qword;
7#endif
8
9#include <sys/types.h>
10
11#define MAX_REGNAME 8
12#define MAX_PREFIX_STR 32
13#define MAX_MNEM_STR 16
14#define MAX_INSN_SIZE 20
15#define MAX_OP_STRING 32
16#define MAX_OP_RAW_STRING 64
17#define MAX_OP_XML_STRING 256
18#define MAX_NUM_OPERANDS 8
19#define MAX_INSN_STRING 512
20#define MAX_INSN_RAW_STRING 1024
21#define MAX_INSN_XML_STRING 4096
22
23#include "../../../config.h"
24
25
26const char * version_string( void ) {
27	return PACKAGE_VERSION;
28}
29
30%}
31
32const char * version_string( void );
33
34%rename(X86_Register) x86_reg_t;
35%rename(X86_EAddr) x86_ea_t;
36%rename(X86_Operand) x86_op_t;
37//%rename(X86_OpList) x86_oplist_t;
38%rename(X86_Insn) x86_insn_t;
39%rename(X86_InvOperand) x86_invariant_op_t;
40%rename(X86_Invariant) x86_invariant_t;
41
42%include "carrays.i"
43
44%array_class( unsigned char, byteArray );
45
46
47%apply (unsigned char *STRING, int LENGTH) {
48	(unsigned char *buf, size_t buf_len)
49};
50
51
52%inline %{
53
54
55enum x86_asm_format {
56	unknown_syntax = 0,		/* never use! */
57	native_syntax, 			/* header: 35 bytes */
58	intel_syntax, 			/* header: 23 bytes */
59	att_syntax,  			/* header: 23 bytes */
60	xml_syntax,			/* header: 679 bytes */
61	raw_syntax			/* header: 172 bytes */
62};
63%}
64
65/* ================================================================== */
66/* operand class */
67%inline %{
68	enum x86_reg_type {
69	        reg_gen         = 0x00001, reg_in          = 0x00002,
70	        reg_out         = 0x00004, reg_local       = 0x00008,
71	        reg_fpu         = 0x00010, reg_seg         = 0x00020,
72	        reg_simd        = 0x00040, reg_sys         = 0x00080,
73	        reg_sp          = 0x00100, reg_fp          = 0x00200,
74	        reg_pc          = 0x00400, reg_retaddr     = 0x00800,
75	        reg_cond        = 0x01000, reg_zero        = 0x02000,
76	        reg_ret         = 0x04000, reg_src         = 0x10000,
77	        reg_dest        = 0x20000, reg_count       = 0x40000
78	};
79
80	typedef struct {
81       	 	char name[MAX_REGNAME];
82	        enum x86_reg_type type;
83	        unsigned int size;
84	        unsigned int id;
85		unsigned int alias;
86		unsigned int shift;
87	} x86_reg_t;
88
89	void x86_reg_from_id( unsigned int id, x86_reg_t * reg );
90
91	typedef struct {
92	        unsigned int     scale;
93	        x86_reg_t        index, base;
94	        long             disp;
95	        char             disp_sign;
96	        char             disp_size;
97	} x86_ea_t;
98
99	enum x86_op_type {
100	        op_unused = 0,
101	        op_register = 1,
102	        op_immediate = 2,
103	        op_relative_near = 3,
104	        op_relative_far = 4,
105	        op_absolute = 5,
106	        op_expression = 6,
107	        op_offset = 7,
108	        op_unknown
109	};
110
111	enum x86_op_datatype {
112	       	op_byte = 1, op_word = 2,
113	        op_dword = 3, op_qword = 4,
114	        op_dqword = 5, op_sreal = 6,
115	        op_dreal = 7, op_extreal = 8,
116	        op_bcd = 9,  op_ssimd = 10,
117	        op_dsimd = 11, op_sssimd = 12,
118	        op_sdsimd = 13, op_descr32 = 14,
119		op_descr16 = 15, op_pdescr32 = 16,
120		op_pdescr16 = 17, op_fpuenv = 18,
121		op_fpregset = 19,
122	};
123
124	enum x86_op_access {
125	        op_read = 1,
126	        op_write = 2,
127	        op_execute = 4
128	};
129
130	enum x86_op_flags {
131	        op_signed = 1, op_string = 2,
132	        op_constant = 4, op_pointer = 8,
133		op_sysref = 0x010, op_implied = 0x020,
134		op_hardcode = 0x40, op_es_seg = 0x100,
135	        op_cs_seg = 0x200, op_ss_seg = 0x300,
136	        op_ds_seg = 0x400, op_fs_seg = 0x500,
137	        op_gs_seg = 0x600
138	};
139
140	typedef struct {
141	        enum x86_op_type        type;
142	        enum x86_op_datatype    datatype;
143	        enum x86_op_access      access;
144	        enum x86_op_flags       flags;
145	        union {
146	                char            sbyte;
147	                short           sword;
148	                long            sdword;
149	                qword           sqword;
150	                unsigned char   byte;
151	       	         unsigned short  word;
152	                unsigned long   dword;
153	                qword           qword;
154	                float           sreal;
155	                double          dreal;
156	                unsigned char   extreal[10];
157	                unsigned char   bcd[10];
158	                qword           dqword[2];
159	                unsigned char   simd[16];
160	                unsigned char   fpuenv[28];
161	                void            * address;
162	                unsigned long   offset;
163	                x86_reg_t       reg;
164	                char            relative_near;
165	       	         long            relative_far;
166       	         	x86_ea_t        expression;
167        	} data;
168		void * insn;
169	} x86_op_t;
170
171	unsigned int x86_operand_size( x86_op_t *op );
172
173	int x86_format_operand(x86_op_t *op, char *buf, int len,
174        	          enum x86_asm_format format);
175%}
176
177%extend x86_reg_t{
178	x86_reg_t * aliased_reg( ) {
179		x86_reg_t * reg = (x86_reg_t * )
180				  calloc( sizeof(x86_reg_t), 1 );
181		x86_reg_from_id( self->id, reg );
182		return reg;
183	}
184}
185
186%extend x86_op_t{
187	size_t size() {
188		return x86_operand_size( self );
189	}
190	char * format( enum x86_asm_format format ) {
191		char *buf, *str;
192		size_t len;
193
194		switch ( format ) {
195			case xml_syntax:
196				len = MAX_OP_XML_STRING;
197				break;
198			case raw_syntax:
199				len = MAX_OP_RAW_STRING;
200				break;
201			case native_syntax:
202			case intel_syntax:
203			case att_syntax:
204			case unknown_syntax:
205			default:
206				len = MAX_OP_STRING;
207				break;
208		}
209
210		buf = (char * ) calloc( len + 1, 1 );
211		x86_format_operand( self, buf, len, format );
212
213		/* drop buffer down to a reasonable size */
214		str = strdup( buf );
215		free(buf);
216		return str;
217	}
218
219	int is_address( ) {
220		if ( self->type == op_absolute ||
221		     self->type == op_offset ) {
222		     return 1;
223		}
224
225		return 0;
226	}
227
228	int is_relative( ) {
229		if ( self->type == op_relative_near ||
230		     self->type == op_relative_far ) {
231		     return 1;
232		}
233
234		return 0;
235	}
236
237	%newobject copy;
238	x86_op_t * copy() {
239		x86_op_t *op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
240
241		if ( op ) {
242			memcpy( op, self, sizeof(x86_op_t) );
243		}
244
245		return op;
246	}
247}
248
249/* ================================================================== */
250/* operand list class */
251%inline %{
252	typedef struct X86_OpListNode {
253		x86_op_t *op;
254		struct X86_OpListNode *next, *prev;
255	} X86_OpListNode;
256
257	typedef struct X86_OpList {
258		size_t count;
259		X86_OpListNode *head, *tail, *curr;
260	} X86_OpList;
261%}
262
263%extend X86_OpList {
264	X86_OpList () {
265		X86_OpList *list = (X86_OpList *)
266				calloc( sizeof(X86_OpList), 1 );
267		list->count = 0;
268		return list;
269	}
270
271	~X86_OpList() {
272		X86_OpListNode *node, *next;
273
274		node = self->head;
275		while ( node ) {
276			next = node->next;
277			/* free( node->insn ); */
278			free( node );
279			node = next;
280		}
281
282		free( self );
283	}
284
285	X86_OpListNode * first() {
286		self->curr = self->head;
287		return self->head;
288	}
289
290	X86_OpListNode * last() {
291		self->curr = self->tail;
292		return self->tail;
293	}
294
295	X86_OpListNode * next() {
296		if (! self->curr ) {
297			self->curr = self->head;
298			return self->head;
299		}
300
301		self->curr = self->curr->next;
302		return self->curr;
303	}
304
305	X86_OpListNode * prev() {
306		if (! self->curr ) {
307			self->curr = self->tail;
308			return self->tail;
309		}
310
311		self->curr = self->curr->prev;
312		return self->curr;
313	}
314
315	%newobject append;
316	void append( x86_op_t *op ) {
317		X86_OpListNode *node = (X86_OpListNode *)
318					calloc( sizeof(X86_OpListNode) , 1 );
319		if (! node ) {
320			return;
321		}
322
323		self->count++;
324		if ( ! self->tail ) {
325			self->head = self->tail = node;
326		} else {
327			self->tail->next = node;
328			node->prev = self->tail;
329			self->tail = node;
330		}
331
332		node->op = x86_op_t_copy( op );
333	}
334}
335
336%inline %{
337	typedef struct x86_operand_list {
338		x86_op_t op;
339		struct x86_operand_list *next;
340	} x86_oplist_t;
341%}
342
343%extend x86_oplist_t {
344	%newobject x86_oplist_node_copy;
345}
346
347/* ================================================================== */
348/* instruction class */
349%inline %{
350	x86_oplist_t * x86_oplist_node_copy( x86_oplist_t * list ) {
351		x86_oplist_t *ptr;
352		ptr = (x86_oplist_t *) calloc( sizeof(x86_oplist_t), 1 );
353		if ( ptr ) {
354			memcpy( &ptr->op, &list->op, sizeof(x86_op_t) );
355		}
356
357		return ptr;
358	}
359
360	enum x86_insn_group {
361		insn_none = 0, insn_controlflow = 1,
362	        insn_arithmetic = 2, insn_logic = 3,
363	        insn_stack = 4, insn_comparison = 5,
364	        insn_move = 6, insn_string = 7,
365	        insn_bit_manip = 8, insn_flag_manip = 9,
366	        insn_fpu = 10, insn_interrupt = 13,
367	        insn_system = 14, insn_other = 15
368	};
369
370	enum x86_insn_type {
371		insn_invalid = 0, insn_jmp = 0x1001,
372	        insn_jcc = 0x1002, insn_call = 0x1003,
373	        insn_callcc = 0x1004, insn_return = 0x1005,
374	        insn_add = 0x2001, insn_sub = 0x2002,
375	        insn_mul = 0x2003, insn_div = 0x2004,
376	        insn_inc = 0x2005, insn_dec = 0x2006,
377	        insn_shl = 0x2007, insn_shr = 0x2008,
378	        insn_rol = 0x2009, insn_ror = 0x200A,
379	        insn_and = 0x3001, insn_or = 0x3002,
380	        insn_xor = 0x3003, insn_not = 0x3004,
381	        insn_neg = 0x3005, insn_push = 0x4001,
382	        insn_pop = 0x4002, insn_pushregs = 0x4003,
383	        insn_popregs = 0x4004, insn_pushflags = 0x4005,
384	        insn_popflags = 0x4006, insn_enter = 0x4007,
385	        insn_leave = 0x4008, insn_test = 0x5001,
386	        insn_cmp = 0x5002, insn_mov = 0x6001,
387	        insn_movcc = 0x6002, insn_xchg = 0x6003,
388	        insn_xchgcc = 0x6004, insn_strcmp = 0x7001,
389	        insn_strload = 0x7002, insn_strmov = 0x7003,
390	        insn_strstore = 0x7004, insn_translate = 0x7005,
391	        insn_bittest = 0x8001, insn_bitset = 0x8002,
392	        insn_bitclear = 0x8003, insn_clear_carry = 0x9001,
393	        insn_clear_zero = 0x9002, insn_clear_oflow = 0x9003,
394	        insn_clear_dir = 0x9004, insn_clear_sign = 0x9005,
395	        insn_clear_parity = 0x9006, insn_set_carry = 0x9007,
396	        insn_set_zero = 0x9008, insn_set_oflow = 0x9009,
397	        insn_set_dir = 0x900A, insn_set_sign = 0x900B,
398	        insn_set_parity = 0x900C, insn_tog_carry = 0x9010,
399	        insn_tog_zero = 0x9020, insn_tog_oflow = 0x9030,
400	        insn_tog_dir = 0x9040, insn_tog_sign = 0x9050,
401	        insn_tog_parity = 0x9060, insn_fmov = 0xA001,
402	        insn_fmovcc = 0xA002, insn_fneg = 0xA003,
403	       	insn_fabs = 0xA004, insn_fadd = 0xA005,
404	        insn_fsub = 0xA006, insn_fmul = 0xA007,
405	        insn_fdiv = 0xA008, insn_fsqrt = 0xA009,
406	        insn_fcmp = 0xA00A, insn_fcos = 0xA00C,
407	        insn_fldpi = 0xA00D, insn_fldz = 0xA00E,
408	        insn_ftan = 0xA00F, insn_fsine = 0xA010,
409	        insn_fsys = 0xA020, insn_int = 0xD001,
410	        insn_intcc = 0xD002,   insn_iret = 0xD003,
411	        insn_bound = 0xD004, insn_debug = 0xD005,
412	        insn_trace = 0xD006, insn_invalid_op = 0xD007,
413	        insn_oflow = 0xD008, insn_halt = 0xE001,
414	        insn_in = 0xE002, insn_out = 0xE003,
415	        insn_cpuid = 0xE004, insn_nop = 0xF001,
416	        insn_bcdconv = 0xF002, insn_szconv = 0xF003
417	};
418
419	enum x86_insn_note {
420		insn_note_ring0		= 1,
421		insn_note_smm		= 2,
422		insn_note_serial	= 4
423	};
424
425	enum x86_flag_status {
426	        insn_carry_set = 0x1,
427	        insn_zero_set = 0x2,
428	        insn_oflow_set = 0x4,
429	        insn_dir_set = 0x8,
430	        insn_sign_set = 0x10,
431	        insn_parity_set = 0x20,
432	        insn_carry_or_zero_set = 0x40,
433	        insn_zero_set_or_sign_ne_oflow = 0x80,
434	        insn_carry_clear = 0x100,
435	        insn_zero_clear = 0x200,
436	        insn_oflow_clear = 0x400,
437	        insn_dir_clear = 0x800,
438	        insn_sign_clear = 0x1000,
439	        insn_parity_clear = 0x2000,
440	        insn_sign_eq_oflow = 0x4000,
441	        insn_sign_ne_oflow = 0x8000
442	};
443
444	enum x86_insn_cpu {
445		cpu_8086 	= 1, cpu_80286	= 2,
446		cpu_80386	= 3, cpu_80387	= 4,
447		cpu_80486	= 5, cpu_pentium	= 6,
448		cpu_pentiumpro	= 7, cpu_pentium2	= 8,
449		cpu_pentium3	= 9, cpu_pentium4	= 10,
450		cpu_k6		= 16, cpu_k7		= 32,
451		cpu_athlon	= 48
452	};
453
454	enum x86_insn_isa {
455		isa_gp		= 1, isa_fp		= 2,
456		isa_fpumgt	= 3, isa_mmx		= 4,
457		isa_sse1	= 5, isa_sse2	= 6,
458		isa_sse3	= 7, isa_3dnow	= 8,
459		isa_sys		= 9
460	};
461
462	enum x86_insn_prefix {
463	        insn_no_prefix = 0,
464	        insn_rep_zero = 1,
465	        insn_rep_notzero = 2,
466	        insn_lock = 4
467	};
468
469
470	typedef struct {
471        	unsigned long addr;
472	        unsigned long offset;
473	        enum x86_insn_group group;
474	        enum x86_insn_type type;
475		enum x86_insn_note note;
476	        unsigned char bytes[MAX_INSN_SIZE];
477	        unsigned char size;
478		unsigned char addr_size;
479		unsigned char op_size;
480		enum x86_insn_cpu cpu;
481		enum x86_insn_isa isa;
482	        enum x86_flag_status flags_set;
483	        enum x86_flag_status flags_tested;
484		unsigned char stack_mod;
485		long stack_mod_val;
486	        enum x86_insn_prefix prefix;
487	        char prefix_string[MAX_PREFIX_STR];
488	        char mnemonic[MAX_MNEM_STR];
489	        x86_oplist_t *operands;
490		size_t operand_count;
491		size_t explicit_count;
492	        void *block;
493	        void *function;
494	        int tag;
495	} x86_insn_t;
496
497	typedef void (*x86_operand_fn)(x86_op_t *op, x86_insn_t *insn,
498		      void *arg);
499
500	enum x86_op_foreach_type {
501		op_any 	= 0,
502		op_dest = 1,
503		op_src 	= 2,
504		op_ro 	= 3,
505		op_wo 	= 4,
506		op_xo 	= 5,
507		op_rw 	= 6,
508		op_implicit = 0x10,
509		op_explicit = 0x20
510	};
511
512	size_t x86_operand_count( x86_insn_t *insn,
513				enum x86_op_foreach_type type );
514	x86_op_t * x86_operand_1st( x86_insn_t *insn );
515	x86_op_t * x86_operand_2nd( x86_insn_t *insn );
516	x86_op_t * x86_operand_3rd( x86_insn_t *insn );
517	long x86_get_rel_offset( x86_insn_t *insn );
518	x86_op_t * x86_get_branch_target( x86_insn_t *insn );
519	x86_op_t * x86_get_imm( x86_insn_t *insn );
520	unsigned char * x86_get_raw_imm( x86_insn_t *insn );
521	void x86_set_insn_addr( x86_insn_t *insn, unsigned long addr );
522	int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
523                        enum x86_asm_format format);
524	int x86_format_insn(x86_insn_t *insn, char *buf, int len,
525				enum x86_asm_format);
526	void x86_oplist_free( x86_insn_t *insn );
527	int x86_insn_is_valid( x86_insn_t *insn );
528%}
529
530%extend x86_insn_t {
531	x86_insn_t() {
532		x86_insn_t *insn = (x86_insn_t *)
533				   calloc( sizeof(x86_insn_t), 1 );
534		return insn;
535	}
536	~x86_insn_t() {
537		x86_oplist_free( self );
538		free( self );
539	}
540
541	int is_valid( ) {
542		return x86_insn_is_valid( self );
543	}
544
545	x86_op_t * operand_1st() {
546		return x86_operand_1st( self );
547	}
548
549	x86_op_t * operand_2nd() {
550		return x86_operand_2nd( self );
551	}
552
553	x86_op_t * operand_3rd() {
554		return x86_operand_3rd( self );
555	}
556
557	x86_op_t * operand_dest() {
558		return x86_operand_1st( self );
559	}
560
561	x86_op_t * operand_src() {
562		return x86_operand_2nd( self );
563	}
564
565	size_t num_operands( enum x86_op_foreach_type type ) {
566		return x86_operand_count( self, type );
567	}
568
569	long rel_offset() {
570		return x86_get_rel_offset( self );
571	}
572
573	x86_op_t * branch_target() {
574		return x86_get_branch_target( self );
575	}
576
577	x86_op_t * imm() {
578		return x86_get_imm( self );
579	}
580
581	unsigned char * raw_imm() {
582		return x86_get_raw_imm( self );
583	}
584
585	%newobject format;
586	char * format( enum x86_asm_format format ) {
587		char *buf, *str;
588		size_t len;
589
590		switch ( format ) {
591			case xml_syntax:
592				len = MAX_INSN_XML_STRING;
593				break;
594			case raw_syntax:
595				len = MAX_INSN_RAW_STRING;
596				break;
597			case native_syntax:
598			case intel_syntax:
599			case att_syntax:
600			case unknown_syntax:
601			default:
602				len = MAX_INSN_STRING;
603				break;
604		}
605
606		buf = (char * ) calloc( len + 1, 1 );
607		x86_format_insn( self, buf, len, format );
608
609		/* drop buffer down to a reasonable size */
610		str = strdup( buf );
611		free(buf);
612		return str;
613	}
614
615	%newobject format_mnemonic;
616	char * format_mnemonic( enum x86_asm_format format ) {
617		char *buf, *str;
618		size_t len = MAX_MNEM_STR + MAX_PREFIX_STR + 4;
619
620		buf = (char * ) calloc( len, 1 );
621		x86_format_mnemonic( self, buf, len, format );
622
623		/* drop buffer down to a reasonable size */
624		str = strdup( buf );
625		free(buf);
626
627		return str;
628	}
629
630	%newobject copy;
631	x86_insn_t * copy() {
632		x86_oplist_t *ptr, *list, *last = NULL;
633		x86_insn_t *insn = (x86_insn_t *)
634				   calloc( sizeof(x86_insn_t), 1 );
635
636		if ( insn ) {
637			memcpy( insn, self, sizeof(x86_insn_t) );
638			insn->operands = NULL;
639			insn->block = NULL;
640			insn->function = NULL;
641
642			/* copy operand list */
643			for ( list = self->operands; list; list = list->next ) {
644				ptr = x86_oplist_node_copy( list );
645
646				if (! ptr ) {
647					continue;
648				}
649
650				if ( insn->operands ) {
651					last->next = ptr;
652				} else {
653					insn->operands = ptr;
654				}
655				last = ptr;
656			}
657		}
658
659		return insn;
660	}
661
662	X86_OpList * operand_list( ) {
663		x86_oplist_t *list = self->operands;
664		X86_OpList *op_list = new_X86_OpList();
665
666		for ( list = self->operands; list; list = list->next ) {
667			X86_OpList_append( op_list, &list->op );
668		}
669
670		return op_list;
671	}
672}
673
674/* ================================================================== */
675/* invariant instruction class */
676%inline %{
677	#define X86_WILDCARD_BYTE 0xF4
678
679	typedef struct {
680        	enum x86_op_type        type;
681        	enum x86_op_datatype    datatype;
682        	enum x86_op_access      access;
683        	enum x86_op_flags       flags;
684	} x86_invariant_op_t;
685
686	typedef struct {
687		unsigned char bytes[64];
688		unsigned int  size;
689        	enum x86_insn_group group;
690        	enum x86_insn_type type;
691		x86_invariant_op_t operands[3];
692	} x86_invariant_t;
693%}
694
695%extend x86_invariant_t {
696
697	x86_invariant_t() {
698		x86_invariant_t *inv = (x86_invariant_t *)
699				calloc( sizeof(x86_invariant_t), 1 );
700		return inv;
701	}
702
703	~x86_invariant_t() {
704		free( self );
705	}
706}
707
708/* ================================================================== */
709/* instruction list class */
710%inline %{
711	typedef struct X86_InsnListNode {
712		x86_insn_t *insn;
713		struct X86_InsnListNode *next, *prev;
714	} X86_InsnListNode;
715
716	typedef struct X86_InsnList {
717		size_t count;
718		X86_InsnListNode *head, *tail, *curr;
719	} X86_InsnList;
720%}
721
722%extend X86_InsnList {
723	X86_InsnList () {
724		X86_InsnList *list = (X86_InsnList *)
725				calloc( sizeof(X86_InsnList), 1 );
726		list->count = 0;
727		return list;
728	}
729
730	~X86_InsnList() {
731		X86_InsnListNode *node, *next;
732
733		node = self->head;
734		while ( node ) {
735			next = node->next;
736			/* free( node->insn ); */
737			free( node );
738			node = next;
739		}
740
741		free( self );
742	}
743
744	X86_InsnListNode * first() { return self->head; }
745
746	X86_InsnListNode * last() { return self->tail; }
747
748	X86_InsnListNode * next() {
749		if (! self->curr ) {
750			self->curr = self->head;
751			return self->head;
752		}
753
754		self->curr = self->curr->next;
755		return self->curr;
756	}
757
758	X86_InsnListNode * prev() {
759		if (! self->curr ) {
760			self->curr = self->tail;
761			return self->tail;
762		}
763
764		self->curr = self->curr->prev;
765		return self->curr;
766	}
767
768	%newobject append;
769	void append( x86_insn_t *insn ) {
770		X86_InsnListNode *node = (X86_InsnListNode *)
771					calloc( sizeof(X86_InsnListNode) , 1 );
772		if (! node ) {
773			return;
774		}
775
776		self->count++;
777		if ( ! self->tail ) {
778			self->head = self->tail = node;
779		} else {
780			self->tail->next = node;
781			node->prev = self->tail;
782			self->tail = node;
783		}
784
785		node->insn = x86_insn_t_copy( insn );
786	}
787}
788
789/* ================================================================== */
790/* address table class */
791/* slight TODO */
792
793/* ================================================================== */
794/* Main disassembler class */
795%inline %{
796
797	enum x86_options {
798		opt_none= 0,
799		opt_ignore_nulls=1,
800		opt_16_bit=2
801		};
802	enum x86_report_codes {
803        	report_disasm_bounds,
804        	report_insn_bounds,
805        	report_invalid_insn,
806        	report_unknown
807	};
808
809
810	typedef struct {
811		enum x86_report_codes last_error;
812		void * last_error_data;
813		void * disasm_callback;
814		void * disasm_resolver;
815	} X86_Disasm;
816
817	typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
818				 	 void *data, void *arg );
819	typedef void (*DISASM_CALLBACK)( x86_insn_t *insn, void * arg );
820	typedef long (*DISASM_RESOLVER)( x86_op_t *op,
821					 x86_insn_t * current_insn,
822				 	 void *arg );
823
824	void x86_report_error( enum x86_report_codes code, void *data );
825	int x86_init( enum x86_options options, DISASM_REPORTER reporter,
826		      void *arg);
827	void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
828	void x86_set_options( enum x86_options options );
829	enum x86_options x86_get_options( void );
830	int x86_cleanup(void);
831	int x86_format_header( char *buf, int len, enum x86_asm_format format);
832	unsigned int x86_endian(void);
833	unsigned int x86_addr_size(void);
834	unsigned int x86_op_size(void);
835	unsigned int x86_word_size(void);
836	unsigned int x86_max_insn_size(void);
837	unsigned int x86_sp_reg(void);
838	unsigned int x86_fp_reg(void);
839	unsigned int x86_ip_reg(void);
840	size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
841			  x86_invariant_t *inv );
842	size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );
843	int x86_disasm( unsigned char *buf, unsigned int buf_len,
844	                unsigned long buf_rva, unsigned int offset,
845	                x86_insn_t * insn );
846	int x86_disasm_range( unsigned char *buf, unsigned long buf_rva,
847	                      unsigned int offset, unsigned int len,
848	                      DISASM_CALLBACK func, void *arg );
849	int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
850	                        unsigned long buf_rva, unsigned int offset,
851	                        DISASM_CALLBACK func, void *arg,
852	                        DISASM_RESOLVER resolver, void *r_arg );
853
854	void x86_default_reporter( enum x86_report_codes code,
855				   void *data, void *arg ) {
856		X86_Disasm *dis = (X86_Disasm *) arg;
857		if ( dis ) {
858			dis->last_error = code;
859			dis->last_error_data = data;
860		}
861	}
862
863	void x86_default_callback( x86_insn_t *insn, void *arg ) {
864		X86_InsnList *list = (X86_InsnList *) arg;
865		if ( list ) {
866			X86_InsnList_append( list, insn );
867		}
868	}
869
870	/* TODO: resolver stack, maybe a callback */
871	long x86_default_resolver( x86_op_t *op, x86_insn_t *insn, void *arg ) {
872		X86_Disasm *dis = (X86_Disasm *) arg;
873		if ( dis ) {
874			//return dis->resolver( op, insn );
875			return 0;
876		}
877
878		return 0;
879	}
880
881%}
882
883%extend X86_Disasm {
884
885	X86_Disasm( ) {
886		X86_Disasm * dis = (X86_Disasm *)
887				calloc( sizeof( X86_Disasm ), 1 );
888		x86_init( opt_none, x86_default_reporter, dis );
889		return dis;
890	}
891
892	X86_Disasm( enum x86_options options ) {
893		X86_Disasm * dis = (X86_Disasm *)
894				calloc( sizeof( X86_Disasm ), 1 );
895		x86_init( options, x86_default_reporter, dis );
896		return dis;
897	}
898
899	X86_Disasm( enum x86_options options, DISASM_REPORTER reporter ) {
900		X86_Disasm * dis = (X86_Disasm *)
901				calloc( sizeof( X86_Disasm ), 1 );
902		x86_init( options, reporter, NULL );
903		return dis;
904	}
905
906	X86_Disasm( enum x86_options options, DISASM_REPORTER reporter,
907		    void * arg ) {
908		X86_Disasm * dis = (X86_Disasm *)
909				calloc( sizeof( X86_Disasm ), 1 );
910		x86_init( options, reporter, arg );
911		return dis;
912	}
913
914	~X86_Disasm() {
915		x86_cleanup();
916		free( self );
917	}
918
919	void set_options( enum x86_options options ) {
920		return x86_set_options( options );
921	}
922
923	enum x86_options options() {
924		return x86_get_options();
925	}
926
927	void set_callback( void * callback ) {
928		self->disasm_callback = callback;
929	}
930
931	void set_resolver( void * callback ) {
932		self->disasm_resolver = callback;
933	}
934
935	void report_error( enum x86_report_codes code ) {
936		x86_report_error( code, NULL );
937	}
938
939	%newobject disasm;
940	x86_insn_t * disasm( unsigned char *buf, size_t buf_len,
941		           unsigned long buf_rva, unsigned int offset ) {
942		x86_insn_t *insn = calloc( sizeof( x86_insn_t ), 1 );
943		x86_disasm( buf, buf_len, buf_rva, offset, insn );
944		return insn;
945	}
946
947	int disasm_range( unsigned char *buf, size_t buf_len,
948	              unsigned long buf_rva, unsigned int offset,
949		      unsigned int len ) {
950
951		X86_InsnList *list = new_X86_InsnList();
952
953		if ( len > buf_len ) {
954			len = buf_len;
955		}
956
957		return x86_disasm_range( buf, buf_rva, offset, len,
958				x86_default_callback, list );
959	}
960
961	int disasm_forward( unsigned char *buf, size_t buf_len,
962			    unsigned long buf_rva, unsigned int offset ) {
963		X86_InsnList *list = new_X86_InsnList();
964
965		/* use default resolver: damn SWIG callbacks! */
966		return x86_disasm_forward( buf, buf_len, buf_rva, offset,
967			                   x86_default_callback, list,
968					   x86_default_resolver, NULL );
969	}
970
971	size_t disasm_invariant( unsigned char *buf, size_t buf_len,
972			  x86_invariant_t *inv ) {
973		return x86_invariant_disasm( buf, buf_len, inv );
974	}
975
976	size_t disasm_size( unsigned char *buf, size_t buf_len ) {
977		return x86_size_disasm( buf, buf_len );
978	}
979
980	%newobject format_header;
981	char * format_header( enum x86_asm_format format) {
982		char *buf, *str;
983		size_t len;
984
985		switch ( format ) {
986			/* these were obtained from x86_format.c */
987			case xml_syntax:
988				len = 679; break;
989			case raw_syntax:
990				len = 172; break;
991			case native_syntax:
992				len = 35; break;
993			case intel_syntax:
994				len = 23; break;
995			case att_syntax:
996				len = 23; break;
997			case unknown_syntax:
998			default:
999				len = 23; break;
1000		}
1001
1002		buf = (char * ) calloc( len + 1, 1 );
1003		x86_format_header( buf, len, format );
1004
1005		return buf;
1006	}
1007
1008	unsigned int endian() {
1009		return x86_endian();
1010	}
1011
1012	unsigned int addr_size() {
1013		return x86_addr_size();
1014	}
1015
1016	unsigned int op_size() {
1017		return x86_op_size();
1018	}
1019
1020	unsigned int word_size() {
1021		return x86_word_size();
1022	}
1023
1024	unsigned int max_insn_size() {
1025		return x86_max_insn_size();
1026	}
1027
1028	unsigned int sp_reg() {
1029		return x86_sp_reg();
1030	}
1031
1032	unsigned int fp_reg() {
1033		return x86_fp_reg();
1034	}
1035
1036	unsigned int ip_reg() {
1037		return x86_ip_reg();
1038	}
1039
1040	%newobject reg_from_id;
1041	x86_reg_t * reg_from_id( unsigned int id ) {
1042		x86_reg_t * reg = calloc( sizeof(x86_reg_t), 1 );
1043		x86_reg_from_id( id, reg );
1044		return reg;
1045	}
1046
1047	unsigned char wildcard_byte() { return X86_WILDCARD_BYTE; }
1048
1049	int max_register_string() { return MAX_REGNAME; }
1050
1051	int max_prefix_string() { return MAX_PREFIX_STR; }
1052
1053	int max_mnemonic_string() { return MAX_MNEM_STR; }
1054
1055	int max_operand_string( enum x86_asm_format format ) {
1056		switch ( format ) {
1057			case xml_syntax:
1058				return  MAX_OP_XML_STRING;
1059				break;
1060			case raw_syntax:
1061				return MAX_OP_RAW_STRING;
1062				break;
1063			case native_syntax:
1064			case intel_syntax:
1065			case att_syntax:
1066			case unknown_syntax:
1067			default:
1068				return MAX_OP_STRING;
1069				break;
1070		}
1071	}
1072
1073
1074	int max_insn_string( enum x86_asm_format format ) {
1075		switch ( format ) {
1076			case xml_syntax:
1077				return  MAX_INSN_XML_STRING;
1078				break;
1079			case raw_syntax:
1080				return MAX_INSN_RAW_STRING;
1081				break;
1082			case native_syntax:
1083			case intel_syntax:
1084			case att_syntax:
1085			case unknown_syntax:
1086			default:
1087				return MAX_INSN_STRING;
1088				break;
1089		}
1090	}
1091
1092	int max_num_operands( ) { return MAX_NUM_OPERANDS; }
1093}
1094
1095/* python callback, per the manual */
1096/*%typemap(python,in) PyObject *pyfunc {
1097	if (!PyCallable_Check($source)) {
1098		PyErr_SetString(PyExc_TypeError, "Need a callable object!");
1099 		return NULL;
1100	}
1101	$target = $source;
1102}*/
1103
1104/* python FILE * callback, per the manual */
1105/*
1106%typemap(python,in) FILE * {
1107  if (!PyFile_Check($source)) {
1108      PyErr_SetString(PyExc_TypeError, "Need a file!");
1109      return NULL;
1110  }
1111  $target = PyFile_AsFile($source);
1112}*/
1113
1114
1115