Compare commits
20 Commits
96518634fb
...
c10639fd46
Author | SHA1 | Date | |
---|---|---|---|
c10639fd46 | |||
73e4a90d3a | |||
4266196b2d | |||
16e9efa4f5 | |||
5b2c610527 | |||
e382ca102a | |||
05b9a021dc | |||
d503a69239 | |||
52e0963cc7 | |||
81eb7da837 | |||
141a558dd8 | |||
039cd50187 | |||
63a445cbba | |||
3e9ae003b7 | |||
017c82e561 | |||
4059906e78 | |||
3fadb5aa5a | |||
ad3325548d | |||
21d3181e00 | |||
9233bcc513 |
18
.github/workflows/stale.yml
vendored
Normal file
18
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: 'Close stale issues and PRs'
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 5 * * *'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v4
|
||||||
|
with:
|
||||||
|
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 15 days.'
|
||||||
|
days-before-stale: 60
|
||||||
|
days-before-close: 15
|
||||||
|
exempt-all-milestones: true
|
||||||
|
exempt-issue-labels: 'pinned'
|
||||||
|
exempt-pr-labels: 'pinned'
|
@ -11,13 +11,13 @@ module Common =
|
|||||||
let UC_API_MINOR = 0
|
let UC_API_MINOR = 0
|
||||||
|
|
||||||
let UC_API_PATCH = 0
|
let UC_API_PATCH = 0
|
||||||
let UC_API_EXTRA = 5
|
let UC_API_EXTRA = 6
|
||||||
let UC_VERSION_MAJOR = 2
|
let UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
let UC_VERSION_MINOR = 0
|
let UC_VERSION_MINOR = 0
|
||||||
|
|
||||||
let UC_VERSION_PATCH = 0
|
let UC_VERSION_PATCH = 0
|
||||||
let UC_VERSION_EXTRA = 5
|
let UC_VERSION_EXTRA = 6
|
||||||
let UC_SECOND_SCALE = 1000000
|
let UC_SECOND_SCALE = 1000000
|
||||||
let UC_MILISECOND_SCALE = 1000
|
let UC_MILISECOND_SCALE = 1000
|
||||||
let UC_ARCH_ARM = 1
|
let UC_ARCH_ARM = 1
|
||||||
@ -38,6 +38,7 @@ module Common =
|
|||||||
let UC_MODE_THUMB = 16
|
let UC_MODE_THUMB = 16
|
||||||
let UC_MODE_MCLASS = 32
|
let UC_MODE_MCLASS = 32
|
||||||
let UC_MODE_V8 = 64
|
let UC_MODE_V8 = 64
|
||||||
|
let UC_MODE_ARMBE8 = 128
|
||||||
let UC_MODE_ARM926 = 128
|
let UC_MODE_ARM926 = 128
|
||||||
let UC_MODE_ARM946 = 256
|
let UC_MODE_ARM946 = 256
|
||||||
let UC_MODE_ARM1176 = 512
|
let UC_MODE_ARM1176 = 512
|
||||||
|
@ -6,13 +6,13 @@ const (
|
|||||||
API_MINOR = 0
|
API_MINOR = 0
|
||||||
|
|
||||||
API_PATCH = 0
|
API_PATCH = 0
|
||||||
API_EXTRA = 5
|
API_EXTRA = 6
|
||||||
VERSION_MAJOR = 2
|
VERSION_MAJOR = 2
|
||||||
|
|
||||||
VERSION_MINOR = 0
|
VERSION_MINOR = 0
|
||||||
|
|
||||||
VERSION_PATCH = 0
|
VERSION_PATCH = 0
|
||||||
VERSION_EXTRA = 5
|
VERSION_EXTRA = 6
|
||||||
SECOND_SCALE = 1000000
|
SECOND_SCALE = 1000000
|
||||||
MILISECOND_SCALE = 1000
|
MILISECOND_SCALE = 1000
|
||||||
ARCH_ARM = 1
|
ARCH_ARM = 1
|
||||||
@ -33,6 +33,7 @@ const (
|
|||||||
MODE_THUMB = 16
|
MODE_THUMB = 16
|
||||||
MODE_MCLASS = 32
|
MODE_MCLASS = 32
|
||||||
MODE_V8 = 64
|
MODE_V8 = 64
|
||||||
|
MODE_ARMBE8 = 128
|
||||||
MODE_ARM926 = 128
|
MODE_ARM926 = 128
|
||||||
MODE_ARM946 = 256
|
MODE_ARM946 = 256
|
||||||
MODE_ARM1176 = 512
|
MODE_ARM1176 = 512
|
||||||
|
@ -8,13 +8,13 @@ public interface UnicornConst {
|
|||||||
public static final int UC_API_MINOR = 0;
|
public static final int UC_API_MINOR = 0;
|
||||||
|
|
||||||
public static final int UC_API_PATCH = 0;
|
public static final int UC_API_PATCH = 0;
|
||||||
public static final int UC_API_EXTRA = 5;
|
public static final int UC_API_EXTRA = 6;
|
||||||
public static final int UC_VERSION_MAJOR = 2;
|
public static final int UC_VERSION_MAJOR = 2;
|
||||||
|
|
||||||
public static final int UC_VERSION_MINOR = 0;
|
public static final int UC_VERSION_MINOR = 0;
|
||||||
|
|
||||||
public static final int UC_VERSION_PATCH = 0;
|
public static final int UC_VERSION_PATCH = 0;
|
||||||
public static final int UC_VERSION_EXTRA = 5;
|
public static final int UC_VERSION_EXTRA = 6;
|
||||||
public static final int UC_SECOND_SCALE = 1000000;
|
public static final int UC_SECOND_SCALE = 1000000;
|
||||||
public static final int UC_MILISECOND_SCALE = 1000;
|
public static final int UC_MILISECOND_SCALE = 1000;
|
||||||
public static final int UC_ARCH_ARM = 1;
|
public static final int UC_ARCH_ARM = 1;
|
||||||
@ -35,6 +35,7 @@ public interface UnicornConst {
|
|||||||
public static final int UC_MODE_THUMB = 16;
|
public static final int UC_MODE_THUMB = 16;
|
||||||
public static final int UC_MODE_MCLASS = 32;
|
public static final int UC_MODE_MCLASS = 32;
|
||||||
public static final int UC_MODE_V8 = 64;
|
public static final int UC_MODE_V8 = 64;
|
||||||
|
public static final int UC_MODE_ARMBE8 = 128;
|
||||||
public static final int UC_MODE_ARM926 = 128;
|
public static final int UC_MODE_ARM926 = 128;
|
||||||
public static final int UC_MODE_ARM946 = 256;
|
public static final int UC_MODE_ARM946 = 256;
|
||||||
public static final int UC_MODE_ARM1176 = 512;
|
public static final int UC_MODE_ARM1176 = 512;
|
||||||
|
@ -9,13 +9,13 @@ const UC_API_MAJOR = 2;
|
|||||||
UC_API_MINOR = 0;
|
UC_API_MINOR = 0;
|
||||||
|
|
||||||
UC_API_PATCH = 0;
|
UC_API_PATCH = 0;
|
||||||
UC_API_EXTRA = 5;
|
UC_API_EXTRA = 6;
|
||||||
UC_VERSION_MAJOR = 2;
|
UC_VERSION_MAJOR = 2;
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0;
|
UC_VERSION_MINOR = 0;
|
||||||
|
|
||||||
UC_VERSION_PATCH = 0;
|
UC_VERSION_PATCH = 0;
|
||||||
UC_VERSION_EXTRA = 5;
|
UC_VERSION_EXTRA = 6;
|
||||||
UC_SECOND_SCALE = 1000000;
|
UC_SECOND_SCALE = 1000000;
|
||||||
UC_MILISECOND_SCALE = 1000;
|
UC_MILISECOND_SCALE = 1000;
|
||||||
UC_ARCH_ARM = 1;
|
UC_ARCH_ARM = 1;
|
||||||
@ -36,6 +36,7 @@ const UC_API_MAJOR = 2;
|
|||||||
UC_MODE_THUMB = 16;
|
UC_MODE_THUMB = 16;
|
||||||
UC_MODE_MCLASS = 32;
|
UC_MODE_MCLASS = 32;
|
||||||
UC_MODE_V8 = 64;
|
UC_MODE_V8 = 64;
|
||||||
|
UC_MODE_ARMBE8 = 128;
|
||||||
UC_MODE_ARM926 = 128;
|
UC_MODE_ARM926 = 128;
|
||||||
UC_MODE_ARM946 = 256;
|
UC_MODE_ARM946 = 256;
|
||||||
UC_MODE_ARM1176 = 512;
|
UC_MODE_ARM1176 = 512;
|
||||||
|
@ -29,7 +29,7 @@ SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
|||||||
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
||||||
BUILD_DIR = os.path.join(UC_DIR, 'build_python')
|
BUILD_DIR = os.path.join(UC_DIR, 'build_python')
|
||||||
|
|
||||||
VERSION = "2.0.0rc5.post1"
|
VERSION = "2.0.0rc6"
|
||||||
|
|
||||||
if SYSTEM == 'darwin':
|
if SYSTEM == 'darwin':
|
||||||
LIBRARY_FILE = "libunicorn.dylib"
|
LIBRARY_FILE = "libunicorn.dylib"
|
||||||
|
@ -4,13 +4,13 @@ UC_API_MAJOR = 2
|
|||||||
UC_API_MINOR = 0
|
UC_API_MINOR = 0
|
||||||
|
|
||||||
UC_API_PATCH = 0
|
UC_API_PATCH = 0
|
||||||
UC_API_EXTRA = 5
|
UC_API_EXTRA = 6
|
||||||
UC_VERSION_MAJOR = 2
|
UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0
|
UC_VERSION_MINOR = 0
|
||||||
|
|
||||||
UC_VERSION_PATCH = 0
|
UC_VERSION_PATCH = 0
|
||||||
UC_VERSION_EXTRA = 5
|
UC_VERSION_EXTRA = 6
|
||||||
UC_SECOND_SCALE = 1000000
|
UC_SECOND_SCALE = 1000000
|
||||||
UC_MILISECOND_SCALE = 1000
|
UC_MILISECOND_SCALE = 1000
|
||||||
UC_ARCH_ARM = 1
|
UC_ARCH_ARM = 1
|
||||||
@ -31,6 +31,7 @@ UC_MODE_ARM = 0
|
|||||||
UC_MODE_THUMB = 16
|
UC_MODE_THUMB = 16
|
||||||
UC_MODE_MCLASS = 32
|
UC_MODE_MCLASS = 32
|
||||||
UC_MODE_V8 = 64
|
UC_MODE_V8 = 64
|
||||||
|
UC_MODE_ARMBE8 = 128
|
||||||
UC_MODE_ARM926 = 128
|
UC_MODE_ARM926 = 128
|
||||||
UC_MODE_ARM946 = 256
|
UC_MODE_ARM946 = 256
|
||||||
UC_MODE_ARM1176 = 512
|
UC_MODE_ARM1176 = 512
|
||||||
|
@ -6,13 +6,13 @@ module UnicornEngine
|
|||||||
UC_API_MINOR = 0
|
UC_API_MINOR = 0
|
||||||
|
|
||||||
UC_API_PATCH = 0
|
UC_API_PATCH = 0
|
||||||
UC_API_EXTRA = 5
|
UC_API_EXTRA = 6
|
||||||
UC_VERSION_MAJOR = 2
|
UC_VERSION_MAJOR = 2
|
||||||
|
|
||||||
UC_VERSION_MINOR = 0
|
UC_VERSION_MINOR = 0
|
||||||
|
|
||||||
UC_VERSION_PATCH = 0
|
UC_VERSION_PATCH = 0
|
||||||
UC_VERSION_EXTRA = 5
|
UC_VERSION_EXTRA = 6
|
||||||
UC_SECOND_SCALE = 1000000
|
UC_SECOND_SCALE = 1000000
|
||||||
UC_MILISECOND_SCALE = 1000
|
UC_MILISECOND_SCALE = 1000
|
||||||
UC_ARCH_ARM = 1
|
UC_ARCH_ARM = 1
|
||||||
@ -33,6 +33,7 @@ module UnicornEngine
|
|||||||
UC_MODE_THUMB = 16
|
UC_MODE_THUMB = 16
|
||||||
UC_MODE_MCLASS = 32
|
UC_MODE_MCLASS = 32
|
||||||
UC_MODE_V8 = 64
|
UC_MODE_V8 = 64
|
||||||
|
UC_MODE_ARMBE8 = 128
|
||||||
UC_MODE_ARM926 = 128
|
UC_MODE_ARM926 = 128
|
||||||
UC_MODE_ARM946 = 256
|
UC_MODE_ARM946 = 256
|
||||||
UC_MODE_ARM1176 = 512
|
UC_MODE_ARM1176 = 512
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "unicorn-engine"
|
name = "unicorn-engine"
|
||||||
version = "2.0.0-rc5.post1"
|
version = "2.0.0-rc6"
|
||||||
authors = ["Ziqiao Kong", "Lukas Seidel"]
|
authors = ["Ziqiao Kong", "Lukas Seidel"]
|
||||||
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
|
documentation = "https://github.com/unicorn-engine/unicorn/wiki"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
@ -24,8 +24,14 @@ bitflags = "1.3"
|
|||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build-helper = "0.1"
|
reqwest = { optional = true, version = "0.11", features = ["blocking"] }
|
||||||
reqwest = { version = "0.11", features = ["blocking"] }
|
flate2 = { optional = true, version = "1.0" }
|
||||||
flate2 = "1.0.22"
|
tar = { optional = true, version = "0.4" }
|
||||||
tar = "0.4.37"
|
bytes = { optional = true, version = "1" }
|
||||||
bytes = "1.1.0"
|
pkg-config = { optional = true, version = "0.3" }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["build_unicorn_cmake"]
|
||||||
|
|
||||||
|
use_system_unicorn = ["pkg-config"]
|
||||||
|
build_unicorn_cmake = ["reqwest", "flate2", "tar", "bytes"]
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use bytes::Buf;
|
use bytes::Buf;
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
#[cfg(feature = "use_system_unicorn")]
|
||||||
|
use pkg_config;
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use reqwest::header::USER_AGENT;
|
use reqwest::header::USER_AGENT;
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use std::{env, process::Command};
|
use std::{env, process::Command};
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
use tar::Archive;
|
use tar::Archive;
|
||||||
|
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
fn find_unicorn(unicorn_dir: &Path) -> Option<PathBuf> {
|
fn find_unicorn(unicorn_dir: &Path) -> Option<PathBuf> {
|
||||||
for entry in std::fs::read_dir(unicorn_dir).ok()? {
|
for entry in std::fs::read_dir(unicorn_dir).ok()? {
|
||||||
let entry = entry.unwrap();
|
let entry = entry.unwrap();
|
||||||
@ -18,11 +27,13 @@ fn find_unicorn(unicorn_dir: &Path) -> Option<PathBuf> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
fn out_dir() -> PathBuf {
|
fn out_dir() -> PathBuf {
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
Path::new(&out_dir).to_path_buf()
|
Path::new(&out_dir).to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
fn download_unicorn() -> PathBuf {
|
fn download_unicorn() -> PathBuf {
|
||||||
// https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-tar
|
// https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-tar
|
||||||
let pkg_version;
|
let pkg_version;
|
||||||
@ -51,8 +62,9 @@ fn download_unicorn() -> PathBuf {
|
|||||||
find_unicorn(&out_dir).unwrap()
|
find_unicorn(&out_dir).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
#[allow(clippy::branches_sharing_code)]
|
#[allow(clippy::branches_sharing_code)]
|
||||||
fn main() {
|
fn build_with_cmake() {
|
||||||
let profile = env::var("PROFILE").unwrap();
|
let profile = env::var("PROFILE").unwrap();
|
||||||
|
|
||||||
if let Some(unicorn_dir) = find_unicorn(&out_dir()) {
|
if let Some(unicorn_dir) = find_unicorn(&out_dir()) {
|
||||||
@ -183,3 +195,16 @@ fn main() {
|
|||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rerun-if-changed=src");
|
println!("cargo:rerun-if-changed=src");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
if cfg!(feature = "use_system_unicorn") {
|
||||||
|
#[cfg(feature = "use_system_unicorn")]
|
||||||
|
pkg_config::Config::new()
|
||||||
|
.atleast_version("2")
|
||||||
|
.probe("unicorn")
|
||||||
|
.expect("Could not find system unicorn2");
|
||||||
|
} else {
|
||||||
|
#[cfg(feature = "build_unicorn_cmake")]
|
||||||
|
build_with_cmake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -52,7 +52,7 @@ msbuild unicorn.sln -p:Plaform=Win32 -p:Configuration=Release
|
|||||||
|
|
||||||
## Cross build with NDK
|
## Cross build with NDK
|
||||||
|
|
||||||
To build Unicorn2 on the Android platform, firstly you need to download [NDK](https://developer.android.com/ndk/downloads).
|
To cross-build and run Unicorn2 on the Android platform, firstly you need to download [NDK](https://developer.android.com/ndk/downloads).
|
||||||
|
|
||||||
For newer NDK, please make sure your cmake version is above 3.19.
|
For newer NDK, please make sure your cmake version is above 3.19.
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ You may get the possible values from this [page](https://developer.android.com/n
|
|||||||
|
|
||||||
Unicorn2 support cross-build for `armeabi-v7a`, `arm64-v8a`, `x86` and `x86_64`.
|
Unicorn2 support cross-build for `armeabi-v7a`, `arm64-v8a`, `x86` and `x86_64`.
|
||||||
|
|
||||||
Note the build is only tested and guaranteed to work under Linux, however, other systems may still work.
|
Note the build is only tested and guaranteed to work under Linux and macOS, however, other systems may still work.
|
||||||
|
|
||||||
## Cross build from Linux host to Windows, with Mingw
|
## Cross build from Linux host to Windows, with Mingw
|
||||||
|
|
||||||
@ -97,15 +97,16 @@ This requires MSYS2 to be installed on the Windows machine. You need to download
|
|||||||
Then from MSYS2 console, install packages below:
|
Then from MSYS2 console, install packages below:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake
|
pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja
|
||||||
```
|
```
|
||||||
|
|
||||||
- Build Unicorn and samples with the following commands.
|
- Build Unicorn and samples with the following commands.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
export PATH=/mingw64/bin:$PATH
|
||||||
mkdir build; cd build
|
mkdir build; cd build
|
||||||
/mingw64/bin/cmake .. -G "MSYS Makefiles" -DCMAKE_C_COMPILER=/mingw64/bin/gcc.exe -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make.exe -DCMAKE_AR=/mingw64/bin/ar.exe -DUNICORN_ARCH=x86
|
/mingw64/bin/cmake .. -G "Ninja"
|
||||||
mingw32-make
|
ninja -C .
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the way to build on MSYS changes as time goes, please keep in mind that always use the cmake shipped with mingw64 and choose MSYS Makefiles.
|
Note that the way to build on MSYS changes as time goes, please keep in mind that always use the cmake shipped with mingw64 and choose MSYS Makefiles.
|
||||||
|
68
docs/FAQ.md
Normal file
68
docs/FAQ.md
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
## Why is my execution so slow?
|
||||||
|
|
||||||
|
Typically, it’s due to
|
||||||
|
|
||||||
|
- Instrumenting every instruction executed.
|
||||||
|
- Instrumenting every memory access.
|
||||||
|
|
||||||
|
Optimize your program with less instrumentation.
|
||||||
|
|
||||||
|
## Why do I get a wrong PC after emulation stops?
|
||||||
|
|
||||||
|
PC is only guaranteed to be correct if you install `UC_HOOK_CODE`. This is due to the fact that updating PC is a big performance overhead during emulation.
|
||||||
|
|
||||||
|
## I get an “Unhandled CPU Exception”, why?
|
||||||
|
|
||||||
|
Unicorn is a pure CPU emulator and usually it’s due to no handler registered for instructions like `syscall` and `SVC`. If you expect system emulation, you probably would like [qiling framework](https://github.com/qilingframework/qiling).
|
||||||
|
|
||||||
|
## I would like to instrument a specific instruction but get a `UC_ERR_HOOK`, why?
|
||||||
|
|
||||||
|
Currently, only a small subset of the instructions can be instrumented.
|
||||||
|
|
||||||
|
On x86, all available instructions are: `in` `out` `syscall` `sysenter` `cpuid`.
|
||||||
|
|
||||||
|
## Emulating some instructions gives an error, what should I do?
|
||||||
|
|
||||||
|
1. Some instructions are not enabled by default on some architectures. For example, you have to setup CSR on RISC-V or VFP on ARM before emulating floating-point instructions. Refer to the corresponding manual to check if you leave out possible switches in special registers.
|
||||||
|
2. If you are on ARM, please check whether you are emulating a THUMB instruction. If so, please use `UC_MODE_THUMB` and make sure the starting address is odd.
|
||||||
|
3. If either is not the case, it might be some newer instruction sets that qemu5 doesn’t support.
|
||||||
|
|
||||||
|
If you are still using Unicorn1, please upgrade to Unicorn2 for better support.
|
||||||
|
|
||||||
|
## I can't recover from unmapped read/write even I return `true` in the hook, why?
|
||||||
|
|
||||||
|
This is a minor change in memory hooks behavior between Unicorn1 and Unicorn2. To gracefully recover from memory read/write error, you have to map the invalid memory before you return true.
|
||||||
|
|
||||||
|
It is due to the fact that, if users return `true` without memory mapping set up correctly, we don't know what to do next. In Unicorn1, the behavior is __undefined__ in this case but in Unicorn2 we would like to force users to set up memory mapping in the hook to continue execution.
|
||||||
|
|
||||||
|
See the [sample](https://github.com/unicorn-engine/unicorn/blob/c05fbb7e63aed0b60fc2888e08beceb17bce8ac4/samples/sample_x86.c#L1379-L1393) for details.
|
||||||
|
|
||||||
|
## How to emulate interrupts (or ticks) with Unicorn?
|
||||||
|
|
||||||
|
As stated, Unicorn is a pure CPU emulator. For such emulation, you have two choices:
|
||||||
|
|
||||||
|
- Use the `timeout` parameter of `uc_emu_start`
|
||||||
|
- Use the `count` parameter of `uc_emu_start`
|
||||||
|
|
||||||
|
After emulation stops, you may check anything you feel interested and resume emulation accordingly.
|
||||||
|
|
||||||
|
Note that for cortex-m `exec_return`, Unicorn has a magic software exception with interrupt number 8. You may register a hook to handle that.
|
||||||
|
|
||||||
|
## Why not keep up the upstream qemu?
|
||||||
|
|
||||||
|
To provide end users with simple API, Unicorn does lots of dirty hacks within qemu code which prevents it from sync painlessly.
|
||||||
|
|
||||||
|
## Is there anyway to disable softmmu to speed up execution?
|
||||||
|
|
||||||
|
Yes, it’s possible but that is not Unicorn’s goal and there is no simple switch in qemu to disable softmmu.
|
||||||
|
|
||||||
|
## I'd like to make contributions, where do I start?
|
||||||
|
|
||||||
|
See [milestones](https://github.com/unicorn-engine/unicorn/milestones) and [coding convention](https://github.com/unicorn-engine/unicorn/wiki/Coding-Convention
|
||||||
|
).
|
||||||
|
|
||||||
|
Be sure to send pull requests for our **dev** branch only.
|
||||||
|
|
||||||
|
## Which qemu version is Unicorn based on?
|
||||||
|
|
||||||
|
Prior to 2.0.0, Unicorn is based on qemu 2.2.1. After that, Unicorn is based on qemu 5.0.1.
|
@ -72,7 +72,7 @@ typedef size_t uc_hook;
|
|||||||
#define UC_API_MAJOR 2
|
#define UC_API_MAJOR 2
|
||||||
#define UC_API_MINOR 0
|
#define UC_API_MINOR 0
|
||||||
#define UC_API_PATCH 0
|
#define UC_API_PATCH 0
|
||||||
#define UC_API_EXTRA 5
|
#define UC_API_EXTRA 6
|
||||||
|
|
||||||
// Unicorn package version
|
// Unicorn package version
|
||||||
#define UC_VERSION_MAJOR UC_API_MAJOR
|
#define UC_VERSION_MAJOR UC_API_MAJOR
|
||||||
|
@ -2192,6 +2192,10 @@ ARMCPU *cpu_arm_init(struct uc_struct *uc)
|
|||||||
// Big endian code access.
|
// Big endian code access.
|
||||||
env->cp15.sctlr_ns |= SCTLR_B;
|
env->cp15.sctlr_ns |= SCTLR_B;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backward compatiblity, start arm CPU in non-secure state.
|
||||||
|
env->cp15.scr_el3 |= SCR_NS;
|
||||||
|
|
||||||
arm_rebuild_hflags(env);
|
arm_rebuild_hflags(env);
|
||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
|
@ -378,6 +378,9 @@ ARMCPU *cpu_aarch64_init(struct uc_struct *uc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backward compatability to enable FULL 64bits address space.
|
||||||
|
env->pstate = PSTATE_MODE_EL1h;
|
||||||
|
|
||||||
arm_rebuild_hflags(env);
|
arm_rebuild_hflags(env);
|
||||||
|
|
||||||
return cpu;
|
return cpu;
|
||||||
|
@ -7927,7 +7927,9 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask,
|
|||||||
* In a V8 implementation, it is permitted for privileged software to
|
* In a V8 implementation, it is permitted for privileged software to
|
||||||
* change the CPSR A/F bits regardless of the SCR.AW/FW bits.
|
* change the CPSR A/F bits regardless of the SCR.AW/FW bits.
|
||||||
*/
|
*/
|
||||||
if (write_type != CPSRWriteRaw && !arm_feature(env, ARM_FEATURE_V8) &&
|
if (write_type != CPSRWriteByUnicorn &&
|
||||||
|
write_type != CPSRWriteRaw &&
|
||||||
|
!arm_feature(env, ARM_FEATURE_V8) &&
|
||||||
arm_feature(env, ARM_FEATURE_EL3) &&
|
arm_feature(env, ARM_FEATURE_EL3) &&
|
||||||
!arm_feature(env, ARM_FEATURE_EL2) &&
|
!arm_feature(env, ARM_FEATURE_EL2) &&
|
||||||
!arm_is_secure(env)) {
|
!arm_is_secure(env)) {
|
||||||
|
@ -248,6 +248,12 @@ static uc_err reg_read(CPUARMState *env, unsigned int regid, void *value)
|
|||||||
case UC_ARM_REG_FPEXC:
|
case UC_ARM_REG_FPEXC:
|
||||||
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC];
|
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPEXC];
|
||||||
break;
|
break;
|
||||||
|
case UC_ARM_REG_FPSCR:
|
||||||
|
*(int32_t *)value = vfp_get_fpscr(env);
|
||||||
|
break;
|
||||||
|
case UC_ARM_REG_FPSID:
|
||||||
|
*(int32_t *)value = env->vfp.xregs[ARM_VFP_FPSID];
|
||||||
|
break;
|
||||||
case UC_ARM_REG_IPSR:
|
case UC_ARM_REG_IPSR:
|
||||||
*(int32_t *)value = v7m_mrs_xpsr(env, 5);
|
*(int32_t *)value = v7m_mrs_xpsr(env, 5);
|
||||||
break;
|
break;
|
||||||
@ -353,6 +359,12 @@ static uc_err reg_write(CPUARMState *env, unsigned int regid, const void *value)
|
|||||||
case UC_ARM_REG_FPEXC:
|
case UC_ARM_REG_FPEXC:
|
||||||
env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value;
|
env->vfp.xregs[ARM_VFP_FPEXC] = *(int32_t *)value;
|
||||||
break;
|
break;
|
||||||
|
case UC_ARM_REG_FPSCR:
|
||||||
|
vfp_set_fpscr(env, *(int32_t *)value);
|
||||||
|
break;
|
||||||
|
case UC_ARM_REG_FPSID:
|
||||||
|
env->vfp.xregs[ARM_VFP_FPSID] = *(int32_t *)value;
|
||||||
|
break;
|
||||||
case UC_ARM_REG_IPSR:
|
case UC_ARM_REG_IPSR:
|
||||||
v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value);
|
v7m_msr_xpsr(env, 0b1000, 5, *(uint32_t *)value);
|
||||||
break;
|
break;
|
||||||
|
@ -491,13 +491,13 @@ static void test_arm_not_allow_privilege_escalation()
|
|||||||
static void test_arm_mrc()
|
static void test_arm_mrc()
|
||||||
{
|
{
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
// mrc p15, #0, r0, c1, c1, #0
|
// mrc p15, #0, r1, c13, c0, #3
|
||||||
char code[] = "\x11\x0F\x11\xEE";
|
char code[] = "\x1d\xee\x70\x1f";
|
||||||
|
|
||||||
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1,
|
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_THUMB, code, sizeof(code) - 1,
|
||||||
UC_CPU_ARM_MAX);
|
UC_CPU_ARM_MAX);
|
||||||
|
|
||||||
OK(uc_emu_start(uc, code_start, code_start + sizeof(code) - 1, 0, 0));
|
OK(uc_emu_start(uc, code_start | 1, code_start + sizeof(code) - 1, 0, 0));
|
||||||
|
|
||||||
OK(uc_close(uc));
|
OK(uc_close(uc));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user