Fix ARM Python bindings (#2127)

This commit is contained in:
peace-maker 2023-07-29 02:34:17 +02:00 committed by GitHub
parent 489538fa05
commit 4a7a55f62a
25 changed files with 1308 additions and 786 deletions

View File

@ -31,7 +31,7 @@ template = {
'comment_close': '',
},
'python': {
'header': "from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM\n"
'header': "from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM\n"
"# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.py]\n",
'footer': "",
'line_format': '%s = %s\n',

View File

@ -4,7 +4,7 @@ PYTHON3 ?= python3
.PHONY: gen_const install install3 install_cython sdist sdist3 bdist bdist3 clean check
gen_const:
cd .. && $(PYTHON2) const_generator.py python
cd .. && $(PYTHON3) const_generator.py python
install:
rm -rf src/

View File

@ -741,6 +741,23 @@ class CsInsn(object):
return self._raw.detail.contents.groups[:self._raw.detail.contents.groups_count]
raise CsError(CS_ERR_DETAIL)
# return whether instruction has writeback operands.
@property
def writeback(self):
if self._raw.id == 0:
raise CsError(CS_ERR_SKIPDATA)
if self._cs._diet:
# Diet engine cannot provide @writeback.
raise CsError(CS_ERR_DIET)
if self._cs._detail:
if hasattr(self, 'arm64_writeback'):
return self.arm64_writeback
return self._raw.detail.contents.writeback
raise CsError(CS_ERR_DETAIL)
def __gen_detail(self):
if self._raw.id == 0:
@ -749,10 +766,10 @@ class CsInsn(object):
arch = self._cs.arch
if arch == CS_ARCH_ARM:
(self.usermode, self.vector_size, self.vector_data, self.cps_mode, self.cps_flag, self.cc, self.update_flags, \
self.writeback, self.post_index, self.mem_barrier, self.operands) = arm.get_arch_info(self._raw.detail.contents.arch.arm)
(self.usermode, self.vector_size, self.vector_data, self.cps_mode, self.cps_flag, self.cc, self.vcc, self.update_flags, \
self.post_index, self.mem_barrier, self.pred_mask, self.operands) = arm.get_arch_info(self._raw.detail.contents.arch.arm)
elif arch == CS_ARCH_ARM64:
(self.cc, self.update_flags, self.writeback, self.post_index, self.operands) = \
(self.cc, self.update_flags, self.arm64_writeback, self.post_index, self.operands) = \
arm64.get_arch_info(self._raw.detail.contents.arch.arm64)
elif arch == CS_ARCH_X86:
(self.prefix, self.opcode, self.rex, self.addr_size, \

View File

@ -20,10 +20,26 @@ class ArmOpShift(ctypes.Structure):
('value', ctypes.c_uint),
)
class ArmSysopReg(ctypes.Union):
_fields_ = (
('mclasssysreg', ctypes.c_uint),
('bankedreg', ctypes.c_uint),
)
class ArmOpSysop(ctypes.Structure):
_fields_ = (
('reg', ArmSysopReg),
('psr_bits', ctypes.c_uint),
('sysm', ctypes.c_uint16),
('msr_mask', ctypes.c_uint8),
)
class ArmOpValue(ctypes.Union):
_fields_ = (
('reg', ctypes.c_uint),
('sysop', ArmOpSysop),
('imm', ctypes.c_int32),
('pred', ctypes.c_int),
('fp', ctypes.c_double),
('mem', ArmOpMem),
('setend', ctypes.c_int),
@ -40,13 +56,21 @@ class ArmOp(ctypes.Structure):
('neon_lane', ctypes.c_int8),
)
@property
def reg(self):
return self.value.reg
@property
def sysop(self):
return self.value.sysop
@property
def imm(self):
return self.value.imm
@property
def reg(self):
return self.value.reg
def pred(self):
return self.value.pred
@property
def fp(self):
@ -69,15 +93,16 @@ class CsArm(ctypes.Structure):
('cps_mode', ctypes.c_int),
('cps_flag', ctypes.c_int),
('cc', ctypes.c_uint),
('vcc', ctypes.c_uint),
('update_flags', ctypes.c_bool),
('writeback', ctypes.c_bool),
('post_index', ctypes.c_bool),
('mem_barrier', ctypes.c_int),
('pred_mask', ctypes.c_uint8),
('op_count', ctypes.c_uint8),
('operands', ArmOp * 36),
)
def get_arch_info(a):
return (a.usermode, a.vector_size, a.vector_data, a.cps_mode, a.cps_flag, a.cc, a.update_flags, \
a.writeback, a.post_index, a.mem_barrier, copy_ctypes_list(a.operands[:a.op_count]))
return (a.usermode, a.vector_size, a.vector_data, a.cps_mode, a.cps_flag, a.cc, a.vcc, a.update_flags, \
a.post_index, a.mem_barrier, a.pred_mask, copy_ctypes_list(a.operands[:a.op_count]))

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.py]
ARM64_SFT_INVALID = 0

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [bpf_const.py]
BPF_OP_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [evm_const.py]
EVM_INS_STOP = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [m680x_const.py]
M680X_OPERAND_COUNT = 9

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [m68k_const.py]
M68K_OPERAND_COUNT = 4

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.py]
MIPS_OP_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mos65xx_const.py]
MOS65XX_REG_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.py]
PPC_BC_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [riscv_const.py]
# Operand type for instruction's operands

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sh_const.py]
SH_REG_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.py]
SPARC_CC_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sysz_const.py]
SYSZ_CC_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [tms320c64x_const.py]
TMS320C64X_OP_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [tricore_const.py]
TRICORE_OP_INVALID = CS_OP_INVALID
TRICORE_OP_REG = CS_OP_REG

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [wasm_const.py]
WASM_OP_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.py]
X86_REG_INVALID = 0

