From a1d5c5f1b014360d5e8e3e759eb6ec68d452aa64 Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 18 Oct 2021 21:39:59 +0200 Subject: [PATCH 01/40] Don't reply on git command --- .github/workflows/Crate-publishing.yml | 2 +- bindings/rust/Cargo.toml | 4 ++ bindings/rust/build.rs | 73 ++++++++++++++++++-------- 3 files changed, 56 insertions(+), 23 deletions(-) diff --git a/.github/workflows/Crate-publishing.yml b/.github/workflows/Crate-publishing.yml index fcd5552b..bcbd2cb1 100644 --- a/.github/workflows/Crate-publishing.yml +++ b/.github/workflows/Crate-publishing.yml @@ -15,7 +15,7 @@ on: pull_request: env: - CI: true + UNICORN_VERSION: dev jobs: build: diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index 45d10f16..9c020538 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -25,3 +25,7 @@ libc = "0.2" [build-dependencies] build-helper = "0.1" +reqwest = { version = "0.11", features = ["blocking"] } +flate2 = "1.0.22" +tar = "0.4.37" +bytes = "1.1.0" \ No newline at end of file diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index c128ef14..8a64ae9e 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,31 +1,60 @@ +use std::fmt::format; use std::result::Result; use std::{env, process::Command}; +use std::path::{Path, PathBuf}; +use bytes::Buf; +use flate2::read::GzDecoder; +use reqwest::header::USER_AGENT; +use tar::Archive; + + +fn find_unicorn(unicorn_dir: &PathBuf) -> Option { + for entry in std::fs::read_dir(unicorn_dir).ok()? { + let entry = entry.unwrap(); + let path = entry.path(); + + if path.is_dir() && path.file_name()?.to_str()?.contains("unicorn") { + return Some(path); + } + } + + None +} + +fn download_unicorn() -> Option { + // https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-tar + let pkg_version; + if let Ok(unicorn_version) = env::var("UNICORN_VERSION") { + pkg_version = unicorn_version; + } else { + pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); + } + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let client = reqwest::blocking::Client::new(); + let resp = client + .get(format!( + "https://api.github.com/repos/unicorn-engine/unicorn/tarball/{}", + pkg_version + )) + .header(USER_AGENT, "unicorn-engine-rust-bindings") + .send().unwrap() + .bytes().unwrap(); + let tar = GzDecoder::new(resp.reader()); + + let mut archive = Archive::new(tar); + archive.unpack(&out_dir).unwrap(); + + match find_unicorn(&out_dir) { + Some(dir) => Some(String::from(out_dir.join(dir).to_str()?)), + None => None + } +} fn main() { - let out_dir = env::var("OUT_DIR").unwrap(); + let profile = env::var("PROFILE").unwrap(); - let mut version = String::from("dev"); - if let Result::Ok(version_env) = env::var("UNICORN_BRANCH") { - version = version_env; - } - let unicorn_dir; - if let Result::Ok(_) = env::var("CI") { - unicorn_dir = format!("../.."); - } else { - unicorn_dir = format!("{}/unicorn_git", out_dir); - - Command::new("rm").arg("-rf").arg(&unicorn_dir); - - Command::new("git") - .arg("clone") - .arg("git@github.com:unicorn-engine/unicorn.git") - .arg("-b") - .arg(version) - .arg(&unicorn_dir) - .output() - .expect("Fail to clone Unicorn repository."); - } + let unicorn_dir = download_unicorn().unwrap(); println!("cargo:rerun-if-changed={}", &unicorn_dir); From 2463467302aa478e42bd9a24caa6858b4733aa46 Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 18 Oct 2021 21:41:19 +0200 Subject: [PATCH 02/40] Format the code --- bindings/rust/build.rs | 18 +++++++++--------- bindings/rust/tests/unicorn.rs | 12 +++++++----- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 8a64ae9e..77225768 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,13 +1,12 @@ -use std::fmt::format; -use std::result::Result; -use std::{env, process::Command}; -use std::path::{Path, PathBuf}; use bytes::Buf; use flate2::read::GzDecoder; use reqwest::header::USER_AGENT; +use std::fmt::format; +use std::path::{Path, PathBuf}; +use std::result::Result; +use std::{env, process::Command}; use tar::Archive; - fn find_unicorn(unicorn_dir: &PathBuf) -> Option { for entry in std::fs::read_dir(unicorn_dir).ok()? { let entry = entry.unwrap(); @@ -37,8 +36,10 @@ fn download_unicorn() -> Option { pkg_version )) .header(USER_AGENT, "unicorn-engine-rust-bindings") - .send().unwrap() - .bytes().unwrap(); + .send() + .unwrap() + .bytes() + .unwrap(); let tar = GzDecoder::new(resp.reader()); let mut archive = Archive::new(tar); @@ -46,12 +47,11 @@ fn download_unicorn() -> Option { match find_unicorn(&out_dir) { Some(dir) => Some(String::from(out_dir.join(dir).to_str()?)), - None => None + None => None, } } fn main() { - let profile = env::var("PROFILE").unwrap(); let unicorn_dir = download_unicorn().unwrap(); diff --git a/bindings/rust/tests/unicorn.rs b/bindings/rust/tests/unicorn.rs index 6f8f2143..aaf208b3 100644 --- a/bindings/rust/tests/unicorn.rs +++ b/bindings/rust/tests/unicorn.rs @@ -1,6 +1,8 @@ use std::cell::RefCell; use std::rc::Rc; -use unicorn_engine::unicorn_const::{uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE}; +use unicorn_engine::unicorn_const::{ + uc_error, Arch, HookType, MemType, Mode, Permission, SECOND_SCALE, +}; use unicorn_engine::{InsnSysX86, RegisterARM, RegisterMIPS, RegisterPPC, RegisterX86}; pub static X86_REGISTERS: [RegisterX86; 125] = [ @@ -602,8 +604,8 @@ fn x86_context_save_and_restore() { let x86_code: Vec = vec![ 0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x05, ]; - let mut unicorn = - unicorn_engine::Unicorn::new(Arch::X86, mode).expect("failed to initialize unicorn instance"); + let mut unicorn = unicorn_engine::Unicorn::new(Arch::X86, mode) + .expect("failed to initialize unicorn instance"); let mut emu = unicorn.borrow(); assert_eq!(emu.mem_map(0x1000, 0x4000, Permission::ALL), Ok(())); assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(())); @@ -619,8 +621,8 @@ fn x86_context_save_and_restore() { let context = context.unwrap(); /* and create a new emulator, into which we will "restore" that context */ - let mut unicorn2 = - unicorn_engine::Unicorn::new(Arch::X86, mode).expect("failed to initialize unicorn instance"); + let mut unicorn2 = unicorn_engine::Unicorn::new(Arch::X86, mode) + .expect("failed to initialize unicorn instance"); let emu2 = unicorn2.borrow(); assert_eq!(emu2.context_restore(&context), Ok(())); for register in X86_REGISTERS.iter() { From fbdd321afe63e728c7dcaa8994df9184b5b7758d Mon Sep 17 00:00:00 2001 From: mio Date: Mon, 18 Oct 2021 21:44:10 +0200 Subject: [PATCH 03/40] Remove useless import --- bindings/rust/build.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 77225768..9900870d 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,9 +1,7 @@ use bytes::Buf; use flate2::read::GzDecoder; use reqwest::header::USER_AGENT; -use std::fmt::format; -use std::path::{Path, PathBuf}; -use std::result::Result; +use std::path::PathBuf; use std::{env, process::Command}; use tar::Archive; From 47f986fc937a022c4616526dc71b992c1de4b39d Mon Sep 17 00:00:00 2001 From: Quentin DUCASSE Date: Tue, 19 Oct 2021 17:12:52 +0200 Subject: [PATCH 04/40] Unit test POC for RISCV issue --- tests/unit/test_arm64.c | 48 ++++++++++++++- tests/unit/test_riscv.c | 129 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 175 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 972d24c6..59333f4d 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -3,6 +3,52 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; +static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +static void test_arm64_until() { + uc_engine *uc; + char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91"; + + /* + mov x16, #1 + mov x17, #0x20 + add x28, x28, 8 + */ + + uint64_t r_x16 = 0x12341234; + uint64_t r_x17 = 0x78907890; + uint64_t r_pc = 0x00000000; + uint64_t r_x28 = 0x12341234; + + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); + + OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28)); + OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc)); + + TEST_CHECK(r_x16 == 0x1); + TEST_CHECK(r_x17 == 0x20); + TEST_CHECK(r_x28 == 0x1234123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + + TEST_LIST = { + { "test_arm64_until", test_arm64_until }, { NULL, NULL } -}; \ No newline at end of file +}; diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 972d24c6..674954db 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -3,6 +3,133 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; +static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + +static void test_riscv32_nop() { + uc_engine* uc; + char code[] = "\x13\x00\x00\x00"; // nop + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x5678; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + TEST_CHECK(r_t0 == 0x1234); + TEST_CHECK(r_t1 == 0x5678); + + OK(uc_close(uc)); +} + +static void test_riscv64_nop() { + uc_engine* uc; + char code[] = "\x13\x00\x00\x00"; // nop + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x5678; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + TEST_CHECK(r_t0 == 0x1234); + TEST_CHECK(r_t1 == 0x5678); + + OK(uc_close(uc)); +} + +static void test_riscv32_until_pc_update() { + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +static void test_riscv64_until_pc_update() { + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + TEST_LIST = { + { "test_riscv32_nop", test_riscv32_nop }, + { "test_riscv64_nop", test_riscv64_nop }, + { "test_riscv32_until_pc_update", test_riscv32_until_pc_update }, + { "test_riscv64_until_pc_update", test_riscv64_until_pc_update }, { NULL, NULL } -}; \ No newline at end of file +}; From 5fd90ca1ef646a77a02ef252af86365a1134fad3 Mon Sep 17 00:00:00 2001 From: Quentin DUCASSE Date: Tue, 19 Oct 2021 17:20:10 +0200 Subject: [PATCH 05/40] Added 3 steps unit test --- tests/unit/test_riscv.c | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 674954db..8617e631 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -126,9 +126,89 @@ static void test_riscv64_until_pc_update() { OK(uc_close(uc)); } +static void test_riscv32_3steps_pc_update() { + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + +static void test_riscv64_3steps_pc_update() { + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; + + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ + + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; + + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); + + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + + OK(uc_close(uc)); +} + + TEST_LIST = { { "test_riscv32_nop", test_riscv32_nop }, { "test_riscv64_nop", test_riscv64_nop }, + { "test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update }, + { "test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update }, { "test_riscv32_until_pc_update", test_riscv32_until_pc_update }, { "test_riscv64_until_pc_update", test_riscv64_until_pc_update }, { NULL, NULL } From 567bd08b86ca63718f1e1018da18a9958d5fa233 Mon Sep 17 00:00:00 2001 From: mio Date: Tue, 19 Oct 2021 23:22:13 +0200 Subject: [PATCH 06/40] Update riscv pc and fix #1465 --- qemu/target/riscv/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 7aa55188..9898093d 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -899,6 +899,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *ctx = container_of(dcbase, DisasContext, base); + TCGContext *tcg_ctx = ctx->uc->tcg_ctx; switch (ctx->base.is_jmp) { case DISAS_TOO_MANY: @@ -907,6 +908,7 @@ static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) case DISAS_NORETURN: break; case DISAS_UC_EXIT: + tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_pc, ctx->base.pc_next); gen_helper_uc_riscv_exit(ctx->uc->tcg_ctx, ctx->uc->tcg_ctx->cpu_env); break; default: From 91451aa2f5026601759f5283e1980434f6608b37 Mon Sep 17 00:00:00 2001 From: mio Date: Wed, 20 Oct 2021 21:27:22 +0200 Subject: [PATCH 07/40] Add a new unit test file --- CMakeLists.txt | 3 +++ tests/unit/test_mem.c | 5 +++++ 2 files changed, 8 insertions(+) create mode 100644 tests/unit/test_mem.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 22ad17c7..1eca217e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1100,6 +1100,9 @@ if (UNICORN_HAS_RISCV) set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_riscv) endif() +# Extra tests +set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_mem) + target_compile_options(unicorn PRIVATE ${UNICORN_COMPILE_OPTIONS} ) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c new file mode 100644 index 00000000..653f036f --- /dev/null +++ b/tests/unit/test_mem.c @@ -0,0 +1,5 @@ +#include "unicorn_test.h" + +TEST_LIST = { + { NULL, NULL } +}; \ No newline at end of file From 160045a910af9f78b9ff9b4f2a163b96db1dc7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aurimas=20Bla=C5=BEulionis?= <0x60@pm.me> Date: Fri, 25 Jun 2021 21:49:10 +0100 Subject: [PATCH 08/40] Binary search mapped blocks --- tests/unit/test_mem.c | 22 ++++++++++++- uc.c | 73 ++++++++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 23 deletions(-) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 653f036f..c8c54077 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -1,5 +1,25 @@ #include "unicorn_test.h" +static void test_map_correct() { + uc_engine* uc; + + OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); + + OK(uc_close(uc)); +} + +static void test_map_wrapping() { + uc_engine* uc; + + OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc)); + uc_assert_err(UC_ERR_ARG, uc_mem_map (uc, (~0ll - 0x4000) & ~0xfff, 0x8000, UC_PROT_ALL)); + + OK(uc_close(uc)); +} + TEST_LIST = { + { "test_map_correct", test_map_correct }, + { "test_map_wrapping", test_map_wrapping }, { NULL, NULL } -}; \ No newline at end of file +}; diff --git a/uc.c b/uc.c index 3e24674c..f41e8306 100644 --- a/uc.c +++ b/uc.c @@ -765,26 +765,52 @@ uc_err uc_emu_stop(uc_engine *uc) return UC_ERR_OK; } +// return target index where a memory region at the address exists, or could be inserted +// +// address either is inside the mapping at the returned index, or is in free space before +// the next mapping. +// +// if there is overlap, between regions, ending address will be higher than the starting +// address of the mapping at returned index +static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) { + int left, right, mid; + MemoryRegion *mapping; + + left = 0; + right = uc->mapped_block_count; + + while (left < right) { + mid = left + (right - left) / 2; + + mapping = uc->mapped_blocks[mid]; + + if (mapping->end - 1 < address) { + left = mid + 1; + } else if (mapping->addr > address) { + right = mid; + } else { + return mid; + } + } + + return left; +} + // find if a memory range overlaps with existing mapped regions static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) { unsigned int i; uint64_t end = begin + size - 1; - for(i = 0; i < uc->mapped_block_count; i++) { - // begin address falls inside this region? - if (begin >= uc->mapped_blocks[i]->addr && begin <= uc->mapped_blocks[i]->end - 1) { - return true; - } - // end address falls inside this region? - if (end >= uc->mapped_blocks[i]->addr && end <= uc->mapped_blocks[i]->end - 1) { - return true; - } - // this region falls totally inside this range? - if (begin < uc->mapped_blocks[i]->addr && end > uc->mapped_blocks[i]->end - 1) { - return true; - } - } + i = bsearch_mapped_blocks(uc, begin); + + // is this the highest region with no possible overlap? + if (i >= uc->mapped_block_count) + return false; + + // end address overlaps this region? + if (end >= uc->mapped_blocks[i]->addr) + return true; // not found return false; @@ -794,6 +820,7 @@ static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, MemoryRegion *block) { MemoryRegion **regions; + int pos; if (block == NULL) { return UC_ERR_NOMEM; @@ -808,7 +835,12 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per uc->mapped_blocks = regions; } - uc->mapped_blocks[uc->mapped_block_count] = block; + pos = bsearch_mapped_blocks(uc, block->addr); + + // shift the array right to give space for the new pointer + memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], sizeof(MemoryRegion*) * (uc->mapped_block_count - pos)); + + uc->mapped_blocks[pos] = block; uc->mapped_block_count++; return UC_ERR_OK; @@ -1225,13 +1257,10 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) return uc->mapped_blocks[i]; } - for(i = 0; i < uc->mapped_block_count; i++) { - if (address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) { - // cache this index for the next query - uc->mapped_block_cache_index = i; - return uc->mapped_blocks[i]; - } - } + i = bsearch_mapped_blocks(uc, address); + + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) + return uc->mapped_blocks[i]; // not found return NULL; From dd7476a9bdcf06ccc2d11f49d66ce9edf09612d7 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 00:51:16 +0200 Subject: [PATCH 09/40] Initial import unicornafl --- CMakeLists.txt | 6 + include/afl/afl-common.h | 49 +++ include/afl/afl-cpu-inl.h | 521 ++++++++++++++++++++++++++++ include/afl/afl-cpu-translate-inl.h | 81 +++++ include/afl/afl-tcg-op-inl.h | 76 ++++ include/afl/afl-tcg-runtime-inl.h | 123 +++++++ include/afl/config.h | 452 ++++++++++++++++++++++++ include/afl/types.h | 193 +++++++++++ include/uc_priv.h | 44 ++- include/unicorn/unicorn.h | 81 +++++ qemu/aarch64.h | 5 + qemu/aarch64eb.h | 5 + qemu/accel/tcg/cpu-exec.c | 37 ++ qemu/accel/tcg/tcg-runtime.c | 4 + qemu/accel/tcg/tcg-runtime.h | 7 + qemu/accel/tcg/translator.c | 30 ++ qemu/arm.h | 5 + qemu/armeb.h | 5 + qemu/include/tcg/tcg-op.h | 4 + qemu/m68k.h | 5 + qemu/mips.h | 5 + qemu/mips64.h | 5 + qemu/mips64el.h | 5 + qemu/mipsel.h | 5 + qemu/ppc.h | 5 + qemu/ppc64.h | 5 + qemu/riscv32.h | 5 + qemu/riscv64.h | 5 + qemu/softmmu/cpus.c | 15 + qemu/sparc.h | 5 + qemu/sparc64.h | 5 + qemu/target/arm/translate-a64.c | 20 ++ qemu/target/arm/translate.c | 15 + qemu/target/i386/translate.c | 19 + qemu/target/m68k/translate.c | 15 + qemu/target/mips/translate.c | 16 + qemu/target/ppc/translate.c | 15 + qemu/target/riscv/translate.c | 16 + qemu/target/sparc/translate.c | 18 + qemu/x86_64.h | 5 + symbols.sh | 5 + uc.c | 328 +++++++++++++++++ 42 files changed, 2269 insertions(+), 1 deletion(-) create mode 100644 include/afl/afl-common.h create mode 100644 include/afl/afl-cpu-inl.h create mode 100644 include/afl/afl-cpu-translate-inl.h create mode 100644 include/afl/afl-tcg-op-inl.h create mode 100644 include/afl/afl-tcg-runtime-inl.h create mode 100644 include/afl/config.h create mode 100644 include/afl/types.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eca217e..69af3b8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,8 @@ else() include_directories( ${CMAKE_BINARY_DIR} ) + # Try to build AFL support on all other platform. + set(UNICORN_HAS_AFL TRUE) endif() include_directories( @@ -326,6 +328,10 @@ else() OUTPUT_FILE ${CMAKE_BINARY_DIR}/riscv64-softmmu/config-target.h ) endif() + if (UNICORN_HAS_AFL) + # Make it globally + set (UNICORN_CFLAGS ${UNICORN_CFLAGS} -DUNICORN_HAS_AFL) + endif() add_compile_options( ${UNICORN_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH} diff --git a/include/afl/afl-common.h b/include/afl/afl-common.h new file mode 100644 index 00000000..eb342255 --- /dev/null +++ b/include/afl/afl-common.h @@ -0,0 +1,49 @@ +/* + american fuzzy lop++ - unicorn instrumentation + ---------------------------------------------- + + Originally written by Andrew Griffiths and + Michal Zalewski + + Adapted for afl-unicorn by Dominik Maier + + CompareCoverage and NeverZero counters by Andrea Fioraldi + + + Copyright 2015, 2016, 2017 Google Inc. All rights reserved. + Copyright 2019 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This code is a shim patched into the separately-distributed source + code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality + to implement AFL-style instrumentation and to take care of the remaining + parts of the AFL fork server logic. + + The resulting libunicorn binary is essentially a standalone instrumentation + tool; for an example of how to leverage it for other purposes, you can + have a look at afl-showmap.c. + + */ + +#include "config.h" +#include "types.h" + +/* NeverZero */ + +#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO) +#define INC_AFL_AREA(loc) \ + asm volatile( \ + "addb $1, (%0, %1, 1)\n" \ + "adcb $0, (%0, %1, 1)\n" \ + : /* no out */ \ + : "r"(afl_area_ptr), "r"(loc) \ + : "memory", "eax") +#else +#define INC_AFL_AREA(loc) afl_area_ptr[loc]++ +#endif + diff --git a/include/afl/afl-cpu-inl.h b/include/afl/afl-cpu-inl.h new file mode 100644 index 00000000..5a781e6f --- /dev/null +++ b/include/afl/afl-cpu-inl.h @@ -0,0 +1,521 @@ +/* + american fuzzy lop++ - unicorn instrumentation + ---------------------------------------------- + + Originally written by Andrew Griffiths and + Michal Zalewski + + Adapted for afl-unicorn by Dominik Maier + + CompareCoverage and NeverZero counters by Andrea Fioraldi + + + Copyright 2015, 2016, 2017 Google Inc. All rights reserved. + Copyright 2019 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This code is a shim patched into the separately-distributed source + code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality + to implement AFL-style instrumentation and to take care of the remaining + parts of the AFL fork server logic. + + The resulting libunicorn binary is essentially a standalone instrumentation + tool; for an example of how to leverage it for other purposes, you can + have a look at afl-showmap.c. + + */ + +#include +#include +#include +#include +#include "config.h" +#include "types.h" +#include "afl-common.h" + +/* We use one additional file descriptor to relay "needs translation" + or "child done" messages between the child and the fork server. */ + +#define FF16 (0xFFFFFFFFFFFFFFFF) + +/* Copied from aflpp/types.h to talk to forkserver */ +#define FS_OPT_ENABLED 0x80000001 +#define FS_OPT_SHDMEM_FUZZ 0x01000000 + +/** + * The correct fds for reading and writing pipes + */ + +#define _R(pipe) ((pipe)[0]) +#define _W(pipe) ((pipe)[1]) + +/* Function declarations. */ + +static void afl_setup(struct uc_struct*); +static inline uc_afl_ret afl_forkserver(CPUState*); +static int afl_find_wifsignaled_id(void); + +static enum afl_child_ret afl_handle_child_requests(CPUState*); +static void afl_request_tsl(CPUState *cpu, target_ulong, target_ulong, uint64_t, uint32_t); +static uc_afl_ret afl_request_next(struct uc_struct* uc, bool found_crash); + +// static TranslationBlock* tb_find_slow(CPUArchState*, target_ulong, target_ulong, uint64_t); + +/* Data structure passed around by the translate handlers: */ + +struct afl_tsl { + + target_ulong pc; + target_ulong cs_base; + uint64_t flags; + uint32_t cf_mask; +#if defined(TARGET_MIPS) + TCGv_i32 hflags; + TCGv_i32 btarget; +#endif + +}; + +/* Current state, as forwarded from forkserver child to parent */ + +enum afl_child_ret { + + // Persistent + AFL_CHILD_NEXT, + // Crash discovered but still alive in persistent mode + AFL_CHILD_FOUND_CRASH, + // Read again, one afl_tsl struct. + AFL_CHILD_TSL_REQUEST, + // Child no longer there. Read status code. + AFL_CHILD_EXITED, + +}; + +static int wifsignaled; + +/************************* + * ACTUAL IMPLEMENTATION * + *************************/ + +/* Set up SHM region and initialize other stuff. */ + +static void afl_setup(struct uc_struct* uc) { + + char *id_str = getenv(SHM_ENV_VAR); + char *inst_r = getenv("AFL_INST_RATIO"); + + // A value we can use to tell AFL our persistent mode found a crash + wifsignaled = afl_find_wifsignaled_id(); + + int shm_id; + + if (inst_r) { + + unsigned int r; + + r = atoi(inst_r); + + if (r > 100) r = 100; + if (!r) r = 1; + + uc->afl_inst_rms = MAP_SIZE * r / 100; + + } else { + + uc->afl_inst_rms = MAP_SIZE; + + } + + if (id_str) { + + shm_id = atoi(id_str); + uc->afl_area_ptr = shmat(shm_id, NULL, 0); + uc->afl_prev_loc = 0; + uc->afl_area_ptr[0] = 1; + + if (uc->afl_area_ptr == (void*)-1) exit(1); + + } + + /* Maintain for compatibility */ + if (getenv("AFL_QEMU_COMPCOV")) { uc->afl_compcov_level = 1; } + if (getenv("AFL_COMPCOV_LEVEL")) { + + uc->afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL")); + + } +#if defined(AFL_DEBUG) + if (uc->afl_compcov_level) { + printf("[d] USING AFL_COMPCOV_LEVEL %d\n", uc->afl_compcov_level); + } +#endif + +} + +// Some dirty hack to come up with a valid statuscode that AFL will just accept. + +static int afl_find_wifsignaled_id(void) { + + int ret = 0; // A faux status code that AFL will accept as signaled/crashed. 1 on linux. + while (!(WIFSIGNALED(ret))) ret++; + +#if defined(AFL_DEBUG) + printf("[d] wifsignaled is %d (WIFSIGNALED(x)=%d)\n", ret, WIFSIGNALED(ret)); +#endif + + return ret; + +} + +/* Fork server logic, invoked by calling uc_afl_forkserver_start. + Roughly follows https://github.com/vanhauser-thc/AFLplusplus/blob/c83e8e1e6255374b085292ba8673efdca7388d76/llvm_mode/afl-llvm-rt.o.c#L130 + */ + +static inline uc_afl_ret afl_forkserver(CPUState* cpu) { + + unsigned char tmp[4] = {0}; + pid_t child_pid; + enum afl_child_ret child_ret = AFL_CHILD_EXITED; + bool first_round = true; + u32 status = 0; + + if (!cpu->uc->afl_area_ptr) return UC_AFL_RET_NO_AFL; + + if (cpu->uc->afl_testcase_ptr) { + /* Parent supports testcases via shared map - and the user wants to use it. Tell AFL. */ + status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + } + + /* Phone home and tell the parent that we're OK. If parent isn't there, + assume we're not running in forkserver mode and just execute program. */ + + if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_NO_AFL; + + /* afl tells us in an extra message if it accepted this option or not */ + if (cpu->uc->afl_testcase_ptr && getenv(SHM_FUZZ_ENV_VAR)) { + if (read(FORKSRV_FD, &status, 4) != 4) { + fprintf(stderr, "[!] AFL parent exited before forkserver was up\n"); + return UC_AFL_RET_ERROR; + } + if (status != (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { + fprintf(stderr, "[!] Unexpected response from AFL++ on forkserver setup\n"); + return UC_AFL_RET_ERROR; + } + } else { +#if defined(AFL_DEBUG) + printf("[d] AFL++ sharedmap fuzzing not supported/SHM_FUZZ_ENV_VAR not set\n"); +#endif + } + + void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); + +#if defined(AFL_DEBUG) + printf("[d] Entering forkserver loop\n"); +#endif + + while (1) { + + uint32_t was_killed; + int status; + + /* Wait for parent by reading from the pipe. Abort if read fails. */ + + if (read(FORKSRV_FD, &was_killed, 4) != 4) return UC_AFL_RET_FINISHED; + + /* If we stopped the child in persistent mode, but there was a race + condition and afl-fuzz already issued SIGKILL, write off the old + process. */ + + if ((child_ret != AFL_CHILD_EXITED) && was_killed) { + +#if defined(AFL_DEBUG) + printf("[d] Child was killed by AFL in the meantime.\n"); +#endif + + child_ret = AFL_CHILD_EXITED; + if (waitpid(child_pid, &status, 0) < 0) { + perror("[!] Error waiting for child!"); + return UC_AFL_RET_ERROR; + } + + } + + if (child_ret == AFL_CHILD_EXITED) { + + /* Child dead. Establish new a channel with child to grab translation commands. + We'll read from _R(afl_child_pipe), child will write to _W(afl_child_pipe). */ + + /* close the read fd of previous round. */ + + if (_R(cpu->uc->afl_child_pipe)) { + close(_R(cpu->uc->afl_child_pipe)); + close(_W(cpu->uc->afl_parent_pipe)); + } + + if (pipe(cpu->uc->afl_child_pipe)) { + perror("[!] Error creating pipe to child"); + return UC_AFL_RET_ERROR; + } + if (pipe(cpu->uc->afl_parent_pipe)) { + perror("[!] Error creating pipe to parent"); + close(_R(cpu->uc->afl_child_pipe)); + close(_W(cpu->uc->afl_child_pipe)); + return UC_AFL_RET_ERROR; + } + + /* Create a clone of our process. */ + + child_pid = fork(); + if (child_pid < 0) { + perror("[!] Could not fork! "); + return UC_AFL_RET_ERROR; + } + + /* In child process: close fds, resume execution. */ + + if (!child_pid) { // New child + + signal(SIGCHLD, old_sigchld_handler); + // FORKSRV_FD is for communication with AFL, we don't need it in the child. + close(FORKSRV_FD); + close(FORKSRV_FD + 1); + close(_R(cpu->uc->afl_child_pipe)); + close(_W(cpu->uc->afl_parent_pipe)); + cpu->uc->afl_child_request_next = afl_request_next; + + memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); + MEM_BARRIER(); // Make very sure everything has been written to the map at this point + + if (!first_round) { + + // For persistent mode: Clear the map manually after forks. + memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); + + } else { + // For persistent mode: Clear the map manually after forks. + //memset(env->uc->afl_area_ptr, 0, MAP_SIZE); + + first_round = false; + } + + cpu->uc->afl_prev_loc = 0; + // Tell AFL we're alive + cpu->uc->afl_area_ptr[0] = 1; + + return UC_AFL_RET_CHILD; + + } else { // parent for new child + + /* If we don't close this in parent, we don't get notified on afl_child_pipe once child is gone. */ + + close(_W(cpu->uc->afl_child_pipe)); + close(_R(cpu->uc->afl_parent_pipe)); + + } + + } else { // parent, in persistent mode + + /* Special handling for persistent mode: if the child is alive but + currently stopped, simply restart it with a write to afl_parent_pipe. + In case we fuzz using shared map, use this method to forward the size + of the current testcase to the child without cost. */ + + if (write(_W(cpu->uc->afl_parent_pipe), tmp, 4) != 4) { + + fprintf(stderr,"[!] Child died when we tried to resume it\n"); + return UC_AFL_RET_ERROR; + + } + + } + + /* In parent process: write PID to AFL. */ + + if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { + return UC_AFL_RET_FINISHED; + } + + /* Collect translation requests until child finishes a run or dies */ + + child_ret = afl_handle_child_requests(cpu); + + if (child_ret == AFL_CHILD_NEXT) { + + /* Child asks for next in persistent mode */ + + status = 0; + + } else if (child_ret == AFL_CHILD_FOUND_CRASH) { + + /* WIFSIGNALED(wifsignaled) == 1 -> tells AFL the child crashed (even though it's still alive for persistent mode) */ + + status = wifsignaled; + + } else if (child_ret == AFL_CHILD_EXITED) { + + /* If child exited, get and relay exit status to parent through waitpid. */ + + if (waitpid(child_pid, &status, 0) < 0) { + + // Zombie Child could not be collected. Scary! + perror("[!] The child's exit code could not be determined. "); + return UC_AFL_RET_ERROR; + + } + + } + + /* Relay wait status to AFL pipe, then loop back. */ + + if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_FINISHED; + + } + +} + +/* This code is invoked whenever Unicorn decides that it doesn't have a + translation of a particular block and needs to compute it. When this happens, + we tell the parent to mirror the operation, so that the next fork() has a + cached copy. */ + +static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong cb, uint64_t flags, uint32_t cf_mask) { + + /* Dual use: if this func is not set, we're not a child process */ + + struct uc_struct* uc = cpu->uc; + if (uc->afl_child_request_next == NULL) return; + enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; + + struct afl_tsl t = { + .pc = pc, + .cs_base = cb, + .flags = flags, + .cf_mask = cf_mask, +#if defined(TARGET_MIPS) + .hflags = cpu->uc->tcg_ctx->hflags, + .btarget = cpu->uc->tcg_ctx->btarget, +#endif + }; + +#if defined(AFL_DEBUG) + printf("Requesting tsl, pc=0x%llx, cb=0x%llx, flags=0x%llx\n", (unsigned long long) pc, (unsigned long long) cb, (unsigned long long) flags); +#endif + + // We write tsl requests in two steps but that's fine since cache requests are not very common over the time of fuzzing. + + if ((write(_W(uc->afl_child_pipe), &tsl_req, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) + || write(_W(uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) { + + fprintf(stderr, "Error writing to child pipe. Parent dead?\n"); + + } + +} + +/* This code is invoked whenever the child decides that it is done with one fuzz-case. */ + +static uc_afl_ret afl_request_next(struct uc_struct* uc, bool crash_found) { + + enum afl_child_ret msg = crash_found? AFL_CHILD_FOUND_CRASH : AFL_CHILD_NEXT; + char tmp[4]; + +#if defined(AFL_DEBUG) + printf("[d] request next. crash found: %s\n", crash_found ? "true": "false"); +#endif + + MEM_BARRIER(); // Make very sure everything has been written to the map at this point + + if (write(_W(uc->afl_child_pipe), &msg, sizeof(msg)) != sizeof(msg)) { + + fprintf(stderr, "[!] Error writing to parent pipe. Parent dead?\n"); + return UC_AFL_RET_ERROR; + + } + + // Once the parent has written something, the next persistent loop starts. + // The parent itself will wait for AFL to signal the new testcases is available. + // This blocks until the next testcase is ready. + if (read(_R(uc->afl_parent_pipe), tmp, 4) != 4) { + + fprintf(stderr, "[!] Error reading from parent pipe. Parent dead?\n"); + return UC_AFL_RET_ERROR; + + } + + /* For shared map fuzzing, the forkserver parent forwards the size of the current testcase. */ + memset(uc->afl_area_ptr, 0, MAP_SIZE); + MEM_BARRIER(); // Also make sure nothing read before this point. + + // Start with a clean slate. + uc->afl_prev_loc = 0; + uc->afl_area_ptr[0] = 1; + + return UC_AFL_RET_CHILD; + +} + + +/* This is the reading side of afl_child_pipe. It will handle persistent mode and (tsl) cache requests. + Since timeouts are handled by afl-fuzz simply killing the child, we can just wait until the pipe breaks. + For persistent mode, we will also receive child responses over this chanel. + For persistent mode, if child is still alive, this will return if the child crashed or not */ + +static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { + + enum afl_child_ret child_msg; + struct afl_tsl t; + + while (1) { + + /* Broken pipe means it's time to return to the fork server routine. */ + + if (read(_R(cpu->uc->afl_child_pipe), &child_msg, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) return AFL_CHILD_EXITED; // child is dead. + + if (child_msg == AFL_CHILD_NEXT || child_msg == AFL_CHILD_FOUND_CRASH) { + + // Forward if child found a crash or not, for persistent mode. + return child_msg; + + } else if (child_msg == AFL_CHILD_TSL_REQUEST) { + + // TODO: Add option to disable cache for self-modifying code? // Ignore code that has not been loaded? + + // Child will send a tsl request next, that we have to cache. + if (read(_R(cpu->uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) return AFL_CHILD_EXITED; // child is dead. + + // Prepare hflags for delay slot +#if defined(TARGET_MIPS) + struct afl_tsl tmp; + tmp.hflags = cpu->uc->tcg_ctx->hflags; + tmp.btarget = cpu->uc->tcg_ctx->btarget; + cpu->uc->tcg_ctx->hflags = t.hflags; + cpu->uc->tcg_ctx->btarget = t.btarget; +#endif + + // Cache. + //tb_find_slow(env, t.pc, t.cs_base, t.flags); + + // TODO: Caching! tb = tb_find(cpu, last_tb, tb_exit, t.cflags); + + // Restore hflags +#if defined(TARGET_MIPS) + cpu->uc->tcg_ctx->hflags = tmp.hflags; + cpu->uc->tcg_ctx->btarget = tmp.btarget; +#endif + + } else { + + fprintf(stderr, "[!] Unexpected response by child! %d. Please report this as bug for unicornafl.\n" + " Expected one of {AFL_CHILD_NEXT: %d, AFL_CHILD_FOUND_CRASH: %d, AFL_CHILD_TSL_REQUEST: %d}.\n", + child_msg, AFL_CHILD_NEXT, AFL_CHILD_FOUND_CRASH, AFL_CHILD_TSL_REQUEST); + + } + + } + +} diff --git a/include/afl/afl-cpu-translate-inl.h b/include/afl/afl-cpu-translate-inl.h new file mode 100644 index 00000000..7692ff3c --- /dev/null +++ b/include/afl/afl-cpu-translate-inl.h @@ -0,0 +1,81 @@ +/* + american fuzzy lop++ - unicorn instrumentation + ---------------------------------------------- + + Originally written by Andrew Griffiths and + Michal Zalewski + + Adapted for afl-unicorn by Dominik Maier + + CompareCoverage and NeverZero counters by Andrea Fioraldi + + + Copyright 2015, 2016, 2017 Google Inc. All rights reserved. + Copyright 2019 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This code is a shim patched into the separately-distributed source + code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality + to implement AFL-style instrumentation and to take care of the remaining + parts of the AFL fork server logic. + + The resulting libunicorn binary is essentially a standalone instrumentation + tool; for an example of how to leverage it for other purposes, you can + have a look at afl-showmap.c. + + */ + +#include "config.h" +#include "types.h" + +/* These are executed on code generation. Execution is in afl-unicorn-tcg-runtime-inl.h */ +/* Roughly afl_gen_maybe_log -> gen_afl_maybe_log -> emit HELPER(afl_maybe_log) -> call afl_maybe_log */ + +static void afl_gen_maybe_log(TCGContext *s, uint64_t cur_loc) { + + if (!s->uc->afl_area_ptr) return; + + /* "Hash" */ + + cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); + cur_loc &= MAP_SIZE - 7; + + /* Implement probabilistic instrumentation by looking at scrambled block + address. This keeps the instrumented locations stable across runs. */ + + if (cur_loc >= s->uc->afl_inst_rms) return; + + gen_afl_maybe_log(s, cur_loc); + +} + +// Currently only arm32 and x86. We undefine it for others to silence unused func compiler warnings. +#if defined(ARCH_HAS_COMPCOV) +static void afl_gen_compcov(TCGContext *s, uint64_t cur_loc, TCGv arg1, + TCGv arg2, TCGMemOp ot, int is_imm) { + + if (!s->uc->afl_compcov_level || !s->uc->afl_area_ptr) return; + + if (!is_imm && s->uc->afl_compcov_level < 2) return; + + cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); + cur_loc &= MAP_SIZE - 7; + + if (cur_loc >= s->uc->afl_inst_rms) return; + + switch (ot) { + + case MO_64: gen_afl_compcov_log_64(s, cur_loc, (TCGv_i64)arg1, (TCGv_i64)arg2); break; + case MO_32: gen_afl_compcov_log_32(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; + case MO_16: gen_afl_compcov_log_16(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; + default: return; + + } + +} +#endif \ No newline at end of file diff --git a/include/afl/afl-tcg-op-inl.h b/include/afl/afl-tcg-op-inl.h new file mode 100644 index 00000000..5770066c --- /dev/null +++ b/include/afl/afl-tcg-op-inl.h @@ -0,0 +1,76 @@ +/* + american fuzzy lop++ - unicorn instrumentation + ---------------------------------------------- + + Originally written by Andrew Griffiths and + Michal Zalewski + + Adapted for afl-unicorn by Dominik Maier + + CompareCoverage and NeverZero counters by Andrea Fioraldi + + + Copyright 2015, 2016, 2017 Google Inc. All rights reserved. + Copyright 2019 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This code is a shim patched into the separately-distributed source + code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality + to implement AFL-style instrumentation and to take care of the remaining + parts of the AFL fork server logic. + + The resulting libunicorn binary is essentially a standalone instrumentation + tool; for an example of how to leverage it for other purposes, you can + have a look at afl-showmap.c. + + */ + +static inline void gen_afl_maybe_log(TCGContext *tcg_ctx, uint64_t cur_loc) { + + TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); + TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); + gen_helper_afl_maybe_log(tcg_ctx, tuc, tcur_loc); + +} + +static inline void gen_afl_compcov_log_16(TCGContext *tcg_ctx, uint64_t cur_loc, + TCGv_i32 arg1, TCGv_i32 arg2) { +#if defined(AFL_DEBUG) + printf("[d] Emitting 16 bit COMPCOV instrumentation for loc 0x%lx\n", cur_loc); +#endif + + TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); + TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); + gen_helper_afl_compcov_log_16(tcg_ctx, tuc, tcur_loc, arg1, arg2); + +} + +static inline void gen_afl_compcov_log_32(TCGContext *tcg_ctx, uint64_t cur_loc, + TCGv_i32 arg1, TCGv_i32 arg2) { +#if defined(AFL_DEBUG) + printf("[d] Emitting 32 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); +#endif + + TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); + TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); + gen_helper_afl_compcov_log_32(tcg_ctx, tuc, tcur_loc, arg1, arg2); + +} + +static inline void gen_afl_compcov_log_64(TCGContext *tcg_ctx, uint64_t cur_loc, + TCGv_i64 arg1, TCGv_i64 arg2) { +#if defined(AFL_DEBUG) + printf("[d] Emitting 64 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); +#endif + + TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); + TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); + gen_helper_afl_compcov_log_64(tcg_ctx, tuc, tcur_loc, arg1, arg2); + +} + diff --git a/include/afl/afl-tcg-runtime-inl.h b/include/afl/afl-tcg-runtime-inl.h new file mode 100644 index 00000000..237c55b5 --- /dev/null +++ b/include/afl/afl-tcg-runtime-inl.h @@ -0,0 +1,123 @@ +/* + american fuzzy lop++ - unicorn instrumentation + ---------------------------------------------- + + Originally written by Andrew Griffiths and + Michal Zalewski + + Adapted for afl-unicorn by Dominik Maier + + CompareCoverage and NeverZero counters by Andrea Fioraldi + + + Copyright 2015, 2016, 2017 Google Inc. All rights reserved. + Copyright 2019 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + This code is a shim patched into the separately-distributed source + code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality + to implement AFL-style instrumentation and to take care of the remaining + parts of the AFL fork server logic. + + The resulting libunicorn binary is essentially a standalone instrumentation + tool; for an example of how to leverage it for other purposes, you can + have a look at afl-showmap.c. + + */ + +#include "uc_priv.h" +#include "afl-common.h" + +/* This is the main instrumentation function, patched in at translate. + cur_loc has already been shifted in afl-unicorn-translate-inl.h at this point. + Also this helper will only be emitted if running instrumented. */ + +void HELPER(afl_maybe_log)(void* uc_ptr, uint64_t cur_loc) { + + struct uc_struct* uc = (struct uc_struct*) uc_ptr; + u8* afl_area_ptr = uc->afl_area_ptr; // Don't remove, it's used by INC_AFL_AREA implicitly; + + register uintptr_t afl_idx = cur_loc ^ uc->afl_prev_loc; + + INC_AFL_AREA(afl_idx); + +#if defined(AFL_DEBUG) + printf("[d] At loc 0x%llx: prev: 0x%llx, afl_idx: %lu, map[afl_idx]: %d\n", (unsigned long long) cur_loc, (unsigned long long) uc->afl_prev_loc, (unsigned long) afl_idx, afl_area_ptr[afl_idx]); +#endif + + uc->afl_prev_loc = cur_loc >> 1; + +} + +void HELPER(afl_compcov_log_16)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, + uint32_t arg2) { + + u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; + + if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } + +} + +void HELPER(afl_compcov_log_32)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, + uint32_t arg2) { + + u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; + + if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { + + INC_AFL_AREA(cur_loc + 2); + if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { + + INC_AFL_AREA(cur_loc + 1); + if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } + + } + + } + +} + +void HELPER(afl_compcov_log_64)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1, + uint64_t arg2) { + + u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; + + if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) { + + INC_AFL_AREA(cur_loc + 6); + if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) { + + INC_AFL_AREA(cur_loc + 5); + if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) { + + INC_AFL_AREA(cur_loc + 4); + if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) { + + INC_AFL_AREA(cur_loc + 3); + if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { + + INC_AFL_AREA(cur_loc + 2); + if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { + + INC_AFL_AREA(cur_loc + 1); + if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } + + } + + } + + } + + } + + } + + } + +} + diff --git a/include/afl/config.h b/include/afl/config.h new file mode 100644 index 00000000..b5137553 --- /dev/null +++ b/include/afl/config.h @@ -0,0 +1,452 @@ +/* + american fuzzy lop++ - vaguely configurable bits + ------------------------------------------------ + + Originally written by Michal Zalewski + + Now maintained by Marc Heuse , + Heiko Eißfeldt , + Andrea Fioraldi , + Dominik Maier + + Copyright 2016, 2017 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + */ + +#ifndef _HAVE_CONFIG_H +#define _HAVE_CONFIG_H + +/* Version string: */ + +// c = release, d = volatile github dev, e = experimental branch +#define VERSION "++3.01a" + +/****************************************************** + * * + * Settings that may be of interest to power users: * + * * + ******************************************************/ + +/* console output colors: There are three ways to configure its behavior + * 1. default: colored outputs fixed on: defined USE_COLOR && defined + * ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect + * 2. defined USE_COLOR && !defined ALWAYS_COLORED + * -> depending on env var AFL_NO_COLOR=1 colors can be switched off + * at run-time. Default is to use colors. + * 3. colored outputs fixed off: !defined USE_COLOR + * The env var. AFL_NO_COLOR will have no effect + */ + +/* Comment out to disable terminal colors (note that this makes afl-analyze + a lot less nice): */ + +#define USE_COLOR + +#ifdef USE_COLOR + /* Comment in to always enable terminal colors */ + /* Comment out to enable runtime controlled terminal colors via AFL_NO_COLOR + */ + #define ALWAYS_COLORED 1 +#endif + +/* StatsD config + Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment + variable. +*/ +#define STATSD_UPDATE_SEC 1 +#define STATSD_DEFAULT_PORT 8125 +#define STATSD_DEFAULT_HOST "127.0.0.1" + +/* If you want to have the original afl internal memory corruption checks. + Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ + +//#define _WANT_ORIGINAL_AFL_ALLOC + +/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ + +#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb + #define FANCY_BOXES +#endif + +/* Default timeout for fuzzed code (milliseconds). This is the upper bound, + also used for detecting hangs; the actual value is auto-scaled: */ + +#define EXEC_TIMEOUT 1000U + +/* Timeout rounding factor when auto-scaling (milliseconds): */ + +#define EXEC_TM_ROUND 20U + +/* 64bit arch MACRO */ +#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) + #define WORD_SIZE_64 1 +#endif + +/* Default memory limit for child process (MB) 0 = disabled : */ + +#define MEM_LIMIT 0U + +/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ + +#define MEM_LIMIT_QEMU 0U + +/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ + +#define MEM_LIMIT_UNICORN 0U + +/* Number of calibration cycles per every new test case (and for test + cases that show variable behavior): */ + +#define CAL_CYCLES 8U +#define CAL_CYCLES_LONG 40U + +/* Number of subsequent timeouts before abandoning an input file: */ + +#define TMOUT_LIMIT 250U + +/* Maximum number of unique hangs or crashes to record: */ + +#define KEEP_UNIQUE_HANG 500U +#define KEEP_UNIQUE_CRASH 5000U + +/* Baseline number of random tweaks during a single 'havoc' stage: */ + +#define HAVOC_CYCLES 256U +#define HAVOC_CYCLES_INIT 1024U + +/* Maximum multiplier for the above (should be a power of two, beware + of 32-bit int overflows): */ + +#define HAVOC_MAX_MULT 64U +#define HAVOC_MAX_MULT_MOPT 64U + +/* Absolute minimum number of havoc cycles (after all adjustments): */ + +#define HAVOC_MIN 12U + +/* Power Schedule Divisor */ +#define POWER_BETA 1U +#define MAX_FACTOR (POWER_BETA * 32) + +/* Maximum stacking for havoc-stage tweaks. The actual value is calculated + like this: + + n = random between 1 and HAVOC_STACK_POW2 + stacking = 2^n + + In other words, the default (n = 4) produces 2, 4, 8, 16 + stacked tweaks: */ + +#define HAVOC_STACK_POW2 4U + +/* Caps on block sizes for cloning and deletion operations. Each of these + ranges has a 33% probability of getting picked, except for the first + two cycles where smaller blocks are favored: */ + +#define HAVOC_BLK_SMALL 32U +#define HAVOC_BLK_MEDIUM 128U +#define HAVOC_BLK_LARGE 1500U + +/* Extra-large blocks, selected very rarely (<5% of the time): */ + +#define HAVOC_BLK_XL 32768U + +/* Probabilities of skipping non-favored entries in the queue, expressed as + percentages: */ + +#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ +#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ +#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ + +/* Splicing cycle count: */ + +#define SPLICE_CYCLES 15 + +/* Nominal per-splice havoc cycle length: */ + +#define SPLICE_HAVOC 32 + +/* Maximum offset for integer addition / subtraction stages: */ + +#define ARITH_MAX 35 + +/* Limits for the test case trimmer. The absolute minimum chunk size; and + the starting and ending divisors for chopping up the input file: */ + +#define TRIM_MIN_BYTES 4 +#define TRIM_START_STEPS 16 +#define TRIM_END_STEPS 1024 + +/* Maximum size of input file, in bytes (keep under 100MB, default 1MB): + (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c + and afl-fuzz-state.c have to be changed as well! */ + +#define MAX_FILE (1 * 1024 * 1024U) + +/* The same, for the test case minimizer: */ + +#define TMIN_MAX_FILE (10 * 1024 * 1024) + +/* Block normalization steps for afl-tmin: */ + +#define TMIN_SET_MIN_SIZE 4 +#define TMIN_SET_STEPS 128 + +/* Maximum dictionary token size (-x), in bytes: */ + +#define MAX_DICT_FILE 128 + +/* Length limits for auto-detected dictionary tokens: */ + +#define MIN_AUTO_EXTRA 3 +#define MAX_AUTO_EXTRA 32 + +/* Maximum number of user-specified dictionary tokens to use in deterministic + steps; past this point, the "extras/user" step will be still carried out, + but with proportionally lower odds: */ + +#define MAX_DET_EXTRAS 256 + +/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing + (first value), and to keep in memory as candidates. The latter should be much + higher than the former. */ + +#define USE_AUTO_EXTRAS 128 +#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) + +/* Scaling factor for the effector map used to skip some of the more + expensive deterministic steps. The actual divisor is set to + 2^EFF_MAP_SCALE2 bytes: */ + +#define EFF_MAP_SCALE2 3 + +/* Minimum input file length at which the effector logic kicks in: */ + +#define EFF_MIN_LEN 128 + +/* Maximum effector density past which everything is just fuzzed + unconditionally (%): */ + +#define EFF_MAX_PERC 90 + +/* UI refresh frequency (Hz): */ + +#define UI_TARGET_HZ 5 + +/* Fuzzer stats file and plot update intervals (sec): */ + +#define STATS_UPDATE_SEC 60 +#define PLOT_UPDATE_SEC 5 + +/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ + +#define AVG_SMOOTHING 16 + +/* Sync interval (every n havoc cycles): */ + +#define SYNC_INTERVAL 8 + +/* Output directory reuse grace period (minutes): */ + +#define OUTPUT_GRACE 25 + +/* Uncomment to use simple file names (id_NNNNNN): */ + +// #define SIMPLE_FILES + +/* List of interesting values to use in fuzzing. */ + +#define INTERESTING_8 \ + -128, /* Overflow signed 8-bit when decremented */ \ + -1, /* */ \ + 0, /* */ \ + 1, /* */ \ + 16, /* One-off with common buffer size */ \ + 32, /* One-off with common buffer size */ \ + 64, /* One-off with common buffer size */ \ + 100, /* One-off with common buffer size */ \ + 127 /* Overflow signed 8-bit when incremented */ + +#define INTERESTING_8_LEN 9 + +#define INTERESTING_16 \ + -32768, /* Overflow signed 16-bit when decremented */ \ + -129, /* Overflow signed 8-bit */ \ + 128, /* Overflow signed 8-bit */ \ + 255, /* Overflow unsig 8-bit when incremented */ \ + 256, /* Overflow unsig 8-bit */ \ + 512, /* One-off with common buffer size */ \ + 1000, /* One-off with common buffer size */ \ + 1024, /* One-off with common buffer size */ \ + 4096, /* One-off with common buffer size */ \ + 32767 /* Overflow signed 16-bit when incremented */ + +#define INTERESTING_16_LEN 10 + +#define INTERESTING_32 \ + -2147483648LL, /* Overflow signed 32-bit when decremented */ \ + -100663046, /* Large negative number (endian-agnostic) */ \ + -32769, /* Overflow signed 16-bit */ \ + 32768, /* Overflow signed 16-bit */ \ + 65535, /* Overflow unsig 16-bit when incremented */ \ + 65536, /* Overflow unsig 16 bit */ \ + 100663045, /* Large positive number (endian-agnostic) */ \ + 2147483647 /* Overflow signed 32-bit when incremented */ + +#define INTERESTING_32_LEN 8 + +/*********************************************************** + * * + * Really exotic stuff you probably don't want to touch: * + * * + ***********************************************************/ + +/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ + +#define RESEED_RNG 100000 + +/* The default maximum testcase cache size in MB, 0 = disable. + A value between 50 and 250 is a good default value. Note that the + number of entries will be auto assigned if not specified via the + AFL_TESTCACHE_ENTRIES env variable */ + +#define TESTCASE_CACHE_SIZE 50 + +/* Maximum line length passed from GCC to 'as' and used for parsing + configuration files: */ + +#define MAX_LINE 8192 + +/* Environment variable used to pass SHM ID to the called program. */ + +#define SHM_ENV_VAR "__AFL_SHM_ID" + +/* Environment variable used to pass SHM FUZZ ID to the called program. */ + +#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID" + +/* Other less interesting, internal-only variables. */ + +#define CLANG_ENV_VAR "__AFL_CLANG_MODE" +#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" +#define PERSIST_ENV_VAR "__AFL_PERSISTENT" +#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" + +/* In-code signatures for deferred and persistent mode. */ + +#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" +#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" + +/* Distinctive bitmap signature used to indicate failed execution: */ + +#define EXEC_FAIL_SIG 0xfee1dead + +/* Distinctive exit code used to indicate MSAN trip condition: */ + +#define MSAN_ERROR 86 + +/* Designated file descriptors for forkserver commands (the application will + use FORKSRV_FD and FORKSRV_FD + 1): */ + +#define FORKSRV_FD 198 + +/* Fork server init timeout multiplier: we'll wait the user-selected + timeout plus this much for the fork server to spin up. */ + +#define FORK_WAIT_MULT 10 + +/* Calibration timeout adjustments, to be a bit more generous when resuming + fuzzing sessions or trying to calibrate already-added internal finds. + The first value is a percentage, the other is in milliseconds: */ + +#define CAL_TMOUT_PERC 125 +#define CAL_TMOUT_ADD 50 + +/* Number of chances to calibrate a case before giving up: */ + +#define CAL_CHANCES 3 + +/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than + 2; you probably want to keep it under 18 or so for performance reasons + (adjusting AFL_INST_RATIO when compiling is probably a better way to solve + problems with complex programs). You need to recompile the target binary + after changing this - otherwise, SEGVs may ensue. */ + +#define MAP_SIZE_POW2 16 +#define MAP_SIZE (1U << MAP_SIZE_POW2) + +/* Maximum allocator request size (keep well under INT_MAX): */ + +#define MAX_ALLOC 0x40000000 + +/* A made-up hashing seed: */ + +#define HASH_CONST 0xa5b35705 + +/* Constants for afl-gotcpu to control busy loop timing: */ + +#define CTEST_TARGET_MS 5000 +#define CTEST_CORE_TRG_MS 1000 +#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) + +/* Enable NeverZero counters in QEMU mode */ + +#define AFL_QEMU_NOT_ZERO + +/* AFL RedQueen */ + +#define CMPLOG_SHM_ENV_VAR "__AFL_CMPLOG_SHM_ID" + +/* CPU Affinity lockfile env var */ + +#define CPU_AFFINITY_ENV_VAR "__AFL_LOCKFILE" + +/* Uncomment this to use inferior block-coverage-based instrumentation. Note + that you need to recompile the target binary for this to have any effect: */ + +// #define COVERAGE_ONLY + +/* Uncomment this to ignore hit counts and output just one bit per tuple. + As with the previous setting, you will need to recompile the target + binary: */ + +// #define SKIP_COUNTS + +/* Uncomment this to use instrumentation data to record newly discovered paths, + but do not use them as seeds for fuzzing. This is useful for conveniently + measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ + +// #define IGNORE_FINDS + +/* Text mutations */ + +/* Minimum length of a queue input to be evaluated for "is_ascii"? */ + +#define AFL_TXT_MIN_LEN 12 + +/* What is the minimum percentage of ascii characters present to be classifed + as "is_ascii"? */ + +#define AFL_TXT_MIN_PERCENT 94 + +/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ + +#define AFL_TXT_BIAS 6 + +/* Maximum length of a string to tamper with */ + +#define AFL_TXT_STRING_MAX_LEN 1024 + +/* Maximum mutations on a string */ + +#define AFL_TXT_STRING_MAX_MUTATIONS 6 + +#endif /* ! _HAVE_CONFIG_H */ + diff --git a/include/afl/types.h b/include/afl/types.h new file mode 100644 index 00000000..7b94fb83 --- /dev/null +++ b/include/afl/types.h @@ -0,0 +1,193 @@ +/* + american fuzzy lop++ - type definitions and minor macros + -------------------------------------------------------- + + Originally written by Michal Zalewski + + Now maintained by Marc Heuse , + Heiko Eißfeldt , + Andrea Fioraldi , + Dominik Maier + + Copyright 2016, 2017 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + */ + +#ifndef _HAVE_TYPES_H +#define _HAVE_TYPES_H + +#include +#include +#include "config.h" + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +#ifdef WORD_SIZE_64 +typedef unsigned __int128 uint128_t; +typedef uint128_t u128; +#endif + +/* Extended forkserver option values */ + +/* Reporting errors */ +#define FS_OPT_ERROR 0xf800008f +#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8) +#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8) +#define FS_ERROR_MAP_SIZE 1 +#define FS_ERROR_MAP_ADDR 2 +#define FS_ERROR_SHM_OPEN 4 +#define FS_ERROR_SHMAT 8 +#define FS_ERROR_MMAP 16 + +/* Reporting options */ +#define FS_OPT_ENABLED 0x80000001 +#define FS_OPT_MAPSIZE 0x40000000 +#define FS_OPT_SNAPSHOT 0x20000000 +#define FS_OPT_AUTODICT 0x10000000 +#define FS_OPT_SHDMEM_FUZZ 0x01000000 +#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 +// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 +#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1) +#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) +#define FS_OPT_SET_MAPSIZE(x) \ + (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) + +typedef unsigned long long u64; + +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +#ifdef WORD_SIZE_64 +typedef __int128 int128_t; +typedef int128_t s128; +#endif + +#ifndef MIN + #define MIN(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + \ + }) + + #define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) + +#endif /* !MIN */ + +#define SWAP16(_x) \ + ({ \ + \ + u16 _ret = (_x); \ + (u16)((_ret << 8) | (_ret >> 8)); \ + \ + }) + +#define SWAP32(_x) \ + ({ \ + \ + u32 _ret = (_x); \ + (u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | \ + ((_ret >> 8) & 0x0000FF00)); \ + \ + }) + +#define SWAP64(_x) \ + ({ \ + \ + u64 _ret = (_x); \ + _ret = \ + (_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \ + _ret = \ + (_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \ + _ret = \ + (_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8; \ + _ret; \ + \ + }) + +// It is impossible to define 128 bit constants, so ... +#ifdef WORD_SIZE_64 + #define SWAPN(_x, _l) \ + ({ \ + \ + u128 _res = (_x), _ret; \ + char *d = (char *)&_ret, *s = (char *)&_res; \ + int i; \ + for (i = 0; i < 16; i++) \ + d[15 - i] = s[i]; \ + u32 sr = 128U - ((_l) << 3U); \ + (_ret >>= sr); \ + (u128) _ret; \ + \ + }) +#endif + +#define SWAPNN(_x, _y, _l) \ + ({ \ + \ + char *d = (char *)(_x), *s = (char *)(_y); \ + u32 i, l = (_l)-1; \ + for (i = 0; i <= l; i++) \ + d[l - i] = s[i]; \ + \ + }) + +#ifdef AFL_LLVM_PASS + #if defined(__linux__) || !defined(__ANDROID__) + #define AFL_SR(s) (srandom(s)) + #define AFL_R(x) (random() % (x)) + #else + #define AFL_SR(s) ((void)s) + #define AFL_R(x) (arc4random_uniform(x)) + #endif +#else + #if defined(__linux__) || !defined(__ANDROID__) + #define SR(s) (srandom(s)) + #define R(x) (random() % (x)) + #else + #define SR(s) ((void)s) + #define R(x) (arc4random_uniform(x)) + #endif +#endif /* ^AFL_LLVM_PASS */ + +#define STRINGIFY_INTERNAL(x) #x +#define STRINGIFY(x) STRINGIFY_INTERNAL(x) + +#define MEM_BARRIER() __asm__ volatile("" ::: "memory") + +#if __GNUC__ < 6 + #ifndef likely + #define likely(_x) (_x) + #endif + #ifndef unlikely + #define unlikely(_x) (_x) + #endif +#else + #ifndef likely + #define likely(_x) __builtin_expect(!!(_x), 1) + #endif + #ifndef unlikely + #define unlikely(_x) __builtin_expect(!!(_x), 0) + #endif +#endif + +#endif /* ! _HAVE_TYPES_H */ + diff --git a/include/uc_priv.h b/include/uc_priv.h index 8c564396..4f1bf4a9 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -15,14 +15,26 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the uc_mode enum typedef. +#ifdef UNICORN_HAS_AFL +#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ + |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) +#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) +#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) +#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) +#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) +#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN|UC_MODE_AFL) +#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) +#else #define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|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_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN) #define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|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 UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) +#endif + #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -95,6 +107,20 @@ typedef void (*uc_softfloat_initialize)(void); // tcg flush softmmu tlb typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); +typedef enum uc_afl_ret { + UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent + UC_AFL_RET_CHILD, // Fork worked. we are a child + UC_AFL_RET_NO_AFL, // No AFL, no need to fork. + UC_AFL_RET_CALLED_TWICE, // AFL has already been started before. + UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) +} uc_afl_ret; + +// we use this as shortcut deep inside uc_afl for the arch specific uc_afl_next(uc, bool) +typedef uc_afl_ret(*uc_afl_ret_uc_bool_t)(struct uc_struct*, bool); + +// afl_forkserver_start +typedef int (*uc_afl_forkserver_t)(struct uc_struct*); + struct hook { int type; // UC_HOOK_* int insn; // instruction for HOOK_INSN @@ -282,6 +308,22 @@ struct uc_struct { bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()? struct list saved_contexts; // The contexts saved by this uc_struct. bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. + +#ifdef UNICORN_HAS_AFL + uc_afl_forkserver_t afl_forkserver_start; // function to start afl forkserver + uc_afl_ret_uc_bool_t afl_child_request_next; // function from child to ask for new testcase (if in child) + int afl_child_pipe[2]; // pipe used to send information from child process to forkserver + int afl_parent_pipe[2]; // pipe used to send information from parent to child in forkserver + uint8_t *afl_area_ptr; // map, shared with afl, to report coverage feedback etc. during runs + uint64_t afl_prev_loc; // previous location + int afl_compcov_level; // how much compcove we want + unsigned int afl_inst_rms; + size_t exit_count; // number of exits set in afl_fuzz or afl_forkserver + uint64_t *exits; // pointer to the actual exits + char *afl_testcase_ptr; // map, shared with afl, to get testcases delivered from for each run + uint32_t *afl_testcase_size_p; // size of the current testcase, if using shared map fuzzing with afl. + void *afl_data_ptr; // Pointer for various (bindings-related) uses. +#endif }; // Metadata stub for the variable-size cpu context used with uc_context_*() diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d7780e56..042318e8 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -105,6 +105,7 @@ typedef enum uc_arch { typedef enum uc_mode { UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode + UC_MODE_AFL = 1 << 29, // arm / arm64 UC_MODE_ARM = 0, // ARM mode @@ -171,6 +172,10 @@ typedef enum uc_err { UC_ERR_HOOK_EXIST, // hook for this event already existed UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() UC_ERR_EXCEPTION, // Unhandled CPU exception + UC_ERR_AFL_RET_ERROR, // Something went horribly wrong in the parent + UC_ERR_AFL_RET_NO_AFL, // No AFL, no need to fork. + UC_ERR_AFL_RET_CALLED_TWICE, // AFL has already been started before. + UC_ERR_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) } uc_err; @@ -568,6 +573,82 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); UNICORN_EXPORT uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count); +/* Callback function called for each input from AFL. + This function is mandatory. + It's purpose is to place the input at the right place in unicorn. + @uc: Unicorn instance + @input: The current input we're working on. Place this somewhere in unicorn's memory now. + @input_len: length of the input + @persistent_round: which round we are currently crashing in, if using persistent mode. + @data: Data pointer passed to uc_afl_fuzz(...). + @return: + If you return is true, all is well. Fuzzing starts. + If you return false, the input is rejected; we will continue with the next input. +*/ +typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, size_t input_len, uint32_t persistent_round, void *data); + +/* Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. + This function is not mandatory (pass NULL). + @uc: Unicorn instance + @unicorn_result: The error state returned by the current testcase + @input: The current input we're workin with. + @input_len: length of the input + @persistent_round: which round we are currently crashing in, if using persistent mode. + @data: Data pointer passed to uc_afl_fuzz(...). +@Return: + If you return false, the crash is considered invalid and not reported to AFL. + If return is true, the crash is reported. + -> The child will die and the forkserver will spawn a new child. +*/ +typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, int input_len, int persistent_round, void *data); + +/* + The main fuzzer. + Starts uc_afl_forkserver(), then beginns a persistent loop. + Reads input, calls the place_input callback, emulates, uc_afl_next(...), repeats. + If unicorn errors out, will call the validate_crash_callback, if set. + Will only retrun in the parent after the whole fuzz thing has been finished and afl died. + The child processes never return from here. + + Note: This API is not supported on Windows. + + @uc: handle returned by uc_open() + @input_file: filename/path to the (AFL) inputfile. Usualy suplied on the commandline. + @place_input_callback: Callback function that will be called before each test runs. + This function needs to write the input from afl to the correct position on the unicorn object. + @exits: address list of exits where fuzzing should stop (len == exit_count) + @exit_count: number of exits where fuzzing should stop + @validate_crash_callback: Optional callback (if not needed, pass NULL), that determines + if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. + @always_validate: If false, validate_crash_callback will only be called for crashes. + @persistent_iters: + The amount of loop iterations in persistent mode before restarteing with a new forked child. + If your target cannot be fuzzed using persistent mode (global state changes a lot), + set persistent_iters = 1 for the normal fork-server experience. + Else, the default is usually around 1000. + If your target is super stable (and unicorn is, too - not sure about that one), + you may pass persistent_iter = 0 for that an infinite fuzz loop. + @data: Your very own data pointer. This will passed into every callback. + @return uc_afl_ret: + >UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent + >UC_AFL_RET_CHILD, // Can never happen, the child will loop happily or exit. + >UC_AFL_RET_NO_AFL, // No AFL, we ran the testacse once and are done. + >UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) + >> We're retuning after having fuzzed. We may now pack our bags and exit. +*/ +UNICORN_EXPORT +uc_err uc_afl_fuzz( + uc_engine *uc, + char* input_file, + uc_afl_cb_place_input_t place_input_callback, + uint64_t *exits, + size_t exit_count, + uc_afl_cb_validate_crash_t validate_crash_callback, + bool always_validate, + uint32_t persistent_iters, + void *data +); + /* Stop emulation (which was started by uc_emu_start() API. This is typically called from callback functions registered via tracing APIs. diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 75d71514..21397dcd 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif +#define afl_forkserver_start afl_forkserver_start_aarch64 +#define helper_afl_maybe_log helper_afl_maybe_log_aarch64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64 #define use_idiv_instructions use_idiv_instructions_aarch64 #define arm_arch arm_arch_aarch64 #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index ee750153..55536832 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64eb #endif +#define afl_forkserver_start afl_forkserver_start_aarch64eb +#define helper_afl_maybe_log helper_afl_maybe_log_aarch64eb +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64eb +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64eb +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64eb #define use_idiv_instructions use_idiv_instructions_aarch64eb #define arm_arch arm_arch_aarch64eb #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64eb diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index 79bcdd13..ea5b8045 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -29,6 +29,10 @@ #include "sysemu/cpus.h" #include "uc_priv.h" +#ifdef UNICORN_HAS_AFL +#include "afl/afl-cpu-inl.h" +#endif + /* -icount align implementation. */ typedef struct SyncClocks { @@ -254,6 +258,11 @@ static inline TranslationBlock *tb_find(CPUState *cpu, /* We add the TB in the virtual pc hash table for the fast lookup */ cpu->tb_jmp_cache[tb_jmp_cache_hash_func(cpu->uc, pc)] = tb; } + +#if defined(UNICORN_HAS_AFL) + afl_request_tsl(cpu, pc, cs_base, flags, cf_mask); +#endif + /* We don't take care of direct jumps when address mapping changes in * system emulation. So it's not safe to make a direct jump to a TB * spanning two pages because the mapping for the second page can change. @@ -579,3 +588,31 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) return ret; } + +#ifdef UNICORN_HAS_AFL +int afl_forkserver_start(struct uc_struct *uc) +{ + // Not sure if we need all of this setup foo. + CPUState *cpu = uc->cpu; + if (!cpu->created) { + cpu->created = true; + cpu->halted = 0; + qemu_init_vcpu(cpu); + + } + cpu_resume(cpu); + + if (uc->count_hook != 0) { + uc_hook_del(uc, uc->count_hook); + uc->count_hook = 0; + } + + uc->quit_request = false; + uc->cpu = cpu; + smp_mb(); + + // Would love to not have the extra step in cpus.c, but it doesn't work otherwise(?) + afl_setup(uc); + return afl_forkserver(cpu); +} +#endif \ No newline at end of file diff --git a/qemu/accel/tcg/tcg-runtime.c b/qemu/accel/tcg/tcg-runtime.c index 1e8283ea..67829b91 100644 --- a/qemu/accel/tcg/tcg-runtime.c +++ b/qemu/accel/tcg/tcg-runtime.c @@ -32,6 +32,10 @@ #include +#ifdef UNICORN_HAS_AFL +#include "afl/afl-tcg-runtime-inl.h" +#endif + /* 32-bit helpers */ int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2) diff --git a/qemu/accel/tcg/tcg-runtime.h b/qemu/accel/tcg/tcg-runtime.h index ab7369e8..813c1c07 100644 --- a/qemu/accel/tcg/tcg-runtime.h +++ b/qemu/accel/tcg/tcg-runtime.h @@ -259,3 +259,10 @@ DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) + +#if defined(UNICORN_HAS_AFL) +DEF_HELPER_FLAGS_2(afl_maybe_log, 0, void, ptr, i64) +DEF_HELPER_FLAGS_4(afl_compcov_log_16, 0, void, ptr, i64, i32, i32) +DEF_HELPER_FLAGS_4(afl_compcov_log_32, 0, void, ptr, i64, i32, i32) +DEF_HELPER_FLAGS_4(afl_compcov_log_64, 0, void, ptr, i64, i64, i64) +#endif \ No newline at end of file diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 0fca28a9..96f92873 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -17,6 +17,11 @@ #include +#if defined(UNICORN_HAS_AFL) +#undef ARCH_HAS_COMPCOV +#include "afl/afl-cpu-translate-inl.h" +#endif + /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if (1) the target is sufficiently clean to support reporting, @@ -56,6 +61,27 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Reset the temp count so that we can identify leaks */ tcg_clear_temp_count(); + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = cpu->uc->exits; + size_t exit_count = cpu->uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (tb->pc == exits[i]) { + // This should catch that instruction is at the end + // and generate appropriate halting code. + gen_tb_start(tcg_ctx, db->tb); + ops->tb_start(db, cpu); + db->num_insns++; + ops->insn_start(db, cpu); + ops->translate_insn(db, cpu); + goto _end_loop; + } + } + } + } + /* Unicorn: early check to see if the address of this block is * the "run until" address. */ if (tb->pc == cpu->uc->addr_end) { @@ -81,6 +107,10 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, // tcg_dump_ops(tcg_ctx, false, "translator loop"); +#ifdef UNICORN_HAS_AFL + afl_gen_maybe_log(tcg_ctx, tb->pc); +#endif + /* Start translating. */ gen_tb_start(tcg_ctx, db->tb); // tcg_dump_ops(tcg_ctx, false, "tb start"); diff --git a/qemu/arm.h b/qemu/arm.h index d3cc372d..ef9fa72d 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif +#define afl_forkserver_start afl_forkserver_start_arm +#define helper_afl_maybe_log helper_afl_maybe_log_arm +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_arm +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_arm +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_arm #define use_idiv_instructions use_idiv_instructions_arm #define arm_arch arm_arch_arm #define tb_target_set_jmp_target tb_target_set_jmp_target_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 0a51a80d..7ecccaaa 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _armeb #endif +#define afl_forkserver_start afl_forkserver_start_armeb +#define helper_afl_maybe_log helper_afl_maybe_log_armeb +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_armeb +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_armeb +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_armeb #define use_idiv_instructions use_idiv_instructions_armeb #define arm_arch arm_arch_armeb #define tb_target_set_jmp_target tb_target_set_jmp_target_armeb diff --git a/qemu/include/tcg/tcg-op.h b/qemu/include/tcg/tcg-op.h index 73d1b93f..915fe79f 100644 --- a/qemu/include/tcg/tcg-op.h +++ b/qemu/include/tcg/tcg-op.h @@ -29,6 +29,10 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" +#ifdef UNICORN_HAS_AFL +#include "afl/afl-tcg-op-inl.h" +#endif + 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); diff --git a/qemu/m68k.h b/qemu/m68k.h index cb3d430b..77fb249c 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif +#define afl_forkserver_start afl_forkserver_start_m68k +#define helper_afl_maybe_log helper_afl_maybe_log_m68k +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_m68k +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_m68k +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_m68k #define use_idiv_instructions use_idiv_instructions_m68k #define arm_arch arm_arch_m68k #define tb_target_set_jmp_target tb_target_set_jmp_target_m68k diff --git a/qemu/mips.h b/qemu/mips.h index a2b78379..9eef9f63 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif +#define afl_forkserver_start afl_forkserver_start_mips +#define helper_afl_maybe_log helper_afl_maybe_log_mips +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips #define use_idiv_instructions use_idiv_instructions_mips #define arm_arch arm_arch_mips #define tb_target_set_jmp_target tb_target_set_jmp_target_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9faef36b..9dde191e 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif +#define afl_forkserver_start afl_forkserver_start_mips64 +#define helper_afl_maybe_log helper_afl_maybe_log_mips64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64 #define use_idiv_instructions use_idiv_instructions_mips64 #define arm_arch arm_arch_mips64 #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 6f748b36..4634c429 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif +#define afl_forkserver_start afl_forkserver_start_mips64el +#define helper_afl_maybe_log helper_afl_maybe_log_mips64el +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64el +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64el +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64el #define use_idiv_instructions use_idiv_instructions_mips64el #define arm_arch arm_arch_mips64el #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index a4831183..1e6ce28b 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif +#define afl_forkserver_start afl_forkserver_start_mipsel +#define helper_afl_maybe_log helper_afl_maybe_log_mipsel +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mipsel +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mipsel +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mipsel #define use_idiv_instructions use_idiv_instructions_mipsel #define arm_arch arm_arch_mipsel #define tb_target_set_jmp_target tb_target_set_jmp_target_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index 8cb9ea3e..e787604c 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif +#define afl_forkserver_start afl_forkserver_start_ppc +#define helper_afl_maybe_log helper_afl_maybe_log_ppc +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc #define use_idiv_instructions use_idiv_instructions_ppc #define arm_arch arm_arch_ppc #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index 1d055072..ada125c0 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif +#define afl_forkserver_start afl_forkserver_start_ppc64 +#define helper_afl_maybe_log helper_afl_maybe_log_ppc64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc64 #define use_idiv_instructions use_idiv_instructions_ppc64 #define arm_arch arm_arch_ppc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index df9eed70..f91bcf0b 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif +#define afl_forkserver_start afl_forkserver_start_riscv32 +#define helper_afl_maybe_log helper_afl_maybe_log_riscv32 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv32 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv32 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv32 #define use_idiv_instructions use_idiv_instructions_riscv32 #define arm_arch arm_arch_riscv32 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index c41e7178..c59c5148 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif +#define afl_forkserver_start afl_forkserver_start_riscv64 +#define helper_afl_maybe_log helper_afl_maybe_log_riscv64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv64 #define use_idiv_instructions use_idiv_instructions_riscv64 #define arm_arch arm_arch_riscv64 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv64 diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index f983f634..acb7f14b 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -194,6 +194,21 @@ void resume_all_vcpus(struct uc_struct* uc) tb_flush_jmp_cache(cpu, uc->addr_end); } + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = uc->exits; + size_t exit_count = uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + TranslationBlock *tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(uc, exits[i])]; + if (tb) { + qht_remove(&uc->tcg_ctx->tb_ctx.htable, tb, tb->hash); + tb_flush_jmp_cache(cpu, uc->exits[i]); + } + } + } + } cpu->created = false; } diff --git a/qemu/sparc.h b/qemu/sparc.h index 741e7565..daa2dcb6 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif +#define afl_forkserver_start afl_forkserver_start_sparc +#define helper_afl_maybe_log helper_afl_maybe_log_sparc +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc #define use_idiv_instructions use_idiv_instructions_sparc #define arm_arch arm_arch_sparc #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 5262a11b..a2e1ec32 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif +#define afl_forkserver_start afl_forkserver_start_sparc64 +#define helper_afl_maybe_log helper_afl_maybe_log_sparc64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc64 #define use_idiv_instructions use_idiv_instructions_sparc64 #define arm_arch arm_arch_sparc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc64 diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index a9eb1ca0..5ab0e963 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -37,6 +37,11 @@ #include "qemu/atomic128.h" #include "kvm-consts.h" +#if defined(UNICORN_HAS_AFL) +#undef ARCH_HAS_COMPCOV +#include "afl/afl-cpu-translate-inl.h" +#endif + static const char *regnames[] = { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", @@ -14636,6 +14641,21 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; + if (dc->uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = dc->uc->exits; + size_t exit_count = dc->uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (dcbase->pc_next == exits[i]) { + dcbase->is_jmp = DISAS_WFI; + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 742a55fd..fe325e1c 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11420,6 +11420,21 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } + if (dc->uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = dc->uc->exits; + size_t exit_count = dc->uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (dcbase->pc_next == exits[i]) { + dcbase->is_jmp = DISAS_WFI; + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index cf148c4b..4b44bafd 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4764,6 +4764,25 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; + if (s->uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = s->uc->exits; + size_t exit_count = s->uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (s->pc == exits[i]) { + // imitate the HLT instruction + gen_update_cc_op(s); + gen_jmp_im(s, pc_start - s->cs_base); + gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start)); + s->base.is_jmp = DISAS_NORETURN; + return s->pc; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { // imitate the HLT instruction diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 323eff44..c1940270 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6325,6 +6325,21 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUM68KState *env = cpu->env_ptr; uint16_t insn; + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = uc->exits; + size_t exit_count = uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (dc->pc == exits[i]) { + gen_exception(dc, dc->pc, EXCP_HLT); + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { gen_exception(dc, dc->pc, EXCP_HLT); diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 97e680a3..ff36123b 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30930,6 +30930,22 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) bool hook_insn = false; is_slot = ctx->hflags & MIPS_HFLAG_BMASK; + + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = uc->exits; + size_t exit_count = uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (ctx->base.pc_next == exits[i]) {// raise a special interrupt to quit + gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); + ctx->base.is_jmp = DISAS_NORETURN; + return; + } + } + } + } // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 8cfebab2..623e8b4c 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7625,6 +7625,21 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = uc->exits; + size_t exit_count = uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (ctx->base.pc_next == exits[i]) { + gen_wait(ctx); + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { gen_wait(ctx); diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 9898093d..3e78dbfc 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -849,6 +849,22 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) TCGOp *tcg_op, *prev_op = NULL; bool insn_hook = false; + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = ctx->uc->exits; + size_t exit_count = ctx->uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (ctx->base.pc_next == exits[i]) { + // Unicorn: We have to exit current execution here. + dcbase->is_jmp = DISAS_UC_EXIT; + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == ctx->uc->addr_end) { // Unicorn: We have to exit current execution here. diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index c6f3d9cd..66f834d3 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5950,6 +5950,24 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPUSPARCState *env = cs->env_ptr; unsigned int insn; + if (uc->mode & UC_MODE_AFL) { + // UNICORN-AFL supports (and needs) multiple exits. + uint64_t *exits = uc->exits; + size_t exit_count = uc->exit_count; + if (exit_count) { + size_t i; + for (i = 0; i < exit_count; i++) { + if (dc->pc == exits[i]) { +#ifndef TARGET_SPARC64 + gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); +#endif + dcbase->is_jmp = DISAS_NORETURN; + return; + } + } + } + } + // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { #ifndef TARGET_SPARC64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index a1896af7..233e03c3 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,6 +4,11 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif +#define afl_forkserver_start afl_forkserver_start_x86_64 +#define helper_afl_maybe_log helper_afl_maybe_log_x86_64 +#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_x86_64 +#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_x86_64 +#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_x86_64 #define use_idiv_instructions use_idiv_instructions_x86_64 #define arm_arch arm_arch_x86_64 #define tb_target_set_jmp_target tb_target_set_jmp_target_x86_64 diff --git a/symbols.sh b/symbols.sh index 19997fb4..0f8541b2 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,6 +4,11 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" +afl_forkserver_start \ +helper_afl_maybe_log \ +helper_afl_compcov_log_16 \ +helper_afl_compcov_log_32 \ +helper_afl_compcov_log_64 \ use_idiv_instructions \ arm_arch \ tb_target_set_jmp_target \ diff --git a/uc.c b/uc.c index 3e24674c..40ac6001 100644 --- a/uc.c +++ b/uc.c @@ -26,6 +26,17 @@ #include "qemu/include/qemu/queue.h" +#ifdef UNICORN_HAS_AFL +#include +#include +#include +#include +#include +#include +#include "afl/config.h" +#include "afl/types.h" +#endif + UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) { @@ -93,6 +104,14 @@ const char *uc_strerror(uc_err code) return "Insufficient resource (UC_ERR_RESOURCE)"; case UC_ERR_EXCEPTION: return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; + case UC_ERR_AFL_RET_ERROR: + return "Something went horribly wrong in the parent (UC_ERR_AFL_RET_ERROR)"; + case UC_ERR_AFL_RET_NO_AFL: + return "No AFL, no need to fork (UC_ERR_AFL_RET_NO_AFL)"; + case UC_ERR_AFL_RET_CALLED_TWICE: + return "AFL has already been started before (UC_ERR_AFL_RET_CALLED_TWICE)"; + case UC_ERR_AFL_RET_FINISHED: + return "We forked before but now parent is gone (UC_ERR_AFL_REG_FINISHED)"; } } @@ -748,6 +767,315 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time } +static inline uc_afl_ret uc_afl_forkserver_start(uc_engine *uc, uint64_t *exits, size_t exit_count) +{ + /* + Why we need exits as parameter to forkserver: + In the original unicorn-afl, Unicorn needed to flush the tb cache for every iteration. + This is super slow. + Problem was, that the original forked server doesn't know about possible future exits. + The cached blocks, in the next child, therefore would have no exit set and run forever. + Also it's nice to have multiple exits, so let's just do it right. + */ + + if (!uc) { + fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); + return UC_AFL_RET_ERROR; + } + if (!exits) { + fprintf(stderr, "[!] Nullptr provided for exits.\n"); + return UC_AFL_RET_ERROR; + } + if (!exit_count) { + fprintf(stderr, "[!] No exits provided (exit_count was 0).\n"); + return UC_AFL_RET_ERROR; + } + if (unlikely(uc->afl_area_ptr)) { +#if defined(AFL_DEBUG) + fprintf(stderr, "[!] forkserver_start(...) called twice. Already fuzzing!\n"); +#endif + return UC_AFL_RET_CALLED_TWICE; // AFL has already been started before. + } + + /* Copy exits to unicorn env buffer */ + uc->exits = g_realloc(uc->exits, sizeof(exits[0]) * exit_count); + if (uc->exits == NULL) { + perror("[!] malloc failed when starting forkserver."); + return UC_AFL_RET_ERROR; + } + memcpy(uc->exits, exits, sizeof(exits[0]) * exit_count); + uc->exit_count = exit_count; + // Set addr_end to make sure unicorn will not stop at addr 0x0. + uc->addr_end = uc->exits[0]; + + /* Fork() :) */ + return uc->afl_forkserver_start(uc); + +} + +/* AFL++ supports testcase forwarding via shared map. + If the env variable is set, get the shared map here. + returns true if we enabled shmap fuzzing, false otherwise. */ +static bool uc_afl_enable_shm_testcases(uc_engine *uc) { + + char *id_str = getenv(SHM_FUZZ_ENV_VAR); + if (id_str) { + int shm_id = atoi(id_str); + char *map = (char *)shmat(shm_id, NULL, 0); + if (!map || map == (void *)-1) { + perror("[!] could not access fuzzing shared memory"); + exit(1); + } + uc->afl_testcase_size_p = (u32 *)map; + uc->afl_testcase_ptr = (map + sizeof(u32)); +#if defined(AFL_DEBUG) + printf("[d] successfully opened shared memory for testcases with id %d\n", shm_id); +#endif + return true; + + } else { +#if defined(AFL_DEBUG) + printf("[d] SHM_FUZZ_ENV_VAR not set - not using shared map fuzzing.\n"); +#endif + return false; + } + +} + +/* returns the filesize in bytes, -1 or error. */ +static inline off_t uc_afl_mmap_file(char *filename, char **buf_ptr) { + + off_t ret = -1; + + int fd = open(filename, O_RDONLY); + + struct stat st = {0}; + if (fstat(fd, &st)) goto exit; + + off_t in_len = st.st_size; + + *buf_ptr = mmap(0, in_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + + if (*buf_ptr != MAP_FAILED) ret = in_len; + +exit: + close(fd); + return ret; + +} + +/* A start with "less features" for our afl use-case */ +/* this is largely copied from uc_emu_start, just without setting the entry point, counter and timeout. */ +int uc_afl_emu_start(uc_engine *uc) { + + uc->emu_counter = 0; + uc->invalid_error = UC_ERR_OK; + uc->emulation_done = false; + uc->stop_request = false; + + // remove count hook if counting isn't necessary + if (uc->count_hook != 0) { + uc_hook_del(uc, uc->count_hook); + uc->count_hook = 0; + } + + uc->vm_start(uc); + + // emulation is done + uc->emulation_done = true; + + return uc->invalid_error; + +} + +/* afl_next that expects you know what you're doing + Specifically, it won't check for afl_area_ptr and next to be set. */ +static inline uc_afl_ret uc_afl_next_inl(uc_engine *uc, bool crash_found) +{ + // Tell the parent we need a new testcase, then stop until testcase is available. + if (uc->afl_child_request_next(uc, crash_found) == UC_AFL_RET_ERROR) return UC_AFL_RET_ERROR; + return UC_AFL_RET_CHILD; + +} + + +/* similar to __afl_persistent loop */ +static inline uc_afl_ret uc_afl_next(uc_engine *uc, bool crash_found) +{ + + if (unlikely(!uc->afl_area_ptr)) { + fprintf(stderr, "[!] uc_afl_next(...) called before forkserver_start(...)."); + return UC_AFL_RET_ERROR; + } + + // Tell the parent we need a new testcase, then stop until testcase is available. + if (uc->afl_child_request_next) { + + return uc_afl_next_inl(uc, crash_found); + + } + + return UC_AFL_RET_NO_AFL; +} + +UNICORN_EXPORT +uc_err uc_afl_fuzz( + uc_engine *uc, + char* input_file, + uc_afl_cb_place_input_t place_input_callback, + uint64_t *exits, + size_t exit_count, + uc_afl_cb_validate_crash_t validate_crash_callback, + bool always_validate, + uint32_t persistent_iters, + void *data +){ +#ifndef UNICORN_HAS_AFL + return UC_ERR_MODE; +#else + if (!uc) { + fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); + return UC_AFL_RET_ERROR; + } + if (!input_file || input_file[0] == 0) { + fprintf(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); + return UC_AFL_RET_ERROR; + } + if (!place_input_callback) { + fprintf(stderr, "[!] no place_input_callback set.\n"); + return UC_AFL_RET_ERROR; + } + if (always_validate && !validate_crash_callback) { + fprintf(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); + return UC_AFL_RET_ERROR; + } + if (!exit_count) { + fprintf(stderr, "[!] Nullptr provided for exits.\n"); + return UC_AFL_RET_ERROR; + } + + uint32_t mmap_in_len = 0; + char *in_buf = NULL; + uint32_t *in_len_p = NULL; + + bool use_shmap_input = uc_afl_enable_shm_testcases(uc); + if (use_shmap_input) { + /* For shared map fuzzing, the ptr stays the same */ + in_buf = uc->afl_testcase_ptr; + in_len_p = uc->afl_testcase_size_p; + } else { + in_len_p = &mmap_in_len; + } + + uc_afl_ret afl_ret = uc_afl_forkserver_start(uc, exits, exit_count); + switch(afl_ret) { + case UC_AFL_RET_CHILD: + break; + case UC_AFL_RET_NO_AFL: + // Not running in AFL. + persistent_iters = 1; + break; + case UC_AFL_RET_FINISHED: + // Nothing more to do + return afl_ret; + case UC_AFL_RET_ERROR: + case UC_AFL_RET_CALLED_TWICE: + // Nothing more we can do + return afl_ret; + default: + // What have we done + fprintf(stderr, "[!] Unexpected forkserver return: %d", afl_ret); + return UC_AFL_RET_ERROR; + } + + bool first_round = true; + bool crash_found = false; + +#if defined(AFL_DEBUG) + if (uc->afl_testcase_ptr) { + printf("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); + } +#endif + + // 0 means never stop child in persistence mode. + uint32_t i; + for (i = 0; persistent_iters == 0 || i < persistent_iters; i++) { + + // The main fuzz loop starts here :) + if (first_round) { + first_round = false; + } else { + if (uc_afl_next_inl(uc, crash_found) == UC_AFL_RET_ERROR) { + /* parent is probably gone */ + exit(1); + } + crash_found = false; + } + + /* get input, call place input callback, emulate, unmap input (if needed) */ + if (unlikely(!use_shmap_input)) { + /* in_buf and the len are not in a shared map (as it would be for sharedmem fuzzing + No shmap fuzzing involved - Let's read a "normal" file. */ + off_t in_len = uc_afl_mmap_file(input_file, &in_buf); + if (unlikely(in_len < 0)) { + fprintf(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); + perror("mmap"); + fflush(stderr); + return UC_AFL_RET_ERROR; + } + mmap_in_len = in_len; + } + bool input_accepted = place_input_callback(uc, in_buf, *in_len_p, i, data); + + if (unlikely(!input_accepted)) { + // Apparently the input was not to the users' liking. Let's continue. + goto next_iter; + } + + uc_err uc_emu_ret = uc_afl_emu_start(uc); + + if (unlikely((uc_emu_ret != UC_ERR_OK) || (always_validate && validate_crash_callback))) { + + if (validate_crash_callback != NULL && validate_crash_callback( + uc, uc_emu_ret, in_buf, *in_len_p, i, data) != true) { + // The callback thinks this is not a valid crash. Ignore. + goto next_iter; + } + if (persistent_iters != 1) { + // We're inpersistent mode and can report the crash via afl_next. No reason to die. + crash_found = true; + goto next_iter; + } + + fprintf(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); + fflush(stderr); + + abort(); + + } +next_iter: + if (!use_shmap_input) munmap(in_buf, mmap_in_len); + } + // UC_AFL_RET_CHILD -> We looped through all iters. + // We are still in the child, nothing good will come after this. + // Exit and let the next generation run. + if (likely(afl_ret == UC_AFL_RET_CHILD)) { + exit(0); + } + + if (uc->afl_area_ptr) { + // Nothing should ever come after this but clean it up still. + // shmdt(uc->afl_area_ptr); + uc->afl_area_ptr = NULL; + uc->afl_testcase_ptr = NULL; + + } + + // UC_AFL_RET_NO_AFL -> Not fuzzing. We ran once. + return UC_AFL_RET_NO_AFL; +#endif +} + UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) { From f08b7d6b5b4afe4d0401ac92e4cf2922824161ec Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 00:57:32 +0200 Subject: [PATCH 10/40] Make gen_const work and updates constants --- bindings/Makefile | 4 ++-- bindings/dotnet/UnicornManaged/Const/Common.fs | 5 +++++ bindings/go/Makefile | 2 +- bindings/go/unicorn/unicorn_const.go | 5 +++++ bindings/java/Makefile | 2 +- bindings/java/unicorn/UnicornConst.java | 5 +++++ bindings/pascal/unicorn/UnicornConst.pas | 5 +++++ bindings/python/Makefile | 12 ++++++------ bindings/python/unicorn/unicorn_const.py | 5 +++++ bindings/ruby/Makefile | 2 +- .../unicorn_gem/lib/unicorn_engine/unicorn_const.rb | 5 +++++ 11 files changed, 41 insertions(+), 11 deletions(-) diff --git a/bindings/Makefile b/bindings/Makefile index 296b44f3..44423401 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -24,8 +24,8 @@ build: $(MAKE) -C go gen_const $(MAKE) -C java gen_const $(MAKE) -C ruby gen_const - python const_generator.py dotnet - python const_generator.py pascal + python3 const_generator.py dotnet + python3 const_generator.py pascal install: build $(MAKE) -C python install diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 0b91cac1..03cc19a4 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -28,6 +28,7 @@ module Common = let UC_MODE_LITTLE_ENDIAN = 0 let UC_MODE_BIG_ENDIAN = 1073741824 + let UC_MODE_AFL = 536870912 let UC_MODE_ARM = 0 let UC_MODE_THUMB = 16 @@ -75,6 +76,10 @@ module Common = let UC_ERR_HOOK_EXIST = 19 let UC_ERR_RESOURCE = 20 let UC_ERR_EXCEPTION = 21 + let UC_ERR_AFL_RET_ERROR = 22 + let UC_ERR_AFL_RET_NO_AFL = 23 + let UC_ERR_AFL_RET_CALLED_TWICE = 24 + let UC_ERR_AFL_RET_FINISHED = 25 let UC_MEM_READ = 16 let UC_MEM_WRITE = 17 let UC_MEM_FETCH = 18 diff --git a/bindings/go/Makefile b/bindings/go/Makefile index fe898ae1..f8b0d5f1 100644 --- a/bindings/go/Makefile +++ b/bindings/go/Makefile @@ -6,7 +6,7 @@ all: gen_const cd unicorn && go build gen_const: - cd .. && python const_generator.py go + cd .. && python3 const_generator.py go test: all cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 6196fde5..a45e1452 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -23,6 +23,7 @@ const ( MODE_LITTLE_ENDIAN = 0 MODE_BIG_ENDIAN = 1073741824 + MODE_AFL = 536870912 MODE_ARM = 0 MODE_THUMB = 16 @@ -70,6 +71,10 @@ const ( ERR_HOOK_EXIST = 19 ERR_RESOURCE = 20 ERR_EXCEPTION = 21 + ERR_AFL_RET_ERROR = 22 + ERR_AFL_RET_NO_AFL = 23 + ERR_AFL_RET_CALLED_TWICE = 24 + ERR_AFL_RET_FINISHED = 25 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 73d20725..313db888 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -19,7 +19,7 @@ uninstall: $(MAKE) -f Makefile.build uninstall gen_const: - cd .. && python const_generator.py java + cd .. && python3 const_generator.py java clean: rm -f unicorn/*.class diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index f4396003..ce6744be 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -25,6 +25,7 @@ public interface UnicornConst { public static final int UC_MODE_LITTLE_ENDIAN = 0; public static final int UC_MODE_BIG_ENDIAN = 1073741824; + public static final int UC_MODE_AFL = 536870912; public static final int UC_MODE_ARM = 0; public static final int UC_MODE_THUMB = 16; @@ -72,6 +73,10 @@ public interface UnicornConst { public static final int UC_ERR_HOOK_EXIST = 19; public static final int UC_ERR_RESOURCE = 20; public static final int UC_ERR_EXCEPTION = 21; + public static final int UC_ERR_AFL_RET_ERROR = 22; + public static final int UC_ERR_AFL_RET_NO_AFL = 23; + public static final int UC_ERR_AFL_RET_CALLED_TWICE = 24; + public static final int UC_ERR_AFL_RET_FINISHED = 25; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 29303b89..3f202cb9 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -26,6 +26,7 @@ const UC_API_MAJOR = 2; UC_MODE_LITTLE_ENDIAN = 0; UC_MODE_BIG_ENDIAN = 1073741824; + UC_MODE_AFL = 536870912; UC_MODE_ARM = 0; UC_MODE_THUMB = 16; @@ -73,6 +74,10 @@ const UC_API_MAJOR = 2; UC_ERR_HOOK_EXIST = 19; UC_ERR_RESOURCE = 20; UC_ERR_EXCEPTION = 21; + UC_ERR_AFL_RET_ERROR = 22; + UC_ERR_AFL_RET_NO_AFL = 23; + UC_ERR_AFL_RET_CALLED_TWICE = 24; + UC_ERR_AFL_RET_FINISHED = 25; UC_MEM_READ = 16; UC_MEM_WRITE = 17; UC_MEM_FETCH = 18; diff --git a/bindings/python/Makefile b/bindings/python/Makefile index ea831fd9..363d646f 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -3,16 +3,16 @@ .PHONY: gen_const install install3 clean sdist sdist3 bdist bdist3 sdist_win bdist_win gen_const: - cd .. && python const_generator.py python + cd .. && python3 const_generator.py python install: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll if test -n "${DESTDIR}"; then \ - python setup.py install --root="${DESTDIR}"; \ + python3 setup.py install --root="${DESTDIR}"; \ else \ - python setup.py install; \ + python3 setup.py install; \ fi install3: @@ -30,7 +30,7 @@ sdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with source code of the core sdist3: @@ -44,7 +44,7 @@ bdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py bdist_wheel register upload + python3 setup.py bdist_wheel register upload # build & upload PyPi package with precompiled core bdist3: @@ -57,7 +57,7 @@ bdist3: # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand sdist_win: rm -rf src/ dist/ - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with prebuilt core # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index a517572a..1b9ac693 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -21,6 +21,7 @@ UC_ARCH_MAX = 9 UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 +UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -68,6 +69,10 @@ UC_ERR_FETCH_UNALIGNED = 18 UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 +UC_ERR_AFL_RET_ERROR = 22 +UC_ERR_AFL_RET_NO_AFL = 23 +UC_ERR_AFL_RET_CALLED_TWICE = 24 +UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index 9d52de94..aa92fa53 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -8,4 +8,4 @@ install: gen_const cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem gen_const: - cd .. && python const_generator.py ruby + cd .. && python3 const_generator.py ruby diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index a09f3e82..698b71c0 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -23,6 +23,7 @@ module UnicornEngine UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 + UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -70,6 +71,10 @@ module UnicornEngine UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 + UC_ERR_AFL_RET_ERROR = 22 + UC_ERR_AFL_RET_NO_AFL = 23 + UC_ERR_AFL_RET_CALLED_TWICE = 24 + UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 From 6f4563c12bf2036c5121098afded12706bd6be59 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 01:20:02 +0200 Subject: [PATCH 11/40] Fix typo --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 40ac6001..c5024447 100644 --- a/uc.c +++ b/uc.c @@ -111,7 +111,7 @@ const char *uc_strerror(uc_err code) case UC_ERR_AFL_RET_CALLED_TWICE: return "AFL has already been started before (UC_ERR_AFL_RET_CALLED_TWICE)"; case UC_ERR_AFL_RET_FINISHED: - return "We forked before but now parent is gone (UC_ERR_AFL_REG_FINISHED)"; + return "We forked before but now parent is gone (UC_ERR_AFL_RET_FINISHED)"; } } From 17963ff4aaa0e0414e9b53deeba80f1bbc754a35 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 01:27:51 +0200 Subject: [PATCH 12/40] Update python bindings for afl --- bindings/python/unicorn/unicorn.py | 135 ++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index 58c6ee06..dbbc4d35 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -9,7 +9,7 @@ import os.path import sys import weakref import functools - +import gc from . import x86_const, arm64_const, unicorn_const as uc if not hasattr(sys.modules[__name__], "__file__"): @@ -120,6 +120,15 @@ class _uc_mem_region(ctypes.Structure): ("perms", ctypes.c_uint32), ] +#typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, +# size_t input_len, uint32_t persistent_round, void *data); +AFL_PLACE_INPUT_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.POINTER(ctypes.c_char), + ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) + +#typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, +# int input_len, int persistent_round, void *data); +AFL_VALIDATE_CRASH_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ucerr, ctypes.POINTER(ctypes.c_char), + ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) _setup_prototype(_uc, "uc_version", ctypes.c_uint, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) _setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) @@ -151,6 +160,7 @@ _setup_prototype(_uc, "uc_context_free", ucerr, uc_context) _setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32)) # https://bugs.python.org/issue42880 _setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64) +_setup_prototype(_uc, "uc_afl_fuzz", ucerr, uc_engine, ctypes.c_char_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint64), ctypes.c_size_t, ctypes.c_void_p, ctypes.c_bool, ctypes.c_uint32, ctypes.c_void_p) UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p) @@ -411,6 +421,8 @@ class Uc(object): self._callback_count = 0 self._cleanup.register(self) + self.afl_called_before = False # type: bool + @staticmethod def release_handle(uch): if uch: @@ -432,6 +444,127 @@ class Uc(object): status = _uc.uc_emu_stop(self._uch) if status != uc.UC_ERR_OK: raise UcError(status) + + def afl_fuzz( + self, # type: Uc + input_file, # type: str + place_input_callback, # type: Callable[[Uc, bytes, int, Any], Optional[bool]] + exits, # type: List[int] + validate_crash_callback=None, # type: Optional[Callable[[Uc, UcError, bytes, int, Any], Optional[bool]]] + always_validate=False, # type: bool + persistent_iters=1, # type: int + data=None, # type: Any + ): + # type: (...) -> bool + """ + The main fuzzer. + Starts the forkserver, then beginns a persistent loop. + Reads input, calls the place_input callback, emulates, repeats. + If unicorn errors out, will call the validate_crash_callback, if set. + Will only return in the parent after the whole fuzz thing has been finished and afl died. + The child processes never return from here. + + :param input_file: filename/path to the (AFL) inputfile. Usually supplied on the commandline. + :param place_input_callback: Callback function that will be called before each test runs. + This function needs to write the input from afl to the correct position on the unicorn object. + This function is mandatory. + It's purpose is to place the input at the right place in unicorn. + + @uc: (Uc) Unicorn instance + @input: (bytes) The current input we're working on. Place this somewhere in unicorn's memory now. + @persistent_round: (int) which round we are currently crashing in, if using persistent mode. + @data: (Any) Data pointer passed to uc_afl_fuzz(...). + + @return: (bool) + If you return is True (or None) all is well. Fuzzing starts. + If you return False, the input is rejected; we will continue with the next input. + :param exits: address list of exits where fuzzing should stop + :param persistent_iters: + The amount of loop iterations in persistent mode before restarting with a new forked child. + If your target cannot be fuzzed using persistent mode (global state changes a lot), + set persistent_iters = 1 for the normal fork-server experience. + Else, the default is usually around 1000. + If your target is super stable (and unicorn is, too - not sure about that one), + you may pass persistent_iter = 0 for that an infinite fuzz loop. + :param validate_crash_callback: Optional callback (if not needed, pass NULL), that determines + if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. + Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. + This function is not mandatory. + @uc: Unicorn instance + @unicorn_result: The error state returned by the current testcase + @input: The current input we're working with. + @persistent_round: which round we are currently crashing in, if using persistent mode. + @data: Data pointer passed to uc_afl_fuzz(...). + + @Return: + If you return false, the crash is considered invalid and not reported to AFL. + -> Next loop iteration begins. + If return is true, the crash is reported // the program crashes. + -> The child will die and the forkserver will spawn a new child. + :param always_validate: If false, validate_crash_callback will only be called for crashes. + :param data: Your very own data pointer. This will passed into every callback. + + :return: + True, if we fuzzed. + False, if AFL was not available but we ran once. + raises UcAflException if nothing worked. + """ + if self.afl_called_before: + raise UcError(uc.UC_ERR_AFL_RET_CALLED_TWICE) + self.afl_called_before = True + self._pre_afl() + exit_count = len(exits) + + def place_input_wrapper(c_uc, input, input_len, persistent_round, c_data): + # print("Calling back home. :)", c_uc, input, input_len, persistent_round, c_data) + ret = place_input_callback( + self, + ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, + persistent_round, + data + ) + if ret is False: + return False + return True + + def validate_crash_wrapper(c_uc, uc_err, input, input_len, persistent_round, c_data): + # print("Calling after crash!", c_uc, input, input_len, persistent_round, c_data) + # assert type(uc_err) == int + ret = validate_crash_callback( + self, + UcError(uc_err), + ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, + persistent_round, + data + ) + if ret is False or (ret is None and uc_err == uc.UC_ERR_OK): + return False + return True + + # This only returns in the parent, child processes all die or loop or other things. + status = _uc.uc_afl_fuzz( + self._uch, + input_file.encode('utf-8'), + AFL_PLACE_INPUT_CB(place_input_wrapper), + (ctypes.c_uint64 * exit_count)(*exits), + exit_count, # bad languages, like c, need more params. + AFL_VALIDATE_CRASH_CB(validate_crash_wrapper) if validate_crash_callback else None, + always_validate, + persistent_iters, + None # no need to pass the user data through C as the callback keeps it as closure. + ) + if status != uc.UC_ERR_OK: + # Something went wrong. + raise UcError(status) + + def _pre_afl(self): + # type: (Uc) -> None + """ + Internal func making sure exits are set and flushing buffers/gc + :param exits: exits + """ + sys.stdout.flush() # otherwise children will inherit the unflushed buffer + gc.collect() # Collect all unneeded memory, No need to clone it on fork. # return the value of a register def reg_read(self, reg_id, opt=None): From d965c0f159256b10042a46a032dc56690baf5b45 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 10:46:52 +0200 Subject: [PATCH 13/40] Use UCLOG and fix uc_afl_fuzz --- include/afl/afl-cpu-inl.h | 26 ++++++++++------ include/uc_priv.h | 5 +++ qemu/tcg/tcg.c | 64 +++++++++++++++++++-------------------- qemu/unicorn_common.h | 5 ++- uc.c | 38 ++++++++++++----------- 5 files changed, 78 insertions(+), 60 deletions(-) diff --git a/include/afl/afl-cpu-inl.h b/include/afl/afl-cpu-inl.h index 5a781e6f..fcb44b8e 100644 --- a/include/afl/afl-cpu-inl.h +++ b/include/afl/afl-cpu-inl.h @@ -75,8 +75,8 @@ struct afl_tsl { uint64_t flags; uint32_t cf_mask; #if defined(TARGET_MIPS) - TCGv_i32 hflags; - TCGv_i32 btarget; + target_ulong hflags; + target_ulong btarget; #endif }; @@ -390,6 +390,9 @@ static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong struct uc_struct* uc = cpu->uc; if (uc->afl_child_request_next == NULL) return; enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; +#if defined(TARGET_MIPS) + CPUArchState* env = cpu->env_ptr; +#endif struct afl_tsl t = { .pc = pc, @@ -397,8 +400,8 @@ static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong .flags = flags, .cf_mask = cf_mask, #if defined(TARGET_MIPS) - .hflags = cpu->uc->tcg_ctx->hflags, - .btarget = cpu->uc->tcg_ctx->btarget, + .hflags = env->hflags, + .btarget = env->btarget, #endif }; @@ -469,6 +472,9 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { enum afl_child_ret child_msg; struct afl_tsl t; +#if defined(TARGET_MIPS) + CPUArchState* env = cpu->env_ptr; +#endif while (1) { @@ -491,10 +497,10 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { // Prepare hflags for delay slot #if defined(TARGET_MIPS) struct afl_tsl tmp; - tmp.hflags = cpu->uc->tcg_ctx->hflags; - tmp.btarget = cpu->uc->tcg_ctx->btarget; - cpu->uc->tcg_ctx->hflags = t.hflags; - cpu->uc->tcg_ctx->btarget = t.btarget; + tmp.hflags = env->hflags; + tmp.btarget = env->btarget; + env->hflags = t.hflags; + env->btarget = t.btarget; #endif // Cache. @@ -504,8 +510,8 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { // Restore hflags #if defined(TARGET_MIPS) - cpu->uc->tcg_ctx->hflags = tmp.hflags; - cpu->uc->tcg_ctx->btarget = tmp.btarget; + env->hflags = tmp.hflags; + env->btarget = tmp.btarget; #endif } else { diff --git a/include/uc_priv.h b/include/uc_priv.h index 4f1bf4a9..b881a666 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -35,6 +35,11 @@ #define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) #endif +#ifndef NDEBUG +#define UCLOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define UCLOG(...) +#endif #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 5fd5ff0f..6e4f3d49 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -1655,7 +1655,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) def = &s->tcg_op_defs[c]; if (c == INDEX_op_insn_start) { nb_oargs = 0; - printf(" ----"); + UCLOG(" ----"); for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { target_ulong a; @@ -1664,7 +1664,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) #else a = op->args[i]; #endif - printf(" " TARGET_FMT_lx, a); + UCLOG(" " TARGET_FMT_lx, a); } } else if (c == INDEX_op_call) { /* variable number of arguments */ @@ -1673,11 +1673,11 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) nb_cargs = def->nb_cargs; /* function name, flags, out args */ - printf(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, + UCLOG(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, tcg_find_helper(s, op->args[nb_oargs + nb_iargs]), op->args[nb_oargs + nb_iargs + 1], nb_oargs); for (i = 0; i < nb_oargs; i++) { - printf(",%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG(",%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[i])); } for (i = 0; i < nb_iargs; i++) { @@ -1686,33 +1686,33 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) if (arg != TCG_CALL_DUMMY_ARG) { t = tcg_get_arg_str(s, buf, sizeof(buf), arg); } - printf(",%s", t); + UCLOG(",%s", t); } } else { - printf(" %s ", def->name); + UCLOG(" %s ", def->name); nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; if (def->flags & TCG_OPF_VECTOR) { - printf("v%d,e%d,", 64 << TCGOP_VECL(op), + UCLOG("v%d,e%d,", 64 << TCGOP_VECL(op), 8 << TCGOP_VECE(op)); } k = 0; for (i = 0; i < nb_oargs; i++) { if (k != 0) { - printf(","); + UCLOG(","); } - printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } for (i = 0; i < nb_iargs; i++) { if (k != 0) { - printf(","); + UCLOG(","); } - printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } switch (c) { @@ -1728,9 +1728,9 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_cmpsel_vec: if (op->args[k] < ARRAY_SIZE(cond_name) && cond_name[op->args[k]]) { - printf(",%s", cond_name[op->args[k++]]); + UCLOG(",%s", cond_name[op->args[k++]]); } else { - printf(",$0x%" TCG_PRIlx, op->args[k++]); + UCLOG(",$0x%" TCG_PRIlx, op->args[k++]); } i = 1; break; @@ -1744,12 +1744,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned ix = get_mmuidx(oi); if (op & ~(MO_AMASK | MO_BSWAP | MO_SSIZE)) { - printf(",$0x%x,%u", op, ix); + UCLOG(",$0x%x,%u", op, ix); } else { const char *s_al, *s_op; s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT]; s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)]; - printf(",%s%s,%u", s_al, s_op, ix); + UCLOG(",%s%s,%u", s_al, s_op, ix); } i = 1; } @@ -1764,7 +1764,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: case INDEX_op_brcond2_i32: - printf("%s$L%d", k ? "," : "", + UCLOG("%s$L%d", k ? "," : "", arg_label(op->args[k])->id); i++, k++; break; @@ -1772,12 +1772,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) break; } for (; i < nb_cargs; i++, k++) { - printf("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); + UCLOG("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); } if(c == INDEX_op_mov_i64){ struct TCGTemp* tp = arg_temp(op->args[1]); if (tp && tp->val_type == TEMP_VAL_MEM){ - printf(" mem_base=%p ", tp->mem_base); + UCLOG(" mem_base=%p ", tp->mem_base); } } } @@ -1786,19 +1786,19 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned life = op->life; if (life & (SYNC_ARG * 3)) { - printf(" sync:"); + UCLOG(" sync:"); for (i = 0; i < 2; ++i) { if (life & (SYNC_ARG << i)) { - printf(" %d", i); + UCLOG(" %d", i); } } } life /= DEAD_ARG; if (life) { - printf(" dead:"); + UCLOG(" dead:"); for (i = 0; life; ++i, life >>= 1) { if (life & 1) { - printf(" %d", i); + UCLOG(" %d", i); } } } @@ -1809,28 +1809,28 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) TCGRegSet set = op->output_pref[i]; if (i == 0) { - printf(" pref="); + UCLOG(" pref="); } else { - printf(","); + UCLOG(","); } if (set == 0) { - printf("none"); + UCLOG("none"); } else if (set == MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS)) { - printf("all"); + UCLOG("all"); #ifdef CONFIG_DEBUG_TCG } else if (tcg_regset_single(set)) { TCGReg reg = tcg_regset_first(set); printf("%s", tcg_target_reg_names[reg]); #endif } else if (TCG_TARGET_NB_REGS <= 32) { - printf("%#x", (uint32_t)set); + UCLOG("%#x", (uint32_t)set); } else { - printf("%#" PRIx64, (uint64_t)set); + UCLOG("%#" PRIx64, (uint64_t)set); } } } - printf("\n"); + UCLOG("\n"); } #if 0 @@ -1863,16 +1863,16 @@ void tcg_dump_ops(TCGContext *s, bool have_prefs, const char *headline) int insn_idx = 0; int op_idx = 0; - printf("\n*** %s\n", headline); + UCLOG("\n*** %s\n", headline); // tcg_dump_tbs(s, tcg_dump_tb, NULL); QTAILQ_FOREACH(op, &s->ops, link) { if (op->opc == INDEX_op_insn_start) { - printf("\n insn_idx=%d", insn_idx); + UCLOG("\n insn_idx=%d", insn_idx); insn_idx++; op_idx = 0; } else { - printf(" %d: ", op_idx); + UCLOG(" %d: ", op_idx); } op_idx++; tcg_dump_op(s, have_prefs, op); diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 84bbb9f1..02b10ea8 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -11,6 +11,7 @@ void vm_start(struct uc_struct*); void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size); +int afl_forkserver_start(struct uc_struct*); // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, @@ -106,7 +107,9 @@ static inline void uc_common_init(struct uc_struct* uc) uc->softfloat_initialize = softfloat_init; uc->tcg_flush_tlb = tcg_flush_softmmu_tlb; uc->memory_map_io = memory_map_io; - +#ifdef UNICORN_HAS_AFL + uc->afl_forkserver_start = afl_forkserver_start; +#endif if (!uc->release) uc->release = release_common; } diff --git a/uc.c b/uc.c index c5024447..2ad8edc7 100644 --- a/uc.c +++ b/uc.c @@ -934,24 +934,27 @@ uc_err uc_afl_fuzz( return UC_ERR_MODE; #else if (!uc) { - fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); + return UC_ERR_AFL_RET_ERROR; + } + if (!(uc->mode & UC_MODE_AFL)) { + return UC_ERR_MODE; } if (!input_file || input_file[0] == 0) { - fprintf(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); + return UC_ERR_AFL_RET_ERROR; } if (!place_input_callback) { - fprintf(stderr, "[!] no place_input_callback set.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] no place_input_callback set.\n"); + return UC_ERR_AFL_RET_ERROR; } if (always_validate && !validate_crash_callback) { - fprintf(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); + return UC_ERR_AFL_RET_ERROR; } if (!exit_count) { - fprintf(stderr, "[!] Nullptr provided for exits.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Nullptr provided for exits.\n"); + return UC_ERR_AFL_RET_ERROR; } uint32_t mmap_in_len = 0; @@ -977,15 +980,16 @@ uc_err uc_afl_fuzz( break; case UC_AFL_RET_FINISHED: // Nothing more to do - return afl_ret; + return UC_ERR_AFL_RET_FINISHED; case UC_AFL_RET_ERROR: + return UC_ERR_AFL_RET_ERROR; case UC_AFL_RET_CALLED_TWICE: // Nothing more we can do - return afl_ret; + return UC_ERR_AFL_RET_CALLED_TWICE; default: // What have we done - fprintf(stderr, "[!] Unexpected forkserver return: %d", afl_ret); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Unexpected forkserver return: %d", afl_ret); + return UC_ERR_AFL_RET_ERROR; } bool first_round = true; @@ -993,7 +997,7 @@ uc_err uc_afl_fuzz( #if defined(AFL_DEBUG) if (uc->afl_testcase_ptr) { - printf("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); + UCLOG("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); } #endif @@ -1018,7 +1022,7 @@ uc_err uc_afl_fuzz( No shmap fuzzing involved - Let's read a "normal" file. */ off_t in_len = uc_afl_mmap_file(input_file, &in_buf); if (unlikely(in_len < 0)) { - fprintf(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); + UCLOG(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); perror("mmap"); fflush(stderr); return UC_AFL_RET_ERROR; @@ -1047,7 +1051,7 @@ uc_err uc_afl_fuzz( goto next_iter; } - fprintf(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); + UCLOG(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); fflush(stderr); abort(); From 1fa2eb688b19b5c67670e7690d3674d26648f4f9 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 14:39:40 +0200 Subject: [PATCH 14/40] Fix UC_MODE_AFL and update config --- include/afl/config.h | 74 +++++++++++++++++++++++++++++---- include/uc_priv.h | 1 + qemu/accel/tcg/translator.c | 2 +- qemu/softmmu/cpus.c | 2 +- qemu/target/arm/translate-a64.c | 2 +- qemu/target/arm/translate.c | 2 +- qemu/target/i386/translate.c | 2 +- qemu/target/m68k/translate.c | 2 +- qemu/target/mips/translate.c | 2 +- qemu/target/ppc/translate.c | 2 +- qemu/target/riscv/translate.c | 2 +- qemu/target/sparc/translate.c | 2 +- uc.c | 7 +++- 13 files changed, 83 insertions(+), 19 deletions(-) diff --git a/include/afl/config.h b/include/afl/config.h index b5137553..4630da0c 100644 --- a/include/afl/config.h +++ b/include/afl/config.h @@ -10,7 +10,7 @@ Dominik Maier Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Copyright 2019-2021 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,8 +25,8 @@ /* Version string: */ -// c = release, d = volatile github dev, e = experimental branch -#define VERSION "++3.01a" +// c = release, a = volatile github dev, e = experimental branch +#define VERSION "++3.15a" /****************************************************** * * @@ -34,6 +34,55 @@ * * ******************************************************/ +/* Default shared memory map size. Most targets just need a coverage map + between 20-250kb. Plus there is an auto-detection feature in afl-fuzz. + However if a target has problematic constructors and init arrays then + this can fail. Hence afl-fuzz deploys a larger default map. The largest + map seen so far is the xlsx fuzzer for libreoffice which is 5MB. + At runtime this value can be overriden via AFL_MAP_SIZE. + Default: 8MB (defined in bytes) */ +#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024) + +/* Default file permission umode when creating files (default: 0600) */ +#define DEFAULT_PERMISSION 0600 + +/* CMPLOG/REDQUEEN TUNING + * + * Here you can modify tuning and solving options for CMPLOG. + * Note that these are run-time options for afl-fuzz, no target + * recompilation required. + * + */ + +/* if TRANSFORM is enabled with '-l T', this additionally enables base64 + encoding/decoding */ +// #define CMPLOG_SOLVE_TRANSFORM_BASE64 + +/* If a redqueen pass finds more than one solution, try to combine them? */ +#define CMPLOG_COMBINE + +/* Minimum % of the corpus to perform cmplog on. Default: 10% */ +#define CMPLOG_CORPUS_PERCENT 5U + +/* Number of potential positions from which we decide if cmplog becomes + useless, default 8096 */ +#define CMPLOG_POSITIONS_MAX (12 * 1024) + +/* Maximum allowed fails per CMP value. Default: 128 */ +#define CMPLOG_FAIL_MAX 96 + +/* -------------------------------------*/ +/* Now non-cmplog configuration options */ +/* -------------------------------------*/ + +/* If a persistent target keeps state and found crashes are not reproducable + then enable this option and set the AFL_PERSISTENT_RECORD env variable + to a number. These number of testcases prior and including the crash case + will be kept and written to the crash/ directory as RECORD:... files. + Note that every crash will be written, not only unique ones! */ + +//#define AFL_PERSISTENT_RECORD + /* console output colors: There are three ways to configure its behavior * 1. default: colored outputs fixed on: defined USE_COLOR && defined * ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect @@ -67,7 +116,7 @@ /* If you want to have the original afl internal memory corruption checks. Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ -//#define _WANT_ORIGINAL_AFL_ALLOC +// #define _WANT_ORIGINAL_AFL_ALLOC /* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ @@ -105,7 +154,7 @@ cases that show variable behavior): */ #define CAL_CYCLES 8U -#define CAL_CYCLES_LONG 40U +#define CAL_CYCLES_LONG 20U /* Number of subsequent timeouts before abandoning an input file: */ @@ -114,7 +163,7 @@ /* Maximum number of unique hangs or crashes to record: */ #define KEEP_UNIQUE_HANG 500U -#define KEEP_UNIQUE_CRASH 5000U +#define KEEP_UNIQUE_CRASH 10000U /* Baseline number of random tweaks during a single 'havoc' stage: */ @@ -188,11 +237,11 @@ (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c and afl-fuzz-state.c have to be changed as well! */ -#define MAX_FILE (1 * 1024 * 1024U) +#define MAX_FILE (1 * 1024 * 1024L) /* The same, for the test case minimizer: */ -#define TMIN_MAX_FILE (10 * 1024 * 1024) +#define TMIN_MAX_FILE (10 * 1024 * 1024L) /* Block normalization steps for afl-tmin: */ @@ -253,6 +302,11 @@ #define SYNC_INTERVAL 8 +/* Sync time (minimum time between syncing in ms, time is halfed for -M main + nodes) - default is 30 minutes: */ + +#define SYNC_TIME (30 * 60 * 1000) + /* Output directory reuse grace period (minutes): */ #define OUTPUT_GRACE 25 @@ -352,6 +406,10 @@ #define MSAN_ERROR 86 +/* Distinctive exit code used to indicate LSAN trip condition: */ + +#define LSAN_ERROR 23 + /* Designated file descriptors for forkserver commands (the application will use FORKSRV_FD and FORKSRV_FD + 1): */ diff --git a/include/uc_priv.h b/include/uc_priv.h index b881a666..a148c10e 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -315,6 +315,7 @@ struct uc_struct { bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. #ifdef UNICORN_HAS_AFL + bool afl; uc_afl_forkserver_t afl_forkserver_start; // function to start afl forkserver uc_afl_ret_uc_bool_t afl_child_request_next; // function from child to ask for new testcase (if in child) int afl_child_pipe[2]; // pipe used to send information from child process to forkserver diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 96f92873..0ee09488 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -61,7 +61,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Reset the temp count so that we can identify leaks */ tcg_clear_temp_count(); - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = cpu->uc->exits; size_t exit_count = cpu->uc->exit_count; diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index acb7f14b..242b0279 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -194,7 +194,7 @@ void resume_all_vcpus(struct uc_struct* uc) tb_flush_jmp_cache(cpu, uc->addr_end); } - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; size_t exit_count = uc->exit_count; diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index 5ab0e963..d3c4d5f2 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -14641,7 +14641,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; - if (dc->uc->mode & UC_MODE_AFL) { + if (dc->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = dc->uc->exits; size_t exit_count = dc->uc->exit_count; diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index fe325e1c..f7f77666 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11420,7 +11420,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } - if (dc->uc->mode & UC_MODE_AFL) { + if (dc->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = dc->uc->exits; size_t exit_count = dc->uc->exit_count; diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index 4b44bafd..a82ec50d 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4764,7 +4764,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; - if (s->uc->mode & UC_MODE_AFL) { + if (s->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = s->uc->exits; size_t exit_count = s->uc->exit_count; diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index c1940270..44929992 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6325,7 +6325,7 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUM68KState *env = cpu->env_ptr; uint16_t insn; - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; size_t exit_count = uc->exit_count; diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index ff36123b..c604056a 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30931,7 +30931,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; size_t exit_count = uc->exit_count; diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 623e8b4c..8394ac5f 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7625,7 +7625,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; size_t exit_count = uc->exit_count; diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 3e78dbfc..5ec8a16d 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -849,7 +849,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) TCGOp *tcg_op, *prev_op = NULL; bool insn_hook = false; - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = ctx->uc->exits; size_t exit_count = ctx->uc->exit_count; diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 66f834d3..46061c32 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5950,7 +5950,7 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPUSPARCState *env = cs->env_ptr; unsigned int insn; - if (uc->mode & UC_MODE_AFL) { + if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; size_t exit_count = uc->exit_count; diff --git a/uc.c b/uc.c index 2ad8edc7..4ee3c8f2 100644 --- a/uc.c +++ b/uc.c @@ -162,6 +162,11 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) return UC_ERR_NOMEM; } + if (mode & UC_MODE_AFL) { + uc->afl = true; + mode &= (~UC_MODE_AFL); + } + /* qemu/exec.c: phys_map_node_reserve() */ uc->alloc_hint = 16; uc->errnum = UC_ERR_OK; @@ -937,7 +942,7 @@ uc_err uc_afl_fuzz( UCLOG(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); return UC_ERR_AFL_RET_ERROR; } - if (!(uc->mode & UC_MODE_AFL)) { + if (!(uc->afl)) { return UC_ERR_MODE; } if (!input_file || input_file[0] == 0) { From 7ac7c23c12fe5d82137ac17241931aa75863ef8d Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 16:11:58 +0200 Subject: [PATCH 15/40] Fix Windows build for AFL integration --- qemu/accel/tcg/translator.c | 2 ++ qemu/softmmu/cpus.c | 2 ++ qemu/target/arm/translate-a64.c | 2 ++ qemu/target/arm/translate.c | 2 ++ qemu/target/i386/translate.c | 2 ++ qemu/target/m68k/translate.c | 2 ++ qemu/target/mips/translate.c | 4 +++- qemu/target/ppc/translate.c | 2 ++ qemu/target/riscv/translate.c | 2 ++ qemu/target/sparc/translate.c | 2 ++ uc.c | 3 ++- 11 files changed, 23 insertions(+), 2 deletions(-) diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 0ee09488..8afbc1fd 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -61,6 +61,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Reset the temp count so that we can identify leaks */ tcg_clear_temp_count(); +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = cpu->uc->exits; @@ -81,6 +82,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, } } } +#endif /* Unicorn: early check to see if the address of this block is * the "run until" address. */ diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index 242b0279..464e7b94 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -194,6 +194,7 @@ void resume_all_vcpus(struct uc_struct* uc) tb_flush_jmp_cache(cpu, uc->addr_end); } +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; @@ -209,6 +210,7 @@ void resume_all_vcpus(struct uc_struct* uc) } } } +#endif cpu->created = false; } diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index d3c4d5f2..ef8ad7aa 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -14641,6 +14641,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; +#ifdef UNICORN_HAS_AFL if (dc->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = dc->uc->exits; @@ -14655,6 +14656,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } } } +#endif // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index f7f77666..1c4827d7 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11420,6 +11420,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } +#ifdef UNICORN_HAS_AFL if (dc->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = dc->uc->exits; @@ -11434,6 +11435,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } } } +#endif // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index a82ec50d..fce8d914 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4764,6 +4764,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; +#ifdef UNICORN_HAS_AFL if (s->uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = s->uc->exits; @@ -4782,6 +4783,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) } } } +#endif // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 44929992..0dc9af2b 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6325,6 +6325,7 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUM68KState *env = cpu->env_ptr; uint16_t insn; +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; @@ -6339,6 +6340,7 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } } } +#endif // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index c604056a..4660a2b3 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30930,7 +30930,8 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) bool hook_insn = false; is_slot = ctx->hflags & MIPS_HFLAG_BMASK; - + +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; @@ -30946,6 +30947,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } } } +#endif // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 8394ac5f..2e06bbb7 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7625,6 +7625,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; @@ -7639,6 +7640,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } } } +#endif // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 5ec8a16d..a1ef4139 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -849,6 +849,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) TCGOp *tcg_op, *prev_op = NULL; bool insn_hook = false; +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = ctx->uc->exits; @@ -864,6 +865,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } } } +#endif // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == ctx->uc->addr_end) { diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 46061c32..6c45978c 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5950,6 +5950,7 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPUSPARCState *env = cs->env_ptr; unsigned int insn; +#ifdef UNICORN_HAS_AFL if (uc->afl) { // UNICORN-AFL supports (and needs) multiple exits. uint64_t *exits = uc->exits; @@ -5967,6 +5968,7 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) } } } +#endif // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { diff --git a/uc.c b/uc.c index 4ee3c8f2..a4f438b8 100644 --- a/uc.c +++ b/uc.c @@ -771,7 +771,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } - +#ifdef UNICORN_HAS_AFL static inline uc_afl_ret uc_afl_forkserver_start(uc_engine *uc, uint64_t *exits, size_t exit_count) { /* @@ -922,6 +922,7 @@ static inline uc_afl_ret uc_afl_next(uc_engine *uc, bool crash_found) return UC_AFL_RET_NO_AFL; } +#endif UNICORN_EXPORT uc_err uc_afl_fuzz( From e695686c15c84188f5b8d01d2a659cf79166b937 Mon Sep 17 00:00:00 2001 From: lazymio Date: Tue, 26 Oct 2021 11:22:21 +0200 Subject: [PATCH 16/40] Remove AFL Integration by reverting --- CMakeLists.txt | 6 - bindings/Makefile | 4 +- .../dotnet/UnicornManaged/Const/Common.fs | 5 - bindings/go/Makefile | 2 +- bindings/go/unicorn/unicorn_const.go | 5 - bindings/java/Makefile | 2 +- bindings/java/unicorn/UnicornConst.java | 5 - bindings/pascal/unicorn/UnicornConst.pas | 5 - bindings/python/Makefile | 12 +- bindings/python/unicorn/unicorn.py | 135 +---- bindings/python/unicorn/unicorn_const.py | 5 - bindings/ruby/Makefile | 2 +- .../lib/unicorn_engine/unicorn_const.rb | 5 - include/afl/afl-common.h | 49 -- include/afl/afl-cpu-inl.h | 527 ------------------ include/afl/afl-cpu-translate-inl.h | 81 --- include/afl/afl-tcg-op-inl.h | 76 --- include/afl/afl-tcg-runtime-inl.h | 123 ---- include/afl/config.h | 510 ----------------- include/afl/types.h | 193 ------- include/uc_priv.h | 50 +- include/unicorn/unicorn.h | 81 --- qemu/aarch64.h | 5 - qemu/aarch64eb.h | 5 - qemu/accel/tcg/cpu-exec.c | 37 -- qemu/accel/tcg/tcg-runtime.c | 4 - qemu/accel/tcg/tcg-runtime.h | 7 - qemu/accel/tcg/translator.c | 32 -- qemu/arm.h | 5 - qemu/armeb.h | 5 - qemu/include/tcg/tcg-op.h | 4 - qemu/m68k.h | 5 - qemu/mips.h | 5 - qemu/mips64.h | 5 - qemu/mips64el.h | 5 - qemu/mipsel.h | 5 - qemu/ppc.h | 5 - qemu/ppc64.h | 5 - qemu/riscv32.h | 5 - qemu/riscv64.h | 5 - qemu/softmmu/cpus.c | 17 - qemu/sparc.h | 5 - qemu/sparc64.h | 5 - qemu/target/arm/translate-a64.c | 22 - qemu/target/arm/translate.c | 17 - qemu/target/i386/translate.c | 21 - qemu/target/m68k/translate.c | 17 - qemu/target/mips/translate.c | 18 - qemu/target/ppc/translate.c | 17 - qemu/target/riscv/translate.c | 18 - qemu/target/sparc/translate.c | 20 - qemu/tcg/tcg.c | 64 +-- qemu/unicorn_common.h | 5 +- qemu/x86_64.h | 5 - symbols.sh | 5 - uc.c | 338 ----------- 56 files changed, 46 insertions(+), 2580 deletions(-) delete mode 100644 include/afl/afl-common.h delete mode 100644 include/afl/afl-cpu-inl.h delete mode 100644 include/afl/afl-cpu-translate-inl.h delete mode 100644 include/afl/afl-tcg-op-inl.h delete mode 100644 include/afl/afl-tcg-runtime-inl.h delete mode 100644 include/afl/config.h delete mode 100644 include/afl/types.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 69af3b8e..1eca217e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,6 @@ else() include_directories( ${CMAKE_BINARY_DIR} ) - # Try to build AFL support on all other platform. - set(UNICORN_HAS_AFL TRUE) endif() include_directories( @@ -328,10 +326,6 @@ else() OUTPUT_FILE ${CMAKE_BINARY_DIR}/riscv64-softmmu/config-target.h ) endif() - if (UNICORN_HAS_AFL) - # Make it globally - set (UNICORN_CFLAGS ${UNICORN_CFLAGS} -DUNICORN_HAS_AFL) - endif() add_compile_options( ${UNICORN_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/qemu/tcg/${UNICORN_TARGET_ARCH} diff --git a/bindings/Makefile b/bindings/Makefile index 44423401..296b44f3 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -24,8 +24,8 @@ build: $(MAKE) -C go gen_const $(MAKE) -C java gen_const $(MAKE) -C ruby gen_const - python3 const_generator.py dotnet - python3 const_generator.py pascal + python const_generator.py dotnet + python const_generator.py pascal install: build $(MAKE) -C python install diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 03cc19a4..0b91cac1 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -28,7 +28,6 @@ module Common = let UC_MODE_LITTLE_ENDIAN = 0 let UC_MODE_BIG_ENDIAN = 1073741824 - let UC_MODE_AFL = 536870912 let UC_MODE_ARM = 0 let UC_MODE_THUMB = 16 @@ -76,10 +75,6 @@ module Common = let UC_ERR_HOOK_EXIST = 19 let UC_ERR_RESOURCE = 20 let UC_ERR_EXCEPTION = 21 - let UC_ERR_AFL_RET_ERROR = 22 - let UC_ERR_AFL_RET_NO_AFL = 23 - let UC_ERR_AFL_RET_CALLED_TWICE = 24 - let UC_ERR_AFL_RET_FINISHED = 25 let UC_MEM_READ = 16 let UC_MEM_WRITE = 17 let UC_MEM_FETCH = 18 diff --git a/bindings/go/Makefile b/bindings/go/Makefile index f8b0d5f1..fe898ae1 100644 --- a/bindings/go/Makefile +++ b/bindings/go/Makefile @@ -6,7 +6,7 @@ all: gen_const cd unicorn && go build gen_const: - cd .. && python3 const_generator.py go + cd .. && python const_generator.py go test: all cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index a45e1452..6196fde5 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -23,7 +23,6 @@ const ( MODE_LITTLE_ENDIAN = 0 MODE_BIG_ENDIAN = 1073741824 - MODE_AFL = 536870912 MODE_ARM = 0 MODE_THUMB = 16 @@ -71,10 +70,6 @@ const ( ERR_HOOK_EXIST = 19 ERR_RESOURCE = 20 ERR_EXCEPTION = 21 - ERR_AFL_RET_ERROR = 22 - ERR_AFL_RET_NO_AFL = 23 - ERR_AFL_RET_CALLED_TWICE = 24 - ERR_AFL_RET_FINISHED = 25 MEM_READ = 16 MEM_WRITE = 17 MEM_FETCH = 18 diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 313db888..73d20725 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -19,7 +19,7 @@ uninstall: $(MAKE) -f Makefile.build uninstall gen_const: - cd .. && python3 const_generator.py java + cd .. && python const_generator.py java clean: rm -f unicorn/*.class diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index ce6744be..f4396003 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -25,7 +25,6 @@ public interface UnicornConst { public static final int UC_MODE_LITTLE_ENDIAN = 0; public static final int UC_MODE_BIG_ENDIAN = 1073741824; - public static final int UC_MODE_AFL = 536870912; public static final int UC_MODE_ARM = 0; public static final int UC_MODE_THUMB = 16; @@ -73,10 +72,6 @@ public interface UnicornConst { public static final int UC_ERR_HOOK_EXIST = 19; public static final int UC_ERR_RESOURCE = 20; public static final int UC_ERR_EXCEPTION = 21; - public static final int UC_ERR_AFL_RET_ERROR = 22; - public static final int UC_ERR_AFL_RET_NO_AFL = 23; - public static final int UC_ERR_AFL_RET_CALLED_TWICE = 24; - public static final int UC_ERR_AFL_RET_FINISHED = 25; public static final int UC_MEM_READ = 16; public static final int UC_MEM_WRITE = 17; public static final int UC_MEM_FETCH = 18; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 3f202cb9..29303b89 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -26,7 +26,6 @@ const UC_API_MAJOR = 2; UC_MODE_LITTLE_ENDIAN = 0; UC_MODE_BIG_ENDIAN = 1073741824; - UC_MODE_AFL = 536870912; UC_MODE_ARM = 0; UC_MODE_THUMB = 16; @@ -74,10 +73,6 @@ const UC_API_MAJOR = 2; UC_ERR_HOOK_EXIST = 19; UC_ERR_RESOURCE = 20; UC_ERR_EXCEPTION = 21; - UC_ERR_AFL_RET_ERROR = 22; - UC_ERR_AFL_RET_NO_AFL = 23; - UC_ERR_AFL_RET_CALLED_TWICE = 24; - UC_ERR_AFL_RET_FINISHED = 25; UC_MEM_READ = 16; UC_MEM_WRITE = 17; UC_MEM_FETCH = 18; diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 363d646f..ea831fd9 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -3,16 +3,16 @@ .PHONY: gen_const install install3 clean sdist sdist3 bdist bdist3 sdist_win bdist_win gen_const: - cd .. && python3 const_generator.py python + cd .. && python const_generator.py python install: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll if test -n "${DESTDIR}"; then \ - python3 setup.py install --root="${DESTDIR}"; \ + python setup.py install --root="${DESTDIR}"; \ else \ - python3 setup.py install; \ + python setup.py install; \ fi install3: @@ -30,7 +30,7 @@ sdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python3 setup.py sdist register upload + python setup.py sdist register upload # build & upload PyPi package with source code of the core sdist3: @@ -44,7 +44,7 @@ bdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python3 setup.py bdist_wheel register upload + python setup.py bdist_wheel register upload # build & upload PyPi package with precompiled core bdist3: @@ -57,7 +57,7 @@ bdist3: # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand sdist_win: rm -rf src/ dist/ - python3 setup.py sdist register upload + python setup.py sdist register upload # build & upload PyPi package with prebuilt core # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand diff --git a/bindings/python/unicorn/unicorn.py b/bindings/python/unicorn/unicorn.py index dbbc4d35..58c6ee06 100644 --- a/bindings/python/unicorn/unicorn.py +++ b/bindings/python/unicorn/unicorn.py @@ -9,7 +9,7 @@ import os.path import sys import weakref import functools -import gc + from . import x86_const, arm64_const, unicorn_const as uc if not hasattr(sys.modules[__name__], "__file__"): @@ -120,15 +120,6 @@ class _uc_mem_region(ctypes.Structure): ("perms", ctypes.c_uint32), ] -#typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, -# size_t input_len, uint32_t persistent_round, void *data); -AFL_PLACE_INPUT_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.POINTER(ctypes.c_char), - ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) - -#typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, -# int input_len, int persistent_round, void *data); -AFL_VALIDATE_CRASH_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ucerr, ctypes.POINTER(ctypes.c_char), - ctypes.c_size_t, ctypes.c_uint32, ctypes.c_void_p) _setup_prototype(_uc, "uc_version", ctypes.c_uint, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)) _setup_prototype(_uc, "uc_arch_supported", ctypes.c_bool, ctypes.c_int) @@ -160,7 +151,6 @@ _setup_prototype(_uc, "uc_context_free", ucerr, uc_context) _setup_prototype(_uc, "uc_mem_regions", ucerr, uc_engine, ctypes.POINTER(ctypes.POINTER(_uc_mem_region)), ctypes.POINTER(ctypes.c_uint32)) # https://bugs.python.org/issue42880 _setup_prototype(_uc, "uc_hook_add", ucerr, uc_engine, ctypes.POINTER(uc_hook_h), ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint64, ctypes.c_uint64) -_setup_prototype(_uc, "uc_afl_fuzz", ucerr, uc_engine, ctypes.c_char_p, ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint64), ctypes.c_size_t, ctypes.c_void_p, ctypes.c_bool, ctypes.c_uint32, ctypes.c_void_p) UC_HOOK_CODE_CB = ctypes.CFUNCTYPE(None, uc_engine, ctypes.c_uint64, ctypes.c_size_t, ctypes.c_void_p) UC_HOOK_INSN_INVALID_CB = ctypes.CFUNCTYPE(ctypes.c_bool, uc_engine, ctypes.c_void_p) @@ -421,8 +411,6 @@ class Uc(object): self._callback_count = 0 self._cleanup.register(self) - self.afl_called_before = False # type: bool - @staticmethod def release_handle(uch): if uch: @@ -444,127 +432,6 @@ class Uc(object): status = _uc.uc_emu_stop(self._uch) if status != uc.UC_ERR_OK: raise UcError(status) - - def afl_fuzz( - self, # type: Uc - input_file, # type: str - place_input_callback, # type: Callable[[Uc, bytes, int, Any], Optional[bool]] - exits, # type: List[int] - validate_crash_callback=None, # type: Optional[Callable[[Uc, UcError, bytes, int, Any], Optional[bool]]] - always_validate=False, # type: bool - persistent_iters=1, # type: int - data=None, # type: Any - ): - # type: (...) -> bool - """ - The main fuzzer. - Starts the forkserver, then beginns a persistent loop. - Reads input, calls the place_input callback, emulates, repeats. - If unicorn errors out, will call the validate_crash_callback, if set. - Will only return in the parent after the whole fuzz thing has been finished and afl died. - The child processes never return from here. - - :param input_file: filename/path to the (AFL) inputfile. Usually supplied on the commandline. - :param place_input_callback: Callback function that will be called before each test runs. - This function needs to write the input from afl to the correct position on the unicorn object. - This function is mandatory. - It's purpose is to place the input at the right place in unicorn. - - @uc: (Uc) Unicorn instance - @input: (bytes) The current input we're working on. Place this somewhere in unicorn's memory now. - @persistent_round: (int) which round we are currently crashing in, if using persistent mode. - @data: (Any) Data pointer passed to uc_afl_fuzz(...). - - @return: (bool) - If you return is True (or None) all is well. Fuzzing starts. - If you return False, the input is rejected; we will continue with the next input. - :param exits: address list of exits where fuzzing should stop - :param persistent_iters: - The amount of loop iterations in persistent mode before restarting with a new forked child. - If your target cannot be fuzzed using persistent mode (global state changes a lot), - set persistent_iters = 1 for the normal fork-server experience. - Else, the default is usually around 1000. - If your target is super stable (and unicorn is, too - not sure about that one), - you may pass persistent_iter = 0 for that an infinite fuzz loop. - :param validate_crash_callback: Optional callback (if not needed, pass NULL), that determines - if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. - Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. - This function is not mandatory. - @uc: Unicorn instance - @unicorn_result: The error state returned by the current testcase - @input: The current input we're working with. - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). - - @Return: - If you return false, the crash is considered invalid and not reported to AFL. - -> Next loop iteration begins. - If return is true, the crash is reported // the program crashes. - -> The child will die and the forkserver will spawn a new child. - :param always_validate: If false, validate_crash_callback will only be called for crashes. - :param data: Your very own data pointer. This will passed into every callback. - - :return: - True, if we fuzzed. - False, if AFL was not available but we ran once. - raises UcAflException if nothing worked. - """ - if self.afl_called_before: - raise UcError(uc.UC_ERR_AFL_RET_CALLED_TWICE) - self.afl_called_before = True - self._pre_afl() - exit_count = len(exits) - - def place_input_wrapper(c_uc, input, input_len, persistent_round, c_data): - # print("Calling back home. :)", c_uc, input, input_len, persistent_round, c_data) - ret = place_input_callback( - self, - ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, - persistent_round, - data - ) - if ret is False: - return False - return True - - def validate_crash_wrapper(c_uc, uc_err, input, input_len, persistent_round, c_data): - # print("Calling after crash!", c_uc, input, input_len, persistent_round, c_data) - # assert type(uc_err) == int - ret = validate_crash_callback( - self, - UcError(uc_err), - ctypes.cast(input, ctypes.POINTER(ctypes.c_char * input_len)).contents, - persistent_round, - data - ) - if ret is False or (ret is None and uc_err == uc.UC_ERR_OK): - return False - return True - - # This only returns in the parent, child processes all die or loop or other things. - status = _uc.uc_afl_fuzz( - self._uch, - input_file.encode('utf-8'), - AFL_PLACE_INPUT_CB(place_input_wrapper), - (ctypes.c_uint64 * exit_count)(*exits), - exit_count, # bad languages, like c, need more params. - AFL_VALIDATE_CRASH_CB(validate_crash_wrapper) if validate_crash_callback else None, - always_validate, - persistent_iters, - None # no need to pass the user data through C as the callback keeps it as closure. - ) - if status != uc.UC_ERR_OK: - # Something went wrong. - raise UcError(status) - - def _pre_afl(self): - # type: (Uc) -> None - """ - Internal func making sure exits are set and flushing buffers/gc - :param exits: exits - """ - sys.stdout.flush() # otherwise children will inherit the unflushed buffer - gc.collect() # Collect all unneeded memory, No need to clone it on fork. # return the value of a register def reg_read(self, reg_id, opt=None): diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index 1b9ac693..a517572a 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -21,7 +21,6 @@ UC_ARCH_MAX = 9 UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 -UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -69,10 +68,6 @@ UC_ERR_FETCH_UNALIGNED = 18 UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 -UC_ERR_AFL_RET_ERROR = 22 -UC_ERR_AFL_RET_NO_AFL = 23 -UC_ERR_AFL_RET_CALLED_TWICE = 24 -UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index aa92fa53..9d52de94 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -8,4 +8,4 @@ install: gen_const cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem gen_const: - cd .. && python3 const_generator.py ruby + cd .. && python const_generator.py ruby diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index 698b71c0..a09f3e82 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -23,7 +23,6 @@ module UnicornEngine UC_MODE_LITTLE_ENDIAN = 0 UC_MODE_BIG_ENDIAN = 1073741824 - UC_MODE_AFL = 536870912 UC_MODE_ARM = 0 UC_MODE_THUMB = 16 @@ -71,10 +70,6 @@ module UnicornEngine UC_ERR_HOOK_EXIST = 19 UC_ERR_RESOURCE = 20 UC_ERR_EXCEPTION = 21 - UC_ERR_AFL_RET_ERROR = 22 - UC_ERR_AFL_RET_NO_AFL = 23 - UC_ERR_AFL_RET_CALLED_TWICE = 24 - UC_ERR_AFL_RET_FINISHED = 25 UC_MEM_READ = 16 UC_MEM_WRITE = 17 UC_MEM_FETCH = 18 diff --git a/include/afl/afl-common.h b/include/afl/afl-common.h deleted file mode 100644 index eb342255..00000000 --- a/include/afl/afl-common.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "config.h" -#include "types.h" - -/* NeverZero */ - -#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO) -#define INC_AFL_AREA(loc) \ - asm volatile( \ - "addb $1, (%0, %1, 1)\n" \ - "adcb $0, (%0, %1, 1)\n" \ - : /* no out */ \ - : "r"(afl_area_ptr), "r"(loc) \ - : "memory", "eax") -#else -#define INC_AFL_AREA(loc) afl_area_ptr[loc]++ -#endif - diff --git a/include/afl/afl-cpu-inl.h b/include/afl/afl-cpu-inl.h deleted file mode 100644 index fcb44b8e..00000000 --- a/include/afl/afl-cpu-inl.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include -#include -#include -#include -#include "config.h" -#include "types.h" -#include "afl-common.h" - -/* We use one additional file descriptor to relay "needs translation" - or "child done" messages between the child and the fork server. */ - -#define FF16 (0xFFFFFFFFFFFFFFFF) - -/* Copied from aflpp/types.h to talk to forkserver */ -#define FS_OPT_ENABLED 0x80000001 -#define FS_OPT_SHDMEM_FUZZ 0x01000000 - -/** - * The correct fds for reading and writing pipes - */ - -#define _R(pipe) ((pipe)[0]) -#define _W(pipe) ((pipe)[1]) - -/* Function declarations. */ - -static void afl_setup(struct uc_struct*); -static inline uc_afl_ret afl_forkserver(CPUState*); -static int afl_find_wifsignaled_id(void); - -static enum afl_child_ret afl_handle_child_requests(CPUState*); -static void afl_request_tsl(CPUState *cpu, target_ulong, target_ulong, uint64_t, uint32_t); -static uc_afl_ret afl_request_next(struct uc_struct* uc, bool found_crash); - -// static TranslationBlock* tb_find_slow(CPUArchState*, target_ulong, target_ulong, uint64_t); - -/* Data structure passed around by the translate handlers: */ - -struct afl_tsl { - - target_ulong pc; - target_ulong cs_base; - uint64_t flags; - uint32_t cf_mask; -#if defined(TARGET_MIPS) - target_ulong hflags; - target_ulong btarget; -#endif - -}; - -/* Current state, as forwarded from forkserver child to parent */ - -enum afl_child_ret { - - // Persistent - AFL_CHILD_NEXT, - // Crash discovered but still alive in persistent mode - AFL_CHILD_FOUND_CRASH, - // Read again, one afl_tsl struct. - AFL_CHILD_TSL_REQUEST, - // Child no longer there. Read status code. - AFL_CHILD_EXITED, - -}; - -static int wifsignaled; - -/************************* - * ACTUAL IMPLEMENTATION * - *************************/ - -/* Set up SHM region and initialize other stuff. */ - -static void afl_setup(struct uc_struct* uc) { - - char *id_str = getenv(SHM_ENV_VAR); - char *inst_r = getenv("AFL_INST_RATIO"); - - // A value we can use to tell AFL our persistent mode found a crash - wifsignaled = afl_find_wifsignaled_id(); - - int shm_id; - - if (inst_r) { - - unsigned int r; - - r = atoi(inst_r); - - if (r > 100) r = 100; - if (!r) r = 1; - - uc->afl_inst_rms = MAP_SIZE * r / 100; - - } else { - - uc->afl_inst_rms = MAP_SIZE; - - } - - if (id_str) { - - shm_id = atoi(id_str); - uc->afl_area_ptr = shmat(shm_id, NULL, 0); - uc->afl_prev_loc = 0; - uc->afl_area_ptr[0] = 1; - - if (uc->afl_area_ptr == (void*)-1) exit(1); - - } - - /* Maintain for compatibility */ - if (getenv("AFL_QEMU_COMPCOV")) { uc->afl_compcov_level = 1; } - if (getenv("AFL_COMPCOV_LEVEL")) { - - uc->afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL")); - - } -#if defined(AFL_DEBUG) - if (uc->afl_compcov_level) { - printf("[d] USING AFL_COMPCOV_LEVEL %d\n", uc->afl_compcov_level); - } -#endif - -} - -// Some dirty hack to come up with a valid statuscode that AFL will just accept. - -static int afl_find_wifsignaled_id(void) { - - int ret = 0; // A faux status code that AFL will accept as signaled/crashed. 1 on linux. - while (!(WIFSIGNALED(ret))) ret++; - -#if defined(AFL_DEBUG) - printf("[d] wifsignaled is %d (WIFSIGNALED(x)=%d)\n", ret, WIFSIGNALED(ret)); -#endif - - return ret; - -} - -/* Fork server logic, invoked by calling uc_afl_forkserver_start. - Roughly follows https://github.com/vanhauser-thc/AFLplusplus/blob/c83e8e1e6255374b085292ba8673efdca7388d76/llvm_mode/afl-llvm-rt.o.c#L130 - */ - -static inline uc_afl_ret afl_forkserver(CPUState* cpu) { - - unsigned char tmp[4] = {0}; - pid_t child_pid; - enum afl_child_ret child_ret = AFL_CHILD_EXITED; - bool first_round = true; - u32 status = 0; - - if (!cpu->uc->afl_area_ptr) return UC_AFL_RET_NO_AFL; - - if (cpu->uc->afl_testcase_ptr) { - /* Parent supports testcases via shared map - and the user wants to use it. Tell AFL. */ - status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); - } - - /* Phone home and tell the parent that we're OK. If parent isn't there, - assume we're not running in forkserver mode and just execute program. */ - - if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_NO_AFL; - - /* afl tells us in an extra message if it accepted this option or not */ - if (cpu->uc->afl_testcase_ptr && getenv(SHM_FUZZ_ENV_VAR)) { - if (read(FORKSRV_FD, &status, 4) != 4) { - fprintf(stderr, "[!] AFL parent exited before forkserver was up\n"); - return UC_AFL_RET_ERROR; - } - if (status != (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) { - fprintf(stderr, "[!] Unexpected response from AFL++ on forkserver setup\n"); - return UC_AFL_RET_ERROR; - } - } else { -#if defined(AFL_DEBUG) - printf("[d] AFL++ sharedmap fuzzing not supported/SHM_FUZZ_ENV_VAR not set\n"); -#endif - } - - void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); - -#if defined(AFL_DEBUG) - printf("[d] Entering forkserver loop\n"); -#endif - - while (1) { - - uint32_t was_killed; - int status; - - /* Wait for parent by reading from the pipe. Abort if read fails. */ - - if (read(FORKSRV_FD, &was_killed, 4) != 4) return UC_AFL_RET_FINISHED; - - /* If we stopped the child in persistent mode, but there was a race - condition and afl-fuzz already issued SIGKILL, write off the old - process. */ - - if ((child_ret != AFL_CHILD_EXITED) && was_killed) { - -#if defined(AFL_DEBUG) - printf("[d] Child was killed by AFL in the meantime.\n"); -#endif - - child_ret = AFL_CHILD_EXITED; - if (waitpid(child_pid, &status, 0) < 0) { - perror("[!] Error waiting for child!"); - return UC_AFL_RET_ERROR; - } - - } - - if (child_ret == AFL_CHILD_EXITED) { - - /* Child dead. Establish new a channel with child to grab translation commands. - We'll read from _R(afl_child_pipe), child will write to _W(afl_child_pipe). */ - - /* close the read fd of previous round. */ - - if (_R(cpu->uc->afl_child_pipe)) { - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_parent_pipe)); - } - - if (pipe(cpu->uc->afl_child_pipe)) { - perror("[!] Error creating pipe to child"); - return UC_AFL_RET_ERROR; - } - if (pipe(cpu->uc->afl_parent_pipe)) { - perror("[!] Error creating pipe to parent"); - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_child_pipe)); - return UC_AFL_RET_ERROR; - } - - /* Create a clone of our process. */ - - child_pid = fork(); - if (child_pid < 0) { - perror("[!] Could not fork! "); - return UC_AFL_RET_ERROR; - } - - /* In child process: close fds, resume execution. */ - - if (!child_pid) { // New child - - signal(SIGCHLD, old_sigchld_handler); - // FORKSRV_FD is for communication with AFL, we don't need it in the child. - close(FORKSRV_FD); - close(FORKSRV_FD + 1); - close(_R(cpu->uc->afl_child_pipe)); - close(_W(cpu->uc->afl_parent_pipe)); - cpu->uc->afl_child_request_next = afl_request_next; - - memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); - MEM_BARRIER(); // Make very sure everything has been written to the map at this point - - if (!first_round) { - - // For persistent mode: Clear the map manually after forks. - memset(cpu->uc->afl_area_ptr, 0, MAP_SIZE); - - } else { - // For persistent mode: Clear the map manually after forks. - //memset(env->uc->afl_area_ptr, 0, MAP_SIZE); - - first_round = false; - } - - cpu->uc->afl_prev_loc = 0; - // Tell AFL we're alive - cpu->uc->afl_area_ptr[0] = 1; - - return UC_AFL_RET_CHILD; - - } else { // parent for new child - - /* If we don't close this in parent, we don't get notified on afl_child_pipe once child is gone. */ - - close(_W(cpu->uc->afl_child_pipe)); - close(_R(cpu->uc->afl_parent_pipe)); - - } - - } else { // parent, in persistent mode - - /* Special handling for persistent mode: if the child is alive but - currently stopped, simply restart it with a write to afl_parent_pipe. - In case we fuzz using shared map, use this method to forward the size - of the current testcase to the child without cost. */ - - if (write(_W(cpu->uc->afl_parent_pipe), tmp, 4) != 4) { - - fprintf(stderr,"[!] Child died when we tried to resume it\n"); - return UC_AFL_RET_ERROR; - - } - - } - - /* In parent process: write PID to AFL. */ - - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { - return UC_AFL_RET_FINISHED; - } - - /* Collect translation requests until child finishes a run or dies */ - - child_ret = afl_handle_child_requests(cpu); - - if (child_ret == AFL_CHILD_NEXT) { - - /* Child asks for next in persistent mode */ - - status = 0; - - } else if (child_ret == AFL_CHILD_FOUND_CRASH) { - - /* WIFSIGNALED(wifsignaled) == 1 -> tells AFL the child crashed (even though it's still alive for persistent mode) */ - - status = wifsignaled; - - } else if (child_ret == AFL_CHILD_EXITED) { - - /* If child exited, get and relay exit status to parent through waitpid. */ - - if (waitpid(child_pid, &status, 0) < 0) { - - // Zombie Child could not be collected. Scary! - perror("[!] The child's exit code could not be determined. "); - return UC_AFL_RET_ERROR; - - } - - } - - /* Relay wait status to AFL pipe, then loop back. */ - - if (write(FORKSRV_FD + 1, &status, 4) != 4) return UC_AFL_RET_FINISHED; - - } - -} - -/* This code is invoked whenever Unicorn decides that it doesn't have a - translation of a particular block and needs to compute it. When this happens, - we tell the parent to mirror the operation, so that the next fork() has a - cached copy. */ - -static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong cb, uint64_t flags, uint32_t cf_mask) { - - /* Dual use: if this func is not set, we're not a child process */ - - struct uc_struct* uc = cpu->uc; - if (uc->afl_child_request_next == NULL) return; - enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; -#if defined(TARGET_MIPS) - CPUArchState* env = cpu->env_ptr; -#endif - - struct afl_tsl t = { - .pc = pc, - .cs_base = cb, - .flags = flags, - .cf_mask = cf_mask, -#if defined(TARGET_MIPS) - .hflags = env->hflags, - .btarget = env->btarget, -#endif - }; - -#if defined(AFL_DEBUG) - printf("Requesting tsl, pc=0x%llx, cb=0x%llx, flags=0x%llx\n", (unsigned long long) pc, (unsigned long long) cb, (unsigned long long) flags); -#endif - - // We write tsl requests in two steps but that's fine since cache requests are not very common over the time of fuzzing. - - if ((write(_W(uc->afl_child_pipe), &tsl_req, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) - || write(_W(uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) { - - fprintf(stderr, "Error writing to child pipe. Parent dead?\n"); - - } - -} - -/* This code is invoked whenever the child decides that it is done with one fuzz-case. */ - -static uc_afl_ret afl_request_next(struct uc_struct* uc, bool crash_found) { - - enum afl_child_ret msg = crash_found? AFL_CHILD_FOUND_CRASH : AFL_CHILD_NEXT; - char tmp[4]; - -#if defined(AFL_DEBUG) - printf("[d] request next. crash found: %s\n", crash_found ? "true": "false"); -#endif - - MEM_BARRIER(); // Make very sure everything has been written to the map at this point - - if (write(_W(uc->afl_child_pipe), &msg, sizeof(msg)) != sizeof(msg)) { - - fprintf(stderr, "[!] Error writing to parent pipe. Parent dead?\n"); - return UC_AFL_RET_ERROR; - - } - - // Once the parent has written something, the next persistent loop starts. - // The parent itself will wait for AFL to signal the new testcases is available. - // This blocks until the next testcase is ready. - if (read(_R(uc->afl_parent_pipe), tmp, 4) != 4) { - - fprintf(stderr, "[!] Error reading from parent pipe. Parent dead?\n"); - return UC_AFL_RET_ERROR; - - } - - /* For shared map fuzzing, the forkserver parent forwards the size of the current testcase. */ - memset(uc->afl_area_ptr, 0, MAP_SIZE); - MEM_BARRIER(); // Also make sure nothing read before this point. - - // Start with a clean slate. - uc->afl_prev_loc = 0; - uc->afl_area_ptr[0] = 1; - - return UC_AFL_RET_CHILD; - -} - - -/* This is the reading side of afl_child_pipe. It will handle persistent mode and (tsl) cache requests. - Since timeouts are handled by afl-fuzz simply killing the child, we can just wait until the pipe breaks. - For persistent mode, we will also receive child responses over this chanel. - For persistent mode, if child is still alive, this will return if the child crashed or not */ - -static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { - - enum afl_child_ret child_msg; - struct afl_tsl t; -#if defined(TARGET_MIPS) - CPUArchState* env = cpu->env_ptr; -#endif - - while (1) { - - /* Broken pipe means it's time to return to the fork server routine. */ - - if (read(_R(cpu->uc->afl_child_pipe), &child_msg, sizeof(enum afl_child_ret)) != sizeof(enum afl_child_ret)) return AFL_CHILD_EXITED; // child is dead. - - if (child_msg == AFL_CHILD_NEXT || child_msg == AFL_CHILD_FOUND_CRASH) { - - // Forward if child found a crash or not, for persistent mode. - return child_msg; - - } else if (child_msg == AFL_CHILD_TSL_REQUEST) { - - // TODO: Add option to disable cache for self-modifying code? // Ignore code that has not been loaded? - - // Child will send a tsl request next, that we have to cache. - if (read(_R(cpu->uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) return AFL_CHILD_EXITED; // child is dead. - - // Prepare hflags for delay slot -#if defined(TARGET_MIPS) - struct afl_tsl tmp; - tmp.hflags = env->hflags; - tmp.btarget = env->btarget; - env->hflags = t.hflags; - env->btarget = t.btarget; -#endif - - // Cache. - //tb_find_slow(env, t.pc, t.cs_base, t.flags); - - // TODO: Caching! tb = tb_find(cpu, last_tb, tb_exit, t.cflags); - - // Restore hflags -#if defined(TARGET_MIPS) - env->hflags = tmp.hflags; - env->btarget = tmp.btarget; -#endif - - } else { - - fprintf(stderr, "[!] Unexpected response by child! %d. Please report this as bug for unicornafl.\n" - " Expected one of {AFL_CHILD_NEXT: %d, AFL_CHILD_FOUND_CRASH: %d, AFL_CHILD_TSL_REQUEST: %d}.\n", - child_msg, AFL_CHILD_NEXT, AFL_CHILD_FOUND_CRASH, AFL_CHILD_TSL_REQUEST); - - } - - } - -} diff --git a/include/afl/afl-cpu-translate-inl.h b/include/afl/afl-cpu-translate-inl.h deleted file mode 100644 index 7692ff3c..00000000 --- a/include/afl/afl-cpu-translate-inl.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "config.h" -#include "types.h" - -/* These are executed on code generation. Execution is in afl-unicorn-tcg-runtime-inl.h */ -/* Roughly afl_gen_maybe_log -> gen_afl_maybe_log -> emit HELPER(afl_maybe_log) -> call afl_maybe_log */ - -static void afl_gen_maybe_log(TCGContext *s, uint64_t cur_loc) { - - if (!s->uc->afl_area_ptr) return; - - /* "Hash" */ - - cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); - cur_loc &= MAP_SIZE - 7; - - /* Implement probabilistic instrumentation by looking at scrambled block - address. This keeps the instrumented locations stable across runs. */ - - if (cur_loc >= s->uc->afl_inst_rms) return; - - gen_afl_maybe_log(s, cur_loc); - -} - -// Currently only arm32 and x86. We undefine it for others to silence unused func compiler warnings. -#if defined(ARCH_HAS_COMPCOV) -static void afl_gen_compcov(TCGContext *s, uint64_t cur_loc, TCGv arg1, - TCGv arg2, TCGMemOp ot, int is_imm) { - - if (!s->uc->afl_compcov_level || !s->uc->afl_area_ptr) return; - - if (!is_imm && s->uc->afl_compcov_level < 2) return; - - cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); - cur_loc &= MAP_SIZE - 7; - - if (cur_loc >= s->uc->afl_inst_rms) return; - - switch (ot) { - - case MO_64: gen_afl_compcov_log_64(s, cur_loc, (TCGv_i64)arg1, (TCGv_i64)arg2); break; - case MO_32: gen_afl_compcov_log_32(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; - case MO_16: gen_afl_compcov_log_16(s, cur_loc, (TCGv_i32)arg1, (TCGv_i32)arg2); break; - default: return; - - } - -} -#endif \ No newline at end of file diff --git a/include/afl/afl-tcg-op-inl.h b/include/afl/afl-tcg-op-inl.h deleted file mode 100644 index 5770066c..00000000 --- a/include/afl/afl-tcg-op-inl.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -static inline void gen_afl_maybe_log(TCGContext *tcg_ctx, uint64_t cur_loc) { - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_maybe_log(tcg_ctx, tuc, tcur_loc); - -} - -static inline void gen_afl_compcov_log_16(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i32 arg1, TCGv_i32 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 16 bit COMPCOV instrumentation for loc 0x%lx\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_16(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - -static inline void gen_afl_compcov_log_32(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i32 arg1, TCGv_i32 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 32 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_32(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - -static inline void gen_afl_compcov_log_64(TCGContext *tcg_ctx, uint64_t cur_loc, - TCGv_i64 arg1, TCGv_i64 arg2) { -#if defined(AFL_DEBUG) - printf("[d] Emitting 64 bit COMPCOV instrumentation for loc 0x%lux\n", cur_loc); -#endif - - TCGv_ptr tuc = tcg_const_ptr(tcg_ctx, tcg_ctx->uc); - TCGv_i64 tcur_loc = tcg_const_i64(tcg_ctx, cur_loc); - gen_helper_afl_compcov_log_64(tcg_ctx, tuc, tcur_loc, arg1, arg2); - -} - diff --git a/include/afl/afl-tcg-runtime-inl.h b/include/afl/afl-tcg-runtime-inl.h deleted file mode 100644 index 237c55b5..00000000 --- a/include/afl/afl-tcg-runtime-inl.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - american fuzzy lop++ - unicorn instrumentation - ---------------------------------------------- - - Originally written by Andrew Griffiths and - Michal Zalewski - - Adapted for afl-unicorn by Dominik Maier - - CompareCoverage and NeverZero counters by Andrea Fioraldi - - - Copyright 2015, 2016, 2017 Google Inc. All rights reserved. - Copyright 2019 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - This code is a shim patched into the separately-distributed source - code of Unicorn 1.0.1. It leverages the built-in QEMU tracing functionality - to implement AFL-style instrumentation and to take care of the remaining - parts of the AFL fork server logic. - - The resulting libunicorn binary is essentially a standalone instrumentation - tool; for an example of how to leverage it for other purposes, you can - have a look at afl-showmap.c. - - */ - -#include "uc_priv.h" -#include "afl-common.h" - -/* This is the main instrumentation function, patched in at translate. - cur_loc has already been shifted in afl-unicorn-translate-inl.h at this point. - Also this helper will only be emitted if running instrumented. */ - -void HELPER(afl_maybe_log)(void* uc_ptr, uint64_t cur_loc) { - - struct uc_struct* uc = (struct uc_struct*) uc_ptr; - u8* afl_area_ptr = uc->afl_area_ptr; // Don't remove, it's used by INC_AFL_AREA implicitly; - - register uintptr_t afl_idx = cur_loc ^ uc->afl_prev_loc; - - INC_AFL_AREA(afl_idx); - -#if defined(AFL_DEBUG) - printf("[d] At loc 0x%llx: prev: 0x%llx, afl_idx: %lu, map[afl_idx]: %d\n", (unsigned long long) cur_loc, (unsigned long long) uc->afl_prev_loc, (unsigned long) afl_idx, afl_area_ptr[afl_idx]); -#endif - - uc->afl_prev_loc = cur_loc >> 1; - -} - -void HELPER(afl_compcov_log_16)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, - uint32_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - -} - -void HELPER(afl_compcov_log_32)(void* uc_ptr, uint64_t cur_loc, uint32_t arg1, - uint32_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { - - INC_AFL_AREA(cur_loc + 2); - if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { - - INC_AFL_AREA(cur_loc + 1); - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - - } - - } - -} - -void HELPER(afl_compcov_log_64)(void* uc_ptr, uint64_t cur_loc, uint64_t arg1, - uint64_t arg2) { - - u8* afl_area_ptr = ((struct uc_struct*)uc_ptr)->afl_area_ptr; - - if ((arg1 & 0xff00000000000000) == (arg2 & 0xff00000000000000)) { - - INC_AFL_AREA(cur_loc + 6); - if ((arg1 & 0xff000000000000) == (arg2 & 0xff000000000000)) { - - INC_AFL_AREA(cur_loc + 5); - if ((arg1 & 0xff0000000000) == (arg2 & 0xff0000000000)) { - - INC_AFL_AREA(cur_loc + 4); - if ((arg1 & 0xff00000000) == (arg2 & 0xff00000000)) { - - INC_AFL_AREA(cur_loc + 3); - if ((arg1 & 0xff000000) == (arg2 & 0xff000000)) { - - INC_AFL_AREA(cur_loc + 2); - if ((arg1 & 0xff0000) == (arg2 & 0xff0000)) { - - INC_AFL_AREA(cur_loc + 1); - if ((arg1 & 0xff00) == (arg2 & 0xff00)) { INC_AFL_AREA(cur_loc); } - - } - - } - - } - - } - - } - - } - -} - diff --git a/include/afl/config.h b/include/afl/config.h deleted file mode 100644 index 4630da0c..00000000 --- a/include/afl/config.h +++ /dev/null @@ -1,510 +0,0 @@ -/* - american fuzzy lop++ - vaguely configurable bits - ------------------------------------------------ - - Originally written by Michal Zalewski - - Now maintained by Marc Heuse , - Heiko Eißfeldt , - Andrea Fioraldi , - Dominik Maier - - Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2021 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_CONFIG_H -#define _HAVE_CONFIG_H - -/* Version string: */ - -// c = release, a = volatile github dev, e = experimental branch -#define VERSION "++3.15a" - -/****************************************************** - * * - * Settings that may be of interest to power users: * - * * - ******************************************************/ - -/* Default shared memory map size. Most targets just need a coverage map - between 20-250kb. Plus there is an auto-detection feature in afl-fuzz. - However if a target has problematic constructors and init arrays then - this can fail. Hence afl-fuzz deploys a larger default map. The largest - map seen so far is the xlsx fuzzer for libreoffice which is 5MB. - At runtime this value can be overriden via AFL_MAP_SIZE. - Default: 8MB (defined in bytes) */ -#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024) - -/* Default file permission umode when creating files (default: 0600) */ -#define DEFAULT_PERMISSION 0600 - -/* CMPLOG/REDQUEEN TUNING - * - * Here you can modify tuning and solving options for CMPLOG. - * Note that these are run-time options for afl-fuzz, no target - * recompilation required. - * - */ - -/* if TRANSFORM is enabled with '-l T', this additionally enables base64 - encoding/decoding */ -// #define CMPLOG_SOLVE_TRANSFORM_BASE64 - -/* If a redqueen pass finds more than one solution, try to combine them? */ -#define CMPLOG_COMBINE - -/* Minimum % of the corpus to perform cmplog on. Default: 10% */ -#define CMPLOG_CORPUS_PERCENT 5U - -/* Number of potential positions from which we decide if cmplog becomes - useless, default 8096 */ -#define CMPLOG_POSITIONS_MAX (12 * 1024) - -/* Maximum allowed fails per CMP value. Default: 128 */ -#define CMPLOG_FAIL_MAX 96 - -/* -------------------------------------*/ -/* Now non-cmplog configuration options */ -/* -------------------------------------*/ - -/* If a persistent target keeps state and found crashes are not reproducable - then enable this option and set the AFL_PERSISTENT_RECORD env variable - to a number. These number of testcases prior and including the crash case - will be kept and written to the crash/ directory as RECORD:... files. - Note that every crash will be written, not only unique ones! */ - -//#define AFL_PERSISTENT_RECORD - -/* console output colors: There are three ways to configure its behavior - * 1. default: colored outputs fixed on: defined USE_COLOR && defined - * ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect - * 2. defined USE_COLOR && !defined ALWAYS_COLORED - * -> depending on env var AFL_NO_COLOR=1 colors can be switched off - * at run-time. Default is to use colors. - * 3. colored outputs fixed off: !defined USE_COLOR - * The env var. AFL_NO_COLOR will have no effect - */ - -/* Comment out to disable terminal colors (note that this makes afl-analyze - a lot less nice): */ - -#define USE_COLOR - -#ifdef USE_COLOR - /* Comment in to always enable terminal colors */ - /* Comment out to enable runtime controlled terminal colors via AFL_NO_COLOR - */ - #define ALWAYS_COLORED 1 -#endif - -/* StatsD config - Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment - variable. -*/ -#define STATSD_UPDATE_SEC 1 -#define STATSD_DEFAULT_PORT 8125 -#define STATSD_DEFAULT_HOST "127.0.0.1" - -/* If you want to have the original afl internal memory corruption checks. - Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ - -// #define _WANT_ORIGINAL_AFL_ALLOC - -/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ - -#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb - #define FANCY_BOXES -#endif - -/* Default timeout for fuzzed code (milliseconds). This is the upper bound, - also used for detecting hangs; the actual value is auto-scaled: */ - -#define EXEC_TIMEOUT 1000U - -/* Timeout rounding factor when auto-scaling (milliseconds): */ - -#define EXEC_TM_ROUND 20U - -/* 64bit arch MACRO */ -#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__)) - #define WORD_SIZE_64 1 -#endif - -/* Default memory limit for child process (MB) 0 = disabled : */ - -#define MEM_LIMIT 0U - -/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ - -#define MEM_LIMIT_QEMU 0U - -/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ - -#define MEM_LIMIT_UNICORN 0U - -/* Number of calibration cycles per every new test case (and for test - cases that show variable behavior): */ - -#define CAL_CYCLES 8U -#define CAL_CYCLES_LONG 20U - -/* Number of subsequent timeouts before abandoning an input file: */ - -#define TMOUT_LIMIT 250U - -/* Maximum number of unique hangs or crashes to record: */ - -#define KEEP_UNIQUE_HANG 500U -#define KEEP_UNIQUE_CRASH 10000U - -/* Baseline number of random tweaks during a single 'havoc' stage: */ - -#define HAVOC_CYCLES 256U -#define HAVOC_CYCLES_INIT 1024U - -/* Maximum multiplier for the above (should be a power of two, beware - of 32-bit int overflows): */ - -#define HAVOC_MAX_MULT 64U -#define HAVOC_MAX_MULT_MOPT 64U - -/* Absolute minimum number of havoc cycles (after all adjustments): */ - -#define HAVOC_MIN 12U - -/* Power Schedule Divisor */ -#define POWER_BETA 1U -#define MAX_FACTOR (POWER_BETA * 32) - -/* Maximum stacking for havoc-stage tweaks. The actual value is calculated - like this: - - n = random between 1 and HAVOC_STACK_POW2 - stacking = 2^n - - In other words, the default (n = 4) produces 2, 4, 8, 16 - stacked tweaks: */ - -#define HAVOC_STACK_POW2 4U - -/* Caps on block sizes for cloning and deletion operations. Each of these - ranges has a 33% probability of getting picked, except for the first - two cycles where smaller blocks are favored: */ - -#define HAVOC_BLK_SMALL 32U -#define HAVOC_BLK_MEDIUM 128U -#define HAVOC_BLK_LARGE 1500U - -/* Extra-large blocks, selected very rarely (<5% of the time): */ - -#define HAVOC_BLK_XL 32768U - -/* Probabilities of skipping non-favored entries in the queue, expressed as - percentages: */ - -#define SKIP_TO_NEW_PROB 99 /* ...when there are new, pending favorites */ -#define SKIP_NFAV_OLD_PROB 95 /* ...no new favs, cur entry already fuzzed */ -#define SKIP_NFAV_NEW_PROB 75 /* ...no new favs, cur entry not fuzzed yet */ - -/* Splicing cycle count: */ - -#define SPLICE_CYCLES 15 - -/* Nominal per-splice havoc cycle length: */ - -#define SPLICE_HAVOC 32 - -/* Maximum offset for integer addition / subtraction stages: */ - -#define ARITH_MAX 35 - -/* Limits for the test case trimmer. The absolute minimum chunk size; and - the starting and ending divisors for chopping up the input file: */ - -#define TRIM_MIN_BYTES 4 -#define TRIM_START_STEPS 16 -#define TRIM_END_STEPS 1024 - -/* Maximum size of input file, in bytes (keep under 100MB, default 1MB): - (note that if this value is changed, several areas in afl-cc.c, afl-fuzz.c - and afl-fuzz-state.c have to be changed as well! */ - -#define MAX_FILE (1 * 1024 * 1024L) - -/* The same, for the test case minimizer: */ - -#define TMIN_MAX_FILE (10 * 1024 * 1024L) - -/* Block normalization steps for afl-tmin: */ - -#define TMIN_SET_MIN_SIZE 4 -#define TMIN_SET_STEPS 128 - -/* Maximum dictionary token size (-x), in bytes: */ - -#define MAX_DICT_FILE 128 - -/* Length limits for auto-detected dictionary tokens: */ - -#define MIN_AUTO_EXTRA 3 -#define MAX_AUTO_EXTRA 32 - -/* Maximum number of user-specified dictionary tokens to use in deterministic - steps; past this point, the "extras/user" step will be still carried out, - but with proportionally lower odds: */ - -#define MAX_DET_EXTRAS 256 - -/* Maximum number of auto-extracted dictionary tokens to actually use in fuzzing - (first value), and to keep in memory as candidates. The latter should be much - higher than the former. */ - -#define USE_AUTO_EXTRAS 128 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) - -/* Scaling factor for the effector map used to skip some of the more - expensive deterministic steps. The actual divisor is set to - 2^EFF_MAP_SCALE2 bytes: */ - -#define EFF_MAP_SCALE2 3 - -/* Minimum input file length at which the effector logic kicks in: */ - -#define EFF_MIN_LEN 128 - -/* Maximum effector density past which everything is just fuzzed - unconditionally (%): */ - -#define EFF_MAX_PERC 90 - -/* UI refresh frequency (Hz): */ - -#define UI_TARGET_HZ 5 - -/* Fuzzer stats file and plot update intervals (sec): */ - -#define STATS_UPDATE_SEC 60 -#define PLOT_UPDATE_SEC 5 - -/* Smoothing divisor for CPU load and exec speed stats (1 - no smoothing). */ - -#define AVG_SMOOTHING 16 - -/* Sync interval (every n havoc cycles): */ - -#define SYNC_INTERVAL 8 - -/* Sync time (minimum time between syncing in ms, time is halfed for -M main - nodes) - default is 30 minutes: */ - -#define SYNC_TIME (30 * 60 * 1000) - -/* Output directory reuse grace period (minutes): */ - -#define OUTPUT_GRACE 25 - -/* Uncomment to use simple file names (id_NNNNNN): */ - -// #define SIMPLE_FILES - -/* List of interesting values to use in fuzzing. */ - -#define INTERESTING_8 \ - -128, /* Overflow signed 8-bit when decremented */ \ - -1, /* */ \ - 0, /* */ \ - 1, /* */ \ - 16, /* One-off with common buffer size */ \ - 32, /* One-off with common buffer size */ \ - 64, /* One-off with common buffer size */ \ - 100, /* One-off with common buffer size */ \ - 127 /* Overflow signed 8-bit when incremented */ - -#define INTERESTING_8_LEN 9 - -#define INTERESTING_16 \ - -32768, /* Overflow signed 16-bit when decremented */ \ - -129, /* Overflow signed 8-bit */ \ - 128, /* Overflow signed 8-bit */ \ - 255, /* Overflow unsig 8-bit when incremented */ \ - 256, /* Overflow unsig 8-bit */ \ - 512, /* One-off with common buffer size */ \ - 1000, /* One-off with common buffer size */ \ - 1024, /* One-off with common buffer size */ \ - 4096, /* One-off with common buffer size */ \ - 32767 /* Overflow signed 16-bit when incremented */ - -#define INTERESTING_16_LEN 10 - -#define INTERESTING_32 \ - -2147483648LL, /* Overflow signed 32-bit when decremented */ \ - -100663046, /* Large negative number (endian-agnostic) */ \ - -32769, /* Overflow signed 16-bit */ \ - 32768, /* Overflow signed 16-bit */ \ - 65535, /* Overflow unsig 16-bit when incremented */ \ - 65536, /* Overflow unsig 16 bit */ \ - 100663045, /* Large positive number (endian-agnostic) */ \ - 2147483647 /* Overflow signed 32-bit when incremented */ - -#define INTERESTING_32_LEN 8 - -/*********************************************************** - * * - * Really exotic stuff you probably don't want to touch: * - * * - ***********************************************************/ - -/* Call count interval between reseeding the libc PRNG from /dev/urandom: */ - -#define RESEED_RNG 100000 - -/* The default maximum testcase cache size in MB, 0 = disable. - A value between 50 and 250 is a good default value. Note that the - number of entries will be auto assigned if not specified via the - AFL_TESTCACHE_ENTRIES env variable */ - -#define TESTCASE_CACHE_SIZE 50 - -/* Maximum line length passed from GCC to 'as' and used for parsing - configuration files: */ - -#define MAX_LINE 8192 - -/* Environment variable used to pass SHM ID to the called program. */ - -#define SHM_ENV_VAR "__AFL_SHM_ID" - -/* Environment variable used to pass SHM FUZZ ID to the called program. */ - -#define SHM_FUZZ_ENV_VAR "__AFL_SHM_FUZZ_ID" - -/* Other less interesting, internal-only variables. */ - -#define CLANG_ENV_VAR "__AFL_CLANG_MODE" -#define AS_LOOP_ENV_VAR "__AFL_AS_LOOPCHECK" -#define PERSIST_ENV_VAR "__AFL_PERSISTENT" -#define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" - -/* In-code signatures for deferred and persistent mode. */ - -#define PERSIST_SIG "##SIG_AFL_PERSISTENT##" -#define DEFER_SIG "##SIG_AFL_DEFER_FORKSRV##" - -/* Distinctive bitmap signature used to indicate failed execution: */ - -#define EXEC_FAIL_SIG 0xfee1dead - -/* Distinctive exit code used to indicate MSAN trip condition: */ - -#define MSAN_ERROR 86 - -/* Distinctive exit code used to indicate LSAN trip condition: */ - -#define LSAN_ERROR 23 - -/* Designated file descriptors for forkserver commands (the application will - use FORKSRV_FD and FORKSRV_FD + 1): */ - -#define FORKSRV_FD 198 - -/* Fork server init timeout multiplier: we'll wait the user-selected - timeout plus this much for the fork server to spin up. */ - -#define FORK_WAIT_MULT 10 - -/* Calibration timeout adjustments, to be a bit more generous when resuming - fuzzing sessions or trying to calibrate already-added internal finds. - The first value is a percentage, the other is in milliseconds: */ - -#define CAL_TMOUT_PERC 125 -#define CAL_TMOUT_ADD 50 - -/* Number of chances to calibrate a case before giving up: */ - -#define CAL_CHANCES 3 - -/* Map size for the traced binary (2^MAP_SIZE_POW2). Must be greater than - 2; you probably want to keep it under 18 or so for performance reasons - (adjusting AFL_INST_RATIO when compiling is probably a better way to solve - problems with complex programs). You need to recompile the target binary - after changing this - otherwise, SEGVs may ensue. */ - -#define MAP_SIZE_POW2 16 -#define MAP_SIZE (1U << MAP_SIZE_POW2) - -/* Maximum allocator request size (keep well under INT_MAX): */ - -#define MAX_ALLOC 0x40000000 - -/* A made-up hashing seed: */ - -#define HASH_CONST 0xa5b35705 - -/* Constants for afl-gotcpu to control busy loop timing: */ - -#define CTEST_TARGET_MS 5000 -#define CTEST_CORE_TRG_MS 1000 -#define CTEST_BUSY_CYCLES (10 * 1000 * 1000) - -/* Enable NeverZero counters in QEMU mode */ - -#define AFL_QEMU_NOT_ZERO - -/* AFL RedQueen */ - -#define CMPLOG_SHM_ENV_VAR "__AFL_CMPLOG_SHM_ID" - -/* CPU Affinity lockfile env var */ - -#define CPU_AFFINITY_ENV_VAR "__AFL_LOCKFILE" - -/* Uncomment this to use inferior block-coverage-based instrumentation. Note - that you need to recompile the target binary for this to have any effect: */ - -// #define COVERAGE_ONLY - -/* Uncomment this to ignore hit counts and output just one bit per tuple. - As with the previous setting, you will need to recompile the target - binary: */ - -// #define SKIP_COUNTS - -/* Uncomment this to use instrumentation data to record newly discovered paths, - but do not use them as seeds for fuzzing. This is useful for conveniently - measuring coverage that could be attained by a "dumb" fuzzing algorithm: */ - -// #define IGNORE_FINDS - -/* Text mutations */ - -/* Minimum length of a queue input to be evaluated for "is_ascii"? */ - -#define AFL_TXT_MIN_LEN 12 - -/* What is the minimum percentage of ascii characters present to be classifed - as "is_ascii"? */ - -#define AFL_TXT_MIN_PERCENT 94 - -/* How often to perform ASCII mutations 0 = disable, 1-8 are good values */ - -#define AFL_TXT_BIAS 6 - -/* Maximum length of a string to tamper with */ - -#define AFL_TXT_STRING_MAX_LEN 1024 - -/* Maximum mutations on a string */ - -#define AFL_TXT_STRING_MAX_MUTATIONS 6 - -#endif /* ! _HAVE_CONFIG_H */ - diff --git a/include/afl/types.h b/include/afl/types.h deleted file mode 100644 index 7b94fb83..00000000 --- a/include/afl/types.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - american fuzzy lop++ - type definitions and minor macros - -------------------------------------------------------- - - Originally written by Michal Zalewski - - Now maintained by Marc Heuse , - Heiko Eißfeldt , - Andrea Fioraldi , - Dominik Maier - - Copyright 2016, 2017 Google Inc. All rights reserved. - Copyright 2019-2020 AFLplusplus Project. All rights reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at: - - http://www.apache.org/licenses/LICENSE-2.0 - - */ - -#ifndef _HAVE_TYPES_H -#define _HAVE_TYPES_H - -#include -#include -#include "config.h" - -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -#ifdef WORD_SIZE_64 -typedef unsigned __int128 uint128_t; -typedef uint128_t u128; -#endif - -/* Extended forkserver option values */ - -/* Reporting errors */ -#define FS_OPT_ERROR 0xf800008f -#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8) -#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8) -#define FS_ERROR_MAP_SIZE 1 -#define FS_ERROR_MAP_ADDR 2 -#define FS_ERROR_SHM_OPEN 4 -#define FS_ERROR_SHMAT 8 -#define FS_ERROR_MMAP 16 - -/* Reporting options */ -#define FS_OPT_ENABLED 0x80000001 -#define FS_OPT_MAPSIZE 0x40000000 -#define FS_OPT_SNAPSHOT 0x20000000 -#define FS_OPT_AUTODICT 0x10000000 -#define FS_OPT_SHDMEM_FUZZ 0x01000000 -#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000 -// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 -#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1) -#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) -#define FS_OPT_SET_MAPSIZE(x) \ - (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) - -typedef unsigned long long u64; - -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; -#ifdef WORD_SIZE_64 -typedef __int128 int128_t; -typedef int128_t s128; -#endif - -#ifndef MIN - #define MIN(a, b) \ - ({ \ - \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; \ - \ - }) - - #define MAX(a, b) \ - ({ \ - \ - __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a > _b ? _a : _b; \ - \ - }) - -#endif /* !MIN */ - -#define SWAP16(_x) \ - ({ \ - \ - u16 _ret = (_x); \ - (u16)((_ret << 8) | (_ret >> 8)); \ - \ - }) - -#define SWAP32(_x) \ - ({ \ - \ - u32 _ret = (_x); \ - (u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | \ - ((_ret >> 8) & 0x0000FF00)); \ - \ - }) - -#define SWAP64(_x) \ - ({ \ - \ - u64 _ret = (_x); \ - _ret = \ - (_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \ - _ret = \ - (_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \ - _ret = \ - (_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8; \ - _ret; \ - \ - }) - -// It is impossible to define 128 bit constants, so ... -#ifdef WORD_SIZE_64 - #define SWAPN(_x, _l) \ - ({ \ - \ - u128 _res = (_x), _ret; \ - char *d = (char *)&_ret, *s = (char *)&_res; \ - int i; \ - for (i = 0; i < 16; i++) \ - d[15 - i] = s[i]; \ - u32 sr = 128U - ((_l) << 3U); \ - (_ret >>= sr); \ - (u128) _ret; \ - \ - }) -#endif - -#define SWAPNN(_x, _y, _l) \ - ({ \ - \ - char *d = (char *)(_x), *s = (char *)(_y); \ - u32 i, l = (_l)-1; \ - for (i = 0; i <= l; i++) \ - d[l - i] = s[i]; \ - \ - }) - -#ifdef AFL_LLVM_PASS - #if defined(__linux__) || !defined(__ANDROID__) - #define AFL_SR(s) (srandom(s)) - #define AFL_R(x) (random() % (x)) - #else - #define AFL_SR(s) ((void)s) - #define AFL_R(x) (arc4random_uniform(x)) - #endif -#else - #if defined(__linux__) || !defined(__ANDROID__) - #define SR(s) (srandom(s)) - #define R(x) (random() % (x)) - #else - #define SR(s) ((void)s) - #define R(x) (arc4random_uniform(x)) - #endif -#endif /* ^AFL_LLVM_PASS */ - -#define STRINGIFY_INTERNAL(x) #x -#define STRINGIFY(x) STRINGIFY_INTERNAL(x) - -#define MEM_BARRIER() __asm__ volatile("" ::: "memory") - -#if __GNUC__ < 6 - #ifndef likely - #define likely(_x) (_x) - #endif - #ifndef unlikely - #define unlikely(_x) (_x) - #endif -#else - #ifndef likely - #define likely(_x) __builtin_expect(!!(_x), 1) - #endif - #ifndef unlikely - #define unlikely(_x) __builtin_expect(!!(_x), 0) - #endif -#endif - -#endif /* ! _HAVE_TYPES_H */ - diff --git a/include/uc_priv.h b/include/uc_priv.h index a148c10e..8c564396 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -15,31 +15,14 @@ // These are masks of supported modes for each cpu/arch. // They should be updated when changes are made to the uc_mode enum typedef. -#ifdef UNICORN_HAS_AFL -#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ - |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) -#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_PPC_MASK (UC_MODE_PPC32|UC_MODE_PPC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_SPARC_MASK (UC_MODE_SPARC32|UC_MODE_SPARC64|UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_M68K_MASK (UC_MODE_BIG_ENDIAN|UC_MODE_AFL) -#define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN|UC_MODE_AFL) -#else #define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS \ |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|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_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_PPC32|UC_MODE_PPC64|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 UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) -#endif - -#ifndef NDEBUG -#define UCLOG(...) fprintf(stderr, __VA_ARGS__) -#else -#define UCLOG(...) -#endif #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -112,20 +95,6 @@ typedef void (*uc_softfloat_initialize)(void); // tcg flush softmmu tlb typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); -typedef enum uc_afl_ret { - UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent - UC_AFL_RET_CHILD, // Fork worked. we are a child - UC_AFL_RET_NO_AFL, // No AFL, no need to fork. - UC_AFL_RET_CALLED_TWICE, // AFL has already been started before. - UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) -} uc_afl_ret; - -// we use this as shortcut deep inside uc_afl for the arch specific uc_afl_next(uc, bool) -typedef uc_afl_ret(*uc_afl_ret_uc_bool_t)(struct uc_struct*, bool); - -// afl_forkserver_start -typedef int (*uc_afl_forkserver_t)(struct uc_struct*); - struct hook { int type; // UC_HOOK_* int insn; // instruction for HOOK_INSN @@ -313,23 +282,6 @@ struct uc_struct { bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()? struct list saved_contexts; // The contexts saved by this uc_struct. bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. - -#ifdef UNICORN_HAS_AFL - bool afl; - uc_afl_forkserver_t afl_forkserver_start; // function to start afl forkserver - uc_afl_ret_uc_bool_t afl_child_request_next; // function from child to ask for new testcase (if in child) - int afl_child_pipe[2]; // pipe used to send information from child process to forkserver - int afl_parent_pipe[2]; // pipe used to send information from parent to child in forkserver - uint8_t *afl_area_ptr; // map, shared with afl, to report coverage feedback etc. during runs - uint64_t afl_prev_loc; // previous location - int afl_compcov_level; // how much compcove we want - unsigned int afl_inst_rms; - size_t exit_count; // number of exits set in afl_fuzz or afl_forkserver - uint64_t *exits; // pointer to the actual exits - char *afl_testcase_ptr; // map, shared with afl, to get testcases delivered from for each run - uint32_t *afl_testcase_size_p; // size of the current testcase, if using shared map fuzzing with afl. - void *afl_data_ptr; // Pointer for various (bindings-related) uses. -#endif }; // Metadata stub for the variable-size cpu context used with uc_context_*() diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 042318e8..d7780e56 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -105,7 +105,6 @@ typedef enum uc_arch { typedef enum uc_mode { UC_MODE_LITTLE_ENDIAN = 0, // little-endian mode (default mode) UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode - UC_MODE_AFL = 1 << 29, // arm / arm64 UC_MODE_ARM = 0, // ARM mode @@ -172,10 +171,6 @@ typedef enum uc_err { UC_ERR_HOOK_EXIST, // hook for this event already existed UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() UC_ERR_EXCEPTION, // Unhandled CPU exception - UC_ERR_AFL_RET_ERROR, // Something went horribly wrong in the parent - UC_ERR_AFL_RET_NO_AFL, // No AFL, no need to fork. - UC_ERR_AFL_RET_CALLED_TWICE, // AFL has already been started before. - UC_ERR_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) } uc_err; @@ -573,82 +568,6 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); UNICORN_EXPORT uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count); -/* Callback function called for each input from AFL. - This function is mandatory. - It's purpose is to place the input at the right place in unicorn. - @uc: Unicorn instance - @input: The current input we're working on. Place this somewhere in unicorn's memory now. - @input_len: length of the input - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). - @return: - If you return is true, all is well. Fuzzing starts. - If you return false, the input is rejected; we will continue with the next input. -*/ -typedef bool (*uc_afl_cb_place_input_t)(uc_engine *uc, char *input, size_t input_len, uint32_t persistent_round, void *data); - -/* Callback function called after a non-UC_ERR_OK returncode was returned by Unicorn. - This function is not mandatory (pass NULL). - @uc: Unicorn instance - @unicorn_result: The error state returned by the current testcase - @input: The current input we're workin with. - @input_len: length of the input - @persistent_round: which round we are currently crashing in, if using persistent mode. - @data: Data pointer passed to uc_afl_fuzz(...). -@Return: - If you return false, the crash is considered invalid and not reported to AFL. - If return is true, the crash is reported. - -> The child will die and the forkserver will spawn a new child. -*/ -typedef bool (*uc_afl_cb_validate_crash_t)(uc_engine *uc, uc_err unicorn_result, char *input, int input_len, int persistent_round, void *data); - -/* - The main fuzzer. - Starts uc_afl_forkserver(), then beginns a persistent loop. - Reads input, calls the place_input callback, emulates, uc_afl_next(...), repeats. - If unicorn errors out, will call the validate_crash_callback, if set. - Will only retrun in the parent after the whole fuzz thing has been finished and afl died. - The child processes never return from here. - - Note: This API is not supported on Windows. - - @uc: handle returned by uc_open() - @input_file: filename/path to the (AFL) inputfile. Usualy suplied on the commandline. - @place_input_callback: Callback function that will be called before each test runs. - This function needs to write the input from afl to the correct position on the unicorn object. - @exits: address list of exits where fuzzing should stop (len == exit_count) - @exit_count: number of exits where fuzzing should stop - @validate_crash_callback: Optional callback (if not needed, pass NULL), that determines - if a non-OK uc_err is an actual error. If false is returned, the test-case will not crash. - @always_validate: If false, validate_crash_callback will only be called for crashes. - @persistent_iters: - The amount of loop iterations in persistent mode before restarteing with a new forked child. - If your target cannot be fuzzed using persistent mode (global state changes a lot), - set persistent_iters = 1 for the normal fork-server experience. - Else, the default is usually around 1000. - If your target is super stable (and unicorn is, too - not sure about that one), - you may pass persistent_iter = 0 for that an infinite fuzz loop. - @data: Your very own data pointer. This will passed into every callback. - @return uc_afl_ret: - >UC_AFL_RET_ERROR = 0, // Something went horribly wrong in the parent - >UC_AFL_RET_CHILD, // Can never happen, the child will loop happily or exit. - >UC_AFL_RET_NO_AFL, // No AFL, we ran the testacse once and are done. - >UC_AFL_RET_FINISHED, // We forked before but now AFL is gone (parent) - >> We're retuning after having fuzzed. We may now pack our bags and exit. -*/ -UNICORN_EXPORT -uc_err uc_afl_fuzz( - uc_engine *uc, - char* input_file, - uc_afl_cb_place_input_t place_input_callback, - uint64_t *exits, - size_t exit_count, - uc_afl_cb_validate_crash_t validate_crash_callback, - bool always_validate, - uint32_t persistent_iters, - void *data -); - /* Stop emulation (which was started by uc_emu_start() API. This is typically called from callback functions registered via tracing APIs. diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 21397dcd..75d71514 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif -#define afl_forkserver_start afl_forkserver_start_aarch64 -#define helper_afl_maybe_log helper_afl_maybe_log_aarch64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64 #define use_idiv_instructions use_idiv_instructions_aarch64 #define arm_arch arm_arch_aarch64 #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index 55536832..ee750153 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64eb #endif -#define afl_forkserver_start afl_forkserver_start_aarch64eb -#define helper_afl_maybe_log helper_afl_maybe_log_aarch64eb -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_aarch64eb -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_aarch64eb -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_aarch64eb #define use_idiv_instructions use_idiv_instructions_aarch64eb #define arm_arch arm_arch_aarch64eb #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64eb diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index ea5b8045..79bcdd13 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -29,10 +29,6 @@ #include "sysemu/cpus.h" #include "uc_priv.h" -#ifdef UNICORN_HAS_AFL -#include "afl/afl-cpu-inl.h" -#endif - /* -icount align implementation. */ typedef struct SyncClocks { @@ -258,11 +254,6 @@ static inline TranslationBlock *tb_find(CPUState *cpu, /* We add the TB in the virtual pc hash table for the fast lookup */ cpu->tb_jmp_cache[tb_jmp_cache_hash_func(cpu->uc, pc)] = tb; } - -#if defined(UNICORN_HAS_AFL) - afl_request_tsl(cpu, pc, cs_base, flags, cf_mask); -#endif - /* We don't take care of direct jumps when address mapping changes in * system emulation. So it's not safe to make a direct jump to a TB * spanning two pages because the mapping for the second page can change. @@ -588,31 +579,3 @@ int cpu_exec(struct uc_struct *uc, CPUState *cpu) return ret; } - -#ifdef UNICORN_HAS_AFL -int afl_forkserver_start(struct uc_struct *uc) -{ - // Not sure if we need all of this setup foo. - CPUState *cpu = uc->cpu; - if (!cpu->created) { - cpu->created = true; - cpu->halted = 0; - qemu_init_vcpu(cpu); - - } - cpu_resume(cpu); - - if (uc->count_hook != 0) { - uc_hook_del(uc, uc->count_hook); - uc->count_hook = 0; - } - - uc->quit_request = false; - uc->cpu = cpu; - smp_mb(); - - // Would love to not have the extra step in cpus.c, but it doesn't work otherwise(?) - afl_setup(uc); - return afl_forkserver(cpu); -} -#endif \ No newline at end of file diff --git a/qemu/accel/tcg/tcg-runtime.c b/qemu/accel/tcg/tcg-runtime.c index 67829b91..1e8283ea 100644 --- a/qemu/accel/tcg/tcg-runtime.c +++ b/qemu/accel/tcg/tcg-runtime.c @@ -32,10 +32,6 @@ #include -#ifdef UNICORN_HAS_AFL -#include "afl/afl-tcg-runtime-inl.h" -#endif - /* 32-bit helpers */ int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2) diff --git a/qemu/accel/tcg/tcg-runtime.h b/qemu/accel/tcg/tcg-runtime.h index 813c1c07..ab7369e8 100644 --- a/qemu/accel/tcg/tcg-runtime.h +++ b/qemu/accel/tcg/tcg-runtime.h @@ -259,10 +259,3 @@ DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32) DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32) - -#if defined(UNICORN_HAS_AFL) -DEF_HELPER_FLAGS_2(afl_maybe_log, 0, void, ptr, i64) -DEF_HELPER_FLAGS_4(afl_compcov_log_16, 0, void, ptr, i64, i32, i32) -DEF_HELPER_FLAGS_4(afl_compcov_log_32, 0, void, ptr, i64, i32, i32) -DEF_HELPER_FLAGS_4(afl_compcov_log_64, 0, void, ptr, i64, i64, i64) -#endif \ No newline at end of file diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 8afbc1fd..0fca28a9 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -17,11 +17,6 @@ #include -#if defined(UNICORN_HAS_AFL) -#undef ARCH_HAS_COMPCOV -#include "afl/afl-cpu-translate-inl.h" -#endif - /* Pairs with tcg_clear_temp_count. To be called by #TranslatorOps.{translate_insn,tb_stop} if (1) the target is sufficiently clean to support reporting, @@ -61,29 +56,6 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Reset the temp count so that we can identify leaks */ tcg_clear_temp_count(); -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = cpu->uc->exits; - size_t exit_count = cpu->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (tb->pc == exits[i]) { - // This should catch that instruction is at the end - // and generate appropriate halting code. - gen_tb_start(tcg_ctx, db->tb); - ops->tb_start(db, cpu); - db->num_insns++; - ops->insn_start(db, cpu); - ops->translate_insn(db, cpu); - goto _end_loop; - } - } - } - } -#endif - /* Unicorn: early check to see if the address of this block is * the "run until" address. */ if (tb->pc == cpu->uc->addr_end) { @@ -109,10 +81,6 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, // tcg_dump_ops(tcg_ctx, false, "translator loop"); -#ifdef UNICORN_HAS_AFL - afl_gen_maybe_log(tcg_ctx, tb->pc); -#endif - /* Start translating. */ gen_tb_start(tcg_ctx, db->tb); // tcg_dump_ops(tcg_ctx, false, "tb start"); diff --git a/qemu/arm.h b/qemu/arm.h index ef9fa72d..d3cc372d 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif -#define afl_forkserver_start afl_forkserver_start_arm -#define helper_afl_maybe_log helper_afl_maybe_log_arm -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_arm -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_arm -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_arm #define use_idiv_instructions use_idiv_instructions_arm #define arm_arch arm_arch_arm #define tb_target_set_jmp_target tb_target_set_jmp_target_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 7ecccaaa..0a51a80d 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _armeb #endif -#define afl_forkserver_start afl_forkserver_start_armeb -#define helper_afl_maybe_log helper_afl_maybe_log_armeb -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_armeb -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_armeb -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_armeb #define use_idiv_instructions use_idiv_instructions_armeb #define arm_arch arm_arch_armeb #define tb_target_set_jmp_target tb_target_set_jmp_target_armeb diff --git a/qemu/include/tcg/tcg-op.h b/qemu/include/tcg/tcg-op.h index 915fe79f..73d1b93f 100644 --- a/qemu/include/tcg/tcg-op.h +++ b/qemu/include/tcg/tcg-op.h @@ -29,10 +29,6 @@ #include "exec/helper-proto.h" #include "exec/helper-gen.h" -#ifdef UNICORN_HAS_AFL -#include "afl/afl-tcg-op-inl.h" -#endif - 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); diff --git a/qemu/m68k.h b/qemu/m68k.h index 77fb249c..cb3d430b 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif -#define afl_forkserver_start afl_forkserver_start_m68k -#define helper_afl_maybe_log helper_afl_maybe_log_m68k -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_m68k -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_m68k -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_m68k #define use_idiv_instructions use_idiv_instructions_m68k #define arm_arch arm_arch_m68k #define tb_target_set_jmp_target tb_target_set_jmp_target_m68k diff --git a/qemu/mips.h b/qemu/mips.h index 9eef9f63..a2b78379 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif -#define afl_forkserver_start afl_forkserver_start_mips -#define helper_afl_maybe_log helper_afl_maybe_log_mips -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips #define use_idiv_instructions use_idiv_instructions_mips #define arm_arch arm_arch_mips #define tb_target_set_jmp_target tb_target_set_jmp_target_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9dde191e..9faef36b 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif -#define afl_forkserver_start afl_forkserver_start_mips64 -#define helper_afl_maybe_log helper_afl_maybe_log_mips64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64 #define use_idiv_instructions use_idiv_instructions_mips64 #define arm_arch arm_arch_mips64 #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 4634c429..6f748b36 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif -#define afl_forkserver_start afl_forkserver_start_mips64el -#define helper_afl_maybe_log helper_afl_maybe_log_mips64el -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mips64el -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mips64el -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mips64el #define use_idiv_instructions use_idiv_instructions_mips64el #define arm_arch arm_arch_mips64el #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 1e6ce28b..a4831183 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif -#define afl_forkserver_start afl_forkserver_start_mipsel -#define helper_afl_maybe_log helper_afl_maybe_log_mipsel -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_mipsel -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_mipsel -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_mipsel #define use_idiv_instructions use_idiv_instructions_mipsel #define arm_arch arm_arch_mipsel #define tb_target_set_jmp_target tb_target_set_jmp_target_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index e787604c..8cb9ea3e 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif -#define afl_forkserver_start afl_forkserver_start_ppc -#define helper_afl_maybe_log helper_afl_maybe_log_ppc -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc #define use_idiv_instructions use_idiv_instructions_ppc #define arm_arch arm_arch_ppc #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index ada125c0..1d055072 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif -#define afl_forkserver_start afl_forkserver_start_ppc64 -#define helper_afl_maybe_log helper_afl_maybe_log_ppc64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_ppc64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_ppc64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_ppc64 #define use_idiv_instructions use_idiv_instructions_ppc64 #define arm_arch arm_arch_ppc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index f91bcf0b..df9eed70 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif -#define afl_forkserver_start afl_forkserver_start_riscv32 -#define helper_afl_maybe_log helper_afl_maybe_log_riscv32 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv32 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv32 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv32 #define use_idiv_instructions use_idiv_instructions_riscv32 #define arm_arch arm_arch_riscv32 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index c59c5148..c41e7178 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif -#define afl_forkserver_start afl_forkserver_start_riscv64 -#define helper_afl_maybe_log helper_afl_maybe_log_riscv64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_riscv64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_riscv64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_riscv64 #define use_idiv_instructions use_idiv_instructions_riscv64 #define arm_arch arm_arch_riscv64 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv64 diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index 464e7b94..f983f634 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -194,23 +194,6 @@ void resume_all_vcpus(struct uc_struct* uc) tb_flush_jmp_cache(cpu, uc->addr_end); } -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - TranslationBlock *tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(uc, exits[i])]; - if (tb) { - qht_remove(&uc->tcg_ctx->tb_ctx.htable, tb, tb->hash); - tb_flush_jmp_cache(cpu, uc->exits[i]); - } - } - } - } -#endif cpu->created = false; } diff --git a/qemu/sparc.h b/qemu/sparc.h index daa2dcb6..741e7565 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif -#define afl_forkserver_start afl_forkserver_start_sparc -#define helper_afl_maybe_log helper_afl_maybe_log_sparc -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc #define use_idiv_instructions use_idiv_instructions_sparc #define arm_arch arm_arch_sparc #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index a2e1ec32..5262a11b 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif -#define afl_forkserver_start afl_forkserver_start_sparc64 -#define helper_afl_maybe_log helper_afl_maybe_log_sparc64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_sparc64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_sparc64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_sparc64 #define use_idiv_instructions use_idiv_instructions_sparc64 #define arm_arch arm_arch_sparc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc64 diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index ef8ad7aa..a9eb1ca0 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -37,11 +37,6 @@ #include "qemu/atomic128.h" #include "kvm-consts.h" -#if defined(UNICORN_HAS_AFL) -#undef ARCH_HAS_COMPCOV -#include "afl/afl-cpu-translate-inl.h" -#endif - static const char *regnames[] = { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", @@ -14641,23 +14636,6 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) DisasContext *dc = container_of(dcbase, DisasContext, base); CPUARMState *env = cpu->env_ptr; -#ifdef UNICORN_HAS_AFL - if (dc->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = dc->uc->exits; - size_t exit_count = dc->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dcbase->pc_next == exits[i]) { - dcbase->is_jmp = DISAS_WFI; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 1c4827d7..742a55fd 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11420,23 +11420,6 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) return; } -#ifdef UNICORN_HAS_AFL - if (dc->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = dc->uc->exits; - size_t exit_count = dc->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dcbase->pc_next == exits[i]) { - dcbase->is_jmp = DISAS_WFI; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dcbase->pc_next == dc->uc->addr_end) { // imitate WFI instruction to halt emulation diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index fce8d914..cf148c4b 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4764,27 +4764,6 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; -#ifdef UNICORN_HAS_AFL - if (s->uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = s->uc->exits; - size_t exit_count = s->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (s->pc == exits[i]) { - // imitate the HLT instruction - gen_update_cc_op(s); - gen_jmp_im(s, pc_start - s->cs_base); - gen_helper_hlt(tcg_ctx, tcg_ctx->cpu_env, tcg_const_i32(tcg_ctx, s->pc - pc_start)); - s->base.is_jmp = DISAS_NORETURN; - return s->pc; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (s->pc == s->uc->addr_end) { // imitate the HLT instruction diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 0dc9af2b..323eff44 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6325,23 +6325,6 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUM68KState *env = cpu->env_ptr; uint16_t insn; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dc->pc == exits[i]) { - gen_exception(dc, dc->pc, EXCP_HLT); - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { gen_exception(dc, dc->pc, EXCP_HLT); diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 4660a2b3..97e680a3 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30931,24 +30931,6 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) {// raise a special interrupt to quit - gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); - ctx->base.is_jmp = DISAS_NORETURN; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { // raise a special interrupt to quit diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 2e06bbb7..8cfebab2 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7625,23 +7625,6 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n", ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) { - gen_wait(ctx); - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == uc->addr_end) { gen_wait(ctx); diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index a1ef4139..9898093d 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -849,24 +849,6 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) TCGOp *tcg_op, *prev_op = NULL; bool insn_hook = false; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = ctx->uc->exits; - size_t exit_count = ctx->uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (ctx->base.pc_next == exits[i]) { - // Unicorn: We have to exit current execution here. - dcbase->is_jmp = DISAS_UC_EXIT; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (ctx->base.pc_next == ctx->uc->addr_end) { // Unicorn: We have to exit current execution here. diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index 6c45978c..c6f3d9cd 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5950,26 +5950,6 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) CPUSPARCState *env = cs->env_ptr; unsigned int insn; -#ifdef UNICORN_HAS_AFL - if (uc->afl) { - // UNICORN-AFL supports (and needs) multiple exits. - uint64_t *exits = uc->exits; - size_t exit_count = uc->exit_count; - if (exit_count) { - size_t i; - for (i = 0; i < exit_count; i++) { - if (dc->pc == exits[i]) { -#ifndef TARGET_SPARC64 - gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); -#endif - dcbase->is_jmp = DISAS_NORETURN; - return; - } - } - } - } -#endif - // Unicorn: end address tells us to stop emulation if (dc->pc == uc->addr_end) { #ifndef TARGET_SPARC64 diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 6e4f3d49..5fd5ff0f 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -1655,7 +1655,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) def = &s->tcg_op_defs[c]; if (c == INDEX_op_insn_start) { nb_oargs = 0; - UCLOG(" ----"); + printf(" ----"); for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { target_ulong a; @@ -1664,7 +1664,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) #else a = op->args[i]; #endif - UCLOG(" " TARGET_FMT_lx, a); + printf(" " TARGET_FMT_lx, a); } } else if (c == INDEX_op_call) { /* variable number of arguments */ @@ -1673,11 +1673,11 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) nb_cargs = def->nb_cargs; /* function name, flags, out args */ - UCLOG(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, + printf(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, tcg_find_helper(s, op->args[nb_oargs + nb_iargs]), op->args[nb_oargs + nb_iargs + 1], nb_oargs); for (i = 0; i < nb_oargs; i++) { - UCLOG(",%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf(",%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[i])); } for (i = 0; i < nb_iargs; i++) { @@ -1686,33 +1686,33 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) if (arg != TCG_CALL_DUMMY_ARG) { t = tcg_get_arg_str(s, buf, sizeof(buf), arg); } - UCLOG(",%s", t); + printf(",%s", t); } } else { - UCLOG(" %s ", def->name); + printf(" %s ", def->name); nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; if (def->flags & TCG_OPF_VECTOR) { - UCLOG("v%d,e%d,", 64 << TCGOP_VECL(op), + printf("v%d,e%d,", 64 << TCGOP_VECL(op), 8 << TCGOP_VECE(op)); } k = 0; for (i = 0; i < nb_oargs; i++) { if (k != 0) { - UCLOG(","); + printf(","); } - UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } for (i = 0; i < nb_iargs; i++) { if (k != 0) { - UCLOG(","); + printf(","); } - UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), + printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } switch (c) { @@ -1728,9 +1728,9 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_cmpsel_vec: if (op->args[k] < ARRAY_SIZE(cond_name) && cond_name[op->args[k]]) { - UCLOG(",%s", cond_name[op->args[k++]]); + printf(",%s", cond_name[op->args[k++]]); } else { - UCLOG(",$0x%" TCG_PRIlx, op->args[k++]); + printf(",$0x%" TCG_PRIlx, op->args[k++]); } i = 1; break; @@ -1744,12 +1744,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned ix = get_mmuidx(oi); if (op & ~(MO_AMASK | MO_BSWAP | MO_SSIZE)) { - UCLOG(",$0x%x,%u", op, ix); + printf(",$0x%x,%u", op, ix); } else { const char *s_al, *s_op; s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT]; s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)]; - UCLOG(",%s%s,%u", s_al, s_op, ix); + printf(",%s%s,%u", s_al, s_op, ix); } i = 1; } @@ -1764,7 +1764,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: case INDEX_op_brcond2_i32: - UCLOG("%s$L%d", k ? "," : "", + printf("%s$L%d", k ? "," : "", arg_label(op->args[k])->id); i++, k++; break; @@ -1772,12 +1772,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) break; } for (; i < nb_cargs; i++, k++) { - UCLOG("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); + printf("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); } if(c == INDEX_op_mov_i64){ struct TCGTemp* tp = arg_temp(op->args[1]); if (tp && tp->val_type == TEMP_VAL_MEM){ - UCLOG(" mem_base=%p ", tp->mem_base); + printf(" mem_base=%p ", tp->mem_base); } } } @@ -1786,19 +1786,19 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned life = op->life; if (life & (SYNC_ARG * 3)) { - UCLOG(" sync:"); + printf(" sync:"); for (i = 0; i < 2; ++i) { if (life & (SYNC_ARG << i)) { - UCLOG(" %d", i); + printf(" %d", i); } } } life /= DEAD_ARG; if (life) { - UCLOG(" dead:"); + printf(" dead:"); for (i = 0; life; ++i, life >>= 1) { if (life & 1) { - UCLOG(" %d", i); + printf(" %d", i); } } } @@ -1809,28 +1809,28 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) TCGRegSet set = op->output_pref[i]; if (i == 0) { - UCLOG(" pref="); + printf(" pref="); } else { - UCLOG(","); + printf(","); } if (set == 0) { - UCLOG("none"); + printf("none"); } else if (set == MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS)) { - UCLOG("all"); + printf("all"); #ifdef CONFIG_DEBUG_TCG } else if (tcg_regset_single(set)) { TCGReg reg = tcg_regset_first(set); printf("%s", tcg_target_reg_names[reg]); #endif } else if (TCG_TARGET_NB_REGS <= 32) { - UCLOG("%#x", (uint32_t)set); + printf("%#x", (uint32_t)set); } else { - UCLOG("%#" PRIx64, (uint64_t)set); + printf("%#" PRIx64, (uint64_t)set); } } } - UCLOG("\n"); + printf("\n"); } #if 0 @@ -1863,16 +1863,16 @@ void tcg_dump_ops(TCGContext *s, bool have_prefs, const char *headline) int insn_idx = 0; int op_idx = 0; - UCLOG("\n*** %s\n", headline); + printf("\n*** %s\n", headline); // tcg_dump_tbs(s, tcg_dump_tb, NULL); QTAILQ_FOREACH(op, &s->ops, link) { if (op->opc == INDEX_op_insn_start) { - UCLOG("\n insn_idx=%d", insn_idx); + printf("\n insn_idx=%d", insn_idx); insn_idx++; op_idx = 0; } else { - UCLOG(" %d: ", op_idx); + printf(" %d: ", op_idx); } op_idx++; tcg_dump_op(s, have_prefs, op); diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 02b10ea8..84bbb9f1 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -11,7 +11,6 @@ void vm_start(struct uc_struct*); void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size); -int afl_forkserver_start(struct uc_struct*); // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, @@ -107,9 +106,7 @@ static inline void uc_common_init(struct uc_struct* uc) uc->softfloat_initialize = softfloat_init; uc->tcg_flush_tlb = tcg_flush_softmmu_tlb; uc->memory_map_io = memory_map_io; -#ifdef UNICORN_HAS_AFL - uc->afl_forkserver_start = afl_forkserver_start; -#endif + if (!uc->release) uc->release = release_common; } diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 233e03c3..a1896af7 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,11 +4,6 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif -#define afl_forkserver_start afl_forkserver_start_x86_64 -#define helper_afl_maybe_log helper_afl_maybe_log_x86_64 -#define helper_afl_compcov_log_16 helper_afl_compcov_log_16_x86_64 -#define helper_afl_compcov_log_32 helper_afl_compcov_log_32_x86_64 -#define helper_afl_compcov_log_64 helper_afl_compcov_log_64_x86_64 #define use_idiv_instructions use_idiv_instructions_x86_64 #define arm_arch arm_arch_x86_64 #define tb_target_set_jmp_target tb_target_set_jmp_target_x86_64 diff --git a/symbols.sh b/symbols.sh index 0f8541b2..19997fb4 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,11 +4,6 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" -afl_forkserver_start \ -helper_afl_maybe_log \ -helper_afl_compcov_log_16 \ -helper_afl_compcov_log_32 \ -helper_afl_compcov_log_64 \ use_idiv_instructions \ arm_arch \ tb_target_set_jmp_target \ diff --git a/uc.c b/uc.c index a4f438b8..3e24674c 100644 --- a/uc.c +++ b/uc.c @@ -26,17 +26,6 @@ #include "qemu/include/qemu/queue.h" -#ifdef UNICORN_HAS_AFL -#include -#include -#include -#include -#include -#include -#include "afl/config.h" -#include "afl/types.h" -#endif - UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor) { @@ -104,14 +93,6 @@ const char *uc_strerror(uc_err code) return "Insufficient resource (UC_ERR_RESOURCE)"; case UC_ERR_EXCEPTION: return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; - case UC_ERR_AFL_RET_ERROR: - return "Something went horribly wrong in the parent (UC_ERR_AFL_RET_ERROR)"; - case UC_ERR_AFL_RET_NO_AFL: - return "No AFL, no need to fork (UC_ERR_AFL_RET_NO_AFL)"; - case UC_ERR_AFL_RET_CALLED_TWICE: - return "AFL has already been started before (UC_ERR_AFL_RET_CALLED_TWICE)"; - case UC_ERR_AFL_RET_FINISHED: - return "We forked before but now parent is gone (UC_ERR_AFL_RET_FINISHED)"; } } @@ -162,11 +143,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) return UC_ERR_NOMEM; } - if (mode & UC_MODE_AFL) { - uc->afl = true; - mode &= (~UC_MODE_AFL); - } - /* qemu/exec.c: phys_map_node_reserve() */ uc->alloc_hint = 16; uc->errnum = UC_ERR_OK; @@ -771,320 +747,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } -#ifdef UNICORN_HAS_AFL -static inline uc_afl_ret uc_afl_forkserver_start(uc_engine *uc, uint64_t *exits, size_t exit_count) -{ - /* - Why we need exits as parameter to forkserver: - In the original unicorn-afl, Unicorn needed to flush the tb cache for every iteration. - This is super slow. - Problem was, that the original forked server doesn't know about possible future exits. - The cached blocks, in the next child, therefore would have no exit set and run forever. - Also it's nice to have multiple exits, so let's just do it right. - */ - - if (!uc) { - fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_AFL_RET_ERROR; - } - if (!exits) { - fprintf(stderr, "[!] Nullptr provided for exits.\n"); - return UC_AFL_RET_ERROR; - } - if (!exit_count) { - fprintf(stderr, "[!] No exits provided (exit_count was 0).\n"); - return UC_AFL_RET_ERROR; - } - if (unlikely(uc->afl_area_ptr)) { -#if defined(AFL_DEBUG) - fprintf(stderr, "[!] forkserver_start(...) called twice. Already fuzzing!\n"); -#endif - return UC_AFL_RET_CALLED_TWICE; // AFL has already been started before. - } - - /* Copy exits to unicorn env buffer */ - uc->exits = g_realloc(uc->exits, sizeof(exits[0]) * exit_count); - if (uc->exits == NULL) { - perror("[!] malloc failed when starting forkserver."); - return UC_AFL_RET_ERROR; - } - memcpy(uc->exits, exits, sizeof(exits[0]) * exit_count); - uc->exit_count = exit_count; - // Set addr_end to make sure unicorn will not stop at addr 0x0. - uc->addr_end = uc->exits[0]; - - /* Fork() :) */ - return uc->afl_forkserver_start(uc); - -} - -/* AFL++ supports testcase forwarding via shared map. - If the env variable is set, get the shared map here. - returns true if we enabled shmap fuzzing, false otherwise. */ -static bool uc_afl_enable_shm_testcases(uc_engine *uc) { - - char *id_str = getenv(SHM_FUZZ_ENV_VAR); - if (id_str) { - int shm_id = atoi(id_str); - char *map = (char *)shmat(shm_id, NULL, 0); - if (!map || map == (void *)-1) { - perror("[!] could not access fuzzing shared memory"); - exit(1); - } - uc->afl_testcase_size_p = (u32 *)map; - uc->afl_testcase_ptr = (map + sizeof(u32)); -#if defined(AFL_DEBUG) - printf("[d] successfully opened shared memory for testcases with id %d\n", shm_id); -#endif - return true; - - } else { -#if defined(AFL_DEBUG) - printf("[d] SHM_FUZZ_ENV_VAR not set - not using shared map fuzzing.\n"); -#endif - return false; - } - -} - -/* returns the filesize in bytes, -1 or error. */ -static inline off_t uc_afl_mmap_file(char *filename, char **buf_ptr) { - - off_t ret = -1; - - int fd = open(filename, O_RDONLY); - - struct stat st = {0}; - if (fstat(fd, &st)) goto exit; - - off_t in_len = st.st_size; - - *buf_ptr = mmap(0, in_len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (*buf_ptr != MAP_FAILED) ret = in_len; - -exit: - close(fd); - return ret; - -} - -/* A start with "less features" for our afl use-case */ -/* this is largely copied from uc_emu_start, just without setting the entry point, counter and timeout. */ -int uc_afl_emu_start(uc_engine *uc) { - - uc->emu_counter = 0; - uc->invalid_error = UC_ERR_OK; - uc->emulation_done = false; - uc->stop_request = false; - - // remove count hook if counting isn't necessary - if (uc->count_hook != 0) { - uc_hook_del(uc, uc->count_hook); - uc->count_hook = 0; - } - - uc->vm_start(uc); - - // emulation is done - uc->emulation_done = true; - - return uc->invalid_error; - -} - -/* afl_next that expects you know what you're doing - Specifically, it won't check for afl_area_ptr and next to be set. */ -static inline uc_afl_ret uc_afl_next_inl(uc_engine *uc, bool crash_found) -{ - // Tell the parent we need a new testcase, then stop until testcase is available. - if (uc->afl_child_request_next(uc, crash_found) == UC_AFL_RET_ERROR) return UC_AFL_RET_ERROR; - return UC_AFL_RET_CHILD; - -} - - -/* similar to __afl_persistent loop */ -static inline uc_afl_ret uc_afl_next(uc_engine *uc, bool crash_found) -{ - - if (unlikely(!uc->afl_area_ptr)) { - fprintf(stderr, "[!] uc_afl_next(...) called before forkserver_start(...)."); - return UC_AFL_RET_ERROR; - } - - // Tell the parent we need a new testcase, then stop until testcase is available. - if (uc->afl_child_request_next) { - - return uc_afl_next_inl(uc, crash_found); - - } - - return UC_AFL_RET_NO_AFL; -} -#endif - -UNICORN_EXPORT -uc_err uc_afl_fuzz( - uc_engine *uc, - char* input_file, - uc_afl_cb_place_input_t place_input_callback, - uint64_t *exits, - size_t exit_count, - uc_afl_cb_validate_crash_t validate_crash_callback, - bool always_validate, - uint32_t persistent_iters, - void *data -){ -#ifndef UNICORN_HAS_AFL - return UC_ERR_MODE; -#else - if (!uc) { - UCLOG(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!(uc->afl)) { - return UC_ERR_MODE; - } - if (!input_file || input_file[0] == 0) { - UCLOG(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!place_input_callback) { - UCLOG(stderr, "[!] no place_input_callback set.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (always_validate && !validate_crash_callback) { - UCLOG(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); - return UC_ERR_AFL_RET_ERROR; - } - if (!exit_count) { - UCLOG(stderr, "[!] Nullptr provided for exits.\n"); - return UC_ERR_AFL_RET_ERROR; - } - - uint32_t mmap_in_len = 0; - char *in_buf = NULL; - uint32_t *in_len_p = NULL; - - bool use_shmap_input = uc_afl_enable_shm_testcases(uc); - if (use_shmap_input) { - /* For shared map fuzzing, the ptr stays the same */ - in_buf = uc->afl_testcase_ptr; - in_len_p = uc->afl_testcase_size_p; - } else { - in_len_p = &mmap_in_len; - } - - uc_afl_ret afl_ret = uc_afl_forkserver_start(uc, exits, exit_count); - switch(afl_ret) { - case UC_AFL_RET_CHILD: - break; - case UC_AFL_RET_NO_AFL: - // Not running in AFL. - persistent_iters = 1; - break; - case UC_AFL_RET_FINISHED: - // Nothing more to do - return UC_ERR_AFL_RET_FINISHED; - case UC_AFL_RET_ERROR: - return UC_ERR_AFL_RET_ERROR; - case UC_AFL_RET_CALLED_TWICE: - // Nothing more we can do - return UC_ERR_AFL_RET_CALLED_TWICE; - default: - // What have we done - UCLOG(stderr, "[!] Unexpected forkserver return: %d", afl_ret); - return UC_ERR_AFL_RET_ERROR; - } - - bool first_round = true; - bool crash_found = false; - -#if defined(AFL_DEBUG) - if (uc->afl_testcase_ptr) { - UCLOG("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); - } -#endif - - // 0 means never stop child in persistence mode. - uint32_t i; - for (i = 0; persistent_iters == 0 || i < persistent_iters; i++) { - - // The main fuzz loop starts here :) - if (first_round) { - first_round = false; - } else { - if (uc_afl_next_inl(uc, crash_found) == UC_AFL_RET_ERROR) { - /* parent is probably gone */ - exit(1); - } - crash_found = false; - } - - /* get input, call place input callback, emulate, unmap input (if needed) */ - if (unlikely(!use_shmap_input)) { - /* in_buf and the len are not in a shared map (as it would be for sharedmem fuzzing - No shmap fuzzing involved - Let's read a "normal" file. */ - off_t in_len = uc_afl_mmap_file(input_file, &in_buf); - if (unlikely(in_len < 0)) { - UCLOG(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); - perror("mmap"); - fflush(stderr); - return UC_AFL_RET_ERROR; - } - mmap_in_len = in_len; - } - bool input_accepted = place_input_callback(uc, in_buf, *in_len_p, i, data); - - if (unlikely(!input_accepted)) { - // Apparently the input was not to the users' liking. Let's continue. - goto next_iter; - } - - uc_err uc_emu_ret = uc_afl_emu_start(uc); - - if (unlikely((uc_emu_ret != UC_ERR_OK) || (always_validate && validate_crash_callback))) { - - if (validate_crash_callback != NULL && validate_crash_callback( - uc, uc_emu_ret, in_buf, *in_len_p, i, data) != true) { - // The callback thinks this is not a valid crash. Ignore. - goto next_iter; - } - if (persistent_iters != 1) { - // We're inpersistent mode and can report the crash via afl_next. No reason to die. - crash_found = true; - goto next_iter; - } - - UCLOG(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); - fflush(stderr); - - abort(); - - } -next_iter: - if (!use_shmap_input) munmap(in_buf, mmap_in_len); - } - // UC_AFL_RET_CHILD -> We looped through all iters. - // We are still in the child, nothing good will come after this. - // Exit and let the next generation run. - if (likely(afl_ret == UC_AFL_RET_CHILD)) { - exit(0); - } - - if (uc->afl_area_ptr) { - // Nothing should ever come after this but clean it up still. - // shmdt(uc->afl_area_ptr); - uc->afl_area_ptr = NULL; - uc->afl_testcase_ptr = NULL; - - } - - // UC_AFL_RET_NO_AFL -> Not fuzzing. We ran once. - return UC_AFL_RET_NO_AFL; -#endif -} UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) From 9131856506c575d6e6c7d634526079cfa769b434 Mon Sep 17 00:00:00 2001 From: lazymio Date: Tue, 26 Oct 2021 11:32:57 +0200 Subject: [PATCH 17/40] More tests --- tests/unit/test_mem.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index c8c54077..008ec146 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -4,7 +4,16 @@ static void test_map_correct() { uc_engine* uc; OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc)); - OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); + OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000] + OK(uc_mem_map (uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000] + OK(uc_mem_map (uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000] + uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL)); + OK(uc_mem_map(uc, 0x35000, 0x5000, UC_PROT_ALL)); + OK(uc_mem_map(uc, 0x50000, 0x5000, UC_PROT_ALL)); OK(uc_close(uc)); } From 9e1443013bdcb4c72d4481929ff2534bcad78c75 Mon Sep 17 00:00:00 2001 From: lazymio Date: Tue, 26 Oct 2021 13:10:59 +0200 Subject: [PATCH 18/40] Fix gen_const --- bindings/Makefile | 6 +++--- bindings/go/Makefile | 2 +- bindings/java/Makefile | 2 +- bindings/python/Makefile | 12 ++++++------ bindings/ruby/Makefile | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bindings/Makefile b/bindings/Makefile index 296b44f3..bc5fb243 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -24,8 +24,8 @@ build: $(MAKE) -C go gen_const $(MAKE) -C java gen_const $(MAKE) -C ruby gen_const - python const_generator.py dotnet - python const_generator.py pascal + python3 const_generator.py dotnet + python3 const_generator.py pascal install: build $(MAKE) -C python install @@ -40,7 +40,7 @@ python: %.c.txt: c $(ENV_VARS) ../samples/$(@:%.c.txt=%) > $@ %.py.txt: python - $(ENV_VARS) python python/$(@:%.txt=%) > $@ + $(ENV_VARS) python3 python/$(@:%.txt=%) > $@ %.py.test: %.c.txt %.py.txt $(DIFF) -u $(@:%.py.test=%.c.txt) $(@:%.py.test=%.py.txt) diff --git a/bindings/go/Makefile b/bindings/go/Makefile index fe898ae1..f8b0d5f1 100644 --- a/bindings/go/Makefile +++ b/bindings/go/Makefile @@ -6,7 +6,7 @@ all: gen_const cd unicorn && go build gen_const: - cd .. && python const_generator.py go + cd .. && python3 const_generator.py go test: all cd unicorn && LD_LIBRARY_PATH=../../../ DYLD_LIBRARY_PATH=../../../ go test diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 73d20725..313db888 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -19,7 +19,7 @@ uninstall: $(MAKE) -f Makefile.build uninstall gen_const: - cd .. && python const_generator.py java + cd .. && python3 const_generator.py java clean: rm -f unicorn/*.class diff --git a/bindings/python/Makefile b/bindings/python/Makefile index ea831fd9..363d646f 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -3,16 +3,16 @@ .PHONY: gen_const install install3 clean sdist sdist3 bdist bdist3 sdist_win bdist_win gen_const: - cd .. && python const_generator.py python + cd .. && python3 const_generator.py python install: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll if test -n "${DESTDIR}"; then \ - python setup.py install --root="${DESTDIR}"; \ + python3 setup.py install --root="${DESTDIR}"; \ else \ - python setup.py install; \ + python3 setup.py install; \ fi install3: @@ -30,7 +30,7 @@ sdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with source code of the core sdist3: @@ -44,7 +44,7 @@ bdist: rm -rf src/ dist/ rm -rf prebuilt/win64/unicorn.dll rm -rf prebuilt/win32/unicorn.dll - python setup.py bdist_wheel register upload + python3 setup.py bdist_wheel register upload # build & upload PyPi package with precompiled core bdist3: @@ -57,7 +57,7 @@ bdist3: # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand sdist_win: rm -rf src/ dist/ - python setup.py sdist register upload + python3 setup.py sdist register upload # build & upload PyPi package with prebuilt core # NOTE: be sure to have precompiled core under prebuilt/win*/ beforehand diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile index 9d52de94..aa92fa53 100644 --- a/bindings/ruby/Makefile +++ b/bindings/ruby/Makefile @@ -8,4 +8,4 @@ install: gen_const cd unicorn_gem && gem install --local pkg/unicorn-engine-1.0.1.gem gen_const: - cd .. && python const_generator.py ruby + cd .. && python3 const_generator.py ruby From e62b0ef255994591e7ea6a96577ddf8f4ad05eaa Mon Sep 17 00:00:00 2001 From: lazymio Date: Fri, 29 Oct 2021 12:44:49 +0200 Subject: [PATCH 19/40] Add clang-format and format code to qemu code style --- .clang-format | 16 + include/uc_priv.h | 186 +- include/unicorn/arm.h | 4 +- include/unicorn/arm64.h | 6 +- include/unicorn/m68k.h | 4 +- include/unicorn/mips.h | 7 +- include/unicorn/platform.h | 168 +- include/unicorn/ppc.h | 2 +- include/unicorn/riscv.h | 200 +- include/unicorn/sparc.h | 10 +- include/unicorn/unicorn.h | 344 +-- include/unicorn/x86.h | 289 ++- qemu/target/arm/unicorn.h | 44 +- qemu/target/i386/unicorn.c | 2602 +++++++++++----------- qemu/target/i386/unicorn.h | 14 +- qemu/target/m68k/unicorn.c | 48 +- qemu/target/m68k/unicorn.h | 14 +- qemu/target/mips/unicorn.c | 107 +- qemu/target/mips/unicorn.h | 38 +- qemu/target/ppc/unicorn.c | 86 +- qemu/target/ppc/unicorn.h | 22 +- qemu/target/riscv/unicorn.c | 360 +-- qemu/target/riscv/unicorn.h | 22 +- qemu/target/sparc/unicorn.c | 56 +- qemu/target/sparc/unicorn.h | 22 +- samples/mem_apis.c | 179 +- samples/sample_arm.c | 100 +- samples/sample_arm64.c | 71 +- samples/sample_batch_reg.c | 33 +- samples/sample_m68k.c | 56 +- samples/sample_mips.c | 32 +- samples/sample_ppc.c | 30 +- samples/sample_riscv.c | 72 +- samples/sample_sparc.c | 30 +- samples/sample_x86.c | 429 ++-- samples/sample_x86_32_gdt_and_seg_regs.c | 184 +- samples/shellcode.c | 90 +- tests/unit/acutest.h | 1369 ++++++------ tests/unit/test_arm.c | 118 +- tests/unit/test_arm64.c | 67 +- tests/unit/test_m68k.c | 4 +- tests/unit/test_mem.c | 46 +- tests/unit/test_mips.c | 71 +- tests/unit/test_ppc.c | 17 +- tests/unit/test_riscv.c | 269 +-- tests/unit/test_sparc.c | 4 +- tests/unit/test_x86.c | 342 +-- tests/unit/unicorn_test.h | 16 +- uc.c | 857 +++---- 49 files changed, 4967 insertions(+), 4190 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..04e13156 --- /dev/null +++ b/.clang-format @@ -0,0 +1,16 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +UseTab: Never +BreakBeforeBraces: Linux +AllowShortIfStatementsOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortFunctionsOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +IndentCaseLabels: false +ColumnLimit: 80 +SortIncludes: false +AllowShortLambdasOnASingleLine: Inline +AlwaysBreakBeforeMultilineStrings: false +BreakStringLiterals: true +PointerAlignment: Right diff --git a/include/uc_priv.h b/include/uc_priv.h index 8c564396..bcdf9059 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -2,7 +2,6 @@ /* By Nguyen Anh Quynh , 2015 */ /* Modified for Unicorn Engine by Chen Huitao, 2020 */ - #ifndef UC_PRIV_H #define UC_PRIV_H @@ -15,16 +14,22 @@ // 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|UC_MODE_MCLASS \ - |UC_MODE_ARM926|UC_MODE_ARM946|UC_MODE_ARM1176|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_PPC32|UC_MODE_PPC64|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 UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) +#define UC_MODE_ARM_MASK \ + (UC_MODE_ARM | UC_MODE_THUMB | UC_MODE_LITTLE_ENDIAN | UC_MODE_MCLASS | \ + UC_MODE_ARM926 | UC_MODE_ARM946 | UC_MODE_ARM1176 | 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_PPC32 | UC_MODE_PPC64 | 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 UC_MODE_RISCV_MASK \ + (UC_MODE_RISCV32 | UC_MODE_RISCV64 | UC_MODE_LITTLE_ENDIAN) -#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define ARR_SIZE(a) (sizeof(a) / sizeof(a[0])) #define READ_QWORD(x) ((uint64_t)x) #define READ_DWORD(x) (x & 0xffffffff) @@ -36,15 +41,19 @@ #define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8)) #define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff)) - -typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result); +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 *regs, void **vals, int count); -typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +typedef int (*reg_read_t)(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +typedef int (*reg_write_t)(struct uc_struct *uc, unsigned int *regs, + void *const *vals, int count); -typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +typedef int (*context_reg_read_t)(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +typedef int (*context_reg_write_t)(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); typedef struct { context_reg_read_t context_reg_read; context_reg_write_t context_reg_write; @@ -52,30 +61,40 @@ typedef struct { typedef void (*reg_reset_t)(struct uc_struct *uc); -typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, const uint8_t *buf, int len); +typedef bool (*uc_write_mem_t)(AddressSpace *as, hwaddr addr, + const uint8_t *buf, int len); -typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, int len); +typedef bool (*uc_read_mem_t)(AddressSpace *as, hwaddr addr, uint8_t *buf, + int len); -typedef void (*uc_args_void_t)(void*); +typedef void (*uc_args_void_t)(void *); -typedef void (*uc_args_uc_t)(struct uc_struct*); -typedef void (*uc_args_int_uc_t)(struct uc_struct*); +typedef void (*uc_args_uc_t)(struct uc_struct *); +typedef void (*uc_args_int_uc_t)(struct uc_struct *); -typedef void (*uc_args_uc_long_t)(struct uc_struct*, unsigned long); +typedef void (*uc_args_uc_long_t)(struct uc_struct *, unsigned long); typedef void (*uc_args_uc_u64_t)(struct uc_struct *, uint64_t addr); -typedef MemoryRegion* (*uc_args_uc_ram_size_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms); +typedef MemoryRegion *(*uc_args_uc_ram_size_t)(struct uc_struct *, hwaddr begin, + size_t size, uint32_t perms); -typedef MemoryRegion* (*uc_args_uc_ram_size_ptr_t)(struct uc_struct*, hwaddr begin, size_t size, uint32_t perms, void *ptr); +typedef MemoryRegion *(*uc_args_uc_ram_size_ptr_t)(struct uc_struct *, + hwaddr begin, size_t size, + uint32_t perms, void *ptr); -typedef void (*uc_mem_unmap_t)(struct uc_struct*, MemoryRegion *mr); +typedef void (*uc_mem_unmap_t)(struct uc_struct *, MemoryRegion *mr); typedef void (*uc_readonly_mem_t)(MemoryRegion *mr, bool readonly); typedef int (*uc_cpus_init)(struct uc_struct *, const char *); -typedef MemoryRegion* (*uc_memory_map_io_t)(struct uc_struct *uc, ram_addr_t begin, size_t size, uc_cb_mmio_read_t read_cb, uc_cb_mmio_write_t write_cb, void *user_data_read, void *user_data_write); +typedef MemoryRegion *(*uc_memory_map_io_t)(struct uc_struct *uc, + ram_addr_t begin, size_t size, + uc_cb_mmio_read_t read_cb, + uc_cb_mmio_write_t write_cb, + void *user_data_read, + void *user_data_write); // which interrupt should make emulation stop? typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno); @@ -84,7 +103,7 @@ typedef bool (*uc_args_int_t)(struct uc_struct *uc, int intno); typedef uint64_t (*uc_mem_redirect_t)(uint64_t address); // validate if Unicorn supports hooking a given instruction -typedef bool(*uc_insn_hook_validate)(uint32_t insn_enum); +typedef bool (*uc_insn_hook_validate)(uint32_t insn_enum); // init target page typedef void (*uc_target_page_init)(struct uc_struct *); @@ -96,11 +115,13 @@ typedef void (*uc_softfloat_initialize)(void); typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); struct hook { - int type; // UC_HOOK_* - int insn; // instruction for HOOK_INSN - int refs; // reference count to free hook stored in multiple lists - bool to_delete; // set to true when the hook is deleted by the user. The destruction of the hook is delayed. - uint64_t begin, end; // only trigger if PC or memory access is in this address (depends on hook type) + int type; // UC_HOOK_* + int insn; // instruction for HOOK_INSN + int refs; // reference count to free hook stored in multiple lists + bool to_delete; // set to true when the hook is deleted by the user. The + // destruction of the hook is delayed. + 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; }; @@ -132,31 +153,31 @@ typedef enum uc_hook_idx { } uc_hook_idx; // The lowest 6 bits are used for hook type index. -#define UC_HOOK_IDX_MASK ((1<<6)-1) +#define UC_HOOK_IDX_MASK ((1 << 6) - 1) // hook flags -#define UC_HOOK_FLAG_NO_STOP (1 << 6) // Don't stop emulation in this uc_tracecode. +#define UC_HOOK_FLAG_NO_STOP \ + (1 << 6) // Don't stop emulation in this uc_tracecode. // The rest of bits are reserved for hook flags. #define UC_HOOK_FLAG_MASK (~(UC_HOOK_IDX_MASK)) -#define HOOK_FOREACH_VAR_DECLARE \ - struct list_item *cur +#define HOOK_FOREACH_VAR_DECLARE struct list_item *cur // for loop macro to loop over hook lists -#define HOOK_FOREACH(uc, hh, idx) \ - for ( \ - cur = (uc)->hook[idx##_IDX].head; \ - cur != NULL && ((hh) = (struct hook *)cur->data); \ - cur = cur->next) +#define HOOK_FOREACH(uc, hh, idx) \ + for (cur = (uc)->hook[idx##_IDX].head; \ + cur != NULL && ((hh) = (struct hook *)cur->data); 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) && !((hh)->to_delete)) +#define HOOK_BOUND_CHECK(hh, addr) \ + ((((addr) >= (hh)->begin && (addr) <= (hh)->end) || \ + (hh)->begin > (hh)->end) && \ + !((hh)->to_delete)) #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) +#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) { @@ -168,7 +189,7 @@ static inline bool _hook_exists_bounded(struct list_item *cur, uint64_t addr) return false; } -//relloc increment, KEEP THIS A POWER OF 2! +// relloc increment, KEEP THIS A POWER OF 2! #define MEM_BLOCK_INCR 32 typedef struct TargetPageBits TargetPageBits; @@ -177,7 +198,7 @@ typedef struct TCGContext TCGContext; struct uc_struct { uc_arch arch; uc_mode mode; - uc_err errnum; // qemu/cpu-exec.c + uc_err errnum; // qemu/cpu-exec.c AddressSpace address_space_memory; AddressSpace address_space_io; query_t query; @@ -187,9 +208,10 @@ struct uc_struct { uc_write_mem_t write_mem; uc_read_mem_t read_mem; - uc_args_void_t release; // release resource when uc_close() - uc_args_uc_u64_t set_pc; // set PC for tracecode - uc_args_int_t stop_interrupt; // check if the interrupt should stop emulation + uc_args_void_t release; // release resource when uc_close() + uc_args_uc_u64_t set_pc; // set PC for tracecode + uc_args_int_t + stop_interrupt; // check if the interrupt should stop emulation uc_memory_map_io_t memory_map_io; uc_args_uc_t init_arch, cpu_exec_init_all; @@ -212,21 +234,21 @@ struct uc_struct { uc_insn_hook_validate insn_hook_validate; MemoryRegion *system_memory; // qemu/exec.c - MemoryRegion *system_io; // qemu/exec.c + MemoryRegion *system_io; // qemu/exec.c MemoryRegion io_mem_unassigned; // qemu/exec.c - RAMList ram_list; // qemu/exec.c + RAMList ram_list; // qemu/exec.c /* qemu/exec.c */ unsigned int alloc_hint; /* qemu/exec-vary.c */ TargetPageBits *init_target_page; - BounceBuffer bounce; // qemu/cpu-exec.c + BounceBuffer bounce; // qemu/cpu-exec.c volatile sig_atomic_t exit_request; // qemu/cpu-exec.c /* qemu/accel/tcg/cpu-exec-common.c */ /* always be true after call tcg_exec_init(). */ bool tcg_allowed; /* This is a multi-level map on the virtual address space. The bottom level has pointers to PageDesc. */ - void **l1_map; // qemu/accel/tcg/translate-all.c + void **l1_map; // qemu/accel/tcg/translate-all.c size_t l1_map_size; /* qemu/accel/tcg/translate-all.c */ int v_l1_size; @@ -248,28 +270,33 @@ struct uc_struct { uc_hook count_hook; size_t emu_counter; // current counter of uc_emu_start() - size_t emu_count; // save counter of uc_emu_start() + size_t emu_count; // save counter of uc_emu_start() int size_recur_mem; // size for mem access when in a recursive call - 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() - bool timed_out; // emulation timed out, that can retrieve via uc_query(UC_QUERY_TIMEOUT) - QemuThread timer; // timer for emulation timeout - uint64_t timeout; // timeout for uc_emu_start() + 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() + bool timed_out; // emulation timed out, that can retrieve via + // uc_query(UC_QUERY_TIMEOUT) + QemuThread timer; // timer for emulation timeout + uint64_t timeout; // timeout for uc_emu_start() - uint64_t invalid_addr; // invalid address to be accessed - int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE + uint64_t invalid_addr; // invalid address to be accessed + int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE - uint64_t addr_end; // address where emulation stops (@end param of uc_emu_start()) + uint64_t addr_end; // address where emulation stops (@end param of + // uc_emu_start()) - int thumb; // thumb mode for ARM + int thumb; // thumb mode for ARM MemoryRegion **mapped_blocks; uint32_t mapped_block_count; uint32_t mapped_block_cache_index; - void *qemu_thread_data; // to support cross compile to Windows (qemu-thread-win32.c) + void *qemu_thread_data; // to support cross compile to Windows + // (qemu-thread-win32.c) uint32_t target_page_size; uint32_t target_page_align; uint64_t qemu_host_page_size; @@ -277,26 +304,29 @@ struct uc_struct { int qemu_icache_linesize; /* ARCH_REGS_STORAGE_SIZE */ int cpu_context_size; - uint64_t next_pc; // save next PC for some special cases - bool hook_insert; // insert new hook at begin of the hook list (append by default) - bool first_tb; // is this the first Translation-Block ever generated since uc_emu_start()? + uint64_t next_pc; // save next PC for some special cases + bool hook_insert; // insert new hook at begin of the hook list (append by + // default) + bool first_tb; // is this the first Translation-Block ever generated since + // uc_emu_start()? struct list saved_contexts; // The contexts saved by this uc_struct. - bool no_exit_request; // Disable check_exit_request temporarily. A workaround to treat the IT block as a whole block. + bool no_exit_request; // Disable check_exit_request temporarily. A + // workaround to treat the IT block as a whole block. }; // Metadata stub for the variable-size cpu context used with uc_context_*() // We also save cpu->jmp_env, so emulation can be reentrant struct uc_context { - size_t context_size; // size of the real internal context structure - size_t jmp_env_size; // size of cpu->jmp_env - uc_mode mode; // the mode of this context (uc may be free-ed already) - uc_arch arch; // the arch of this context (uc may be free-ed already) - struct uc_struct *uc; // the uc_struct which creates this context - char data[0]; // context + cpu->jmp_env + size_t context_size; // size of the real internal context structure + size_t jmp_env_size; // size of cpu->jmp_env + uc_mode mode; // the mode of this context (uc may be free-ed already) + uc_arch arch; // the arch of this context (uc may be free-ed already) + struct uc_struct *uc; // the uc_struct which creates this context + char data[0]; // context + cpu->jmp_env }; // check if this address is mapped in (via uc_mem_map()) -MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address); +MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address); #endif /* vim: set ts=4 noet: */ diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 9ce7b0b3..5bd72d63 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> ARM registers @@ -158,7 +158,7 @@ typedef enum uc_arm_reg { UC_ARM_REG_XPSR_NZCVQ, UC_ARM_REG_XPSR_G, UC_ARM_REG_XPSR_NZCVQG, - UC_ARM_REG_ENDING, // <-- mark the end of the list or registers + UC_ARM_REG_ENDING, // <-- mark the end of the list or registers //> alias registers UC_ARM_REG_R13 = UC_ARM_REG_SP, diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index 0f66518d..256b2a50 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> ARM64 registers @@ -281,7 +281,7 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_V31, //> pseudo registers - UC_ARM64_REG_PC, // program counter register + UC_ARM64_REG_PC, // program counter register UC_ARM64_REG_CPACR_EL1, @@ -327,7 +327,7 @@ typedef enum uc_arm64_reg { UC_ARM64_REG_VBAR_EL2, UC_ARM64_REG_VBAR_EL3, - UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers + UC_ARM64_REG_ENDING, // <-- mark the end of the list of registers //> alias registers diff --git a/include/unicorn/m68k.h b/include/unicorn/m68k.h index 80e8b920..01cb0af1 100644 --- a/include/unicorn/m68k.h +++ b/include/unicorn/m68k.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> M68K registers @@ -40,7 +40,7 @@ typedef enum uc_m68k_reg { UC_M68K_REG_SR, UC_M68K_REG_PC, - UC_M68K_REG_ENDING, // <-- mark the end of the list of registers + UC_M68K_REG_ENDING, // <-- mark the end of the list of registers } uc_m68k_reg; #ifdef __cplusplus diff --git a/include/unicorn/mips.h b/include/unicorn/mips.h index df54893f..b8d203f9 100644 --- a/include/unicorn/mips.h +++ b/include/unicorn/mips.h @@ -16,7 +16,7 @@ extern "C" { #undef mips #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> MIPS registers @@ -179,7 +179,7 @@ typedef enum UC_MIPS_REG { UC_MIPS_REG_CP0_USERLOCAL, UC_MIPS_REG_CP0_STATUS, - UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers + UC_MIPS_REG_ENDING, // <-- mark the end of the list or registers // alias registers UC_MIPS_REG_ZERO = UC_MIPS_REG_0, @@ -212,7 +212,8 @@ typedef enum UC_MIPS_REG { UC_MIPS_REG_K1 = UC_MIPS_REG_27, UC_MIPS_REG_GP = UC_MIPS_REG_28, UC_MIPS_REG_SP = UC_MIPS_REG_29, - UC_MIPS_REG_FP = UC_MIPS_REG_30, UC_MIPS_REG_S8 = UC_MIPS_REG_30, + UC_MIPS_REG_FP = UC_MIPS_REG_30, + UC_MIPS_REG_S8 = UC_MIPS_REG_30, UC_MIPS_REG_RA = UC_MIPS_REG_31, UC_MIPS_REG_HI0 = UC_MIPS_REG_AC0, diff --git a/include/unicorn/platform.h b/include/unicorn/platform.h index 1d5dc314..385d1e03 100644 --- a/include/unicorn/platform.h +++ b/include/unicorn/platform.h @@ -22,16 +22,17 @@ MSVC++ 7.0 _MSC_VER == 1300 MSVC++ 6.0 _MSC_VER == 1200 MSVC++ 5.0 _MSC_VER == 1100 */ -#define MSC_VER_VS2003 1310 -#define MSC_VER_VS2005 1400 -#define MSC_VER_VS2008 1500 -#define MSC_VER_VS2010 1600 -#define MSC_VER_VS2012 1700 -#define MSC_VER_VS2013 1800 -#define MSC_VER_VS2015 1900 +#define MSC_VER_VS2003 1310 +#define MSC_VER_VS2005 1400 +#define MSC_VER_VS2008 1500 +#define MSC_VER_VS2010 1600 +#define MSC_VER_VS2012 1700 +#define MSC_VER_VS2013 1800 +#define MSC_VER_VS2015 1900 // handle stdbool.h compatibility -#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)) +#if !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && \ + (defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)) // MSVC // stdbool.h @@ -41,62 +42,65 @@ MSVC++ 5.0 _MSC_VER == 1100 typedef unsigned char bool; #define false 0 #define true 1 -#endif // __cplusplus +#endif // __cplusplus #else // VisualStudio 2013+ -> C99 is supported #include -#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) +#endif // (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) #else // not MSVC -> C99 is supported #include -#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)) +#endif // !defined(__CYGWIN__) && !defined(__MINGW32__) && !defined(__MINGW64__) + // && (defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined + // (_WIN64)) #if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE) // this system does not have stdint.h -typedef signed char int8_t; +typedef signed char int8_t; typedef signed short int16_t; -typedef signed int int32_t; -typedef unsigned char uint8_t; +typedef signed int int32_t; +typedef unsigned char uint8_t; typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef signed long long int64_t; +typedef unsigned int uint32_t; +typedef signed long long int64_t; typedef unsigned long long uint64_t; #ifndef _INTPTR_T_DEFINED - #define _INTPTR_T_DEFINED - #ifdef _WIN64 -typedef long long intptr_t; - #else /* _WIN64 */ -typedef _W64 int intptr_t; - #endif /* _WIN64 */ +#define _INTPTR_T_DEFINED +#ifdef _WIN64 +typedef long long intptr_t; +#else /* _WIN64 */ +typedef _W64 int intptr_t; +#endif /* _WIN64 */ #endif /* _INTPTR_T_DEFINED */ #ifndef _UINTPTR_T_DEFINED - #define _UINTPTR_T_DEFINED - #ifdef _WIN64 +#define _UINTPTR_T_DEFINED +#ifdef _WIN64 typedef unsigned long long uintptr_t; - #else /* _WIN64 */ -typedef _W64 unsigned int uintptr_t; - #endif /* _WIN64 */ +#else /* _WIN64 */ +typedef _W64 unsigned int uintptr_t; +#endif /* _WIN64 */ #endif /* _UINTPTR_T_DEFINED */ -#define INT8_MIN (-127i8 - 1) -#define INT16_MIN (-32767i16 - 1) -#define INT32_MIN (-2147483647i32 - 1) -#define INT64_MIN (-9223372036854775807i64 - 1) -#define INT8_MAX 127i8 -#define INT16_MAX 32767i16 -#define INT32_MAX 2147483647i32 -#define INT64_MAX 9223372036854775807i64 -#define UINT8_MAX 0xffui8 -#define UINT16_MAX 0xffffui16 -#define UINT32_MAX 0xffffffffui32 -#define UINT64_MAX 0xffffffffffffffffui64 +#define INT8_MIN (-127i8 - 1) +#define INT16_MIN (-32767i16 - 1) +#define INT32_MIN (-2147483647i32 - 1) +#define INT64_MIN (-9223372036854775807i64 - 1) +#define INT8_MAX 127i8 +#define INT16_MAX 32767i16 +#define INT32_MAX 2147483647i32 +#define INT64_MAX 9223372036854775807i64 +#define UINT8_MAX 0xffui8 +#define UINT16_MAX 0xffffui16 +#define UINT32_MAX 0xffffffffui32 +#define UINT64_MAX 0xffffffffffffffffui64 #else // this system has stdint.h #include -#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || defined(_KERNEL_MODE) +#endif // (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2010)) || + // defined(_KERNEL_MODE) // handle inttypes.h compatibility #if (defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013)) || defined(_KERNEL_MODE) @@ -105,52 +109,53 @@ typedef _W64 unsigned int uintptr_t; #define __PRI_8_LENGTH_MODIFIER__ "hh" #define __PRI_64_LENGTH_MODIFIER__ "ll" -#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d" -#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i" -#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o" -#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u" -#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x" -#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X" +#define PRId8 __PRI_8_LENGTH_MODIFIER__ "d" +#define PRIi8 __PRI_8_LENGTH_MODIFIER__ "i" +#define PRIo8 __PRI_8_LENGTH_MODIFIER__ "o" +#define PRIu8 __PRI_8_LENGTH_MODIFIER__ "u" +#define PRIx8 __PRI_8_LENGTH_MODIFIER__ "x" +#define PRIX8 __PRI_8_LENGTH_MODIFIER__ "X" -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" #if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) -#define PRId32 "ld" -#define PRIi32 "li" -#define PRIo32 "lo" -#define PRIu32 "lu" -#define PRIx32 "lx" -#define PRIX32 "lX" -#else // OSX -#define PRId32 "d" -#define PRIi32 "i" -#define PRIo32 "o" -#define PRIu32 "u" -#define PRIx32 "x" -#define PRIX32 "X" -#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) +#define PRId32 "ld" +#define PRIi32 "li" +#define PRIo32 "lo" +#define PRIu32 "lu" +#define PRIx32 "lx" +#define PRIX32 "lX" +#else // OSX +#define PRId32 "d" +#define PRIi32 "i" +#define PRIo32 "o" +#define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#endif // defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) #if defined(_MSC_VER) && (_MSC_VER <= MSC_VER_VS2012) // redefine functions from inttypes.h used in cstool #define strtoull _strtoui64 #endif -#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d" -#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i" -#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o" -#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u" -#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x" -#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X" +#define PRId64 __PRI_64_LENGTH_MODIFIER__ "d" +#define PRIi64 __PRI_64_LENGTH_MODIFIER__ "i" +#define PRIo64 __PRI_64_LENGTH_MODIFIER__ "o" +#define PRIu64 __PRI_64_LENGTH_MODIFIER__ "u" +#define PRIx64 __PRI_64_LENGTH_MODIFIER__ "x" +#define PRIX64 __PRI_64_LENGTH_MODIFIER__ "X" #else // this system has inttypes.h by default #include -#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) || defined(_KERNEL_MODE) +#endif // #if defined(_MSC_VER) && (_MSC_VER < MSC_VER_VS2013) || + // defined(_KERNEL_MODE) // sys/time.h compatibility #if defined(_MSC_VER) @@ -174,7 +179,7 @@ static int usleep(uint32_t usec) if (!timer) return -1; - due.QuadPart = (-((int64_t) usec)) * 10LL; + due.QuadPart = (-((int64_t)usec)) * 10LL; if (!SetWaitableTimer(timer, &due, 0, NULL, NULL, 0)) { CloseHandle(timer); return -1; @@ -191,23 +196,22 @@ static int usleep(uint32_t usec) // misc support #if defined(_MSC_VER) -#ifdef _WIN64 -typedef signed __int64 ssize_t; +#ifdef _WIN64 +typedef signed __int64 ssize_t; #else -typedef _W64 signed int ssize_t; +typedef _W64 signed int ssize_t; #endif #ifndef va_copy -#define va_copy(d,s) ((d) = (s)) +#define va_copy(d, s) ((d) = (s)) #endif -#define strcasecmp _stricmp +#define strcasecmp _stricmp #if (_MSC_VER < MSC_VER_VS2015) -#define snprintf _snprintf +#define snprintf _snprintf #endif #if (_MSC_VER <= MSC_VER_VS2013) -#define strtoll _strtoi64 +#define strtoll _strtoi64 #endif #endif - #endif // UNICORN_PLATFORM_H diff --git a/include/unicorn/ppc.h b/include/unicorn/ppc.h index 9fded44c..a6181834 100644 --- a/include/unicorn/ppc.h +++ b/include/unicorn/ppc.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> PPC registers diff --git a/include/unicorn/riscv.h b/include/unicorn/riscv.h index 42a26627..a058ebab 100644 --- a/include/unicorn/riscv.h +++ b/include/unicorn/riscv.h @@ -12,7 +12,7 @@ extern "C" { #endif #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> RISCV registers @@ -53,111 +53,111 @@ typedef enum uc_riscv_reg { UC_RISCV_REG_X31, //> Floating-point registers - UC_RISCV_REG_F0, // "ft0" - UC_RISCV_REG_F1, // "ft1" - UC_RISCV_REG_F2, // "ft2" - UC_RISCV_REG_F3, // "ft3" - UC_RISCV_REG_F4, // "ft4" - UC_RISCV_REG_F5, // "ft5" - UC_RISCV_REG_F6, // "ft6" - UC_RISCV_REG_F7, // "ft7" - UC_RISCV_REG_F8, // "fs0" - UC_RISCV_REG_F9, // "fs1" - UC_RISCV_REG_F10, // "fa0" - UC_RISCV_REG_F11, // "fa1" - UC_RISCV_REG_F12, // "fa2" - UC_RISCV_REG_F13, // "fa3" - UC_RISCV_REG_F14, // "fa4" - UC_RISCV_REG_F15, // "fa5" - UC_RISCV_REG_F16, // "fa6" - UC_RISCV_REG_F17, // "fa7" - UC_RISCV_REG_F18, // "fs2" - UC_RISCV_REG_F19, // "fs3" - UC_RISCV_REG_F20, // "fs4" - UC_RISCV_REG_F21, // "fs5" - UC_RISCV_REG_F22, // "fs6" - UC_RISCV_REG_F23, // "fs7" - UC_RISCV_REG_F24, // "fs8" - UC_RISCV_REG_F25, // "fs9" - UC_RISCV_REG_F26, // "fs10" - UC_RISCV_REG_F27, // "fs11" - UC_RISCV_REG_F28, // "ft8" - UC_RISCV_REG_F29, // "ft9" - UC_RISCV_REG_F30, // "ft10" - UC_RISCV_REG_F31, // "ft11" + UC_RISCV_REG_F0, // "ft0" + UC_RISCV_REG_F1, // "ft1" + UC_RISCV_REG_F2, // "ft2" + UC_RISCV_REG_F3, // "ft3" + UC_RISCV_REG_F4, // "ft4" + UC_RISCV_REG_F5, // "ft5" + UC_RISCV_REG_F6, // "ft6" + UC_RISCV_REG_F7, // "ft7" + UC_RISCV_REG_F8, // "fs0" + UC_RISCV_REG_F9, // "fs1" + UC_RISCV_REG_F10, // "fa0" + UC_RISCV_REG_F11, // "fa1" + UC_RISCV_REG_F12, // "fa2" + UC_RISCV_REG_F13, // "fa3" + UC_RISCV_REG_F14, // "fa4" + UC_RISCV_REG_F15, // "fa5" + UC_RISCV_REG_F16, // "fa6" + UC_RISCV_REG_F17, // "fa7" + UC_RISCV_REG_F18, // "fs2" + UC_RISCV_REG_F19, // "fs3" + UC_RISCV_REG_F20, // "fs4" + UC_RISCV_REG_F21, // "fs5" + UC_RISCV_REG_F22, // "fs6" + UC_RISCV_REG_F23, // "fs7" + UC_RISCV_REG_F24, // "fs8" + UC_RISCV_REG_F25, // "fs9" + UC_RISCV_REG_F26, // "fs10" + UC_RISCV_REG_F27, // "fs11" + UC_RISCV_REG_F28, // "ft8" + UC_RISCV_REG_F29, // "ft9" + UC_RISCV_REG_F30, // "ft10" + UC_RISCV_REG_F31, // "ft11" - UC_RISCV_REG_PC, // PC register + UC_RISCV_REG_PC, // PC register - UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers + UC_RISCV_REG_ENDING, // <-- mark the end of the list or registers //> Alias registers - UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero" - UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra" - UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp" - UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp" - UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp" - UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0" - UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1" - UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2" - UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0" - UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp" - UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1" - UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0" - UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1" - UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2" - UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3" - UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4" - UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5" - UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6" - UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7" - UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2" - UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3" - UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4" - UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5" - UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6" - UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7" - UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8" - UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9" - UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10" - UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11" - UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3" - UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4" - UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5" - UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6" + UC_RISCV_REG_ZERO = UC_RISCV_REG_X0, // "zero" + UC_RISCV_REG_RA = UC_RISCV_REG_X1, // "ra" + UC_RISCV_REG_SP = UC_RISCV_REG_X2, // "sp" + UC_RISCV_REG_GP = UC_RISCV_REG_X3, // "gp" + UC_RISCV_REG_TP = UC_RISCV_REG_X4, // "tp" + UC_RISCV_REG_T0 = UC_RISCV_REG_X5, // "t0" + UC_RISCV_REG_T1 = UC_RISCV_REG_X6, // "t1" + UC_RISCV_REG_T2 = UC_RISCV_REG_X7, // "t2" + UC_RISCV_REG_S0 = UC_RISCV_REG_X8, // "s0" + UC_RISCV_REG_FP = UC_RISCV_REG_X8, // "fp" + UC_RISCV_REG_S1 = UC_RISCV_REG_X9, // "s1" + UC_RISCV_REG_A0 = UC_RISCV_REG_X10, // "a0" + UC_RISCV_REG_A1 = UC_RISCV_REG_X11, // "a1" + UC_RISCV_REG_A2 = UC_RISCV_REG_X12, // "a2" + UC_RISCV_REG_A3 = UC_RISCV_REG_X13, // "a3" + UC_RISCV_REG_A4 = UC_RISCV_REG_X14, // "a4" + UC_RISCV_REG_A5 = UC_RISCV_REG_X15, // "a5" + UC_RISCV_REG_A6 = UC_RISCV_REG_X16, // "a6" + UC_RISCV_REG_A7 = UC_RISCV_REG_X17, // "a7" + UC_RISCV_REG_S2 = UC_RISCV_REG_X18, // "s2" + UC_RISCV_REG_S3 = UC_RISCV_REG_X19, // "s3" + UC_RISCV_REG_S4 = UC_RISCV_REG_X20, // "s4" + UC_RISCV_REG_S5 = UC_RISCV_REG_X21, // "s5" + UC_RISCV_REG_S6 = UC_RISCV_REG_X22, // "s6" + UC_RISCV_REG_S7 = UC_RISCV_REG_X23, // "s7" + UC_RISCV_REG_S8 = UC_RISCV_REG_X24, // "s8" + UC_RISCV_REG_S9 = UC_RISCV_REG_X25, // "s9" + UC_RISCV_REG_S10 = UC_RISCV_REG_X26, // "s10" + UC_RISCV_REG_S11 = UC_RISCV_REG_X27, // "s11" + UC_RISCV_REG_T3 = UC_RISCV_REG_X28, // "t3" + UC_RISCV_REG_T4 = UC_RISCV_REG_X29, // "t4" + UC_RISCV_REG_T5 = UC_RISCV_REG_X30, // "t5" + UC_RISCV_REG_T6 = UC_RISCV_REG_X31, // "t6" - UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0" - UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1" - UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2" - UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3" - UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4" - UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5" - UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6" - UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7" - UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0" - UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1" + UC_RISCV_REG_FT0 = UC_RISCV_REG_F0, // "ft0" + UC_RISCV_REG_FT1 = UC_RISCV_REG_F1, // "ft1" + UC_RISCV_REG_FT2 = UC_RISCV_REG_F2, // "ft2" + UC_RISCV_REG_FT3 = UC_RISCV_REG_F3, // "ft3" + UC_RISCV_REG_FT4 = UC_RISCV_REG_F4, // "ft4" + UC_RISCV_REG_FT5 = UC_RISCV_REG_F5, // "ft5" + UC_RISCV_REG_FT6 = UC_RISCV_REG_F6, // "ft6" + UC_RISCV_REG_FT7 = UC_RISCV_REG_F7, // "ft7" + UC_RISCV_REG_FS0 = UC_RISCV_REG_F8, // "fs0" + UC_RISCV_REG_FS1 = UC_RISCV_REG_F9, // "fs1" - UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0" - UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1" - UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2" - UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3" - UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4" - UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5" - UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6" - UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7" - UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2" - UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3" - UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4" - UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5" - UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6" - UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7" - UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8" - UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9" - UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10" - UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11" - UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8" - UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9" - UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10" - UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11" + UC_RISCV_REG_FA0 = UC_RISCV_REG_F10, // "fa0" + UC_RISCV_REG_FA1 = UC_RISCV_REG_F11, // "fa1" + UC_RISCV_REG_FA2 = UC_RISCV_REG_F12, // "fa2" + UC_RISCV_REG_FA3 = UC_RISCV_REG_F13, // "fa3" + UC_RISCV_REG_FA4 = UC_RISCV_REG_F14, // "fa4" + UC_RISCV_REG_FA5 = UC_RISCV_REG_F15, // "fa5" + UC_RISCV_REG_FA6 = UC_RISCV_REG_F16, // "fa6" + UC_RISCV_REG_FA7 = UC_RISCV_REG_F17, // "fa7" + UC_RISCV_REG_FS2 = UC_RISCV_REG_F18, // "fs2" + UC_RISCV_REG_FS3 = UC_RISCV_REG_F19, // "fs3" + UC_RISCV_REG_FS4 = UC_RISCV_REG_F20, // "fs4" + UC_RISCV_REG_FS5 = UC_RISCV_REG_F21, // "fs5" + UC_RISCV_REG_FS6 = UC_RISCV_REG_F22, // "fs6" + UC_RISCV_REG_FS7 = UC_RISCV_REG_F23, // "fs7" + UC_RISCV_REG_FS8 = UC_RISCV_REG_F24, // "fs8" + UC_RISCV_REG_FS9 = UC_RISCV_REG_F25, // "fs9" + UC_RISCV_REG_FS10 = UC_RISCV_REG_F26, // "fs10" + UC_RISCV_REG_FS11 = UC_RISCV_REG_F27, // "fs11" + UC_RISCV_REG_FT8 = UC_RISCV_REG_F28, // "ft8" + UC_RISCV_REG_FT9 = UC_RISCV_REG_F29, // "ft9" + UC_RISCV_REG_FT10 = UC_RISCV_REG_F30, // "ft10" + UC_RISCV_REG_FT11 = UC_RISCV_REG_F31, // "ft11" } uc_riscv_reg; #ifdef __cplusplus diff --git a/include/unicorn/sparc.h b/include/unicorn/sparc.h index 08e05386..f9ec729d 100644 --- a/include/unicorn/sparc.h +++ b/include/unicorn/sparc.h @@ -16,7 +16,7 @@ extern "C" { #undef sparc #ifdef _MSC_VER -#pragma warning(disable:4201) +#pragma warning(disable : 4201) #endif //> SPARC registers @@ -71,7 +71,7 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_F58, UC_SPARC_REG_F60, UC_SPARC_REG_F62, - UC_SPARC_REG_FCC0, // Floating condition codes + UC_SPARC_REG_FCC0, // Floating condition codes UC_SPARC_REG_FCC1, UC_SPARC_REG_FCC2, UC_SPARC_REG_FCC3, @@ -91,7 +91,7 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_I5, UC_SPARC_REG_FP, UC_SPARC_REG_I7, - UC_SPARC_REG_ICC, // Integer condition codes + UC_SPARC_REG_ICC, // Integer condition codes UC_SPARC_REG_L0, UC_SPARC_REG_L1, UC_SPARC_REG_L2, @@ -114,9 +114,9 @@ typedef enum uc_sparc_reg { UC_SPARC_REG_XCC, // pseudo register - UC_SPARC_REG_PC, // program counter register + UC_SPARC_REG_PC, // program counter register - UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers + UC_SPARC_REG_ENDING, // <-- mark the end of the list of registers // extras UC_SPARC_REG_O6 = UC_SPARC_REG_SP, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index d7780e56..0d217bd4 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -42,11 +42,11 @@ typedef size_t uc_hook; #endif #ifdef _MSC_VER -#pragma warning(disable:4201) -#pragma warning(disable:4100) +#pragma warning(disable : 4201) +#pragma warning(disable : 4100) #ifdef UNICORN_SHARED #define UNICORN_EXPORT __declspec(dllexport) -#else // defined(UNICORN_STATIC) +#else // defined(UNICORN_STATIC) #define UNICORN_EXPORT #endif #else @@ -62,7 +62,8 @@ typedef size_t uc_hook; #elif defined(_MSC_VER) #define UNICORN_DEPRECATED __declspec(deprecated) #else -#pragma message("WARNING: You need to implement UNICORN_DEPRECATED for this compiler") +#pragma message( \ + "WARNING: You need to implement UNICORN_DEPRECATED for this compiler") #define UNICORN_DEPRECATED #endif @@ -75,7 +76,6 @@ typedef size_t uc_hook; #define UC_VERSION_MINOR UC_API_MINOR #define UC_VERSION_EXTRA 0 - /* Macro to create combined version which can be compared to result of uc_version() API. @@ -90,14 +90,14 @@ typedef size_t uc_hook; // Architecture type typedef enum uc_arch { - UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) - 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_SPARC, // Sparc architecture - UC_ARCH_M68K, // M68K architecture - UC_ARCH_RISCV, // RISCV architecture + UC_ARCH_ARM = 1, // ARM architecture (including Thumb, Thumb-2) + 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_SPARC, // Sparc architecture + UC_ARCH_M68K, // M68K architecture + UC_ARCH_RISCV, // RISCV architecture UC_ARCH_MAX, } uc_arch; @@ -107,41 +107,42 @@ typedef enum uc_mode { UC_MODE_BIG_ENDIAN = 1 << 30, // big-endian mode // arm / arm64 - 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 - UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) + 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 + UC_MODE_V8 = 1 << 6, // ARMv8 A32 encodings for ARM (currently unsupported) // arm (32bit) cpu types - UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type - UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type - UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type + UC_MODE_ARM926 = 1 << 7, // ARM926 CPU type + UC_MODE_ARM946 = 1 << 8, // ARM946 CPU type + UC_MODE_ARM1176 = 1 << 9, // ARM1176 CPU type // mips - 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 + 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 - 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_16 = 1 << 1, // 16-bit 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 - UC_MODE_PPC64 = 1 << 3, // 64-bit mode (currently unsupported) - UC_MODE_QPX = 1 << 4, // Quad Processing eXtensions mode (currently unsupported) + // ppc + UC_MODE_PPC32 = 1 << 2, // 32-bit 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) + 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) // riscv - UC_MODE_RISCV32 = 1 << 2, // 32-bit mode - UC_MODE_RISCV64 = 1 << 3, // 64-bit mode + UC_MODE_RISCV32 = 1 << 2, // 32-bit mode + UC_MODE_RISCV64 = 1 << 3, // 64-bit mode // m68k } uc_mode; @@ -149,39 +150,48 @@ typedef enum uc_mode { // All type of errors encountered by Unicorn API. // These are values returned by uc_errno() typedef enum uc_err { - UC_ERR_OK = 0, // No error: everything was fine - UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() - UC_ERR_ARCH, // Unsupported architecture: uc_open() - UC_ERR_HANDLE, // Invalid handle - UC_ERR_MODE, // Invalid/unsupported mode: uc_open() - UC_ERR_VERSION, // Unsupported version (bindings) - UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: uc_emu_start() - UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: uc_emu_start() - UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: uc_emu_start() - UC_ERR_HOOK, // Invalid hook type: uc_hook_add() - UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: uc_emu_start() - UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() - UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: uc_emu_start() - UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: uc_emu_start() - UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: uc_emu_start() - UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific function API) + UC_ERR_OK = 0, // No error: everything was fine + UC_ERR_NOMEM, // Out-Of-Memory error: uc_open(), uc_emulate() + UC_ERR_ARCH, // Unsupported architecture: uc_open() + UC_ERR_HANDLE, // Invalid handle + UC_ERR_MODE, // Invalid/unsupported mode: uc_open() + UC_ERR_VERSION, // Unsupported version (bindings) + UC_ERR_READ_UNMAPPED, // Quit emulation due to READ on unmapped memory: + // uc_emu_start() + UC_ERR_WRITE_UNMAPPED, // Quit emulation due to WRITE on unmapped memory: + // uc_emu_start() + UC_ERR_FETCH_UNMAPPED, // Quit emulation due to FETCH on unmapped memory: + // uc_emu_start() + UC_ERR_HOOK, // Invalid hook type: uc_hook_add() + UC_ERR_INSN_INVALID, // Quit emulation due to invalid instruction: + // uc_emu_start() + UC_ERR_MAP, // Invalid memory mapping: uc_mem_map() + UC_ERR_WRITE_PROT, // Quit emulation due to UC_MEM_WRITE_PROT violation: + // uc_emu_start() + UC_ERR_READ_PROT, // Quit emulation due to UC_MEM_READ_PROT violation: + // uc_emu_start() + UC_ERR_FETCH_PROT, // Quit emulation due to UC_MEM_FETCH_PROT violation: + // uc_emu_start() + UC_ERR_ARG, // Inavalid argument provided to uc_xxx function (See specific + // function API) UC_ERR_READ_UNALIGNED, // Unaligned read - UC_ERR_WRITE_UNALIGNED, // Unaligned write - UC_ERR_FETCH_UNALIGNED, // Unaligned fetch - UC_ERR_HOOK_EXIST, // hook for this event already existed - UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() - UC_ERR_EXCEPTION, // Unhandled CPU exception + UC_ERR_WRITE_UNALIGNED, // Unaligned write + UC_ERR_FETCH_UNALIGNED, // Unaligned fetch + UC_ERR_HOOK_EXIST, // hook for this event already existed + UC_ERR_RESOURCE, // Insufficient resource: uc_emu_start() + UC_ERR_EXCEPTION, // Unhandled CPU exception } 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 + @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); +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()) @@ -189,14 +199,16 @@ typedef void (*uc_cb_hookcode_t)(uc_engine *uc, uint64_t address, uint32_t size, @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); +typedef void (*uc_cb_hookintr_t)(uc_engine *uc, uint32_t intno, + void *user_data); /* Callback function for tracing invalid instructions @user_data: user data passed to tracing APIs. - @return: return true to continue, or false to stop program (due to invalid instruction). + @return: return true to continue, or false to stop program (due to invalid + instruction). */ typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data); @@ -207,7 +219,8 @@ typedef bool (*uc_cb_hookinsn_invalid_t)(uc_engine *uc, void *user_data); @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); +typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, + void *user_data); /* Callback function for OUT instruction of X86 @@ -216,7 +229,8 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, void @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); +typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, + uint32_t value, void *user_data); /* Callback function for MMIO read @@ -225,7 +239,8 @@ typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_ @size: data size to read @user_data: user data passed to uc_mmio_map() */ -typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned size, void *user_data); +typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data); /* Callback function for MMIO write @@ -235,28 +250,30 @@ typedef uint64_t (*uc_cb_mmio_read_t)(uc_engine *uc, uint64_t offset, unsigned s @value: data value to be written @user_data: user data passed to uc_mmio_map() */ -typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, unsigned size, uint64_t value, void *user_data); - +typedef void (*uc_cb_mmio_write_t)(uc_engine *uc, uint64_t offset, + unsigned size, uint64_t value, + void *user_data); // All type of memory accesses for UC_HOOK_MEM_* typedef enum uc_mem_type { - UC_MEM_READ = 16, // Memory is read from - UC_MEM_WRITE, // Memory is written to - UC_MEM_FETCH, // Memory is fetched - UC_MEM_READ_UNMAPPED, // Unmapped memory is read from - UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to - UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched - UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory - UC_MEM_READ_PROT, // Read from read protected, but mapped, memory - UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory - UC_MEM_READ_AFTER, // Memory is read from (successful access) + UC_MEM_READ = 16, // Memory is read from + UC_MEM_WRITE, // Memory is written to + UC_MEM_FETCH, // Memory is fetched + UC_MEM_READ_UNMAPPED, // Unmapped memory is read from + UC_MEM_WRITE_UNMAPPED, // Unmapped memory is written to + UC_MEM_FETCH_UNMAPPED, // Unmapped memory is fetched + UC_MEM_WRITE_PROT, // Write to write protected, but mapped, memory + UC_MEM_READ_PROT, // Read from read protected, but mapped, memory + UC_MEM_FETCH_PROT, // Fetch from non-executable, but mapped, memory + UC_MEM_READ_AFTER, // Memory is read from (successful access) } uc_mem_type; // All type of hooks for uc_hook_add() API. typedef enum uc_hook_type { // Hook all interrupt/syscall events UC_HOOK_INTR = 1 << 0, - // Hook a particular instruction - only a very small subset of instructions supported here + // Hook a particular instruction - only a very small subset of instructions + // supported here UC_HOOK_INSN = 1 << 1, // Hook a range of code UC_HOOK_CODE = 1 << 2, @@ -288,21 +305,29 @@ typedef enum uc_hook_type { } uc_hook_type; // Hook type for all events of unmapped memory access -#define UC_HOOK_MEM_UNMAPPED (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + UC_HOOK_MEM_FETCH_UNMAPPED) +#define UC_HOOK_MEM_UNMAPPED \ + (UC_HOOK_MEM_READ_UNMAPPED + UC_HOOK_MEM_WRITE_UNMAPPED + \ + UC_HOOK_MEM_FETCH_UNMAPPED) // Hook type for all events of illegal protected memory access -#define UC_HOOK_MEM_PROT (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT) +#define UC_HOOK_MEM_PROT \ + (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_FETCH_PROT) // Hook type for all events of illegal read memory access -#define UC_HOOK_MEM_READ_INVALID (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED) +#define UC_HOOK_MEM_READ_INVALID \ + (UC_HOOK_MEM_READ_PROT + UC_HOOK_MEM_READ_UNMAPPED) // Hook type for all events of illegal write memory access -#define UC_HOOK_MEM_WRITE_INVALID (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED) +#define UC_HOOK_MEM_WRITE_INVALID \ + (UC_HOOK_MEM_WRITE_PROT + UC_HOOK_MEM_WRITE_UNMAPPED) // Hook type for all events of illegal fetch memory access -#define UC_HOOK_MEM_FETCH_INVALID (UC_HOOK_MEM_FETCH_PROT + UC_HOOK_MEM_FETCH_UNMAPPED) +#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 -// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and UC_HOOK_MEM_READ_UNMAPPED, so -// this hook may technically trigger on some invalid reads. -#define UC_HOOK_MEM_VALID (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) +// NOTE: UC_HOOK_MEM_READ is triggered before UC_HOOK_MEM_READ_PROT and +// UC_HOOK_MEM_READ_UNMAPPED, so +// this hook may technically trigger on some invalid reads. +#define UC_HOOK_MEM_VALID \ + (UC_HOOK_MEM_READ + UC_HOOK_MEM_WRITE + UC_HOOK_MEM_FETCH) /* Callback function for hooking memory (READ, WRITE & FETCH) @@ -314,7 +339,8 @@ typedef enum uc_hook_type { @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); + uint64_t address, int size, int64_t value, + void *user_data); /* Callback function for handling invalid memory access events (UNMAPPED and @@ -326,21 +352,24 @@ typedef void (*uc_cb_hookmem_t)(uc_engine *uc, uc_mem_type type, @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). - NOTE: returning true to continue execution will only work if if the accessed - memory is made accessible with the correct permissions during the hook. + @return: return true to continue, or false to stop program (due to invalid + memory). NOTE: returning true to continue execution will only work if if the + accessed memory is made accessible with the correct permissions during the + hook. - In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED callback, - the memory should be uc_mem_map()-ed with the correct permissions, and the - instruction will then read or write to the address as it was supposed to. + In the event of a UC_MEM_READ_UNMAPPED or UC_MEM_WRITE_UNMAPPED + callback, the memory should be uc_mem_map()-ed with the correct permissions, + and the instruction will then read or write to the address as it was supposed + to. - In the event of a UC_MEM_FETCH_UNMAPPED callback, the memory can be mapped - in as executable, in which case execution will resume from the fetched address. - The instruction pointer may be written to in order to change where execution resumes, - but the fetch must succeed if execution is to resume. + In the event of a UC_MEM_FETCH_UNMAPPED callback, the memory can be + mapped in as executable, in which case execution will resume from the fetched + address. The instruction pointer may be written to in order to change where + execution resumes, but the fetch must succeed if execution is to resume. */ typedef bool (*uc_cb_eventmem_t)(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data); + uint64_t address, int size, int64_t value, + void *user_data); /* Memory region mapped by uc_mem_map() and uc_mem_map_ptr() @@ -357,8 +386,9 @@ typedef enum uc_query_type { // Dynamically query current hardware mode. UC_QUERY_MODE = 1, UC_QUERY_PAGE_SIZE, // query pagesize of engine - UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode) - UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if result = True) + UC_QUERY_ARCH, // query architecture of engine (for ARM to query Thumb mode) + UC_QUERY_TIMEOUT, // query if emulation stops due to timeout (indicated if + // result = True) } uc_query_type; // Opaque storage for CPU context, used with uc_context_*() @@ -385,7 +415,6 @@ typedef struct uc_context uc_context; UNICORN_EXPORT unsigned int uc_version(unsigned int *major, unsigned int *minor); - /* Determine if the given architecture is supported by this library. @@ -396,7 +425,6 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor); UNICORN_EXPORT bool uc_arch_supported(uc_arch arch); - /* Create new instance of unicorn engine. @@ -499,7 +527,8 @@ uc_err uc_reg_read(uc_engine *uc, int regid, void *value); for detailed error). */ UNICORN_EXPORT -uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, int count); +uc_err uc_reg_write_batch(uc_engine *uc, int *regs, void *const *vals, + int count); /* Read multiple register values. @@ -529,7 +558,8 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *regs, void **vals, int count); for detailed error). */ UNICORN_EXPORT -uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t size); +uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *bytes, + size_t size); /* Read a range of bytes in memory. @@ -566,7 +596,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t size); 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); +uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, + uint64_t timeout, size_t count); /* Stop emulation (which was started by uc_emu_start() API. @@ -585,15 +616,17 @@ uc_err uc_emu_stop(uc_engine *uc); The callback will be run when the hook event is hit. @uc: handle returned by uc_open() - @hh: hook handle returned from this registration. To be used in uc_hook_del() API + @hh: hook handle returned from this registration. To be used in uc_hook_del() + API @type: hook type @callback: callback to be run when instruction is hit @user_data: user-defined data. This will be passed to callback function in its last argument @user_data @begin: start address of the area where the callback is effect (inclusive) @end: end address of the area where the callback is effect (inclusive) - NOTE 1: the callback is called only if related address is in range [@begin, @end] - NOTE 2: if @begin > @end, callback is called whenever this hook type is triggered + NOTE 1: the callback is called only if related address is in range [@begin, + @end] NOTE 2: if @begin > @end, callback is called whenever this hook type is + triggered @...: variable arguments (depending on @type) NOTE: if @type = UC_HOOK_INSN, this is the instruction ID. currently, only x86 in, out, syscall, sysenter, cpuid are supported. @@ -603,7 +636,7 @@ uc_err uc_emu_stop(uc_engine *uc); */ UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, - void *user_data, uint64_t begin, uint64_t end, ...); + void *user_data, uint64_t begin, uint64_t end, ...); /* Unregister (remove) a hook callback. @@ -621,11 +654,11 @@ UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh); typedef enum uc_prot { - UC_PROT_NONE = 0, - UC_PROT_READ = 1, - UC_PROT_WRITE = 2, - UC_PROT_EXEC = 4, - UC_PROT_ALL = 7, + UC_PROT_NONE = 0, + UC_PROT_READ = 1, + UC_PROT_WRITE = 2, + UC_PROT_EXEC = 4, + UC_PROT_ALL = 7, } uc_prot; /* @@ -634,12 +667,14 @@ typedef enum uc_prot { @uc: handle returned by uc_open() @address: starting address of the new memory region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new memory region to be mapped in. - This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: Permissions for the newly mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, 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). @@ -653,21 +688,25 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); @uc: handle returned by uc_open() @address: starting address of the new memory region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new memory region to be mapped in. - This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: Permissions for the newly mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. - @ptr: pointer to host memory backing the newly mapped memory. This host memory is - expected to be an equal or larger size than provided, and be mapped with at - least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is undefined. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, or this will return with UC_ERR_ARG error. + @ptr: pointer to host memory backing the newly mapped memory. This host memory + is expected to be an equal or larger size than provided, and be mapped with at + least PROT_READ | PROT_WRITE. If it is not, the resulting behavior is + undefined. @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_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, void *ptr); +uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, void *ptr); /* Map MMIO in for emulation. @@ -675,15 +714,16 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per @uc: handle returned by uc_open() @address: starting address of the new MMIO region to be mapped in. - This address must be aligned to 4KB, or this will return with UC_ERR_ARG error. + This address must be aligned to 4KB, or this will return with UC_ERR_ARG + error. @size: size of the new MMIO region to be mapped in. This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. @read_cb: function for handling reads from this MMIO region. - @user_data_read: user-defined data. This will be passed to @read_cb function in its - last argument @user_data + @user_data_read: user-defined data. This will be passed to @read_cb function in + its last argument @user_data @write_cb: function for handling writes to this MMIO region. - @user_data_write: user-defined data. This will be passed to @write_cb function in its - last argument @user_data + @user_data_write: user-defined data. This will be passed to @write_cb function + in its last argument @user_data @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). */ @@ -698,9 +738,11 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, @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. + 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. - This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. + 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). @@ -714,18 +756,21 @@ uc_err uc_mem_unmap(uc_engine *uc, uint64_t address, size_t size); @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. + 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. - This size must be multiple of 4KB, or this will return with UC_ERR_ARG error. + This size must be multiple of 4KB, or this will return with UC_ERR_ARG + error. @perms: New permissions for the mapped region. - This must be some combination of UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, - or this will return with UC_ERR_ARG error. + This must be some combination of UC_PROT_READ | UC_PROT_WRITE | + UC_PROT_EXEC, 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). */ UNICORN_EXPORT -uc_err uc_mem_protect(uc_engine *uc, uint64_t address, size_t size, uint32_t perms); +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() @@ -763,9 +808,9 @@ uc_err uc_context_alloc(uc_engine *uc, uc_context **context); /* Free the memory allocated by uc_mem_regions. - WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc should - be free-ed by uc_context_free(). Calling uc_free() may still work, but the result - is **undefined**. + WARNING: After Unicorn 1.0.1rc5, the memory allocated by uc_context_alloc + should be free-ed by uc_context_free(). Calling uc_free() may still work, but + the result is **undefined**. @mem: memory allocated by uc_mem_regions (returned in *regions). @@ -827,7 +872,8 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value); for detailed error). */ UNICORN_EXPORT -uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, int count); +uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, + int count); /* Read multiple register values from a context. @@ -841,7 +887,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *regs, void *const *vals, for detailed error). */ UNICORN_EXPORT -uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int count); +uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, + int count); /* Restore the current CPU context from a saved copy. @@ -849,7 +896,8 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co state saved by uc_context_save(). @uc: handle returned by uc_open() - @context: handle returned by uc_context_alloc that has been used with uc_context_save + @context: handle returned by uc_context_alloc that has been used with + uc_context_save @return UC_ERR_OK on success, or other value on failure (refer to uc_err enum for detailed error). @@ -857,10 +905,9 @@ uc_err uc_context_reg_read_batch(uc_context *ctx, int *regs, void **vals, int co UNICORN_EXPORT uc_err uc_context_restore(uc_engine *uc, uc_context *context); - /* - Return the size needed to store the cpu context. Can be used to allocate a buffer - to contain the cpu context and directly call uc_context_save. + Return the size needed to store the cpu context. Can be used to allocate a + buffer to contain the cpu context and directly call uc_context_save. @uc: handle returned by uc_open() @@ -869,7 +916,6 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context); UNICORN_EXPORT size_t uc_context_size(uc_engine *uc); - /* Free the context allocated by uc_context_alloc(). diff --git a/include/unicorn/x86.h b/include/unicorn/x86.h index 9533a72f..1f9b740e 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -16,14 +16,14 @@ extern "C" { // Memory-Management Register for instructions IDTR, GDTR, LDTR, TR. // Borrow from SegmentCache in qemu/target-i386/cpu.h typedef struct uc_x86_mmr { - uint16_t selector; /* not used by GDTR and IDTR */ - uint64_t base; /* handle 32 or 64 bit CPUs */ + uint16_t selector; /* not used by GDTR and IDTR */ + uint64_t base; /* handle 32 or 64 bit CPUs */ uint32_t limit; - uint32_t flags; /* not used by GDTR and IDTR */ + uint32_t flags; /* not used by GDTR and IDTR */ } uc_x86_mmr; -// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the register ID) in -// call to uc_reg_write/uc_reg_read() to manipulate MSRs. +// Model-Specific Register structure, use this with UC_X86_REG_MSR (as the +// register ID) in call to uc_reg_write/uc_reg_read() to manipulate MSRs. typedef struct uc_x86_msr { uint32_t rid; // MSR id uint64_t value; // MSR value @@ -35,62 +35,241 @@ typedef void (*uc_cb_insn_syscall_t)(struct uc_struct *uc, void *user_data); //> X86 registers typedef enum uc_x86_reg { - UC_X86_REG_INVALID = 0, - UC_X86_REG_AH, UC_X86_REG_AL, UC_X86_REG_AX, UC_X86_REG_BH, UC_X86_REG_BL, - UC_X86_REG_BP, UC_X86_REG_BPL, UC_X86_REG_BX, UC_X86_REG_CH, UC_X86_REG_CL, - UC_X86_REG_CS, UC_X86_REG_CX, UC_X86_REG_DH, UC_X86_REG_DI, UC_X86_REG_DIL, - UC_X86_REG_DL, UC_X86_REG_DS, UC_X86_REG_DX, UC_X86_REG_EAX, UC_X86_REG_EBP, - UC_X86_REG_EBX, UC_X86_REG_ECX, UC_X86_REG_EDI, UC_X86_REG_EDX, UC_X86_REG_EFLAGS, - UC_X86_REG_EIP, UC_X86_REG_ES, UC_X86_REG_ESI, UC_X86_REG_ESP, - UC_X86_REG_FPSW, UC_X86_REG_FS, UC_X86_REG_GS, UC_X86_REG_IP, UC_X86_REG_RAX, - UC_X86_REG_RBP, UC_X86_REG_RBX, UC_X86_REG_RCX, UC_X86_REG_RDI, UC_X86_REG_RDX, - UC_X86_REG_RIP, UC_X86_REG_RSI, UC_X86_REG_RSP, UC_X86_REG_SI, - UC_X86_REG_SIL, UC_X86_REG_SP, UC_X86_REG_SPL, UC_X86_REG_SS, UC_X86_REG_CR0, - UC_X86_REG_CR1, UC_X86_REG_CR2, UC_X86_REG_CR3, UC_X86_REG_CR4, UC_X86_REG_CR8, - UC_X86_REG_DR0, UC_X86_REG_DR1, UC_X86_REG_DR2, UC_X86_REG_DR3, UC_X86_REG_DR4, - UC_X86_REG_DR5, UC_X86_REG_DR6, UC_X86_REG_DR7, UC_X86_REG_FP0, UC_X86_REG_FP1, - UC_X86_REG_FP2, UC_X86_REG_FP3, - UC_X86_REG_FP4, UC_X86_REG_FP5, UC_X86_REG_FP6, UC_X86_REG_FP7, - UC_X86_REG_K0, UC_X86_REG_K1, UC_X86_REG_K2, UC_X86_REG_K3, UC_X86_REG_K4, - UC_X86_REG_K5, UC_X86_REG_K6, UC_X86_REG_K7, UC_X86_REG_MM0, UC_X86_REG_MM1, - UC_X86_REG_MM2, UC_X86_REG_MM3, UC_X86_REG_MM4, UC_X86_REG_MM5, UC_X86_REG_MM6, - UC_X86_REG_MM7, UC_X86_REG_R8, UC_X86_REG_R9, UC_X86_REG_R10, UC_X86_REG_R11, - UC_X86_REG_R12, UC_X86_REG_R13, UC_X86_REG_R14, UC_X86_REG_R15, - UC_X86_REG_ST0, UC_X86_REG_ST1, UC_X86_REG_ST2, UC_X86_REG_ST3, - UC_X86_REG_ST4, UC_X86_REG_ST5, UC_X86_REG_ST6, UC_X86_REG_ST7, - UC_X86_REG_XMM0, UC_X86_REG_XMM1, UC_X86_REG_XMM2, UC_X86_REG_XMM3, UC_X86_REG_XMM4, - UC_X86_REG_XMM5, UC_X86_REG_XMM6, UC_X86_REG_XMM7, UC_X86_REG_XMM8, UC_X86_REG_XMM9, - UC_X86_REG_XMM10, UC_X86_REG_XMM11, UC_X86_REG_XMM12, UC_X86_REG_XMM13, UC_X86_REG_XMM14, - UC_X86_REG_XMM15, UC_X86_REG_XMM16, UC_X86_REG_XMM17, UC_X86_REG_XMM18, UC_X86_REG_XMM19, - UC_X86_REG_XMM20, UC_X86_REG_XMM21, UC_X86_REG_XMM22, UC_X86_REG_XMM23, UC_X86_REG_XMM24, - UC_X86_REG_XMM25, UC_X86_REG_XMM26, UC_X86_REG_XMM27, UC_X86_REG_XMM28, UC_X86_REG_XMM29, - UC_X86_REG_XMM30, UC_X86_REG_XMM31, UC_X86_REG_YMM0, UC_X86_REG_YMM1, UC_X86_REG_YMM2, - UC_X86_REG_YMM3, UC_X86_REG_YMM4, UC_X86_REG_YMM5, UC_X86_REG_YMM6, UC_X86_REG_YMM7, - UC_X86_REG_YMM8, UC_X86_REG_YMM9, UC_X86_REG_YMM10, UC_X86_REG_YMM11, UC_X86_REG_YMM12, - UC_X86_REG_YMM13, UC_X86_REG_YMM14, UC_X86_REG_YMM15, UC_X86_REG_YMM16, UC_X86_REG_YMM17, - UC_X86_REG_YMM18, UC_X86_REG_YMM19, UC_X86_REG_YMM20, UC_X86_REG_YMM21, UC_X86_REG_YMM22, - UC_X86_REG_YMM23, UC_X86_REG_YMM24, UC_X86_REG_YMM25, UC_X86_REG_YMM26, UC_X86_REG_YMM27, - UC_X86_REG_YMM28, UC_X86_REG_YMM29, UC_X86_REG_YMM30, UC_X86_REG_YMM31, UC_X86_REG_ZMM0, - UC_X86_REG_ZMM1, UC_X86_REG_ZMM2, UC_X86_REG_ZMM3, UC_X86_REG_ZMM4, UC_X86_REG_ZMM5, - UC_X86_REG_ZMM6, UC_X86_REG_ZMM7, UC_X86_REG_ZMM8, UC_X86_REG_ZMM9, UC_X86_REG_ZMM10, - UC_X86_REG_ZMM11, UC_X86_REG_ZMM12, UC_X86_REG_ZMM13, UC_X86_REG_ZMM14, UC_X86_REG_ZMM15, - UC_X86_REG_ZMM16, UC_X86_REG_ZMM17, UC_X86_REG_ZMM18, UC_X86_REG_ZMM19, UC_X86_REG_ZMM20, - UC_X86_REG_ZMM21, UC_X86_REG_ZMM22, UC_X86_REG_ZMM23, UC_X86_REG_ZMM24, UC_X86_REG_ZMM25, - UC_X86_REG_ZMM26, UC_X86_REG_ZMM27, UC_X86_REG_ZMM28, UC_X86_REG_ZMM29, UC_X86_REG_ZMM30, - UC_X86_REG_ZMM31, UC_X86_REG_R8B, UC_X86_REG_R9B, UC_X86_REG_R10B, UC_X86_REG_R11B, - UC_X86_REG_R12B, UC_X86_REG_R13B, UC_X86_REG_R14B, UC_X86_REG_R15B, UC_X86_REG_R8D, - UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D, - UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W, - UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W, - UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW, - UC_X86_REG_FPTAG, + UC_X86_REG_INVALID = 0, + UC_X86_REG_AH, + UC_X86_REG_AL, + UC_X86_REG_AX, + UC_X86_REG_BH, + UC_X86_REG_BL, + UC_X86_REG_BP, + UC_X86_REG_BPL, + UC_X86_REG_BX, + UC_X86_REG_CH, + UC_X86_REG_CL, + UC_X86_REG_CS, + UC_X86_REG_CX, + UC_X86_REG_DH, + UC_X86_REG_DI, + UC_X86_REG_DIL, + UC_X86_REG_DL, + UC_X86_REG_DS, + UC_X86_REG_DX, + UC_X86_REG_EAX, + UC_X86_REG_EBP, + UC_X86_REG_EBX, + UC_X86_REG_ECX, + UC_X86_REG_EDI, + UC_X86_REG_EDX, + UC_X86_REG_EFLAGS, + UC_X86_REG_EIP, + UC_X86_REG_ES, + UC_X86_REG_ESI, + UC_X86_REG_ESP, + UC_X86_REG_FPSW, + UC_X86_REG_FS, + UC_X86_REG_GS, + UC_X86_REG_IP, + UC_X86_REG_RAX, + UC_X86_REG_RBP, + UC_X86_REG_RBX, + UC_X86_REG_RCX, + UC_X86_REG_RDI, + UC_X86_REG_RDX, + UC_X86_REG_RIP, + UC_X86_REG_RSI, + UC_X86_REG_RSP, + UC_X86_REG_SI, + UC_X86_REG_SIL, + UC_X86_REG_SP, + UC_X86_REG_SPL, + UC_X86_REG_SS, + UC_X86_REG_CR0, + UC_X86_REG_CR1, + UC_X86_REG_CR2, + UC_X86_REG_CR3, + UC_X86_REG_CR4, + UC_X86_REG_CR8, + UC_X86_REG_DR0, + UC_X86_REG_DR1, + UC_X86_REG_DR2, + UC_X86_REG_DR3, + UC_X86_REG_DR4, + UC_X86_REG_DR5, + UC_X86_REG_DR6, + UC_X86_REG_DR7, + UC_X86_REG_FP0, + UC_X86_REG_FP1, + UC_X86_REG_FP2, + UC_X86_REG_FP3, + UC_X86_REG_FP4, + UC_X86_REG_FP5, + UC_X86_REG_FP6, + UC_X86_REG_FP7, + UC_X86_REG_K0, + UC_X86_REG_K1, + UC_X86_REG_K2, + UC_X86_REG_K3, + UC_X86_REG_K4, + UC_X86_REG_K5, + UC_X86_REG_K6, + UC_X86_REG_K7, + UC_X86_REG_MM0, + UC_X86_REG_MM1, + UC_X86_REG_MM2, + UC_X86_REG_MM3, + UC_X86_REG_MM4, + UC_X86_REG_MM5, + UC_X86_REG_MM6, + UC_X86_REG_MM7, + UC_X86_REG_R8, + UC_X86_REG_R9, + UC_X86_REG_R10, + UC_X86_REG_R11, + UC_X86_REG_R12, + UC_X86_REG_R13, + UC_X86_REG_R14, + UC_X86_REG_R15, + UC_X86_REG_ST0, + UC_X86_REG_ST1, + UC_X86_REG_ST2, + UC_X86_REG_ST3, + UC_X86_REG_ST4, + UC_X86_REG_ST5, + UC_X86_REG_ST6, + UC_X86_REG_ST7, + UC_X86_REG_XMM0, + UC_X86_REG_XMM1, + UC_X86_REG_XMM2, + UC_X86_REG_XMM3, + UC_X86_REG_XMM4, + UC_X86_REG_XMM5, + UC_X86_REG_XMM6, + UC_X86_REG_XMM7, + UC_X86_REG_XMM8, + UC_X86_REG_XMM9, + UC_X86_REG_XMM10, + UC_X86_REG_XMM11, + UC_X86_REG_XMM12, + UC_X86_REG_XMM13, + UC_X86_REG_XMM14, + UC_X86_REG_XMM15, + UC_X86_REG_XMM16, + UC_X86_REG_XMM17, + UC_X86_REG_XMM18, + UC_X86_REG_XMM19, + UC_X86_REG_XMM20, + UC_X86_REG_XMM21, + UC_X86_REG_XMM22, + UC_X86_REG_XMM23, + UC_X86_REG_XMM24, + UC_X86_REG_XMM25, + UC_X86_REG_XMM26, + UC_X86_REG_XMM27, + UC_X86_REG_XMM28, + UC_X86_REG_XMM29, + UC_X86_REG_XMM30, + UC_X86_REG_XMM31, + UC_X86_REG_YMM0, + UC_X86_REG_YMM1, + UC_X86_REG_YMM2, + UC_X86_REG_YMM3, + UC_X86_REG_YMM4, + UC_X86_REG_YMM5, + UC_X86_REG_YMM6, + UC_X86_REG_YMM7, + UC_X86_REG_YMM8, + UC_X86_REG_YMM9, + UC_X86_REG_YMM10, + UC_X86_REG_YMM11, + UC_X86_REG_YMM12, + UC_X86_REG_YMM13, + UC_X86_REG_YMM14, + UC_X86_REG_YMM15, + UC_X86_REG_YMM16, + UC_X86_REG_YMM17, + UC_X86_REG_YMM18, + UC_X86_REG_YMM19, + UC_X86_REG_YMM20, + UC_X86_REG_YMM21, + UC_X86_REG_YMM22, + UC_X86_REG_YMM23, + UC_X86_REG_YMM24, + UC_X86_REG_YMM25, + UC_X86_REG_YMM26, + UC_X86_REG_YMM27, + UC_X86_REG_YMM28, + UC_X86_REG_YMM29, + UC_X86_REG_YMM30, + UC_X86_REG_YMM31, + UC_X86_REG_ZMM0, + UC_X86_REG_ZMM1, + UC_X86_REG_ZMM2, + UC_X86_REG_ZMM3, + UC_X86_REG_ZMM4, + UC_X86_REG_ZMM5, + UC_X86_REG_ZMM6, + UC_X86_REG_ZMM7, + UC_X86_REG_ZMM8, + UC_X86_REG_ZMM9, + UC_X86_REG_ZMM10, + UC_X86_REG_ZMM11, + UC_X86_REG_ZMM12, + UC_X86_REG_ZMM13, + UC_X86_REG_ZMM14, + UC_X86_REG_ZMM15, + UC_X86_REG_ZMM16, + UC_X86_REG_ZMM17, + UC_X86_REG_ZMM18, + UC_X86_REG_ZMM19, + UC_X86_REG_ZMM20, + UC_X86_REG_ZMM21, + UC_X86_REG_ZMM22, + UC_X86_REG_ZMM23, + UC_X86_REG_ZMM24, + UC_X86_REG_ZMM25, + UC_X86_REG_ZMM26, + UC_X86_REG_ZMM27, + UC_X86_REG_ZMM28, + UC_X86_REG_ZMM29, + UC_X86_REG_ZMM30, + UC_X86_REG_ZMM31, + UC_X86_REG_R8B, + UC_X86_REG_R9B, + UC_X86_REG_R10B, + UC_X86_REG_R11B, + UC_X86_REG_R12B, + UC_X86_REG_R13B, + UC_X86_REG_R14B, + UC_X86_REG_R15B, + UC_X86_REG_R8D, + UC_X86_REG_R9D, + UC_X86_REG_R10D, + UC_X86_REG_R11D, + UC_X86_REG_R12D, + UC_X86_REG_R13D, + UC_X86_REG_R14D, + UC_X86_REG_R15D, + UC_X86_REG_R8W, + UC_X86_REG_R9W, + UC_X86_REG_R10W, + UC_X86_REG_R11W, + UC_X86_REG_R12W, + UC_X86_REG_R13W, + UC_X86_REG_R14W, + UC_X86_REG_R15W, + UC_X86_REG_IDTR, + UC_X86_REG_GDTR, + UC_X86_REG_LDTR, + UC_X86_REG_TR, + UC_X86_REG_FPCW, + UC_X86_REG_FPTAG, UC_X86_REG_MSR, // Model-Specific Register UC_X86_REG_MXCSR, UC_X86_REG_FS_BASE, // Base regs for x86_64 UC_X86_REG_GS_BASE, UC_X86_REG_FLAGS, UC_X86_REG_RFLAGS, - UC_X86_REG_ENDING // <-- mark the end of the list of registers + UC_X86_REG_ENDING // <-- mark the end of the list of registers } uc_x86_reg; //> X86 instructions diff --git a/qemu/target/arm/unicorn.h b/qemu/target/arm/unicorn.h index be5e23fc..270444bd 100644 --- a/qemu/target/arm/unicorn.h +++ b/qemu/target/arm/unicorn.h @@ -5,26 +5,38 @@ #define UC_QEMU_TARGET_ARM_H // functions to read & write registers -int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void arm_reg_reset(struct uc_struct *uc); void arm64_reg_reset(struct uc_struct *uc); -void arm_uc_init(struct uc_struct* uc); -void armeb_uc_init(struct uc_struct* uc); +void arm_uc_init(struct uc_struct *uc); +void armeb_uc_init(struct uc_struct *uc); -void arm64_uc_init(struct uc_struct* uc); -void arm64eb_uc_init(struct uc_struct* uc); +void arm64_uc_init(struct uc_struct *uc); +void arm64eb_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/i386/unicorn.c b/qemu/target/i386/unicorn.c index eef1e471..404f8444 100644 --- a/qemu/target/i386/unicorn.c +++ b/qemu/target/i386/unicorn.c @@ -6,18 +6,18 @@ #include "sysemu/cpus.h" #include "cpu.h" #include "unicorn_common.h" -#include /* needed for uc_x86_mmr */ +#include /* needed for uc_x86_mmr */ #include "unicorn.h" -#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) +#define FPST(n) (env->fpregs[(env->fpstt + (n)) & 7].d) #define X86_NON_CS_FLAGS (DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK) static void load_seg_16_helper(CPUX86State *env, int seg, uint32_t selector) { - cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, X86_NON_CS_FLAGS); + cpu_x86_load_seg_cache(env, seg, selector, (selector << 4), 0xffff, + X86_NON_CS_FLAGS); } - void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f); floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper); @@ -28,7 +28,7 @@ static void x86_set_pc(struct uc_struct *uc, uint64_t address) { if (uc->mode == UC_MODE_16) { int16_t cs = (uint16_t)X86_CPU(uc->cpu)->env.segs[R_CS].selector; - ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs*16; + ((CPUX86State *)uc->cpu->env_ptr)->eip = address - cs * 16; } else ((CPUX86State *)uc->cpu->env_ptr)->eip = address; } @@ -59,11 +59,16 @@ void x86_reg_reset(struct uc_struct *uc) { CPUArchState *env = uc->cpu->env_ptr; - env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; - env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_AES | CPUID_EXT_CX16; + env->features[FEAT_1_EDX] = CPUID_CX8 | CPUID_CMOV | CPUID_SSE2 | + CPUID_FXSR | CPUID_SSE | CPUID_CLFLUSH; + env->features[FEAT_1_ECX] = CPUID_EXT_SSSE3 | CPUID_EXT_SSE41 | + CPUID_EXT_SSE42 | CPUID_EXT_AES | + CPUID_EXT_CX16; env->features[FEAT_8000_0001_EDX] = CPUID_EXT2_3DNOW | CPUID_EXT2_RDTSCP; - 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->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; memset(env->regs, 0, sizeof(env->regs)); memset(env->segs, 0, sizeof(env->segs)); @@ -81,7 +86,7 @@ void x86_reg_reset(struct uc_struct *uc) env->fpstt = 0; /* top of stack index */ env->fpus = 0; env->fpuc = 0; - memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ + memset(env->fptags, 0, sizeof(env->fptags)); /* 0 = valid, 1 = empty */ env->mxcsr = 0; memset(env->xmm_regs, 0, sizeof(env->xmm_regs)); @@ -129,43 +134,44 @@ void x86_reg_reset(struct uc_struct *uc) // TODO: reset other registers in CPUX86State qemu/target-i386/cpu.h // properly initialize internal setup for each mode - switch(uc->mode) { - default: - break; - case UC_MODE_16: - env->hflags = 0; - env->cr[0] = 0; - //undo the damage done by the memset of env->segs above - //for R_CS, not quite the same as x86_cpu_reset - cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, - DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | + switch (uc->mode) { + default: + break; + case UC_MODE_16: + env->hflags = 0; + env->cr[0] = 0; + // undo the damage done by the memset of env->segs above + // for R_CS, not quite the same as x86_cpu_reset + cpu_x86_load_seg_cache(env, R_CS, 0, 0, 0xffff, + DESC_P_MASK | DESC_S_MASK | DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK); - //remainder yields same state as x86_cpu_reset - load_seg_16_helper(env, R_DS, 0); - load_seg_16_helper(env, R_ES, 0); - load_seg_16_helper(env, R_SS, 0); - load_seg_16_helper(env, R_FS, 0); - load_seg_16_helper(env, R_GS, 0); + // remainder yields same state as x86_cpu_reset + load_seg_16_helper(env, R_DS, 0); + load_seg_16_helper(env, R_ES, 0); + load_seg_16_helper(env, R_SS, 0); + load_seg_16_helper(env, R_FS, 0); + load_seg_16_helper(env, R_GS, 0); - break; - case UC_MODE_32: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - break; - case UC_MODE_64: - env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | HF_LMA_MASK | HF_OSFXSR_MASK; - env->hflags &= ~(HF_ADDSEG_MASK); - env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated - cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode - /* If we are operating in 64bit mode then add the Long Mode flag - * to the CPUID feature flag - */ - env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; - break; + break; + case UC_MODE_32: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_OSFXSR_MASK; + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + break; + case UC_MODE_64: + env->hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK | + HF_LMA_MASK | HF_OSFXSR_MASK; + env->hflags &= ~(HF_ADDSEG_MASK); + env->efer |= MSR_EFER_LMA | MSR_EFER_LME; // extended mode activated + cpu_x86_update_cr0(env, CR0_PE_MASK); // protected mode + /* If we are operating in 64bit mode then add the Long Mode flag + * to the CPUID feature flag + */ + env->features[FEAT_8000_0001_EDX] |= CPUID_EXT2_LM; + break; } } -static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) +static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) { uint64_t ecx = env->regs[R_ECX]; uint64_t eax = env->regs[R_EAX]; @@ -175,14 +181,14 @@ static int x86_msr_read(CPUX86State *env, uc_x86_msr *msr) helper_rdmsr(env); msr->value = ((uint32_t)env->regs[R_EAX]) | - ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); + ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); env->regs[R_EAX] = eax; env->regs[R_ECX] = ecx; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } @@ -201,1258 +207,1249 @@ static int x86_msr_write(CPUX86State *env, uc_x86_msr *msr) env->regs[R_EAX] = eax; env->regs[R_EDX] = edx; - /* The implementation doesn't throw exception or return an error if there is one, so - * we will return 0. */ + /* The implementation doesn't throw exception or return an error if there is + * one, so we will return 0. */ return 0; } -static void reg_read(CPUX86State *env, unsigned int regid, void *value, uc_mode mode) +static void reg_read(CPUX86State *env, unsigned int regid, void *value, + uc_mode mode) { - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; - cpu_get_fp80(value, (uint16_t*)((char*)value+sizeof(uint64_t)), reg); - } - return; - case UC_X86_REG_FPSW: - { - uint16_t fpus = env->fpus; - fpus = fpus & ~0x3800; - fpus |= ( env->fpstt & 0x7 ) << 11; - *(uint16_t*) value = fpus; - } - return; - case UC_X86_REG_FPCW: - *(uint16_t*) value = env->fpuc; - return; - case UC_X86_REG_FPTAG: - { - #define EXPD(fp) (fp.l.upper & 0x7fff) - #define MANTD(fp) (fp.l.lower) - #define MAXEXPD 0x7fff - int fptag, exp, i; - uint64_t mant; - CPU_LDoubleU tmp; - fptag = 0; - for (i = 7; i >= 0; i--) { - fptag <<= 2; - if (env->fptags[i]) { - fptag |= 3; - } else { - tmp.d = env->fpregs[i].d; - exp = EXPD(tmp); - mant = MANTD(tmp); - if (exp == 0 && mant == 0) { - /* zero */ - fptag |= 1; - } else if (exp == 0 || exp == MAXEXPD - || (mant & (1LL << 63)) == 0) { - /* NaNs, infinity, denormal */ - fptag |= 2; - } - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + floatx80 reg = env->fpregs[regid - UC_X86_REG_FP0].d; + cpu_get_fp80(value, (uint16_t *)((char *)value + sizeof(uint64_t)), + reg); + } + return; + case UC_X86_REG_FPSW: { + uint16_t fpus = env->fpus; + fpus = fpus & ~0x3800; + fpus |= (env->fpstt & 0x7) << 11; + *(uint16_t *)value = fpus; + } + return; + case UC_X86_REG_FPCW: + *(uint16_t *)value = env->fpuc; + return; + case UC_X86_REG_FPTAG: { +#define EXPD(fp) (fp.l.upper & 0x7fff) +#define MANTD(fp) (fp.l.lower) +#define MAXEXPD 0x7fff + int fptag, exp, i; + uint64_t mant; + CPU_LDoubleU tmp; + fptag = 0; + for (i = 7; i >= 0; i--) { + fptag <<= 2; + if (env->fptags[i]) { + fptag |= 3; + } else { + tmp.d = env->fpregs[i].d; + exp = EXPD(tmp); + mant = MANTD(tmp); + if (exp == 0 && mant == 0) { + /* zero */ + fptag |= 1; + } else if (exp == 0 || exp == MAXEXPD || + (mant & (1LL << 63)) == 0) { + /* NaNs, infinity, denormal */ + fptag |= 2; } - *(uint16_t*) value = fptag; - } - return; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - return; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); - return; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *dst = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - dst[0] = lo_reg->_d[0]; - dst[1] = lo_reg->_d[1]; - dst[2] = hi_reg->_d[0]; - dst[3] = hi_reg->_d[1]; - return; } + } + *(uint16_t *)value = fptag; + } + return; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + return; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(value, &FPST(regid - UC_X86_REG_ST0), 10); + return; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *dst = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + dst[0] = lo_reg->_d[0]; + dst[1] = lo_reg->_d[1]; + dst[2] = hi_reg->_d[0]; + dst[3] = hi_reg->_d[1]; + return; + } } - switch(mode) { + switch (mode) { + default: + break; + case UC_MODE_16: + switch (regid) { default: break; - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - *(int16_t *)value = env->segs[R_ES].selector; - return; - case UC_X86_REG_SS: - *(int16_t *)value = env->segs[R_SS].selector; - return; - case UC_X86_REG_DS: - *(int16_t *)value = env->segs[R_DS].selector; - return; - case UC_X86_REG_FS: - *(int16_t *)value = env->segs[R_FS].selector; - return; - case UC_X86_REG_GS: - *(int16_t *)value = env->segs[R_GS].selector; - return; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - return; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EAX: - *(int32_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_EBX: - *(int32_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_ECX: - *(int32_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_EDX: - *(int32_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_ESP: - *(int32_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_EBP: - *(int32_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_ESI: - *(int32_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_EDI: - *(int32_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_EIP: - *(int32_t *)value = env->eip; - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_FS_BASE: - *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; - break; - } + case UC_X86_REG_ES: + *(int16_t *)value = env->segs[R_ES].selector; + return; + case UC_X86_REG_SS: + *(int16_t *)value = env->segs[R_SS].selector; + return; + case UC_X86_REG_DS: + *(int16_t *)value = env->segs[R_DS].selector; + return; + case UC_X86_REG_FS: + *(int16_t *)value = env->segs[R_FS].selector; + return; + case UC_X86_REG_GS: + *(int16_t *)value = env->segs[R_GS].selector; + return; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + return; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int32_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int32_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EAX: + *(int32_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_EBX: + *(int32_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_ECX: + *(int32_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_EDX: + *(int32_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_ESP: + *(int32_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_EBP: + *(int32_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_ESI: + *(int32_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_EDI: + *(int32_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_EIP: + *(int32_t *)value = env->eip; + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = (uint32_t)env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_FS_BASE: + *(uint32_t *)value = (uint32_t)env->segs[R_FS].base; + break; + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; - break; - case UC_X86_REG_FLAGS: - *(int16_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_EFLAGS: - *(int32_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RFLAGS: - *(int64_t *)value = cpu_compute_eflags(env); - break; - case UC_X86_REG_RAX: - *(uint64_t *)value = env->regs[R_EAX]; - break; - case UC_X86_REG_EAX: - *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AX: - *(int16_t *)value = READ_WORD(env->regs[R_EAX]); - break; - case UC_X86_REG_AH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); - break; - case UC_X86_REG_AL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); - break; - case UC_X86_REG_RBX: - *(uint64_t *)value = env->regs[R_EBX]; - break; - case UC_X86_REG_EBX: - *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BX: - *(int16_t *)value = READ_WORD(env->regs[R_EBX]); - break; - case UC_X86_REG_BH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); - break; - case UC_X86_REG_BL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); - break; - case UC_X86_REG_RCX: - *(uint64_t *)value = env->regs[R_ECX]; - break; - case UC_X86_REG_ECX: - *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CX: - *(int16_t *)value = READ_WORD(env->regs[R_ECX]); - break; - case UC_X86_REG_CH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); - break; - case UC_X86_REG_CL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); - break; - case UC_X86_REG_RDX: - *(uint64_t *)value = env->regs[R_EDX]; - break; - case UC_X86_REG_EDX: - *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DX: - *(int16_t *)value = READ_WORD(env->regs[R_EDX]); - break; - case UC_X86_REG_DH: - *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); - break; - case UC_X86_REG_DL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); - break; - case UC_X86_REG_RSP: - *(uint64_t *)value = env->regs[R_ESP]; - break; - case UC_X86_REG_ESP: - *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SP: - *(int16_t *)value = READ_WORD(env->regs[R_ESP]); - break; - case UC_X86_REG_SPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); - break; - case UC_X86_REG_RBP: - *(uint64_t *)value = env->regs[R_EBP]; - break; - case UC_X86_REG_EBP: - *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BP: - *(int16_t *)value = READ_WORD(env->regs[R_EBP]); - break; - case UC_X86_REG_BPL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); - break; - case UC_X86_REG_RSI: - *(uint64_t *)value = env->regs[R_ESI]; - break; - case UC_X86_REG_ESI: - *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SI: - *(int16_t *)value = READ_WORD(env->regs[R_ESI]); - break; - case UC_X86_REG_SIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); - break; - case UC_X86_REG_RDI: - *(uint64_t *)value = env->regs[R_EDI]; - break; - case UC_X86_REG_EDI: - *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DI: - *(int16_t *)value = READ_WORD(env->regs[R_EDI]); - break; - case UC_X86_REG_DIL: - *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); - break; - case UC_X86_REG_RIP: - *(uint64_t *)value = env->eip; - break; - case UC_X86_REG_EIP: - *(int32_t *)value = READ_DWORD(env->eip); - break; - case UC_X86_REG_IP: - *(int16_t *)value = READ_WORD(env->eip); - break; - case UC_X86_REG_CS: - *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; - break; - case UC_X86_REG_DS: - *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; - break; - case UC_X86_REG_SS: - *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; - break; - case UC_X86_REG_ES: - *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; - break; - case UC_X86_REG_FS: - *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; - break; - case UC_X86_REG_GS: - *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; - break; - case UC_X86_REG_R8: - *(int64_t *)value = READ_QWORD(env->regs[8]); - break; - case UC_X86_REG_R8D: - *(int32_t *)value = READ_DWORD(env->regs[8]); - break; - case UC_X86_REG_R8W: - *(int16_t *)value = READ_WORD(env->regs[8]); - break; - case UC_X86_REG_R8B: - *(int8_t *)value = READ_BYTE_L(env->regs[8]); - break; - case UC_X86_REG_R9: - *(int64_t *)value = READ_QWORD(env->regs[9]); - break; - case UC_X86_REG_R9D: - *(int32_t *)value = READ_DWORD(env->regs[9]); - break; - case UC_X86_REG_R9W: - *(int16_t *)value = READ_WORD(env->regs[9]); - break; - case UC_X86_REG_R9B: - *(int8_t *)value = READ_BYTE_L(env->regs[9]); - break; - case UC_X86_REG_R10: - *(int64_t *)value = READ_QWORD(env->regs[10]); - break; - case UC_X86_REG_R10D: - *(int32_t *)value = READ_DWORD(env->regs[10]); - break; - case UC_X86_REG_R10W: - *(int16_t *)value = READ_WORD(env->regs[10]); - break; - case UC_X86_REG_R10B: - *(int8_t *)value = READ_BYTE_L(env->regs[10]); - break; - case UC_X86_REG_R11: - *(int64_t *)value = READ_QWORD(env->regs[11]); - break; - case UC_X86_REG_R11D: - *(int32_t *)value = READ_DWORD(env->regs[11]); - break; - case UC_X86_REG_R11W: - *(int16_t *)value = READ_WORD(env->regs[11]); - break; - case UC_X86_REG_R11B: - *(int8_t *)value = READ_BYTE_L(env->regs[11]); - break; - case UC_X86_REG_R12: - *(int64_t *)value = READ_QWORD(env->regs[12]); - break; - case UC_X86_REG_R12D: - *(int32_t *)value = READ_DWORD(env->regs[12]); - break; - case UC_X86_REG_R12W: - *(int16_t *)value = READ_WORD(env->regs[12]); - break; - case UC_X86_REG_R12B: - *(int8_t *)value = READ_BYTE_L(env->regs[12]); - break; - case UC_X86_REG_R13: - *(int64_t *)value = READ_QWORD(env->regs[13]); - break; - case UC_X86_REG_R13D: - *(int32_t *)value = READ_DWORD(env->regs[13]); - break; - case UC_X86_REG_R13W: - *(int16_t *)value = READ_WORD(env->regs[13]); - break; - case UC_X86_REG_R13B: - *(int8_t *)value = READ_BYTE_L(env->regs[13]); - break; - case UC_X86_REG_R14: - *(int64_t *)value = READ_QWORD(env->regs[14]); - break; - case UC_X86_REG_R14D: - *(int32_t *)value = READ_DWORD(env->regs[14]); - break; - case UC_X86_REG_R14W: - *(int16_t *)value = READ_WORD(env->regs[14]); - break; - case UC_X86_REG_R14B: - *(int8_t *)value = READ_BYTE_L(env->regs[14]); - break; - case UC_X86_REG_R15: - *(int64_t *)value = READ_QWORD(env->regs[15]); - break; - case UC_X86_REG_R15D: - *(int32_t *)value = READ_DWORD(env->regs[15]); - break; - case UC_X86_REG_R15W: - *(int16_t *)value = READ_WORD(env->regs[15]); - break; - case UC_X86_REG_R15B: - *(int8_t *)value = READ_BYTE_L(env->regs[15]); - break; - case UC_X86_REG_IDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; - ((uc_x86_mmr *)value)->base = env->idt.base; - break; - case UC_X86_REG_GDTR: - ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; - ((uc_x86_mmr *)value)->base = env->gdt.base; - break; - case UC_X86_REG_LDTR: - ((uc_x86_mmr *)value)->limit = env->ldt.limit; - ((uc_x86_mmr *)value)->base = env->ldt.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; - ((uc_x86_mmr *)value)->flags = env->ldt.flags; - break; - case UC_X86_REG_TR: - ((uc_x86_mmr *)value)->limit = env->tr.limit; - ((uc_x86_mmr *)value)->base = env->tr.base; - ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; - ((uc_x86_mmr *)value)->flags = env->tr.flags; - break; - case UC_X86_REG_MSR: - x86_msr_read(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - *(uint32_t *)value = env->mxcsr; - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *dst = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - dst[0] = reg->_d[0]; - dst[1] = reg->_d[1]; - break; - } - case UC_X86_REG_FS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; - break; - case UC_X86_REG_GS_BASE: - *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; - break; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + *(int64_t *)value = env->cr[regid - UC_X86_REG_CR0]; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + *(int64_t *)value = env->dr[regid - UC_X86_REG_DR0]; + break; + case UC_X86_REG_FLAGS: + *(int16_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_EFLAGS: + *(int32_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RFLAGS: + *(int64_t *)value = cpu_compute_eflags(env); + break; + case UC_X86_REG_RAX: + *(uint64_t *)value = env->regs[R_EAX]; + break; + case UC_X86_REG_EAX: + *(int32_t *)value = READ_DWORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AX: + *(int16_t *)value = READ_WORD(env->regs[R_EAX]); + break; + case UC_X86_REG_AH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EAX]); + break; + case UC_X86_REG_AL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EAX]); + break; + case UC_X86_REG_RBX: + *(uint64_t *)value = env->regs[R_EBX]; + break; + case UC_X86_REG_EBX: + *(int32_t *)value = READ_DWORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BX: + *(int16_t *)value = READ_WORD(env->regs[R_EBX]); + break; + case UC_X86_REG_BH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EBX]); + break; + case UC_X86_REG_BL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBX]); + break; + case UC_X86_REG_RCX: + *(uint64_t *)value = env->regs[R_ECX]; + break; + case UC_X86_REG_ECX: + *(int32_t *)value = READ_DWORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CX: + *(int16_t *)value = READ_WORD(env->regs[R_ECX]); + break; + case UC_X86_REG_CH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_ECX]); + break; + case UC_X86_REG_CL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ECX]); + break; + case UC_X86_REG_RDX: + *(uint64_t *)value = env->regs[R_EDX]; + break; + case UC_X86_REG_EDX: + *(int32_t *)value = READ_DWORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DX: + *(int16_t *)value = READ_WORD(env->regs[R_EDX]); + break; + case UC_X86_REG_DH: + *(int8_t *)value = READ_BYTE_H(env->regs[R_EDX]); + break; + case UC_X86_REG_DL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDX]); + break; + case UC_X86_REG_RSP: + *(uint64_t *)value = env->regs[R_ESP]; + break; + case UC_X86_REG_ESP: + *(int32_t *)value = READ_DWORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SP: + *(int16_t *)value = READ_WORD(env->regs[R_ESP]); + break; + case UC_X86_REG_SPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESP]); + break; + case UC_X86_REG_RBP: + *(uint64_t *)value = env->regs[R_EBP]; + break; + case UC_X86_REG_EBP: + *(int32_t *)value = READ_DWORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BP: + *(int16_t *)value = READ_WORD(env->regs[R_EBP]); + break; + case UC_X86_REG_BPL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EBP]); + break; + case UC_X86_REG_RSI: + *(uint64_t *)value = env->regs[R_ESI]; + break; + case UC_X86_REG_ESI: + *(int32_t *)value = READ_DWORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SI: + *(int16_t *)value = READ_WORD(env->regs[R_ESI]); + break; + case UC_X86_REG_SIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_ESI]); + break; + case UC_X86_REG_RDI: + *(uint64_t *)value = env->regs[R_EDI]; + break; + case UC_X86_REG_EDI: + *(int32_t *)value = READ_DWORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DI: + *(int16_t *)value = READ_WORD(env->regs[R_EDI]); + break; + case UC_X86_REG_DIL: + *(int8_t *)value = READ_BYTE_L(env->regs[R_EDI]); + break; + case UC_X86_REG_RIP: + *(uint64_t *)value = env->eip; + break; + case UC_X86_REG_EIP: + *(int32_t *)value = READ_DWORD(env->eip); + break; + case UC_X86_REG_IP: + *(int16_t *)value = READ_WORD(env->eip); + break; + case UC_X86_REG_CS: + *(int16_t *)value = (uint16_t)env->segs[R_CS].selector; + break; + case UC_X86_REG_DS: + *(int16_t *)value = (uint16_t)env->segs[R_DS].selector; + break; + case UC_X86_REG_SS: + *(int16_t *)value = (uint16_t)env->segs[R_SS].selector; + break; + case UC_X86_REG_ES: + *(int16_t *)value = (uint16_t)env->segs[R_ES].selector; + break; + case UC_X86_REG_FS: + *(int16_t *)value = (uint16_t)env->segs[R_FS].selector; + break; + case UC_X86_REG_GS: + *(int16_t *)value = (uint16_t)env->segs[R_GS].selector; + break; + case UC_X86_REG_R8: + *(int64_t *)value = READ_QWORD(env->regs[8]); + break; + case UC_X86_REG_R8D: + *(int32_t *)value = READ_DWORD(env->regs[8]); + break; + case UC_X86_REG_R8W: + *(int16_t *)value = READ_WORD(env->regs[8]); + break; + case UC_X86_REG_R8B: + *(int8_t *)value = READ_BYTE_L(env->regs[8]); + break; + case UC_X86_REG_R9: + *(int64_t *)value = READ_QWORD(env->regs[9]); + break; + case UC_X86_REG_R9D: + *(int32_t *)value = READ_DWORD(env->regs[9]); + break; + case UC_X86_REG_R9W: + *(int16_t *)value = READ_WORD(env->regs[9]); + break; + case UC_X86_REG_R9B: + *(int8_t *)value = READ_BYTE_L(env->regs[9]); + break; + case UC_X86_REG_R10: + *(int64_t *)value = READ_QWORD(env->regs[10]); + break; + case UC_X86_REG_R10D: + *(int32_t *)value = READ_DWORD(env->regs[10]); + break; + case UC_X86_REG_R10W: + *(int16_t *)value = READ_WORD(env->regs[10]); + break; + case UC_X86_REG_R10B: + *(int8_t *)value = READ_BYTE_L(env->regs[10]); + break; + case UC_X86_REG_R11: + *(int64_t *)value = READ_QWORD(env->regs[11]); + break; + case UC_X86_REG_R11D: + *(int32_t *)value = READ_DWORD(env->regs[11]); + break; + case UC_X86_REG_R11W: + *(int16_t *)value = READ_WORD(env->regs[11]); + break; + case UC_X86_REG_R11B: + *(int8_t *)value = READ_BYTE_L(env->regs[11]); + break; + case UC_X86_REG_R12: + *(int64_t *)value = READ_QWORD(env->regs[12]); + break; + case UC_X86_REG_R12D: + *(int32_t *)value = READ_DWORD(env->regs[12]); + break; + case UC_X86_REG_R12W: + *(int16_t *)value = READ_WORD(env->regs[12]); + break; + case UC_X86_REG_R12B: + *(int8_t *)value = READ_BYTE_L(env->regs[12]); + break; + case UC_X86_REG_R13: + *(int64_t *)value = READ_QWORD(env->regs[13]); + break; + case UC_X86_REG_R13D: + *(int32_t *)value = READ_DWORD(env->regs[13]); + break; + case UC_X86_REG_R13W: + *(int16_t *)value = READ_WORD(env->regs[13]); + break; + case UC_X86_REG_R13B: + *(int8_t *)value = READ_BYTE_L(env->regs[13]); + break; + case UC_X86_REG_R14: + *(int64_t *)value = READ_QWORD(env->regs[14]); + break; + case UC_X86_REG_R14D: + *(int32_t *)value = READ_DWORD(env->regs[14]); + break; + case UC_X86_REG_R14W: + *(int16_t *)value = READ_WORD(env->regs[14]); + break; + case UC_X86_REG_R14B: + *(int8_t *)value = READ_BYTE_L(env->regs[14]); + break; + case UC_X86_REG_R15: + *(int64_t *)value = READ_QWORD(env->regs[15]); + break; + case UC_X86_REG_R15D: + *(int32_t *)value = READ_DWORD(env->regs[15]); + break; + case UC_X86_REG_R15W: + *(int16_t *)value = READ_WORD(env->regs[15]); + break; + case UC_X86_REG_R15B: + *(int8_t *)value = READ_BYTE_L(env->regs[15]); + break; + case UC_X86_REG_IDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->idt.limit; + ((uc_x86_mmr *)value)->base = env->idt.base; + break; + case UC_X86_REG_GDTR: + ((uc_x86_mmr *)value)->limit = (uint16_t)env->gdt.limit; + ((uc_x86_mmr *)value)->base = env->gdt.base; + break; + case UC_X86_REG_LDTR: + ((uc_x86_mmr *)value)->limit = env->ldt.limit; + ((uc_x86_mmr *)value)->base = env->ldt.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->ldt.selector; + ((uc_x86_mmr *)value)->flags = env->ldt.flags; + break; + case UC_X86_REG_TR: + ((uc_x86_mmr *)value)->limit = env->tr.limit; + ((uc_x86_mmr *)value)->base = env->tr.base; + ((uc_x86_mmr *)value)->selector = (uint16_t)env->tr.selector; + ((uc_x86_mmr *)value)->flags = env->tr.flags; + break; + case UC_X86_REG_MSR: + x86_msr_read(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + *(uint32_t *)value = env->mxcsr; + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *dst = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + dst[0] = reg->_d[0]; + dst[1] = reg->_d[1]; + break; + } + case UC_X86_REG_FS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_FS].base; + break; + case UC_X86_REG_GS_BASE: + *(uint64_t *)value = (uint64_t)env->segs[R_GS].base; + break; + } + break; #endif } return; } -static int reg_write(CPUX86State *env, unsigned int regid, const void *value, uc_mode mode) +static int reg_write(CPUX86State *env, unsigned int regid, const void *value, + uc_mode mode) { int ret; - - switch(regid) { - default: - break; - case UC_X86_REG_FP0: - case UC_X86_REG_FP1: - case UC_X86_REG_FP2: - case UC_X86_REG_FP3: - case UC_X86_REG_FP4: - case UC_X86_REG_FP5: - case UC_X86_REG_FP6: - case UC_X86_REG_FP7: - { - uint64_t mant = *(uint64_t*) value; - uint16_t upper = *(uint16_t*) ((char*)value + sizeof(uint64_t)); - env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); - } - return 0; - case UC_X86_REG_FPSW: - { - uint16_t fpus = *(uint16_t*) value; - env->fpus = fpus & ~0x3800; - env->fpstt = (fpus >> 11) & 0x7; - } - return 0; - case UC_X86_REG_FPCW: - cpu_set_fpuc(env, *(uint16_t *)value); - return 0; - case UC_X86_REG_FPTAG: - { - int i; - uint16_t fptag = *(uint16_t*) value; - for (i = 0; i < 8; i++) { - env->fptags[i] = ((fptag & 3) == 3); - fptag >>= 2; - } - return 0; - } - break; - case UC_X86_REG_XMM0: - case UC_X86_REG_XMM1: - case UC_X86_REG_XMM2: - case UC_X86_REG_XMM3: - case UC_X86_REG_XMM4: - case UC_X86_REG_XMM5: - case UC_X86_REG_XMM6: - case UC_X86_REG_XMM7: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - return 0; - } - case UC_X86_REG_ST0: - case UC_X86_REG_ST1: - case UC_X86_REG_ST2: - case UC_X86_REG_ST3: - case UC_X86_REG_ST4: - case UC_X86_REG_ST5: - case UC_X86_REG_ST6: - case UC_X86_REG_ST7: - { - // value must be big enough to keep 80 bits (10 bytes) - memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); - return 0; - } - case UC_X86_REG_YMM0: - case UC_X86_REG_YMM1: - case UC_X86_REG_YMM2: - case UC_X86_REG_YMM3: - case UC_X86_REG_YMM4: - case UC_X86_REG_YMM5: - case UC_X86_REG_YMM6: - case UC_X86_REG_YMM7: - case UC_X86_REG_YMM8: - case UC_X86_REG_YMM9: - case UC_X86_REG_YMM10: - case UC_X86_REG_YMM11: - case UC_X86_REG_YMM12: - case UC_X86_REG_YMM13: - case UC_X86_REG_YMM14: - case UC_X86_REG_YMM15: - { - float64 *src = (float64*)value; - XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; - XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; - lo_reg->_d[0] = src[0]; - lo_reg->_d[1] = src[1]; - hi_reg->_d[0] = src[2]; - hi_reg->_d[1] = src[3]; - return 0; - } + switch (regid) { + default: + break; + case UC_X86_REG_FP0: + case UC_X86_REG_FP1: + case UC_X86_REG_FP2: + case UC_X86_REG_FP3: + case UC_X86_REG_FP4: + case UC_X86_REG_FP5: + case UC_X86_REG_FP6: + case UC_X86_REG_FP7: { + uint64_t mant = *(uint64_t *)value; + uint16_t upper = *(uint16_t *)((char *)value + sizeof(uint64_t)); + env->fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper); + } + return 0; + case UC_X86_REG_FPSW: { + uint16_t fpus = *(uint16_t *)value; + env->fpus = fpus & ~0x3800; + env->fpstt = (fpus >> 11) & 0x7; + } + return 0; + case UC_X86_REG_FPCW: + cpu_set_fpuc(env, *(uint16_t *)value); + return 0; + case UC_X86_REG_FPTAG: { + int i; + uint16_t fptag = *(uint16_t *)value; + for (i = 0; i < 8; i++) { + env->fptags[i] = ((fptag & 3) == 3); + fptag >>= 2; + } + + return 0; + } break; + case UC_X86_REG_XMM0: + case UC_X86_REG_XMM1: + case UC_X86_REG_XMM2: + case UC_X86_REG_XMM3: + case UC_X86_REG_XMM4: + case UC_X86_REG_XMM5: + case UC_X86_REG_XMM6: + case UC_X86_REG_XMM7: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + return 0; + } + case UC_X86_REG_ST0: + case UC_X86_REG_ST1: + case UC_X86_REG_ST2: + case UC_X86_REG_ST3: + case UC_X86_REG_ST4: + case UC_X86_REG_ST5: + case UC_X86_REG_ST6: + case UC_X86_REG_ST7: { + // value must be big enough to keep 80 bits (10 bytes) + memcpy(&FPST(regid - UC_X86_REG_ST0), value, 10); + return 0; + } + case UC_X86_REG_YMM0: + case UC_X86_REG_YMM1: + case UC_X86_REG_YMM2: + case UC_X86_REG_YMM3: + case UC_X86_REG_YMM4: + case UC_X86_REG_YMM5: + case UC_X86_REG_YMM6: + case UC_X86_REG_YMM7: + case UC_X86_REG_YMM8: + case UC_X86_REG_YMM9: + case UC_X86_REG_YMM10: + case UC_X86_REG_YMM11: + case UC_X86_REG_YMM12: + case UC_X86_REG_YMM13: + case UC_X86_REG_YMM14: + case UC_X86_REG_YMM15: { + float64 *src = (float64 *)value; + XMMReg *lo_reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_YMM0]; + XMMReg *hi_reg = &env->ymmh_regs[regid - UC_X86_REG_YMM0]; + lo_reg->_d[0] = src[0]; + lo_reg->_d[1] = src[1]; + hi_reg->_d[0] = src[2]; + hi_reg->_d[1] = src[3]; + return 0; + } } - switch(mode) { + switch (mode) { + default: + break; + + case UC_MODE_16: + switch (regid) { default: break; - - case UC_MODE_16: - switch(regid) { - default: break; - case UC_X86_REG_ES: - load_seg_16_helper(env, R_ES, *(uint16_t *)value); - return 0; - case UC_X86_REG_SS: - load_seg_16_helper(env, R_SS, *(uint16_t *)value); - return 0; - case UC_X86_REG_DS: - load_seg_16_helper(env, R_DS, *(uint16_t *)value); - return 0; - case UC_X86_REG_FS: - load_seg_16_helper(env, R_FS, *(uint16_t *)value); - return 0; - case UC_X86_REG_GS: - load_seg_16_helper(env, R_GS, *(uint16_t *)value); - return 0; - } - // fall-thru - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_EAX: - env->regs[R_EAX] = *(uint32_t *)value; - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_EBX: - env->regs[R_EBX] = *(uint32_t *)value; - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_ECX: - env->regs[R_ECX] = *(uint32_t *)value; - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_EDX: - env->regs[R_EDX] = *(uint32_t *)value; - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_ESP: - env->regs[R_ESP] = *(uint32_t *)value; - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_EBP: - env->regs[R_EBP] = *(uint32_t *)value; - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_ESI: - env->regs[R_ESI] = *(uint32_t *)value; - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_EDI: - env->regs[R_EDI] = *(uint32_t *)value; - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - env->eip = *(uint16_t *)value; - break; - case UC_X86_REG_CS: - ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); - break; - case UC_X86_REG_DS: - ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); - break; - case UC_X86_REG_SS: - ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); - break; - case UC_X86_REG_ES: - ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - /* - // Don't think base registers are a "thing" on x86 - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint32_t *)value; - continue; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint32_t *)value; - continue; - */ - } + case UC_X86_REG_ES: + load_seg_16_helper(env, R_ES, *(uint16_t *)value); + return 0; + case UC_X86_REG_SS: + load_seg_16_helper(env, R_SS, *(uint16_t *)value); + return 0; + case UC_X86_REG_DS: + load_seg_16_helper(env, R_DS, *(uint16_t *)value); + return 0; + case UC_X86_REG_FS: + load_seg_16_helper(env, R_FS, *(uint16_t *)value); + return 0; + case UC_X86_REG_GS: + load_seg_16_helper(env, R_GS, *(uint16_t *)value); + return 0; + } + // fall-thru + case UC_MODE_32: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint32_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint32_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_EAX: + env->regs[R_EAX] = *(uint32_t *)value; + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_EBX: + env->regs[R_EBX] = *(uint32_t *)value; + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_ECX: + env->regs[R_ECX] = *(uint32_t *)value; + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_EDX: + env->regs[R_EDX] = *(uint32_t *)value; + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_ESP: + env->regs[R_ESP] = *(uint32_t *)value; + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_EBP: + env->regs[R_EBP] = *(uint32_t *)value; + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_ESI: + env->regs[R_ESI] = *(uint32_t *)value; + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_EDI: + env->regs[R_EDI] = *(uint32_t *)value; + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + env->eip = *(uint16_t *)value; + break; + case UC_X86_REG_CS: + ret = uc_check_cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_CS, *(uint16_t *)value); + break; + case UC_X86_REG_DS: + ret = uc_check_cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_DS, *(uint16_t *)value); + break; + case UC_X86_REG_SS: + ret = uc_check_cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_SS, *(uint16_t *)value); + break; + case UC_X86_REG_ES: + ret = uc_check_cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_ES, *(uint16_t *)value); + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = (uint32_t)((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = (uint32_t)((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + /* + // Don't think base registers are a "thing" on x86 + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint32_t *)value; + continue; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint32_t *)value; + continue; + */ + } + break; #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_CR0: - case UC_X86_REG_CR1: - case UC_X86_REG_CR2: - case UC_X86_REG_CR3: - case UC_X86_REG_CR4: - env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; - break; - case UC_X86_REG_DR0: - case UC_X86_REG_DR1: - case UC_X86_REG_DR2: - case UC_X86_REG_DR3: - case UC_X86_REG_DR4: - case UC_X86_REG_DR5: - case UC_X86_REG_DR6: - case UC_X86_REG_DR7: - env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; - break; - case UC_X86_REG_FLAGS: - cpu_load_eflags(env, *(uint16_t*)value, -1); - break; - case UC_X86_REG_EFLAGS: - cpu_load_eflags(env, *(uint32_t *)value, -1); - break; - case UC_X86_REG_RFLAGS: - cpu_load_eflags(env, *(uint64_t *)value, -1); - break; - case UC_X86_REG_RAX: - env->regs[R_EAX] = *(uint64_t *)value; - break; - case UC_X86_REG_EAX: - WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); - break; - case UC_X86_REG_AX: - WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); - break; - case UC_X86_REG_AH: - WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_AL: - WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); - break; - case UC_X86_REG_RBX: - env->regs[R_EBX] = *(uint64_t *)value; - break; - case UC_X86_REG_EBX: - WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); - break; - case UC_X86_REG_BX: - WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); - break; - case UC_X86_REG_BH: - WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_BL: - WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); - break; - case UC_X86_REG_RCX: - env->regs[R_ECX] = *(uint64_t *)value; - break; - case UC_X86_REG_ECX: - WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); - break; - case UC_X86_REG_CX: - WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); - break; - case UC_X86_REG_CH: - WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_CL: - WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); - break; - case UC_X86_REG_RDX: - env->regs[R_EDX] = *(uint64_t *)value; - break; - case UC_X86_REG_EDX: - WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); - break; - case UC_X86_REG_DX: - WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); - break; - case UC_X86_REG_DH: - WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_DL: - WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); - break; - case UC_X86_REG_RSP: - env->regs[R_ESP] = *(uint64_t *)value; - break; - case UC_X86_REG_ESP: - WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); - break; - case UC_X86_REG_SP: - WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); - break; - case UC_X86_REG_SPL: - WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); - break; - case UC_X86_REG_RBP: - env->regs[R_EBP] = *(uint64_t *)value; - break; - case UC_X86_REG_EBP: - WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); - break; - case UC_X86_REG_BP: - WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); - break; - case UC_X86_REG_BPL: - WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); - break; - case UC_X86_REG_RSI: - env->regs[R_ESI] = *(uint64_t *)value; - break; - case UC_X86_REG_ESI: - WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); - break; - case UC_X86_REG_SI: - WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); - break; - case UC_X86_REG_SIL: - WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); - break; - case UC_X86_REG_RDI: - env->regs[R_EDI] = *(uint64_t *)value; - break; - case UC_X86_REG_EDI: - WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); - break; - case UC_X86_REG_DI: - WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); - break; - case UC_X86_REG_DIL: - WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); - break; - case UC_X86_REG_RIP: - env->eip = *(uint64_t *)value; - break; - case UC_X86_REG_EIP: - env->eip = *(uint32_t *)value; - break; - case UC_X86_REG_IP: - WRITE_WORD(env->eip, *(uint16_t *)value); - break; - case UC_X86_REG_CS: - env->segs[R_CS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_DS: - env->segs[R_DS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_SS: - env->segs[R_SS].selector = *(uint16_t *)value; - break; - case UC_X86_REG_ES: - env->segs[R_ES].selector = *(uint16_t *)value; - break; - case UC_X86_REG_FS: - ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); - break; - case UC_X86_REG_GS: - ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - if (ret) { - return ret; - } - cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); - break; - case UC_X86_REG_R8: - env->regs[8] = *(uint64_t *)value; - break; - case UC_X86_REG_R8D: - WRITE_DWORD(env->regs[8], *(uint32_t *)value); - break; - case UC_X86_REG_R8W: - WRITE_WORD(env->regs[8], *(uint16_t *)value); - break; - case UC_X86_REG_R8B: - WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); - break; - case UC_X86_REG_R9: - env->regs[9] = *(uint64_t *)value; - break; - case UC_X86_REG_R9D: - WRITE_DWORD(env->regs[9], *(uint32_t *)value); - break; - case UC_X86_REG_R9W: - WRITE_WORD(env->regs[9], *(uint16_t *)value); - break; - case UC_X86_REG_R9B: - WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); - break; - case UC_X86_REG_R10: - env->regs[10] = *(uint64_t *)value; - break; - case UC_X86_REG_R10D: - WRITE_DWORD(env->regs[10], *(uint32_t *)value); - break; - case UC_X86_REG_R10W: - WRITE_WORD(env->regs[10], *(uint16_t *)value); - break; - case UC_X86_REG_R10B: - WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); - break; - case UC_X86_REG_R11: - env->regs[11] = *(uint64_t *)value; - break; - case UC_X86_REG_R11D: - WRITE_DWORD(env->regs[11], *(uint32_t *)value); - break; - case UC_X86_REG_R11W: - WRITE_WORD(env->regs[11], *(uint16_t *)value); - break; - case UC_X86_REG_R11B: - WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); - break; - case UC_X86_REG_R12: - env->regs[12] = *(uint64_t *)value; - break; - case UC_X86_REG_R12D: - WRITE_DWORD(env->regs[12], *(uint32_t *)value); - break; - case UC_X86_REG_R12W: - WRITE_WORD(env->regs[12], *(uint16_t *)value); - break; - case UC_X86_REG_R12B: - WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); - break; - case UC_X86_REG_R13: - env->regs[13] = *(uint64_t *)value; - break; - case UC_X86_REG_R13D: - WRITE_DWORD(env->regs[13], *(uint32_t *)value); - break; - case UC_X86_REG_R13W: - WRITE_WORD(env->regs[13], *(uint16_t *)value); - break; - case UC_X86_REG_R13B: - WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); - break; - case UC_X86_REG_R14: - env->regs[14] = *(uint64_t *)value; - break; - case UC_X86_REG_R14D: - WRITE_DWORD(env->regs[14], *(uint32_t *)value); - break; - case UC_X86_REG_R14W: - WRITE_WORD(env->regs[14], *(uint16_t *)value); - break; - case UC_X86_REG_R14B: - WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); - break; - case UC_X86_REG_R15: - env->regs[15] = *(uint64_t *)value; - break; - case UC_X86_REG_R15D: - WRITE_DWORD(env->regs[15], *(uint32_t *)value); - break; - case UC_X86_REG_R15W: - WRITE_WORD(env->regs[15], *(uint16_t *)value); - break; - case UC_X86_REG_R15B: - WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); - break; - case UC_X86_REG_IDTR: - env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->idt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_GDTR: - env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; - env->gdt.base = ((uc_x86_mmr *)value)->base; - break; - case UC_X86_REG_LDTR: - env->ldt.limit = ((uc_x86_mmr *)value)->limit; - env->ldt.base = ((uc_x86_mmr *)value)->base; - env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->ldt.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_TR: - env->tr.limit = ((uc_x86_mmr *)value)->limit; - env->tr.base = ((uc_x86_mmr *)value)->base; - env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; - env->tr.flags = ((uc_x86_mmr *)value)->flags; - break; - case UC_X86_REG_MSR: - x86_msr_write(env, (uc_x86_msr *)value); - break; - case UC_X86_REG_MXCSR: - cpu_set_mxcsr(env, *(uint32_t *)value); - break; - case UC_X86_REG_XMM8: - case UC_X86_REG_XMM9: - case UC_X86_REG_XMM10: - case UC_X86_REG_XMM11: - case UC_X86_REG_XMM12: - case UC_X86_REG_XMM13: - case UC_X86_REG_XMM14: - case UC_X86_REG_XMM15: - { - float64 *src = (float64*)value; - XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; - reg->_d[0] = src[0]; - reg->_d[1] = src[1]; - break; - } - case UC_X86_REG_FS_BASE: - env->segs[R_FS].base = *(uint64_t *)value; - return 0; - case UC_X86_REG_GS_BASE: - env->segs[R_GS].base = *(uint64_t *)value; - return 0; - } + case UC_MODE_64: + switch (regid) { + default: break; + case UC_X86_REG_CR0: + case UC_X86_REG_CR1: + case UC_X86_REG_CR2: + case UC_X86_REG_CR3: + case UC_X86_REG_CR4: + env->cr[regid - UC_X86_REG_CR0] = *(uint64_t *)value; + break; + case UC_X86_REG_DR0: + case UC_X86_REG_DR1: + case UC_X86_REG_DR2: + case UC_X86_REG_DR3: + case UC_X86_REG_DR4: + case UC_X86_REG_DR5: + case UC_X86_REG_DR6: + case UC_X86_REG_DR7: + env->dr[regid - UC_X86_REG_DR0] = *(uint64_t *)value; + break; + case UC_X86_REG_FLAGS: + cpu_load_eflags(env, *(uint16_t *)value, -1); + break; + case UC_X86_REG_EFLAGS: + cpu_load_eflags(env, *(uint32_t *)value, -1); + break; + case UC_X86_REG_RFLAGS: + cpu_load_eflags(env, *(uint64_t *)value, -1); + break; + case UC_X86_REG_RAX: + env->regs[R_EAX] = *(uint64_t *)value; + break; + case UC_X86_REG_EAX: + WRITE_DWORD(env->regs[R_EAX], *(uint32_t *)value); + break; + case UC_X86_REG_AX: + WRITE_WORD(env->regs[R_EAX], *(uint16_t *)value); + break; + case UC_X86_REG_AH: + WRITE_BYTE_H(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_AL: + WRITE_BYTE_L(env->regs[R_EAX], *(uint8_t *)value); + break; + case UC_X86_REG_RBX: + env->regs[R_EBX] = *(uint64_t *)value; + break; + case UC_X86_REG_EBX: + WRITE_DWORD(env->regs[R_EBX], *(uint32_t *)value); + break; + case UC_X86_REG_BX: + WRITE_WORD(env->regs[R_EBX], *(uint16_t *)value); + break; + case UC_X86_REG_BH: + WRITE_BYTE_H(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_BL: + WRITE_BYTE_L(env->regs[R_EBX], *(uint8_t *)value); + break; + case UC_X86_REG_RCX: + env->regs[R_ECX] = *(uint64_t *)value; + break; + case UC_X86_REG_ECX: + WRITE_DWORD(env->regs[R_ECX], *(uint32_t *)value); + break; + case UC_X86_REG_CX: + WRITE_WORD(env->regs[R_ECX], *(uint16_t *)value); + break; + case UC_X86_REG_CH: + WRITE_BYTE_H(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_CL: + WRITE_BYTE_L(env->regs[R_ECX], *(uint8_t *)value); + break; + case UC_X86_REG_RDX: + env->regs[R_EDX] = *(uint64_t *)value; + break; + case UC_X86_REG_EDX: + WRITE_DWORD(env->regs[R_EDX], *(uint32_t *)value); + break; + case UC_X86_REG_DX: + WRITE_WORD(env->regs[R_EDX], *(uint16_t *)value); + break; + case UC_X86_REG_DH: + WRITE_BYTE_H(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_DL: + WRITE_BYTE_L(env->regs[R_EDX], *(uint8_t *)value); + break; + case UC_X86_REG_RSP: + env->regs[R_ESP] = *(uint64_t *)value; + break; + case UC_X86_REG_ESP: + WRITE_DWORD(env->regs[R_ESP], *(uint32_t *)value); + break; + case UC_X86_REG_SP: + WRITE_WORD(env->regs[R_ESP], *(uint16_t *)value); + break; + case UC_X86_REG_SPL: + WRITE_BYTE_L(env->regs[R_ESP], *(uint8_t *)value); + break; + case UC_X86_REG_RBP: + env->regs[R_EBP] = *(uint64_t *)value; + break; + case UC_X86_REG_EBP: + WRITE_DWORD(env->regs[R_EBP], *(uint32_t *)value); + break; + case UC_X86_REG_BP: + WRITE_WORD(env->regs[R_EBP], *(uint16_t *)value); + break; + case UC_X86_REG_BPL: + WRITE_BYTE_L(env->regs[R_EBP], *(uint8_t *)value); + break; + case UC_X86_REG_RSI: + env->regs[R_ESI] = *(uint64_t *)value; + break; + case UC_X86_REG_ESI: + WRITE_DWORD(env->regs[R_ESI], *(uint32_t *)value); + break; + case UC_X86_REG_SI: + WRITE_WORD(env->regs[R_ESI], *(uint16_t *)value); + break; + case UC_X86_REG_SIL: + WRITE_BYTE_L(env->regs[R_ESI], *(uint8_t *)value); + break; + case UC_X86_REG_RDI: + env->regs[R_EDI] = *(uint64_t *)value; + break; + case UC_X86_REG_EDI: + WRITE_DWORD(env->regs[R_EDI], *(uint32_t *)value); + break; + case UC_X86_REG_DI: + WRITE_WORD(env->regs[R_EDI], *(uint16_t *)value); + break; + case UC_X86_REG_DIL: + WRITE_BYTE_L(env->regs[R_EDI], *(uint8_t *)value); + break; + case UC_X86_REG_RIP: + env->eip = *(uint64_t *)value; + break; + case UC_X86_REG_EIP: + env->eip = *(uint32_t *)value; + break; + case UC_X86_REG_IP: + WRITE_WORD(env->eip, *(uint16_t *)value); + break; + case UC_X86_REG_CS: + env->segs[R_CS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_DS: + env->segs[R_DS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_SS: + env->segs[R_SS].selector = *(uint16_t *)value; + break; + case UC_X86_REG_ES: + env->segs[R_ES].selector = *(uint16_t *)value; + break; + case UC_X86_REG_FS: + ret = uc_check_cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_FS, *(uint16_t *)value); + break; + case UC_X86_REG_GS: + ret = uc_check_cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + if (ret) { + return ret; + } + cpu_x86_load_seg(env, R_GS, *(uint16_t *)value); + break; + case UC_X86_REG_R8: + env->regs[8] = *(uint64_t *)value; + break; + case UC_X86_REG_R8D: + WRITE_DWORD(env->regs[8], *(uint32_t *)value); + break; + case UC_X86_REG_R8W: + WRITE_WORD(env->regs[8], *(uint16_t *)value); + break; + case UC_X86_REG_R8B: + WRITE_BYTE_L(env->regs[8], *(uint8_t *)value); + break; + case UC_X86_REG_R9: + env->regs[9] = *(uint64_t *)value; + break; + case UC_X86_REG_R9D: + WRITE_DWORD(env->regs[9], *(uint32_t *)value); + break; + case UC_X86_REG_R9W: + WRITE_WORD(env->regs[9], *(uint16_t *)value); + break; + case UC_X86_REG_R9B: + WRITE_BYTE_L(env->regs[9], *(uint8_t *)value); + break; + case UC_X86_REG_R10: + env->regs[10] = *(uint64_t *)value; + break; + case UC_X86_REG_R10D: + WRITE_DWORD(env->regs[10], *(uint32_t *)value); + break; + case UC_X86_REG_R10W: + WRITE_WORD(env->regs[10], *(uint16_t *)value); + break; + case UC_X86_REG_R10B: + WRITE_BYTE_L(env->regs[10], *(uint8_t *)value); + break; + case UC_X86_REG_R11: + env->regs[11] = *(uint64_t *)value; + break; + case UC_X86_REG_R11D: + WRITE_DWORD(env->regs[11], *(uint32_t *)value); + break; + case UC_X86_REG_R11W: + WRITE_WORD(env->regs[11], *(uint16_t *)value); + break; + case UC_X86_REG_R11B: + WRITE_BYTE_L(env->regs[11], *(uint8_t *)value); + break; + case UC_X86_REG_R12: + env->regs[12] = *(uint64_t *)value; + break; + case UC_X86_REG_R12D: + WRITE_DWORD(env->regs[12], *(uint32_t *)value); + break; + case UC_X86_REG_R12W: + WRITE_WORD(env->regs[12], *(uint16_t *)value); + break; + case UC_X86_REG_R12B: + WRITE_BYTE_L(env->regs[12], *(uint8_t *)value); + break; + case UC_X86_REG_R13: + env->regs[13] = *(uint64_t *)value; + break; + case UC_X86_REG_R13D: + WRITE_DWORD(env->regs[13], *(uint32_t *)value); + break; + case UC_X86_REG_R13W: + WRITE_WORD(env->regs[13], *(uint16_t *)value); + break; + case UC_X86_REG_R13B: + WRITE_BYTE_L(env->regs[13], *(uint8_t *)value); + break; + case UC_X86_REG_R14: + env->regs[14] = *(uint64_t *)value; + break; + case UC_X86_REG_R14D: + WRITE_DWORD(env->regs[14], *(uint32_t *)value); + break; + case UC_X86_REG_R14W: + WRITE_WORD(env->regs[14], *(uint16_t *)value); + break; + case UC_X86_REG_R14B: + WRITE_BYTE_L(env->regs[14], *(uint8_t *)value); + break; + case UC_X86_REG_R15: + env->regs[15] = *(uint64_t *)value; + break; + case UC_X86_REG_R15D: + WRITE_DWORD(env->regs[15], *(uint32_t *)value); + break; + case UC_X86_REG_R15W: + WRITE_WORD(env->regs[15], *(uint16_t *)value); + break; + case UC_X86_REG_R15B: + WRITE_BYTE_L(env->regs[15], *(uint8_t *)value); + break; + case UC_X86_REG_IDTR: + env->idt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->idt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_GDTR: + env->gdt.limit = (uint16_t)((uc_x86_mmr *)value)->limit; + env->gdt.base = ((uc_x86_mmr *)value)->base; + break; + case UC_X86_REG_LDTR: + env->ldt.limit = ((uc_x86_mmr *)value)->limit; + env->ldt.base = ((uc_x86_mmr *)value)->base; + env->ldt.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->ldt.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_TR: + env->tr.limit = ((uc_x86_mmr *)value)->limit; + env->tr.base = ((uc_x86_mmr *)value)->base; + env->tr.selector = (uint16_t)((uc_x86_mmr *)value)->selector; + env->tr.flags = ((uc_x86_mmr *)value)->flags; + break; + case UC_X86_REG_MSR: + x86_msr_write(env, (uc_x86_msr *)value); + break; + case UC_X86_REG_MXCSR: + cpu_set_mxcsr(env, *(uint32_t *)value); + break; + case UC_X86_REG_XMM8: + case UC_X86_REG_XMM9: + case UC_X86_REG_XMM10: + case UC_X86_REG_XMM11: + case UC_X86_REG_XMM12: + case UC_X86_REG_XMM13: + case UC_X86_REG_XMM14: + case UC_X86_REG_XMM15: { + float64 *src = (float64 *)value; + XMMReg *reg = (XMMReg *)&env->xmm_regs[regid - UC_X86_REG_XMM0]; + reg->_d[0] = src[0]; + reg->_d[1] = src[1]; + break; + } + case UC_X86_REG_FS_BASE: + env->segs[R_FS].base = *(uint64_t *)value; + return 0; + case UC_X86_REG_GS_BASE: + env->segs[R_GS].base = *(uint64_t *)value; + return 0; + } + break; #endif } return 0; } -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; @@ -1466,9 +1463,10 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUX86State* env = &(X86_CPU(uc->cpu)->env); + CPUX86State *env = &(X86_CPU(uc->cpu)->env); int i; int ret; @@ -1476,37 +1474,37 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, uc->mode); - if (ret){ + if (ret) { return ret; } - switch(uc->mode) { + switch (uc->mode) { + default: + break; + case UC_MODE_32: + switch (regid) { default: break; - case UC_MODE_32: - switch(regid) { - default: - break; - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #ifdef TARGET_X86_64 - case UC_MODE_64: - switch(regid) { - default: - break; - case UC_X86_REG_RIP: - case UC_X86_REG_EIP: - case UC_X86_REG_IP: - // force to quit execution and flush TB - uc->quit_request = true; - uc_emu_stop(uc); - break; - } + case UC_MODE_64: + switch (regid) { + default: + break; + case UC_X86_REG_RIP: + case UC_X86_REG_EIP: + case UC_X86_REG_IP: + // force to quit execution and flush TB + uc->quit_request = true; + uc_emu_stop(uc); + break; + } #endif } } @@ -1515,7 +1513,8 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i } DEFAULT_VISIBILITY -int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1530,7 +1529,8 @@ int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals } DEFAULT_VISIBILITY -int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { CPUX86State *env = (CPUX86State *)ctx->data; int i; @@ -1540,7 +1540,7 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons unsigned int regid = regs[i]; const void *value = vals[i]; ret = reg_write(env, regid, value, ctx->mode); - if (ret){ + if (ret) { return ret; } } @@ -1550,22 +1550,20 @@ int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *cons static bool x86_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case EXCP06_ILLOP: - return true; + switch (intno) { + default: + return false; + case EXCP06_ILLOP: + return true; } } static bool x86_insn_hook_validate(uint32_t insn_enum) { - //for x86 we can only hook IN, OUT, and SYSCALL - if (insn_enum != UC_X86_INS_IN - && insn_enum != UC_X86_INS_OUT - && insn_enum != UC_X86_INS_SYSCALL - && insn_enum != UC_X86_INS_SYSENTER - && insn_enum != UC_X86_INS_CPUID) { + // for x86 we can only hook IN, OUT, and SYSCALL + if (insn_enum != UC_X86_INS_IN && insn_enum != UC_X86_INS_OUT && + insn_enum != UC_X86_INS_SYSCALL && insn_enum != UC_X86_INS_SYSENTER && + insn_enum != UC_X86_INS_CPUID) { return false; } return true; @@ -1585,7 +1583,7 @@ static int x86_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void x86_uc_init(struct uc_struct* uc) +void x86_uc_init(struct uc_struct *uc) { uc->reg_read = x86_reg_read; uc->reg_write = x86_reg_write; diff --git a/qemu/target/i386/unicorn.h b/qemu/target/i386/unicorn.h index b07be9d2..7c456cfb 100644 --- a/qemu/target/i386/unicorn.h +++ b/qemu/target/i386/unicorn.h @@ -6,12 +6,16 @@ #define UC_QEMU_TARGET_I386_H // functions to read & write registers -int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int x86_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int x86_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void x86_reg_reset(struct uc_struct *uc); -void x86_uc_init(struct uc_struct* uc); +void x86_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/m68k/unicorn.c b/qemu/target/m68k/unicorn.c index 1b9c5b14..72ce6ce5 100644 --- a/qemu/target/m68k/unicorn.c +++ b/qemu/target/m68k/unicorn.c @@ -15,7 +15,7 @@ static void m68k_set_pc(struct uc_struct *uc, uint64_t address) ((CPUM68KState *)uc->cpu->env_ptr)->pc = address; } -static void m68k_release(void* ctx) +static void m68k_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; @@ -51,11 +51,12 @@ static void reg_read(CPUM68KState *env, unsigned int regid, void *value) else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) *(int32_t *)value = env->dregs[regid - UC_M68K_REG_D0]; else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - *(int32_t *)value = env->pc; - break; + switch (regid) { + default: + break; + case UC_M68K_REG_PC: + *(int32_t *)value = env->pc; + break; } } @@ -69,18 +70,20 @@ static void reg_write(CPUM68KState *env, unsigned int regid, const void *value) else if (regid >= UC_M68K_REG_D0 && regid <= UC_M68K_REG_D7) env->dregs[regid - UC_M68K_REG_D0] = *(uint32_t *)value; else { - switch(regid) { - default: break; - case UC_M68K_REG_PC: - env->pc = *(uint32_t *)value; - break; + switch (regid) { + default: + break; + case UC_M68K_REG_PC: + env->pc = *(uint32_t *)value; + break; } } } -int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { - CPUM68KState* env = &(M68K_CPU(uc->cpu)->env); + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { @@ -92,16 +95,17 @@ int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou return 0; } -int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUM68KState* env = &(M68K_CPU(uc->cpu)->env); + CPUM68KState *env = &(M68K_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if (regid == UC_M68K_REG_PC){ + if (regid == UC_M68K_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -112,9 +116,10 @@ int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, } DEFAULT_VISIBILITY -int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { - CPUM68KState* env = (CPUM68KState* )ctx->data; + CPUM68KState *env = (CPUM68KState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -127,9 +132,10 @@ int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **val } DEFAULT_VISIBILITY -int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { - CPUM68KState* env = (CPUM68KState* )ctx->data; + CPUM68KState *env = (CPUM68KState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -153,7 +159,7 @@ static int m68k_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void m68k_uc_init(struct uc_struct* uc) +void m68k_uc_init(struct uc_struct *uc) { uc->release = m68k_release; uc->reg_read = m68k_reg_read; diff --git a/qemu/target/m68k/unicorn.h b/qemu/target/m68k/unicorn.h index 2eeeaae8..ebd5c310 100644 --- a/qemu/target/m68k/unicorn.h +++ b/qemu/target/m68k/unicorn.h @@ -5,12 +5,16 @@ #define UC_QEMU_TARGET_M68K_H // functions to read & write registers -int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); -int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int m68k_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int m68k_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); +int m68k_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int m68k_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void m68k_reg_reset(struct uc_struct *uc); -void m68k_uc_init(struct uc_struct* uc); +void m68k_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/mips/unicorn.c b/qemu/target/mips/unicorn.c index 2c9dae5f..c2840828 100644 --- a/qemu/target/mips/unicorn.c +++ b/qemu/target/mips/unicorn.c @@ -37,7 +37,6 @@ static void mips_set_pc(struct uc_struct *uc, uint64_t address) ((CPUMIPSState *)uc->cpu->env_ptr)->active_tc.PC = address; } - static void mips_release(void *ctx) { int i; @@ -75,20 +74,21 @@ static void reg_read(CPUMIPSState *env, unsigned int regid, void *value) if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) *(mipsreg_t *)value = env->active_tc.gpr[regid - UC_MIPS_REG_0]; else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - *(mipsreg_t *)value = env->active_tc.PC; - break; - case UC_MIPS_REG_CP0_CONFIG3: - *(mipsreg_t *)value = env->CP0_Config3; - break; - case UC_MIPS_REG_CP0_STATUS: - *(mipsreg_t *)value = env->CP0_Status; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; - break; + switch (regid) { + default: + break; + case UC_MIPS_REG_PC: + *(mipsreg_t *)value = env->active_tc.PC; + break; + case UC_MIPS_REG_CP0_CONFIG3: + *(mipsreg_t *)value = env->CP0_Config3; + break; + case UC_MIPS_REG_CP0_STATUS: + *(mipsreg_t *)value = env->CP0_Status; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; + break; } } @@ -100,31 +100,33 @@ static void reg_write(CPUMIPSState *env, unsigned int regid, const void *value) if (regid >= UC_MIPS_REG_0 && regid <= UC_MIPS_REG_31) env->active_tc.gpr[regid - UC_MIPS_REG_0] = *(mipsreg_t *)value; else { - switch(regid) { - default: break; - case UC_MIPS_REG_PC: - env->active_tc.PC = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_CONFIG3: - env->CP0_Config3 = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_STATUS: - // TODO: ALL CP0 REGS - // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf - // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf - env->CP0_Status = *(mipsreg_t *)value; - compute_hflags(env); - break; - case UC_MIPS_REG_CP0_USERLOCAL: - env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; - break; + switch (regid) { + default: + break; + case UC_MIPS_REG_PC: + env->active_tc.PC = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_CONFIG3: + env->CP0_Config3 = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_STATUS: + // TODO: ALL CP0 REGS + // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00090-2B-MIPS32PRA-AFP-06.02.pdf + // https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00582-2B-microMIPS32-AFP-05.04.pdf + env->CP0_Status = *(mipsreg_t *)value; + compute_hflags(env); + break; + case UC_MIPS_REG_CP0_USERLOCAL: + env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; + break; } } return; } -int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; @@ -138,7 +140,8 @@ int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int cou return 0; } -int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUMIPSState *env = &(MIPS_CPU(uc->cpu)->env); int i; @@ -147,7 +150,7 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_MIPS_REG_PC){ + if (regid == UC_MIPS_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -160,15 +163,19 @@ int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif #endif { @@ -187,15 +194,19 @@ DEFAULT_VISIBILITY DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif #endif { @@ -226,15 +237,15 @@ static int mips_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_MIPS64 #ifdef TARGET_WORDS_BIGENDIAN - void mips64_uc_init(struct uc_struct* uc) +void mips64_uc_init(struct uc_struct *uc) #else - void mips64el_uc_init(struct uc_struct* uc) +void mips64el_uc_init(struct uc_struct *uc) #endif #else // if TARGET_MIPS #ifdef TARGET_WORDS_BIGENDIAN - void mips_uc_init(struct uc_struct* uc) +void mips_uc_init(struct uc_struct *uc) #else - void mipsel_uc_init(struct uc_struct* uc) +void mipsel_uc_init(struct uc_struct *uc) #endif #endif { diff --git a/qemu/target/mips/unicorn.h b/qemu/target/mips/unicorn.h index 6179a3c3..5a806522 100644 --- a/qemu/target/mips/unicorn.h +++ b/qemu/target/mips/unicorn.h @@ -5,22 +5,32 @@ #define UC_QEMU_TARGET_MIPS_H // functions to read & write registers -int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int mips_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int mips_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int mips_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mipsel_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mipsel_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mips64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int mips64el_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int mips64el_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void mips_reg_reset(struct uc_struct *uc); -void mips_uc_init(struct uc_struct* uc); -void mipsel_uc_init(struct uc_struct* uc); -void mips64_uc_init(struct uc_struct* uc); -void mips64el_uc_init(struct uc_struct* uc); +void mips_uc_init(struct uc_struct *uc); +void mipsel_uc_init(struct uc_struct *uc); +void mips64_uc_init(struct uc_struct *uc); +void mips64el_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/ppc/unicorn.c b/qemu/target/ppc/unicorn.c index 66b7da7d..99438c27 100644 --- a/qemu/target/ppc/unicorn.c +++ b/qemu/target/ppc/unicorn.c @@ -18,14 +18,14 @@ typedef uint32_t ppcreg_t; static uint64_t ppc_mem_redirect(uint64_t address) { -/* // kseg0 range masks off high address bit - if (address >= 0x80000000 && address <= 0x9fffffff) - return address & 0x7fffffff; + /* // kseg0 range masks off high address bit + if (address >= 0x80000000 && address <= 0x9fffffff) + return address & 0x7fffffff; - // kseg1 range masks off top 3 address bits - if (address >= 0xa0000000 && address <= 0xbfffffff) { - return address & 0x1fffffff; - }*/ + // kseg1 range masks off top 3 address bits + if (address >= 0xa0000000 && address <= 0xbfffffff) { + return address & 0x1fffffff; + }*/ // no redirect return address; @@ -59,12 +59,12 @@ static void ppc_release(void *ctx) for (i = 0; i < 32; i++) { g_free(tcg_ctx->cpu_gpr[i]); } -// g_free(tcg_ctx->cpu_PC); + // g_free(tcg_ctx->cpu_PC); g_free(tcg_ctx->btarget); g_free(tcg_ctx->bcond); g_free(tcg_ctx->cpu_dspctrl); -// g_free(tcg_ctx->tb_ctx.tbs); + // g_free(tcg_ctx->tb_ctx.tbs); ppc_cpu_instance_finalize(tcg_ctx->uc->cpu); ppc_cpu_unrealize(tcg_ctx->uc->cpu); @@ -84,17 +84,18 @@ static void reg_read(CPUPPCState *env, unsigned int regid, void *value) if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) *(ppcreg_t *)value = env->gpr[regid - UC_PPC_REG_0]; else { - switch(regid) { - default: break; - case UC_PPC_REG_PC: - *(ppcreg_t *)value = env->nip; - break; -/* case UC_PPC_REG_CP0_CONFIG3: - *(mipsreg_t *)value = env->CP0_Config3; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; - break; */ + switch (regid) { + default: + break; + case UC_PPC_REG_PC: + *(ppcreg_t *)value = env->nip; + break; + /* case UC_PPC_REG_CP0_CONFIG3: + *(mipsreg_t *)value = env->CP0_Config3; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + *(mipsreg_t *)value = env->active_tc.CP0_UserLocal; + break; */ } } @@ -106,24 +107,26 @@ static void reg_write(CPUPPCState *env, unsigned int regid, const void *value) if (regid >= UC_PPC_REG_0 && regid <= UC_PPC_REG_31) env->gpr[regid - UC_PPC_REG_0] = *(ppcreg_t *)value; else { - switch(regid) { - default: break; - case UC_PPC_REG_PC: - env->nip = *(ppcreg_t *)value; - break; -/* case UC_MIPS_REG_CP0_CONFIG3: - env->CP0_Config3 = *(mipsreg_t *)value; - break; - case UC_MIPS_REG_CP0_USERLOCAL: - env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; - break; */ + switch (regid) { + default: + break; + case UC_PPC_REG_PC: + env->nip = *(ppcreg_t *)value; + break; + /* case UC_MIPS_REG_CP0_CONFIG3: + env->CP0_Config3 = *(mipsreg_t *)value; + break; + case UC_MIPS_REG_CP0_USERLOCAL: + env->active_tc.CP0_UserLocal = *(mipsreg_t *)value; + break; */ } } return; } -int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; @@ -137,7 +140,8 @@ int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUPPCState *env = &(POWERPC_CPU(uc->cpu)->env); int i; @@ -158,9 +162,11 @@ int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; @@ -177,9 +183,11 @@ int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPUPPCState *env = (CPUPPCState *)ctx->data; @@ -208,9 +216,9 @@ static int ppc_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_PPC64 -void ppc64_uc_init(struct uc_struct* uc) +void ppc64_uc_init(struct uc_struct *uc) #else -void ppc_uc_init(struct uc_struct* uc) +void ppc_uc_init(struct uc_struct *uc) #endif { uc->reg_read = ppc_reg_read; diff --git a/qemu/target/ppc/unicorn.h b/qemu/target/ppc/unicorn.h index ef3bcf6e..2afaa3a0 100644 --- a/qemu/target/ppc/unicorn.h +++ b/qemu/target/ppc/unicorn.h @@ -5,16 +5,22 @@ #define UC_QEMU_TARGET_PPC_H // functions to read & write registers -int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int ppc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int ppc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int ppc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int ppc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int ppc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int ppc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void ppc_reg_reset(struct uc_struct *uc); -void ppc_uc_init(struct uc_struct* uc); -void ppc64_uc_init(struct uc_struct* uc); +void ppc_uc_init(struct uc_struct *uc); +void ppc64_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/riscv/unicorn.c b/qemu/target/riscv/unicorn.c index 4bf9f2b7..c66a5c9a 100644 --- a/qemu/target/riscv/unicorn.c +++ b/qemu/target/riscv/unicorn.c @@ -36,99 +36,97 @@ static void riscv_release(void *ctx) } } -void riscv_reg_reset(struct uc_struct *uc) -{ -} +void riscv_reg_reset(struct uc_struct *uc) {} static void reg_read(CPURISCVState *env, unsigned int regid, void *value) { - switch(regid) { - case UC_RISCV_REG_X0: - case UC_RISCV_REG_X1: - case UC_RISCV_REG_X2: - case UC_RISCV_REG_X3: - case UC_RISCV_REG_X4: - case UC_RISCV_REG_X5: - case UC_RISCV_REG_X6: - case UC_RISCV_REG_X7: - case UC_RISCV_REG_X8: - case UC_RISCV_REG_X9: - case UC_RISCV_REG_X10: - case UC_RISCV_REG_X11: - case UC_RISCV_REG_X12: - case UC_RISCV_REG_X13: - case UC_RISCV_REG_X14: - case UC_RISCV_REG_X15: - case UC_RISCV_REG_X16: - case UC_RISCV_REG_X17: - case UC_RISCV_REG_X18: - case UC_RISCV_REG_X19: - case UC_RISCV_REG_X20: - case UC_RISCV_REG_X21: - case UC_RISCV_REG_X22: - case UC_RISCV_REG_X23: - case UC_RISCV_REG_X24: - case UC_RISCV_REG_X25: - case UC_RISCV_REG_X26: - case UC_RISCV_REG_X27: - case UC_RISCV_REG_X28: - case UC_RISCV_REG_X29: - case UC_RISCV_REG_X30: - case UC_RISCV_REG_X31: + switch (regid) { + case UC_RISCV_REG_X0: + case UC_RISCV_REG_X1: + case UC_RISCV_REG_X2: + case UC_RISCV_REG_X3: + case UC_RISCV_REG_X4: + case UC_RISCV_REG_X5: + case UC_RISCV_REG_X6: + case UC_RISCV_REG_X7: + case UC_RISCV_REG_X8: + case UC_RISCV_REG_X9: + case UC_RISCV_REG_X10: + case UC_RISCV_REG_X11: + case UC_RISCV_REG_X12: + case UC_RISCV_REG_X13: + case UC_RISCV_REG_X14: + case UC_RISCV_REG_X15: + case UC_RISCV_REG_X16: + case UC_RISCV_REG_X17: + case UC_RISCV_REG_X18: + case UC_RISCV_REG_X19: + case UC_RISCV_REG_X20: + case UC_RISCV_REG_X21: + case UC_RISCV_REG_X22: + case UC_RISCV_REG_X23: + case UC_RISCV_REG_X24: + case UC_RISCV_REG_X25: + case UC_RISCV_REG_X26: + case UC_RISCV_REG_X27: + case UC_RISCV_REG_X28: + case UC_RISCV_REG_X29: + case UC_RISCV_REG_X30: + case UC_RISCV_REG_X31: #ifdef TARGET_RISCV64 - *(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; + *(int64_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; #else - *(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; + *(int32_t *)value = env->gpr[regid - UC_RISCV_REG_X0]; #endif - break; - case UC_RISCV_REG_PC: + break; + case UC_RISCV_REG_PC: #ifdef TARGET_RISCV64 - *(int64_t *)value = env->pc; + *(int64_t *)value = env->pc; #else - *(int32_t *)value = env->pc; + *(int32_t *)value = env->pc; #endif - break; + break; - case UC_RISCV_REG_F0: // "ft0" - case UC_RISCV_REG_F1: // "ft1" - case UC_RISCV_REG_F2: // "ft2" - case UC_RISCV_REG_F3: // "ft3" - case UC_RISCV_REG_F4: // "ft4" - case UC_RISCV_REG_F5: // "ft5" - case UC_RISCV_REG_F6: // "ft6" - case UC_RISCV_REG_F7: // "ft7" - case UC_RISCV_REG_F8: // "fs0" - case UC_RISCV_REG_F9: // "fs1" - case UC_RISCV_REG_F10: // "fa0" - case UC_RISCV_REG_F11: // "fa1" - case UC_RISCV_REG_F12: // "fa2" - case UC_RISCV_REG_F13: // "fa3" - case UC_RISCV_REG_F14: // "fa4" - case UC_RISCV_REG_F15: // "fa5" - case UC_RISCV_REG_F16: // "fa6" - case UC_RISCV_REG_F17: // "fa7" - case UC_RISCV_REG_F18: // "fs2" - case UC_RISCV_REG_F19: // "fs3" - case UC_RISCV_REG_F20: // "fs4" - case UC_RISCV_REG_F21: // "fs5" - case UC_RISCV_REG_F22: // "fs6" - case UC_RISCV_REG_F23: // "fs7" - case UC_RISCV_REG_F24: // "fs8" - case UC_RISCV_REG_F25: // "fs9" - case UC_RISCV_REG_F26: // "fs10" - case UC_RISCV_REG_F27: // "fs11" - case UC_RISCV_REG_F28: // "ft8" - case UC_RISCV_REG_F29: // "ft9" - case UC_RISCV_REG_F30: // "ft10" - case UC_RISCV_REG_F31: // "ft11" + case UC_RISCV_REG_F0: // "ft0" + case UC_RISCV_REG_F1: // "ft1" + case UC_RISCV_REG_F2: // "ft2" + case UC_RISCV_REG_F3: // "ft3" + case UC_RISCV_REG_F4: // "ft4" + case UC_RISCV_REG_F5: // "ft5" + case UC_RISCV_REG_F6: // "ft6" + case UC_RISCV_REG_F7: // "ft7" + case UC_RISCV_REG_F8: // "fs0" + case UC_RISCV_REG_F9: // "fs1" + case UC_RISCV_REG_F10: // "fa0" + case UC_RISCV_REG_F11: // "fa1" + case UC_RISCV_REG_F12: // "fa2" + case UC_RISCV_REG_F13: // "fa3" + case UC_RISCV_REG_F14: // "fa4" + case UC_RISCV_REG_F15: // "fa5" + case UC_RISCV_REG_F16: // "fa6" + case UC_RISCV_REG_F17: // "fa7" + case UC_RISCV_REG_F18: // "fs2" + case UC_RISCV_REG_F19: // "fs3" + case UC_RISCV_REG_F20: // "fs4" + case UC_RISCV_REG_F21: // "fs5" + case UC_RISCV_REG_F22: // "fs6" + case UC_RISCV_REG_F23: // "fs7" + case UC_RISCV_REG_F24: // "fs8" + case UC_RISCV_REG_F25: // "fs9" + case UC_RISCV_REG_F26: // "fs10" + case UC_RISCV_REG_F27: // "fs11" + case UC_RISCV_REG_F28: // "ft8" + case UC_RISCV_REG_F29: // "ft9" + case UC_RISCV_REG_F30: // "ft10" + case UC_RISCV_REG_F31: // "ft11" #ifdef TARGET_RISCV64 - *(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; + *(int64_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; #else - *(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; + *(int32_t *)value = env->fpr[regid - UC_RISCV_REG_F0]; #endif - break; - default: - break; + break; + default: + break; } return; @@ -136,96 +134,97 @@ static void reg_read(CPURISCVState *env, unsigned int regid, void *value) static void reg_write(CPURISCVState *env, unsigned int regid, const void *value) { - switch(regid) { - case UC_RISCV_REG_X0: - case UC_RISCV_REG_X1: - case UC_RISCV_REG_X2: - case UC_RISCV_REG_X3: - case UC_RISCV_REG_X4: - case UC_RISCV_REG_X5: - case UC_RISCV_REG_X6: - case UC_RISCV_REG_X7: - case UC_RISCV_REG_X8: - case UC_RISCV_REG_X9: - case UC_RISCV_REG_X10: - case UC_RISCV_REG_X11: - case UC_RISCV_REG_X12: - case UC_RISCV_REG_X13: - case UC_RISCV_REG_X14: - case UC_RISCV_REG_X15: - case UC_RISCV_REG_X16: - case UC_RISCV_REG_X17: - case UC_RISCV_REG_X18: - case UC_RISCV_REG_X19: - case UC_RISCV_REG_X20: - case UC_RISCV_REG_X21: - case UC_RISCV_REG_X22: - case UC_RISCV_REG_X23: - case UC_RISCV_REG_X24: - case UC_RISCV_REG_X25: - case UC_RISCV_REG_X26: - case UC_RISCV_REG_X27: - case UC_RISCV_REG_X28: - case UC_RISCV_REG_X29: - case UC_RISCV_REG_X30: - case UC_RISCV_REG_X31: + switch (regid) { + case UC_RISCV_REG_X0: + case UC_RISCV_REG_X1: + case UC_RISCV_REG_X2: + case UC_RISCV_REG_X3: + case UC_RISCV_REG_X4: + case UC_RISCV_REG_X5: + case UC_RISCV_REG_X6: + case UC_RISCV_REG_X7: + case UC_RISCV_REG_X8: + case UC_RISCV_REG_X9: + case UC_RISCV_REG_X10: + case UC_RISCV_REG_X11: + case UC_RISCV_REG_X12: + case UC_RISCV_REG_X13: + case UC_RISCV_REG_X14: + case UC_RISCV_REG_X15: + case UC_RISCV_REG_X16: + case UC_RISCV_REG_X17: + case UC_RISCV_REG_X18: + case UC_RISCV_REG_X19: + case UC_RISCV_REG_X20: + case UC_RISCV_REG_X21: + case UC_RISCV_REG_X22: + case UC_RISCV_REG_X23: + case UC_RISCV_REG_X24: + case UC_RISCV_REG_X25: + case UC_RISCV_REG_X26: + case UC_RISCV_REG_X27: + case UC_RISCV_REG_X28: + case UC_RISCV_REG_X29: + case UC_RISCV_REG_X30: + case UC_RISCV_REG_X31: #ifdef TARGET_RISCV64 - env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value; + env->gpr[regid - UC_RISCV_REG_X0] = *(uint64_t *)value; #else - env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value; + env->gpr[regid - UC_RISCV_REG_X0] = *(uint32_t *)value; #endif - break; - case UC_RISCV_REG_PC: + break; + case UC_RISCV_REG_PC: #ifdef TARGET_RISCV64 - env->pc = *(uint64_t *)value; + env->pc = *(uint64_t *)value; #else - env->pc = *(uint32_t *)value; + env->pc = *(uint32_t *)value; #endif - break; - case UC_RISCV_REG_F0: // "ft0" - case UC_RISCV_REG_F1: // "ft1" - case UC_RISCV_REG_F2: // "ft2" - case UC_RISCV_REG_F3: // "ft3" - case UC_RISCV_REG_F4: // "ft4" - case UC_RISCV_REG_F5: // "ft5" - case UC_RISCV_REG_F6: // "ft6" - case UC_RISCV_REG_F7: // "ft7" - case UC_RISCV_REG_F8: // "fs0" - case UC_RISCV_REG_F9: // "fs1" - case UC_RISCV_REG_F10: // "fa0" - case UC_RISCV_REG_F11: // "fa1" - case UC_RISCV_REG_F12: // "fa2" - case UC_RISCV_REG_F13: // "fa3" - case UC_RISCV_REG_F14: // "fa4" - case UC_RISCV_REG_F15: // "fa5" - case UC_RISCV_REG_F16: // "fa6" - case UC_RISCV_REG_F17: // "fa7" - case UC_RISCV_REG_F18: // "fs2" - case UC_RISCV_REG_F19: // "fs3" - case UC_RISCV_REG_F20: // "fs4" - case UC_RISCV_REG_F21: // "fs5" - case UC_RISCV_REG_F22: // "fs6" - case UC_RISCV_REG_F23: // "fs7" - case UC_RISCV_REG_F24: // "fs8" - case UC_RISCV_REG_F25: // "fs9" - case UC_RISCV_REG_F26: // "fs10" - case UC_RISCV_REG_F27: // "fs11" - case UC_RISCV_REG_F28: // "ft8" - case UC_RISCV_REG_F29: // "ft9" - case UC_RISCV_REG_F30: // "ft10" - case UC_RISCV_REG_F31: // "ft11" + break; + case UC_RISCV_REG_F0: // "ft0" + case UC_RISCV_REG_F1: // "ft1" + case UC_RISCV_REG_F2: // "ft2" + case UC_RISCV_REG_F3: // "ft3" + case UC_RISCV_REG_F4: // "ft4" + case UC_RISCV_REG_F5: // "ft5" + case UC_RISCV_REG_F6: // "ft6" + case UC_RISCV_REG_F7: // "ft7" + case UC_RISCV_REG_F8: // "fs0" + case UC_RISCV_REG_F9: // "fs1" + case UC_RISCV_REG_F10: // "fa0" + case UC_RISCV_REG_F11: // "fa1" + case UC_RISCV_REG_F12: // "fa2" + case UC_RISCV_REG_F13: // "fa3" + case UC_RISCV_REG_F14: // "fa4" + case UC_RISCV_REG_F15: // "fa5" + case UC_RISCV_REG_F16: // "fa6" + case UC_RISCV_REG_F17: // "fa7" + case UC_RISCV_REG_F18: // "fs2" + case UC_RISCV_REG_F19: // "fs3" + case UC_RISCV_REG_F20: // "fs4" + case UC_RISCV_REG_F21: // "fs5" + case UC_RISCV_REG_F22: // "fs6" + case UC_RISCV_REG_F23: // "fs7" + case UC_RISCV_REG_F24: // "fs8" + case UC_RISCV_REG_F25: // "fs9" + case UC_RISCV_REG_F26: // "fs10" + case UC_RISCV_REG_F27: // "fs11" + case UC_RISCV_REG_F28: // "ft8" + case UC_RISCV_REG_F29: // "ft9" + case UC_RISCV_REG_F30: // "ft10" + case UC_RISCV_REG_F31: // "ft11" #ifdef TARGET_RISCV64 - env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value; + env->fpr[regid - UC_RISCV_REG_F0] = *(uint64_t *)value; #else - env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value; + env->fpr[regid - UC_RISCV_REG_F0] = *(uint32_t *)value; #endif - break; - default: - break; + break; + default: + break; } } -int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; @@ -239,7 +238,8 @@ int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPURISCVState *env = &(RISCV_CPU(uc->cpu)->env); int i; @@ -248,11 +248,11 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_RISCV_REG_PC){ + if (regid == UC_RISCV_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); - } + } } return 0; @@ -260,10 +260,12 @@ int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else - /* TARGET_RISCV64 */ -int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +/* TARGET_RISCV64 */ +int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; @@ -280,10 +282,12 @@ int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void ** DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else - /* TARGET_RISCV64 */ -int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +/* TARGET_RISCV64 */ +int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPURISCVState *env = (CPURISCVState *)ctx->data; @@ -301,14 +305,14 @@ int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void * static bool riscv_stop_interrupt(struct uc_struct *uc, int intno) { // detect stop exception - switch(intno){ - default: - return false; - case RISCV_EXCP_UNICORN_END: - return true; - case RISCV_EXCP_BREAKPOINT: - uc->invalid_error = UC_ERR_EXCEPTION; - return true; + switch (intno) { + default: + return false; + case RISCV_EXCP_UNICORN_END: + return true; + case RISCV_EXCP_BREAKPOINT: + uc->invalid_error = UC_ERR_EXCEPTION; + return true; } } @@ -332,10 +336,10 @@ static int riscv_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_RISCV32 -void riscv32_uc_init(struct uc_struct* uc) +void riscv32_uc_init(struct uc_struct *uc) #else - /* TARGET_RISCV64 */ -void riscv64_uc_init(struct uc_struct* uc) +/* TARGET_RISCV64 */ +void riscv64_uc_init(struct uc_struct *uc) #endif { uc->reg_read = riscv_reg_read; diff --git a/qemu/target/riscv/unicorn.h b/qemu/target/riscv/unicorn.h index 58371737..6add9369 100644 --- a/qemu/target/riscv/unicorn.h +++ b/qemu/target/riscv/unicorn.h @@ -6,16 +6,22 @@ #define UC_QEMU_TARGET_RISCV_H // functions to read & write registers -int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int riscv_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int riscv_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int riscv32_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int riscv32_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int riscv64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int riscv64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void riscv_reg_reset(struct uc_struct *uc); -void riscv32_uc_init(struct uc_struct* uc); -void riscv64_uc_init(struct uc_struct* uc); +void riscv32_uc_init(struct uc_struct *uc); +void riscv64_uc_init(struct uc_struct *uc); #endif diff --git a/qemu/target/sparc/unicorn.c b/qemu/target/sparc/unicorn.c index aad52ebb..4733ac99 100644 --- a/qemu/target/sparc/unicorn.c +++ b/qemu/target/sparc/unicorn.c @@ -10,11 +10,11 @@ static bool sparc_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case TT_ILL_INSN: - return true; + switch (intno) { + default: + return false; + case TT_ILL_INSN: + return true; } } @@ -63,15 +63,16 @@ static void reg_read(CPUSPARCState *env, unsigned int regid, void *value) else if (regid >= UC_SPARC_REG_O0 && regid <= UC_SPARC_REG_O7) *(int32_t *)value = env->regwptr[regid - UC_SPARC_REG_O0]; else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) - *(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; + *(int32_t *)value = env->regwptr[8 + regid - UC_SPARC_REG_L0]; else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - *(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; + *(int32_t *)value = env->regwptr[16 + regid - UC_SPARC_REG_I0]; else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - *(int32_t *)value = env->pc; - break; + switch (regid) { + default: + break; + case UC_SPARC_REG_PC: + *(int32_t *)value = env->pc; + break; } } @@ -87,21 +88,23 @@ static void reg_write(CPUSPARCState *env, unsigned int regid, const void *value) else if (regid >= UC_SPARC_REG_L0 && regid <= UC_SPARC_REG_L7) env->regwptr[8 + regid - UC_SPARC_REG_L0] = *(uint32_t *)value; else if (regid >= UC_SPARC_REG_I0 && regid <= UC_SPARC_REG_I7) - env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; + env->regwptr[16 + regid - UC_SPARC_REG_I0] = *(uint32_t *)value; else { - switch(regid) { - default: break; - case UC_SPARC_REG_PC: - env->pc = *(uint32_t *)value; - env->npc = *(uint32_t *)value + 4; - break; + switch (regid) { + default: + break; + case UC_SPARC_REG_PC: + env->pc = *(uint32_t *)value; + env->npc = *(uint32_t *)value + 4; + break; } } return; } -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; @@ -115,7 +118,8 @@ int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count) +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUSPARCState *env = &(SPARC_CPU(uc->cpu)->env); int i; @@ -124,7 +128,7 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if( regid == UC_SPARC_REG_PC){ + if (regid == UC_SPARC_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -136,7 +140,8 @@ int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, } DEFAULT_VISIBILITY -int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; int i; @@ -151,7 +156,8 @@ int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **va } DEFAULT_VISIBILITY -int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count) +int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) { CPUSPARCState *env = (CPUSPARCState *)ctx->data; int i; @@ -177,7 +183,7 @@ static int sparc_cpus_init(struct uc_struct *uc, const char *cpu_model) } DEFAULT_VISIBILITY -void sparc_uc_init(struct uc_struct* uc) +void sparc_uc_init(struct uc_struct *uc) { uc->release = sparc_release; uc->reg_read = sparc_reg_read; diff --git a/qemu/target/sparc/unicorn.h b/qemu/target/sparc/unicorn.h index 2e90e0e3..1f9818aa 100644 --- a/qemu/target/sparc/unicorn.h +++ b/qemu/target/sparc/unicorn.h @@ -5,16 +5,22 @@ #define UC_QEMU_TARGET_SPARC_H // functions to read & write registers -int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count); -int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, int count); +int sparc_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count); +int sparc_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count); -int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); -int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count); -int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void *const *vals, int count); +int sparc_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int sparc_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); +int sparc64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count); +int sparc64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count); void sparc_reg_reset(struct uc_struct *uc); -void sparc_uc_init(struct uc_struct* uc); -void sparc64_uc_init(struct uc_struct* uc); +void sparc_uc_init(struct uc_struct *uc); +void sparc64_uc_init(struct uc_struct *uc); #endif diff --git a/samples/mem_apis.c b/samples/mem_apis.c index 767e6aec..57756f3c 100644 --- a/samples/mem_apis.c +++ b/samples/mem_apis.c @@ -14,24 +14,24 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ #define __STDC_FORMAT_MACROS - #include #include #include #include #include - static int insts_executed; // callback for tracing instructions, detect HLT and terminate emulation -static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, + void *user_data) { uint8_t opcode; unsigned char buf[256]; @@ -39,61 +39,81 @@ static void hook_code(uc_engine *uc, uint64_t addr, uint32_t size, void *user_da insts_executed++; if (uc_mem_read(uc, addr, buf, size) != UC_ERR_OK) { - printf("not ok - uc_mem_read fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); + printf("not ok - uc_mem_read fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); if (uc_emu_stop(uc) != UC_ERR_OK) { - printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); + printf("not ok - uc_emu_stop fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); _exit(-1); } } opcode = buf[0]; switch (opcode) { - case 0x41: // inc ecx - if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { - printf("not ok - uc_mem_protect fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - case 0x42: // inc edx - if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) { - printf("not ok - uc_mem_unmap fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - case 0xf4: // hlt - if (uc_emu_stop(uc) != UC_ERR_OK) { - printf("not ok - uc_emu_stop fail during hook_code callback, addr: 0x%" PRIx64 "\n", addr); - _exit(-1); - } - break; - default: // all others - break; + case 0x41: // inc ecx + if (uc_mem_protect(uc, 0x101000, 0x1000, UC_PROT_READ) != UC_ERR_OK) { + printf("not ok - uc_mem_protect fail during hook_code callback, " + "addr: 0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + case 0x42: // inc edx + if (uc_mem_unmap(uc, 0x101000, 0x1000) != UC_ERR_OK) { + printf("not ok - uc_mem_unmap fail during hook_code callback, " + "addr: 0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + case 0xf4: // hlt + if (uc_emu_stop(uc) != UC_ERR_OK) { + printf("not ok - uc_emu_stop fail during hook_code callback, addr: " + "0x%" PRIx64 "\n", + addr); + _exit(-1); + } + break; + default: // all others + break; } } // callback for tracing invalid memory access (READ/WRITE/EXEC) -static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, - uint64_t addr, int size, int64_t value, void *user_data) +static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t addr, + int size, int64_t value, void *user_data) { - switch(type) { - default: - printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, addr); - return false; - case UC_MEM_READ_UNMAPPED: - printf("not ok - Read from invalid memory at 0x%"PRIx64 ", data size = %u\n", addr, size); - return false; - case UC_MEM_WRITE_UNMAPPED: - printf("not ok - Write to invalid memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); - return false; - case UC_MEM_FETCH_PROT: - printf("not ok - Fetch from non-executable memory at 0x%"PRIx64 "\n", addr); - return false; - case UC_MEM_WRITE_PROT: - printf("not ok - Write to non-writeable memory at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", addr, size, value); - return false; - case UC_MEM_READ_PROT: - printf("not ok - Read from non-readable memory at 0x%"PRIx64 ", data size = %u\n", addr, size); - return false; + switch (type) { + default: + printf("not ok - UC_HOOK_MEM_INVALID type: %d at 0x%" PRIx64 "\n", type, + addr); + return false; + case UC_MEM_READ_UNMAPPED: + printf("not ok - Read from invalid memory at 0x%" PRIx64 + ", data size = %u\n", + addr, size); + return false; + case UC_MEM_WRITE_UNMAPPED: + printf("not ok - Write to invalid memory at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + addr, size, value); + return false; + case UC_MEM_FETCH_PROT: + printf("not ok - Fetch from non-executable memory at 0x%" PRIx64 "\n", + addr); + return false; + case UC_MEM_WRITE_PROT: + printf("not ok - Write to non-writeable memory at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + addr, size, value); + return false; + case UC_MEM_READ_PROT: + printf("not ok - Read from non-readable memory at 0x%" PRIx64 + ", data size = %u\n", + addr, size); + return false; } } @@ -107,7 +127,8 @@ static void do_nx_demo(bool cause_fault) insts_executed = 0; printf("===================================\n"); - printf("# Example of marking memory NX (%s)\n", cause_fault ? "faulting" : "non-faulting"); + printf("# Example of marking memory NX (%s)\n", + cause_fault ? "faulting" : "non-faulting"); // Initialize emulator in X86-32bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); @@ -129,14 +150,16 @@ static void do_nx_demo(bool cause_fault) page2: @2000 jmp page1 */ - memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax - memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00", 5); // jump to 0x102000 + memset(code_buf, 0x40, sizeof(code_buf)); // fill with inc eax + memcpy(code_buf + 0x1000 - 5, "\xe9\x00\x10\x00\x00", + 5); // jump to 0x102000 memcpy(code_buf + 0x2000, "\xe9\xfb\xef\xff\xff", 5); // jump to 0x101000 - code_buf[0x1fff] = 0xf4; //hlt + code_buf[0x1fff] = 0xf4; // hlt if (cause_fault) { - // insert instruction to trigger U_PROT_EXEC change (see hook_code function) - code_buf[0x1000] = 0x41; // inc ecx at page1 + // insert instruction to trigger U_PROT_EXEC change (see hook_code + // function) + code_buf[0x1000] = 0x41; // inc ecx at page1 } // write machine code to be emulated to memory @@ -146,9 +169,10 @@ 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, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -157,7 +181,8 @@ static void do_nx_demo(bool cause_fault) printf("BEGINNING EXECUTION\n"); err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); printf("FAILED EXECUTION\n"); } else { printf("SUCCESSFUL EXECUTION\n"); @@ -212,11 +237,12 @@ static void do_perms_demo(bool change_perms) */ memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1); memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000); - code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt + code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt if (change_perms) { - // write protect memory area [0x101000, 0x101fff]. see hook_code function - code_buf[0] = 0x41; // inc ecx + // write protect memory area [0x101000, 0x101fff]. see hook_code + // function + code_buf[0] = 0x41; // inc ecx } // write machine code to be emulated to memory @@ -226,10 +252,10 @@ static void do_perms_demo(bool change_perms) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, - UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -239,7 +265,8 @@ static void do_perms_demo(bool change_perms) err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { printf("FAILED EXECUTION\n"); - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); } else { printf("SUCCESSFUL EXECUTION\n"); } @@ -253,11 +280,11 @@ static void perms_test() { printf("Permissions demo - step 1: show that area is writeable\n"); do_perms_demo(false); - printf("Permissions demo - step 2: show that code fails when memory marked unwriteable\n"); + printf("Permissions demo - step 2: show that code fails when memory marked " + "unwriteable\n"); do_perms_demo(true); } - static void do_unmap_demo(bool do_unmap) { uc_engine *uc; @@ -290,11 +317,11 @@ static void do_unmap_demo(bool do_unmap) */ memcpy(code_buf, WRITE_DEMO, sizeof(WRITE_DEMO) - 1); memset(code_buf + sizeof(WRITE_DEMO) - 1, 0x90, 1000); - code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt + code_buf[sizeof(WRITE_DEMO) - 1 + 1000] = 0xf4; // hlt if (do_unmap) { // unmap memory area [0x101000, 0x101fff]. see hook_code function - code_buf[0] = 0x42; // inc edx (see hook_code function) + code_buf[0] = 0x42; // inc edx (see hook_code function) } // write machine code to be emulated to memory @@ -304,10 +331,10 @@ static void do_unmap_demo(bool do_unmap) } // intercept code and invalid memory events - if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != UC_ERR_OK || - uc_hook_add(uc, &trace1, - UC_HOOK_MEM_INVALID, - hook_mem_invalid, NULL, 1, 0) != UC_ERR_OK) { + if (uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0) != + UC_ERR_OK || + uc_hook_add(uc, &trace1, UC_HOOK_MEM_INVALID, hook_mem_invalid, NULL, 1, + 0) != UC_ERR_OK) { printf("not ok - Failed to install hooks\n"); return; } @@ -317,7 +344,8 @@ static void do_unmap_demo(bool do_unmap) err = uc_emu_start(uc, 0x100000, 0x103000, 0, 0); if (err != UC_ERR_OK) { printf("FAILED EXECUTION\n"); - printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, uc_strerror(err)); + printf("not ok - Failure on uc_emu_start() with error %u: %s\n", err, + uc_strerror(err)); } else { printf("SUCCESSFUL EXECUTION\n"); } @@ -331,7 +359,8 @@ static void unmap_test() { printf("Unmap demo - step 1: show that area is writeable\n"); do_unmap_demo(false); - printf("Unmap demo - step 2: show that code fails when memory is unmapped\n"); + printf( + "Unmap demo - step 2: show that code fails when memory is unmapped\n"); do_unmap_demo(true); } diff --git a/samples/sample_arm.c b/samples/sample_arm.c index bda2d0b0..ac25e598 100644 --- a/samples/sample_arm.c +++ b/samples/sample_arm.c @@ -6,29 +6,37 @@ #include #include - // code to be emulated // #define ARM_CODE "\x37\x00\xa0\xe3" // mov r0, #0x37 #define ARM_CODE "\x00\xf0\x20\xe3" // nop -// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, r2, r3 +// #define ARM_CODE "\x37\x00\xa0\xe3\x03\x10\x42\xe0" // mov r0, #0x37; sub r1, +// r2, r3 #define THUMB_CODE "\x83\xb0" // sub sp, #0xc -#define ARM_THUM_COND_CODE "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov r2, #0x4d' +#define ARM_THUM_COND_CODE \ + "\x9a\x42\x14\xbf\x68\x22\x4d\x22" // 'cmp r2, r3\nit ne\nmov r2, #0x68\nmov + // r2, #0x4d' // code to be emulated -#define ARM_CODE_EB "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3 -#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc +#define ARM_CODE_EB \ + "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3 +#define THUMB_CODE_EB "\xb0\x83" // sub sp, #0xc // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_arm(void) @@ -37,18 +45,18 @@ static void test_arm(void) uc_err err; uc_hook trace1, trace2; - int r0 = 0x1234; // R0 register - int r2 = 0x6789; // R1 register - int r3 = 0x3333; // R2 register - int r1; // R1 register + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register printf("Emulate ARM code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -71,7 +79,7 @@ static void test_arm(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -93,15 +101,15 @@ static void test_thumb(void) uc_err err; uc_hook trace1, trace2; - int sp = 0x1234; // R0 register + int sp = 0x1234; // R0 register printf("Emulate THUMB code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -123,7 +131,7 @@ static void test_thumb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. // Note we start at ADDRESS | 1 to indicate THUMB mode. - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -143,18 +151,18 @@ static void test_armeb(void) uc_err err; uc_hook trace1, trace2; - int r0 = 0x1234; // R0 register - int r2 = 0x6789; // R1 register - int r3 = 0x3333; // R2 register - int r1; // R1 register + int r0 = 0x1234; // R0 register + int r2 = 0x6789; // R1 register + int r3 = 0x3333; // R2 register + int r1; // R1 register printf("Emulate ARM Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -177,7 +185,7 @@ static void test_armeb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE_EB) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -199,15 +207,15 @@ static void test_thumbeb(void) uc_err err; uc_hook trace1, trace2; - int sp = 0x1234; // R0 register + int sp = 0x1234; // R0 register printf("Emulate THUMB Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -229,7 +237,8 @@ static void test_thumbeb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. // Note we start at ADDRESS | 1 to indicate THUMB mode. - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(THUMB_CODE_EB) - 1, 0, + 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -257,8 +266,8 @@ static void test_thumb_mrs(void) // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -288,14 +297,15 @@ static void test_thumb_mrs(void) uc_reg_read(uc, UC_ARM_REG_PC, &pc); printf(">>> PC = 0x%x\n", pc); - if (pc != ADDRESS + 4){ + if (pc != ADDRESS + 4) { printf("Error, PC was 0x%x, expected was 0x%x.\n", pc, ADDRESS + 4); } uc_close(uc); } -static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_out) +static void test_thumb_ite_internal(bool step, uint32_t *r2_out, + uint32_t *r3_out) { uc_engine *uc; uc_err err; @@ -305,14 +315,15 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); - uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, sizeof(ARM_THUM_COND_CODE) - 1); + uc_mem_write(uc, ADDRESS, ARM_THUM_COND_CODE, + sizeof(ARM_THUM_COND_CODE) - 1); uc_reg_write(uc, UC_ARM_REG_SP, &sp); @@ -320,16 +331,19 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou uc_reg_write(uc, UC_ARM_REG_R3, &r3); if (!step) { - err = uc_emu_start(uc, ADDRESS | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS | 1, + ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } } else { int i, addr = ADDRESS; for (i = 0; i < sizeof(ARM_THUM_COND_CODE) / 2; i++) { - err = uc_emu_start(uc, addr | 1, ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1); + err = uc_emu_start(uc, addr | 1, + ADDRESS + sizeof(ARM_THUM_COND_CODE) - 1, 0, 1); if (err) { - printf("Failed on uc_emu_start() with error returned: %u\n", err); + printf("Failed on uc_emu_start() with error returned: %u\n", + err); } uc_reg_read(uc, UC_ARM_REG_PC, &addr); } @@ -344,13 +358,13 @@ static void test_thumb_ite_internal(bool step, uint32_t *r2_out, uint32_t *r3_ou *r3_out = r3; } -static void test_thumb_ite() +static void test_thumb_ite() { uint32_t r2, r3; uint32_t step_r2, step_r3; printf("Emulate a THUMB ITE block as a whole or per instruction.\n"); - + // Run once. printf("Running the entire binary.\n"); test_thumb_ite_internal(false, &r2, &r3); diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 74ea4e05..16db549f 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -6,48 +6,53 @@ #include #include - // code to be emulated -#define ARM64_CODE "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], #0 -//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; ldrb w15, [x13] +#define ARM64_CODE \ + "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], + // #0 +//#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; +//ldrb w15, [x13] #define ARM64_CODE_EB ARM64_CODE // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_arm64_mem_fetch(void) { - uc_engine* uc; + uc_engine *uc; uc_err err; uint64_t x1, sp, x0; // msr x0, CurrentEL - unsigned char shellcode0[4] = { - 64, 66, 56, 213 - }; + unsigned char shellcode0[4] = {64, 66, 56, 213}; // .text:00000000004002C0 LDR X1, [SP,#arg_0] - unsigned char shellcode[4] = { - 0xE1, 0x03, 0x40, 0xF9 - }; + unsigned char shellcode[4] = {0xE1, 0x03, 0x40, 0xF9}; unsigned shellcode_address = 0x4002C0; uint64_t data_address = 0x10000000000000; - printf(">>> Emulate ARM64 fetching stack data from high address %"PRIx64"\n", data_address); + printf(">>> Emulate ARM64 fetching stack data from high address %" PRIx64 + "\n", + data_address); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -60,16 +65,16 @@ static void test_arm64_mem_fetch(void) uc_mem_write(uc, shellcode_address, shellcode0, 4); uc_mem_write(uc, shellcode_address + 4, shellcode, 4); - err = uc_emu_start(uc, shellcode_address, shellcode_address+4, 0, 0); + err = uc_emu_start(uc, shellcode_address, shellcode_address + 4, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } x0 = 0; uc_reg_read(uc, UC_ARM64_REG_X0, &x0); - printf(">>> x0(Exception Level)=%"PRIx64"\n", x0>>2); + printf(">>> x0(Exception Level)=%" PRIx64 "\n", x0 >> 2); - err = uc_emu_start(uc, shellcode_address+4, shellcode_address+8, 0, 0); + err = uc_emu_start(uc, shellcode_address + 4, shellcode_address + 8, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -87,17 +92,17 @@ static void test_arm64(void) uc_err err; uc_hook trace1, trace2; - int64_t x11 = 0x12345678; // X11 register - int64_t x13 = 0x10000 + 0x8; // X13 register - int64_t x15 = 0x33; // X15 register + int64_t x11 = 0x12345678; // X11 register + int64_t x13 = 0x10000 + 0x8; // X13 register + int64_t x15 = 0x33; // X15 register printf("Emulate ARM64 code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -120,7 +125,7 @@ static void test_arm64(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -141,17 +146,17 @@ static void test_arm64eb(void) uc_err err; uc_hook trace1, trace2; - int64_t x11 = 0x12345678; // X11 register - int64_t x13 = 0x10000 + 0x8; // X13 register - int64_t x15 = 0x33; // X15 register + int64_t x11 = 0x12345678; // X11 register + int64_t x13 = 0x10000 + 0x8; // X13 register + int64_t x15 = 0x33; // X15 register printf("Emulate ARM64 Big-Endian code\n"); // Initialize emulator in ARM mode err = uc_open(UC_ARCH_ARM64, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -174,7 +179,7 @@ static void test_arm64eb(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM64_CODE_EB) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } @@ -190,7 +195,7 @@ static void test_arm64eb(void) } int main(int argc, char **argv, char **envp) -{ +{ test_arm64_mem_fetch(); test_arm64(); diff --git a/samples/sample_batch_reg.c b/samples/sample_batch_reg.c index b1b51b6d..8b5736f4 100644 --- a/samples/sample_batch_reg.c +++ b/samples/sample_batch_reg.c @@ -2,17 +2,15 @@ #include #include +int syscall_abi[] = {UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, + UC_X86_REG_RDX, UC_X86_REG_R10, UC_X86_REG_R8, + UC_X86_REG_R9}; -int syscall_abi[] = { - UC_X86_REG_RAX, UC_X86_REG_RDI, UC_X86_REG_RSI, UC_X86_REG_RDX, - UC_X86_REG_R10, UC_X86_REG_R8, UC_X86_REG_R9 -}; +uint64_t vals[7] = {200, 10, 11, 12, 13, 14, 15}; -uint64_t vals[7] = { 200, 10, 11, 12, 13, 14, 15 }; - -// This part of the API is less... clean... because Unicorn supports arbitrary register types. -// So the least intrusive solution is passing individual pointers. -// On the plus side, you only need to make this pointer array once. +// This part of the API is less... clean... because Unicorn supports arbitrary +// register types. So the least intrusive solution is passing individual +// pointers. On the plus side, you only need to make this pointer array once. void *ptrs[7]; void uc_perror(const char *func, uc_err err) @@ -22,8 +20,12 @@ void uc_perror(const char *func, uc_err err) #define BASE 0x10000 -// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov r9, 6; syscall -#define CODE "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05" +// mov rax, 100; mov rdi, 1; mov rsi, 2; mov rdx, 3; mov r10, 4; mov r8, 5; mov +// r9, 6; syscall +#define CODE \ + "\x48\xc7\xc0\x64\x00\x00\x00\x48\xc7\xc7\x01\x00\x00\x00\x48\xc7\xc6\x02" \ + "\x00\x00\x00\x48\xc7\xc2\x03\x00\x00\x00\x49\xc7\xc2\x04\x00\x00\x00\x49" \ + "\xc7\xc0\x05\x00\x00\x00\x49\xc7\xc1\x06\x00\x00\x00\x0f\x05" void hook_syscall(uc_engine *uc, void *user_data) { @@ -34,7 +36,8 @@ void hook_syscall(uc_engine *uc, void *user_data) printf("syscall: {"); for (i = 0; i < 7; i++) { - if (i != 0) printf(", "); + if (i != 0) + printf(", "); printf("%" PRIu64, vals[i]); } @@ -80,7 +83,8 @@ int main() printf("reg_read_batch = {"); for (i = 0; i < 7; i++) { - if (i != 0) printf(", "); + if (i != 0) + printf(", "); printf("%" PRIu64, vals[i]); } @@ -90,7 +94,8 @@ int main() printf("\n"); printf("running syscall shellcode\n"); - if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL))) { + if ((err = uc_hook_add(uc, &sys_hook, UC_HOOK_INSN, hook_syscall, NULL, 1, + 0, UC_X86_INS_SYSCALL))) { uc_perror("uc_hook_add", err); return 1; } diff --git a/samples/sample_m68k.c b/samples/sample_m68k.c index 49e47e5b..ed58f9fe 100644 --- a/samples/sample_m68k.c +++ b/samples/sample_m68k.c @@ -6,21 +6,25 @@ #include #include - // code to be emulated #define M68K_CODE "\x76\xed" // movq #-19, %d3 // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_m68k(void) @@ -29,34 +33,34 @@ static void test_m68k(void) uc_hook trace1, trace2; uc_err err; - int d0 = 0x0000; // d0 data register - int d1 = 0x0000; // d1 data register - int d2 = 0x0000; // d2 data register - int d3 = 0x0000; // d3 data register - int d4 = 0x0000; // d4 data register - int d5 = 0x0000; // d5 data register - int d6 = 0x0000; // d6 data register - int d7 = 0x0000; // d7 data register + int d0 = 0x0000; // d0 data register + int d1 = 0x0000; // d1 data register + int d2 = 0x0000; // d2 data register + int d3 = 0x0000; // d3 data register + int d4 = 0x0000; // d4 data register + int d5 = 0x0000; // d5 data register + int d6 = 0x0000; // d6 data register + int d7 = 0x0000; // d7 data register - int a0 = 0x0000; // a0 address register - int a1 = 0x0000; // a1 address register - int a2 = 0x0000; // a2 address register - int a3 = 0x0000; // a3 address register - int a4 = 0x0000; // a4 address register - int a5 = 0x0000; // a5 address register - int a6 = 0x0000; // a6 address register - int a7 = 0x0000; // a6 address register + int a0 = 0x0000; // a0 address register + int a1 = 0x0000; // a1 address register + int a2 = 0x0000; // a2 address register + int a3 = 0x0000; // a3 address register + int a4 = 0x0000; // a4 address register + int a5 = 0x0000; // a5 address register + int a6 = 0x0000; // a6 address register + int a7 = 0x0000; // a6 address register - int pc = 0x0000; // program counter - int sr = 0x0000; // status register + int pc = 0x0000; // program counter + int sr = 0x0000; // status register printf("Emulate M68K code\n"); // Initialize emulator in M68K mode err = uc_open(UC_ARCH_M68K, UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -96,7 +100,7 @@ static void test_m68k(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE)-1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(M68K_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); } diff --git a/samples/sample_mips.c b/samples/sample_mips.c index ef26af11..3bcafafd 100644 --- a/samples/sample_mips.c +++ b/samples/sample_mips.c @@ -6,7 +6,6 @@ #include #include - // code to be emulated #define MIPS_CODE_EB "\x34\x21\x34\x56" // ori $at, $at, 0x3456; #define MIPS_CODE_EL "\x56\x34\x21\x34" // ori $at, $at, 0x3456; @@ -14,14 +13,19 @@ // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_mips_eb(void) @@ -30,15 +34,15 @@ static void test_mips_eb(void) uc_err err; uc_hook trace1, trace2; - int r1 = 0x6789; // R1 register + int r1 = 0x6789; // R1 register printf("Emulate MIPS code (big-endian)\n"); // Initialize emulator in MIPS mode err = uc_open(UC_ARCH_MIPS, UC_MODE_MIPS32 + UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -61,7 +65,8 @@ static void test_mips_eb(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EB) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers @@ -79,7 +84,7 @@ static void test_mips_el(void) uc_err err; uc_hook trace1, trace2; - int r1 = 0x6789; // R1 register + int r1 = 0x6789; // R1 register printf("===========================\n"); printf("Emulate MIPS code (little-endian)\n"); @@ -87,8 +92,8 @@ static void test_mips_el(void) // Initialize emulator in MIPS mode 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)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -111,7 +116,8 @@ static void test_mips_el(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(MIPS_CODE_EL) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers diff --git a/samples/sample_ppc.c b/samples/sample_ppc.c index 12dbbd3f..cd09ae5e 100644 --- a/samples/sample_ppc.c +++ b/samples/sample_ppc.c @@ -6,22 +6,25 @@ #include #include - // code to be emulated #define PPC_CODE "\x7F\x46\x1A\x14" // add r26, r6, r3 // memory address where emulation starts #define ADDRESS 0x10000 - -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_ppc(void) @@ -30,17 +33,17 @@ static void test_ppc(void) uc_err err; uc_hook trace1, trace2; - int r3 = 0x1234; // R3 register - int r6 = 0x6789; // R6 register - int r26 = 0x8877; // R26 register (result) + int r3 = 0x1234; // R3 register + int r6 = 0x6789; // R6 register + int r26 = 0x8877; // R26 register (result) printf("Emulate PPC code\n"); // Initialize emulator in PPC mode - err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN , &uc); + err = uc_open(UC_ARCH_PPC, UC_MODE_PPC32 | UC_MODE_BIG_ENDIAN, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -63,7 +66,7 @@ static void test_ppc(void) // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) -1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(PPC_CODE) - 1, 0, 0); if (err) { printf("Failed on uc_emu_start() with error returned: %u\n", err); return; @@ -79,7 +82,6 @@ static void test_ppc(void) uc_close(uc); } - int main(int argc, char **argv, char **envp) { test_ppc(); diff --git a/samples/sample_riscv.c b/samples/sample_riscv.c index 73bdf98d..6e36f53a 100644 --- a/samples/sample_riscv.c +++ b/samples/sample_riscv.c @@ -5,7 +5,6 @@ #include #include - // code to be emulated #if 0 $ cstool riscv64 1305100093850502 @@ -15,23 +14,30 @@ $ cstool riscv64 1305100093850502 //#define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02\x93\x85\x05\x02" #define RISCV_CODE "\x13\x05\x10\x00\x93\x85\x05\x02" - // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } -static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code3(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); if (address == ADDRESS) { printf("stop emulation\n"); uc_emu_stop(uc); @@ -52,8 +58,8 @@ static void test_riscv(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -106,8 +112,8 @@ static void test_riscv2(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -171,8 +177,8 @@ static void test_riscv3(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -226,8 +232,8 @@ static void test_riscv_step(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -297,8 +303,8 @@ static void test_riscv_timeout(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV32, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -365,8 +371,8 @@ static void test_riscv_sd64(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -401,13 +407,14 @@ static void test_riscv_sd64(void) } static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void *user_data) + int size, int64_t value, void *user_data) { uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; - printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n", - address, algined_address, size, aligned_size); + printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 + "), block size = 0x%x (0x%x)\n", + address, algined_address, size, aligned_size); uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL); @@ -439,7 +446,8 @@ static void test_recover_from_illegal(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // auto-allocate memory on access - uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1, 0); + uc_hook_add(uc, &mem_alloc, UC_HOOK_MEM_UNMAPPED, hook_memalloc, NULL, 1, + 0); // tracing all basic blocks with customized callback uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); @@ -469,8 +477,8 @@ static void test_recover_from_illegal(void) uc_reg_read(uc, UC_RISCV_REG_A0, &a0); uc_reg_read(uc, UC_RISCV_REG_A1, &a1); - printf(">>> A0 = 0x%"PRIx64 "\n", a0); - printf(">>> A1 = 0x%"PRIx64 "\n", a1); + printf(">>> A0 = 0x%" PRIx64 "\n", a0); + printf(">>> A1 = 0x%" PRIx64 "\n", a1); uc_close(uc); } @@ -495,8 +503,8 @@ static void test_riscv_func_return(void) // Initialize emulator in RISCV64 mode err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &uc); if (err) { - printf("Failed on uc_open() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -527,7 +535,9 @@ static void test_riscv_func_return(void) uc_reg_read(uc, UC_RISCV_REG_PC, &pc); if (pc != ra) { - printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra); + printf("Error after execution: PC is: 0x%" PRIx64 + ", expected was 0x%" PRIx64 "\n", + pc, ra); if (pc == 0x10000) { printf(" PC did not change during execution\n"); } @@ -551,7 +561,9 @@ static void test_riscv_func_return(void) uc_reg_read(uc, UC_RISCV_REG_PC, &pc); if (pc != ra) { - printf("Error after execution: PC is: 0x%"PRIx64 ", expected was 0x%"PRIx64 "\n", pc, ra); + printf("Error after execution: PC is: 0x%" PRIx64 + ", expected was 0x%" PRIx64 "\n", + pc, ra); if (pc == 0x10004) { printf(" PC did not change during execution\n"); } diff --git a/samples/sample_sparc.c b/samples/sample_sparc.c index 04c2a359..f7609282 100644 --- a/samples/sample_sparc.c +++ b/samples/sample_sparc.c @@ -6,7 +6,6 @@ #include #include - // code to be emulated #define SPARC_CODE "\x86\x00\x40\x02" // add %g1, %g2, %g3; //#define SPARC_CODE "\xbb\x70\x00\x00" // illegal code @@ -14,14 +13,19 @@ // memory address where emulation starts #define ADDRESS 0x10000 -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); } static void test_sparc(void) @@ -30,17 +34,17 @@ static void test_sparc(void) uc_err err; uc_hook trace1, trace2; - int g1 = 0x1230; // G1 register - int g2 = 0x6789; // G2 register - int g3 = 0x5555; // G3 register + int g1 = 0x1230; // G1 register + int g2 = 0x6789; // G2 register + int g3 = 0x5555; // G3 register printf("Emulate SPARC code\n"); // Initialize emulator in Sparc mode - err = uc_open(UC_ARCH_SPARC, UC_MODE_SPARC32|UC_MODE_BIG_ENDIAN, &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)); + printf("Failed on uc_open() with error returned: %u (%s)\n", err, + uc_strerror(err)); return; } @@ -65,8 +69,8 @@ static void test_sparc(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(SPARC_CODE) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned: %u (%s)\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned: %u (%s)\n", err, + uc_strerror(err)); } // now print out some registers diff --git a/samples/sample_x86.c b/samples/sample_x86.c index 6732e076..3b9d280f 100644 --- a/samples/sample_x86.c +++ b/samples/sample_x86.c @@ -6,27 +6,45 @@ #include #include - // code to be emulated -#define X86_CODE32 "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1 -#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop -// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" +#define X86_CODE32 \ + "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1 +#define X86_CODE32_JUMP \ + "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop +// #define X86_CODE32_SELF +// "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41" //#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx; #define X86_CODE32_LOOP "\x41\x4a\xeb\xfe" // INC ecx; DEC edx; JMP self-loop -#define X86_CODE32_MEM_WRITE "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC edx -#define X86_CODE32_MEM_READ "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx -#define X86_CODE32_MEM_READ_IN_TB "\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx +#define X86_CODE32_MEM_WRITE \ + "\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov [0xaaaaaaaa], ecx; INC ecx; DEC + // edx +#define X86_CODE32_MEM_READ \ + "\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" // mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx +#define X86_CODE32_MEM_READ_IN_TB \ + "\x40\x8b\x1d\x00\x00\x10\x00\x42" // inc eax; mov ebx, [0x100000]; inc edx -#define X86_CODE32_JMP_INVALID "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx -#define X86_CODE32_INOUT "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, AL; INC ebx -#define X86_CODE32_INC "\x40" // INC eax +#define X86_CODE32_JMP_INVALID \ + "\xe9\xe9\xee\xee\xee\x41\x4a" // JMP outside; INC ecx; DEC edx +#define X86_CODE32_INOUT \ + "\x41\xE4\x3F\x4a\xE6\x46\x43" // INC ecx; IN AL, 0x3f; DEC edx; OUT 0x46, + // AL; INC ebx +#define X86_CODE32_INC "\x40" // INC eax -//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 \x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // <== still crash -//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" -#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E\x09\x3C\x59" -#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al +//#define X86_CODE64 "\x41\xBC\x3B\xB0\x28\x2A \x49\x0F\xC9 \x90 +//\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" // +//<== still crash #define X86_CODE64 +//"\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9" +#define X86_CODE64 \ + "\x41\xBC\x3B\xB0\x28\x2A\x49\x0F\xC9\x90\x4D\x0F\xAD\xCF\x49\x87\xFD\x90" \ + "\x48\x81\xD2\x8A\xCE\x77\x35\x48\xF7\xD9\x4D\x29\xF4\x49\x81\xC9\xF6\x8A" \ + "\xC6\x53\x4D\x87\xED\x48\x0F\xAD\xD2\x49\xF7\xD4\x48\xF7\xE1\x4D\x19\xC5" \ + "\x4D\x89\xC5\x48\xF7\xD6\x41\xB8\x4F\x8D\x6B\x59\x4D\x87\xD0\x68\x6A\x1E" \ + "\x09\x3C\x59" +#define X86_CODE16 "\x00\x00" // add byte ptr [bx + si], al #define X86_CODE64_SYSCALL "\x0f\x05" // SYSCALL -#define X86_MMIO_CODE "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx; mov ecx, [0x20004] +#define X86_MMIO_CODE \ + "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00" // mov [0x20004], ecx; + // mov ecx, [0x20004] /* * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 * 0x1003 dw 0x3ea98b13 @@ -37,16 +55,21 @@ #define ADDRESS 0x1000000 // callback for tracing basic blocks -static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size); + printf(">>> Tracing basic block at 0x%" PRIx64 ", block size = 0x%x\n", + address, size); } // callback for tracing instruction -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { int eflags; - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); uc_reg_read(uc, UC_X86_REG_EFLAGS, &eflags); printf(">>> --- EFLAGS is 0x%x\n", eflags); @@ -57,13 +80,16 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user } // callback for tracing instruction -static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { uint64_t rip; uc_reg_read(uc, UC_X86_REG_RIP, &rip); - printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); - printf(">>> RIP is 0x%"PRIx64 "\n", rip); + printf(">>> Tracing instruction at 0x%" PRIx64 + ", instruction size = 0x%x\n", + address, size); + printf(">>> RIP is 0x%" PRIx64 "\n", rip); // Uncomment below code to stop the emulation using uc_emu_stop() // if (address == 0x1000009) @@ -71,44 +97,48 @@ static void hook_code64(uc_engine *uc, uint64_t address, uint32_t size, void *us } // callback for tracing memory access (READ or WRITE) -static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) +static bool hook_mem_invalid(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - default: - // return false to indicate we want to stop emulation - return false; - case UC_MEM_WRITE_UNMAPPED: - printf(">>> Missing memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", - address, size, value); - // map this memory in with 2MB in size - uc_mem_map(uc, 0xaaaa0000, 2 * 1024*1024, UC_PROT_ALL); - // return true to indicate we want to continue - return true; + switch (type) { + default: + // return false to indicate we want to stop emulation + return false; + case UC_MEM_WRITE_UNMAPPED: + printf(">>> Missing memory is being WRITE at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + address, size, value); + // map this memory in with 2MB in size + uc_mem_map(uc, 0xaaaa0000, 2 * 1024 * 1024, UC_PROT_ALL); + // return true to indicate we want to continue + return true; } } // dummy callback static bool hook_mem_invalid_dummy(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) + uint64_t address, int size, int64_t value, + void *user_data) { // stop emulation return false; } -static void hook_mem64(uc_engine *uc, uc_mem_type type, - uint64_t address, int size, int64_t value, void *user_data) +static void hook_mem64(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - default: break; - case UC_MEM_READ: - printf(">>> Memory is being READ at 0x%"PRIx64 ", data size = %u\n", - address, size); - break; - case UC_MEM_WRITE: - printf(">>> Memory is being WRITE at 0x%"PRIx64 ", data size = %u, data value = 0x%"PRIx64 "\n", - address, size, value); - break; + switch (type) { + default: + break; + case UC_MEM_READ: + printf(">>> Memory is being READ at 0x%" PRIx64 ", data size = %u\n", + address, size); + break; + case UC_MEM_WRITE: + printf(">>> Memory is being WRITE at 0x%" PRIx64 + ", data size = %u, data value = 0x%" PRIx64 "\n", + address, size, value); + break; } } @@ -120,47 +150,50 @@ static uint32_t hook_in(uc_engine *uc, uint32_t port, int size, void *user_data) uc_reg_read(uc, UC_X86_REG_EIP, &eip); - printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, eip); + printf("--- reading from port 0x%x, size: %u, address: 0x%x\n", port, size, + eip); - switch(size) { - default: - return 0; // should never reach this - case 1: - // read 1 byte to AL - return 0xf1; - case 2: - // read 2 byte to AX - return 0xf2; - break; - case 4: - // read 4 byte to EAX - return 0xf4; + switch (size) { + default: + return 0; // should never reach this + case 1: + // read 1 byte to AL + return 0xf1; + case 2: + // read 2 byte to AX + return 0xf2; + break; + case 4: + // read 4 byte to EAX + return 0xf4; } } // callback for OUT instruction (X86). -static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data) +static void hook_out(uc_engine *uc, uint32_t port, int size, uint32_t value, + void *user_data) { uint32_t tmp = 0; uint32_t eip; uc_reg_read(uc, UC_X86_REG_EIP, &eip); - printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", port, size, value, eip); + printf("--- writing to port 0x%x, size: %u, value: 0x%x, address: 0x%x\n", + port, size, value, eip); // confirm that value is indeed the value of AL/AX/EAX - switch(size) { - default: - return; // should never reach this - case 1: - uc_reg_read(uc, UC_X86_REG_AL, &tmp); - break; - case 2: - uc_reg_read(uc, UC_X86_REG_AX, &tmp); - break; - case 4: - uc_reg_read(uc, UC_X86_REG_EAX, &tmp); - break; + switch (size) { + default: + return; // should never reach this + case 1: + uc_reg_read(uc, UC_X86_REG_AL, &tmp); + break; + case 2: + uc_reg_read(uc, UC_X86_REG_AX, &tmp); + break; + case 4: + uc_reg_read(uc, UC_X86_REG_EAX, &tmp); + break; } printf("--- register value = 0x%x\n", tmp); @@ -176,17 +209,18 @@ static void hook_syscall(uc_engine *uc, void *user_data) rax = 0x200; uc_reg_write(uc, UC_X86_REG_RAX, &rax); } else - printf("ERROR: was not expecting rax=0x%"PRIx64 " in syscall\n", rax); + printf("ERROR: was not expecting rax=0x%" PRIx64 " in syscall\n", rax); } static bool hook_memalloc(uc_engine *uc, uc_mem_type type, uint64_t address, - int size, int64_t value, void *user_data) + int size, int64_t value, void *user_data) { uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; - printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 "), block size = 0x%x (0x%x)\n", - address, algined_address, size, aligned_size); + printf(">>> Allocating block at 0x%" PRIx64 " (0x%" PRIx64 + "), block size = 0x%x (0x%x)\n", + address, algined_address, size, aligned_size); uc_mem_map(uc, algined_address, aligned_size, UC_PROT_ALL); @@ -206,8 +240,8 @@ static void test_miss_code(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("Emulate i386 code - missing code\n"); @@ -231,8 +265,8 @@ static void test_miss_code(void) // emulate machine code, without having the code in yet err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -253,8 +287,8 @@ static void test_i386(void) uint32_t tmp; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register // XMM0 and XMM1 registers, low qword then high qword uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607}; uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070}; @@ -292,8 +326,8 @@ static void test_i386(void) // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -304,7 +338,7 @@ static void test_i386(void) uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0); printf(">>> ECX = 0x%x\n", r_ecx); printf(">>> EDX = 0x%x\n", r_edx); - printf(">>> XMM0 = 0x%.16"PRIx64"%.16"PRIx64"\n", r_xmm0[1], r_xmm0[0]); + printf(">>> XMM0 = 0x%.16" PRIx64 "%.16" PRIx64 "\n", r_xmm0[1], r_xmm0[0]); // read from memory if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp))) @@ -323,8 +357,8 @@ static void test_i386_map_ptr(void) uc_hook trace1, trace2; void *mem; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code - use uc_mem_map_ptr()\n"); @@ -364,8 +398,8 @@ static void test_i386_map_ptr(void) // emulate machine code in infinite time err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -407,7 +441,7 @@ static void test_i386_jump(void) // write machine code to be emulated to memory if (uc_mem_write(uc, ADDRESS, X86_CODE32_JUMP, - sizeof(X86_CODE32_JUMP) - 1)) { + sizeof(X86_CODE32_JUMP) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -419,10 +453,11 @@ static void test_i386_jump(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JUMP) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf(">>> Emulation done. Below is the CPU context\n"); @@ -436,8 +471,8 @@ static void test_i386_loop(void) uc_engine *uc; uc_err err; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that loop forever\n"); @@ -453,7 +488,8 @@ static void test_i386_loop(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP, sizeof(X86_CODE32_LOOP) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_LOOP, + sizeof(X86_CODE32_LOOP) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -464,10 +500,11 @@ static void test_i386_loop(void) // emulate machine code in 2 seconds, so we can quit even // if the code loops - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, 2 * UC_SECOND_SCALE, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_LOOP) - 1, + 2 * UC_SECOND_SCALE, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -488,8 +525,8 @@ static void test_i386_invalid_mem_read(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that read from invalid memory\n"); @@ -505,7 +542,8 @@ static void test_i386_invalid_mem_read(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ, sizeof(X86_CODE32_MEM_READ) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ, + sizeof(X86_CODE32_MEM_READ) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -521,10 +559,11 @@ static void test_i386_invalid_mem_read(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ) - 1, + 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -546,8 +585,8 @@ static void test_i386_invalid_mem_write(void) uc_hook trace1, trace2, trace3; uint32_t tmp; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that write to invalid memory\n"); @@ -563,7 +602,8 @@ static void test_i386_invalid_mem_write(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, sizeof(X86_CODE32_MEM_WRITE) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_WRITE, + sizeof(X86_CODE32_MEM_WRITE) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -579,13 +619,16 @@ static void test_i386_invalid_mem_write(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // intercept invalid memory events - uc_hook_add(uc, &trace3, UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, hook_mem_invalid, NULL, 1, 0); + uc_hook_add(uc, &trace3, + UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED, + hook_mem_invalid, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_WRITE) - 1, + 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -617,8 +660,8 @@ static void test_i386_jump_invalid(void) uc_err err; uc_hook trace1, trace2; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register printf("===================================\n"); printf("Emulate i386 code that jumps to invalid memory\n"); @@ -634,7 +677,8 @@ static void test_i386_jump_invalid(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID, sizeof(X86_CODE32_JMP_INVALID) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_JMP_INVALID, + sizeof(X86_CODE32_JMP_INVALID) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -650,10 +694,11 @@ static void test_i386_jump_invalid(void) uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, + ADDRESS + sizeof(X86_CODE32_JMP_INVALID) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -673,9 +718,8 @@ static void test_i386_inout(void) uc_err err; uc_hook trace1, trace2, trace3, trace4; - - int r_eax = 0x1234; // EAX register - int r_ecx = 0x6789; // ECX register + int r_eax = 0x1234; // EAX register + int r_ecx = 0x6789; // ECX register printf("===================================\n"); printf("Emulate i386 code with IN/OUT instructions\n"); @@ -691,7 +735,8 @@ static void test_i386_inout(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT, sizeof(X86_CODE32_INOUT) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_INOUT, + sizeof(X86_CODE32_INOUT) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -709,13 +754,15 @@ static void test_i386_inout(void) // uc IN instruction uc_hook_add(uc, &trace3, UC_HOOK_INSN, hook_in, NULL, 1, 0, UC_X86_INS_IN); // uc OUT instruction - uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, UC_X86_INS_OUT); + uc_hook_add(uc, &trace4, UC_HOOK_INSN, hook_out, NULL, 1, 0, + UC_X86_INS_OUT); // emulate machine code in infinite time - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INOUT) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -736,7 +783,7 @@ static void test_i386_context_save(void) uc_context *context; uc_err err; - int r_eax = 0x1; // EAX register + int r_eax = 0x1; // EAX register printf("===================================\n"); printf("Save/restore CPU context in opaque blob\n"); @@ -765,8 +812,8 @@ static void test_i386_context_save(void) err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -795,8 +842,8 @@ static void test_i386_context_save(void) err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_INC) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -830,7 +877,8 @@ static void test_i386_context_save(void) } // now print out some registers - printf(">>> CPU context restored with modification. Below is the CPU context\n"); + printf(">>> CPU context restored with modification. Below is the CPU " + "context\n"); uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); printf(">>> EAX = 0x%x\n", r_eax); @@ -928,7 +976,6 @@ static void test_x86_64(void) int64_t rsp = ADDRESS + 0x200000; - printf("Emulate x86_64 code\n"); // Initialize emulator in X86-64bit mode @@ -969,7 +1016,8 @@ static void test_x86_64(void) uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0); // tracing all instructions in the range [ADDRESS, ADDRESS+20] - uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, ADDRESS+20); + uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code64, NULL, ADDRESS, + ADDRESS + 20); // tracing all memory WRITE access (with @begin > @end) uc_hook_add(uc, &trace3, UC_HOOK_MEM_WRITE, hook_mem64, NULL, 1, 0); @@ -981,8 +1029,8 @@ static void test_x86_64(void) // finishing all the code. err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1043,23 +1091,26 @@ static void test_x86_64_syscall(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL, sizeof(X86_CODE64_SYSCALL) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE64_SYSCALL, + sizeof(X86_CODE64_SYSCALL) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } // hook interrupts for syscall - uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, UC_X86_INS_SYSCALL); + uc_hook_add(uc, &trace1, UC_HOOK_INSN, hook_syscall, NULL, 1, 0, + UC_X86_INS_SYSCALL); // initialize machine registers uc_reg_write(uc, UC_X86_REG_RAX, &rax); // emulate machine code in infinite time (last param = 0), or when // finishing all the code. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE64_SYSCALL) - 1, 0, + 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1109,8 +1160,8 @@ static void test_x86_16(void) // finishing all the code. err = uc_emu_start(uc, 0, sizeof(X86_CODE16) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } // now print out some registers @@ -1131,12 +1182,13 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_err err; uc_hook trace1; - int r_eax = 0x1234; // EAX register - int r_edx = 0x7890; // EDX register + int r_eax = 0x1234; // EAX register + int r_edx = 0x7890; // EDX register int r_eip = 0; printf("===================================\n"); - printf("Emulate i386 code that read invalid memory in the middle of a TB\n"); + printf( + "Emulate i386 code that read invalid memory in the middle of a TB\n"); // Initialize emulator in X86-32bit mode err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); @@ -1149,7 +1201,8 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB, sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_MEM_READ_IN_TB, + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -1159,13 +1212,15 @@ static void test_i386_invalid_mem_read_in_tb(void) uc_reg_write(uc, UC_X86_REG_EDX, &r_edx); // Add a dummy callback. - uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1, 0); - + uc_hook_add(uc, &trace1, UC_HOOK_MEM_READ, hook_mem_invalid_dummy, NULL, 1, + 0); + // Let it crash by design. - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0); + err = uc_emu_start(uc, ADDRESS, + ADDRESS + sizeof(X86_CODE32_MEM_READ_IN_TB) - 1, 0, 0); if (err) { printf("uc_emu_start() failed BY DESIGN with error returned %u: %s\n", - err, uc_strerror(err)); + err, uc_strerror(err)); } printf(">>> Emulation done. Below is the CPU context\n"); @@ -1174,21 +1229,24 @@ static void test_i386_invalid_mem_read_in_tb(void) printf(">>> EIP = 0x%x\n", r_eip); if (r_eip != ADDRESS + 1) { - printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the middle of TB!\n", r_eip); + printf(">>> ERROR: Wrong PC 0x%x when reading unmapped memory in the " + "middle of TB!\n", + r_eip); } else { - printf(">>> The PC is correct after reading unmapped memory in the middle of TB.\n"); + printf(">>> The PC is correct after reading unmapped memory in the " + "middle of TB.\n"); } uc_close(uc); } -static void test_i386_smc_xor() +static void test_i386_smc_xor() { uc_engine *uc; uc_err err; - uint32_t r_edi = ADDRESS; // ECX register - uint32_t r_eax = 0xbc4177e6; // EDX register + uint32_t r_edi = ADDRESS; // ECX register + uint32_t r_eax = 0xbc4177e6; // EDX register uint32_t result; printf("===================================\n"); @@ -1216,15 +1274,15 @@ static void test_i386_smc_xor() // **Important Note** // - // Since SMC code will cause TB regeneration, the XOR in fact would executed - // twice (the first execution won't take effect.). Thus, if you would like to - // use count to control the emulation, the count should be set to 2. + // Since SMC code will cause TB regeneration, the XOR in fact would executed + // twice (the first execution won't take effect.). Thus, if you would like + // to use count to control the emulation, the count should be set to 2. // // err = uc_emu_start(uc, ADDRESS, ADDRESS + 3, 0, 0); err = uc_emu_start(uc, ADDRESS, 0, 0, 2); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf(">>> Emulation done. Below is the result.\n"); @@ -1232,30 +1290,38 @@ static void test_i386_smc_xor() uc_mem_read(uc, ADDRESS + 3, (void *)&result, 4); if (result == (0x3ea98b13 ^ 0xbc4177e6)) { - printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result); + printf(">>> SMC emulation is correct. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", + result); } else { - printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", result); + printf(">>> SMC emulation is wrong. 0x3ea98b13 ^ 0xbc4177e6 = 0x%x\n", + result); } uc_close(uc); } -static uint64_t mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) +static uint64_t mmio_read_callback(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data) { - printf(">>> Read IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes and return 0x19260817\n", offset, size); + printf(">>> Read IO memory at offset 0x%" PRIu64 " with 0x%" PRIu32 + " bytes and return 0x19260817\n", + offset, size); // The value returned here would be written to ecx. return 0x19260817; } -static void mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) +static void mmio_write_callback(uc_engine *uc, uint64_t offset, unsigned size, + uint64_t value, void *user_data) { - printf(">>> Write value 0x%"PRIu64" to IO memory at offset 0x%"PRIu64" with 0x%"PRIu32" bytes\n", value, offset, size); + printf(">>> Write value 0x%" PRIu64 " to IO memory at offset 0x%" PRIu64 + " with 0x%" PRIu32 " bytes\n", + value, offset, size); return; } static void test_i386_mmio() { - uc_engine* uc; + uc_engine *uc; int r_ecx = 0xdeadbeef; uc_err err; @@ -1283,7 +1349,8 @@ static void test_i386_mmio() return; } - err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL, mmio_write_callback, NULL); + err = uc_mmio_map(uc, 0x20000, 0x4000, mmio_read_callback, NULL, + mmio_write_callback, NULL); if (err) { printf("Failed on uc_mmio_map() with error returned: %u\n", err); return; @@ -1314,8 +1381,7 @@ int main(int argc, char **argv, char **envp) if (argc == 2) { if (!strcmp(argv[1], "-16")) { test_x86_16(); - } - else if (!strcmp(argv[1], "-32")) { + } else if (!strcmp(argv[1], "-32")) { test_miss_code(); test_i386(); test_i386_map_ptr(); @@ -1326,17 +1392,14 @@ int main(int argc, char **argv, char **envp) test_i386_invalid_mem_read(); test_i386_invalid_mem_write(); test_i386_jump_invalid(); - //test_i386_invalid_c6c7(); - } - else if (!strcmp(argv[1], "-64")) { + // test_i386_invalid_c6c7(); + } else if (!strcmp(argv[1], "-64")) { test_x86_64(); test_x86_64_syscall(); - } - else if (!strcmp(argv[1], "-h")) { + } else if (!strcmp(argv[1], "-h")) { printf("Syntax: %s <-16|-32|-64>\n", argv[0]); } - } - else { + } else { test_x86_16(); test_miss_code(); test_i386(); @@ -1348,7 +1411,7 @@ int main(int argc, char **argv, char **envp) test_i386_invalid_mem_read(); test_i386_invalid_mem_write(); test_i386_jump_invalid(); - //test_i386_invalid_c6c7(); + // test_i386_invalid_c6c7(); test_x86_64(); test_x86_64_syscall(); test_i386_invalid_mem_read_in_tb(); diff --git a/samples/sample_x86_32_gdt_and_seg_regs.c b/samples/sample_x86_32_gdt_and_seg_regs.c index e6023f8e..1ffd8892 100644 --- a/samples/sample_x86_32_gdt_and_seg_regs.c +++ b/samples/sample_x86_32_gdt_and_seg_regs.c @@ -26,62 +26,64 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #pragma pack(push, 1) struct SegmentDescriptor { - union { - struct { + union { + struct { #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned short limit0; - unsigned short base0; - unsigned char base1; - unsigned char type:4; - unsigned char system:1; /* S flag */ - unsigned char dpl:2; - unsigned char present:1; /* P flag */ - unsigned char limit1:4; - unsigned char avail:1; - unsigned char is_64_code:1; /* L flag */ - unsigned char db:1; /* DB flag */ - unsigned char granularity:1; /* G flag */ - unsigned char base2; + unsigned short limit0; + unsigned short base0; + unsigned char base1; + unsigned char type : 4; + unsigned char system : 1; /* S flag */ + unsigned char dpl : 2; + unsigned char present : 1; /* P flag */ + unsigned char limit1 : 4; + unsigned char avail : 1; + unsigned char is_64_code : 1; /* L flag */ + unsigned char db : 1; /* DB flag */ + unsigned char granularity : 1; /* G flag */ + unsigned char base2; #else - unsigned char base2; - unsigned char granularity:1; /* G flag */ - unsigned char db:1; /* DB flag */ - unsigned char is_64_code:1; /* L flag */ - unsigned char avail:1; - unsigned char limit1:4; - unsigned char present:1; /* P flag */ - unsigned char dpl:2; - unsigned char system:1; /* S flag */ - unsigned char type:4; - unsigned char base1; - unsigned short base0; - unsigned short limit0; + unsigned char base2; + unsigned char granularity : 1; /* G flag */ + unsigned char db : 1; /* DB flag */ + unsigned char is_64_code : 1; /* L flag */ + unsigned char avail : 1; + unsigned char limit1 : 4; + unsigned char present : 1; /* P flag */ + unsigned char dpl : 2; + unsigned char system : 1; /* S flag */ + unsigned char type : 4; + unsigned char base1; + unsigned short base0; + unsigned short limit0; #endif - }; - uint64_t desc; - }; + }; + uint64_t desc; + }; }; #pragma pack(pop) -#define SEGBASE(d) ((uint32_t)((((d).desc >> 16) & 0xffffff) | (((d).desc >> 32) & 0xff000000))) +#define SEGBASE(d) \ + ((uint32_t)((((d).desc >> 16) & 0xffffff) | \ + (((d).desc >> 32) & 0xff000000))) #define SEGLIMIT(d) ((d).limit0 | (((unsigned int)(d).limit1) << 16)) /** * Assert that err matches expect */ -#define uc_assert_err(expect, err) \ -do { \ - uc_err __err = err; \ - if (__err != expect) { \ - fprintf(stderr, "%s", uc_strerror(__err)); \ - exit(1); \ - } \ -} while (0) +#define uc_assert_err(expect, err) \ + do { \ + uc_err __err = err; \ + if (__err != expect) { \ + fprintf(stderr, "%s", uc_strerror(__err)); \ + exit(1); \ + } \ + } while (0) /** * Assert that err is UC_ERR_OK */ -#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err) +#define uc_assert_success(err) uc_assert_err(UC_ERR_OK, err) /** * Assert that err is anything but UC_ERR_OK @@ -90,55 +92,61 @@ do { \ * as this serves to document which errors a function will return * in various scenarios. */ -#define uc_assert_fail(err) \ -do { \ - uc_err __err = err; \ - if (__err == UC_ERR_OK) { \ - fprintf(stderr, "%s", uc_strerror(__err)); \ - exit(1); \ - } \ -} while (0) +#define uc_assert_fail(err) \ + do { \ + uc_err __err = err; \ + if (__err == UC_ERR_OK) { \ + fprintf(stderr, "%s", uc_strerror(__err)); \ + exit(1); \ + } \ + } while (0) -#define OK(x) uc_assert_success(x) +#define OK(x) uc_assert_success(x) /******************************************************************************/ -static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address, int size, int64_t value, void *user_data) +static void hook_mem(uc_engine *uc, uc_mem_type type, uint64_t address, + int size, int64_t value, void *user_data) { - switch(type) { - case UC_MEM_WRITE: - printf("mem write at 0x%"PRIx64 ", size = %u, value = 0x%"PRIx64 "\n", address, size, value); - break; - default: break; + switch (type) { + case UC_MEM_WRITE: + printf("mem write at 0x%" PRIx64 ", size = %u, value = 0x%" PRIx64 "\n", + address, size, value); + break; + default: + break; } } -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { - printf("Executing at 0x%"PRIx64 ", ilen = 0x%x\n", address, size); + printf("Executing at 0x%" PRIx64 ", ilen = 0x%x\n", address, size); } -//VERY basic descriptor init function, sets many fields to user space sane defaults -static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base, uint32_t limit, uint8_t is_code) +// VERY basic descriptor init function, sets many fields to user space sane +// defaults +static void init_descriptor(struct SegmentDescriptor *desc, uint32_t base, + uint32_t limit, uint8_t is_code) { - desc->desc = 0; //clear the descriptor + desc->desc = 0; // clear the descriptor desc->base0 = base & 0xffff; desc->base1 = (base >> 16) & 0xff; desc->base2 = base >> 24; if (limit > 0xfffff) { - //need Giant granularity + // need Giant granularity limit >>= 12; desc->granularity = 1; } desc->limit0 = limit & 0xffff; desc->limit1 = limit >> 16; - //some sane defaults + // some sane defaults desc->dpl = 3; desc->present = 1; - desc->db = 1; //32 bit + desc->db = 1; // 32 bit desc->type = is_code ? 0xb : 3; - desc->system = 1; //code or data + desc->system = 1; // code or data } /* @@ -149,7 +157,7 @@ static void hex_dump(unsigned char *ptr, unsigned int len) if (i != 0 && (i & 0xf) == 0) { fprintf(stderr, "\n"); } - fprintf(stderr, "%02hhx", ptr[i]); + fprintf(stderr, "%02hhx", ptr[i]); } fprintf(stderr, "\n"); } @@ -163,7 +171,7 @@ static void gdt_demo() uint8_t buf[128]; uc_x86_mmr gdtr; int i; - + /* bits 32 @@ -174,29 +182,33 @@ static void gdt_demo() mov dword [fs:4], 0x89abcdef */ - const uint8_t code[] = "\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89"; + const uint8_t code[] = + "\x68\x67\x45\x23\x01\x68\xef\xcd\xab\x89\x64\xc7\x05\x00\x00\x00\x00" + "\x67\x45\x23\x01\x64\xc7\x05\x04\x00\x00\x00\xef\xcd\xab\x89"; const uint64_t code_address = 0x1000000; const uint64_t stack_address = 0x120000; const uint64_t gdt_address = 0xc0000000; const uint64_t fs_address = 0x7efdd000; - struct SegmentDescriptor *gdt = (struct SegmentDescriptor*)calloc(31, sizeof(struct SegmentDescriptor)); + struct SegmentDescriptor *gdt = (struct SegmentDescriptor *)calloc( + 31, sizeof(struct SegmentDescriptor)); - int r_esp = (int)stack_address + 0x1000; // initial esp + int r_esp = (int)stack_address + 0x1000; // initial esp int r_cs = 0x73; - int r_ss = 0x88; //ring 0 + int r_ss = 0x88; // ring 0 int r_ds = 0x7b; int r_es = 0x7b; int r_fs = 0x83; - gdtr.base = gdt_address; + gdtr.base = gdt_address; gdtr.limit = 31 * sizeof(struct SegmentDescriptor) - 1; - init_descriptor(&gdt[14], 0, 0xfffff000, 1); //code segment - init_descriptor(&gdt[15], 0, 0xfffff000, 0); //data segment - init_descriptor(&gdt[16], 0x7efdd000, 0xfff, 0); //one page data segment simulate fs - init_descriptor(&gdt[17], 0, 0xfffff000, 0); //ring 0 data - gdt[17].dpl = 0; //set descriptor privilege level + init_descriptor(&gdt[14], 0, 0xfffff000, 1); // code segment + init_descriptor(&gdt[15], 0, 0xfffff000, 0); // data segment + init_descriptor(&gdt[16], 0x7efdd000, 0xfff, + 0); // one page data segment simulate fs + init_descriptor(&gdt[17], 0, 0xfffff000, 0); // ring 0 data + gdt[17].dpl = 0; // set descriptor privilege level /* fprintf(stderr, "GDT: \n"); @@ -207,9 +219,11 @@ static void gdt_demo() err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); uc_assert_success(err); - uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address, code_address + sizeof(code) - 1); + uc_hook_add(uc, &hook1, UC_HOOK_CODE, hook_code, NULL, code_address, + code_address + sizeof(code) - 1); - err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL, (uint64_t)1, (uint64_t)0); + err = uc_hook_add(uc, &hook2, UC_HOOK_MEM_WRITE, hook_mem, NULL, + (uint64_t)1, (uint64_t)0); uc_assert_success(err); // map 1 page of code for this emulation @@ -224,12 +238,13 @@ static void gdt_demo() err = uc_mem_map(uc, gdt_address, 0x10000, UC_PROT_WRITE | UC_PROT_READ); uc_assert_success(err); - //set up a GDT BEFORE you manipulate any segment registers + // set up a GDT BEFORE you manipulate any segment registers err = uc_reg_write(uc, UC_X86_REG_GDTR, &gdtr); uc_assert_success(err); // write gdt to be emulated to memory - err = uc_mem_write(uc, gdt_address, gdt, 31 * sizeof(struct SegmentDescriptor)); + err = uc_mem_write(uc, gdt_address, gdt, + 31 * sizeof(struct SegmentDescriptor)); uc_assert_success(err); // map 1 page for FS @@ -237,7 +252,7 @@ static void gdt_demo() uc_assert_success(err); // write machine code to be emulated to memory - err = uc_mem_write(uc, code_address, code, sizeof(code)-1); + err = uc_mem_write(uc, code_address, code, sizeof(code) - 1); uc_assert_success(err); // initialize machine registers @@ -245,7 +260,8 @@ static void gdt_demo() uc_assert_success(err); // when setting SS, need rpl == cpl && dpl == cpl - // emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0 selector + // emulator starts with cpl == 0, so we need a dpl 0 descriptor and rpl 0 + // selector err = uc_reg_write(uc, UC_X86_REG_SS, &r_ss); uc_assert_success(err); @@ -259,7 +275,7 @@ static void gdt_demo() uc_assert_success(err); // emulate machine code in infinite time - err = uc_emu_start(uc, code_address, code_address+sizeof(code)-1, 0, 0); + err = uc_emu_start(uc, code_address, code_address + sizeof(code) - 1, 0, 0); uc_assert_success(err); // read from memory diff --git a/samples/shellcode.c b/samples/shellcode.c index e0a72c75..9094dc07 100644 --- a/samples/shellcode.c +++ b/samples/shellcode.c @@ -6,23 +6,31 @@ #include #include - // code to be emulated -#define X86_CODE32 "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f" +#define X86_CODE32 \ + "\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd" \ + "\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c" \ + "\x6f" -#define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41" +#define X86_CODE32_SELF \ + "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89" \ + "\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31" \ + "\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3" \ + "\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41\x41\x41\x41\x41" // memory address where emulation starts #define ADDRESS 0x1000000 -#define MIN(a, b) (a < b? a : b) +#define MIN(a, b) (a < b ? a : b) // callback for tracing instruction -static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) +static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, + void *user_data) { int r_eip; uint8_t tmp[16]; - printf("Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size); + printf("Tracing instruction at 0x%" PRIx64 ", instruction size = 0x%x\n", + address, size); uc_reg_read(uc, UC_X86_REG_EIP, &r_eip); printf("*** EIP = %x ***: ", r_eip); @@ -30,7 +38,7 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user size = MIN(sizeof(tmp), size); if (!uc_mem_read(uc, address, tmp, size)) { uint32_t i; - for (i=0; i>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax); - break; - case 1: // sys_exit - printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno); - uc_emu_stop(uc); - break; - case 4: // sys_write - // ECX = buffer address - uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); + switch (r_eax) { + default: + printf(">>> 0x%x: interrupt 0x%x, EAX = 0x%x\n", r_eip, intno, r_eax); + break; + case 1: // sys_exit + printf(">>> 0x%x: interrupt 0x%x, SYS_EXIT. quit!\n\n", r_eip, intno); + uc_emu_stop(uc); + break; + case 4: // sys_write + // ECX = buffer address + uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx); - // EDX = buffer size - uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); + // EDX = buffer size + uc_reg_read(uc, UC_X86_REG_EDX, &r_edx); - // read the buffer in - size = MIN(sizeof(buffer)-1, r_edx); + // read the buffer in + size = MIN(sizeof(buffer) - 1, r_edx); - if (!uc_mem_read(uc, r_ecx, buffer, size)) { - buffer[size] = '\0'; - printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u, content = '%s'\n", - r_eip, intno, r_ecx, r_edx, buffer); - } else { - printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = %u (cannot get content)\n", - r_eip, intno, r_ecx, r_edx); - } - break; + if (!uc_mem_read(uc, r_ecx, buffer, size)) { + buffer[size] = '\0'; + printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = " + "%u, content = '%s'\n", + r_eip, intno, r_ecx, r_edx, buffer); + } else { + printf(">>> 0x%x: interrupt 0x%x, SYS_WRITE. buffer = 0x%x, size = " + "%u (cannot get content)\n", + r_eip, intno, r_ecx, r_edx); + } + break; } } @@ -88,7 +98,7 @@ static void test_i386(void) uc_err err; uc_hook trace1, trace2; - int r_esp = ADDRESS + 0x200000; // ESP register + int r_esp = ADDRESS + 0x200000; // ESP register printf("Emulate i386 code\n"); @@ -103,7 +113,8 @@ static void test_i386(void) uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL); // write machine code to be emulated to memory - if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF, sizeof(X86_CODE32_SELF) - 1)) { + if (uc_mem_write(uc, ADDRESS, X86_CODE32_SELF, + sizeof(X86_CODE32_SELF) - 1)) { printf("Failed to write emulation code to memory, quit!\n"); return; } @@ -120,11 +131,13 @@ static void test_i386(void) printf("\n>>> Start tracing this Linux code\n"); // emulate machine code in infinite time - // err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, 12); <--- emulate only 12 instructions - err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0); + // err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF), 0, + // 12); <--- emulate only 12 instructions + err = + uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(X86_CODE32_SELF) - 1, 0, 0); if (err) { - printf("Failed on uc_emu_start() with error returned %u: %s\n", - err, uc_strerror(err)); + printf("Failed on uc_emu_start() with error returned %u: %s\n", err, + uc_strerror(err)); } printf("\n>>> Emulation done.\n"); @@ -137,8 +150,7 @@ int main(int argc, char **argv, char **envp) if (argc == 2) { if (!strcmp(argv[1], "-32")) { test_i386(); - } - else if (!strcmp(argv[1], "-h")) { + } else if (!strcmp(argv[1], "-h")) { printf("Syntax: %s <-32|-64>\n", argv[0]); } } else { diff --git a/tests/unit/acutest.h b/tests/unit/acutest.h index 376748bd..6b4d596d 100644 --- a/tests/unit/acutest.h +++ b/tests/unit/acutest.h @@ -27,7 +27,6 @@ #ifndef ACUTEST_H #define ACUTEST_H - /************************ *** Public interface *** ************************/ @@ -59,8 +58,7 @@ * * Note the list has to be ended with a zeroed record. */ -#define TEST_LIST const struct acutest_test_ acutest_list_[] - +#define TEST_LIST const struct acutest_test_ acutest_list_[] /* Macros for testing whether an unit test succeeds or fails. These macros * can be used arbitrarily in functions implementing the unit tests. @@ -81,9 +79,9 @@ * TEST_CHECK(ptr->member2 > 200); * } */ -#define TEST_CHECK_(cond,...) acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) -#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) - +#define TEST_CHECK_(cond, ...) \ + acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) acutest_check_((cond), __FILE__, __LINE__, "%s", #cond) /* These macros are the same as TEST_CHECK_ and TEST_CHECK except that if the * condition fails, the currently executed unit test is immediately aborted. @@ -100,17 +98,16 @@ * effects to the outside world (e.g. communicating with some server, inserting * into a database etc.). */ -#define TEST_ASSERT_(cond,...) \ +#define TEST_ASSERT_(cond, ...) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ acutest_abort_(); \ - } while(0) + } while (0) #define TEST_ASSERT(cond) \ do { \ - if(!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ + if (!acutest_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ acutest_abort_(); \ - } while(0) - + } while (0) #ifdef __cplusplus /* Macros to verify that the code (the 1st argument) throws exception of given @@ -134,15 +131,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ - acutest_check_(exc_ok_, __FILE__, __LINE__, #code " throws " #exctype);\ - if(msg_ != NULL) \ + acutest_check_(exc_ok_, __FILE__, __LINE__, \ + #code " throws " #exctype); \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) + } while (0) #define TEST_EXCEPTION_(code, exctype, ...) \ do { \ bool exc_ok_ = false; \ @@ -150,17 +148,16 @@ try { \ code; \ msg_ = "No exception thrown."; \ - } catch(exctype const&) { \ - exc_ok_= true; \ - } catch(...) { \ + } catch (exctype const &) { \ + exc_ok_ = true; \ + } catch (...) { \ msg_ = "Unexpected exception thrown."; \ } \ acutest_check_(exc_ok_, __FILE__, __LINE__, __VA_ARGS__); \ - if(msg_ != NULL) \ + if (msg_ != NULL) \ acutest_message_("%s", msg_); \ - } while(0) -#endif /* #ifdef __cplusplus */ - + } while (0) +#endif /* #ifdef __cplusplus */ /* Sometimes it is useful to split execution of more complex unit tests to some * smaller parts and associate those parts with some names. @@ -180,18 +177,16 @@ * implicitly the previous one. To end the test case explicitly (e.g. to end * the last test case after exiting the loop), you may use TEST_CASE(NULL). */ -#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) -#define TEST_CASE(name) acutest_case_("%s", name) - +#define TEST_CASE_(...) acutest_case_(__VA_ARGS__) +#define TEST_CASE(name) acutest_case_("%s", name) /* Maximal output per TEST_CASE call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_CASE_MAXSIZE - #define TEST_CASE_MAXSIZE 64 +#define TEST_CASE_MAXSIZE 64 #endif - /* printf-like macro for outputting an extra information about a failure. * * Intended use is to output some computed output versus the expected value, @@ -213,17 +208,15 @@ * The macro can deal with multi-line output fairly well. It also automatically * adds a final new-line if there is none present. */ -#define TEST_MSG(...) acutest_message_(__VA_ARGS__) - +#define TEST_MSG(...) acutest_message_(__VA_ARGS__) /* Maximal output per TEST_MSG call. Longer messages are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_MSG_MAXSIZE - #define TEST_MSG_MAXSIZE 1024 +#define TEST_MSG_MAXSIZE 1024 #endif - /* Macro for dumping a block of memory. * * Its intended use is very similar to what TEST_MSG is for, but instead of @@ -235,16 +228,15 @@ * TEST_DUMP("Expected:", addr_expected, size_expected); * TEST_DUMP("Produced:", addr_produced, size_produced); */ -#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) +#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size) /* Maximal output per TEST_DUMP call (in bytes to dump). Longer blocks are cut. * You may define another limit prior including "acutest.h" */ #ifndef TEST_DUMP_MAXSIZE - #define TEST_DUMP_MAXSIZE 1024 +#define TEST_DUMP_MAXSIZE 1024 #endif - /* Common test initialiation/clean-up * * In some test suites, it may be needed to perform some sort of the same @@ -258,14 +250,13 @@ * Examples of various ways how to use the macro TEST_INIT: * * #define TEST_INIT my_init_func(); - * #define TEST_INIT my_init_func() // Works even without the semicolon - * #define TEST_INIT setlocale(LC_ALL, NULL); - * #define TEST_INIT { setlocale(LC_ALL, NULL); my_init_func(); } + * #define TEST_INIT my_init_func() // Works even without the + * semicolon #define TEST_INIT setlocale(LC_ALL, NULL); #define TEST_INIT + * { setlocale(LC_ALL, NULL); my_init_func(); } * * TEST_FINI is to be used in the same way. */ - /********************** *** Implementation *** **********************/ @@ -280,76 +271,76 @@ #include #if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) - #define ACUTEST_UNIX_ 1 - #include - #include - #include - #include - #include - #include - #include +#define ACUTEST_UNIX_ 1 +#include +#include +#include +#include +#include +#include +#include - #if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC - #define ACUTEST_HAS_POSIX_TIMER_ 1 - #endif +#if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC +#define ACUTEST_HAS_POSIX_TIMER_ 1 +#endif #endif #if defined(_gnu_linux_) || defined(__linux__) - #define ACUTEST_LINUX_ 1 - #include - #include +#define ACUTEST_LINUX_ 1 +#include +#include #endif #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) - #define ACUTEST_WIN_ 1 - #include - #include +#define ACUTEST_WIN_ 1 +#include +#include #endif #if defined(__APPLE__) - #define ACUTEST_MACOS_ - #include - #include - #include - #include - #include +#define ACUTEST_MACOS_ +#include +#include +#include +#include +#include #endif #ifdef __cplusplus - #include +#include #endif #ifdef __has_include - #if __has_include() - #include - #endif +#if __has_include() +#include +#endif #endif -/* Enable the use of the non-standard keyword __attribute__ to silence warnings under some compilers */ +/* Enable the use of the non-standard keyword __attribute__ to silence warnings + * under some compilers */ #if defined(__GNUC__) || defined(__clang__) - #define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) +#define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr)) #else - #define ACUTEST_ATTRIBUTE_(attr) +#define ACUTEST_ATTRIBUTE_(attr) #endif /* Note our global private identifiers end with '_' to mitigate risk of clash * with the unit tests implementation. */ #ifdef __cplusplus - extern "C" { +extern "C" { #endif #ifdef _MSC_VER - /* In the multi-platform code like ours, we cannot use the non-standard - * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of - * standard sprintf(). Hence, lets disable the warning C4996. */ - #pragma warning(push) - #pragma warning(disable: 4996) +/* In the multi-platform code like ours, we cannot use the non-standard + * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of + * standard sprintf(). Hence, lets disable the warning C4996. */ +#pragma warning(push) +#pragma warning(disable : 4996) #endif - struct acutest_test_ { - const char* name; + const char *name; void (*func)(void); }; @@ -366,18 +357,17 @@ enum { extern const struct acutest_test_ acutest_list_[]; -int acutest_check_(int cond, const char* file, int line, const char* fmt, ...); -void acutest_case_(const char* fmt, ...); -void acutest_message_(const char* fmt, ...); -void acutest_dump_(const char* title, const void* addr, size_t size); +int acutest_check_(int cond, const char *file, int line, const char *fmt, ...); +void acutest_case_(const char *fmt, ...); +void acutest_message_(const char *fmt, ...); +void acutest_dump_(const char *title, const void *addr, size_t size); void acutest_abort_(void) ACUTEST_ATTRIBUTE_(noreturn); - #ifndef TEST_NO_MAIN -static char* acutest_argv0_ = NULL; +static char *acutest_argv0_ = NULL; static size_t acutest_list_size_ = 0; -static struct acutest_test_data_* acutest_test_data_ = NULL; +static struct acutest_test_data_ *acutest_test_data_ = NULL; static size_t acutest_count_ = 0; static int acutest_no_exec_ = -1; static int acutest_no_summary_ = 0; @@ -392,7 +382,7 @@ static FILE *acutest_xml_output_ = NULL; static int acutest_stat_failed_units_ = 0; static int acutest_stat_run_units_ = 0; -static const struct acutest_test_* acutest_current_test_ = NULL; +static const struct acutest_test_ *acutest_current_test_ = NULL; static int acutest_current_index_ = 0; static char acutest_case_name_[TEST_CASE_MAXSIZE] = ""; static int acutest_test_already_logged_ = 0; @@ -405,132 +395,116 @@ static int acutest_timer_ = 0; static int acutest_abort_has_jmp_buf_ = 0; static jmp_buf acutest_abort_jmp_buf_; - -static void -acutest_cleanup_(void) +static void acutest_cleanup_(void) { - free((void*) acutest_test_data_); + free((void *)acutest_test_data_); } -static void ACUTEST_ATTRIBUTE_(noreturn) -acutest_exit_(int exit_code) +static void ACUTEST_ATTRIBUTE_(noreturn) acutest_exit_(int exit_code) { acutest_cleanup_(); exit(exit_code); } #if defined ACUTEST_WIN_ - typedef LARGE_INTEGER acutest_timer_type_; - static LARGE_INTEGER acutest_timer_freq_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef LARGE_INTEGER acutest_timer_type_; +static LARGE_INTEGER acutest_timer_freq_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - QueryPerformanceFrequency(´st_timer_freq_); - } +static void acutest_timer_init_(void) +{ + QueryPerformanceFrequency(´st_timer_freq_); +} - static void - acutest_timer_get_time_(LARGE_INTEGER* ts) - { - QueryPerformanceCounter(ts); - } +static void acutest_timer_get_time_(LARGE_INTEGER *ts) +{ + QueryPerformanceCounter(ts); +} - static double - acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) - { - double duration = (double)(end.QuadPart - start.QuadPart); - duration /= (double)acutest_timer_freq_.QuadPart; - return duration; - } +static double acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) +{ + double duration = (double)(end.QuadPart - start.QuadPart); + duration /= (double)acutest_timer_freq_.QuadPart; + return duration; +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #elif defined ACUTEST_HAS_POSIX_TIMER_ - static clockid_t acutest_timer_id_; - typedef struct timespec acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +static clockid_t acutest_timer_id_; +typedef struct timespec acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - static void - acutest_timer_init_(void) - { - if(acutest_timer_ == 1) - acutest_timer_id_ = CLOCK_MONOTONIC; - else if(acutest_timer_ == 2) - acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; - } +static void acutest_timer_init_(void) +{ + if (acutest_timer_ == 1) + acutest_timer_id_ = CLOCK_MONOTONIC; + else if (acutest_timer_ == 2) + acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; +} - static void - acutest_timer_get_time_(struct timespec* ts) - { - clock_gettime(acutest_timer_id_, ts); - } +static void acutest_timer_get_time_(struct timespec *ts) +{ + clock_gettime(acutest_timer_id_, ts); +} - static double - acutest_timer_diff_(struct timespec start, struct timespec end) - { - double endns; - double startns; +static double acutest_timer_diff_(struct timespec start, struct timespec end) +{ + double endns; + double startns; - endns = end.tv_sec; - endns *= 1e9; - endns += end.tv_nsec; + endns = end.tv_sec; + endns *= 1e9; + endns += end.tv_nsec; - startns = start.tv_sec; - startns *= 1e9; - startns += start.tv_nsec; + startns = start.tv_sec; + startns *= 1e9; + startns += start.tv_nsec; - return ((endns - startns)/ 1e9); - } + return ((endns - startns) / 1e9); +} - static void - acutest_timer_print_diff_(void) - { - printf("%.6lf secs", - acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); - } +static void acutest_timer_print_diff_(void) +{ + printf("%.6lf secs", + acutest_timer_diff_(acutest_timer_start_, acutest_timer_end_)); +} #else - typedef int acutest_timer_type_; - static acutest_timer_type_ acutest_timer_start_; - static acutest_timer_type_ acutest_timer_end_; +typedef int acutest_timer_type_; +static acutest_timer_type_ acutest_timer_start_; +static acutest_timer_type_ acutest_timer_end_; - void - acutest_timer_init_(void) - {} +void acutest_timer_init_(void) {} - static void - acutest_timer_get_time_(int* ts) - { - (void) ts; - } +static void acutest_timer_get_time_(int *ts) +{ + (void)ts; +} - static double - acutest_timer_diff_(int start, int end) - { - (void) start; - (void) end; - return 0.0; - } +static double acutest_timer_diff_(int start, int end) +{ + (void)start; + (void)end; + return 0.0; +} - static void - acutest_timer_print_diff_(void) - {} +static void acutest_timer_print_diff_(void) {} #endif -#define ACUTEST_COLOR_DEFAULT_ 0 -#define ACUTEST_COLOR_GREEN_ 1 -#define ACUTEST_COLOR_RED_ 2 -#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 -#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 -#define ACUTEST_COLOR_RED_INTENSIVE_ 5 +#define ACUTEST_COLOR_DEFAULT_ 0 +#define ACUTEST_COLOR_GREEN_ 1 +#define ACUTEST_COLOR_RED_ 2 +#define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 3 +#define ACUTEST_COLOR_GREEN_INTENSIVE_ 4 +#define ACUTEST_COLOR_RED_INTENSIVE_ 5 -static int ACUTEST_ATTRIBUTE_(format (printf, 2, 3)) -acutest_colored_printf_(int color, const char* fmt, ...) +static int ACUTEST_ATTRIBUTE_(format(printf, 2, 3)) + acutest_colored_printf_(int color, const char *fmt, ...) { va_list args; char buffer[256]; @@ -539,22 +513,34 @@ acutest_colored_printf_(int color, const char* fmt, ...) va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); - buffer[sizeof(buffer)-1] = '\0'; + buffer[sizeof(buffer) - 1] = '\0'; - if(!acutest_colorize_) { + if (!acutest_colorize_) { return printf("%s", buffer); } #if defined ACUTEST_UNIX_ { - const char* col_str; - switch(color) { - case ACUTEST_COLOR_GREEN_: col_str = "\033[0;32m"; break; - case ACUTEST_COLOR_RED_: col_str = "\033[0;31m"; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: col_str = "\033[1;32m"; break; - case ACUTEST_COLOR_RED_INTENSIVE_: col_str = "\033[1;31m"; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: col_str = "\033[1m"; break; - default: col_str = "\033[0m"; break; + const char *col_str; + switch (color) { + case ACUTEST_COLOR_GREEN_: + col_str = "\033[0;32m"; + break; + case ACUTEST_COLOR_RED_: + col_str = "\033[0;31m"; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + col_str = "\033[1;32m"; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + col_str = "\033[1;31m"; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + col_str = "\033[1m"; + break; + default: + col_str = "\033[0m"; + break; } printf("%s", col_str); n = printf("%s", buffer); @@ -570,15 +556,28 @@ acutest_colored_printf_(int color, const char* fmt, ...) h = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleScreenBufferInfo(h, &info); - switch(color) { - case ACUTEST_COLOR_GREEN_: attr = FOREGROUND_GREEN; break; - case ACUTEST_COLOR_RED_: attr = FOREGROUND_RED; break; - case ACUTEST_COLOR_GREEN_INTENSIVE_: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_RED_INTENSIVE_: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; - case ACUTEST_COLOR_DEFAULT_INTENSIVE_: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; - default: attr = 0; break; + switch (color) { + case ACUTEST_COLOR_GREEN_: + attr = FOREGROUND_GREEN; + break; + case ACUTEST_COLOR_RED_: + attr = FOREGROUND_RED; + break; + case ACUTEST_COLOR_GREEN_INTENSIVE_: + attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_RED_INTENSIVE_: + attr = FOREGROUND_RED | FOREGROUND_INTENSITY; + break; + case ACUTEST_COLOR_DEFAULT_INTENSIVE_: + attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | + FOREGROUND_INTENSITY; + break; + default: + attr = 0; + break; } - if(attr != 0) + if (attr != 0) SetConsoleTextAttribute(h, attr); n = printf("%s", buffer); SetConsoleTextAttribute(h, info.wAttributes); @@ -590,48 +589,50 @@ acutest_colored_printf_(int color, const char* fmt, ...) #endif } -static void -acutest_begin_test_line_(const struct acutest_test_* test) +static void acutest_begin_test_line_(const struct acutest_test_ *test) { - if(!acutest_tap_) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s:\n", test->name); + if (!acutest_tap_) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s:\n", test->name); acutest_test_already_logged_++; - } else if(acutest_verbose_level_ >= 1) { + } else if (acutest_verbose_level_ >= 1) { int n; char spaces[48]; - n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s... ", test->name); + n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Test %s... ", test->name); memset(spaces, ' ', sizeof(spaces)); - if(n < (int) sizeof(spaces)) - printf("%.*s", (int) sizeof(spaces) - n, spaces); + if (n < (int)sizeof(spaces)) + printf("%.*s", (int)sizeof(spaces) - n, spaces); } else { acutest_test_already_logged_ = 1; } } } -static void -acutest_finish_test_line_(int result) +static void acutest_finish_test_line_(int result) { - if(acutest_tap_) { - const char* str = (result == 0) ? "ok" : "not ok"; + if (acutest_tap_) { + const char *str = (result == 0) ? "ok" : "not ok"; - printf("%s %d - %s\n", str, acutest_current_index_ + 1, acutest_current_test_->name); + printf("%s %d - %s\n", str, acutest_current_index_ + 1, + acutest_current_test_->name); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf("# Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ : ACUTEST_COLOR_RED_INTENSIVE_; - const char* str = (result == 0) ? "OK" : "FAILED"; + int color = (result == 0) ? ACUTEST_COLOR_GREEN_INTENSIVE_ + : ACUTEST_COLOR_RED_INTENSIVE_; + const char *str = (result == 0) ? "OK" : "FAILED"; printf("[ "); acutest_colored_printf_(color, "%s", str); printf(" ]"); - if(result == 0 && acutest_timer_) { + if (result == 0 && acutest_timer_) { printf(" "); acutest_timer_print_diff_(); } @@ -640,37 +641,36 @@ acutest_finish_test_line_(int result) } } -static void -acutest_line_indent_(int level) +static void acutest_line_indent_(int level) { static const char spaces[] = " "; int n = level * 2; - if(acutest_tap_ && n > 0) { + if (acutest_tap_ && n > 0) { n--; printf("#"); } - while(n > 16) { + while (n > 16) { printf("%s", spaces); n -= 16; } printf("%.*s", n, spaces); } -int ACUTEST_ATTRIBUTE_(format (printf, 4, 5)) -acutest_check_(int cond, const char* file, int line, const char* fmt, ...) +int ACUTEST_ATTRIBUTE_(format(printf, 4, 5)) + acutest_check_(int cond, const char *file, int line, const char *fmt, ...) { const char *result_str; int result_color; int verbose_level; - if(cond) { + if (cond) { result_str = "ok"; result_color = ACUTEST_COLOR_GREEN_; verbose_level = 3; } else { - if(!acutest_test_already_logged_ && acutest_current_test_ != NULL) + if (!acutest_test_already_logged_ && acutest_current_test_ != NULL) acutest_finish_test_line_(-1); result_str = "failed"; @@ -680,30 +680,31 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) acutest_test_already_logged_++; } - if(acutest_verbose_level_ >= verbose_level) { + if (acutest_verbose_level_ >= verbose_level) { va_list args; - if(!acutest_case_already_logged_ && acutest_case_name_[0]) { + if (!acutest_case_already_logged_ && acutest_case_name_[0]) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Case %s:\n", acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } acutest_line_indent_(acutest_case_name_[0] ? 2 : 1); - if(file != NULL) { + if (file != NULL) { #ifdef ACUTEST_WIN_ - const char* lastsep1 = strrchr(file, '\\'); - const char* lastsep2 = strrchr(file, '/'); - if(lastsep1 == NULL) - lastsep1 = file-1; - if(lastsep2 == NULL) - lastsep2 = file-1; + const char *lastsep1 = strrchr(file, '\\'); + const char *lastsep2 = strrchr(file, '/'); + if (lastsep1 == NULL) + lastsep1 = file - 1; + if (lastsep2 == NULL) + lastsep2 = file - 1; file = (lastsep1 > lastsep2 ? lastsep1 : lastsep2) + 1; #else - const char* lastsep = strrchr(file, '/'); - if(lastsep != NULL) - file = lastsep+1; + const char *lastsep = strrchr(file, '/'); + if (lastsep != NULL) + file = lastsep + 1; #endif printf("%s:%d: Check ", file, line); } @@ -722,20 +723,20 @@ acutest_check_(int cond, const char* file, int line, const char* fmt, ...) return !acutest_cond_failed_; } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_case_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_case_(const char *fmt, ...) { va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; - if(acutest_case_name_[0]) { + if (acutest_case_name_[0]) { acutest_case_already_logged_ = 0; acutest_case_name_[0] = '\0'; } - if(fmt == NULL) + if (fmt == NULL) return; va_start(args, fmt); @@ -743,90 +744,90 @@ acutest_case_(const char* fmt, ...) va_end(args); acutest_case_name_[sizeof(acutest_case_name_) - 1] = '\0'; - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", acutest_case_name_); + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", + acutest_case_name_); acutest_test_already_logged_++; acutest_case_already_logged_++; } } -void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_message_(const char* fmt, ...) +void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_message_(const char *fmt, ...) { char buffer[TEST_MSG_MAXSIZE]; - char* line_beg; - char* line_end; + char *line_beg; + char *line_end; va_list args; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; va_start(args, fmt); vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); va_end(args); - buffer[TEST_MSG_MAXSIZE-1] = '\0'; + buffer[TEST_MSG_MAXSIZE - 1] = '\0'; line_beg = buffer; - while(1) { + while (1) { line_end = strchr(line_beg, '\n'); - if(line_end == NULL) + if (line_end == NULL) break; acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%.*s\n", (int)(line_end - line_beg), line_beg); line_beg = line_end + 1; } - if(line_beg[0] != '\0') { + if (line_beg[0] != '\0') { acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); printf("%s\n", line_beg); } } -void -acutest_dump_(const char* title, const void* addr, size_t size) +void acutest_dump_(const char *title, const void *addr, size_t size) { static const size_t BYTES_PER_LINE = 16; size_t line_beg; size_t truncate = 0; - if(acutest_verbose_level_ < 2) + if (acutest_verbose_level_ < 2) return; /* We allow extra message only when something is already wrong in the * current test. */ - if(acutest_current_test_ == NULL || !acutest_cond_failed_) + if (acutest_current_test_ == NULL || !acutest_cond_failed_) return; - if(size > TEST_DUMP_MAXSIZE) { + if (size > TEST_DUMP_MAXSIZE) { truncate = size - TEST_DUMP_MAXSIZE; size = TEST_DUMP_MAXSIZE; } acutest_line_indent_(acutest_case_name_[0] ? 3 : 2); - printf((title[strlen(title)-1] == ':') ? "%s\n" : "%s:\n", title); + printf((title[strlen(title) - 1] == ':') ? "%s\n" : "%s:\n", title); - for(line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { + for (line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { size_t line_end = line_beg + BYTES_PER_LINE; size_t off; acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); printf("%08lx: ", (unsigned long)line_beg); - for(off = line_beg; off < line_end; off++) { - if(off < size) - printf(" %02x", ((const unsigned char*)addr)[off]); + for (off = line_beg; off < line_end; off++) { + if (off < size) + printf(" %02x", ((const unsigned char *)addr)[off]); else printf(" "); } printf(" "); - for(off = line_beg; off < line_end; off++) { - unsigned char byte = ((const unsigned char*)addr)[off]; - if(off < size) + for (off = line_beg; off < line_end; off++) { + unsigned char byte = ((const unsigned char *)addr)[off]; + if (off < size) printf("%c", (iscntrl(byte) ? '.' : byte)); else break; @@ -835,135 +836,128 @@ acutest_dump_(const char* title, const void* addr, size_t size) printf("\n"); } - if(truncate > 0) { + if (truncate > 0) { acutest_line_indent_(acutest_case_name_[0] ? 4 : 3); - printf(" ... (and more %u bytes)\n", (unsigned) truncate); + printf(" ... (and more %u bytes)\n", (unsigned)truncate); } } /* This is called just before each test */ -static void -acutest_init_(const char *test_name) +static void acutest_init_(const char *test_name) { #ifdef TEST_INIT - TEST_INIT - ; /* Allow for a single unterminated function call */ + TEST_INIT; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } /* This is called after each test */ -static void -acutest_fini_(const char *test_name) +static void acutest_fini_(const char *test_name) { #ifdef TEST_FINI - TEST_FINI - ; /* Allow for a single unterminated function call */ + TEST_FINI; /* Allow for a single unterminated function call */ #endif /* Suppress any warnings about unused variable. */ - (void) test_name; + (void)test_name; } -void -acutest_abort_(void) +void acutest_abort_(void) { - if(acutest_abort_has_jmp_buf_) { + if (acutest_abort_has_jmp_buf_) { longjmp(acutest_abort_jmp_buf_, 1); } else { - if(acutest_current_test_ != NULL) + if (acutest_current_test_ != NULL) acutest_fini_(acutest_current_test_->name); abort(); } } -static void -acutest_list_names_(void) +static void acutest_list_names_(void) { - const struct acutest_test_* test; + const struct acutest_test_ *test; printf("Unit tests:\n"); - for(test = ´st_list_[0]; test->func != NULL; test++) + for (test = ´st_list_[0]; test->func != NULL; test++) printf(" %s\n", test->name); } -static void -acutest_remember_(int i) +static void acutest_remember_(int i) { - if(acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) + if (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_) return; acutest_test_data_[i].flags |= ACUTEST_FLAG_RUN_; acutest_count_++; } -static void -acutest_set_success_(int i, int success) +static void acutest_set_success_(int i, int success) { - acutest_test_data_[i].flags |= success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; + acutest_test_data_[i].flags |= + success ? ACUTEST_FLAG_SUCCESS_ : ACUTEST_FLAG_FAILURE_; } -static void -acutest_set_duration_(int i, double duration) +static void acutest_set_duration_(int i, double duration) { acutest_test_data_[i].duration = duration; } -static int -acutest_name_contains_word_(const char* name, const char* pattern) +static int acutest_name_contains_word_(const char *name, const char *pattern) { static const char word_delim[] = " \t-_/.,:;"; - const char* substr; + const char *substr; size_t pattern_len; pattern_len = strlen(pattern); substr = strstr(name, pattern); - while(substr != NULL) { - int starts_on_word_boundary = (substr == name || strchr(word_delim, substr[-1]) != NULL); - int ends_on_word_boundary = (substr[pattern_len] == '\0' || strchr(word_delim, substr[pattern_len]) != NULL); + while (substr != NULL) { + int starts_on_word_boundary = + (substr == name || strchr(word_delim, substr[-1]) != NULL); + int ends_on_word_boundary = + (substr[pattern_len] == '\0' || + strchr(word_delim, substr[pattern_len]) != NULL); - if(starts_on_word_boundary && ends_on_word_boundary) + if (starts_on_word_boundary && ends_on_word_boundary) return 1; - substr = strstr(substr+1, pattern); + substr = strstr(substr + 1, pattern); } return 0; } -static int -acutest_lookup_(const char* pattern) +static int acutest_lookup_(const char *pattern) { int i; int n = 0; /* Try exact match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strcmp(acutest_list_[i].name, pattern) == 0) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strcmp(acutest_list_[i].name, pattern) == 0) { acutest_remember_(i); n++; break; } } - if(n > 0) + if (n > 0) return n; /* Try word match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(acutest_name_contains_word_(acutest_list_[i].name, pattern)) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (acutest_name_contains_word_(acutest_list_[i].name, pattern)) { acutest_remember_(i); n++; } } - if(n > 0) + if (n > 0) return n; /* Try relaxed match. */ - for(i = 0; i < (int) acutest_list_size_; i++) { - if(strstr(acutest_list_[i].name, pattern) != NULL) { + for (i = 0; i < (int)acutest_list_size_; i++) { + if (strstr(acutest_list_[i].name, pattern) != NULL) { acutest_remember_(i); n++; } @@ -972,21 +966,20 @@ acutest_lookup_(const char* pattern) return n; } - /* Called if anything goes bad in Acutest, or if the unit test ends in other * way then by normal returning from its function (e.g. exception or some * abnormal child process termination). */ -static void ACUTEST_ATTRIBUTE_(format (printf, 1, 2)) -acutest_error_(const char* fmt, ...) +static void ACUTEST_ATTRIBUTE_(format(printf, 1, 2)) + acutest_error_(const char *fmt, ...) { - if(acutest_verbose_level_ == 0) + if (acutest_verbose_level_ == 0) return; - if(acutest_verbose_level_ >= 2) { + if (acutest_verbose_level_ >= 2) { va_list args; acutest_line_indent_(1); - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "ERROR: "); va_start(args, fmt); vprintf(fmt, args); @@ -994,14 +987,13 @@ acutest_error_(const char* fmt, ...) printf("\n"); } - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { printf("\n"); } } /* Call directly the given test unit function. */ -static int -acutest_do_run_(const struct acutest_test_* test, int index) +static int acutest_do_run_(const struct acutest_test_ *test, int index) { int status = -1; @@ -1022,9 +1014,9 @@ acutest_do_run_(const struct acutest_test_* test, int index) fflush(stdout); fflush(stderr); - if(!acutest_worker_) { + if (!acutest_worker_) { acutest_abort_has_jmp_buf_ = 1; - if(setjmp(acutest_abort_jmp_buf_) != 0) { + if (setjmp(acutest_abort_jmp_buf_) != 0) { acutest_was_aborted_ = 1; goto aborted; } @@ -1032,56 +1024,58 @@ acutest_do_run_(const struct acutest_test_* test, int index) acutest_timer_get_time_(´st_timer_start_); test->func(); -aborted: + aborted: acutest_abort_has_jmp_buf_ = 0; acutest_timer_get_time_(´st_timer_end_); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); - if(acutest_test_failures_ == 0) { - acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS: "); + if (acutest_test_failures_ == 0) { + acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, + "SUCCESS: "); printf("All conditions have passed.\n"); - if(acutest_timer_) { + if (acutest_timer_) { acutest_line_indent_(1); printf("Duration: "); acutest_timer_print_diff_(); printf("\n"); } } else { - acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); - if(!acutest_was_aborted_) { + acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, + "FAILED: "); + if (!acutest_was_aborted_) { printf("%d condition%s %s failed.\n", - acutest_test_failures_, - (acutest_test_failures_ == 1) ? "" : "s", - (acutest_test_failures_ == 1) ? "has" : "have"); + acutest_test_failures_, + (acutest_test_failures_ == 1) ? "" : "s", + (acutest_test_failures_ == 1) ? "has" : "have"); } else { printf("Aborted.\n"); } } printf("\n"); - } else if(acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { + } else if (acutest_verbose_level_ >= 1 && acutest_test_failures_ == 0) { acutest_finish_test_line_(0); } status = (acutest_test_failures_ == 0) ? 0 : -1; #ifdef __cplusplus - } catch(std::exception& e) { - const char* what = e.what(); + } catch (std::exception &e) { + const char *what = e.what(); acutest_check_(0, NULL, 0, "Threw std::exception"); - if(what != NULL) + if (what != NULL) acutest_message_("std::exception::what(): %s", what); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); } - } catch(...) { + } catch (...) { acutest_check_(0, NULL, 0, "Threw an exception"); - if(acutest_verbose_level_ >= 3) { + if (acutest_verbose_level_ >= 3) { acutest_line_indent_(1); acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: "); printf("C++ exception.\n\n"); @@ -1099,8 +1093,8 @@ aborted: /* Trigger the unit test. If possible (and not suppressed) it starts a child * process who calls acutest_do_run_(), otherwise it calls acutest_do_run_() * directly. */ -static void -acutest_run_(const struct acutest_test_* test, int index, int master_index) +static void acutest_run_(const struct acutest_test_ *test, int index, + int master_index) { int failed = 1; acutest_timer_type_ start, end; @@ -1109,7 +1103,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_test_already_logged_ = 0; acutest_timer_get_time_(&start); - if(!acutest_no_exec_) { + if (!acutest_no_exec_) { #if defined(ACUTEST_UNIX_) @@ -1121,10 +1115,10 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) fflush(stderr); pid = fork(); - if(pid == (pid_t)-1) { + if (pid == (pid_t)-1) { acutest_error_("Cannot fork. %s [%d]", strerror(errno), errno); failed = 1; - } else if(pid == 0) { + } else if (pid == 0) { /* Child: Do the test. */ acutest_worker_ = 1; failed = (acutest_do_run_(test, index) != 0); @@ -1132,29 +1126,54 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) } else { /* Parent: Wait until child terminates and analyze its exit code. */ waitpid(pid, &exit_code, 0); - if(WIFEXITED(exit_code)) { - switch(WEXITSTATUS(exit_code)) { - case 0: failed = 0; break; /* test has passed. */ - case 1: /* noop */ break; /* "normal" failure. */ - default: acutest_error_("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + if (WIFEXITED(exit_code)) { + switch (WEXITSTATUS(exit_code)) { + case 0: + failed = 0; + break; /* test has passed. */ + case 1: /* noop */ + break; /* "normal" failure. */ + default: + acutest_error_("Unexpected exit code [%d]", + WEXITSTATUS(exit_code)); } - } else if(WIFSIGNALED(exit_code)) { + } else if (WIFSIGNALED(exit_code)) { char tmp[32]; - const char* signame; - switch(WTERMSIG(exit_code)) { - case SIGINT: signame = "SIGINT"; break; - case SIGHUP: signame = "SIGHUP"; break; - case SIGQUIT: signame = "SIGQUIT"; break; - case SIGABRT: signame = "SIGABRT"; break; - case SIGKILL: signame = "SIGKILL"; break; - case SIGSEGV: signame = "SIGSEGV"; break; - case SIGILL: signame = "SIGILL"; break; - case SIGTERM: signame = "SIGTERM"; break; - default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + const char *signame; + switch (WTERMSIG(exit_code)) { + case SIGINT: + signame = "SIGINT"; + break; + case SIGHUP: + signame = "SIGHUP"; + break; + case SIGQUIT: + signame = "SIGQUIT"; + break; + case SIGABRT: + signame = "SIGABRT"; + break; + case SIGKILL: + signame = "SIGKILL"; + break; + case SIGSEGV: + signame = "SIGSEGV"; + break; + case SIGILL: + signame = "SIGILL"; + break; + case SIGTERM: + signame = "SIGTERM"; + break; + default: + sprintf(tmp, "signal %d", WTERMSIG(exit_code)); + signame = tmp; + break; } acutest_error_("Test interrupted by %s.", signame); } else { - acutest_error_("Test ended in an unexpected way [%d].", exit_code); + acutest_error_("Test ended in an unexpected way [%d].", + exit_code); } } @@ -1167,29 +1186,38 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) /* Windows has no fork(). So we propagate all info into the child * through a command line arguments. */ - _snprintf(buffer, sizeof(buffer)-1, - "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d --color=%s -- \"%s\"", - acutest_argv0_, index, acutest_timer_ ? "--time" : "", - acutest_tap_ ? "--tap" : "", acutest_verbose_level_, - acutest_colorize_ ? "always" : "never", - test->name); + _snprintf(buffer, sizeof(buffer) - 1, + "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d " + "--color=%s -- \"%s\"", + acutest_argv0_, index, acutest_timer_ ? "--time" : "", + acutest_tap_ ? "--tap" : "", acutest_verbose_level_, + acutest_colorize_ ? "always" : "never", test->name); memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(STARTUPINFO); - if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, + &startupInfo, &processInfo)) { WaitForSingleObject(processInfo.hProcess, INFINITE); GetExitCodeProcess(processInfo.hProcess, &exitCode); CloseHandle(processInfo.hThread); CloseHandle(processInfo.hProcess); failed = (exitCode != 0); - if(exitCode > 1) { - switch(exitCode) { - case 3: acutest_error_("Aborted."); break; - case 0xC0000005: acutest_error_("Access violation."); break; - default: acutest_error_("Test ended in an unexpected way [%lu].", exitCode); break; + if (exitCode > 1) { + switch (exitCode) { + case 3: + acutest_error_("Aborted."); + break; + case 0xC0000005: + acutest_error_("Access violation."); + break; + default: + acutest_error_("Test ended in an unexpected way [%lu].", + exitCode); + break; } } } else { - acutest_error_("Cannot create unit test subprocess [%ld].", GetLastError()); + acutest_error_("Cannot create unit test subprocess [%ld].", + GetLastError()); failed = 1; } @@ -1209,7 +1237,7 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) acutest_current_test_ = NULL; acutest_stat_run_units_++; - if(failed) + if (failed) acutest_stat_failed_units_++; acutest_set_success_(master_index, !failed); @@ -1218,12 +1246,13 @@ acutest_run_(const struct acutest_test_* test, int index, int master_index) #if defined(ACUTEST_WIN_) /* Callback for SEH events. */ -static LONG CALLBACK -acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) +static LONG CALLBACK acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) { acutest_check_(0, NULL, 0, "Unhandled SEH exception"); - acutest_message_("Exception code: 0x%08lx", ptrs->ExceptionRecord->ExceptionCode); - acutest_message_("Exception address: 0x%p", ptrs->ExceptionRecord->ExceptionAddress); + acutest_message_("Exception code: 0x%08lx", + ptrs->ExceptionRecord->ExceptionCode); + acutest_message_("Exception address: 0x%p", + ptrs->ExceptionRecord->ExceptionAddress); fflush(stdout); fflush(stderr); @@ -1232,38 +1261,37 @@ acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) } #endif +#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 +#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 -#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 -#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 - -#define ACUTEST_CMDLINE_OPTID_NONE_ 0 -#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) -#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) -#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) +#define ACUTEST_CMDLINE_OPTID_NONE_ 0 +#define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) +#define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) +#define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) typedef struct acutest_test_CMDLINE_OPTION_ { char shortname; - const char* longname; + const char *longname; int id; unsigned flags; } ACUTEST_CMDLINE_OPTION_; -static int -acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, - const char* arggroup, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_handle_short_opt_group_( + const ACUTEST_CMDLINE_OPTION_ *options, const char *arggroup, + int (*callback)(int /*optval*/, const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; + const ACUTEST_CMDLINE_OPTION_ *opt; int i; int ret = 0; - for(i = 0; arggroup[i] != '\0'; i++) { - for(opt = options; opt->id != 0; opt++) { - if(arggroup[i] == opt->shortname) + for (i = 0; arggroup[i] != '\0'; i++) { + for (opt = options; opt->id != 0; opt++) { + if (arggroup[i] == opt->shortname) break; } - if(opt->id != 0 && !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + if (opt->id != 0 && + !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { ret = callback(opt->id, NULL); } else { /* Unknown option. */ @@ -1271,106 +1299,116 @@ acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_* options, badoptname[0] = '-'; badoptname[1] = arggroup[i]; badoptname[2] = '\0'; - ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ : ACUTEST_CMDLINE_OPTID_UNKNOWN_), - badoptname); + ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_ + : ACUTEST_CMDLINE_OPTID_UNKNOWN_), + badoptname); } - if(ret != 0) + if (ret != 0) break; } return ret; } -#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 +#define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32 -static int -acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** argv, - int (*callback)(int /*optval*/, const char* /*arg*/)) +static int acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_ *options, + int argc, char **argv, + int (*callback)(int /*optval*/, + const char * /*arg*/)) { - const ACUTEST_CMDLINE_OPTION_* opt; - char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_+1]; + const ACUTEST_CMDLINE_OPTION_ *opt; + char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_ + 1]; int after_doubledash = 0; int i = 1; int ret = 0; auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_] = '\0'; - while(i < argc) { - if(after_doubledash || strcmp(argv[i], "-") == 0) { + while (i < argc) { + if (after_doubledash || strcmp(argv[i], "-") == 0) { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); - } else if(strcmp(argv[i], "--") == 0) { - /* End of options. All the remaining members are non-option arguments. */ + } else if (strcmp(argv[i], "--") == 0) { + /* End of options. All the remaining members are non-option + * arguments. */ after_doubledash = 1; - } else if(argv[i][0] != '-') { + } else if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { - for(opt = options; opt->id != 0; opt++) { - if(opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { + for (opt = options; opt->id != 0; opt++) { + if (opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { size_t len = strlen(opt->longname); - if(strncmp(argv[i]+2, opt->longname, len) == 0) { + if (strncmp(argv[i] + 2, opt->longname, len) == 0) { /* Regular long option. */ - if(argv[i][2+len] == '\0') { + if (argv[i][2 + len] == '\0') { /* with no argument provided. */ - if(!(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) + if (!(opt->flags & + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) ret = callback(opt->id, NULL); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; - } else if(argv[i][2+len] == '=') { + } else if (argv[i][2 + len] == '=') { /* with an argument provided. */ - if(opt->flags & (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { - ret = callback(opt->id, argv[i]+2+len+1); + if (opt->flags & + (ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ | + ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + ret = callback(opt->id, argv[i] + 2 + len + 1); } else { sprintf(auxbuf, "--%s", opt->longname); - ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, auxbuf); + ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, + auxbuf); } break; } else { continue; } } - } else if(opt->shortname != '\0' && argv[i][0] == '-') { - if(argv[i][1] == opt->shortname) { + } else if (opt->shortname != '\0' && argv[i][0] == '-') { + if (argv[i][1] == opt->shortname) { /* Regular short option. */ - if(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { - if(argv[i][2] != '\0') - ret = callback(opt->id, argv[i]+2); - else if(i+1 < argc) + if (opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_) { + if (argv[i][2] != '\0') + ret = callback(opt->id, argv[i] + 2); + else if (i + 1 < argc) ret = callback(opt->id, argv[++i]); else - ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + ret = callback( + ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); break; } else { ret = callback(opt->id, NULL); /* There might be more (argument-less) short options * grouped together. */ - if(ret == 0 && argv[i][2] != '\0') - ret = acutest_cmdline_handle_short_opt_group_(options, argv[i]+2, callback); + if (ret == 0 && argv[i][2] != '\0') + ret = acutest_cmdline_handle_short_opt_group_( + options, argv[i] + 2, callback); break; } } } } - if(opt->id == 0) { /* still not handled? */ - if(argv[i][0] != '-') { + if (opt->id == 0) { /* still not handled? */ + if (argv[i][0] != '-') { /* Non-option argument. */ ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]); } else { /* Unknown option. */ - char* badoptname = argv[i]; + char *badoptname = argv[i]; - if(strncmp(badoptname, "--", 2) == 0) { + if (strncmp(badoptname, "--", 2) == 0) { /* Strip any argument from the long option. */ - char* assignment = strchr(badoptname, '='); - if(assignment != NULL) { + char *assignment = strchr(badoptname, '='); + if (assignment != NULL) { size_t len = assignment - badoptname; - if(len > ACUTEST_CMDLINE_AUXBUF_SIZE_) + if (len > ACUTEST_CMDLINE_AUXBUF_SIZE_) len = ACUTEST_CMDLINE_AUXBUF_SIZE_; strncpy(auxbuf, badoptname, len); auxbuf[len] = '\0'; @@ -1383,7 +1421,7 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a } } - if(ret != 0) + if (ret != 0) return ret; i++; } @@ -1391,28 +1429,34 @@ acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_* options, int argc, char** a return ret; } -static void -acutest_help_(void) +static void acutest_help_(void) { printf("Usage: %s [options] [test...]\n", acutest_argv0_); printf("\n"); - printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); - printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("Run the specified unit tests; or if the option '--skip' is used, " + "run all\n"); + printf("tests in the suite but those listed. By default, if no tests are " + "specified\n"); printf("on the command line, all unit tests in the suite are run.\n"); printf("\n"); printf("Options:\n"); - printf(" -s, --skip Execute all unit tests but the listed ones\n"); - printf(" --exec[=WHEN] If supported, execute unit tests as child processes\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf( + " -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --exec[=WHEN] If supported, execute unit tests as child " + "processes\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" -E, --no-exec Same as --exec=never\n"); #if defined ACUTEST_WIN_ printf(" -t, --time Measure test duration\n"); #elif defined ACUTEST_HAS_POSIX_TIMER_ printf(" -t, --time Measure test duration (real time)\n"); - printf(" --time=TIMER Measure test duration, using given timer\n"); + printf( + " --time=TIMER Measure test duration, using given timer\n"); printf(" (TIMER is one of 'real', 'cpu')\n"); #endif - printf(" --no-summary Suppress printing of test results summary\n"); + printf( + " --no-summary Suppress printing of test results summary\n"); printf(" --tap Produce TAP-compliant output\n"); printf(" (See https://testanything.org/)\n"); printf(" -x, --xml-output=FILE Enable XUnit output to the given file\n"); @@ -1420,213 +1464,232 @@ acutest_help_(void) printf(" -v, --verbose Make output more verbose\n"); printf(" --verbose=LEVEL Set verbose level to LEVEL:\n"); printf(" 0 ... Be silent\n"); - printf(" 1 ... Output one line per test (and summary)\n"); - printf(" 2 ... As 1 and failed conditions (this is default)\n"); - printf(" 3 ... As 1 and all conditions (and extended summary)\n"); + printf(" 1 ... Output one line per test (and " + "summary)\n"); + printf(" 2 ... As 1 and failed conditions (this " + "is default)\n"); + printf(" 3 ... As 1 and all conditions (and " + "extended summary)\n"); printf(" -q, --quiet Same as --verbose=0\n"); printf(" --color[=WHEN] Enable colorized output\n"); - printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" (WHEN is one of 'auto', 'always', " + "'never')\n"); printf(" --no-color Same as --color=never\n"); printf(" -h, --help Display this help and exit\n"); - if(acutest_list_size_ < 16) { + if (acutest_list_size_ < 16) { printf("\n"); acutest_list_names_(); } } static const ACUTEST_CMDLINE_OPTION_ acutest_cmdline_options_[] = { - { 's', "skip", 's', 0 }, - { 0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'E', "no-exec", 'E', 0 }, + {'s', "skip", 's', 0}, + {0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'E', "no-exec", 'E', 0}, #if defined ACUTEST_WIN_ - { 't', "time", 't', 0 }, - { 0, "timer", 't', 0 }, /* kept for compatibility */ + {'t', "time", 't', 0}, + {0, "timer", 't', 0}, /* kept for compatibility */ #elif defined ACUTEST_HAS_POSIX_TIMER_ - { 't', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "timer", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, /* kept for compatibility */ + {'t', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "timer", 't', + ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, /* kept for compatibility */ #endif - { 0, "no-summary", 'S', 0 }, - { 0, "tap", 'T', 0 }, - { 'l', "list", 'l', 0 }, - { 'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 'q', "quiet", 'q', 0 }, - { 0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, - { 0, "no-color", 'C', 0 }, - { 'h', "help", 'h', 0 }, - { 0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, /* internal */ - { 'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, - { 0, NULL, 0, 0 } -}; + {0, "no-summary", 'S', 0}, + {0, "tap", 'T', 0}, + {'l', "list", 'l', 0}, + {'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {'q', "quiet", 'q', 0}, + {0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, + {0, "no-color", 'C', 0}, + {'h', "help", 'h', 0}, + {0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, /* internal */ + {'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, + {0, NULL, 0, 0}}; -static int -acutest_cmdline_callback_(int id, const char* arg) +static int acutest_cmdline_callback_(int id, const char *arg) { - switch(id) { - case 's': - acutest_skip_mode_ = 1; - break; + switch (id) { + case 's': + acutest_skip_mode_ = 1; + break; - case 'e': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_no_exec_ = 0; - } else if(strcmp(arg, "never") == 0) { - acutest_no_exec_ = 1; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --exec.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'E': + case 'e': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_no_exec_ = 0; + } else if (strcmp(arg, "never") == 0) { acutest_no_exec_ = 1; - break; + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --exec.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; - case 't': -#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ - if(arg == NULL || strcmp(arg, "real") == 0) { - acutest_timer_ = 1; - #ifndef ACUTEST_WIN_ - } else if(strcmp(arg, "cpu") == 0) { - acutest_timer_ = 2; - #endif - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --time.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } + case 'E': + acutest_no_exec_ = 1; + break; + + case 't': +#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ + if (arg == NULL || strcmp(arg, "real") == 0) { + acutest_timer_ = 1; +#ifndef ACUTEST_WIN_ + } else if (strcmp(arg, "cpu") == 0) { + acutest_timer_ = 2; #endif - break; + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --time.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + } +#endif + break; - case 'S': - acutest_no_summary_ = 1; - break; + case 'S': + acutest_no_summary_ = 1; + break; - case 'T': - acutest_tap_ = 1; - break; + case 'T': + acutest_tap_ = 1; + break; - case 'l': - acutest_list_names_(); - acutest_exit_(0); - break; + case 'l': + acutest_list_names_(); + acutest_exit_(0); + break; - case 'v': - acutest_verbose_level_ = (arg != NULL ? atoi(arg) : acutest_verbose_level_+1); - break; + case 'v': + acutest_verbose_level_ = + (arg != NULL ? atoi(arg) : acutest_verbose_level_ + 1); + break; - case 'q': - acutest_verbose_level_ = 0; - break; + case 'q': + acutest_verbose_level_ = 0; + break; - case 'c': - if(arg == NULL || strcmp(arg, "always") == 0) { - acutest_colorize_ = 1; - } else if(strcmp(arg, "never") == 0) { - acutest_colorize_ = 0; - } else if(strcmp(arg, "auto") == 0) { - /*noop*/ - } else { - fprintf(stderr, "%s: Unrecognized argument '%s' for option --color.\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case 'C': + case 'c': + if (arg == NULL || strcmp(arg, "always") == 0) { + acutest_colorize_ = 1; + } else if (strcmp(arg, "never") == 0) { acutest_colorize_ = 0; - break; - - case 'h': - acutest_help_(); - acutest_exit_(0); - break; - - case 'w': - acutest_worker_ = 1; - acutest_worker_index_ = atoi(arg); - break; - case 'x': - acutest_xml_output_ = fopen(arg, "w"); - if (!acutest_xml_output_) { - fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); - acutest_exit_(2); - } - break; - - case 0: - if(acutest_lookup_(arg) == 0) { - fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, arg); - fprintf(stderr, "Try '%s --list' for list of unit tests.\n", acutest_argv0_); - acutest_exit_(2); - } - break; - - case ACUTEST_CMDLINE_OPTID_UNKNOWN_: - fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + } else if (strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, + "%s: Unrecognized argument '%s' for option --color.\n", + acutest_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); acutest_exit_(2); - break; + } + break; - case ACUTEST_CMDLINE_OPTID_MISSINGARG_: - fprintf(stderr, "The command line option '%s' requires an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); - acutest_exit_(2); - break; + case 'C': + acutest_colorize_ = 0; + break; - case ACUTEST_CMDLINE_OPTID_BOGUSARG_: - fprintf(stderr, "The command line option '%s' does not expect an argument.\n", arg); - fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_); + case 'h': + acutest_help_(); + acutest_exit_(0); + break; + + case 'w': + acutest_worker_ = 1; + acutest_worker_index_ = atoi(arg); + break; + case 'x': + acutest_xml_output_ = fopen(arg, "w"); + if (!acutest_xml_output_) { + fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); acutest_exit_(2); - break; + } + break; + + case 0: + if (acutest_lookup_(arg) == 0) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, + arg); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", + acutest_argv0_); + acutest_exit_(2); + } + break; + + case ACUTEST_CMDLINE_OPTID_UNKNOWN_: + fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_MISSINGARG_: + fprintf(stderr, "The command line option '%s' requires an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; + + case ACUTEST_CMDLINE_OPTID_BOGUSARG_: + fprintf(stderr, + "The command line option '%s' does not expect an argument.\n", + arg); + fprintf(stderr, "Try '%s --help' for more information.\n", + acutest_argv0_); + acutest_exit_(2); + break; } return 0; } - #ifdef ACUTEST_LINUX_ -static int -acutest_is_tracer_present_(void) +static int acutest_is_tracer_present_(void) { /* Must be large enough so the line 'TracerPid: ${PID}' can fit in. */ static const int OVERLAP = 32; - char buf[256+OVERLAP+1]; + char buf[256 + OVERLAP + 1]; int tracer_present = 0; int fd; size_t n_read = 0; fd = open("/proc/self/status", O_RDONLY); - if(fd == -1) + if (fd == -1) return 0; - while(1) { + while (1) { static const char pattern[] = "TracerPid:"; - const char* field; + const char *field; - while(n_read < sizeof(buf) - 1) { + while (n_read < sizeof(buf) - 1) { ssize_t n; n = read(fd, buf + n_read, sizeof(buf) - 1 - n_read); - if(n <= 0) + if (n <= 0) break; n_read += n; } buf[n_read] = '\0'; field = strstr(buf, pattern); - if(field != NULL && field < buf + sizeof(buf) - OVERLAP) { - pid_t tracer_pid = (pid_t) atoi(field + sizeof(pattern) - 1); + if (field != NULL && field < buf + sizeof(buf) - OVERLAP) { + pid_t tracer_pid = (pid_t)atoi(field + sizeof(pattern) - 1); tracer_present = (tracer_pid != 0); break; } - if(n_read == sizeof(buf)-1) { - memmove(buf, buf + sizeof(buf)-1 - OVERLAP, OVERLAP); + if (n_read == sizeof(buf) - 1) { + memmove(buf, buf + sizeof(buf) - 1 - OVERLAP, OVERLAP); n_read = OVERLAP; } else { break; @@ -1639,8 +1702,7 @@ acutest_is_tracer_present_(void) #endif #ifdef ACUTEST_MACOS_ -static bool -acutest_AmIBeingDebugged(void) +static bool acutest_AmIBeingDebugged(void) { int junk; int mib[4]; @@ -1664,12 +1726,11 @@ acutest_AmIBeingDebugged(void) assert(junk == 0); // We're being debugged if the P_TRACED flag is set. - return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + return ((info.kp_proc.p_flag & P_TRACED) != 0); } #endif -int -main(int argc, char** argv) +int main(int argc, char **argv) { int i; @@ -1678,28 +1739,30 @@ main(int argc, char** argv) #if defined ACUTEST_UNIX_ acutest_colorize_ = isatty(STDOUT_FILENO); #elif defined ACUTEST_WIN_ - #if defined _BORLANDC_ +#if defined _BORLANDC_ acutest_colorize_ = isatty(_fileno(stdout)); - #else +#else acutest_colorize_ = _isatty(_fileno(stdout)); - #endif +#endif #else acutest_colorize_ = 0; #endif /* Count all test units */ acutest_list_size_ = 0; - for(i = 0; acutest_list_[i].func != NULL; i++) + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_list_size_++; - acutest_test_data_ = (struct acutest_test_data_*)calloc(acutest_list_size_, sizeof(struct acutest_test_data_)); - if(acutest_test_data_ == NULL) { + acutest_test_data_ = (struct acutest_test_data_ *)calloc( + acutest_list_size_, sizeof(struct acutest_test_data_)); + if (acutest_test_data_ == NULL) { fprintf(stderr, "Out of memory.\n"); acutest_exit_(2); } /* Parse options */ - acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, acutest_cmdline_callback_); + acutest_cmdline_read_(acutest_cmdline_options_, argc, argv, + acutest_cmdline_callback_); /* Initialize the proper timer. */ acutest_timer_init_(); @@ -1712,83 +1775,89 @@ main(int argc, char** argv) #endif /* By default, we want to run all tests. */ - if(acutest_count_ == 0) { - for(i = 0; acutest_list_[i].func != NULL; i++) + if (acutest_count_ == 0) { + for (i = 0; acutest_list_[i].func != NULL; i++) acutest_remember_(i); } /* Guess whether we want to run unit tests as child processes. */ - if(acutest_no_exec_ < 0) { + if (acutest_no_exec_ < 0) { acutest_no_exec_ = 0; - if(acutest_count_ <= 1) { + if (acutest_count_ <= 1) { acutest_no_exec_ = 1; } else { #ifdef ACUTEST_WIN_ - if(IsDebuggerPresent()) + if (IsDebuggerPresent()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_LINUX_ - if(acutest_is_tracer_present_()) + if (acutest_is_tracer_present_()) acutest_no_exec_ = 1; #endif #ifdef ACUTEST_MACOS_ - if(acutest_AmIBeingDebugged()) + if (acutest_AmIBeingDebugged()) acutest_no_exec_ = 1; #endif #ifdef RUNNING_ON_VALGRIND - /* RUNNING_ON_VALGRIND is provided by optionally included */ - if(RUNNING_ON_VALGRIND) + /* RUNNING_ON_VALGRIND is provided by optionally included + * */ + if (RUNNING_ON_VALGRIND) acutest_no_exec_ = 1; #endif } } - if(acutest_tap_) { + if (acutest_tap_) { /* TAP requires we know test result ("ok", "not ok") before we output * anything about the test, and this gets problematic for larger verbose * levels. */ - if(acutest_verbose_level_ > 2) + if (acutest_verbose_level_ > 2) acutest_verbose_level_ = 2; /* TAP harness should provide some summary. */ acutest_no_summary_ = 1; - if(!acutest_worker_) - printf("1..%d\n", (int) acutest_count_); + if (!acutest_worker_) + printf("1..%d\n", (int)acutest_count_); } int index = acutest_worker_index_; - for(i = 0; acutest_list_[i].func != NULL; i++) { + for (i = 0; acutest_list_[i].func != NULL; i++) { int run = (acutest_test_data_[i].flags & ACUTEST_FLAG_RUN_); if (acutest_skip_mode_) /* Run all tests except those listed. */ run = !run; - if(run) + if (run) acutest_run_(´st_list_[i], index++, i); } /* Write a summary */ - if(!acutest_no_summary_ && acutest_verbose_level_ >= 1) { - if(acutest_verbose_level_ >= 3) { - acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Summary:\n"); + if (!acutest_no_summary_ && acutest_verbose_level_ >= 1) { + if (acutest_verbose_level_ >= 3) { + acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, + "Summary:\n"); - printf(" Count of all unit tests: %4d\n", (int) acutest_list_size_); - printf(" Count of run unit tests: %4d\n", acutest_stat_run_units_); - printf(" Count of failed unit tests: %4d\n", acutest_stat_failed_units_); - printf(" Count of skipped unit tests: %4d\n", (int) acutest_list_size_ - acutest_stat_run_units_); + printf(" Count of all unit tests: %4d\n", + (int)acutest_list_size_); + printf(" Count of run unit tests: %4d\n", + acutest_stat_run_units_); + printf(" Count of failed unit tests: %4d\n", + acutest_stat_failed_units_); + printf(" Count of skipped unit tests: %4d\n", + (int)acutest_list_size_ - acutest_stat_run_units_); } - if(acutest_stat_failed_units_ == 0) { + if (acutest_stat_failed_units_ == 0) { acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS:"); printf(" All unit tests have passed.\n"); } else { acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED:"); printf(" %d of %d unit tests %s failed.\n", - acutest_stat_failed_units_, acutest_stat_run_units_, - (acutest_stat_failed_units_ == 1) ? "has" : "have"); + acutest_stat_failed_units_, acutest_stat_run_units_, + (acutest_stat_failed_units_ == 1) ? "has" : "have"); } - if(acutest_verbose_level_ >= 3) + if (acutest_verbose_level_ >= 3) printf("\n"); } @@ -1801,16 +1870,23 @@ main(int argc, char** argv) #else const char *suite_name = argv[0]; #endif - fprintf(acutest_xml_output_, "\n"); - fprintf(acutest_xml_output_, "\n", - suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, acutest_stat_failed_units_, - (int)acutest_list_size_ - acutest_stat_run_units_); - for(i = 0; acutest_list_[i].func != NULL; i++) { + fprintf(acutest_xml_output_, + "\n"); + fprintf(acutest_xml_output_, + "\n", + suite_name, (int)acutest_list_size_, acutest_stat_failed_units_, + acutest_stat_failed_units_, + (int)acutest_list_size_ - acutest_stat_run_units_); + for (i = 0; acutest_list_[i].func != NULL; i++) { struct acutest_test_data_ *details = ´st_test_data_[i]; - fprintf(acutest_xml_output_, " \n", acutest_list_[i].name, details->duration); + fprintf(acutest_xml_output_, + " \n", + acutest_list_[i].name, details->duration); if (details->flags & ACUTEST_FLAG_FAILURE_) fprintf(acutest_xml_output_, " \n"); - if (!(details->flags & ACUTEST_FLAG_FAILURE_) && !(details->flags & ACUTEST_FLAG_SUCCESS_)) + if (!(details->flags & ACUTEST_FLAG_FAILURE_) && + !(details->flags & ACUTEST_FLAG_SUCCESS_)) fprintf(acutest_xml_output_, " \n"); fprintf(acutest_xml_output_, " \n"); } @@ -1823,15 +1899,14 @@ main(int argc, char** argv) return (acutest_stat_failed_units_ == 0) ? 0 : 1; } - -#endif /* #ifndef TEST_NO_MAIN */ +#endif /* #ifndef TEST_NO_MAIN */ #ifdef _MSC_VER - #pragma warning(pop) +#pragma warning(pop) #endif #ifdef __cplusplus - } /* extern "C" */ +} /* extern "C" */ #endif -#endif /* #ifndef ACUTEST_H */ +#endif /* #ifndef ACUTEST_H */ diff --git a/tests/unit/test_arm.c b/tests/unit/test_arm.c index 6a609243..4bfd3127 100644 --- a/tests/unit/test_arm.c +++ b/tests/unit/test_arm.c @@ -3,14 +3,17 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_arm_nop() { - uc_engine* uc; +static void test_arm_nop() +{ + uc_engine *uc; char code[] = "\x00\xf0\x20\xe3"; // nop int r_r0 = 0x1234; int r_r2 = 0x6789; @@ -29,8 +32,9 @@ static void test_arm_nop() { OK(uc_close(uc)); } -static void test_arm_thumb_sub() { - uc_engine* uc; +static void test_arm_thumb_sub() +{ + uc_engine *uc; char code[] = "\x83\xb0"; // sub sp, #0xc int r_sp = 0x1234; @@ -45,15 +49,18 @@ static void test_arm_thumb_sub() { OK(uc_close(uc)); } -static void test_armeb_sub() { - uc_engine* uc; - char code[] = "\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3 +static void test_armeb_sub() +{ + uc_engine *uc; + char code[] = + "\xe3\xa0\x00\x37\xe0\x42\x10\x03"; // mov r0, #0x37; sub r1, r2, r3 int r_r0 = 0x1234; int r_r2 = 0x6789; int r_r3 = 0x3333; int r_r1; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_R0, &r_r0)); OK(uc_reg_write(uc, UC_ARM_REG_R2, &r_r2)); OK(uc_reg_write(uc, UC_ARM_REG_R3, &r_r3)); @@ -73,12 +80,14 @@ static void test_armeb_sub() { OK(uc_close(uc)); } -static void test_arm_thumbeb_sub() { - uc_engine* uc; +static void test_arm_thumbeb_sub() +{ + uc_engine *uc; char code[] = "\xb0\x83"; // sub sp, #0xc int r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); @@ -89,16 +98,25 @@ static void test_arm_thumbeb_sub() { OK(uc_close(uc)); } -static void test_arm_thumb_ite_count_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) { - uint64_t* count = (uint64_t*)user_data; +static void test_arm_thumb_ite_count_callback(uc_engine *uc, uint64_t address, + uint32_t size, void *user_data) +{ + uint64_t *count = (uint64_t *)user_data; (*count) += 1; } -static void test_arm_thumb_ite() { - uc_engine* uc; +static void test_arm_thumb_ite() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete ne; ldrne r2, [sp]; ldreq r2, [sp,#4]; movne r3, #0x78; moveq r3, #0x15 + char code[] = + "\x9a\x42\x15\xbf\x00\x9a\x01\x9a\x78\x23\x15\x23"; // cmp r2, r3; itete + // ne; ldrne r2, + // [sp]; ldreq r2, + // [sp,#4]; movne + // r3, #0x78; moveq + // r3, #0x15 int r_sp = 0x8000; int r_r2 = 0; int r_r3 = 1; @@ -116,7 +134,8 @@ static void test_arm_thumb_ite() { r_r2 = 0x4d; OK(uc_mem_write(uc, r_sp + 4, &r_r2, 4)); - OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback, &count, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_arm_thumb_ite_count_callback, + &count, 1, 0)); // Execute four instructions at a time. OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); @@ -146,19 +165,22 @@ static void test_arm_thumb_ite() { OK(uc_close(uc)); } -static void test_arm_m_thumb_mrs() { - uc_engine* uc; - char code[] = "\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr +static void test_arm_m_thumb_mrs() +{ + uc_engine *uc; + char code[] = + "\xef\xf3\x14\x80\xef\xf3\x00\x81"; // mrs r0, control; mrs r1, apsr uint32_t r_control = 0b10; uint32_t r_apsr = (0b10101 << 27); uint32_t r_r0, r_r1; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_ARM_REG_CONTROL, &r_control)); OK(uc_reg_write(uc, UC_ARM_REG_APSR_NZCVQ, &r_apsr)); OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0)); - + OK(uc_reg_read(uc, UC_ARM_REG_R0, &r_r0)); OK(uc_reg_read(uc, UC_ARM_REG_R1, &r_r1)); @@ -168,8 +190,9 @@ static void test_arm_m_thumb_mrs() { OK(uc_close(uc)); } -static void test_arm_m_control() { - uc_engine* uc; +static void test_arm_m_control() +{ + uc_engine *uc; int r_control, r_msp, r_psp; OK(uc_open(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, &uc)); @@ -195,16 +218,19 @@ static void test_arm_m_control() { OK(uc_reg_read(uc, UC_ARM_REG_R13, &r_msp)); TEST_CHECK(r_psp != r_msp); TEST_CHECK(r_msp == 0x1000); - + OK(uc_close(uc)); } // // Some notes: -// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the EXC_RETURN. We can't -// help user handle EXC_RETURN since unicorn is designed not to handle any CPU exception. +// Qemu raise a special exception EXCP_EXCEPTION_EXIT to handle the +// EXC_RETURN. We can't help user handle EXC_RETURN since unicorn is designed +// not to handle any CPU exception. // -static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void* data) { +static void test_arm_m_exc_return_hook_interrupt(uc_engine *uc, int intno, + void *data) +{ int r_pc; OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc)); @@ -213,16 +239,19 @@ static void test_arm_m_exc_return_hook_interrupt(uc_engine* uc, int intno, void* OK(uc_emu_stop(uc)); } -static void test_arm_m_exc_return() { - uc_engine* uc; +static void test_arm_m_exc_return() +{ + uc_engine *uc; char code[] = "\x6f\xf0\x02\x00\x00\x47"; // mov r0, #0xFFFFFFFD; bx r0; int r_ipsr; int r_sp = 0x8000; uc_hook hook; - uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_MCLASS, code, + sizeof(code) - 1); OK(uc_mem_map(uc, r_sp - 0x1000, 0x1000, UC_PROT_ALL)); - OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, test_arm_m_exc_return_hook_interrupt, NULL, 0, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_INTR, + test_arm_m_exc_return_hook_interrupt, NULL, 0, 0)); r_sp -= 0x1c; OK(uc_reg_write(uc, UC_ARM_REG_SP, &r_sp)); @@ -230,20 +259,19 @@ static void test_arm_m_exc_return() { r_ipsr = 16; // We are in whatever exception. OK(uc_reg_write(uc, UC_ARM_REG_IPSR, &r_ipsr)); - OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 2)); // Just execute 2 instructions. + OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, + 2)); // Just execute 2 instructions. OK(uc_hook_del(uc, hook)); OK(uc_close(uc)); } -TEST_LIST = { - { "test_arm_nop", test_arm_nop }, - { "test_arm_thumb_sub", test_arm_thumb_sub }, - { "test_armeb_sub", test_armeb_sub }, - { "test_arm_thumbeb_sub", test_arm_thumbeb_sub }, - { "test_arm_thumb_ite", test_arm_thumb_ite }, - { "test_arm_m_thumb_mrs", test_arm_m_thumb_mrs }, - { "test_arm_m_control", test_arm_m_control }, - { "test_arm_m_exc_return", test_arm_m_exc_return }, - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{"test_arm_nop", test_arm_nop}, + {"test_arm_thumb_sub", test_arm_thumb_sub}, + {"test_armeb_sub", test_armeb_sub}, + {"test_arm_thumbeb_sub", test_arm_thumbeb_sub}, + {"test_arm_thumb_ite", test_arm_thumb_ite}, + {"test_arm_m_thumb_mrs", test_arm_m_thumb_mrs}, + {"test_arm_m_control", test_arm_m_control}, + {"test_arm_m_exc_return", test_arm_m_exc_return}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_arm64.c b/tests/unit/test_arm64.c index 59333f4d..302945db 100644 --- a/tests/unit/test_arm64.c +++ b/tests/unit/test_arm64.c @@ -3,52 +3,51 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_arm64_until() { - uc_engine *uc; - char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91"; +static void test_arm64_until() +{ + uc_engine *uc; + char code[] = "\x30\x00\x80\xd2\x11\x04\x80\xd2\x9c\x23\x00\x91"; - /* - mov x16, #1 - mov x17, #0x20 - add x28, x28, 8 - */ + /* + mov x16, #1 + mov x17, #0x20 + add x28, x28, 8 + */ - uint64_t r_x16 = 0x12341234; - uint64_t r_x17 = 0x78907890; - uint64_t r_pc = 0x00000000; - uint64_t r_x28 = 0x12341234; + uint64_t r_x16 = 0x12341234; + uint64_t r_x17 = 0x78907890; + uint64_t r_pc = 0x00000000; + uint64_t r_x28 = 0x12341234; - uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_ARM64, UC_MODE_ARM, code, sizeof(code) - 1); - // initialize machine registers - OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16)); - OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17)); - OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28)); + // initialize machine registers + OK(uc_reg_write(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_write(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_write(uc, UC_ARM64_REG_X28, &r_x28)); - // emulate the three instructions - OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 3)); - OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16)); - OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17)); - OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28)); - OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_ARM64_REG_X16, &r_x16)); + OK(uc_reg_read(uc, UC_ARM64_REG_X17, &r_x17)); + OK(uc_reg_read(uc, UC_ARM64_REG_X28, &r_x28)); + OK(uc_reg_read(uc, UC_ARM64_REG_PC, &r_pc)); - TEST_CHECK(r_x16 == 0x1); - TEST_CHECK(r_x17 == 0x20); - TEST_CHECK(r_x28 == 0x1234123c); - TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + TEST_CHECK(r_x16 == 0x1); + TEST_CHECK(r_x17 == 0x20); + TEST_CHECK(r_x28 == 0x1234123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); - OK(uc_close(uc)); + OK(uc_close(uc)); } - -TEST_LIST = { - { "test_arm64_until", test_arm64_until }, - { NULL, NULL } -}; +TEST_LIST = {{"test_arm64_until", test_arm64_until}, {NULL, NULL}}; diff --git a/tests/unit/test_m68k.c b/tests/unit/test_m68k.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_m68k.c +++ b/tests/unit/test_m68k.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_mem.c b/tests/unit/test_mem.c index 008ec146..987a3ae3 100644 --- a/tests/unit/test_mem.c +++ b/tests/unit/test_mem.c @@ -1,34 +1,40 @@ #include "unicorn_test.h" -static void test_map_correct() { - uc_engine* uc; +static void test_map_correct() +{ + uc_engine *uc; - OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc)); - OK(uc_mem_map (uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000] - OK(uc_mem_map (uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000] - OK(uc_mem_map (uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000] - uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL)); - uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL)); - uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL)); - uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL)); - uc_assert_err(UC_ERR_MAP, uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL)); + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + OK(uc_mem_map(uc, 0x40000, 0x1000 * 16, UC_PROT_ALL)); // [0x40000, 0x50000] + OK(uc_mem_map(uc, 0x60000, 0x1000 * 16, UC_PROT_ALL)); // [0x60000, 0x70000] + OK(uc_mem_map(uc, 0x20000, 0x1000 * 16, UC_PROT_ALL)); // [0x20000, 0x30000] + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x10000, 0x2000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x25000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x35000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x45000, 0x1000 * 16, UC_PROT_ALL)); + uc_assert_err(UC_ERR_MAP, + uc_mem_map(uc, 0x55000, 0x2000 * 16, UC_PROT_ALL)); OK(uc_mem_map(uc, 0x35000, 0x5000, UC_PROT_ALL)); OK(uc_mem_map(uc, 0x50000, 0x5000, UC_PROT_ALL)); OK(uc_close(uc)); } -static void test_map_wrapping() { - uc_engine* uc; +static void test_map_wrapping() +{ + uc_engine *uc; - OK(uc_open (UC_ARCH_X86, UC_MODE_64, &uc)); - uc_assert_err(UC_ERR_ARG, uc_mem_map (uc, (~0ll - 0x4000) & ~0xfff, 0x8000, UC_PROT_ALL)); + OK(uc_open(UC_ARCH_X86, UC_MODE_64, &uc)); + uc_assert_err(UC_ERR_ARG, uc_mem_map(uc, (~0ll - 0x4000) & ~0xfff, 0x8000, + UC_PROT_ALL)); OK(uc_close(uc)); } -TEST_LIST = { - { "test_map_correct", test_map_correct }, - { "test_map_wrapping", test_map_wrapping }, - { NULL, NULL } -}; +TEST_LIST = {{"test_map_correct", test_map_correct}, + {"test_map_wrapping", test_map_wrapping}, + {NULL, NULL}}; diff --git a/tests/unit/test_mips.c b/tests/unit/test_mips.c index bfff4cad..61699e5d 100644 --- a/tests/unit/test_mips.c +++ b/tests/unit/test_mips.c @@ -3,18 +3,22 @@ const uint64_t code_start = 0x10000000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_mips_el_ori() { - uc_engine* uc; +static void test_mips_el_ori() +{ + uc_engine *uc; char code[] = "\x56\x34\x21\x34"; // ori $at, $at, 0x3456; int r_r1 = 0x6789; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -26,12 +30,14 @@ static void test_mips_el_ori() { OK(uc_close(uc)); } -static void test_mips_eb_ori() { - uc_engine* uc; +static void test_mips_eb_ori() +{ + uc_engine *uc; char code[] = "\x34\x21\x34\x56"; // ori $at, $at, 0x3456; int r_r1 = 0x6789; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_MIPS_REG_1, &r_r1)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -43,37 +49,43 @@ static void test_mips_eb_ori() { OK(uc_close(uc)); } -static void test_mips_stop_at_branch() { - uc_engine* uc; - char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; +static void test_mips_stop_at_branch() +{ + uc_engine *uc; + char code[] = + "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; int r_pc = 0x0; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); - + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); + // Execute one instruction with branch delay slot. OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 1)); OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc)); - // Even if we just execute one instruction, the instruction in the + // Even if we just execute one instruction, the instruction in the // delay slot would also be executed. TEST_CHECK(r_pc == code_start + 0x8); OK(uc_close(uc)); } -static void test_mips_stop_at_delay_slot() { - uc_engine* uc; - char code[] = "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; +static void test_mips_stop_at_delay_slot() +{ + uc_engine *uc; + char code[] = + "\x02\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00"; // j 0x8; nop; int r_pc = 0x0; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); - + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); + // Stop at the delay slot by design. OK(uc_emu_start(uc, code_start, code_start + 4, 0, 0)); OK(uc_reg_read(uc, UC_MIPS_REG_PC, &r_pc)); - + // The branch instruction isn't committed and the PC is not updated. // Users is responsible to restart emulation at the branch instruction. TEST_CHECK(r_pc == code_start); @@ -81,12 +93,14 @@ static void test_mips_stop_at_delay_slot() { OK(uc_close(uc)); } -static void test_mips_lwx_exception_issue_1314() { - uc_engine* uc; +static void test_mips_lwx_exception_issue_1314() +{ + uc_engine *uc; char code[] = "\x0a\xc8\x79\x7e"; // lwx $t9, $t9($s3) int reg; - uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_MIPS, UC_MODE_32 | UC_MODE_LITTLE_ENDIAN, code, + sizeof(code) - 1); OK(uc_mem_map(uc, 0x10000, 0x4000, UC_PROT_ALL)); // Enable DSP @@ -113,10 +127,9 @@ static void test_mips_lwx_exception_issue_1314() { } TEST_LIST = { - { "test_mips_stop_at_branch", test_mips_stop_at_branch }, - { "test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot}, - { "test_mips_el_ori", test_mips_el_ori}, - { "test_mips_eb_ori", test_mips_eb_ori}, - { "test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314}, - { NULL, NULL } -}; \ No newline at end of file + {"test_mips_stop_at_branch", test_mips_stop_at_branch}, + {"test_mips_stop_at_delay_slot", test_mips_stop_at_delay_slot}, + {"test_mips_el_ori", test_mips_el_ori}, + {"test_mips_eb_ori", test_mips_eb_ori}, + {"test_mips_lwx_exception_issue_1314", test_mips_lwx_exception_issue_1314}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_ppc.c b/tests/unit/test_ppc.c index c457bd70..41fed7c4 100644 --- a/tests/unit/test_ppc.c +++ b/tests/unit/test_ppc.c @@ -3,18 +3,22 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_ppc32_add() { - uc_engine* uc; +static void test_ppc32_add() +{ + uc_engine *uc; char code[] = "\x7f\x46\x1a\x14"; // ADD 26, 6, 3 int reg; - uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_PPC, UC_MODE_32 | UC_MODE_BIG_ENDIAN, code, + sizeof(code) - 1); reg = 42; OK(uc_reg_write(uc, UC_PPC_REG_3, ®)); @@ -30,7 +34,4 @@ static void test_ppc32_add() { OK(uc_close(uc)); } -TEST_LIST = { - { "test_ppc32_add", test_ppc32_add }, - { NULL, NULL} -}; \ No newline at end of file +TEST_LIST = {{"test_ppc32_add", test_ppc32_add}, {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_riscv.c b/tests/unit/test_riscv.c index 8617e631..24fb87e1 100644 --- a/tests/unit/test_riscv.c +++ b/tests/unit/test_riscv.c @@ -3,19 +3,23 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); } -static void test_riscv32_nop() { - uc_engine* uc; +static void test_riscv32_nop() +{ + uc_engine *uc; char code[] = "\x13\x00\x00\x00"; // nop uint32_t r_t0 = 0x1234; uint32_t r_t1 = 0x5678; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); @@ -29,13 +33,15 @@ static void test_riscv32_nop() { OK(uc_close(uc)); } -static void test_riscv64_nop() { - uc_engine* uc; +static void test_riscv64_nop() +{ + uc_engine *uc; char code[] = "\x13\x00\x00\x00"; // nop uint64_t r_t0 = 0x1234; uint64_t r_t1 = 0x5678; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); @@ -49,167 +55,172 @@ static void test_riscv64_nop() { OK(uc_close(uc)); } -static void test_riscv32_until_pc_update() { - uc_engine *uc; - char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; +static void test_riscv32_until_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; - /* - addi t0, zero, 1 - addi t1, zero, 0x20 - addi sp, sp, 8 - */ + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ - uint32_t r_t0 = 0x1234; - uint32_t r_t1 = 0x7890; - uint32_t r_pc = 0x0000; - uint32_t r_sp = 0x1234; + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); - // initialize machine registers - OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); - // emulate the three instructions - OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); - OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); - TEST_CHECK(r_t0 == 0x1); - TEST_CHECK(r_t1 == 0x20); - TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); - TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); - OK(uc_close(uc)); + OK(uc_close(uc)); } -static void test_riscv64_until_pc_update() { - uc_engine *uc; - char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; +static void test_riscv64_until_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; - /* - addi t0, zero, 1 - addi t1, zero, 0x20 - addi sp, sp, 8 - */ + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ - uint64_t r_t0 = 0x1234; - uint64_t r_t1 = 0x7890; - uint64_t r_pc = 0x0000; - uint64_t r_sp = 0x1234; + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); - // initialize machine registers - OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); - // emulate the three instructions - OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + // emulate the three instructions + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); - OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); - TEST_CHECK(r_t0 == 0x1); - TEST_CHECK(r_t1 == 0x20); - TEST_CHECK(r_sp == 0x123c); - TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); - OK(uc_close(uc)); + OK(uc_close(uc)); } -static void test_riscv32_3steps_pc_update() { - uc_engine *uc; - char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; +static void test_riscv32_3steps_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; - /* - addi t0, zero, 1 - addi t1, zero, 0x20 - addi sp, sp, 8 - */ + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ - uint32_t r_t0 = 0x1234; - uint32_t r_t1 = 0x7890; - uint32_t r_pc = 0x0000; - uint32_t r_sp = 0x1234; + uint32_t r_t0 = 0x1234; + uint32_t r_t1 = 0x7890; + uint32_t r_pc = 0x0000; + uint32_t r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV32, code, + sizeof(code) - 1); - // initialize machine registers - OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); - // emulate the three instructions - OK(uc_emu_start(uc, code_start, -1, 0, 3)); + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); - OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); - OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); - TEST_CHECK(r_t0 == 0x1); - TEST_CHECK(r_t1 == 0x20); - TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); - TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); - OK(uc_close(uc)); + OK(uc_close(uc)); } -static void test_riscv64_3steps_pc_update() { - uc_engine *uc; - char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; +static void test_riscv64_3steps_pc_update() +{ + uc_engine *uc; + char code[] = "\x93\x02\x10\x00\x13\x03\x00\x02\x13\x01\x81\x00"; - /* - addi t0, zero, 1 - addi t1, zero, 0x20 - addi sp, sp, 8 - */ + /* + addi t0, zero, 1 + addi t1, zero, 0x20 + addi sp, sp, 8 + */ - uint64_t r_t0 = 0x1234; - uint64_t r_t1 = 0x7890; - uint64_t r_pc = 0x0000; - uint64_t r_sp = 0x1234; + uint64_t r_t0 = 0x1234; + uint64_t r_t1 = 0x7890; + uint64_t r_pc = 0x0000; + uint64_t r_sp = 0x1234; - uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, sizeof(code) - 1); + uc_common_setup(&uc, UC_ARCH_RISCV, UC_MODE_RISCV64, code, + sizeof(code) - 1); - // initialize machine registers - OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); + // initialize machine registers + OK(uc_reg_write(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_write(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_write(uc, UC_RISCV_REG_SP, &r_sp)); - // emulate the three instructions - OK(uc_emu_start(uc, code_start, -1, 0, 3)); + // emulate the three instructions + OK(uc_emu_start(uc, code_start, -1, 0, 3)); - OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); - OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); - OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); - OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); + OK(uc_reg_read(uc, UC_RISCV_REG_T0, &r_t0)); + OK(uc_reg_read(uc, UC_RISCV_REG_T1, &r_t1)); + OK(uc_reg_read(uc, UC_RISCV_REG_SP, &r_sp)); + OK(uc_reg_read(uc, UC_RISCV_REG_PC, &r_pc)); - TEST_CHECK(r_t0 == 0x1); - TEST_CHECK(r_t1 == 0x20); - TEST_CHECK(r_sp == 0x123c); - TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); + TEST_CHECK(r_t0 == 0x1); + TEST_CHECK(r_t1 == 0x20); + TEST_CHECK(r_sp == 0x123c); + TEST_CHECK(r_pc == (code_start + sizeof(code) - 1)); - OK(uc_close(uc)); + OK(uc_close(uc)); } - -TEST_LIST = { - { "test_riscv32_nop", test_riscv32_nop }, - { "test_riscv64_nop", test_riscv64_nop }, - { "test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update }, - { "test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update }, - { "test_riscv32_until_pc_update", test_riscv32_until_pc_update }, - { "test_riscv64_until_pc_update", test_riscv64_until_pc_update }, - { NULL, NULL } -}; +TEST_LIST = {{"test_riscv32_nop", test_riscv32_nop}, + {"test_riscv64_nop", test_riscv64_nop}, + {"test_riscv32_3steps_pc_update", test_riscv32_3steps_pc_update}, + {"test_riscv64_3steps_pc_update", test_riscv64_3steps_pc_update}, + {"test_riscv32_until_pc_update", test_riscv32_until_pc_update}, + {"test_riscv64_until_pc_update", test_riscv64_until_pc_update}, + {NULL, NULL}}; diff --git a/tests/unit/test_sparc.c b/tests/unit/test_sparc.c index 972d24c6..4c2505f4 100644 --- a/tests/unit/test_sparc.c +++ b/tests/unit/test_sparc.c @@ -3,6 +3,4 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -TEST_LIST = { - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 17d346ef..ab9eca6f 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -3,7 +3,9 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; -static void uc_common_setup(uc_engine** uc, uc_arch arch, uc_mode mode, const char* code, uint64_t size) { +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ OK(uc_open(arch, mode, uc)); OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); OK(uc_mem_write(*uc, code_start, code, size)); @@ -14,22 +16,26 @@ typedef struct _INSN_IN_RESULT { int size; } INSN_IN_RESULT; -static void test_x86_in_callback(uc_engine* uc, uint32_t port, int size, void* user_data) { - INSN_IN_RESULT* result = (INSN_IN_RESULT*)user_data; +static void test_x86_in_callback(uc_engine *uc, uint32_t port, int size, + void *user_data) +{ + INSN_IN_RESULT *result = (INSN_IN_RESULT *)user_data; result->port = port; result->size = size; } -static void test_x86_in() { - uc_engine* uc; +static void test_x86_in() +{ + uc_engine *uc; uc_hook hook; char code[] = "\xe5\x10"; // IN eax, 0x10 INSN_IN_RESULT result; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0, UC_X86_INS_IN)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_in_callback, &result, 1, 0, + UC_X86_INS_IN)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(result.port == 0x10); TEST_CHECK(result.size == 4); @@ -44,23 +50,27 @@ typedef struct _INSN_OUT_RESULT { uint32_t value; } INSN_OUT_RESULT; -static void test_x86_out_callback(uc_engine* uc, uint32_t port, int size, uint32_t value, void* user_data) { - INSN_OUT_RESULT* result = (INSN_OUT_RESULT*)user_data; +static void test_x86_out_callback(uc_engine *uc, uint32_t port, int size, + uint32_t value, void *user_data) +{ + INSN_OUT_RESULT *result = (INSN_OUT_RESULT *)user_data; result->port = port; result->size = size; result->value = value; } -static void test_x86_out() { - uc_engine* uc; +static void test_x86_out() +{ + uc_engine *uc; uc_hook hook; char code[] = "\xb0\x32\xe6\x46"; // MOV al, 0x32; OUT 0x46, al; INSN_OUT_RESULT result; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1, 0, UC_X86_INS_OUT)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_out_callback, &result, 1, + 0, UC_X86_INS_OUT)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(result.port == 0x46); TEST_CHECK(result.size == 1); @@ -82,8 +92,11 @@ typedef struct _MEM_HOOK_RESULTS { MEM_HOOK_RESULT results[16]; } MEM_HOOK_RESULTS; -static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { - MEM_HOOK_RESULTS* r = (MEM_HOOK_RESULTS*)user_data; +static bool test_x86_mem_hook_all_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ + MEM_HOOK_RESULTS *r = (MEM_HOOK_RESULTS *)user_data; uint64_t count = r->count; if (count >= 16) { @@ -103,27 +116,28 @@ static bool test_x86_mem_hook_all_callback(uc_engine* uc, uc_mem_type type, uint return true; } -static void test_x86_mem_hook_all() { - uc_engine* uc; +static void test_x86_mem_hook_all() +{ + uc_engine *uc; uc_hook hook; // mov eax, 0xdeadbeef; // mov [0x8000], eax; // mov eax, [0x10000]; - char code[] = "\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00"; - MEM_HOOK_RESULTS r = { 0 }; - MEM_HOOK_RESULT expects[3] = { - {UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef}, - {UC_MEM_READ_UNMAPPED, 0x10000, 4, 0}, - {UC_MEM_READ, 0x10000, 4, 0} - }; + char code[] = + "\xb8\xef\xbe\xad\xde\xa3\x00\x80\x00\x00\xa1\x00\x00\x01\x00"; + MEM_HOOK_RESULTS r = {0}; + MEM_HOOK_RESULT expects[3] = {{UC_MEM_WRITE, 0x8000, 4, 0xdeadbeef}, + {UC_MEM_READ_UNMAPPED, 0x10000, 4, 0}, + {UC_MEM_READ, 0x10000, 4, 0}}; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_mem_map(uc, 0x8000, 0x1000, UC_PROT_ALL)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID, test_x86_mem_hook_all_callback, &r, 1, 0)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_VALID | UC_HOOK_MEM_INVALID, + test_x86_mem_hook_all_callback, &r, 1, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); TEST_CHECK(r.count == 3); - for (int i = 0; i < r.count; i ++) { + for (int i = 0; i < r.count; i++) { TEST_CHECK(expects[i].type == r.results[i].type); TEST_CHECK(expects[i].address == r.results[i].address); TEST_CHECK(expects[i].size == r.results[i].size); @@ -134,9 +148,11 @@ static void test_x86_mem_hook_all() { OK(uc_close(uc)); } -static void test_x86_inc_dec_pxor() { - uc_engine* uc; - char code[] = "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1 +static void test_x86_inc_dec_pxor() +{ + uc_engine *uc; + char code[] = + "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1 int r_ecx = 0x1234; int r_edx = 0x7890; uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607}; @@ -162,9 +178,11 @@ static void test_x86_inc_dec_pxor() { OK(uc_close(uc)); } -static void test_x86_relative_jump() { - uc_engine* uc; - char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; nop; nop; nop +static void test_x86_relative_jump() +{ + uc_engine *uc; + char code[] = "\xeb\x02\x90\x90\x90\x90\x90\x90"; // jmp 4; nop; nop; nop; + // nop; nop; nop int r_eip; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); @@ -178,8 +196,9 @@ static void test_x86_relative_jump() { OK(uc_close(uc)); } -static void test_x86_loop() { - uc_engine* uc; +static void test_x86_loop() +{ + uc_engine *uc; char code[] = "\x41\x4a\xeb\xfe"; // inc ecx; dec edx; jmp $; int r_ecx = 0x1234; int r_edx = 0x7890; @@ -188,7 +207,8 @@ static void test_x86_loop() { OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 1 * 1000000, + 0)); OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx)); @@ -199,40 +219,50 @@ static void test_x86_loop() { OK(uc_close(uc)); } -static void test_x86_invalid_mem_read() { - uc_engine* uc; +static void test_x86_invalid_mem_read() +{ + uc_engine *uc; char code[] = "\x8b\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_READ_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_invalid_mem_write() { - uc_engine* uc; +static void test_x86_invalid_mem_write() +{ + uc_engine *uc; char code[] = "\x89\x0d\xaa\xaa\xaa\xaa"; // mov ecx, [0xAAAAAAAA] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_WRITE_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_WRITE_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_invalid_jump() { - uc_engine* uc; +static void test_x86_invalid_jump() +{ + uc_engine *uc; char code[] = "\xe9\xe9\xee\xee\xee"; // jmp 0xEEEEEEEE uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - uc_assert_err(UC_ERR_FETCH_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_FETCH_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_close(uc)); } -static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) { +static void test_x86_64_syscall_callback(uc_engine *uc, void *user_data) +{ uint64_t rax; OK(uc_reg_read(uc, UC_X86_REG_RAX, &rax)); @@ -240,15 +270,17 @@ static void test_x86_64_syscall_callback(uc_engine* uc, void* user_data) { TEST_CHECK(rax == 0x100); } -static void test_x86_64_syscall() { - uc_engine* uc; +static void test_x86_64_syscall() +{ + uc_engine *uc; uc_hook hook; char code[] = "\x0f\x05"; // syscall uint64_t r_rax = 0x100; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_64, code, sizeof(code) - 1); OK(uc_reg_write(uc, UC_X86_REG_RAX, &r_rax)); - OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL, 1, 0, UC_X86_INS_SYSCALL)); + OK(uc_hook_add(uc, &hook, UC_HOOK_INSN, test_x86_64_syscall_callback, NULL, + 1, 0, UC_X86_INS_SYSCALL)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -256,8 +288,9 @@ static void test_x86_64_syscall() { OK(uc_close(uc)); } -static void test_x86_16_add() { - uc_engine* uc; +static void test_x86_16_add() +{ + uc_engine *uc; char code[] = "\x00\x00"; // add byte ptr [bx + si], al uint16_t r_ax = 7; uint16_t r_bx = 5; @@ -277,9 +310,10 @@ static void test_x86_16_add() { OK(uc_close(uc)); } -static void test_x86_reg_save() { - uc_engine* uc; - uc_context* ctx; +static void test_x86_reg_save() +{ + uc_engine *uc; + uc_context *ctx; char code[] = "\x40"; // inc eax int r_eax = 1; @@ -289,7 +323,7 @@ static void test_x86_reg_save() { OK(uc_context_alloc(uc, &ctx)); OK(uc_context_save(uc, ctx)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); - + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); TEST_CHECK(r_eax == 2); @@ -302,27 +336,38 @@ static void test_x86_reg_save() { OK(uc_close(uc)); } -static bool test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { - // False indicates that we fail to handle this ERROR and let the emulation stop. +static bool +test_x86_invalid_mem_read_stop_in_cb_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ + // False indicates that we fail to handle this ERROR and let the emulation + // stop. // - // Note that the memory must be mapped properly if we return true! Check test_x86_mem_hook_all for example. + // Note that the memory must be mapped properly if we return true! Check + // test_x86_mem_hook_all for example. return false; } -static void test_x86_invalid_mem_read_stop_in_cb() { - uc_engine* uc; +static void test_x86_invalid_mem_read_stop_in_cb() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx, [0x100000]; inc edx + char code[] = "\x40\x8b\x1d\x00\x00\x10\x00\x42"; // inc eax; mov ebx, + // [0x100000]; inc edx int r_eax = 0x1234; int r_edx = 0x5678; int r_eip = 0; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_READ, + test_x86_invalid_mem_read_stop_in_cb_callback, NULL, 1, 0)); OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - uc_assert_err(UC_ERR_READ_UNMAPPED, uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + uc_assert_err( + UC_ERR_READ_UNMAPPED, + uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); // The state of Unicorn should be correct at this time. OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip)); @@ -336,8 +381,9 @@ static void test_x86_invalid_mem_read_stop_in_cb() { OK(uc_close(uc)); } - -static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint32_t size, void* user_data) { +static void test_x86_x87_fnstenv_callback(uc_engine *uc, uint64_t address, + uint32_t size, void *user_data) +{ uint32_t r_eip; uint32_t r_eax; uint32_t fnstenv[7]; @@ -345,8 +391,8 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3 if (address == code_start + 4) { // The first fnstenv executed // Save the address of the fld. OK(uc_reg_read(uc, UC_X86_REG_EIP, &r_eip)); - *((uint32_t*)user_data) = r_eip; - + *((uint32_t *)user_data) = r_eip; + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); OK(uc_mem_read(uc, r_eax, fnstenv, sizeof(fnstenv))); // Don't update FCS:FIP for fnop. @@ -354,10 +400,13 @@ static void test_x86_x87_fnstenv_callback(uc_engine* uc, uint64_t address, uint3 } } -static void test_x86_x87_fnstenv() { - uc_engine* uc; +static void test_x86_x87_fnstenv() +{ + uc_engine *uc; uc_hook hook; - char code[] = "\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr [eax];fnstenv [eax] + char code[] = + "\xd9\xd0\xd9\x30\xd9\x00\xd9\x30"; // fnop;fnstenv [eax];fld dword ptr + // [eax];fnstenv [eax] uint32_t base = code_start + 3 * code_len; uint32_t last_eip; uint32_t fnstenv[7]; @@ -366,25 +415,31 @@ static void test_x86_x87_fnstenv() { OK(uc_mem_map(uc, base, code_len, UC_PROT_ALL)); OK(uc_reg_write(uc, UC_X86_REG_EAX, &base)); - OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback, &last_eip, 1, 0)); - + OK(uc_hook_add(uc, &hook, UC_HOOK_CODE, test_x86_x87_fnstenv_callback, + &last_eip, 1, 0)); + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); OK(uc_mem_read(uc, base, fnstenv, sizeof(fnstenv))); - //But update FCS:FIP for fld. + // But update FCS:FIP for fld. TEST_CHECK(fnstenv[3] == last_eip); OK(uc_close(uc)); } -static uint64_t test_x86_mmio_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) { +static uint64_t test_x86_mmio_read_callback(uc_engine *uc, uint64_t offset, + unsigned size, void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); return 0x19260817; } -static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) { +static void test_x86_mmio_write_callback(uc_engine *uc, uint64_t offset, + unsigned size, uint64_t value, + void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); TEST_CHECK(value == 0xdeadbeef); @@ -392,14 +447,19 @@ static void test_x86_mmio_write_callback(uc_engine* uc, uint64_t offset, unsigne return; } -static void test_x86_mmio() { - uc_engine* uc; +static void test_x86_mmio() +{ + uc_engine *uc; int r_ecx = 0xdeadbeef; - char code[] = "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004], ecx; mov ecx, [0x20004] + char code[] = + "\x89\x0d\x04\x00\x02\x00\x8b\x0d\x04\x00\x02\x00"; // mov [0x20004], + // ecx; mov ecx, + // [0x20004] uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); - OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL, test_x86_mmio_write_callback, NULL)); + OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_read_callback, NULL, + test_x86_mmio_write_callback, NULL)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -410,7 +470,10 @@ static void test_x86_mmio() { OK(uc_close(uc)); } -static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint64_t address, int size, uint64_t value, void* user_data) { +static bool test_x86_missing_code_callback(uc_engine *uc, uc_mem_type type, + uint64_t address, int size, + uint64_t value, void *user_data) +{ char code[] = "\x41\x4a"; // inc ecx; dec edx; uint64_t algined_address = address & 0xFFFFFFFFFFFFF000ULL; int aligned_size = ((int)(size / 0x1000) + 1) * 0x1000; @@ -422,8 +485,9 @@ static bool test_x86_missing_code_callback(uc_engine* uc, uc_mem_type type, uint return true; } -static void test_x86_missing_code() { - uc_engine* uc; +static void test_x86_missing_code() +{ + uc_engine *uc; uc_hook hook; int r_ecx = 0x1234; int r_edx = 0x7890; @@ -432,7 +496,8 @@ static void test_x86_missing_code() { OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, test_x86_missing_code_callback, NULL, 1, 0)); + OK(uc_hook_add(uc, &hook, UC_HOOK_MEM_UNMAPPED, + test_x86_missing_code_callback, NULL, 1, 0)); OK(uc_emu_start(uc, code_start, code_start + 2, 0, 0)); @@ -445,13 +510,14 @@ static void test_x86_missing_code() { OK(uc_close(uc)); } -static void test_x86_smc_xor() { - uc_engine* uc; +static void test_x86_smc_xor() +{ + uc_engine *uc; /* - * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 - * 0x1003 dw 0x3ea98b13 - */ - char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e"; + * 0x1000 xor dword ptr [edi+0x3], eax ; edi=0x1000, eax=0xbc4177e6 + * 0x1003 dw 0x3ea98b13 + */ + char code[] = "\x31\x47\x03\x13\x8b\xa9\x3e"; int r_edi = code_start; int r_eax = 0xbc4177e6; uint32_t result; @@ -469,14 +535,23 @@ static void test_x86_smc_xor() { OK(uc_close(uc)); } -static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine* uc, uint64_t offset, unsigned size, void* user_data) { +static uint64_t test_x86_mmio_uc_mem_rw_read_callback(uc_engine *uc, + uint64_t offset, + unsigned size, + void *user_data) +{ TEST_CHECK(offset == 8); TEST_CHECK(size == 4); return 0x19260817; } -static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offset, unsigned size, uint64_t value, void* user_data) { +static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine *uc, + uint64_t offset, + unsigned size, + uint64_t value, + void *user_data) +{ TEST_CHECK(offset == 4); TEST_CHECK(size == 4); TEST_CHECK(value == 0xdeadbeef); @@ -484,39 +559,40 @@ static void test_x86_mmio_uc_mem_rw_write_callback(uc_engine* uc, uint64_t offse return; } - -static void test_x86_mmio_uc_mem_rw() { - uc_engine* uc; +static void test_x86_mmio_uc_mem_rw() +{ + uc_engine *uc; int data = 0xdeadbeef; OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); - OK(uc_mmio_map(uc, - 0x20000, 0x1000, - test_x86_mmio_uc_mem_rw_read_callback, NULL, - test_x86_mmio_uc_mem_rw_write_callback, NULL)); + OK(uc_mmio_map(uc, 0x20000, 0x1000, test_x86_mmio_uc_mem_rw_read_callback, + NULL, test_x86_mmio_uc_mem_rw_write_callback, NULL)); - OK(uc_mem_write(uc, 0x20004, (void*)&data, 4)); - OK(uc_mem_read(uc, 0x20008, (void*)&data, 4)); + OK(uc_mem_write(uc, 0x20004, (void *)&data, 4)); + OK(uc_mem_read(uc, 0x20008, (void *)&data, 4)); TEST_CHECK(data == 0x19260817); OK(uc_close(uc)); } -static void test_x86_sysenter_hook(uc_engine* uc, void* user) { - *(int*)user = 1; +static void test_x86_sysenter_hook(uc_engine *uc, void *user) +{ + *(int *)user = 1; } -static void test_x86_sysenter() { - uc_engine* uc; +static void test_x86_sysenter() +{ + uc_engine *uc; char code[] = "\x0F\x34"; // sysenter uc_hook h; int called = 0; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0, UC_X86_INS_SYSENTER)); + OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_sysenter_hook, &called, 1, 0, + UC_X86_INS_SYSENTER)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -525,21 +601,24 @@ static void test_x86_sysenter() { OK(uc_close(uc)); } -static void test_x86_hook_cpuid_callback(uc_engine* uc, void* data) { +static void test_x86_hook_cpuid_callback(uc_engine *uc, void *data) +{ int reg = 7; OK(uc_reg_write(uc, UC_X86_REG_EAX, ®)); } -static void test_x86_hook_cpuid() { - uc_engine* uc; +static void test_x86_hook_cpuid() +{ + uc_engine *uc; char code[] = "\x40\x0F\xA2"; // INC EAX; CPUID uc_hook h; int reg; uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); - OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1, 0, UC_X86_INS_CPUID)); + OK(uc_hook_add(uc, &h, UC_HOOK_INSN, test_x86_hook_cpuid_callback, NULL, 1, + 0, UC_X86_INS_CPUID)); OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); @@ -550,26 +629,25 @@ static void test_x86_hook_cpuid() { OK(uc_close(uc)); } -TEST_LIST = { - { "test_x86_in", test_x86_in }, - { "test_x86_out", test_x86_out }, - { "test_x86_mem_hook_all", test_x86_mem_hook_all }, - { "test_x86_inc_dec_pxor", test_x86_inc_dec_pxor }, - { "test_x86_relative_jump", test_x86_relative_jump }, - { "test_x86_loop", test_x86_loop }, - { "test_x86_invalid_mem_read", test_x86_invalid_mem_read }, - { "test_x86_invalid_mem_write", test_x86_invalid_mem_write }, - { "test_x86_invalid_jump", test_x86_invalid_jump}, - { "test_x86_64_syscall", test_x86_64_syscall }, - { "test_x86_16_add", test_x86_16_add }, - { "test_x86_reg_save", test_x86_reg_save }, - { "test_x86_invalid_mem_read_stop_in_cb", test_x86_invalid_mem_read_stop_in_cb }, - { "test_x86_x87_fnstenv", test_x86_x87_fnstenv}, - { "test_x86_mmio", test_x86_mmio}, - { "test_x86_missing_code", test_x86_missing_code}, - { "test_x86_smc_xor", test_x86_smc_xor}, - { "test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw}, - { "test_x86_sysenter", test_x86_sysenter}, - { "test_x86_hook_cpuid", test_x86_hook_cpuid}, - { NULL, NULL } -}; \ No newline at end of file +TEST_LIST = {{"test_x86_in", test_x86_in}, + {"test_x86_out", test_x86_out}, + {"test_x86_mem_hook_all", test_x86_mem_hook_all}, + {"test_x86_inc_dec_pxor", test_x86_inc_dec_pxor}, + {"test_x86_relative_jump", test_x86_relative_jump}, + {"test_x86_loop", test_x86_loop}, + {"test_x86_invalid_mem_read", test_x86_invalid_mem_read}, + {"test_x86_invalid_mem_write", test_x86_invalid_mem_write}, + {"test_x86_invalid_jump", test_x86_invalid_jump}, + {"test_x86_64_syscall", test_x86_64_syscall}, + {"test_x86_16_add", test_x86_16_add}, + {"test_x86_reg_save", test_x86_reg_save}, + {"test_x86_invalid_mem_read_stop_in_cb", + test_x86_invalid_mem_read_stop_in_cb}, + {"test_x86_x87_fnstenv", test_x86_x87_fnstenv}, + {"test_x86_mmio", test_x86_mmio}, + {"test_x86_missing_code", test_x86_missing_code}, + {"test_x86_smc_xor", test_x86_smc_xor}, + {"test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw}, + {"test_x86_sysenter", test_x86_sysenter}, + {"test_x86_hook_cpuid", test_x86_hook_cpuid}, + {NULL, NULL}}; \ No newline at end of file diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index e3a45c02..8c47310c 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -8,17 +8,17 @@ /** * Assert that err matches expect */ -#define uc_assert_err(expect, err) \ -do { \ - uc_err __err = err; \ - if (!TEST_CHECK(__err == expect)) { \ - TEST_MSG("%s", uc_strerror(__err)); \ - } \ -} while (0) +#define uc_assert_err(expect, err) \ + do { \ + uc_err __err = err; \ + if (!TEST_CHECK(__err == expect)) { \ + TEST_MSG("%s", uc_strerror(__err)); \ + } \ + } while (0) /** * Assert that err is UC_ERR_OK */ -#define OK(stat) uc_assert_err(UC_ERR_OK, stat) +#define OK(stat) uc_assert_err(UC_ERR_OK, stat) #endif /* UNICORN_TEST_H */ diff --git a/uc.c b/uc.c index f41e8306..07ae921f 100644 --- a/uc.c +++ b/uc.c @@ -10,7 +10,7 @@ #include #endif -#include // nanosleep +#include // nanosleep #include #include "uc_priv.h" @@ -37,100 +37,105 @@ unsigned int uc_version(unsigned int *major, unsigned int *minor) return (UC_API_MAJOR << 8) + UC_API_MINOR; } - UNICORN_EXPORT uc_err uc_errno(uc_engine *uc) { return uc->errnum; } - UNICORN_EXPORT const char *uc_strerror(uc_err code) { - switch(code) { - default: - return "Unknown error code"; - case UC_ERR_OK: - return "OK (UC_ERR_OK)"; - case UC_ERR_NOMEM: - return "No memory available or memory not present (UC_ERR_NOMEM)"; - case UC_ERR_ARCH: - return "Invalid/unsupported architecture (UC_ERR_ARCH)"; - case UC_ERR_HANDLE: - return "Invalid handle (UC_ERR_HANDLE)"; - case UC_ERR_MODE: - return "Invalid mode (UC_ERR_MODE)"; - case UC_ERR_VERSION: - return "Different API version between core & binding (UC_ERR_VERSION)"; - case UC_ERR_READ_UNMAPPED: - return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; - case UC_ERR_WRITE_UNMAPPED: - return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; - case UC_ERR_FETCH_UNMAPPED: - return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; - case UC_ERR_HOOK: - return "Invalid hook type (UC_ERR_HOOK)"; - case UC_ERR_INSN_INVALID: - return "Invalid instruction (UC_ERR_INSN_INVALID)"; - case UC_ERR_MAP: - return "Invalid memory mapping (UC_ERR_MAP)"; - case UC_ERR_WRITE_PROT: - return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; - case UC_ERR_READ_PROT: - return "Read from non-readable memory (UC_ERR_READ_PROT)"; - case UC_ERR_FETCH_PROT: - return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; - case UC_ERR_ARG: - return "Invalid argument (UC_ERR_ARG)"; - case UC_ERR_READ_UNALIGNED: - return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; - case UC_ERR_WRITE_UNALIGNED: - 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_RESOURCE: - return "Insufficient resource (UC_ERR_RESOURCE)"; - case UC_ERR_EXCEPTION: - return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; + switch (code) { + default: + return "Unknown error code"; + case UC_ERR_OK: + return "OK (UC_ERR_OK)"; + case UC_ERR_NOMEM: + return "No memory available or memory not present (UC_ERR_NOMEM)"; + case UC_ERR_ARCH: + return "Invalid/unsupported architecture (UC_ERR_ARCH)"; + case UC_ERR_HANDLE: + return "Invalid handle (UC_ERR_HANDLE)"; + case UC_ERR_MODE: + return "Invalid mode (UC_ERR_MODE)"; + case UC_ERR_VERSION: + return "Different API version between core & binding (UC_ERR_VERSION)"; + case UC_ERR_READ_UNMAPPED: + return "Invalid memory read (UC_ERR_READ_UNMAPPED)"; + case UC_ERR_WRITE_UNMAPPED: + return "Invalid memory write (UC_ERR_WRITE_UNMAPPED)"; + case UC_ERR_FETCH_UNMAPPED: + return "Invalid memory fetch (UC_ERR_FETCH_UNMAPPED)"; + case UC_ERR_HOOK: + return "Invalid hook type (UC_ERR_HOOK)"; + case UC_ERR_INSN_INVALID: + return "Invalid instruction (UC_ERR_INSN_INVALID)"; + case UC_ERR_MAP: + return "Invalid memory mapping (UC_ERR_MAP)"; + case UC_ERR_WRITE_PROT: + return "Write to write-protected memory (UC_ERR_WRITE_PROT)"; + case UC_ERR_READ_PROT: + return "Read from non-readable memory (UC_ERR_READ_PROT)"; + case UC_ERR_FETCH_PROT: + return "Fetch from non-executable memory (UC_ERR_FETCH_PROT)"; + case UC_ERR_ARG: + return "Invalid argument (UC_ERR_ARG)"; + case UC_ERR_READ_UNALIGNED: + return "Read from unaligned memory (UC_ERR_READ_UNALIGNED)"; + case UC_ERR_WRITE_UNALIGNED: + 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_RESOURCE: + return "Insufficient resource (UC_ERR_RESOURCE)"; + case UC_ERR_EXCEPTION: + return "Unhandled CPU exception (UC_ERR_EXCEPTION)"; } } - UNICORN_EXPORT bool uc_arch_supported(uc_arch arch) { switch (arch) { #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: return true; + case UC_ARCH_ARM: + return true; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: return true; + case UC_ARCH_ARM64: + return true; #endif #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: return true; + case UC_ARCH_M68K: + return true; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: return true; + case UC_ARCH_MIPS: + return true; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: return true; + case UC_ARCH_PPC: + return true; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: return true; + case UC_ARCH_SPARC: + return true; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: return true; + case UC_ARCH_X86: + return true; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: return true; + case UC_ARCH_RISCV: + return true; #endif - /* Invalid or disabled arch */ - default: return false; + /* Invalid or disabled arch */ + default: + return false; } } - UNICORN_EXPORT uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) { @@ -156,142 +161,138 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) QTAILQ_INIT(&uc->address_spaces); - switch(arch) { - default: - break; + switch (arch) { + default: + 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; + 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; + 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: - if ((mode & ~UC_MODE_ARM_MASK)) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = armeb_uc_init; - } else { - uc->init_arch = arm_uc_init; - } + case UC_ARCH_ARM: + if ((mode & ~UC_MODE_ARM_MASK)) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = armeb_uc_init; + } else { + uc->init_arch = arm_uc_init; + } - if (mode & UC_MODE_THUMB) { - uc->thumb = 1; - } - break; + if (mode & UC_MODE_THUMB) { + uc->thumb = 1; + } + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & ~UC_MODE_ARM_MASK) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_BIG_ENDIAN) { - uc->init_arch = arm64eb_uc_init; - } else { - uc->init_arch = arm64_uc_init; - } - break; + case UC_ARCH_ARM64: + if (mode & ~UC_MODE_ARM_MASK) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_BIG_ENDIAN) { + uc->init_arch = arm64eb_uc_init; + } else { + 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) { +#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) { - uc->init_arch = mips_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mips_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64_uc_init; - } + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64_uc_init; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - uc->init_arch = mipsel_uc_init; - } + if (mode & UC_MODE_MIPS32) { + uc->init_arch = mipsel_uc_init; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - uc->init_arch = mips64el_uc_init; - } -#endif + if (mode & UC_MODE_MIPS64) { + uc->init_arch = mips64el_uc_init; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if ((mode & ~UC_MODE_SPARC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_SPARC32|UC_MODE_SPARC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_SPARC64) { - uc->init_arch = sparc64_uc_init; - } else { - uc->init_arch = sparc_uc_init; - } - break; + case UC_ARCH_SPARC: + if ((mode & ~UC_MODE_SPARC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_SPARC32 | UC_MODE_SPARC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_SPARC64) { + uc->init_arch = sparc64_uc_init; + } else { + uc->init_arch = sparc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if ((mode & ~UC_MODE_PPC_MASK) || - !(mode & UC_MODE_BIG_ENDIAN) || - !(mode & (UC_MODE_PPC32|UC_MODE_PPC64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_PPC64) { - uc->init_arch = ppc64_uc_init; - } else { - uc->init_arch = ppc_uc_init; - } - break; + case UC_ARCH_PPC: + if ((mode & ~UC_MODE_PPC_MASK) || !(mode & UC_MODE_BIG_ENDIAN) || + !(mode & (UC_MODE_PPC32 | UC_MODE_PPC64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_PPC64) { + uc->init_arch = ppc64_uc_init; + } else { + uc->init_arch = ppc_uc_init; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if ((mode & ~UC_MODE_RISCV_MASK) || - !(mode & (UC_MODE_RISCV32|UC_MODE_RISCV64))) { - free(uc); - return UC_ERR_MODE; - } - if (mode & UC_MODE_RISCV32) { - uc->init_arch = riscv32_uc_init; - } else if (mode & UC_MODE_RISCV64) { - uc->init_arch =riscv64_uc_init; - } else { - free(uc); - return UC_ERR_MODE; - } - break; + case UC_ARCH_RISCV: + if ((mode & ~UC_MODE_RISCV_MASK) || + !(mode & (UC_MODE_RISCV32 | UC_MODE_RISCV64))) { + free(uc); + return UC_ERR_MODE; + } + if (mode & UC_MODE_RISCV32) { + uc->init_arch = riscv32_uc_init; + } else if (mode & UC_MODE_RISCV64) { + uc->init_arch = riscv64_uc_init; + } else { + free(uc); + return UC_ERR_MODE; + } + break; #endif - } if (uc->init_arch == NULL) { @@ -317,7 +318,6 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) } } - UNICORN_EXPORT uc_err uc_close(uc_engine *uc) { @@ -341,7 +341,7 @@ uc_err uc_close(uc_engine *uc) /* flatviews */ g_hash_table_destroy(uc->flat_views); - + // During flatviews destruction, we may still access memory regions. // So we free them afterwards. /* memory */ @@ -390,7 +390,7 @@ uc_err uc_close(uc_engine *uc) cur = uc->saved_contexts.head; while (cur != NULL) { struct list_item *next = cur->next; - struct uc_context *context = (struct uc_context*)cur->data; + struct uc_context *context = (struct uc_context *)cur->data; context->uc = NULL; cur = next; } @@ -403,7 +403,6 @@ uc_err uc_close(uc_engine *uc) return UC_ERR_OK; } - UNICORN_EXPORT uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) { @@ -417,7 +416,6 @@ uc_err uc_reg_read_batch(uc_engine *uc, int *ids, void **vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) { @@ -431,7 +429,6 @@ uc_err uc_reg_write_batch(uc_engine *uc, int *ids, void *const *vals, int count) return ret; } - UNICORN_EXPORT uc_err uc_reg_read(uc_engine *uc, int regid, void *value) { @@ -450,13 +447,13 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) { size_t count = 0, len; - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); count += len; address += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -464,7 +461,6 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) return (count == size); } - UNICORN_EXPORT uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) { @@ -484,11 +480,12 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { len = (size_t)MIN(size - count, mr->end - address); - if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->read_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } count += len; @@ -507,7 +504,8 @@ uc_err uc_mem_read(uc_engine *uc, uint64_t address, void *_bytes, size_t size) } UNICORN_EXPORT -uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t size) +uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, + size_t size) { size_t count = 0, len; const uint8_t *bytes = _bytes; @@ -525,21 +523,23 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } // memory area can overlap adjacent memory blocks - while(count < size) { + while (count < size) { MemoryRegion *mr = memory_mapping(uc, address); if (mr) { uint32_t operms = mr->perms; - if (!(operms & UC_PROT_WRITE)) {// write protected - // but this is not the program accessing memory, so temporarily mark writable + if (!(operms & UC_PROT_WRITE)) { // write protected + // but this is not the program accessing memory, so temporarily + // mark writable uc->readonly_mem(mr, false); } len = (size_t)MIN(size - count, mr->end - address); - if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == false) { + if (uc->write_mem(&uc->address_space_memory, address, bytes, len) == + false) { break; } - if (!(operms & UC_PROT_WRITE)) {// write protected + if (!(operms & UC_PROT_WRITE)) { // write protected // now write protect it again uc->readonly_mem(mr, true); } @@ -547,7 +547,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t count += len; address += len; bytes += len; - } else {// this address is not mapped in yet + } else { // this address is not mapped in yet break; } } @@ -559,7 +559,7 @@ uc_err uc_mem_write(uc_engine *uc, uint64_t address, const void *_bytes, size_t } } -#define TIMEOUT_STEP 2 // microseconds +#define TIMEOUT_STEP 2 // microseconds static void *_timeout_fn(void *arg) { struct uc_struct *uc = arg; @@ -571,7 +571,7 @@ static void *_timeout_fn(void *arg) if (uc->emulation_done) { break; } - } while((uint64_t)(get_clock() - current_time) < uc->timeout); + } while ((uint64_t)(get_clock() - current_time) < uc->timeout); // timeout before emulation is done? if (!uc->emulation_done) { @@ -586,11 +586,12 @@ static void *_timeout_fn(void *arg) static void enable_emu_timer(uc_engine *uc, uint64_t timeout) { uc->timeout = timeout; - qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, - uc, QEMU_THREAD_JOINABLE); + qemu_thread_create(uc, &uc->timer, "timeout", _timeout_fn, uc, + QEMU_THREAD_JOINABLE); } -static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, void *user_data) +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++; @@ -604,11 +605,12 @@ static void hook_count_cb(struct uc_struct *uc, uint64_t address, uint32_t size, static void clear_deleted_hooks(uc_engine *uc) { - struct list_item * cur; - struct hook * hook; + struct list_item *cur; + struct hook *hook; int i; - - for (cur = uc->hooks_to_del.head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + + for (cur = uc->hooks_to_del.head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { assert(hook->to_delete); for (i = 0; i < UC_HOOK_MAX; i++) { if (list_remove(&uc->hook[i], (void *)hook)) { @@ -626,7 +628,8 @@ static void clear_deleted_hooks(uc_engine *uc) } UNICORN_EXPORT -uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t timeout, size_t count) +uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, + uint64_t timeout, size_t count) { // reset the counter uc->emu_counter = 0; @@ -636,69 +639,69 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time uc->timed_out = false; uc->first_tb = true; - switch(uc->arch) { - default: - break; + switch (uc->arch) { + default: + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - uc_reg_write(uc, UC_M68K_REG_PC, &begin); - break; + case UC_ARCH_M68K: + uc_reg_write(uc, UC_M68K_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - switch(uc->mode) { - default: - break; - case UC_MODE_16: { - uint64_t ip; - uint16_t cs; - - uc_reg_read(uc, UC_X86_REG_CS, &cs); - // compensate for later adding up IP & CS - ip = begin - cs*16; - uc_reg_write(uc, UC_X86_REG_IP, &ip); - break; - } - case UC_MODE_32: - uc_reg_write(uc, UC_X86_REG_EIP, &begin); - break; - case UC_MODE_64: - uc_reg_write(uc, UC_X86_REG_RIP, &begin); - break; - } + case UC_ARCH_X86: + switch (uc->mode) { + default: break; + case UC_MODE_16: { + uint64_t ip; + uint16_t cs; + + uc_reg_read(uc, UC_X86_REG_CS, &cs); + // compensate for later adding up IP & CS + ip = begin - cs * 16; + uc_reg_write(uc, UC_X86_REG_IP, &ip); + break; + } + case UC_MODE_32: + uc_reg_write(uc, UC_X86_REG_EIP, &begin); + break; + case UC_MODE_64: + uc_reg_write(uc, UC_X86_REG_RIP, &begin); + break; + } + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - uc_reg_write(uc, UC_ARM_REG_R15, &begin); - break; + case UC_ARCH_ARM: + uc_reg_write(uc, UC_ARM_REG_R15, &begin); + break; #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - uc_reg_write(uc, UC_ARM64_REG_PC, &begin); - break; + case UC_ARCH_ARM64: + uc_reg_write(uc, UC_ARM64_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_MIPS - case UC_ARCH_MIPS: - // TODO: MIPS32/MIPS64/BIGENDIAN etc - uc_reg_write(uc, UC_MIPS_REG_PC, &begin); - break; + case UC_ARCH_MIPS: + // TODO: MIPS32/MIPS64/BIGENDIAN etc + uc_reg_write(uc, UC_MIPS_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - // TODO: Sparc/Sparc64 - uc_reg_write(uc, UC_SPARC_REG_PC, &begin); - break; + case UC_ARCH_SPARC: + // TODO: Sparc/Sparc64 + uc_reg_write(uc, UC_SPARC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - uc_reg_write(uc, UC_PPC_REG_PC, &begin); - break; + case UC_ARCH_PPC: + uc_reg_write(uc, UC_PPC_REG_PC, &begin); + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - uc_reg_write(uc, UC_RISCV_REG_PC, &begin); - break; + case UC_ARCH_RISCV: + uc_reg_write(uc, UC_RISCV_REG_PC, &begin); + break; #endif } @@ -717,7 +720,8 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time // so instead of appending, we must insert the hook at the begin // of the hook list uc->hook_insert = 1; - err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, NULL, 1, 0); + err = uc_hook_add(uc, &uc->count_hook, UC_HOOK_CODE, hook_count_cb, + NULL, 1, 0); // restore to append mode for uc_hook_add() uc->hook_insert = 0; if (err != UC_ERR_OK) { @@ -728,7 +732,7 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time uc->addr_end = until; if (timeout) { - enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds + enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds } uc->vm_start(uc); @@ -747,7 +751,6 @@ uc_err uc_emu_start(uc_engine* uc, uint64_t begin, uint64_t until, uint64_t time return uc->invalid_error; } - UNICORN_EXPORT uc_err uc_emu_stop(uc_engine *uc) { @@ -765,14 +768,16 @@ uc_err uc_emu_stop(uc_engine *uc) return UC_ERR_OK; } -// return target index where a memory region at the address exists, or could be inserted +// return target index where a memory region at the address exists, or could be +// inserted // -// address either is inside the mapping at the returned index, or is in free space before -// the next mapping. +// address either is inside the mapping at the returned index, or is in free +// space before the next mapping. // -// if there is overlap, between regions, ending address will be higher than the starting -// address of the mapping at returned index -static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) { +// if there is overlap, between regions, ending address will be higher than the +// starting address of the mapping at returned index +static int bsearch_mapped_blocks(const uc_engine *uc, uint64_t address) +{ int left, right, mid; MemoryRegion *mapping; @@ -817,7 +822,8 @@ static bool memory_overlap(struct uc_struct *uc, uint64_t begin, size_t size) } // common setup/error checking shared between uc_mem_map and uc_mem_map_ptr -static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms, MemoryRegion *block) +static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, MemoryRegion *block) { MemoryRegion **regions; int pos; @@ -826,9 +832,10 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per return UC_ERR_NOMEM; } - if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { //time to grow - regions = (MemoryRegion**)g_realloc(uc->mapped_blocks, - sizeof(MemoryRegion*) * (uc->mapped_block_count + MEM_BLOCK_INCR)); + if ((uc->mapped_block_count & (MEM_BLOCK_INCR - 1)) == 0) { // time to grow + regions = (MemoryRegion **)g_realloc( + uc->mapped_blocks, + sizeof(MemoryRegion *) * (uc->mapped_block_count + MEM_BLOCK_INCR)); if (regions == NULL) { return UC_ERR_NOMEM; } @@ -838,7 +845,8 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per pos = bsearch_mapped_blocks(uc, block->addr); // shift the array right to give space for the new pointer - memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], sizeof(MemoryRegion*) * (uc->mapped_block_count - pos)); + memmove(&uc->mapped_blocks[pos + 1], &uc->mapped_blocks[pos], + sizeof(MemoryRegion *) * (uc->mapped_block_count - pos)); uc->mapped_blocks[pos] = block; uc->mapped_block_count++; @@ -846,7 +854,8 @@ static uc_err mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t per return UC_ERR_OK; } -static uc_err mem_map_check(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 (size == 0) { // invalid memory mapping @@ -895,11 +904,13 @@ uc_err uc_mem_map(uc_engine *uc, uint64_t address, size_t size, uint32_t perms) return res; } - return mem_map(uc, address, size, perms, uc->memory_map(uc, address, size, perms)); + 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 uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, + uint32_t perms, void *ptr) { uc_err res; @@ -916,7 +927,8 @@ uc_err uc_mem_map_ptr(uc_engine *uc, uint64_t address, size_t size, uint32_t per return res; } - return mem_map(uc, address, size, UC_PROT_ALL, uc->memory_map_ptr(uc, address, size, perms, ptr)); + return mem_map(uc, address, size, UC_PROT_ALL, + uc->memory_map_ptr(uc, address, size, perms, ptr)); } UNICORN_EXPORT @@ -937,7 +949,8 @@ uc_err uc_mmio_map(uc_engine *uc, uint64_t address, size_t size, // The callbacks do not need to be checked for NULL here, as their presence // (or lack thereof) will determine the permissions used. return mem_map(uc, address, size, UC_PROT_NONE, - uc->memory_map_io(uc, address, size, read_cb, write_cb, user_data_read, user_data_write)); + uc->memory_map_io(uc, address, size, read_cb, write_cb, + user_data_read, user_data_write)); } // Create a backup copy of the indicated MemoryRegion. @@ -946,7 +959,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) { uint8_t *block = (uint8_t *)g_malloc0((size_t)int128_get64(mr->size)); if (block != NULL) { - uc_err err = uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); + uc_err err = + uc_mem_read(uc, mr->addr, block, (size_t)int128_get64(mr->size)); if (err != UC_ERR_OK) { free(block); block = NULL; @@ -971,8 +985,8 @@ static uint8_t *copy_region(struct uc_struct *uc, MemoryRegion *mr) */ // TODO: investigate whether qemu region manipulation functions already offered // this capability -static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t address, - size_t size, bool do_delete) +static bool split_region(struct uc_struct *uc, MemoryRegion *mr, + uint64_t address, size_t size, bool do_delete) { uint8_t *backup; uint32_t perms; @@ -999,8 +1013,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres return false; } - QLIST_FOREACH(block, &uc->ram_list.blocks, next) { - if (block->offset <= mr->addr && block->used_length >= (mr->end - mr->addr)) { + QLIST_FOREACH(block, &uc->ram_list.blocks, next) + { + if (block->offset <= mr->addr && + block->used_length >= (mr->end - mr->addr)) { break; } } @@ -1022,13 +1038,15 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres } } - // save the essential information required for the split before mr gets deleted + // save the essential information required for the split before mr gets + // deleted perms = mr->perms; begin = mr->addr; end = mr->end; // unmap this region first, then do split it later - if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != UC_ERR_OK) { + if (uc_mem_unmap(uc, mr->addr, (size_t)int128_get64(mr->size)) != + UC_ERR_OK) { goto error; } @@ -1052,10 +1070,10 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres r_size = (size_t)(end - chunk_end); m_size = (size_t)(chunk_end - address); - // If there are error in any of the below operations, things are too far gone - // at that point to recover. Could try to remap orignal region, but these smaller - // allocation just failed so no guarantee that we can recover the original - // allocation at this point + // If there are error in any of the below operations, things are too far + // gone at that point to recover. Could try to remap orignal region, but + // these smaller allocation just failed so no guarantee that we can recover + // the original allocation at this point if (l_size > 0) { if (!prealloc) { if (uc_mem_map(uc, begin, l_size, perms) != UC_ERR_OK) { @@ -1076,11 +1094,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, address, m_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, address, backup + l_size, m_size) != UC_ERR_OK) { + if (uc_mem_write(uc, address, backup + l_size, m_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, address, m_size, perms, backup + l_size) != + UC_ERR_OK) { goto error; } } @@ -1091,11 +1111,13 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres if (uc_mem_map(uc, chunk_end, r_size, perms) != UC_ERR_OK) { goto error; } - if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != UC_ERR_OK) { + if (uc_mem_write(uc, chunk_end, backup + l_size + m_size, r_size) != + UC_ERR_OK) { goto error; } } else { - if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, backup + l_size + m_size) != UC_ERR_OK) { + if (uc_mem_map_ptr(uc, chunk_end, r_size, perms, + backup + l_size + m_size) != UC_ERR_OK) { goto error; } } @@ -1114,7 +1136,8 @@ error: } UNICORN_EXPORT -uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint32_t perms) +uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, + uint32_t perms) { MemoryRegion *mr; uint64_t addr = address; @@ -1154,7 +1177,7 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, false)) { @@ -1163,7 +1186,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 mr = memory_mapping(uc, addr); // will this remove EXEC permission? - if (((mr->perms & UC_PROT_EXEC) != 0) && ((perms & UC_PROT_EXEC) == 0)) { + if (((mr->perms & UC_PROT_EXEC) != 0) && + ((perms & UC_PROT_EXEC) == 0)) { remove_exec = true; } mr->perms = perms; @@ -1173,7 +1197,8 @@ uc_err uc_mem_protect(struct uc_struct *uc, uint64_t address, size_t size, uint3 addr += len; } - // if EXEC permission is removed, then quit TB and continue at the same place + // 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); @@ -1217,7 +1242,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // We may need to split regions if this area spans adjacent regions addr = address; count = 0; - while(count < size) { + while (count < size) { mr = memory_mapping(uc, addr); len = (size_t)MIN(size - count, mr->end - addr); if (!split_region(uc, mr, addr, len, true)) { @@ -1228,7 +1253,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) // so unmap here mr = memory_mapping(uc, addr); if (mr != NULL) { - uc->memory_unmap(uc, mr); + uc->memory_unmap(uc, mr); } count += len; addr += len; @@ -1238,7 +1263,7 @@ uc_err uc_mem_unmap(struct uc_struct *uc, uint64_t address, size_t size) } // find the memory region of this address -MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) +MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address) { unsigned int i; @@ -1253,13 +1278,15 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) // try with the cache index first i = uc->mapped_block_cache_index; - if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address < uc->mapped_blocks[i]->end) { + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address < uc->mapped_blocks[i]->end) { return uc->mapped_blocks[i]; } i = bsearch_mapped_blocks(uc, address); - if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && address <= uc->mapped_blocks[i]->end - 1) + if (i < uc->mapped_block_count && address >= uc->mapped_blocks[i]->addr && + address <= uc->mapped_blocks[i]->end - 1) return uc->mapped_blocks[i]; // not found @@ -1268,7 +1295,7 @@ MemoryRegion *memory_mapping(struct uc_struct* uc, uint64_t address) UNICORN_EXPORT uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, - void *user_data, uint64_t begin, uint64_t end, ...) + void *user_data, uint64_t begin, uint64_t end, ...) { int ret = UC_ERR_OK; int i = 0; @@ -1296,7 +1323,7 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, va_end(valist); if (uc->insn_hook_validate) { - if (! uc->insn_hook_validate(hook->insn)) { + if (!uc->insn_hook_validate(hook->insn)) { free(hook); return UC_ERR_HOOK; } @@ -1352,7 +1379,6 @@ uc_err uc_hook_add(uc_engine *uc, uc_hook *hh, int type, void *callback, return ret; } - UNICORN_EXPORT uc_err uc_hook_del(uc_engine *uc, uc_hook hh) { @@ -1365,7 +1391,7 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) // an optimization would be to align the hook pointer // and store the type mask in the hook pointer. for (i = 0; i < UC_HOOK_MAX; i++) { - if (list_exists(&uc->hook[i], (void *) hook)) { + if (list_exists(&uc->hook[i], (void *)hook)) { hook->to_delete = true; list_append(&uc->hooks_to_del, hook); } @@ -1375,13 +1401,18 @@ uc_err uc_hook_del(uc_engine *uc, uc_hook hh) } // TCG helper -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address); -void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t address) +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address); +void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, + int64_t address) { struct uc_struct *uc = handle; struct list_item *cur; struct hook *hook; - int hook_flags = index & UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See the comments of uc_hook_idx for details. + int hook_flags = + index & + UC_HOOK_FLAG_MASK; // The index here may contain additional flags. See + // the comments of uc_hook_idx for details. index = index & UC_HOOK_IDX_MASK; @@ -1395,30 +1426,35 @@ void helper_uc_tracecode(int32_t size, uc_hook_idx index, void *handle, int64_t return; } - for (cur = uc->hook[index].head; cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + for (cur = uc->hook[index].head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { if (hook->to_delete) { continue; } - // on invalid block/instruction, call instruction counter (if enable), then quit + // on invalid block/instruction, call instruction counter (if enable), + // then quit if (size == 0) { if (index == UC_HOOK_CODE_IDX && uc->count_hook) { // this is the instruction counter (first hook in the list) - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } return; } if (HOOK_BOUND_CHECK(hook, (uint64_t)address)) { - ((uc_cb_hookcode_t)hook->callback)(uc, address, size, hook->user_data); + ((uc_cb_hookcode_t)hook->callback)(uc, address, size, + hook->user_data); } // the last callback may already asked to stop emulation // Unicorn: - // In an ARM IT block, we behave like the emulation continues normally. No check_exit_request - // is generated and the hooks are triggered normally. In other words, the whole IT block is - // treated as a single instruction. + // In an ARM IT block, we behave like the emulation continues + // normally. No check_exit_request is generated and the hooks are + // triggered normally. In other words, the whole IT block is treated + // as a single instruction. if (uc->stop_request && !(hook_flags & UC_HOOK_FLAG_NO_STOP)) { break; } @@ -1455,29 +1491,29 @@ uc_err uc_mem_regions(uc_engine *uc, uc_mem_region **regions, uint32_t *count) UNICORN_EXPORT uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) { - switch(type) { - default: - return UC_ERR_ARG; + switch (type) { + default: + return UC_ERR_ARG; - case UC_QUERY_PAGE_SIZE: - *result = uc->target_page_size; - break; + case UC_QUERY_PAGE_SIZE: + *result = uc->target_page_size; + break; - case UC_QUERY_ARCH: - *result = uc->arch; - break; + case UC_QUERY_ARCH: + *result = uc->arch; + break; - case UC_QUERY_MODE: + case UC_QUERY_MODE: #ifdef UNICORN_HAS_ARM - if (uc->arch == UC_ARCH_ARM) { - return uc->query(uc, type, result); - } + if (uc->arch == UC_ARCH_ARM) { + return uc->query(uc, type, result); + } #endif - return UC_ERR_ARG; + return UC_ERR_ARG; - case UC_QUERY_TIMEOUT: - *result = uc->timed_out; - break; + case UC_QUERY_TIMEOUT: + *result = uc->timed_out; + break; } return UC_ERR_OK; @@ -1517,20 +1553,20 @@ UNICORN_EXPORT size_t uc_context_size(uc_engine *uc) { // return the total size of struct uc_context - return sizeof(uc_context) + uc->cpu_context_size + sizeof(*uc->cpu->jmp_env); + return sizeof(uc_context) + uc->cpu_context_size + + sizeof(*uc->cpu->jmp_env); } UNICORN_EXPORT uc_err uc_context_save(uc_engine *uc, uc_context *context) { memcpy(context->data, uc->cpu->env_ptr, context->context_size); - memcpy(context->data + context->context_size, uc->cpu->jmp_env, context->jmp_env_size); + memcpy(context->data + context->context_size, uc->cpu->jmp_env, + context->jmp_env_size); return UC_ERR_OK; } - - UNICORN_EXPORT uc_err uc_context_reg_write(uc_context *ctx, int regid, const void *value) { @@ -1544,120 +1580,123 @@ uc_err uc_context_reg_read(uc_context *ctx, int regid, void *value) } // Keep in mind that we don't a uc_engine when r/w the registers of a context. -static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, context_reg_rw_t *rw) +static void find_context_reg_rw_function(uc_arch arch, uc_mode mode, + context_reg_rw_t *rw) { // We believe that the arch/mode pair is correct. - switch(arch) { - default: - rw->context_reg_read = NULL; - rw->context_reg_write = NULL; - break; + switch (arch) { + default: + rw->context_reg_read = NULL; + rw->context_reg_write = NULL; + break; #ifdef UNICORN_HAS_M68K - case UC_ARCH_M68K: - rw->context_reg_read = m68k_context_reg_read; - rw->context_reg_write = m68k_context_reg_write; - break; + case UC_ARCH_M68K: + rw->context_reg_read = m68k_context_reg_read; + rw->context_reg_write = m68k_context_reg_write; + break; #endif #ifdef UNICORN_HAS_X86 - case UC_ARCH_X86: - rw->context_reg_read = x86_context_reg_read; - rw->context_reg_write = x86_context_reg_write; - break; + case UC_ARCH_X86: + rw->context_reg_read = x86_context_reg_read; + rw->context_reg_write = x86_context_reg_write; + break; #endif #ifdef UNICORN_HAS_ARM - case UC_ARCH_ARM: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = armeb_context_reg_read; - rw->context_reg_write = armeb_context_reg_write; - } else { - rw->context_reg_read = arm_context_reg_read; - rw->context_reg_write = arm_context_reg_write; - } + case UC_ARCH_ARM: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = armeb_context_reg_read; + rw->context_reg_write = armeb_context_reg_write; + } else { + rw->context_reg_read = arm_context_reg_read; + rw->context_reg_write = arm_context_reg_write; + } #endif #ifdef UNICORN_HAS_ARM64 - case UC_ARCH_ARM64: - if (mode & UC_MODE_BIG_ENDIAN) { - rw->context_reg_read = arm64eb_context_reg_read; - rw->context_reg_write = arm64eb_context_reg_write; - } else { - rw->context_reg_read = arm64_context_reg_read; - rw->context_reg_write = arm64_context_reg_write; - } - break; + case UC_ARCH_ARM64: + if (mode & UC_MODE_BIG_ENDIAN) { + rw->context_reg_read = arm64eb_context_reg_read; + rw->context_reg_write = arm64eb_context_reg_write; + } else { + rw->context_reg_read = arm64_context_reg_read; + rw->context_reg_write = arm64_context_reg_write; + } + 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_BIG_ENDIAN) { +#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_BIG_ENDIAN) { #ifdef UNICORN_HAS_MIPS - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mips_context_reg_read; - rw->context_reg_write = mips_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mips_context_reg_read; + rw->context_reg_write = mips_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64 - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64_context_reg_read; - rw->context_reg_write = mips64_context_reg_write; - } + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64_context_reg_read; + rw->context_reg_write = mips64_context_reg_write; + } #endif - } else { // little endian + } else { // little endian #ifdef UNICORN_HAS_MIPSEL - if (mode & UC_MODE_MIPS32) { - rw->context_reg_read = mipsel_context_reg_read; - rw->context_reg_write = mipsel_context_reg_write; - } + if (mode & UC_MODE_MIPS32) { + rw->context_reg_read = mipsel_context_reg_read; + rw->context_reg_write = mipsel_context_reg_write; + } #endif #ifdef UNICORN_HAS_MIPS64EL - if (mode & UC_MODE_MIPS64) { - rw->context_reg_read = mips64el_context_reg_read; - rw->context_reg_write = mips64el_context_reg_write; - } -#endif + if (mode & UC_MODE_MIPS64) { + rw->context_reg_read = mips64el_context_reg_read; + rw->context_reg_write = mips64el_context_reg_write; } - break; +#endif + } + break; #endif #ifdef UNICORN_HAS_SPARC - case UC_ARCH_SPARC: - if (mode & UC_MODE_SPARC64) { - rw->context_reg_read = sparc64_context_reg_read; - rw->context_reg_write = sparc64_context_reg_write; - } else { - rw->context_reg_read = sparc_context_reg_read; - rw->context_reg_write = sparc_context_reg_write; - } - break; + case UC_ARCH_SPARC: + if (mode & UC_MODE_SPARC64) { + rw->context_reg_read = sparc64_context_reg_read; + rw->context_reg_write = sparc64_context_reg_write; + } else { + rw->context_reg_read = sparc_context_reg_read; + rw->context_reg_write = sparc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_PPC - case UC_ARCH_PPC: - if (mode & UC_MODE_PPC64) { - rw->context_reg_read = ppc64_context_reg_read; - rw->context_reg_write = ppc64_context_reg_write; - } else { - rw->context_reg_read = ppc_context_reg_read; - rw->context_reg_write = ppc_context_reg_write; - } - break; + case UC_ARCH_PPC: + if (mode & UC_MODE_PPC64) { + rw->context_reg_read = ppc64_context_reg_read; + rw->context_reg_write = ppc64_context_reg_write; + } else { + rw->context_reg_read = ppc_context_reg_read; + rw->context_reg_write = ppc_context_reg_write; + } + break; #endif #ifdef UNICORN_HAS_RISCV - case UC_ARCH_RISCV: - if (mode & UC_MODE_RISCV32) { - rw->context_reg_read = riscv32_context_reg_read; - rw->context_reg_write = riscv32_context_reg_write; - } else if (mode & UC_MODE_RISCV64) { - rw->context_reg_read = riscv64_context_reg_read; - rw->context_reg_write = riscv64_context_reg_write; - } - break; + case UC_ARCH_RISCV: + if (mode & UC_MODE_RISCV32) { + rw->context_reg_read = riscv32_context_reg_read; + rw->context_reg_write = riscv32_context_reg_write; + } else if (mode & UC_MODE_RISCV64) { + rw->context_reg_read = riscv64_context_reg_read; + rw->context_reg_write = riscv64_context_reg_write; + } + break; #endif } - + return; } UNICORN_EXPORT -uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, int count) +uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1673,7 +1712,8 @@ uc_err uc_context_reg_write_batch(uc_context *ctx, int *ids, void *const *vals, } UNICORN_EXPORT -uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, int count) +uc_err uc_context_reg_read_batch(uc_context *ctx, int *ids, void **vals, + int count) { int ret = UC_ERR_OK; context_reg_rw_t rw; @@ -1693,7 +1733,8 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) { memcpy(uc->cpu->env_ptr, context->data, context->context_size); if (list_exists(&uc->saved_contexts, context)) { - memcpy(uc->cpu->jmp_env, context->data + context->context_size, context->jmp_env_size); + memcpy(uc->cpu->jmp_env, context->data + context->context_size, + context->jmp_env_size); } return UC_ERR_OK; @@ -1702,7 +1743,7 @@ uc_err uc_context_restore(uc_engine *uc, uc_context *context) UNICORN_EXPORT uc_err uc_context_free(uc_context *context) { - uc_engine* uc = context->uc; + uc_engine *uc = context->uc; // if uc is NULL, it means that uc_engine has been free-ed. if (uc) { list_remove(&uc->saved_contexts, context); From bd4741ea8c0cee63144b93e058c6e8915d095f79 Mon Sep 17 00:00:00 2001 From: lazymio Date: Fri, 29 Oct 2021 12:46:06 +0200 Subject: [PATCH 20/40] Add format.sh --- format.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 format.sh diff --git a/format.sh b/format.sh new file mode 100644 index 00000000..d4418b15 --- /dev/null +++ b/format.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +find . -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./msvc -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./include -maxdepth 2 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./tests/unit -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./samples -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./qemu "(" -name "unicorn.c" -or -name "unicorn.h" ")" -exec clang-format -i -style=file "{}" ";" From 090686f8ed3c3ca174803bdbcfe4badcbf6d8d1e Mon Sep 17 00:00:00 2001 From: lazymio Date: Sat, 30 Oct 2021 04:45:32 +0200 Subject: [PATCH 21/40] uc_ctl proposal (#1473) * Add uc_ctl * Add comments * Slightly changed for bindings generation * Generate bindings --- bindings/const_generator.py | 57 +++- bindings/dotnet/UnicornManaged/Const/Arm.fs | 34 ++ bindings/dotnet/UnicornManaged/Const/Arm64.fs | 5 + .../dotnet/UnicornManaged/Const/Common.fs | 16 + bindings/dotnet/UnicornManaged/Const/M68k.fs | 10 + bindings/dotnet/UnicornManaged/Const/Mips.fs | 30 ++ bindings/dotnet/UnicornManaged/Const/Ppc.fs | 301 +++++++++++++++++ bindings/dotnet/UnicornManaged/Const/Riscv.fs | 10 + bindings/dotnet/UnicornManaged/Const/Sparc.fs | 32 ++ bindings/dotnet/UnicornManaged/Const/X86.fs | 39 +++ bindings/go/unicorn/arm64_const.go | 5 + bindings/go/unicorn/arm_const.go | 34 ++ bindings/go/unicorn/m68k_const.go | 10 + bindings/go/unicorn/mips_const.go | 30 ++ bindings/go/unicorn/ppc_const.go | 301 +++++++++++++++++ bindings/go/unicorn/riscv_const.go | 10 + bindings/go/unicorn/sparc_const.go | 32 ++ bindings/go/unicorn/unicorn_const.go | 16 + bindings/go/unicorn/x86_const.go | 39 +++ bindings/java/unicorn/Arm64Const.java | 5 + bindings/java/unicorn/ArmConst.java | 34 ++ bindings/java/unicorn/M68kConst.java | 10 + bindings/java/unicorn/MipsConst.java | 30 ++ bindings/java/unicorn/PpcConst.java | 301 +++++++++++++++++ bindings/java/unicorn/RiscvConst.java | 10 + bindings/java/unicorn/SparcConst.java | 32 ++ bindings/java/unicorn/UnicornConst.java | 16 + bindings/java/unicorn/X86Const.java | 39 +++ bindings/pascal/unicorn/Arm64Const.pas | 5 + bindings/pascal/unicorn/ArmConst.pas | 34 ++ bindings/pascal/unicorn/M68kConst.pas | 10 + bindings/pascal/unicorn/MipsConst.pas | 30 ++ bindings/pascal/unicorn/PpcConst.pas | 301 +++++++++++++++++ bindings/pascal/unicorn/RiscvConst.pas | 10 + bindings/pascal/unicorn/SparcConst.pas | 32 ++ bindings/pascal/unicorn/UnicornConst.pas | 16 + bindings/pascal/unicorn/X86Const.pas | 39 +++ bindings/python/unicorn/arm64_const.py | 5 + bindings/python/unicorn/arm_const.py | 34 ++ bindings/python/unicorn/m68k_const.py | 10 + bindings/python/unicorn/mips_const.py | 30 ++ bindings/python/unicorn/ppc_const.py | 301 +++++++++++++++++ bindings/python/unicorn/riscv_const.py | 10 + bindings/python/unicorn/sparc_const.py | 32 ++ bindings/python/unicorn/unicorn_const.py | 16 + bindings/python/unicorn/x86_const.py | 39 +++ .../lib/unicorn_engine/arm64_const.rb | 5 + .../lib/unicorn_engine/arm_const.rb | 34 ++ .../lib/unicorn_engine/m68k_const.rb | 10 + .../lib/unicorn_engine/mips_const.rb | 30 ++ .../lib/unicorn_engine/ppc_const.rb | 301 +++++++++++++++++ .../lib/unicorn_engine/riscv_const.rb | 10 + .../lib/unicorn_engine/sparc_const.rb | 32 ++ .../lib/unicorn_engine/unicorn_const.rb | 16 + .../lib/unicorn_engine/x86_const.rb | 39 +++ include/unicorn/arm.h | 36 +++ include/unicorn/arm64.h | 7 + include/unicorn/m68k.h | 12 + include/unicorn/mips.h | 32 ++ include/unicorn/ppc.h | 305 ++++++++++++++++++ include/unicorn/riscv.h | 14 + include/unicorn/sparc.h | 36 +++ include/unicorn/unicorn.h | 116 +++++++ include/unicorn/x86.h | 41 +++ uc.c | 6 + 65 files changed, 3520 insertions(+), 4 deletions(-) diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 30b870d8..64c518a8 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -136,7 +136,20 @@ def gen(lang): previous = {} count = 0 - for line in lines: + skip = 0 + in_comment = False + + for lno, line in enumerate(lines): + if "/*" in line: + in_comment = True + if "*/" in line: + in_comment = False + if in_comment: + continue + if skip > 0: + # Due to clang-format, values may come up in the next line + skip -= 1 + continue line = line.strip() if line.startswith(MARKUP): # markup for comments @@ -148,6 +161,8 @@ def gen(lang): continue tmp = line.strip().split(',') + if len(tmp) >= 2 and tmp[0] != "#define" and not tmp[0].startswith("UC_"): + continue for t in tmp: t = t.strip() if not t or t.startswith('//'): continue @@ -159,18 +174,52 @@ def gen(lang): define = True f.pop(0) f.insert(1, '=') - - if f[0].startswith("UC_" + prefix.upper()): + if f[0].startswith("UC_" + prefix.upper()) or f[0].startswith("UC_CPU"): if len(f) > 1 and f[1] not in ('//', '='): print("WARNING: Unable to convert %s" % f) print(" Line =", line) continue elif len(f) > 1 and f[1] == '=': - rhs = ''.join(f[2:]) + # Like: + # UC_A = + # (1 << 2) + # #define UC_B \ + # (UC_A | UC_C) + # Let's search the next line + if len(f) == 2: + if lno == len(lines) - 1: + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + 1] + next_line_tmp = next_line.strip().split(",") + rhs = next_line_tmp[0] + elif f[-1] == "\\": + idx = 0 + rhs = "" + while True: + idx += 1 + if lno + idx == len(lines): + print("WARNING: Unable to convert %s" % f) + print(" Line =", line) + continue + skip += 1 + next_line = lines[lno + idx] + next_line_f = re.split('\s+', next_line.strip()) + if next_line_f[-1] == "\\": + rhs += "".join(next_line_f[:-1]) + else: + rhs += next_line.strip() + break + else: + rhs = ''.join(f[2:]) else: rhs = str(count) + lhs = f[0].strip() + #print(f'lhs: {lhs} rhs: {rhs} f:{f}') # evaluate bitshifts in constants e.g. "UC_X86 = 1 << 1" match = re.match(r'(?P\s*\d+\s*<<\s*\d+\s*)', rhs) if match: diff --git a/bindings/dotnet/UnicornManaged/Const/Arm.fs b/bindings/dotnet/UnicornManaged/Const/Arm.fs index 76deda67..d0e039fe 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm.fs @@ -7,6 +7,40 @@ open System [] module Arm = + let UC_CPU_ARM_926 = 0 + let UC_CPU_ARM_946 = 1 + let UC_CPU_ARM_1026 = 2 + let UC_CPU_ARM_1136_R2 = 3 + let UC_CPU_ARM_1136 = 4 + let UC_CPU_ARM_1176 = 5 + let UC_CPU_ARM_11MPCORE = 6 + let UC_CPU_ARM_CORTEX_M0 = 7 + let UC_CPU_ARM_CORTEX_M3 = 8 + let UC_CPU_ARM_CORTEX_M4 = 9 + let UC_CPU_ARM_CORTEX_M7 = 10 + let UC_CPU_ARM_CORTEX_M33 = 11 + let UC_CPU_ARM_CORTEX_R5 = 12 + let UC_CPU_ARM_CORTEX_R5F = 13 + let UC_CPU_ARM_CORTEX_A8 = 14 + let UC_CPU_ARM_CORTEX_A9 = 15 + let UC_CPU_ARM_CORTEX_A7 = 16 + let UC_CPU_ARM_CORTEX_A15 = 17 + let UC_CPU_ARM_TI925T = 18 + let UC_CPU_ARM_SA1100 = 19 + let UC_CPU_ARM_SA1110 = 20 + let UC_CPU_ARM_PXA250 = 21 + let UC_CPU_ARM_PXA255 = 22 + let UC_CPU_ARM_PXA260 = 23 + let UC_CPU_ARM_PXA261 = 24 + let UC_CPU_ARM_PXA262 = 25 + let UC_CPU_ARM_PXA270A0 = 26 + let UC_CPU_ARM_PXA270A1 = 27 + let UC_CPU_ARM_PXA270B0 = 28 + let UC_CPU_ARM_PXA270B1 = 29 + let UC_CPU_ARM_PXA270C0 = 30 + let UC_CPU_ARM_PXA270C5 = 31 + let UC_CPU_ARM_MAX = 32 + // ARM registers let UC_ARM_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Arm64.fs b/bindings/dotnet/UnicornManaged/Const/Arm64.fs index a2ec894e..56d0de58 100644 --- a/bindings/dotnet/UnicornManaged/Const/Arm64.fs +++ b/bindings/dotnet/UnicornManaged/Const/Arm64.fs @@ -7,6 +7,11 @@ open System [] module Arm64 = + let UC_CPU_AARCH64_A57 = 0 + let UC_CPU_AARCH64_A53 = 1 + let UC_CPU_AARCH64_A72 = 2 + let UC_CPU_AARCH64_MAX = 3 + // ARM64 registers let UC_ARM64_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Common.fs b/bindings/dotnet/UnicornManaged/Const/Common.fs index 0b91cac1..9ec83525 100644 --- a/bindings/dotnet/UnicornManaged/Const/Common.fs +++ b/bindings/dotnet/UnicornManaged/Const/Common.fs @@ -112,6 +112,22 @@ module Common = let UC_QUERY_ARCH = 3 let UC_QUERY_TIMEOUT = 4 + let UC_CTL_IO_NONE = 0 + let UC_CTL_IO_WRITE = 1 + let UC_CTL_IO_READ = 2 + let UC_CTL_IO_READ_WRITE = 3 + + let UC_CTL_UC_MODE = 0 + let UC_CTL_UC_PAGE_SIZE = 1 + let UC_CTL_UC_ARCH = 2 + let UC_CTL_UC_TIMEOUT = 3 + let UC_CTL_UC_EXITS_CNT = 4 + let UC_CTL_UC_EXITS = 5 + let UC_CTL_CPU_MODEL = 6 + let UC_CTL_TB_EDGE = 7 + let UC_CTL_TB_REQUEST_CACHE = 8 + let UC_CTL_TB_REMOVE_CACHE = 9 + let UC_PROT_NONE = 0 let UC_PROT_READ = 1 let UC_PROT_WRITE = 2 diff --git a/bindings/dotnet/UnicornManaged/Const/M68k.fs b/bindings/dotnet/UnicornManaged/Const/M68k.fs index 8fc5157e..36808a79 100644 --- a/bindings/dotnet/UnicornManaged/Const/M68k.fs +++ b/bindings/dotnet/UnicornManaged/Const/M68k.fs @@ -7,6 +7,16 @@ open System [] module M68k = + let UC_CPU_M5206_CPU = 0 + let UC_CPU_M68000_CPU = 1 + let UC_CPU_M68020_CPU = 2 + let UC_CPU_M68030_CPU = 3 + let UC_CPU_M68040_CPU = 4 + let UC_CPU_M68060_CPU = 5 + let UC_CPU_M5208_CPU = 6 + let UC_CPU_CFV4E_CPU = 7 + let UC_CPU_ANY_CPU = 8 + // M68K registers let UC_M68K_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Mips.fs b/bindings/dotnet/UnicornManaged/Const/Mips.fs index a8ac5925..48a65287 100644 --- a/bindings/dotnet/UnicornManaged/Const/Mips.fs +++ b/bindings/dotnet/UnicornManaged/Const/Mips.fs @@ -7,6 +7,36 @@ open System [] module Mips = + let UC_CPU_MIPS_4KC = 0 + let UC_CPU_MIPS_4KM = 1 + let UC_CPU_MIPS_4KECR1 = 2 + let UC_CPU_MIPS_4KEMR1 = 3 + let UC_CPU_MIPS_4KEC = 4 + let UC_CPU_MIPS_4KEM = 5 + let UC_CPU_MIPS_24KC = 6 + let UC_CPU_MIPS_24KEC = 7 + let UC_CPU_MIPS_24KF = 8 + let UC_CPU_MIPS_34KF = 9 + let UC_CPU_MIPS_74KF = 10 + let UC_CPU_MIPS_M14K = 11 + let UC_CPU_MIPS_M14KC = 12 + let UC_CPU_MIPS_P5600 = 13 + let UC_CPU_MIPS_MIPS32R6_GENERIC = 14 + let UC_CPU_MIPS_I7200 = 15 + let UC_CPU_MIPS_R4000 = 16 + let UC_CPU_MIPS_VR5432 = 17 + let UC_CPU_MIPS_5KC = 18 + let UC_CPU_MIPS_5KF = 19 + let UC_CPU_MIPS_20KC = 20 + let UC_CPU_MIPS_MIPS64R2_GENERIC = 21 + let UC_CPU_MIPS_5KEC = 22 + let UC_CPU_MIPS_5KEF = 23 + let UC_CPU_MIPS_I6400 = 24 + let UC_CPU_MIPS_I6500 = 25 + let UC_CPU_MIPS_LOONGSON_2E = 26 + let UC_CPU_MIPS_LOONGSON_2F = 27 + let UC_CPU_MIPS_MIPS64DSPR2 = 28 + // MIPS registers let UC_MIPS_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Ppc.fs b/bindings/dotnet/UnicornManaged/Const/Ppc.fs index 2e6c91aa..cfa5be62 100644 --- a/bindings/dotnet/UnicornManaged/Const/Ppc.fs +++ b/bindings/dotnet/UnicornManaged/Const/Ppc.fs @@ -7,6 +7,307 @@ open System [] module Ppc = + let UC_CPU_PPC_401A1 = 0 + let UC_CPU_PPC_401B2 = 1 + let UC_CPU_PPC_401C2 = 2 + let UC_CPU_PPC_401D2 = 3 + let UC_CPU_PPC_401E2 = 4 + let UC_CPU_PPC_401F2 = 5 + let UC_CPU_PPC_401G2 = 6 + let UC_CPU_PPC_COBRA = 7 + let UC_CPU_PPC_403GA = 8 + let UC_CPU_PPC_403GB = 9 + let UC_CPU_PPC_403GC = 10 + let UC_CPU_PPC_403GCX = 11 + let UC_CPU_PPC_405D2 = 12 + let UC_CPU_PPC_405D4 = 13 + let UC_CPU_PPC_405CRA = 14 + let UC_CPU_PPC_405CRB = 15 + let UC_CPU_PPC_405CRC = 16 + let UC_CPU_PPC_405EP = 17 + let UC_CPU_PPC_405EZ = 18 + let UC_CPU_PPC_405GPA = 19 + let UC_CPU_PPC_405GPB = 20 + let UC_CPU_PPC_405GPC = 21 + let UC_CPU_PPC_405GPD = 22 + let UC_CPU_PPC_405GPR = 23 + let UC_CPU_PPC_405LP = 24 + let UC_CPU_PPC_NPE405H = 25 + let UC_CPU_PPC_NPE405H2 = 26 + let UC_CPU_PPC_NPE405L = 27 + let UC_CPU_PPC_NPE4GS3 = 28 + let UC_CPU_PPC_STB03 = 29 + let UC_CPU_PPC_STB04 = 30 + let UC_CPU_PPC_STB25 = 31 + let UC_CPU_PPC_X2VP4 = 32 + let UC_CPU_PPC_440_XILINX = 33 + let UC_CPU_PPC_440EPA = 34 + let UC_CPU_PPC_440EPB = 35 + let UC_CPU_PPC_440GPB = 36 + let UC_CPU_PPC_440GPC = 37 + let UC_CPU_PPC_440GRX = 38 + let UC_CPU_PPC_440GXA = 39 + let UC_CPU_PPC_440GXB = 40 + let UC_CPU_PPC_440GXC = 41 + let UC_CPU_PPC_440GXF = 42 + let UC_CPU_PPC_440SP = 43 + let UC_CPU_PPC_440SP2 = 44 + let UC_CPU_PPC_440SPE = 45 + let UC_CPU_PPC_460EXB = 46 + let UC_CPU_PPC_MPC5XX = 47 + let UC_CPU_PPC_MPC8XX = 48 + let UC_CPU_PPC_G2 = 49 + let UC_CPU_PPC_G2H4 = 50 + let UC_CPU_PPC_G2GP = 51 + let UC_CPU_PPC_G2LS = 52 + let UC_CPU_PPC_MPC603 = 53 + let UC_CPU_PPC_G2_HIP3 = 54 + let UC_CPU_PPC_G2_HIP4 = 55 + let UC_CPU_PPC_G2LE = 56 + let UC_CPU_PPC_G2LEGP = 57 + let UC_CPU_PPC_G2LELS = 58 + let UC_CPU_PPC_G2LEGP1 = 59 + let UC_CPU_PPC_G2LEGP3 = 60 + let UC_CPU_PPC_E200Z5 = 61 + let UC_CPU_PPC_E200Z6 = 62 + let UC_CPU_PPC_E300C1 = 63 + let UC_CPU_PPC_E300C2 = 64 + let UC_CPU_PPC_E300C3 = 65 + let UC_CPU_PPC_E300C4 = 66 + let UC_CPU_PPC_E500V1_V10 = 67 + let UC_CPU_PPC_E500V1_V20 = 68 + let UC_CPU_PPC_E500V2_V10 = 69 + let UC_CPU_PPC_E500V2_V11 = 70 + let UC_CPU_PPC_E500V2_V20 = 71 + let UC_CPU_PPC_E500V2_V21 = 72 + let UC_CPU_PPC_E500V2_V22 = 73 + let UC_CPU_PPC_E500V2_V30 = 74 + let UC_CPU_PPC_E500MC = 75 + let UC_CPU_PPC_E5500 = 76 + let UC_CPU_PPC_E6500 = 77 + let UC_CPU_PPC_E600 = 78 + let UC_CPU_PPC_601_V0 = 79 + let UC_CPU_PPC_601_V1 = 80 + let UC_CPU_PPC_601_V2 = 81 + let UC_CPU_PPC_602 = 82 + let UC_CPU_PPC_603 = 83 + let UC_CPU_PPC_603E_V11 = 84 + let UC_CPU_PPC_603E_V12 = 85 + let UC_CPU_PPC_603E_V13 = 86 + let UC_CPU_PPC_603E_V14 = 87 + let UC_CPU_PPC_603E_V22 = 88 + let UC_CPU_PPC_603E_V3 = 89 + let UC_CPU_PPC_603E_V4 = 90 + let UC_CPU_PPC_603E_V41 = 91 + let UC_CPU_PPC_603E7T = 92 + let UC_CPU_PPC_603E7V = 93 + let UC_CPU_PPC_603E7V1 = 94 + let UC_CPU_PPC_603E7V2 = 95 + let UC_CPU_PPC_603E7 = 96 + let UC_CPU_PPC_603P = 97 + let UC_CPU_PPC_604 = 98 + let UC_CPU_PPC_604E_V10 = 99 + let UC_CPU_PPC_604E_V22 = 100 + let UC_CPU_PPC_604E_V24 = 101 + let UC_CPU_PPC_604R = 102 + let UC_CPU_PPC_7X0_V10 = 103 + let UC_CPU_PPC_7X0_V20 = 104 + let UC_CPU_PPC_7X0_V21 = 105 + let UC_CPU_PPC_7X0_V22 = 106 + let UC_CPU_PPC_7X0_V30 = 107 + let UC_CPU_PPC_7X0_V31 = 108 + let UC_CPU_PPC_740E = 109 + let UC_CPU_PPC_750E = 110 + let UC_CPU_PPC_7X0P = 111 + let UC_CPU_PPC_750CL_V10 = 112 + let UC_CPU_PPC_750CL_V20 = 113 + let UC_CPU_PPC_750CX_V10 = 114 + let UC_CPU_PPC_750CX_V20 = 115 + let UC_CPU_PPC_750CX_V21 = 116 + let UC_CPU_PPC_750CX_V22 = 117 + let UC_CPU_PPC_750CXE_V21 = 118 + let UC_CPU_PPC_750CXE_V22 = 119 + let UC_CPU_PPC_750CXE_V23 = 120 + let UC_CPU_PPC_750CXE_V24 = 121 + let UC_CPU_PPC_750CXE_V24B = 122 + let UC_CPU_PPC_750CXE_V30 = 123 + let UC_CPU_PPC_750CXE_V31 = 124 + let UC_CPU_PPC_750CXE_V31B = 125 + let UC_CPU_PPC_750CXR = 126 + let UC_CPU_PPC_750FL = 127 + let UC_CPU_PPC_750FX_V10 = 128 + let UC_CPU_PPC_750FX_V20 = 129 + let UC_CPU_PPC_750FX_V21 = 130 + let UC_CPU_PPC_750FX_V22 = 131 + let UC_CPU_PPC_750FX_V23 = 132 + let UC_CPU_PPC_750GL = 133 + let UC_CPU_PPC_750GX_V10 = 134 + let UC_CPU_PPC_750GX_V11 = 135 + let UC_CPU_PPC_750GX_V12 = 136 + let UC_CPU_PPC_750L_V20 = 137 + let UC_CPU_PPC_750L_V21 = 138 + let UC_CPU_PPC_750L_V22 = 139 + let UC_CPU_PPC_750L_V30 = 140 + let UC_CPU_PPC_750L_V32 = 141 + let UC_CPU_PPC_7X5_V10 = 142 + let UC_CPU_PPC_7X5_V11 = 143 + let UC_CPU_PPC_7X5_V20 = 144 + let UC_CPU_PPC_7X5_V21 = 145 + let UC_CPU_PPC_7X5_V22 = 146 + let UC_CPU_PPC_7X5_V23 = 147 + let UC_CPU_PPC_7X5_V24 = 148 + let UC_CPU_PPC_7X5_V25 = 149 + let UC_CPU_PPC_7X5_V26 = 150 + let UC_CPU_PPC_7X5_V27 = 151 + let UC_CPU_PPC_7X5_V28 = 152 + let UC_CPU_PPC_7400_V10 = 153 + let UC_CPU_PPC_7400_V11 = 154 + let UC_CPU_PPC_7400_V20 = 155 + let UC_CPU_PPC_7400_V21 = 156 + let UC_CPU_PPC_7400_V22 = 157 + let UC_CPU_PPC_7400_V26 = 158 + let UC_CPU_PPC_7400_V27 = 159 + let UC_CPU_PPC_7400_V28 = 160 + let UC_CPU_PPC_7400_V29 = 161 + let UC_CPU_PPC_7410_V10 = 162 + let UC_CPU_PPC_7410_V11 = 163 + let UC_CPU_PPC_7410_V12 = 164 + let UC_CPU_PPC_7410_V13 = 165 + let UC_CPU_PPC_7410_V14 = 166 + let UC_CPU_PPC_7448_V10 = 167 + let UC_CPU_PPC_7448_V11 = 168 + let UC_CPU_PPC_7448_V20 = 169 + let UC_CPU_PPC_7448_V21 = 170 + let UC_CPU_PPC_7450_V10 = 171 + let UC_CPU_PPC_7450_V11 = 172 + let UC_CPU_PPC_7450_V12 = 173 + let UC_CPU_PPC_7450_V20 = 174 + let UC_CPU_PPC_7450_V21 = 175 + let UC_CPU_PPC_74X1_V23 = 176 + let UC_CPU_PPC_74X1_V210 = 177 + let UC_CPU_PPC_74X5_V10 = 178 + let UC_CPU_PPC_74X5_V21 = 179 + let UC_CPU_PPC_74X5_V32 = 180 + let UC_CPU_PPC_74X5_V33 = 181 + let UC_CPU_PPC_74X5_V34 = 182 + let UC_CPU_PPC_74X7_V10 = 183 + let UC_CPU_PPC_74X7_V11 = 184 + let UC_CPU_PPC_74X7_V12 = 185 + let UC_CPU_PPC_74X7A_V10 = 186 + let UC_CPU_PPC_74X7A_V11 = 187 + let UC_CPU_PPC_74X7A_V12 = 188 + let UC_CPU_PPC_IOP480 = 1 + let UC_CPU_PPC_X2VP20 = 42 + let UC_CPU_PPC_440GRA = 35 + let UC_CPU_PPC_440EPX = 38 + let UC_CPU_PPC_MPC5200_V10 = 59 + let UC_CPU_PPC_MPC5200_V11 = 59 + let UC_CPU_PPC_MPC5200_V12 = 59 + let UC_CPU_PPC_MPC5200B_V20 = 59 + let UC_CPU_PPC_MPC5200B_V21 = 59 + let UC_CPU_PPC_MPC834X = 63 + let UC_CPU_PPC_MPC837X = 66 + let UC_CPU_PPC_E500 = 73 + let UC_CPU_PPC_MPC8533_V10 = 72 + let UC_CPU_PPC_MPC8533_V11 = 73 + let UC_CPU_PPC_MPC8533E_V10 = 72 + let UC_CPU_PPC_MPC8533E_V11 = 73 + let UC_CPU_PPC_MPC8540_V10 = 67 + let UC_CPU_PPC_MPC8540_V20 = 68 + let UC_CPU_PPC_MPC8540_V21 = 68 + let UC_CPU_PPC_MPC8541_V10 = 68 + let UC_CPU_PPC_MPC8541_V11 = 68 + let UC_CPU_PPC_MPC8541E_V10 = 68 + let UC_CPU_PPC_MPC8541E_V11 = 68 + let UC_CPU_PPC_MPC8543_V10 = 69 + let UC_CPU_PPC_MPC8543_V11 = 70 + let UC_CPU_PPC_MPC8543_V20 = 71 + let UC_CPU_PPC_MPC8543_V21 = 72 + let UC_CPU_PPC_MPC8543E_V10 = 69 + let UC_CPU_PPC_MPC8543E_V11 = 70 + let UC_CPU_PPC_MPC8543E_V20 = 71 + let UC_CPU_PPC_MPC8543E_V21 = 72 + let UC_CPU_PPC_MPC8544_V10 = 72 + let UC_CPU_PPC_MPC8544_V11 = 73 + let UC_CPU_PPC_MPC8544E_V11 = 73 + let UC_CPU_PPC_MPC8544E_V10 = 72 + let UC_CPU_PPC_MPC8545_V10 = 69 + let UC_CPU_PPC_MPC8545_V20 = 71 + let UC_CPU_PPC_MPC8545_V21 = 72 + let UC_CPU_PPC_MPC8545E_V10 = 69 + let UC_CPU_PPC_MPC8545E_V20 = 71 + let UC_CPU_PPC_MPC8545E_V21 = 72 + let UC_CPU_PPC_MPC8547E_V10 = 69 + let UC_CPU_PPC_MPC8547E_V20 = 71 + let UC_CPU_PPC_MPC8547E_V21 = 72 + let UC_CPU_PPC_MPC8548_V10 = 69 + let UC_CPU_PPC_MPC8548_V11 = 70 + let UC_CPU_PPC_MPC8548_V20 = 71 + let UC_CPU_PPC_MPC8548_V21 = 72 + let UC_CPU_PPC_MPC8548E_V10 = 69 + let UC_CPU_PPC_MPC8548E_V11 = 70 + let UC_CPU_PPC_MPC8548E_V20 = 71 + let UC_CPU_PPC_MPC8548E_V21 = 72 + let UC_CPU_PPC_MPC8555_V10 = 69 + let UC_CPU_PPC_MPC8555_V11 = 70 + let UC_CPU_PPC_MPC8555E_V10 = 69 + let UC_CPU_PPC_MPC8555E_V11 = 70 + let UC_CPU_PPC_MPC8560_V10 = 69 + let UC_CPU_PPC_MPC8560_V20 = 71 + let UC_CPU_PPC_MPC8560_V21 = 72 + let UC_CPU_PPC_MPC8567 = 73 + let UC_CPU_PPC_MPC8567E = 73 + let UC_CPU_PPC_MPC8568 = 73 + let UC_CPU_PPC_MPC8568E = 73 + let UC_CPU_PPC_MPC8572 = 74 + let UC_CPU_PPC_MPC8572E = 74 + let UC_CPU_PPC_MPC8610 = 78 + let UC_CPU_PPC_MPC8641 = 78 + let UC_CPU_PPC_MPC8641D = 78 + + let UC_CPU_PPC64_620 = 0 + let UC_CPU_PPC64_630 = 1 + let UC_CPU_PPC64_631 = 2 + let UC_CPU_PPC64_POWER4 = 3 + let UC_CPU_PPC64_POWER4P = 4 + let UC_CPU_PPC64_POWER5 = 5 + let UC_CPU_PPC64_POWER5P_V21 = 6 + let UC_CPU_PPC64_POWER6 = 7 + let UC_CPU_PPC64_POWER_SERVER_MASK = 8 + let UC_CPU_PPC64_POWER7_BASE = 9 + let UC_CPU_PPC64_POWER7_V23 = 10 + let UC_CPU_PPC64_POWER7P_BASE = 11 + let UC_CPU_PPC64_POWER7P_V21 = 12 + let UC_CPU_PPC64_POWER8E_BASE = 13 + let UC_CPU_PPC64_POWER8E_V21 = 14 + let UC_CPU_PPC64_POWER8_BASE = 15 + let UC_CPU_PPC64_POWER8_V20 = 16 + let UC_CPU_PPC64_POWER8NVL_BASE = 17 + let UC_CPU_PPC64_POWER8NVL_V10 = 18 + let UC_CPU_PPC64_POWER9_BASE = 19 + let UC_CPU_PPC64_POWER9_DD1 = 20 + let UC_CPU_PPC64_POWER9_DD20 = 21 + let UC_CPU_PPC64_POWER10_BASE = 22 + let UC_CPU_PPC64_POWER10_DD1 = 23 + let UC_CPU_PPC64_970_V22 = 24 + let UC_CPU_PPC64_970FX_V10 = 25 + let UC_CPU_PPC64_970FX_V20 = 26 + let UC_CPU_PPC64_970FX_V21 = 27 + let UC_CPU_PPC64_970FX_V30 = 28 + let UC_CPU_PPC64_970FX_V31 = 29 + let UC_CPU_PPC64_970MP_V10 = 30 + let UC_CPU_PPC64_970MP_V11 = 31 + let UC_CPU_PPC64_CELL_V10 = 32 + let UC_CPU_PPC64_CELL_V20 = 33 + let UC_CPU_PPC64_CELL_V30 = 34 + let UC_CPU_PPC64_CELL_V31 = 35 + let UC_CPU_PPC64_RS64 = 36 + let UC_CPU_PPC64_RS64II = 37 + let UC_CPU_PPC64_RS64III = 38 + let UC_CPU_PPC64_RS64IV = 39 + let UC_CPU_PPC64_CELL_V32 = 35 + let UC_CPU_PPC64_CELL = 35 + // PPC registers let UC_PPC_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Riscv.fs b/bindings/dotnet/UnicornManaged/Const/Riscv.fs index 5fd11e95..ca5881f1 100644 --- a/bindings/dotnet/UnicornManaged/Const/Riscv.fs +++ b/bindings/dotnet/UnicornManaged/Const/Riscv.fs @@ -7,6 +7,16 @@ open System [] module Riscv = + let UC_CPU_RISCV32_ANY = 0 + let UC_CPU_RISCV32_BASE32 = 1 + let UC_CPU_RISCV32_SIFIVE_E31 = 2 + let UC_CPU_RISCV32_SIFIVE_U34 = 3 + + let UC_CPU_RISCV64_ANY = 0 + let UC_CPU_RISCV64_BASE64 = 1 + let UC_CPU_RISCV64_SIFIVE_E51 = 2 + let UC_CPU_RISCV64_SIFIVE_U54 = 3 + // RISCV registers let UC_RISCV_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/Sparc.fs b/bindings/dotnet/UnicornManaged/Const/Sparc.fs index 9a91e1a7..c6c15dd6 100644 --- a/bindings/dotnet/UnicornManaged/Const/Sparc.fs +++ b/bindings/dotnet/UnicornManaged/Const/Sparc.fs @@ -7,6 +7,38 @@ open System [] module Sparc = + let UC_CPU_SPARC_FUJITSU_MB86904 = 0 + let UC_CPU_SPARC_FUJITSU_MB86907 = 1 + let UC_CPU_SPARC_TI_MICROSPARC_I = 2 + let UC_CPU_SPARC_TI_MICROSPARC_II = 3 + let UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 + let UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 + let UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 + let UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 + let UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 + let UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 + let UC_CPU_SPARC_TI_SUPERSPARC_II = 10 + let UC_CPU_SPARC_LEON2 = 11 + let UC_CPU_SPARC_LEON3 = 12 + + let UC_CPU_SPARC64_FUJITSU = 0 + let UC_CPU_SPARC64_FUJITSU_III = 1 + let UC_CPU_SPARC64_FUJITSU_IV = 2 + let UC_CPU_SPARC64_FUJITSU_V = 3 + let UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 + let UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 + let UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 + let UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + let UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 + let UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + let UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + let UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + let UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + let UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + // SPARC registers let UC_SPARC_REG_INVALID = 0 diff --git a/bindings/dotnet/UnicornManaged/Const/X86.fs b/bindings/dotnet/UnicornManaged/Const/X86.fs index fd5ddba6..11c7217b 100644 --- a/bindings/dotnet/UnicornManaged/Const/X86.fs +++ b/bindings/dotnet/UnicornManaged/Const/X86.fs @@ -7,6 +7,45 @@ open System [] module X86 = + let UC_CPU_X86_QEMU64 = 0 + let UC_CPU_X86_PHENOM = 1 + let UC_CPU_X86_CORE2DUO = 2 + let UC_CPU_X86_KVM64 = 3 + let UC_CPU_X86_QEMU32 = 4 + let UC_CPU_X86_KVM32 = 5 + let UC_CPU_X86_COREDUO = 6 + let UC_CPU_X86_486 = 7 + let UC_CPU_X86_PENTIUM = 8 + let UC_CPU_X86_PENTIUM2 = 9 + let UC_CPU_X86_PENTIUM3 = 10 + let UC_CPU_X86_ATHLON = 11 + let UC_CPU_X86_N270 = 12 + let UC_CPU_X86_CONROE = 13 + let UC_CPU_X86_PENRYN = 14 + let UC_CPU_X86_NEHALEM = 15 + let UC_CPU_X86_WESTMERE = 16 + let UC_CPU_X86_SANDYBRIDGE = 17 + let UC_CPU_X86_IVYBRIDGE = 18 + let UC_CPU_X86_HASWELL = 19 + let UC_CPU_X86_BROADWELL = 20 + let UC_CPU_X86_SKYLAKE_CLIENT = 21 + let UC_CPU_X86_SKYLAKE_SERVER = 22 + let UC_CPU_X86_CASCADELAKE_SERVER = 23 + let UC_CPU_X86_COOPERLAKE = 24 + let UC_CPU_X86_ICELAKE_CLIENT = 25 + let UC_CPU_X86_ICELAKE_SERVER = 26 + let UC_CPU_X86_DENVERTON = 27 + let UC_CPU_X86_SNOWRIDGE = 28 + let UC_CPU_X86_KNIGHTSMILL = 29 + let UC_CPU_X86_OPTERON_G1 = 30 + let UC_CPU_X86_OPTERON_G2 = 31 + let UC_CPU_X86_OPTERON_G3 = 32 + let UC_CPU_X86_OPTERON_G4 = 33 + let UC_CPU_X86_OPTERON_G5 = 34 + let UC_CPU_X86_EPYC = 35 + let UC_CPU_X86_DHYANA = 36 + let UC_CPU_X86_EPYC_ROME = 37 + // X86 registers let UC_X86_REG_INVALID = 0 diff --git a/bindings/go/unicorn/arm64_const.go b/bindings/go/unicorn/arm64_const.go index fb8dc906..d2bfd18a 100644 --- a/bindings/go/unicorn/arm64_const.go +++ b/bindings/go/unicorn/arm64_const.go @@ -2,6 +2,11 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.go] const ( + CPU_AARCH64_A57 = 0 + CPU_AARCH64_A53 = 1 + CPU_AARCH64_A72 = 2 + CPU_AARCH64_MAX = 3 + // ARM64 registers ARM64_REG_INVALID = 0 diff --git a/bindings/go/unicorn/arm_const.go b/bindings/go/unicorn/arm_const.go index eab0e336..007c9cad 100644 --- a/bindings/go/unicorn/arm_const.go +++ b/bindings/go/unicorn/arm_const.go @@ -2,6 +2,40 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.go] const ( + CPU_ARM_926 = 0 + CPU_ARM_946 = 1 + CPU_ARM_1026 = 2 + CPU_ARM_1136_R2 = 3 + CPU_ARM_1136 = 4 + CPU_ARM_1176 = 5 + CPU_ARM_11MPCORE = 6 + CPU_ARM_CORTEX_M0 = 7 + CPU_ARM_CORTEX_M3 = 8 + CPU_ARM_CORTEX_M4 = 9 + CPU_ARM_CORTEX_M7 = 10 + CPU_ARM_CORTEX_M33 = 11 + CPU_ARM_CORTEX_R5 = 12 + CPU_ARM_CORTEX_R5F = 13 + CPU_ARM_CORTEX_A8 = 14 + CPU_ARM_CORTEX_A9 = 15 + CPU_ARM_CORTEX_A7 = 16 + CPU_ARM_CORTEX_A15 = 17 + CPU_ARM_TI925T = 18 + CPU_ARM_SA1100 = 19 + CPU_ARM_SA1110 = 20 + CPU_ARM_PXA250 = 21 + CPU_ARM_PXA255 = 22 + CPU_ARM_PXA260 = 23 + CPU_ARM_PXA261 = 24 + CPU_ARM_PXA262 = 25 + CPU_ARM_PXA270A0 = 26 + CPU_ARM_PXA270A1 = 27 + CPU_ARM_PXA270B0 = 28 + CPU_ARM_PXA270B1 = 29 + CPU_ARM_PXA270C0 = 30 + CPU_ARM_PXA270C5 = 31 + CPU_ARM_MAX = 32 + // ARM registers ARM_REG_INVALID = 0 diff --git a/bindings/go/unicorn/m68k_const.go b/bindings/go/unicorn/m68k_const.go index 36ba914a..efa02e03 100644 --- a/bindings/go/unicorn/m68k_const.go +++ b/bindings/go/unicorn/m68k_const.go @@ -2,6 +2,16 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.go] const ( + CPU_M5206_CPU = 0 + CPU_M68000_CPU = 1 + CPU_M68020_CPU = 2 + CPU_M68030_CPU = 3 + CPU_M68040_CPU = 4 + CPU_M68060_CPU = 5 + CPU_M5208_CPU = 6 + CPU_CFV4E_CPU = 7 + CPU_ANY_CPU = 8 + // M68K registers M68K_REG_INVALID = 0 diff --git a/bindings/go/unicorn/mips_const.go b/bindings/go/unicorn/mips_const.go index 20a33756..e45291b5 100644 --- a/bindings/go/unicorn/mips_const.go +++ b/bindings/go/unicorn/mips_const.go @@ -2,6 +2,36 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go] const ( + CPU_MIPS_4KC = 0 + CPU_MIPS_4KM = 1 + CPU_MIPS_4KECR1 = 2 + CPU_MIPS_4KEMR1 = 3 + CPU_MIPS_4KEC = 4 + CPU_MIPS_4KEM = 5 + CPU_MIPS_24KC = 6 + CPU_MIPS_24KEC = 7 + CPU_MIPS_24KF = 8 + CPU_MIPS_34KF = 9 + CPU_MIPS_74KF = 10 + CPU_MIPS_M14K = 11 + CPU_MIPS_M14KC = 12 + CPU_MIPS_P5600 = 13 + CPU_MIPS_MIPS32R6_GENERIC = 14 + CPU_MIPS_I7200 = 15 + CPU_MIPS_R4000 = 16 + CPU_MIPS_VR5432 = 17 + CPU_MIPS_5KC = 18 + CPU_MIPS_5KF = 19 + CPU_MIPS_20KC = 20 + CPU_MIPS_MIPS64R2_GENERIC = 21 + CPU_MIPS_5KEC = 22 + CPU_MIPS_5KEF = 23 + CPU_MIPS_I6400 = 24 + CPU_MIPS_I6500 = 25 + CPU_MIPS_LOONGSON_2E = 26 + CPU_MIPS_LOONGSON_2F = 27 + CPU_MIPS_MIPS64DSPR2 = 28 + // MIPS registers MIPS_REG_INVALID = 0 diff --git a/bindings/go/unicorn/ppc_const.go b/bindings/go/unicorn/ppc_const.go index f0180eeb..03eba18e 100644 --- a/bindings/go/unicorn/ppc_const.go +++ b/bindings/go/unicorn/ppc_const.go @@ -2,6 +2,307 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.go] const ( + CPU_PPC_401A1 = 0 + CPU_PPC_401B2 = 1 + CPU_PPC_401C2 = 2 + CPU_PPC_401D2 = 3 + CPU_PPC_401E2 = 4 + CPU_PPC_401F2 = 5 + CPU_PPC_401G2 = 6 + CPU_PPC_COBRA = 7 + CPU_PPC_403GA = 8 + CPU_PPC_403GB = 9 + CPU_PPC_403GC = 10 + CPU_PPC_403GCX = 11 + CPU_PPC_405D2 = 12 + CPU_PPC_405D4 = 13 + CPU_PPC_405CRA = 14 + CPU_PPC_405CRB = 15 + CPU_PPC_405CRC = 16 + CPU_PPC_405EP = 17 + CPU_PPC_405EZ = 18 + CPU_PPC_405GPA = 19 + CPU_PPC_405GPB = 20 + CPU_PPC_405GPC = 21 + CPU_PPC_405GPD = 22 + CPU_PPC_405GPR = 23 + CPU_PPC_405LP = 24 + CPU_PPC_NPE405H = 25 + CPU_PPC_NPE405H2 = 26 + CPU_PPC_NPE405L = 27 + CPU_PPC_NPE4GS3 = 28 + CPU_PPC_STB03 = 29 + CPU_PPC_STB04 = 30 + CPU_PPC_STB25 = 31 + CPU_PPC_X2VP4 = 32 + CPU_PPC_440_XILINX = 33 + CPU_PPC_440EPA = 34 + CPU_PPC_440EPB = 35 + CPU_PPC_440GPB = 36 + CPU_PPC_440GPC = 37 + CPU_PPC_440GRX = 38 + CPU_PPC_440GXA = 39 + CPU_PPC_440GXB = 40 + CPU_PPC_440GXC = 41 + CPU_PPC_440GXF = 42 + CPU_PPC_440SP = 43 + CPU_PPC_440SP2 = 44 + CPU_PPC_440SPE = 45 + CPU_PPC_460EXB = 46 + CPU_PPC_MPC5XX = 47 + CPU_PPC_MPC8XX = 48 + CPU_PPC_G2 = 49 + CPU_PPC_G2H4 = 50 + CPU_PPC_G2GP = 51 + CPU_PPC_G2LS = 52 + CPU_PPC_MPC603 = 53 + CPU_PPC_G2_HIP3 = 54 + CPU_PPC_G2_HIP4 = 55 + CPU_PPC_G2LE = 56 + CPU_PPC_G2LEGP = 57 + CPU_PPC_G2LELS = 58 + CPU_PPC_G2LEGP1 = 59 + CPU_PPC_G2LEGP3 = 60 + CPU_PPC_E200Z5 = 61 + CPU_PPC_E200Z6 = 62 + CPU_PPC_E300C1 = 63 + CPU_PPC_E300C2 = 64 + CPU_PPC_E300C3 = 65 + CPU_PPC_E300C4 = 66 + CPU_PPC_E500V1_V10 = 67 + CPU_PPC_E500V1_V20 = 68 + CPU_PPC_E500V2_V10 = 69 + CPU_PPC_E500V2_V11 = 70 + CPU_PPC_E500V2_V20 = 71 + CPU_PPC_E500V2_V21 = 72 + CPU_PPC_E500V2_V22 = 73 + CPU_PPC_E500V2_V30 = 74 + CPU_PPC_E500MC = 75 + CPU_PPC_E5500 = 76 + CPU_PPC_E6500 = 77 + CPU_PPC_E600 = 78 + CPU_PPC_601_V0 = 79 + CPU_PPC_601_V1 = 80 + CPU_PPC_601_V2 = 81 + CPU_PPC_602 = 82 + CPU_PPC_603 = 83 + CPU_PPC_603E_V11 = 84 + CPU_PPC_603E_V12 = 85 + CPU_PPC_603E_V13 = 86 + CPU_PPC_603E_V14 = 87 + CPU_PPC_603E_V22 = 88 + CPU_PPC_603E_V3 = 89 + CPU_PPC_603E_V4 = 90 + CPU_PPC_603E_V41 = 91 + CPU_PPC_603E7T = 92 + CPU_PPC_603E7V = 93 + CPU_PPC_603E7V1 = 94 + CPU_PPC_603E7V2 = 95 + CPU_PPC_603E7 = 96 + CPU_PPC_603P = 97 + CPU_PPC_604 = 98 + CPU_PPC_604E_V10 = 99 + CPU_PPC_604E_V22 = 100 + CPU_PPC_604E_V24 = 101 + CPU_PPC_604R = 102 + CPU_PPC_7X0_V10 = 103 + CPU_PPC_7X0_V20 = 104 + CPU_PPC_7X0_V21 = 105 + CPU_PPC_7X0_V22 = 106 + CPU_PPC_7X0_V30 = 107 + CPU_PPC_7X0_V31 = 108 + CPU_PPC_740E = 109 + CPU_PPC_750E = 110 + CPU_PPC_7X0P = 111 + CPU_PPC_750CL_V10 = 112 + CPU_PPC_750CL_V20 = 113 + CPU_PPC_750CX_V10 = 114 + CPU_PPC_750CX_V20 = 115 + CPU_PPC_750CX_V21 = 116 + CPU_PPC_750CX_V22 = 117 + CPU_PPC_750CXE_V21 = 118 + CPU_PPC_750CXE_V22 = 119 + CPU_PPC_750CXE_V23 = 120 + CPU_PPC_750CXE_V24 = 121 + CPU_PPC_750CXE_V24B = 122 + CPU_PPC_750CXE_V30 = 123 + CPU_PPC_750CXE_V31 = 124 + CPU_PPC_750CXE_V31B = 125 + CPU_PPC_750CXR = 126 + CPU_PPC_750FL = 127 + CPU_PPC_750FX_V10 = 128 + CPU_PPC_750FX_V20 = 129 + CPU_PPC_750FX_V21 = 130 + CPU_PPC_750FX_V22 = 131 + CPU_PPC_750FX_V23 = 132 + CPU_PPC_750GL = 133 + CPU_PPC_750GX_V10 = 134 + CPU_PPC_750GX_V11 = 135 + CPU_PPC_750GX_V12 = 136 + CPU_PPC_750L_V20 = 137 + CPU_PPC_750L_V21 = 138 + CPU_PPC_750L_V22 = 139 + CPU_PPC_750L_V30 = 140 + CPU_PPC_750L_V32 = 141 + CPU_PPC_7X5_V10 = 142 + CPU_PPC_7X5_V11 = 143 + CPU_PPC_7X5_V20 = 144 + CPU_PPC_7X5_V21 = 145 + CPU_PPC_7X5_V22 = 146 + CPU_PPC_7X5_V23 = 147 + CPU_PPC_7X5_V24 = 148 + CPU_PPC_7X5_V25 = 149 + CPU_PPC_7X5_V26 = 150 + CPU_PPC_7X5_V27 = 151 + CPU_PPC_7X5_V28 = 152 + CPU_PPC_7400_V10 = 153 + CPU_PPC_7400_V11 = 154 + CPU_PPC_7400_V20 = 155 + CPU_PPC_7400_V21 = 156 + CPU_PPC_7400_V22 = 157 + CPU_PPC_7400_V26 = 158 + CPU_PPC_7400_V27 = 159 + CPU_PPC_7400_V28 = 160 + CPU_PPC_7400_V29 = 161 + CPU_PPC_7410_V10 = 162 + CPU_PPC_7410_V11 = 163 + CPU_PPC_7410_V12 = 164 + CPU_PPC_7410_V13 = 165 + CPU_PPC_7410_V14 = 166 + CPU_PPC_7448_V10 = 167 + CPU_PPC_7448_V11 = 168 + CPU_PPC_7448_V20 = 169 + CPU_PPC_7448_V21 = 170 + CPU_PPC_7450_V10 = 171 + CPU_PPC_7450_V11 = 172 + CPU_PPC_7450_V12 = 173 + CPU_PPC_7450_V20 = 174 + CPU_PPC_7450_V21 = 175 + CPU_PPC_74X1_V23 = 176 + CPU_PPC_74X1_V210 = 177 + CPU_PPC_74X5_V10 = 178 + CPU_PPC_74X5_V21 = 179 + CPU_PPC_74X5_V32 = 180 + CPU_PPC_74X5_V33 = 181 + CPU_PPC_74X5_V34 = 182 + CPU_PPC_74X7_V10 = 183 + CPU_PPC_74X7_V11 = 184 + CPU_PPC_74X7_V12 = 185 + CPU_PPC_74X7A_V10 = 186 + CPU_PPC_74X7A_V11 = 187 + CPU_PPC_74X7A_V12 = 188 + CPU_PPC_IOP480 = 1 + CPU_PPC_X2VP20 = 42 + CPU_PPC_440GRA = 35 + CPU_PPC_440EPX = 38 + CPU_PPC_MPC5200_V10 = 59 + CPU_PPC_MPC5200_V11 = 59 + CPU_PPC_MPC5200_V12 = 59 + CPU_PPC_MPC5200B_V20 = 59 + CPU_PPC_MPC5200B_V21 = 59 + CPU_PPC_MPC834X = 63 + CPU_PPC_MPC837X = 66 + CPU_PPC_E500 = 73 + CPU_PPC_MPC8533_V10 = 72 + CPU_PPC_MPC8533_V11 = 73 + CPU_PPC_MPC8533E_V10 = 72 + CPU_PPC_MPC8533E_V11 = 73 + CPU_PPC_MPC8540_V10 = 67 + CPU_PPC_MPC8540_V20 = 68 + CPU_PPC_MPC8540_V21 = 68 + CPU_PPC_MPC8541_V10 = 68 + CPU_PPC_MPC8541_V11 = 68 + CPU_PPC_MPC8541E_V10 = 68 + CPU_PPC_MPC8541E_V11 = 68 + CPU_PPC_MPC8543_V10 = 69 + CPU_PPC_MPC8543_V11 = 70 + CPU_PPC_MPC8543_V20 = 71 + CPU_PPC_MPC8543_V21 = 72 + CPU_PPC_MPC8543E_V10 = 69 + CPU_PPC_MPC8543E_V11 = 70 + CPU_PPC_MPC8543E_V20 = 71 + CPU_PPC_MPC8543E_V21 = 72 + CPU_PPC_MPC8544_V10 = 72 + CPU_PPC_MPC8544_V11 = 73 + CPU_PPC_MPC8544E_V11 = 73 + CPU_PPC_MPC8544E_V10 = 72 + CPU_PPC_MPC8545_V10 = 69 + CPU_PPC_MPC8545_V20 = 71 + CPU_PPC_MPC8545_V21 = 72 + CPU_PPC_MPC8545E_V10 = 69 + CPU_PPC_MPC8545E_V20 = 71 + CPU_PPC_MPC8545E_V21 = 72 + CPU_PPC_MPC8547E_V10 = 69 + CPU_PPC_MPC8547E_V20 = 71 + CPU_PPC_MPC8547E_V21 = 72 + CPU_PPC_MPC8548_V10 = 69 + CPU_PPC_MPC8548_V11 = 70 + CPU_PPC_MPC8548_V20 = 71 + CPU_PPC_MPC8548_V21 = 72 + CPU_PPC_MPC8548E_V10 = 69 + CPU_PPC_MPC8548E_V11 = 70 + CPU_PPC_MPC8548E_V20 = 71 + CPU_PPC_MPC8548E_V21 = 72 + CPU_PPC_MPC8555_V10 = 69 + CPU_PPC_MPC8555_V11 = 70 + CPU_PPC_MPC8555E_V10 = 69 + CPU_PPC_MPC8555E_V11 = 70 + CPU_PPC_MPC8560_V10 = 69 + CPU_PPC_MPC8560_V20 = 71 + CPU_PPC_MPC8560_V21 = 72 + CPU_PPC_MPC8567 = 73 + CPU_PPC_MPC8567E = 73 + CPU_PPC_MPC8568 = 73 + CPU_PPC_MPC8568E = 73 + CPU_PPC_MPC8572 = 74 + CPU_PPC_MPC8572E = 74 + CPU_PPC_MPC8610 = 78 + CPU_PPC_MPC8641 = 78 + CPU_PPC_MPC8641D = 78 + + CPU_PPC64_620 = 0 + CPU_PPC64_630 = 1 + CPU_PPC64_631 = 2 + CPU_PPC64_POWER4 = 3 + CPU_PPC64_POWER4P = 4 + CPU_PPC64_POWER5 = 5 + CPU_PPC64_POWER5P_V21 = 6 + CPU_PPC64_POWER6 = 7 + CPU_PPC64_POWER_SERVER_MASK = 8 + CPU_PPC64_POWER7_BASE = 9 + CPU_PPC64_POWER7_V23 = 10 + CPU_PPC64_POWER7P_BASE = 11 + CPU_PPC64_POWER7P_V21 = 12 + CPU_PPC64_POWER8E_BASE = 13 + CPU_PPC64_POWER8E_V21 = 14 + CPU_PPC64_POWER8_BASE = 15 + CPU_PPC64_POWER8_V20 = 16 + CPU_PPC64_POWER8NVL_BASE = 17 + CPU_PPC64_POWER8NVL_V10 = 18 + CPU_PPC64_POWER9_BASE = 19 + CPU_PPC64_POWER9_DD1 = 20 + CPU_PPC64_POWER9_DD20 = 21 + CPU_PPC64_POWER10_BASE = 22 + CPU_PPC64_POWER10_DD1 = 23 + CPU_PPC64_970_V22 = 24 + CPU_PPC64_970FX_V10 = 25 + CPU_PPC64_970FX_V20 = 26 + CPU_PPC64_970FX_V21 = 27 + CPU_PPC64_970FX_V30 = 28 + CPU_PPC64_970FX_V31 = 29 + CPU_PPC64_970MP_V10 = 30 + CPU_PPC64_970MP_V11 = 31 + CPU_PPC64_CELL_V10 = 32 + CPU_PPC64_CELL_V20 = 33 + CPU_PPC64_CELL_V30 = 34 + CPU_PPC64_CELL_V31 = 35 + CPU_PPC64_RS64 = 36 + CPU_PPC64_RS64II = 37 + CPU_PPC64_RS64III = 38 + CPU_PPC64_RS64IV = 39 + CPU_PPC64_CELL_V32 = 35 + CPU_PPC64_CELL = 35 + // PPC registers PPC_REG_INVALID = 0 diff --git a/bindings/go/unicorn/riscv_const.go b/bindings/go/unicorn/riscv_const.go index 506a9f90..4295dcc6 100644 --- a/bindings/go/unicorn/riscv_const.go +++ b/bindings/go/unicorn/riscv_const.go @@ -2,6 +2,16 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.go] const ( + CPU_RISCV32_ANY = 0 + CPU_RISCV32_BASE32 = 1 + CPU_RISCV32_SIFIVE_E31 = 2 + CPU_RISCV32_SIFIVE_U34 = 3 + + CPU_RISCV64_ANY = 0 + CPU_RISCV64_BASE64 = 1 + CPU_RISCV64_SIFIVE_E51 = 2 + CPU_RISCV64_SIFIVE_U54 = 3 + // RISCV registers RISCV_REG_INVALID = 0 diff --git a/bindings/go/unicorn/sparc_const.go b/bindings/go/unicorn/sparc_const.go index afd94f45..02bea244 100644 --- a/bindings/go/unicorn/sparc_const.go +++ b/bindings/go/unicorn/sparc_const.go @@ -2,6 +2,38 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.go] const ( + CPU_SPARC_FUJITSU_MB86904 = 0 + CPU_SPARC_FUJITSU_MB86907 = 1 + CPU_SPARC_TI_MICROSPARC_I = 2 + CPU_SPARC_TI_MICROSPARC_II = 3 + CPU_SPARC_TI_MICROSPARC_IIEP = 4 + CPU_SPARC_TI_SUPERSPARC_40 = 5 + CPU_SPARC_TI_SUPERSPARC_50 = 6 + CPU_SPARC_TI_SUPERSPARC_51 = 7 + CPU_SPARC_TI_SUPERSPARC_60 = 8 + CPU_SPARC_TI_SUPERSPARC_61 = 9 + CPU_SPARC_TI_SUPERSPARC_II = 10 + CPU_SPARC_LEON2 = 11 + CPU_SPARC_LEON3 = 12 + + CPU_SPARC64_FUJITSU = 0 + CPU_SPARC64_FUJITSU_III = 1 + CPU_SPARC64_FUJITSU_IV = 2 + CPU_SPARC64_FUJITSU_V = 3 + CPU_SPARC64_TI_ULTRASPARC_I = 4 + CPU_SPARC64_TI_ULTRASPARC_II = 5 + CPU_SPARC64_TI_ULTRASPARC_III = 6 + CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + CPU_SPARC64_SUN_ULTRASPARC_III = 8 + CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + CPU_SPARC64_NEC_ULTRASPARC_I = 16 + // SPARC registers SPARC_REG_INVALID = 0 diff --git a/bindings/go/unicorn/unicorn_const.go b/bindings/go/unicorn/unicorn_const.go index 6196fde5..883453da 100644 --- a/bindings/go/unicorn/unicorn_const.go +++ b/bindings/go/unicorn/unicorn_const.go @@ -107,6 +107,22 @@ const ( QUERY_ARCH = 3 QUERY_TIMEOUT = 4 + CTL_IO_NONE = 0 + CTL_IO_WRITE = 1 + CTL_IO_READ = 2 + CTL_IO_READ_WRITE = 3 + + CTL_UC_MODE = 0 + CTL_UC_PAGE_SIZE = 1 + CTL_UC_ARCH = 2 + CTL_UC_TIMEOUT = 3 + CTL_UC_EXITS_CNT = 4 + CTL_UC_EXITS = 5 + CTL_CPU_MODEL = 6 + CTL_TB_EDGE = 7 + CTL_TB_REQUEST_CACHE = 8 + CTL_TB_REMOVE_CACHE = 9 + PROT_NONE = 0 PROT_READ = 1 PROT_WRITE = 2 diff --git a/bindings/go/unicorn/x86_const.go b/bindings/go/unicorn/x86_const.go index 2a5015bf..c8c45848 100644 --- a/bindings/go/unicorn/x86_const.go +++ b/bindings/go/unicorn/x86_const.go @@ -2,6 +2,45 @@ package unicorn // For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.go] const ( + CPU_X86_QEMU64 = 0 + CPU_X86_PHENOM = 1 + CPU_X86_CORE2DUO = 2 + CPU_X86_KVM64 = 3 + CPU_X86_QEMU32 = 4 + CPU_X86_KVM32 = 5 + CPU_X86_COREDUO = 6 + CPU_X86_486 = 7 + CPU_X86_PENTIUM = 8 + CPU_X86_PENTIUM2 = 9 + CPU_X86_PENTIUM3 = 10 + CPU_X86_ATHLON = 11 + CPU_X86_N270 = 12 + CPU_X86_CONROE = 13 + CPU_X86_PENRYN = 14 + CPU_X86_NEHALEM = 15 + CPU_X86_WESTMERE = 16 + CPU_X86_SANDYBRIDGE = 17 + CPU_X86_IVYBRIDGE = 18 + CPU_X86_HASWELL = 19 + CPU_X86_BROADWELL = 20 + CPU_X86_SKYLAKE_CLIENT = 21 + CPU_X86_SKYLAKE_SERVER = 22 + CPU_X86_CASCADELAKE_SERVER = 23 + CPU_X86_COOPERLAKE = 24 + CPU_X86_ICELAKE_CLIENT = 25 + CPU_X86_ICELAKE_SERVER = 26 + CPU_X86_DENVERTON = 27 + CPU_X86_SNOWRIDGE = 28 + CPU_X86_KNIGHTSMILL = 29 + CPU_X86_OPTERON_G1 = 30 + CPU_X86_OPTERON_G2 = 31 + CPU_X86_OPTERON_G3 = 32 + CPU_X86_OPTERON_G4 = 33 + CPU_X86_OPTERON_G5 = 34 + CPU_X86_EPYC = 35 + CPU_X86_DHYANA = 36 + CPU_X86_EPYC_ROME = 37 + // X86 registers X86_REG_INVALID = 0 diff --git a/bindings/java/unicorn/Arm64Const.java b/bindings/java/unicorn/Arm64Const.java index dc70de85..93cb6975 100644 --- a/bindings/java/unicorn/Arm64Const.java +++ b/bindings/java/unicorn/Arm64Const.java @@ -4,6 +4,11 @@ package unicorn; public interface Arm64Const { + public static final int UC_CPU_AARCH64_A57 = 0; + public static final int UC_CPU_AARCH64_A53 = 1; + public static final int UC_CPU_AARCH64_A72 = 2; + public static final int UC_CPU_AARCH64_MAX = 3; + // ARM64 registers public static final int UC_ARM64_REG_INVALID = 0; diff --git a/bindings/java/unicorn/ArmConst.java b/bindings/java/unicorn/ArmConst.java index 4508430a..4f68cf51 100644 --- a/bindings/java/unicorn/ArmConst.java +++ b/bindings/java/unicorn/ArmConst.java @@ -4,6 +4,40 @@ package unicorn; public interface ArmConst { + public static final int UC_CPU_ARM_926 = 0; + public static final int UC_CPU_ARM_946 = 1; + public static final int UC_CPU_ARM_1026 = 2; + public static final int UC_CPU_ARM_1136_R2 = 3; + public static final int UC_CPU_ARM_1136 = 4; + public static final int UC_CPU_ARM_1176 = 5; + public static final int UC_CPU_ARM_11MPCORE = 6; + public static final int UC_CPU_ARM_CORTEX_M0 = 7; + public static final int UC_CPU_ARM_CORTEX_M3 = 8; + public static final int UC_CPU_ARM_CORTEX_M4 = 9; + public static final int UC_CPU_ARM_CORTEX_M7 = 10; + public static final int UC_CPU_ARM_CORTEX_M33 = 11; + public static final int UC_CPU_ARM_CORTEX_R5 = 12; + public static final int UC_CPU_ARM_CORTEX_R5F = 13; + public static final int UC_CPU_ARM_CORTEX_A8 = 14; + public static final int UC_CPU_ARM_CORTEX_A9 = 15; + public static final int UC_CPU_ARM_CORTEX_A7 = 16; + public static final int UC_CPU_ARM_CORTEX_A15 = 17; + public static final int UC_CPU_ARM_TI925T = 18; + public static final int UC_CPU_ARM_SA1100 = 19; + public static final int UC_CPU_ARM_SA1110 = 20; + public static final int UC_CPU_ARM_PXA250 = 21; + public static final int UC_CPU_ARM_PXA255 = 22; + public static final int UC_CPU_ARM_PXA260 = 23; + public static final int UC_CPU_ARM_PXA261 = 24; + public static final int UC_CPU_ARM_PXA262 = 25; + public static final int UC_CPU_ARM_PXA270A0 = 26; + public static final int UC_CPU_ARM_PXA270A1 = 27; + public static final int UC_CPU_ARM_PXA270B0 = 28; + public static final int UC_CPU_ARM_PXA270B1 = 29; + public static final int UC_CPU_ARM_PXA270C0 = 30; + public static final int UC_CPU_ARM_PXA270C5 = 31; + public static final int UC_CPU_ARM_MAX = 32; + // ARM registers public static final int UC_ARM_REG_INVALID = 0; diff --git a/bindings/java/unicorn/M68kConst.java b/bindings/java/unicorn/M68kConst.java index 4f0574d8..fa7d2d66 100644 --- a/bindings/java/unicorn/M68kConst.java +++ b/bindings/java/unicorn/M68kConst.java @@ -4,6 +4,16 @@ package unicorn; public interface M68kConst { + public static final int UC_CPU_M5206_CPU = 0; + public static final int UC_CPU_M68000_CPU = 1; + public static final int UC_CPU_M68020_CPU = 2; + public static final int UC_CPU_M68030_CPU = 3; + public static final int UC_CPU_M68040_CPU = 4; + public static final int UC_CPU_M68060_CPU = 5; + public static final int UC_CPU_M5208_CPU = 6; + public static final int UC_CPU_CFV4E_CPU = 7; + public static final int UC_CPU_ANY_CPU = 8; + // M68K registers public static final int UC_M68K_REG_INVALID = 0; diff --git a/bindings/java/unicorn/MipsConst.java b/bindings/java/unicorn/MipsConst.java index bace395c..43c53ac0 100644 --- a/bindings/java/unicorn/MipsConst.java +++ b/bindings/java/unicorn/MipsConst.java @@ -4,6 +4,36 @@ package unicorn; public interface MipsConst { + public static final int UC_CPU_MIPS_4KC = 0; + public static final int UC_CPU_MIPS_4KM = 1; + public static final int UC_CPU_MIPS_4KECR1 = 2; + public static final int UC_CPU_MIPS_4KEMR1 = 3; + public static final int UC_CPU_MIPS_4KEC = 4; + public static final int UC_CPU_MIPS_4KEM = 5; + public static final int UC_CPU_MIPS_24KC = 6; + public static final int UC_CPU_MIPS_24KEC = 7; + public static final int UC_CPU_MIPS_24KF = 8; + public static final int UC_CPU_MIPS_34KF = 9; + public static final int UC_CPU_MIPS_74KF = 10; + public static final int UC_CPU_MIPS_M14K = 11; + public static final int UC_CPU_MIPS_M14KC = 12; + public static final int UC_CPU_MIPS_P5600 = 13; + public static final int UC_CPU_MIPS_MIPS32R6_GENERIC = 14; + public static final int UC_CPU_MIPS_I7200 = 15; + public static final int UC_CPU_MIPS_R4000 = 16; + public static final int UC_CPU_MIPS_VR5432 = 17; + public static final int UC_CPU_MIPS_5KC = 18; + public static final int UC_CPU_MIPS_5KF = 19; + public static final int UC_CPU_MIPS_20KC = 20; + public static final int UC_CPU_MIPS_MIPS64R2_GENERIC = 21; + public static final int UC_CPU_MIPS_5KEC = 22; + public static final int UC_CPU_MIPS_5KEF = 23; + public static final int UC_CPU_MIPS_I6400 = 24; + public static final int UC_CPU_MIPS_I6500 = 25; + public static final int UC_CPU_MIPS_LOONGSON_2E = 26; + public static final int UC_CPU_MIPS_LOONGSON_2F = 27; + public static final int UC_CPU_MIPS_MIPS64DSPR2 = 28; + // MIPS registers public static final int UC_MIPS_REG_INVALID = 0; diff --git a/bindings/java/unicorn/PpcConst.java b/bindings/java/unicorn/PpcConst.java index 86597be6..09cada99 100644 --- a/bindings/java/unicorn/PpcConst.java +++ b/bindings/java/unicorn/PpcConst.java @@ -4,6 +4,307 @@ package unicorn; public interface PpcConst { + public static final int UC_CPU_PPC_401A1 = 0; + public static final int UC_CPU_PPC_401B2 = 1; + public static final int UC_CPU_PPC_401C2 = 2; + public static final int UC_CPU_PPC_401D2 = 3; + public static final int UC_CPU_PPC_401E2 = 4; + public static final int UC_CPU_PPC_401F2 = 5; + public static final int UC_CPU_PPC_401G2 = 6; + public static final int UC_CPU_PPC_COBRA = 7; + public static final int UC_CPU_PPC_403GA = 8; + public static final int UC_CPU_PPC_403GB = 9; + public static final int UC_CPU_PPC_403GC = 10; + public static final int UC_CPU_PPC_403GCX = 11; + public static final int UC_CPU_PPC_405D2 = 12; + public static final int UC_CPU_PPC_405D4 = 13; + public static final int UC_CPU_PPC_405CRA = 14; + public static final int UC_CPU_PPC_405CRB = 15; + public static final int UC_CPU_PPC_405CRC = 16; + public static final int UC_CPU_PPC_405EP = 17; + public static final int UC_CPU_PPC_405EZ = 18; + public static final int UC_CPU_PPC_405GPA = 19; + public static final int UC_CPU_PPC_405GPB = 20; + public static final int UC_CPU_PPC_405GPC = 21; + public static final int UC_CPU_PPC_405GPD = 22; + public static final int UC_CPU_PPC_405GPR = 23; + public static final int UC_CPU_PPC_405LP = 24; + public static final int UC_CPU_PPC_NPE405H = 25; + public static final int UC_CPU_PPC_NPE405H2 = 26; + public static final int UC_CPU_PPC_NPE405L = 27; + public static final int UC_CPU_PPC_NPE4GS3 = 28; + public static final int UC_CPU_PPC_STB03 = 29; + public static final int UC_CPU_PPC_STB04 = 30; + public static final int UC_CPU_PPC_STB25 = 31; + public static final int UC_CPU_PPC_X2VP4 = 32; + public static final int UC_CPU_PPC_440_XILINX = 33; + public static final int UC_CPU_PPC_440EPA = 34; + public static final int UC_CPU_PPC_440EPB = 35; + public static final int UC_CPU_PPC_440GPB = 36; + public static final int UC_CPU_PPC_440GPC = 37; + public static final int UC_CPU_PPC_440GRX = 38; + public static final int UC_CPU_PPC_440GXA = 39; + public static final int UC_CPU_PPC_440GXB = 40; + public static final int UC_CPU_PPC_440GXC = 41; + public static final int UC_CPU_PPC_440GXF = 42; + public static final int UC_CPU_PPC_440SP = 43; + public static final int UC_CPU_PPC_440SP2 = 44; + public static final int UC_CPU_PPC_440SPE = 45; + public static final int UC_CPU_PPC_460EXB = 46; + public static final int UC_CPU_PPC_MPC5XX = 47; + public static final int UC_CPU_PPC_MPC8XX = 48; + public static final int UC_CPU_PPC_G2 = 49; + public static final int UC_CPU_PPC_G2H4 = 50; + public static final int UC_CPU_PPC_G2GP = 51; + public static final int UC_CPU_PPC_G2LS = 52; + public static final int UC_CPU_PPC_MPC603 = 53; + public static final int UC_CPU_PPC_G2_HIP3 = 54; + public static final int UC_CPU_PPC_G2_HIP4 = 55; + public static final int UC_CPU_PPC_G2LE = 56; + public static final int UC_CPU_PPC_G2LEGP = 57; + public static final int UC_CPU_PPC_G2LELS = 58; + public static final int UC_CPU_PPC_G2LEGP1 = 59; + public static final int UC_CPU_PPC_G2LEGP3 = 60; + public static final int UC_CPU_PPC_E200Z5 = 61; + public static final int UC_CPU_PPC_E200Z6 = 62; + public static final int UC_CPU_PPC_E300C1 = 63; + public static final int UC_CPU_PPC_E300C2 = 64; + public static final int UC_CPU_PPC_E300C3 = 65; + public static final int UC_CPU_PPC_E300C4 = 66; + public static final int UC_CPU_PPC_E500V1_V10 = 67; + public static final int UC_CPU_PPC_E500V1_V20 = 68; + public static final int UC_CPU_PPC_E500V2_V10 = 69; + public static final int UC_CPU_PPC_E500V2_V11 = 70; + public static final int UC_CPU_PPC_E500V2_V20 = 71; + public static final int UC_CPU_PPC_E500V2_V21 = 72; + public static final int UC_CPU_PPC_E500V2_V22 = 73; + public static final int UC_CPU_PPC_E500V2_V30 = 74; + public static final int UC_CPU_PPC_E500MC = 75; + public static final int UC_CPU_PPC_E5500 = 76; + public static final int UC_CPU_PPC_E6500 = 77; + public static final int UC_CPU_PPC_E600 = 78; + public static final int UC_CPU_PPC_601_V0 = 79; + public static final int UC_CPU_PPC_601_V1 = 80; + public static final int UC_CPU_PPC_601_V2 = 81; + public static final int UC_CPU_PPC_602 = 82; + public static final int UC_CPU_PPC_603 = 83; + public static final int UC_CPU_PPC_603E_V11 = 84; + public static final int UC_CPU_PPC_603E_V12 = 85; + public static final int UC_CPU_PPC_603E_V13 = 86; + public static final int UC_CPU_PPC_603E_V14 = 87; + public static final int UC_CPU_PPC_603E_V22 = 88; + public static final int UC_CPU_PPC_603E_V3 = 89; + public static final int UC_CPU_PPC_603E_V4 = 90; + public static final int UC_CPU_PPC_603E_V41 = 91; + public static final int UC_CPU_PPC_603E7T = 92; + public static final int UC_CPU_PPC_603E7V = 93; + public static final int UC_CPU_PPC_603E7V1 = 94; + public static final int UC_CPU_PPC_603E7V2 = 95; + public static final int UC_CPU_PPC_603E7 = 96; + public static final int UC_CPU_PPC_603P = 97; + public static final int UC_CPU_PPC_604 = 98; + public static final int UC_CPU_PPC_604E_V10 = 99; + public static final int UC_CPU_PPC_604E_V22 = 100; + public static final int UC_CPU_PPC_604E_V24 = 101; + public static final int UC_CPU_PPC_604R = 102; + public static final int UC_CPU_PPC_7X0_V10 = 103; + public static final int UC_CPU_PPC_7X0_V20 = 104; + public static final int UC_CPU_PPC_7X0_V21 = 105; + public static final int UC_CPU_PPC_7X0_V22 = 106; + public static final int UC_CPU_PPC_7X0_V30 = 107; + public static final int UC_CPU_PPC_7X0_V31 = 108; + public static final int UC_CPU_PPC_740E = 109; + public static final int UC_CPU_PPC_750E = 110; + public static final int UC_CPU_PPC_7X0P = 111; + public static final int UC_CPU_PPC_750CL_V10 = 112; + public static final int UC_CPU_PPC_750CL_V20 = 113; + public static final int UC_CPU_PPC_750CX_V10 = 114; + public static final int UC_CPU_PPC_750CX_V20 = 115; + public static final int UC_CPU_PPC_750CX_V21 = 116; + public static final int UC_CPU_PPC_750CX_V22 = 117; + public static final int UC_CPU_PPC_750CXE_V21 = 118; + public static final int UC_CPU_PPC_750CXE_V22 = 119; + public static final int UC_CPU_PPC_750CXE_V23 = 120; + public static final int UC_CPU_PPC_750CXE_V24 = 121; + public static final int UC_CPU_PPC_750CXE_V24B = 122; + public static final int UC_CPU_PPC_750CXE_V30 = 123; + public static final int UC_CPU_PPC_750CXE_V31 = 124; + public static final int UC_CPU_PPC_750CXE_V31B = 125; + public static final int UC_CPU_PPC_750CXR = 126; + public static final int UC_CPU_PPC_750FL = 127; + public static final int UC_CPU_PPC_750FX_V10 = 128; + public static final int UC_CPU_PPC_750FX_V20 = 129; + public static final int UC_CPU_PPC_750FX_V21 = 130; + public static final int UC_CPU_PPC_750FX_V22 = 131; + public static final int UC_CPU_PPC_750FX_V23 = 132; + public static final int UC_CPU_PPC_750GL = 133; + public static final int UC_CPU_PPC_750GX_V10 = 134; + public static final int UC_CPU_PPC_750GX_V11 = 135; + public static final int UC_CPU_PPC_750GX_V12 = 136; + public static final int UC_CPU_PPC_750L_V20 = 137; + public static final int UC_CPU_PPC_750L_V21 = 138; + public static final int UC_CPU_PPC_750L_V22 = 139; + public static final int UC_CPU_PPC_750L_V30 = 140; + public static final int UC_CPU_PPC_750L_V32 = 141; + public static final int UC_CPU_PPC_7X5_V10 = 142; + public static final int UC_CPU_PPC_7X5_V11 = 143; + public static final int UC_CPU_PPC_7X5_V20 = 144; + public static final int UC_CPU_PPC_7X5_V21 = 145; + public static final int UC_CPU_PPC_7X5_V22 = 146; + public static final int UC_CPU_PPC_7X5_V23 = 147; + public static final int UC_CPU_PPC_7X5_V24 = 148; + public static final int UC_CPU_PPC_7X5_V25 = 149; + public static final int UC_CPU_PPC_7X5_V26 = 150; + public static final int UC_CPU_PPC_7X5_V27 = 151; + public static final int UC_CPU_PPC_7X5_V28 = 152; + public static final int UC_CPU_PPC_7400_V10 = 153; + public static final int UC_CPU_PPC_7400_V11 = 154; + public static final int UC_CPU_PPC_7400_V20 = 155; + public static final int UC_CPU_PPC_7400_V21 = 156; + public static final int UC_CPU_PPC_7400_V22 = 157; + public static final int UC_CPU_PPC_7400_V26 = 158; + public static final int UC_CPU_PPC_7400_V27 = 159; + public static final int UC_CPU_PPC_7400_V28 = 160; + public static final int UC_CPU_PPC_7400_V29 = 161; + public static final int UC_CPU_PPC_7410_V10 = 162; + public static final int UC_CPU_PPC_7410_V11 = 163; + public static final int UC_CPU_PPC_7410_V12 = 164; + public static final int UC_CPU_PPC_7410_V13 = 165; + public static final int UC_CPU_PPC_7410_V14 = 166; + public static final int UC_CPU_PPC_7448_V10 = 167; + public static final int UC_CPU_PPC_7448_V11 = 168; + public static final int UC_CPU_PPC_7448_V20 = 169; + public static final int UC_CPU_PPC_7448_V21 = 170; + public static final int UC_CPU_PPC_7450_V10 = 171; + public static final int UC_CPU_PPC_7450_V11 = 172; + public static final int UC_CPU_PPC_7450_V12 = 173; + public static final int UC_CPU_PPC_7450_V20 = 174; + public static final int UC_CPU_PPC_7450_V21 = 175; + public static final int UC_CPU_PPC_74X1_V23 = 176; + public static final int UC_CPU_PPC_74X1_V210 = 177; + public static final int UC_CPU_PPC_74X5_V10 = 178; + public static final int UC_CPU_PPC_74X5_V21 = 179; + public static final int UC_CPU_PPC_74X5_V32 = 180; + public static final int UC_CPU_PPC_74X5_V33 = 181; + public static final int UC_CPU_PPC_74X5_V34 = 182; + public static final int UC_CPU_PPC_74X7_V10 = 183; + public static final int UC_CPU_PPC_74X7_V11 = 184; + public static final int UC_CPU_PPC_74X7_V12 = 185; + public static final int UC_CPU_PPC_74X7A_V10 = 186; + public static final int UC_CPU_PPC_74X7A_V11 = 187; + public static final int UC_CPU_PPC_74X7A_V12 = 188; + public static final int UC_CPU_PPC_IOP480 = 1; + public static final int UC_CPU_PPC_X2VP20 = 42; + public static final int UC_CPU_PPC_440GRA = 35; + public static final int UC_CPU_PPC_440EPX = 38; + public static final int UC_CPU_PPC_MPC5200_V10 = 59; + public static final int UC_CPU_PPC_MPC5200_V11 = 59; + public static final int UC_CPU_PPC_MPC5200_V12 = 59; + public static final int UC_CPU_PPC_MPC5200B_V20 = 59; + public static final int UC_CPU_PPC_MPC5200B_V21 = 59; + public static final int UC_CPU_PPC_MPC834X = 63; + public static final int UC_CPU_PPC_MPC837X = 66; + public static final int UC_CPU_PPC_E500 = 73; + public static final int UC_CPU_PPC_MPC8533_V10 = 72; + public static final int UC_CPU_PPC_MPC8533_V11 = 73; + public static final int UC_CPU_PPC_MPC8533E_V10 = 72; + public static final int UC_CPU_PPC_MPC8533E_V11 = 73; + public static final int UC_CPU_PPC_MPC8540_V10 = 67; + public static final int UC_CPU_PPC_MPC8540_V20 = 68; + public static final int UC_CPU_PPC_MPC8540_V21 = 68; + public static final int UC_CPU_PPC_MPC8541_V10 = 68; + public static final int UC_CPU_PPC_MPC8541_V11 = 68; + public static final int UC_CPU_PPC_MPC8541E_V10 = 68; + public static final int UC_CPU_PPC_MPC8541E_V11 = 68; + public static final int UC_CPU_PPC_MPC8543_V10 = 69; + public static final int UC_CPU_PPC_MPC8543_V11 = 70; + public static final int UC_CPU_PPC_MPC8543_V20 = 71; + public static final int UC_CPU_PPC_MPC8543_V21 = 72; + public static final int UC_CPU_PPC_MPC8543E_V10 = 69; + public static final int UC_CPU_PPC_MPC8543E_V11 = 70; + public static final int UC_CPU_PPC_MPC8543E_V20 = 71; + public static final int UC_CPU_PPC_MPC8543E_V21 = 72; + public static final int UC_CPU_PPC_MPC8544_V10 = 72; + public static final int UC_CPU_PPC_MPC8544_V11 = 73; + public static final int UC_CPU_PPC_MPC8544E_V11 = 73; + public static final int UC_CPU_PPC_MPC8544E_V10 = 72; + public static final int UC_CPU_PPC_MPC8545_V10 = 69; + public static final int UC_CPU_PPC_MPC8545_V20 = 71; + public static final int UC_CPU_PPC_MPC8545_V21 = 72; + public static final int UC_CPU_PPC_MPC8545E_V10 = 69; + public static final int UC_CPU_PPC_MPC8545E_V20 = 71; + public static final int UC_CPU_PPC_MPC8545E_V21 = 72; + public static final int UC_CPU_PPC_MPC8547E_V10 = 69; + public static final int UC_CPU_PPC_MPC8547E_V20 = 71; + public static final int UC_CPU_PPC_MPC8547E_V21 = 72; + public static final int UC_CPU_PPC_MPC8548_V10 = 69; + public static final int UC_CPU_PPC_MPC8548_V11 = 70; + public static final int UC_CPU_PPC_MPC8548_V20 = 71; + public static final int UC_CPU_PPC_MPC8548_V21 = 72; + public static final int UC_CPU_PPC_MPC8548E_V10 = 69; + public static final int UC_CPU_PPC_MPC8548E_V11 = 70; + public static final int UC_CPU_PPC_MPC8548E_V20 = 71; + public static final int UC_CPU_PPC_MPC8548E_V21 = 72; + public static final int UC_CPU_PPC_MPC8555_V10 = 69; + public static final int UC_CPU_PPC_MPC8555_V11 = 70; + public static final int UC_CPU_PPC_MPC8555E_V10 = 69; + public static final int UC_CPU_PPC_MPC8555E_V11 = 70; + public static final int UC_CPU_PPC_MPC8560_V10 = 69; + public static final int UC_CPU_PPC_MPC8560_V20 = 71; + public static final int UC_CPU_PPC_MPC8560_V21 = 72; + public static final int UC_CPU_PPC_MPC8567 = 73; + public static final int UC_CPU_PPC_MPC8567E = 73; + public static final int UC_CPU_PPC_MPC8568 = 73; + public static final int UC_CPU_PPC_MPC8568E = 73; + public static final int UC_CPU_PPC_MPC8572 = 74; + public static final int UC_CPU_PPC_MPC8572E = 74; + public static final int UC_CPU_PPC_MPC8610 = 78; + public static final int UC_CPU_PPC_MPC8641 = 78; + public static final int UC_CPU_PPC_MPC8641D = 78; + + public static final int UC_CPU_PPC64_620 = 0; + public static final int UC_CPU_PPC64_630 = 1; + public static final int UC_CPU_PPC64_631 = 2; + public static final int UC_CPU_PPC64_POWER4 = 3; + public static final int UC_CPU_PPC64_POWER4P = 4; + public static final int UC_CPU_PPC64_POWER5 = 5; + public static final int UC_CPU_PPC64_POWER5P_V21 = 6; + public static final int UC_CPU_PPC64_POWER6 = 7; + public static final int UC_CPU_PPC64_POWER_SERVER_MASK = 8; + public static final int UC_CPU_PPC64_POWER7_BASE = 9; + public static final int UC_CPU_PPC64_POWER7_V23 = 10; + public static final int UC_CPU_PPC64_POWER7P_BASE = 11; + public static final int UC_CPU_PPC64_POWER7P_V21 = 12; + public static final int UC_CPU_PPC64_POWER8E_BASE = 13; + public static final int UC_CPU_PPC64_POWER8E_V21 = 14; + public static final int UC_CPU_PPC64_POWER8_BASE = 15; + public static final int UC_CPU_PPC64_POWER8_V20 = 16; + public static final int UC_CPU_PPC64_POWER8NVL_BASE = 17; + public static final int UC_CPU_PPC64_POWER8NVL_V10 = 18; + public static final int UC_CPU_PPC64_POWER9_BASE = 19; + public static final int UC_CPU_PPC64_POWER9_DD1 = 20; + public static final int UC_CPU_PPC64_POWER9_DD20 = 21; + public static final int UC_CPU_PPC64_POWER10_BASE = 22; + public static final int UC_CPU_PPC64_POWER10_DD1 = 23; + public static final int UC_CPU_PPC64_970_V22 = 24; + public static final int UC_CPU_PPC64_970FX_V10 = 25; + public static final int UC_CPU_PPC64_970FX_V20 = 26; + public static final int UC_CPU_PPC64_970FX_V21 = 27; + public static final int UC_CPU_PPC64_970FX_V30 = 28; + public static final int UC_CPU_PPC64_970FX_V31 = 29; + public static final int UC_CPU_PPC64_970MP_V10 = 30; + public static final int UC_CPU_PPC64_970MP_V11 = 31; + public static final int UC_CPU_PPC64_CELL_V10 = 32; + public static final int UC_CPU_PPC64_CELL_V20 = 33; + public static final int UC_CPU_PPC64_CELL_V30 = 34; + public static final int UC_CPU_PPC64_CELL_V31 = 35; + public static final int UC_CPU_PPC64_RS64 = 36; + public static final int UC_CPU_PPC64_RS64II = 37; + public static final int UC_CPU_PPC64_RS64III = 38; + public static final int UC_CPU_PPC64_RS64IV = 39; + public static final int UC_CPU_PPC64_CELL_V32 = 35; + public static final int UC_CPU_PPC64_CELL = 35; + // PPC registers public static final int UC_PPC_REG_INVALID = 0; diff --git a/bindings/java/unicorn/RiscvConst.java b/bindings/java/unicorn/RiscvConst.java index ca375f1a..d835296c 100644 --- a/bindings/java/unicorn/RiscvConst.java +++ b/bindings/java/unicorn/RiscvConst.java @@ -4,6 +4,16 @@ package unicorn; public interface RiscvConst { + public static final int UC_CPU_RISCV32_ANY = 0; + public static final int UC_CPU_RISCV32_BASE32 = 1; + public static final int UC_CPU_RISCV32_SIFIVE_E31 = 2; + public static final int UC_CPU_RISCV32_SIFIVE_U34 = 3; + + public static final int UC_CPU_RISCV64_ANY = 0; + public static final int UC_CPU_RISCV64_BASE64 = 1; + public static final int UC_CPU_RISCV64_SIFIVE_E51 = 2; + public static final int UC_CPU_RISCV64_SIFIVE_U54 = 3; + // RISCV registers public static final int UC_RISCV_REG_INVALID = 0; diff --git a/bindings/java/unicorn/SparcConst.java b/bindings/java/unicorn/SparcConst.java index de0dc184..27b3b618 100644 --- a/bindings/java/unicorn/SparcConst.java +++ b/bindings/java/unicorn/SparcConst.java @@ -4,6 +4,38 @@ package unicorn; public interface SparcConst { + public static final int UC_CPU_SPARC_FUJITSU_MB86904 = 0; + public static final int UC_CPU_SPARC_FUJITSU_MB86907 = 1; + public static final int UC_CPU_SPARC_TI_MICROSPARC_I = 2; + public static final int UC_CPU_SPARC_TI_MICROSPARC_II = 3; + public static final int UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_40 = 5; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_50 = 6; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_51 = 7; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_60 = 8; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_61 = 9; + public static final int UC_CPU_SPARC_TI_SUPERSPARC_II = 10; + public static final int UC_CPU_SPARC_LEON2 = 11; + public static final int UC_CPU_SPARC_LEON3 = 12; + + public static final int UC_CPU_SPARC64_FUJITSU = 0; + public static final int UC_CPU_SPARC64_FUJITSU_III = 1; + public static final int UC_CPU_SPARC64_FUJITSU_IV = 2; + public static final int UC_CPU_SPARC64_FUJITSU_V = 3; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_I = 4; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_II = 5; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_III = 6; + public static final int UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14; + public static final int UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15; + public static final int UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16; + // SPARC registers public static final int UC_SPARC_REG_INVALID = 0; diff --git a/bindings/java/unicorn/UnicornConst.java b/bindings/java/unicorn/UnicornConst.java index f4396003..0c519d65 100644 --- a/bindings/java/unicorn/UnicornConst.java +++ b/bindings/java/unicorn/UnicornConst.java @@ -109,6 +109,22 @@ public interface UnicornConst { public static final int UC_QUERY_ARCH = 3; public static final int UC_QUERY_TIMEOUT = 4; + public static final int UC_CTL_IO_NONE = 0; + public static final int UC_CTL_IO_WRITE = 1; + public static final int UC_CTL_IO_READ = 2; + public static final int UC_CTL_IO_READ_WRITE = 3; + + public static final int UC_CTL_UC_MODE = 0; + public static final int UC_CTL_UC_PAGE_SIZE = 1; + public static final int UC_CTL_UC_ARCH = 2; + public static final int UC_CTL_UC_TIMEOUT = 3; + public static final int UC_CTL_UC_EXITS_CNT = 4; + public static final int UC_CTL_UC_EXITS = 5; + public static final int UC_CTL_CPU_MODEL = 6; + public static final int UC_CTL_TB_EDGE = 7; + public static final int UC_CTL_TB_REQUEST_CACHE = 8; + public static final int UC_CTL_TB_REMOVE_CACHE = 9; + public static final int UC_PROT_NONE = 0; public static final int UC_PROT_READ = 1; public static final int UC_PROT_WRITE = 2; diff --git a/bindings/java/unicorn/X86Const.java b/bindings/java/unicorn/X86Const.java index a097b525..a12e55bc 100644 --- a/bindings/java/unicorn/X86Const.java +++ b/bindings/java/unicorn/X86Const.java @@ -4,6 +4,45 @@ package unicorn; public interface X86Const { + public static final int UC_CPU_X86_QEMU64 = 0; + public static final int UC_CPU_X86_PHENOM = 1; + public static final int UC_CPU_X86_CORE2DUO = 2; + public static final int UC_CPU_X86_KVM64 = 3; + public static final int UC_CPU_X86_QEMU32 = 4; + public static final int UC_CPU_X86_KVM32 = 5; + public static final int UC_CPU_X86_COREDUO = 6; + public static final int UC_CPU_X86_486 = 7; + public static final int UC_CPU_X86_PENTIUM = 8; + public static final int UC_CPU_X86_PENTIUM2 = 9; + public static final int UC_CPU_X86_PENTIUM3 = 10; + public static final int UC_CPU_X86_ATHLON = 11; + public static final int UC_CPU_X86_N270 = 12; + public static final int UC_CPU_X86_CONROE = 13; + public static final int UC_CPU_X86_PENRYN = 14; + public static final int UC_CPU_X86_NEHALEM = 15; + public static final int UC_CPU_X86_WESTMERE = 16; + public static final int UC_CPU_X86_SANDYBRIDGE = 17; + public static final int UC_CPU_X86_IVYBRIDGE = 18; + public static final int UC_CPU_X86_HASWELL = 19; + public static final int UC_CPU_X86_BROADWELL = 20; + public static final int UC_CPU_X86_SKYLAKE_CLIENT = 21; + public static final int UC_CPU_X86_SKYLAKE_SERVER = 22; + public static final int UC_CPU_X86_CASCADELAKE_SERVER = 23; + public static final int UC_CPU_X86_COOPERLAKE = 24; + public static final int UC_CPU_X86_ICELAKE_CLIENT = 25; + public static final int UC_CPU_X86_ICELAKE_SERVER = 26; + public static final int UC_CPU_X86_DENVERTON = 27; + public static final int UC_CPU_X86_SNOWRIDGE = 28; + public static final int UC_CPU_X86_KNIGHTSMILL = 29; + public static final int UC_CPU_X86_OPTERON_G1 = 30; + public static final int UC_CPU_X86_OPTERON_G2 = 31; + public static final int UC_CPU_X86_OPTERON_G3 = 32; + public static final int UC_CPU_X86_OPTERON_G4 = 33; + public static final int UC_CPU_X86_OPTERON_G5 = 34; + public static final int UC_CPU_X86_EPYC = 35; + public static final int UC_CPU_X86_DHYANA = 36; + public static final int UC_CPU_X86_EPYC_ROME = 37; + // X86 registers public static final int UC_X86_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/Arm64Const.pas b/bindings/pascal/unicorn/Arm64Const.pas index d348039a..416ec2f7 100644 --- a/bindings/pascal/unicorn/Arm64Const.pas +++ b/bindings/pascal/unicorn/Arm64Const.pas @@ -5,6 +5,11 @@ unit Arm64Const; interface const + UC_CPU_AARCH64_A57 = 0; + UC_CPU_AARCH64_A53 = 1; + UC_CPU_AARCH64_A72 = 2; + UC_CPU_AARCH64_MAX = 3; + // ARM64 registers UC_ARM64_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/ArmConst.pas b/bindings/pascal/unicorn/ArmConst.pas index b70b8326..1a85d9f3 100644 --- a/bindings/pascal/unicorn/ArmConst.pas +++ b/bindings/pascal/unicorn/ArmConst.pas @@ -5,6 +5,40 @@ unit ArmConst; interface const + UC_CPU_ARM_926 = 0; + UC_CPU_ARM_946 = 1; + UC_CPU_ARM_1026 = 2; + UC_CPU_ARM_1136_R2 = 3; + UC_CPU_ARM_1136 = 4; + UC_CPU_ARM_1176 = 5; + UC_CPU_ARM_11MPCORE = 6; + UC_CPU_ARM_CORTEX_M0 = 7; + UC_CPU_ARM_CORTEX_M3 = 8; + UC_CPU_ARM_CORTEX_M4 = 9; + UC_CPU_ARM_CORTEX_M7 = 10; + UC_CPU_ARM_CORTEX_M33 = 11; + UC_CPU_ARM_CORTEX_R5 = 12; + UC_CPU_ARM_CORTEX_R5F = 13; + UC_CPU_ARM_CORTEX_A8 = 14; + UC_CPU_ARM_CORTEX_A9 = 15; + UC_CPU_ARM_CORTEX_A7 = 16; + UC_CPU_ARM_CORTEX_A15 = 17; + UC_CPU_ARM_TI925T = 18; + UC_CPU_ARM_SA1100 = 19; + UC_CPU_ARM_SA1110 = 20; + UC_CPU_ARM_PXA250 = 21; + UC_CPU_ARM_PXA255 = 22; + UC_CPU_ARM_PXA260 = 23; + UC_CPU_ARM_PXA261 = 24; + UC_CPU_ARM_PXA262 = 25; + UC_CPU_ARM_PXA270A0 = 26; + UC_CPU_ARM_PXA270A1 = 27; + UC_CPU_ARM_PXA270B0 = 28; + UC_CPU_ARM_PXA270B1 = 29; + UC_CPU_ARM_PXA270C0 = 30; + UC_CPU_ARM_PXA270C5 = 31; + UC_CPU_ARM_MAX = 32; + // ARM registers UC_ARM_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/M68kConst.pas b/bindings/pascal/unicorn/M68kConst.pas index be78f78a..0db7ee82 100644 --- a/bindings/pascal/unicorn/M68kConst.pas +++ b/bindings/pascal/unicorn/M68kConst.pas @@ -5,6 +5,16 @@ unit M68kConst; interface const + UC_CPU_M5206_CPU = 0; + UC_CPU_M68000_CPU = 1; + UC_CPU_M68020_CPU = 2; + UC_CPU_M68030_CPU = 3; + UC_CPU_M68040_CPU = 4; + UC_CPU_M68060_CPU = 5; + UC_CPU_M5208_CPU = 6; + UC_CPU_CFV4E_CPU = 7; + UC_CPU_ANY_CPU = 8; + // M68K registers UC_M68K_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/MipsConst.pas b/bindings/pascal/unicorn/MipsConst.pas index 90f22248..3b1df5f0 100644 --- a/bindings/pascal/unicorn/MipsConst.pas +++ b/bindings/pascal/unicorn/MipsConst.pas @@ -5,6 +5,36 @@ unit MipsConst; interface const + UC_CPU_MIPS_4KC = 0; + UC_CPU_MIPS_4KM = 1; + UC_CPU_MIPS_4KECR1 = 2; + UC_CPU_MIPS_4KEMR1 = 3; + UC_CPU_MIPS_4KEC = 4; + UC_CPU_MIPS_4KEM = 5; + UC_CPU_MIPS_24KC = 6; + UC_CPU_MIPS_24KEC = 7; + UC_CPU_MIPS_24KF = 8; + UC_CPU_MIPS_34KF = 9; + UC_CPU_MIPS_74KF = 10; + UC_CPU_MIPS_M14K = 11; + UC_CPU_MIPS_M14KC = 12; + UC_CPU_MIPS_P5600 = 13; + UC_CPU_MIPS_MIPS32R6_GENERIC = 14; + UC_CPU_MIPS_I7200 = 15; + UC_CPU_MIPS_R4000 = 16; + UC_CPU_MIPS_VR5432 = 17; + UC_CPU_MIPS_5KC = 18; + UC_CPU_MIPS_5KF = 19; + UC_CPU_MIPS_20KC = 20; + UC_CPU_MIPS_MIPS64R2_GENERIC = 21; + UC_CPU_MIPS_5KEC = 22; + UC_CPU_MIPS_5KEF = 23; + UC_CPU_MIPS_I6400 = 24; + UC_CPU_MIPS_I6500 = 25; + UC_CPU_MIPS_LOONGSON_2E = 26; + UC_CPU_MIPS_LOONGSON_2F = 27; + UC_CPU_MIPS_MIPS64DSPR2 = 28; + // MIPS registers UC_MIPS_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/PpcConst.pas b/bindings/pascal/unicorn/PpcConst.pas index 2c6633db..9158c4e3 100644 --- a/bindings/pascal/unicorn/PpcConst.pas +++ b/bindings/pascal/unicorn/PpcConst.pas @@ -5,6 +5,307 @@ unit PpcConst; interface const + UC_CPU_PPC_401A1 = 0; + UC_CPU_PPC_401B2 = 1; + UC_CPU_PPC_401C2 = 2; + UC_CPU_PPC_401D2 = 3; + UC_CPU_PPC_401E2 = 4; + UC_CPU_PPC_401F2 = 5; + UC_CPU_PPC_401G2 = 6; + UC_CPU_PPC_COBRA = 7; + UC_CPU_PPC_403GA = 8; + UC_CPU_PPC_403GB = 9; + UC_CPU_PPC_403GC = 10; + UC_CPU_PPC_403GCX = 11; + UC_CPU_PPC_405D2 = 12; + UC_CPU_PPC_405D4 = 13; + UC_CPU_PPC_405CRA = 14; + UC_CPU_PPC_405CRB = 15; + UC_CPU_PPC_405CRC = 16; + UC_CPU_PPC_405EP = 17; + UC_CPU_PPC_405EZ = 18; + UC_CPU_PPC_405GPA = 19; + UC_CPU_PPC_405GPB = 20; + UC_CPU_PPC_405GPC = 21; + UC_CPU_PPC_405GPD = 22; + UC_CPU_PPC_405GPR = 23; + UC_CPU_PPC_405LP = 24; + UC_CPU_PPC_NPE405H = 25; + UC_CPU_PPC_NPE405H2 = 26; + UC_CPU_PPC_NPE405L = 27; + UC_CPU_PPC_NPE4GS3 = 28; + UC_CPU_PPC_STB03 = 29; + UC_CPU_PPC_STB04 = 30; + UC_CPU_PPC_STB25 = 31; + UC_CPU_PPC_X2VP4 = 32; + UC_CPU_PPC_440_XILINX = 33; + UC_CPU_PPC_440EPA = 34; + UC_CPU_PPC_440EPB = 35; + UC_CPU_PPC_440GPB = 36; + UC_CPU_PPC_440GPC = 37; + UC_CPU_PPC_440GRX = 38; + UC_CPU_PPC_440GXA = 39; + UC_CPU_PPC_440GXB = 40; + UC_CPU_PPC_440GXC = 41; + UC_CPU_PPC_440GXF = 42; + UC_CPU_PPC_440SP = 43; + UC_CPU_PPC_440SP2 = 44; + UC_CPU_PPC_440SPE = 45; + UC_CPU_PPC_460EXB = 46; + UC_CPU_PPC_MPC5XX = 47; + UC_CPU_PPC_MPC8XX = 48; + UC_CPU_PPC_G2 = 49; + UC_CPU_PPC_G2H4 = 50; + UC_CPU_PPC_G2GP = 51; + UC_CPU_PPC_G2LS = 52; + UC_CPU_PPC_MPC603 = 53; + UC_CPU_PPC_G2_HIP3 = 54; + UC_CPU_PPC_G2_HIP4 = 55; + UC_CPU_PPC_G2LE = 56; + UC_CPU_PPC_G2LEGP = 57; + UC_CPU_PPC_G2LELS = 58; + UC_CPU_PPC_G2LEGP1 = 59; + UC_CPU_PPC_G2LEGP3 = 60; + UC_CPU_PPC_E200Z5 = 61; + UC_CPU_PPC_E200Z6 = 62; + UC_CPU_PPC_E300C1 = 63; + UC_CPU_PPC_E300C2 = 64; + UC_CPU_PPC_E300C3 = 65; + UC_CPU_PPC_E300C4 = 66; + UC_CPU_PPC_E500V1_V10 = 67; + UC_CPU_PPC_E500V1_V20 = 68; + UC_CPU_PPC_E500V2_V10 = 69; + UC_CPU_PPC_E500V2_V11 = 70; + UC_CPU_PPC_E500V2_V20 = 71; + UC_CPU_PPC_E500V2_V21 = 72; + UC_CPU_PPC_E500V2_V22 = 73; + UC_CPU_PPC_E500V2_V30 = 74; + UC_CPU_PPC_E500MC = 75; + UC_CPU_PPC_E5500 = 76; + UC_CPU_PPC_E6500 = 77; + UC_CPU_PPC_E600 = 78; + UC_CPU_PPC_601_V0 = 79; + UC_CPU_PPC_601_V1 = 80; + UC_CPU_PPC_601_V2 = 81; + UC_CPU_PPC_602 = 82; + UC_CPU_PPC_603 = 83; + UC_CPU_PPC_603E_V11 = 84; + UC_CPU_PPC_603E_V12 = 85; + UC_CPU_PPC_603E_V13 = 86; + UC_CPU_PPC_603E_V14 = 87; + UC_CPU_PPC_603E_V22 = 88; + UC_CPU_PPC_603E_V3 = 89; + UC_CPU_PPC_603E_V4 = 90; + UC_CPU_PPC_603E_V41 = 91; + UC_CPU_PPC_603E7T = 92; + UC_CPU_PPC_603E7V = 93; + UC_CPU_PPC_603E7V1 = 94; + UC_CPU_PPC_603E7V2 = 95; + UC_CPU_PPC_603E7 = 96; + UC_CPU_PPC_603P = 97; + UC_CPU_PPC_604 = 98; + UC_CPU_PPC_604E_V10 = 99; + UC_CPU_PPC_604E_V22 = 100; + UC_CPU_PPC_604E_V24 = 101; + UC_CPU_PPC_604R = 102; + UC_CPU_PPC_7X0_V10 = 103; + UC_CPU_PPC_7X0_V20 = 104; + UC_CPU_PPC_7X0_V21 = 105; + UC_CPU_PPC_7X0_V22 = 106; + UC_CPU_PPC_7X0_V30 = 107; + UC_CPU_PPC_7X0_V31 = 108; + UC_CPU_PPC_740E = 109; + UC_CPU_PPC_750E = 110; + UC_CPU_PPC_7X0P = 111; + UC_CPU_PPC_750CL_V10 = 112; + UC_CPU_PPC_750CL_V20 = 113; + UC_CPU_PPC_750CX_V10 = 114; + UC_CPU_PPC_750CX_V20 = 115; + UC_CPU_PPC_750CX_V21 = 116; + UC_CPU_PPC_750CX_V22 = 117; + UC_CPU_PPC_750CXE_V21 = 118; + UC_CPU_PPC_750CXE_V22 = 119; + UC_CPU_PPC_750CXE_V23 = 120; + UC_CPU_PPC_750CXE_V24 = 121; + UC_CPU_PPC_750CXE_V24B = 122; + UC_CPU_PPC_750CXE_V30 = 123; + UC_CPU_PPC_750CXE_V31 = 124; + UC_CPU_PPC_750CXE_V31B = 125; + UC_CPU_PPC_750CXR = 126; + UC_CPU_PPC_750FL = 127; + UC_CPU_PPC_750FX_V10 = 128; + UC_CPU_PPC_750FX_V20 = 129; + UC_CPU_PPC_750FX_V21 = 130; + UC_CPU_PPC_750FX_V22 = 131; + UC_CPU_PPC_750FX_V23 = 132; + UC_CPU_PPC_750GL = 133; + UC_CPU_PPC_750GX_V10 = 134; + UC_CPU_PPC_750GX_V11 = 135; + UC_CPU_PPC_750GX_V12 = 136; + UC_CPU_PPC_750L_V20 = 137; + UC_CPU_PPC_750L_V21 = 138; + UC_CPU_PPC_750L_V22 = 139; + UC_CPU_PPC_750L_V30 = 140; + UC_CPU_PPC_750L_V32 = 141; + UC_CPU_PPC_7X5_V10 = 142; + UC_CPU_PPC_7X5_V11 = 143; + UC_CPU_PPC_7X5_V20 = 144; + UC_CPU_PPC_7X5_V21 = 145; + UC_CPU_PPC_7X5_V22 = 146; + UC_CPU_PPC_7X5_V23 = 147; + UC_CPU_PPC_7X5_V24 = 148; + UC_CPU_PPC_7X5_V25 = 149; + UC_CPU_PPC_7X5_V26 = 150; + UC_CPU_PPC_7X5_V27 = 151; + UC_CPU_PPC_7X5_V28 = 152; + UC_CPU_PPC_7400_V10 = 153; + UC_CPU_PPC_7400_V11 = 154; + UC_CPU_PPC_7400_V20 = 155; + UC_CPU_PPC_7400_V21 = 156; + UC_CPU_PPC_7400_V22 = 157; + UC_CPU_PPC_7400_V26 = 158; + UC_CPU_PPC_7400_V27 = 159; + UC_CPU_PPC_7400_V28 = 160; + UC_CPU_PPC_7400_V29 = 161; + UC_CPU_PPC_7410_V10 = 162; + UC_CPU_PPC_7410_V11 = 163; + UC_CPU_PPC_7410_V12 = 164; + UC_CPU_PPC_7410_V13 = 165; + UC_CPU_PPC_7410_V14 = 166; + UC_CPU_PPC_7448_V10 = 167; + UC_CPU_PPC_7448_V11 = 168; + UC_CPU_PPC_7448_V20 = 169; + UC_CPU_PPC_7448_V21 = 170; + UC_CPU_PPC_7450_V10 = 171; + UC_CPU_PPC_7450_V11 = 172; + UC_CPU_PPC_7450_V12 = 173; + UC_CPU_PPC_7450_V20 = 174; + UC_CPU_PPC_7450_V21 = 175; + UC_CPU_PPC_74X1_V23 = 176; + UC_CPU_PPC_74X1_V210 = 177; + UC_CPU_PPC_74X5_V10 = 178; + UC_CPU_PPC_74X5_V21 = 179; + UC_CPU_PPC_74X5_V32 = 180; + UC_CPU_PPC_74X5_V33 = 181; + UC_CPU_PPC_74X5_V34 = 182; + UC_CPU_PPC_74X7_V10 = 183; + UC_CPU_PPC_74X7_V11 = 184; + UC_CPU_PPC_74X7_V12 = 185; + UC_CPU_PPC_74X7A_V10 = 186; + UC_CPU_PPC_74X7A_V11 = 187; + UC_CPU_PPC_74X7A_V12 = 188; + UC_CPU_PPC_IOP480 = 1; + UC_CPU_PPC_X2VP20 = 42; + UC_CPU_PPC_440GRA = 35; + UC_CPU_PPC_440EPX = 38; + UC_CPU_PPC_MPC5200_V10 = 59; + UC_CPU_PPC_MPC5200_V11 = 59; + UC_CPU_PPC_MPC5200_V12 = 59; + UC_CPU_PPC_MPC5200B_V20 = 59; + UC_CPU_PPC_MPC5200B_V21 = 59; + UC_CPU_PPC_MPC834X = 63; + UC_CPU_PPC_MPC837X = 66; + UC_CPU_PPC_E500 = 73; + UC_CPU_PPC_MPC8533_V10 = 72; + UC_CPU_PPC_MPC8533_V11 = 73; + UC_CPU_PPC_MPC8533E_V10 = 72; + UC_CPU_PPC_MPC8533E_V11 = 73; + UC_CPU_PPC_MPC8540_V10 = 67; + UC_CPU_PPC_MPC8540_V20 = 68; + UC_CPU_PPC_MPC8540_V21 = 68; + UC_CPU_PPC_MPC8541_V10 = 68; + UC_CPU_PPC_MPC8541_V11 = 68; + UC_CPU_PPC_MPC8541E_V10 = 68; + UC_CPU_PPC_MPC8541E_V11 = 68; + UC_CPU_PPC_MPC8543_V10 = 69; + UC_CPU_PPC_MPC8543_V11 = 70; + UC_CPU_PPC_MPC8543_V20 = 71; + UC_CPU_PPC_MPC8543_V21 = 72; + UC_CPU_PPC_MPC8543E_V10 = 69; + UC_CPU_PPC_MPC8543E_V11 = 70; + UC_CPU_PPC_MPC8543E_V20 = 71; + UC_CPU_PPC_MPC8543E_V21 = 72; + UC_CPU_PPC_MPC8544_V10 = 72; + UC_CPU_PPC_MPC8544_V11 = 73; + UC_CPU_PPC_MPC8544E_V11 = 73; + UC_CPU_PPC_MPC8544E_V10 = 72; + UC_CPU_PPC_MPC8545_V10 = 69; + UC_CPU_PPC_MPC8545_V20 = 71; + UC_CPU_PPC_MPC8545_V21 = 72; + UC_CPU_PPC_MPC8545E_V10 = 69; + UC_CPU_PPC_MPC8545E_V20 = 71; + UC_CPU_PPC_MPC8545E_V21 = 72; + UC_CPU_PPC_MPC8547E_V10 = 69; + UC_CPU_PPC_MPC8547E_V20 = 71; + UC_CPU_PPC_MPC8547E_V21 = 72; + UC_CPU_PPC_MPC8548_V10 = 69; + UC_CPU_PPC_MPC8548_V11 = 70; + UC_CPU_PPC_MPC8548_V20 = 71; + UC_CPU_PPC_MPC8548_V21 = 72; + UC_CPU_PPC_MPC8548E_V10 = 69; + UC_CPU_PPC_MPC8548E_V11 = 70; + UC_CPU_PPC_MPC8548E_V20 = 71; + UC_CPU_PPC_MPC8548E_V21 = 72; + UC_CPU_PPC_MPC8555_V10 = 69; + UC_CPU_PPC_MPC8555_V11 = 70; + UC_CPU_PPC_MPC8555E_V10 = 69; + UC_CPU_PPC_MPC8555E_V11 = 70; + UC_CPU_PPC_MPC8560_V10 = 69; + UC_CPU_PPC_MPC8560_V20 = 71; + UC_CPU_PPC_MPC8560_V21 = 72; + UC_CPU_PPC_MPC8567 = 73; + UC_CPU_PPC_MPC8567E = 73; + UC_CPU_PPC_MPC8568 = 73; + UC_CPU_PPC_MPC8568E = 73; + UC_CPU_PPC_MPC8572 = 74; + UC_CPU_PPC_MPC8572E = 74; + UC_CPU_PPC_MPC8610 = 78; + UC_CPU_PPC_MPC8641 = 78; + UC_CPU_PPC_MPC8641D = 78; + + UC_CPU_PPC64_620 = 0; + UC_CPU_PPC64_630 = 1; + UC_CPU_PPC64_631 = 2; + UC_CPU_PPC64_POWER4 = 3; + UC_CPU_PPC64_POWER4P = 4; + UC_CPU_PPC64_POWER5 = 5; + UC_CPU_PPC64_POWER5P_V21 = 6; + UC_CPU_PPC64_POWER6 = 7; + UC_CPU_PPC64_POWER_SERVER_MASK = 8; + UC_CPU_PPC64_POWER7_BASE = 9; + UC_CPU_PPC64_POWER7_V23 = 10; + UC_CPU_PPC64_POWER7P_BASE = 11; + UC_CPU_PPC64_POWER7P_V21 = 12; + UC_CPU_PPC64_POWER8E_BASE = 13; + UC_CPU_PPC64_POWER8E_V21 = 14; + UC_CPU_PPC64_POWER8_BASE = 15; + UC_CPU_PPC64_POWER8_V20 = 16; + UC_CPU_PPC64_POWER8NVL_BASE = 17; + UC_CPU_PPC64_POWER8NVL_V10 = 18; + UC_CPU_PPC64_POWER9_BASE = 19; + UC_CPU_PPC64_POWER9_DD1 = 20; + UC_CPU_PPC64_POWER9_DD20 = 21; + UC_CPU_PPC64_POWER10_BASE = 22; + UC_CPU_PPC64_POWER10_DD1 = 23; + UC_CPU_PPC64_970_V22 = 24; + UC_CPU_PPC64_970FX_V10 = 25; + UC_CPU_PPC64_970FX_V20 = 26; + UC_CPU_PPC64_970FX_V21 = 27; + UC_CPU_PPC64_970FX_V30 = 28; + UC_CPU_PPC64_970FX_V31 = 29; + UC_CPU_PPC64_970MP_V10 = 30; + UC_CPU_PPC64_970MP_V11 = 31; + UC_CPU_PPC64_CELL_V10 = 32; + UC_CPU_PPC64_CELL_V20 = 33; + UC_CPU_PPC64_CELL_V30 = 34; + UC_CPU_PPC64_CELL_V31 = 35; + UC_CPU_PPC64_RS64 = 36; + UC_CPU_PPC64_RS64II = 37; + UC_CPU_PPC64_RS64III = 38; + UC_CPU_PPC64_RS64IV = 39; + UC_CPU_PPC64_CELL_V32 = 35; + UC_CPU_PPC64_CELL = 35; + // PPC registers UC_PPC_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/RiscvConst.pas b/bindings/pascal/unicorn/RiscvConst.pas index 7aaa9b74..98a30ce5 100644 --- a/bindings/pascal/unicorn/RiscvConst.pas +++ b/bindings/pascal/unicorn/RiscvConst.pas @@ -5,6 +5,16 @@ unit RiscvConst; interface const + UC_CPU_RISCV32_ANY = 0; + UC_CPU_RISCV32_BASE32 = 1; + UC_CPU_RISCV32_SIFIVE_E31 = 2; + UC_CPU_RISCV32_SIFIVE_U34 = 3; + + UC_CPU_RISCV64_ANY = 0; + UC_CPU_RISCV64_BASE64 = 1; + UC_CPU_RISCV64_SIFIVE_E51 = 2; + UC_CPU_RISCV64_SIFIVE_U54 = 3; + // RISCV registers UC_RISCV_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/SparcConst.pas b/bindings/pascal/unicorn/SparcConst.pas index 32ed3013..9e77d3bb 100644 --- a/bindings/pascal/unicorn/SparcConst.pas +++ b/bindings/pascal/unicorn/SparcConst.pas @@ -5,6 +5,38 @@ unit SparcConst; interface const + UC_CPU_SPARC_FUJITSU_MB86904 = 0; + UC_CPU_SPARC_FUJITSU_MB86907 = 1; + UC_CPU_SPARC_TI_MICROSPARC_I = 2; + UC_CPU_SPARC_TI_MICROSPARC_II = 3; + UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4; + UC_CPU_SPARC_TI_SUPERSPARC_40 = 5; + UC_CPU_SPARC_TI_SUPERSPARC_50 = 6; + UC_CPU_SPARC_TI_SUPERSPARC_51 = 7; + UC_CPU_SPARC_TI_SUPERSPARC_60 = 8; + UC_CPU_SPARC_TI_SUPERSPARC_61 = 9; + UC_CPU_SPARC_TI_SUPERSPARC_II = 10; + UC_CPU_SPARC_LEON2 = 11; + UC_CPU_SPARC_LEON3 = 12; + + UC_CPU_SPARC64_FUJITSU = 0; + UC_CPU_SPARC64_FUJITSU_III = 1; + UC_CPU_SPARC64_FUJITSU_IV = 2; + UC_CPU_SPARC64_FUJITSU_V = 3; + UC_CPU_SPARC64_TI_ULTRASPARC_I = 4; + UC_CPU_SPARC64_TI_ULTRASPARC_II = 5; + UC_CPU_SPARC64_TI_ULTRASPARC_III = 6; + UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7; + UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8; + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9; + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10; + UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11; + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12; + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13; + UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14; + UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15; + UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16; + // SPARC registers UC_SPARC_REG_INVALID = 0; diff --git a/bindings/pascal/unicorn/UnicornConst.pas b/bindings/pascal/unicorn/UnicornConst.pas index 29303b89..6884687b 100644 --- a/bindings/pascal/unicorn/UnicornConst.pas +++ b/bindings/pascal/unicorn/UnicornConst.pas @@ -110,6 +110,22 @@ const UC_API_MAJOR = 2; UC_QUERY_ARCH = 3; UC_QUERY_TIMEOUT = 4; + UC_CTL_IO_NONE = 0; + UC_CTL_IO_WRITE = 1; + UC_CTL_IO_READ = 2; + UC_CTL_IO_READ_WRITE = 3; + + UC_CTL_UC_MODE = 0; + UC_CTL_UC_PAGE_SIZE = 1; + UC_CTL_UC_ARCH = 2; + UC_CTL_UC_TIMEOUT = 3; + UC_CTL_UC_EXITS_CNT = 4; + UC_CTL_UC_EXITS = 5; + UC_CTL_CPU_MODEL = 6; + UC_CTL_TB_EDGE = 7; + UC_CTL_TB_REQUEST_CACHE = 8; + UC_CTL_TB_REMOVE_CACHE = 9; + UC_PROT_NONE = 0; UC_PROT_READ = 1; UC_PROT_WRITE = 2; diff --git a/bindings/pascal/unicorn/X86Const.pas b/bindings/pascal/unicorn/X86Const.pas index 9f05a6f6..446f7602 100644 --- a/bindings/pascal/unicorn/X86Const.pas +++ b/bindings/pascal/unicorn/X86Const.pas @@ -5,6 +5,45 @@ unit X86Const; interface const + UC_CPU_X86_QEMU64 = 0; + UC_CPU_X86_PHENOM = 1; + UC_CPU_X86_CORE2DUO = 2; + UC_CPU_X86_KVM64 = 3; + UC_CPU_X86_QEMU32 = 4; + UC_CPU_X86_KVM32 = 5; + UC_CPU_X86_COREDUO = 6; + UC_CPU_X86_486 = 7; + UC_CPU_X86_PENTIUM = 8; + UC_CPU_X86_PENTIUM2 = 9; + UC_CPU_X86_PENTIUM3 = 10; + UC_CPU_X86_ATHLON = 11; + UC_CPU_X86_N270 = 12; + UC_CPU_X86_CONROE = 13; + UC_CPU_X86_PENRYN = 14; + UC_CPU_X86_NEHALEM = 15; + UC_CPU_X86_WESTMERE = 16; + UC_CPU_X86_SANDYBRIDGE = 17; + UC_CPU_X86_IVYBRIDGE = 18; + UC_CPU_X86_HASWELL = 19; + UC_CPU_X86_BROADWELL = 20; + UC_CPU_X86_SKYLAKE_CLIENT = 21; + UC_CPU_X86_SKYLAKE_SERVER = 22; + UC_CPU_X86_CASCADELAKE_SERVER = 23; + UC_CPU_X86_COOPERLAKE = 24; + UC_CPU_X86_ICELAKE_CLIENT = 25; + UC_CPU_X86_ICELAKE_SERVER = 26; + UC_CPU_X86_DENVERTON = 27; + UC_CPU_X86_SNOWRIDGE = 28; + UC_CPU_X86_KNIGHTSMILL = 29; + UC_CPU_X86_OPTERON_G1 = 30; + UC_CPU_X86_OPTERON_G2 = 31; + UC_CPU_X86_OPTERON_G3 = 32; + UC_CPU_X86_OPTERON_G4 = 33; + UC_CPU_X86_OPTERON_G5 = 34; + UC_CPU_X86_EPYC = 35; + UC_CPU_X86_DHYANA = 36; + UC_CPU_X86_EPYC_ROME = 37; + // X86 registers UC_X86_REG_INVALID = 0; diff --git a/bindings/python/unicorn/arm64_const.py b/bindings/python/unicorn/arm64_const.py index ae8e77eb..867aba49 100644 --- a/bindings/python/unicorn/arm64_const.py +++ b/bindings/python/unicorn/arm64_const.py @@ -1,5 +1,10 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.py] +UC_CPU_AARCH64_A57 = 0 +UC_CPU_AARCH64_A53 = 1 +UC_CPU_AARCH64_A72 = 2 +UC_CPU_AARCH64_MAX = 3 + # ARM64 registers UC_ARM64_REG_INVALID = 0 diff --git a/bindings/python/unicorn/arm_const.py b/bindings/python/unicorn/arm_const.py index 8526f2b9..af8fb5ab 100644 --- a/bindings/python/unicorn/arm_const.py +++ b/bindings/python/unicorn/arm_const.py @@ -1,5 +1,39 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.py] +UC_CPU_ARM_926 = 0 +UC_CPU_ARM_946 = 1 +UC_CPU_ARM_1026 = 2 +UC_CPU_ARM_1136_R2 = 3 +UC_CPU_ARM_1136 = 4 +UC_CPU_ARM_1176 = 5 +UC_CPU_ARM_11MPCORE = 6 +UC_CPU_ARM_CORTEX_M0 = 7 +UC_CPU_ARM_CORTEX_M3 = 8 +UC_CPU_ARM_CORTEX_M4 = 9 +UC_CPU_ARM_CORTEX_M7 = 10 +UC_CPU_ARM_CORTEX_M33 = 11 +UC_CPU_ARM_CORTEX_R5 = 12 +UC_CPU_ARM_CORTEX_R5F = 13 +UC_CPU_ARM_CORTEX_A8 = 14 +UC_CPU_ARM_CORTEX_A9 = 15 +UC_CPU_ARM_CORTEX_A7 = 16 +UC_CPU_ARM_CORTEX_A15 = 17 +UC_CPU_ARM_TI925T = 18 +UC_CPU_ARM_SA1100 = 19 +UC_CPU_ARM_SA1110 = 20 +UC_CPU_ARM_PXA250 = 21 +UC_CPU_ARM_PXA255 = 22 +UC_CPU_ARM_PXA260 = 23 +UC_CPU_ARM_PXA261 = 24 +UC_CPU_ARM_PXA262 = 25 +UC_CPU_ARM_PXA270A0 = 26 +UC_CPU_ARM_PXA270A1 = 27 +UC_CPU_ARM_PXA270B0 = 28 +UC_CPU_ARM_PXA270B1 = 29 +UC_CPU_ARM_PXA270C0 = 30 +UC_CPU_ARM_PXA270C5 = 31 +UC_CPU_ARM_MAX = 32 + # ARM registers UC_ARM_REG_INVALID = 0 diff --git a/bindings/python/unicorn/m68k_const.py b/bindings/python/unicorn/m68k_const.py index 37b00b99..f585b225 100644 --- a/bindings/python/unicorn/m68k_const.py +++ b/bindings/python/unicorn/m68k_const.py @@ -1,5 +1,15 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.py] +UC_CPU_M5206_CPU = 0 +UC_CPU_M68000_CPU = 1 +UC_CPU_M68020_CPU = 2 +UC_CPU_M68030_CPU = 3 +UC_CPU_M68040_CPU = 4 +UC_CPU_M68060_CPU = 5 +UC_CPU_M5208_CPU = 6 +UC_CPU_CFV4E_CPU = 7 +UC_CPU_ANY_CPU = 8 + # M68K registers UC_M68K_REG_INVALID = 0 diff --git a/bindings/python/unicorn/mips_const.py b/bindings/python/unicorn/mips_const.py index a8370ae4..43b0e49f 100644 --- a/bindings/python/unicorn/mips_const.py +++ b/bindings/python/unicorn/mips_const.py @@ -1,5 +1,35 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.py] +UC_CPU_MIPS_4KC = 0 +UC_CPU_MIPS_4KM = 1 +UC_CPU_MIPS_4KECR1 = 2 +UC_CPU_MIPS_4KEMR1 = 3 +UC_CPU_MIPS_4KEC = 4 +UC_CPU_MIPS_4KEM = 5 +UC_CPU_MIPS_24KC = 6 +UC_CPU_MIPS_24KEC = 7 +UC_CPU_MIPS_24KF = 8 +UC_CPU_MIPS_34KF = 9 +UC_CPU_MIPS_74KF = 10 +UC_CPU_MIPS_M14K = 11 +UC_CPU_MIPS_M14KC = 12 +UC_CPU_MIPS_P5600 = 13 +UC_CPU_MIPS_MIPS32R6_GENERIC = 14 +UC_CPU_MIPS_I7200 = 15 +UC_CPU_MIPS_R4000 = 16 +UC_CPU_MIPS_VR5432 = 17 +UC_CPU_MIPS_5KC = 18 +UC_CPU_MIPS_5KF = 19 +UC_CPU_MIPS_20KC = 20 +UC_CPU_MIPS_MIPS64R2_GENERIC = 21 +UC_CPU_MIPS_5KEC = 22 +UC_CPU_MIPS_5KEF = 23 +UC_CPU_MIPS_I6400 = 24 +UC_CPU_MIPS_I6500 = 25 +UC_CPU_MIPS_LOONGSON_2E = 26 +UC_CPU_MIPS_LOONGSON_2F = 27 +UC_CPU_MIPS_MIPS64DSPR2 = 28 + # MIPS registers UC_MIPS_REG_INVALID = 0 diff --git a/bindings/python/unicorn/ppc_const.py b/bindings/python/unicorn/ppc_const.py index 18162dac..1d4813cb 100644 --- a/bindings/python/unicorn/ppc_const.py +++ b/bindings/python/unicorn/ppc_const.py @@ -1,5 +1,306 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.py] +UC_CPU_PPC_401A1 = 0 +UC_CPU_PPC_401B2 = 1 +UC_CPU_PPC_401C2 = 2 +UC_CPU_PPC_401D2 = 3 +UC_CPU_PPC_401E2 = 4 +UC_CPU_PPC_401F2 = 5 +UC_CPU_PPC_401G2 = 6 +UC_CPU_PPC_COBRA = 7 +UC_CPU_PPC_403GA = 8 +UC_CPU_PPC_403GB = 9 +UC_CPU_PPC_403GC = 10 +UC_CPU_PPC_403GCX = 11 +UC_CPU_PPC_405D2 = 12 +UC_CPU_PPC_405D4 = 13 +UC_CPU_PPC_405CRA = 14 +UC_CPU_PPC_405CRB = 15 +UC_CPU_PPC_405CRC = 16 +UC_CPU_PPC_405EP = 17 +UC_CPU_PPC_405EZ = 18 +UC_CPU_PPC_405GPA = 19 +UC_CPU_PPC_405GPB = 20 +UC_CPU_PPC_405GPC = 21 +UC_CPU_PPC_405GPD = 22 +UC_CPU_PPC_405GPR = 23 +UC_CPU_PPC_405LP = 24 +UC_CPU_PPC_NPE405H = 25 +UC_CPU_PPC_NPE405H2 = 26 +UC_CPU_PPC_NPE405L = 27 +UC_CPU_PPC_NPE4GS3 = 28 +UC_CPU_PPC_STB03 = 29 +UC_CPU_PPC_STB04 = 30 +UC_CPU_PPC_STB25 = 31 +UC_CPU_PPC_X2VP4 = 32 +UC_CPU_PPC_440_XILINX = 33 +UC_CPU_PPC_440EPA = 34 +UC_CPU_PPC_440EPB = 35 +UC_CPU_PPC_440GPB = 36 +UC_CPU_PPC_440GPC = 37 +UC_CPU_PPC_440GRX = 38 +UC_CPU_PPC_440GXA = 39 +UC_CPU_PPC_440GXB = 40 +UC_CPU_PPC_440GXC = 41 +UC_CPU_PPC_440GXF = 42 +UC_CPU_PPC_440SP = 43 +UC_CPU_PPC_440SP2 = 44 +UC_CPU_PPC_440SPE = 45 +UC_CPU_PPC_460EXB = 46 +UC_CPU_PPC_MPC5XX = 47 +UC_CPU_PPC_MPC8XX = 48 +UC_CPU_PPC_G2 = 49 +UC_CPU_PPC_G2H4 = 50 +UC_CPU_PPC_G2GP = 51 +UC_CPU_PPC_G2LS = 52 +UC_CPU_PPC_MPC603 = 53 +UC_CPU_PPC_G2_HIP3 = 54 +UC_CPU_PPC_G2_HIP4 = 55 +UC_CPU_PPC_G2LE = 56 +UC_CPU_PPC_G2LEGP = 57 +UC_CPU_PPC_G2LELS = 58 +UC_CPU_PPC_G2LEGP1 = 59 +UC_CPU_PPC_G2LEGP3 = 60 +UC_CPU_PPC_E200Z5 = 61 +UC_CPU_PPC_E200Z6 = 62 +UC_CPU_PPC_E300C1 = 63 +UC_CPU_PPC_E300C2 = 64 +UC_CPU_PPC_E300C3 = 65 +UC_CPU_PPC_E300C4 = 66 +UC_CPU_PPC_E500V1_V10 = 67 +UC_CPU_PPC_E500V1_V20 = 68 +UC_CPU_PPC_E500V2_V10 = 69 +UC_CPU_PPC_E500V2_V11 = 70 +UC_CPU_PPC_E500V2_V20 = 71 +UC_CPU_PPC_E500V2_V21 = 72 +UC_CPU_PPC_E500V2_V22 = 73 +UC_CPU_PPC_E500V2_V30 = 74 +UC_CPU_PPC_E500MC = 75 +UC_CPU_PPC_E5500 = 76 +UC_CPU_PPC_E6500 = 77 +UC_CPU_PPC_E600 = 78 +UC_CPU_PPC_601_V0 = 79 +UC_CPU_PPC_601_V1 = 80 +UC_CPU_PPC_601_V2 = 81 +UC_CPU_PPC_602 = 82 +UC_CPU_PPC_603 = 83 +UC_CPU_PPC_603E_V11 = 84 +UC_CPU_PPC_603E_V12 = 85 +UC_CPU_PPC_603E_V13 = 86 +UC_CPU_PPC_603E_V14 = 87 +UC_CPU_PPC_603E_V22 = 88 +UC_CPU_PPC_603E_V3 = 89 +UC_CPU_PPC_603E_V4 = 90 +UC_CPU_PPC_603E_V41 = 91 +UC_CPU_PPC_603E7T = 92 +UC_CPU_PPC_603E7V = 93 +UC_CPU_PPC_603E7V1 = 94 +UC_CPU_PPC_603E7V2 = 95 +UC_CPU_PPC_603E7 = 96 +UC_CPU_PPC_603P = 97 +UC_CPU_PPC_604 = 98 +UC_CPU_PPC_604E_V10 = 99 +UC_CPU_PPC_604E_V22 = 100 +UC_CPU_PPC_604E_V24 = 101 +UC_CPU_PPC_604R = 102 +UC_CPU_PPC_7X0_V10 = 103 +UC_CPU_PPC_7X0_V20 = 104 +UC_CPU_PPC_7X0_V21 = 105 +UC_CPU_PPC_7X0_V22 = 106 +UC_CPU_PPC_7X0_V30 = 107 +UC_CPU_PPC_7X0_V31 = 108 +UC_CPU_PPC_740E = 109 +UC_CPU_PPC_750E = 110 +UC_CPU_PPC_7X0P = 111 +UC_CPU_PPC_750CL_V10 = 112 +UC_CPU_PPC_750CL_V20 = 113 +UC_CPU_PPC_750CX_V10 = 114 +UC_CPU_PPC_750CX_V20 = 115 +UC_CPU_PPC_750CX_V21 = 116 +UC_CPU_PPC_750CX_V22 = 117 +UC_CPU_PPC_750CXE_V21 = 118 +UC_CPU_PPC_750CXE_V22 = 119 +UC_CPU_PPC_750CXE_V23 = 120 +UC_CPU_PPC_750CXE_V24 = 121 +UC_CPU_PPC_750CXE_V24B = 122 +UC_CPU_PPC_750CXE_V30 = 123 +UC_CPU_PPC_750CXE_V31 = 124 +UC_CPU_PPC_750CXE_V31B = 125 +UC_CPU_PPC_750CXR = 126 +UC_CPU_PPC_750FL = 127 +UC_CPU_PPC_750FX_V10 = 128 +UC_CPU_PPC_750FX_V20 = 129 +UC_CPU_PPC_750FX_V21 = 130 +UC_CPU_PPC_750FX_V22 = 131 +UC_CPU_PPC_750FX_V23 = 132 +UC_CPU_PPC_750GL = 133 +UC_CPU_PPC_750GX_V10 = 134 +UC_CPU_PPC_750GX_V11 = 135 +UC_CPU_PPC_750GX_V12 = 136 +UC_CPU_PPC_750L_V20 = 137 +UC_CPU_PPC_750L_V21 = 138 +UC_CPU_PPC_750L_V22 = 139 +UC_CPU_PPC_750L_V30 = 140 +UC_CPU_PPC_750L_V32 = 141 +UC_CPU_PPC_7X5_V10 = 142 +UC_CPU_PPC_7X5_V11 = 143 +UC_CPU_PPC_7X5_V20 = 144 +UC_CPU_PPC_7X5_V21 = 145 +UC_CPU_PPC_7X5_V22 = 146 +UC_CPU_PPC_7X5_V23 = 147 +UC_CPU_PPC_7X5_V24 = 148 +UC_CPU_PPC_7X5_V25 = 149 +UC_CPU_PPC_7X5_V26 = 150 +UC_CPU_PPC_7X5_V27 = 151 +UC_CPU_PPC_7X5_V28 = 152 +UC_CPU_PPC_7400_V10 = 153 +UC_CPU_PPC_7400_V11 = 154 +UC_CPU_PPC_7400_V20 = 155 +UC_CPU_PPC_7400_V21 = 156 +UC_CPU_PPC_7400_V22 = 157 +UC_CPU_PPC_7400_V26 = 158 +UC_CPU_PPC_7400_V27 = 159 +UC_CPU_PPC_7400_V28 = 160 +UC_CPU_PPC_7400_V29 = 161 +UC_CPU_PPC_7410_V10 = 162 +UC_CPU_PPC_7410_V11 = 163 +UC_CPU_PPC_7410_V12 = 164 +UC_CPU_PPC_7410_V13 = 165 +UC_CPU_PPC_7410_V14 = 166 +UC_CPU_PPC_7448_V10 = 167 +UC_CPU_PPC_7448_V11 = 168 +UC_CPU_PPC_7448_V20 = 169 +UC_CPU_PPC_7448_V21 = 170 +UC_CPU_PPC_7450_V10 = 171 +UC_CPU_PPC_7450_V11 = 172 +UC_CPU_PPC_7450_V12 = 173 +UC_CPU_PPC_7450_V20 = 174 +UC_CPU_PPC_7450_V21 = 175 +UC_CPU_PPC_74X1_V23 = 176 +UC_CPU_PPC_74X1_V210 = 177 +UC_CPU_PPC_74X5_V10 = 178 +UC_CPU_PPC_74X5_V21 = 179 +UC_CPU_PPC_74X5_V32 = 180 +UC_CPU_PPC_74X5_V33 = 181 +UC_CPU_PPC_74X5_V34 = 182 +UC_CPU_PPC_74X7_V10 = 183 +UC_CPU_PPC_74X7_V11 = 184 +UC_CPU_PPC_74X7_V12 = 185 +UC_CPU_PPC_74X7A_V10 = 186 +UC_CPU_PPC_74X7A_V11 = 187 +UC_CPU_PPC_74X7A_V12 = 188 +UC_CPU_PPC_IOP480 = 1 +UC_CPU_PPC_X2VP20 = 42 +UC_CPU_PPC_440GRA = 35 +UC_CPU_PPC_440EPX = 38 +UC_CPU_PPC_MPC5200_V10 = 59 +UC_CPU_PPC_MPC5200_V11 = 59 +UC_CPU_PPC_MPC5200_V12 = 59 +UC_CPU_PPC_MPC5200B_V20 = 59 +UC_CPU_PPC_MPC5200B_V21 = 59 +UC_CPU_PPC_MPC834X = 63 +UC_CPU_PPC_MPC837X = 66 +UC_CPU_PPC_E500 = 73 +UC_CPU_PPC_MPC8533_V10 = 72 +UC_CPU_PPC_MPC8533_V11 = 73 +UC_CPU_PPC_MPC8533E_V10 = 72 +UC_CPU_PPC_MPC8533E_V11 = 73 +UC_CPU_PPC_MPC8540_V10 = 67 +UC_CPU_PPC_MPC8540_V20 = 68 +UC_CPU_PPC_MPC8540_V21 = 68 +UC_CPU_PPC_MPC8541_V10 = 68 +UC_CPU_PPC_MPC8541_V11 = 68 +UC_CPU_PPC_MPC8541E_V10 = 68 +UC_CPU_PPC_MPC8541E_V11 = 68 +UC_CPU_PPC_MPC8543_V10 = 69 +UC_CPU_PPC_MPC8543_V11 = 70 +UC_CPU_PPC_MPC8543_V20 = 71 +UC_CPU_PPC_MPC8543_V21 = 72 +UC_CPU_PPC_MPC8543E_V10 = 69 +UC_CPU_PPC_MPC8543E_V11 = 70 +UC_CPU_PPC_MPC8543E_V20 = 71 +UC_CPU_PPC_MPC8543E_V21 = 72 +UC_CPU_PPC_MPC8544_V10 = 72 +UC_CPU_PPC_MPC8544_V11 = 73 +UC_CPU_PPC_MPC8544E_V11 = 73 +UC_CPU_PPC_MPC8544E_V10 = 72 +UC_CPU_PPC_MPC8545_V10 = 69 +UC_CPU_PPC_MPC8545_V20 = 71 +UC_CPU_PPC_MPC8545_V21 = 72 +UC_CPU_PPC_MPC8545E_V10 = 69 +UC_CPU_PPC_MPC8545E_V20 = 71 +UC_CPU_PPC_MPC8545E_V21 = 72 +UC_CPU_PPC_MPC8547E_V10 = 69 +UC_CPU_PPC_MPC8547E_V20 = 71 +UC_CPU_PPC_MPC8547E_V21 = 72 +UC_CPU_PPC_MPC8548_V10 = 69 +UC_CPU_PPC_MPC8548_V11 = 70 +UC_CPU_PPC_MPC8548_V20 = 71 +UC_CPU_PPC_MPC8548_V21 = 72 +UC_CPU_PPC_MPC8548E_V10 = 69 +UC_CPU_PPC_MPC8548E_V11 = 70 +UC_CPU_PPC_MPC8548E_V20 = 71 +UC_CPU_PPC_MPC8548E_V21 = 72 +UC_CPU_PPC_MPC8555_V10 = 69 +UC_CPU_PPC_MPC8555_V11 = 70 +UC_CPU_PPC_MPC8555E_V10 = 69 +UC_CPU_PPC_MPC8555E_V11 = 70 +UC_CPU_PPC_MPC8560_V10 = 69 +UC_CPU_PPC_MPC8560_V20 = 71 +UC_CPU_PPC_MPC8560_V21 = 72 +UC_CPU_PPC_MPC8567 = 73 +UC_CPU_PPC_MPC8567E = 73 +UC_CPU_PPC_MPC8568 = 73 +UC_CPU_PPC_MPC8568E = 73 +UC_CPU_PPC_MPC8572 = 74 +UC_CPU_PPC_MPC8572E = 74 +UC_CPU_PPC_MPC8610 = 78 +UC_CPU_PPC_MPC8641 = 78 +UC_CPU_PPC_MPC8641D = 78 + +UC_CPU_PPC64_620 = 0 +UC_CPU_PPC64_630 = 1 +UC_CPU_PPC64_631 = 2 +UC_CPU_PPC64_POWER4 = 3 +UC_CPU_PPC64_POWER4P = 4 +UC_CPU_PPC64_POWER5 = 5 +UC_CPU_PPC64_POWER5P_V21 = 6 +UC_CPU_PPC64_POWER6 = 7 +UC_CPU_PPC64_POWER_SERVER_MASK = 8 +UC_CPU_PPC64_POWER7_BASE = 9 +UC_CPU_PPC64_POWER7_V23 = 10 +UC_CPU_PPC64_POWER7P_BASE = 11 +UC_CPU_PPC64_POWER7P_V21 = 12 +UC_CPU_PPC64_POWER8E_BASE = 13 +UC_CPU_PPC64_POWER8E_V21 = 14 +UC_CPU_PPC64_POWER8_BASE = 15 +UC_CPU_PPC64_POWER8_V20 = 16 +UC_CPU_PPC64_POWER8NVL_BASE = 17 +UC_CPU_PPC64_POWER8NVL_V10 = 18 +UC_CPU_PPC64_POWER9_BASE = 19 +UC_CPU_PPC64_POWER9_DD1 = 20 +UC_CPU_PPC64_POWER9_DD20 = 21 +UC_CPU_PPC64_POWER10_BASE = 22 +UC_CPU_PPC64_POWER10_DD1 = 23 +UC_CPU_PPC64_970_V22 = 24 +UC_CPU_PPC64_970FX_V10 = 25 +UC_CPU_PPC64_970FX_V20 = 26 +UC_CPU_PPC64_970FX_V21 = 27 +UC_CPU_PPC64_970FX_V30 = 28 +UC_CPU_PPC64_970FX_V31 = 29 +UC_CPU_PPC64_970MP_V10 = 30 +UC_CPU_PPC64_970MP_V11 = 31 +UC_CPU_PPC64_CELL_V10 = 32 +UC_CPU_PPC64_CELL_V20 = 33 +UC_CPU_PPC64_CELL_V30 = 34 +UC_CPU_PPC64_CELL_V31 = 35 +UC_CPU_PPC64_RS64 = 36 +UC_CPU_PPC64_RS64II = 37 +UC_CPU_PPC64_RS64III = 38 +UC_CPU_PPC64_RS64IV = 39 +UC_CPU_PPC64_CELL_V32 = 35 +UC_CPU_PPC64_CELL = 35 + # PPC registers UC_PPC_REG_INVALID = 0 diff --git a/bindings/python/unicorn/riscv_const.py b/bindings/python/unicorn/riscv_const.py index e4adbcd7..91463afb 100644 --- a/bindings/python/unicorn/riscv_const.py +++ b/bindings/python/unicorn/riscv_const.py @@ -1,5 +1,15 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.py] +UC_CPU_RISCV32_ANY = 0 +UC_CPU_RISCV32_BASE32 = 1 +UC_CPU_RISCV32_SIFIVE_E31 = 2 +UC_CPU_RISCV32_SIFIVE_U34 = 3 + +UC_CPU_RISCV64_ANY = 0 +UC_CPU_RISCV64_BASE64 = 1 +UC_CPU_RISCV64_SIFIVE_E51 = 2 +UC_CPU_RISCV64_SIFIVE_U54 = 3 + # RISCV registers UC_RISCV_REG_INVALID = 0 diff --git a/bindings/python/unicorn/sparc_const.py b/bindings/python/unicorn/sparc_const.py index 7bd326d0..a15599f0 100644 --- a/bindings/python/unicorn/sparc_const.py +++ b/bindings/python/unicorn/sparc_const.py @@ -1,5 +1,37 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.py] +UC_CPU_SPARC_FUJITSU_MB86904 = 0 +UC_CPU_SPARC_FUJITSU_MB86907 = 1 +UC_CPU_SPARC_TI_MICROSPARC_I = 2 +UC_CPU_SPARC_TI_MICROSPARC_II = 3 +UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 +UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 +UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 +UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 +UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 +UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 +UC_CPU_SPARC_TI_SUPERSPARC_II = 10 +UC_CPU_SPARC_LEON2 = 11 +UC_CPU_SPARC_LEON3 = 12 + +UC_CPU_SPARC64_FUJITSU = 0 +UC_CPU_SPARC64_FUJITSU_III = 1 +UC_CPU_SPARC64_FUJITSU_IV = 2 +UC_CPU_SPARC64_FUJITSU_V = 3 +UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 +UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 +UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 +UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 +UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 +UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 +UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 +UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 +UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 +UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 +UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 +UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 +UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + # SPARC registers UC_SPARC_REG_INVALID = 0 diff --git a/bindings/python/unicorn/unicorn_const.py b/bindings/python/unicorn/unicorn_const.py index a517572a..10a7ae51 100644 --- a/bindings/python/unicorn/unicorn_const.py +++ b/bindings/python/unicorn/unicorn_const.py @@ -105,6 +105,22 @@ UC_QUERY_PAGE_SIZE = 2 UC_QUERY_ARCH = 3 UC_QUERY_TIMEOUT = 4 +UC_CTL_IO_NONE = 0 +UC_CTL_IO_WRITE = 1 +UC_CTL_IO_READ = 2 +UC_CTL_IO_READ_WRITE = 3 + +UC_CTL_UC_MODE = 0 +UC_CTL_UC_PAGE_SIZE = 1 +UC_CTL_UC_ARCH = 2 +UC_CTL_UC_TIMEOUT = 3 +UC_CTL_UC_EXITS_CNT = 4 +UC_CTL_UC_EXITS = 5 +UC_CTL_CPU_MODEL = 6 +UC_CTL_TB_EDGE = 7 +UC_CTL_TB_REQUEST_CACHE = 8 +UC_CTL_TB_REMOVE_CACHE = 9 + UC_PROT_NONE = 0 UC_PROT_READ = 1 UC_PROT_WRITE = 2 diff --git a/bindings/python/unicorn/x86_const.py b/bindings/python/unicorn/x86_const.py index 35803fe7..46454371 100644 --- a/bindings/python/unicorn/x86_const.py +++ b/bindings/python/unicorn/x86_const.py @@ -1,5 +1,44 @@ # For Unicorn Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.py] +UC_CPU_X86_QEMU64 = 0 +UC_CPU_X86_PHENOM = 1 +UC_CPU_X86_CORE2DUO = 2 +UC_CPU_X86_KVM64 = 3 +UC_CPU_X86_QEMU32 = 4 +UC_CPU_X86_KVM32 = 5 +UC_CPU_X86_COREDUO = 6 +UC_CPU_X86_486 = 7 +UC_CPU_X86_PENTIUM = 8 +UC_CPU_X86_PENTIUM2 = 9 +UC_CPU_X86_PENTIUM3 = 10 +UC_CPU_X86_ATHLON = 11 +UC_CPU_X86_N270 = 12 +UC_CPU_X86_CONROE = 13 +UC_CPU_X86_PENRYN = 14 +UC_CPU_X86_NEHALEM = 15 +UC_CPU_X86_WESTMERE = 16 +UC_CPU_X86_SANDYBRIDGE = 17 +UC_CPU_X86_IVYBRIDGE = 18 +UC_CPU_X86_HASWELL = 19 +UC_CPU_X86_BROADWELL = 20 +UC_CPU_X86_SKYLAKE_CLIENT = 21 +UC_CPU_X86_SKYLAKE_SERVER = 22 +UC_CPU_X86_CASCADELAKE_SERVER = 23 +UC_CPU_X86_COOPERLAKE = 24 +UC_CPU_X86_ICELAKE_CLIENT = 25 +UC_CPU_X86_ICELAKE_SERVER = 26 +UC_CPU_X86_DENVERTON = 27 +UC_CPU_X86_SNOWRIDGE = 28 +UC_CPU_X86_KNIGHTSMILL = 29 +UC_CPU_X86_OPTERON_G1 = 30 +UC_CPU_X86_OPTERON_G2 = 31 +UC_CPU_X86_OPTERON_G3 = 32 +UC_CPU_X86_OPTERON_G4 = 33 +UC_CPU_X86_OPTERON_G5 = 34 +UC_CPU_X86_EPYC = 35 +UC_CPU_X86_DHYANA = 36 +UC_CPU_X86_EPYC_ROME = 37 + # X86 registers UC_X86_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb index 4c98dd0f..ce051599 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm64_const.rb @@ -2,6 +2,11 @@ module UnicornEngine + UC_CPU_AARCH64_A57 = 0 + UC_CPU_AARCH64_A53 = 1 + UC_CPU_AARCH64_A72 = 2 + UC_CPU_AARCH64_MAX = 3 + # ARM64 registers UC_ARM64_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb index 1d908787..66ad11bf 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/arm_const.rb @@ -2,6 +2,40 @@ module UnicornEngine + UC_CPU_ARM_926 = 0 + UC_CPU_ARM_946 = 1 + UC_CPU_ARM_1026 = 2 + UC_CPU_ARM_1136_R2 = 3 + UC_CPU_ARM_1136 = 4 + UC_CPU_ARM_1176 = 5 + UC_CPU_ARM_11MPCORE = 6 + UC_CPU_ARM_CORTEX_M0 = 7 + UC_CPU_ARM_CORTEX_M3 = 8 + UC_CPU_ARM_CORTEX_M4 = 9 + UC_CPU_ARM_CORTEX_M7 = 10 + UC_CPU_ARM_CORTEX_M33 = 11 + UC_CPU_ARM_CORTEX_R5 = 12 + UC_CPU_ARM_CORTEX_R5F = 13 + UC_CPU_ARM_CORTEX_A8 = 14 + UC_CPU_ARM_CORTEX_A9 = 15 + UC_CPU_ARM_CORTEX_A7 = 16 + UC_CPU_ARM_CORTEX_A15 = 17 + UC_CPU_ARM_TI925T = 18 + UC_CPU_ARM_SA1100 = 19 + UC_CPU_ARM_SA1110 = 20 + UC_CPU_ARM_PXA250 = 21 + UC_CPU_ARM_PXA255 = 22 + UC_CPU_ARM_PXA260 = 23 + UC_CPU_ARM_PXA261 = 24 + UC_CPU_ARM_PXA262 = 25 + UC_CPU_ARM_PXA270A0 = 26 + UC_CPU_ARM_PXA270A1 = 27 + UC_CPU_ARM_PXA270B0 = 28 + UC_CPU_ARM_PXA270B1 = 29 + UC_CPU_ARM_PXA270C0 = 30 + UC_CPU_ARM_PXA270C5 = 31 + UC_CPU_ARM_MAX = 32 + # ARM registers UC_ARM_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb index dc641535..4a473674 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/m68k_const.rb @@ -2,6 +2,16 @@ module UnicornEngine + UC_CPU_M5206_CPU = 0 + UC_CPU_M68000_CPU = 1 + UC_CPU_M68020_CPU = 2 + UC_CPU_M68030_CPU = 3 + UC_CPU_M68040_CPU = 4 + UC_CPU_M68060_CPU = 5 + UC_CPU_M5208_CPU = 6 + UC_CPU_CFV4E_CPU = 7 + UC_CPU_ANY_CPU = 8 + # M68K registers UC_M68K_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb index f9fe86bd..13920c06 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/mips_const.rb @@ -2,6 +2,36 @@ module UnicornEngine + UC_CPU_MIPS_4KC = 0 + UC_CPU_MIPS_4KM = 1 + UC_CPU_MIPS_4KECR1 = 2 + UC_CPU_MIPS_4KEMR1 = 3 + UC_CPU_MIPS_4KEC = 4 + UC_CPU_MIPS_4KEM = 5 + UC_CPU_MIPS_24KC = 6 + UC_CPU_MIPS_24KEC = 7 + UC_CPU_MIPS_24KF = 8 + UC_CPU_MIPS_34KF = 9 + UC_CPU_MIPS_74KF = 10 + UC_CPU_MIPS_M14K = 11 + UC_CPU_MIPS_M14KC = 12 + UC_CPU_MIPS_P5600 = 13 + UC_CPU_MIPS_MIPS32R6_GENERIC = 14 + UC_CPU_MIPS_I7200 = 15 + UC_CPU_MIPS_R4000 = 16 + UC_CPU_MIPS_VR5432 = 17 + UC_CPU_MIPS_5KC = 18 + UC_CPU_MIPS_5KF = 19 + UC_CPU_MIPS_20KC = 20 + UC_CPU_MIPS_MIPS64R2_GENERIC = 21 + UC_CPU_MIPS_5KEC = 22 + UC_CPU_MIPS_5KEF = 23 + UC_CPU_MIPS_I6400 = 24 + UC_CPU_MIPS_I6500 = 25 + UC_CPU_MIPS_LOONGSON_2E = 26 + UC_CPU_MIPS_LOONGSON_2F = 27 + UC_CPU_MIPS_MIPS64DSPR2 = 28 + # MIPS registers UC_MIPS_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb index e8f33330..94748d5c 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/ppc_const.rb @@ -2,6 +2,307 @@ module UnicornEngine + UC_CPU_PPC_401A1 = 0 + UC_CPU_PPC_401B2 = 1 + UC_CPU_PPC_401C2 = 2 + UC_CPU_PPC_401D2 = 3 + UC_CPU_PPC_401E2 = 4 + UC_CPU_PPC_401F2 = 5 + UC_CPU_PPC_401G2 = 6 + UC_CPU_PPC_COBRA = 7 + UC_CPU_PPC_403GA = 8 + UC_CPU_PPC_403GB = 9 + UC_CPU_PPC_403GC = 10 + UC_CPU_PPC_403GCX = 11 + UC_CPU_PPC_405D2 = 12 + UC_CPU_PPC_405D4 = 13 + UC_CPU_PPC_405CRA = 14 + UC_CPU_PPC_405CRB = 15 + UC_CPU_PPC_405CRC = 16 + UC_CPU_PPC_405EP = 17 + UC_CPU_PPC_405EZ = 18 + UC_CPU_PPC_405GPA = 19 + UC_CPU_PPC_405GPB = 20 + UC_CPU_PPC_405GPC = 21 + UC_CPU_PPC_405GPD = 22 + UC_CPU_PPC_405GPR = 23 + UC_CPU_PPC_405LP = 24 + UC_CPU_PPC_NPE405H = 25 + UC_CPU_PPC_NPE405H2 = 26 + UC_CPU_PPC_NPE405L = 27 + UC_CPU_PPC_NPE4GS3 = 28 + UC_CPU_PPC_STB03 = 29 + UC_CPU_PPC_STB04 = 30 + UC_CPU_PPC_STB25 = 31 + UC_CPU_PPC_X2VP4 = 32 + UC_CPU_PPC_440_XILINX = 33 + UC_CPU_PPC_440EPA = 34 + UC_CPU_PPC_440EPB = 35 + UC_CPU_PPC_440GPB = 36 + UC_CPU_PPC_440GPC = 37 + UC_CPU_PPC_440GRX = 38 + UC_CPU_PPC_440GXA = 39 + UC_CPU_PPC_440GXB = 40 + UC_CPU_PPC_440GXC = 41 + UC_CPU_PPC_440GXF = 42 + UC_CPU_PPC_440SP = 43 + UC_CPU_PPC_440SP2 = 44 + UC_CPU_PPC_440SPE = 45 + UC_CPU_PPC_460EXB = 46 + UC_CPU_PPC_MPC5XX = 47 + UC_CPU_PPC_MPC8XX = 48 + UC_CPU_PPC_G2 = 49 + UC_CPU_PPC_G2H4 = 50 + UC_CPU_PPC_G2GP = 51 + UC_CPU_PPC_G2LS = 52 + UC_CPU_PPC_MPC603 = 53 + UC_CPU_PPC_G2_HIP3 = 54 + UC_CPU_PPC_G2_HIP4 = 55 + UC_CPU_PPC_G2LE = 56 + UC_CPU_PPC_G2LEGP = 57 + UC_CPU_PPC_G2LELS = 58 + UC_CPU_PPC_G2LEGP1 = 59 + UC_CPU_PPC_G2LEGP3 = 60 + UC_CPU_PPC_E200Z5 = 61 + UC_CPU_PPC_E200Z6 = 62 + UC_CPU_PPC_E300C1 = 63 + UC_CPU_PPC_E300C2 = 64 + UC_CPU_PPC_E300C3 = 65 + UC_CPU_PPC_E300C4 = 66 + UC_CPU_PPC_E500V1_V10 = 67 + UC_CPU_PPC_E500V1_V20 = 68 + UC_CPU_PPC_E500V2_V10 = 69 + UC_CPU_PPC_E500V2_V11 = 70 + UC_CPU_PPC_E500V2_V20 = 71 + UC_CPU_PPC_E500V2_V21 = 72 + UC_CPU_PPC_E500V2_V22 = 73 + UC_CPU_PPC_E500V2_V30 = 74 + UC_CPU_PPC_E500MC = 75 + UC_CPU_PPC_E5500 = 76 + UC_CPU_PPC_E6500 = 77 + UC_CPU_PPC_E600 = 78 + UC_CPU_PPC_601_V0 = 79 + UC_CPU_PPC_601_V1 = 80 + UC_CPU_PPC_601_V2 = 81 + UC_CPU_PPC_602 = 82 + UC_CPU_PPC_603 = 83 + UC_CPU_PPC_603E_V11 = 84 + UC_CPU_PPC_603E_V12 = 85 + UC_CPU_PPC_603E_V13 = 86 + UC_CPU_PPC_603E_V14 = 87 + UC_CPU_PPC_603E_V22 = 88 + UC_CPU_PPC_603E_V3 = 89 + UC_CPU_PPC_603E_V4 = 90 + UC_CPU_PPC_603E_V41 = 91 + UC_CPU_PPC_603E7T = 92 + UC_CPU_PPC_603E7V = 93 + UC_CPU_PPC_603E7V1 = 94 + UC_CPU_PPC_603E7V2 = 95 + UC_CPU_PPC_603E7 = 96 + UC_CPU_PPC_603P = 97 + UC_CPU_PPC_604 = 98 + UC_CPU_PPC_604E_V10 = 99 + UC_CPU_PPC_604E_V22 = 100 + UC_CPU_PPC_604E_V24 = 101 + UC_CPU_PPC_604R = 102 + UC_CPU_PPC_7X0_V10 = 103 + UC_CPU_PPC_7X0_V20 = 104 + UC_CPU_PPC_7X0_V21 = 105 + UC_CPU_PPC_7X0_V22 = 106 + UC_CPU_PPC_7X0_V30 = 107 + UC_CPU_PPC_7X0_V31 = 108 + UC_CPU_PPC_740E = 109 + UC_CPU_PPC_750E = 110 + UC_CPU_PPC_7X0P = 111 + UC_CPU_PPC_750CL_V10 = 112 + UC_CPU_PPC_750CL_V20 = 113 + UC_CPU_PPC_750CX_V10 = 114 + UC_CPU_PPC_750CX_V20 = 115 + UC_CPU_PPC_750CX_V21 = 116 + UC_CPU_PPC_750CX_V22 = 117 + UC_CPU_PPC_750CXE_V21 = 118 + UC_CPU_PPC_750CXE_V22 = 119 + UC_CPU_PPC_750CXE_V23 = 120 + UC_CPU_PPC_750CXE_V24 = 121 + UC_CPU_PPC_750CXE_V24B = 122 + UC_CPU_PPC_750CXE_V30 = 123 + UC_CPU_PPC_750CXE_V31 = 124 + UC_CPU_PPC_750CXE_V31B = 125 + UC_CPU_PPC_750CXR = 126 + UC_CPU_PPC_750FL = 127 + UC_CPU_PPC_750FX_V10 = 128 + UC_CPU_PPC_750FX_V20 = 129 + UC_CPU_PPC_750FX_V21 = 130 + UC_CPU_PPC_750FX_V22 = 131 + UC_CPU_PPC_750FX_V23 = 132 + UC_CPU_PPC_750GL = 133 + UC_CPU_PPC_750GX_V10 = 134 + UC_CPU_PPC_750GX_V11 = 135 + UC_CPU_PPC_750GX_V12 = 136 + UC_CPU_PPC_750L_V20 = 137 + UC_CPU_PPC_750L_V21 = 138 + UC_CPU_PPC_750L_V22 = 139 + UC_CPU_PPC_750L_V30 = 140 + UC_CPU_PPC_750L_V32 = 141 + UC_CPU_PPC_7X5_V10 = 142 + UC_CPU_PPC_7X5_V11 = 143 + UC_CPU_PPC_7X5_V20 = 144 + UC_CPU_PPC_7X5_V21 = 145 + UC_CPU_PPC_7X5_V22 = 146 + UC_CPU_PPC_7X5_V23 = 147 + UC_CPU_PPC_7X5_V24 = 148 + UC_CPU_PPC_7X5_V25 = 149 + UC_CPU_PPC_7X5_V26 = 150 + UC_CPU_PPC_7X5_V27 = 151 + UC_CPU_PPC_7X5_V28 = 152 + UC_CPU_PPC_7400_V10 = 153 + UC_CPU_PPC_7400_V11 = 154 + UC_CPU_PPC_7400_V20 = 155 + UC_CPU_PPC_7400_V21 = 156 + UC_CPU_PPC_7400_V22 = 157 + UC_CPU_PPC_7400_V26 = 158 + UC_CPU_PPC_7400_V27 = 159 + UC_CPU_PPC_7400_V28 = 160 + UC_CPU_PPC_7400_V29 = 161 + UC_CPU_PPC_7410_V10 = 162 + UC_CPU_PPC_7410_V11 = 163 + UC_CPU_PPC_7410_V12 = 164 + UC_CPU_PPC_7410_V13 = 165 + UC_CPU_PPC_7410_V14 = 166 + UC_CPU_PPC_7448_V10 = 167 + UC_CPU_PPC_7448_V11 = 168 + UC_CPU_PPC_7448_V20 = 169 + UC_CPU_PPC_7448_V21 = 170 + UC_CPU_PPC_7450_V10 = 171 + UC_CPU_PPC_7450_V11 = 172 + UC_CPU_PPC_7450_V12 = 173 + UC_CPU_PPC_7450_V20 = 174 + UC_CPU_PPC_7450_V21 = 175 + UC_CPU_PPC_74X1_V23 = 176 + UC_CPU_PPC_74X1_V210 = 177 + UC_CPU_PPC_74X5_V10 = 178 + UC_CPU_PPC_74X5_V21 = 179 + UC_CPU_PPC_74X5_V32 = 180 + UC_CPU_PPC_74X5_V33 = 181 + UC_CPU_PPC_74X5_V34 = 182 + UC_CPU_PPC_74X7_V10 = 183 + UC_CPU_PPC_74X7_V11 = 184 + UC_CPU_PPC_74X7_V12 = 185 + UC_CPU_PPC_74X7A_V10 = 186 + UC_CPU_PPC_74X7A_V11 = 187 + UC_CPU_PPC_74X7A_V12 = 188 + UC_CPU_PPC_IOP480 = 1 + UC_CPU_PPC_X2VP20 = 42 + UC_CPU_PPC_440GRA = 35 + UC_CPU_PPC_440EPX = 38 + UC_CPU_PPC_MPC5200_V10 = 59 + UC_CPU_PPC_MPC5200_V11 = 59 + UC_CPU_PPC_MPC5200_V12 = 59 + UC_CPU_PPC_MPC5200B_V20 = 59 + UC_CPU_PPC_MPC5200B_V21 = 59 + UC_CPU_PPC_MPC834X = 63 + UC_CPU_PPC_MPC837X = 66 + UC_CPU_PPC_E500 = 73 + UC_CPU_PPC_MPC8533_V10 = 72 + UC_CPU_PPC_MPC8533_V11 = 73 + UC_CPU_PPC_MPC8533E_V10 = 72 + UC_CPU_PPC_MPC8533E_V11 = 73 + UC_CPU_PPC_MPC8540_V10 = 67 + UC_CPU_PPC_MPC8540_V20 = 68 + UC_CPU_PPC_MPC8540_V21 = 68 + UC_CPU_PPC_MPC8541_V10 = 68 + UC_CPU_PPC_MPC8541_V11 = 68 + UC_CPU_PPC_MPC8541E_V10 = 68 + UC_CPU_PPC_MPC8541E_V11 = 68 + UC_CPU_PPC_MPC8543_V10 = 69 + UC_CPU_PPC_MPC8543_V11 = 70 + UC_CPU_PPC_MPC8543_V20 = 71 + UC_CPU_PPC_MPC8543_V21 = 72 + UC_CPU_PPC_MPC8543E_V10 = 69 + UC_CPU_PPC_MPC8543E_V11 = 70 + UC_CPU_PPC_MPC8543E_V20 = 71 + UC_CPU_PPC_MPC8543E_V21 = 72 + UC_CPU_PPC_MPC8544_V10 = 72 + UC_CPU_PPC_MPC8544_V11 = 73 + UC_CPU_PPC_MPC8544E_V11 = 73 + UC_CPU_PPC_MPC8544E_V10 = 72 + UC_CPU_PPC_MPC8545_V10 = 69 + UC_CPU_PPC_MPC8545_V20 = 71 + UC_CPU_PPC_MPC8545_V21 = 72 + UC_CPU_PPC_MPC8545E_V10 = 69 + UC_CPU_PPC_MPC8545E_V20 = 71 + UC_CPU_PPC_MPC8545E_V21 = 72 + UC_CPU_PPC_MPC8547E_V10 = 69 + UC_CPU_PPC_MPC8547E_V20 = 71 + UC_CPU_PPC_MPC8547E_V21 = 72 + UC_CPU_PPC_MPC8548_V10 = 69 + UC_CPU_PPC_MPC8548_V11 = 70 + UC_CPU_PPC_MPC8548_V20 = 71 + UC_CPU_PPC_MPC8548_V21 = 72 + UC_CPU_PPC_MPC8548E_V10 = 69 + UC_CPU_PPC_MPC8548E_V11 = 70 + UC_CPU_PPC_MPC8548E_V20 = 71 + UC_CPU_PPC_MPC8548E_V21 = 72 + UC_CPU_PPC_MPC8555_V10 = 69 + UC_CPU_PPC_MPC8555_V11 = 70 + UC_CPU_PPC_MPC8555E_V10 = 69 + UC_CPU_PPC_MPC8555E_V11 = 70 + UC_CPU_PPC_MPC8560_V10 = 69 + UC_CPU_PPC_MPC8560_V20 = 71 + UC_CPU_PPC_MPC8560_V21 = 72 + UC_CPU_PPC_MPC8567 = 73 + UC_CPU_PPC_MPC8567E = 73 + UC_CPU_PPC_MPC8568 = 73 + UC_CPU_PPC_MPC8568E = 73 + UC_CPU_PPC_MPC8572 = 74 + UC_CPU_PPC_MPC8572E = 74 + UC_CPU_PPC_MPC8610 = 78 + UC_CPU_PPC_MPC8641 = 78 + UC_CPU_PPC_MPC8641D = 78 + + UC_CPU_PPC64_620 = 0 + UC_CPU_PPC64_630 = 1 + UC_CPU_PPC64_631 = 2 + UC_CPU_PPC64_POWER4 = 3 + UC_CPU_PPC64_POWER4P = 4 + UC_CPU_PPC64_POWER5 = 5 + UC_CPU_PPC64_POWER5P_V21 = 6 + UC_CPU_PPC64_POWER6 = 7 + UC_CPU_PPC64_POWER_SERVER_MASK = 8 + UC_CPU_PPC64_POWER7_BASE = 9 + UC_CPU_PPC64_POWER7_V23 = 10 + UC_CPU_PPC64_POWER7P_BASE = 11 + UC_CPU_PPC64_POWER7P_V21 = 12 + UC_CPU_PPC64_POWER8E_BASE = 13 + UC_CPU_PPC64_POWER8E_V21 = 14 + UC_CPU_PPC64_POWER8_BASE = 15 + UC_CPU_PPC64_POWER8_V20 = 16 + UC_CPU_PPC64_POWER8NVL_BASE = 17 + UC_CPU_PPC64_POWER8NVL_V10 = 18 + UC_CPU_PPC64_POWER9_BASE = 19 + UC_CPU_PPC64_POWER9_DD1 = 20 + UC_CPU_PPC64_POWER9_DD20 = 21 + UC_CPU_PPC64_POWER10_BASE = 22 + UC_CPU_PPC64_POWER10_DD1 = 23 + UC_CPU_PPC64_970_V22 = 24 + UC_CPU_PPC64_970FX_V10 = 25 + UC_CPU_PPC64_970FX_V20 = 26 + UC_CPU_PPC64_970FX_V21 = 27 + UC_CPU_PPC64_970FX_V30 = 28 + UC_CPU_PPC64_970FX_V31 = 29 + UC_CPU_PPC64_970MP_V10 = 30 + UC_CPU_PPC64_970MP_V11 = 31 + UC_CPU_PPC64_CELL_V10 = 32 + UC_CPU_PPC64_CELL_V20 = 33 + UC_CPU_PPC64_CELL_V30 = 34 + UC_CPU_PPC64_CELL_V31 = 35 + UC_CPU_PPC64_RS64 = 36 + UC_CPU_PPC64_RS64II = 37 + UC_CPU_PPC64_RS64III = 38 + UC_CPU_PPC64_RS64IV = 39 + UC_CPU_PPC64_CELL_V32 = 35 + UC_CPU_PPC64_CELL = 35 + # PPC registers UC_PPC_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb index 2122099d..5eb5cd85 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/riscv_const.rb @@ -2,6 +2,16 @@ module UnicornEngine + UC_CPU_RISCV32_ANY = 0 + UC_CPU_RISCV32_BASE32 = 1 + UC_CPU_RISCV32_SIFIVE_E31 = 2 + UC_CPU_RISCV32_SIFIVE_U34 = 3 + + UC_CPU_RISCV64_ANY = 0 + UC_CPU_RISCV64_BASE64 = 1 + UC_CPU_RISCV64_SIFIVE_E51 = 2 + UC_CPU_RISCV64_SIFIVE_U54 = 3 + # RISCV registers UC_RISCV_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb index b5c42470..dbf3f938 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/sparc_const.rb @@ -2,6 +2,38 @@ module UnicornEngine + UC_CPU_SPARC_FUJITSU_MB86904 = 0 + UC_CPU_SPARC_FUJITSU_MB86907 = 1 + UC_CPU_SPARC_TI_MICROSPARC_I = 2 + UC_CPU_SPARC_TI_MICROSPARC_II = 3 + UC_CPU_SPARC_TI_MICROSPARC_IIEP = 4 + UC_CPU_SPARC_TI_SUPERSPARC_40 = 5 + UC_CPU_SPARC_TI_SUPERSPARC_50 = 6 + UC_CPU_SPARC_TI_SUPERSPARC_51 = 7 + UC_CPU_SPARC_TI_SUPERSPARC_60 = 8 + UC_CPU_SPARC_TI_SUPERSPARC_61 = 9 + UC_CPU_SPARC_TI_SUPERSPARC_II = 10 + UC_CPU_SPARC_LEON2 = 11 + UC_CPU_SPARC_LEON3 = 12 + + UC_CPU_SPARC64_FUJITSU = 0 + UC_CPU_SPARC64_FUJITSU_III = 1 + UC_CPU_SPARC64_FUJITSU_IV = 2 + UC_CPU_SPARC64_FUJITSU_V = 3 + UC_CPU_SPARC64_TI_ULTRASPARC_I = 4 + UC_CPU_SPARC64_TI_ULTRASPARC_II = 5 + UC_CPU_SPARC64_TI_ULTRASPARC_III = 6 + UC_CPU_SPARC64_TI_ULTRASPARC_IIE = 7 + UC_CPU_SPARC64_SUN_ULTRASPARC_III = 8 + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU = 9 + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII = 10 + UC_CPU_SPARC64_SUN_ULTRASPARC_IV = 11 + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS = 12 + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS = 13 + UC_CPU_SPARC64_SUN_ULTRASPARC_T1 = 14 + UC_CPU_SPARC64_SUN_ULTRASPARC_T2 = 15 + UC_CPU_SPARC64_NEC_ULTRASPARC_I = 16 + # SPARC registers UC_SPARC_REG_INVALID = 0 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb index a09f3e82..b179d3eb 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/unicorn_const.rb @@ -107,6 +107,22 @@ module UnicornEngine UC_QUERY_ARCH = 3 UC_QUERY_TIMEOUT = 4 + UC_CTL_IO_NONE = 0 + UC_CTL_IO_WRITE = 1 + UC_CTL_IO_READ = 2 + UC_CTL_IO_READ_WRITE = 3 + + UC_CTL_UC_MODE = 0 + UC_CTL_UC_PAGE_SIZE = 1 + UC_CTL_UC_ARCH = 2 + UC_CTL_UC_TIMEOUT = 3 + UC_CTL_UC_EXITS_CNT = 4 + UC_CTL_UC_EXITS = 5 + UC_CTL_CPU_MODEL = 6 + UC_CTL_TB_EDGE = 7 + UC_CTL_TB_REQUEST_CACHE = 8 + UC_CTL_TB_REMOVE_CACHE = 9 + UC_PROT_NONE = 0 UC_PROT_READ = 1 UC_PROT_WRITE = 2 diff --git a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb index 49ef2549..6fae393c 100644 --- a/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb +++ b/bindings/ruby/unicorn_gem/lib/unicorn_engine/x86_const.rb @@ -2,6 +2,45 @@ module UnicornEngine + UC_CPU_X86_QEMU64 = 0 + UC_CPU_X86_PHENOM = 1 + UC_CPU_X86_CORE2DUO = 2 + UC_CPU_X86_KVM64 = 3 + UC_CPU_X86_QEMU32 = 4 + UC_CPU_X86_KVM32 = 5 + UC_CPU_X86_COREDUO = 6 + UC_CPU_X86_486 = 7 + UC_CPU_X86_PENTIUM = 8 + UC_CPU_X86_PENTIUM2 = 9 + UC_CPU_X86_PENTIUM3 = 10 + UC_CPU_X86_ATHLON = 11 + UC_CPU_X86_N270 = 12 + UC_CPU_X86_CONROE = 13 + UC_CPU_X86_PENRYN = 14 + UC_CPU_X86_NEHALEM = 15 + UC_CPU_X86_WESTMERE = 16 + UC_CPU_X86_SANDYBRIDGE = 17 + UC_CPU_X86_IVYBRIDGE = 18 + UC_CPU_X86_HASWELL = 19 + UC_CPU_X86_BROADWELL = 20 + UC_CPU_X86_SKYLAKE_CLIENT = 21 + UC_CPU_X86_SKYLAKE_SERVER = 22 + UC_CPU_X86_CASCADELAKE_SERVER = 23 + UC_CPU_X86_COOPERLAKE = 24 + UC_CPU_X86_ICELAKE_CLIENT = 25 + UC_CPU_X86_ICELAKE_SERVER = 26 + UC_CPU_X86_DENVERTON = 27 + UC_CPU_X86_SNOWRIDGE = 28 + UC_CPU_X86_KNIGHTSMILL = 29 + UC_CPU_X86_OPTERON_G1 = 30 + UC_CPU_X86_OPTERON_G2 = 31 + UC_CPU_X86_OPTERON_G3 = 32 + UC_CPU_X86_OPTERON_G4 = 33 + UC_CPU_X86_OPTERON_G5 = 34 + UC_CPU_X86_EPYC = 35 + UC_CPU_X86_DHYANA = 36 + UC_CPU_X86_EPYC_ROME = 37 + # X86 registers UC_X86_REG_INVALID = 0 diff --git a/include/unicorn/arm.h b/include/unicorn/arm.h index 5bd72d63..d9cf4949 100644 --- a/include/unicorn/arm.h +++ b/include/unicorn/arm.h @@ -15,6 +15,42 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_arm { + UC_CPU_ARM_926 = 0, + UC_CPU_ARM_946, + UC_CPU_ARM_1026, + UC_CPU_ARM_1136_R2, + UC_CPU_ARM_1136, + UC_CPU_ARM_1176, + UC_CPU_ARM_11MPCORE, + UC_CPU_ARM_CORTEX_M0, + UC_CPU_ARM_CORTEX_M3, + UC_CPU_ARM_CORTEX_M4, + UC_CPU_ARM_CORTEX_M7, + UC_CPU_ARM_CORTEX_M33, + UC_CPU_ARM_CORTEX_R5, + UC_CPU_ARM_CORTEX_R5F, + UC_CPU_ARM_CORTEX_A8, + UC_CPU_ARM_CORTEX_A9, + UC_CPU_ARM_CORTEX_A7, + UC_CPU_ARM_CORTEX_A15, + UC_CPU_ARM_TI925T, + UC_CPU_ARM_SA1100, + UC_CPU_ARM_SA1110, + UC_CPU_ARM_PXA250, + UC_CPU_ARM_PXA255, + UC_CPU_ARM_PXA260, + UC_CPU_ARM_PXA261, + UC_CPU_ARM_PXA262, + UC_CPU_ARM_PXA270A0, + UC_CPU_ARM_PXA270A1, + UC_CPU_ARM_PXA270B0, + UC_CPU_ARM_PXA270B1, + UC_CPU_ARM_PXA270C0, + UC_CPU_ARM_PXA270C5, + UC_CPU_ARM_MAX +} uc_cpu_arm; + //> ARM registers typedef enum uc_arm_reg { UC_ARM_REG_INVALID = 0, diff --git a/include/unicorn/arm64.h b/include/unicorn/arm64.h index 256b2a50..5cbd6229 100644 --- a/include/unicorn/arm64.h +++ b/include/unicorn/arm64.h @@ -15,6 +15,13 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_aarch64 { + UC_CPU_AARCH64_A57 = 0, + UC_CPU_AARCH64_A53, + UC_CPU_AARCH64_A72, + UC_CPU_AARCH64_MAX +} uc_cpu_aarch64; + //> ARM64 registers typedef enum uc_arm64_reg { UC_ARM64_REG_INVALID = 0, diff --git a/include/unicorn/m68k.h b/include/unicorn/m68k.h index 01cb0af1..27ea64df 100644 --- a/include/unicorn/m68k.h +++ b/include/unicorn/m68k.h @@ -15,6 +15,18 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_m68k { + UC_CPU_M5206_CPU = 0, + UC_CPU_M68000_CPU, + UC_CPU_M68020_CPU, + UC_CPU_M68030_CPU, + UC_CPU_M68040_CPU, + UC_CPU_M68060_CPU, + UC_CPU_M5208_CPU, + UC_CPU_CFV4E_CPU, + UC_CPU_ANY_CPU, +} uc_cpu_m68k; + //> M68K registers typedef enum uc_m68k_reg { UC_M68K_REG_INVALID = 0, diff --git a/include/unicorn/mips.h b/include/unicorn/mips.h index b8d203f9..977ee534 100644 --- a/include/unicorn/mips.h +++ b/include/unicorn/mips.h @@ -19,6 +19,38 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_mips { + UC_CPU_MIPS_4KC = 0, + UC_CPU_MIPS_4KM, + UC_CPU_MIPS_4KECR1, + UC_CPU_MIPS_4KEMR1, + UC_CPU_MIPS_4KEC, + UC_CPU_MIPS_4KEM, + UC_CPU_MIPS_24KC, + UC_CPU_MIPS_24KEC, + UC_CPU_MIPS_24KF, + UC_CPU_MIPS_34KF, + UC_CPU_MIPS_74KF, + UC_CPU_MIPS_M14K, + UC_CPU_MIPS_M14KC, + UC_CPU_MIPS_P5600, + UC_CPU_MIPS_MIPS32R6_GENERIC, + UC_CPU_MIPS_I7200, + UC_CPU_MIPS_R4000, + UC_CPU_MIPS_VR5432, + UC_CPU_MIPS_5KC, + UC_CPU_MIPS_5KF, + UC_CPU_MIPS_20KC, + UC_CPU_MIPS_MIPS64R2_GENERIC, + UC_CPU_MIPS_5KEC, + UC_CPU_MIPS_5KEF, + UC_CPU_MIPS_I6400, + UC_CPU_MIPS_I6500, + UC_CPU_MIPS_LOONGSON_2E, + UC_CPU_MIPS_LOONGSON_2F, + UC_CPU_MIPS_MIPS64DSPR2 +} uc_cpu_mips; + //> MIPS registers typedef enum UC_MIPS_REG { UC_MIPS_REG_INVALID = 0, diff --git a/include/unicorn/ppc.h b/include/unicorn/ppc.h index a6181834..9d09a990 100644 --- a/include/unicorn/ppc.h +++ b/include/unicorn/ppc.h @@ -15,6 +15,311 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_ppc { + UC_CPU_PPC_401A1 = 0, + UC_CPU_PPC_401B2, + UC_CPU_PPC_401C2, + UC_CPU_PPC_401D2, + UC_CPU_PPC_401E2, + UC_CPU_PPC_401F2, + UC_CPU_PPC_401G2, + UC_CPU_PPC_COBRA, + UC_CPU_PPC_403GA, + UC_CPU_PPC_403GB, + UC_CPU_PPC_403GC, + UC_CPU_PPC_403GCX, + UC_CPU_PPC_405D2, + UC_CPU_PPC_405D4, + UC_CPU_PPC_405CRA, + UC_CPU_PPC_405CRB, + UC_CPU_PPC_405CRC, + UC_CPU_PPC_405EP, + UC_CPU_PPC_405EZ, + UC_CPU_PPC_405GPA, + UC_CPU_PPC_405GPB, + UC_CPU_PPC_405GPC, + UC_CPU_PPC_405GPD, + UC_CPU_PPC_405GPR, + UC_CPU_PPC_405LP, + UC_CPU_PPC_NPE405H, + UC_CPU_PPC_NPE405H2, + UC_CPU_PPC_NPE405L, + UC_CPU_PPC_NPE4GS3, + UC_CPU_PPC_STB03, + UC_CPU_PPC_STB04, + UC_CPU_PPC_STB25, + UC_CPU_PPC_X2VP4, + UC_CPU_PPC_440_XILINX, + UC_CPU_PPC_440EPA, + UC_CPU_PPC_440EPB, + UC_CPU_PPC_440GPB, + UC_CPU_PPC_440GPC, + UC_CPU_PPC_440GRX, + UC_CPU_PPC_440GXA, + UC_CPU_PPC_440GXB, + UC_CPU_PPC_440GXC, + UC_CPU_PPC_440GXF, + UC_CPU_PPC_440SP, + UC_CPU_PPC_440SP2, + UC_CPU_PPC_440SPE, + UC_CPU_PPC_460EXB, + UC_CPU_PPC_MPC5XX, + UC_CPU_PPC_MPC8XX, + UC_CPU_PPC_G2, + UC_CPU_PPC_G2H4, + UC_CPU_PPC_G2GP, + UC_CPU_PPC_G2LS, + UC_CPU_PPC_MPC603, + UC_CPU_PPC_G2_HIP3, + UC_CPU_PPC_G2_HIP4, + UC_CPU_PPC_G2LE, + UC_CPU_PPC_G2LEGP, + UC_CPU_PPC_G2LELS, + UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_G2LEGP3, + UC_CPU_PPC_E200Z5, + UC_CPU_PPC_E200Z6, + UC_CPU_PPC_E300C1, + UC_CPU_PPC_E300C2, + UC_CPU_PPC_E300C3, + UC_CPU_PPC_E300C4, + UC_CPU_PPC_E500V1_V10, + UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_E500MC, + UC_CPU_PPC_E5500, + UC_CPU_PPC_E6500, + UC_CPU_PPC_E600, + UC_CPU_PPC_601_V0, + UC_CPU_PPC_601_V1, + UC_CPU_PPC_601_V2, + UC_CPU_PPC_602, + UC_CPU_PPC_603, + UC_CPU_PPC_603E_V11, + UC_CPU_PPC_603E_V12, + UC_CPU_PPC_603E_V13, + UC_CPU_PPC_603E_V14, + UC_CPU_PPC_603E_V22, + UC_CPU_PPC_603E_V3, + UC_CPU_PPC_603E_V4, + UC_CPU_PPC_603E_V41, + UC_CPU_PPC_603E7T, + UC_CPU_PPC_603E7V, + UC_CPU_PPC_603E7V1, + UC_CPU_PPC_603E7V2, + UC_CPU_PPC_603E7, + UC_CPU_PPC_603P, + UC_CPU_PPC_604, + UC_CPU_PPC_604E_V10, + UC_CPU_PPC_604E_V22, + UC_CPU_PPC_604E_V24, + UC_CPU_PPC_604R, + UC_CPU_PPC_7X0_V10, + UC_CPU_PPC_7X0_V20, + UC_CPU_PPC_7X0_V21, + UC_CPU_PPC_7X0_V22, + UC_CPU_PPC_7X0_V30, + UC_CPU_PPC_7X0_V31, + UC_CPU_PPC_740E, + UC_CPU_PPC_750E, + UC_CPU_PPC_7X0P, + UC_CPU_PPC_750CL_V10, + UC_CPU_PPC_750CL_V20, + UC_CPU_PPC_750CX_V10, + UC_CPU_PPC_750CX_V20, + UC_CPU_PPC_750CX_V21, + UC_CPU_PPC_750CX_V22, + UC_CPU_PPC_750CXE_V21, + UC_CPU_PPC_750CXE_V22, + UC_CPU_PPC_750CXE_V23, + UC_CPU_PPC_750CXE_V24, + UC_CPU_PPC_750CXE_V24B, + UC_CPU_PPC_750CXE_V30, + UC_CPU_PPC_750CXE_V31, + UC_CPU_PPC_750CXE_V31B, + UC_CPU_PPC_750CXR, + UC_CPU_PPC_750FL, + UC_CPU_PPC_750FX_V10, + UC_CPU_PPC_750FX_V20, + UC_CPU_PPC_750FX_V21, + UC_CPU_PPC_750FX_V22, + UC_CPU_PPC_750FX_V23, + UC_CPU_PPC_750GL, + UC_CPU_PPC_750GX_V10, + UC_CPU_PPC_750GX_V11, + UC_CPU_PPC_750GX_V12, + UC_CPU_PPC_750L_V20, + UC_CPU_PPC_750L_V21, + UC_CPU_PPC_750L_V22, + UC_CPU_PPC_750L_V30, + UC_CPU_PPC_750L_V32, + UC_CPU_PPC_7X5_V10, + UC_CPU_PPC_7X5_V11, + UC_CPU_PPC_7X5_V20, + UC_CPU_PPC_7X5_V21, + UC_CPU_PPC_7X5_V22, + UC_CPU_PPC_7X5_V23, + UC_CPU_PPC_7X5_V24, + UC_CPU_PPC_7X5_V25, + UC_CPU_PPC_7X5_V26, + UC_CPU_PPC_7X5_V27, + UC_CPU_PPC_7X5_V28, + UC_CPU_PPC_7400_V10, + UC_CPU_PPC_7400_V11, + UC_CPU_PPC_7400_V20, + UC_CPU_PPC_7400_V21, + UC_CPU_PPC_7400_V22, + UC_CPU_PPC_7400_V26, + UC_CPU_PPC_7400_V27, + UC_CPU_PPC_7400_V28, + UC_CPU_PPC_7400_V29, + UC_CPU_PPC_7410_V10, + UC_CPU_PPC_7410_V11, + UC_CPU_PPC_7410_V12, + UC_CPU_PPC_7410_V13, + UC_CPU_PPC_7410_V14, + UC_CPU_PPC_7448_V10, + UC_CPU_PPC_7448_V11, + UC_CPU_PPC_7448_V20, + UC_CPU_PPC_7448_V21, + UC_CPU_PPC_7450_V10, + UC_CPU_PPC_7450_V11, + UC_CPU_PPC_7450_V12, + UC_CPU_PPC_7450_V20, + UC_CPU_PPC_7450_V21, + UC_CPU_PPC_74X1_V23, + UC_CPU_PPC_74X1_V210, + UC_CPU_PPC_74X5_V10, + UC_CPU_PPC_74X5_V21, + UC_CPU_PPC_74X5_V32, + UC_CPU_PPC_74X5_V33, + UC_CPU_PPC_74X5_V34, + UC_CPU_PPC_74X7_V10, + UC_CPU_PPC_74X7_V11, + UC_CPU_PPC_74X7_V12, + UC_CPU_PPC_74X7A_V10, + UC_CPU_PPC_74X7A_V11, + UC_CPU_PPC_74X7A_V12, + UC_CPU_PPC_IOP480 = UC_CPU_PPC_401B2, + UC_CPU_PPC_X2VP20 = UC_CPU_PPC_440GXF, + UC_CPU_PPC_440GRA = UC_CPU_PPC_440EPB, + UC_CPU_PPC_440EPX = UC_CPU_PPC_440GRX, + UC_CPU_PPC_MPC5200_V10 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200_V11 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200_V12 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200B_V20 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC5200B_V21 = UC_CPU_PPC_G2LEGP1, + UC_CPU_PPC_MPC834X = UC_CPU_PPC_E300C1, + UC_CPU_PPC_MPC837X = UC_CPU_PPC_E300C4, + UC_CPU_PPC_E500 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8533_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8533_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8533E_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8533E_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8540_V10 = UC_CPU_PPC_E500V1_V10, + UC_CPU_PPC_MPC8540_V20 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8540_V21 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541_V10 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541_V11 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541E_V10 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8541E_V11 = UC_CPU_PPC_E500V1_V20, + UC_CPU_PPC_MPC8543_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8543_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8543_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8543_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8543E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8543E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8543E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8543E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8544_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8544_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8544E_V11 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8544E_V10 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8545_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8545_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8545_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8545E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8545E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8545E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8547E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8547E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8547E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8548_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8548_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8548_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8548_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8548E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8548E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8548E_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8548E_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8555_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8555_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8555E_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8555E_V11 = UC_CPU_PPC_E500V2_V11, + UC_CPU_PPC_MPC8560_V10 = UC_CPU_PPC_E500V2_V10, + UC_CPU_PPC_MPC8560_V20 = UC_CPU_PPC_E500V2_V20, + UC_CPU_PPC_MPC8560_V21 = UC_CPU_PPC_E500V2_V21, + UC_CPU_PPC_MPC8567 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8567E = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8568 = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8568E = UC_CPU_PPC_E500V2_V22, + UC_CPU_PPC_MPC8572 = UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_MPC8572E = UC_CPU_PPC_E500V2_V30, + UC_CPU_PPC_MPC8610 = UC_CPU_PPC_E600, + UC_CPU_PPC_MPC8641 = UC_CPU_PPC_E600, + UC_CPU_PPC_MPC8641D = UC_CPU_PPC_E600, +} uc_cpu_ppc; + +typedef enum uc_cpu_ppc64 { + UC_CPU_PPC64_620 = 0, + UC_CPU_PPC64_630, + UC_CPU_PPC64_631, + UC_CPU_PPC64_POWER4, + UC_CPU_PPC64_POWER4P, + UC_CPU_PPC64_POWER5, + UC_CPU_PPC64_POWER5P_V21, + UC_CPU_PPC64_POWER6, + UC_CPU_PPC64_POWER_SERVER_MASK, + UC_CPU_PPC64_POWER7_BASE, + UC_CPU_PPC64_POWER7_V23, + UC_CPU_PPC64_POWER7P_BASE, + UC_CPU_PPC64_POWER7P_V21, + UC_CPU_PPC64_POWER8E_BASE, + UC_CPU_PPC64_POWER8E_V21, + UC_CPU_PPC64_POWER8_BASE, + UC_CPU_PPC64_POWER8_V20, + UC_CPU_PPC64_POWER8NVL_BASE, + UC_CPU_PPC64_POWER8NVL_V10, + UC_CPU_PPC64_POWER9_BASE, + UC_CPU_PPC64_POWER9_DD1, + UC_CPU_PPC64_POWER9_DD20, + UC_CPU_PPC64_POWER10_BASE, + UC_CPU_PPC64_POWER10_DD1, + UC_CPU_PPC64_970_V22, + UC_CPU_PPC64_970FX_V10, + UC_CPU_PPC64_970FX_V20, + UC_CPU_PPC64_970FX_V21, + UC_CPU_PPC64_970FX_V30, + UC_CPU_PPC64_970FX_V31, + UC_CPU_PPC64_970MP_V10, + UC_CPU_PPC64_970MP_V11, + UC_CPU_PPC64_CELL_V10, + UC_CPU_PPC64_CELL_V20, + UC_CPU_PPC64_CELL_V30, + UC_CPU_PPC64_CELL_V31, + UC_CPU_PPC64_RS64, + UC_CPU_PPC64_RS64II, + UC_CPU_PPC64_RS64III, + UC_CPU_PPC64_RS64IV, + UC_CPU_PPC64_CELL_V32 = UC_CPU_PPC64_CELL_V31, + UC_CPU_PPC64_CELL = UC_CPU_PPC64_CELL_V32, +} uc_cpu_ppc64; + //> PPC registers typedef enum uc_ppc_reg { UC_PPC_REG_INVALID = 0, diff --git a/include/unicorn/riscv.h b/include/unicorn/riscv.h index a058ebab..be821d77 100644 --- a/include/unicorn/riscv.h +++ b/include/unicorn/riscv.h @@ -15,6 +15,20 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_riscv32 { + UC_CPU_RISCV32_ANY = 0, + UC_CPU_RISCV32_BASE32, + UC_CPU_RISCV32_SIFIVE_E31, + UC_CPU_RISCV32_SIFIVE_U34, +} uc_cpu_riscv32; + +typedef enum uc_cpu_riscv64 { + UC_CPU_RISCV64_ANY = 0, + UC_CPU_RISCV64_BASE64, + UC_CPU_RISCV64_SIFIVE_E51, + UC_CPU_RISCV64_SIFIVE_U54, +} uc_cpu_riscv64; + //> RISCV registers typedef enum uc_riscv_reg { UC_RISCV_REG_INVALID = 0, diff --git a/include/unicorn/sparc.h b/include/unicorn/sparc.h index f9ec729d..1bed80ae 100644 --- a/include/unicorn/sparc.h +++ b/include/unicorn/sparc.h @@ -19,6 +19,42 @@ extern "C" { #pragma warning(disable : 4201) #endif +typedef enum uc_cpu_sparc { + UC_CPU_SPARC_FUJITSU_MB86904 = 0, + UC_CPU_SPARC_FUJITSU_MB86907, + UC_CPU_SPARC_TI_MICROSPARC_I, + UC_CPU_SPARC_TI_MICROSPARC_II, + UC_CPU_SPARC_TI_MICROSPARC_IIEP, + UC_CPU_SPARC_TI_SUPERSPARC_40, + UC_CPU_SPARC_TI_SUPERSPARC_50, + UC_CPU_SPARC_TI_SUPERSPARC_51, + UC_CPU_SPARC_TI_SUPERSPARC_60, + UC_CPU_SPARC_TI_SUPERSPARC_61, + UC_CPU_SPARC_TI_SUPERSPARC_II, + UC_CPU_SPARC_LEON2, + UC_CPU_SPARC_LEON3 +} uc_cpu_sparc; + +typedef enum uc_cpu_sparc64 { + UC_CPU_SPARC64_FUJITSU = 0, + UC_CPU_SPARC64_FUJITSU_III, + UC_CPU_SPARC64_FUJITSU_IV, + UC_CPU_SPARC64_FUJITSU_V, + UC_CPU_SPARC64_TI_ULTRASPARC_I, + UC_CPU_SPARC64_TI_ULTRASPARC_II, + UC_CPU_SPARC64_TI_ULTRASPARC_III, + UC_CPU_SPARC64_TI_ULTRASPARC_IIE, + UC_CPU_SPARC64_SUN_ULTRASPARC_III, + UC_CPU_SPARC64_SUN_ULTRASPARC_III_CU, + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII, + UC_CPU_SPARC64_SUN_ULTRASPARC_IV, + UC_CPU_SPARC64_SUN_ULTRASPARC_IV_PLUS, + UC_CPU_SPARC64_SUN_ULTRASPARC_IIII_PLUS, + UC_CPU_SPARC64_SUN_ULTRASPARC_T1, + UC_CPU_SPARC64_SUN_ULTRASPARC_T2, + UC_CPU_SPARC64_NEC_ULTRASPARC_I, +} uc_cpu_sparc64; + //> SPARC registers typedef enum uc_sparc_reg { UC_SPARC_REG_INVALID = 0, diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 0d217bd4..51dc212c 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -391,6 +391,108 @@ typedef enum uc_query_type { // result = True) } uc_query_type; +// The implementation of uc_ctl is like what Linux ioctl does but slightly +// different. +// +// A uc_control_type passed to uc_ctl is constructed as: +// +// R/W NR Reserved Type +// [ ] [ ] [ ] [ ] +// 31 30 29 26 25 16 15 0 +// +// @R/W: Whether the operation is a read or write access. +// @NR: Number of arguments. +// @Reserved: Should be zero, reserved for future extension. +// @Type: Taken from uc_control_type enum. +// +// See the helper macros below. + +// No input and output arguments. +#define UC_CTL_IO_NONE (0) +// The arguments are used for input. +#define UC_CTL_IO_WRITE (1) +// The arguments are used for ouput. +#define UC_CTL_IO_READ (2) +// The arguments include both input and output arugments. +#define UC_CTL_IO_READ_WRITE (UC_CTL_IO_WRITE | UC_CTL_IO_READ) + +#define UC_CTL(type, nr, rw) ((type) | ((nr) << 26) | ((rw) << 30)) +#define UC_CTL_NONE(type, nr) UC_CTL(type, nr, UC_CTL_IO_NONE) +#define UC_CTL_READ(type, nr) UC_CTL(type, nr, UC_CTL_IO_READ) +#define UC_CTL_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_WRITE) +#define UC_CTL_READ_WRITE(type, nr) UC_CTL(type, nr, UC_CTL_IO_READ_WRITE) + +// All type of controls for uc_ctl API. +// The controls are organized in a tree level. +// If a control don't have `Set` or `Get` for @args, it means it's r/o or w/o. +typedef enum uc_control_type { + // Current mode. + // Read: @args = (*int) + UC_CTL_UC_MODE = 0, + // Curent page size. + // Write: @args = (int) + // Read: @args = (*int) + UC_CTL_UC_PAGE_SIZE, + // Current arch. + // Read: @args = (*int) + UC_CTL_UC_ARCH, + // Current timeout. + // Read: @args = (*uint64_t) + UC_CTL_UC_TIMEOUT, + // The number of current exists. + // Read: @args = (*size_t) + UC_CTL_UC_EXITS_CNT, + // Current exists. + // Write: @args = (*uint64_t exists, size_t len) + // @len = UC_CTL_UC_EXITS_CNT + // Read: @args = (*uint64_t exists, size_t len) + // @len = UC_CTL_UC_EXITS_CNT + UC_CTL_UC_EXITS, + // Set the cpu model of uc. + // Note this option can only be set before any Unicorn + // API is called except for uc_open. + // Write: @args = (int) + // Read: @args = (int) + UC_CTL_CPU_MODEL, + // Request the edge of two TBs. + // Read: @args = (uint64_t, uint64_t, *uint64_t) + UC_CTL_TB_EDGE, + // Request a tb cache at a specific address + // Read: @args = (uint64_t) + UC_CTL_TB_REQUEST_CACHE, + // Remove a tb cache at a specific address + // Read: @args = (uint64_t) + UC_CTL_TB_REMOVE_CACHE + +} uc_control_type; + +#define uc_ctl_get_mode(uc, mode) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_MODE, 1), (mode)) +#define uc_ctl_get_page_size(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1, (ptr)) +#define uc_ctl_set_page_size(uc, page_size) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_PAGE_SIZE, 1), (page_size)) +#define uc_ctl_get_arch(uc, arch) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_ARCH, 1), (arch)) +#define uc_ctl_get_timeout(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_TIMEOUT, 1), (ptr)) +#define uc_ctl_get_exists_cnt(uc, ptr) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS_CNT, 1), (ptr)) +#define uc_ctl_get_exists(uc, buffer, len) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS, 2), (buffer), (len)) +#define uc_ctl_set_exists(uc, buffer, len) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_EXITS, 2), (buffer), (len)) +#define uc_ctl_get_cpu_model(uc, model) \ + uc_ctl(uc, UC_CTL_READ(UC_CTL_CPU_MODEL, 1), (model)) +#define uc_ctl_set_cpu_model(uc, model) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model)) +#define uc_ctl_remove_cache(uc, address) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 1), (address)) +#define uc_ctl_request_cache(uc, address) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REQUEST_CACHE, 1), (address)) +#define uc_ctl_get_edge(uc, addr1, addr2, ptr) \ + uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_EDGE, 3), (addr1), (addr2), (ptr)) + // Opaque storage for CPU context, used with uc_context_*() struct uc_context; typedef struct uc_context uc_context; @@ -467,6 +569,20 @@ uc_err uc_close(uc_engine *uc); UNICORN_EXPORT uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result); +/* + Control internal states of engine. + + Also see uc_ctl_* macro helpers for easy use. + + @uc: handle returned by uc_open() + @option: control type. + @args: See uc_control_type for details about variadic arguments. + + @return: error code of uc_err enum type (UC_ERR_*, see above) +*/ +UNICORN_EXPORT +uc_err uc_ctl(uc_engine *uc, uc_control_type option, ...); + /* 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/include/unicorn/x86.h b/include/unicorn/x86.h index 1f9b740e..f91ce057 100644 --- a/include/unicorn/x86.h +++ b/include/unicorn/x86.h @@ -13,6 +13,47 @@ extern "C" { #include "platform.h" +typedef enum uc_cpu_x86 { + UC_CPU_X86_QEMU64 = 0, + UC_CPU_X86_PHENOM, + UC_CPU_X86_CORE2DUO, + UC_CPU_X86_KVM64, + UC_CPU_X86_QEMU32, + UC_CPU_X86_KVM32, + UC_CPU_X86_COREDUO, + UC_CPU_X86_486, + UC_CPU_X86_PENTIUM, + UC_CPU_X86_PENTIUM2, + UC_CPU_X86_PENTIUM3, + UC_CPU_X86_ATHLON, + UC_CPU_X86_N270, + UC_CPU_X86_CONROE, + UC_CPU_X86_PENRYN, + UC_CPU_X86_NEHALEM, + UC_CPU_X86_WESTMERE, + UC_CPU_X86_SANDYBRIDGE, + UC_CPU_X86_IVYBRIDGE, + UC_CPU_X86_HASWELL, + UC_CPU_X86_BROADWELL, + UC_CPU_X86_SKYLAKE_CLIENT, + UC_CPU_X86_SKYLAKE_SERVER, + UC_CPU_X86_CASCADELAKE_SERVER, + UC_CPU_X86_COOPERLAKE, + UC_CPU_X86_ICELAKE_CLIENT, + UC_CPU_X86_ICELAKE_SERVER, + UC_CPU_X86_DENVERTON, + UC_CPU_X86_SNOWRIDGE, + UC_CPU_X86_KNIGHTSMILL, + UC_CPU_X86_OPTERON_G1, + UC_CPU_X86_OPTERON_G2, + UC_CPU_X86_OPTERON_G3, + UC_CPU_X86_OPTERON_G4, + UC_CPU_X86_OPTERON_G5, + UC_CPU_X86_EPYC, + UC_CPU_X86_DHYANA, + UC_CPU_X86_EPYC_ROME +} uc_cpu_x86; + // Memory-Management Register for instructions IDTR, GDTR, LDTR, TR. // Borrow from SegmentCache in qemu/target-i386/cpu.h typedef struct uc_x86_mmr { diff --git a/uc.c b/uc.c index 07ae921f..ec0b7d5f 100644 --- a/uc.c +++ b/uc.c @@ -1519,6 +1519,12 @@ uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) return UC_ERR_OK; } +UNICORN_EXPORT +uc_err uc_ctl(uc_engine *uc, uc_control_type option, ...) +{ + return UC_ERR_ARG; +} + UNICORN_EXPORT uc_err uc_context_alloc(uc_engine *uc, uc_context **context) { From 47113d5a836518cb1d95e43c8947bba29e241299 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 31 Oct 2021 10:42:07 +0100 Subject: [PATCH 22/40] Format --- samples/sample_arm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/sample_arm64.c b/samples/sample_arm64.c index 16db549f..ba09b77a 100644 --- a/samples/sample_arm64.c +++ b/samples/sample_arm64.c @@ -11,7 +11,7 @@ "\xab\x05\x00\xb8\xaf\x05\x40\x38" // str w11, [x13], #0; ldrb w15, [x13], // #0 //#define ARM64_CODE_EB "\xb8\x00\x05\xab\x38\x40\x05\xaf" // str w11, [x13]; -//ldrb w15, [x13] +// ldrb w15, [x13] #define ARM64_CODE_EB ARM64_CODE // memory address where emulation starts From 8e6f7e4fbabaaebd88c7715080bce1df79c0af26 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 31 Oct 2021 15:56:58 +0100 Subject: [PATCH 23/40] Add a regression test --- tests/unit/test_x86.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index ab9eca6f..abb37b19 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -629,6 +629,36 @@ static void test_x86_hook_cpuid() OK(uc_close(uc)); } +// This is a regression bug. +static void test_x86_clear_tb_cache() { + uc_engine *uc; + char code[] = + "\x41\x4a"; // INC ecx; DEC edx; + int r_ecx = 0x1234; + int r_edx = 0x7890; + uint64_t code_start = 0x1240; // Choose this address by design + uint64_t code_len = 0x1000; + + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); + OK(uc_mem_map(uc, code_start & (1<<12), code_len, UC_PROT_ALL)); + OK(uc_mem_write(uc, code_start, code, sizeof(code))); + OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); + OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); + + OK(uc_emu_start(uc, code_start, code_start + 1, 0, 0)); + + // If tb cache is not cleared, edx would be still 0x7890 + OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); + + OK(uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx)); + OK(uc_reg_read(uc, UC_X86_REG_EDX, &r_edx)); + + TEST_CHECK(r_ecx == 0x1236); + TEST_CHECK(r_edx == 0x788f); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_x86_in", test_x86_in}, {"test_x86_out", test_x86_out}, {"test_x86_mem_hook_all", test_x86_mem_hook_all}, @@ -650,4 +680,5 @@ TEST_LIST = {{"test_x86_in", test_x86_in}, {"test_x86_mmio_uc_mem_rw", test_x86_mmio_uc_mem_rw}, {"test_x86_sysenter", test_x86_sysenter}, {"test_x86_hook_cpuid", test_x86_hook_cpuid}, + {"test_x86_clear_tb_cache", test_x86_clear_tb_cache}, {NULL, NULL}}; \ No newline at end of file From 4bcf1c4a7c45b9ae397468984d37042bdf11d2b6 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 31 Oct 2021 19:43:56 +0100 Subject: [PATCH 24/40] Flush TB at exit with a better approach instead of flushing tlb in uc1 --- qemu/aarch64.h | 1 + qemu/aarch64eb.h | 1 + qemu/accel/tcg/translate-all.h | 1 + qemu/arm.h | 1 + qemu/armeb.h | 1 + qemu/m68k.h | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/ppc.h | 1 + qemu/ppc64.h | 1 + qemu/riscv32.h | 1 + qemu/riscv64.h | 1 + qemu/softmmu/cpus.c | 15 ++++++++++----- qemu/sparc.h | 1 + qemu/sparc64.h | 1 + qemu/x86_64.h | 1 + symbols.sh | 1 + tests/unit/test_x86.c | 12 ++++++------ 20 files changed, 34 insertions(+), 11 deletions(-) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index 75d71514..1ef7fd53 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64 #define use_idiv_instructions use_idiv_instructions_aarch64 #define arm_arch arm_arch_aarch64 #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index ee750153..25c3c8a2 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _aarch64eb #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_aarch64eb #define use_idiv_instructions use_idiv_instructions_aarch64eb #define arm_arch arm_arch_aarch64eb #define tb_target_set_jmp_target tb_target_set_jmp_target_aarch64eb diff --git a/qemu/accel/tcg/translate-all.h b/qemu/accel/tcg/translate-all.h index 71be1d41..30ce55d1 100644 --- a/qemu/accel/tcg/translate-all.h +++ b/qemu/accel/tcg/translate-all.h @@ -30,6 +30,7 @@ void tb_invalidate_phys_page_fast(struct uc_struct *uc, struct page_collection * tb_page_addr_t start, int len, uintptr_t retaddr); void tb_invalidate_phys_page_range(struct uc_struct *uc, tb_page_addr_t start, tb_page_addr_t end); +void tb_invalidate_phys_range(struct uc_struct *uc, ram_addr_t start, ram_addr_t end); void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr); #endif /* TRANSLATE_ALL_H */ diff --git a/qemu/arm.h b/qemu/arm.h index d3cc372d..545a9ca6 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _arm #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_arm #define use_idiv_instructions use_idiv_instructions_arm #define arm_arch arm_arch_arm #define tb_target_set_jmp_target tb_target_set_jmp_target_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 0a51a80d..988dab96 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _armeb #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_armeb #define use_idiv_instructions use_idiv_instructions_armeb #define arm_arch arm_arch_armeb #define tb_target_set_jmp_target tb_target_set_jmp_target_armeb diff --git a/qemu/m68k.h b/qemu/m68k.h index cb3d430b..81472490 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _m68k #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_m68k #define use_idiv_instructions use_idiv_instructions_m68k #define arm_arch arm_arch_m68k #define tb_target_set_jmp_target tb_target_set_jmp_target_m68k diff --git a/qemu/mips.h b/qemu/mips.h index a2b78379..cd1cccb4 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips #define use_idiv_instructions use_idiv_instructions_mips #define arm_arch arm_arch_mips #define tb_target_set_jmp_target tb_target_set_jmp_target_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 9faef36b..e56c5f1f 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64 #define use_idiv_instructions use_idiv_instructions_mips64 #define arm_arch arm_arch_mips64 #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 6f748b36..8e3bdbfe 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mips64el #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mips64el #define use_idiv_instructions use_idiv_instructions_mips64el #define arm_arch arm_arch_mips64el #define tb_target_set_jmp_target tb_target_set_jmp_target_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index a4831183..1c1660f3 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _mipsel #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_mipsel #define use_idiv_instructions use_idiv_instructions_mipsel #define arm_arch arm_arch_mipsel #define tb_target_set_jmp_target tb_target_set_jmp_target_mipsel diff --git a/qemu/ppc.h b/qemu/ppc.h index 8cb9ea3e..87a216a3 100644 --- a/qemu/ppc.h +++ b/qemu/ppc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc #define use_idiv_instructions use_idiv_instructions_ppc #define arm_arch arm_arch_ppc #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc diff --git a/qemu/ppc64.h b/qemu/ppc64.h index 1d055072..d4f27146 100644 --- a/qemu/ppc64.h +++ b/qemu/ppc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _ppc64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_ppc64 #define use_idiv_instructions use_idiv_instructions_ppc64 #define arm_arch arm_arch_ppc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_ppc64 diff --git a/qemu/riscv32.h b/qemu/riscv32.h index df9eed70..57795e38 100644 --- a/qemu/riscv32.h +++ b/qemu/riscv32.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv32 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv32 #define use_idiv_instructions use_idiv_instructions_riscv32 #define arm_arch arm_arch_riscv32 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv32 diff --git a/qemu/riscv64.h b/qemu/riscv64.h index c41e7178..4b19f2c9 100644 --- a/qemu/riscv64.h +++ b/qemu/riscv64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _riscv64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_riscv64 #define use_idiv_instructions use_idiv_instructions_riscv64 #define arm_arch arm_arch_riscv64 #define tb_target_set_jmp_target tb_target_set_jmp_target_riscv64 diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index f983f634..173a2e1e 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -27,6 +27,7 @@ #include "qemu/bitmap.h" #include "tcg/tcg.h" #include "exec/tb-hash.h" +#include "accel/tcg/translate-all.h" #include "uc_priv.h" @@ -173,6 +174,7 @@ void cpu_stop_current(struct uc_struct *uc) void resume_all_vcpus(struct uc_struct* uc) { CPUState *cpu = uc->cpu; + tb_page_addr_t addr; cpu->halted = 0; cpu->exit_request = 0; cpu->exception_index = -1; @@ -188,12 +190,15 @@ void resume_all_vcpus(struct uc_struct* uc) // clear the cache of the addr_end address, since the generated code // at that address is to exit emulation, but not for the instruction there. // if we dont do this, next time we cannot emulate at that address - TranslationBlock *tb = cpu->tb_jmp_cache[tb_jmp_cache_hash_func(uc, uc->addr_end)]; - if (tb) { - qht_remove(&uc->tcg_ctx->tb_ctx.htable, tb, tb->hash); - tb_flush_jmp_cache(cpu, uc->addr_end); - } + // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) + addr = get_page_addr_code(uc->cpu->env_ptr, uc->addr_end); + // Unicorn: Why addr - 1? + // 0: INC ecx + // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) + // + // While tb_invalidate_phys_range invalides [start, end) + tb_invalidate_phys_range(uc, addr - 1, addr - 1 + 8); cpu->created = false; } diff --git a/qemu/sparc.h b/qemu/sparc.h index 741e7565..ecb8c6c2 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc #define use_idiv_instructions use_idiv_instructions_sparc #define arm_arch arm_arch_sparc #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 5262a11b..22d1ea35 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _sparc64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_sparc64 #define use_idiv_instructions use_idiv_instructions_sparc64 #define arm_arch arm_arch_sparc64 #define tb_target_set_jmp_target tb_target_set_jmp_target_sparc64 diff --git a/qemu/x86_64.h b/qemu/x86_64.h index a1896af7..d0d3fba0 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -4,6 +4,7 @@ #ifndef UNICORN_ARCH_POSTFIX #define UNICORN_ARCH_POSTFIX _x86_64 #endif +#define tb_invalidate_phys_range tb_invalidate_phys_range_x86_64 #define use_idiv_instructions use_idiv_instructions_x86_64 #define arm_arch arm_arch_x86_64 #define tb_target_set_jmp_target tb_target_set_jmp_target_x86_64 diff --git a/symbols.sh b/symbols.sh index 19997fb4..a30c0f90 100755 --- a/symbols.sh +++ b/symbols.sh @@ -4,6 +4,7 @@ CMD_PATH=$(realpath $0) SOURCE_DIR=$(dirname ${CMD_PATH}) COMMON_SYMBOLS=" +tb_invalidate_phys_range \ use_idiv_instructions \ arm_arch \ tb_target_set_jmp_target \ diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index abb37b19..2d73bd96 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -630,23 +630,23 @@ static void test_x86_hook_cpuid() } // This is a regression bug. -static void test_x86_clear_tb_cache() { +static void test_x86_clear_tb_cache() +{ uc_engine *uc; - char code[] = - "\x41\x4a"; // INC ecx; DEC edx; + char code[] = "\x83\xc1\x01\x4a"; // INC ecx; DEC edx; int r_ecx = 0x1234; int r_edx = 0x7890; uint64_t code_start = 0x1240; // Choose this address by design uint64_t code_len = 0x1000; OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); - OK(uc_mem_map(uc, code_start & (1<<12), code_len, UC_PROT_ALL)); + OK(uc_mem_map(uc, code_start & (1 << 12), code_len, UC_PROT_ALL)); OK(uc_mem_write(uc, code_start, code, sizeof(code))); OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); - OK(uc_emu_start(uc, code_start, code_start + 1, 0, 0)); - + OK(uc_emu_start(uc, code_start, code_start + 3, 0, 0)); + // If tb cache is not cleared, edx would be still 0x7890 OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0)); From 84abf1d3a4f70c6597612d6c325caa80a70762b2 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 31 Oct 2021 21:01:55 +0100 Subject: [PATCH 25/40] A stronger test and handle addr_end = 0 --- qemu/accel/tcg/translate-all.c | 3 ++- qemu/softmmu/cpus.c | 23 ++++++++++++++--------- tests/unit/test_x86.c | 6 +++++- uc.c | 6 ++++++ 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 79434101..d59b9604 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -1753,7 +1753,8 @@ void tb_invalidate_phys_range(struct uc_struct *uc, ram_addr_t start, ram_addr_t pages = page_collection_lock(uc, start, end); for (next = (start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - start < end; + //start < end; Unicorn: Fix possible wrap around + (intptr_t)(end - start) > 0; start = next, next += TARGET_PAGE_SIZE) { PageDesc *pd = page_find(uc, start >> TARGET_PAGE_BITS); tb_page_addr_t bound = MIN(next, end); diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index 173a2e1e..12cb84e4 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -174,7 +174,7 @@ void cpu_stop_current(struct uc_struct *uc) void resume_all_vcpus(struct uc_struct* uc) { CPUState *cpu = uc->cpu; - tb_page_addr_t addr; + tb_page_addr_t start, end; cpu->halted = 0; cpu->exit_request = 0; cpu->exception_index = -1; @@ -190,15 +190,20 @@ void resume_all_vcpus(struct uc_struct* uc) // clear the cache of the addr_end address, since the generated code // at that address is to exit emulation, but not for the instruction there. // if we dont do this, next time we cannot emulate at that address + if (uc->addr_end != 0) { + // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) + end = get_page_addr_code(uc->cpu->env_ptr, uc->addr_end); - // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) - addr = get_page_addr_code(uc->cpu->env_ptr, uc->addr_end); - // Unicorn: Why addr - 1? - // 0: INC ecx - // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) - // - // While tb_invalidate_phys_range invalides [start, end) - tb_invalidate_phys_range(uc, addr - 1, addr - 1 + 8); + // For 32bit target. + start = (end - 1) & (target_ulong)(-1); + end = end & (target_ulong)(-1); + // Unicorn: Why start - 1? + // 0: INC ecx + // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) + // + // While tb_invalidate_phys_range invalides [start, end) + tb_invalidate_phys_range(uc, start, end); + } cpu->created = false; } diff --git a/tests/unit/test_x86.c b/tests/unit/test_x86.c index 2d73bd96..bbf35697 100644 --- a/tests/unit/test_x86.c +++ b/tests/unit/test_x86.c @@ -633,7 +633,7 @@ static void test_x86_hook_cpuid() static void test_x86_clear_tb_cache() { uc_engine *uc; - char code[] = "\x83\xc1\x01\x4a"; // INC ecx; DEC edx; + char code[] = "\x83\xc1\x01\x4a"; // ADD ecx, 1; DEC edx; int r_ecx = 0x1234; int r_edx = 0x7890; uint64_t code_start = 0x1240; // Choose this address by design @@ -645,6 +645,10 @@ static void test_x86_clear_tb_cache() OK(uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx)); OK(uc_reg_write(uc, UC_X86_REG_EDX, &r_edx)); + // This emulation should take no effect at all. + OK(uc_emu_start(uc, code_start, code_start, 0, 0)); + + // Emulate ADD ecx, 1. OK(uc_emu_start(uc, code_start, code_start + 3, 0, 0)); // If tb cache is not cleared, edx would be still 0x7890 diff --git a/uc.c b/uc.c index ec0b7d5f..67be4960 100644 --- a/uc.c +++ b/uc.c @@ -639,6 +639,12 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, uc->timed_out = false; uc->first_tb = true; + // In this case, we don't do any emulation because it will generate + // an empty translation block which we can't invalidate. + if (begin == until) { + return UC_ERR_OK; + } + switch (uc->arch) { default: break; From b07baede63af48132fa39966a412a7e8393326f8 Mon Sep 17 00:00:00 2001 From: lazymio Date: Sun, 31 Oct 2021 21:07:30 +0100 Subject: [PATCH 26/40] Format --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 67be4960..8dd778cd 100644 --- a/uc.c +++ b/uc.c @@ -644,7 +644,7 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, if (begin == until) { return UC_ERR_OK; } - + switch (uc->arch) { default: break; From 3dd2e0f95d9582598da37bd3fafb3a10af69a266 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 00:39:36 +0100 Subject: [PATCH 27/40] Basic implementation of uc_ctl --- CMakeLists.txt | 2 + glib_compat/gtree.c | 2 +- glib_compat/gtree.h | 2 + include/uc_priv.h | 32 +++++- include/unicorn/unicorn.h | 37 ++++--- qemu/accel/tcg/translate-all.c | 96 +++++++++++++++++ qemu/accel/tcg/translator.c | 2 +- qemu/softmmu/cpus.c | 36 ++++--- qemu/target/arm/translate-a64.c | 2 +- qemu/target/arm/translate.c | 4 +- qemu/target/i386/translate.c | 2 +- qemu/target/m68k/translate.c | 2 +- qemu/target/mips/translate.c | 2 +- qemu/target/ppc/translate.c | 2 +- qemu/target/riscv/translate.c | 2 +- qemu/target/sparc/translate.c | 2 +- samples/sample_ctl.c | 76 +++++++++++++ tests/unit/test_ctl.c | 25 +++++ uc.c | 183 ++++++++++++++++++++++++++++++-- 19 files changed, 459 insertions(+), 52 deletions(-) create mode 100644 samples/sample_ctl.c create mode 100644 tests/unit/test_ctl.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eca217e..0c22f03d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1102,6 +1102,8 @@ endif() # Extra tests set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_mem) +set(UNICORN_TEST_FILE ${UNICORN_TEST_FILE} test_ctl) +set(UNICORN_SAMPLE_FILE ${UNICORN_SAMPLE_FILE} sample_ctl) target_compile_options(unicorn PRIVATE ${UNICORN_COMPILE_OPTIONS} diff --git a/glib_compat/gtree.c b/glib_compat/gtree.c index a790d568..b2617a3f 100644 --- a/glib_compat/gtree.c +++ b/glib_compat/gtree.c @@ -260,7 +260,7 @@ static inline GTreeNode *g_tree_node_next (GTreeNode *node) return tmp; } -static void g_tree_remove_all (GTree *tree) +void g_tree_remove_all (GTree *tree) { GTreeNode *node; GTreeNode *next; diff --git a/glib_compat/gtree.h b/glib_compat/gtree.h index f62dbe08..47b6c880 100644 --- a/glib_compat/gtree.h +++ b/glib_compat/gtree.h @@ -44,6 +44,8 @@ void g_tree_destroy (GTree *tree); void g_tree_insert (GTree *tree, gpointer key, gpointer value); +void g_tree_remove_all (GTree *tree); + gboolean g_tree_remove (GTree *tree, gconstpointer key); gpointer g_tree_lookup (GTree *tree, gconstpointer key); diff --git a/include/uc_priv.h b/include/uc_priv.h index bcdf9059..19dbecda 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -41,6 +41,8 @@ #define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8)) #define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff)) +struct TranslationBlock; + typedef uc_err (*query_t)(struct uc_struct *uc, uc_query_type type, size_t *result); @@ -114,6 +116,14 @@ typedef void (*uc_softfloat_initialize)(void); // tcg flush softmmu tlb typedef void (*uc_tcg_flush_tlb)(struct uc_struct *uc); +// Invalidate the TB at given address +typedef void (*uc_invalidate_tb_t)(struct uc_struct *uc, uint64_t start, + size_t len); + +// Request generating TB at given address +typedef struct TranslationBlock *(*uc_gen_tb_t)(struct uc_struct *uc, + uint64_t pc); + struct hook { int type; // UC_HOOK_* int insn; // instruction for HOOK_INSN @@ -226,6 +236,8 @@ struct uc_struct { uc_target_page_init target_page; uc_softfloat_initialize softfloat_initialize; uc_tcg_flush_tlb tcg_flush_tlb; + uc_invalidate_tb_t uc_invalidate_tb; + uc_gen_tb_t uc_gen_tb; /* only 1 cpu in unicorn, do not need current_cpu to handle current running cpu. */ @@ -288,8 +300,9 @@ struct uc_struct { uint64_t invalid_addr; // invalid address to be accessed int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE - uint64_t addr_end; // address where emulation stops (@end param of - // uc_emu_start()) + int use_exit; + GTree *exits; // addresses where emulation stops (@until param of + // uc_emu_start()) Also see UC_CTL_USE_EXITS for more details. int thumb; // thumb mode for ARM MemoryRegion **mapped_blocks; @@ -328,5 +341,20 @@ struct uc_context { // check if this address is mapped in (via uc_mem_map()) MemoryRegion *memory_mapping(struct uc_struct *uc, uint64_t address); +// We have to support 32bit system so we can't hold uint64_t on void* +static inline void uc_add_exit(uc_engine *uc, uint64_t addr) +{ + uint64_t *new_exit = g_malloc(sizeof(uint64_t)); + *new_exit = addr; + g_tree_insert(uc->exits, (gpointer)new_exit, (gpointer)1); +} + +// This function has to exist since we would like to accept uint32_t or +// it's complex to achieve so. +static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr) +{ + return g_tree_lookup(uc->exits, (gpointer)(&addr)) == (gpointer)1; +} + #endif /* vim: set ts=4 noet: */ diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 51dc212c..a9f49650 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -427,40 +427,43 @@ typedef enum uc_query_type { // If a control don't have `Set` or `Get` for @args, it means it's r/o or w/o. typedef enum uc_control_type { // Current mode. - // Read: @args = (*int) + // Read: @args = (int*) UC_CTL_UC_MODE = 0, // Curent page size. - // Write: @args = (int) - // Read: @args = (*int) + // Write: @args = (uint32_t) + // Read: @args = (uint32_t*) UC_CTL_UC_PAGE_SIZE, // Current arch. - // Read: @args = (*int) + // Read: @args = (int*) UC_CTL_UC_ARCH, // Current timeout. - // Read: @args = (*uint64_t) + // Read: @args = (uint64_t*) UC_CTL_UC_TIMEOUT, + // Enable multiple exists. + // Without this control, reading/setting exists won't work. + // This is for API backward compatibility. + // Write: @args = (int) + UC_CTL_UC_USE_EXITS, // The number of current exists. - // Read: @args = (*size_t) + // Read: @args = (size_t*) UC_CTL_UC_EXITS_CNT, // Current exists. - // Write: @args = (*uint64_t exists, size_t len) + // Write: @args = (uint64_t* exists, size_t len) // @len = UC_CTL_UC_EXITS_CNT - // Read: @args = (*uint64_t exists, size_t len) + // Read: @args = (uint64_t* exists, size_t len) // @len = UC_CTL_UC_EXITS_CNT UC_CTL_UC_EXITS, + // Set the cpu model of uc. // Note this option can only be set before any Unicorn // API is called except for uc_open. // Write: @args = (int) // Read: @args = (int) UC_CTL_CPU_MODEL, - // Request the edge of two TBs. - // Read: @args = (uint64_t, uint64_t, *uint64_t) - UC_CTL_TB_EDGE, // Request a tb cache at a specific address // Read: @args = (uint64_t) UC_CTL_TB_REQUEST_CACHE, - // Remove a tb cache at a specific address + // Invalidate a tb cache at a specific address // Read: @args = (uint64_t) UC_CTL_TB_REMOVE_CACHE @@ -469,13 +472,15 @@ typedef enum uc_control_type { #define uc_ctl_get_mode(uc, mode) \ uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_MODE, 1), (mode)) #define uc_ctl_get_page_size(uc, ptr) \ - uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1, (ptr)) + uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_PAGE_SIZE, 1), (ptr)) #define uc_ctl_set_page_size(uc, page_size) \ uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_PAGE_SIZE, 1), (page_size)) #define uc_ctl_get_arch(uc, arch) \ uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_ARCH, 1), (arch)) #define uc_ctl_get_timeout(uc, ptr) \ uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_TIMEOUT, 1), (ptr)) +#define uc_ctl_exits_enabled(uc, enabled) \ + uc_ctl(uc, UC_CTL_WRITE(UC_CTL_UC_USE_EXITS, 1), (enabled)) #define uc_ctl_get_exists_cnt(uc, ptr) \ uc_ctl(uc, UC_CTL_READ(UC_CTL_UC_EXITS_CNT, 1), (ptr)) #define uc_ctl_get_exists(uc, buffer, len) \ @@ -487,11 +492,9 @@ typedef enum uc_control_type { #define uc_ctl_set_cpu_model(uc, model) \ uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model)) #define uc_ctl_remove_cache(uc, address) \ - uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REMOVE_CACHE, 1), (address)) + uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REMOVE_CACHE, 1), (address)) #define uc_ctl_request_cache(uc, address) \ - uc_ctl(uc, UC_CTL_WRITE(UC_CTL_TB_REQUEST_CACHE, 1), (address)) -#define uc_ctl_get_edge(uc, addr1, addr2, ptr) \ - uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_EDGE, 3), (addr1), (addr2), (ptr)) + uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REQUEST_CACHE, 1), (address)) // Opaque storage for CPU context, used with uc_context_*() struct uc_context; diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index d59b9604..a7b94d99 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -980,6 +980,99 @@ static void tb_htable_init(struct uc_struct *uc) qht_init(&uc->tcg_ctx->tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); } +// GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) +// Unicorn: Why addr - 1? +// 0: INC ecx +// 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) +// +// While tb_invalidate_phys_range invalides [start, end) +// +// This function is designed to used with g_tree_foreach +static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) { + uint64_t exit = *((uint64_t*)key); + uc_engine* uc = (uc_engine*)data; + tb_page_addr_t start, end; + + if (exit != 0) { + end = get_page_addr_code(uc->cpu->env_ptr, exit); + + start = (end-1) ; + end = end & (target_ulong)(-1); + + tb_invalidate_phys_range(uc, start, end); + } + + return false; +} + +static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t len) { + tb_page_addr_t start, end; + + // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) + start = get_page_addr_code(uc->cpu->env_ptr, start_addr) & (target_ulong)(-1); + + // For 32bit target. + end = (start + len) & (target_ulong)(-1); + + // We get a wrap? + if (start > end) { + return; + } + + tb_invalidate_phys_range(uc, start, end); +} + +static TranslationBlock* uc_gen_tb(struct uc_struct *uc, uint64_t addr) { + TranslationBlock *tb; + target_ulong cs_base, pc; + CPUState *cpu = uc->cpu; + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + uint32_t flags; + uint32_t hash; + uint32_t cflags = cpu->cflags_next_tb; + + if (cflags == -1) { + cflags = curr_cflags(); + } + + cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); + + // Unicorn: Our hack here. + pc = addr; + + hash = tb_jmp_cache_hash_func(env->uc, pc); + tb = cpu->tb_jmp_cache[hash]; + + cflags &= ~CF_CLUSTER_MASK; + cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT; + + if (likely(tb && + tb->pc == pc && + tb->cs_base == cs_base && + tb->flags == flags && + tb->trace_vcpu_dstate == *cpu->trace_dstate && + (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) == cflags)) { + return tb; + } + + tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags); + cpu->tb_jmp_cache[hash] = tb; + + if (tb != NULL) { + return tb; + } + + if (tb == NULL) { + mmap_lock(); + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); + mmap_unlock(); + /* We add the TB in the virtual pc hash table for the fast lookup */ + cpu->tb_jmp_cache[hash] = tb; + } + + return tb; +} + /* Must be called before using the QEMU cpus. 'tb_size' is the size (in bytes) allocated to the translation buffer. Zero means default size. */ @@ -1000,6 +1093,9 @@ void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size) tcg_prologue_init(uc->tcg_ctx); /* cpu_interrupt_handler is not used in uc1 */ uc->l1_map = g_malloc0(sizeof(void *) * V_L1_MAX_SIZE); + /* Invalidate / Cache TBs */ + uc->uc_invalidate_tb = uc_invalidate_tb; + uc->uc_gen_tb = uc_gen_tb; } /* call with @p->lock held */ diff --git a/qemu/accel/tcg/translator.c b/qemu/accel/tcg/translator.c index 0fca28a9..9ed272fd 100644 --- a/qemu/accel/tcg/translator.c +++ b/qemu/accel/tcg/translator.c @@ -58,7 +58,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, /* Unicorn: early check to see if the address of this block is * the "run until" address. */ - if (tb->pc == cpu->uc->addr_end) { + if (uc_addr_is_exit(uc, tb->pc)) { // This should catch that instruction is at the end // and generate appropriate halting code. gen_tb_start(tcg_ctx, db->tb); diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index 12cb84e4..c318b855 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -171,10 +171,28 @@ void cpu_stop_current(struct uc_struct *uc) } } + +// Unicorn: Why addr - 1? +// 0: INC ecx +// 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) +// +// While tb_invalidate_phys_range invalides [start, end) +// +// This function is designed to used with g_tree_foreach +static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) { + uint64_t exit = *((uint64_t*)key); + uc_engine* uc = (uc_engine*)data; + + if (exit != 0) { + uc->uc_invalidate_tb(uc, exit - 1, 1); + } + + return false; +} + void resume_all_vcpus(struct uc_struct* uc) { CPUState *cpu = uc->cpu; - tb_page_addr_t start, end; cpu->halted = 0; cpu->exit_request = 0; cpu->exception_index = -1; @@ -187,23 +205,11 @@ void resume_all_vcpus(struct uc_struct* uc) } } - // clear the cache of the addr_end address, since the generated code + // clear the cache of the exits address, since the generated code // at that address is to exit emulation, but not for the instruction there. // if we dont do this, next time we cannot emulate at that address - if (uc->addr_end != 0) { - // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) - end = get_page_addr_code(uc->cpu->env_ptr, uc->addr_end); - // For 32bit target. - start = (end - 1) & (target_ulong)(-1); - end = end & (target_ulong)(-1); - // Unicorn: Why start - 1? - // 0: INC ecx - // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) - // - // While tb_invalidate_phys_range invalides [start, end) - tb_invalidate_phys_range(uc, start, end); - } + g_tree_foreach(uc->exits, uc_exit_invalidate_iter, (void*)uc); cpu->created = false; } diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index a9eb1ca0..914b382b 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -14637,7 +14637,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPUARMState *env = cpu->env_ptr; // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == dc->uc->addr_end) { + if (uc_addr_is_exit(dc->uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; } else { diff --git a/qemu/target/arm/translate.c b/qemu/target/arm/translate.c index 742a55fd..efdfc4b4 100644 --- a/qemu/target/arm/translate.c +++ b/qemu/target/arm/translate.c @@ -11421,7 +11421,7 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == dc->uc->addr_end) { + if (uc_addr_is_exit(dc->uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; } else { @@ -11499,7 +11499,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } // Unicorn: end address tells us to stop emulation - if (dcbase->pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, dcbase->pc_next)) { // imitate WFI instruction to halt emulation dcbase->is_jmp = DISAS_WFI; return; diff --git a/qemu/target/i386/translate.c b/qemu/target/i386/translate.c index cf148c4b..8616b12f 100644 --- a/qemu/target/i386/translate.c +++ b/qemu/target/i386/translate.c @@ -4765,7 +4765,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->uc = env->uc; // Unicorn: end address tells us to stop emulation - if (s->pc == s->uc->addr_end) { + if (uc_addr_is_exit(env->uc, s->pc)) { // imitate the HLT instruction gen_update_cc_op(s); gen_jmp_im(s, pc_start - s->cs_base); diff --git a/qemu/target/m68k/translate.c b/qemu/target/m68k/translate.c index 323eff44..c447a905 100644 --- a/qemu/target/m68k/translate.c +++ b/qemu/target/m68k/translate.c @@ -6326,7 +6326,7 @@ static void m68k_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) uint16_t insn; // Unicorn: end address tells us to stop emulation - if (dc->pc == uc->addr_end) { + if (uc_addr_is_exit(uc, dc->pc)) { gen_exception(dc, dc->pc, EXCP_HLT); return; } diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 97e680a3..e9fceaf9 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -30932,7 +30932,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) is_slot = ctx->hflags & MIPS_HFLAG_BMASK; // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { // raise a special interrupt to quit gen_helper_wait(tcg_ctx, tcg_ctx->cpu_env); ctx->base.is_jmp = DISAS_NORETURN; diff --git a/qemu/target/ppc/translate.c b/qemu/target/ppc/translate.c index 8cfebab2..fec05d19 100644 --- a/qemu/target/ppc/translate.c +++ b/qemu/target/ppc/translate.c @@ -7626,7 +7626,7 @@ static void ppc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) ctx->base.pc_next, ctx->mem_idx, (int)msr_ir); // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { gen_wait(ctx); return; } diff --git a/qemu/target/riscv/translate.c b/qemu/target/riscv/translate.c index 9898093d..e256958f 100644 --- a/qemu/target/riscv/translate.c +++ b/qemu/target/riscv/translate.c @@ -850,7 +850,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) bool insn_hook = false; // Unicorn: end address tells us to stop emulation - if (ctx->base.pc_next == ctx->uc->addr_end) { + if (uc_addr_is_exit(uc, ctx->base.pc_next)) { // Unicorn: We have to exit current execution here. dcbase->is_jmp = DISAS_UC_EXIT; } else { diff --git a/qemu/target/sparc/translate.c b/qemu/target/sparc/translate.c index c6f3d9cd..8c2a8b40 100644 --- a/qemu/target/sparc/translate.c +++ b/qemu/target/sparc/translate.c @@ -5951,7 +5951,7 @@ static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) unsigned int insn; // Unicorn: end address tells us to stop emulation - if (dc->pc == uc->addr_end) { + if (uc_addr_is_exit(uc, dc->pc)) { #ifndef TARGET_SPARC64 gen_helper_power_down(tcg_ctx, tcg_ctx->cpu_env); #endif diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c new file mode 100644 index 00000000..543a6e6a --- /dev/null +++ b/samples/sample_ctl.c @@ -0,0 +1,76 @@ +/* Unicorn Emulator Engine */ +/* By Lazymio(@wtdcode), 2021 */ + +/* Sample code to demonstrate how to use uc_ctl */ + +#include +#include + +// code to be emulated +// code to be emulated +#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx; PXOR xmm0, xmm1 + +// memory address where emulation starts +#define ADDRESS 0x10000 + +static void test_uc_ctl_read(void) +{ + uc_engine *uc; + uc_err err; + uint32_t tmp; + uc_hook trace1, trace2; + int mode, arch; + uint32_t pagesize; + uint64_t timeout; + + int r_ecx = 0x1234; // ECX register + int r_edx = 0x7890; // EDX register + + printf("Reading some properties by uc_ctl.\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + // Let's query some properties by uc_ctl. + // Note uc_ctl_* is just tiny macro wrappers for uc_ctl(). + err = uc_ctl_get_mode(uc, &mode); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_arch(uc, &arch); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_timeout(uc, &timeout); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_get_page_size(uc, &pagesize); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + printf(">>> mode = %d, arch = %d, timeout=%" PRIu64 ", pagesize=%" PRIu32 + "\n", + mode, arch, timeout, pagesize); + + uc_close(uc); +} + +int main(int argc, char **argv, char **envp) +{ + test_uc_ctl_read(); + + return 0; +} diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c new file mode 100644 index 00000000..f2f66625 --- /dev/null +++ b/tests/unit/test_ctl.c @@ -0,0 +1,25 @@ +#include "unicorn_test.h" + +const uint64_t code_start = 0x1000; +const uint64_t code_len = 0x4000; + +#define GEN_SIMPLE_READ_TEST(field, ctl_type, arg_type, expected) \ + static void test_uc_ctl_##field() \ + { \ + uc_engine *uc; \ + arg_type arg; \ + OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); \ + OK(uc_ctl(uc, UC_CTL_READ(ctl_type, 1), &arg)); \ + TEST_CHECK(arg == expected); \ + } + +GEN_SIMPLE_READ_TEST(mode, UC_CTL_UC_MODE, int, 4) +GEN_SIMPLE_READ_TEST(arch, UC_CTL_UC_ARCH, int, 4) +GEN_SIMPLE_READ_TEST(page_size, UC_CTL_UC_PAGE_SIZE, uint32_t, 4096) +GEN_SIMPLE_READ_TEST(time_out, UC_CTL_UC_TIMEOUT, uint64_t, 0) + +TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, + {"test_uc_ctl_page_size", test_uc_ctl_page_size}, + {"test_uc_ctl_arch", test_uc_ctl_arch}, + {"test_uc_ctl_time_out", test_uc_ctl_time_out}, + {NULL, NULL}}; \ No newline at end of file diff --git a/uc.c b/uc.c index 8dd778cd..3d765be4 100644 --- a/uc.c +++ b/uc.c @@ -136,6 +136,20 @@ bool uc_arch_supported(uc_arch arch) } } +static gint uc_exits_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ + uint64_t lhs = *((uint64_t *)a); + uint64_t rhs = *((uint64_t *)b); + + if (lhs < rhs) { + return -1; + } else if (lhs == rhs) { + return 0; + } else { + return 1; + } +} + UNICORN_EXPORT uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) { @@ -161,6 +175,8 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result) QTAILQ_INIT(&uc->address_spaces); + uc->exits = g_tree_new_full(uc_exits_cmp, NULL, g_free, NULL); + switch (arch) { default: break; @@ -396,6 +412,8 @@ uc_err uc_close(uc_engine *uc) } list_clear(&uc->saved_contexts); + g_tree_destroy(uc->exits); + // finally, free uc itself. memset(uc, 0, sizeof(*uc)); free(uc); @@ -735,7 +753,10 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, } } - uc->addr_end = until; + // This is low efficiency for compatibility. + // Consider a new uc_ctl to set not updating uc->exists in uc_emu_start? + g_tree_remove_all(uc->exits); + uc_add_exit(uc, until); if (timeout) { enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds @@ -1525,12 +1546,6 @@ uc_err uc_query(uc_engine *uc, uc_query_type type, size_t *result) return UC_ERR_OK; } -UNICORN_EXPORT -uc_err uc_ctl(uc_engine *uc, uc_control_type option, ...) -{ - return UC_ERR_ARG; -} - UNICORN_EXPORT uc_err uc_context_alloc(uc_engine *uc, uc_context **context) { @@ -1762,3 +1777,157 @@ uc_err uc_context_free(uc_context *context) } return uc_free(context); } + +typedef struct _uc_ctl_exit_request { + uint64_t *array; + size_t len; +} uc_ctl_exit_request; + +static inline gboolean uc_read_exit_iter(gpointer key, gpointer val, + gpointer data) +{ + uc_ctl_exit_request *req = (uc_ctl_exit_request *)data; + + req->array[req->len++] = *(uint64_t *)key; + + return false; +} + +UNICORN_EXPORT +uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) +{ + int rw, type; + uc_err err = UC_ERR_OK; + va_list args; + + rw = control >> 30; + type = (control & ((1 << 16) - 1)); + va_start(args, control); + + switch (type) { + case UC_CTL_UC_MODE: { + if (rw == UC_CTL_IO_READ) { + int *pmode = va_arg(args, int *); + *pmode = uc->mode; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_ARCH: { + if (rw == UC_CTL_IO_READ) { + int *arch = va_arg(args, int *); + *arch = uc->arch; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_TIMEOUT: { + if (rw == UC_CTL_IO_READ) { + size_t *arch = va_arg(args, size_t *); + *arch = uc->timeout; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_PAGE_SIZE: { + if (rw == UC_CTL_IO_READ) { + uint32_t *page_size = va_arg(args, uint32_t *); + *page_size = uc->target_page_size; + } else { + // Not implemented. + err = UC_ERR_ARG; + } + break; + } + case UC_CTL_UC_USE_EXITS: { + if (rw == UC_CTL_IO_WRITE) { + int use_exit = va_arg(args, int); + uc->use_exit = use_exit; + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_EXITS_CNT: { + if (!uc->use_exit) { + err = UC_ERR_ARG; + } else if (rw == UC_CTL_IO_READ) { + size_t *exits_cnt = va_arg(args, size_t *); + *exits_cnt = g_tree_nnodes(uc->exits); + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_UC_EXITS: { + if (!uc->use_exit) { + err = UC_ERR_ARG; + } else if (rw == UC_CTL_IO_READ) { + uint64_t *exits = va_arg(args, uint64_t *); + size_t cnt = va_arg(args, size_t); + if (cnt < g_tree_nnodes(uc->exits)) { + err = UC_ERR_ARG; + } else { + uc_ctl_exit_request req; + req.array = exits; + req.len = 0; + + g_tree_foreach(uc->exits, uc_read_exit_iter, (void *)&req); + } + } else if (rw == UC_CTL_IO_WRITE) { + uint64_t *exits = va_arg(args, uint64_t *); + size_t cnt = va_arg(args, size_t); + + g_tree_remove_all(uc->exits); + + for (size_t i = 0; i < cnt; i++) { + uc_add_exit(uc, exits[i]); + } + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_CPU_MODEL: + // Not implemented. + err = UC_ERR_ARG; + break; + + case UC_CTL_TB_REQUEST_CACHE: { + if (rw == UC_CTL_IO_READ) { + uint64_t addr = va_arg(args, uint64_t); + uc->uc_gen_tb(uc, addr); + } else { + err = UC_ERR_ARG; + } + break; + } + + case UC_CTL_TB_REMOVE_CACHE: { + if (rw == UC_CTL_IO_READ) { + uint64_t addr = va_arg(args, uint64_t); + uc->uc_invalidate_tb(uc, addr, 1); + } else { + err = UC_ERR_ARG; + } + break; + } + + default: + err = UC_ERR_ARG; + break; + } + + va_end(args); + + return err; +} \ No newline at end of file From 0a3e46bf4f4050acee4531719932ee44f0a97525 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 09:41:25 +0100 Subject: [PATCH 28/40] Format --- qemu/accel/tcg/translate-all.c | 30 ++++-------------------------- qemu/softmmu/cpus.c | 21 ++++++++++++--------- samples/sample_ctl.c | 1 - 3 files changed, 16 insertions(+), 36 deletions(-) diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index a7b94d99..5c7f3abe 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -980,32 +980,9 @@ static void tb_htable_init(struct uc_struct *uc) qht_init(&uc->tcg_ctx->tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); } -// GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) -// Unicorn: Why addr - 1? -// 0: INC ecx -// 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) -// -// While tb_invalidate_phys_range invalides [start, end) -// -// This function is designed to used with g_tree_foreach -static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) { - uint64_t exit = *((uint64_t*)key); - uc_engine* uc = (uc_engine*)data; - tb_page_addr_t start, end; - - if (exit != 0) { - end = get_page_addr_code(uc->cpu->env_ptr, exit); - start = (end-1) ; - end = end & (target_ulong)(-1); - - tb_invalidate_phys_range(uc, start, end); - } - - return false; -} - -static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t len) { +static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t len) +{ tb_page_addr_t start, end; // GVA to GPA (GPA -> HVA via page_find, HVA->HPA via host mmu) @@ -1022,7 +999,8 @@ static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t l tb_invalidate_phys_range(uc, start, end); } -static TranslationBlock* uc_gen_tb(struct uc_struct *uc, uint64_t addr) { +static TranslationBlock* uc_gen_tb(struct uc_struct *uc, uint64_t addr) +{ TranslationBlock *tb; target_ulong cs_base, pc; CPUState *cpu = uc->cpu; diff --git a/qemu/softmmu/cpus.c b/qemu/softmmu/cpus.c index c318b855..25568fac 100644 --- a/qemu/softmmu/cpus.c +++ b/qemu/softmmu/cpus.c @@ -172,18 +172,21 @@ void cpu_stop_current(struct uc_struct *uc) } -// Unicorn: Why addr - 1? -// 0: INC ecx -// 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) -// -// While tb_invalidate_phys_range invalides [start, end) -// -// This function is designed to used with g_tree_foreach -static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) { + +static inline gboolean uc_exit_invalidate_iter(gpointer key, gpointer val, gpointer data) +{ uint64_t exit = *((uint64_t*)key); - uc_engine* uc = (uc_engine*)data; + uc_engine *uc = (uc_engine*)data; if (exit != 0) { + // Unicorn: Why addr - 1? + // + // 0: INC ecx + // 1: DEC edx <--- We put exit here, then the range of TB is [0, 1) + // + // While tb_invalidate_phys_range invalides [start, end) + // + // This function is designed to used with g_tree_foreach uc->uc_invalidate_tb(uc, exit - 1, 1); } diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 543a6e6a..359b1e71 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -6,7 +6,6 @@ #include #include -// code to be emulated // code to be emulated #define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx; PXOR xmm0, xmm1 From 6c3960242b39239f1b5ae7acf50229cbc7e80c70 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 10:17:58 +0100 Subject: [PATCH 29/40] Format unicorn_arm and unicorn_aarch64 --- format.sh | 2 +- qemu/target/arm/unicorn_aarch64.c | 270 +++++++++--------- qemu/target/arm/unicorn_arm.c | 451 +++++++++++++++--------------- 3 files changed, 377 insertions(+), 346 deletions(-) diff --git a/format.sh b/format.sh index d4418b15..0bf864e8 100644 --- a/format.sh +++ b/format.sh @@ -5,4 +5,4 @@ find ./msvc -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format - find ./include -maxdepth 2 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" find ./tests/unit -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" find ./samples -maxdepth 1 "(" -name "*.c" -or -name "*.h" ")" -exec clang-format -i -style=file "{}" ";" -find ./qemu "(" -name "unicorn.c" -or -name "unicorn.h" ")" -exec clang-format -i -style=file "{}" ";" +find ./qemu "(" -name "unicorn.c" -or -name "unicorn.h" -or -name "unicorn_arm.c" -or -name "unicorn_aarch64.c" ")" -exec clang-format -i -style=file "{}" ";" diff --git a/qemu/target/arm/unicorn_aarch64.c b/qemu/target/arm/unicorn_aarch64.c index 14361f1c..872ed08a 100644 --- a/qemu/target/arm/unicorn_aarch64.c +++ b/qemu/target/arm/unicorn_aarch64.c @@ -17,7 +17,7 @@ static void arm64_set_pc(struct uc_struct *uc, uint64_t address) ((CPUARMState *)uc->cpu->env_ptr)->pc = address; } -static void arm64_release(void* ctx) +static void arm64_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; @@ -38,11 +38,13 @@ static void arm64_release(void* ctx) g_free(fast->table); } - QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } - QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } @@ -98,73 +100,78 @@ static void reg_read(CPUARMState *env, unsigned int regid, void *value) } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { *(int32_t *)value = READ_DWORD(env->xregs[regid - UC_ARM64_REG_W0]); } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { // FIXME - float64 *dst = (float64*) value; + float64 *dst = (float64 *)value; uint32_t reg_index = regid - UC_ARM64_REG_Q0; dst[0] = env->vfp.zregs[reg_index].d[0]; dst[1] = env->vfp.zregs[reg_index].d[1]; } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { - *(float64*)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0]; + *(float64 *)value = env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0]; } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { - *(int32_t*)value = READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]); + *(int32_t *)value = + READ_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0]); } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { - *(int16_t*)value = READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]); + *(int16_t *)value = + READ_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0]); } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { - *(int8_t*)value = READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]); + *(int8_t *)value = + READ_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0]); } else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) { - *(uint64_t*)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0]; + *(uint64_t *)value = env->elr_el[regid - UC_ARM64_REG_ELR_EL0]; } else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) { - *(uint64_t*)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0]; + *(uint64_t *)value = env->sp_el[regid - UC_ARM64_REG_SP_EL0]; } else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) { - *(uint64_t*)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0]; + *(uint64_t *)value = env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0]; } else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) { - *(uint64_t*)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0]; - } else if (regid >= UC_ARM64_REG_VBAR_EL0 && regid <= UC_ARM64_REG_VBAR_EL3) { - *(uint64_t*)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0]; + *(uint64_t *)value = env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0]; + } else if (regid >= UC_ARM64_REG_VBAR_EL0 && + regid <= UC_ARM64_REG_VBAR_EL3) { + *(uint64_t *)value = env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0]; } else { - switch(regid) { - default: break; - case UC_ARM64_REG_CPACR_EL1: - // *(uint32_t *)value = env->cp15.c1_coproc; - break; - case UC_ARM64_REG_TPIDR_EL0: - // *(int64_t *)value = env->cp15.tpidr_el0; - break; - case UC_ARM64_REG_TPIDRRO_EL0: - // *(int64_t *)value = env->cp15.tpidrro_el0; - break; - case UC_ARM64_REG_TPIDR_EL1: - // *(int64_t *)value = env->cp15.tpidr_el1; - break; - case UC_ARM64_REG_X29: - *(int64_t *)value = env->xregs[29]; - break; - case UC_ARM64_REG_X30: - *(int64_t *)value = env->xregs[30]; - break; - case UC_ARM64_REG_PC: - *(uint64_t *)value = env->pc; - break; - case UC_ARM64_REG_SP: - *(int64_t *)value = env->xregs[31]; - break; - case UC_ARM64_REG_NZCV: - *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; - break; - case UC_ARM64_REG_PSTATE: - *(uint32_t *)value = pstate_read(env); - break; - case UC_ARM64_REG_TTBR0_EL1: - // *(uint64_t *)value = env->cp15.ttbr0_el1; - break; - case UC_ARM64_REG_TTBR1_EL1: - // *(uint64_t *)value = env->cp15.ttbr1_el1; - break; - case UC_ARM64_REG_PAR_EL1: - // *(uint64_t *)value = env->cp15.par_el1; - break; - case UC_ARM64_REG_MAIR_EL1: - // *(uint64_t *)value = env->cp15.mair_el1; - break; + switch (regid) { + default: + break; + case UC_ARM64_REG_CPACR_EL1: + // *(uint32_t *)value = env->cp15.c1_coproc; + break; + case UC_ARM64_REG_TPIDR_EL0: + // *(int64_t *)value = env->cp15.tpidr_el0; + break; + case UC_ARM64_REG_TPIDRRO_EL0: + // *(int64_t *)value = env->cp15.tpidrro_el0; + break; + case UC_ARM64_REG_TPIDR_EL1: + // *(int64_t *)value = env->cp15.tpidr_el1; + break; + case UC_ARM64_REG_X29: + *(int64_t *)value = env->xregs[29]; + break; + case UC_ARM64_REG_X30: + *(int64_t *)value = env->xregs[30]; + break; + case UC_ARM64_REG_PC: + *(uint64_t *)value = env->pc; + break; + case UC_ARM64_REG_SP: + *(int64_t *)value = env->xregs[31]; + break; + case UC_ARM64_REG_NZCV: + *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; + break; + case UC_ARM64_REG_PSTATE: + *(uint32_t *)value = pstate_read(env); + break; + case UC_ARM64_REG_TTBR0_EL1: + // *(uint64_t *)value = env->cp15.ttbr0_el1; + break; + case UC_ARM64_REG_TTBR1_EL1: + // *(uint64_t *)value = env->cp15.ttbr1_el1; + break; + case UC_ARM64_REG_PAR_EL1: + // *(uint64_t *)value = env->cp15.par_el1; + break; + case UC_ARM64_REG_MAIR_EL1: + // *(uint64_t *)value = env->cp15.mair_el1; + break; } } @@ -181,82 +188,88 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { WRITE_DWORD(env->xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value); } else if (regid >= UC_ARM64_REG_Q0 && regid <= UC_ARM64_REG_Q31) { - float64 *src = (float64*) value; + float64 *src = (float64 *)value; uint32_t reg_index = regid - UC_ARM64_REG_Q0; env->vfp.zregs[reg_index].d[0] = src[0]; env->vfp.zregs[reg_index].d[1] = src[1]; } else if (regid >= UC_ARM64_REG_D0 && regid <= UC_ARM64_REG_D31) { - env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = * (float64*) value; + env->vfp.zregs[regid - UC_ARM64_REG_D0].d[0] = *(float64 *)value; } else if (regid >= UC_ARM64_REG_S0 && regid <= UC_ARM64_REG_S31) { - WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0], *(int32_t*) value); + WRITE_DWORD(env->vfp.zregs[regid - UC_ARM64_REG_S0].d[0], + *(int32_t *)value); } else if (regid >= UC_ARM64_REG_H0 && regid <= UC_ARM64_REG_H31) { - WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0], *(int16_t*) value); + WRITE_WORD(env->vfp.zregs[regid - UC_ARM64_REG_H0].d[0], + *(int16_t *)value); } else if (regid >= UC_ARM64_REG_B0 && regid <= UC_ARM64_REG_B31) { - WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0], *(int8_t*) value); + WRITE_BYTE_L(env->vfp.zregs[regid - UC_ARM64_REG_B0].d[0], + *(int8_t *)value); } else if (regid >= UC_ARM64_REG_ELR_EL0 && regid <= UC_ARM64_REG_ELR_EL3) { - env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t*)value; + env->elr_el[regid - UC_ARM64_REG_ELR_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_SP_EL0 && regid <= UC_ARM64_REG_SP_EL3) { - env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t*)value; + env->sp_el[regid - UC_ARM64_REG_SP_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_ESR_EL0 && regid <= UC_ARM64_REG_ESR_EL3) { - env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t*)value; + env->cp15.esr_el[regid - UC_ARM64_REG_ESR_EL0] = *(uint64_t *)value; } else if (regid >= UC_ARM64_REG_FAR_EL0 && regid <= UC_ARM64_REG_FAR_EL3) { - env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t*)value; - } else if (regid >= UC_ARM64_REG_VBAR_EL0 && regid <= UC_ARM64_REG_VBAR_EL3) { - env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t*)value; + env->cp15.far_el[regid - UC_ARM64_REG_FAR_EL0] = *(uint64_t *)value; + } else if (regid >= UC_ARM64_REG_VBAR_EL0 && + regid <= UC_ARM64_REG_VBAR_EL3) { + env->cp15.vbar_el[regid - UC_ARM64_REG_VBAR_EL0] = *(uint64_t *)value; } else { - switch(regid) { - default: break; - case UC_ARM64_REG_CPACR_EL1: - //env->cp15.c1_coproc = *(uint32_t *)value; - break; - case UC_ARM64_REG_TPIDR_EL0: - //env->cp15.tpidr_el0 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TPIDRRO_EL0: - //env->cp15.tpidrro_el0 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TPIDR_EL1: - //env->cp15.tpidr_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_X29: - env->xregs[29] = *(uint64_t *)value; - break; - case UC_ARM64_REG_X30: - env->xregs[30] = *(uint64_t *)value; - break; - case UC_ARM64_REG_PC: - env->pc = *(uint64_t *)value; - break; - case UC_ARM64_REG_SP: - env->xregs[31] = *(uint64_t *)value; - break; - case UC_ARM64_REG_NZCV: - //cpsr_write(env, *(uint32_t *)value, CPSR_NZCV); - break; - case UC_ARM64_REG_PSTATE: - pstate_write(env, *(uint32_t *)value); - break; - case UC_ARM64_REG_TTBR0_EL1: - //env->cp15.ttbr0_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_TTBR1_EL1: - //env->cp15.ttbr1_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_PAR_EL1: - //env->cp15.par_el1 = *(uint64_t *)value; - break; - case UC_ARM64_REG_MAIR_EL1: - //env->cp15.mair_el1 = *(uint64_t *)value; - break; + switch (regid) { + default: + break; + case UC_ARM64_REG_CPACR_EL1: + // env->cp15.c1_coproc = *(uint32_t *)value; + break; + case UC_ARM64_REG_TPIDR_EL0: + // env->cp15.tpidr_el0 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TPIDRRO_EL0: + // env->cp15.tpidrro_el0 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TPIDR_EL1: + // env->cp15.tpidr_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_X29: + env->xregs[29] = *(uint64_t *)value; + break; + case UC_ARM64_REG_X30: + env->xregs[30] = *(uint64_t *)value; + break; + case UC_ARM64_REG_PC: + env->pc = *(uint64_t *)value; + break; + case UC_ARM64_REG_SP: + env->xregs[31] = *(uint64_t *)value; + break; + case UC_ARM64_REG_NZCV: + // cpsr_write(env, *(uint32_t *)value, CPSR_NZCV); + break; + case UC_ARM64_REG_PSTATE: + pstate_write(env, *(uint32_t *)value); + break; + case UC_ARM64_REG_TTBR0_EL1: + // env->cp15.ttbr0_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_TTBR1_EL1: + // env->cp15.ttbr1_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_PAR_EL1: + // env->cp15.par_el1 = *(uint64_t *)value; + break; + case UC_ARM64_REG_MAIR_EL1: + // env->cp15.mair_el1 = *(uint64_t *)value; + break; } } return; } -int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { - CPUARMState *env= &(ARM_CPU(uc->cpu)->env); + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { @@ -268,16 +281,17 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co return 0; } -int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) +int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { - CPUARMState *env= &(ARM_CPU(uc->cpu)->env); + CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_ARM64_REG_PC){ + if (regid == UC_ARM64_REG_PC) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -289,12 +303,14 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm64eb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { - CPUARMState *env= (CPUARMState *)ctx->data; + CPUARMState *env = (CPUARMState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -308,12 +324,14 @@ int arm64_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **va DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm64eb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm64_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { - CPUARMState *env= (CPUARMState *)ctx->data; + CPUARMState *env = (CPUARMState *)ctx->data; int i; for (i = 0; i < count; i++) { @@ -339,9 +357,9 @@ static int arm64_cpus_init(struct uc_struct *uc, const char *cpu_model) DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -void arm64eb_uc_init(struct uc_struct* uc) +void arm64eb_uc_init(struct uc_struct *uc) #else -void arm64_uc_init(struct uc_struct* uc) +void arm64_uc_init(struct uc_struct *uc) #endif { uc->reg_read = arm64_reg_read; diff --git a/qemu/target/arm/unicorn_arm.c b/qemu/target/arm/unicorn_arm.c index 9a5a698d..2b30db80 100644 --- a/qemu/target/arm/unicorn_arm.c +++ b/qemu/target/arm/unicorn_arm.c @@ -23,7 +23,7 @@ static void arm_release(void *ctx) { int i; TCGContext *tcg_ctx = (TCGContext *)ctx; - ARMCPU* cpu = (ARMCPU *)tcg_ctx->uc->cpu; + ARMCPU *cpu = (ARMCPU *)tcg_ctx->uc->cpu; CPUTLBDesc *d = cpu->neg.tlb.d; CPUTLBDescFast *f = cpu->neg.tlb.f; CPUTLBDesc *desc; @@ -40,11 +40,13 @@ static void arm_release(void *ctx) g_free(fast->table); } - QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->pre_el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } - QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) { + QLIST_FOREACH_SAFE(entry, &cpu->el_change_hooks, node, next) + { QLIST_SAFE_REMOVE(entry, node); g_free(entry); } @@ -120,7 +122,8 @@ static uint32_t v7m_mrs_xpsr(CPUARMState *env, uint32_t reg) return xpsr_read(env) & mask; } -static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask, uint32_t reg, uint32_t val) +static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask, uint32_t reg, + uint32_t val) { uint32_t xpsrmask = 0; @@ -150,85 +153,86 @@ static void reg_read(CPUARMState *env, unsigned int regid, void *value) *(int32_t *)value = env->regs[regid - UC_ARM_REG_R0]; } else if (regid >= UC_ARM_REG_D0 && regid <= UC_ARM_REG_D31) { uint32_t reg_index = regid - UC_ARM_REG_D0; - *(float64 *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1]; + *(float64 *)value = env->vfp.zregs[reg_index / 2].d[reg_index & 1]; } else { - switch(regid) { - case UC_ARM_REG_APSR: - if (arm_feature(env, ARM_FEATURE_M)) { - *(int32_t *)value = v7m_mrs_xpsr(env, 0); - } else { - *(int32_t *)value = cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE); - } - break; - case UC_ARM_REG_APSR_NZCV: - *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; - break; - case UC_ARM_REG_CPSR: - *(int32_t *)value = cpsr_read(env); - break; - case UC_ARM_REG_SPSR: - *(int32_t *)value = env->spsr; - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - *(int32_t *)value = env->regs[13]; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - *(int32_t *)value = env->regs[14]; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - *(int32_t *)value = env->regs[15]; - break; - case UC_ARM_REG_C1_C0_2: - *(int32_t *)value = env->cp15.cpacr_el1; - break; - case UC_ARM_REG_C13_C0_3: - *(int32_t *)value = env->cp15.tpidrro_el[0]; - break; - case UC_ARM_REG_FPEXC: - *(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC]; - break; - case UC_ARM_REG_IPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 5); - break; - case UC_ARM_REG_MSP: - *(uint32_t *)value = helper_v7m_mrs(env, 8); - break; - case UC_ARM_REG_PSP: - *(uint32_t *)value = helper_v7m_mrs(env, 9); - break; - case UC_ARM_REG_IAPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 1); - break; - case UC_ARM_REG_EAPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 2); - break; - case UC_ARM_REG_XPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 3); - break; - case UC_ARM_REG_EPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 6); - break; - case UC_ARM_REG_IEPSR: - *(int32_t *)value = v7m_mrs_xpsr(env, 7); - break; - case UC_ARM_REG_PRIMASK: - *(uint32_t *)value = helper_v7m_mrs(env, 16); - break; - case UC_ARM_REG_BASEPRI: - *(uint32_t *)value = helper_v7m_mrs(env, 17); - break; - case UC_ARM_REG_BASEPRI_MAX: - *(uint32_t *)value = helper_v7m_mrs(env, 18); - break; - case UC_ARM_REG_FAULTMASK: - *(uint32_t *)value = helper_v7m_mrs(env, 19); - break; - case UC_ARM_REG_CONTROL: - *(uint32_t *)value = helper_v7m_mrs(env, 20); - break; + switch (regid) { + case UC_ARM_REG_APSR: + if (arm_feature(env, ARM_FEATURE_M)) { + *(int32_t *)value = v7m_mrs_xpsr(env, 0); + } else { + *(int32_t *)value = + cpsr_read(env) & (CPSR_NZCV | CPSR_Q | CPSR_GE); + } + break; + case UC_ARM_REG_APSR_NZCV: + *(int32_t *)value = cpsr_read(env) & CPSR_NZCV; + break; + case UC_ARM_REG_CPSR: + *(int32_t *)value = cpsr_read(env); + break; + case UC_ARM_REG_SPSR: + *(int32_t *)value = env->spsr; + break; + // case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + *(int32_t *)value = env->regs[13]; + break; + // case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + *(int32_t *)value = env->regs[14]; + break; + // case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + *(int32_t *)value = env->regs[15]; + break; + case UC_ARM_REG_C1_C0_2: + *(int32_t *)value = env->cp15.cpacr_el1; + break; + case UC_ARM_REG_C13_C0_3: + *(int32_t *)value = env->cp15.tpidrro_el[0]; + break; + case UC_ARM_REG_FPEXC: + *(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC]; + break; + case UC_ARM_REG_IPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 5); + break; + case UC_ARM_REG_MSP: + *(uint32_t *)value = helper_v7m_mrs(env, 8); + break; + case UC_ARM_REG_PSP: + *(uint32_t *)value = helper_v7m_mrs(env, 9); + break; + case UC_ARM_REG_IAPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 1); + break; + case UC_ARM_REG_EAPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 2); + break; + case UC_ARM_REG_XPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 3); + break; + case UC_ARM_REG_EPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 6); + break; + case UC_ARM_REG_IEPSR: + *(int32_t *)value = v7m_mrs_xpsr(env, 7); + break; + case UC_ARM_REG_PRIMASK: + *(uint32_t *)value = helper_v7m_mrs(env, 16); + break; + case UC_ARM_REG_BASEPRI: + *(uint32_t *)value = helper_v7m_mrs(env, 17); + break; + case UC_ARM_REG_BASEPRI_MAX: + *(uint32_t *)value = helper_v7m_mrs(env, 18); + break; + case UC_ARM_REG_FAULTMASK: + *(uint32_t *)value = helper_v7m_mrs(env, 19); + break; + case UC_ARM_REG_CONTROL: + *(uint32_t *)value = helper_v7m_mrs(env, 20); + break; } } @@ -243,125 +247,127 @@ static void reg_write(CPUARMState *env, unsigned int regid, const void *value) uint32_t reg_index = regid - UC_ARM_REG_D0; env->vfp.zregs[reg_index / 2].d[reg_index & 1] = *(float64 *)value; } else { - switch(regid) { - case UC_ARM_REG_APSR: - if (!arm_feature(env, ARM_FEATURE_M)) { - cpsr_write(env, *(uint32_t *)value, (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteRaw); - } else { - // Same with UC_ARM_REG_APSR_NZCVQ - v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); - } - break; - case UC_ARM_REG_APSR_NZCV: - cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); - break; - case UC_ARM_REG_CPSR: - cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteRaw); - break; - case UC_ARM_REG_SPSR: - env->spsr = *(uint32_t *)value; - break; - //case UC_ARM_REG_SP: - case UC_ARM_REG_R13: - env->regs[13] = *(uint32_t *)value; - break; - //case UC_ARM_REG_LR: - case UC_ARM_REG_R14: - env->regs[14] = *(uint32_t *)value; - break; - //case UC_ARM_REG_PC: - case UC_ARM_REG_R15: - env->pc = (*(uint32_t *)value & ~1); - env->thumb = (*(uint32_t *)value & 1); - env->uc->thumb = (*(uint32_t *)value & 1); - env->regs[15] = (*(uint32_t *)value & ~1); - break; + switch (regid) { + case UC_ARM_REG_APSR: + if (!arm_feature(env, ARM_FEATURE_M)) { + cpsr_write(env, *(uint32_t *)value, + (CPSR_NZCV | CPSR_Q | CPSR_GE), CPSRWriteRaw); + } else { + // Same with UC_ARM_REG_APSR_NZCVQ + v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); + } + break; + case UC_ARM_REG_APSR_NZCV: + cpsr_write(env, *(uint32_t *)value, CPSR_NZCV, CPSRWriteRaw); + break; + case UC_ARM_REG_CPSR: + cpsr_write(env, *(uint32_t *)value, ~0, CPSRWriteRaw); + break; + case UC_ARM_REG_SPSR: + env->spsr = *(uint32_t *)value; + break; + // case UC_ARM_REG_SP: + case UC_ARM_REG_R13: + env->regs[13] = *(uint32_t *)value; + break; + // case UC_ARM_REG_LR: + case UC_ARM_REG_R14: + env->regs[14] = *(uint32_t *)value; + break; + // case UC_ARM_REG_PC: + case UC_ARM_REG_R15: + env->pc = (*(uint32_t *)value & ~1); + env->thumb = (*(uint32_t *)value & 1); + env->uc->thumb = (*(uint32_t *)value & 1); + env->regs[15] = (*(uint32_t *)value & ~1); + break; // case UC_ARM_REG_C1_C0_2: // env->cp15.c1_coproc = *(int32_t *)value; // break; - case UC_ARM_REG_C13_C0_3: - env->cp15.tpidrro_el[0] = *(int32_t *)value; - break; - case UC_ARM_REG_FPEXC: - env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; - break; - case UC_ARM_REG_IPSR: - v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value); - break; - case UC_ARM_REG_MSP: - helper_v7m_msr(env, 8, *(uint32_t *)value); - break; - case UC_ARM_REG_PSP: - helper_v7m_msr(env, 9, *(uint32_t *)value); - break; - case UC_ARM_REG_CONTROL: - helper_v7m_msr(env, 20, *(uint32_t *)value); - break; - case UC_ARM_REG_EPSR: - v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value); - break; - case UC_ARM_REG_IEPSR: - v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value); - break; - case UC_ARM_REG_PRIMASK: - helper_v7m_msr(env, 16, *(uint32_t *)value); - break; - case UC_ARM_REG_BASEPRI: - helper_v7m_msr(env, 17, *(uint32_t *)value); - break; - case UC_ARM_REG_BASEPRI_MAX: - helper_v7m_msr(env, 18, *(uint32_t *)value); - break; - case UC_ARM_REG_FAULTMASK: - helper_v7m_msr(env, 19, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_G: - v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_APSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR: - case UC_ARM_REG_IAPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR_G: - v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_IAPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR: - case UC_ARM_REG_EAPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR_G: - v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_EAPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR: - case UC_ARM_REG_XPSR_NZCVQ: - v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR_G: - v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value); - break; - case UC_ARM_REG_XPSR_NZCVQG: - v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value); - break; + case UC_ARM_REG_C13_C0_3: + env->cp15.tpidrro_el[0] = *(int32_t *)value; + break; + case UC_ARM_REG_FPEXC: + env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value; + break; + case UC_ARM_REG_IPSR: + v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value); + break; + case UC_ARM_REG_MSP: + helper_v7m_msr(env, 8, *(uint32_t *)value); + break; + case UC_ARM_REG_PSP: + helper_v7m_msr(env, 9, *(uint32_t *)value); + break; + case UC_ARM_REG_CONTROL: + helper_v7m_msr(env, 20, *(uint32_t *)value); + break; + case UC_ARM_REG_EPSR: + v7m_msr_xpsr(env, 0b1000, 6, *(uint32_t *)value); + break; + case UC_ARM_REG_IEPSR: + v7m_msr_xpsr(env, 0b1000, 7, *(uint32_t *)value); + break; + case UC_ARM_REG_PRIMASK: + helper_v7m_msr(env, 16, *(uint32_t *)value); + break; + case UC_ARM_REG_BASEPRI: + helper_v7m_msr(env, 17, *(uint32_t *)value); + break; + case UC_ARM_REG_BASEPRI_MAX: + helper_v7m_msr(env, 18, *(uint32_t *)value); + break; + case UC_ARM_REG_FAULTMASK: + helper_v7m_msr(env, 19, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_G: + v7m_msr_xpsr(env, 0b0100, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_APSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 0, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR: + case UC_ARM_REG_IAPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR_G: + v7m_msr_xpsr(env, 0b0100, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_IAPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 1, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR: + case UC_ARM_REG_EAPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR_G: + v7m_msr_xpsr(env, 0b0100, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_EAPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 2, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR: + case UC_ARM_REG_XPSR_NZCVQ: + v7m_msr_xpsr(env, 0b1000, 3, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR_G: + v7m_msr_xpsr(env, 0b0100, 3, *(uint32_t *)value); + break; + case UC_ARM_REG_XPSR_NZCVQG: + v7m_msr_xpsr(env, 0b1100, 3, *(uint32_t *)value); + break; } } return; } -int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int count) +int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, + int count) { CPUARMState *env = &(ARM_CPU(uc->cpu)->env); int i; @@ -375,7 +381,8 @@ int arm_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun return 0; } -int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, int count) +int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, + int count) { CPUArchState *env = &(ARM_CPU(uc->cpu)->env); int i; @@ -384,7 +391,7 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i unsigned int regid = regs[i]; const void *value = vals[i]; reg_write(env, regid, value); - if(regid == UC_ARM_REG_R15){ + if (regid == UC_ARM_REG_R15) { // force to quit execution and flush TB uc->quit_request = true; uc_emu_stop(uc); @@ -396,9 +403,11 @@ int arm_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, i DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int armeb_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #else -int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals, int count) +int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, + void **vals, int count) #endif { CPUARMState *env = (CPUARMState *)ctx->data; @@ -415,9 +424,11 @@ int arm_context_reg_read(struct uc_context *ctx, unsigned int *regs, void **vals DEFAULT_VISIBILITY #ifdef TARGET_WORDS_BIGENDIAN -int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int armeb_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #else -int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* const* vals, int count) +int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, + void *const *vals, int count) #endif { CPUARMState *env = (CPUARMState *)ctx->data; @@ -434,33 +445,35 @@ int arm_context_reg_write(struct uc_context *ctx, unsigned int *regs, void* cons static bool arm_stop_interrupt(struct uc_struct *uc, int intno) { - switch(intno) { - default: - return false; - case EXCP_UDEF: - case EXCP_YIELD: - return true; - case EXCP_INVSTATE: - uc->invalid_error = UC_ERR_EXCEPTION; - return true; + switch (intno) { + default: + return false; + case EXCP_UDEF: + case EXCP_YIELD: + return true; + case EXCP_INVSTATE: + uc->invalid_error = UC_ERR_EXCEPTION; + return true; } } -static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result) +static uc_err arm_query(struct uc_struct *uc, uc_query_type type, + size_t *result) { CPUState *mycpu = uc->cpu; uint32_t mode; - switch(type) { - case UC_QUERY_MODE: - // zero out ARM/THUMB mode - mode = uc->mode & ~(UC_MODE_ARM | UC_MODE_THUMB); - // THUMB mode or ARM MOde - mode += ((ARM_CPU(mycpu)->env.thumb != 0)? UC_MODE_THUMB : UC_MODE_ARM); - *result = mode; - return UC_ERR_OK; - default: - return UC_ERR_ARG; + switch (type) { + case UC_QUERY_MODE: + // zero out ARM/THUMB mode + mode = uc->mode & ~(UC_MODE_ARM | UC_MODE_THUMB); + // THUMB mode or ARM MOde + mode += + ((ARM_CPU(mycpu)->env.thumb != 0) ? UC_MODE_THUMB : UC_MODE_ARM); + *result = mode; + return UC_ERR_OK; + default: + return UC_ERR_ARG; } } @@ -477,9 +490,9 @@ static int arm_cpus_init(struct uc_struct *uc, const char *cpu_model) } #ifdef TARGET_WORDS_BIGENDIAN -void armeb_uc_init(struct uc_struct* uc) +void armeb_uc_init(struct uc_struct *uc) #else -void arm_uc_init(struct uc_struct* uc) +void arm_uc_init(struct uc_struct *uc) #endif { uc->reg_read = arm_reg_read; From c60825bf6e85e57a469e1df3b527d954cf9bf357 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 10:22:30 +0100 Subject: [PATCH 30/40] Remove unused args --- samples/sample_ctl.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 359b1e71..d5e9f36b 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -16,8 +16,6 @@ static void test_uc_ctl_read(void) { uc_engine *uc; uc_err err; - uint32_t tmp; - uc_hook trace1, trace2; int mode, arch; uint32_t pagesize; uint64_t timeout; From 147cb6224015bf4ad3cedeea5c44b187d0f0d6d5 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 10:23:47 +0100 Subject: [PATCH 31/40] Add uc_close --- tests/unit/test_ctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index f2f66625..30d0dede 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -11,6 +11,7 @@ const uint64_t code_len = 0x4000; OK(uc_open(UC_ARCH_X86, UC_MODE_32, &uc)); \ OK(uc_ctl(uc, UC_CTL_READ(ctl_type, 1), &arg)); \ TEST_CHECK(arg == expected); \ + OK(uc_close(uc)); \ } GEN_SIMPLE_READ_TEST(mode, UC_CTL_UC_MODE, int, 4) From f3cb4feec4ff271130a0d6e34778d6d3acb19d3b Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 10:39:31 +0100 Subject: [PATCH 32/40] Fix build on Windows --- uc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/uc.c b/uc.c index 3d765be4..dc52ce8b 100644 --- a/uc.c +++ b/uc.c @@ -1800,7 +1800,8 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) uc_err err = UC_ERR_OK; va_list args; - rw = control >> 30; + // MSVC Would do signed shift on signed integers. + rw = (uint32_t)control >> 30; type = (control & ((1 << 16) - 1)); va_start(args, control); From fe3b798ba77a3e336f0d51386078171e8896dcc2 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 11:02:31 +0100 Subject: [PATCH 33/40] Remove unused args --- samples/sample_ctl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index d5e9f36b..65aeff62 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -20,9 +20,6 @@ static void test_uc_ctl_read(void) uint32_t pagesize; uint64_t timeout; - int r_ecx = 0x1234; // ECX register - int r_edx = 0x7890; // EDX register - printf("Reading some properties by uc_ctl.\n"); // Initialize emulator in X86-32bit mode From a888835962db6b542d16a1eb9585352a5070e84a Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 11:02:44 +0100 Subject: [PATCH 34/40] Fix mingw64 and win32 build --- uc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uc.c b/uc.c index dc52ce8b..d023918e 100644 --- a/uc.c +++ b/uc.c @@ -1828,7 +1828,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) case UC_CTL_UC_TIMEOUT: { if (rw == UC_CTL_IO_READ) { - size_t *arch = va_arg(args, size_t *); + uint64_t *arch = va_arg(args, uint64_t *); *arch = uc->timeout; } else { err = UC_ERR_ARG; From fb45b287ba937a7b54f705df112b26dfba8e8099 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 14:00:43 +0100 Subject: [PATCH 35/40] Add multiple exits mechanism and tests&samples --- include/uc_priv.h | 2 +- samples/sample_ctl.c | 102 +++++++++++++++++++++++++++++++++++++++++- tests/unit/test_ctl.c | 45 +++++++++++++++++++ uc.c | 18 ++++---- 4 files changed, 157 insertions(+), 10 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 19dbecda..7af8d91a 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -300,7 +300,7 @@ struct uc_struct { uint64_t invalid_addr; // invalid address to be accessed int invalid_error; // invalid memory code: 1 = READ, 2 = WRITE, 3 = CODE - int use_exit; + int use_exits; GTree *exits; // addresses where emulation stops (@until param of // uc_emu_start()) Also see UC_CTL_USE_EXITS for more details. diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 65aeff62..88e570aa 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -7,7 +7,17 @@ #include // code to be emulated -#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx; PXOR xmm0, xmm1 + +// INC ecx; DEC edx; PXOR xmm0, xmm1 +#define X86_CODE32 "\x41\x4a" +// cmp eax, 0; +// jg lb; +// inc eax; +// nop; +// lb: +// inc ebx; +// nop; +#define X86_JUMP_CODE "\x83\xf8\x00\x7f\x02\x40\x90\x43\x90" // memory address where emulation starts #define ADDRESS 0x10000 @@ -62,9 +72,99 @@ static void test_uc_ctl_read(void) uc_close(uc); } +void test_uc_ctl_exits() +{ + uc_engine *uc; + uc_err err; + int r_eax, r_ebx; + uint64_t exits[] = {ADDRESS + 6, ADDRESS + 8}; + + printf("Using multiple exits by uc_ctl.\n"); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + err = uc_mem_map(uc, ADDRESS, 0x1000, UC_PROT_ALL); + if (err) { + printf("Failed on uc_mem_map() with error returned: %u\n", err); + return; + } + + // Write our code to the memory. + err = uc_mem_write(uc, ADDRESS, X86_JUMP_CODE, sizeof(X86_JUMP_CODE) - 1); + if (err) { + printf("Failed on uc_mem_write() with error returned: %u\n", err); + return; + } + + // Enable multiple exits. + err = uc_ctl_exits_enabled(uc, true); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + err = uc_ctl_set_exists(uc, exits, 2); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + + // This should stop at ADDRESS + 6 and increase eax, even thouhg we don't + // provide an exit. + err = uc_emu_start(uc, ADDRESS, 0, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + return; + } + + err = uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + err = uc_reg_read(uc, UC_X86_REG_EBX, &r_ebx); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + printf(">>> eax = %" PRId32 " and ebx = %" PRId32 + " after the first emulation\n", + r_eax, r_ebx); + + // This should stop at ADDRESS + 8, even thouhg we don't provide an exit. + err = uc_emu_start(uc, ADDRESS, 0, 0, 0); + if (err) { + printf("Failed on uc_emu_start() with error returned: %u\n", err); + return; + } + + err = uc_reg_read(uc, UC_X86_REG_EAX, &r_eax); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + err = uc_reg_read(uc, UC_X86_REG_EBX, &r_ebx); + if (err) { + printf("Failed on uc_reg_read() with error returned: %u\n", err); + return; + } + printf(">>> eax = %" PRId32 " and ebx = %" PRId32 + " after the second emulation\n", + r_eax, r_ebx); + + uc_close(uc); +} + int main(int argc, char **argv, char **envp) { test_uc_ctl_read(); + printf("====================\n"); + test_uc_ctl_exits(); return 0; } diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 30d0dede..5cf19096 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -3,6 +3,14 @@ const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; +static void uc_common_setup(uc_engine **uc, uc_arch arch, uc_mode mode, + const char *code, uint64_t size) +{ + OK(uc_open(arch, mode, uc)); + OK(uc_mem_map(*uc, code_start, code_len, UC_PROT_ALL)); + OK(uc_mem_write(*uc, code_start, code, size)); +} + #define GEN_SIMPLE_READ_TEST(field, ctl_type, arg_type, expected) \ static void test_uc_ctl_##field() \ { \ @@ -19,8 +27,45 @@ GEN_SIMPLE_READ_TEST(arch, UC_CTL_UC_ARCH, int, 4) GEN_SIMPLE_READ_TEST(page_size, UC_CTL_UC_PAGE_SIZE, uint32_t, 4096) GEN_SIMPLE_READ_TEST(time_out, UC_CTL_UC_TIMEOUT, uint64_t, 0) +static void test_uc_ctl_exits() +{ + uc_engine *uc; + // cmp eax, 0; + // jg lb; + // inc eax; + // nop; <---- exit1 + // lb: + // inc ebx; + // nop; <---- exit2 + char code[] = "\x83\xf8\x00\x7f\x02\x40\x90\x43\x90"; + int r_eax; + int r_ebx; + uint64_t exits[] = {code_start + 6, code_start + 8}; + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + OK(uc_ctl_exits_enabled(uc, true)); + OK(uc_ctl_set_exists(uc, exits, 2)); + r_eax = 0; + r_ebx = 0; + OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_eax)); + OK(uc_reg_write(uc, UC_X86_REG_EAX, &r_ebx)); + + // Run two times. + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + OK(uc_emu_start(uc, code_start, 0, 0, 0)); + + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_eax)); + OK(uc_reg_read(uc, UC_X86_REG_EAX, &r_ebx)); + + TEST_CHECK(r_eax == 1); + TEST_CHECK(r_ebx == 1); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, {"test_uc_ctl_arch", test_uc_ctl_arch}, {"test_uc_ctl_time_out", test_uc_ctl_time_out}, + {"test_uc_ctl_exits", test_uc_ctl_exits}, {NULL, NULL}}; \ No newline at end of file diff --git a/uc.c b/uc.c index d023918e..b8351c97 100644 --- a/uc.c +++ b/uc.c @@ -753,10 +753,12 @@ uc_err uc_emu_start(uc_engine *uc, uint64_t begin, uint64_t until, } } - // This is low efficiency for compatibility. - // Consider a new uc_ctl to set not updating uc->exists in uc_emu_start? - g_tree_remove_all(uc->exits); - uc_add_exit(uc, until); + // If UC_CTL_UC_USE_EXITS is set, then the @until param won't have any + // effect. This is designed for the backward compatibility. + if (!uc->use_exits) { + g_tree_remove_all(uc->exits); + uc_add_exit(uc, until); + } if (timeout) { enable_emu_timer(uc, timeout * 1000); // microseconds -> nanoseconds @@ -1848,8 +1850,8 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } case UC_CTL_UC_USE_EXITS: { if (rw == UC_CTL_IO_WRITE) { - int use_exit = va_arg(args, int); - uc->use_exit = use_exit; + int use_exits = va_arg(args, int); + uc->use_exits = use_exits; } else { err = UC_ERR_ARG; } @@ -1857,7 +1859,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } case UC_CTL_UC_EXITS_CNT: { - if (!uc->use_exit) { + if (!uc->use_exits) { err = UC_ERR_ARG; } else if (rw == UC_CTL_IO_READ) { size_t *exits_cnt = va_arg(args, size_t *); @@ -1869,7 +1871,7 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) } case UC_CTL_UC_EXITS: { - if (!uc->use_exit) { + if (!uc->use_exits) { err = UC_ERR_ARG; } else if (rw == UC_CTL_IO_READ) { uint64_t *exits = va_arg(args, uint64_t *); From cee44b0464b9fed9c5dba51687c7a3b1af7d1100 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 14:46:01 +0100 Subject: [PATCH 36/40] Add tests and samples to show how to control TB cache --- samples/sample_ctl.c | 83 +++++++++++++++++++++++++++++++++++++++++++ tests/unit/test_ctl.c | 51 ++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 88e570aa..54f996b1 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -5,6 +5,7 @@ #include #include +#include // code to be emulated @@ -160,11 +161,93 @@ void test_uc_ctl_exits() uc_close(uc); } +#define TB_COUNT (8) +#define TCG_MAX_INSNS (512) // from tcg.h +#define CODE_LEN TB_COUNT *TCG_MAX_INSNS + +double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) +{ + time_t t1, t2; + + t1 = clock(); + + uc_emu_start(uc, start, end, 0, 0); + + t2 = clock(); + + return (t2 - t1) * 1000.0 / CLOCKS_PER_SEC; +} + +static void test_uc_ctl_tb_cache() +{ + uc_engine *uc; + uc_err err; + char code[CODE_LEN]; + double standard, cached, evicted; + + // Fill the code buffer with NOP. + memset(code, 0x90, CODE_LEN); + + // Initialize emulator in X86-32bit mode + err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); + if (err) { + printf("Failed on uc_open() with error returned: %u\n", err); + return; + } + + err = uc_mem_map(uc, ADDRESS, 0x10000, UC_PROT_ALL); + if (err) { + printf("Failed on uc_mem_map() with error returned: %u\n", err); + return; + } + + // Write our code to the memory. + err = uc_mem_write(uc, ADDRESS, code, sizeof(code) - 1); + if (err) { + printf("Failed on uc_mem_write() with error returned: %u\n", err); + return; + } + + // Do emulation without any cache. + standard = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + // Now we request cache for all TBs. + for (int i = 0; i < TB_COUNT; i++) { + err = uc_ctl_request_cache(uc, ADDRESS + i * TCG_MAX_INSNS); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + } + + // Do emulation with all TB cached. + cached = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + // Now we clear cache for all TBs. + for (int i = 0; i < TB_COUNT; i++) { + err = uc_ctl_remove_cache(uc, ADDRESS + i * TCG_MAX_INSNS); + if (err) { + printf("Failed on uc_ctl() with error returned: %u\n", err); + return; + } + } + + // Do emulation with all TB cache evicted. + evicted = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1); + + printf(">>> Run time: First time: %f, Cached: %f, Cache evicted: %f\n", + standard, cached, evicted); + + uc_close(uc); +} + int main(int argc, char **argv, char **envp) { test_uc_ctl_read(); printf("====================\n"); test_uc_ctl_exits(); + printf("====================\n"); + test_uc_ctl_tb_cache(); return 0; } diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 5cf19096..06fea9f4 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -1,4 +1,6 @@ #include "unicorn_test.h" +#include +#include const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; @@ -63,9 +65,58 @@ static void test_uc_ctl_exits() OK(uc_close(uc)); } +double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) +{ + time_t t1, t2; + + t1 = clock(); + + OK(uc_emu_start(uc, start, end, 0, 0)); + + t2 = clock(); + + return (t2 - t1) * 1000.0 / CLOCKS_PER_SEC; +} + +#define TB_COUNT (8) +#define TCG_MAX_INSNS (512) // from tcg.h +#define CODE_LEN TB_COUNT *TCG_MAX_INSNS + +static void test_uc_ctl_tb_cache() +{ + uc_engine *uc; + char code[CODE_LEN]; + double standard, cached, evicted; + + memset(code, 0x90, CODE_LEN); + + uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); + + standard = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + for (int i = 0; i < TB_COUNT; i++) { + OK(uc_ctl_request_cache(uc, code_start + i * TCG_MAX_INSNS)); + } + + cached = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + for (int i = 0; i < TB_COUNT; i++) { + OK(uc_ctl_remove_cache(uc, code_start + i * TCG_MAX_INSNS)); + } + evicted = time_emulation(uc, code_start, code_start + sizeof(code) - 1); + + // In fact, evicted is also slightly faster than standard but we don't do + // this guarantee. + TEST_CHECK(cached < standard); + TEST_CHECK(evicted > cached); + + OK(uc_close(uc)); +} + TEST_LIST = {{"test_uc_ctl_mode", test_uc_ctl_mode}, {"test_uc_ctl_page_size", test_uc_ctl_page_size}, {"test_uc_ctl_arch", test_uc_ctl_arch}, {"test_uc_ctl_time_out", test_uc_ctl_time_out}, {"test_uc_ctl_exits", test_uc_ctl_exits}, + {"test_uc_ctl_tb_cache", test_uc_ctl_tb_cache}, {NULL, NULL}}; \ No newline at end of file From 97046185954b6cc04ae6fe1f10b1ee59a9c2fe98 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 15:33:36 +0100 Subject: [PATCH 37/40] Fix test for Android due to clock() not working --- tests/unit/test_ctl.c | 98 +++++++++++++++++++++++++++++++++++++-- tests/unit/unicorn_test.h | 1 + 2 files changed, 95 insertions(+), 4 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 06fea9f4..be795d36 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -2,6 +2,94 @@ #include #include +// We have to copy this for Android. +#ifdef _WIN32 + +#include "windows.h" + +static int64_t clock_freq; + +static inline int64_t get_clock_realtime(void) +{ + // code from + // https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows + // >>>>>>>>> + const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); + + long tv_sec, tv_usec; + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime(&system_time); + SystemTimeToFileTime(&system_time, &file_time); + time = ((uint64_t)file_time.dwLowDateTime); + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tv_sec = (long)((time - EPOCH) / 10000000L); + tv_usec = (long)(system_time.wMilliseconds * 1000); + // <<<<<<<<< + + return tv_sec * 1000000000LL + (tv_usec * 1000); +} + +static void init_get_clock(void) +{ + LARGE_INTEGER freq; + int ret = QueryPerformanceFrequency(&freq); + if (ret == 0) { + fprintf(stderr, "Could not calibrate ticks\n"); + exit(1); + } + clock_freq = freq.QuadPart; +} + +static inline int64_t get_clock(void) +{ + LARGE_INTEGER ti; + QueryPerformanceCounter(&ti); + return muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq); +} + +#else + +#include + +static int use_rt_clock; + +/* get host real time in nanosecond */ +static inline int64_t get_clock_realtime(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); +} + +static void init_get_clock(void) +{ + struct timespec ts; + + use_rt_clock = 0; + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + use_rt_clock = 1; + } +} + +static inline int64_t get_clock(void) +{ + if (use_rt_clock) { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000000000LL + ts.tv_nsec; + } else { + /* XXX: using gettimeofday leads to problems if the date + changes, so it should be avoided. */ + return get_clock_realtime(); + } +} +#endif + const uint64_t code_start = 0x1000; const uint64_t code_len = 0x4000; @@ -67,15 +155,15 @@ static void test_uc_ctl_exits() double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) { - time_t t1, t2; + int64_t t1, t2; - t1 = clock(); + t1 = get_clock(); OK(uc_emu_start(uc, start, end, 0, 0)); - t2 = clock(); + t2 = get_clock(); - return (t2 - t1) * 1000.0 / CLOCKS_PER_SEC; + return t2 - t1; } #define TB_COUNT (8) @@ -88,6 +176,8 @@ static void test_uc_ctl_tb_cache() char code[CODE_LEN]; double standard, cached, evicted; + init_get_clock(); + memset(code, 0x90, CODE_LEN); uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); diff --git a/tests/unit/unicorn_test.h b/tests/unit/unicorn_test.h index 8c47310c..a2e12042 100644 --- a/tests/unit/unicorn_test.h +++ b/tests/unit/unicorn_test.h @@ -2,6 +2,7 @@ #define UNICORN_TEST_H #include +#include #include #include "acutest.h" From 14e175394be53799dd4a3d29cd0d533b885b201e Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 19:43:30 +0100 Subject: [PATCH 38/40] Fix Win32 time function for test_ctl --- tests/unit/test_ctl.c | 51 ++----------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index be795d36..4be60a54 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -7,8 +7,6 @@ #include "windows.h" -static int64_t clock_freq; - static inline int64_t get_clock_realtime(void) { // code from @@ -32,31 +30,10 @@ static inline int64_t get_clock_realtime(void) return tv_sec * 1000000000LL + (tv_usec * 1000); } - -static void init_get_clock(void) -{ - LARGE_INTEGER freq; - int ret = QueryPerformanceFrequency(&freq); - if (ret == 0) { - fprintf(stderr, "Could not calibrate ticks\n"); - exit(1); - } - clock_freq = freq.QuadPart; -} - -static inline int64_t get_clock(void) -{ - LARGE_INTEGER ti; - QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, NANOSECONDS_PER_SECOND, clock_freq); -} - #else #include -static int use_rt_clock; - /* get host real time in nanosecond */ static inline int64_t get_clock_realtime(void) { @@ -66,28 +43,6 @@ static inline int64_t get_clock_realtime(void) return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); } -static void init_get_clock(void) -{ - struct timespec ts; - - use_rt_clock = 0; - if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - use_rt_clock = 1; - } -} - -static inline int64_t get_clock(void) -{ - if (use_rt_clock) { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return ts.tv_sec * 1000000000LL + ts.tv_nsec; - } else { - /* XXX: using gettimeofday leads to problems if the date - changes, so it should be avoided. */ - return get_clock_realtime(); - } -} #endif const uint64_t code_start = 0x1000; @@ -157,11 +112,11 @@ double time_emulation(uc_engine *uc, uint64_t start, uint64_t end) { int64_t t1, t2; - t1 = get_clock(); + t1 = get_clock_realtime(); OK(uc_emu_start(uc, start, end, 0, 0)); - t2 = get_clock(); + t2 = get_clock_realtime(); return t2 - t1; } @@ -176,8 +131,6 @@ static void test_uc_ctl_tb_cache() char code[CODE_LEN]; double standard, cached, evicted; - init_get_clock(); - memset(code, 0x90, CODE_LEN); uc_common_setup(&uc, UC_ARCH_X86, UC_MODE_32, code, sizeof(code) - 1); From b7e82d460ca2b42c5a61e0f87530732367e8af67 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 22:11:43 +0100 Subject: [PATCH 39/40] Expose more TB related stuff --- include/uc_priv.h | 3 +- include/unicorn/unicorn.h | 13 +++++++-- qemu/accel/tcg/translate-all.c | 50 +++++++++++++++++++--------------- samples/sample_ctl.c | 8 +++++- tests/unit/test_ctl.c | 2 +- uc.c | 5 ++-- 6 files changed, 50 insertions(+), 31 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index 7af8d91a..d4223d37 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -121,8 +121,7 @@ typedef void (*uc_invalidate_tb_t)(struct uc_struct *uc, uint64_t start, size_t len); // Request generating TB at given address -typedef struct TranslationBlock *(*uc_gen_tb_t)(struct uc_struct *uc, - uint64_t pc); +typedef uc_err (*uc_gen_tb_t)(struct uc_struct *uc, uint64_t pc, uc_tb *out_tb); struct hook { int type; // UC_HOOK_* diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index a9f49650..2d29094f 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -391,6 +391,13 @@ typedef enum uc_query_type { // result = True) } uc_query_type; +// Represent a TranslationBlock. +typedef struct uc_tb { + uint64_t pc; + uint16_t icount; + uint16_t size; +} uc_tb; + // The implementation of uc_ctl is like what Linux ioctl does but slightly // different. // @@ -461,7 +468,7 @@ typedef enum uc_control_type { // Read: @args = (int) UC_CTL_CPU_MODEL, // Request a tb cache at a specific address - // Read: @args = (uint64_t) + // Read: @args = (uint64_t, uc_tb*) UC_CTL_TB_REQUEST_CACHE, // Invalidate a tb cache at a specific address // Read: @args = (uint64_t) @@ -493,8 +500,8 @@ typedef enum uc_control_type { uc_ctl(uc, UC_CTL_WRITE(UC_CTL_CPU_MODEL, 1), (model)) #define uc_ctl_remove_cache(uc, address) \ uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REMOVE_CACHE, 1), (address)) -#define uc_ctl_request_cache(uc, address) \ - uc_ctl(uc, UC_CTL_READ(UC_CTL_TB_REQUEST_CACHE, 1), (address)) +#define uc_ctl_request_cache(uc, address, tb) \ + uc_ctl(uc, UC_CTL_READ_WRITE(UC_CTL_TB_REQUEST_CACHE, 2), (address), (tb)) // Opaque storage for CPU context, used with uc_context_*() struct uc_context; diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index 5c7f3abe..c9d41e8d 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -999,7 +999,7 @@ static void uc_invalidate_tb(struct uc_struct *uc, uint64_t start_addr, size_t l tb_invalidate_phys_range(uc, start, end); } -static TranslationBlock* uc_gen_tb(struct uc_struct *uc, uint64_t addr) +static uc_err uc_gen_tb(struct uc_struct *uc, uint64_t addr, uc_tb *out_tb) { TranslationBlock *tb; target_ulong cs_base, pc; @@ -1024,31 +1024,37 @@ static TranslationBlock* uc_gen_tb(struct uc_struct *uc, uint64_t addr) cflags &= ~CF_CLUSTER_MASK; cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT; - if (likely(tb && - tb->pc == pc && - tb->cs_base == cs_base && - tb->flags == flags && - tb->trace_vcpu_dstate == *cpu->trace_dstate && - (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) == cflags)) { - return tb; - } + if (unlikely(!(tb && + tb->pc == pc && + tb->cs_base == cs_base && + tb->flags == flags && + tb->trace_vcpu_dstate == *cpu->trace_dstate && + (tb_cflags(tb) & (CF_HASH_MASK | CF_INVALID)) == cflags))) { - tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags); - cpu->tb_jmp_cache[hash] = tb; - - if (tb != NULL) { - return tb; - } - - if (tb == NULL) { - mmap_lock(); - tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); - mmap_unlock(); - /* We add the TB in the virtual pc hash table for the fast lookup */ + tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags); cpu->tb_jmp_cache[hash] = tb; + + if (tb == NULL) { + mmap_lock(); + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); + mmap_unlock(); + /* We add the TB in the virtual pc hash table for the fast lookup */ + cpu->tb_jmp_cache[hash] = tb; + } } - return tb; + // If we still couldn't generate a TB, it must be out of memory. + if (tb == NULL) { + return UC_ERR_NOMEM; + } + + if (out_tb != NULL) { + out_tb->pc = tb->pc; + out_tb->size = tb->size; + out_tb->icount = tb->icount; + } + + return UC_ERR_OK; } /* Must be called before using the QEMU cpus. 'tb_size' is the size diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 54f996b1..593cd9a8 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -182,9 +182,12 @@ static void test_uc_ctl_tb_cache() { uc_engine *uc; uc_err err; + uc_tb tb; char code[CODE_LEN]; double standard, cached, evicted; + printf("Controling the TB cache in a finer granularity by uc_ctl.\n"); + // Fill the code buffer with NOP. memset(code, 0x90, CODE_LEN); @@ -213,7 +216,10 @@ static void test_uc_ctl_tb_cache() // Now we request cache for all TBs. for (int i = 0; i < TB_COUNT; i++) { - err = uc_ctl_request_cache(uc, ADDRESS + i * TCG_MAX_INSNS); + err = uc_ctl_request_cache(uc, ADDRESS + i * TCG_MAX_INSNS, &tb); + printf(">>> TB is cached at 0x%" PRIx64 " which has %" PRIu16 + " instructions with %" PRIu16 " bytes.\n", + tb.pc, tb.icount, tb.size); if (err) { printf("Failed on uc_ctl() with error returned: %u\n", err); return; diff --git a/tests/unit/test_ctl.c b/tests/unit/test_ctl.c index 4be60a54..31594bfc 100644 --- a/tests/unit/test_ctl.c +++ b/tests/unit/test_ctl.c @@ -138,7 +138,7 @@ static void test_uc_ctl_tb_cache() standard = time_emulation(uc, code_start, code_start + sizeof(code) - 1); for (int i = 0; i < TB_COUNT; i++) { - OK(uc_ctl_request_cache(uc, code_start + i * TCG_MAX_INSNS)); + OK(uc_ctl_request_cache(uc, code_start + i * TCG_MAX_INSNS, NULL)); } cached = time_emulation(uc, code_start, code_start + sizeof(code) - 1); diff --git a/uc.c b/uc.c index b8351c97..9b82a0e6 100644 --- a/uc.c +++ b/uc.c @@ -1906,9 +1906,10 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...) break; case UC_CTL_TB_REQUEST_CACHE: { - if (rw == UC_CTL_IO_READ) { + if (rw == UC_CTL_IO_READ_WRITE) { uint64_t addr = va_arg(args, uint64_t); - uc->uc_gen_tb(uc, addr); + uc_tb *tb = va_arg(args, uc_tb *); + err = uc->uc_gen_tb(uc, addr, tb); } else { err = UC_ERR_ARG; } From c11b9aa5c3bd2500ce1fc8821f70d38d26987fd7 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 1 Nov 2021 23:27:35 +0100 Subject: [PATCH 40/40] Add a new hook type UC_HOOK_EDGE_GENERATED and corresponding sample --- include/uc_priv.h | 9 +++++++++ include/unicorn/unicorn.h | 29 ++++++++++++++++++++++------- qemu/accel/tcg/cpu-exec.c | 21 +++++++++++++++++++++ qemu/accel/tcg/translate-all.c | 4 +--- samples/sample_ctl.c | 27 +++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 10 deletions(-) diff --git a/include/uc_priv.h b/include/uc_priv.h index d4223d37..17978aaa 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -157,10 +157,19 @@ typedef enum uc_hook_idx { UC_HOOK_MEM_FETCH_IDX, UC_HOOK_MEM_READ_AFTER_IDX, UC_HOOK_INSN_INVALID_IDX, + UC_HOOK_EDGE_GENERATED_IDX, UC_HOOK_MAX, } uc_hook_idx; +// Copy the essential information from TranslationBlock +#define UC_TB_COPY(uc_tb, tb) \ + do { \ + (uc_tb)->pc = tb->pc; \ + (uc_tb)->icount = tb->icount; \ + (uc_tb)->size = tb->size; \ + } while (0) + // The lowest 6 bits are used for hook type index. #define UC_HOOK_IDX_MASK ((1 << 6) - 1) diff --git a/include/unicorn/unicorn.h b/include/unicorn/unicorn.h index 2d29094f..c30f55a6 100644 --- a/include/unicorn/unicorn.h +++ b/include/unicorn/unicorn.h @@ -232,6 +232,22 @@ typedef uint32_t (*uc_cb_insn_in_t)(uc_engine *uc, uint32_t port, int size, typedef void (*uc_cb_insn_out_t)(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data); +// Represent a TranslationBlock. +typedef struct uc_tb { + uint64_t pc; + uint16_t icount; + uint16_t size; +} uc_tb; + +/* + Callback function for new edges between translation blocks. + + @cur_tb: Current TB which is to be generated. + @prev_tb: The previous TB. +*/ +typedef void (*uc_hook_edge_gen_t)(uc_engine *uc, uc_tb *cur_tb, uc_tb *prev_tb, + void *user_data); + /* Callback function for MMIO read @@ -302,6 +318,12 @@ typedef enum uc_hook_type { UC_HOOK_MEM_READ_AFTER = 1 << 13, // Hook invalid instructions exceptions. UC_HOOK_INSN_INVALID = 1 << 14, + // Hook on new edge generation. Could be useful in program analysis. + // + // NOTE: This is different from UC_HOOK_BLOCK in 2 ways: + // 1. The hook is called before executing code. + // 2. The hook is only called when generation is triggered. + UC_HOOK_EDGE_GENERATED = 1 << 15 } uc_hook_type; // Hook type for all events of unmapped memory access @@ -391,13 +413,6 @@ typedef enum uc_query_type { // result = True) } uc_query_type; -// Represent a TranslationBlock. -typedef struct uc_tb { - uint64_t pc; - uint16_t icount; - uint16_t size; -} uc_tb; - // The implementation of uc_ctl is like what Linux ioctl does but slightly // different. // diff --git a/qemu/accel/tcg/cpu-exec.c b/qemu/accel/tcg/cpu-exec.c index 79bcdd13..99a17273 100644 --- a/qemu/accel/tcg/cpu-exec.c +++ b/qemu/accel/tcg/cpu-exec.c @@ -245,6 +245,10 @@ static inline TranslationBlock *tb_find(CPUState *cpu, TranslationBlock *tb; target_ulong cs_base, pc; uint32_t flags; + uc_tb cur_tb, prev_tb; + uc_engine *uc = cpu->uc; + struct list_item *cur; + struct hook *hook; tb = tb_lookup__cpu_state(cpu, &pc, &cs_base, &flags, cf_mask); if (tb == NULL) { @@ -265,6 +269,23 @@ static inline TranslationBlock *tb_find(CPUState *cpu, if (last_tb) { tb_add_jump(last_tb, tb_exit, tb); } + + UC_TB_COPY(&cur_tb, tb); + + if (last_tb) { + UC_TB_COPY(&prev_tb, last_tb); + for (cur = uc->hook[UC_HOOK_EDGE_GENERATED_IDX].head; + cur != NULL && (hook = (struct hook *)cur->data); cur = cur->next) { + if (hook->to_delete) { + continue; + } + + if (HOOK_BOUND_CHECK(hook, (uint64_t)tb->pc)) { + ((uc_hook_edge_gen_t)hook->callback)(uc, &cur_tb, &prev_tb, hook->user_data); + } + } + } + return tb; } diff --git a/qemu/accel/tcg/translate-all.c b/qemu/accel/tcg/translate-all.c index c9d41e8d..b9f3c272 100644 --- a/qemu/accel/tcg/translate-all.c +++ b/qemu/accel/tcg/translate-all.c @@ -1049,9 +1049,7 @@ static uc_err uc_gen_tb(struct uc_struct *uc, uint64_t addr, uc_tb *out_tb) } if (out_tb != NULL) { - out_tb->pc = tb->pc; - out_tb->size = tb->size; - out_tb->icount = tb->icount; + UC_TB_COPY(out_tb, tb); } return UC_ERR_OK; diff --git a/samples/sample_ctl.c b/samples/sample_ctl.c index 593cd9a8..3e63c4f6 100644 --- a/samples/sample_ctl.c +++ b/samples/sample_ctl.c @@ -73,10 +73,17 @@ static void test_uc_ctl_read(void) uc_close(uc); } +static void trace_new_edge(uc_engine *uc, uc_tb *cur, uc_tb *prev, void *data) +{ + printf(">>> Getting a new edge from 0x%" PRIx64 " to 0x%" PRIx64 ".\n", + prev->pc + prev->size - 1, cur->pc); +} + void test_uc_ctl_exits() { uc_engine *uc; uc_err err; + uc_hook h; int r_eax, r_ebx; uint64_t exits[] = {ADDRESS + 6, ADDRESS + 8}; @@ -102,6 +109,14 @@ void test_uc_ctl_exits() return; } + // We trace if any new edge is generated. + err = uc_hook_add(uc, &h, UC_HOOK_EDGE_GENERATED, trace_new_edge, NULL, 0, + -1); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + return; + } + // Enable multiple exits. err = uc_ctl_exits_enabled(uc, true); if (err) { @@ -183,6 +198,7 @@ static void test_uc_ctl_tb_cache() uc_engine *uc; uc_err err; uc_tb tb; + uc_hook h; char code[CODE_LEN]; double standard, cached, evicted; @@ -211,6 +227,17 @@ static void test_uc_ctl_tb_cache() return; } + // We trace if any new edge is generated. + // Note: In this sample, there is only **one** basic block while muliple + // translation blocks is generated due to QEMU tcg buffer limit. In this + // case, we don't consider it as a new edge. + err = uc_hook_add(uc, &h, UC_HOOK_EDGE_GENERATED, trace_new_edge, NULL, 0, + -1); + if (err) { + printf("Failed on uc_hook_add() with error returned: %u\n", err); + return; + } + // Do emulation without any cache. standard = time_emulation(uc, ADDRESS, ADDRESS + sizeof(code) - 1);