diff --git a/bindings/java/unicorn/MemRegion.java b/bindings/java/unicorn/MemRegion.java new file mode 100755 index 00000000..b729b3a9 --- /dev/null +++ b/bindings/java/unicorn/MemRegion.java @@ -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; + } + +} + diff --git a/bindings/java/unicorn/Unicorn.java b/bindings/java/unicorn/Unicorn.java old mode 100644 new mode 100755 index 5a28c267..f1a5d15f --- a/bindings/java/unicorn/Unicorn.java +++ b/bindings/java/unicorn/Unicorn.java @@ -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; + } diff --git a/bindings/java/unicorn_Unicorn.c b/bindings/java/unicorn_Unicorn.c old mode 100644 new mode 100755 index a14bd9e4..01af31ee --- a/bindings/java/unicorn_Unicorn.c +++ b/bindings/java/unicorn_Unicorn.c @@ -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, ®ions, &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, "", "(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; +}