1 // Capstone Java binding
2 // By Nguyen Anh Quynh & Dang Hoang Vu,  2013
3 
4 package capstone;
5 
6 import com.sun.jna.Library;
7 import com.sun.jna.Memory;
8 import com.sun.jna.Native;
9 import com.sun.jna.NativeLong;
10 import com.sun.jna.ptr.ByteByReference;
11 import com.sun.jna.ptr.NativeLongByReference;
12 import com.sun.jna.Structure;
13 import com.sun.jna.Union;
14 import com.sun.jna.Pointer;
15 import com.sun.jna.ptr.PointerByReference;
16 import com.sun.jna.ptr.IntByReference;
17 
18 import java.util.List;
19 import java.util.Arrays;
20 import java.lang.RuntimeException;
21 
22 public class Capstone {
23 
24   protected static abstract class OpInfo {};
25   protected static abstract class UnionOpInfo extends Structure {};
26 
27   public static class UnionArch extends Union {
28     public static class ByValue extends UnionArch implements Union.ByValue {};
29 
30     public Arm.UnionOpInfo arm;
31     public Arm64.UnionOpInfo arm64;
32     public X86.UnionOpInfo x86;
33     public Mips.UnionOpInfo mips;
34     public Ppc.UnionOpInfo ppc;
35     public Sparc.UnionOpInfo sparc;
36     public Systemz.UnionOpInfo sysz;
37     public Xcore.UnionOpInfo xcore;
38     public M680x.UnionOpInfo m680x;
39   }
40 
41   protected static class _cs_insn extends Structure {
42     // instruction ID.
43     public int id;
44     // instruction address.
45     public long address;
46     // instruction size.
47     public short size;
48     // machine bytes of instruction.
49     public byte[] bytes;
50     // instruction mnemonic. NOTE: irrelevant for diet engine.
51     public byte[] mnemonic;
52     // instruction operands. NOTE: irrelevant for diet engine.
53     public byte[] op_str;
54     // detail information of instruction.
55     public _cs_detail.ByReference cs_detail;
56 
_cs_insn()57     public _cs_insn() {
58       bytes = new byte[16];
59       mnemonic = new byte[32];
60       op_str = new byte[160];
61       java.util.Arrays.fill(mnemonic, (byte) 0);
62       java.util.Arrays.fill(op_str, (byte) 0);
63     }
64 
_cs_insn(Pointer p)65     public _cs_insn(Pointer p) {
66       this();
67       useMemory(p);
68       read();
69     }
70 
71     @Override
getFieldOrder()72     public List getFieldOrder() {
73       return Arrays.asList("id", "address", "size", "bytes", "mnemonic", "op_str", "cs_detail");
74     }
75   }
76 
77   protected static class _cs_detail extends Structure {
78     public static class ByReference extends _cs_detail implements Structure.ByReference {};
79 
80     // list of all implicit registers being read.
81     public short[] regs_read = new short[12];
82     public byte regs_read_count;
83     // list of all implicit registers being written.
84     public short[] regs_write = new short[20];
85     public byte regs_write_count;
86     // list of semantic groups this instruction belongs to.
87     public byte[] groups = new byte[8];
88     public byte groups_count;
89 
90     public UnionArch arch;
91 
92     @Override
getFieldOrder()93     public List getFieldOrder() {
94       return Arrays.asList("regs_read", "regs_read_count", "regs_write", "regs_write_count", "groups", "groups_count", "arch");
95     }
96   }
97 
98   public static class CsInsn {
99     private NativeLong csh;
100     private CS cs;
101     private _cs_insn raw;
102     private int arch;
103 
104     // instruction ID.
105     public int id;
106     // instruction address.
107     public long address;
108     // instruction size.
109     public short size;
110     // Machine bytes of this instruction, with number of bytes indicated by size above
111     public byte[] bytes;
112     // instruction mnemonic. NOTE: irrelevant for diet engine.
113     public String mnemonic;
114     // instruction operands. NOTE: irrelevant for diet engine.
115     public String opStr;
116     // list of all implicit registers being read.
117     public short[] regsRead;
118     // list of all implicit registers being written.
119     public short[] regsWrite;
120     // list of semantic groups this instruction belongs to.
121     public byte[] groups;
122     public OpInfo operands;
123 
CsInsn(_cs_insn insn, int _arch, NativeLong _csh, CS _cs, boolean diet)124     public CsInsn (_cs_insn insn, int _arch, NativeLong _csh, CS _cs, boolean diet) {
125       id = insn.id;
126       address = insn.address;
127       size = insn.size;
128 
129       if (!diet) {
130         int lm = 0;
131         while (insn.mnemonic[lm++] != 0);
132         int lo = 0;
133         while (insn.op_str[lo++] != 0);
134         mnemonic = new String(insn.mnemonic, 0, lm-1);
135         opStr = new String(insn.op_str, 0, lo-1);
136         bytes = Arrays.copyOf(insn.bytes, insn.size);
137       }
138 
139       cs = _cs;
140       arch = _arch;
141       raw = insn;
142       csh = _csh;
143 
144       if (insn.cs_detail != null) {
145         if (!diet) {
146           regsRead = new short[insn.cs_detail.regs_read_count];
147           for (int i=0; i<regsRead.length; i++)
148             regsRead[i] = insn.cs_detail.regs_read[i];
149           regsWrite = new short[insn.cs_detail.regs_write_count];
150           for (int i=0; i<regsWrite.length; i++)
151             regsWrite[i] = insn.cs_detail.regs_write[i];
152           groups = new byte[insn.cs_detail.groups_count];
153           for (int i=0; i<groups.length; i++)
154             groups[i] = insn.cs_detail.groups[i];
155         }
156 
157         operands = getOptInfo(insn.cs_detail);
158       }
159     }
160 
getOptInfo(_cs_detail detail)161     private OpInfo getOptInfo(_cs_detail detail) {
162       OpInfo op_info = null;
163 
164       switch (this.arch) {
165         case CS_ARCH_ARM:
166           detail.arch.setType(Arm.UnionOpInfo.class);
167           detail.arch.read();
168           op_info = new Arm.OpInfo((Arm.UnionOpInfo) detail.arch.arm);
169           break;
170         case CS_ARCH_ARM64:
171           detail.arch.setType(Arm64.UnionOpInfo.class);
172           detail.arch.read();
173           op_info = new Arm64.OpInfo((Arm64.UnionOpInfo) detail.arch.arm64);
174           break;
175         case CS_ARCH_MIPS:
176           detail.arch.setType(Mips.UnionOpInfo.class);
177           detail.arch.read();
178           op_info = new Mips.OpInfo((Mips.UnionOpInfo) detail.arch.mips);
179           break;
180         case CS_ARCH_X86:
181           detail.arch.setType(X86.UnionOpInfo.class);
182           detail.arch.read();
183           op_info = new X86.OpInfo((X86.UnionOpInfo) detail.arch.x86);
184           break;
185         case CS_ARCH_SPARC:
186           detail.arch.setType(Sparc.UnionOpInfo.class);
187           detail.arch.read();
188           op_info = new Sparc.OpInfo((Sparc.UnionOpInfo) detail.arch.sparc);
189           break;
190         case CS_ARCH_SYSZ:
191           detail.arch.setType(Systemz.UnionOpInfo.class);
192           detail.arch.read();
193           op_info = new Systemz.OpInfo((Systemz.UnionOpInfo) detail.arch.sysz);
194           break;
195         case CS_ARCH_PPC:
196           detail.arch.setType(Ppc.UnionOpInfo.class);
197           detail.arch.read();
198           op_info = new Ppc.OpInfo((Ppc.UnionOpInfo) detail.arch.ppc);
199           break;
200         case CS_ARCH_XCORE:
201           detail.arch.setType(Xcore.UnionOpInfo.class);
202           detail.arch.read();
203           op_info = new Xcore.OpInfo((Xcore.UnionOpInfo) detail.arch.xcore);
204           break;
205         case CS_ARCH_M680X:
206           detail.arch.setType(M680x.UnionOpInfo.class);
207           detail.arch.read();
208           op_info = new M680x.OpInfo((M680x.UnionOpInfo) detail.arch.m680x);
209           break;
210         default:
211       }
212 
213       return op_info;
214     }
215 
opCount(int type)216     public int opCount(int type) {
217       return cs.cs_op_count(csh, raw.getPointer(), type);
218     }
219 
opIndex(int type, int index)220     public int opIndex(int type, int index) {
221       return cs.cs_op_index(csh, raw.getPointer(), type, index);
222     }
223 
regRead(int reg_id)224     public boolean regRead(int reg_id) {
225       return cs.cs_reg_read(csh, raw.getPointer(), reg_id) != 0;
226     }
227 
regWrite(int reg_id)228     public boolean regWrite(int reg_id) {
229       return cs.cs_reg_write(csh, raw.getPointer(), reg_id) != 0;
230     }
231 
errno()232     public int errno() {
233       return cs.cs_errno(csh);
234     }
235 
regName(int reg_id)236     public String regName(int reg_id) {
237       return cs.cs_reg_name(csh, reg_id);
238     }
239 
insnName()240     public String insnName() {
241       return cs.cs_insn_name(csh, id);
242     }
243 
groupName(int id)244     public String groupName(int id) {
245       return cs.cs_group_name(csh, id);
246     }
247 
group(int gid)248     public boolean group(int gid) {
249       return cs.cs_insn_group(csh, raw.getPointer(), gid) != 0;
250     }
251 
regsAccess()252     public CsRegsAccess regsAccess() {
253       Memory regsReadMemory = new Memory(64*2);
254       ByteByReference regsReadCountRef = new ByteByReference();
255       Memory regsWriteMemory = new Memory(64*2);
256       ByteByReference regsWriteCountRef = new ByteByReference();
257 
258       int c = cs.cs_regs_access(csh, raw.getPointer(), regsReadMemory, regsReadCountRef, regsWriteMemory, regsWriteCountRef);
259       if (c != CS_ERR_OK) {
260         return null;
261       }
262 
263       byte regsReadCount = regsReadCountRef.getValue();
264       byte regsWriteCount = regsWriteCountRef.getValue();
265 
266       short[] regsRead = new short[regsReadCount];
267       regsReadMemory.read(0, regsRead, 0, regsReadCount);
268 
269       short[] regsWrite = new short[regsWriteCount];
270       regsWriteMemory.read(0, regsWrite, 0, regsWriteCount);
271 
272       return new CsRegsAccess(regsRead, regsWrite);
273     }
274   }
275 
276   public static class CsRegsAccess {
277     public short[] regsRead;
278     public short[] regsWrite;
279 
CsRegsAccess(short[] regsRead, short[] regsWrite)280     public CsRegsAccess(short[] regsRead, short[] regsWrite) {
281       this.regsRead = regsRead;
282       this.regsWrite = regsWrite;
283     }
284   }
285 
fromArrayRaw(_cs_insn[] arr_raw)286   private CsInsn[] fromArrayRaw(_cs_insn[] arr_raw) {
287     CsInsn[] arr = new CsInsn[arr_raw.length];
288 
289     for (int i = 0; i < arr_raw.length; i++) {
290       arr[i] = new CsInsn(arr_raw[i], this.arch, ns.csh, cs, this.diet);
291     }
292 
293     return arr;
294   }
295 
296   private interface CS extends Library {
cs_open(int arch, int mode, NativeLongByReference handle)297     public int cs_open(int arch, int mode, NativeLongByReference handle);
cs_disasm(NativeLong handle, byte[] code, NativeLong code_len, long addr, NativeLong count, PointerByReference insn)298     public NativeLong cs_disasm(NativeLong handle, byte[] code, NativeLong code_len,
299         long addr, NativeLong count, PointerByReference insn);
cs_free(Pointer p, NativeLong count)300     public void cs_free(Pointer p, NativeLong count);
cs_close(NativeLongByReference handle)301     public int cs_close(NativeLongByReference handle);
cs_option(NativeLong handle, int option, NativeLong optionValue)302     public int cs_option(NativeLong handle, int option, NativeLong optionValue);
303 
cs_reg_name(NativeLong csh, int id)304     public String cs_reg_name(NativeLong csh, int id);
cs_op_count(NativeLong csh, Pointer insn, int type)305     public int cs_op_count(NativeLong csh, Pointer insn, int type);
cs_op_index(NativeLong csh, Pointer insn, int type, int index)306     public int cs_op_index(NativeLong csh, Pointer insn, int type, int index);
307 
cs_insn_name(NativeLong csh, int id)308     public String cs_insn_name(NativeLong csh, int id);
cs_group_name(NativeLong csh, int id)309     public String cs_group_name(NativeLong csh, int id);
cs_insn_group(NativeLong csh, Pointer insn, int id)310     public byte cs_insn_group(NativeLong csh, Pointer insn, int id);
cs_reg_read(NativeLong csh, Pointer insn, int id)311     public byte cs_reg_read(NativeLong csh, Pointer insn, int id);
cs_reg_write(NativeLong csh, Pointer insn, int id)312     public byte cs_reg_write(NativeLong csh, Pointer insn, int id);
cs_errno(NativeLong csh)313     public int cs_errno(NativeLong csh);
cs_version(IntByReference major, IntByReference minor)314     public int cs_version(IntByReference major, IntByReference minor);
cs_support(int query)315     public boolean cs_support(int query);
cs_strerror(int code)316     public String cs_strerror(int code);
cs_regs_access(NativeLong handle, Pointer insn, Pointer regs_read, ByteByReference regs_read_count, Pointer regs_write, ByteByReference regs_write_count)317     public int cs_regs_access(NativeLong handle, Pointer insn, Pointer regs_read, ByteByReference regs_read_count, Pointer regs_write, ByteByReference regs_write_count);
318   }
319 
320   // Capstone API version
321   public static final int CS_API_MAJOR = 4;
322   public static final int CS_API_MINOR = 0;
323 
324   // architectures
325   public static final int CS_ARCH_ARM = 0;
326   public static final int CS_ARCH_ARM64 = 1;
327   public static final int CS_ARCH_MIPS = 2;
328   public static final int CS_ARCH_X86 = 3;
329   public static final int CS_ARCH_PPC = 4;
330   public static final int CS_ARCH_SPARC = 5;
331   public static final int CS_ARCH_SYSZ = 6;
332   public static final int CS_ARCH_XCORE = 7;
333   public static final int CS_ARCH_M68K = 8;
334   public static final int CS_ARCH_TMS320C64X = 9;
335   public static final int CS_ARCH_M680X = 10;
336   public static final int CS_ARCH_MAX = 11;
337   public static final int CS_ARCH_ALL = 0xFFFF; // query id for cs_support()
338 
339   // disasm mode
340   public static final int CS_MODE_LITTLE_ENDIAN = 0;  // little-endian mode (default mode)
341   public static final int CS_MODE_ARM = 0;	          // 32-bit ARM
342   public static final int CS_MODE_16 = 1 << 1;		// 16-bit mode for X86
343   public static final int CS_MODE_32 = 1 << 2;		// 32-bit mode for X86
344   public static final int CS_MODE_64 = 1 << 3;		// 64-bit mode for X86, PPC
345   public static final int CS_MODE_THUMB = 1 << 4;	  // ARM's Thumb mode, including Thumb-2
346   public static final int CS_MODE_MCLASS = 1 << 5;	  // ARM's Cortex-M series
347   public static final int CS_MODE_V8 = 1 << 6;	      // ARMv8 A32 encodings for ARM
348   public static final int CS_MODE_MICRO = 1 << 4;	  // MicroMips mode (Mips arch)
349   public static final int CS_MODE_MIPS3 = 1 << 5;     // Mips III ISA
350   public static final int CS_MODE_MIPS32R6 = 1 << 6;  // Mips32r6 ISA
351   public static final int CS_MODE_MIPS2 = 1 << 7;  // Mips II ISA
352   public static final int CS_MODE_BIG_ENDIAN = 1 << 31; // big-endian mode
353   public static final int CS_MODE_V9 = 1 << 4;	      // SparcV9 mode (Sparc arch)
354   public static final int CS_MODE_MIPS32 = CS_MODE_32; // Mips32 ISA
355   public static final int CS_MODE_MIPS64 = CS_MODE_64; // Mips64 ISA
356   public static final int CS_MODE_QPX = 1 << 4; // Quad Processing eXtensions mode (PPC)
357   public static final int CS_MODE_M680X_6301 = 1 << 1; // M680X Hitachi 6301,6303 mode
358   public static final int CS_MODE_M680X_6309 = 1 << 2; // M680X Hitachi 6309 mode
359   public static final int CS_MODE_M680X_6800 = 1 << 3; // M680X Motorola 6800,6802 mode
360   public static final int CS_MODE_M680X_6801 = 1 << 4; // M680X Motorola 6801,6803 mode
361   public static final int CS_MODE_M680X_6805 = 1 << 5; // M680X Motorola 6805 mode
362   public static final int CS_MODE_M680X_6808 = 1 << 6; // M680X Motorola 6808 mode
363   public static final int CS_MODE_M680X_6809 = 1 << 7; // M680X Motorola 6809 mode
364   public static final int CS_MODE_M680X_6811 = 1 << 8; // M680X Motorola/Freescale 68HC11 mode
365   public static final int CS_MODE_M680X_CPU12 = 1 << 9; // M680X Motorola/Freescale/NXP CPU12 mode
366   public static final int CS_MODE_M680X_HCS08 = 1 << 10; // M680X Freescale HCS08 mode
367 
368   // Capstone error
369   public static final int CS_ERR_OK = 0;
370   public static final int CS_ERR_MEM = 1;	    // Out-Of-Memory error
371   public static final int CS_ERR_ARCH = 2;	  // Unsupported architecture
372   public static final int CS_ERR_HANDLE = 3;	// Invalid handle
373   public static final int CS_ERR_CSH = 4;	    // Invalid csh argument
374   public static final int CS_ERR_MODE = 5;	  // Invalid/unsupported mode
375   public static final int CS_ERR_OPTION = 6;  // Invalid/unsupported option: cs_option()
376   public static final int CS_ERR_DETAIL = 7;  // Invalid/unsupported option: cs_option()
377   public static final int CS_ERR_MEMSETUP = 8;
378   public static final int CS_ERR_VERSION = 9;  //Unsupported version (bindings)
379   public static final int CS_ERR_DIET = 10;  //Information irrelevant in diet engine
380   public static final int CS_ERR_SKIPDATA = 11;  //Access irrelevant data for "data" instruction in SKIPDATA mode
381   public static final int CS_ERR_X86_ATT = 12;  //X86 AT&T syntax is unsupported (opt-out at compile time)
382   public static final int CS_ERR_X86_INTEL = 13;  //X86 Intel syntax is unsupported (opt-out at compile time)
383 
384   // Capstone option type
385   public static final int CS_OPT_SYNTAX = 1;  // Intel X86 asm syntax (CS_ARCH_X86 arch)
386   public static final int CS_OPT_DETAIL = 2;  // Break down instruction structure into details
387   public static final int CS_OPT_MODE = 3;  // Change engine's mode at run-time
388 
389   // Capstone option value
390   public static final int CS_OPT_OFF = 0;  // Turn OFF an option - default option of CS_OPT_DETAIL
391   public static final int CS_OPT_SYNTAX_INTEL = 1;  // Intel X86 asm syntax - default syntax on X86 (CS_OPT_SYNTAX,  CS_ARCH_X86)
392   public static final int CS_OPT_SYNTAX_ATT = 2;    // ATT asm syntax (CS_OPT_SYNTAX, CS_ARCH_X86)
393   public static final int CS_OPT_ON = 3;  // Turn ON an option (CS_OPT_DETAIL)
394   public static final int CS_OPT_SYNTAX_NOREGNAME = 3; // PPC asm syntax: Prints register name with only number (CS_OPT_SYNTAX)
395 
396   // Common instruction operand types - to be consistent across all architectures.
397   public static final int CS_OP_INVALID = 0;
398   public static final int CS_OP_REG = 1;
399   public static final int CS_OP_IMM = 2;
400   public static final int CS_OP_MEM = 3;
401   public static final int CS_OP_FP  = 4;
402 
403   // Common instruction operand access types - to be consistent across all architectures.
404   // It is possible to combine access types, for example: CS_AC_READ | CS_AC_WRITE
405   public static final int CS_AC_INVALID = 0;
406   public static final int CS_AC_READ = 1 << 0;
407   public static final int CS_AC_WRITE = 1 << 1;
408 
409   // Common instruction groups - to be consistent across all architectures.
410   public static final int CS_GRP_INVALID = 0;  // uninitialized/invalid group.
411   public static final int CS_GRP_JUMP    = 1;  // all jump instructions (conditional+direct+indirect jumps)
412   public static final int CS_GRP_CALL    = 2;  // all call instructions
413   public static final int CS_GRP_RET     = 3;  // all return instructions
414   public static final int CS_GRP_INT     = 4;  // all interrupt instructions (int+syscall)
415   public static final int CS_GRP_IRET    = 5;  // all interrupt return instructions
416   public static final int CS_GRP_PRIVILEGE = 6;  // all privileged instructions
417 
418   // Query id for cs_support()
419   public static final int CS_SUPPORT_DIET = CS_ARCH_ALL+1;	  // diet mode
420   public static final int CS_SUPPORT_X86_REDUCE = CS_ARCH_ALL+2;  // X86 reduce mode
421 
422   protected class NativeStruct {
423       private NativeLong csh;
424       private NativeLongByReference handleRef;
425   }
426 
427   private static final CsInsn[] EMPTY_INSN = new CsInsn[0];
428 
429   protected NativeStruct ns; // for memory retention
430   private CS cs;
431   public int arch;
432   public int mode;
433   private int syntax;
434   private int detail;
435   private boolean diet;
436 
Capstone(int arch, int mode)437   public Capstone(int arch, int mode) {
438     cs = (CS)Native.loadLibrary("capstone", CS.class);
439     int version = cs.cs_version(null, null);
440     if (version != (CS_API_MAJOR << 8) + CS_API_MINOR) {
441       throw new RuntimeException("Different API version between core & binding (CS_ERR_VERSION)");
442     }
443 
444     this.arch = arch;
445     this.mode = mode;
446     ns = new NativeStruct();
447     ns.handleRef = new NativeLongByReference();
448     if (cs.cs_open(arch, mode, ns.handleRef) != CS_ERR_OK) {
449       throw new RuntimeException("ERROR: Wrong arch or mode");
450     }
451     ns.csh = ns.handleRef.getValue();
452     this.detail = CS_OPT_OFF;
453 	this.diet = cs.cs_support(CS_SUPPORT_DIET);
454   }
455 
456   // return combined API version
version()457   public int version() {
458     return cs.cs_version(null, null);
459   }
460 
461   // set Assembly syntax
setSyntax(int syntax)462   public void setSyntax(int syntax) {
463     if (cs.cs_option(ns.csh, CS_OPT_SYNTAX, new NativeLong(syntax)) == CS_ERR_OK) {
464       this.syntax = syntax;
465     } else {
466       throw new RuntimeException("ERROR: Failed to set assembly syntax");
467     }
468   }
469 
470   // set detail option at run-time
setDetail(int opt)471   public void setDetail(int opt) {
472     if (cs.cs_option(ns.csh, CS_OPT_DETAIL, new NativeLong(opt)) == CS_ERR_OK) {
473       this.detail = opt;
474     } else {
475       throw new RuntimeException("ERROR: Failed to set detail option");
476     }
477   }
478 
479   // set mode option at run-time
setMode(int opt)480   public void setMode(int opt) {
481     if (cs.cs_option(ns.csh, CS_OPT_MODE, new NativeLong(opt)) == CS_ERR_OK) {
482       this.mode = opt;
483     } else {
484       throw new RuntimeException("ERROR: Failed to set mode option");
485     }
486   }
487 
488   // destructor automatically caled at destroyed time.
finalize()489   protected void finalize() {
490     // FIXME: crashed on Ubuntu 14.04 64bit, OpenJDK java 1.6.0_33
491     // cs.cs_close(ns.handleRef);
492   }
493 
494   // destructor automatically caled at destroyed time.
close()495   public int close() {
496     return cs.cs_close(ns.handleRef);
497   }
498 
499   /**
500    * Disassemble instructions from @code assumed to be located at @address,
501    * stop when encountering first broken instruction.
502    *
503    * @param code The source machine code bytes.
504    * @param address The address of the first machine code byte.
505    * @return the array of successfully disassembled instructions, empty if no instruction could be disassembled.
506    */
disasm(byte[] code, long address)507   public CsInsn[] disasm(byte[] code, long address) {
508     return disasm(code, address, 0);
509   }
510 
511   /**
512    * Disassemble up to @count instructions from @code assumed to be located at @address,
513    * stop when encountering first broken instruction.
514    *
515    * @param code The source machine code bytes.
516    * @param address The address of the first machine code byte.
517    * @param count The maximum number of instructions to disassemble, 0 for no maximum.
518    * @return the array of successfully disassembled instructions, empty if no instruction could be disassembled.
519    */
disasm(byte[] code, long address, long count)520   public CsInsn[] disasm(byte[] code, long address, long count) {
521     PointerByReference insnRef = new PointerByReference();
522 
523     NativeLong c = cs.cs_disasm(ns.csh, code, new NativeLong(code.length), address, new NativeLong(count), insnRef);
524 
525     if (0 == c.intValue()) {
526     	return EMPTY_INSN;
527     }
528 
529     Pointer p = insnRef.getValue();
530     _cs_insn byref = new _cs_insn(p);
531 
532     CsInsn[] allInsn = fromArrayRaw((_cs_insn[]) byref.toArray(c.intValue()));
533 
534     // free allocated memory
535     // cs.cs_free(p, c);
536     // FIXME(danghvu): Can't free because memory is still inside CsInsn
537 
538     return allInsn;
539   }
540 
strerror(int code)541   public String strerror(int code) {
542     return cs.cs_strerror(code);
543   }
544 }
545