From 47150b6df3a844540e462db1aed083fe38a44d98 Mon Sep 17 00:00:00 2001 From: Elton G Date: Sun, 15 Jan 2017 13:13:35 +0100 Subject: [PATCH] reg_read and reg_write now work with registers W0 through W30 in Aarch64 (#716) * reg_read and reg_write now work with registers W0 through W30 in Aarch64 emulaton * Added a regress test for the ARM64 reg_read and reg_write on 32-bit registers (W0-W30) Added a new macro in uc_priv.h (WRITE_DWORD_TO_QWORD), in order to write to the lower 32 bits of a 64 bit value without overwriting the whole value when using reg_write * Fixed WRITE_DWORD macro reg_write would zero out the high order bits when writing to 32 bit registers e.g. uc.reg_write(UC_X86_REG_EAX, 0) would also set register RAX to zero --- include/uc_priv.h | 2 +- qemu/target-arm/unicorn_aarch64.c | 12 +++++++---- tests/regress/arm64_reg_rw_w0_w30.py | 30 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 tests/regress/arm64_reg_rw_w0_w30.py diff --git a/include/uc_priv.h b/include/uc_priv.h index 2dd86799..dd4a211b 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -27,7 +27,7 @@ #define READ_WORD(x) (x & 0xffff) #define READ_BYTE_H(x) ((x & 0xffff) >> 8) #define READ_BYTE_L(x) (x & 0xff) -#define WRITE_DWORD(x, w) (x = (x & ~0xffffffff) | (w & 0xffffffff)) +#define WRITE_DWORD(x, w) (x = (x & ~0xffffffffLL) | (w & 0xffffffff)) #define WRITE_WORD(x, w) (x = (x & ~0xffff) | (w & 0xffff)) #define WRITE_BYTE_H(x, b) (x = (x & ~0xff00) | ((b & 0xff) << 8)) #define WRITE_BYTE_L(x, b) (x = (x & ~0xff) | (b & 0xff)) diff --git a/qemu/target-arm/unicorn_aarch64.c b/qemu/target-arm/unicorn_aarch64.c index 1d9fb328..9955b42e 100644 --- a/qemu/target-arm/unicorn_aarch64.c +++ b/qemu/target-arm/unicorn_aarch64.c @@ -50,9 +50,11 @@ int arm64_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int co for (i = 0; i < count; i++) { unsigned int regid = regs[i]; void *value = vals[i]; - if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) + if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { *(int64_t *)value = ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0]; - else { + } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { + *(int32_t *)value = READ_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0]); + } else { switch(regid) { default: break; case UC_ARM64_REG_X29: @@ -82,9 +84,11 @@ int arm64_reg_write(struct uc_struct *uc, unsigned int *regs, void* const* vals, for (i = 0; i < count; i++) { unsigned int regid = regs[i]; const void *value = vals[i]; - if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) + if (regid >= UC_ARM64_REG_X0 && regid <= UC_ARM64_REG_X28) { ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_X0] = *(uint64_t *)value; - else { + } else if (regid >= UC_ARM64_REG_W0 && regid <= UC_ARM64_REG_W30) { + WRITE_DWORD(ARM_CPU(uc, mycpu)->env.xregs[regid - UC_ARM64_REG_W0], *(uint32_t *)value); + } else { switch(regid) { default: break; case UC_ARM64_REG_X29: diff --git a/tests/regress/arm64_reg_rw_w0_w30.py b/tests/regress/arm64_reg_rw_w0_w30.py new file mode 100644 index 00000000..fc34ea4c --- /dev/null +++ b/tests/regress/arm64_reg_rw_w0_w30.py @@ -0,0 +1,30 @@ +#!/usr/bin/python + +from unicorn import * +from unicorn.arm64_const import * +from unicorn.x86_const import * + +import regress + +class Arm64RegReadWriteW0ThroughW30(regress.RegressTest): + """ + Testing the functionality to read/write 32-bit registers in AArch64 + See issue #716 + """ + + def runTest(self): + uc = Uc(UC_ARCH_ARM64, UC_MODE_ARM) + + uc.reg_write(UC_ARM64_REG_X0, 0x1234567890abcdef) + self.assertEquals(uc.reg_read(UC_ARM64_REG_X0), 0x1234567890abcdef) + self.assertEquals(uc.reg_read(UC_ARM64_REG_W0), 0x90abcdef) + + uc.reg_write(UC_ARM64_REG_X30, 0xa1b2c3d4e5f6a7b8) + self.assertEquals(uc.reg_read(UC_ARM64_REG_W30), 0xe5f6a7b8) + + uc.reg_write(UC_ARM64_REG_W30, 0xaabbccdd) + self.assertEquals(uc.reg_read(UC_ARM64_REG_X30), 0xa1b2c3d4aabbccdd) + self.assertEquals(uc.reg_read(UC_ARM64_REG_W30), 0xaabbccdd) + +if __name__ == '__main__': + regress.main()