arm64eb: add support for ARM64 big endian.

This commit is contained in:
zhangwm 2017-04-24 23:25:30 +08:00
parent 513075e061
commit 2e973a13f0
15 changed files with 3331 additions and 11 deletions

1
.gitignore vendored
View File

@ -15,6 +15,7 @@
qemu/config-all-devices.mak
qemu/aarch64-softmmu/
qemu/aarch64eb-softmmu/
qemu/arm-softmmu/
qemu/armeb-softmmu/
qemu/m68k-softmmu/

View File

@ -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;))

View 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()

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

7
qemu/configure vendored
View File

@ -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)

View 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

View File

@ -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))

View File

@ -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

View File

@ -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);

View File

@ -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
View 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
View File

@ -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: