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
This commit is contained in:
parent
55f0292aa9
commit
47150b6df3
@ -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))
|
||||
|
@ -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:
|
||||
|
30
tests/regress/arm64_reg_rw_w0_w30.py
Normal file
30
tests/regress/arm64_reg_rw_w0_w30.py
Normal file
@ -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()
|
Loading…
Reference in New Issue
Block a user