View File

@ -1,4 +1,4 @@
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_MEM
from . import CS_OP_INVALID, CS_OP_REG, CS_OP_IMM, CS_OP_FP, CS_OP_PRED, CS_OP_SPECIAL, CS_OP_MEM
# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [xcore_const.py]
XCORE_OP_INVALID = 0

View File

@ -24,10 +24,10 @@ class CsDetail(object):
if arch == capstone.CS_ARCH_ARM:
(self.usermode, self.vector_size, self.vector_data, self.cps_mode, self.cps_flag, \
self.cc, self.update_flags, self.writeback, self.post_index, self.mem_barrier, self.operands) = \
self.cc, self.vcc, self.update_flags, self.post_index, self.mem_barrier, self.pred_mask, self.operands) = \
arm.get_arch_info(detail.arch.arm)
elif arch == capstone.CS_ARCH_ARM64:
(self.cc, self.update_flags, self.writeback, self.post_index, self.operands) = \
(self.cc, self.update_flags, self.arm64_writeback, self.post_index, self.operands) = \
arm64.get_arch_info(detail.arch.arm64)
elif arch == capstone.CS_ARCH_X86:
(self.prefix, self.opcode, self.rex, self.addr_size, \

View File

@ -39,22 +39,22 @@ def print_insn_detail(insn):
for i in insn.operands:
if i.type == ARM_OP_REG:
print("\t\toperands[%u].type: REG = %s" % (c, insn.reg_name(i.reg)))
if i.type == ARM_OP_IMM:
elif i.type == ARM_OP_IMM:
print("\t\toperands[%u].type: IMM = 0x%s" % (c, to_x_32(i.imm)))
if i.type == ARM_OP_PIMM:
print("\t\toperands[%u].type: P-IMM = %u" % (c, i.imm))
if i.type == ARM_OP_CIMM:
print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
if i.type == ARM_OP_FP:
elif i.type == ARM_OP_FP:
print("\t\toperands[%u].type: FP = %f" % (c, i.fp))
if i.type == ARM_OP_SYSREG:
print("\t\toperands[%u].type: SYSREG = %u" % (c, i.reg))
if i.type == ARM_OP_SETEND:
elif i.type == ARM_OP_PRED:
print("\t\toperands[%u].type: PRED = %d" % (c, i.pred))
elif i.type == ARM_OP_CIMM:
print("\t\toperands[%u].type: C-IMM = %u" % (c, i.imm))
elif i.type == ARM_OP_PIMM:
print("\t\toperands[%u].type: P-IMM = %u" % (c, i.imm))
elif i.type == ARM_OP_SETEND:
if i.setend == ARM_SETEND_BE:
print("\t\toperands[%u].type: SETEND = be" % c)
else:
print("\t\toperands[%u].type: SETEND = le" % c)
if i.type == ARM_OP_MEM:
elif i.type == ARM_OP_MEM:
print("\t\toperands[%u].type: MEM" % c)
if i.mem.base != 0:
print("\t\t\toperands[%u].mem.base: REG = %s" \
@ -71,6 +71,31 @@ def print_insn_detail(insn):
if i.mem.lshift != 0:
print("\t\t\toperands[%u].mem.lshift: 0x%s" \
% (c, to_x_32(i.mem.lshift)))
elif i.type == ARM_OP_SYSM:
print("\t\toperands[%u].type: SYSM = 0x%x" % (c, i.sysop.sysm))
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type == ARM_OP_SYSREG:
print("\t\toperands[%u].type: SYSREG = %s" % (c, insn.reg_name(i.sysop.reg.mclasssysreg)))
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type == ARM_OP_BANKEDREG:
print("\t\toperands[%u].type: BANKEDREG = %u" % (c, i.sysop.reg.bankedreg))
if i.sysop.msr_mask != 2 ** (ctypes.sizeof(ctypes.c_uint8) * 8) - 1:
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
elif i.type in [ARM_OP_SPSR, ARM_OP_CPSR]:
print("\t\toperands[%u].type: %sPSR = " % (c, "S" if i.type == ARM_OP_SPSR else "C"), end="")
field = i.sysop.psr_bits
if (field & ARM_FIELD_SPSR_F) > 0 or (field & ARM_FIELD_CPSR_F) > 0:
print("f", end="")
if (field & ARM_FIELD_SPSR_S) > 0 or (field & ARM_FIELD_CPSR_S) > 0:
print("s", end="")
if (field & ARM_FIELD_SPSR_X) > 0 or (field & ARM_FIELD_CPSR_X) > 0:
print("x", end="")
if (field & ARM_FIELD_SPSR_C) > 0 or (field & ARM_FIELD_CPSR_C) > 0:
print("c", end="")
print()
print("\t\toperands[%u].type: MASK = %u" % (c, i.sysop.msr_mask))
else:
print("\t\toperands[%u].type: UNKNOWN = %u" % (c, i.type))
if i.neon_lane != -1:
print("\t\toperands[%u].neon_lane = %u" % (c, i.neon_lane))
@ -83,8 +108,14 @@ def print_insn_detail(insn):
print("\t\toperands[%u].access: READ | WRITE\n" % (c))
if i.shift.type != ARM_SFT_INVALID and i.shift.value:
print("\t\t\tShift: %u = %u" \
% (i.shift.type, i.shift.value))
if i.shift.type < ARM_SFT_ASR_REG:
# shift with constant value
print("\t\t\tShift: %u = %u" \
% (i.shift.type, i.shift.value))
else:
# shift with register
print("\t\t\tShift: %u = %s" \
% (i.shift.type, insn.reg_name(i.shift.value)))
if i.vector_index != -1:
print("\t\t\toperands[%u].vector_index = %u" %(c, i.vector_index))
if i.subtracted:
@ -92,6 +123,10 @@ def print_insn_detail(insn):
c += 1
if not insn.cc in [ARMCC_AL, ARMCC_UNDEF]:
print("\tCode condition: %u" % insn.cc)
if insn.vcc != ARMVCC_None:
print("\tVector code condition: %u" % insn.vcc)
if insn.update_flags:
print("\tUpdate-flags: True")
if insn.writeback:
@ -99,8 +134,6 @@ def print_insn_detail(insn):
print("\tWrite-back: Post")
else:
print("\tWrite-back: Pre")
if not insn.cc in [ARM_CC_AL, ARM_CC_INVALID]:
print("\tCode condition: %u" % insn.cc)
if insn.cps_mode:
print("\tCPSI-mode: %u" %(insn.cps_mode))
if insn.cps_flag:
@ -113,6 +146,8 @@ def print_insn_detail(insn):
print("\tUser-mode: True")
if insn.mem_barrier:
print("\tMemory-barrier: %u" %(insn.mem_barrier))
if insn.pred_mask:
print("\tPredicate Mask: 0x%x" %(insn.pred_mask))
(regs_read, regs_write) = insn.regs_access()

View File

@ -93,9 +93,37 @@ static void print_insn_detail(csh cs_handle, cs_insn *ins)
case ARM_OP_SETEND:
printf("\t\toperands[%u].type: SETEND = %s\n", i, op->setend == ARM_SETEND_BE? "be" : "le");
break;
case ARM_OP_SYSREG:
printf("\t\toperands[%u].type: SYSREG = %u\n", i, op->reg);
case ARM_OP_SYSM:
printf("\t\toperands[%u].type: SYSM = 0x%" PRIx16 "\n", i, op->sysop.sysm);
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
break;
case ARM_OP_SYSREG:
printf("\t\toperands[%u].type: SYSREG = %s\n", i, cs_reg_name(handle, (uint32_t) op->sysop.reg.mclasssysreg));
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
break;
case ARM_OP_BANKEDREG:
// FIXME: Printing the name is currenliy not supported if the encodings overlap
// with system registers.
printf("\t\toperands[%u].type: BANKEDREG = %" PRIu32 "\n", i, (uint32_t) op->sysop.reg.bankedreg);
if (op->sysop.msr_mask != UINT8_MAX)
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
case ARM_OP_SPSR:
case ARM_OP_CPSR: {
const char type = op->type == ARM_OP_SPSR ? 'S' : 'C';
printf("\t\toperands[%u].type: %cPSR = ", i, type);
uint16_t field = op->sysop.psr_bits;
if ((field & ARM_FIELD_SPSR_F) || (field & ARM_FIELD_CPSR_F))
printf("f");
if ((field & ARM_FIELD_SPSR_S) || (field & ARM_FIELD_CPSR_S))
printf("s");
if ((field & ARM_FIELD_SPSR_X) || (field & ARM_FIELD_CPSR_X))
printf("x");
if ((field & ARM_FIELD_SPSR_C) || (field & ARM_FIELD_CPSR_C))
printf("c");
printf("\n");
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
break;
}
}
if (op->neon_lane != -1) {
@ -137,6 +165,9 @@ static void print_insn_detail(csh cs_handle, cs_insn *ins)
if (arm->cc != ARMCC_AL && arm->cc != ARMCC_UNDEF)
printf("\tCode condition: %u\n", arm->cc);
if (arm->vcc != ARMVCC_None)
printf("\tVector code condition: %u\n", arm->vcc);
if (arm->update_flags)
printf("\tUpdate-flags: True\n");