Merge branch 'dev' into systemz
This commit is contained in:
commit
7095605607
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,3 +1,3 @@
|
||||
[submodule "docs/Unicorn_Engine_Documentation"]
|
||||
path = docs/Unicorn_Engine_Documentation
|
||||
url = git@github.com:kabeor/Unicorn-Engine-Documentation
|
||||
url = https://github.com/kabeor/Unicorn-Engine-Documentation
|
||||
|
@ -20,6 +20,8 @@ if (NOT UNICORN_ARCH)
|
||||
set(UNICORN_ARCH "x86 arm aarch64 riscv mips sparc m68k ppc s390x")
|
||||
endif()
|
||||
|
||||
option(UNICORN_TRACER "Trace unicorn execution" OFF)
|
||||
|
||||
string(TOUPPER ${UNICORN_ARCH} UNICORN_ARCH)
|
||||
string(REPLACE " " ";" UNICORN_ARCH_LIST ${UNICORN_ARCH})
|
||||
|
||||
@ -210,6 +212,9 @@ else()
|
||||
if (UNICORN_FUZZ)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS} ${CMAKE_C_FLAGS}")
|
||||
endif()
|
||||
if(UNICORN_TRACER)
|
||||
set (EXTRA_CFLAGS "${EXTRA_CFLAGS} -DUNICORN_TRACER")
|
||||
endif()
|
||||
|
||||
set(TARGET_LIST "--target-list=")
|
||||
if (UNICORN_HAS_X86)
|
||||
@ -426,6 +431,11 @@ else()
|
||||
# Log and pow
|
||||
target_link_libraries(x86_64-softmmu m)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(x86_64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_ARM)
|
||||
@ -464,6 +474,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(arm-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(armeb-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -498,6 +512,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/arm
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(armeb-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_AARCH64)
|
||||
@ -542,6 +561,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(aarch64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(aarch64eb-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -582,6 +605,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/arm
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(aarch64eb-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_M68K)
|
||||
@ -612,6 +640,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/m68k
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(m68k-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_MIPS)
|
||||
@ -647,6 +680,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(mips-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(mipsel-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -679,6 +716,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(mipsel-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(mips64-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -711,6 +752,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(mips64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(mips64el-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -742,6 +787,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/mips
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(mips64el-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_SPARC)
|
||||
@ -776,6 +826,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(sparc-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(sparc64-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -807,6 +861,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/sparc
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(sparc64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_PPC)
|
||||
@ -854,6 +913,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(ppc-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(ppc64-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -901,6 +964,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/ppc
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(ppc64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_RISCV)
|
||||
@ -933,6 +1001,10 @@ else()
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(riscv32-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
add_library(riscv64-softmmu
|
||||
${UNICORN_ARCH_COMMON}
|
||||
|
||||
@ -961,6 +1033,11 @@ else()
|
||||
-I${CMAKE_CURRENT_SOURCE_DIR}/qemu/target/riscv
|
||||
)
|
||||
endif()
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(riscv64-softmmu PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (UNICORN_HAS_S390X)
|
||||
@ -1179,6 +1256,15 @@ 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)
|
||||
|
||||
if(UNICORN_TRACER)
|
||||
target_compile_options(unicorn-common PRIVATE -DUNICORN_TRACER)
|
||||
target_compile_options(unicorn PRIVATE -DUNICORN_TRACER)
|
||||
endif()
|
||||
|
||||
target_compile_options(unicorn-common PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_compile_options(unicorn PRIVATE
|
||||
${UNICORN_COMPILE_OPTIONS}
|
||||
)
|
||||
|
@ -27,7 +27,7 @@ LIBS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'lib')
|
||||
HEADERS_DIR = os.path.join(ROOT_DIR, 'unicorn', 'include')
|
||||
SRC_DIR = os.path.join(ROOT_DIR, 'src')
|
||||
UC_DIR = os.path.join(ROOT_DIR, '../..')
|
||||
BUILD_DIR = os.path.join(UC_DIR, 'build')
|
||||
BUILD_DIR = os.path.join(UC_DIR, 'build_python')
|
||||
|
||||
VERSION = "2.0.0rc5.post1"
|
||||
|
||||
@ -131,7 +131,10 @@ def build_libraries():
|
||||
os.mkdir(BUILD_DIR)
|
||||
conf = 'Debug' if os.getenv('DEBUG', '') else 'Release'
|
||||
|
||||
subprocess.check_call(["cmake", '-B', BUILD_DIR, "-DCMAKE_BUILD_TYPE=" + conf])
|
||||
cmake_args = ["cmake", '-B', BUILD_DIR, "-DCMAKE_BUILD_TYPE=" + conf]
|
||||
if os.getenv("TRACE", ""):
|
||||
cmake_args += ["-DUNICORN_TRACER=on"]
|
||||
subprocess.check_call(cmake_args)
|
||||
os.chdir(BUILD_DIR)
|
||||
threads = os.getenv("THREADS", "4")
|
||||
subprocess.check_call(["cmake", "--build", ".", "-j" + threads])
|
||||
|
@ -460,6 +460,7 @@ class Uc(object):
|
||||
|
||||
# emulate from @begin, and stop when reaching address @until
|
||||
def emu_start(self, begin, until, timeout=0, count=0):
|
||||
self._hook_exception = None
|
||||
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
@ -96,12 +96,13 @@ pub trait IsUcHook<'a> {}
|
||||
|
||||
impl<'a, D, F> IsUcHook<'a> for UcHook<'a, D, F> {}
|
||||
|
||||
pub extern "C" fn mmio_read_callback_proxy<D, F> (
|
||||
pub extern "C" fn mmio_read_callback_proxy<D, F>(
|
||||
uc: uc_handle,
|
||||
offset: u64,
|
||||
size: usize,
|
||||
user_data: *mut UcHook<D, F>,
|
||||
) -> u64 where
|
||||
) -> u64
|
||||
where
|
||||
F: FnMut(&mut crate::Unicorn<D>, u64, usize) -> u64,
|
||||
{
|
||||
let user_data = unsafe { &mut *user_data };
|
||||
@ -109,7 +110,7 @@ pub extern "C" fn mmio_read_callback_proxy<D, F> (
|
||||
(user_data.callback)(&mut user_data.uc, offset, size)
|
||||
}
|
||||
|
||||
pub extern "C" fn mmio_write_callback_proxy<D, F> (
|
||||
pub extern "C" fn mmio_write_callback_proxy<D, F>(
|
||||
uc: uc_handle,
|
||||
offset: u64,
|
||||
size: usize,
|
||||
|
@ -84,29 +84,32 @@ pub struct MmioCallbackScope<'a> {
|
||||
|
||||
impl<'a> MmioCallbackScope<'a> {
|
||||
fn has_regions(&self) -> bool {
|
||||
self.regions.len() > 0
|
||||
!self.regions.is_empty()
|
||||
}
|
||||
|
||||
fn unmap(&mut self, begin: u64, size: usize) {
|
||||
let end: u64 = begin + size as u64;
|
||||
self.regions = self.regions.iter().flat_map( |(b, s)| {
|
||||
let e: u64 = b + *s as u64;
|
||||
if begin > *b {
|
||||
if begin >= e {
|
||||
// The unmapped region is completely after this region
|
||||
vec![(*b, *s)]
|
||||
} else {
|
||||
if end >= e {
|
||||
self.regions = self
|
||||
.regions
|
||||
.iter()
|
||||
.flat_map(|(b, s)| {
|
||||
let e: u64 = b + *s as u64;
|
||||
if begin > *b {
|
||||
if begin >= e {
|
||||
// The unmapped region is completely after this region
|
||||
vec![(*b, *s)]
|
||||
} else if end >= e {
|
||||
// The unmapped region overlaps with the end of this region
|
||||
vec![(*b, (begin - *b) as usize)]
|
||||
} else {
|
||||
// The unmapped region is in the middle of this region
|
||||
let second_b = end + 1;
|
||||
vec![(*b, (begin - *b) as usize), (second_b, (e - second_b) as usize)]
|
||||
vec![
|
||||
(*b, (begin - *b) as usize),
|
||||
(second_b, (e - second_b) as usize),
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if end > *b {
|
||||
} else if end > *b {
|
||||
if end >= e {
|
||||
// The unmapped region completely contains this region
|
||||
vec![]
|
||||
@ -118,8 +121,8 @@ impl<'a> MmioCallbackScope<'a> {
|
||||
// The unmapped region is completely before this region
|
||||
vec![(*b, *s)]
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,7 +321,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
/// `size` must be a multiple of 4kb or this will return `Error::ARG`.
|
||||
pub fn mmio_map<R: 'a, W: 'a>(
|
||||
&mut self,
|
||||
address: u64,
|
||||
address: u64,
|
||||
size: libc::size_t,
|
||||
read_callback: Option<R>,
|
||||
write_callback: Option<W>,
|
||||
@ -327,7 +330,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
R: FnMut(&mut Unicorn<D>, u64, usize) -> u64,
|
||||
W: FnMut(&mut Unicorn<D>, u64, usize, u64),
|
||||
{
|
||||
let mut read_data = read_callback.map( |c| {
|
||||
let mut read_data = read_callback.map(|c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
@ -335,7 +338,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
},
|
||||
})
|
||||
});
|
||||
let mut write_data = write_callback.map( |c| {
|
||||
let mut write_data = write_callback.map(|c| {
|
||||
Box::new(ffi::UcHook {
|
||||
callback: c,
|
||||
uc: Unicorn {
|
||||
@ -363,9 +366,9 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
};
|
||||
|
||||
if err == uc_error::OK {
|
||||
let rd = read_data.map( |c| c as Box<dyn ffi::IsUcHook> );
|
||||
let wd = write_data.map( |c| c as Box<dyn ffi::IsUcHook> );
|
||||
self.inner_mut().mmio_callbacks.push(MmioCallbackScope{
|
||||
let rd = read_data.map(|c| c as Box<dyn ffi::IsUcHook>);
|
||||
let wd = write_data.map(|c| c as Box<dyn ffi::IsUcHook>);
|
||||
self.inner_mut().mmio_callbacks.push(MmioCallbackScope {
|
||||
regions: vec![(address, size)],
|
||||
read_callback: rd,
|
||||
write_callback: wd,
|
||||
@ -390,7 +393,12 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
where
|
||||
F: FnMut(&mut Unicorn<D>, u64, usize) -> u64,
|
||||
{
|
||||
self.mmio_map(address, size, Some(callback), None::<fn(&mut Unicorn<D>, u64, usize, u64)>)
|
||||
self.mmio_map(
|
||||
address,
|
||||
size,
|
||||
Some(callback),
|
||||
None::<fn(&mut Unicorn<D>, u64, usize, u64)>,
|
||||
)
|
||||
}
|
||||
|
||||
/// Map in a write-only MMIO region backed by a callback.
|
||||
@ -406,7 +414,12 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
where
|
||||
F: FnMut(&mut Unicorn<D>, u64, usize, u64),
|
||||
{
|
||||
self.mmio_map(address, size, None::<fn(&mut Unicorn<D>, u64, usize) -> u64>, Some(callback))
|
||||
self.mmio_map(
|
||||
address,
|
||||
size,
|
||||
None::<fn(&mut Unicorn<D>, u64, usize) -> u64>,
|
||||
Some(callback),
|
||||
)
|
||||
}
|
||||
|
||||
/// Unmap a memory region.
|
||||
@ -429,7 +442,9 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
for scope in self.inner_mut().mmio_callbacks.iter_mut() {
|
||||
scope.unmap(address, size);
|
||||
}
|
||||
self.inner_mut().mmio_callbacks.retain( |scope| scope.has_regions() );
|
||||
self.inner_mut()
|
||||
.mmio_callbacks
|
||||
.retain(|scope| scope.has_regions());
|
||||
}
|
||||
|
||||
/// Set the memory permissions for an existing memory region.
|
||||
@ -817,11 +832,12 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
let err: uc_error;
|
||||
|
||||
// drop the hook
|
||||
self.inner_mut()
|
||||
let inner = self.inner_mut();
|
||||
inner
|
||||
.hooks
|
||||
.retain(|(hook_ptr, _hook_impl)| hook_ptr != &hook);
|
||||
|
||||
err = unsafe { ffi::uc_hook_del(self.inner().uc, hook) };
|
||||
err = unsafe { ffi::uc_hook_del(inner.uc, hook) };
|
||||
|
||||
if err == uc_error::OK {
|
||||
Ok(())
|
||||
|
@ -427,7 +427,10 @@ fn x86_mmio() {
|
||||
|
||||
{
|
||||
// MOV eax, [0x2004]; MOV [0x2008], ax;
|
||||
let x86_code: Vec<u8> = vec![0x8B, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, 0x66, 0x89, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00];
|
||||
let x86_code: Vec<u8> = vec![
|
||||
0x8B, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, 0x66, 0x89, 0x04, 0x25, 0x08, 0x20, 0x00,
|
||||
0x00,
|
||||
];
|
||||
|
||||
let read_cell = Rc::new(RefCell::new(MmioReadExpectation(0, 0)));
|
||||
let cb_read_cell = read_cell.clone();
|
||||
@ -436,7 +439,7 @@ fn x86_mmio() {
|
||||
42
|
||||
};
|
||||
|
||||
let write_cell = Rc::new(RefCell::new(MmioWriteExpectation(0,0,0)));
|
||||
let write_cell = Rc::new(RefCell::new(MmioWriteExpectation(0, 0, 0)));
|
||||
let cb_write_cell = write_cell.clone();
|
||||
let write_callback = move |_: &mut Unicorn<'_, ()>, offset, size, value| {
|
||||
*cb_write_cell.borrow_mut() = MmioWriteExpectation(offset, size, value);
|
||||
@ -444,7 +447,10 @@ fn x86_mmio() {
|
||||
|
||||
assert_eq!(emu.mem_write(0x1000, &x86_code), Ok(()));
|
||||
|
||||
assert_eq!(emu.mmio_map(0x2000, 0x1000, Some(read_callback), Some(write_callback)), Ok(()));
|
||||
assert_eq!(
|
||||
emu.mmio_map(0x2000, 0x1000, Some(read_callback), Some(write_callback)),
|
||||
Ok(())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
emu.emu_start(
|
||||
@ -494,9 +500,11 @@ fn x86_mmio() {
|
||||
|
||||
{
|
||||
// MOV ax, 42; MOV [0x2008], ax;
|
||||
let x86_code: Vec<u8> = vec![0x66, 0xB8, 0x2A, 0x00, 0x66, 0x89, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00];
|
||||
let x86_code: Vec<u8> = vec![
|
||||
0x66, 0xB8, 0x2A, 0x00, 0x66, 0x89, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00,
|
||||
];
|
||||
|
||||
let write_cell = Rc::new(RefCell::new(MmioWriteExpectation(0,0,0)));
|
||||
let write_cell = Rc::new(RefCell::new(MmioWriteExpectation(0, 0, 0)));
|
||||
let cb_write_cell = write_cell.clone();
|
||||
let write_callback = move |_: &mut Unicorn<'_, ()>, offset, size, value| {
|
||||
*cb_write_cell.borrow_mut() = MmioWriteExpectation(offset, size, value);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e1111e1b8b253bf7292ad911f43c125808a95f1e
|
||||
Subproject commit db5434ad4e40c6657766aa6a54eafd92af38192e
|
@ -369,6 +369,8 @@ struct uc_struct {
|
||||
int nested_level; // Current nested_level
|
||||
|
||||
struct TranslationBlock *last_tb; // The real last tb we executed.
|
||||
|
||||
FlatView *empty_view; // Static function variable moved from flatviews_init
|
||||
};
|
||||
|
||||
// Metadata stub for the variable-size cpu context used with uc_context_*()
|
||||
@ -397,5 +399,31 @@ static inline int uc_addr_is_exit(uc_engine *uc, uint64_t addr)
|
||||
return g_tree_lookup(uc->exits, (gpointer)(&addr)) == (gpointer)1;
|
||||
}
|
||||
|
||||
#ifdef UNICORN_TRACER
|
||||
#define UC_TRACE_START(loc) trace_start(get_tracer(), loc)
|
||||
#define UC_TRACE_END(loc, fmt, ...) \
|
||||
trace_end(get_tracer(), loc, fmt, __VA_ARGS__)
|
||||
|
||||
typedef enum trace_loc {
|
||||
UC_TRACE_TB_EXEC = 0,
|
||||
UC_TRACE_TB_TRANS,
|
||||
UC_TRACER_MAX
|
||||
} trace_loc;
|
||||
|
||||
typedef struct uc_tracer {
|
||||
int64_t starts[UC_TRACER_MAX];
|
||||
} uc_tracer;
|
||||
|
||||
uc_tracer *get_tracer();
|
||||
|
||||
void trace_start(uc_tracer *tracer, trace_loc loc);
|
||||
|
||||
void trace_end(uc_tracer *tracer, trace_loc loc, const char *fmt, ...);
|
||||
|
||||
#else
|
||||
#define UC_TRACE_START(loc)
|
||||
#define UC_TRACE_END(loc, fmt, ...)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* vim: set ts=4 noet: */
|
||||
|
@ -55,9 +55,12 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||
int tb_exit;
|
||||
uint8_t *tb_ptr = itb->tc.ptr;
|
||||
|
||||
UC_TRACE_START(UC_TRACE_TB_EXEC);
|
||||
tb_exec_lock(cpu->uc->tcg_ctx);
|
||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
tb_exec_unlock(cpu->uc->tcg_ctx);
|
||||
UC_TRACE_END(UC_TRACE_TB_EXEC, "[uc] exec tb 0x%" PRIx64 ": ", itb->pc);
|
||||
|
||||
cpu->can_do_io = 1;
|
||||
last_tb = (TranslationBlock *)(ret & ~TB_EXIT_MASK);
|
||||
tb_exit = ret & TB_EXIT_MASK;
|
||||
|
@ -1619,7 +1619,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
tcg_func_start(tcg_ctx);
|
||||
|
||||
tcg_ctx->cpu = env_cpu(env);
|
||||
UC_TRACE_START(UC_TRACE_TB_TRANS);
|
||||
gen_intermediate_code(cpu, tb, max_insns);
|
||||
UC_TRACE_END(UC_TRACE_TB_TRANS, "[uc] translate tb 0x%" PRIx64 ": ", tb->pc);
|
||||
tcg_ctx->cpu = NULL;
|
||||
|
||||
/* generate machine code */
|
||||
|
@ -119,18 +119,13 @@ struct uc_struct;
|
||||
* Only allow MAP_JIT for Mojave or later.
|
||||
*
|
||||
* Source: https://github.com/moby/hyperkit/pull/259/files#diff-e6b5417230ff2daff9155d9b15aefae12e89410ec2dca1f59d04be511f6737fcR41
|
||||
*
|
||||
* But using MAP_JIT causes performance regression for fork() so we only use MAP_JIT on Apple M1.
|
||||
*
|
||||
* Issue: https://github.com/desktop/desktop/issues/12978
|
||||
*/
|
||||
#if defined(__APPLE__)
|
||||
#if defined(HAVE_PTHREAD_JIT_PROTECT)
|
||||
#define USE_MAP_JIT
|
||||
#else
|
||||
#include <Availability.h>
|
||||
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 && defined(MAP_JIT)
|
||||
#define USE_MAP_JIT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__APPLE__) && defined(HAVE_PTHREAD_JIT_PROTECT) && defined(__arm__)
|
||||
#define USE_MAP_JIT
|
||||
#endif
|
||||
|
||||
#include <glib_compat.h>
|
||||
|
@ -783,8 +783,6 @@ static void address_space_update_topology_pass(AddressSpace *as,
|
||||
|
||||
static void flatviews_init(struct uc_struct *uc)
|
||||
{
|
||||
static FlatView *empty_view;
|
||||
|
||||
if (uc->flat_views) {
|
||||
return;
|
||||
}
|
||||
@ -792,13 +790,13 @@ static void flatviews_init(struct uc_struct *uc)
|
||||
uc->flat_views = g_hash_table_new_full(NULL, NULL, NULL,
|
||||
(GDestroyNotify) flatview_unref);
|
||||
|
||||
if (!empty_view) {
|
||||
empty_view = generate_memory_topology(uc, NULL);
|
||||
if (!uc->empty_view) {
|
||||
uc->empty_view = generate_memory_topology(uc, NULL);
|
||||
/* We keep it alive forever in the global variable. */
|
||||
flatview_ref(empty_view);
|
||||
flatview_ref(uc->empty_view);
|
||||
} else {
|
||||
g_hash_table_replace(uc->flat_views, NULL, empty_view);
|
||||
flatview_ref(empty_view);
|
||||
g_hash_table_replace(uc->flat_views, NULL, uc->empty_view);
|
||||
flatview_ref(uc->empty_view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11432,6 +11432,21 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||
dc->pc_curr = dc->base.pc_next;
|
||||
insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
|
||||
dc->insn = insn;
|
||||
|
||||
// Unicorn:
|
||||
//
|
||||
// If we get an error during fetching code, we have to skip the instruction decoding
|
||||
// to ensure the PC remains unchanged.
|
||||
//
|
||||
// This is to keep the same behavior with Unicorn1, though, it's inconsistent with
|
||||
// official arm documents.
|
||||
//
|
||||
// See discussion here: https://github.com/unicorn-engine/unicorn/issues/1536
|
||||
if (dc->uc->invalid_error) {
|
||||
dcbase->is_jmp = DISAS_WFI;
|
||||
return;
|
||||
}
|
||||
|
||||
dc->base.pc_next += 4;
|
||||
disas_arm_insn(dc, insn);
|
||||
|
||||
|
@ -529,6 +529,69 @@ static void test_arm_hflags_rebuilt()
|
||||
OK(uc_close(uc));
|
||||
}
|
||||
|
||||
static bool test_arm_mem_access_abort_hook_mem(uc_engine *uc, uc_mem_type type,
|
||||
uint64_t addr, int size,
|
||||
int64_t val, void *data)
|
||||
{
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_PC, data));
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool test_arm_mem_access_abort_hook_insn_invalid(uc_engine *uc,
|
||||
void *data)
|
||||
{
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_PC, data));
|
||||
return false;
|
||||
}
|
||||
|
||||
static void test_arm_mem_access_abort()
|
||||
{
|
||||
// LDR r0, [r0]
|
||||
// Undefined instruction
|
||||
char code[] = "\x00\x00\x90\xe5\x00\xa0\xf0\xf7";
|
||||
uc_engine *uc;
|
||||
uint32_t r_pc, r_r0, r_pc_in_hook;
|
||||
uc_hook hk, hkk;
|
||||
|
||||
uc_common_setup(&uc, UC_ARCH_ARM, UC_MODE_ARM, code, sizeof(code) - 1,
|
||||
UC_CPU_ARM_CORTEX_A9);
|
||||
|
||||
r_r0 = 0x990000;
|
||||
OK(uc_reg_write(uc, UC_ARM_REG_R0, &r_r0));
|
||||
|
||||
OK(uc_hook_add(uc, &hk,
|
||||
UC_HOOK_MEM_READ_UNMAPPED | UC_HOOK_MEM_WRITE_UNMAPPED |
|
||||
UC_HOOK_MEM_FETCH_UNMAPPED,
|
||||
test_arm_mem_access_abort_hook_mem, (void *)&r_pc_in_hook, 1,
|
||||
0));
|
||||
OK(uc_hook_add(uc, &hkk, UC_HOOK_INSN_INVALID,
|
||||
test_arm_mem_access_abort_hook_insn_invalid,
|
||||
(void *)&r_pc_in_hook, 1, 0));
|
||||
|
||||
uc_assert_err(UC_ERR_READ_UNMAPPED,
|
||||
uc_emu_start(uc, code_start, code_start + 4, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc));
|
||||
|
||||
TEST_CHECK(r_pc == r_pc_in_hook);
|
||||
|
||||
uc_assert_err(UC_ERR_INSN_INVALID,
|
||||
uc_emu_start(uc, code_start + 4, code_start + 8, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc));
|
||||
|
||||
TEST_CHECK(r_pc == r_pc_in_hook);
|
||||
|
||||
uc_assert_err(UC_ERR_FETCH_UNMAPPED,
|
||||
uc_emu_start(uc, 0x900000, 0x900000 + 8, 0, 0));
|
||||
|
||||
OK(uc_reg_read(uc, UC_ARM_REG_PC, &r_pc));
|
||||
|
||||
TEST_CHECK(r_pc == r_pc_in_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},
|
||||
@ -545,4 +608,5 @@ TEST_LIST = {{"test_arm_nop", test_arm_nop},
|
||||
test_arm_not_allow_privilege_escalation},
|
||||
{"test_arm_mrc", test_arm_mrc},
|
||||
{"test_arm_hflags_rebuilt", test_arm_hflags_rebuilt},
|
||||
{"test_arm_mem_access_abort", test_arm_mem_access_abort},
|
||||
{NULL, NULL}};
|
28
uc.c
28
uc.c
@ -2221,3 +2221,31 @@ uc_err uc_ctl(uc_engine *uc, uc_control_type control, ...)
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef UNICORN_TRACER
|
||||
uc_tracer *get_tracer()
|
||||
{
|
||||
static uc_tracer tracer;
|
||||
return &tracer;
|
||||
}
|
||||
|
||||
void trace_start(uc_tracer *tracer, trace_loc loc)
|
||||
{
|
||||
tracer->starts[loc] = get_clock();
|
||||
}
|
||||
|
||||
void trace_end(uc_tracer *tracer, trace_loc loc, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int64_t end = get_clock();
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vfprintf(stderr, fmt, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, "%.6fus\n",
|
||||
(double)(end - tracer->starts[loc]) / (double)(1000));
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user