1 #include <stdlib.h> 2 #include "libdis.h" 3 4 5 static void x86_oplist_append( x86_insn_t *insn, x86_oplist_t *op ) { 6 x86_oplist_t *list; 7 8 if (! insn ) { 9 return; 10 } 11 12 list = insn->operands; 13 if (! list ) { 14 insn->operand_count = 1; 15 /* Note that we have no way of knowing if this is an 16 * exlicit operand or not, since the caller fills 17 * the x86_op_t after we return. We increase the 18 * explicit count automatically, and ia32_insn_implicit_ops 19 * decrements it */ 20 insn->explicit_count = 1; 21 insn->operands = op; 22 return; 23 } 24 25 /* get to end of list */ 26 for ( ; list->next; list = list->next ) 27 ; 28 29 insn->operand_count = insn->operand_count + 1; 30 insn->explicit_count = insn->explicit_count + 1; 31 list->next = op; 32 33 return; 34 } 35 36 x86_op_t * x86_operand_new( x86_insn_t *insn ) { 37 x86_oplist_t *op; 38 39 if (! insn ) { 40 return(NULL); 41 } 42 op = calloc( sizeof(x86_oplist_t), 1 ); 43 op->op.insn = insn; 44 x86_oplist_append( insn, op ); 45 return( &(op->op) ); 46 } 47 48 void x86_oplist_free( x86_insn_t *insn ) { 49 x86_oplist_t *op, *list; 50 51 if (! insn ) { 52 return; 53 } 54 55 for ( list = insn->operands; list; ) { 56 op = list; 57 list = list->next; 58 free(op); 59 } 60 61 insn->operands = NULL; 62 insn->operand_count = 0; 63 insn->explicit_count = 0; 64 65 return; 66 } 67 68 /* ================================================== LIBDISASM API */ 69 /* these could probably just be #defines, but that means exposing the 70 enum... yet one more confusing thing in the API */ 71 int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg, 72 enum x86_op_foreach_type type ){ 73 x86_oplist_t *list; 74 char explicit = 1, implicit = 1; 75 76 if (! insn || ! func ) { 77 return 0; 78 } 79 80 /* note: explicit and implicit can be ORed together to 81 * allow an "all" limited by access type, even though the 82 * user is stupid to do this since it is default behavior :) */ 83 if ( (type & op_explicit) && ! (type & op_implicit) ) { 84 implicit = 0; 85 } 86 if ( (type & op_implicit) && ! (type & op_explicit) ) { 87 explicit = 0; 88 } 89 90 type = type & 0x0F; /* mask out explicit/implicit operands */ 91 92 for ( list = insn->operands; list; list = list->next ) { 93 if (! implicit && (list->op.flags & op_implied) ) { 94 /* operand is implicit */ 95 continue; 96 } 97 98 if (! explicit && ! (list->op.flags & op_implied) ) { 99 /* operand is not implicit */ 100 continue; 101 } 102 103 switch ( type ) { 104 case op_any: 105 break; 106 case op_dest: 107 if (! (list->op.access & op_write) ) { 108 continue; 109 } 110 break; 111 case op_src: 112 if (! (list->op.access & op_read) ) { 113 continue; 114 } 115 break; 116 case op_ro: 117 if (! (list->op.access & op_read) || 118 (list->op.access & op_write ) ) { 119 continue; 120 } 121 break; 122 case op_wo: 123 if (! (list->op.access & op_write) || 124 (list->op.access & op_read ) ) { 125 continue; 126 } 127 break; 128 case op_xo: 129 if (! (list->op.access & op_execute) ) { 130 continue; 131 } 132 break; 133 case op_rw: 134 if (! (list->op.access & op_write) || 135 ! (list->op.access & op_read ) ) { 136 continue; 137 } 138 break; 139 case op_implicit: case op_explicit: /* make gcc happy */ 140 break; 141 } 142 /* any non-continue ends up here: invoke the callback */ 143 (*func)( &list->op, insn, arg ); 144 } 145 146 return 1; 147 } 148 149 static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) { 150 size_t * count = (size_t *) arg; 151 *count = *count + 1; 152 } 153 154 size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type ) { 155 size_t count = 0; 156 157 /* save us a list traversal for common counts... */ 158 if ( type == op_any ) { 159 return insn->operand_count; 160 } else if ( type == op_explicit ) { 161 return insn->explicit_count; 162 } 163 164 x86_operand_foreach( insn, count_operand, &count, type ); 165 return count; 166 } 167 168 /* accessor functions */ 169 x86_op_t * x86_operand_1st( x86_insn_t *insn ) { 170 if (! insn->explicit_count ) { 171 return NULL; 172 } 173 174 return &(insn->operands->op); 175 } 176 177 x86_op_t * x86_operand_2nd( x86_insn_t *insn ) { 178 if ( insn->explicit_count < 2 ) { 179 return NULL; 180 } 181 182 return &(insn->operands->next->op); 183 } 184 185 x86_op_t * x86_operand_3rd( x86_insn_t *insn ) { 186 if ( insn->explicit_count < 3 ) { 187 return NULL; 188 } 189 190 return &(insn->operands->next->next->op); 191 } 192