implement missing APIs (uc_query, uc_mem_map_ptr, uc_mem_regions) in java binding

This commit is contained in:
Chris Eagle 2016-02-06 15:16:44 -08:00
parent 6986fa3947
commit aa1657006b
3 changed files with 148 additions and 5 deletions

View File

@ -0,0 +1,37 @@
/*
Java bindings for the Unicorn Emulator Engine
Copyright(c) 2016 Chris Eagle
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package unicorn;
public class MemRegion {
public long begin;
public long end;
public int perms;
public MemRegion(long begin, long end, int perms) {
this.begin = begin;
this.end = end;
this.perms = perms;
}
}

40
bindings/java/unicorn/Unicorn.java Normal file → Executable file
View File

@ -288,7 +288,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*
* @param arch Architecture type (UC_ARCH_*)
* @param mode Hardware mode. This is combined of UC_MODE_*
* @see unicorn.UnicornArchs, unicorn.UnicornModes
* @see unicorn.UnicornConst
*
*/
public Unicorn(int arch, int mode) throws UnicornException {
@ -327,7 +327,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*
* @param arch Architecture type (UC_ARCH_*)
* @return true if this library supports the given arch.
* @see unicorn.UnicornArchs
* @see unicorn.UnicornConst
*/
public native static boolean arch_supported(int arch);
@ -337,12 +337,23 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/
public native void close() throws UnicornException;
/**
* Query internal status of engine.
*
* @param type query type. See UC_QUERY_*
* @param result save the internal status queried
*
* @return: error code. see UC_ERR_*
* @see unicorn.UnicornConst
*/
public native int query(int type) throws UnicornException;
/**
* Report the last error number when some API function fail.
* Like glibc's errno, uc_errno might not retain its old value once accessed.
*
* @return Error code of uc_err enum type (UC_ERR_*, see above)
* @see unicorn.UnicornErrors
* @see unicorn.UnicornConst
*/
public native int errno();
@ -351,7 +362,7 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*
* @param code Error code (see UC_ERR_* above)
* @return Returns a String that describes the error code
* @see unicorn.UnicornErrors
* @see unicorn.UnicornConst
*/
public native static String strerror(int code);
@ -625,6 +636,19 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/
public native void mem_map(long address, long size, int perms) throws UnicornException;
/**
* Map existing host memory in for emulation.
* This API adds a memory region that can be used by emulation.
*
* @param address Base address of the memory range
* @param size Size of the memory block.
* @param perms Permissions on the memory block. A combination of UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC
* @param ptr Block of host memory backing the newly mapped memory. This block is
* expected to be an equal or larger size than provided, and be mapped with at
* least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined.
*/
public native void mem_map_ptr(long address, long size, int perms, byte[] block) throws UnicornException;
/**
* Unmap a range of memory.
*
@ -642,5 +666,13 @@ public class Unicorn implements UnicornConst, ArmConst, Arm64Const, M68kConst, S
*/
public native void mem_protect(long address, long size, int perms) throws UnicornException;
/**
* Retrieve all memory regions mapped by mem_map() and mem_map_ptr()
* NOTE: memory regions may be split by mem_unmap()
*
* @return list of mapped regions.
*/
public native MemRegion[] mem_regions() throws UnicornException;
}

76
bindings/java/unicorn_Unicorn.c Normal file → Executable file
View File

@ -244,7 +244,28 @@ JNIEXPORT jboolean JNICALL Java_unicorn_Unicorn_arch_1supported
JNIEXPORT void JNICALL Java_unicorn_Unicorn_close
(JNIEnv *env, jobject self) {
uc_engine *eng = getEngine(env, self);
uc_close(eng);
uc_err err = uc_close(eng);
if (err != UC_ERR_OK) {
throwException(env, err);
}
//We also need to ReleaseByteArrayElements for any regions that
//were mapped with uc_mem_map_ptr
}
/*
* Class: unicorn_Unicorn
* Method: query
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_unicorn_Unicorn_query
(JNIEnv *env, jobject self, jint type) {
uc_engine *eng = getEngine(env, self);
size_t result;
uc_err err = uc_query(eng, type, &result);
if (err != UC_ERR_OK) {
throwException(env, err);
}
return (jint)result;
}
/*
@ -508,6 +529,24 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map
}
}
/*
* Class: unicorn_Unicorn
* Method: mem_map_ptr
* Signature: (JJI[B)V
*/
JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1map_1ptr
(JNIEnv *env, jobject self, jlong address, jlong size, jint perms, jbyteArray block) {
uc_engine *eng = getEngine(env, self);
jbyte *array = (*env)->GetByteArrayElements(env, block, NULL);
uc_err err = uc_mem_map_ptr(eng, (uint64_t)address, (size_t)size, (uint32_t)perms, (void*)array);
if (err != UC_ERR_OK) {
throwException(env, err);
}
//Need to track address/block/array so that we can ReleaseByteArrayElements when the
//block gets unmapped or when uc_close gets called
//(*env)->ReleaseByteArrayElements(env, block, array, JNI_ABORT);
}
/*
* Class: unicorn_Unicorn
* Method: mem_unmap
@ -521,6 +560,9 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1unmap
if (err != UC_ERR_OK) {
throwException(env, err);
}
//If a region was mapped using uc_mem_map_ptr, we also need to
//ReleaseByteArrayElements for that region
}
/*
@ -537,3 +579,35 @@ JNIEXPORT void JNICALL Java_unicorn_Unicorn_mem_1protect
throwException(env, err);
}
}
/*
* Class: unicorn_Unicorn
* Method: mem_regions
* Signature: ()[Lunicorn/MemRegion;
*/
JNIEXPORT jobjectArray JNICALL Java_unicorn_Unicorn_mem_1regions
(JNIEnv *env, jobject self) {
uc_engine *eng = getEngine(env, self);
uc_mem_region *regions = NULL;
uint32_t count = 0;
uint32_t i;
uc_err err = uc_mem_regions(eng, &regions, &count);
if (err != UC_ERR_OK) {
throwException(env, err);
}
jclass clz = (*env)->FindClass(env, "unicorn/MemRegion");
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
jobjectArray result = (*env)->NewObjectArray(env, (jsize)count, clz, NULL);
jmethodID cons = (*env)->GetMethodID(env, clz, "<init>", "(JJI)V");
for (i = 0; i < count; i++) {
jobject mr = (*env)->NewObject(env, clz, cons, regions[i].begin, regions[i].end, regions[i].perms);
(*env)->SetObjectArrayElement(env, result, (jsize)i, mr);
}
free(regions);
return result;
}