mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-22 18:45:34 +00:00
fix conflicts
This commit is contained in:
commit
094ca80092
17
.travis.yml
17
.travis.yml
|
@ -12,6 +12,23 @@ compiler:
|
|||
os:
|
||||
- linux
|
||||
- osx
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: gcc
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang
|
||||
- os: osx
|
||||
script: brew install --HEAD unicorn && brew test unicorn
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
script: brew install --HEAD unicorn && brew test unicorn
|
||||
compiler: clang
|
||||
allow_failures:
|
||||
- os: osx
|
||||
script: brew install --HEAD unicorn && brew test unicorn
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
|
|
|
@ -66,4 +66,4 @@ farmdve: Memory leaking fix
|
|||
Andrew Dutcher: uc_context_{save, restore} API.
|
||||
Stephen Groat: improved CI setup.
|
||||
David Zimmer: VB6 binding.
|
||||
|
||||
zhangwm: ARM big endian.
|
||||
|
|
5
Makefile
5
Makefile
|
@ -26,8 +26,11 @@ ifneq (,$(findstring x86,$(UNICORN_ARCHS)))
|
|||
endif
|
||||
ifneq (,$(findstring arm,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(call GENOBJ,arm-softmmu)
|
||||
UC_TARGET_OBJ += $(call GENOBJ,armeb-softmmu)
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARMEB
|
||||
UNICORN_TARGETS += arm-softmmu,
|
||||
UNICORN_TARGETS += armeb-softmmu,
|
||||
endif
|
||||
ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(call GENOBJ,m68k-softmmu)
|
||||
|
@ -297,7 +300,7 @@ dist:
|
|||
|
||||
# run "make header" whenever qemu/header_gen.py is modified
|
||||
header:
|
||||
$(eval TARGETS := m68k arm aarch64 mips mipsel mips64 mips64el\
|
||||
$(eval TARGETS := m68k arm armeb aarch64 mips mipsel mips64 mips64el\
|
||||
powerpc sparc sparc64 x86_64)
|
||||
$(foreach var,$(TARGETS),\
|
||||
$(shell python qemu/header_gen.py $(var) > qemu/$(var).h;))
|
||||
|
|
104
bindings/python/sample_armeb.py
Executable file
104
bindings/python/sample_armeb.py
Executable file
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env python
|
||||
# Sample code for ARM big endian of Unicorn. zhangwm <rustydaar@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.arm_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
ARM_CODE = b"\xe3\xa0\x00\x37\xe0\x42\x10\x03" # mov r0, #0x37; sub r1, r2, r3
|
||||
THUMB_CODE = b"\xb0\x83" # sub sp, #0xc
|
||||
# memory address where emulation starts
|
||||
ADDRESS = 0x10000
|
||||
|
||||
|
||||
# callback for tracing basic blocks
|
||||
def hook_block(uc, address, size, user_data):
|
||||
print(">>> Tracing basic block at 0x%x, block size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# callback for tracing instructions
|
||||
def hook_code(uc, address, size, user_data):
|
||||
print(">>> Tracing instruction at 0x%x, instruction size = 0x%x" %(address, size))
|
||||
|
||||
|
||||
# Test ARM
|
||||
def test_arm():
|
||||
print("Emulate ARM code")
|
||||
try:
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, ARM_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM_REG_R0, 0x1234)
|
||||
mu.reg_write(UC_ARM_REG_R2, 0x6789)
|
||||
mu.reg_write(UC_ARM_REG_R3, 0x3333)
|
||||
mu.reg_write(UC_ARM_REG_APSR, 0xFFFFFFFF) #All application flags turned on
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing one instruction at ADDRESS with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code, begin=ADDRESS, end=ADDRESS)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(ARM_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
r0 = mu.reg_read(UC_ARM_REG_R0)
|
||||
r1 = mu.reg_read(UC_ARM_REG_R1)
|
||||
print(">>> R0 = 0x%x" %r0)
|
||||
print(">>> R1 = 0x%x" %r1)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
def test_thumb():
|
||||
print("Emulate THUMB code")
|
||||
try:
|
||||
# Initialize emulator in thumb mode
|
||||
mu = Uc(UC_ARCH_ARM, UC_MODE_THUMB | UC_MODE_BIG_ENDIAN)
|
||||
|
||||
# map 2MB memory for this emulation
|
||||
mu.mem_map(ADDRESS, 2 * 1024 * 1024)
|
||||
|
||||
# write machine code to be emulated to memory
|
||||
mu.mem_write(ADDRESS, THUMB_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM_REG_SP, 0x1234)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
||||
# tracing all instructions with customized callback
|
||||
mu.hook_add(UC_HOOK_CODE, hook_code)
|
||||
|
||||
# emulate machine code in infinite time
|
||||
# Note we start at ADDRESS | 1 to indicate THUMB mode.
|
||||
mu.emu_start(ADDRESS | 1, ADDRESS + len(THUMB_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
sp = mu.reg_read(UC_ARM_REG_SP)
|
||||
print(">>> SP = 0x%x" %sp)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_arm()
|
||||
print("=" * 26)
|
||||
test_thumb()
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
// 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)
|
||||
#define UC_MODE_ARM_MASK (UC_MODE_ARM|UC_MODE_THUMB|UC_MODE_LITTLE_ENDIAN|UC_MODE_MCLASS|UC_MODE_BIG_ENDIAN)
|
||||
#define UC_MODE_MIPS_MASK (UC_MODE_MIPS32|UC_MODE_MIPS64|UC_MODE_LITTLE_ENDIAN|UC_MODE_BIG_ENDIAN)
|
||||
#define UC_MODE_X86_MASK (UC_MODE_16|UC_MODE_32|UC_MODE_64|UC_MODE_LITTLE_ENDIAN)
|
||||
#define UC_MODE_PPC_MASK (UC_MODE_PPC64|UC_MODE_BIG_ENDIAN)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_AARCH64_H
|
||||
#define UNICORN_AUTOGEN_AARCH64_H
|
||||
#define arm_release arm_release_aarch64
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_aarch64
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_aarch64
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_aarch64
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_ARM_H
|
||||
#define UNICORN_AUTOGEN_ARM_H
|
||||
#define arm_release arm_release_arm
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_arm
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_arm
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_arm
|
||||
|
@ -3016,4 +3017,5 @@
|
|||
#define xpsr_write xpsr_write_arm
|
||||
#define xscale_cpar_write xscale_cpar_write_arm
|
||||
#define xscale_cp_reginfo xscale_cp_reginfo_arm
|
||||
#define ARM_REGS_STORAGE_SIZE ARM_REGS_STORAGE_SIZE_arm
|
||||
#endif
|
||||
|
|
3021
qemu/armeb.h
Normal file
3021
qemu/armeb.h
Normal file
File diff suppressed because it is too large
Load diff
0
qemu/default-configs/armeb-softmmu.mak
Normal file
0
qemu/default-configs/armeb-softmmu.mak
Normal file
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
for d in x86_64 arm m68k aarch64 mips mipsel mips64 mips64el sparc sparc64; do
|
||||
for d in x86_64 arm armeb m68k aarch64 mips mipsel mips64 mips64el sparc sparc64; do
|
||||
python header_gen.py $d > $d.h
|
||||
done
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import sys
|
||||
|
||||
symbols = (
|
||||
'arm_release',
|
||||
'aarch64_tb_set_jmp_target',
|
||||
'ppc_tb_set_jmp_target',
|
||||
'use_idiv_instructions_rt',
|
||||
|
@ -3024,6 +3025,10 @@ symbols = (
|
|||
'xscale_cp_reginfo'
|
||||
)
|
||||
|
||||
arm_symbols = (
|
||||
'ARM_REGS_STORAGE_SIZE',
|
||||
)
|
||||
|
||||
mips_symbols = (
|
||||
'cpu_mips_exec',
|
||||
'cpu_mips_get_random',
|
||||
|
@ -3930,7 +3935,9 @@ mips_symbols = (
|
|||
'mips_reg_write',
|
||||
'mips_tcg_init',
|
||||
'mips_cpu_list',
|
||||
'mips_release'
|
||||
'mips_release',
|
||||
'MIPS64_REGS_STORAGE_SIZE',
|
||||
'MIPS_REGS_STORAGE_SIZE'
|
||||
)
|
||||
|
||||
sparc_symbols = (
|
||||
|
@ -4018,6 +4025,10 @@ if __name__ == '__main__':
|
|||
for s in symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
||||
if 'arm' in arch:
|
||||
for s in arm_symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
||||
if 'mips' in arch:
|
||||
for s in mips_symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_M68K_H
|
||||
#define UNICORN_AUTOGEN_M68K_H
|
||||
#define arm_release arm_release_m68k
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_m68k
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_m68k
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_m68k
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_MIPS_H
|
||||
#define UNICORN_AUTOGEN_MIPS_H
|
||||
#define arm_release arm_release_mips
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips
|
||||
|
@ -3922,4 +3923,6 @@
|
|||
#define mips_tcg_init mips_tcg_init_mips
|
||||
#define mips_cpu_list mips_cpu_list_mips
|
||||
#define mips_release mips_release_mips
|
||||
#define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips
|
||||
#define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_MIPS64_H
|
||||
#define UNICORN_AUTOGEN_MIPS64_H
|
||||
#define arm_release arm_release_mips64
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips64
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64
|
||||
|
@ -3922,4 +3923,6 @@
|
|||
#define mips_tcg_init mips_tcg_init_mips64
|
||||
#define mips_cpu_list mips_cpu_list_mips64
|
||||
#define mips_release mips_release_mips64
|
||||
#define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips64
|
||||
#define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips64
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_MIPS64EL_H
|
||||
#define UNICORN_AUTOGEN_MIPS64EL_H
|
||||
#define arm_release arm_release_mips64el
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mips64el
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mips64el
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_mips64el
|
||||
|
@ -3922,4 +3923,6 @@
|
|||
#define mips_tcg_init mips_tcg_init_mips64el
|
||||
#define mips_cpu_list mips_cpu_list_mips64el
|
||||
#define mips_release mips_release_mips64el
|
||||
#define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips64el
|
||||
#define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips64el
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_MIPSEL_H
|
||||
#define UNICORN_AUTOGEN_MIPSEL_H
|
||||
#define arm_release arm_release_mipsel
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_mipsel
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_mipsel
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_mipsel
|
||||
|
@ -3922,4 +3923,6 @@
|
|||
#define mips_tcg_init mips_tcg_init_mipsel
|
||||
#define mips_cpu_list mips_cpu_list_mipsel
|
||||
#define mips_release mips_release_mipsel
|
||||
#define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mipsel
|
||||
#define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mipsel
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_POWERPC_H
|
||||
#define UNICORN_AUTOGEN_POWERPC_H
|
||||
#define arm_release arm_release_powerpc
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_powerpc
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_powerpc
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_powerpc
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_SPARC_H
|
||||
#define UNICORN_AUTOGEN_SPARC_H
|
||||
#define arm_release arm_release_sparc
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_sparc
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_SPARC64_H
|
||||
#define UNICORN_AUTOGEN_SPARC64_H
|
||||
#define arm_release arm_release_sparc64
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_sparc64
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_sparc64
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_sparc64
|
||||
|
|
|
@ -15,11 +15,13 @@ void arm64_reg_reset(struct uc_struct *uc);
|
|||
|
||||
DEFAULT_VISIBILITY
|
||||
void arm_uc_init(struct uc_struct* uc);
|
||||
void armeb_uc_init(struct uc_struct* uc);
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
void arm64_uc_init(struct uc_struct* uc);
|
||||
|
||||
extern const int ARM_REGS_STORAGE_SIZE;
|
||||
extern const int ARM_REGS_STORAGE_SIZE_arm;
|
||||
extern const int ARM_REGS_STORAGE_SIZE_armeb;
|
||||
extern const int ARM64_REGS_STORAGE_SIZE;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "unicorn_common.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
|
||||
const int ARM_REGS_STORAGE_SIZE = offsetof(CPUARMState, tlb_table);
|
||||
|
||||
static void arm_set_pc(struct uc_struct *uc, uint64_t address)
|
||||
|
@ -183,7 +182,11 @@ static uc_err arm_query(struct uc_struct *uc, uc_query_type type, size_t *result
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
void armeb_uc_init(struct uc_struct* uc)
|
||||
#else
|
||||
void arm_uc_init(struct uc_struct* uc)
|
||||
#endif
|
||||
{
|
||||
register_accel_types(uc);
|
||||
arm_cpu_register_types(uc);
|
||||
|
|
|
@ -9,14 +9,11 @@
|
|||
#include "unicorn_common.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
// prevent the lines from being compiled twice
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
#ifdef TARGET_MIPS64
|
||||
const int MIPS64_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table);
|
||||
#else // MIPS32
|
||||
const int MIPS_REGS_STORAGE_SIZE = offsetof(CPUMIPSState, tlb_table);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
typedef uint64_t mipsreg_t;
|
||||
|
|
|
@ -15,7 +15,9 @@ void mipsel_uc_init(struct uc_struct* uc);
|
|||
void mips64_uc_init(struct uc_struct* uc);
|
||||
void mips64el_uc_init(struct uc_struct* uc);
|
||||
|
||||
extern const int MIPS_REGS_STORAGE_SIZE;
|
||||
extern const int MIPS64_REGS_STORAGE_SIZE;
|
||||
extern const int MIPS_REGS_STORAGE_SIZE_mips;
|
||||
extern const int MIPS_REGS_STORAGE_SIZE_mipsel;
|
||||
extern const int MIPS64_REGS_STORAGE_SIZE_mips64;
|
||||
extern const int MIPS64_REGS_STORAGE_SIZE_mips64el;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* Autogen header for Unicorn Engine - DONOT MODIFY */
|
||||
#ifndef UNICORN_AUTOGEN_X86_64_H
|
||||
#define UNICORN_AUTOGEN_X86_64_H
|
||||
#define arm_release arm_release_x86_64
|
||||
#define aarch64_tb_set_jmp_target aarch64_tb_set_jmp_target_x86_64
|
||||
#define ppc_tb_set_jmp_target ppc_tb_set_jmp_target_x86_64
|
||||
#define use_idiv_instructions_rt use_idiv_instructions_rt_x86_64
|
||||
|
|
|
@ -64,6 +64,7 @@ UNICORN_ARCHS := $(shell if [ -e ../config.log ]; then cat ../config.log;\
|
|||
SOURCES =
|
||||
ifneq (,$(findstring arm,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_arm.c
|
||||
SOURCES += sample_armeb.c
|
||||
endif
|
||||
ifneq (,$(findstring aarch64,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_arm64.c
|
||||
|
|
|
@ -25,6 +25,7 @@ fi
|
|||
if test -e $DIR/sample_arm; then
|
||||
echo "=========================="
|
||||
$DIR/sample_arm
|
||||
$DIR/sample_armeb
|
||||
fi
|
||||
if test -e $DIR/sample_arm64; then
|
||||
echo "=========================="
|
||||
|
|
176
samples/sample_armeb.c
Normal file
176
samples/sample_armeb.c
Normal file
|
@ -0,0 +1,176 @@
|
|||
/* Unicorn Emulator Engine */
|
||||
/* By zhangwm, 2017 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate ARM code */
|
||||
|
||||
// windows specific
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define PRIx64 "llX"
|
||||
#ifdef DYNLOAD
|
||||
#include "unicorn_dynload.h"
|
||||
#else // DYNLOAD
|
||||
#include <unicorn/unicorn.h>
|
||||
#ifdef _WIN64
|
||||
#pragma comment(lib, "unicorn_staload64.lib")
|
||||
#else // _WIN64
|
||||
#pragma comment(lib, "unicorn_staload.lib")
|
||||
#endif // _WIN64
|
||||
#endif // DYNLOAD
|
||||
|
||||
// posix specific
|
||||
#else // _MSC_VER
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <unicorn/unicorn.h>
|
||||
#endif // _MSC_VER
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define ARM_CODE "\xe3\xa0\x00\x37\xe0\x42\x10\x03" // mov r0, #0x37; sub r1, r2, r3
|
||||
#define THUMB_CODE "\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)
|
||||
{
|
||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||
{
|
||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||
}
|
||||
|
||||
static void test_arm(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int r0 = 0x1234; // R0 register
|
||||
int r2 = 0x6789; // R1 register
|
||||
int r3 = 0x3333; // R2 register
|
||||
int r1; // R1 register
|
||||
|
||||
printf("Emulate ARM code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_ARM + UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, ARM_CODE, sizeof(ARM_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_write(uc, UC_ARM_REG_R2, &r2);
|
||||
uc_reg_write(uc, UC_ARM_REG_R3, &r3);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS);
|
||||
|
||||
// emulate machine code in infinite time (last param = 0), or when
|
||||
// finishing all the code.
|
||||
err = uc_emu_start(uc, ADDRESS, ADDRESS + sizeof(ARM_CODE) -1, 0, 0);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
|
||||
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
|
||||
printf(">>> R0 = 0x%x\n", r0);
|
||||
printf(">>> R1 = 0x%x\n", r1);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
static void test_thumb(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int sp = 0x1234; // R0 register
|
||||
|
||||
printf("Emulate THUMB code\n");
|
||||
|
||||
// Initialize emulator in ARM mode
|
||||
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB + UC_MODE_BIG_ENDIAN, &uc);
|
||||
if (err) {
|
||||
printf("Failed on uc_open() with error returned: %u (%s)\n",
|
||||
err, uc_strerror(err));
|
||||
return;
|
||||
}
|
||||
|
||||
// map 2MB memory for this emulation
|
||||
uc_mem_map(uc, ADDRESS, 2 * 1024 * 1024, UC_PROT_ALL);
|
||||
|
||||
// write machine code to be emulated to memory
|
||||
uc_mem_write(uc, ADDRESS, THUMB_CODE, sizeof(THUMB_CODE) - 1);
|
||||
|
||||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
|
||||
|
||||
// tracing one instruction at ADDRESS with customized callback
|
||||
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, ADDRESS, ADDRESS);
|
||||
|
||||
// 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);
|
||||
if (err) {
|
||||
printf("Failed on uc_emu_start() with error returned: %u\n", err);
|
||||
}
|
||||
|
||||
// now print out some registers
|
||||
printf(">>> Emulation done. Below is the CPU context\n");
|
||||
|
||||
uc_reg_read(uc, UC_ARM_REG_SP, &sp);
|
||||
printf(">>> SP = 0x%x\n", sp);
|
||||
|
||||
uc_close(uc);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
// dynamically load shared library
|
||||
#ifdef DYNLOAD
|
||||
if (!uc_dyn_load(NULL, 0)) {
|
||||
printf("Error dynamically loading shared library.\n");
|
||||
printf("Please check that unicorn.dll/unicorn.so is available as well as\n");
|
||||
printf("any other dependent dll/so files.\n");
|
||||
printf("The easiest way is to place them in the same directory as this app.\n");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
test_arm();
|
||||
printf("==========================\n");
|
||||
test_thumb();
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
27
uc.c
27
uc.c
|
@ -188,12 +188,15 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
|||
#endif
|
||||
#ifdef UNICORN_HAS_ARM
|
||||
case UC_ARCH_ARM:
|
||||
if ((mode & ~UC_MODE_ARM_MASK) ||
|
||||
(mode & UC_MODE_BIG_ENDIAN)) {
|
||||
if ((mode & ~UC_MODE_ARM_MASK)) {
|
||||
free(uc);
|
||||
return UC_ERR_MODE;
|
||||
}
|
||||
uc->init_arch = arm_uc_init;
|
||||
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;
|
||||
|
@ -853,6 +856,7 @@ static bool split_region(struct uc_struct *uc, MemoryRegion *mr, uint64_t addres
|
|||
goto error;
|
||||
}
|
||||
|
||||
free(backup);
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
@ -1165,13 +1169,26 @@ static size_t cpu_context_size(uc_arch arch, uc_mode mode)
|
|||
case UC_ARCH_X86: return X86_REGS_STORAGE_SIZE;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_ARM
|
||||
case UC_ARCH_ARM: return ARM_REGS_STORAGE_SIZE;
|
||||
case UC_ARCH_ARM: return mode & UC_MODE_BIG_ENDIAN ? ARM_REGS_STORAGE_SIZE_armeb : ARM_REGS_STORAGE_SIZE_arm;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_ARM64
|
||||
case UC_ARCH_ARM64: return ARM64_REGS_STORAGE_SIZE;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_MIPS
|
||||
case UC_ARCH_MIPS: return mode & UC_MODE_MIPS64 ? MIPS64_REGS_STORAGE_SIZE : MIPS_REGS_STORAGE_SIZE;
|
||||
case UC_ARCH_MIPS:
|
||||
if (mode & UC_MODE_MIPS64) {
|
||||
if (mode & UC_MODE_BIG_ENDIAN) {
|
||||
return MIPS64_REGS_STORAGE_SIZE_mips64;
|
||||
} else {
|
||||
return MIPS64_REGS_STORAGE_SIZE_mips64el;
|
||||
}
|
||||
} else {
|
||||
if (mode & UC_MODE_BIG_ENDIAN) {
|
||||
return MIPS_REGS_STORAGE_SIZE_mips;
|
||||
} else {
|
||||
return MIPS_REGS_STORAGE_SIZE_mipsel;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_SPARC
|
||||
case UC_ARCH_SPARC: return mode & UC_MODE_SPARC64 ? SPARC64_REGS_STORAGE_SIZE : SPARC_REGS_STORAGE_SIZE;
|
||||
|
|
Loading…
Reference in a new issue