arm64eb: add support for ARM64 big endian.
This commit is contained in:
parent
513075e061
commit
2e973a13f0
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@
|
||||
qemu/config-all-devices.mak
|
||||
|
||||
qemu/aarch64-softmmu/
|
||||
qemu/aarch64eb-softmmu/
|
||||
qemu/arm-softmmu/
|
||||
qemu/armeb-softmmu/
|
||||
qemu/m68k-softmmu/
|
||||
|
5
Makefile
5
Makefile
@ -39,8 +39,11 @@ ifneq (,$(findstring m68k,$(UNICORN_ARCHS)))
|
||||
endif
|
||||
ifneq (,$(findstring aarch64,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(call GENOBJ,aarch64-softmmu)
|
||||
UC_TARGET_OBJ += $(call GENOBJ,aarch64eb-softmmu)
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM64
|
||||
UNICORN_CFLAGS += -DUNICORN_HAS_ARM64EB
|
||||
UNICORN_TARGETS += aarch64-softmmu,
|
||||
UNICORN_TARGETS += aarch64eb-softmmu,
|
||||
endif
|
||||
ifneq (,$(findstring mips,$(UNICORN_ARCHS)))
|
||||
UC_TARGET_OBJ += $(call GENOBJ,mips-softmmu)
|
||||
@ -300,7 +303,7 @@ dist:
|
||||
|
||||
# run "make header" whenever qemu/header_gen.py is modified
|
||||
header:
|
||||
$(eval TARGETS := m68k arm armeb aarch64 mips mipsel mips64 mips64el\
|
||||
$(eval TARGETS := m68k arm armeb aarch64 aarch64eb mips mipsel mips64 mips64el\
|
||||
powerpc sparc sparc64 x86_64)
|
||||
$(foreach var,$(TARGETS),\
|
||||
$(shell python qemu/header_gen.py $(var) > qemu/$(var).h;))
|
||||
|
68
bindings/python/sample_arm64eb.py
Executable file
68
bindings/python/sample_arm64eb.py
Executable file
@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample code for ARM64 of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
|
||||
# Python sample ported by Loi Anh Tuan <loianhtuan@gmail.com>
|
||||
# AARCH64 Python sample ported by zhangwm <rustydaar@gmail.com>
|
||||
|
||||
from __future__ import print_function
|
||||
from unicorn import *
|
||||
from unicorn.arm64_const import *
|
||||
|
||||
|
||||
# code to be emulated
|
||||
ARM64_CODE = b"\x8b\x0f\x01\xab" #add x11, x13, x15
|
||||
|
||||
# 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 ARM64
|
||||
def test_arm64():
|
||||
print("Emulate ARM64 code")
|
||||
try:
|
||||
# Initialize emulator in ARM mode
|
||||
mu = Uc(UC_ARCH_ARM64, 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, ARM64_CODE)
|
||||
|
||||
# initialize machine registers
|
||||
mu.reg_write(UC_ARM64_REG_X11, 0x1234)
|
||||
mu.reg_write(UC_ARM64_REG_X13, 0x6789)
|
||||
mu.reg_write(UC_ARM64_REG_X15, 0x3333)
|
||||
|
||||
# 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
|
||||
mu.emu_start(ADDRESS, ADDRESS + len(ARM64_CODE))
|
||||
|
||||
# now print out some registers
|
||||
print(">>> Emulation done. Below is the CPU context")
|
||||
|
||||
x11 = mu.reg_read(UC_ARM64_REG_X11)
|
||||
x13 = mu.reg_read(UC_ARM64_REG_X13)
|
||||
x15 = mu.reg_read(UC_ARM64_REG_X15)
|
||||
print(">>> X11 = 0x%x" %x11)
|
||||
|
||||
except UcError as e:
|
||||
print("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_arm64()
|
@ -5,7 +5,7 @@ UC_API_MINOR = 0
|
||||
UC_VERSION_MAJOR = 1
|
||||
|
||||
UC_VERSION_MINOR = 0
|
||||
UC_VERSION_EXTRA = 1
|
||||
UC_VERSION_EXTRA = 2
|
||||
UC_SECOND_SCALE = 1000000
|
||||
UC_MILISECOND_SCALE = 1000
|
||||
UC_ARCH_ARM = 1
|
||||
|
@ -3017,4 +3017,40 @@
|
||||
#define xpsr_write xpsr_write_aarch64
|
||||
#define xscale_cpar_write xscale_cpar_write_aarch64
|
||||
#define xscale_cp_reginfo xscale_cp_reginfo_aarch64
|
||||
#define ARM64_REGS_STORAGE_SIZE ARM64_REGS_STORAGE_SIZE_aarch64
|
||||
#define arm64_release arm64_release_aarch64
|
||||
#define arm64_reg_reset arm64_reg_reset_aarch64
|
||||
#define arm64_reg_read arm64_reg_read_aarch64
|
||||
#define arm64_reg_write arm64_reg_write_aarch64
|
||||
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64
|
||||
#define aarch64_cpu_register_types aarch64_cpu_register_types_aarch64
|
||||
#define helper_udiv64 helper_udiv64_aarch64
|
||||
#define helper_sdiv64 helper_sdiv64_aarch64
|
||||
#define helper_cls64 helper_cls64_aarch64
|
||||
#define helper_cls32 helper_cls32_aarch64
|
||||
#define helper_rbit64 helper_rbit64_aarch64
|
||||
#define helper_vfp_cmps_a64 helper_vfp_cmps_a64_aarch64
|
||||
#define helper_vfp_cmpes_a64 helper_vfp_cmpes_a64_aarch64
|
||||
#define helper_vfp_cmpd_a64 helper_vfp_cmpd_a64_aarch64
|
||||
#define helper_vfp_cmped_a64 helper_vfp_cmped_a64_aarch64
|
||||
#define helper_vfp_mulxs helper_vfp_mulxs_aarch64
|
||||
#define helper_vfp_mulxd helper_vfp_mulxd_aarch64
|
||||
#define helper_simd_tbl helper_simd_tbl_aarch64
|
||||
#define helper_neon_ceq_f64 helper_neon_ceq_f64_aarch64
|
||||
#define helper_neon_cge_f64 helper_neon_cge_f64_aarch64
|
||||
#define helper_neon_cgt_f64 helper_neon_cgt_f64_aarch64
|
||||
#define helper_recpsf_f32 helper_recpsf_f32_aarch64
|
||||
#define helper_recpsf_f64 helper_recpsf_f64_aarch64
|
||||
#define helper_rsqrtsf_f32 helper_rsqrtsf_f32_aarch64
|
||||
#define helper_rsqrtsf_f64 helper_rsqrtsf_f64_aarch64
|
||||
#define helper_neon_addlp_s8 helper_neon_addlp_s8_aarch64
|
||||
#define helper_neon_addlp_u8 helper_neon_addlp_u8_aarch64
|
||||
#define helper_neon_addlp_s16 helper_neon_addlp_s16_aarch64
|
||||
#define helper_neon_addlp_u16 helper_neon_addlp_u16_aarch64
|
||||
#define helper_frecpx_f32 helper_frecpx_f32_aarch64
|
||||
#define helper_frecpx_f64 helper_frecpx_f64_aarch64
|
||||
#define helper_fcvtx_f64_to_f32 helper_fcvtx_f64_to_f32_aarch64
|
||||
#define helper_crc32_64 helper_crc32_64_aarch64
|
||||
#define helper_crc32c_64 helper_crc32c_64_aarch64
|
||||
#define aarch64_cpu_do_interrupt aarch64_cpu_do_interrupt_aarch64
|
||||
#endif
|
||||
|
3056
qemu/aarch64eb.h
Normal file
3056
qemu/aarch64eb.h
Normal file
File diff suppressed because it is too large
Load Diff
7
qemu/configure
vendored
7
qemu/configure
vendored
@ -351,7 +351,7 @@ case "$cpu" in
|
||||
armv*b|armv*l|arm)
|
||||
cpu="arm"
|
||||
;;
|
||||
aarch64)
|
||||
aarch64|aarch64eb)
|
||||
cpu="aarch64"
|
||||
;;
|
||||
mips*)
|
||||
@ -1237,7 +1237,7 @@ target_name=`echo $target | cut -d '-' -f 1`
|
||||
target_bigendian="no"
|
||||
|
||||
case "$target_name" in
|
||||
armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
|
||||
aarch64eb|armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
|
||||
target_bigendian=yes
|
||||
;;
|
||||
esac
|
||||
@ -1272,8 +1272,9 @@ case "$target_name" in
|
||||
TARGET_ARCH=arm
|
||||
bflt="yes"
|
||||
;;
|
||||
aarch64)
|
||||
aarch64|aarch64eb)
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_ARCH=aarch64
|
||||
bflt="yes"
|
||||
;;
|
||||
cris)
|
||||
|
0
qemu/default-configs/aarch64eb-softmmu.mak
Normal file
0
qemu/default-configs/aarch64eb-softmmu.mak
Normal file
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
for d in x86_64 arm armeb m68k aarch64 mips mipsel mips64 mips64el sparc sparc64; do
|
||||
for d in x86_64 arm armeb m68k aarch64 aarch64eb mips mipsel mips64 mips64el sparc sparc64; do
|
||||
python header_gen.py $d > $d.h
|
||||
done
|
||||
|
@ -3029,6 +3029,46 @@ arm_symbols = (
|
||||
'ARM_REGS_STORAGE_SIZE',
|
||||
)
|
||||
|
||||
aarch64_symbols = (
|
||||
'ARM64_REGS_STORAGE_SIZE',
|
||||
'arm64_release',
|
||||
'arm64_reg_reset',
|
||||
'arm64_reg_read',
|
||||
'arm64_reg_write',
|
||||
'gen_a64_set_pc_im',
|
||||
'aarch64_cpu_register_types',
|
||||
'helper_udiv64',
|
||||
'helper_sdiv64',
|
||||
'helper_cls64',
|
||||
'helper_cls32',
|
||||
'helper_rbit64',
|
||||
'helper_vfp_cmps_a64',
|
||||
'helper_vfp_cmpes_a64',
|
||||
'helper_vfp_cmpd_a64',
|
||||
'helper_vfp_cmped_a64',
|
||||
'helper_vfp_mulxs',
|
||||
'helper_vfp_mulxd',
|
||||
'helper_simd_tbl',
|
||||
'helper_neon_ceq_f64',
|
||||
'helper_neon_cge_f64',
|
||||
'helper_neon_cgt_f64',
|
||||
'helper_recpsf_f32',
|
||||
'helper_recpsf_f64',
|
||||
'helper_rsqrtsf_f32',
|
||||
'helper_rsqrtsf_f64',
|
||||
'helper_neon_addlp_s8',
|
||||
'helper_neon_addlp_u8',
|
||||
'helper_neon_addlp_s16',
|
||||
'helper_neon_addlp_u16',
|
||||
'helper_frecpx_f32',
|
||||
'helper_frecpx_f64',
|
||||
'helper_fcvtx_f64_to_f32',
|
||||
'helper_crc32_64',
|
||||
'helper_crc32c_64',
|
||||
'aarch64_cpu_do_interrupt',
|
||||
|
||||
)
|
||||
|
||||
mips_symbols = (
|
||||
'cpu_mips_exec',
|
||||
'cpu_mips_get_random',
|
||||
@ -4029,6 +4069,10 @@ if __name__ == '__main__':
|
||||
for s in arm_symbols:
|
||||
print("#define %s %s_%s" %(s, s, arch))
|
||||
|
||||
if 'aarch64' in arch:
|
||||
for s in aarch64_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))
|
||||
|
@ -19,9 +19,11 @@ void armeb_uc_init(struct uc_struct* uc);
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
void arm64_uc_init(struct uc_struct* uc);
|
||||
void arm64eb_uc_init(struct uc_struct* uc);
|
||||
|
||||
extern const int ARM_REGS_STORAGE_SIZE_arm;
|
||||
extern const int ARM_REGS_STORAGE_SIZE_armeb;
|
||||
extern const int ARM64_REGS_STORAGE_SIZE;
|
||||
extern const int ARM64_REGS_STORAGE_SIZE_aarch64;
|
||||
extern const int ARM64_REGS_STORAGE_SIZE_aarch64eb;
|
||||
|
||||
#endif
|
||||
|
@ -155,7 +155,11 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals,
|
||||
}
|
||||
|
||||
DEFAULT_VISIBILITY
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
void arm64eb_uc_init(struct uc_struct* uc)
|
||||
#else
|
||||
void arm64_uc_init(struct uc_struct* uc)
|
||||
#endif
|
||||
{
|
||||
register_accel_types(uc);
|
||||
arm_cpu_register_types(uc);
|
||||
|
@ -68,6 +68,7 @@ SOURCES += sample_armeb.c
|
||||
endif
|
||||
ifneq (,$(findstring aarch64,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_arm64.c
|
||||
SOURCES += sample_arm64eb.c
|
||||
endif
|
||||
ifneq (,$(findstring mips,$(UNICORN_ARCHS)))
|
||||
SOURCES += sample_mips.c
|
||||
|
101
samples/sample_arm64eb.c
Normal file
101
samples/sample_arm64eb.c
Normal file
@ -0,0 +1,101 @@
|
||||
/* Unicorn Emulator Engine */
|
||||
/* By Nguyen Anh Quynh, 2015 */
|
||||
/* modify from arm64 sample zhangwm, 2017 */
|
||||
|
||||
/* Sample code to demonstrate how to emulate ARM64EB code */
|
||||
|
||||
#include <unicorn/unicorn.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// code to be emulated
|
||||
#define ARM_CODE "\x8b\x0f\x01\xab" // add x11, x13, x15
|
||||
|
||||
// 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_arm64(void)
|
||||
{
|
||||
uc_engine *uc;
|
||||
uc_err err;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
int64_t x11 = 0x1234; // X11 register
|
||||
int64_t x13 = 0x6789; // X13 register
|
||||
int64_t x15 = 0x3333; // X15 register
|
||||
|
||||
printf("Emulate ARM64 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));
|
||||
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_ARM64_REG_X11, &x11);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X13, &x13);
|
||||
uc_reg_write(uc, UC_ARM64_REG_X15, &x15);
|
||||
|
||||
// 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_ARM64_REG_X11, &x11);
|
||||
printf(">>> X11 = 0x%" PRIx64 "\n", x11);
|
||||
|
||||
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_arm64();
|
||||
|
||||
// dynamically free shared library
|
||||
#ifdef DYNLOAD
|
||||
uc_dyn_free();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
11
uc.c
11
uc.c
@ -204,12 +204,15 @@ uc_err uc_open(uc_arch arch, uc_mode mode, uc_engine **result)
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_ARM64
|
||||
case UC_ARCH_ARM64:
|
||||
if ((mode & ~UC_MODE_ARM_MASK) ||
|
||||
(mode & UC_MODE_BIG_ENDIAN)) {
|
||||
if (mode & ~UC_MODE_ARM_MASK) {
|
||||
free(uc);
|
||||
return UC_ERR_MODE;
|
||||
}
|
||||
uc->init_arch = arm64_uc_init;
|
||||
if (mode & UC_MODE_BIG_ENDIAN) {
|
||||
uc->init_arch = arm64eb_uc_init;
|
||||
} else {
|
||||
uc->init_arch = arm64_uc_init;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -1172,7 +1175,7 @@ static size_t cpu_context_size(uc_arch arch, uc_mode mode)
|
||||
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;
|
||||
case UC_ARCH_ARM64: return mode & UC_MODE_BIG_ENDIAN ? ARM64_REGS_STORAGE_SIZE_aarch64eb : ARM64_REGS_STORAGE_SIZE_aarch64;
|
||||
#endif
|
||||
#ifdef UNICORN_HAS_MIPS
|
||||
case UC_ARCH_MIPS:
|
||||
|
Loading…
Reference in New Issue
Block a user