armeb: Add support for ARM big endian.

This commit is contained in:
zhangwm 2017-03-13 22:32:44 +08:00
parent ee89c4a421
commit d8fe34a2e8
9 changed files with 3144 additions and 6 deletions

View file

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

105
bindings/python/sample_armeb.py Executable file
View file

@ -0,0 +1,105 @@
#!/usr/bin/env python
# Sample code for ARM of Unicorn. Nguyen Anh Quynh <aquynh@gmail.com>
# Python sample ported by Loi Anh Tuan <loianhtuan@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()

View file

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

3020
qemu/armeb.h Normal file

File diff suppressed because it is too large Load diff

View file

View file

@ -15,6 +15,7 @@ void arm64_reg_reset(struct uc_struct *uc);
__attribute__ ((visibility ("default")))
void arm_uc_init(struct uc_struct* uc);
void armeb_uc_init(struct uc_struct* uc);
__attribute__ ((visibility ("default")))
void arm64_uc_init(struct uc_struct* uc);

View file

@ -9,8 +9,9 @@
#include "unicorn_common.h"
#include "uc_priv.h"
#ifndef TARGET_WORDS_BIGENDIAN
const int ARM_REGS_STORAGE_SIZE = offsetof(CPUARMState, tlb_table);
#endif
static void arm_set_pc(struct uc_struct *uc, uint64_t address)
{
@ -181,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);

View file

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

9
uc.c
View file

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