blob: 3a10962b3b8800b8c32cd3c2d122803a95b0543c [file] [log] [blame]
danghvu6a6947f2013-11-26 22:28:41 -06001// Capstone Java binding
2// By Nguyen Anh Quynh & Dang Hoang Vu, 2013
3
danghvuf86a7d52013-11-27 15:09:07 -06004import capstone.Capstone;
keenkd03cab42018-07-13 03:52:19 -05005import static capstone.Capstone.CS_AC_READ;
6import static capstone.Capstone.CS_AC_WRITE;
7import capstone.Capstone.CsRegsAccess;
danghvuf86a7d52013-11-27 15:09:07 -06008import capstone.X86;
9
danghvu2f666882013-12-01 13:32:16 -060010import static capstone.X86_const.*;
11
danghvu6a6947f2013-11-26 22:28:41 -060012public class TestX86 {
13
14 static byte[] hexString2Byte(String s) {
15 // from http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java
16 int len = s.length();
17 byte[] data = new byte[len / 2];
18 for (int i = 0; i < len; i += 2) {
19 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
20 + Character.digit(s.charAt(i+1), 16));
21 }
22 return data;
23 }
24
danghvu6a6947f2013-11-26 22:28:41 -060025 static final String X86_CODE64 = "55488b05b8130000";
danghvu7b088042013-11-27 10:58:31 -060026 static final String X86_CODE16 = "8d4c320801d881c6341200000523010000368b849123010000418d8439896700008d8789670000b4c6";
27 static final String X86_CODE32 = "8d4c320801d881c6341200000523010000368b849123010000418d8439896700008d8789670000b4c6";
danghvu6a6947f2013-11-26 22:28:41 -060028
29 public static Capstone cs;
30
31 private static String hex(int i) {
32 return Integer.toString(i, 16);
33 }
34
35 private static String hex(long i) {
36 return Long.toString(i, 16);
37 }
38
39 private static String array2hex(byte[] arr) {
40 String ret = "";
41 for (int i=0 ;i<arr.length; i++)
42 ret += String.format("0x%02x ", arr[i]);
43 return ret;
44 }
45
danghvu4ef20d52013-12-16 23:25:57 -060046 public static void print_ins_detail(Capstone.CsInsn ins) {
47 System.out.printf("0x%x:\t%s\t%s\n", ins.address, ins.mnemonic, ins.opStr);
danghvu6a6947f2013-11-26 22:28:41 -060048
danghvu4ef20d52013-12-16 23:25:57 -060049 X86.OpInfo operands = (X86.OpInfo) ins.operands;
danghvu6a6947f2013-11-26 22:28:41 -060050
danghvu4ef20d52013-12-16 23:25:57 -060051 System.out.printf("\tPrefix: %s\n", array2hex(operands.prefix));
danghvu6a6947f2013-11-26 22:28:41 -060052
danghvu4ef20d52013-12-16 23:25:57 -060053 System.out.printf("\tOpcode: %s\n", array2hex(operands.opcode));
danghvu6a6947f2013-11-26 22:28:41 -060054
Nguyen Anh Quynh9f6ed712014-07-01 10:13:28 +080055 // print REX prefix (non-zero value is relevant for x86_64)
56 System.out.printf("\trex: 0x%x\n", operands.rex);
57
Nguyen Anh Quynhe68ce0e2014-06-18 12:33:39 +080058 // print address size
59 System.out.printf("\taddr_size: %d\n", operands.addrSize);
danghvu6a6947f2013-11-26 22:28:41 -060060
61 // print modRM byte
danghvu4ef20d52013-12-16 23:25:57 -060062 System.out.printf("\tmodrm: 0x%x\n", operands.modrm);
danghvu6a6947f2013-11-26 22:28:41 -060063
keenkd03cab42018-07-13 03:52:19 -050064 // print modRM offset
65 if (operands.encoding.modrmOffset != 0) {
66 System.out.printf("\tmodrm offset: 0x%x\n", operands.encoding.modrmOffset);
67 }
68
danghvu6a6947f2013-11-26 22:28:41 -060069 // print displacement value
danghvu4ef20d52013-12-16 23:25:57 -060070 System.out.printf("\tdisp: 0x%x\n", operands.disp);
danghvu6a6947f2013-11-26 22:28:41 -060071
keenkd03cab42018-07-13 03:52:19 -050072 // print displacement offset
73 if (operands.encoding.dispOffset != 0) {
74 System.out.printf("\tdisp offset: 0x%x\n", operands.encoding.dispOffset);
75 }
76
77 //print displacement size
78 if (operands.encoding.dispSize != 0) {
79 System.out.printf("\tdisp size: 0x%x\n", operands.encoding.dispSize);
80 }
81
danghvu6a6947f2013-11-26 22:28:41 -060082 // SIB is not available in 16-bit mode
danghvuf3ef6962013-11-27 21:41:17 -060083 if ( (cs.mode & Capstone.CS_MODE_16) == 0) {
danghvu35855b52013-11-26 22:42:30 -060084 // print SIB byte
danghvu4ef20d52013-12-16 23:25:57 -060085 System.out.printf("\tsib: 0x%x\n", operands.sib);
86 if (operands.sib != 0)
danghvu53bbee32014-09-27 15:41:45 -050087 System.out.printf("\t\tsib_base: %s\n\t\tsib_index: %s\n\t\tsib_scale: %d\n",
88 ins.regName(operands.sibBase), ins.regName(operands.sibIndex), operands.sibScale);
danghvuf3ef6962013-11-27 21:41:17 -060089 }
danghvu6a6947f2013-11-26 22:28:41 -060090
Nguyen Anh Quynhdebaa2e2015-03-07 13:46:21 +080091 if (operands.xopCC != 0)
92 System.out.printf("\txop_cc: %u\n", operands.xopCC);
93
Nguyen Anh Quynh4c5eabc2014-06-24 23:50:41 +080094 if (operands.sseCC != 0)
95 System.out.printf("\tsse_cc: %u\n", operands.sseCC);
96
97 if (operands.avxCC != 0)
98 System.out.printf("\tavx_cc: %u\n", operands.avxCC);
99
Nguyen Anh Quynh1a66fec2014-06-26 12:09:15 +0800100 if (operands.avxSae)
101 System.out.printf("\tavx_sae: TRUE\n");
102
103 if (operands.avxRm != 0)
104 System.out.printf("\tavx_rm: %u\n", operands.avxRm);
105
danghvu4ef20d52013-12-16 23:25:57 -0600106 int count = ins.opCount(X86_OP_IMM);
danghvu6a6947f2013-11-26 22:28:41 -0600107 if (count > 0) {
108 System.out.printf("\timm_count: %d\n", count);
keenkd03cab42018-07-13 03:52:19 -0500109 System.out.printf("\timm offset: 0x%x\n", operands.encoding.immOffset);
110 System.out.printf("\timm size: 0x%x\n", operands.encoding.immSize);
danghvu6a6947f2013-11-26 22:28:41 -0600111 for (int i=0; i<count; i++) {
danghvu4ef20d52013-12-16 23:25:57 -0600112 int index = ins.opIndex(X86_OP_IMM, i + 1);
113 System.out.printf("\t\timms[%d]: 0x%x\n", i+1, (operands.op[index].value.imm));
danghvu6a6947f2013-11-26 22:28:41 -0600114 }
115 }
116
danghvu4ef20d52013-12-16 23:25:57 -0600117 if (operands.op.length != 0) {
118 System.out.printf("\top_count: %d\n", operands.op.length);
119 for (int c=0; c<operands.op.length; c++) {
120 X86.Operand i = (X86.Operand) operands.op[c];
danghvu6a6947f2013-11-26 22:28:41 -0600121 String imm = hex(i.value.imm);
danghvu2f666882013-12-01 13:32:16 -0600122 if (i.type == X86_OP_REG)
danghvu4ef20d52013-12-16 23:25:57 -0600123 System.out.printf("\t\toperands[%d].type: REG = %s\n", c, ins.regName(i.value.reg));
danghvu2f666882013-12-01 13:32:16 -0600124 if (i.type == X86_OP_IMM)
danghvu7b088042013-11-27 10:58:31 -0600125 System.out.printf("\t\toperands[%d].type: IMM = 0x%x\n", c, i.value.imm);
danghvu2f666882013-12-01 13:32:16 -0600126 if (i.type == X86_OP_MEM) {
danghvu6a6947f2013-11-26 22:28:41 -0600127 System.out.printf("\t\toperands[%d].type: MEM\n",c);
Nguyen Anh Quynh04678422014-06-24 14:35:47 +0800128 String segment = ins.regName(i.value.mem.segment);
danghvu4ef20d52013-12-16 23:25:57 -0600129 String base = ins.regName(i.value.mem.base);
130 String index = ins.regName(i.value.mem.index);
Nguyen Anh Quynh04678422014-06-24 14:35:47 +0800131 if (segment != null)
132 System.out.printf("\t\t\toperands[%d].mem.segment: REG = %s\n", c, segment);
danghvu6a6947f2013-11-26 22:28:41 -0600133 if (base != null)
134 System.out.printf("\t\t\toperands[%d].mem.base: REG = %s\n", c, base);
135 if (index != null)
136 System.out.printf("\t\t\toperands[%d].mem.index: REG = %s\n", c, index);
137 if (i.value.mem.scale != 1)
danghvu7b088042013-11-27 10:58:31 -0600138 System.out.printf("\t\t\toperands[%d].mem.scale: %d\n", c, i.value.mem.scale);
danghvu6a6947f2013-11-26 22:28:41 -0600139 if (i.value.mem.disp != 0)
danghvu7b088042013-11-27 10:58:31 -0600140 System.out.printf("\t\t\toperands[%d].mem.disp: 0x%x\n", c, i.value.mem.disp);
danghvu6a6947f2013-11-26 22:28:41 -0600141 }
Nguyen Anh Quynh83800cd2014-06-18 14:21:36 +0800142
Nguyen Anh Quynh0d716452014-06-24 22:51:56 +0800143 // AVX broadcast type
144 if (i.avx_bcast != X86_AVX_BCAST_INVALID) {
145 System.out.printf("\t\toperands[%d].avx_bcast: %d\n", c, i.avx_bcast);
146 }
147
Nguyen Anh Quynh92a3d4c2014-06-25 23:10:39 +0800148 // AVX zero opmask {z}
Nguyen Anh Quynh7de200a2014-06-26 11:31:36 +0800149 if (i.avx_zero_opmask) {
150 System.out.printf("\t\toperands[%d].avx_zero_opmask: TRUE\n", c);
Nguyen Anh Quynh92a3d4c2014-06-25 23:10:39 +0800151 }
152
Nguyen Anh Quynhf1ec5262014-06-25 22:03:18 +0800153 System.out.printf("\t\toperands[%d].size: %d\n", c, i.size);
keenkd03cab42018-07-13 03:52:19 -0500154 switch(i.access) {
155 case CS_AC_READ:
156 System.out.printf("\t\toperands[%d].access: READ\n", c);
157 break;
158 case CS_AC_WRITE:
159 System.out.printf("\t\toperands[%d].access: WRITE\n", c);
160 break;
161 case CS_AC_READ | CS_AC_WRITE:
162 System.out.printf("\t\toperands[%d].access: READ | WRITE\n", c);
163 break;
164 }
165 }
166
167 // Print out all registers accessed by this instruction (either implicit or explicit)
168 CsRegsAccess regsAccess = ins.regsAccess();
169 if (regsAccess != null) {
170 short[] regsRead = regsAccess.regsRead;
171 short[] regsWrite = regsAccess.regsWrite;
172
173 if (regsRead.length > 0) {
174 System.out.printf("\tRegisters read:");
175 for (int i = 0; i < regsRead.length; i++) {
176 System.out.printf(" %s", ins.regName(regsRead[i]));
177 }
178 System.out.print("\n");
179 }
180
181 if (regsWrite.length > 0) {
182 System.out.printf("\tRegister modified:");
183 for (int i = 0; i < regsWrite.length; i++) {
184 System.out.printf(" %s", ins.regName(regsWrite[i]));
185 }
186 System.out.print("\n");
187 }
danghvu6a6947f2013-11-26 22:28:41 -0600188 }
189 }
190 }
191
192 public static void main(String argv[]) {
193
Akihiko Odaki01f6dda2016-09-04 10:28:16 +0900194 final TestBasic.platform[] all_tests = {
195 new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_16, hexString2Byte(X86_CODE16), "X86 16bit (Intel syntax)"),
196 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 new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_32, hexString2Byte(X86_CODE32), "X86 32 (Intel syntax)"),
198 new TestBasic.platform(Capstone.CS_ARCH_X86, Capstone.CS_MODE_64, hexString2Byte(X86_CODE64), "X86 64 (Intel syntax)"),
danghvu6a6947f2013-11-26 22:28:41 -0600199 };
200
201 for (int i=0; i<all_tests.length; i++) {
Akihiko Odaki01f6dda2016-09-04 10:28:16 +0900202 TestBasic.platform test = all_tests[i];
danghvuf3ef6962013-11-27 21:41:17 -0600203 System.out.println(new String(new char[16]).replace("\0", "*"));
danghvu6a6947f2013-11-26 22:28:41 -0600204 System.out.println("Platform: " + test.comment);
Akihiko Odaki01f6dda2016-09-04 10:28:16 +0900205 System.out.println("Code: " + TestBasic.stringToHex(test.code));
danghvu6a6947f2013-11-26 22:28:41 -0600206 System.out.println("Disasm:");
207
208 cs = new Capstone(test.arch, test.mode);
Nguyen Anh Quynh6a1107c2014-01-07 23:47:18 +0800209 cs.setDetail(Capstone.CS_OPT_ON);
danghvu05006912013-12-05 19:33:38 -0600210 if (test.syntax != 0) {
211 cs.setSyntax(test.syntax);
212 }
danghvu4ef20d52013-12-16 23:25:57 -0600213 Capstone.CsInsn[] all_ins = cs.disasm(test.code, 0x1000);
danghvu6a6947f2013-11-26 22:28:41 -0600214
215 for (int j = 0; j < all_ins.length; j++) {
216 print_ins_detail(all_ins[j]);
217 System.out.println();
218 }
danghvuf3ef6962013-11-27 21:41:17 -0600219
220 System.out.printf("0x%x:\n\n", all_ins[all_ins.length-1].address + all_ins[all_ins.length-1].size);
Nguyen Anh Quynh0ea529a2014-11-19 10:58:31 +0800221
222 // Close when done
223 cs.close();
danghvu6a6947f2013-11-26 22:28:41 -0600224 }
225 }
226
227}