Merge branch 'master' of https://github.com/feliam/unicorn into feliam-master
This commit is contained in:
commit
d8f82b1b3d
|
@ -156,6 +156,24 @@ def uc_arch_supported(query):
|
|||
return _uc.uc_arch_supported(query)
|
||||
|
||||
|
||||
class uc_x86_mmr(ctypes.Structure):
|
||||
'''Memory-Management Register for instructions IDTR, GDTR, LDTR, TR.'''
|
||||
_fields_ = [
|
||||
("selector", ctypes.c_uint16), # not used by GDTR and IDTR
|
||||
("base", ctypes.c_uint64), # handle 32 or 64 bit CPUs
|
||||
("limit", ctypes.c_uint32),
|
||||
("flags", ctypes.c_uint32), # not used by GDTR and IDTR
|
||||
]
|
||||
|
||||
|
||||
class uc_x86_float80(ctypes.Structure):
|
||||
'''Float80'''
|
||||
_fields_ = [
|
||||
("mantissa", ctypes.c_uint64),
|
||||
("exponent", ctypes.c_uint16),
|
||||
]
|
||||
|
||||
|
||||
class Uc(object):
|
||||
def __init__(self, arch, mode):
|
||||
# verify version compatibility with the core before doing anything
|
||||
|
@ -205,6 +223,20 @@ class Uc(object):
|
|||
|
||||
# return the value of a register
|
||||
def reg_read(self, reg_id):
|
||||
if self._arch == UC_ARCH_X86:
|
||||
if reg_id in [ x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
reg = uc_x86_mmr()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return (reg.selector,reg.base, reg.limits, reg.flags)
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0,x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
return (reg.mantissa, reg.exponent)
|
||||
|
||||
# read to 64bit number to be safe
|
||||
reg = ctypes.c_int64(0)
|
||||
status = _uc.uc_reg_read(self._uch, reg_id, ctypes.byref(reg))
|
||||
|
@ -215,8 +247,25 @@ class Uc(object):
|
|||
|
||||
# write to a register
|
||||
def reg_write(self, reg_id, value):
|
||||
# convert to 64bit number to be safe
|
||||
reg = ctypes.c_int64(value)
|
||||
reg = None
|
||||
|
||||
if self._arch == UC_ARCH_X86:
|
||||
if reg_id in [ x86_const.UC_X86_REG_IDTR, x86_const.UC_X86_REG_GDTR, x86_const.UC_X86_REG_LDTR, x86_const.UC_X86_REG_TR]:
|
||||
assert isinstance(value, tuple) and len(value)==4
|
||||
reg = uc_x86_mmr()
|
||||
reg.selector=value[0]
|
||||
reg.base=value[1]
|
||||
reg.limits=value[2]
|
||||
reg.flags=value[3]
|
||||
if reg_id in range(x86_const.UC_X86_REG_FP0, x86_const.UC_X86_REG_FP0+8):
|
||||
reg = uc_x86_float80()
|
||||
reg.mantissa = value[0]
|
||||
reg.exponent = value[1]
|
||||
|
||||
if reg is None:
|
||||
# convert to 64bit number to be safe
|
||||
reg = ctypes.c_int64(value)
|
||||
|
||||
status = _uc.uc_reg_write(self._uch, reg_id, ctypes.byref(reg))
|
||||
if status != UC_ERR_OK:
|
||||
raise UcError(status)
|
||||
|
|
|
@ -248,7 +248,9 @@ UC_X86_REG_IDTR = 242
|
|||
UC_X86_REG_GDTR = 243
|
||||
UC_X86_REG_LDTR = 244
|
||||
UC_X86_REG_TR = 245
|
||||
UC_X86_REG_ENDING = 246
|
||||
UC_X86_REG_FPTAGS = 246
|
||||
UC_X86_REG_FPCW = 247
|
||||
UC_X86_REG_ENDING = 248
|
||||
|
||||
# X86 instructions
|
||||
|
||||
|
|
|
@ -73,7 +73,8 @@ typedef enum uc_x86_reg {
|
|||
UC_X86_REG_R9D, UC_X86_REG_R10D, UC_X86_REG_R11D, UC_X86_REG_R12D, UC_X86_REG_R13D,
|
||||
UC_X86_REG_R14D, UC_X86_REG_R15D, UC_X86_REG_R8W, UC_X86_REG_R9W, UC_X86_REG_R10W,
|
||||
UC_X86_REG_R11W, UC_X86_REG_R12W, UC_X86_REG_R13W, UC_X86_REG_R14W, UC_X86_REG_R15W,
|
||||
UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR,
|
||||
UC_X86_REG_IDTR, UC_X86_REG_GDTR, UC_X86_REG_LDTR, UC_X86_REG_TR, UC_X86_REG_FPCW,
|
||||
UC_X86_REG_FPTAG,
|
||||
|
||||
UC_X86_REG_ENDING // <-- mark the end of the list of registers
|
||||
} uc_x86_reg;
|
||||
|
|
|
@ -140,6 +140,57 @@ int x86_reg_read(struct uc_struct *uc, unsigned int regid, void *value)
|
|||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
switch(regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_X86_REG_FP0 ... UC_X86_REG_FP7:
|
||||
{
|
||||
floatx80 reg = X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d;
|
||||
cpu_get_fp80(value, value+sizeof(uint64_t), reg);
|
||||
}
|
||||
break;
|
||||
case UC_X86_REG_FPSW:
|
||||
{
|
||||
uint16_t fpus = X86_CPU(uc, mycpu)->env.fpus;
|
||||
fpus = fpus & ~0x3800;
|
||||
fpus |= ( X86_CPU(uc, mycpu)->env.fpstt & 0x7 ) << 11;
|
||||
*(uint16_t*) value = fpus;
|
||||
}
|
||||
case UC_X86_REG_FPCW:
|
||||
*(uint16_t*) value = X86_CPU(uc, mycpu)->env.fpuc;
|
||||
break;
|
||||
case UC_X86_REG_FPTAG:
|
||||
{
|
||||
#define EXPD(fp) (fp.l.upper & 0x7fff)
|
||||
#define MANTD(fp) (fp.l.lower)
|
||||
#define MAXEXPD 0x7fff
|
||||
int fptag, exp, i;
|
||||
uint64_t mant;
|
||||
CPU_LDoubleU tmp;
|
||||
fptag = 0;
|
||||
for (i = 7; i >= 0; i--) {
|
||||
fptag <<= 2;
|
||||
if (X86_CPU(uc, mycpu)->env.fptags[i]) {
|
||||
fptag |= 3;
|
||||
} else {
|
||||
tmp.d = X86_CPU(uc, mycpu)->env.fpregs[i].d;
|
||||
exp = EXPD(tmp);
|
||||
mant = MANTD(tmp);
|
||||
if (exp == 0 && mant == 0) {
|
||||
/* zero */
|
||||
fptag |= 1;
|
||||
} else if (exp == 0 || exp == MAXEXPD
|
||||
|| (mant & (1LL << 63)) == 0) {
|
||||
/* NaNs, infinity, denormal */
|
||||
fptag |= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
*(uint16_t*) value = fptag;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch(uc->mode) {
|
||||
default:
|
||||
break;
|
||||
|
@ -573,6 +624,38 @@ int x86_reg_write(struct uc_struct *uc, unsigned int regid, const void *value)
|
|||
{
|
||||
CPUState *mycpu = first_cpu;
|
||||
|
||||
switch(regid) {
|
||||
default:
|
||||
break;
|
||||
case UC_X86_REG_FP0 ... UC_X86_REG_FP7:
|
||||
{
|
||||
uint64_t mant = *(uint64_t*) value;
|
||||
uint16_t upper = *(uint16_t*) (value + sizeof(uint64_t));
|
||||
X86_CPU(uc, mycpu)->env.fpregs[regid - UC_X86_REG_FP0].d = cpu_set_fp80(mant, upper);
|
||||
}
|
||||
break;
|
||||
case UC_X86_REG_FPSW:
|
||||
{
|
||||
uint16_t fpus = *(uint16_t*) value;
|
||||
X86_CPU(uc, mycpu)->env.fpus = fpus & ~0x3800;
|
||||
X86_CPU(uc, mycpu)->env.fpstt = (fpus >> 11) & 0x7;
|
||||
}
|
||||
break;
|
||||
case UC_X86_REG_FPCW:
|
||||
*(uint16_t*) value = X86_CPU(uc, mycpu)->env.fpuc;
|
||||
break;
|
||||
case UC_X86_REG_FPTAG:
|
||||
{
|
||||
int i;
|
||||
uint16_t fptag = *(uint16_t*) value;
|
||||
for (i = 0; i < 8; i++) {
|
||||
X86_CPU(uc, mycpu)->env.fptags[i] = ((fptag & 3) == 3);
|
||||
fptag >>= 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch(uc->mode) {
|
||||
default:
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue