Refactor java binding, remove offset dependency

This commit is contained in:
danghvu 2013-11-27 02:13:32 -06:00
parent 35855b5b93
commit 5f495529b0
7 changed files with 243 additions and 221 deletions

View File

@ -63,32 +63,22 @@ class Arm {
}
}
public static class OpValue extends Union implements Union.ByReference {
public static class OpValue extends Union {
public int reg;
public long imm;
public double fp;
public MemType mem;
public OpValue(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("reg", "imm", "fp", "mem");
}
}
public static class OpShift extends Structure implements Structure.ByReference {
public static class OpShift extends Structure {
public int type;
public int value;
public OpShift(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("type","value");
@ -100,38 +90,53 @@ class Arm {
public int type;
public OpValue value;
public void read() {
super.read();
if (type == ARM_OP_MEM)
value.setType(MemType.class);
if (type == ARM_OP_FP)
value.setType(Double.TYPE);
if (type == ARM_OP_PIMM || type == ARM_OP_IMM || type == ARM_OP_CIMM)
value.setType(Long.TYPE);
if (type == ARM_OP_REG)
value.setType(Integer.TYPE);
readField("value");
}
@Override
public List getFieldOrder() {
return Arrays.asList("shift", "type", "value");
}
}
public static class UnionOpInfo extends Structure {
public int cc;
public byte _update_flags;
public byte _writeback;
public byte op_count;
public Operand [] op = new Operand[32];
@Override
public List getFieldOrder() {
return Arrays.asList("cc", "_update_flags", "_writeback", "op_count", "op");
}
}
public static class OpInfo extends Capstone.OpInfo {
public int cc;
public boolean update_flags;
public boolean writeback;
public Operand [] op = null;
public Operand [] op;
public OpInfo(Pointer p) {
cc = p.getInt(0);
update_flags = (boolean) (p.getByte(4) > 0);
writeback = (boolean) (p.getByte(5) > 0);
int op_count = p.getShort(6);
if (op_count == 0) {
op = null;
return;
}
op = new Operand[op_count];
for (int i=0; i<op_count; i++) {
Pointer p1 = p.share(8 + i*40);
op[i] = new Operand();
op[i].shift = new OpShift(p1);
op[i].type = p1.getInt(8);
op[i].value = new OpValue(p1.share(16));
if (op[i].type == ARM_OP_MEM) {
op[i].value.setType(MemType.class);
op[i].value.read();
}
}
public OpInfo(UnionOpInfo op_info) {
cc = op_info.cc;
update_flags = (op_info._update_flags > 0);
writeback = (op_info._writeback > 0);
if (op_info.op_count == 0) return;
op = new Operand[op_info.op_count];
for (int i=0; i<op_info.op_count; i++)
op[i] = op_info.op[i];
}
}

View File

@ -68,32 +68,22 @@ class Arm64 {
}
}
public static class OpValue extends Union implements Union.ByReference {
public static class OpValue extends Union {
public int reg;
public long imm;
public double fp;
public MemType mem;
public OpValue(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("reg", "imm", "fp", "mem");
}
}
public static class OpShift extends Structure implements Structure.ByReference {
public static class OpShift extends Structure {
public int type;
public int value;
public OpShift(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("type","value");
@ -106,39 +96,62 @@ class Arm64 {
public int type;
public OpValue value;
public void read() {
super.read();
if (type == ARM64_OP_MEM)
value.setType(MemType.class);
if (type == ARM64_OP_FP)
value.setType(Double.TYPE);
if (type == ARM64_OP_IMM || type == ARM64_OP_CIMM)
value.setType(Long.TYPE);
if (type == ARM64_OP_REG)
value.setType(Integer.TYPE);
if (type == ARM64_OP_INVALID)
return;
readField("value");
}
@Override
public List getFieldOrder() {
return Arrays.asList("shift", "ext", "type", "value");
}
}
public static class OpInfo extends Capstone.OpInfo {
public static class UnionOpInfo extends Structure {
public int cc;
public byte _update_flags;
public byte _writeback;
public byte op_count;
public Operand [] op;
public OpInfo(Pointer p) {
cc = p.getInt(0);
update_flags = (boolean) (p.getByte(4) > 0);
writeback = (boolean) (p.getByte(5) > 0);
int op_count = p.getShort(6);
if (op_count == 0) {
op = null;
return;
}
public Operand [] op = new Operand[32];
public void read() {
readField("cc");
readField("_update_flags");
readField("_writeback");
readField("op_count");
op = new Operand[op_count];
for (int i=0; i<op_count; i++) {
Pointer p1 = p.share(8 + i*32);
op[i] = new Operand();
op[i].shift = new OpShift(p1);
op[i].ext = p1.getInt(8);
op[i].type = p1.getInt(12);
op[i].value = new OpValue(p1.share(16));
if (op[i].type == ARM64_OP_MEM) {
op[i].value.setType(MemType.class);
op[i].value.read();
}
}
readField("op");
}
@Override
public List getFieldOrder() {
return Arrays.asList("cc", "_update_flags", "_writeback", "op_count", "op");
}
}
public static class OpInfo extends Capstone.OpInfo {
public int cc;
public boolean update_flags;
public boolean writeback;
public Operand [] op = null;
public OpInfo(UnionOpInfo op_info) {
cc = op_info.cc;
update_flags = (op_info._update_flags > 0);
writeback = (op_info._writeback > 0);
if (op_info.op_count == 0) return;
op = op_info.op;
}
}

View File

@ -18,92 +18,109 @@ class Capstone {
public int arch;
public int mode;
public static class OpInfo {
public int cc;
public boolean update_flags;
public boolean writeback;
public static abstract class OpInfo {
}
public class cs_insn {
/*
== total size: 1728
@id: 0
@address: 8
@size: 16
@mnemonic: 18
@operands: 50
@regs_read: 148
@regs_write: 276
@groups: 404
@arch: 440
*/
public static class PrivateOpInfo extends Union {
public X86.UnionOpInfo x86;
public Arm64.UnionOpInfo arm64;
public Arm.UnionOpInfo arm;
public Mips.UnionOpInfo mips;
}
public static class _cs_insn extends Structure implements Structure.ByReference {
public int id;
public long address;
public short size;
public String mnemonic;
public String operands;
public int[] regs_read;
public int[] regs_write;
public int[] groups;
public byte[] mnemonic = new byte[32];
public byte[] operands = new byte[96];
public int[] regs_read = new int[32];
public int[] regs_write = new int[32];
public int[] groups = new int[8];
public OpInfo op_info;
public PrivateOpInfo _op_info;
Pointer ptr_cs_ins;
long handleval;
public _cs_insn(Pointer p) { super(p); }
@Override
public List getFieldOrder() {
return Arrays.asList("id", "address", "size", "mnemonic", "operands", "regs_read", "regs_write", "groups", "_op_info");
}
}
public static class cs_insn {
OpInfo op_info;
Pointer ptr_origin;
long csh;
CS cs;
int id;
long address;
short size;
String mnemonic;
String operands;
int[] regs_read;
int[] regs_write;
int[] groups;
public cs_insn (_cs_insn struct, Pointer _ptr_origin, long _csh, CS _cs, OpInfo _op_info) {
id = struct.id;
address = struct.address;
size = struct.size;
mnemonic = new String(struct.mnemonic).replace("\u0000","");
operands = new String(struct.operands).replace("\u0000","");
regs_read = struct.regs_read;
regs_write = struct.regs_write;
groups = struct.groups;
ptr_origin = _ptr_origin;
op_info = _op_info;
csh = _csh;
cs = _cs;
}
public int op_count(int type) {
return cs.cs_op_count(handleval, ptr_cs_ins, type);
return cs.cs_op_count(csh, ptr_origin, type);
}
public int op_index(int type, int index) {
return cs.cs_op_index(handleval, ptr_cs_ins, type, index);
return cs.cs_op_index(csh, ptr_origin, type, index);
}
}
private cs_insn fromPointer(Pointer pointer) {
cs_insn insn = new cs_insn();
insn.id = pointer.getInt(0);
insn.address = pointer.getLong(8);
insn.size = pointer.getShort(16);
insn.mnemonic = pointer.getString(18);
insn.operands = pointer.getString(50);
insn.regs_read = pointer.getIntArray(148, 32);
insn.regs_write = pointer.getIntArray(276, 32);
insn.groups = pointer.getIntArray(404, 8);
private cs_insn fromPointer(Pointer pointer)
{
_cs_insn insn = new _cs_insn(pointer);
OpInfo op_info = null;
switch (this.arch) {
case CS_ARCH_ARM:
insn.op_info = new Arm.OpInfo(pointer.share(440));
insn._op_info.setType(Arm.UnionOpInfo.class);
insn.read();
op_info = new Arm.OpInfo(insn._op_info.arm);
break;
case CS_ARCH_ARM64:
insn.op_info = new Arm64.OpInfo(pointer.share(440));
insn._op_info.setType(Arm64.UnionOpInfo.class);
insn.read();
op_info = new Arm64.OpInfo(insn._op_info.arm64);
break;
case CS_ARCH_MIPS:
insn.op_info = new Mips.OpInfo(pointer.share(440));
insn._op_info.setType(Mips.UnionOpInfo.class);
insn.read();
op_info = new Mips.OpInfo(insn._op_info.mips);
break;
case CS_ARCH_X86:
insn.op_info = new X86.OpInfo(pointer.share(440));
insn._op_info.setType(X86.UnionOpInfo.class);
insn.read();
op_info = new X86.OpInfo(insn._op_info.x86);
break;
default:
insn.op_info = null;
}
insn.ptr_cs_ins = pointer;
insn.handleval = handle.getValue();
return insn;
return new cs_insn(insn, pointer, csh, cs, op_info);
}
private cs_insn[] fromArrayPointer(Pointer pointer, int numberResults) {
private cs_insn[] fromArrayPointer(Pointer pointer, int numberResults)
{
cs_insn[] arr = new cs_insn[numberResults];
int offset = 0;
@ -120,7 +137,7 @@ class Capstone {
public long cs_disasm_dyn(long handle, byte[] code, long code_len,
long addr, long count, PointerByReference insn);
public void cs_free(Pointer p);
public boolean cs_close(long handle);
public int cs_close(long handle);
public String cs_reg_name(long csh, int id);
public int cs_op_count(long csh, Pointer insn, int type);
public int cs_op_index(long csh, Pointer insn, int type, int index);
@ -150,7 +167,7 @@ class Capstone {
public static final int CS_ERR_MODE = 5; // Invalid/unsupported mode
private LongByReference handle;
private long csh;
private PointerByReference insnRef;
private CS cs;
@ -159,28 +176,32 @@ class Capstone {
this.arch = arch;
this.mode = mode;
cs = (CS)Native.loadLibrary("capstone", CS.class);
handle = new LongByReference();
if (cs.cs_open(arch, mode, handle) != CS_ERR_OK) {
LongByReference handleref = new LongByReference();
if (cs.cs_open(arch, mode, handleref) != CS_ERR_OK) {
throw new RuntimeException("ERROR: Wrong arch or mode");
}
csh = handleref.getValue();
}
public String reg_name(int reg) {
return cs.cs_reg_name(handle.getValue(), reg);
return cs.cs_reg_name(csh, reg);
}
protected void finalize() {
cs.cs_close(handle.getValue());
protected void finalize()
{
cs.cs_close(csh);
}
cs_insn[] disasm(byte[] code, long address) {
cs_insn[] disasm(byte[] code, long address)
{
return disasm(code, address, 0);
}
cs_insn[] disasm(byte[] code, long address, long count) {
cs_insn[] disasm(byte[] code, long address, long count)
{
insnRef = new PointerByReference();
long c = cs.cs_disasm_dyn(handle.getValue(), code, code.length, address, count, insnRef);
long c = cs.cs_disasm_dyn(csh, code, code.length, address, count, insnRef);
Pointer p = insnRef.getValue();
cs_insn[] all_insn = fromArrayPointer(p, (int)c);

View File

@ -27,16 +27,11 @@ class Mips {
}
}
public static class OpValue extends Union implements Union.ByReference {
public static class OpValue extends Union {
public int reg;
public long imm;
public MemType mem;
public OpValue(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("reg", "imm", "mem");
@ -47,34 +42,50 @@ class Mips {
public int type;
public OpValue value;
public void read() {
super.read();
if (type == MIPS_OP_MEM)
value.setType(MemType.class);
if (type == MIPS_OP_IMM)
value.setType(Long.TYPE);
if (type == MIPS_OP_REG)
value.setType(Integer.TYPE);
if (type == MIPS_OP_INVALID)
return;
readField("value");
}
@Override
public List getFieldOrder() {
return Arrays.asList("type", "value");
}
}
public static class UnionOpInfo extends Structure {
public short op_count;
public Operand [] op = new Operand[8];
public void read() {
readField("op_count");
op = new Operand[op_count];
readField("op");
}
@Override
public List getFieldOrder() {
return Arrays.asList("op_count", "op");
}
}
public static class OpInfo extends Capstone.OpInfo {
public Operand [] op;
public OpInfo(Pointer p) {
int op_count = p.getShort(0);
if (op_count == 0) {
public OpInfo(UnionOpInfo e) {
if (e.op_count == 0) {
op = null;
return;
}
op = new Operand[op_count];
for (int i=0; i<op_count; i++) {
Pointer p1 = p.share(i*24);
op[i] = new Operand();
op[i].type = p1.getInt(8);
op[i].value = new OpValue(p1.share(16));
if (op[i].type == MIPS_OP_MEM) {
op[i].value.setType(MemType.class);
op[i].value.read();
}
}
op = e.op;
}
}

View File

@ -6,7 +6,6 @@ import com.sun.jna.Memory;
import com.sun.jna.Pointer;
public class Test {
public static class platform {
public int arch;
public int mode;

View File

@ -47,7 +47,7 @@ public class TestX86 {
System.out.printf("\tPrefix: %s\n", array2hex(op_info.prefix));
if (op_info.segment != X86.X86_REG_INVALID)
System.out.println("\tSegment override:" + cs.reg_name(op_info.segment));
System.out.println("\tSegment override: " + cs.reg_name(op_info.segment));
System.out.printf("\tOpcode: %s\n", array2hex(op_info.opcode));
@ -65,7 +65,7 @@ public class TestX86 {
// SIB is not available in 16-bit mode
if ( (cs.mode & Capstone.CS_MODE_16) == 0)
// print SIB byte
System.out.printf("\tsib: 0x%s\n", hex(op_info.sib));
System.out.printf("\tsib: 0x%x\n", op_info.sib);
int count = ins.op_count(X86.X86_OP_IMM);
if (count > 0) {

View File

@ -30,17 +30,12 @@ class X86 {
}
}
public static class OpValue extends Union implements Union.ByReference {
public static class OpValue extends Union {
public int reg;
public long imm;
public double fp;
public MemType mem;
public OpValue(Pointer p) {
super(p);
read();
}
@Override
public List getFieldOrder() {
return Arrays.asList("reg", "imm", "fp", "mem");
@ -51,16 +46,31 @@ class X86 {
public int type;
public OpValue value;
public void read() {
super.read();
if (type == X86_OP_MEM)
value.setType(MemType.class);
if (type == X86_OP_FP)
value.setType(Double.TYPE);
if (type == X86_OP_IMM)
value.setType(Long.TYPE);
if (type == X86_OP_REG)
value.setType(Integer.TYPE);
if (type == X86_OP_INVALID)
return;
readField("value");
}
@Override
public List getFieldOrder() {
return Arrays.asList("shift", "type", "value");
return Arrays.asList("type", "value");
}
}
public static class X86extra extends Structure implements Structure.ByReference {
public byte [] prefix;
public static class UnionOpInfo extends Structure {
public byte [] prefix = new byte[5];
public int segment;
public byte [] opcode;
public byte [] opcode = new byte[3];
public byte op_size;
public byte addr_size;
public byte disp_size;
@ -72,38 +82,18 @@ class X86 {
public byte sib_scale;
public int sib_base;
public X86extra(Pointer p) {
super (p);
prefix = new byte[5];
opcode = new byte[3];
read();
}
public int op_count;
public Operand [] op = new Operand[8];
@Override
public List getFieldOrder() {
return Arrays.asList("prefix", "segment", "opcode", "op_size", "addr_size", "disp_size", "imm_size", "modrm", "sib", "disp", "sib_index", "sib_scale", "sib_base");
return Arrays.asList("prefix", "segment", "opcode", "op_size", "addr_size", "disp_size",
"imm_size", "modrm", "sib", "disp", "sib_index", "sib_scale", "sib_base", "op_count", "op");
}
/* 15 + 4*8
('prefix', ctypes.c_uint8 * 5),
('segment', ctypes.c_uint),
('opcode', ctypes.c_uint8 * 3),
('op_size', ctypes.c_uint8),
('addr_size', ctypes.c_uint8),
('disp_size', ctypes.c_uint8),
('imm_size', ctypes.c_uint8),
('modrm', ctypes.c_uint8),
('sib', ctypes.c_uint8),
('disp', ctypes.c_int32),
('sib_index', ctypes.c_uint),
('sib_scale', ctypes.c_int8),
('sib_base', ctypes.c_uint),
*/
}
public static class OpInfo extends Capstone.OpInfo {
public X86extra e;
public Operand [] op;
public byte [] prefix;
public int segment;
public byte [] opcode;
@ -118,10 +108,9 @@ class X86 {
public byte sib_scale;
public int sib_base;
Operand[] op;
private void copyextra() {
// FIXME: we need to manually copy like this since we want to use JNA constructor
// still better than having a fixed offset
public OpInfo(UnionOpInfo e) {
prefix = e.prefix;
segment = e.segment;
opcode = e.opcode;
@ -135,29 +124,13 @@ class X86 {
sib_index = e.sib_index;
sib_scale = e.sib_scale;
sib_base = e.sib_base;
}
public OpInfo(Pointer p) {
e = new X86extra(p);
copyextra();
int op_count = p.getByte(e.size());
if (op_count == 0) {
if (e.op_count == 0) {
op = null;
return;
}
op = new Operand[op_count];
for (int i=0; i<op_count; i++) {
Pointer p1 = p.share(48 + i*32);
op[i] = new Operand();
op[i].type = p1.getInt(0);
op[i].value = new OpValue(p1.share(8));
if (op[i].type == X86_OP_MEM) {
op[i].value.setType(MemType.class);
op[i].value.read();
}
}
op = new Operand[e.op_count];
for (int i=0; i<e.op_count; i++)
op[i] = e.op[i];
}
}
// all Intel reigsters