xref: /aosp_15_r20/external/capstone/bindings/java/TestX86.java (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
1*9a0e4156SSadaf Ebrahimi // Capstone Java binding
2*9a0e4156SSadaf Ebrahimi // By Nguyen Anh Quynh & Dang Hoang Vu,  2013
3*9a0e4156SSadaf Ebrahimi 
4*9a0e4156SSadaf Ebrahimi import capstone.Capstone;
5*9a0e4156SSadaf Ebrahimi import static capstone.Capstone.CS_AC_READ;
6*9a0e4156SSadaf Ebrahimi import static capstone.Capstone.CS_AC_WRITE;
7*9a0e4156SSadaf Ebrahimi import capstone.Capstone.CsRegsAccess;
8*9a0e4156SSadaf Ebrahimi import capstone.X86;
9*9a0e4156SSadaf Ebrahimi 
10*9a0e4156SSadaf Ebrahimi import static capstone.X86_const.*;
11*9a0e4156SSadaf Ebrahimi 
12*9a0e4156SSadaf Ebrahimi public class TestX86 {
13*9a0e4156SSadaf Ebrahimi 
hexString2Byte(String s)14*9a0e4156SSadaf Ebrahimi   static byte[] hexString2Byte(String s) {
15*9a0e4156SSadaf Ebrahimi     // from http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
16*9a0e4156SSadaf Ebrahimi     int len = s.length();
17*9a0e4156SSadaf Ebrahimi     byte[] data = new byte[len / 2];
18*9a0e4156SSadaf Ebrahimi     for (int i = 0; i < len; i += 2) {
19*9a0e4156SSadaf Ebrahimi       data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
20*9a0e4156SSadaf Ebrahimi           + Character.digit(s.charAt(i+1), 16));
21*9a0e4156SSadaf Ebrahimi     }
22*9a0e4156SSadaf Ebrahimi     return data;
23*9a0e4156SSadaf Ebrahimi   }
24*9a0e4156SSadaf Ebrahimi 
25*9a0e4156SSadaf Ebrahimi   static final String X86_CODE64 = "55488b05b8130000";
26*9a0e4156SSadaf Ebrahimi   static final String X86_CODE16 = "8d4c320801d881c6341200000523010000368b849123010000418d8439896700008d8789670000b4c6";
27*9a0e4156SSadaf Ebrahimi   static final String X86_CODE32 = "8d4c320801d881c6341200000523010000368b849123010000418d8439896700008d8789670000b4c6";
28*9a0e4156SSadaf Ebrahimi 
29*9a0e4156SSadaf Ebrahimi   public static Capstone cs;
30*9a0e4156SSadaf Ebrahimi 
hex(int i)31*9a0e4156SSadaf Ebrahimi   private static String hex(int i) {
32*9a0e4156SSadaf Ebrahimi     return Integer.toString(i, 16);
33*9a0e4156SSadaf Ebrahimi   }
34*9a0e4156SSadaf Ebrahimi 
hex(long i)35*9a0e4156SSadaf Ebrahimi   private static String hex(long i) {
36*9a0e4156SSadaf Ebrahimi     return Long.toString(i, 16);
37*9a0e4156SSadaf Ebrahimi   }
38*9a0e4156SSadaf Ebrahimi 
array2hex(byte[] arr)39*9a0e4156SSadaf Ebrahimi   private static String array2hex(byte[] arr) {
40*9a0e4156SSadaf Ebrahimi     String ret = "";
41*9a0e4156SSadaf Ebrahimi     for (int i=0 ;i<arr.length; i++)
42*9a0e4156SSadaf Ebrahimi       ret += String.format("0x%02x ", arr[i]);
43*9a0e4156SSadaf Ebrahimi     return ret;
44*9a0e4156SSadaf Ebrahimi   }
45*9a0e4156SSadaf Ebrahimi 
print_ins_detail(Capstone.CsInsn ins)46*9a0e4156SSadaf Ebrahimi   public static void print_ins_detail(Capstone.CsInsn ins) {
47*9a0e4156SSadaf Ebrahimi     System.out.printf("0x%x:\t%s\t%s\n", ins.address, ins.mnemonic, ins.opStr);
48*9a0e4156SSadaf Ebrahimi 
49*9a0e4156SSadaf Ebrahimi     X86.OpInfo operands = (X86.OpInfo) ins.operands;
50*9a0e4156SSadaf Ebrahimi 
51*9a0e4156SSadaf Ebrahimi     System.out.printf("\tPrefix: %s\n", array2hex(operands.prefix));
52*9a0e4156SSadaf Ebrahimi 
53*9a0e4156SSadaf Ebrahimi     System.out.printf("\tOpcode: %s\n", array2hex(operands.opcode));
54*9a0e4156SSadaf Ebrahimi 
55*9a0e4156SSadaf Ebrahimi     // print REX prefix (non-zero value is relevant for x86_64)
56*9a0e4156SSadaf Ebrahimi     System.out.printf("\trex: 0x%x\n", operands.rex);
57*9a0e4156SSadaf Ebrahimi 
58*9a0e4156SSadaf Ebrahimi     // print address size
59*9a0e4156SSadaf Ebrahimi     System.out.printf("\taddr_size: %d\n", operands.addrSize);
60*9a0e4156SSadaf Ebrahimi 
61*9a0e4156SSadaf Ebrahimi     // print modRM byte
62*9a0e4156SSadaf Ebrahimi     System.out.printf("\tmodrm: 0x%x\n", operands.modrm);
63*9a0e4156SSadaf Ebrahimi 
64*9a0e4156SSadaf Ebrahimi     // print modRM offset
65*9a0e4156SSadaf Ebrahimi     if (operands.encoding.modrmOffset != 0) {
66*9a0e4156SSadaf Ebrahimi       System.out.printf("\tmodrm offset: 0x%x\n", operands.encoding.modrmOffset);
67*9a0e4156SSadaf Ebrahimi     }
68*9a0e4156SSadaf Ebrahimi 
69*9a0e4156SSadaf Ebrahimi     // print displacement value
70*9a0e4156SSadaf Ebrahimi     System.out.printf("\tdisp: 0x%x\n", operands.disp);
71*9a0e4156SSadaf Ebrahimi 
72*9a0e4156SSadaf Ebrahimi     // print displacement offset
73*9a0e4156SSadaf Ebrahimi     if (operands.encoding.dispOffset != 0) {
74*9a0e4156SSadaf Ebrahimi       System.out.printf("\tdisp offset: 0x%x\n", operands.encoding.dispOffset);
75*9a0e4156SSadaf Ebrahimi     }
76*9a0e4156SSadaf Ebrahimi 
77*9a0e4156SSadaf Ebrahimi     //print displacement size
78*9a0e4156SSadaf Ebrahimi     if (operands.encoding.dispSize != 0) {
79*9a0e4156SSadaf Ebrahimi       System.out.printf("\tdisp size: 0x%x\n", operands.encoding.dispSize);
80*9a0e4156SSadaf Ebrahimi     }
81*9a0e4156SSadaf Ebrahimi 
82*9a0e4156SSadaf Ebrahimi     // SIB is not available in 16-bit mode
83*9a0e4156SSadaf Ebrahimi     if ( (cs.mode & Capstone.CS_MODE_16) == 0) {
84*9a0e4156SSadaf Ebrahimi       // print SIB byte
85*9a0e4156SSadaf Ebrahimi       System.out.printf("\tsib: 0x%x\n", operands.sib);
86*9a0e4156SSadaf Ebrahimi       if (operands.sib != 0)
87*9a0e4156SSadaf Ebrahimi         System.out.printf("\t\tsib_base: %s\n\t\tsib_index: %s\n\t\tsib_scale: %d\n",
88*9a0e4156SSadaf Ebrahimi           ins.regName(operands.sibBase), ins.regName(operands.sibIndex), operands.sibScale);
89*9a0e4156SSadaf Ebrahimi     }
90*9a0e4156SSadaf Ebrahimi 
91*9a0e4156SSadaf Ebrahimi     if (operands.xopCC != 0)
92*9a0e4156SSadaf Ebrahimi         System.out.printf("\txop_cc: %u\n", operands.xopCC);
93*9a0e4156SSadaf Ebrahimi 
94*9a0e4156SSadaf Ebrahimi     if (operands.sseCC != 0)
95*9a0e4156SSadaf Ebrahimi         System.out.printf("\tsse_cc: %u\n", operands.sseCC);
96*9a0e4156SSadaf Ebrahimi 
97*9a0e4156SSadaf Ebrahimi     if (operands.avxCC != 0)
98*9a0e4156SSadaf Ebrahimi         System.out.printf("\tavx_cc: %u\n", operands.avxCC);
99*9a0e4156SSadaf Ebrahimi 
100*9a0e4156SSadaf Ebrahimi     if (operands.avxSae)
101*9a0e4156SSadaf Ebrahimi         System.out.printf("\tavx_sae: TRUE\n");
102*9a0e4156SSadaf Ebrahimi 
103*9a0e4156SSadaf Ebrahimi     if (operands.avxRm != 0)
104*9a0e4156SSadaf Ebrahimi         System.out.printf("\tavx_rm: %u\n", operands.avxRm);
105*9a0e4156SSadaf Ebrahimi 
106*9a0e4156SSadaf Ebrahimi     int count = ins.opCount(X86_OP_IMM);
107*9a0e4156SSadaf Ebrahimi     if (count > 0) {
108*9a0e4156SSadaf Ebrahimi       System.out.printf("\timm_count: %d\n", count);
109*9a0e4156SSadaf Ebrahimi       System.out.printf("\timm offset: 0x%x\n", operands.encoding.immOffset);
110*9a0e4156SSadaf Ebrahimi       System.out.printf("\timm size: 0x%x\n", operands.encoding.immSize);
111*9a0e4156SSadaf Ebrahimi       for (int i=0; i<count; i++) {
112*9a0e4156SSadaf Ebrahimi         int index = ins.opIndex(X86_OP_IMM, i + 1);
113*9a0e4156SSadaf Ebrahimi         System.out.printf("\t\timms[%d]: 0x%x\n", i+1, (operands.op[index].value.imm));
114*9a0e4156SSadaf Ebrahimi       }
115*9a0e4156SSadaf Ebrahimi     }
116*9a0e4156SSadaf Ebrahimi 
117*9a0e4156SSadaf Ebrahimi     if (operands.op.length != 0) {
118*9a0e4156SSadaf Ebrahimi       System.out.printf("\top_count: %d\n", operands.op.length);
119*9a0e4156SSadaf Ebrahimi       for (int c=0; c<operands.op.length; c++) {
120*9a0e4156SSadaf Ebrahimi         X86.Operand i = (X86.Operand) operands.op[c];
121*9a0e4156SSadaf Ebrahimi         String imm = hex(i.value.imm);
122*9a0e4156SSadaf Ebrahimi         if (i.type == X86_OP_REG)
123*9a0e4156SSadaf Ebrahimi           System.out.printf("\t\toperands[%d].type: REG = %s\n", c, ins.regName(i.value.reg));
124*9a0e4156SSadaf Ebrahimi         if (i.type == X86_OP_IMM)
125*9a0e4156SSadaf Ebrahimi           System.out.printf("\t\toperands[%d].type: IMM = 0x%x\n", c, i.value.imm);
126*9a0e4156SSadaf Ebrahimi         if (i.type == X86_OP_MEM) {
127*9a0e4156SSadaf Ebrahimi           System.out.printf("\t\toperands[%d].type: MEM\n",c);
128*9a0e4156SSadaf Ebrahimi           String segment = ins.regName(i.value.mem.segment);
129*9a0e4156SSadaf Ebrahimi           String base = ins.regName(i.value.mem.base);
130*9a0e4156SSadaf Ebrahimi           String index = ins.regName(i.value.mem.index);
131*9a0e4156SSadaf Ebrahimi           if (segment != null)
132*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\t\toperands[%d].mem.segment: REG = %s\n", c, segment);
133*9a0e4156SSadaf Ebrahimi           if (base != null)
134*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\t\toperands[%d].mem.base: REG = %s\n", c, base);
135*9a0e4156SSadaf Ebrahimi           if (index != null)
136*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\t\toperands[%d].mem.index: REG = %s\n", c, index);
137*9a0e4156SSadaf Ebrahimi           if (i.value.mem.scale != 1)
138*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\t\toperands[%d].mem.scale: %d\n", c, i.value.mem.scale);
139*9a0e4156SSadaf Ebrahimi           if (i.value.mem.disp != 0)
140*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\t\toperands[%d].mem.disp: 0x%x\n", c, i.value.mem.disp);
141*9a0e4156SSadaf Ebrahimi         }
142*9a0e4156SSadaf Ebrahimi 
143*9a0e4156SSadaf Ebrahimi         // AVX broadcast type
144*9a0e4156SSadaf Ebrahimi         if (i.avx_bcast != X86_AVX_BCAST_INVALID) {
145*9a0e4156SSadaf Ebrahimi           System.out.printf("\t\toperands[%d].avx_bcast: %d\n", c, i.avx_bcast);
146*9a0e4156SSadaf Ebrahimi         }
147*9a0e4156SSadaf Ebrahimi 
148*9a0e4156SSadaf Ebrahimi         // AVX zero opmask {z}
149*9a0e4156SSadaf Ebrahimi         if (i.avx_zero_opmask) {
150*9a0e4156SSadaf Ebrahimi           System.out.printf("\t\toperands[%d].avx_zero_opmask: TRUE\n", c);
151*9a0e4156SSadaf Ebrahimi         }
152*9a0e4156SSadaf Ebrahimi 
153*9a0e4156SSadaf Ebrahimi         System.out.printf("\t\toperands[%d].size: %d\n", c, i.size);
154*9a0e4156SSadaf Ebrahimi         switch(i.access) {
155*9a0e4156SSadaf Ebrahimi           case CS_AC_READ:
156*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\toperands[%d].access: READ\n", c);
157*9a0e4156SSadaf Ebrahimi             break;
158*9a0e4156SSadaf Ebrahimi           case CS_AC_WRITE:
159*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\toperands[%d].access: WRITE\n", c);
160*9a0e4156SSadaf Ebrahimi             break;
161*9a0e4156SSadaf Ebrahimi           case CS_AC_READ | CS_AC_WRITE:
162*9a0e4156SSadaf Ebrahimi             System.out.printf("\t\toperands[%d].access: READ | WRITE\n", c);
163*9a0e4156SSadaf Ebrahimi             break;
164*9a0e4156SSadaf Ebrahimi         }
165*9a0e4156SSadaf Ebrahimi       }
166*9a0e4156SSadaf Ebrahimi 
167*9a0e4156SSadaf Ebrahimi       // Print out all registers accessed by this instruction (either implicit or explicit)
168*9a0e4156SSadaf Ebrahimi       CsRegsAccess regsAccess = ins.regsAccess();
169*9a0e4156SSadaf Ebrahimi       if (regsAccess != null) {
170*9a0e4156SSadaf Ebrahimi         short[] regsRead = regsAccess.regsRead;
171*9a0e4156SSadaf Ebrahimi         short[] regsWrite = regsAccess.regsWrite;
172*9a0e4156SSadaf Ebrahimi 
173*9a0e4156SSadaf Ebrahimi         if (regsRead.length > 0) {
174*9a0e4156SSadaf Ebrahimi           System.out.printf("\tRegisters read:");
175*9a0e4156SSadaf Ebrahimi           for (int i = 0; i < regsRead.length; i++) {
176*9a0e4156SSadaf Ebrahimi             System.out.printf(" %s", ins.regName(regsRead[i]));
177*9a0e4156SSadaf Ebrahimi           }
178*9a0e4156SSadaf Ebrahimi           System.out.print("\n");
179*9a0e4156SSadaf Ebrahimi         }
180*9a0e4156SSadaf Ebrahimi 
181*9a0e4156SSadaf Ebrahimi         if (regsWrite.length > 0) {
182*9a0e4156SSadaf Ebrahimi           System.out.printf("\tRegister modified:");
183*9a0e4156SSadaf Ebrahimi           for (int i = 0; i < regsWrite.length; i++) {
184*9a0e4156SSadaf Ebrahimi             System.out.printf(" %s", ins.regName(regsWrite[i]));
185*9a0e4156SSadaf Ebrahimi           }
186*9a0e4156SSadaf Ebrahimi           System.out.print("\n");
187*9a0e4156SSadaf Ebrahimi         }
188*9a0e4156SSadaf Ebrahimi       }
189*9a0e4156SSadaf Ebrahimi     }
190*9a0e4156SSadaf Ebrahimi   }
191*9a0e4156SSadaf Ebrahimi 
main(String argv[])192*9a0e4156SSadaf Ebrahimi   public static void main(String argv[]) {
193*9a0e4156SSadaf Ebrahimi 
194*9a0e4156SSadaf Ebrahimi     final TestBasic.platform[] all_tests = {
195*9a0e4156SSadaf Ebrahimi       new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_16, hexString2Byte(X86_CODE16), "X86 16bit (Intel syntax)"),
196*9a0e4156SSadaf Ebrahimi       new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_32, Capstone.CS_OPT_SYNTAX_ATT, hexString2Byte(X86_CODE32), "X86 32 (AT&T syntax)"),
197*9a0e4156SSadaf Ebrahimi       new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_32, hexString2Byte(X86_CODE32), "X86 32 (Intel syntax)"),
198*9a0e4156SSadaf Ebrahimi       new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_64, hexString2Byte(X86_CODE64), "X86 64 (Intel syntax)"),
199*9a0e4156SSadaf Ebrahimi     };
200*9a0e4156SSadaf Ebrahimi 
201*9a0e4156SSadaf Ebrahimi     for (int i=0; i<all_tests.length; i++) {
202*9a0e4156SSadaf Ebrahimi       TestBasic.platform test = all_tests[i];
203*9a0e4156SSadaf Ebrahimi       System.out.println(new String(new char[16]).replace("\0", "*"));
204*9a0e4156SSadaf Ebrahimi       System.out.println("Platform: " + test.comment);
205*9a0e4156SSadaf Ebrahimi       System.out.println("Code: " + TestBasic.stringToHex(test.code));
206*9a0e4156SSadaf Ebrahimi       System.out.println("Disasm:");
207*9a0e4156SSadaf Ebrahimi 
208*9a0e4156SSadaf Ebrahimi       cs = new Capstone(test.arch, test.mode);
209*9a0e4156SSadaf Ebrahimi       cs.setDetail(Capstone.CS_OPT_ON);
210*9a0e4156SSadaf Ebrahimi       if (test.syntax != 0) {
211*9a0e4156SSadaf Ebrahimi         cs.setSyntax(test.syntax);
212*9a0e4156SSadaf Ebrahimi       }
213*9a0e4156SSadaf Ebrahimi       Capstone.CsInsn[] all_ins = cs.disasm(test.code, 0x1000);
214*9a0e4156SSadaf Ebrahimi 
215*9a0e4156SSadaf Ebrahimi       for (int j = 0; j < all_ins.length; j++) {
216*9a0e4156SSadaf Ebrahimi         print_ins_detail(all_ins[j]);
217*9a0e4156SSadaf Ebrahimi         System.out.println();
218*9a0e4156SSadaf Ebrahimi       }
219*9a0e4156SSadaf Ebrahimi 
220*9a0e4156SSadaf Ebrahimi       System.out.printf("0x%x:\n\n", all_ins[all_ins.length-1].address + all_ins[all_ins.length-1].size);
221*9a0e4156SSadaf Ebrahimi 
222*9a0e4156SSadaf Ebrahimi       // Close when done
223*9a0e4156SSadaf Ebrahimi       cs.close();
224*9a0e4156SSadaf Ebrahimi     }
225*9a0e4156SSadaf Ebrahimi   }
226*9a0e4156SSadaf Ebrahimi 
227*9a0e4156SSadaf Ebrahimi }
228