Make close() idempotent and fix Unicorn memory leak.
This commit is contained in:
@@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||||||
|
|
||||||
package unicorn;
|
package unicorn;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ public class Unicorn
|
|||||||
implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst,
|
implements UnicornConst, ArmConst, Arm64Const, M68kConst, SparcConst,
|
||||||
MipsConst, X86Const {
|
MipsConst, X86Const {
|
||||||
|
|
||||||
public long eng;
|
private long eng;
|
||||||
private int arch;
|
private int arch;
|
||||||
private int mode;
|
private int mode;
|
||||||
|
|
||||||
@@ -70,15 +71,13 @@ public class Unicorn
|
|||||||
private ArrayList<Tuple> syscallList = new ArrayList<Tuple>();
|
private ArrayList<Tuple> syscallList = new ArrayList<Tuple>();
|
||||||
|
|
||||||
private Hashtable<Integer, ArrayList<Tuple>> eventMemLists =
|
private Hashtable<Integer, ArrayList<Tuple>> eventMemLists =
|
||||||
new Hashtable<Integer, ArrayList<Tuple>>();
|
new Hashtable<>();
|
||||||
|
|
||||||
private ArrayList<ArrayList<Tuple>> allLists =
|
private ArrayList<ArrayList<Tuple>> allLists = new ArrayList<>();
|
||||||
new ArrayList<ArrayList<Tuple>>();
|
|
||||||
|
|
||||||
private static Hashtable<Integer, Integer> eventMemMap =
|
private static Hashtable<Integer, Integer> eventMemMap = new Hashtable<>();
|
||||||
new Hashtable<Integer, Integer>();
|
private static Hashtable<Long, WeakReference<Unicorn>> unicorns =
|
||||||
private static Hashtable<Long, Unicorn> unicorns =
|
new Hashtable<>();
|
||||||
new Hashtable<Long, Unicorn>();
|
|
||||||
|
|
||||||
// required to load native method implementations
|
// required to load native method implementations
|
||||||
static {
|
static {
|
||||||
@@ -107,7 +106,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.BlockHook
|
* @see hook_add, unicorn.BlockHook
|
||||||
*/
|
*/
|
||||||
private static void invokeBlockCallbacks(long eng, long address, int size) {
|
private static void invokeBlockCallbacks(long eng, long address, int size) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.blockList) {
|
for (Tuple p : u.blockList) {
|
||||||
BlockHook bh = (BlockHook) p.function;
|
BlockHook bh = (BlockHook) p.function;
|
||||||
@@ -126,7 +125,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.InterruptHook
|
* @see hook_add, unicorn.InterruptHook
|
||||||
*/
|
*/
|
||||||
private static void invokeInterruptCallbacks(long eng, int intno) {
|
private static void invokeInterruptCallbacks(long eng, int intno) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.intrList) {
|
for (Tuple p : u.intrList) {
|
||||||
InterruptHook ih = (InterruptHook) p.function;
|
InterruptHook ih = (InterruptHook) p.function;
|
||||||
@@ -146,7 +145,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.CodeHook
|
* @see hook_add, unicorn.CodeHook
|
||||||
*/
|
*/
|
||||||
private static void invokeCodeCallbacks(long eng, long address, int size) {
|
private static void invokeCodeCallbacks(long eng, long address, int size) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.codeList) {
|
for (Tuple p : u.codeList) {
|
||||||
CodeHook ch = (CodeHook) p.function;
|
CodeHook ch = (CodeHook) p.function;
|
||||||
@@ -174,7 +173,7 @@ public class Unicorn
|
|||||||
private static boolean invokeEventMemCallbacks(long eng, int type,
|
private static boolean invokeEventMemCallbacks(long eng, int type,
|
||||||
long address, int size,
|
long address, int size,
|
||||||
long value) {
|
long value) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
ArrayList<Tuple> funcList = u.eventMemLists.get(type);
|
ArrayList<Tuple> funcList = u.eventMemLists.get(type);
|
||||||
@@ -199,7 +198,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.ReadHook
|
* @see hook_add, unicorn.ReadHook
|
||||||
*/
|
*/
|
||||||
private static void invokeReadCallbacks(long eng, long address, int size) {
|
private static void invokeReadCallbacks(long eng, long address, int size) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.readList) {
|
for (Tuple p : u.readList) {
|
||||||
ReadHook rh = (ReadHook) p.function;
|
ReadHook rh = (ReadHook) p.function;
|
||||||
@@ -221,7 +220,7 @@ public class Unicorn
|
|||||||
*/
|
*/
|
||||||
private static void invokeWriteCallbacks(long eng, long address, int size,
|
private static void invokeWriteCallbacks(long eng, long address, int size,
|
||||||
long value) {
|
long value) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.writeList) {
|
for (Tuple p : u.writeList) {
|
||||||
WriteHook wh = (WriteHook) p.function;
|
WriteHook wh = (WriteHook) p.function;
|
||||||
@@ -243,7 +242,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.InHook
|
* @see hook_add, unicorn.InHook
|
||||||
*/
|
*/
|
||||||
private static int invokeInCallbacks(long eng, int port, int size) {
|
private static int invokeInCallbacks(long eng, int port, int size) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.inList) {
|
for (Tuple p : u.inList) {
|
||||||
@@ -267,7 +266,7 @@ public class Unicorn
|
|||||||
*/
|
*/
|
||||||
private static void invokeOutCallbacks(long eng, int port, int size,
|
private static void invokeOutCallbacks(long eng, int port, int size,
|
||||||
int value) {
|
int value) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.outList) {
|
for (Tuple p : u.outList) {
|
||||||
@@ -287,7 +286,7 @@ public class Unicorn
|
|||||||
* @see hook_add, unicorn.SyscallHook
|
* @see hook_add, unicorn.SyscallHook
|
||||||
*/
|
*/
|
||||||
private static void invokeSyscallCallbacks(long eng) {
|
private static void invokeSyscallCallbacks(long eng) {
|
||||||
Unicorn u = unicorns.get(eng);
|
Unicorn u = unicorns.get(eng).get();
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if (u != null) {
|
if (u != null) {
|
||||||
for (Tuple p : u.syscallList) {
|
for (Tuple p : u.syscallList) {
|
||||||
@@ -353,7 +352,7 @@ public class Unicorn
|
|||||||
this.arch = arch;
|
this.arch = arch;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
eng = open(arch, mode);
|
eng = open(arch, mode);
|
||||||
unicorns.put(eng, this);
|
unicorns.put(eng, new WeakReference<>(this));
|
||||||
allLists.add(blockList);
|
allLists.add(blockList);
|
||||||
allLists.add(intrList);
|
allLists.add(intrList);
|
||||||
allLists.add(codeList);
|
allLists.add(codeList);
|
||||||
@@ -369,7 +368,6 @@ public class Unicorn
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected void finalize() {
|
protected void finalize() {
|
||||||
unicorns.remove(eng);
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,7 +377,7 @@ public class Unicorn
|
|||||||
* @return hexadecimal number as (major << 8 | minor), which encodes both major
|
* @return hexadecimal number as (major << 8 | minor), which encodes both major
|
||||||
* & minor versions.
|
* & minor versions.
|
||||||
*
|
*
|
||||||
* For example Unicorn version 1.2 whould yield 0x0102
|
* For example Unicorn version 1.2 would yield 0x0102
|
||||||
*/
|
*/
|
||||||
public native static int version();
|
public native static int version();
|
||||||
|
|
||||||
@@ -396,7 +394,15 @@ public class Unicorn
|
|||||||
* Close the underlying uc_engine* eng associated with this Unicorn object
|
* Close the underlying uc_engine* eng associated with this Unicorn object
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public native void close() throws UnicornException;
|
private native void _close() throws UnicornException;
|
||||||
|
|
||||||
|
public void close() throws UnicornException {
|
||||||
|
if (eng != 0) {
|
||||||
|
_close();
|
||||||
|
unicorns.remove(eng);
|
||||||
|
eng = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query internal status of engine.
|
* Query internal status of engine.
|
||||||
|
|||||||
@@ -388,10 +388,10 @@ JNIEXPORT jboolean JNICALL Java_unicorn_Unicorn_arch_1supported(JNIEnv *env,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: unicorn_Unicorn
|
* Class: unicorn_Unicorn
|
||||||
* Method: close
|
* Method: _close
|
||||||
* Signature: ()V
|
* Signature: ()V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_unicorn_Unicorn_close(JNIEnv *env, jobject self)
|
JNIEXPORT void JNICALL Java_unicorn_Unicorn__1close(JNIEnv *env, jobject self)
|
||||||
{
|
{
|
||||||
uc_engine *eng = getEngine(env, self);
|
uc_engine *eng = getEngine(env, self);
|
||||||
uc_err err = uc_close(eng);
|
uc_err err = uc_close(eng);
|
||||||
|
|||||||
Reference in New Issue
Block a user