Merge branch 'feat/xmm_regs' of https://github.com/rhelmot/unicorn into rhelmot-feat/xmm_regs
This commit is contained in:
commit
40ea64af19
|
@ -6,7 +6,7 @@ from unicorn import *
|
|||
from unicorn.x86_const import *
|
||||
|
||||
|
||||
X86_CODE32 = b"\x41\x4a" # INC ecx; DEC edx
|
||||
X86_CODE32 = b"\x41\x4a\x66\x0f\xef\xc1" # INC ecx; DEC edx; PXOR xmm0, xmm1
|
||||
X86_CODE32_LOOP = b"\x41\x4a\xeb\xfe" # INC ecx; DEC edx; JMP self-loop
|
||||
X86_CODE32_MEM_READ = b"\x8B\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov ecx,[0xaaaaaaaa]; INC ecx; DEC edx
|
||||
X86_CODE32_MEM_WRITE = b"\x89\x0D\xAA\xAA\xAA\xAA\x41\x4a" # mov [0xaaaaaaaa], ecx; INC ecx; DEC edx
|
||||
|
@ -108,6 +108,8 @@ def test_i386():
|
|||
# initialize machine registers
|
||||
mu.reg_write(UC_X86_REG_ECX, 0x1234)
|
||||
mu.reg_write(UC_X86_REG_EDX, 0x7890)
|
||||
mu.reg_write(UC_X86_REG_XMM0, 0x000102030405060708090a0b0c0d0e0f)
|
||||
mu.reg_write(UC_X86_REG_XMM1, 0x00102030405060708090a0b0c0d0e0f0)
|
||||
|
||||
# tracing all basic blocks with customized callback
|
||||
mu.hook_add(UC_HOOK_BLOCK, hook_block)
|
||||
|
@ -123,8 +125,10 @@ def test_i386():
|
|||
|
||||
r_ecx = mu.reg_read(UC_X86_REG_ECX)
|
||||
r_edx = mu.reg_read(UC_X86_REG_EDX)
|
||||
r_xmm0 = mu.reg_read(UC_X86_REG_XMM0)
|
||||
print(">>> ECX = 0x%x" %r_ecx)
|
||||
print(">>> EDX = 0x%x" %r_edx)
|
||||
print(">>> XMM0 = 0x%x" %r_xmm0)
|
||||
|
||||
# read from memory
|
||||
tmp = mu.mem_read(ADDRESS, 2)
|
||||
|
|
|
@ -202,6 +202,14 @@ class uc_x86_float80(ctypes.Structure):
|
|||
]
|
||||
|
||||
|
||||
class uc_x86_xmm(ctypes.Structure):
|
||||
"""128-bit xmm register"""
|
||||
_fields_ = [
|
||||
("low_qword", ctypes.c_uint64),
|
||||
("high_qword", ctypes.c_uint64),
|
||||
]
|
||||
|
||||
|
||||
class Uc(object):
|
||||
def __init__(self, arch, mode):
|
||||
# verify version compatibility with the core before doing anything
|
||||
|
@ -260,6 +268,12 @@ class Uc(object):
|
|||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.mantissa, reg.exponent
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != uc.UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return reg.low_qword | (reg.high_qword << 64)
|
||||
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_int64(0)
|
||||
|
@ -284,6 +298,10 @@ class Uc(object):
|
|||
reg = uc_x86_float80()
|
||||
reg.mantissa = value[0]
|
||||
reg.exponent = value[1]
|
||||
if reg_id in range(x86_const.UC_X86_REG_XMM0, x86_const.UC_X86_REG_XMM0+8):
|
||||
reg = uc_x86_xmm()
|
||||
reg.low_qword = value & 0xffffffffffffffff
|
||||
reg.high_qword = value >> 64
|
||||
|
||||
if reg is None:
|
||||
# convert to 64bit number to be safe
|
||||
|
|
|
@ -195,6 +195,14 @@ int x86_reg_read(struct uc_struct *uc, unsigned int *regs, void **vals, int coun
|
|||
*(uint16_t*) value = fptag;
|
||||
}
|
||||
continue;
|
||||
case UC_X86_REG_XMM0 ... UC_X86_REG_XMM7:
|
||||
{
|
||||
float64 *dst = (float64*)value;
|
||||
XMMReg *reg = &X86_CPU(uc, mycpu)->env.xmm_regs[regid - UC_X86_REG_XMM0];
|
||||
dst[0] = reg->_d[0];
|
||||
dst[1] = reg->_d[1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(uc->mode) {
|
||||
|
@ -666,6 +674,14 @@ int x86_reg_write(struct uc_struct *uc, unsigned int *regs, void *const *vals, i
|
|||
continue;
|
||||
}
|
||||
break;
|
||||
case UC_X86_REG_XMM0 ... UC_X86_REG_XMM7:
|
||||
{
|
||||
float64 *src = (float64*)value;
|
||||
XMMReg *reg = &X86_CPU(uc, mycpu)->env.xmm_regs[regid - UC_X86_REG_XMM0];
|
||||
reg->_d[0] = src[0];
|
||||
reg->_d[1] = src[1];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(uc->mode) {
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
|
||||
// code to be emulated
|
||||
#define X86_CODE32 "\x41\x4a" // INC ecx; DEC edx
|
||||
#define X86_CODE32 "\x41\x4a\x66\x0f\xef\xc1" // INC ecx; DEC edx; PXOR xmm0, xmm1
|
||||
#define X86_CODE32_JUMP "\xeb\x02\x90\x90\x90\x90\x90\x90" // jmp 4; nop; nop; nop; nop; nop; nop
|
||||
// #define X86_CODE32_SELF "\xeb\x1c\x5a\x89\xd6\x8b\x02\x66\x3d\xca\x7d\x75\x06\x66\x05\x03\x03\x89\x02\xfe\xc2\x3d\x41\x41\x41\x41\x75\xe9\xff\xe6\xe8\xdf\xff\xff\xff\x31\xd2\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\xca\x7d\x41\x41\x41\x41"
|
||||
//#define X86_CODE32 "\x51\x51\x51\x51" // PUSH ecx;
|
||||
|
@ -195,6 +195,9 @@ static void test_i386(void)
|
|||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
// XMM0 and XMM1 registers, low qword then high qword
|
||||
uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607};
|
||||
uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070};
|
||||
|
||||
printf("Emulate i386 code\n");
|
||||
|
||||
|
@ -217,6 +220,8 @@ static void test_i386(void)
|
|||
// initialize machine registers
|
||||
uc_reg_write(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_write(uc, UC_X86_REG_XMM0, &r_xmm0);
|
||||
uc_reg_write(uc, UC_X86_REG_XMM1, &r_xmm1);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
|
||||
|
@ -236,8 +241,10 @@ static void test_i386(void)
|
|||
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0);
|
||||
printf(">>> ECX = 0x%x\n", r_ecx);
|
||||
printf(">>> EDX = 0x%x\n", r_edx);
|
||||
printf(">>> XMM0 = 0x%.16lx%.16lx\n", r_xmm0[1], r_xmm0[0]);
|
||||
|
||||
// read from memory
|
||||
if (!uc_mem_read(uc, ADDRESS, &tmp, sizeof(tmp)))
|
||||
|
|
|
@ -119,11 +119,14 @@ static void test_i386(void **state)
|
|||
uint32_t tmp;
|
||||
uc_hook trace1, trace2;
|
||||
|
||||
const uint8_t code[] = "\x41\x4a"; // INC ecx; DEC edx
|
||||
const uint8_t code[] = "\x41\x4a\x66\x0f\xef\xc1"; // INC ecx; DEC edx; PXOR xmm0, xmm1
|
||||
const uint64_t address = 0x1000000;
|
||||
|
||||
int r_ecx = 0x1234; // ECX register
|
||||
int r_edx = 0x7890; // EDX register
|
||||
// XMM0 and XMM1 registers, low qword then high qword
|
||||
uint64_t r_xmm0[2] = {0x08090a0b0c0d0e0f, 0x0001020304050607};
|
||||
uint64_t r_xmm1[2] = {0x8090a0b0c0d0e0f0, 0x0010203040506070};
|
||||
|
||||
// Initialize emulator in X86-32bit mode
|
||||
err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc);
|
||||
|
@ -142,6 +145,10 @@ static void test_i386(void **state)
|
|||
uc_assert_success(err);
|
||||
err = uc_reg_write(uc, UC_X86_REG_EDX, &r_edx);
|
||||
uc_assert_success(err);
|
||||
err = uc_reg_write(uc, UC_X86_REG_XMM0, &r_xmm0);
|
||||
uc_assert_success(err);
|
||||
err = uc_reg_write(uc, UC_X86_REG_XMM1, &r_xmm1);
|
||||
uc_assert_success(err);
|
||||
|
||||
// tracing all basic blocks with customized callback
|
||||
err = uc_hook_add(uc, &trace1, UC_HOOK_BLOCK, hook_block, NULL, 1, 0);
|
||||
|
@ -160,9 +167,12 @@ static void test_i386(void **state)
|
|||
|
||||
uc_reg_read(uc, UC_X86_REG_ECX, &r_ecx);
|
||||
uc_reg_read(uc, UC_X86_REG_EDX, &r_edx);
|
||||
uc_reg_read(uc, UC_X86_REG_XMM0, &r_xmm0);
|
||||
|
||||
assert_int_equal(r_ecx, 0x1235);
|
||||
assert_int_equal(r_edx, 0x788F);
|
||||
uint64_t r_xmm0_expected[2] = {0x8899aabbccddeeff, 0x0011223344556677};
|
||||
assert_memory_equal(r_xmm0, r_xmm0_expected, sizeof(r_xmm0));
|
||||
|
||||
// read from memory
|
||||
err = uc_mem_read(uc, address, (uint8_t *)&tmp, 4);
|
||||
|
|
Loading…
Reference in New Issue