From 2a269acac1158794f8515f1d7e92fd9efb96f068 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 10 Jan 2016 23:56:14 +0800 Subject: [PATCH] regress: add memleak_xxx.c to test memleak issue --- .gitignore | 7 + tests/regress/Makefile | 7 + tests/regress/memleak_arm.c | 178 ++++++++++++++++++++ tests/regress/memleak_arm64.c | 122 ++++++++++++++ tests/regress/memleak_m68k.c | 185 ++++++++++++++++++++ tests/regress/memleak_mips.c | 171 +++++++++++++++++++ tests/regress/memleak_sparc.c | 125 ++++++++++++++ tests/regress/memleak_x86.c | 306 ++++++++++++++++++++++++++++++++++ 8 files changed, 1101 insertions(+) create mode 100644 tests/regress/memleak_arm.c create mode 100644 tests/regress/memleak_arm64.c create mode 100644 tests/regress/memleak_m68k.c create mode 100644 tests/regress/memleak_mips.c create mode 100644 tests/regress/memleak_sparc.c create mode 100644 tests/regress/memleak_x86.c diff --git a/.gitignore b/.gitignore index 4578b7dc..b184113c 100644 --- a/.gitignore +++ b/.gitignore @@ -132,6 +132,13 @@ rw_hookstack hook_extrainvoke sysenter_hook_x86 +memleak_x86 +memleak_arm +memleak_arm64 +memleak_mips +memleak_m68k +memleak_sparc + ################# ## Visual Studio diff --git a/tests/regress/Makefile b/tests/regress/Makefile index 3f1d59a5..388b0b12 100644 --- a/tests/regress/Makefile +++ b/tests/regress/Makefile @@ -37,6 +37,13 @@ TESTS += mips_branch_likely_issue TESTS += hook_extrainvoke TESTS += sysenter_hook_x86 +TESTS += memleak_x86 +TESTS += memleak_arm +TESTS += memleak_arm64 +TESTS += memleak_mips +TESTS += memleak_m68k +TESTS += memleak_sparc + all: $(TESTS) clean: diff --git a/tests/regress/memleak_arm.c b/tests/regress/memleak_arm.c new file mode 100644 index 00000000..21430795 --- /dev/null +++ b/tests/regress/memleak_arm.c @@ -0,0 +1,178 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate ARM code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3 +#define THUMB_CODE "\x83\xb0" // sub sp, #0xc + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_arm(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register + + printf("Emulate ARM code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM_REG_R0, &r0); + uc_reg_write(uc, UC_ARM_REG_R2, &r2); + uc_reg_write(uc, UC_ARM_REG_R3, &r3); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM_REG_R0, &r0); + uc_reg_read(uc, UC_ARM_REG_R1, &r1); + printf(">>> R0 = 0x%x\n", r0); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +static void test_thumb(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int sp = 0x1234; // R0 register + + printf("Emulate THUMB code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, THUMB_CODE, sizeof(THUMB_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM_REG_SP, &sp); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM_REG_SP, &sp); + printf(">>> SP = 0x%x\n", sp); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_arm(); + printf("==========================\n"); + test_thumb(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_arm64.c b/tests/regress/memleak_arm64.c new file mode 100644 index 00000000..e9b43c0e --- /dev/null +++ b/tests/regress/memleak_arm64.c @@ -0,0 +1,122 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate ARM64 code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define ARM_CODE "\xab\x01\x0f\x8b" // add x11, x13, x15 + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_arm64(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int64_t x11 = 0x1234; // X11 register + int64_t x13 = 0x6789; // X13 register + int64_t x15 = 0x3333; // X15 register + + printf("Emulate ARM64 code\n"); + + // Initialize emulator in ARM mode + err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_ARM64_REG_X11, &x11); + uc_reg_write(uc, UC_ARM64_REG_X13, &x13); + uc_reg_write(uc, UC_ARM64_REG_X15, &x15); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_ARM64_REG_X11, &x11); + printf(">>> X11 = 0x%" PRIx64 "\n", x11); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + while(1) { + test_arm64(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_m68k.c b/tests/regress/memleak_m68k.c new file mode 100644 index 00000000..8504daf1 --- /dev/null +++ b/tests/regress/memleak_m68k.c @@ -0,0 +1,185 @@ +/* Unicorn Emulator Engine */ +/* By Loi Anh Tuan, 2015 */ + +/* Sample code to demonstrate how to emulate m68k code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + +// code to be emulated +#define M68K_CODE "\x76\xed" // movq #-19, %d3 + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_m68k(void) +{ + uc_engine *uc; + uc_hook trace1, trace2; + uc_err err; + + int d0 = 0x0000; // d0 data register + int d1 = 0x0000; // d1 data register + int d2 = 0x0000; // d2 data register + int d3 = 0x0000; // d3 data register + int d4 = 0x0000; // d4 data register + int d5 = 0x0000; // d5 data register + int d6 = 0x0000; // d6 data register + int d7 = 0x0000; // d7 data register + + int a0 = 0x0000; // a0 address register + int a1 = 0x0000; // a1 address register + int a2 = 0x0000; // a2 address register + int a3 = 0x0000; // a3 address register + int a4 = 0x0000; // a4 address register + int a5 = 0x0000; // a5 address register + int a6 = 0x0000; // a6 address register + int a7 = 0x0000; // a6 address register + + int pc = 0x0000; // program counter + int sr = 0x0000; // status register + + printf("Emulate M68K code\n"); + + // Initialize emulator in M68K mode + err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, M68K_CODE, sizeof(M68K_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_M68K_REG_D0, &d0); + uc_reg_write(uc, UC_M68K_REG_D1, &d1); + uc_reg_write(uc, UC_M68K_REG_D2, &d2); + uc_reg_write(uc, UC_M68K_REG_D3, &d3); + uc_reg_write(uc, UC_M68K_REG_D4, &d4); + uc_reg_write(uc, UC_M68K_REG_D5, &d5); + uc_reg_write(uc, UC_M68K_REG_D6, &d6); + uc_reg_write(uc, UC_M68K_REG_D7, &d7); + + uc_reg_write(uc, UC_M68K_REG_A0, &a0); + uc_reg_write(uc, UC_M68K_REG_A1, &a1); + uc_reg_write(uc, UC_M68K_REG_A2, &a2); + uc_reg_write(uc, UC_M68K_REG_A3, &a3); + uc_reg_write(uc, UC_M68K_REG_A4, &a4); + uc_reg_write(uc, UC_M68K_REG_A5, &a5); + uc_reg_write(uc, UC_M68K_REG_A6, &a6); + uc_reg_write(uc, UC_M68K_REG_A7, &a7); + + uc_reg_write(uc, UC_M68K_REG_PC, &pc); + uc_reg_write(uc, UC_M68K_REG_SR, &sr); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instruction + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_M68K_REG_D0, &d0); + uc_reg_read(uc, UC_M68K_REG_D1, &d1); + uc_reg_read(uc, UC_M68K_REG_D2, &d2); + uc_reg_read(uc, UC_M68K_REG_D3, &d3); + uc_reg_read(uc, UC_M68K_REG_D4, &d4); + uc_reg_read(uc, UC_M68K_REG_D5, &d5); + uc_reg_read(uc, UC_M68K_REG_D6, &d6); + uc_reg_read(uc, UC_M68K_REG_D7, &d7); + + uc_reg_read(uc, UC_M68K_REG_A0, &a0); + uc_reg_read(uc, UC_M68K_REG_A1, &a1); + uc_reg_read(uc, UC_M68K_REG_A2, &a2); + uc_reg_read(uc, UC_M68K_REG_A3, &a3); + uc_reg_read(uc, UC_M68K_REG_A4, &a4); + uc_reg_read(uc, UC_M68K_REG_A5, &a5); + uc_reg_read(uc, UC_M68K_REG_A6, &a6); + uc_reg_read(uc, UC_M68K_REG_A7, &a7); + + uc_reg_read(uc, UC_M68K_REG_PC, &pc); + uc_reg_read(uc, UC_M68K_REG_SR, &sr); + + printf(">>> A0 = 0x%x\t\t>>> D0 = 0x%x\n", a0, d0); + printf(">>> A1 = 0x%x\t\t>>> D1 = 0x%x\n", a1, d1); + printf(">>> A2 = 0x%x\t\t>>> D2 = 0x%x\n", a2, d2); + printf(">>> A3 = 0x%x\t\t>>> D3 = 0x%x\n", a3, d3); + printf(">>> A4 = 0x%x\t\t>>> D4 = 0x%x\n", a4, d4); + printf(">>> A5 = 0x%x\t\t>>> D5 = 0x%x\n", a5, d5); + printf(">>> A6 = 0x%x\t\t>>> D6 = 0x%x\n", a6, d6); + printf(">>> A7 = 0x%x\t\t>>> D7 = 0x%x\n", a7, d7); + printf(">>> PC = 0x%x\n", pc); + printf(">>> SR = 0x%x\n", sr); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_m68k(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_mips.c b/tests/regress/memleak_mips.c new file mode 100644 index 00000000..e82a301b --- /dev/null +++ b/tests/regress/memleak_mips.c @@ -0,0 +1,171 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate Mips code (big endian) */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456; +#define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456; + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_mips_eb(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r1 = 0x6789; // R1 register + + printf("Emulate MIPS code (big-endian)\n"); + + // Initialize emulator in MIPS mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, MIPS_CODE_EB, sizeof(MIPS_CODE_EB) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_MIPS_REG_1, &r1); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_MIPS_REG_1, &r1); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +static void test_mips_el(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int r1 = 0x6789; // R1 register + + printf("===========================\n"); + printf("Emulate MIPS code (little-endian)\n"); + + // Initialize emulator in MIPS mode + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, MIPS_CODE_EL, sizeof(MIPS_CODE_EL) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_MIPS_REG_1, &r1); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing one instruction at ADDRESS with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)ADDRESS, (uint64_t)ADDRESS); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_MIPS_REG_1, &r1); + printf(">>> R1 = 0x%x\n", r1); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_mips_eb(); + test_mips_el(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_sparc.c b/tests/regress/memleak_sparc.c new file mode 100644 index 00000000..1493d24e --- /dev/null +++ b/tests/regress/memleak_sparc.c @@ -0,0 +1,125 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh, 2015 */ + +/* Sample code to demonstrate how to emulate Sparc code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + + +// code to be emulated +#define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3; +//#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); +} + +static void test_sparc(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2; + + int g1 = 0x1230; // G1 register + int g2 = 0x6789; // G2 register + int g3 = 0x5555; // G3 register + + printf("Emulate SPARC code\n"); + + // Initialize emulator in Sparc mode + err = uc_open(UC_ARCH_SPARC, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u (%s)\n", + err, uc_strerror(err)); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + uc_mem_write(uc, ADDRESS, SPARC_CODE, sizeof(SPARC_CODE) - 1); + + // initialize machine registers + uc_reg_write(uc, UC_SPARC_REG_G1, &g1); + uc_reg_write(uc, UC_SPARC_REG_G2, &g2); + uc_reg_write(uc, UC_SPARC_REG_G3, &g3); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instructions with customized callback + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_SPARC_REG_G3, &g3); + printf(">>> G3 = 0x%x\n", g3); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + // test memleak + while(1) { + test_sparc(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +} diff --git a/tests/regress/memleak_x86.c b/tests/regress/memleak_x86.c new file mode 100644 index 00000000..737f7305 --- /dev/null +++ b/tests/regress/memleak_x86.c @@ -0,0 +1,306 @@ +/* Unicorn Emulator Engine */ +/* By Nguyen Anh Quynh & Dang Hoang Vu, 2015 */ + +/* Sample code to demonstrate how to emulate X86 code */ + +// windows specific +#ifdef _MSC_VER +#include +#include +#define PRIx64 "llX" +#ifdef DYNLOAD +#include "unicorn_dynload.h" +#else // DYNLOAD +#include +#ifdef _WIN64 +#pragma comment(lib, "unicorn_staload64.lib") +#else // _WIN64 +#pragma comment(lib, "unicorn_staload.lib") +#endif // _WIN64 +#endif // DYNLOAD + +// posix specific +#else // _MSC_VER +#include +#include +#include +#endif // _MSC_VER + +// common includes +#include + + +// code to be emulated +#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx +#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop +// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" +//#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx; +#define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop +#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx +#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx + +#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx +#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx + +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" +#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" +#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al +#define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL + +// memory address where emulation starts +#define ADDRESS 0x1000000 + +// callback for tracing basic blocks +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); +} + +// callback for tracing instruction +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + int eflags; + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + + uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); + printf(">>> --- EFLAGS is 0x%x\n", eflags); + + // Uncomment below code to stop the emulation using uc_emu_stop() + // if (address == 0x1000009) + // uc_emu_stop(uc); +} + +// callback for tracing instruction +static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + uint64_t rip; + + uc_reg_read(uc, UC_X86_REG_RIP, &rip); + printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> RIP is 0x%"PRIx64 "\n", rip); + + // Uncomment below code to stop the emulation using uc_emu_stop() + // if (address == 0x1000009) + // uc_emu_stop(uc); +} + +static void hook_mem64(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, int64_t value, void *user_data) +{ + switch(type) { + default: break; + case UC_MEM_READ: + printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n", + address, size); + break; + case UC_MEM_WRITE: + printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", + address, size, value); + break; + } +} + +static void test_i386(void) +{ + uc_engine *uc; + uc_err err; + uint32_t tmp; + uc_hook trace1, trace2; + + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register + + printf("Emulate i386 code\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, X86_CODE32, sizeof(X86_CODE32) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instruction by having @begin > @end + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); + printf(">>> ECX = 0x%x\n", r_ecx); + printf(">>> EDX = 0x%x\n", r_edx); + + // read from memory + if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp))) + printf(">>> Read 4 bytes from [0x%x] = 0x%x\n", ADDRESS, tmp); + else + printf(">>> Failed to read 4 bytes from [0x%x]\n", ADDRESS); + + uc_close(uc); +} + +static void test_x86_64(void) +{ + uc_engine *uc; + uc_err err; + uc_hook trace1, trace2, trace3, trace4; + + int64_t rax = 0x71f3029efd49d41d; + int64_t rbx = 0xd87b45277f133ddb; + int64_t rcx = 0xab40d1ffd8afc461; + int64_t rdx = 0x919317b4a733f01; + int64_t rsi = 0x4c24e753a17ea358; + int64_t rdi = 0xe509a57d2571ce96; + int64_t r8 = 0xea5b108cc2b9ab1f; + int64_t r9 = 0x19ec097c8eb618c1; + int64_t r10 = 0xec45774f00c5f682; + int64_t r11 = 0xe17e9dbec8c074aa; + int64_t r12 = 0x80f86a8dc0f6d457; + int64_t r13 = 0x48288ca5671c5492; + int64_t r14 = 0x595f72f6e4017f6e; + int64_t r15 = 0x1efd97aea331cccc; + + int64_t rsp = ADDRESS + 0x200000; + + + printf("Emulate x86_64 code\n"); + + // Initialize emulator in X86-64bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_64, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // map 2MB memory for this emulation + uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); + + // write machine code to be emulated to memory + if (uc_mem_write(uc, ADDRESS, X86_CODE64, sizeof(X86_CODE64) - 1)) { + printf("Failed to write emulation code to memory, quit!\n"); + return; + } + + // initialize machine registers + uc_reg_write(uc, UC_X86_REG_RSP, &rsp); + + uc_reg_write(uc, UC_X86_REG_RAX, &rax); + uc_reg_write(uc, UC_X86_REG_RBX, &rbx); + uc_reg_write(uc, UC_X86_REG_RCX, &rcx); + uc_reg_write(uc, UC_X86_REG_RDX, &rdx); + uc_reg_write(uc, UC_X86_REG_RSI, &rsi); + uc_reg_write(uc, UC_X86_REG_RDI, &rdi); + uc_reg_write(uc, UC_X86_REG_R8, &r8); + uc_reg_write(uc, UC_X86_REG_R9, &r9); + uc_reg_write(uc, UC_X86_REG_R10, &r10); + uc_reg_write(uc, UC_X86_REG_R11, &r11); + uc_reg_write(uc, UC_X86_REG_R12, &r12); + uc_reg_write(uc, UC_X86_REG_R13, &r13); + uc_reg_write(uc, UC_X86_REG_R14, &r14); + uc_reg_write(uc, UC_X86_REG_R15, &r15); + + // tracing all basic blocks with customized callback + uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all instructions in the range [ADDRESS, ADDRESS+20] + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, (uint64_t)ADDRESS, (uint64_t)(ADDRESS+20)); + + // tracing all memory WRITE access (with @begin > @end) + uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + + // tracing all memory READ access (with @begin > @end) + uc_hook_add(uc, &trace4, UC_HOOK_MEM_READ, hook_mem64, NULL, (uint64_t)1, (uint64_t)0); + + // emulate machine code in infinite time (last param = 0), or when + // finishing all the code. + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned %u: %s\n", + err, uc_strerror(err)); + } + + // now print out some registers + printf(">>> Emulation done. Below is the CPU context\n"); + + uc_reg_read(uc, UC_X86_REG_RAX, &rax); + uc_reg_read(uc, UC_X86_REG_RBX, &rbx); + uc_reg_read(uc, UC_X86_REG_RCX, &rcx); + uc_reg_read(uc, UC_X86_REG_RDX, &rdx); + uc_reg_read(uc, UC_X86_REG_RSI, &rsi); + uc_reg_read(uc, UC_X86_REG_RDI, &rdi); + uc_reg_read(uc, UC_X86_REG_R8, &r8); + uc_reg_read(uc, UC_X86_REG_R9, &r9); + uc_reg_read(uc, UC_X86_REG_R10, &r10); + uc_reg_read(uc, UC_X86_REG_R11, &r11); + uc_reg_read(uc, UC_X86_REG_R12, &r12); + uc_reg_read(uc, UC_X86_REG_R13, &r13); + uc_reg_read(uc, UC_X86_REG_R14, &r14); + uc_reg_read(uc, UC_X86_REG_R15, &r15); + + printf(">>> RAX = 0x%" PRIx64 "\n", rax); + printf(">>> RBX = 0x%" PRIx64 "\n", rbx); + printf(">>> RCX = 0x%" PRIx64 "\n", rcx); + printf(">>> RDX = 0x%" PRIx64 "\n", rdx); + printf(">>> RSI = 0x%" PRIx64 "\n", rsi); + printf(">>> RDI = 0x%" PRIx64 "\n", rdi); + printf(">>> R8 = 0x%" PRIx64 "\n", r8); + printf(">>> R9 = 0x%" PRIx64 "\n", r9); + printf(">>> R10 = 0x%" PRIx64 "\n", r10); + printf(">>> R11 = 0x%" PRIx64 "\n", r11); + printf(">>> R12 = 0x%" PRIx64 "\n", r12); + printf(">>> R13 = 0x%" PRIx64 "\n", r13); + printf(">>> R14 = 0x%" PRIx64 "\n", r14); + printf(">>> R15 = 0x%" PRIx64 "\n", r15); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + // dynamically load shared library +#ifdef DYNLOAD + if (!uc_dyn_load(NULL, 0)) { + printf("Error dynamically loading shared library.\n"); + printf("Please check that unicorn.dll/unicorn.so is available as well as\n"); + printf("any other dependent dll/so files.\n"); + printf("The easiest way is to place them in the same directory as this app.\n"); + return 1; + } +#endif + + while(1) { + test_i386(); + test_x86_64(); + } + + // dynamically free shared library +#ifdef DYNLOAD + uc_dyn_free(); +#endif + + return 0; +}