Reintroduce hook_del(Hook), since it seems useful.
This also improves backwards compatibility a bit.
This commit is contained in:
parent
e787f49d21
commit
48870c4cc3
|
@ -1,15 +1,18 @@
|
||||||
package tests;
|
package tests;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import unicorn.CodeHook;
|
||||||
import unicorn.MemRegion;
|
import unicorn.MemRegion;
|
||||||
import unicorn.TlbFillHook;
|
import unicorn.TlbFillHook;
|
||||||
import unicorn.Unicorn;
|
import unicorn.Unicorn;
|
||||||
|
import unicorn.UnicornException;
|
||||||
import unicorn.X86_Float80;
|
import unicorn.X86_Float80;
|
||||||
|
|
||||||
public class FunctionalityTests {
|
public class FunctionalityTests {
|
||||||
|
@ -181,4 +184,44 @@ public class FunctionalityTests {
|
||||||
assertEquals(Math.sin(-1.1), reg.toDouble(), 1e-12);
|
assertEquals(Math.sin(-1.1), reg.toDouble(), 1e-12);
|
||||||
u.close();
|
u.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveHook() {
|
||||||
|
byte[] X86_CODE = { 0x40, 0x40, 0x40, 0x40 }; // (inc eax) x 4
|
||||||
|
int ADDRESS = 0x10000;
|
||||||
|
final int[] hook_accum = { 0 };
|
||||||
|
|
||||||
|
Unicorn u = new Unicorn(Unicorn.UC_ARCH_X86, Unicorn.UC_MODE_32);
|
||||||
|
u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL);
|
||||||
|
u.mem_write(ADDRESS, X86_CODE);
|
||||||
|
|
||||||
|
CodeHook hook =
|
||||||
|
(uc, address, size, user) -> hook_accum[0] += (int) user;
|
||||||
|
long h1 = u.hook_add(hook, ADDRESS, ADDRESS, 1);
|
||||||
|
long h2 = u.hook_add(hook, ADDRESS + 1, ADDRESS + 1, 2);
|
||||||
|
long h3 = u.hook_add(hook, ADDRESS + 2, ADDRESS + 2, 4);
|
||||||
|
long h4 = u.hook_add(hook, ADDRESS + 3, ADDRESS + 3, 8);
|
||||||
|
|
||||||
|
hook_accum[0] = 0;
|
||||||
|
u.emu_start(ADDRESS, ADDRESS + X86_CODE.length, 0, 0);
|
||||||
|
assertEquals(15, hook_accum[0]);
|
||||||
|
|
||||||
|
u.hook_del(h2);
|
||||||
|
|
||||||
|
hook_accum[0] = 0;
|
||||||
|
u.emu_start(ADDRESS, ADDRESS + X86_CODE.length, 0, 0);
|
||||||
|
assertEquals(13, hook_accum[0]);
|
||||||
|
|
||||||
|
u.hook_del(hook);
|
||||||
|
|
||||||
|
hook_accum[0] = 0;
|
||||||
|
u.emu_start(ADDRESS, ADDRESS + X86_CODE.length, 0, 0);
|
||||||
|
assertEquals(0, hook_accum[0]);
|
||||||
|
|
||||||
|
assertThrows(UnicornException.class, () -> u.hook_del(h1));
|
||||||
|
assertThrows(UnicornException.class, () -> u.hook_del(h3));
|
||||||
|
assertThrows(UnicornException.class, () -> u.hook_del(h4));
|
||||||
|
|
||||||
|
u.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,8 @@ public class Unicorn
|
||||||
|
|
||||||
/** Wrapper around a registered hook */
|
/** Wrapper around a registered hook */
|
||||||
private static class HookWrapper {
|
private static class HookWrapper {
|
||||||
private long nativePtr;
|
Hook hook;
|
||||||
|
long nativePtr;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() {
|
protected void finalize() {
|
||||||
|
@ -685,8 +686,9 @@ public class Unicorn
|
||||||
_ctl_tlb_mode(nativePtr, mode);
|
_ctl_tlb_mode(nativePtr, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long registerHook(long val) {
|
private long registerHook(Hook hook, long val) {
|
||||||
HookWrapper wrapper = new HookWrapper();
|
HookWrapper wrapper = new HookWrapper();
|
||||||
|
wrapper.hook = hook;
|
||||||
wrapper.nativePtr = val;
|
wrapper.nativePtr = val;
|
||||||
long index = nextAllocCounter();
|
long index = nextAllocCounter();
|
||||||
hooks.put(index, wrapper);
|
hooks.put(index, wrapper);
|
||||||
|
@ -705,7 +707,7 @@ public class Unicorn
|
||||||
*/
|
*/
|
||||||
public long hook_add(InterruptHook callback, Object user_data)
|
public long hook_add(InterruptHook callback, Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(
|
return registerHook(callback,
|
||||||
_hook_add(nativePtr, UC_HOOK_INTR, callback, user_data, 1, 0));
|
_hook_add(nativePtr, UC_HOOK_INTR, callback, user_data, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -728,8 +730,8 @@ public class Unicorn
|
||||||
long end,
|
long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_INSN, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_INSN,
|
||||||
user_data, begin, end, insn));
|
callback, user_data, begin, end, insn));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -811,8 +813,8 @@ public class Unicorn
|
||||||
public long hook_add(CodeHook callback, long begin, long end,
|
public long hook_add(CodeHook callback, long begin, long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_CODE, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_CODE,
|
||||||
user_data, begin, end));
|
callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -833,8 +835,8 @@ public class Unicorn
|
||||||
public long hook_add(BlockHook callback, long begin, long end,
|
public long hook_add(BlockHook callback, long begin, long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_BLOCK, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_BLOCK,
|
||||||
user_data, begin, end));
|
callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -859,7 +861,7 @@ public class Unicorn
|
||||||
public long hook_add(MemHook callback, int type, long begin, long end,
|
public long hook_add(MemHook callback, int type, long begin, long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(
|
return registerHook(callback,
|
||||||
_hook_add(nativePtr, type, callback, user_data, begin, end));
|
_hook_add(nativePtr, type, callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -884,7 +886,7 @@ public class Unicorn
|
||||||
public long hook_add(EventMemHook callback, int type, long begin, long end,
|
public long hook_add(EventMemHook callback, int type, long begin, long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(
|
return registerHook(callback,
|
||||||
_hook_add(nativePtr, type, callback, user_data, begin, end));
|
_hook_add(nativePtr, type, callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,7 +904,7 @@ public class Unicorn
|
||||||
*/
|
*/
|
||||||
public long hook_add(EventMemHook callback, int type, Object user_data)
|
public long hook_add(EventMemHook callback, int type, Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(
|
return registerHook(callback,
|
||||||
_hook_add(nativePtr, type, callback, user_data, 1, 0));
|
_hook_add(nativePtr, type, callback, user_data, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -919,8 +921,8 @@ public class Unicorn
|
||||||
*/
|
*/
|
||||||
public long hook_add(InvalidInstructionHook callback,
|
public long hook_add(InvalidInstructionHook callback,
|
||||||
Object user_data) {
|
Object user_data) {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_INSN_INVALID, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_INSN_INVALID,
|
||||||
user_data, 1, 0));
|
callback, user_data, 1, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -941,8 +943,8 @@ public class Unicorn
|
||||||
public long hook_add(EdgeGeneratedHook callback, long begin, long end,
|
public long hook_add(EdgeGeneratedHook callback, long begin, long end,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_EDGE_GENERATED,
|
return registerHook(callback, _hook_add(nativePtr,
|
||||||
callback, user_data, begin, end));
|
UC_HOOK_EDGE_GENERATED, callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -966,8 +968,8 @@ public class Unicorn
|
||||||
int opcode, int flags,
|
int opcode, int flags,
|
||||||
Object user_data)
|
Object user_data)
|
||||||
throws UnicornException {
|
throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_TCG_OPCODE, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_TCG_OPCODE,
|
||||||
user_data, begin, end, opcode, flags));
|
callback, user_data, begin, end, opcode, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -986,8 +988,8 @@ public class Unicorn
|
||||||
*/
|
*/
|
||||||
public long hook_add(TlbFillHook callback, long begin, long end,
|
public long hook_add(TlbFillHook callback, long begin, long end,
|
||||||
Object user_data) throws UnicornException {
|
Object user_data) throws UnicornException {
|
||||||
return registerHook(_hook_add(nativePtr, UC_HOOK_TLB_FILL, callback,
|
return registerHook(callback, _hook_add(nativePtr, UC_HOOK_TLB_FILL,
|
||||||
user_data, begin, end));
|
callback, user_data, begin, end));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove a hook that was previously registered.
|
/** Remove a hook that was previously registered.
|
||||||
|
@ -1003,6 +1005,25 @@ public class Unicorn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Remove all registrations for a given {@link Hook} object.
|
||||||
|
*
|
||||||
|
* @param hook A {@link Hook} object to unregister.
|
||||||
|
*/
|
||||||
|
public void hook_del(Hook hook) throws UnicornException {
|
||||||
|
if (hook == null) {
|
||||||
|
// we use null for "special" hooks that can't be _hook_del'd
|
||||||
|
throw new NullPointerException("hook must not be null");
|
||||||
|
}
|
||||||
|
Iterator<Map.Entry<Long, HookWrapper>> it = hooks.entrySet().iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
HookWrapper wrapper = it.next().getValue();
|
||||||
|
if (wrapper.hook == hook) {
|
||||||
|
it.remove();
|
||||||
|
_hook_del(nativePtr, wrapper.nativePtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a memory-mapped I/O range.
|
* Create a memory-mapped I/O range.
|
||||||
*
|
*
|
||||||
|
@ -1026,7 +1047,7 @@ public class Unicorn
|
||||||
long[] hooks = _mmio_map(nativePtr, address, size, read_cb,
|
long[] hooks = _mmio_map(nativePtr, address, size, read_cb,
|
||||||
user_data_read, write_cb, user_data_write);
|
user_data_read, write_cb, user_data_write);
|
||||||
for (long hook : hooks) {
|
for (long hook : hooks) {
|
||||||
registerHook(hook);
|
registerHook(null, hook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue