Port sample_batch_reg.c to Java, incidentally finding a bug in the generic register implementation.

This commit is contained in:
Robert Xiao 2023-05-14 18:37:30 -07:00
parent edd80ddeda
commit 98f70d3213
3 changed files with 47 additions and 0 deletions

View File

@ -1,5 +1,6 @@
package tests;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
@ -9,6 +10,7 @@ import java.math.BigInteger;
import org.junit.Test;
import unicorn.Arm64_CP;
import unicorn.SyscallHook;
import unicorn.Unicorn;
import unicorn.UnicornException;
import unicorn.X86_Float80;
@ -52,6 +54,43 @@ public class RegTests {
assertEquals(Math.sin(-1.1), reg.toDouble(), 1e-12);
}
/** Test batch register API. Ported from sample_batch_reg.c. Not a sample
* because the Java version of this API is deprecated.
*/
@Test
public void testBatchReg() {
int[] syscall_abi = { Unicorn.UC_X86_REG_RAX, Unicorn.UC_X86_REG_RDI,
Unicorn.UC_X86_REG_RSI, Unicorn.UC_X86_REG_RDX,
Unicorn.UC_X86_REG_R10, Unicorn.UC_X86_REG_R8,
Unicorn.UC_X86_REG_R9 };
Object[] vals = { 200L, 10L, 11L, 12L, 13L, 14L, 15L };
long BASE = 0x10000L;
// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov
// r9, 6; syscall
byte[] CODE =
samples.Utils.hexToBytes("48c7c06400000048c7c70100000048c7c602" +
"00000048c7c20300000049c7c20400000049" +
"c7c00500000049c7c1060000000f05");
Unicorn uc = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_64);
uc.reg_write_batch(syscall_abi, vals);
Object[] rvals = uc.reg_read_batch(syscall_abi);
assertArrayEquals(vals, rvals);
uc.hook_add((SyscallHook) (u, user_data) -> {
Object[] nvals = u.reg_read_batch(syscall_abi);
assertArrayEquals(new Object[] { 100L, 1L, 2L, 3L, 4L, 5L, 6L },
nvals);
}, Unicorn.UC_X86_INS_SYSCALL, 1, 0, null);
uc.mem_map(BASE, 0x1000, Unicorn.UC_PROT_ALL);
uc.mem_write(BASE, CODE);
uc.emu_start(BASE, BASE + CODE.length, 0, 0);
}
@Test
public void testBigIntegerRegister() {
Unicorn uc =

View File

@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import org.junit.Ignore;
import org.junit.Test;
import unicorn.Unicorn;
@ -55,6 +56,7 @@ public class RegressionTests {
}
/** Test that Unicorn instances are properly garbage-collected */
@Ignore("This test is not deterministic")
@Test
public void testUnicornsWillGC() {
final boolean[] close_called = { false };

View File

@ -264,12 +264,14 @@ public class Unicorn
X86_MSR reg = (X86_MSR) opt;
return (Long) _reg_read_x86_msr(ptr, isContext, reg.rid);
}
break;
case UC_ARCH_ARM:
if (regid == UC_ARM_REG_CP_REG) {
Arm_CP reg = (Arm_CP) opt;
return (Long) _reg_read_arm_cp(ptr, isContext, reg.cp, reg.is64,
reg.sec, reg.crn, reg.crm, reg.opc1, reg.opc2);
}
break;
case UC_ARCH_ARM64:
if (regid == UC_ARM64_REG_CP_REG) {
Arm64_CP reg = (Arm64_CP) opt;
@ -280,6 +282,7 @@ public class Unicorn
(regid >= UC_ARM64_REG_V0 && regid <= UC_ARM64_REG_V31)) {
return do_reg_read_bigint(ptr, isContext, regid, 128);
}
break;
}
return _reg_read_long(ptr, isContext, regid);
}
@ -330,6 +333,7 @@ public class Unicorn
_reg_write_x86_msr(ptr, isContext, reg.rid, reg.value);
return;
}
break;
case UC_ARCH_ARM:
if (regid == UC_ARM_REG_CP_REG) {
Arm_CP reg = (Arm_CP) value;
@ -337,6 +341,7 @@ public class Unicorn
reg.crn, reg.crm, reg.opc1, reg.opc2, reg.val);
return;
}
break;
case UC_ARCH_ARM64:
if (regid == UC_ARM64_REG_CP_REG) {
Arm64_CP reg = (Arm64_CP) value;
@ -350,6 +355,7 @@ public class Unicorn
128);
return;
}
break;
}
_reg_write_long(ptr, isContext, regid, (Long) value);
}