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 
version_string(void)26 const char * version_string( void ) {
27 	return PACKAGE_VERSION;
28 }
29 
30 %}
31 
32 const 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 
55 enum 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{
aliased_reg()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{
size()187 	size_t size() {
188 		return x86_operand_size( self );
189 	}
format(enum x86_asm_format format)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 
is_address()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 
is_relative()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;
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 {
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 
~X86_OpList()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 
first()285 	X86_OpListNode * first() {
286 		self->curr = self->head;
287 		return self->head;
288 	}
289 
last()290 	X86_OpListNode * last() {
291 		self->curr = self->tail;
292 		return self->tail;
293 	}
294 
next()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 
prev()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;
append(x86_op_t * op)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 %{
x86_oplist_node_copy(x86_oplist_t * list)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 {
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 	}
~x86_insn_t()536 	~x86_insn_t() {
537 		x86_oplist_free( self );
538 		free( self );
539 	}
540 
is_valid()541 	int is_valid( ) {
542 		return x86_insn_is_valid( self );
543 	}
544 
operand_1st()545 	x86_op_t * operand_1st() {
546 		return x86_operand_1st( self );
547 	}
548 
operand_2nd()549 	x86_op_t * operand_2nd() {
550 		return x86_operand_2nd( self );
551 	}
552 
operand_3rd()553 	x86_op_t * operand_3rd() {
554 		return x86_operand_3rd( self );
555 	}
556 
operand_dest()557 	x86_op_t * operand_dest() {
558 		return x86_operand_1st( self );
559 	}
560 
operand_src()561 	x86_op_t * operand_src() {
562 		return x86_operand_2nd( self );
563 	}
564 
num_operands(enum x86_op_foreach_type type)565 	size_t num_operands( enum x86_op_foreach_type type ) {
566 		return x86_operand_count( self, type );
567 	}
568 
rel_offset()569 	long rel_offset() {
570 		return x86_get_rel_offset( self );
571 	}
572 
branch_target()573 	x86_op_t * branch_target() {
574 		return x86_get_branch_target( self );
575 	}
576 
imm()577 	x86_op_t * imm() {
578 		return x86_get_imm( self );
579 	}
580 
raw_imm()581 	unsigned char * raw_imm() {
582 		return x86_get_raw_imm( self );
583 	}
584 
585 	%newobject format;
format(enum x86_asm_format 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;
format_mnemonic(enum x86_asm_format format)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;
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 
operand_list()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 
x86_invariant_t()697 	x86_invariant_t() {
698 		x86_invariant_t *inv = (x86_invariant_t *)
699 				calloc( sizeof(x86_invariant_t), 1 );
700 		return inv;
701 	}
702 
~x86_invariant_t()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 {
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 
~X86_InsnList()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 
first()744 	X86_InsnListNode * first() { return self->head; }
745 
last()746 	X86_InsnListNode * last() { return self->tail; }
747 
next()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 
prev()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;
append(x86_insn_t * insn)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 
x86_default_reporter(enum x86_report_codes code,void * data,void * arg)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 
x86_default_callback(x86_insn_t * insn,void * arg)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 */
x86_default_resolver(x86_op_t * op,x86_insn_t * insn,void * arg)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 
X86_Disasm()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 
X86_Disasm(enum x86_options options)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 
X86_Disasm(enum x86_options options,DISASM_REPORTER reporter)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 
X86_Disasm(enum x86_options options,DISASM_REPORTER reporter,void * arg)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 
~X86_Disasm()914 	~X86_Disasm() {
915 		x86_cleanup();
916 		free( self );
917 	}
918 
set_options(enum x86_options options)919 	void set_options( enum x86_options options ) {
920 		return x86_set_options( options );
921 	}
922 
options()923 	enum x86_options options() {
924 		return x86_get_options();
925 	}
926 
set_callback(void * callback)927 	void set_callback( void * callback ) {
928 		self->disasm_callback = callback;
929 	}
930 
set_resolver(void * callback)931 	void set_resolver( void * callback ) {
932 		self->disasm_resolver = callback;
933 	}
934 
report_error(enum x86_report_codes code)935 	void report_error( enum x86_report_codes code ) {
936 		x86_report_error( code, NULL );
937 	}
938 
939 	%newobject disasm;
disasm(unsigned char * buf,size_t buf_len,unsigned long buf_rva,unsigned int offset)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 
disasm_range(unsigned char * buf,size_t buf_len,unsigned long buf_rva,unsigned int offset,unsigned int len)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 
disasm_forward(unsigned char * buf,size_t buf_len,unsigned long buf_rva,unsigned int offset)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 
disasm_invariant(unsigned char * buf,size_t buf_len,x86_invariant_t * inv)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 
disasm_size(unsigned char * buf,size_t buf_len)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;
format_header(enum x86_asm_format format)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 
endian()1008 	unsigned int endian() {
1009 		return x86_endian();
1010 	}
1011 
addr_size()1012 	unsigned int addr_size() {
1013 		return x86_addr_size();
1014 	}
1015 
op_size()1016 	unsigned int op_size() {
1017 		return x86_op_size();
1018 	}
1019 
word_size()1020 	unsigned int word_size() {
1021 		return x86_word_size();
1022 	}
1023 
max_insn_size()1024 	unsigned int max_insn_size() {
1025 		return x86_max_insn_size();
1026 	}
1027 
sp_reg()1028 	unsigned int sp_reg() {
1029 		return x86_sp_reg();
1030 	}
1031 
fp_reg()1032 	unsigned int fp_reg() {
1033 		return x86_fp_reg();
1034 	}
1035 
ip_reg()1036 	unsigned int ip_reg() {
1037 		return x86_ip_reg();
1038 	}
1039 
1040 	%newobject reg_from_id;
reg_from_id(unsigned int 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 
wildcard_byte()1047 	unsigned char wildcard_byte() { return X86_WILDCARD_BYTE; }
1048 
max_register_string()1049 	int max_register_string() { return MAX_REGNAME; }
1050 
max_prefix_string()1051 	int max_prefix_string() { return MAX_PREFIX_STR; }
1052 
max_mnemonic_string()1053 	int max_mnemonic_string() { return MAX_MNEM_STR; }
1054 
max_operand_string(enum x86_asm_format format)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 
max_insn_string(enum x86_asm_format format)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 
max_num_operands()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