Improve cython by using CCsInsn when possible
This commit is contained in:
parent
f48a879e31
commit
cfd41dd6f5
|
@ -12,6 +12,7 @@ install:
|
|||
# NOTE: Newer cython can be installed by: sudo pip install --upgrade cython
|
||||
install_cython:
|
||||
# Copy code from capstone/ to pyx/
|
||||
cp capstone/ccapstone.* pyx/
|
||||
cp capstone/__init__.py pyx/__init__.py
|
||||
cp capstone/capstone.py pyx/capstone.pyx
|
||||
cp capstone/arm.py pyx/arm.pyx
|
||||
|
|
|
@ -395,6 +395,14 @@ class Cs(object):
|
|||
self.csh = None
|
||||
raise CsError(status)
|
||||
|
||||
try:
|
||||
from ccapstone import CCs
|
||||
# rewire disasm to use the faster version
|
||||
self.ccs = CCs(self)
|
||||
self.disasm = self.ccs.disasm
|
||||
except:
|
||||
self.ccs = None
|
||||
|
||||
if arch == CS_ARCH_X86:
|
||||
# Intel syntax is default for X86
|
||||
self._syntax = CS_OPT_SYNTAX_INTEL
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
from libcpp cimport bool
|
||||
from libc.stdint cimport uint8_t, uint64_t, uint16_t
|
||||
|
||||
cdef extern from "<capstone/capstone.h>":
|
||||
|
||||
ctypedef size_t csh
|
||||
|
||||
ctypedef enum cs_mode:
|
||||
pass
|
||||
|
||||
ctypedef enum cs_arch:
|
||||
pass
|
||||
|
||||
ctypedef struct cs_detail:
|
||||
pass
|
||||
|
||||
ctypedef struct cs_insn:
|
||||
unsigned int id
|
||||
uint64_t address
|
||||
uint16_t size
|
||||
uint8_t bytes[16]
|
||||
char mnemonic[32]
|
||||
char op_str[96]
|
||||
cs_detail *detail
|
||||
|
||||
ctypedef enum cs_err:
|
||||
pass
|
||||
|
||||
ctypedef enum cs_opt_type:
|
||||
pass
|
||||
|
||||
unsigned int cs_version(int *major, int *minor)
|
||||
|
||||
bool cs_support(int arch)
|
||||
|
||||
cs_err cs_open(cs_arch arch, cs_mode mode, csh *handle)
|
||||
|
||||
cs_err cs_close(csh handle)
|
||||
|
||||
cs_err cs_errno(csh handle)
|
||||
|
||||
size_t cs_disasm_ex(csh handle,
|
||||
const uint8_t *code, size_t code_size,
|
||||
uint64_t address,
|
||||
size_t count,
|
||||
cs_insn **insn)
|
||||
|
||||
cs_err cs_option(csh handle, cs_opt_type type, size_t value)
|
||||
|
||||
void cs_free(cs_insn *insn, size_t count)
|
||||
|
||||
const char *cs_reg_name(csh handle, unsigned int reg_id)
|
||||
|
||||
const char *cs_insn_name(csh handle, unsigned int insn_id)
|
||||
|
||||
bool cs_insn_group(csh handle, cs_insn *insn, unsigned int group_id)
|
||||
|
||||
bool cs_reg_read(csh handle, cs_insn *insn, unsigned int reg_id)
|
||||
|
||||
bool cs_reg_write(csh handle, cs_insn *insn, unsigned int reg_id)
|
||||
|
||||
int cs_op_count(csh handle, cs_insn *insn, unsigned int op_type)
|
||||
|
||||
int cs_op_index(csh handle, cs_insn *insn, unsigned int op_type,
|
||||
unsigned int position)
|
|
@ -0,0 +1,167 @@
|
|||
cimport ccapstone as cc
|
||||
import ctypes
|
||||
from capstone import *
|
||||
import capstone
|
||||
from capstone import arm, x86, mips, ppc, arm64
|
||||
|
||||
class CsDetail:
|
||||
|
||||
def __init__(self, arch, raw_detail = None):
|
||||
if not raw_detail:
|
||||
return
|
||||
detail = ctypes.cast(raw_detail, ctypes.POINTER(capstone._cs_detail)).contents
|
||||
|
||||
self.regs_read = detail.regs_read
|
||||
self.regs_write = detail.regs_write
|
||||
self.groups = detail.groups
|
||||
|
||||
if arch == capstone.CS_ARCH_ARM:
|
||||
(self.cc, self.update_flags, self.writeback, self.operands) = \
|
||||
arm.get_arch_info(detail.arch.arm)
|
||||
elif arch == capstone.CS_ARCH_ARM64:
|
||||
(self.cc, self.update_flags, self.writeback, self.operands) = \
|
||||
arm64.get_arch_info(detail.arch.arm64)
|
||||
elif arch == capstone.CS_ARCH_X86:
|
||||
(self.prefix, self.segment, self.opcode, self.op_size, self.addr_size, \
|
||||
self.disp_size, self.imm_size, self.modrm, self.sib, self.disp, \
|
||||
self.sib_index, self.sib_scale, self.sib_base, self.operands) = x86.get_arch_info(detail.arch.x86)
|
||||
elif arch == capstone.CS_ARCH_MIPS:
|
||||
self.operands = mips.get_arch_info(detail.arch.mips)
|
||||
elif arch == capstone.CS_ARCH_PPC:
|
||||
(self.bc, self.bh, self.update_cr0, self.operands) = \
|
||||
ppc.get_arch_info(detail.arch.ppc)
|
||||
|
||||
cdef class CCsInsn(object):
|
||||
|
||||
cdef cc.cs_insn _raw
|
||||
cdef cc.csh _csh
|
||||
cdef object _detail
|
||||
|
||||
def __cinit__(self, _detail):
|
||||
self._detail = _detail
|
||||
|
||||
def __getattr__(self, name):
|
||||
_detail = self._detail
|
||||
return getattr(_detail, name)
|
||||
|
||||
@property
|
||||
def operands(self):
|
||||
return self._detail.operands
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._raw.id
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return self._raw.address
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
return self._raw.size
|
||||
|
||||
@property
|
||||
def bytes(self):
|
||||
return bytearray(self._raw.bytes)[:self._raw.size]
|
||||
|
||||
@property
|
||||
def mnemonic(self):
|
||||
return self._raw.mnemonic
|
||||
|
||||
@property
|
||||
def op_str(self):
|
||||
return self._raw.op_str
|
||||
|
||||
@property
|
||||
def regs_read(self):
|
||||
if self._detail:
|
||||
detail = self._detail
|
||||
return detail.regs_read[:detail.regs_read_count]
|
||||
|
||||
raise CsError(CS_ERR_DETAIL)
|
||||
|
||||
@property
|
||||
def regs_write(self):
|
||||
if self._detail:
|
||||
detail = self._detail
|
||||
return detail.regs_write[:detail.regs_write_count]
|
||||
|
||||
raise CsError(CS_ERR_DETAIL)
|
||||
|
||||
@property
|
||||
def groups(self):
|
||||
if self._detail:
|
||||
detail = self._detail
|
||||
return detail.groups[:detail.groups_count]
|
||||
|
||||
raise CsError(CS_ERR_DETAIL)
|
||||
|
||||
# get the last error code
|
||||
def errno(self):
|
||||
return cc.cs_errno(self._csh)
|
||||
|
||||
# get the register name, given the register ID
|
||||
def reg_name(self, reg_id):
|
||||
return cc.cs_reg_name(self._csh, reg_id)
|
||||
|
||||
# get the instruction string
|
||||
def insn_name(self):
|
||||
return cc.cs_insn_name(self._csh, self.id)
|
||||
|
||||
# verify if this insn belong to group with id as @group_id
|
||||
def group(self, group_id):
|
||||
return group_id in self._detail.groups
|
||||
|
||||
# verify if this instruction implicitly read register @reg_id
|
||||
def reg_read(self, reg_id):
|
||||
return reg_id in self._detail.regs_read
|
||||
|
||||
# verify if this instruction implicitly modified register @reg_id
|
||||
def reg_write(self, reg_id):
|
||||
return reg_id in self._detail.regs_write
|
||||
|
||||
# return number of operands having same operand type @op_type
|
||||
def op_count(self, op_type):
|
||||
c = 0
|
||||
for op in self._detail.operands:
|
||||
if op.type == op_type:
|
||||
c += 1
|
||||
return c
|
||||
|
||||
# get the operand at position @position of all operands having the same type @op_type
|
||||
def op_find(self, op_type, position):
|
||||
c = 0
|
||||
for op in self._detail.operands:
|
||||
if op.type == op_type:
|
||||
c += 1
|
||||
if c == position:
|
||||
return op
|
||||
|
||||
cdef class CCs:
|
||||
|
||||
cdef cc.csh csh
|
||||
cdef object _cs
|
||||
|
||||
def __cinit__(self, _cs):
|
||||
self.csh = <cc.csh> _cs.csh.value
|
||||
self._cs = _cs
|
||||
|
||||
def getcsh(self):
|
||||
return ctypes.c_size_t(<size_t>self.csh)
|
||||
|
||||
def disasm(self, code, addr, count=0):
|
||||
cdef cc.cs_insn *allinsn
|
||||
cdef res = cc.cs_disasm_ex(self.csh, code, len(code), addr, count, &allinsn)
|
||||
detail = self._cs.detail
|
||||
arch = self._cs.arch
|
||||
|
||||
for i from 0 <= i < res:
|
||||
if detail:
|
||||
dummy = CCsInsn(CsDetail(arch, <size_t>allinsn[i].detail))
|
||||
else:
|
||||
dummy = CCsInsn(None)
|
||||
dummy._raw = allinsn[i]
|
||||
dummy._csh = self.csh
|
||||
yield dummy
|
||||
|
||||
|
|
@ -8,6 +8,7 @@ VERSION = '2.0'
|
|||
compile_args = ['-O3', '-fomit-frame-pointer']
|
||||
|
||||
ext_modules = [ Extension("capstone.capstone", ["pyx/capstone.pyx"], extra_compile_args=compile_args),
|
||||
Extension("capstone.ccapstone", ["pyx/ccapstone.pyx"], libraries=["capstone"], extra_compile_args=compile_args),
|
||||
Extension("capstone.arm", ["pyx/arm.pyx"], extra_compile_args=compile_args),
|
||||
Extension("capstone.arm_const", ["pyx/arm_const.pyx"], extra_compile_args=compile_args),
|
||||
Extension("capstone.arm64", ["pyx/arm64.pyx"], extra_compile_args=compile_args),
|
||||
|
|
Loading…
Reference in New Issue