From b2b1d0be01733d57c251d272cb77091a3eb8d88e Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sun, 10 Jan 2016 23:56:34 -0500 Subject: [PATCH 01/77] add test case demonstrating issue 351 --- tests/regress/emu_clear_errors.py | 80 +++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100755 tests/regress/emu_clear_errors.py diff --git a/tests/regress/emu_clear_errors.py b/tests/regress/emu_clear_errors.py new file mode 100755 index 00000000..4fb6b1df --- /dev/null +++ b/tests/regress/emu_clear_errors.py @@ -0,0 +1,80 @@ +#!/usr/bin/python + +from __future__ import print_function +import binascii +import regress + +from unicorn import * +from unicorn.x86_const import * + + +CODE = binascii.unhexlify(b"".join([ + b"8B 74 01 28", # mov esi, dword ptr [ecx + eax + 0x28] mapped: 0x1000 + b"03 F0", # add esi, eax 0x1004 + b"8D 45 FC", # lea eax, dword ptr [ebp - 4] 0x1006 + b"50", # push eax 0x1009 + b"6A 40", # push 0x40 0x100A + b"6A 10", # push 0x10 0x100C + b"56", # push esi 0x100E + b"FF 15 20 20 00 10" # call some address 0x100F + ]).replace(" ", "")) + + +def showpc(mu): + pc = mu.reg_read(UC_X86_REG_EIP) + print("pc: 0x%x" % (pc)) + + +class HookCodeStopEmuTest(regress.RegressTest): + def test_hook_code_stop_emu(self): + mu = Uc(UC_ARCH_X86, UC_MODE_32) + + # base of CODE + mu.mem_map(0x1000, 0x1000) + mu.mem_write(0x1000, CODE) + mu.reg_write(UC_X86_REG_EIP, 0x1000) + + # base of STACK + mu.mem_map(0x4000, 0x4000) + mu.mem_write(0x4000, "\x00" * 0x4000) + mu.reg_write(UC_X86_REG_ESP, 0x6000) + mu.reg_write(UC_X86_REG_EBP, 0x6000) + + mu.reg_write(UC_X86_REG_ECX, 0x0) + mu.reg_write(UC_X86_REG_EAX, 0x0) + + def _hook(_, access, address, length, value, context): + pc = mu.reg_read(UC_X86_REG_EIP) + print("mem unmapped: pc: %x access: %x address: %x length: %x value: %x" % ( + pc, access, address, length, value)) + mu.emu_stop() + return True + + mu.hook_add(UC_HOOK_MEM_UNMAPPED, _hook) + + # we only expect the following instruction to execute, + # and it will fail, because it accesses unmapped memory. + # mov esi, dword ptr [ecx + eax + 0x28] mapped: 0x1000 + mu.emu_start(0x1000, 0x100F) + showpc(mu) + + # now, we want to reuse the emulator, and keep executing + # from the next instruction + mu.reg_write(UC_X86_REG_EIP, 0x1004) + self.assertEqual(0x1004, mu.reg_read(UC_X86_REG_EIP)) + + # we expect the following instructions to execute + # add esi, eax 0x1004 + # lea eax, dword ptr [ebp - 4] 0x1006 + # push eax 0x1009 + # push 0x40 0x100A + # push 0x10 0x100C + # push esi 0x100E + # + # currently, a UC_ERR_READ_UNMAPPED exception is raised here + mu.emu_start(0x1004, 0x100F) + showpc(mu) + + +if __name__ == '__main__': + regress.main() From b6db70808df22937055a24b265d558327c595782 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Sun, 10 Jan 2016 23:51:11 -0800 Subject: [PATCH 02/77] add regress for #366 --- tests/regress/arm_vldr_invalid.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 tests/regress/arm_vldr_invalid.py diff --git a/tests/regress/arm_vldr_invalid.py b/tests/regress/arm_vldr_invalid.py new file mode 100755 index 00000000..febf93e7 --- /dev/null +++ b/tests/regress/arm_vldr_invalid.py @@ -0,0 +1,18 @@ +#!/usr/bin/python + +from unicorn import * +from unicorn.arm_const import * + +import regress + +class VldrPcInsn(regress.RegressTest): + + def runTest(self): + uc = Uc(UC_ARCH_ARM, UC_MODE_ARM) + uc.mem_map(0x1000, 0x1000) + uc.mem_write(0x1000, 'ed9f8a3d'.decode('hex')) # vldr s16, [pc, #244] + # this will raise invalid insn + uc.emu_start(0x1000, 0x1004) + +if __name__ == '__main__': + regress.main() From a9d4b4cfa78723e8552afb9ac6f2c76f94bc6b8f Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Mon, 11 Jan 2016 09:57:13 -0500 Subject: [PATCH 03/77] add test case in C demonstrating issue 351 --- tests/regress/emu_clear_errors.c | 146 +++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 tests/regress/emu_clear_errors.c diff --git a/tests/regress/emu_clear_errors.c b/tests/regress/emu_clear_errors.c new file mode 100644 index 00000000..9280864f --- /dev/null +++ b/tests/regress/emu_clear_errors.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include + +#include + +static int count = 1; + +bool cb_hookunmapped(uc_engine *uc, uc_mem_type type, uint64_t address, uint32_t size, int64_t value, void *user_data) { + uint32_t pc = 0; + uc_reg_read(uc, UC_X86_REG_EIP, &pc); + fprintf(stderr, "mem unmapped: 0x%x type: %x address: 0x%"PRIx64" length: %x value: %x\n", + pc, type, address, size, value); + + uc_err err = UC_ERR_OK; + err = uc_emu_stop(uc); + if (err != UC_ERR_OK) { + fprintf(stderr, "stop not ok"); + exit(0); + } + return true; +} + +char *CODE = "\x8B\x74\x01\x28" // move esi, dword ptr [ecx + eax + 0x28] + "\x0C\xF0" // add esi, eax + "\x8D\x45\xFC" // lea eax, dword ptr [ebp - 4] + "\x50" // push eax + "\x6A\x40" // push 0x40 + "\x6A\x10" // push 0x10 + "\x56" // push esi + "\xFF\x15\x20\x20\x00\x10"; // call some address + +int main() { + uc_engine *uc; + + uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_open\n", count++); + + err = uc_mem_map(uc, 0x1000, 0x1000, UC_PROT_ALL); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_mem_map: code\n", count++); + + uint8_t code[0x1000]; + memset(code, 0x0, sizeof(code)); + memcpy(code, CODE, sizeof(CODE)); + + err = uc_mem_write(uc, 0x1000, code, sizeof(code)); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_mem_write: code\n", count++); + + uint32_t eip = 0x1000; + err = uc_reg_write(uc, UC_X86_REG_EIP, &eip); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_reg_write: eip\n", count++); + + err = uc_mem_map(uc, 0x4000, 0x4000, UC_PROT_ALL); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_mem_map: stack\n", count++); + + uint8_t stack[0x4000]; + memset(stack, 0x0, sizeof(stack)); + + err = uc_mem_write(uc, 0x4000, code, sizeof(code)); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_mem_write: stack\n", count++); + + uint32_t esp = 0x6000; + err = uc_reg_write(uc, UC_X86_REG_ESP, &esp); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_reg_write: esp\n", count++); + + uint32_t ebp = 0x6000; + err = uc_reg_write(uc, UC_X86_REG_EBP, &ebp); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_reg_write: ebp\n", count++); + + uc_hook h1; + + err = uc_hook_add(uc, &h1, UC_HOOK_MEM_UNMAPPED, cb_hookunmapped, NULL); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_hook_add\n", count++); + + // this should execute only a single instruction at 0x1000, because + // that instruction accesses invalid memory. + err = uc_emu_start(uc, 0x1000, 0x100F, 0, 0); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_emu_start\n", count++); + + // yes, not necessary, but to demonstrate the UC API is working as expected + eip = 0x1004; + err = uc_reg_write(uc, UC_X86_REG_EIP, &eip); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_reg_write: eip\n", count++); + + // this should execute the remaining instructions up to (but not includign) 0x100F. + // currently, it returns an error about an unmapped read. + // seems that this error should have been returned in the previous call + // to emu_start. + err = uc_emu_start(uc, 0x1004, 0x100F, 0, 0); + if (err != UC_ERR_OK) { + fprintf(stderr, "not ok %d - %s\n", count++, uc_strerror(err)); + exit(0); + } + fprintf(stderr, "ok %d - uc_emu_start\n", count++); + + fprintf(stderr, "ok %d - Done", count++); + + return 0; +} From c9f4bd27cca3589592aa72ea3290b53e44befa3d Mon Sep 17 00:00:00 2001 From: farmdve Date: Mon, 11 Jan 2016 18:11:31 +0200 Subject: [PATCH 04/77] Reset env->invalid_error before executing a translation block. --- qemu/cpu-exec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index ca3f69ea..5a1f3798 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -92,6 +92,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq cc->cpu_exec_enter(cpu); cpu->exception_index = -1; + env->invalid_error = UC_ERR_OK; /* prepare setjmp context for exception handling */ for(;;) { From 89eac66bf7824a1df3fca8d3e3095d420d22fcd5 Mon Sep 17 00:00:00 2001 From: farmdve Date: Mon, 11 Jan 2016 18:26:23 +0200 Subject: [PATCH 05/77] Move sanity checks before uc->memory_map is called. --- uc.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/uc.c b/uc.c index 5d6f5f2c..d0e01ac4 100644 --- a/uc.c +++ b/uc.c @@ -606,26 +606,6 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per { MemoryRegion **regions; - if (size == 0) - // invalid memory mapping - return UC_ERR_ARG; - - // address cannot wrapp around - if (address + size - 1 < address) - return UC_ERR_ARG; - - // address must be aligned to uc->target_page_size - if ((address & uc->target_page_align) != 0) - return UC_ERR_ARG; - - // size must be multiple of uc->target_page_size - if ((size & uc->target_page_align) != 0) - return UC_ERR_ARG; - - // check for only valid permissions - if ((perms & ~UC_PROT_ALL) != 0) - return UC_ERR_ARG; - // this area overlaps existing mapped regions? if (memory_overlap(uc, address, size)) return UC_ERR_MAP; @@ -655,6 +635,26 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) address = uc->mem_redirect(address); } + if (size == 0) + // invalid memory mapping + return UC_ERR_ARG; + + // address cannot wrapp around + if (address + size - 1 < address) + return UC_ERR_ARG; + + // address must be aligned to uc->target_page_size + if ((address & uc->target_page_align) != 0) + return UC_ERR_ARG; + + // size must be multiple of uc->target_page_size + if ((size & uc->target_page_align) != 0) + return UC_ERR_ARG; + + // check for only valid permissions + if ((perms & ~UC_PROT_ALL) != 0) + return UC_ERR_ARG; + return mem_map(uc, address, size, perms, uc->memory_map(uc, address, size, perms)); } From e1fe63ae1321e68333154a50522722372005a74e Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 00:37:15 +0800 Subject: [PATCH 06/77] regress: fix compilation warnings for emu_clear_errors.c --- tests/regress/emu_clear_errors.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/regress/emu_clear_errors.c b/tests/regress/emu_clear_errors.c index 9280864f..36c4e745 100644 --- a/tests/regress/emu_clear_errors.c +++ b/tests/regress/emu_clear_errors.c @@ -12,7 +12,7 @@ static int count = 1; bool cb_hookunmapped(uc_engine *uc, uc_mem_type type, uint64_t address, uint32_t size, int64_t value, void *user_data) { uint32_t pc = 0; uc_reg_read(uc, UC_X86_REG_EIP, &pc); - fprintf(stderr, "mem unmapped: 0x%x type: %x address: 0x%"PRIx64" length: %x value: %x\n", + fprintf(stderr, "mem unmapped: 0x%x type: %x address: 0x%"PRIx64" length: %x value: 0x%"PRIx64"\n", pc, type, address, size, value); uc_err err = UC_ERR_OK; @@ -24,14 +24,22 @@ bool cb_hookunmapped(uc_engine *uc, uc_mem_type type, uint64_t address, uint32_t return true; } -char *CODE = "\x8B\x74\x01\x28" // move esi, dword ptr [ecx + eax + 0x28] - "\x0C\xF0" // add esi, eax - "\x8D\x45\xFC" // lea eax, dword ptr [ebp - 4] - "\x50" // push eax - "\x6A\x40" // push 0x40 - "\x6A\x10" // push 0x10 - "\x56" // push esi - "\xFF\x15\x20\x20\x00\x10"; // call some address +// move esi, dword ptr [ecx + eax + 0x28] +// add esi, eax +// lea eax, dword ptr [ebp - 4] +// push eax +// push 0x40 +// push 0x10 +// push esi +// call some address +#define CODE "\x8B\x74\x01\x28" \ + "\x0C\xF0" \ + "\x8D\x45\xFC" \ + "\x50" \ + "\x6A\x40" \ + "\x6A\x10" \ + "\x56" \ + "\xFF\x15\x20\x20\x00\x10" int main() { uc_engine *uc; From 71ad9310fc11f844bc69fb3a78aa72a49a8f8ba2 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 00:59:56 +0800 Subject: [PATCH 07/77] sanity check on arguments of uc_mem_map_ptr() --- uc.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/uc.c b/uc.c index d0e01ac4..f88a2261 100644 --- a/uc.c +++ b/uc.c @@ -628,13 +628,8 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per return UC_ERR_OK; } -UNICORN_EXPORT -uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) +static uc_err mem_map_check(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) { - if (uc->mem_redirect) { - address = uc->mem_redirect(address); - } - if (size == 0) // invalid memory mapping return UC_ERR_ARG; @@ -655,12 +650,30 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) if ((perms & ~UC_PROT_ALL) != 0) return UC_ERR_ARG; + return UC_ERR_OK; +} + +UNICORN_EXPORT +uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) +{ + uc_err res; + + if (uc->mem_redirect) { + address = uc->mem_redirect(address); + } + + res = mem_map_check(uc, address, size, perms); + if (res) + return res; + return mem_map(uc, address, size, perms, uc->memory_map(uc, address, size, perms)); } UNICORN_EXPORT uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr) { + uc_err res; + if (ptr == NULL) return UC_ERR_ARG; @@ -668,6 +681,10 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per address = uc->mem_redirect(address); } + res = mem_map_check(uc, address, size, perms); + if (res) + return res; + return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, perms, ptr)); } From 7695fb1578085c3b8fe55b3aec96e165f6a5d87a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 01:01:11 +0800 Subject: [PATCH 08/77] x86: no need to reset env->invalid_error in x86_reg_reset() as we always do that in cpu_exec() --- qemu/target-i386/unicorn.c | 1 - 1 file changed, 1 deletion(-) diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index 2280d564..11bb8232 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -58,7 +58,6 @@ void x86_reg_reset(struct uc_struct *uc) env->features[FEAT_8000_0001_ECX] = CPUID_EXT3_LAHF_LM | CPUID_EXT3_ABM | CPUID_EXT3_SKINIT | CPUID_EXT3_CR8LEG; env->features[FEAT_7_0_EBX] = CPUID_7_0_EBX_BMI1 | CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ADX | CPUID_7_0_EBX_SMAP; - env->invalid_error = UC_ERR_OK; // no error memset(env->regs, 0, sizeof(env->regs)); memset(env->segs, 0, sizeof(env->segs)); memset(env->cr, 0, sizeof(env->cr)); From 7de48f2f75176f0ae5b48b8f53a50a1ff448f73f Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 01:02:45 +0800 Subject: [PATCH 09/77] regress: add emu_clear_errors to .gitignore --- .gitignore | 1 + tests/regress/Makefile | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4578b7dc..d156a944 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,7 @@ mips_delay_slot_code_hook threaded_emu_start emu_stop_in_hook_overrun mips_branch_likely_issue +emu_clear_errors test_mem_map_ptr test_mem_high diff --git a/tests/regress/Makefile b/tests/regress/Makefile index 3f1d59a5..3de87998 100644 --- a/tests/regress/Makefile +++ b/tests/regress/Makefile @@ -36,6 +36,7 @@ TESTS += emu_stop_in_hook_overrun TESTS += mips_branch_likely_issue TESTS += hook_extrainvoke TESTS += sysenter_hook_x86 +TESTS += emu_clear_errors all: $(TESTS) From 3a8ad6f94473df48190bae54c0d11469db0a2bfc Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 01:03:44 +0800 Subject: [PATCH 10/77] java: add .class & .jar files to .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index d156a944..4f82c74a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ *.so.* *.exe *.dll +*.class +*.jar qemu/config-all-devices.mak From 2542e963a884e04a3c9ea1d7bd2932fbca01c61a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 09:39:24 +0800 Subject: [PATCH 11/77] update README --- README.md | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 52040da6..193bc785 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,34 @@ Unicorn offers some unparalleled features: Further information is available at http://www.unicorn-engine.org -Compilation ------------ - -See [COMPILE.TXT](COMPILE.TXT) file for how to compile and install Unicorn. - - License ------- This project is released under the [GPL license](COPYING). + + +Compilation & Docs +------------------ + +See [COMPILE.TXT](COMPILE.TXT) file for how to compile and install Unicorn. + +More documentation is available in [docs/README](docs/README) + + +Contact +------- + +Contact us via mailing list, email or twitter. More information is available +at http://www.unicorn-engine.org/contact/ + + +Contribute +---------- + +If you want to contribute, please pick up something from our Github issues +at https://github.com/unicorn-engine/unicorn + +We also maintain a TODO list at https://github.com/unicorn-engine/unicorn/wiki/TODO. + +[CREDITS.TXT](CREDITS.TXT) lists important contributors of our project. + From 79060210370ff6ef54a31a525670628cda0356e1 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 09:43:40 +0800 Subject: [PATCH 12/77] rename docs/README to docs/README.md --- README.md | 6 +++--- docs/{README => README.md} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename docs/{README => README.md} (100%) diff --git a/README.md b/README.md index 193bc785..50726a6e 100644 --- a/README.md +++ b/README.md @@ -29,21 +29,21 @@ Compilation & Docs See [COMPILE.TXT](COMPILE.TXT) file for how to compile and install Unicorn. -More documentation is available in [docs/README](docs/README) +More documentation is available in [docs/README.md](docs/README.md). Contact ------- Contact us via mailing list, email or twitter. More information is available -at http://www.unicorn-engine.org/contact/ +at http://www.unicorn-engine.org/contact/. Contribute ---------- If you want to contribute, please pick up something from our Github issues -at https://github.com/unicorn-engine/unicorn +at https://github.com/unicorn-engine/unicorn. We also maintain a TODO list at https://github.com/unicorn-engine/unicorn/wiki/TODO. diff --git a/docs/README b/docs/README.md similarity index 100% rename from docs/README rename to docs/README.md From a5dba24f3e42e79d939c9f3b3bfe1cabcc9d7f2b Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 09:50:17 +0800 Subject: [PATCH 13/77] more readable README.md --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 50726a6e..9164552b 100644 --- a/README.md +++ b/README.md @@ -35,17 +35,15 @@ More documentation is available in [docs/README.md](docs/README.md). Contact ------- -Contact us via mailing list, email or twitter. More information is available -at http://www.unicorn-engine.org/contact/. +[Contact us](http://www.unicorn-engine.org/contact/) via mailing list, email or twitter for any questions. Contribute ---------- -If you want to contribute, please pick up something from our Github issues -at https://github.com/unicorn-engine/unicorn. +If you want to contribute, please pick up something from our [Github issues](https://github.com/unicorn-engine/unicorn). -We also maintain a TODO list at https://github.com/unicorn-engine/unicorn/wiki/TODO. +We also maintain a list of more challenged problems in a [TODO list](https://github.com/unicorn-engine/unicorn/wiki/TODO). -[CREDITS.TXT](CREDITS.TXT) lists important contributors of our project. +[CREDITS.TXT](CREDITS.TXT) records important contributors of our project. From 97e8d9f80b51b2e27390a5ee41d5edec4bd8e352 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 12 Jan 2016 09:53:01 +0800 Subject: [PATCH 14/77] fix link to Github issues in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9164552b..942e1b8e 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Contact Contribute ---------- -If you want to contribute, please pick up something from our [Github issues](https://github.com/unicorn-engine/unicorn). +If you want to contribute, please pick up something from our [Github issues](https://github.com/unicorn-engine/unicorn/issues). We also maintain a list of more challenged problems in a [TODO list](https://github.com/unicorn-engine/unicorn/wiki/TODO). From d0125eb8bf0a8c4757c93cc1482c2ba5d5fa3a70 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 13 Jan 2016 11:35:09 +0800 Subject: [PATCH 15/77] regress: add invalid_write.py to test issue #371 --- tests/regress/invalid_write.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100755 tests/regress/invalid_write.py diff --git a/tests/regress/invalid_write.py b/tests/regress/invalid_write.py new file mode 100755 index 00000000..b37305fc --- /dev/null +++ b/tests/regress/invalid_write.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# Test callback that returns False to cancel emulation + +from __future__ import print_function +from unicorn import * +from unicorn.x86_const import * + +import regress + +X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], ecx; INC ecx; DEC edx + + +# callback for tracing invalid memory access (READ or WRITE) +def hook_mem_invalid(uc, access, address, size, value, user_data): + return False + + +class InvalidWrite(regress.RegressTest): + def test(self): + # Initialize emulator in X86-32bit mode + mu = Uc(UC_ARCH_X86, UC_MODE_32) + + # memory address where emulation starts + ADDRESS = 0x1000000 + + # map 2MB memory for this emulation + mu.mem_map(ADDRESS, 2 * 1024 * 1024) + + # write machine code to be emulated to memory + mu.mem_write(ADDRESS, X86_CODE32_MEM_WRITE) + + # initialize machine registers + mu.reg_write(UC_X86_REG_ECX, 0x1234) + mu.reg_write(UC_X86_REG_EDX, 0x7890) + + # intercept invalid memory events + mu.hook_add(UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid) + + try: + # emulation should return with error UC_ERR_WRITE_UNMAPPED + mu.emu_start(ADDRESS, ADDRESS + len(X86_CODE32_MEM_WRITE)) + except UcError as e: + self.assertEqual(e.errno, UC_ERR_WRITE_UNMAPPED) + + +if __name__ == '__main__': + regress.main() From 3d8f413ce8fc836c6b99f3954600c6ecb55b85bb Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 16 Jan 2016 16:57:17 +0800 Subject: [PATCH 16/77] new API uc_mem_regions() to retrieve the list of memory regions mapped by uc_mem_map_*() --- include/unicorn/unicorn.h | 25 +++++++++++++++++++++++++ uc.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 719cbcf6..e188ccc2 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -215,6 +215,14 @@ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, typedef bool (*uc_cb_eventmem_t)(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data); +/* Memory region mapped by uc_mem_map() and uc_mem_map_ptr() + Retrieve the list of memory regions with uc_mem_regions() +*/ +typedef struct uc_mem_region { + uint64_t begin; // begin address of the region (inclusive) + uint64_t end; // end address of the region (inclusive) + uint32_t perms; // memory permissions of the region +} uc_mem_region; /* Return combined API version & major and minor version numbers. @@ -503,6 +511,23 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); UNICORN_EXPORT uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); +/* + Retrieve all memory regions mapped by uc_mem_map() and uc_mem_map_ptr() + This API allocates memory for @regions, and user must free this memory later + by free() to avoid leaking memory. + NOTE: memory regions may be splitted by uc_mem_unmap() + + @handle: handle returned by uc_open() + @regions: pointer to an array of uc_mem_region struct. This is allocated by + Unicorn, and must be freed by user later + @count: pointer to number of struct uc_mem_region contained in @regions + + @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum + for detailed error). +*/ +UNICORN_EXPORT +uc_err uc_mem_regions(uc_engine *handle, uc_mem_region **regions, uint32_t *count); + #ifdef __cplusplus } #endif diff --git a/uc.c b/uc.c index f88a2261..b354a5fa 100644 --- a/uc.c +++ b/uc.c @@ -1138,3 +1138,31 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) { return hook_del(uc, hh); } + +UNICORN_EXPORT +uint32_t uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) +{ + uint32_t i; + uc_mem_region *r = NULL; + + *count = uc->mapped_block_count; + + if (*count) { + r = malloc(*count * sizeof(uc_mem_region)); + if (r == NULL) { + // out of memory + return UC_ERR_NOMEM; + } + } + + for (i = 0; i < *count; i++) { + r[i].begin = uc->mapped_blocks[i]->addr; + r[i].end = uc->mapped_blocks[i]->end - 1; + r[i].perms = uc->mapped_blocks[i]->perms; + } + + *regions = r; + + return UC_ERR_OK; +} + From 978f671fa5df84d8db44215e414ee31d58e6a2ec Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 16 Jan 2016 18:17:13 +0800 Subject: [PATCH 17/77] fix some comments in unicorn.h --- include/unicorn/unicorn.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index e188ccc2..4570d18c 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -480,7 +480,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per Unmap a region of emulation memory. This API deletes a memory mapping from the emulation memory space. - @handle: handle returned by uc_open() + @uc: handle returned by uc_open() @address: starting address of the memory region to be unmapped. This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. @size: size of the memory region to be modified. @@ -496,7 +496,7 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); Set memory permissions for emulation memory. This API changes permissions on an existing memory region. - @handle: handle returned by uc_open() + @uc: handle returned by uc_open() @address: starting address of the memory region to be modified. This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. @size: size of the memory region to be modified. @@ -517,7 +517,7 @@ uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t per by free() to avoid leaking memory. NOTE: memory regions may be splitted by uc_mem_unmap() - @handle: handle returned by uc_open() + @uc: handle returned by uc_open() @regions: pointer to an array of uc_mem_region struct. This is allocated by Unicorn, and must be freed by user later @count: pointer to number of struct uc_mem_region contained in @regions @@ -526,7 +526,7 @@ uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t per for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_regions(uc_engine *handle, uc_mem_region **regions, uint32_t *count); +uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count); #ifdef __cplusplus } From f5fa84d9851ce4b3cc6c2f0f217cab7fa9396a5a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 16 Jan 2016 18:31:24 +0800 Subject: [PATCH 18/77] consistent style for docs of unicorn.h --- include/unicorn/unicorn.h | 118 ++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 48 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 4570d18c..48fd1891 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -60,8 +60,10 @@ typedef size_t uc_hook; #define UC_API_MAJOR 0 #define UC_API_MINOR 9 -// Macro to create combined version which can be compared to -// result of uc_version() API. +/* + Macro to create combined version which can be compared to + result of uc_version() API. +*/ #define UC_MAKE_VERSION(major, minor) ((major << 8) + minor) // Scales to calculate timeout on microsecond unit @@ -129,27 +131,39 @@ typedef enum uc_err { } uc_err; -// Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) -// @address: address where the code is being executed -// @size: size of machine instruction(s) being executed, or 0 when size is unknown -// @user_data: user data passed to tracing APIs. +/* + Callback function for tracing code (UC_HOOK_CODE & UC_HOOK_BLOCK) + + @address: address where the code is being executed + @size: size of machine instruction(s) being executed, or 0 when size is unknown + @user_data: user data passed to tracing APIs. +*/ typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, void *user_data); -// Callback function for tracing interrupts (for uc_hook_intr()) -// @intno: interrupt number -// @user_data: user data passed to tracing APIs. +/* + Callback function for tracing interrupts (for uc_hook_intr()) + + @intno: interrupt number + @user_data: user data passed to tracing APIs. +*/ typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno, void *user_data); -// Callback function for tracing IN instruction of X86 -// @port: port number -// @size: data size (1/2/4) to be read from this port -// @user_data: user data passed to tracing APIs. +/* + Callback function for tracing IN instruction of X86 + + @port: port number + @size: data size (1/2/4) to be read from this port + @user_data: user data passed to tracing APIs. +*/ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void *user_data); -// x86's handler for OUT -// @port: port number -// @size: data size (1/2/4) to be written to this port -// @value: data value to be written to this port +/* + Callback function for OUT instruction of X86 + + @port: port number + @size: data size (1/2/4) to be written to this port + @value: data value to be written to this port +*/ typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data); // All type of memory accesses for UC_HOOK_MEM_* @@ -195,28 +209,36 @@ typedef enum uc_hook_type { // hook type for all events of illegal memory access #define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT) -// Callback function for hooking memory (UC_MEM_READ, UC_MEM_WRITE & UC_MEM_FETCH) -// @type: this memory is being READ, or WRITE -// @address: address where the code is being executed -// @size: size of data being read or written -// @value: value of data being written to memory, or irrelevant if type = READ. -// @user_data: user data passed to tracing APIs +/* + Callback function for hooking memory (UC_MEM_READ, UC_MEM_WRITE & UC_MEM_FETCH) + + @type: this memory is being READ, or WRITE + @address: address where the code is being executed + @size: size of data being read or written + @value: value of data being written to memory, or irrelevant if type = READ. + @user_data: user data passed to tracing APIs +*/ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data); -// Callback function for handling invalid memory access events (UC_MEM_*_UNMAPPED and -// UC_MEM_*PROT events) -// @type: this memory is being READ, or WRITE -// @address: address where the code is being executed -// @size: size of data being read or written -// @value: value of data being written to memory, or irrelevant if type = READ. -// @user_data: user data passed to tracing APIs -// @return: return true to continue, or false to stop program (due to invalid memory). +/* + Callback function for handling invalid memory access events (UC_MEM_*_UNMAPPED and + UC_MEM_*PROT events) + + @type: this memory is being READ, or WRITE + @address: address where the code is being executed + @size: size of data being read or written + @value: value of data being written to memory, or irrelevant if type = READ. + @user_data: user data passed to tracing APIs + + @return: return true to continue, or false to stop program (due to invalid memory). +*/ typedef bool (*uc_cb_eventmem_t)(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data); -/* Memory region mapped by uc_mem_map() and uc_mem_map_ptr() - Retrieve the list of memory regions with uc_mem_regions() +/* + Memory region mapped by uc_mem_map() and uc_mem_map_ptr() + Retrieve the list of memory regions with uc_mem_regions() */ typedef struct uc_mem_region { uint64_t begin; // begin address of the region (inclusive) @@ -264,7 +286,7 @@ bool uc_arch_supported(uc_arch arch); @uc: pointer to uc_engine, which will be updated at return time @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc); @@ -279,7 +301,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc); @uc: pointer to a handle returned by uc_open() @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_close(uc_engine *uc); @@ -301,7 +323,7 @@ uc_err uc_errno(uc_engine *uc); @code: error code (see UC_ERR_* above) @return: returns a pointer to a string that describes the error code - passed in the argument @code + passed in the argument @code */ UNICORN_EXPORT const char *uc_strerror(uc_err code); @@ -314,7 +336,7 @@ const char *uc_strerror(uc_err code); @value: pointer to the value that will set to register @regid @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_reg_write(uc_engine *uc, int regid, const void *value); @@ -327,7 +349,7 @@ uc_err uc_reg_write(uc_engine *uc, int regid, const void *value); @value: pointer to a variable storing the register value. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value); @@ -343,7 +365,7 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value); NOTE: @bytes must be big enough to contain @size bytes. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size); @@ -359,7 +381,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t s NOTE: @bytes must be big enough to contain @size bytes. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); @@ -376,7 +398,7 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); we will emulate all the code available, until the code is finished. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count); @@ -389,7 +411,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t time @uc: handle returned by uc_open() @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc); @@ -407,7 +429,7 @@ uc_err uc_emu_stop(uc_engine *uc); @...: variable arguments (depending on @type) @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...); @@ -422,7 +444,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *u @hh: handle returned by uc_hook_add() @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh); @@ -449,7 +471,7 @@ typedef enum uc_prot { or this will return with UC_ERR_ARG error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); @@ -471,7 +493,7 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr); @@ -487,7 +509,7 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); @@ -506,7 +528,7 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); or this will return with UC_ERR_ARG error. @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum - for detailed error). + for detailed error). */ UNICORN_EXPORT uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); From f0dac63b69736577785b29ff318d490f638e67a4 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 16 Jan 2016 18:05:32 -0500 Subject: [PATCH 19/77] In response to issue #364, a unit test case has been created for exercising proper flushing of the instruction translation cache. --- tests/unit/Makefile | 5 +- tests/unit/test_tb_x86.c | 301 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_tb_x86.c diff --git a/tests/unit/Makefile b/tests/unit/Makefile index e70c8071..b261da4d 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -4,7 +4,8 @@ CFLAGS += -L ../../ CFLAGS += -lcmocka -lunicorn CFLAGS += -I ../../include -ALL_TESTS = test_sanity test_x86 test_mem_map test_mem_high test_mem_map_ptr +ALL_TESTS = test_sanity test_x86 test_mem_map test_mem_high test_mem_map_ptr \ + test_tb_x86 .PHONY: all all: ${ALL_TESTS} @@ -21,12 +22,14 @@ test: ${ALL_TESTS} ./test_mem_map ./test_mem_map_ptr ./test_mem_high + ./test_tb_x86 test_sanity: test_sanity.c test_x86: test_x86.c test_mem_map: test_mem_map.c test_mem_map_ptr: test_mem_map_ptr.c test_mem_high: test_mem_high.c +test_tb_x86: test_tb_x86.c ${ALL_TESTS}: ${CC} ${CFLAGS} -o $@ $^ diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c new file mode 100644 index 00000000..ce5eb75e --- /dev/null +++ b/tests/unit/test_tb_x86.c @@ -0,0 +1,301 @@ +/** + * Unicorn x86_32 self-modifying unit test + * + * This test demonstrates the flushing of instruction translation cache + * after a self-modification of Intel's x8's "IMUL Gv,Ev,Ib" instruction. + */ +#include "unicorn_test.h" +#include +#include +#include + + +// Demostration of a self-modifying "IMUL eax,mem,Ib" opcode +// And the QEMU's ability to flush the translation buffer properly + +#define MIN(a, b) (a < b? a: b) + +#define CODE_SPACE (2 * 1024 * 1024) +#define PHY_STACK_REGION (0x60000000) + +#define X86_CODE32_ALPHA_MIXED \ + "\x89\xe1\xd9\xcd\xd9\x71\xf4\x5d\x55\x59\x49\x49\x49\x49\x49\x49" \ + "\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x58" \ + "\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30" \ + "\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49\x51\x51\x51\x52" \ + "\x47\x33\x47\x34\x51\x55\x51\x56\x50\x47\x47\x38\x47\x39\x50\x4a" \ + "\x50\x4b\x50\x4c\x50\x4d\x50\x4e\x50\x4f\x50\x50\x50\x31\x47\x42" \ + "\x47\x42\x50\x34\x50\x5a\x50\x45\x51\x52\x46\x32\x47\x31\x50\x4d" \ + "\x51\x51\x50\x4e\x41\x41" + + +/* Called before every test to set up a new instance */ +static int setup(void **state) +{ + uc_engine *uc; + + uc_assert_success(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + + *state = uc; + return 0; +} + + +/* Called after every test to clean up */ +static int teardown(void **state) +{ + uc_engine *uc = *state; + + uc_assert_success(uc_close(uc)); + + *state = NULL; + return 0; +} + + + +static void dump_stack_mem(uc_engine *uc) +{ + uint8_t tmp[256]; + uint32_t size; + + size = sizeof(X86_CODE32_ALPHA_MIXED); + if (size > 255) size = 255; + if (!uc_mem_read(uc, PHY_STACK_REGION, tmp, size)) + { + uint32_t i; + + printf("Stack region dump"); + for (i=0; i Date: Sun, 17 Jan 2016 10:06:00 +0800 Subject: [PATCH 20/77] unit: fix some compilation warnings in test_tb_x86.c --- tests/unit/test_tb_x86.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index ce5eb75e..7b51d71a 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -8,6 +8,7 @@ #include #include #include +#include // Demostration of a self-modifying "IMUL eax,mem,Ib" opcode @@ -110,7 +111,7 @@ static void hook_code32(uc_engine *uc, uint32_t tmp4[1]; uint32_t ecx; - printf("\nhook_code32: Address: %lx, Opcode Size: %d\n", address, size); + printf("\nhook_code32: Address: %"PRIx64", Opcode Size: %d\n", address, size); size = MIN(sizeof(tmp), size); if (!uc_mem_read(uc, address, tmp, size)) { @@ -202,7 +203,7 @@ static void hook_mem32(uc_engine *uc, ctype = '?'; if (type == 16) ctype = 'R'; if (type == 17) ctype = 'W'; - printf("hook_mem32(%c): Address: 0x%lx, Size: %d, Value:0x%lx\n", ctype, address, size, value); + printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); // if (!uc_mem_read(uc, 0x6000003a, tmp, 4)) // { From 1bf85461c26c3bc27b40ff5f0cf5c93b4d53e7c9 Mon Sep 17 00:00:00 2001 From: petevine Date: Mon, 18 Jan 2016 12:47:32 +0100 Subject: [PATCH 21/77] Add getauxval.c back --- qemu/util/getauxval.c | 109 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 qemu/util/getauxval.c diff --git a/qemu/util/getauxval.c b/qemu/util/getauxval.c new file mode 100644 index 00000000..208bfa39 --- /dev/null +++ b/qemu/util/getauxval.c @@ -0,0 +1,109 @@ +/* + * QEMU access to the auxiliary vector + * + * Copyright (C) 2013 Red Hat, Inc + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu-common.h" +#include "qemu/osdep.h" + +#ifdef CONFIG_GETAUXVAL +/* Don't inline this in qemu/osdep.h, because pulling in for + the system declaration of getauxval pulls in the system , which + conflicts with qemu's version. */ + +#include + +unsigned long qemu_getauxval(unsigned long key) +{ + return getauxval(key); +} +#elif defined(__linux__) +#include "elf.h" + +/* Our elf.h doesn't contain Elf32_auxv_t and Elf64_auxv_t, which is ok because + that just makes it easier to define it properly for the host here. */ +typedef struct { + unsigned long a_type; + unsigned long a_val; +} ElfW_auxv_t; + +static const ElfW_auxv_t *auxv; + +static const ElfW_auxv_t *qemu_init_auxval(void) +{ + ElfW_auxv_t *a; + ssize_t size = 512, r, ofs; + int fd; + + /* Allocate some initial storage. Make sure the first entry is set + to end-of-list, so that we've got a valid list in case of error. */ + auxv = a = g_malloc(size); + a[0].a_type = 0; + a[0].a_val = 0; + + fd = open("/proc/self/auxv", O_RDONLY); + if (fd < 0) { + return a; + } + + /* Read the first SIZE bytes. Hopefully, this covers everything. */ + r = read(fd, a, size); + + if (r == size) { + /* Continue to expand until we do get a partial read. */ + do { + ofs = size; + size *= 2; + auxv = a = g_realloc(a, size); + r = read(fd, (char *)a + ofs, ofs); + } while (r == ofs); +} + + close(fd); + return a; +} + +unsigned long qemu_getauxval(unsigned long type) +{ + const ElfW_auxv_t *a = auxv; + + if (unlikely(a == NULL)) { + a = qemu_init_auxval(); + } + + for (; a->a_type != 0; a++) { + if (a->a_type == type) { + return a->a_val; + } + } + + return 0; +} + +#else + +unsigned long qemu_getauxval(unsigned long type) +{ + return 0; +} + +#endif From 8db7f79daf86b579868aa3320b783b9e0c2e1405 Mon Sep 17 00:00:00 2001 From: petevine Date: Mon, 18 Jan 2016 12:48:49 +0100 Subject: [PATCH 22/77] Finish adding getauxval --- qemu/util/Makefile.objs | 1 + 1 file changed, 1 insertion(+) diff --git a/qemu/util/Makefile.objs b/qemu/util/Makefile.objs index 25e6bf34..9f4021b9 100644 --- a/qemu/util/Makefile.objs +++ b/qemu/util/Makefile.objs @@ -8,3 +8,4 @@ util-obj-y += aes.o util-obj-y += qemu-option.o util-obj-y += crc32c.o util-obj-y += host-utils.o +util-obj-y += getauxval.o From d9249b91c28d936cfed58482a7d63478dbda0862 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Mon, 18 Jan 2016 20:42:45 +0800 Subject: [PATCH 23/77] add some missing symbols for ARM backend --- qemu/aarch64.h | 2 ++ qemu/arm.h | 2 ++ qemu/header_gen.py | 2 ++ qemu/m68k.h | 2 ++ qemu/mips.h | 2 ++ qemu/mips64.h | 2 ++ qemu/mips64el.h | 2 ++ qemu/mipsel.h | 2 ++ qemu/powerpc.h | 2 ++ qemu/sparc.h | 2 ++ qemu/sparc64.h | 2 ++ qemu/x86_64.h | 2 ++ 12 files changed, 24 insertions(+) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 2deac84f..0dfd1931 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H +#define use_idiv_instructions use_idiv_instructions_aarch64 +#define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64 #define helper_power_down helper_power_down_aarch64 #define check_exit_request check_exit_request_aarch64 #define address_space_unregister address_space_unregister_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index a5ae3a38..5938d7b1 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H +#define use_idiv_instructions use_idiv_instructions_arm +#define tcg_target_deposit_valid tcg_target_deposit_valid_arm #define helper_power_down helper_power_down_arm #define check_exit_request check_exit_request_arm #define address_space_unregister address_space_unregister_arm diff --git a/qemu/header_gen.py b/qemu/header_gen.py index d889247d..83fcccfb 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7,6 +7,8 @@ import sys symbols = ( + 'use_idiv_instructions', + 'tcg_target_deposit_valid', 'helper_power_down', 'check_exit_request', 'address_space_unregister', diff --git a/qemu/m68k.h b/qemu/m68k.h index f1a6712f..3b5455eb 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H +#define use_idiv_instructions use_idiv_instructions_m68k +#define tcg_target_deposit_valid tcg_target_deposit_valid_m68k #define helper_power_down helper_power_down_m68k #define check_exit_request check_exit_request_m68k #define address_space_unregister address_space_unregister_m68k diff --git a/qemu/mips.h b/qemu/mips.h index ed7e86d1..f441daaa 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H +#define use_idiv_instructions use_idiv_instructions_mips +#define tcg_target_deposit_valid tcg_target_deposit_valid_mips #define helper_power_down helper_power_down_mips #define check_exit_request check_exit_request_mips #define address_space_unregister address_space_unregister_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 96ff3baa..e408f320 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H +#define use_idiv_instructions use_idiv_instructions_mips64 +#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64 #define helper_power_down helper_power_down_mips64 #define check_exit_request check_exit_request_mips64 #define address_space_unregister address_space_unregister_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 60315919..0995c023 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H +#define use_idiv_instructions use_idiv_instructions_mips64el +#define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el #define helper_power_down helper_power_down_mips64el #define check_exit_request check_exit_request_mips64el #define address_space_unregister address_space_unregister_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 54c454f8..70623980 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H +#define use_idiv_instructions use_idiv_instructions_mipsel +#define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel #define helper_power_down helper_power_down_mipsel #define check_exit_request check_exit_request_mipsel #define address_space_unregister address_space_unregister_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 7cd2c00d..cf72f56c 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H +#define use_idiv_instructions use_idiv_instructions_powerpc +#define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc #define helper_power_down helper_power_down_powerpc #define check_exit_request check_exit_request_powerpc #define address_space_unregister address_space_unregister_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index c30dd375..86139dd5 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H +#define use_idiv_instructions use_idiv_instructions_sparc +#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc #define helper_power_down helper_power_down_sparc #define check_exit_request check_exit_request_sparc #define address_space_unregister address_space_unregister_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index c7824ebf..e35b3a6f 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H +#define use_idiv_instructions use_idiv_instructions_sparc64 +#define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64 #define helper_power_down helper_power_down_sparc64 #define check_exit_request check_exit_request_sparc64 #define address_space_unregister address_space_unregister_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 340e4e08..a692a8d6 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1,6 +1,8 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H +#define use_idiv_instructions use_idiv_instructions_x86_64 +#define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64 #define helper_power_down helper_power_down_x86_64 #define check_exit_request check_exit_request_x86_64 #define address_space_unregister address_space_unregister_x86_64 From 3b52af4fbd736b9e4d8c54f91c6c8c3ad28cf0d9 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Mon, 18 Jan 2016 23:53:50 +0800 Subject: [PATCH 24/77] avoid confusion between macro & variable use_idiv_instructions (ARM backend) --- qemu/aarch64.h | 2 +- qemu/arm.h | 2 +- qemu/header_gen.py | 2 +- qemu/m68k.h | 2 +- qemu/mips.h | 2 +- qemu/mips64.h | 2 +- qemu/mips64el.h | 2 +- qemu/mipsel.h | 2 +- qemu/powerpc.h | 2 +- qemu/sparc.h | 2 +- qemu/sparc64.h | 2 +- qemu/tcg/arm/tcg-target.c | 4 ++-- qemu/tcg/arm/tcg-target.h | 3 ++- qemu/x86_64.h | 2 +- 14 files changed, 16 insertions(+), 15 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 0dfd1931..7c0b593f 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H -#define use_idiv_instructions use_idiv_instructions_aarch64 +#define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64 #define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64 #define helper_power_down helper_power_down_aarch64 #define check_exit_request check_exit_request_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index 5938d7b1..fd18ecfa 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H -#define use_idiv_instructions use_idiv_instructions_arm +#define use_idiv_instructions_rt use_idiv_instructions_rt_arm #define tcg_target_deposit_valid tcg_target_deposit_valid_arm #define helper_power_down helper_power_down_arm #define check_exit_request check_exit_request_arm diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 83fcccfb..18abed71 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7,7 +7,7 @@ import sys symbols = ( - 'use_idiv_instructions', + 'use_idiv_instructions_rt', 'tcg_target_deposit_valid', 'helper_power_down', 'check_exit_request', diff --git a/qemu/m68k.h b/qemu/m68k.h index 3b5455eb..368c49ab 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H -#define use_idiv_instructions use_idiv_instructions_m68k +#define use_idiv_instructions_rt use_idiv_instructions_rt_m68k #define tcg_target_deposit_valid tcg_target_deposit_valid_m68k #define helper_power_down helper_power_down_m68k #define check_exit_request check_exit_request_m68k diff --git a/qemu/mips.h b/qemu/mips.h index f441daaa..1ef669f0 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H -#define use_idiv_instructions use_idiv_instructions_mips +#define use_idiv_instructions_rt use_idiv_instructions_rt_mips #define tcg_target_deposit_valid tcg_target_deposit_valid_mips #define helper_power_down helper_power_down_mips #define check_exit_request check_exit_request_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index e408f320..2d8328a7 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H -#define use_idiv_instructions use_idiv_instructions_mips64 +#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64 #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64 #define helper_power_down helper_power_down_mips64 #define check_exit_request check_exit_request_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 0995c023..f2cd15cd 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H -#define use_idiv_instructions use_idiv_instructions_mips64el +#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el #define helper_power_down helper_power_down_mips64el #define check_exit_request check_exit_request_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 70623980..e3ee9cde 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H -#define use_idiv_instructions use_idiv_instructions_mipsel +#define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel #define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel #define helper_power_down helper_power_down_mipsel #define check_exit_request check_exit_request_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index cf72f56c..e450421e 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H -#define use_idiv_instructions use_idiv_instructions_powerpc +#define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc #define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc #define helper_power_down helper_power_down_powerpc #define check_exit_request check_exit_request_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 86139dd5..4f719a70 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H -#define use_idiv_instructions use_idiv_instructions_sparc +#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc #define helper_power_down helper_power_down_sparc #define check_exit_request check_exit_request_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index e35b3a6f..7dd7376c 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H -#define use_idiv_instructions use_idiv_instructions_sparc64 +#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64 #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64 #define helper_power_down helper_power_down_sparc64 #define check_exit_request check_exit_request_sparc64 diff --git a/qemu/tcg/arm/tcg-target.c b/qemu/tcg/arm/tcg-target.c index cabbd1f1..93dfaab3 100644 --- a/qemu/tcg/arm/tcg-target.c +++ b/qemu/tcg/arm/tcg-target.c @@ -57,7 +57,7 @@ static int arm_arch = __ARM_ARCH; #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) #ifndef use_idiv_instructions -bool use_idiv_instructions; +bool use_idiv_instructions_rt; #endif /* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */ @@ -1984,7 +1984,7 @@ static void tcg_target_init(TCGContext *s) #ifndef use_idiv_instructions { unsigned long hwcap = qemu_getauxval(AT_HWCAP); - use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0; + use_idiv_instructions_rt = (hwcap & HWCAP_ARM_IDIVA) != 0; } #endif if (__ARM_ARCH < 7) { diff --git a/qemu/tcg/arm/tcg-target.h b/qemu/tcg/arm/tcg-target.h index 1c719e28..a6ea9763 100644 --- a/qemu/tcg/arm/tcg-target.h +++ b/qemu/tcg/arm/tcg-target.h @@ -52,7 +52,8 @@ typedef enum { #ifdef __ARM_ARCH_EXT_IDIV__ #define use_idiv_instructions 1 #else -extern bool use_idiv_instructions; +extern bool use_idiv_instructions_rt; +#define use_idiv_instructions use_idiv_instructions_rt #endif diff --git a/qemu/x86_64.h b/qemu/x86_64.h index a692a8d6..deee37e8 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1,7 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H -#define use_idiv_instructions use_idiv_instructions_x86_64 +#define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64 #define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64 #define helper_power_down helper_power_down_x86_64 #define check_exit_request check_exit_request_x86_64 From 839ef672b0737dbbe72ab6cd971b307d200d5e2b Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 19 Jan 2016 00:19:28 +0800 Subject: [PATCH 25/77] only declare use_idiv_instructions_rt when __ARM_ARCH_EXT_IDIV__ is not defined --- qemu/tcg/arm/tcg-target.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/tcg/arm/tcg-target.c b/qemu/tcg/arm/tcg-target.c index 93dfaab3..17289d92 100644 --- a/qemu/tcg/arm/tcg-target.c +++ b/qemu/tcg/arm/tcg-target.c @@ -56,7 +56,7 @@ static int arm_arch = __ARM_ARCH; #define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6) #define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) -#ifndef use_idiv_instructions +#ifndef __ARM_ARCH_EXT_IDIV__ bool use_idiv_instructions_rt; #endif @@ -1981,7 +1981,7 @@ static void tcg_target_init(TCGContext *s) { /* Only probe for the platform and capabilities if we havn't already determined maximum values at compile time. */ -#ifndef use_idiv_instructions +#ifndef __ARM_ARCH_EXT_IDIV__ { unsigned long hwcap = qemu_getauxval(AT_HWCAP); use_idiv_instructions_rt = (hwcap & HWCAP_ARM_IDIVA) != 0; From 69b784fc45fc134438e75e4a8f4b0c56015e509a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 19 Jan 2016 09:11:25 +0800 Subject: [PATCH 26/77] samples: LDFLAGS += -lpthread. this fixes issue 382 --- samples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Makefile b/samples/Makefile index 0904512a..02a1f66d 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -27,7 +27,7 @@ LIBDIR = $(BUILDDIR) endif CFLAGS += -Wall -I$(INCDIR) -LDFLAGS += -L$(LIBDIR) -l$(LIBNAME) +LDFLAGS += -lpthread -L$(LIBDIR) -l$(LIBNAME) LDFLAGS_STATIC += $(UNICORN_DEP_LIBS_STATIC) ifeq ($(CROSS),) From ca8c66d9f8100089877928c29b0d81b087c4ca39 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 19 Jan 2016 13:34:08 +0800 Subject: [PATCH 27/77] compile with -j4 option to reduce memory usage (issue #209) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4d7e4e73..c4cb31c7 100644 --- a/Makefile +++ b/Makefile @@ -222,7 +222,7 @@ else endif compile_lib: config qemu/config-host.h-timestamp - rm -rf lib$(LIBNAME)* $(LIBNAME)*.lib $(LIBNAME)*.dll cyg$(LIBNAME)*.dll && cd qemu && $(MAKE) -j 8 + rm -rf lib$(LIBNAME)* $(LIBNAME)*.lib $(LIBNAME)*.dll cyg$(LIBNAME)*.dll && cd qemu && $(MAKE) -j 4 $(MAKE) unicorn cd samples && $(MAKE) clean From 07bd81bda63798d78e2c163b0633d49d2c3061cb Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 11:29:22 +0800 Subject: [PATCH 28/77] do not redefine tb_set_jmp_target1. this partly fixes issue #387 --- qemu/aarch64.h | 1 - qemu/arm.h | 1 - qemu/header_gen.py | 1 - qemu/m68k.h | 1 - qemu/mips.h | 1 - qemu/mips64.h | 1 - qemu/mips64el.h | 1 - qemu/mipsel.h | 1 - qemu/powerpc.h | 1 - qemu/sparc.h | 1 - qemu/sparc64.h | 1 - qemu/x86_64.h | 1 - 12 files changed, 12 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 7c0b593f..af24351f 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_aarch64 #define tb_reset_jump tb_reset_jump_aarch64 #define tb_set_jmp_target tb_set_jmp_target_aarch64 -#define tb_set_jmp_target1 tb_set_jmp_target1_aarch64 #define tcg_accel_class_init tcg_accel_class_init_aarch64 #define tcg_accel_type tcg_accel_type_aarch64 #define tcg_add_param_i32 tcg_add_param_i32_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index fd18ecfa..ad95d316 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_arm #define tb_reset_jump tb_reset_jump_arm #define tb_set_jmp_target tb_set_jmp_target_arm -#define tb_set_jmp_target1 tb_set_jmp_target1_arm #define tcg_accel_class_init tcg_accel_class_init_arm #define tcg_accel_type tcg_accel_type_arm #define tcg_add_param_i32 tcg_add_param_i32_arm diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 18abed71..e9442ecb 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -2816,7 +2816,6 @@ symbols = ( 'tb_phys_invalidate', 'tb_reset_jump', 'tb_set_jmp_target', - 'tb_set_jmp_target1', 'tcg_accel_class_init', 'tcg_accel_type', 'tcg_add_param_i32', diff --git a/qemu/m68k.h b/qemu/m68k.h index 368c49ab..47420bd2 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_m68k #define tb_reset_jump tb_reset_jump_m68k #define tb_set_jmp_target tb_set_jmp_target_m68k -#define tb_set_jmp_target1 tb_set_jmp_target1_m68k #define tcg_accel_class_init tcg_accel_class_init_m68k #define tcg_accel_type tcg_accel_type_m68k #define tcg_add_param_i32 tcg_add_param_i32_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 1ef669f0..b3c31bbb 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_mips #define tb_reset_jump tb_reset_jump_mips #define tb_set_jmp_target tb_set_jmp_target_mips -#define tb_set_jmp_target1 tb_set_jmp_target1_mips #define tcg_accel_class_init tcg_accel_class_init_mips #define tcg_accel_type tcg_accel_type_mips #define tcg_add_param_i32 tcg_add_param_i32_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 2d8328a7..d3938116 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_mips64 #define tb_reset_jump tb_reset_jump_mips64 #define tb_set_jmp_target tb_set_jmp_target_mips64 -#define tb_set_jmp_target1 tb_set_jmp_target1_mips64 #define tcg_accel_class_init tcg_accel_class_init_mips64 #define tcg_accel_type tcg_accel_type_mips64 #define tcg_add_param_i32 tcg_add_param_i32_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index f2cd15cd..362bb30d 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_mips64el #define tb_reset_jump tb_reset_jump_mips64el #define tb_set_jmp_target tb_set_jmp_target_mips64el -#define tb_set_jmp_target1 tb_set_jmp_target1_mips64el #define tcg_accel_class_init tcg_accel_class_init_mips64el #define tcg_accel_type tcg_accel_type_mips64el #define tcg_add_param_i32 tcg_add_param_i32_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index e3ee9cde..5e71bef9 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_mipsel #define tb_reset_jump tb_reset_jump_mipsel #define tb_set_jmp_target tb_set_jmp_target_mipsel -#define tb_set_jmp_target1 tb_set_jmp_target1_mipsel #define tcg_accel_class_init tcg_accel_class_init_mipsel #define tcg_accel_type tcg_accel_type_mipsel #define tcg_add_param_i32 tcg_add_param_i32_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index e450421e..22dad739 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_powerpc #define tb_reset_jump tb_reset_jump_powerpc #define tb_set_jmp_target tb_set_jmp_target_powerpc -#define tb_set_jmp_target1 tb_set_jmp_target1_powerpc #define tcg_accel_class_init tcg_accel_class_init_powerpc #define tcg_accel_type tcg_accel_type_powerpc #define tcg_add_param_i32 tcg_add_param_i32_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 4f719a70..7c78c2e2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_sparc #define tb_reset_jump tb_reset_jump_sparc #define tb_set_jmp_target tb_set_jmp_target_sparc -#define tb_set_jmp_target1 tb_set_jmp_target1_sparc #define tcg_accel_class_init tcg_accel_class_init_sparc #define tcg_accel_type tcg_accel_type_sparc #define tcg_add_param_i32 tcg_add_param_i32_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 7dd7376c..681a7086 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_sparc64 #define tb_reset_jump tb_reset_jump_sparc64 #define tb_set_jmp_target tb_set_jmp_target_sparc64 -#define tb_set_jmp_target1 tb_set_jmp_target1_sparc64 #define tcg_accel_class_init tcg_accel_class_init_sparc64 #define tcg_accel_type tcg_accel_type_sparc64 #define tcg_add_param_i32 tcg_add_param_i32_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index deee37e8..7f00e8b4 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -2810,7 +2810,6 @@ #define tb_phys_invalidate tb_phys_invalidate_x86_64 #define tb_reset_jump tb_reset_jump_x86_64 #define tb_set_jmp_target tb_set_jmp_target_x86_64 -#define tb_set_jmp_target1 tb_set_jmp_target1_x86_64 #define tcg_accel_class_init tcg_accel_class_init_x86_64 #define tcg_accel_type tcg_accel_type_x86_64 #define tcg_add_param_i32 tcg_add_param_i32_x86_64 From 3000ca6abff85d763292cfb1c7b53d911163a035 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 11:33:28 +0800 Subject: [PATCH 29/77] arm64: fix the access to tcg_op_defs[] in arm64 backend (issue #387) --- qemu/tcg/aarch64/tcg-target.c | 2 +- tests/unit/test_tb_x86.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/qemu/tcg/aarch64/tcg-target.c b/qemu/tcg/aarch64/tcg-target.c index 6dff1756..ce8360f6 100644 --- a/qemu/tcg/aarch64/tcg-target.c +++ b/qemu/tcg/aarch64/tcg-target.c @@ -1241,7 +1241,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, { /* 99% of the time, we can signal the use of extension registers by looking to see if the opcode handles 64-bit data. */ - TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; + TCGType ext = (s->tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; /* Hoist the loads of the most common arguments. */ TCGArg a0 = args[0]; diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index 7b51d71a..2edfb270 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -201,9 +201,14 @@ static void hook_mem32(uc_engine *uc, //uint32_t tmp[1]; ctype = '?'; - if (type == 16) ctype = 'R'; - if (type == 17) ctype = 'W'; - printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); + if (type == UC_MEM_READ) { + ctype = 'R'; + printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d \n", ctype, address, size); + } + if (type == UC_MEM_WRITE) { + ctype = 'W'; + printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); + } // if (!uc_mem_read(uc, 0x6000003a, tmp, 4)) // { From 840eb54f055bc23c71f59cb916533751f7198cc8 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 11:33:36 +0800 Subject: [PATCH 30/77] Revert "arm64: fix the access to tcg_op_defs[] in arm64 backend (issue #387)" This reverts commit 3000ca6abff85d763292cfb1c7b53d911163a035. --- qemu/tcg/aarch64/tcg-target.c | 2 +- tests/unit/test_tb_x86.c | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/qemu/tcg/aarch64/tcg-target.c b/qemu/tcg/aarch64/tcg-target.c index ce8360f6..6dff1756 100644 --- a/qemu/tcg/aarch64/tcg-target.c +++ b/qemu/tcg/aarch64/tcg-target.c @@ -1241,7 +1241,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, { /* 99% of the time, we can signal the use of extension registers by looking to see if the opcode handles 64-bit data. */ - TCGType ext = (s->tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; + TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; /* Hoist the loads of the most common arguments. */ TCGArg a0 = args[0]; diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index 2edfb270..7b51d71a 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -201,14 +201,9 @@ static void hook_mem32(uc_engine *uc, //uint32_t tmp[1]; ctype = '?'; - if (type == UC_MEM_READ) { - ctype = 'R'; - printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d \n", ctype, address, size); - } - if (type == UC_MEM_WRITE) { - ctype = 'W'; - printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); - } + if (type == 16) ctype = 'R'; + if (type == 17) ctype = 'W'; + printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); // if (!uc_mem_read(uc, 0x6000003a, tmp, 4)) // { From 3eb51116b957c8cae798bab9f11145f078f7f4e5 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 11:35:01 +0800 Subject: [PATCH 31/77] arm64: fix the access to tcg_op_defs[] in arm64 backend (issue #387) --- qemu/tcg/aarch64/tcg-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu/tcg/aarch64/tcg-target.c b/qemu/tcg/aarch64/tcg-target.c index 6dff1756..ce8360f6 100644 --- a/qemu/tcg/aarch64/tcg-target.c +++ b/qemu/tcg/aarch64/tcg-target.c @@ -1241,7 +1241,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, { /* 99% of the time, we can signal the use of extension registers by looking to see if the opcode handles 64-bit data. */ - TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; + TCGType ext = (s->tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0; /* Hoist the loads of the most common arguments. */ TCGArg a0 = args[0]; From 309abbe45370b72ffef3596d9337b2970d88cf38 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 17:11:57 +0800 Subject: [PATCH 32/77] remove qemu/config-all-disas.mak --- qemu/configure | 3 --- 1 file changed, 3 deletions(-) diff --git a/qemu/configure b/qemu/configure index 7f6d9164..65d09a3b 100755 --- a/qemu/configure +++ b/qemu/configure @@ -1520,8 +1520,6 @@ echo "PIE $pie" config_host_mak="config-host.mak" -echo "# Automatically generated by configure - do not modify" >config-all-disas.mak - echo "# Automatically generated by configure - do not modify" > $config_host_mak echo >> $config_host_mak @@ -1905,7 +1903,6 @@ ldflags="" if test "$tcg_interpreter" = "yes" ; then echo "CONFIG_TCI_DIS=y" >> $config_target_mak - echo "CONFIG_TCI_DIS=y" >> config-all-disas.mak fi case "$ARCH" in From 21c614d0af0d77405bcdd7b290854e5232dfd1e8 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 20:46:26 +0800 Subject: [PATCH 33/77] properly verify ARM mode in uc_open(). see issue #389 --- uc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uc.c b/uc.c index b354a5fa..ee7d5549 100644 --- a/uc.c +++ b/uc.c @@ -184,7 +184,8 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) uc->init_arch = arm_uc_init; // verify mode - if (mode != UC_MODE_ARM && mode != UC_MODE_THUMB) { + // TODO: support Big endian, MCLASS & V8 + if (mode & (~(UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_BIG_ENDIAN | UC_MODE_LITTLE_ENDIAN))) { free(uc); return UC_ERR_MODE; } From 789971eeb9acbad7bd46251740f1b93374f2fe1c Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 00:53:34 +1100 Subject: [PATCH 34/77] Sorted uc_modes by CPU and added masks --- include/unicorn/unicorn.h | 45 +++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 48fd1891..bc2e1d29 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -86,22 +86,35 @@ typedef enum uc_arch { // Mode type typedef enum uc_mode { - UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) - UC_MODE_ARM = 0, // 32-bit ARM - UC_MODE_16 = 1 << 1, // 16-bit mode (X86) - UC_MODE_32 = 1 << 2, // 32-bit mode (X86) - UC_MODE_64 = 1 << 3, // 64-bit mode (X86, PPC) - UC_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 - UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series - UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM - UC_MODE_MICRO = 1 << 4, // MicroMips mode (MIPS) - UC_MODE_MIPS3 = 1 << 5, // Mips III ISA - UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA - UC_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc) - UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (PPC) - UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode - UC_MODE_MIPS32 = UC_MODE_32, // Mips32 ISA (Mips) - UC_MODE_MIPS64 = UC_MODE_64, // Mips64 ISA (Mips) + UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) + UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode (currently only supported by MIPS) + // arm / arm64 + UC_MODE_ARM = 0, // 32-bit ARM + UC_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 + UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) + UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) + UC_MODE_ARM_MASK = UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_MCLASS|UC_MODE_MCLASS|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + // mips + UC_MODE_MICRO = 1 << 4, // MicroMips mode + UC_MODE_MIPS3 = 1 << 5, // Mips III ISA + UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA + UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA + UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA + UC_MODE_MIPS_MASK = UC_MODE_MICRO|UC_MODE_MIPS3|UC_MODE_MIPS32R6|UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + // x86 / x64 + UC_MODE_16 = 1 << 1, // 16-bit mode + UC_MODE_32 = 1 << 2, // 32-bit mode + UC_MODE_64 = 1 << 3, // 64-bit mode + UC_MODE_X86_MASK = UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + // ppc + UC_MODE_PPC64 = 1 << 3, // 64-bit mode + UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode + UC_MODE_PPC_MASK = UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + // sparc + UC_MODE_V9 = 1 << 4, // SparcV9 mode + UC_MODE_SPARC_MASK = UC_MODE_V9|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + // m68k + UC_MODE_M68K_MASK = UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, } uc_mode; // All type of errors encountered by Unicorn API. From b48fbf752002956d1311bf0e528038bcf3254cd4 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 00:55:31 +1100 Subject: [PATCH 35/77] Sorted uc_modes by CPU and added masks --- include/unicorn/unicorn.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index bc2e1d29..ab1e65bb 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -93,7 +93,7 @@ typedef enum uc_mode { UC_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) - UC_MODE_ARM_MASK = UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_MCLASS|UC_MODE_MCLASS|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + UC_MODE_ARM_MASK = UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN, // mips UC_MODE_MICRO = 1 << 4, // MicroMips mode UC_MODE_MIPS3 = 1 << 5, // Mips III ISA @@ -105,16 +105,16 @@ typedef enum uc_mode { UC_MODE_16 = 1 << 1, // 16-bit mode UC_MODE_32 = 1 << 2, // 32-bit mode UC_MODE_64 = 1 << 3, // 64-bit mode - UC_MODE_X86_MASK = UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + UC_MODE_X86_MASK = UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN, // ppc UC_MODE_PPC64 = 1 << 3, // 64-bit mode UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode - UC_MODE_PPC_MASK = UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + UC_MODE_PPC_MASK = UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN, // sparc UC_MODE_V9 = 1 << 4, // SparcV9 mode - UC_MODE_SPARC_MASK = UC_MODE_V9|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + UC_MODE_SPARC_MASK = UC_MODE_V9|UC_MODE_LITTLE_ENDIAN, // m68k - UC_MODE_M68K_MASK = UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, + UC_MODE_M68K_MASK = UC_MODE_LITTLE_ENDIAN, } uc_mode; // All type of errors encountered by Unicorn API. From 6490b4f2a993a1d2ab07d5a5b9c9a88eb2465f3a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Fri, 22 Jan 2016 22:44:18 +0800 Subject: [PATCH 36/77] arm64: fix the issue of multiple definition of aarch64_tb_set_jmp_target (issue #387) --- qemu/aarch64.h | 1 + qemu/arm.h | 1 + qemu/header_gen.py | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/powerpc.h | 1 + qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/x86_64.h | 1 + 12 files changed, 12 insertions(+) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index af24351f..d75c06e1 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_AARCH64_H #define UNICORN_AUTOGEN_AARCH64_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_aarch64 #define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64 #define tcg_target_deposit_valid tcg_target_deposit_valid_aarch64 #define helper_power_down helper_power_down_aarch64 diff --git a/qemu/arm.h b/qemu/arm.h index ad95d316..ef850c24 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_ARM_H #define UNICORN_AUTOGEN_ARM_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_arm #define use_idiv_instructions_rt use_idiv_instructions_rt_arm #define tcg_target_deposit_valid tcg_target_deposit_valid_arm #define helper_power_down helper_power_down_arm diff --git a/qemu/header_gen.py b/qemu/header_gen.py index e9442ecb..46bab7c9 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -7,6 +7,7 @@ import sys symbols = ( + 'aarch64_tb_set_jmp_target', 'use_idiv_instructions_rt', 'tcg_target_deposit_valid', 'helper_power_down', diff --git a/qemu/m68k.h b/qemu/m68k.h index 47420bd2..8e41d569 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_M68K_H #define UNICORN_AUTOGEN_M68K_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_m68k #define use_idiv_instructions_rt use_idiv_instructions_rt_m68k #define tcg_target_deposit_valid tcg_target_deposit_valid_m68k #define helper_power_down helper_power_down_m68k diff --git a/qemu/mips.h b/qemu/mips.h index b3c31bbb..0861ed05 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS_H #define UNICORN_AUTOGEN_MIPS_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips #define use_idiv_instructions_rt use_idiv_instructions_rt_mips #define tcg_target_deposit_valid tcg_target_deposit_valid_mips #define helper_power_down helper_power_down_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index d3938116..be1a4b4c 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64_H #define UNICORN_AUTOGEN_MIPS64_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64 #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64 #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64 #define helper_power_down helper_power_down_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 362bb30d..9e144d9b 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPS64EL_H #define UNICORN_AUTOGEN_MIPS64EL_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64el #define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el #define tcg_target_deposit_valid tcg_target_deposit_valid_mips64el #define helper_power_down helper_power_down_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 5e71bef9..8fb00f62 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_MIPSEL_H #define UNICORN_AUTOGEN_MIPSEL_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mipsel #define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel #define tcg_target_deposit_valid tcg_target_deposit_valid_mipsel #define helper_power_down helper_power_down_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 22dad739..5d2f53f2 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_POWERPC_H #define UNICORN_AUTOGEN_POWERPC_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_powerpc #define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc #define tcg_target_deposit_valid tcg_target_deposit_valid_powerpc #define helper_power_down helper_power_down_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index 7c78c2e2..cf04547f 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC_H #define UNICORN_AUTOGEN_SPARC_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc #define helper_power_down helper_power_down_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 681a7086..2195b1d6 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_SPARC64_H #define UNICORN_AUTOGEN_SPARC64_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc64 #define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64 #define tcg_target_deposit_valid tcg_target_deposit_valid_sparc64 #define helper_power_down helper_power_down_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 7f00e8b4..bbb695e5 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1,6 +1,7 @@ /* Autogen header for Unicorn Engine - DONOT MODIFY */ #ifndef UNICORN_AUTOGEN_X86_64_H #define UNICORN_AUTOGEN_X86_64_H +#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_x86_64 #define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64 #define tcg_target_deposit_valid tcg_target_deposit_valid_x86_64 #define helper_power_down helper_power_down_x86_64 From 82b7599e15757fbb1990dea476233cca05a1f32a Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 09:47:29 +1100 Subject: [PATCH 37/77] Sorted uc_modes by CPU and added masks --- include/uc_priv.h | 9 +++++++++ include/unicorn/unicorn.h | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 5cdf6557..6c7362bc 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -11,6 +11,15 @@ #include "unicorn/unicorn.h" #include "hook.h" +// These are masks of supported modes for each cpu/arch. +// They should be updated when changes are made to the uc_mode enum typedef. +#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_MIPS_MASK (UC_MODE_MICRO|UC_MODE_MIPS3|UC_MODE_MIPS32R6|UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) +#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_SPARC_MASK (UC_MODE_V9|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_M68K_MASK (UC_MODE_LITTLE_ENDIAN) + #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) QTAILQ_HEAD(CPUTailQ, CPUState); diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index ab1e65bb..5150d003 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -93,28 +93,22 @@ typedef enum uc_mode { UC_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) - UC_MODE_ARM_MASK = UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN, // mips UC_MODE_MICRO = 1 << 4, // MicroMips mode UC_MODE_MIPS3 = 1 << 5, // Mips III ISA UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA - UC_MODE_MIPS_MASK = UC_MODE_MICRO|UC_MODE_MIPS3|UC_MODE_MIPS32R6|UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN, // x86 / x64 UC_MODE_16 = 1 << 1, // 16-bit mode UC_MODE_32 = 1 << 2, // 32-bit mode UC_MODE_64 = 1 << 3, // 64-bit mode - UC_MODE_X86_MASK = UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN, // ppc UC_MODE_PPC64 = 1 << 3, // 64-bit mode UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode - UC_MODE_PPC_MASK = UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN, // sparc UC_MODE_V9 = 1 << 4, // SparcV9 mode - UC_MODE_SPARC_MASK = UC_MODE_V9|UC_MODE_LITTLE_ENDIAN, // m68k - UC_MODE_M68K_MASK = UC_MODE_LITTLE_ENDIAN, } uc_mode; // All type of errors encountered by Unicorn API. From b7c43108bdc7dcb77dee7488c4ca0b3ffb53b26c Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 10:45:58 +1100 Subject: [PATCH 38/77] Started fixing uc_mode flag usage --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index ee7d5549..195f626d 100644 --- a/uc.c +++ b/uc.c @@ -185,7 +185,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) // verify mode // TODO: support Big endian, MCLASS & V8 - if (mode & (~(UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_BIG_ENDIAN | UC_MODE_LITTLE_ENDIAN))) { + if (mode & ~UC_MODE_ARM_MASK) { free(uc); return UC_ERR_MODE; } From 8763d426c2fcfa2e72050a927d85843f80dc4758 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:08:49 +1100 Subject: [PATCH 39/77] Fix uc_mode usage in source code --- bindings/msvc/samples/main.c | 2 +- include/uc_priv.h | 8 +-- include/unicorn/unicorn.h | 19 ++++--- qemu/target-arm/unicorn_arm.c | 90 +++++++++++++----------------- samples/sample_mips.c | 2 +- samples/sample_sparc.c | 2 +- tests/regress/sparc_jump_to_zero.c | 2 +- uc.c | 4 +- 8 files changed, 59 insertions(+), 70 deletions(-) diff --git a/bindings/msvc/samples/main.c b/bindings/msvc/samples/main.c index c9a24001..1539d68c 100644 --- a/bindings/msvc/samples/main.c +++ b/bindings/msvc/samples/main.c @@ -75,7 +75,7 @@ int main(int argc, char **argv, char **envp) #endif // Initialize emulator in MIPS 32bit little endian mode - err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc); + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 | UC_MODE_LITTLE_ENDIAN, &uc); if (err) { printf("Failed on uc_open() with error returned: %u\n", err); diff --git a/include/uc_priv.h b/include/uc_priv.h index 6c7362bc..12f0b8bc 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -14,11 +14,11 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the uc_mode enum typedef. #define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN) -#define UC_MODE_MIPS_MASK (UC_MODE_MICRO|UC_MODE_MIPS3|UC_MODE_MIPS32R6|UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) +#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) #define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) -#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_QPX|UC_MODE_LITTLE_ENDIAN) -#define UC_MODE_SPARC_MASK (UC_MODE_V9|UC_MODE_LITTLE_ENDIAN) -#define UC_MODE_M68K_MASK (UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_BIG_ENDIAN) +#define UC_MODE_SPARC_MASK (UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) +#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 5150d003..27bb325b 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -87,16 +87,16 @@ typedef enum uc_arch { // Mode type typedef enum uc_mode { UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) - UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode (currently only supported by MIPS) + UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode // arm / arm64 - UC_MODE_ARM = 0, // 32-bit ARM - UC_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2 + UC_MODE_ARM = 0, // Start executing in ARM mode + UC_MODE_THUMB = 1 << 4, // Start executing in THUMB mode (including Thumb-2) UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) // mips - UC_MODE_MICRO = 1 << 4, // MicroMips mode - UC_MODE_MIPS3 = 1 << 5, // Mips III ISA - UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA + UC_MODE_MICRO = 1 << 4, // MicroMips mode (currently unsupported) + UC_MODE_MIPS3 = 1 << 5, // Mips III ISA (currently unsupported) + UC_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA (currently unsupported) UC_MODE_MIPS32 = 1 << 2, // Mips32 ISA UC_MODE_MIPS64 = 1 << 3, // Mips64 ISA // x86 / x64 @@ -104,10 +104,11 @@ typedef enum uc_mode { UC_MODE_32 = 1 << 2, // 32-bit mode UC_MODE_64 = 1 << 3, // 64-bit mode // ppc - UC_MODE_PPC64 = 1 << 3, // 64-bit mode - UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode + UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) + UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) // sparc - UC_MODE_V9 = 1 << 4, // SparcV9 mode + UC_MODE_SPARC64 = 1 << 3, // 64-bit mode + UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) // m68k } uc_mode; diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 1c4004af..8c3c8f04 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -42,36 +42,30 @@ int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value) mycpu = first_cpu; - switch(uc->mode) { - default: - break; - case UC_MODE_ARM: - case UC_MODE_THUMB: - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; - else { - switch(regid) { - case UC_ARM_REG_CPSR: - *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; - break; - } + if (mode & ~UC_MODE_ARM_MASK) { + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; + else { + switch(regid) { + case UC_ARM_REG_CPSR: + *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); + break; + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; + break; } - break; + } } - return 0; } @@ -84,31 +78,25 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) { CPUState *mycpu = first_cpu; - switch(uc->mode) { - default: - break; - - case UC_MODE_ARM: - case UC_MODE_THUMB: - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; - else { - switch(regid) { - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; - break; - } + if (mode & ~UC_MODE_ARM_MASK) { + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; + else { + switch(regid) { + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; + break; } - break; + } } return 0; diff --git a/samples/sample_mips.c b/samples/sample_mips.c index 3f37b189..b27a02b1 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -105,7 +105,7 @@ static void test_mips_el(void) printf("Emulate MIPS code (little-endian)\n"); // Initialize emulator in MIPS mode - err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32, &uc); + err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_LITTLE_ENDIAN, &uc); if (err) { printf("Failed on uc_open() with error returned: %u (%s)\n", err, uc_strerror(err)); diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index e966f5af..c361232f 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -57,7 +57,7 @@ static void test_sparc(void) printf("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - err = uc_open(UC_ARCH_SPARC, UC_MODE_32, &uc); + err = uc_open(UC_ARCH_SPARC, 0, &uc); if (err) { printf("Failed on uc_open() with error returned: %u (%s)\n", err, uc_strerror(err)); diff --git a/tests/regress/sparc_jump_to_zero.c b/tests/regress/sparc_jump_to_zero.c index 99148f2f..96392f41 100644 --- a/tests/regress/sparc_jump_to_zero.c +++ b/tests/regress/sparc_jump_to_zero.c @@ -1,7 +1,7 @@ #include #define HARDWARE_ARCHITECTURE UC_ARCH_SPARC -#define HARDWARE_MODE UC_MODE_32 +#define HARDWARE_MODE 0 #define MEMORY_STARTING_ADDRESS 0x1000000 #define MEMORY_SIZE 2 * 1024 * 1024 diff --git a/uc.c b/uc.c index 195f626d..8507a862 100644 --- a/uc.c +++ b/uc.c @@ -190,7 +190,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) return UC_ERR_MODE; } - if (mode == UC_MODE_THUMB) + if (mode & UC_MODE_THUMB) uc->thumb = 1; break; #endif @@ -226,7 +226,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_SPARC case UC_ARCH_SPARC: - if (mode & UC_MODE_64) + if (mode & UC_MODE_SPARC64) uc->init_arch = sparc64_uc_init; else uc->init_arch = sparc_uc_init; From 288ef1df0aa82868b1c5c022d39131e84016e8db Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:10:12 +1100 Subject: [PATCH 40/77] Fix uc_mode usage in source code --- include/unicorn/unicorn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 27bb325b..f3468ab6 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -78,7 +78,7 @@ typedef enum uc_arch { UC_ARCH_ARM64, // ARM-64, also called AArch64 UC_ARCH_MIPS, // Mips architecture UC_ARCH_X86, // X86 architecture (including x86 & x86-64) - UC_ARCH_PPC, // PowerPC architecture + UC_ARCH_PPC, // PowerPC architecture (currently unsupported) UC_ARCH_SPARC, // Sparc architecture UC_ARCH_M68K, // M68K architecture UC_ARCH_MAX, From e9ba6ed804fa92b250337aa587597ff164960b67 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:17:59 +1100 Subject: [PATCH 41/77] Fix uc_mode usage in source code --- uc.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/uc.c b/uc.c index 8507a862..0fdf25b0 100644 --- a/uc.c +++ b/uc.c @@ -171,24 +171,33 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) break; #ifdef UNICORN_HAS_M68K case UC_ARCH_M68K: + if ((mode & ~UC_MODE_M68K_MASK) || + !(mode & UC_MODE_BIG_ENDIAN)) { + free(uc); + return UC_ERR_MODE; + } uc->init_arch = m68k_uc_init; break; #endif #ifdef UNICORN_HAS_X86 case UC_ARCH_X86: + if ((mode & ~UC_MODE_X86_MASK) || + (mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64)) { + free(uc); + return UC_ERR_MODE; + } uc->init_arch = x86_uc_init; break; #endif #ifdef UNICORN_HAS_ARM case UC_ARCH_ARM: - uc->init_arch = arm_uc_init; - - // verify mode - // TODO: support Big endian, MCLASS & V8 - if (mode & ~UC_MODE_ARM_MASK) { + if ((mode & ~UC_MODE_ARM_MASK) || + (mode & UC_MODE_BIG_ENDIAN)) { free(uc); return UC_ERR_MODE; } + uc->init_arch = arm_uc_init; if (mode & UC_MODE_THUMB) uc->thumb = 1; @@ -196,12 +205,22 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #endif #ifdef UNICORN_HAS_ARM64 case UC_ARCH_ARM64: + if ((mode & ~UC_MODE_ARM_MASK) || + (mode & UC_MODE_BIG_ENDIAN)) { + free(uc); + return UC_ERR_MODE; + } uc->init_arch = arm64_uc_init; break; #endif #if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) case UC_ARCH_MIPS: + if ((mode & ~UC_MODE_MIPS_MASK) || + !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64)) { + free(uc); + return UC_ERR_MODE; + } if (mode & UC_MODE_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS if (mode & UC_MODE_MIPS32) @@ -226,6 +245,10 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_SPARC case UC_ARCH_SPARC: + if (mode & ~UC_MODE_SPARC_MASK) { + free(uc); + return UC_ERR_MODE; + } if (mode & UC_MODE_SPARC64) uc->init_arch = sparc64_uc_init; else From 678d645b801e6c13671ba93291602440e412fe97 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:29:22 +1100 Subject: [PATCH 42/77] Fix uc_mode usage in source code --- qemu/target-arm/unicorn_arm.c | 4 ++-- uc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 8c3c8f04..6e6417b6 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -42,7 +42,7 @@ int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value) mycpu = first_cpu; - if (mode & ~UC_MODE_ARM_MASK) { + if (uc->mode & ~UC_MODE_ARM_MASK) { if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; else { @@ -78,7 +78,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) { CPUState *mycpu = first_cpu; - if (mode & ~UC_MODE_ARM_MASK) { + if (uc->mode & ~UC_MODE_ARM_MASK) { if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; else { diff --git a/uc.c b/uc.c index 0fdf25b0..5ec5e48a 100644 --- a/uc.c +++ b/uc.c @@ -183,7 +183,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) case UC_ARCH_X86: if ((mode & ~UC_MODE_X86_MASK) || (mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64)) { + !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64))) { free(uc); return UC_ERR_MODE; } @@ -217,7 +217,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) case UC_ARCH_MIPS: if ((mode & ~UC_MODE_MIPS_MASK) || - !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64)) { + !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64))) { free(uc); return UC_ERR_MODE; } From b6e9121f4879a587848d93106f5d1f897727d6f4 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 09:34:02 +0800 Subject: [PATCH 43/77] use spaces, but not tabs, for indentation --- uc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/uc.c b/uc.c index 5ec5e48a..95a9c48e 100644 --- a/uc.c +++ b/uc.c @@ -172,7 +172,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_M68K case UC_ARCH_M68K: if ((mode & ~UC_MODE_M68K_MASK) || - !(mode & UC_MODE_BIG_ENDIAN)) { + !(mode & UC_MODE_BIG_ENDIAN)) { free(uc); return UC_ERR_MODE; } @@ -182,8 +182,8 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_X86 case UC_ARCH_X86: if ((mode & ~UC_MODE_X86_MASK) || - (mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64))) { + (mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_16|UC_MODE_32|UC_MODE_64))) { free(uc); return UC_ERR_MODE; } @@ -193,7 +193,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_ARM case UC_ARCH_ARM: if ((mode & ~UC_MODE_ARM_MASK) || - (mode & UC_MODE_BIG_ENDIAN)) { + (mode & UC_MODE_BIG_ENDIAN)) { free(uc); return UC_ERR_MODE; } @@ -206,7 +206,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_ARM64 case UC_ARCH_ARM64: if ((mode & ~UC_MODE_ARM_MASK) || - (mode & UC_MODE_BIG_ENDIAN)) { + (mode & UC_MODE_BIG_ENDIAN)) { free(uc); return UC_ERR_MODE; } @@ -217,7 +217,7 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #if defined(UNICORN_HAS_MIPS) || defined(UNICORN_HAS_MIPSEL) || defined(UNICORN_HAS_MIPS64) || defined(UNICORN_HAS_MIPS64EL) case UC_ARCH_MIPS: if ((mode & ~UC_MODE_MIPS_MASK) || - !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64))) { + !(mode & (UC_MODE_MIPS32|UC_MODE_MIPS64))) { free(uc); return UC_ERR_MODE; } From d8aaa2f44caaba092a35987239a20f97dffac5b1 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:44:12 +1100 Subject: [PATCH 44/77] Fixes to runtime arm mask checks --- qemu/target-arm/unicorn_arm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 6e6417b6..c75c0244 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -42,7 +42,7 @@ int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value) mycpu = first_cpu; - if (uc->mode & ~UC_MODE_ARM_MASK) { + if (!(uc->mode & ~UC_MODE_ARM_MASK) { if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; else { @@ -78,7 +78,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) { CPUState *mycpu = first_cpu; - if (uc->mode & ~UC_MODE_ARM_MASK) { + if (!(uc->mode & ~UC_MODE_ARM_MASK) { if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; else { From b4b83ff207c7e4b848b19b7fe2cc114cc4ab4d43 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sat, 23 Jan 2016 12:56:47 +1100 Subject: [PATCH 45/77] moar fixes --- qemu/target-arm/unicorn_arm.c | 74 +++++++++++++++++------------------ 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index c75c0244..5065c0f3 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -42,27 +42,25 @@ int arm_reg_read(struct uc_struct *uc, unsigned int regid, void *value) mycpu = first_cpu; - if (!(uc->mode & ~UC_MODE_ARM_MASK) { - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; - else { - switch(regid) { - case UC_ARM_REG_CPSR: - *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; - break; - } + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0]; + else { + switch(regid) { + case UC_ARM_REG_CPSR: + *(int32_t *)value = cpsr_read(&ARM_CPU(uc, mycpu)->env); + break; + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[13]; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[14]; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + *(int32_t *)value = ARM_CPU(uc, mycpu)->env.regs[15]; + break; } } @@ -78,24 +76,22 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) { CPUState *mycpu = first_cpu; - if (!(uc->mode & ~UC_MODE_ARM_MASK) { - if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) - ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; - else { - switch(regid) { - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; - break; - } + if (regid >= UC_ARM_REG_R0 && regid <= UC_ARM_REG_R12) + ARM_CPU(uc, mycpu)->env.regs[regid - UC_ARM_REG_R0] = *(uint32_t *)value; + else { + switch(regid) { + //case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + ARM_CPU(uc, mycpu)->env.regs[13] = *(uint32_t *)value; + break; + //case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + ARM_CPU(uc, mycpu)->env.regs[14] = *(uint32_t *)value; + break; + //case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; + break; } } From 5c6c67bb3a2a01bbad09a67df487d5244ad7c474 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 10:17:42 +0800 Subject: [PATCH 46/77] regress: fix Sparc mode for sparc_reg.py --- tests/regress/sparc_reg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/regress/sparc_reg.py b/tests/regress/sparc_reg.py index 03832de9..4508efab 100755 --- a/tests/regress/sparc_reg.py +++ b/tests/regress/sparc_reg.py @@ -5,7 +5,7 @@ from unicorn.sparc_const import * PAGE_SIZE = 1 * 1024 * 1024 -uc = Uc(UC_ARCH_SPARC, UC_MODE_32) +uc = Uc(UC_ARCH_SPARC, 0) uc.reg_write(UC_SPARC_REG_SP, 100) uc.reg_write(UC_SPARC_REG_FP, 200) From ca79d11211dc5fe86226ad377630c06887d17df1 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 10:31:16 +0800 Subject: [PATCH 47/77] bindings: update constants after recent changes in unicorn.h --- bindings/const_generator.py | 3 ++- bindings/dotnet/UnicornManaged/Const/Common.fs | 14 ++++++++------ bindings/go/unicorn/unicorn_const.go | 14 ++++++++------ bindings/java/unicorn/UnicornConst.java | 14 ++++++++------ bindings/python/unicorn/unicorn_const.py | 14 ++++++++------ 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 7adafe33..826340b2 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -116,7 +116,8 @@ def gen(lang): if f[0].startswith("UC_" + prefix.upper()): if len(f) > 1 and f[1] not in ('//', '='): - print("Error: Unable to convert %s" % f) + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) continue elif len(f) > 1 and f[1] == '=': rhs = ''.join(f[2:]) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 936b6d90..f5c2230c 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -21,22 +21,24 @@ module Common = let UC_ARCH_MAX = 8 let UC_MODE_LITTLE_ENDIAN = 0 + let UC_MODE_BIG_ENDIAN = 1073741824 let UC_MODE_ARM = 0 - let UC_MODE_16 = 2 - let UC_MODE_32 = 4 - let UC_MODE_64 = 8 let UC_MODE_THUMB = 16 let UC_MODE_MCLASS = 32 let UC_MODE_V8 = 64 let UC_MODE_MICRO = 16 let UC_MODE_MIPS3 = 32 let UC_MODE_MIPS32R6 = 64 - let UC_MODE_V9 = 16 - let UC_MODE_QPX = 16 - let UC_MODE_BIG_ENDIAN = 1073741824 let UC_MODE_MIPS32 = 4 let UC_MODE_MIPS64 = 8 + let UC_MODE_16 = 2 + let UC_MODE_32 = 4 + let UC_MODE_64 = 8 + let UC_MODE_PPC64 = 8 + let UC_MODE_QPX = 16 + let UC_MODE_SPARC64 = 8 + let UC_MODE_V9 = 16 let UC_ERR_OK = 0 let UC_ERR_NOMEM = 1 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 38ba0c8b..fb44acd0 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -16,22 +16,24 @@ const ( ARCH_MAX = 8 MODE_LITTLE_ENDIAN = 0 + MODE_BIG_ENDIAN = 1073741824 MODE_ARM = 0 - MODE_16 = 2 - MODE_32 = 4 - MODE_64 = 8 MODE_THUMB = 16 MODE_MCLASS = 32 MODE_V8 = 64 MODE_MICRO = 16 MODE_MIPS3 = 32 MODE_MIPS32R6 = 64 - MODE_V9 = 16 - MODE_QPX = 16 - MODE_BIG_ENDIAN = 1073741824 MODE_MIPS32 = 4 MODE_MIPS64 = 8 + MODE_16 = 2 + MODE_32 = 4 + MODE_64 = 8 + MODE_PPC64 = 8 + MODE_QPX = 16 + MODE_SPARC64 = 8 + MODE_V9 = 16 ERR_OK = 0 ERR_NOMEM = 1 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 2bd8eabe..614326b3 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -18,22 +18,24 @@ public interface UnicornConst { public static final int UC_ARCH_MAX = 8; public static final int UC_MODE_LITTLE_ENDIAN = 0; + public static final int UC_MODE_BIG_ENDIAN = 1073741824; public static final int UC_MODE_ARM = 0; - public static final int UC_MODE_16 = 2; - public static final int UC_MODE_32 = 4; - public static final int UC_MODE_64 = 8; public static final int UC_MODE_THUMB = 16; public static final int UC_MODE_MCLASS = 32; public static final int UC_MODE_V8 = 64; public static final int UC_MODE_MICRO = 16; public static final int UC_MODE_MIPS3 = 32; public static final int UC_MODE_MIPS32R6 = 64; - public static final int UC_MODE_V9 = 16; - public static final int UC_MODE_QPX = 16; - public static final int UC_MODE_BIG_ENDIAN = 1073741824; public static final int UC_MODE_MIPS32 = 4; public static final int UC_MODE_MIPS64 = 8; + public static final int UC_MODE_16 = 2; + public static final int UC_MODE_32 = 4; + public static final int UC_MODE_64 = 8; + public static final int UC_MODE_PPC64 = 8; + public static final int UC_MODE_QPX = 16; + public static final int UC_MODE_SPARC64 = 8; + public static final int UC_MODE_V9 = 16; public static final int UC_ERR_OK = 0; public static final int UC_ERR_NOMEM = 1; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 01cde40c..c99cb816 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -14,22 +14,24 @@ UC_ARCH_M68K = 7 UC_ARCH_MAX = 8 UC_MODE_LITTLE_ENDIAN = 0 +UC_MODE_BIG_ENDIAN = 1073741824 UC_MODE_ARM = 0 -UC_MODE_16 = 2 -UC_MODE_32 = 4 -UC_MODE_64 = 8 UC_MODE_THUMB = 16 UC_MODE_MCLASS = 32 UC_MODE_V8 = 64 UC_MODE_MICRO = 16 UC_MODE_MIPS3 = 32 UC_MODE_MIPS32R6 = 64 -UC_MODE_V9 = 16 -UC_MODE_QPX = 16 -UC_MODE_BIG_ENDIAN = 1073741824 UC_MODE_MIPS32 = 4 UC_MODE_MIPS64 = 8 +UC_MODE_16 = 2 +UC_MODE_32 = 4 +UC_MODE_64 = 8 +UC_MODE_PPC64 = 8 +UC_MODE_QPX = 16 +UC_MODE_SPARC64 = 8 +UC_MODE_V9 = 16 UC_ERR_OK = 0 UC_ERR_NOMEM = 1 From 93052f6566f6ab849712ee80d6e2e04ce7cb8e0e Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Sat, 16 Jan 2016 00:44:02 -0800 Subject: [PATCH 48/77] refactor to allow multiple hooks for one type --- Makefile | 4 +- hook.c | 279 --------------------------- include/hook.h | 20 -- include/list.h | 20 ++ include/uc_priv.h | 87 ++++++--- list.c | 66 +++++++ qemu/Makefile.objs | 2 +- qemu/cpu-exec.c | 10 +- qemu/ioport.c | 62 +++--- qemu/softmmu_template.h | 194 ++++++++++++------- qemu/target-arm/translate-a64.c | 19 +- qemu/target-arm/translate.c | 35 ++-- qemu/target-i386/seg_helper.c | 28 +-- qemu/target-i386/translate.c | 38 ++-- qemu/target-m68k/translate.c | 20 +- qemu/target-mips/translate.c | 50 ++--- qemu/target-sparc/translate.c | 26 +-- qemu/tcg/i386/tcg-target.c | 2 +- qemu/translate-all.c | 2 +- uc.c | 329 ++++++++++---------------------- 20 files changed, 542 insertions(+), 751 deletions(-) delete mode 100644 hook.c delete mode 100644 include/hook.h create mode 100644 include/list.h create mode 100644 list.c diff --git a/Makefile b/Makefile index 4d7e4e73..103dd531 100644 --- a/Makefile +++ b/Makefile @@ -228,7 +228,7 @@ compile_lib: config qemu/config-host.h-timestamp unicorn: $(LIBRARY) $(ARCHIVE) -$(LIBRARY): $(UC_TARGET_OBJ) uc.o hook.o +$(LIBRARY): $(UC_TARGET_OBJ) uc.o list.o ifeq ($(UNICORN_SHARED),yes) ifeq ($(V),0) $(call log,GEN,$(LIBRARY)) @@ -241,7 +241,7 @@ ifneq (,$(LIBRARY_SYMLINK)) endif endif -$(ARCHIVE): $(UC_TARGET_OBJ) uc.o hook.o +$(ARCHIVE): $(UC_TARGET_OBJ) uc.o list.o ifeq ($(UNICORN_STATIC),yes) ifeq ($(V),0) $(call log,GEN,$(ARCHIVE)) diff --git a/hook.c b/hook.c deleted file mode 100644 index 6e575d83..00000000 --- a/hook.c +++ /dev/null @@ -1,279 +0,0 @@ -/* Unicorn Emulator Engine */ -/* By Nguyen Anh Quynh , 2015 */ - -#include "uc_priv.h" -#include "hook.h" - - -// return index for a new hook entry in hook_callbacks[] array. -// this realloc memory if needed. -size_t hook_find_new(struct uc_struct *uc) -{ - size_t i; - struct hook_struct *new; - - // find the first free slot. skip slot 0, so index > 0 - for(i = 1; i < uc->hook_size; i++) { - if (uc->hook_callbacks[i].callback == NULL) { - return i; - } - } - - // not found, so the array is full. - // we have to realloc hook_callbacks[] to contain new hooks - new = realloc(uc->hook_callbacks, - (uc->hook_size + HOOK_SIZE) * sizeof(uc->hook_callbacks[0])); - if (!new) // OOM ? - return 0; - - // reset the newly added slots - memset(new + uc->hook_size, 0, HOOK_SIZE * sizeof(uc->hook_callbacks[0])); - - uc->hook_callbacks = new; - uc->hook_size += HOOK_SIZE; - - // return the first newly allocated slot - return uc->hook_size - HOOK_SIZE; -} - -// return -1 on failure, index to hook_callbacks[] on success. -size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, void *callback, void *user_data) -{ - int i; - - // find the first free slot. skip slot 0, so index > 0 - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].hook_type = type; - uc->hook_callbacks[i].begin = begin; - uc->hook_callbacks[i].end = end; - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - - switch(type) { - default: break; - case UC_HOOK_BLOCK: - uc->hook_block = true; - if (begin > end) - uc->hook_block_idx = i; - break; - case UC_HOOK_CODE: - uc->hook_insn = true; - if (begin > end) - uc->hook_insn_idx = i; - break; - case UC_HOOK_MEM_READ: - uc->hook_mem_read = true; - if (begin > end) - uc->hook_read_idx = i; - break; - case UC_HOOK_MEM_WRITE: - uc->hook_mem_write = true; - if (begin > end) - uc->hook_write_idx = i; - break; - case UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE: - uc->hook_mem_read = true; - uc->hook_mem_write = true; - if (begin > end) { - uc->hook_read_idx = i; - uc->hook_write_idx = i; - } - break; - } - - return i; - } - - // not found - return 0; -} - -// return 0 on success, -1 on failure -uc_err hook_del(struct uc_struct *uc, uc_hook hh) -{ - if (hh == uc->hook_block_idx) { - uc->hook_block_idx = 0; - } - - if (hh == uc->hook_insn_idx) { - uc->hook_insn_idx = 0; - } - - if (hh == uc->hook_read_idx) { - uc->hook_read_idx = 0; - } - - if (hh == uc->hook_write_idx) { - uc->hook_write_idx = 0; - } - - if (hh == uc->hook_mem_read_idx) { - uc->hook_mem_read_idx = 0; - } - - if (hh == uc->hook_mem_write_idx) { - uc->hook_mem_write_idx = 0; - } - - if (hh == uc->hook_mem_fetch_idx) { - uc->hook_mem_fetch_idx = 0; - } - - if (hh == uc->hook_mem_read_prot_idx) { - uc->hook_mem_read_prot_idx = 0; - } - - if (hh == uc->hook_mem_write_prot_idx) { - uc->hook_mem_write_prot_idx = 0; - } - - if (hh == uc->hook_mem_fetch_prot_idx) { - uc->hook_mem_fetch_prot_idx = 0; - } - - if (hh == uc->hook_intr_idx) { - uc->hook_intr_idx = 0; - } - - if (hh == uc->hook_out_idx) { - uc->hook_out_idx = 0; - } - - if (hh == uc->hook_in_idx) { - uc->hook_in_idx = 0; - } - - if(hh == uc->hook_syscall_idx) { - uc->hook_syscall_idx = 0; - } - - uc->hook_callbacks[hh].callback = NULL; - uc->hook_callbacks[hh].user_data = NULL; - uc->hook_callbacks[hh].hook_type = 0; - uc->hook_callbacks[hh].begin = 0; - uc->hook_callbacks[hh].end = 0; - - return UC_ERR_OK; -} - -// return NULL on failure -static struct hook_struct *_hook_find(struct uc_struct *uc, int type, uint64_t address) -{ - int i; - - switch(type) { - default: break; - case UC_HOOK_BLOCK: - // already hooked all blocks? - if (uc->hook_block_idx) - return &uc->hook_callbacks[uc->hook_block_idx]; - break; - case UC_HOOK_CODE: - // already hooked all the code? - if (uc->hook_insn_idx) - return &uc->hook_callbacks[uc->hook_insn_idx]; - break; - case UC_HOOK_MEM_READ: - // already hooked all memory read? - if (uc->hook_read_idx) { - return &uc->hook_callbacks[uc->hook_read_idx]; - } - break; - case UC_HOOK_MEM_WRITE: - // already hooked all memory write? - if (uc->hook_write_idx) - return &uc->hook_callbacks[uc->hook_write_idx]; - break; - } - - // no trace-all callback - for(i = 1; i < uc->hook_size; i++) { - switch(type) { - default: break; - case UC_HOOK_BLOCK: - case UC_HOOK_CODE: - if (uc->hook_callbacks[i].hook_type == type) { - if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end) - return &uc->hook_callbacks[i]; - } - break; - case UC_HOOK_MEM_READ: - if (uc->hook_callbacks[i].hook_type & UC_HOOK_MEM_READ) { - if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end) - return &uc->hook_callbacks[i]; - } - break; - case UC_HOOK_MEM_WRITE: - if (uc->hook_callbacks[i].hook_type & UC_HOOK_MEM_WRITE) { - if (uc->hook_callbacks[i].begin <= address && address <= uc->hook_callbacks[i].end) - return &uc->hook_callbacks[i]; - } - break; - } - } - - // not found - return NULL; -} - - -static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data) -{ - // count this instruction - uc->emu_counter++; - - if (uc->emu_counter > uc->emu_count) - uc_emu_stop(uc); - else if (uc->hook_count_callback) - uc->hook_count_callback(uc, address, size, user_data); -} - -struct hook_struct *hook_find(struct uc_struct *uc, int type, uint64_t address) -{ - // stop executing callbacks if we already got stop request - if (uc->stop_request) - return NULL; - - // UC_HOOK_CODE is special because we may need to count instructions - if (type == UC_HOOK_CODE && uc->emu_count > 0) { - struct hook_struct *st = _hook_find(uc, type, address); - if (st) { - // prepare this struct to pass back to caller - uc->hook_count.hook_type = UC_HOOK_CODE; - uc->hook_count.begin = st->begin; - uc->hook_count.end = st->end; - uc->hook_count.callback = hook_count_cb; - uc->hook_count.user_data = st->user_data; - // save this hook callback so we can call it later - uc->hook_count_callback = st->callback; - } else { - // there is no callback, but we still need to - // handle instruction count - uc->hook_count.hook_type = UC_HOOK_CODE; - uc->hook_count.begin = 1; - uc->hook_count.end = 0; - uc->hook_count.callback = hook_count_cb; - uc->hook_count.user_data = NULL; - uc->hook_count_callback = NULL; // no callback - } - - return &(uc->hook_count); - } else - return _hook_find(uc, type, address); -} - - -// TCG helper -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data); -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data) -{ - struct uc_struct *uc = handle; - - // sync PC in CPUArchState with address - if (uc->set_pc) { - uc->set_pc(uc, address); - } - - ((uc_cb_hookcode_t)callback)(uc, address, size, user_data); -} diff --git a/include/hook.h b/include/hook.h deleted file mode 100644 index 6fbdf509..00000000 --- a/include/hook.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Unicorn Emulator Engine */ -/* By Nguyen Anh Quynh , 2015 */ - -#ifndef UC_HOOK_H -#define UC_HOOK_H - -// return -1 on failure, index to traces[] on success. -size_t hook_add(struct uc_struct *uc, int type, uint64_t begin, uint64_t end, void *callback, void *user_data); - -// return 0 on success, -1 on failure -uc_err hook_del(struct uc_struct *uc, uc_hook hh); - -// return NULL on failure -struct hook_struct *hook_find(struct uc_struct *uc, int type, uint64_t address); - -// return index of an free hook entry in hook_callbacks[] array. -// this realloc memory if needed. -size_t hook_find_new(struct uc_struct *uc); - -#endif diff --git a/include/list.h b/include/list.h new file mode 100644 index 00000000..75ec13e2 --- /dev/null +++ b/include/list.h @@ -0,0 +1,20 @@ +#ifndef UC_LLIST_H +#define UC_LLIST_H + +#include + +struct list_item { + struct list_item *next; + void *data; +}; + +struct list { + struct list_item *head, *tail; +}; + +struct list *list_new(void); +void list_clear(struct list *list); +void *list_append(struct list *list, void *data); +bool list_remove(struct list *list, void *data); + +#endif diff --git a/include/uc_priv.h b/include/uc_priv.h index 5cdf6557..a55c847e 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -9,7 +9,7 @@ #include "qemu.h" #include "unicorn/unicorn.h" -#include "hook.h" +#include "list.h" #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -60,16 +60,62 @@ typedef bool (*uc_args_int_t)(int intno); // some architecture redirect virtual memory to physical memory like Mips typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); - -struct hook_struct { - int hook_type; // uc_tracecode_type & uc_tracemem_type - uint64_t begin, end; // range of address to be monitored - void *callback; // either uc_cb_tracecode_t or uc_cb_tracemem_t +struct hook { + int type; // UC_HOOK_* + int insn; // instruction for HOOK_INSN + int refs; // reference count to free hook stored in multiple lists + uint64_t begin, end; // only trigger if PC or memory access is in this address (depends on hook type) + void *callback; // a uc_cb_* type void *user_data; }; -// extend memory to keep 32 more hooks each time -#define HOOK_SIZE 32 +// hook list offsets +// mirrors the order of uc_hook_type from include/unicorn/unicorn.h +enum uc_hook_idx { + UC_HOOK_INTR_IDX, + UC_HOOK_INSN_IDX, + UC_HOOK_CODE_IDX, + UC_HOOK_BLOCK_IDX, + UC_HOOK_MEM_READ_UNMAPPED_IDX, + UC_HOOK_MEM_WRITE_UNMAPPED_IDX, + UC_HOOK_MEM_FETCH_UNMAPPED_IDX, + UC_HOOK_MEM_READ_PROT_IDX, + UC_HOOK_MEM_WRITE_PROT_IDX, + UC_HOOK_MEM_FETCH_PROT_IDX, + UC_HOOK_MEM_READ_IDX, + UC_HOOK_MEM_WRITE_IDX, + UC_HOOK_MEM_FETCH_IDX, + + UC_HOOK_MAX, +}; + +// for loop macro to loop over hook lists +#define HOOK_FOREACH(uc, hh, idx) \ + struct list_item *cur; \ + for ( \ + cur = (uc)->hook[idx##_IDX].head; \ + cur != NULL && ((hh) = (struct hook *)cur->data) \ + /* stop excuting callbacks on stop request */ \ + && !uc->stop_request; \ + cur = cur->next) + +// if statement to check hook bounds +#define HOOK_BOUND_CHECK(hh, addr) \ + ((((addr) >= (hh)->begin && (addr) < (hh)->end) \ + || (hh)->begin > (hh)->end)) + +#define HOOK_EXISTS(uc, idx) ((uc)->hook[idx##_IDX].head != NULL) +#define HOOK_EXISTS_BOUNDED(uc, idx, addr) _hook_exists_bounded((uc)->hook[idx##_IDX].head, addr) + +static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr) +{ + while (cur != NULL) { + if (HOOK_BOUND_CHECK((struct hook *)cur->data, addr)) + return true; + cur = cur->next; + } + return false; +} //relloc increment, KEEP THIS A POWER OF 2! #define MEM_BLOCK_INCR 32 @@ -144,35 +190,16 @@ struct uc_struct { bool apic_report_tpr_access; CPUState *current_cpu; - // all the hook callbacks - size_t hook_size; - struct hook_struct *hook_callbacks; + // linked lists containing hooks per type + struct list hook[UC_HOOK_MAX]; // hook to count number of instructions for uc_emu_start() - struct hook_struct hook_count; - uc_cb_hookcode_t hook_count_callback; + uc_hook count_hook; size_t emu_counter; // current counter of uc_emu_start() size_t emu_count; // save counter of uc_emu_start() - // indexes if hooking ALL block/code/read/write events - unsigned int hook_block_idx, hook_insn_idx, hook_read_idx, hook_write_idx; - // boolean variables for quick check on hooking block, code, memory accesses - bool hook_block, hook_insn, hook_mem_read, hook_mem_write; uint64_t block_addr; // save the last block address we hooked - // indexes to event callbacks - int hook_mem_read_idx; // for handling invalid memory read access on unmapped memory - int hook_mem_write_idx; // for handling invalid memory write access on unmapped memory - int hook_mem_fetch_idx; // for handling invalid memory fetch access on unmapped memory - int hook_mem_read_prot_idx; // for handling invalid memory read access on read-protected memory - int hook_mem_write_prot_idx; // for handling invalid memory write access on write-protected memory - int hook_mem_fetch_prot_idx; // for handling invalid memory fetch access on non-executable memory - - int hook_intr_idx; // for handling interrupt - int hook_out_idx; // for handling OUT instruction (X86) - int hook_in_idx; // for handling IN instruction (X86) - int hook_syscall_idx; // for handling SYSCALL/SYSENTER (X86) - bool init_tcg; // already initialized local TCGv variables? bool stop_request; // request to immediately stop emulation - for uc_emu_stop() diff --git a/list.c b/list.c new file mode 100644 index 00000000..695f5a24 --- /dev/null +++ b/list.c @@ -0,0 +1,66 @@ +#include +#include +#include "list.h" + +// simple linked list implementation + +struct list *list_new(void) +{ + return calloc(1, sizeof(struct list)); +} + +// removed linked list nodes but does not free their content +void list_clear(struct list *list) +{ + struct list_item *next, *cur = list->head; + while (cur != NULL) { + next = cur->next; + free(cur); + cur = next; + } +} + +// returns generated linked list node, or NULL on failure +void *list_append(struct list *list, void *data) +{ + struct list_item *item = malloc(sizeof(struct list_item)); + if (item == NULL) { + return NULL; + } + item->next = NULL; + item->data = data; + if (list->head == NULL) { + list->head = item; + } else { + list->tail->next = item; + } + list->tail = item; + return item; +} + +// returns true if entry was removed, false otherwise +bool list_remove(struct list *list, void *data) +{ + struct list_item *next, *cur, *prev = NULL; + // is list empty? + if (list->head == NULL) { + return false; + } + cur = list->head; + while (cur != NULL) { + next = cur->next; + if (cur->data == data) { + if (cur == list->head) { + list->head = next; + } + if (cur == list->tail) { + list->tail = prev; + } + free(cur); + return true; + } + prev = cur; + cur = next; + } + return false; +} diff --git a/qemu/Makefile.objs b/qemu/Makefile.objs index 4e7cc899..d309d2a4 100644 --- a/qemu/Makefile.objs +++ b/qemu/Makefile.objs @@ -6,7 +6,7 @@ util-obj-y = util/ qobject/ qapi/ qapi-types.o qapi-visit.o # block-obj-y is code used by both qemu system emulation and qemu-img block-obj-y = -block-obj-y += ../uc.o ../hook.o +block-obj-y += ../uc.o ../list.o #block-obj-$(CONFIG_POSIX) += aio-posix.o #block-obj-$(CONFIG_WIN32) += aio-win32.o diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 5a1f3798..33246009 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -64,6 +64,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq TranslationBlock *tb; uint8_t *tc_ptr; uintptr_t next_tb; + struct hook *hook; /* This must be volatile so it is not trashed by longjmp() */ volatile bool have_tb_lock = false; @@ -127,11 +128,10 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq ret = cpu->exception_index; break; #else - // Unicorn: call interrupt callback if registered - if (uc->hook_intr_idx) - ((uc_cb_hookintr_t)uc->hook_callbacks[uc->hook_intr_idx].callback)( - uc, cpu->exception_index, - uc->hook_callbacks[uc->hook_intr_idx].user_data); + // Unicorn: call registered interrupt callbacks + HOOK_FOREACH(uc, hook, UC_HOOK_INTR) { + ((uc_cb_hookintr_t)hook->callback)(uc, cpu->exception_index, hook->user_data); + } cpu->exception_index = -1; #if defined(TARGET_X86_64) // point EIP to the next instruction after INT diff --git a/qemu/ioport.c b/qemu/ioport.c index 338a296a..c7ac6b85 100644 --- a/qemu/ioport.c +++ b/qemu/ioport.c @@ -66,39 +66,45 @@ const MemoryRegionOps unassigned_io_ops = { void cpu_outb(struct uc_struct *uc, pio_addr_t addr, uint8_t val) { //LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); - // Unicorn: call interrupt callback if registered - if (uc->hook_out_idx) - ((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)( - uc, addr, 1, val, - uc->hook_callbacks[uc->hook_out_idx].user_data); + // Unicorn: call registered OUT callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_OUT) + ((uc_cb_insn_out_t)hook->callback)(uc, addr, 1, val, hook->user_data); + } } void cpu_outw(struct uc_struct *uc, pio_addr_t addr, uint16_t val) { //LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); - // Unicorn: call interrupt callback if registered - if (uc->hook_out_idx) - ((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)( - uc, addr, 2, val, - uc->hook_callbacks[uc->hook_out_idx].user_data); + // Unicorn: call registered OUT callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_OUT) + ((uc_cb_insn_out_t)hook->callback)(uc, addr, 2, val, hook->user_data); + } } void cpu_outl(struct uc_struct *uc, pio_addr_t addr, uint32_t val) { //LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); - if (uc->hook_out_idx) - ((uc_cb_insn_out_t)uc->hook_callbacks[uc->hook_out_idx].callback)( - uc, addr, 4, val, - uc->hook_callbacks[uc->hook_out_idx].user_data); + // Unicorn: call registered OUT callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_OUT) + ((uc_cb_insn_out_t)hook->callback)(uc, addr, 4, val, hook->user_data); + } } uint8_t cpu_inb(struct uc_struct *uc, pio_addr_t addr) { //LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); - if (uc->hook_in_idx) - return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)( - uc, addr, 1, - uc->hook_callbacks[uc->hook_in_idx].user_data); + // Unicorn: call registered IN callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_IN) + return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 1, hook->user_data); + } return 0; } @@ -106,10 +112,12 @@ uint8_t cpu_inb(struct uc_struct *uc, pio_addr_t addr) uint16_t cpu_inw(struct uc_struct *uc, pio_addr_t addr) { //LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); - if (uc->hook_in_idx) - return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)( - uc, addr, 2, - uc->hook_callbacks[uc->hook_in_idx].user_data); + // Unicorn: call registered IN callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_IN) + return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 2, hook->user_data); + } return 0; } @@ -117,10 +125,12 @@ uint16_t cpu_inw(struct uc_struct *uc, pio_addr_t addr) uint32_t cpu_inl(struct uc_struct *uc, pio_addr_t addr) { //LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); - if (uc->hook_in_idx) - return ((uc_cb_insn_in_t)uc->hook_callbacks[uc->hook_in_idx].callback)( - uc, addr, 4, - uc->hook_callbacks[uc->hook_in_idx].user_data); + // Unicorn: call registered IN callbacks + struct hook *hook; + HOOK_FOREACH(uc, hook, UC_HOOK_INSN) { + if (hook->insn == UC_X86_INS_IN) + return ((uc_cb_insn_in_t)hook->callback)(uc, addr, 4, hook->user_data); + } return 0; } diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index e3100fcd..1f636055 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -178,23 +178,33 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t haddr; DATA_TYPE res; int error_code; + struct hook *hook; + bool handled; struct uc_struct *uc = env->uc; MemoryRegion *mr = memory_mapping(uc, addr); // memory might be still unmapped while reading or fetching if (mr == NULL) { + handled = false; #if defined(SOFTMMU_CODE_ACCESS) error_code = UC_ERR_FETCH_UNMAPPED; - if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)( - uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) + break; + } #else error_code = UC_ERR_READ_UNMAPPED; - if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)( - uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) + break; + } #endif + if (handled) { env->invalid_error = UC_ERR_OK; mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time? } else { @@ -209,9 +219,15 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #if defined(SOFTMMU_CODE_ACCESS) // Unicorn: callback on fetch from NX if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable - if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)( - uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data))) + break; + } + + if (handled) { env->invalid_error = UC_ERR_OK; } else { env->invalid_addr = addr; @@ -224,19 +240,25 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #endif // Unicorn: callback on memory read - if (READ_ACCESS_TYPE == MMU_DATA_LOAD && env->uc->hook_mem_read) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr); - if (trace) { - ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ, - (uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data); + if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); } } // Unicorn: callback on non-readable memory if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable - if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)( - uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data))) + break; + } + + if (handled) { env->invalid_error = UC_ERR_OK; } else { env->invalid_addr = addr; @@ -368,23 +390,33 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, uintptr_t haddr; DATA_TYPE res; int error_code; + struct hook *hook; + bool handled; struct uc_struct *uc = env->uc; MemoryRegion *mr = memory_mapping(uc, addr); // memory can be unmapped while reading or fetching if (mr == NULL) { + handled = false; #if defined(SOFTMMU_CODE_ACCESS) error_code = UC_ERR_FETCH_UNMAPPED; - if (uc->hook_mem_fetch_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_idx].callback)( - uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_fetch_idx].user_data)) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) + break; + } #else error_code = UC_ERR_READ_UNMAPPED; - if (uc->hook_mem_read_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_idx].callback)( - uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_read_idx].user_data)) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) + break; + } #endif + if (handled) { env->invalid_error = UC_ERR_OK; mr = memory_mapping(uc, addr); // FIXME: what if mr is still NULL at this time? } else { @@ -399,9 +431,15 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #if defined(SOFTMMU_CODE_ACCESS) // Unicorn: callback on fetch from NX if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable - if (uc->hook_mem_fetch_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].callback)( - uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_fetch_prot_idx].user_data)) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data))) + break; + } + + if (handled) { env->invalid_error = UC_ERR_OK; } else { env->invalid_addr = addr; @@ -414,19 +452,25 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #endif // Unicorn: callback on memory read - if (READ_ACCESS_TYPE == MMU_DATA_LOAD && env->uc->hook_mem_read) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_MEM_READ, addr); - if (trace) { - ((uc_cb_hookmem_t)trace->callback)(env->uc, UC_MEM_READ, - (uint64_t)addr, (int)DATA_SIZE, (int64_t)0, trace->user_data); + if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); } } // Unicorn: callback on non-readable memory if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable - if (uc->hook_mem_read_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_read_prot_idx].callback)( - uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, - uc->hook_callbacks[uc->hook_mem_read_prot_idx].user_data)) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data))) + break; + } + + if (handled) { env->invalid_error = UC_ERR_OK; } else { env->invalid_addr = addr; @@ -595,24 +639,30 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; uintptr_t haddr; + struct hook *hook; + bool handled; struct uc_struct *uc = env->uc; MemoryRegion *mr = memory_mapping(uc, addr); // Unicorn: callback on memory write - if (uc->hook_mem_write) { - struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr); - if (trace) { - ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, - (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); - } + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); } // Unicorn: callback on invalid memory - if (uc->hook_mem_write_idx && mr == NULL) { - if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)( - uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, (int64_t)val, - uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) { + if (mr == NULL) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, val, hook->user_data))) + break; + } + + if (! handled) { // save error & quit env->invalid_addr = addr; env->invalid_error = UC_ERR_WRITE_UNMAPPED; @@ -627,12 +677,17 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on non-writable memory if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable - if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)( - uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val, - uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) { - env->invalid_error = UC_ERR_OK; + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, val, hook->user_data))) + break; } - else { + + if (handled) { + env->invalid_error = UC_ERR_OK; + } else { env->invalid_addr = addr; env->invalid_error = UC_ERR_WRITE_PROT; // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); @@ -742,24 +797,30 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write; uintptr_t haddr; + struct hook *hook; + bool handled; struct uc_struct *uc = env->uc; MemoryRegion *mr = memory_mapping(uc, addr); // Unicorn: callback on memory write - if (uc->hook_mem_write) { - struct hook_struct *trace = hook_find(uc, UC_HOOK_MEM_WRITE, addr); - if (trace) { - ((uc_cb_hookmem_t)trace->callback)(uc, UC_MEM_WRITE, - (uint64_t)addr, (int)DATA_SIZE, (int64_t)val, trace->user_data); - } + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); } // Unicorn: callback on invalid memory - if (uc->hook_mem_write_idx && mr == NULL) { - if (!((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_idx].callback)( - uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, (int64_t)val, - uc->hook_callbacks[uc->hook_mem_write_idx].user_data)) { + if (mr == NULL) { + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, val, hook->user_data))) + break; + } + + if (!handled) { // save error & quit env->invalid_addr = addr; env->invalid_error = UC_ERR_WRITE_UNMAPPED; @@ -774,12 +835,17 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on non-writable memory if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable - if (uc->hook_mem_write_prot_idx != 0 && ((uc_cb_eventmem_t)uc->hook_callbacks[uc->hook_mem_write_prot_idx].callback)( - uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, (int64_t)val, - uc->hook_callbacks[uc->hook_mem_write_prot_idx].user_data)) { - env->invalid_error = UC_ERR_OK; + handled = false; + HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { + if (! HOOK_BOUND_CHECK(hook, addr)) + continue; + if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, val, hook->user_data))) + break; } - else { + + if (handled) { + env->invalid_error = UC_ERR_OK; + } else { env->invalid_addr = addr; env->invalid_error = UC_ERR_WRITE_PROT; // printf("***** Invalid memory write (ro) at " TARGET_FMT_lx "\n", addr); diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index c76de8e0..28d57681 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -10970,6 +10970,7 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn) static void disas_a64_insn(CPUARMState *env, DisasContext *s) { uint32_t insn; + struct hook *hook; TCGContext *tcg_ctx = env->uc->tcg_ctx; // Unicorn: end address tells us to stop emulation @@ -10984,10 +10985,10 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) s->pc += 4; // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc - 4); - if (trace) - gen_uc_tracecode(tcg_ctx, 4, trace->callback, env->uc, s->pc - 4, trace->user_data); + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) + continue; + gen_uc_tracecode(tcg_ctx, 4, hook->callback, env->uc, s->pc - 4, hook->user_data); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -11043,6 +11044,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; + struct hook *hook; pc_start = tb->pc; @@ -11114,12 +11116,13 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (! env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 3560e6ed..bf190452 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -7680,6 +7680,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq TCGv_i32 tmp3; TCGv_i32 addr; TCGv_i64 tmp64; + struct hook *hook; /* M variants do not implement ARM mode. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { @@ -7687,10 +7688,10 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq } // Unicorn: trace this instruction on request - if (s->uc->hook_insn) { - struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc - 4); - if (trace) - gen_uc_tracecode(tcg_ctx, 4, trace->callback, s->uc, s->pc - 4, trace->user_data); + HOOK_FOREACH(s->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) + continue; + gen_uc_tracecode(tcg_ctx, 4, hook->callback, s->uc, s->pc - 4, hook->user_data); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -10390,6 +10391,7 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq TCGv_i32 tmp; TCGv_i32 tmp2; TCGv_i32 addr; + struct hook *hook; // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { @@ -10408,15 +10410,12 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq } // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - struct hook_struct *trace = hook_find(s->uc, UC_HOOK_CODE, s->pc); - if (trace) - gen_uc_tracecode(tcg_ctx, 2, trace->callback, env->uc, s->pc, trace->user_data); - // if requested to emulate only some instructions, check to see - // if we need to exit immediately - if (env->uc->emu_count > 0) { - check_exit_request(tcg_ctx); - } + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, s->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); + // check to see if we need to exit immediately + check_exit_request(tcg_ctx); } insn = arm_lduw_code(env, s->pc, s->bswap_code); @@ -11148,6 +11147,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; + struct hook *hook; /* generate intermediate code */ @@ -11237,12 +11237,13 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (!env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } diff --git a/qemu/target-i386/seg_helper.c b/qemu/target-i386/seg_helper.c index 42b0f37c..4cf6e41a 100644 --- a/qemu/target-i386/seg_helper.c +++ b/qemu/target-i386/seg_helper.c @@ -945,14 +945,16 @@ void helper_syscall(CPUX86State *env, int next_eip_addend) #else void helper_syscall(CPUX86State *env, int next_eip_addend) { - // Unicorn: call interrupt callback if registered - struct uc_struct *uc = env->uc; - if (uc->hook_syscall_idx) { - ((uc_cb_insn_syscall_t)uc->hook_callbacks[uc->hook_syscall_idx].callback)( - uc, uc->hook_callbacks[uc->hook_syscall_idx].user_data); + // Unicorn: call registered syscall hooks + struct hook *hook; + HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { + if (! HOOK_BOUND_CHECK(hook, env->eip)) + continue; + if (hook->insn == UC_X86_INS_SYSCALL) + ((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data); } - env->eip += next_eip_addend; + env->eip += next_eip_addend; return; int selector; @@ -2303,14 +2305,16 @@ void helper_lret_protected(CPUX86State *env, int shift, int addend) void helper_sysenter(CPUX86State *env, int next_eip_addend) { - // Unicorn: call interrupt callback if registered - struct uc_struct *uc = env->uc; - if (uc->hook_syscall_idx) { - ((uc_cb_insn_syscall_t)uc->hook_callbacks[uc->hook_syscall_idx].callback)( - uc, uc->hook_callbacks[uc->hook_syscall_idx].user_data); + // Unicorn: call registered SYSENTER hooks + struct hook *hook; + HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { + if (! HOOK_BOUND_CHECK(hook, env->eip)) + continue; + if (hook->insn == UC_X86_INS_SYSENTER) + ((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data); } - env->eip += next_eip_addend; + env->eip += next_eip_addend; return; if (env->sysenter_cs == 0) { diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 285ba32c..0d83f4bd 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -516,14 +516,14 @@ static inline void gen_op_addq_A0_reg_sN(TCGContext *s, int shift, int reg) static inline void gen_op_ld_v(DisasContext *s, int idx, TCGv t0, TCGv a0) { - if (s->uc->hook_mem_read) + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ)) gen_jmp_im(s, s->prev_pc); // Unicorn: sync EIP tcg_gen_qemu_ld_tl(s->uc, t0, a0, s->mem_index, idx | MO_LE); } static inline void gen_op_st_v(DisasContext *s, int idx, TCGv t0, TCGv a0) { - if (s->uc->hook_mem_write) + if (HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)) gen_jmp_im(s, s->prev_pc); // Unicorn: sync EIP tcg_gen_qemu_st_tl(s->uc, t0, a0, s->mem_index, idx | MO_LE); } @@ -4745,12 +4745,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, TCGv cpu_tmp4 = *(TCGv *)tcg_ctx->cpu_tmp4; TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T; TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs; - struct hook_struct *trace = NULL; + struct hook *hook = NULL; TCGArg *save_opparam_ptr = tcg_ctx->gen_opparam_ptr; bool cc_op_dirty = s->cc_op_dirty; bool changed_cc_op = false; - s->pc = pc_start; // end address tells us to stop emulation @@ -4768,16 +4767,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - trace = hook_find(env->uc, UC_HOOK_CODE, pc_start); - if (trace) { - if (s->last_cc_op != s->cc_op) { - sync_eflags(s, tcg_ctx); - s->last_cc_op = s->cc_op; - changed_cc_op = true; - } + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, pc_start)) { + if (s->last_cc_op != s->cc_op) { + sync_eflags(s, tcg_ctx); + s->last_cc_op = s->cc_op; + changed_cc_op = true; + } + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // generate code to call callback - gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, hook->callback, env->uc, pc_start, hook->user_data); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -8173,7 +8173,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_helper_unlock(tcg_ctx, cpu_env); // Unicorn: patch the callback for the instruction size - if (trace) { + if (hook) { // int i; // for(i = 0; i < 20; i++) // printf("=== [%u] = %x\n", i, *(save_opparam_ptr + i)); @@ -8282,6 +8282,7 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, int num_insns = 0; int max_insns; bool block_full = false; + struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -8387,11 +8388,12 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (!env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index 8c2951d9..0f685d8e 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3031,6 +3031,7 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { TCGContext *tcg_ctx = s->uc->tcg_ctx; uint16_t insn; + struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, s->pc); @@ -3043,11 +3044,10 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) } // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, s->pc); - if (trace) - gen_uc_tracecode(tcg_ctx, 2, trace->callback, env->uc, s->pc, trace->user_data); - + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, s->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -3075,6 +3075,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; + struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -3109,12 +3110,13 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (!env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 75465915..fadbaeb0 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -11331,6 +11331,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n int op, cnvt_op, op1, offset; int funct; int n_bytes; + struct hook *hook; op = (ctx->opcode >> 11) & 0x1f; sa = (ctx->opcode >> 2) & 0x7; @@ -11343,12 +11344,11 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n n_bytes = 2; // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); - if (trace) { - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); - *insn_need_patch = true; - } + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, ctx->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -13932,6 +13932,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; uint32_t op; + struct hook *hook; /* make sure instructions are on a halfword boundary */ if (ctx->pc & 0x1) { @@ -13942,12 +13943,11 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins } // Unicorn: trace this instruction on request - if (env->uc->hook_insn) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); - if (trace) { - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); - *insn_need_patch = true; - } + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, ctx->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -18504,13 +18504,13 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) // Unicorn: trace this instruction on request static void hook_insn(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_patch, int *insn_patch_offset, int offset_value) { - if (env->uc->hook_insn) { - TCGContext *tcg_ctx = ctx->uc->tcg_ctx; - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); - if (trace) { - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); - *insn_need_patch = true; - } + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; + struct hook *hook; + HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, ctx->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); *insn_patch_offset = offset_value; @@ -19178,6 +19178,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGArg *save_opparam_ptr = NULL; bool block_full = false; + struct hook *hook; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -19223,12 +19224,13 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (! env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } @@ -19275,7 +19277,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, int insn_patch_offset = 1; // Unicorn: save param buffer - if (env->uc->hook_insn) + if (HOOK_EXISTS(env->uc, UC_HOOK_CODE)) save_opparam_ptr = tcg_ctx->gen_opparam_ptr; is_slot = ctx.hflags & MIPS_HFLAG_BMASK; diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index fc71e88b..8caba2b7 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -2625,6 +2625,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; + struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, dc->pc); @@ -2637,13 +2638,14 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins } // Unicorn: trace this instruction on request - if (hook_insn && dc->uc->hook_insn) { - struct hook_struct *trace = hook_find(dc->uc, UC_HOOK_CODE, dc->pc); - if (trace) - gen_uc_tracecode(tcg_ctx, 4, trace->callback, dc->uc, dc->pc, trace->user_data); - - // the callback might want to stop emulation immediately - check_exit_request(tcg_ctx); + if (hook_insn) { + HOOK_FOREACH(dc->uc, hook, UC_HOOK_CODE) { + if (! HOOK_BOUND_CHECK(hook, dc->pc)) + continue; + gen_uc_tracecode(tcg_ctx, 4, hook->callback, dc->uc, dc->pc, hook->user_data); + // the callback might want to stop emulation immediately + check_exit_request(tcg_ctx); + } } opc = GET_FIELD(insn, 0, 1); @@ -5388,6 +5390,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, unsigned int insn; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; + struct hook *hook; memset(dc, 0, sizeof(DisasContext)); dc->uc = env->uc; @@ -5428,12 +5431,13 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (env->uc->hook_block && !env->uc->block_full) { - struct hook_struct *trace = hook_find(env->uc, UC_HOOK_BLOCK, pc_start); - if (trace) { + if (!env->uc->block_full) { + HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { + if (! HOOK_BOUND_CHECK(hook, pc_start)) + continue; // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, pc_start, trace->user_data); + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); } } diff --git a/qemu/tcg/i386/tcg-target.c b/qemu/tcg/i386/tcg-target.c index aa06cc18..414c4a72 100644 --- a/qemu/tcg/i386/tcg-target.c +++ b/qemu/tcg/i386/tcg-target.c @@ -1209,7 +1209,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, TCGReg addrlo, TCGReg addrhi, tcg_out_mov(s, ttype, r1, addrlo); // Unicorn: fast path if hookmem is not enable - if (!s->uc->hook_mem_read && !s->uc->hook_mem_write) + if (!HOOK_EXISTS(s->uc, UC_HOOK_MEM_READ) && !HOOK_EXISTS(s->uc, UC_HOOK_MEM_WRITE)) tcg_out_opc(s, OPC_JCC_long + JCC_JNE, 0, 0, 0); else tcg_out_opc(s, OPC_JMP_long, 0, 0, 0); /* slow_path */ diff --git a/qemu/translate-all.c b/qemu/translate-all.c index 11bbb07b..72e1b60f 100644 --- a/qemu/translate-all.c +++ b/qemu/translate-all.c @@ -179,7 +179,7 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s gen_intermediate_code(env, tb); // Unicorn: when tracing block, patch 1st operand for block size - if (env->uc->hook_block && env->uc->block_addr == tb->pc) { + if (HOOK_EXISTS(env->uc, UC_HOOK_BLOCK) && env->uc->block_addr == tb->pc) { if (env->uc->block_full) // block size is unknown *(s->gen_opparam_buf + 1) = 0; else diff --git a/uc.c b/uc.c index b354a5fa..f7f40853 100644 --- a/uc.c +++ b/uc.c @@ -20,7 +20,6 @@ #endif #include "uc_priv.h" -#include "hook.h" // target specific headers #include "qemu/target-m68k/unicorn.h" @@ -95,8 +94,6 @@ const char *uc_strerror(uc_err code) return "Write to unaligned memory (UC_ERR_WRITE_UNALIGNED)"; case UC_ERR_FETCH_UNALIGNED: return "Fetch from unaligned memory (UC_ERR_FETCH_UNALIGNED)"; - case UC_ERR_HOOK_EXIST: - return "Hook for this type event already exists (UC_ERR_HOOK_EXIST)"; case UC_ERR_RESOURCE: return "Insufficient resource (UC_ERR_RESOURCE)"; } @@ -245,9 +242,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) if (uc->reg_reset) uc->reg_reset(uc); - uc->hook_size = HOOK_SIZE; - uc->hook_callbacks = calloc(1, sizeof(uc->hook_callbacks[0]) * HOOK_SIZE); - return UC_ERR_OK; } else { return UC_ERR_ARCH; @@ -259,6 +253,8 @@ UNICORN_EXPORT uc_err uc_close(uc_engine *uc) { int i; + struct list_item *cur; + struct hook *hook; if (uc->release) uc->release(uc->tcg_ctx); @@ -284,7 +280,20 @@ uc_err uc_close(uc_engine *uc) // TODO: remove uc->root (created with object_new()) uc->root->free(uc->root); - free(uc->hook_callbacks); + // free hooks and hook lists + for (i = 0; i < UC_HOOK_MAX; i++) { + cur = uc->hook[i].head; + // hook can be in more than one list + // so we refcount to know when to free + while (cur) { + hook = (struct hook *)cur->data; + if (--hook->refs == 0) { + free(hook); + } + cur = cur->next; + } + list_clear(&uc->hook[i]); + } free(uc->mapped_blocks); @@ -445,6 +454,15 @@ static void enable_emu_timer(uc_engine *uc, uint64_t timeout) uc, QEMU_THREAD_JOINABLE); } +static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data) +{ + // count this instruction. ah ah ah. + uc->emu_counter++; + + if (uc->emu_counter > uc->emu_count) + uc_emu_stop(uc); +} + UNICORN_EXPORT uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count) { @@ -506,8 +524,17 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time } uc->emu_count = count; - if (count > 0) { - uc->hook_insn = true; + // remove count hook if counting isn't necessary + if (count <= 0 && uc->count_hook != 0) { + uc_hook_del(uc, uc->count_hook); + uc->count_hook = 0; + } + // set up count hook to count instructions. + if (count > 0 && uc->count_hook == 0) { + uc_err err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL); + if (err != UC_ERR_OK) { + return err; + } } uc->addr_end = until; @@ -546,37 +573,6 @@ uc_err uc_emu_stop(uc_engine *uc) return UC_ERR_OK; } - -static int _hook_code(uc_engine *uc, int type, uint64_t begin, uint64_t end, - void *callback, void *user_data, uc_hook *hh) -{ - int i; - - i = hook_add(uc, type, begin, end, callback, user_data); - if (i == 0) - return UC_ERR_NOMEM; - - *hh = i; - - return UC_ERR_OK; -} - - -static uc_err _hook_mem_access(uc_engine *uc, uc_hook_type type, - uint64_t begin, uint64_t end, - void *callback, void *user_data, uc_hook *hh) -{ - int i; - - i = hook_add(uc, type, begin, end, callback, user_data); - if (i == 0) - return UC_ERR_NOMEM; - - *hh = i; - - return UC_ERR_OK; -} - // find if a memory range overlaps with existing mapped regions static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) { @@ -935,208 +931,95 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) return NULL; } -static uc_err _hook_mem_invalid(struct uc_struct* uc, int type, uc_cb_eventmem_t callback, - void *user_data, uc_hook *evh) -{ - size_t i; - - // only one event handler at the same time - if ((type & UC_HOOK_MEM_READ_UNMAPPED) != 0 && (uc->hook_mem_read_idx != 0)) - return UC_ERR_HOOK_EXIST; - - if ((type & UC_HOOK_MEM_READ_PROT) != 0 && (uc->hook_mem_read_prot_idx != 0)) - return UC_ERR_HOOK_EXIST; - - if ((type & UC_HOOK_MEM_WRITE_UNMAPPED) != 0 && (uc->hook_mem_write_idx != 0)) - return UC_ERR_HOOK_EXIST; - - if ((type & UC_HOOK_MEM_WRITE_PROT) != 0 && (uc->hook_mem_write_prot_idx != 0)) - return UC_ERR_HOOK_EXIST; - - if ((type & UC_HOOK_MEM_FETCH_UNMAPPED) != 0 && (uc->hook_mem_fetch_idx != 0)) - return UC_ERR_HOOK_EXIST; - - if ((type & UC_HOOK_MEM_FETCH_PROT) != 0 && (uc->hook_mem_fetch_prot_idx != 0)) - return UC_ERR_HOOK_EXIST; - - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - *evh = i; - if (type & UC_HOOK_MEM_READ_UNMAPPED) - uc->hook_mem_read_idx = i; - if (type & UC_HOOK_MEM_READ_PROT) - uc->hook_mem_read_prot_idx = i; - if (type & UC_HOOK_MEM_WRITE_UNMAPPED) - uc->hook_mem_write_idx = i; - if (type & UC_HOOK_MEM_WRITE_PROT) - uc->hook_mem_write_prot_idx = i; - if (type & UC_HOOK_MEM_FETCH_UNMAPPED) - uc->hook_mem_fetch_idx = i; - if (type & UC_HOOK_MEM_FETCH_PROT) - uc->hook_mem_fetch_prot_idx = i; - return UC_ERR_OK; - } else - return UC_ERR_NOMEM; -} - - -static uc_err _hook_intr(struct uc_struct* uc, void *callback, - void *user_data, uc_hook *evh) -{ - size_t i; - - // only one event handler at the same time - if (uc->hook_intr_idx) - return UC_ERR_HOOK_EXIST; - - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - *evh = i; - uc->hook_intr_idx = i; - return UC_ERR_OK; - } else - return UC_ERR_NOMEM; -} - - -static uc_err _hook_insn(struct uc_struct *uc, unsigned int insn_id, void *callback, - void *user_data, uc_hook *evh) -{ - size_t i; - - switch(uc->arch) { - default: break; - case UC_ARCH_X86: - switch(insn_id) { - default: break; - case UC_X86_INS_OUT: - // only one event handler at the same time - if (uc->hook_out_idx) - return UC_ERR_HOOK_EXIST; - - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - *evh = i; - uc->hook_out_idx = i; - return UC_ERR_OK; - } else - return UC_ERR_NOMEM; - case UC_X86_INS_IN: - // only one event handler at the same time - if (uc->hook_in_idx) - return UC_ERR_HOOK_EXIST; - - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - *evh = i; - uc->hook_in_idx = i; - return UC_ERR_OK; - } else - return UC_ERR_NOMEM; - case UC_X86_INS_SYSCALL: - case UC_X86_INS_SYSENTER: - // only one event handler at the same time - if (uc->hook_syscall_idx) - return UC_ERR_HOOK_EXIST; - - i = hook_find_new(uc); - if (i) { - uc->hook_callbacks[i].callback = callback; - uc->hook_callbacks[i].user_data = user_data; - *evh = i; - uc->hook_syscall_idx = i; - return UC_ERR_OK; - } else - return UC_ERR_NOMEM; - } - break; - } - - return UC_ERR_OK; -} - UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, void *user_data, ...) { va_list valist; int ret = UC_ERR_OK; - int id; - uint64_t begin, end; va_start(valist, user_data); - if (type & UC_HOOK_MEM_READ_UNMAPPED) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_UNMAPPED, callback, user_data, hh); + struct hook *hook = calloc(1, sizeof(struct hook)); + if (hook == NULL) { + return UC_ERR_NOMEM; + } + hook->type = type; + hook->callback = callback; + hook->user_data = user_data; + hook->refs = 0; + *hh = (uc_hook)hook; - if (type & UC_HOOK_MEM_WRITE_UNMAPPED) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_UNMAPPED, callback, user_data, hh); - - if (type & UC_HOOK_MEM_FETCH_UNMAPPED) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_UNMAPPED, callback, user_data, hh); - - if (type & UC_HOOK_MEM_READ_PROT) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_READ_PROT, callback, user_data, hh); - - if (type & UC_HOOK_MEM_WRITE_PROT) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_WRITE_PROT, callback, user_data, hh); - - if (type & UC_HOOK_MEM_FETCH_PROT) - ret = _hook_mem_invalid(uc, UC_HOOK_MEM_FETCH_PROT, callback, user_data, hh); - - switch(type) { - default: - break; - case UC_HOOK_INTR: - ret = _hook_intr(uc, callback, user_data, hh); - break; - case UC_HOOK_INSN: - id = va_arg(valist, int); - ret = _hook_insn(uc, id, callback, user_data, hh); - break; - case UC_HOOK_CODE: - begin = va_arg(valist, uint64_t); - end = va_arg(valist, uint64_t); - ret = _hook_code(uc, UC_HOOK_CODE, begin, end, callback, user_data, hh); - break; - case UC_HOOK_BLOCK: - begin = va_arg(valist, uint64_t); - end = va_arg(valist, uint64_t); - ret = _hook_code(uc, UC_HOOK_BLOCK, begin, end, callback, user_data, hh); - break; - case UC_HOOK_MEM_READ: - begin = va_arg(valist, uint64_t); - end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_HOOK_MEM_READ, begin, end, callback, user_data, hh); - break; - case UC_HOOK_MEM_WRITE: - begin = va_arg(valist, uint64_t); - end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh); - break; - case UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE: - begin = va_arg(valist, uint64_t); - end = va_arg(valist, uint64_t); - ret = _hook_mem_access(uc, UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, begin, end, callback, user_data, hh); - break; + // everybody but HOOK_INSN gets begin/end, so exit early here. + if (type & UC_HOOK_INSN) { + hook->insn = va_arg(valist, int); + hook->begin = 1; + hook->end = 0; + if (list_append(&uc->hook[UC_HOOK_INSN_IDX], hook) == NULL) { + free(hook); + return UC_ERR_NOMEM; + } + hook->refs++; + return UC_ERR_OK; } + hook->begin = va_arg(valist, uint64_t); + hook->end = va_arg(valist, uint64_t); va_end(valist); + int i = 0; + while ((type >> i) > 0) { + if ((type >> i) & 1) { + // TODO: invalid hook error? + if (i < UC_HOOK_MAX) { + if (list_append(&uc->hook[i], hook) == NULL) { + if (hook->refs == 0) { + free(hook); + } + return UC_ERR_NOMEM; + } + hook->refs++; + } + } + i++; + } + + // we didn't use the hook + // TODO: return an error? + if (hook->refs == 0) { + free(hook); + } + return ret; } UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh) { - return hook_del(uc, hh); + int i; + struct hook *hook; + for (i = 0; i < UC_HOOK_MAX; i++) { + if (list_remove(&uc->hook[i], (void *)hh)) { + hook = (struct hook *)hh; + if (--hook->refs == 0) { + free(hook); + } + } + } + return UC_ERR_OK; +} + +// TCG helper +void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data); +void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data) +{ + struct uc_struct *uc = handle; + + // sync PC in CPUArchState with address + if (uc->set_pc) { + uc->set_pc(uc, address); + } + + ((uc_cb_hookcode_t)callback)(uc, address, size, user_data); } UNICORN_EXPORT From 33180b5afac6acc9f06ad9cc6e753693fa8ad9bf Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Thu, 21 Jan 2016 20:58:21 -0800 Subject: [PATCH 49/77] add test for multiple basic block hooks --- tests/unit/Makefile | 4 +- tests/unit/test_multihook.c | 111 ++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 tests/unit/test_multihook.c diff --git a/tests/unit/Makefile b/tests/unit/Makefile index b261da4d..cd0e46eb 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -5,7 +5,7 @@ CFLAGS += -lcmocka -lunicorn CFLAGS += -I ../../include ALL_TESTS = test_sanity test_x86 test_mem_map test_mem_high test_mem_map_ptr \ - test_tb_x86 + test_tb_x86 test_multihook .PHONY: all all: ${ALL_TESTS} @@ -23,6 +23,7 @@ test: ${ALL_TESTS} ./test_mem_map_ptr ./test_mem_high ./test_tb_x86 + ./test_multihook test_sanity: test_sanity.c test_x86: test_x86.c @@ -30,6 +31,7 @@ test_mem_map: test_mem_map.c test_mem_map_ptr: test_mem_map_ptr.c test_mem_high: test_mem_high.c test_tb_x86: test_tb_x86.c +test_multihook: test_multihook.c ${ALL_TESTS}: ${CC} ${CFLAGS} -o $@ $^ diff --git a/tests/unit/test_multihook.c b/tests/unit/test_multihook.c new file mode 100644 index 00000000..eb831865 --- /dev/null +++ b/tests/unit/test_multihook.c @@ -0,0 +1,111 @@ +#include "unicorn_test.h" +#include + +#define OK(x) uc_assert_success(x) + +/* Called before every test to set up a new instance */ +static int setup32(void **state) +{ + uc_engine *uc; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + + *state = uc; + return 0; +} + +/* Called after every test to clean up */ +static int teardown(void **state) +{ + uc_engine *uc = *state; + + OK(uc_close(uc)); + + *state = NULL; + return 0; +} + +/******************************************************************************/ + +struct bb { + uint64_t addr; + size_t size; +}; + +struct bbtest { + const struct bb *blocks; + unsigned int blocknum; +}; + + +static void test_basic_blocks_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + struct bbtest *bbtest = user_data; + const struct bb *bb = &bbtest->blocks[bbtest->blocknum]; + + printf("block hook 1: %d == %zu\n", size, bb->size); + assert_int_equal(address, bb->addr); + assert_int_equal((size_t)size, bb->size); +} + +static void test_basic_blocks_hook2(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + struct bbtest *bbtest = user_data; + const struct bb *bb = &bbtest->blocks[bbtest->blocknum++]; + + printf("block hook 2: %d == %zu\n", size, bb->size); + assert_int_equal(address, bb->addr); + assert_int_equal((size_t)size, bb->size); +} + +static void test_basic_blocks(void **state) +{ + uc_engine *uc = *state; + uc_hook trace1, trace2; + +#define BASEADDR 0x1000000 + + uint64_t address = BASEADDR; + const uint8_t code[] = { + 0x33, 0xC0, // xor eax, eax + 0x90, // nop + 0x90, // nop + 0xEB, 0x00, // jmp $+2 + 0x90, // nop + 0x90, // nop + 0x90, // nop + }; + + static const struct bb blocks[] = { + {BASEADDR, 6}, + {BASEADDR+ 6, 3}, + }; + + struct bbtest bbtest = { + .blocks = blocks, + .blocknum = 0, + }; + + +#undef BASEADDR + + // map 2MB memory for this emulation + OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL)); + + // write machine code to be emulated to memory + OK(uc_mem_write(uc, address, code, sizeof(code))); + + // trace all basic blocks + OK(uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, test_basic_blocks_hook, &bbtest, (uint64_t)1, (uint64_t)0)); + OK(uc_hook_add(uc, &trace2, UC_HOOK_BLOCK, test_basic_blocks_hook2, &bbtest, (uint64_t)1, (uint64_t)0)); + + OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_basic_blocks, setup32, teardown), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} From 0886ae8ede5208f56e08415e1869e995f15ca986 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Fri, 22 Jan 2016 18:28:17 -0800 Subject: [PATCH 50/77] rework code/block tracing --- list.c | 2 ++ qemu/target-arm/helper.h | 2 +- qemu/target-arm/translate-a64.c | 18 ++++++----------- qemu/target-arm/translate.c | 29 +++++++++------------------- qemu/target-i386/helper.h | 2 +- qemu/target-i386/translate.c | 25 +++++++----------------- qemu/target-m68k/helper.h | 2 +- qemu/target-m68k/translate.c | 20 ++++++------------- qemu/target-mips/helper.h | 2 +- qemu/target-mips/translate.c | 34 ++++++++++----------------------- qemu/target-sparc/helper.h | 2 +- qemu/target-sparc/translate.c | 26 ++++++++----------------- qemu/tcg/tcg-op.h | 7 +++---- qemu/translate-all.c | 2 +- uc.c | 12 +++++++++--- 15 files changed, 66 insertions(+), 119 deletions(-) diff --git a/list.c b/list.c index 695f5a24..6dbe4782 100644 --- a/list.c +++ b/list.c @@ -18,6 +18,8 @@ void list_clear(struct list *list) free(cur); cur = next; } + list->head = NULL; + list->tail = NULL; } // returns generated linked list node, or NULL on failure diff --git a/qemu/target-arm/helper.h b/qemu/target-arm/helper.h index d2de58d6..6427c18c 100644 --- a/qemu/target-arm/helper.h +++ b/qemu/target-arm/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_FLAGS_1(clz_arm, TCG_CALL_NO_RWG_SE, i32, i32) diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 28d57681..4079a61c 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -10985,10 +10985,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) s->pc += 4; // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, env->uc, s->pc - 4, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc - 4)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, env->uc, s->pc - 4); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -11116,14 +11114,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index bf190452..d097c236 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -7680,7 +7680,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq TCGv_i32 tmp3; TCGv_i32 addr; TCGv_i64 tmp64; - struct hook *hook; /* M variants do not implement ARM mode. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { @@ -7688,10 +7687,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq } // Unicorn: trace this instruction on request - HOOK_FOREACH(s->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, s->uc, s->pc - 4, hook->user_data); + if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc - 4)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, s->uc, s->pc - 4); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -10391,7 +10388,6 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq TCGv_i32 tmp; TCGv_i32 tmp2; TCGv_i32 addr; - struct hook *hook; // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { @@ -10410,11 +10406,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); - // check to see if we need to exit immediately + if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc)) { + gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, s->uc, s->pc); + // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -11147,7 +11141,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; /* generate intermediate code */ @@ -11237,14 +11230,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-i386/helper.h b/qemu/target-i386/helper.h index 8ab196ac..d3b52d1f 100644 --- a/qemu/target-i386/helper.h +++ b/qemu/target-i386/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int) DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int) diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 0d83f4bd..d68cb516 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -4745,7 +4745,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, TCGv cpu_tmp4 = *(TCGv *)tcg_ctx->cpu_tmp4; TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T; TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs; - struct hook *hook = NULL; TCGArg *save_opparam_ptr = tcg_ctx->gen_opparam_ptr; bool cc_op_dirty = s->cc_op_dirty; bool changed_cc_op = false; @@ -4773,14 +4772,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, s->last_cc_op = s->cc_op; changed_cc_op = true; } - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // generate code to call callback - gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, hook->callback, env->uc, pc_start, hook->user_data); - // the callback might want to stop emulation immediately - check_exit_request(tcg_ctx); - } + gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, UC_HOOK_CODE_IDX, env->uc, pc_start); + // the callback might want to stop emulation immediately + check_exit_request(tcg_ctx); } prefixes = 0; @@ -8173,7 +8167,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_helper_unlock(tcg_ctx, cpu_env); // Unicorn: patch the callback for the instruction size - if (hook) { + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, pc_start)) { // int i; // for(i = 0; i < 20; i++) // printf("=== [%u] = %x\n", i, *(save_opparam_ptr + i)); @@ -8282,7 +8276,6 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, int num_insns = 0; int max_insns; bool block_full = false; - struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -8388,13 +8381,9 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-m68k/helper.h b/qemu/target-m68k/helper.h index 865cf95d..caaadb3a 100644 --- a/qemu/target-m68k/helper.h +++ b/qemu/target-m68k/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_1(bitrev, i32, i32) DEF_HELPER_1(ff1, i32, i32) diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index 0f685d8e..bf45a66a 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3031,7 +3031,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { TCGContext *tcg_ctx = s->uc->tcg_ctx; uint16_t insn; - struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, s->pc); @@ -3044,10 +3043,8 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc)) { + gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, env->uc, s->pc); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -3075,7 +3072,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -3110,14 +3106,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index 81f733c2..1924bf6f 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index fadbaeb0..8802c221 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -11331,7 +11331,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n int op, cnvt_op, op1, offset; int funct; int n_bytes; - struct hook *hook; op = (ctx->opcode >> 11) & 0x1f; sa = (ctx->opcode >> 2) & 0x7; @@ -11344,10 +11343,8 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n n_bytes = 2; // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -13932,7 +13929,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; uint32_t op; - struct hook *hook; /* make sure instructions are on a halfword boundary */ if (ctx->pc & 0x1) { @@ -13943,10 +13939,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -18505,11 +18499,8 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) static void hook_insn(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_patch, int *insn_patch_offset, int offset_value) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; - struct hook *hook; - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -19178,7 +19169,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGArg *save_opparam_ptr = NULL; bool block_full = false; - struct hook *hook; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -19224,14 +19214,10 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-sparc/helper.h b/qemu/target-sparc/helper.h index 2557dd08..503e1e5c 100644 --- a/qemu/target-sparc/helper.h +++ b/qemu/target-sparc/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_1(power_down, void, env) #ifndef TARGET_SPARC64 diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index 8caba2b7..a7f067cf 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -2625,7 +2625,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; - struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, dc->pc); @@ -2638,14 +2637,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins } // Unicorn: trace this instruction on request - if (hook_insn) { - HOOK_FOREACH(dc->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, dc->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, dc->uc, dc->pc, hook->user_data); - // the callback might want to stop emulation immediately - check_exit_request(tcg_ctx); - } + if (hook_insn && HOOK_EXISTS_BOUNDED(dc->uc, UC_HOOK_CODE, dc->pc)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, dc->uc, dc->pc); + // the callback might want to stop emulation immediately + check_exit_request(tcg_ctx); } opc = GET_FIELD(insn, 0, 1); @@ -5390,7 +5385,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, unsigned int insn; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; memset(dc, 0, sizeof(DisasContext)); dc->uc = env->uc; @@ -5431,14 +5425,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h index 9f096a3d..87358240 100644 --- a/qemu/tcg/tcg-op.h +++ b/qemu/tcg/tcg-op.h @@ -27,14 +27,13 @@ int gen_new_label(TCGContext *); -static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, void *callback, void *uc, uint64_t pc, void *data) +static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc) { TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size); - TCGv_ptr tcallback = tcg_const_ptr(tcg_ctx, callback); + TCGv_i32 ttype = tcg_const_i32(tcg_ctx, type); TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc); TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc); - TCGv_ptr tdata = tcg_const_ptr(tcg_ctx, data); - gen_helper_uc_tracecode(tcg_ctx, tsize, tcallback, tuc, tpc, tdata); + gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc); } static inline void tcg_gen_op0(TCGContext *s, TCGOpcode opc) diff --git a/qemu/translate-all.c b/qemu/translate-all.c index 72e1b60f..aec38c7c 100644 --- a/qemu/translate-all.c +++ b/qemu/translate-all.c @@ -179,7 +179,7 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s gen_intermediate_code(env, tb); // Unicorn: when tracing block, patch 1st operand for block size - if (HOOK_EXISTS(env->uc, UC_HOOK_BLOCK) && env->uc->block_addr == tb->pc) { + if (env->uc->block_addr == tb->pc && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) { if (env->uc->block_full) // block size is unknown *(s->gen_opparam_buf + 1) = 0; else diff --git a/uc.c b/uc.c index f7f40853..b0f8a976 100644 --- a/uc.c +++ b/uc.c @@ -1009,17 +1009,23 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) } // TCG helper -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data); -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data) +void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address); +void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address) { struct uc_struct *uc = handle; + struct list_item *cur = uc->hook[type].head; + struct hook *hook; // sync PC in CPUArchState with address if (uc->set_pc) { uc->set_pc(uc, address); } - ((uc_cb_hookcode_t)callback)(uc, address, size, user_data); + while (cur != NULL && !uc->stop_request) { + hook = (struct hook *)cur->data; + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + cur = cur->next; + } } UNICORN_EXPORT From d79925f477abb00659c99f08c948ee606a558b46 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 10:48:18 +0800 Subject: [PATCH 51/77] sparc: add SPARC32 mode (= UC_MODE_32) --- bindings/dotnet/UnicornManaged/Const/Common.fs | 1 + bindings/go/unicorn/unicorn_const.go | 1 + bindings/java/unicorn/UnicornConst.java | 1 + bindings/python/sample_sparc.py | 2 +- bindings/python/unicorn/unicorn_const.py | 1 + include/uc_priv.h | 2 +- include/unicorn/unicorn.h | 5 +++-- samples/sample_sparc.c | 2 +- tests/regress/sparc64.py | 2 +- tests/regress/sparc_jump_to_zero.c | 2 +- tests/regress/sparc_reg.py | 2 +- 11 files changed, 13 insertions(+), 8 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index f5c2230c..3ec03c74 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -37,6 +37,7 @@ module Common = let UC_MODE_64 = 8 let UC_MODE_PPC64 = 8 let UC_MODE_QPX = 16 + let UC_MODE_SPARC32 = 4 let UC_MODE_SPARC64 = 8 let UC_MODE_V9 = 16 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index fb44acd0..2d8d2c1a 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -32,6 +32,7 @@ const ( MODE_64 = 8 MODE_PPC64 = 8 MODE_QPX = 16 + MODE_SPARC32 = 4 MODE_SPARC64 = 8 MODE_V9 = 16 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 614326b3..5967d26b 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -34,6 +34,7 @@ public interface UnicornConst { public static final int UC_MODE_64 = 8; public static final int UC_MODE_PPC64 = 8; public static final int UC_MODE_QPX = 16; + public static final int UC_MODE_SPARC32 = 4; public static final int UC_MODE_SPARC64 = 8; public static final int UC_MODE_V9 = 16; diff --git a/bindings/python/sample_sparc.py b/bindings/python/sample_sparc.py index 307ba936..a8bdd586 100755 --- a/bindings/python/sample_sparc.py +++ b/bindings/python/sample_sparc.py @@ -28,7 +28,7 @@ def test_sparc(): print("Emulate SPARC code") try: # Initialize emulator in SPARC EB mode - mu = Uc(UC_ARCH_SPARC, UC_MODE_32) + mu = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32) # map 2MB memory for this emulation mu.mem_map(ADDRESS, 2 * 1024 * 1024) diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index c99cb816..a1967684 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -30,6 +30,7 @@ UC_MODE_32 = 4 UC_MODE_64 = 8 UC_MODE_PPC64 = 8 UC_MODE_QPX = 16 +UC_MODE_SPARC32 = 4 UC_MODE_SPARC64 = 8 UC_MODE_V9 = 16 diff --git a/include/uc_priv.h b/include/uc_priv.h index 12f0b8bc..589a655f 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -17,7 +17,7 @@ #define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) #define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN) #define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_BIG_ENDIAN) -#define UC_MODE_SPARC_MASK (UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) +#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) #define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN) #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index f3468ab6..a6bedfaf 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -89,8 +89,8 @@ typedef enum uc_mode { UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode // arm / arm64 - UC_MODE_ARM = 0, // Start executing in ARM mode - UC_MODE_THUMB = 1 << 4, // Start executing in THUMB mode (including Thumb-2) + UC_MODE_ARM = 0, // ARM mode + UC_MODE_THUMB = 1 << 4, // THUMB mode (including Thumb-2) UC_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series (currently unsupported) UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) // mips @@ -107,6 +107,7 @@ typedef enum uc_mode { UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) // sparc + UC_MODE_SPARC32 = 1 << 2, // 32-bit mode UC_MODE_SPARC64 = 1 << 3, // 64-bit mode UC_MODE_V9 = 1 << 4, // SparcV9 mode (currently unsupported) // m68k diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index c361232f..88bbd01e 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -57,7 +57,7 @@ static void test_sparc(void) printf("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - err = uc_open(UC_ARCH_SPARC, 0, &uc); + err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32, &uc); if (err) { printf("Failed on uc_open() with error returned: %u (%s)\n", err, uc_strerror(err)); diff --git a/tests/regress/sparc64.py b/tests/regress/sparc64.py index 27210bd1..12d3f547 100755 --- a/tests/regress/sparc64.py +++ b/tests/regress/sparc64.py @@ -5,7 +5,7 @@ from unicorn.sparc_const import * PAGE_SIZE = 1 * 1024 * 1024 -uc = Uc(UC_ARCH_SPARC, UC_MODE_64) +uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC64) uc.reg_write(UC_SPARC_REG_SP, 100) print 'writing sp = 100' diff --git a/tests/regress/sparc_jump_to_zero.c b/tests/regress/sparc_jump_to_zero.c index 96392f41..c816b700 100644 --- a/tests/regress/sparc_jump_to_zero.c +++ b/tests/regress/sparc_jump_to_zero.c @@ -1,7 +1,7 @@ #include #define HARDWARE_ARCHITECTURE UC_ARCH_SPARC -#define HARDWARE_MODE 0 +#define HARDWARE_MODE UC_ARCH_SPARC32 #define MEMORY_STARTING_ADDRESS 0x1000000 #define MEMORY_SIZE 2 * 1024 * 1024 diff --git a/tests/regress/sparc_reg.py b/tests/regress/sparc_reg.py index 4508efab..da6987d1 100755 --- a/tests/regress/sparc_reg.py +++ b/tests/regress/sparc_reg.py @@ -5,7 +5,7 @@ from unicorn.sparc_const import * PAGE_SIZE = 1 * 1024 * 1024 -uc = Uc(UC_ARCH_SPARC, 0) +uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32) uc.reg_write(UC_SPARC_REG_SP, 100) uc.reg_write(UC_SPARC_REG_FP, 200) From 2ac1281f82314d4f49b213583c37213ff710a737 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Fri, 22 Jan 2016 18:28:17 -0800 Subject: [PATCH 52/77] rework code/block tracing --- list.c | 2 ++ qemu/target-arm/helper.h | 2 +- qemu/target-arm/translate-a64.c | 20 ++++++------------- qemu/target-arm/translate.c | 29 +++++++++------------------- qemu/target-i386/helper.h | 2 +- qemu/target-i386/translate.c | 25 +++++++----------------- qemu/target-m68k/helper.h | 2 +- qemu/target-m68k/translate.c | 20 ++++++------------- qemu/target-mips/helper.h | 2 +- qemu/target-mips/translate.c | 34 ++++++++++----------------------- qemu/target-sparc/helper.h | 2 +- qemu/target-sparc/translate.c | 26 ++++++++----------------- qemu/tcg/tcg-op.h | 7 +++---- qemu/translate-all.c | 2 +- uc.c | 12 +++++++++--- 15 files changed, 66 insertions(+), 121 deletions(-) diff --git a/list.c b/list.c index 695f5a24..6dbe4782 100644 --- a/list.c +++ b/list.c @@ -18,6 +18,8 @@ void list_clear(struct list *list) free(cur); cur = next; } + list->head = NULL; + list->tail = NULL; } // returns generated linked list node, or NULL on failure diff --git a/qemu/target-arm/helper.h b/qemu/target-arm/helper.h index d2de58d6..6427c18c 100644 --- a/qemu/target-arm/helper.h +++ b/qemu/target-arm/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_FLAGS_1(clz_arm, TCG_CALL_NO_RWG_SE, i32, i32) diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 28d57681..06378453 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -10970,7 +10970,6 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn) static void disas_a64_insn(CPUARMState *env, DisasContext *s) { uint32_t insn; - struct hook *hook; TCGContext *tcg_ctx = env->uc->tcg_ctx; // Unicorn: end address tells us to stop emulation @@ -10985,10 +10984,8 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s) s->pc += 4; // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, env->uc, s->pc - 4, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc - 4)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, env->uc, s->pc - 4); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -11044,7 +11041,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; pc_start = tb->pc; @@ -11116,14 +11112,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index bf190452..d097c236 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -7680,7 +7680,6 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq TCGv_i32 tmp3; TCGv_i32 addr; TCGv_i64 tmp64; - struct hook *hook; /* M variants do not implement ARM mode. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { @@ -7688,10 +7687,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn) // qq } // Unicorn: trace this instruction on request - HOOK_FOREACH(s->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc - 4)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, s->uc, s->pc - 4, hook->user_data); + if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc - 4)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, s->uc, s->pc - 4); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -10391,7 +10388,6 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq TCGv_i32 tmp; TCGv_i32 tmp2; TCGv_i32 addr; - struct hook *hook; // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { @@ -10410,11 +10406,9 @@ static void disas_thumb_insn(CPUARMState *env, DisasContext *s) // qq } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); - // check to see if we need to exit immediately + if (HOOK_EXISTS_BOUNDED(s->uc, UC_HOOK_CODE, s->pc)) { + gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, s->uc, s->pc); + // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -11147,7 +11141,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; /* generate intermediate code */ @@ -11237,14 +11230,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-i386/helper.h b/qemu/target-i386/helper.h index 8ab196ac..d3b52d1f 100644 --- a/qemu/target-i386/helper.h +++ b/qemu/target-i386/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_FLAGS_4(cc_compute_all, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int) DEF_HELPER_FLAGS_4(cc_compute_c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl, int) diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index 0d83f4bd..d68cb516 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -4745,7 +4745,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, TCGv cpu_tmp4 = *(TCGv *)tcg_ctx->cpu_tmp4; TCGv **cpu_T = (TCGv **)tcg_ctx->cpu_T; TCGv **cpu_regs = (TCGv **)tcg_ctx->cpu_regs; - struct hook *hook = NULL; TCGArg *save_opparam_ptr = tcg_ctx->gen_opparam_ptr; bool cc_op_dirty = s->cc_op_dirty; bool changed_cc_op = false; @@ -4773,14 +4772,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, s->last_cc_op = s->cc_op; changed_cc_op = true; } - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // generate code to call callback - gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, hook->callback, env->uc, pc_start, hook->user_data); - // the callback might want to stop emulation immediately - check_exit_request(tcg_ctx); - } + gen_uc_tracecode(tcg_ctx, 0xf1f1f1f1, UC_HOOK_CODE_IDX, env->uc, pc_start); + // the callback might want to stop emulation immediately + check_exit_request(tcg_ctx); } prefixes = 0; @@ -8173,7 +8167,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, gen_helper_unlock(tcg_ctx, cpu_env); // Unicorn: patch the callback for the instruction size - if (hook) { + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, pc_start)) { // int i; // for(i = 0; i < 20; i++) // printf("=== [%u] = %x\n", i, *(save_opparam_ptr + i)); @@ -8282,7 +8276,6 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, int num_insns = 0; int max_insns; bool block_full = false; - struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -8388,13 +8381,9 @@ static inline void gen_intermediate_code_internal(uint8_t *gen_opc_cc_op, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-m68k/helper.h b/qemu/target-m68k/helper.h index 865cf95d..caaadb3a 100644 --- a/qemu/target-m68k/helper.h +++ b/qemu/target-m68k/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_1(bitrev, i32, i32) DEF_HELPER_1(ff1, i32, i32) diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index 0f685d8e..bf45a66a 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3031,7 +3031,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) { TCGContext *tcg_ctx = s->uc->tcg_ctx; uint16_t insn; - struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, s->pc); @@ -3044,10 +3043,8 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, s->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 2, hook->callback, env->uc, s->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, s->pc)) { + gen_uc_tracecode(tcg_ctx, 2, UC_HOOK_CODE_IDX, env->uc, s->pc); // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); } @@ -3075,7 +3072,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, int max_insns; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; /* generate intermediate code */ pc_start = tb->pc; @@ -3110,14 +3106,10 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index 81f733c2..1924bf6f 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) DEF_HELPER_2(raise_exception, noreturn, env, i32) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index fadbaeb0..8802c221 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -11331,7 +11331,6 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n int op, cnvt_op, op1, offset; int funct; int n_bytes; - struct hook *hook; op = (ctx->opcode >> 11) & 0x1f; sa = (ctx->opcode >> 2) & 0x7; @@ -11344,10 +11343,8 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool *insn_n n_bytes = 2; // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -13932,7 +13929,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; uint32_t op; - struct hook *hook; /* make sure instructions are on a halfword boundary */ if (ctx->pc & 0x1) { @@ -13943,10 +13939,8 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins } // Unicorn: trace this instruction on request - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -18505,11 +18499,8 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx) static void hook_insn(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_patch, int *insn_patch_offset, int offset_value) { TCGContext *tcg_ctx = ctx->uc->tcg_ctx; - struct hook *hook; - HOOK_FOREACH(env->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, ctx->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, ctx->pc, hook->user_data); + if (HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_CODE, ctx->pc)) { + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_CODE_IDX, env->uc, ctx->pc); *insn_need_patch = true; // the callback might want to stop emulation immediately check_exit_request(tcg_ctx); @@ -19178,7 +19169,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGArg *save_opparam_ptr = NULL; bool block_full = false; - struct hook *hook; if (search_pc) qemu_log("search pc %d\n", search_pc); @@ -19224,14 +19214,10 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/target-sparc/helper.h b/qemu/target-sparc/helper.h index 2557dd08..503e1e5c 100644 --- a/qemu/target-sparc/helper.h +++ b/qemu/target-sparc/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_5(uc_tracecode, void, i32, ptr, ptr, i64, ptr) +DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_1(power_down, void, env) #ifndef TARGET_SPARC64 diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index 8caba2b7..a7f067cf 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -2625,7 +2625,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32; TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64; target_long simm; - struct hook *hook; if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) { tcg_gen_debug_insn_start(tcg_ctx, dc->pc); @@ -2638,14 +2637,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins } // Unicorn: trace this instruction on request - if (hook_insn) { - HOOK_FOREACH(dc->uc, hook, UC_HOOK_CODE) { - if (! HOOK_BOUND_CHECK(hook, dc->pc)) - continue; - gen_uc_tracecode(tcg_ctx, 4, hook->callback, dc->uc, dc->pc, hook->user_data); - // the callback might want to stop emulation immediately - check_exit_request(tcg_ctx); - } + if (hook_insn && HOOK_EXISTS_BOUNDED(dc->uc, UC_HOOK_CODE, dc->pc)) { + gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, dc->uc, dc->pc); + // the callback might want to stop emulation immediately + check_exit_request(tcg_ctx); } opc = GET_FIELD(insn, 0, 1); @@ -5390,7 +5385,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, unsigned int insn; TCGContext *tcg_ctx = env->uc->tcg_ctx; bool block_full = false; - struct hook *hook; memset(dc, 0, sizeof(DisasContext)); dc->uc = env->uc; @@ -5431,14 +5425,10 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (!env->uc->block_full) { - HOOK_FOREACH(env->uc, hook, UC_HOOK_BLOCK) { - if (! HOOK_BOUND_CHECK(hook, pc_start)) - continue; - // save block address to see if we need to patch block size later - env->uc->block_addr = pc_start; - gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, hook->callback, env->uc, pc_start, hook->user_data); - } + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + // save block address to see if we need to patch block size later + env->uc->block_addr = pc_start; + gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); } gen_tb_start(tcg_ctx); diff --git a/qemu/tcg/tcg-op.h b/qemu/tcg/tcg-op.h index 9f096a3d..87358240 100644 --- a/qemu/tcg/tcg-op.h +++ b/qemu/tcg/tcg-op.h @@ -27,14 +27,13 @@ int gen_new_label(TCGContext *); -static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, void *callback, void *uc, uint64_t pc, void *data) +static inline void gen_uc_tracecode(TCGContext *tcg_ctx, int32_t size, int32_t type, void *uc, uint64_t pc) { TCGv_i32 tsize = tcg_const_i32(tcg_ctx, size); - TCGv_ptr tcallback = tcg_const_ptr(tcg_ctx, callback); + TCGv_i32 ttype = tcg_const_i32(tcg_ctx, type); TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, uc); TCGv_i64 tpc = tcg_const_i64(tcg_ctx, pc); - TCGv_ptr tdata = tcg_const_ptr(tcg_ctx, data); - gen_helper_uc_tracecode(tcg_ctx, tsize, tcallback, tuc, tpc, tdata); + gen_helper_uc_tracecode(tcg_ctx, tsize, ttype, tuc, tpc); } static inline void tcg_gen_op0(TCGContext *s, TCGOpcode opc) diff --git a/qemu/translate-all.c b/qemu/translate-all.c index 72e1b60f..aec38c7c 100644 --- a/qemu/translate-all.c +++ b/qemu/translate-all.c @@ -179,7 +179,7 @@ static int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_s gen_intermediate_code(env, tb); // Unicorn: when tracing block, patch 1st operand for block size - if (HOOK_EXISTS(env->uc, UC_HOOK_BLOCK) && env->uc->block_addr == tb->pc) { + if (env->uc->block_addr == tb->pc && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, tb->pc)) { if (env->uc->block_full) // block size is unknown *(s->gen_opparam_buf + 1) = 0; else diff --git a/uc.c b/uc.c index f7f40853..b0f8a976 100644 --- a/uc.c +++ b/uc.c @@ -1009,17 +1009,23 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) } // TCG helper -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data); -void helper_uc_tracecode(int32_t size, void *callback, void *handle, int64_t address, void *user_data) +void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address); +void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t address) { struct uc_struct *uc = handle; + struct list_item *cur = uc->hook[type].head; + struct hook *hook; // sync PC in CPUArchState with address if (uc->set_pc) { uc->set_pc(uc, address); } - ((uc_cb_hookcode_t)callback)(uc, address, size, user_data); + while (cur != NULL && !uc->stop_request) { + hook = (struct hook *)cur->data; + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + cur = cur->next; + } } UNICORN_EXPORT From 9f9bd7098baa30e83975a56d5cfc87b38f3a0bd1 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Fri, 22 Jan 2016 19:24:45 -0800 Subject: [PATCH 53/77] patch hook bounds to be inclusive --- include/uc_priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index a55c847e..902f9c47 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -101,7 +101,7 @@ enum uc_hook_idx { // if statement to check hook bounds #define HOOK_BOUND_CHECK(hh, addr) \ - ((((addr) >= (hh)->begin && (addr) < (hh)->end) \ + ((((addr) >= (hh)->begin && (addr) <= (hh)->end) \ || (hh)->begin > (hh)->end)) #define HOOK_EXISTS(uc, idx) ((uc)->hook[idx##_IDX].head != NULL) From 1974b23164b287505307a62acf046c3306ef7a5a Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Fri, 22 Jan 2016 19:55:31 -0800 Subject: [PATCH 54/77] add begin>end to samples/mem_apis --- samples/mem_apis.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 50554eeb..bd0d81ba 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -170,7 +170,7 @@ static void do_nx_demo(bool cause_fault) // intercept code and invalid memory events if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL) != UC_ERR_OK) { + hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -251,7 +251,7 @@ static void do_perms_demo(bool change_perms) if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL) != UC_ERR_OK) { + hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -329,7 +329,7 @@ static void do_unmap_demo(bool do_unmap) if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK || uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL) != UC_ERR_OK) { + hook_mem_invalid, NULL, (uint64_t)1, (uint64_t)0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } From 9c2017e115caf4b417b6f27f3cc3299a4317bf7a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 17:08:40 +0800 Subject: [PATCH 55/77] update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4f82c74a..e0d13af9 100644 --- a/.gitignore +++ b/.gitignore @@ -134,6 +134,7 @@ test_mem_high rw_hookstack hook_extrainvoke sysenter_hook_x86 +test_tb_x86 ################# From 4dbad9aa9b97be57a2c1bd84cab48d3d9b683cb8 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sat, 23 Jan 2016 17:14:44 +0800 Subject: [PATCH 56/77] add new API uc_query() to query internal status of emulator at runtime --- include/uc_priv.h | 3 +++ include/unicorn/unicorn.h | 18 ++++++++++++++++++ qemu/target-arm/unicorn_arm.c | 14 ++++++++++++++ uc.c | 12 ++++++++++++ 4 files changed, 47 insertions(+) diff --git a/include/uc_priv.h b/include/uc_priv.h index 589a655f..c4e0e176 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -32,6 +32,8 @@ typedef struct ModuleEntry { typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList; +typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result); + // return 0 on success, -1 on failure typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int regid, void *value); typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int regid, const void *value); @@ -93,6 +95,7 @@ struct uc_struct { struct CPUTailQ cpus; // qemu/cpu-exec.c uc_err errnum; // qemu/cpu-exec.c AddressSpace as; + query_t query; reg_read_t reg_read; reg_write_t reg_write; reg_reset_t reg_reset; diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index a6bedfaf..d5cd1422 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -255,6 +255,12 @@ typedef struct uc_mem_region { uint32_t perms; // memory permissions of the region } uc_mem_region; +// All type of queries for uc_query() API. +typedef enum uc_query_type { + // Query current hardware mode for ARM. Return 1 for Thumb, 0 for ARM + UC_QUERY_ARM_MODE = 1, +} uc_query_type; + /* Return combined API version & major and minor version numbers. @@ -315,6 +321,18 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **uc); UNICORN_EXPORT uc_err uc_close(uc_engine *uc); +/* + Query internal status of engine. + + @uc: handle returned by uc_open() + @type: query type + @result: status retrieved + + @return: error code of uc_err enum type (UC_ERR_*, see above) +*/ +UNICORN_EXPORT +uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result); + /* Report the last error number when some API function fail. Like glibc's errno, uc_errno might not retain its old value once accessed. diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 5065c0f3..0a64d151 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -108,6 +108,19 @@ static bool arm_stop_interrupt(int intno) } } +static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result) +{ + CPUState *mycpu = first_cpu; + + switch(type) { + case UC_QUERY_ARM_MODE: + *result = (ARM_CPU(uc, mycpu)->env.thumb != 0); + return UC_ERR_OK; + default: + return UC_ERR_ARG; + } +} + void arm_uc_init(struct uc_struct* uc) { register_accel_types(uc); @@ -118,5 +131,6 @@ void arm_uc_init(struct uc_struct* uc) uc->reg_reset = arm_reg_reset; uc->set_pc = arm_set_pc; uc->stop_interrupt = arm_stop_interrupt; + uc->query = arm_query; uc_common_init(uc); } diff --git a/uc.c b/uc.c index 95a9c48e..d93fa4e5 100644 --- a/uc.c +++ b/uc.c @@ -1190,3 +1190,15 @@ uint32_t uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) return UC_ERR_OK; } +UNICORN_EXPORT +uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) +{ + switch(uc->arch) { + case UC_ARCH_ARM: + return uc->query(uc, type, result); + default: + return UC_ERR_ARG; + } + + return UC_ERR_OK; +} From 6f3d48077ef0c3cfa2c083ac0ad5f84706613442 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 24 Jan 2016 01:08:23 +0800 Subject: [PATCH 57/77] rename UC_QUERY_ARM_MODE to a more generic name UC_QUERY_MODE. make all bindings support this new constant --- bindings/dotnet/UnicornManaged/Const/Common.fs | 1 + bindings/go/unicorn/unicorn_const.go | 1 + bindings/java/unicorn/UnicornConst.java | 1 + bindings/python/unicorn/unicorn_const.py | 1 + include/unicorn/unicorn.h | 10 ++++++---- qemu/target-arm/unicorn_arm.c | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 3ec03c74..4dce96df 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -90,6 +90,7 @@ module Common = let UC_HOOK_MEM_WRITE_INVALID = 288 let UC_HOOK_MEM_FETCH_INVALID = 576 let UC_HOOK_MEM_INVALID = 1008 + let UC_QUERY_MODE = 1 let UC_PROT_NONE = 0 let UC_PROT_READ = 1 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 2d8d2c1a..8fb6d3f4 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -85,6 +85,7 @@ const ( HOOK_MEM_WRITE_INVALID = 288 HOOK_MEM_FETCH_INVALID = 576 HOOK_MEM_INVALID = 1008 + QUERY_MODE = 1 PROT_NONE = 0 PROT_READ = 1 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 5967d26b..7203fbd0 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -87,6 +87,7 @@ public interface UnicornConst { public static final int UC_HOOK_MEM_WRITE_INVALID = 288; public static final int UC_HOOK_MEM_FETCH_INVALID = 576; public static final int UC_HOOK_MEM_INVALID = 1008; + public static final int UC_QUERY_MODE = 1; public static final int UC_PROT_NONE = 0; public static final int UC_PROT_READ = 1; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index a1967684..dd4c6d16 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -83,6 +83,7 @@ UC_HOOK_MEM_READ_INVALID = 144 UC_HOOK_MEM_WRITE_INVALID = 288 UC_HOOK_MEM_FETCH_INVALID = 576 UC_HOOK_MEM_INVALID = 1008 +UC_QUERY_MODE = 1 UC_PROT_NONE = 0 UC_PROT_READ = 1 diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d5cd1422..6ecd6dc2 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -257,8 +257,9 @@ typedef struct uc_mem_region { // All type of queries for uc_query() API. typedef enum uc_query_type { - // Query current hardware mode for ARM. Return 1 for Thumb, 0 for ARM - UC_QUERY_ARM_MODE = 1, + // Dynamically query current hardware mode. + // For ARM, uc_query() return 1 for Thumb mode, and 0 for Arm mode + UC_QUERY_MODE = 1, } uc_query_type; /* @@ -325,8 +326,9 @@ uc_err uc_close(uc_engine *uc); Query internal status of engine. @uc: handle returned by uc_open() - @type: query type - @result: status retrieved + @type: query type. See uc_query_type + + @result: save the internal status queried @return: error code of uc_err enum type (UC_ERR_*, see above) */ diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 0a64d151..15906deb 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -113,7 +113,7 @@ static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result CPUState *mycpu = first_cpu; switch(type) { - case UC_QUERY_ARM_MODE: + case UC_QUERY_MODE: *result = (ARM_CPU(uc, mycpu)->env.thumb != 0); return UC_ERR_OK; default: From 26d3b1e7d6a1372cbaf72375b55d95bc41757816 Mon Sep 17 00:00:00 2001 From: xorstream Date: Sun, 24 Jan 2016 22:27:33 +1100 Subject: [PATCH 58/77] Added ppc 32bit mode and added sparc mode checks to bring it in line with other archs --- include/unicorn/unicorn.h | 1 + samples/sample_sparc.c | 2 +- tests/regress/sparc_jump_to_zero.c | 2 +- uc.c | 4 +++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 6ecd6dc2..11772b9a 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -104,6 +104,7 @@ typedef enum uc_mode { UC_MODE_32 = 1 << 2, // 32-bit mode UC_MODE_64 = 1 << 3, // 64-bit mode // ppc + UC_MODE_PPC32 = 1 << 2, // 32-bit mode (currently unsupported) UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) // sparc diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 88bbd01e..e6276b14 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -57,7 +57,7 @@ static void test_sparc(void) printf("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32, &uc); + err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &uc); if (err) { printf("Failed on uc_open() with error returned: %u (%s)\n", err, uc_strerror(err)); diff --git a/tests/regress/sparc_jump_to_zero.c b/tests/regress/sparc_jump_to_zero.c index c816b700..2baaa69f 100644 --- a/tests/regress/sparc_jump_to_zero.c +++ b/tests/regress/sparc_jump_to_zero.c @@ -1,7 +1,7 @@ #include #define HARDWARE_ARCHITECTURE UC_ARCH_SPARC -#define HARDWARE_MODE UC_ARCH_SPARC32 +#define HARDWARE_MODE UC_ARCH_SPARC32|UC_MODE_BIG_ENDIAN #define MEMORY_STARTING_ADDRESS 0x1000000 #define MEMORY_SIZE 2 * 1024 * 1024 diff --git a/uc.c b/uc.c index d93fa4e5..1a419e8c 100644 --- a/uc.c +++ b/uc.c @@ -245,7 +245,9 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) #ifdef UNICORN_HAS_SPARC case UC_ARCH_SPARC: - if (mode & ~UC_MODE_SPARC_MASK) { + if ((mode & ~UC_MODE_SPARC_MASK) || + !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_SPARC32|UC_MODE_SPARC64))) { free(uc); return UC_ERR_MODE; } From ec6d4d9ae016a884682f3fe31476a287d457782f Mon Sep 17 00:00:00 2001 From: xorstream Date: Sun, 24 Jan 2016 22:36:37 +1100 Subject: [PATCH 59/77] Removed unneeded arm mode check --- uc.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/uc.c b/uc.c index 1a419e8c..06c15f7e 100644 --- a/uc.c +++ b/uc.c @@ -506,14 +506,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time break; case UC_ARCH_ARM: - switch(uc->mode) { - default: - break; - case UC_MODE_THUMB: - case UC_MODE_ARM: - uc_reg_write(uc, UC_ARM_REG_R15, &begin); - break; - } + uc_reg_write(uc, UC_ARM_REG_R15, &begin); break; case UC_ARCH_ARM64: From 9ec216357137e6d03532488d9b617784a6940b84 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 24 Jan 2016 20:50:26 +0800 Subject: [PATCH 60/77] bindings: add UC_MODE_PPC32 constant after recent update on unicorn.h --- bindings/dotnet/UnicornManaged/Const/Common.fs | 1 + bindings/go/unicorn/unicorn_const.go | 1 + bindings/java/unicorn/UnicornConst.java | 1 + bindings/python/unicorn/unicorn_const.py | 1 + 4 files changed, 4 insertions(+) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 4dce96df..5c5d5a2e 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -35,6 +35,7 @@ module Common = let UC_MODE_16 = 2 let UC_MODE_32 = 4 let UC_MODE_64 = 8 + let UC_MODE_PPC32 = 4 let UC_MODE_PPC64 = 8 let UC_MODE_QPX = 16 let UC_MODE_SPARC32 = 4 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 8fb6d3f4..ef08e0c5 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -30,6 +30,7 @@ const ( MODE_16 = 2 MODE_32 = 4 MODE_64 = 8 + MODE_PPC32 = 4 MODE_PPC64 = 8 MODE_QPX = 16 MODE_SPARC32 = 4 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index 7203fbd0..d68a5f04 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -32,6 +32,7 @@ public interface UnicornConst { public static final int UC_MODE_16 = 2; public static final int UC_MODE_32 = 4; public static final int UC_MODE_64 = 8; + public static final int UC_MODE_PPC32 = 4; public static final int UC_MODE_PPC64 = 8; public static final int UC_MODE_QPX = 16; public static final int UC_MODE_SPARC32 = 4; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index dd4c6d16..fa635b15 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -28,6 +28,7 @@ UC_MODE_MIPS64 = 8 UC_MODE_16 = 2 UC_MODE_32 = 4 UC_MODE_64 = 8 +UC_MODE_PPC32 = 4 UC_MODE_PPC64 = 8 UC_MODE_QPX = 16 UC_MODE_SPARC32 = 4 From 7973f6b4c9642ef86b54c1904b9d29c7091a615b Mon Sep 17 00:00:00 2001 From: xorstream Date: Mon, 25 Jan 2016 13:50:26 +1100 Subject: [PATCH 61/77] Added mode endian flags for sparc tests and fixed mode in sparc_jump_to_zero.c --- tests/regress/sparc64.py | 2 +- tests/regress/sparc_jump_to_zero.c | 2 +- tests/regress/sparc_reg.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/regress/sparc64.py b/tests/regress/sparc64.py index 12d3f547..34307639 100755 --- a/tests/regress/sparc64.py +++ b/tests/regress/sparc64.py @@ -5,7 +5,7 @@ from unicorn.sparc_const import * PAGE_SIZE = 1 * 1024 * 1024 -uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC64) +uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN) uc.reg_write(UC_SPARC_REG_SP, 100) print 'writing sp = 100' diff --git a/tests/regress/sparc_jump_to_zero.c b/tests/regress/sparc_jump_to_zero.c index 2baaa69f..538405f3 100644 --- a/tests/regress/sparc_jump_to_zero.c +++ b/tests/regress/sparc_jump_to_zero.c @@ -1,7 +1,7 @@ #include #define HARDWARE_ARCHITECTURE UC_ARCH_SPARC -#define HARDWARE_MODE UC_ARCH_SPARC32|UC_MODE_BIG_ENDIAN +#define HARDWARE_MODE UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN #define MEMORY_STARTING_ADDRESS 0x1000000 #define MEMORY_SIZE 2 * 1024 * 1024 diff --git a/tests/regress/sparc_reg.py b/tests/regress/sparc_reg.py index da6987d1..3d55065f 100755 --- a/tests/regress/sparc_reg.py +++ b/tests/regress/sparc_reg.py @@ -5,7 +5,7 @@ from unicorn.sparc_const import * PAGE_SIZE = 1 * 1024 * 1024 -uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32) +uc = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN) uc.reg_write(UC_SPARC_REG_SP, 100) uc.reg_write(UC_SPARC_REG_FP, 200) From a640b76b94e71613c40394d1ee9d87b2afdece34 Mon Sep 17 00:00:00 2001 From: Willi Ballenthin Date: Sun, 24 Jan 2016 22:46:13 -0500 Subject: [PATCH 62/77] qemu-thread-posix: bail on mutex errors partially addresses #400 --- qemu/util/qemu-thread-posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qemu/util/qemu-thread-posix.c b/qemu/util/qemu-thread-posix.c index 26cba2da..6430f929 100644 --- a/qemu/util/qemu-thread-posix.c +++ b/qemu/util/qemu-thread-posix.c @@ -29,8 +29,8 @@ static void error_exit(int err, const char *msg) { - // fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err)); - // abort(); + fprintf(stderr, "qemu: %s: %s\n", msg, strerror(err)); + abort(); } void qemu_mutex_init(QemuMutex *mutex) From bc0003188e51ccc84ddec2a9c62bd579304851ef Mon Sep 17 00:00:00 2001 From: xorstream Date: Mon, 25 Jan 2016 17:42:51 +1100 Subject: [PATCH 63/77] uc_mode fixes for bindings --- bindings/java/samples/Sample_mips.java | 2 +- bindings/java/samples/Sample_sparc.java | 2 +- bindings/python/sample_sparc.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/java/samples/Sample_mips.java b/bindings/java/samples/Sample_mips.java index 58191acd..8220c42c 100644 --- a/bindings/java/samples/Sample_mips.java +++ b/bindings/java/samples/Sample_mips.java @@ -113,7 +113,7 @@ public class Sample_mips { System.out.print("Emulate MIPS code (little-endian)\n"); // Initialize emulator in MIPS mode - Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32); + Unicorn u = new Unicorn(Unicorn.UC_ARCH_MIPS, Unicorn.UC_MODE_MIPS32 + Unicorn.UC_MODE_LITTLE_ENDIAN); // map 2MB memory for this emulation u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL); diff --git a/bindings/java/samples/Sample_sparc.java b/bindings/java/samples/Sample_sparc.java index 60298979..71ebdb3f 100644 --- a/bindings/java/samples/Sample_sparc.java +++ b/bindings/java/samples/Sample_sparc.java @@ -76,7 +76,7 @@ public class Sample_sparc { System.out.print("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_32); + Unicorn u = new Unicorn(Unicorn.UC_ARCH_SPARC, Unicorn.UC_MODE_32 + Unicorn.UC_MODE_BIG_ENDIAN); // map 2MB memory for this emulation u.mem_map(ADDRESS, 2 * 1024 * 1024, Unicorn.UC_PROT_ALL); diff --git a/bindings/python/sample_sparc.py b/bindings/python/sample_sparc.py index a8bdd586..ad47d387 100755 --- a/bindings/python/sample_sparc.py +++ b/bindings/python/sample_sparc.py @@ -28,7 +28,7 @@ def test_sparc(): print("Emulate SPARC code") try: # Initialize emulator in SPARC EB mode - mu = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32) + mu = Uc(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN) # map 2MB memory for this emulation mu.mem_map(ADDRESS, 2 * 1024 * 1024) From cee9a7d01111de7c70f2881656139576db021d67 Mon Sep 17 00:00:00 2001 From: Ryan Hileman Date: Mon, 25 Jan 2016 03:51:35 -0800 Subject: [PATCH 64/77] fix missing HOOK_CODE bound check --- uc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/uc.c b/uc.c index b0f8a976..1d1ed539 100644 --- a/uc.c +++ b/uc.c @@ -1023,7 +1023,9 @@ void helper_uc_tracecode(int32_t size, uc_hook_type type, void *handle, int64_t while (cur != NULL && !uc->stop_request) { hook = (struct hook *)cur->data; - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + if (HOOK_BOUND_CHECK(hook, address)) { + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + } cur = cur->next; } } From 2341f5dd1aab8a0cdd20128b47535f07f16f613a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 26 Jan 2016 17:37:48 +0800 Subject: [PATCH 65/77] code style --- qemu/softmmu_template.h | 34 ++++++++++++++++----------------- qemu/target-arm/translate-a64.c | 2 +- qemu/target-i386/seg_helper.c | 4 ++-- qemu/target-mips/translate.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/qemu/softmmu_template.h b/qemu/softmmu_template.h index 1f636055..f58065b9 100644 --- a/qemu/softmmu_template.h +++ b/qemu/softmmu_template.h @@ -190,7 +190,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #if defined(SOFTMMU_CODE_ACCESS) error_code = UC_ERR_FETCH_UNMAPPED; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -198,7 +198,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #else error_code = UC_ERR_READ_UNMAPPED; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -221,7 +221,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -242,7 +242,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on memory read if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); } @@ -252,7 +252,7 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -402,7 +402,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #if defined(SOFTMMU_CODE_ACCESS) error_code = UC_ERR_FETCH_UNMAPPED; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -410,7 +410,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, #else error_code = UC_ERR_READ_UNMAPPED; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_UNMAPPED, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -433,7 +433,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, if (mr != NULL && !(mr->perms & UC_PROT_EXEC)) { // non-executable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_FETCH_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_FETCH_PROT, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -454,7 +454,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, // Unicorn: callback on memory read if (READ_ACCESS_TYPE == MMU_DATA_LOAD) { HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; ((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, addr, DATA_SIZE, 0, hook->user_data); } @@ -464,7 +464,7 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx, if (READ_ACCESS_TYPE == MMU_DATA_LOAD && mr != NULL && !(mr->perms & UC_PROT_READ)) { //non-readable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_READ_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_READ_PROT, addr, DATA_SIZE, 0, hook->user_data))) break; @@ -647,7 +647,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on memory write HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); } @@ -656,13 +656,13 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, if (mr == NULL) { handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, val, hook->user_data))) break; } - if (! handled) { + if (!handled) { // save error & quit env->invalid_addr = addr; env->invalid_error = UC_ERR_WRITE_UNMAPPED; @@ -679,7 +679,7 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, val, hook->user_data))) break; @@ -805,7 +805,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, // Unicorn: callback on memory write HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; ((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, addr, DATA_SIZE, val, hook->user_data); } @@ -814,7 +814,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, if (mr == NULL) { handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_UNMAPPED) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_UNMAPPED, addr, DATA_SIZE, val, hook->user_data))) break; @@ -837,7 +837,7 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, if (mr != NULL && !(mr->perms & UC_PROT_WRITE)) { //non-writable handled = false; HOOK_FOREACH(uc, hook, UC_HOOK_MEM_WRITE_PROT) { - if (! HOOK_BOUND_CHECK(hook, addr)) + if (!HOOK_BOUND_CHECK(hook, addr)) continue; if ((handled = ((uc_cb_eventmem_t)hook->callback)(uc, UC_MEM_WRITE_PROT, addr, DATA_SIZE, val, hook->user_data))) break; diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 06378453..e869da01 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -11112,7 +11112,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); diff --git a/qemu/target-i386/seg_helper.c b/qemu/target-i386/seg_helper.c index 4cf6e41a..4702dfcc 100644 --- a/qemu/target-i386/seg_helper.c +++ b/qemu/target-i386/seg_helper.c @@ -948,7 +948,7 @@ void helper_syscall(CPUX86State *env, int next_eip_addend) // Unicorn: call registered syscall hooks struct hook *hook; HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { - if (! HOOK_BOUND_CHECK(hook, env->eip)) + if (!HOOK_BOUND_CHECK(hook, env->eip)) continue; if (hook->insn == UC_X86_INS_SYSCALL) ((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data); @@ -2308,7 +2308,7 @@ void helper_sysenter(CPUX86State *env, int next_eip_addend) // Unicorn: call registered SYSENTER hooks struct hook *hook; HOOK_FOREACH(env->uc, hook, UC_HOOK_INSN) { - if (! HOOK_BOUND_CHECK(hook, env->eip)) + if (!HOOK_BOUND_CHECK(hook, env->eip)) continue; if (hook->insn == UC_X86_INS_SYSENTER) ((uc_cb_insn_syscall_t)hook->callback)(env->uc, hook->user_data); diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 8802c221..ea9aa453 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -19214,7 +19214,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, // Unicorn: trace this block on request // Only hook this block if it is not broken from previous translation due to // full translation cache - if (! env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { + if (!env->uc->block_full && HOOK_EXISTS_BOUNDED(env->uc, UC_HOOK_BLOCK, pc_start)) { // save block address to see if we need to patch block size later env->uc->block_addr = pc_start; gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, UC_HOOK_BLOCK_IDX, env->uc, pc_start); From 235bf0950b6ac6e75dee3c9094d1917eeb0181b2 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 26 Jan 2016 22:50:35 +0800 Subject: [PATCH 66/77] cosmetic change for mem_apis.c --- samples/mem_apis.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/mem_apis.c b/samples/mem_apis.c index bd0d81ba..008f077d 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -142,13 +142,13 @@ static void do_nx_demo(bool cause_fault) /* bits 32 - page0: + page0: @0 times 4091 inc eax jmp page2 - page1: - times 4095 inc eax + page1: @1000 + times 4095 inc eax (or INC ECX) hlt - page2: + page2: @2000 jmp page1 */ memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax From 876c423dd0d7db85db7e48be0955c09922245e4b Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Tue, 26 Jan 2016 23:12:35 +0800 Subject: [PATCH 67/77] python: support recent change on uc_hook_add() with begin/end params --- bindings/python/unicorn/unicorn.py | 39 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 08be9632..9fd9a896 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -314,25 +314,7 @@ class Uc(object): self._callbacks[self._callback_count] = (callback, user_data) cb = None - if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): - begin = ctypes.c_uint64(arg1) - end = ctypes.c_uint64(arg2) - # set callback with wrapper, so it can be called - # with this object as param - cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ - ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) - elif htype & UC_HOOK_MEM_READ_UNMAPPED or htype & UC_HOOK_MEM_WRITE_UNMAPPED or \ - htype & UC_HOOK_MEM_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \ - htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: - cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) - elif htype in (UC_HOOK_MEM_READ, UC_HOOK_MEM_WRITE, UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE): - cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB) - status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ - cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) - elif htype == UC_HOOK_INSN: + if htype == UC_HOOK_INSN: insn = ctypes.c_int(arg1) if arg1 == x86_const.UC_X86_INS_IN: # IN instruction cb = ctypes.cast(UC_HOOK_INSN_IN_CB(self._hook_insn_in_cb), UC_HOOK_INSN_IN_CB) @@ -346,6 +328,25 @@ class Uc(object): cb = ctypes.cast(UC_HOOK_INTR_CB(self._hook_intr_cb), UC_HOOK_INTR_CB) status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + else: + begin = ctypes.c_uint64(arg1) + end = ctypes.c_uint64(arg2) + if htype in (UC_HOOK_BLOCK, UC_HOOK_CODE): + # set callback with wrapper, so it can be called + # with this object as param + cb = ctypes.cast(UC_HOOK_CODE_CB(self._hookcode_cb), UC_HOOK_CODE_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, cb, \ + ctypes.cast(self._callback_count, ctypes.c_void_p), begin, end) + elif htype & UC_HOOK_MEM_READ_UNMAPPED or htype & UC_HOOK_MEM_WRITE_UNMAPPED or \ + htype & UC_HOOK_MEM_FETCH_UNMAPPED or htype & UC_HOOK_MEM_READ_PROT or \ + htype & UC_HOOK_MEM_WRITE_PROT or htype & UC_HOOK_MEM_FETCH_PROT: + cb = ctypes.cast(UC_HOOK_MEM_INVALID_CB(self._hook_mem_invalid_cb), UC_HOOK_MEM_INVALID_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) + else: + cb = ctypes.cast(UC_HOOK_MEM_ACCESS_CB(self._hook_mem_access_cb), UC_HOOK_MEM_ACCESS_CB) + status = _uc.uc_hook_add(self._uch, ctypes.byref(_h2), htype, \ + cb, ctypes.cast(self._callback_count, ctypes.c_void_p)) # save the ctype function so gc will leave it alone. self._ctype_cbs[self._callback_count] = cb From e750a4e97c4db33aa00866eb4875098b871ce4a8 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Thu, 28 Jan 2016 00:56:55 +0800 Subject: [PATCH 68/77] when uc_mem_exec() remove EXE permission, quit current TB & continue emulating with TB flushed. this fixes issue in PR #378 --- include/uc_priv.h | 1 + qemu/cpus.c | 8 +++++++- uc.c | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 44c116ea..0ef5a3dd 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -215,6 +215,7 @@ struct uc_struct { bool init_tcg; // already initialized local TCGv variables? bool stop_request; // request to immediately stop emulation - for uc_emu_stop() + bool quit_request; // request to quit the current TB, but continue to emulate - for uc_mem_protect() bool emulation_done; // emulation is done by uc_emu_start() QemuThread timer; // timer for emulation timeout uint64_t timeout; // timeout for uc_emu_start() diff --git a/qemu/cpus.c b/qemu/cpus.c index 98ee07c1..64c73b0b 100644 --- a/qemu/cpus.c +++ b/qemu/cpus.c @@ -231,8 +231,14 @@ static bool tcg_exec_all(struct uc_struct* uc) //qemu_clock_enable(QEMU_CLOCK_VIRTUAL, // (cpu->singlestep_enabled & SSTEP_NOTIMER) == 0); if (cpu_can_run(cpu)) { + uc->quit_request = false; r = tcg_cpu_exec(uc, env); - if (uc->stop_request) { + + // quit current TB but continue emulating? + if (uc->quit_request) { + // reset stop_request + uc->stop_request = false; + } else if (uc->stop_request) { //printf(">>> got STOP request!!!\n"); finish = true; break; diff --git a/uc.c b/uc.c index e66b9f82..06b08fca 100644 --- a/uc.c +++ b/uc.c @@ -826,6 +826,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 MemoryRegion *mr; uint64_t addr = address; size_t count, len; + bool remove_exec = false; if (size == 0) // trivial case, no change @@ -862,12 +863,22 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 return UC_ERR_NOMEM; mr = memory_mapping(uc, addr); + // will this remove EXEC permission? + if (((mr->perms & UC_PROT_EXEC) != 0) && ((perms & UC_PROT_EXEC) == 0)) + remove_exec = true; mr->perms = perms; uc->readonly_mem(mr, (perms & UC_PROT_WRITE) == 0); count += len; addr += len; } + + // if EXEC permission is removed, then quit TB and continue at the same place + if (remove_exec) { + uc->quit_request = true; + uc_emu_stop(uc); + } + return UC_ERR_OK; } From 5a04bcb115052835c680a5466ef1cc475bfc2e4d Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Thu, 28 Jan 2016 14:06:17 +0800 Subject: [PATCH 69/77] allow to change PC during callback. this solves issue #210 --- .gitignore | 2 + qemu/cpu-exec.c | 2 + qemu/target-arm/unicorn_aarch64.c | 3 + qemu/target-arm/unicorn_arm.c | 3 + qemu/target-i386/unicorn.c | 15 +++++ qemu/target-m68k/unicorn.c | 3 + qemu/target-mips/unicorn.c | 3 + qemu/target-sparc/unicorn.c | 3 + tests/unit/Makefile | 4 +- tests/unit/test_pc_change.c | 104 ++++++++++++++++++++++++++++++ uc.c | 3 +- 11 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 tests/unit/test_pc_change.c diff --git a/.gitignore b/.gitignore index e0d13af9..d3ddf440 100644 --- a/.gitignore +++ b/.gitignore @@ -135,6 +135,8 @@ rw_hookstack hook_extrainvoke sysenter_hook_x86 test_tb_x86 +test_multihook +test_pc_change ################# diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 33246009..6fd497bf 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -66,6 +66,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq uintptr_t next_tb; struct hook *hook; + /* This must be volatile so it is not trashed by longjmp() */ volatile bool have_tb_lock = false; @@ -100,6 +101,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq if (sigsetjmp(cpu->jmp_env, 0) == 0) { if (uc->stop_request || uc->invalid_error) break; + /* if an exception is pending, we execute it here */ if (cpu->exception_index >= 0) { //printf(">>> GOT INTERRUPT. exception idx = %x\n", cpu->exception_index); // qq diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index 0123b5cb..1ce9d6eb 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -82,6 +82,9 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) break; case UC_ARM64_REG_PC: ARM_CPU(uc, mycpu)->env.pc = *(uint64_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_ARM64_REG_SP: ARM_CPU(uc, mycpu)->env.xregs[31] = *(uint64_t *)value; diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 15906deb..63f2c3f5 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -91,6 +91,9 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) //case UC_ARM_REG_PC: case UC_ARM_REG_R15: ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; } } diff --git a/qemu/target-i386/unicorn.c b/qemu/target-i386/unicorn.c index 11bb8232..0af5763e 100644 --- a/qemu/target-i386/unicorn.c +++ b/qemu/target-i386/unicorn.c @@ -656,9 +656,15 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) break; case UC_X86_REG_EIP: X86_CPU(uc, mycpu)->env.eip = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_X86_REG_IP: WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_X86_REG_CS: X86_CPU(uc, mycpu)->env.segs[R_CS].base = *(uint32_t *)value; @@ -806,12 +812,21 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) break; case UC_X86_REG_RIP: X86_CPU(uc, mycpu)->env.eip = *(uint64_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_X86_REG_EIP: WRITE_DWORD(X86_CPU(uc, mycpu)->env.eip, *(uint32_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_X86_REG_IP: WRITE_WORD(X86_CPU(uc, mycpu)->env.eip, *(uint16_t *)value); + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; case UC_X86_REG_CS: X86_CPU(uc, mycpu)->env.segs[R_CS].base = *(uint64_t *)value; diff --git a/qemu/target-m68k/unicorn.c b/qemu/target-m68k/unicorn.c index df732405..0055d4a1 100644 --- a/qemu/target-m68k/unicorn.c +++ b/qemu/target-m68k/unicorn.c @@ -70,6 +70,9 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) default: break; case UC_M68K_REG_PC: M68K_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; } } diff --git a/qemu/target-mips/unicorn.c b/qemu/target-mips/unicorn.c index 3885d02d..6af98dce 100644 --- a/qemu/target-mips/unicorn.c +++ b/qemu/target-mips/unicorn.c @@ -81,6 +81,9 @@ int mips_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) default: break; case UC_MIPS_REG_PC: MIPS_CPU(uc, mycpu)->env.active_tc.PC = *(uint32_t *)value; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; } } diff --git a/qemu/target-sparc/unicorn.c b/qemu/target-sparc/unicorn.c index d86497b5..e612457b 100644 --- a/qemu/target-sparc/unicorn.c +++ b/qemu/target-sparc/unicorn.c @@ -87,6 +87,9 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) case UC_SPARC_REG_PC: SPARC_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; SPARC_CPU(uc, mycpu)->env.npc = *(uint32_t *)value + 4; + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); break; } } diff --git a/tests/unit/Makefile b/tests/unit/Makefile index cd0e46eb..67376fd2 100644 --- a/tests/unit/Makefile +++ b/tests/unit/Makefile @@ -5,7 +5,7 @@ CFLAGS += -lcmocka -lunicorn CFLAGS += -I ../../include ALL_TESTS = test_sanity test_x86 test_mem_map test_mem_high test_mem_map_ptr \ - test_tb_x86 test_multihook + test_tb_x86 test_multihook test_pc_change .PHONY: all all: ${ALL_TESTS} @@ -24,6 +24,7 @@ test: ${ALL_TESTS} ./test_mem_high ./test_tb_x86 ./test_multihook + ./test_pc_change test_sanity: test_sanity.c test_x86: test_x86.c @@ -32,6 +33,7 @@ test_mem_map_ptr: test_mem_map_ptr.c test_mem_high: test_mem_high.c test_tb_x86: test_tb_x86.c test_multihook: test_multihook.c +test_pc_change: test_pc_change.c ${ALL_TESTS}: ${CC} ${CFLAGS} -o $@ $^ diff --git a/tests/unit/test_pc_change.c b/tests/unit/test_pc_change.c new file mode 100644 index 00000000..7994e772 --- /dev/null +++ b/tests/unit/test_pc_change.c @@ -0,0 +1,104 @@ +// Test PC change during the callback. by Nguyen Anh Quynh, 2016 +#include "unicorn_test.h" +#include + +#define OK(x) uc_assert_success(x) + +/* Called before every test to set up a new instance */ +static int setup32(void **state) +{ + uc_engine *uc; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + + *state = uc; + return 0; +} + +/* Called after every test to clean up */ +static int teardown(void **state) +{ + uc_engine *uc = *state; + + OK(uc_close(uc)); + + *state = NULL; + return 0; +} + +/******************************************************************************/ + +static void test_code_hook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +{ + uint8_t tmp[256]; + int32_t r_eip = 0x1000006; + printf("instruction at 0x%"PRIx64": ", address); + + if (!uc_mem_read(uc, address, tmp, size)) { + uint32_t i; + + for (i = 0; i < size; i++) { + printf("0x%x ", tmp[i]); + } + printf("\n"); + } + + if (address == 0x1000003) { + // change the PC to "inc EDX" + uc_reg_write(uc, UC_X86_REG_EIP, &r_eip); + } +} + +static void test_pc_change(void **state) +{ + uc_engine *uc = *state; + uc_hook trace1; + int32_t r_ecx = 3, r_edx = 15; + +#define BASEADDR 0x1000000 + + uint64_t address = BASEADDR; + const uint8_t code[] = { + 0x41, // inc ECX @0x1000000 + 0x41, // inc ECX + 0x41, // inc ECX + 0x41, // inc ECX @0x1000003 + 0x41, // inc ECX + 0x41, // inc ECX + + 0x42, // inc EDX @0x1000006 + 0x42, // inc EDX + }; + +#undef BASEADDR + + // map 2MB memory for this emulation + OK(uc_mem_map(uc, address, 2 * 1024 * 1024, UC_PROT_ALL)); + + // write machine code to be emulated to memory + OK(uc_mem_write(uc, address, code, sizeof(code))); + + uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); + printf("ECX = %u, EDX = %u\n", r_ecx, r_edx); + + // trace all instructions + OK(uc_hook_add(uc, &trace1, UC_HOOK_CODE, test_code_hook, NULL, (uint64_t)1, (uint64_t)0)); + + OK(uc_emu_start(uc, address, address+sizeof(code), 0, 0)); + + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); + + printf("ECX = %u, EDX = %u\n", r_ecx, r_edx); + assert_int_equal(r_ecx, 6); + assert_int_equal(r_edx, 17); +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_pc_change, setup32, teardown), + }; + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/uc.c b/uc.c index 06b08fca..ab466601 100644 --- a/uc.c +++ b/uc.c @@ -494,7 +494,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time { // reset the counter uc->emu_counter = 0; - uc->stop_request = false; uc->invalid_error = UC_ERR_OK; uc->block_full = false; uc->emulation_done = false; @@ -542,6 +541,8 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time break; } + uc->stop_request = false; + uc->emu_count = count; // remove count hook if counting isn't necessary if (count <= 0 && uc->count_hook != 0) { From c8569d8128ca2f90956576aa88a9fc7e574bedc6 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Thu, 28 Jan 2016 16:03:19 +0800 Subject: [PATCH 70/77] arm: fix change PC feature. now tests/regress/callback-pc.py passes --- qemu/cpu-exec.c | 6 ++++-- qemu/target-arm/unicorn_arm.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 6fd497bf..b9eb9067 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -236,6 +236,7 @@ int cpu_exec(struct uc_struct *uc, CPUArchState *env) // qq tc_ptr = tb->tc_ptr; /* execute the generated code */ next_tb = cpu_tb_exec(cpu, tc_ptr); // qq + switch (next_tb & TB_EXIT_MASK) { case TB_EXIT_REQUESTED: /* Something asked us to stop executing @@ -302,12 +303,13 @@ static tcg_target_ulong cpu_tb_exec(CPUState *cpu, uint8_t *tb_ptr) TranslationBlock *tb = (TranslationBlock *)(next_tb & ~TB_EXIT_MASK); if (cc->synchronize_from_tb) { // avoid sync twice when helper_uc_tracecode() already did this. - if (env->uc->emu_counter <= env->uc->emu_count && !env->uc->stop_request) + if (env->uc->emu_counter <= env->uc->emu_count && + !env->uc->stop_request && !env->uc->quit_request) cc->synchronize_from_tb(cpu, tb); } else { assert(cc->set_pc); // avoid sync twice when helper_uc_tracecode() already did this. - if (env->uc->emu_counter <= env->uc->emu_count) + if (env->uc->emu_counter <= env->uc->emu_count && !env->uc->quit_request) cc->set_pc(cpu, tb->pc); } } diff --git a/qemu/target-arm/unicorn_arm.c b/qemu/target-arm/unicorn_arm.c index 63f2c3f5..c8349806 100644 --- a/qemu/target-arm/unicorn_arm.c +++ b/qemu/target-arm/unicorn_arm.c @@ -90,10 +90,12 @@ int arm_reg_write(struct uc_struct *uc, unsigned int regid, const void *value) break; //case UC_ARM_REG_PC: case UC_ARM_REG_R15: + ARM_CPU(uc, mycpu)->env.pc = *(uint32_t *)value; ARM_CPU(uc, mycpu)->env.regs[15] = *(uint32_t *)value; // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); + break; } } From fc22a359e212f5c666c10adb541b364df39a0be5 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 30 Jan 2016 19:30:17 -0500 Subject: [PATCH 71/77] Issue #364 - Move RIP/PC closer next to the offending self-modifying code which modified the 2nd next instruction (imul) in which that escaped our wonderful ability to invalidate the instruction translation cache in which we badly need to pick up the self-modification being made. --- tests/unit/test_tb_x86.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index 7b51d71a..3abbd16e 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -10,6 +10,8 @@ #include #include +#define RIP_NEXT_TO_THE_SELFMODIFY_OPCODE (1) + // Demostration of a self-modifying "IMUL eax,mem,Ib" opcode // And the QEMU's ability to flush the translation buffer properly @@ -112,6 +114,7 @@ static void hook_code32(uc_engine *uc, uint32_t ecx; printf("\nhook_code32: Address: %"PRIx64", Opcode Size: %d\n", address, size); + print_registers(uc); size = MIN(sizeof(tmp), size); if (!uc_mem_read(uc, address, tmp, size)) { @@ -123,6 +126,8 @@ static void hook_code32(uc_engine *uc, } printf("\n"); } + dump_stack_mem(uc); + if (address == 0x60000025) { @@ -160,7 +165,7 @@ static void hook_code32(uc_engine *uc, } printf("Proved that 0x6000003a contains the proper 0x5151494a\n"); } - dump_stack_mem(uc); + // dump_stack_mem(uc); } // Stop after 'imul eax,[ecx+0x41],0x10 @@ -218,6 +223,18 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) uc_engine *uc = *state; uc_hook trace1, trace2, trace3, trace4; void *mem; +#ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE + // These values assumes just before PC = 0x60000021 + int64_t eax = 0x00000041; + int64_t ecx = 0x5ffffff8; + int64_t edx = 0x5ffffff8; + int64_t ebx = 0x034a129b; + int64_t esp = 0x6010229a; + int64_t ebp = 0x60000002; + int64_t esi = 0x1f350211; + int64_t edi = 0x488ac239; +#else + // These values assumes PC == 0x6000000 int64_t eax = 0x73952c43; int64_t ecx = 0x6010229a; int64_t edx = 0x2a500e50; @@ -226,6 +243,7 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) int64_t ebp = 0x60000000; int64_t esi = 0x1f350211; int64_t edi = 0x488ac239; +#endif mem = calloc(1, CODE_SPACE); assert_int_not_equal(0, mem); @@ -283,7 +301,14 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) (uint64_t)0)); uc_assert_success(uc_emu_start(uc, - PHY_STACK_REGION, +#ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE + // Register set (before self-modifying IMUL opcode) + // Start at "0x00000021: xorb %al, 0x30(%ecx) + // Start at "0x00000021: xor byte ptr [ecx + 0x30], al + PHY_STACK_REGION+0x0021, // 0x0024 didn't work +#else + PHY_STACK_REGION+0x0000, +#endif PHY_STACK_REGION+sizeof(X86_CODE32_ALPHA_MIXED) - 1, 0, 0)); From 1fb5416f4ae63b9a367bd7c201da5dda741de22a Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 31 Jan 2016 13:06:42 +0800 Subject: [PATCH 72/77] unit: simplify test_tb_x86.c --- tests/unit/test_tb_x86.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index 3abbd16e..f28d7617 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -206,8 +206,8 @@ static void hook_mem32(uc_engine *uc, //uint32_t tmp[1]; ctype = '?'; - if (type == 16) ctype = 'R'; - if (type == 17) ctype = 'W'; + if (type == UC_MEM_READ) ctype = 'R'; + if (type == UC_MEM_WRITE) ctype = 'W'; printf("hook_mem32(%c): Address: 0x%"PRIx64", Size: %d, Value:0x%"PRIx64"\n", ctype, address, size, value); // if (!uc_mem_read(uc, 0x6000003a, tmp, 4)) @@ -221,7 +221,7 @@ static void hook_mem32(uc_engine *uc, static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) { uc_engine *uc = *state; - uc_hook trace1, trace2, trace3, trace4; + uc_hook trace1, trace2; void *mem; #ifdef RIP_NEXT_TO_THE_SELFMODIFY_OPCODE // These values assumes just before PC = 0x60000021 @@ -278,23 +278,7 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) uc_assert_success(uc_hook_add(uc, &trace2, - UC_HOOK_MEM_READ, - hook_mem32, - NULL, - (uint64_t)1, - (uint64_t)0)); - - uc_assert_success(uc_hook_add(uc, - &trace3, - UC_HOOK_MEM_WRITE, - hook_mem32, - NULL, - (uint64_t)1, - (uint64_t)0)); - - uc_assert_success(uc_hook_add(uc, - &trace4, - UC_HOOK_MEM_FETCH, + UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE | UC_HOOK_MEM_FETCH, hook_mem32, NULL, (uint64_t)1, From a2ef52172c512dfbbdf0cde9316bbf33a56b9cb2 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 31 Jan 2016 13:12:34 +0800 Subject: [PATCH 73/77] add combination hook type UC_HOOK_MEM_VALID to intercept all valid memory access --- bindings/dotnet/UnicornManaged/Const/Common.fs | 1 + bindings/go/unicorn/unicorn_const.go | 1 + bindings/java/unicorn/UnicornConst.java | 1 + bindings/python/unicorn/unicorn_const.py | 1 + include/unicorn/unicorn.h | 2 ++ 5 files changed, 6 insertions(+) diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 5c5d5a2e..6f106a3e 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -91,6 +91,7 @@ module Common = let UC_HOOK_MEM_WRITE_INVALID = 288 let UC_HOOK_MEM_FETCH_INVALID = 576 let UC_HOOK_MEM_INVALID = 1008 + let UC_HOOK_MEM_VALID = 7168 let UC_QUERY_MODE = 1 let UC_PROT_NONE = 0 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index ef08e0c5..8d634be9 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -86,6 +86,7 @@ const ( HOOK_MEM_WRITE_INVALID = 288 HOOK_MEM_FETCH_INVALID = 576 HOOK_MEM_INVALID = 1008 + HOOK_MEM_VALID = 7168 QUERY_MODE = 1 PROT_NONE = 0 diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index d68a5f04..0fe4f193 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -88,6 +88,7 @@ public interface UnicornConst { public static final int UC_HOOK_MEM_WRITE_INVALID = 288; public static final int UC_HOOK_MEM_FETCH_INVALID = 576; public static final int UC_HOOK_MEM_INVALID = 1008; + public static final int UC_HOOK_MEM_VALID = 7168; public static final int UC_QUERY_MODE = 1; public static final int UC_PROT_NONE = 0; diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index fa635b15..4e942ef5 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -84,6 +84,7 @@ UC_HOOK_MEM_READ_INVALID = 144 UC_HOOK_MEM_WRITE_INVALID = 288 UC_HOOK_MEM_FETCH_INVALID = 576 UC_HOOK_MEM_INVALID = 1008 +UC_HOOK_MEM_VALID = 7168 UC_QUERY_MODE = 1 UC_PROT_NONE = 0 diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 11772b9a..2a556841 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -218,6 +218,8 @@ typedef enum uc_hook_type { #define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED) // hook type for all events of illegal memory access #define UC_HOOK_MEM_INVALID (UC_HOOK_MEM_UNMAPPED + UC_HOOK_MEM_PROT) +// hook type for all events of valid memory access +#define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) /* Callback function for hooking memory (UC_MEM_READ, UC_MEM_WRITE & UC_MEM_FETCH) From 32b9deca04c2d0a98d3fb553abaa57aa97fa372c Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 31 Jan 2016 13:14:11 +0800 Subject: [PATCH 74/77] unit: use UC_HOOK_MEM_VALID for test_tb_x86.c --- tests/unit/test_tb_x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index f28d7617..187e5a69 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -278,7 +278,7 @@ static void test_tb_x86_64_32_imul_Gv_Ev_Ib(void **state) uc_assert_success(uc_hook_add(uc, &trace2, - UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE | UC_HOOK_MEM_FETCH, + UC_HOOK_MEM_VALID, hook_mem32, NULL, (uint64_t)1, From e42aba760f47d1ab2deb7061f6212610d89d4890 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 31 Jan 2016 14:07:35 +0800 Subject: [PATCH 75/77] fix a typo in test_tb_x86.c --- tests/unit/test_tb_x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_tb_x86.c b/tests/unit/test_tb_x86.c index 187e5a69..bf691e8b 100644 --- a/tests/unit/test_tb_x86.c +++ b/tests/unit/test_tb_x86.c @@ -150,7 +150,7 @@ static void hook_code32(uc_engine *uc, printf("FAILED EAX register not having 0x5ffffff9\n"); exit(-1); } - printf("EAX = %8.8x\n", ecx); + printf("ECX = %8.8x\n", ecx); printf("%8.8x + 0x41 = %8.8x\n", 0x5ffffff9, 0x5ffffff9 + 0x41); From 44fa4e29e70743a98d67a800feed596f4909fd12 Mon Sep 17 00:00:00 2001 From: cforgeron Date: Sun, 31 Jan 2016 15:09:20 -0400 Subject: [PATCH 76/77] - Added detect for Python 2/3 so the correct iteritems()/iter is called. - Renamed 'id' variable use (which is a built-in) to my_id. - Small formatting changes to make it more PEP compliant. --- bindings/python/sample_network_auditing.py | 150 +++++++++++++-------- 1 file changed, 92 insertions(+), 58 deletions(-) diff --git a/bindings/python/sample_network_auditing.py b/bindings/python/sample_network_auditing.py index 66e575ce..ccd279cd 100755 --- a/bindings/python/sample_network_auditing.py +++ b/bindings/python/sample_network_auditing.py @@ -7,7 +7,14 @@ from unicorn import * from unicorn.x86_const import * import struct import uuid -import random + +# Python 2/3 Compat without installing six +DEAD_PYTHON = False +import sys + +if sys.version_info[0] < 3: + DEAD_PYTHON = True + print("Python 2.x is dead. Start thinking about migrating to 3.x. https://wiki.python.org/moin/Python2orPython3") SIZE_REG = 4 SOCKETCALL_MAX_ARGS = 3 @@ -51,10 +58,11 @@ X86_REVERSE_TCP_2 = b"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51\x6a\x # memory address where emulation starts ADDRESS = 0x1000000 + # supported classes class IdGenerator: def __init__(self): - self.__next_id = 3 # exclude sdtin, stdout, stderr + self.__next_id = 3 # exclude sdtin, stdout, stderr def next(self): next_id = self.__next_id @@ -63,6 +71,7 @@ class IdGenerator: return next_id + class LogChain: def __init__(self): self.__chains = {} @@ -72,11 +81,11 @@ class LogChain: self.__chains = {} self.__linking_fds = {} - def create_chain(self, id): - if not self.__chains.has_key(id): - self.__chains[id] = [] + def create_chain(self, my_id): + if not my_id in self.__chains: + self.__chains[my_id] = [] else: - print("LogChain: id %d existed" % id) + print("LogChain: id %d existed" % my_id) def add_log(self, id, msg): fd = self.get_original_fd(id) @@ -87,20 +96,25 @@ class LogChain: print("LogChain: id %d doesn't exist" % id) def link_fd(self, from_fd, to_fd): - if not self.__linking_fds.has_key(to_fd): + if not to_fd in self.__linking_fds: self.__linking_fds[to_fd] = [] self.__linking_fds[to_fd].append(from_fd) def get_original_fd(self, fd): - if self.__chains.has_key(fd): + if fd in self.__chains: return fd - for orig_fd, links in self.__linking_fds.iteritems(): - if fd in links: - return orig_fd + if DEAD_PYTHON: + for orig_fd, links in self.__linking_fds.iteritems(): + if fd in links: + return orig_fd + else: + for orig_fd, links in self.__linking_fds.items(): + if fd in links: + return orig_fd - return None + return None def print_report(self): print(""" @@ -108,10 +122,16 @@ class LogChain: | START REPORT | ---------------- """) - for id, logs in self.__chains.iteritems(): - print("---- START FD(%d) ----" % id) - print("\n".join(logs)) - print("---- END FD(%d) ----" % id) + if DEAD_PYTHON: + for my_id, logs in self.__chains.iteritems(): + print("---- START FD(%d) ----" % my_id) + print("\n".join(logs)) + print("---- END FD(%d) ----" % my_id) + else: + for my_id, logs in self.__chains.items(): + print("---- START FD(%d) ----" % my_id) + print("\n".join(logs)) + print("---- END FD(%d) ----" % my_id) print(""" -------------- @@ -119,10 +139,9 @@ class LogChain: -------------- """) + # end supported classes -id_gen = IdGenerator() -fd_chains = LogChain() # utilities def bin_to_ipv4(ip): @@ -132,6 +151,7 @@ def bin_to_ipv4(ip): (ip & 0xff00) >> 8, (ip & 0xff)) + def read_string(uc, addr): ret = "" @@ -140,36 +160,43 @@ def read_string(uc, addr): while c != 0x0: ret += chr(c) - c = uc.mem_read(addr+read_bytes, 1)[0] + c = uc.mem_read(addr + read_bytes, 1)[0] read_bytes += 1 return ret + def parse_sock_address(sock_addr): sin_family, = struct.unpack("HI", sock_addr[2:8]) + + if sin_family == 2: # AF_INET + port, host = struct.unpack(">HI", sock_addr[2:8]) return "%s:%d" % (bin_to_ipv4(host), port) - elif sin_family == 6: # AF_INET6 + elif sin_family == 6: # AF_INET6 return "" + def print_sockcall(msg): print(">>> SOCKCALL %s" % msg) + + # end utilities # callback for tracing instructions def hook_code(uc, address, size, user_data): - print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size)) + print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" % (address, size)) # read this instruction code from memory tmp = uc.mem_read(address, size) - print(">>> Instruction code at [0x%x] =" %(address), end="") + print(">>> Instruction code at [0x%x] =" % (address), end="") for i in tmp: - print(" %x" %i, end="") + print(" %x" % i, end="") print("") + # callback for tracing Linux interrupt def hook_intr(uc, intno, user_data): + global id_gen + # only handle Linux syscall if intno != 0x80: return @@ -182,17 +209,17 @@ def hook_intr(uc, intno, user_data): # print(">>> INTERRUPT %d" % eax) - if eax == 1: # sys_exit + if eax == 1: # sys_exit print(">>> SYS_EXIT") uc.emu_stop() - elif eax == 3: # sys_read + elif eax == 3: # sys_read fd = ebx buf = ecx count = edx dummy_content = str(uuid.uuid1())[:32] if len(dummy_content) > count: - dummy_content = dummy_content[:count] + dummy_content = dummy_content[:count] uc.mem_write(buf, dummy_content) @@ -200,7 +227,7 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print(">>> %s" % msg) - elif eax == 4: # sys_write + elif eax == 4: # sys_write fd = ebx buf = ecx count = edx @@ -211,13 +238,13 @@ def hook_intr(uc, intno, user_data): print(">>> %s" % msg) fd_chains.add_log(fd, msg) - elif eax == 5: # sys_open + elif eax == 5: # sys_open filename_addr = ebx flags = ecx mode = edx filename = read_string(uc, filename_addr) - dummy_fd = id_gen.next() + dummy_fd = id_gen.next() uc.reg_write(UC_X86_REG_EAX, dummy_fd) msg = "open file (filename=%s flags=%d mode=%d) with fd(%d)" % (filename, flags, mode, dummy_fd) @@ -225,42 +252,42 @@ def hook_intr(uc, intno, user_data): fd_chains.create_chain(dummy_fd) fd_chains.add_log(dummy_fd, msg) print(">>> %s" % msg) - elif eax == 11: # sys_execv + elif eax == 11: # sys_execv # print(">>> ebx=0x%x, ecx=0x%x, edx=0x%x" % (ebx, ecx, edx)) filename = read_string(uc, ebx) print(">>> SYS_EXECV filename=%s" % filename) - elif eax == 63: # sys_dup2 + elif eax == 63: # sys_dup2 fd_chains.link_fd(ecx, ebx) print(">>> SYS_DUP2 oldfd=%d newfd=%d" % (ebx, ecx)) - elif eax == 102: # sys_socketcall + elif eax == 102: # sys_socketcall # ref: http://www.skyfree.org/linux/kernel_network/socket.html call = uc.reg_read(UC_X86_REG_EBX) args = uc.reg_read(UC_X86_REG_ECX) SOCKETCALL_NUM_ARGS = { - 1: 3, # sys_socket - 2: 3, # sys_bind - 3: 3, # sys_connect - 4: 2, # sys_listen - 5: 3, # sys_accept - 9: 4, # sys_send + 1: 3, # sys_socket + 2: 3, # sys_bind + 3: 3, # sys_connect + 4: 2, # sys_listen + 5: 3, # sys_accept + 9: 4, # sys_send 11: 4, # sys_receive - 13: 2 # sys_shutdown + 13: 2 # sys_shutdown } - buf = uc.mem_read(args, SOCKETCALL_NUM_ARGS[call]*SIZE_REG) - args = struct.unpack("<" + "I"*SOCKETCALL_NUM_ARGS[call], buf) + buf = uc.mem_read(args, SOCKETCALL_NUM_ARGS[call] * SIZE_REG) + args = struct.unpack("<" + "I" * SOCKETCALL_NUM_ARGS[call], buf) # int sys_socketcall(int call, unsigned long *args) - if call == 1: # sys_socket + if call == 1: # sys_socket # err = sys_socket(a0,a1,a[2]) # int sys_socket(int family, int type, int protocol) family = args[0] sock_type = args[1] protocol = args[2] - dummy_fd = id_gen.next() + dummy_fd = id_gen.next() uc.reg_write(UC_X86_REG_EAX, dummy_fd) if family == 2: # AF_INET @@ -269,10 +296,10 @@ def hook_intr(uc, intno, user_data): fd_chains.create_chain(dummy_fd) fd_chains.add_log(dummy_fd, msg) print_sockcall(msg) - elif family == 3: # AF_INET6 + elif family == 3: # AF_INET6 pass - elif call == 2: # sys_bind + elif call == 2: # sys_bind fd = args[0] umyaddr = args[1] addrlen = args[2] @@ -283,19 +310,19 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 3: # sys_connect + elif call == 3: # sys_connect # err = sys_connect(a0, (struct sockaddr *)a1, a[2]) # int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen) fd = args[0] uservaddr = args[1] addrlen = args[2] - sock_addr = uc.mem_read(uservaddr, addrlen) + sock_addr = uc.mem_read(uservaddr, addrlen) msg = "fd(%d) connect to %s" % (fd, parse_sock_address(sock_addr)) fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 4: # sys_listen + elif call == 4: # sys_listen fd = args[0] backlog = args[1] @@ -303,7 +330,7 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 5: # sys_accept + elif call == 5: # sys_accept fd = args[0] upeer_sockaddr = args[1] upeer_addrlen = args[2] @@ -321,7 +348,7 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 9: # sys_send + elif call == 9: # sys_send fd = args[0] buff = args[1] length = args[2] @@ -332,7 +359,7 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 11: # sys_receive + elif call == 11: # sys_receive fd = args[0] ubuf = args[1] size = args[2] @@ -342,7 +369,7 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) - elif call == 13: # sys_shutdown + elif call == 13: # sys_shutdown fd = args[0] how = args[1] @@ -350,8 +377,11 @@ def hook_intr(uc, intno, user_data): fd_chains.add_log(fd, msg) print_sockcall(msg) + # Test X86 32 bit def test_i386(code): + global fd_chains + fd_chains.clean() print("Emulate i386 code") try: @@ -366,7 +396,7 @@ def test_i386(code): # initialize stack mu.reg_write(UC_X86_REG_ESP, ADDRESS + 0x200000) - + # tracing all instructions with customized callback # mu.hook_add(UC_HOOK_CODE, hook_code) @@ -384,9 +414,13 @@ def test_i386(code): fd_chains.print_report() + +# Globals +fd_chains = LogChain() +id_gen = IdGenerator() + if __name__ == '__main__': - test_i386(X86_SEND_ETCPASSWD) + test_i386(X86_SEND_ETCPASSWD) test_i386(X86_BIND_TCP) test_i386(X86_REVERSE_TCP) test_i386(X86_REVERSE_TCP_2) - From de224f1573357acc84cda6a1efbc9104c31210c3 Mon Sep 17 00:00:00 2001 From: cforgeron Date: Sun, 31 Jan 2016 17:01:14 -0400 Subject: [PATCH 77/77] - Switch to 'in' which works in 2/3 instead of legacy '.has_key()' - Renamed 'id' variable use (which is a built-in) to my_id. - Small formatting changes to make it more PEP compliant. --- bindings/python/sample_network_auditing.py | 34 +++++----------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/bindings/python/sample_network_auditing.py b/bindings/python/sample_network_auditing.py index ccd279cd..69a2d2d7 100755 --- a/bindings/python/sample_network_auditing.py +++ b/bindings/python/sample_network_auditing.py @@ -8,14 +8,6 @@ from unicorn.x86_const import * import struct import uuid -# Python 2/3 Compat without installing six -DEAD_PYTHON = False -import sys - -if sys.version_info[0] < 3: - DEAD_PYTHON = True - print("Python 2.x is dead. Start thinking about migrating to 3.x. https://wiki.python.org/moin/Python2orPython3") - SIZE_REG = 4 SOCKETCALL_MAX_ARGS = 3 @@ -105,14 +97,9 @@ class LogChain: if fd in self.__chains: return fd - if DEAD_PYTHON: - for orig_fd, links in self.__linking_fds.iteritems(): - if fd in links: - return orig_fd - else: - for orig_fd, links in self.__linking_fds.items(): - if fd in links: - return orig_fd + for orig_fd, links in self.__linking_fds.items(): + if fd in links: + return orig_fd return None @@ -122,16 +109,11 @@ class LogChain: | START REPORT | ---------------- """) - if DEAD_PYTHON: - for my_id, logs in self.__chains.iteritems(): - print("---- START FD(%d) ----" % my_id) - print("\n".join(logs)) - print("---- END FD(%d) ----" % my_id) - else: - for my_id, logs in self.__chains.items(): - print("---- START FD(%d) ----" % my_id) - print("\n".join(logs)) - print("---- END FD(%d) ----" % my_id) + + for my_id, logs in self.__chains.items(): + print("---- START FD(%d) ----" % my_id) + print("\n".join(logs)) + print("---- END FD(%d) ----" % my_id) print(""" --------------