GDT/LDT/IDT/FPU access from python bingings

This commit is contained in:
feliam 2016-03-09 18:07:38 -03:00
parent 2cfe6fb9c0
commit ff66a72d7b
2 changed files with 86 additions and 3 deletions

View File

@ -156,6 +156,23 @@ 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
@ -188,7 +205,6 @@ class Uc(object):
except: # _uc might be pulled from under our feet
pass
# emulate from @begin, and stop when reaching address @until
def emu_start(self, begin, until, timeout=0, count=0):
status = _uc.uc_emu_start(self._uch, begin, until, timeout, count)
@ -205,6 +221,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 +245,22 @@ 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)
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]
else:
# 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)

View File

@ -140,6 +140,25 @@ 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 & ~(7<<11);
fpus |= (X86_CPU(uc, mycpu)->env.fpstt&7)<<11;
*(uint16_t*) value = fpus;
}
break;
}
switch(uc->mode) {
default:
break;
@ -573,6 +592,26 @@ 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:
{
//floatx80 cpu_set_fp80(uint64_t mant, uint16_t upper);
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;
X86_CPU(uc, mycpu)->env.fpstt = (fpus>>11)&7;
}
break;
}
switch(uc->mode) {
default:
break;