diff --git a/bindings/go/keystone/keystone_const.go b/bindings/go/keystone/keystone_const.go index 7768d1ad9b07d463a4ee30f15b80d313513186c7..7cf27ef5cf4bbcfb8f60d9a4fb1874fd72cc89c0 100644 --- a/bindings/go/keystone/keystone_const.go +++ b/bindings/go/keystone/keystone_const.go @@ -45,6 +45,7 @@ const ( ) const ( + OPT_SYM_RESOLVER OptionValue = 2 OPT_SYNTAX_INTEL OptionValue = 1 OPT_SYNTAX_ATT OptionValue = 2 OPT_SYNTAX_NASM OptionValue = 4 diff --git a/bindings/nodejs/consts/keystone.js b/bindings/nodejs/consts/keystone.js index a077580ffe7797dafa2715ff4650189c96eea34c..1b8a5f7ca79d306ff34923d74293b9381b7ac0a4 100644 --- a/bindings/nodejs/consts/keystone.js +++ b/bindings/nodejs/consts/keystone.js @@ -78,6 +78,7 @@ module.exports.ERR_ASM_INVALIDOPERAND = 512 module.exports.ERR_ASM_MISSINGFEATURE = 513 module.exports.ERR_ASM_MNEMONICFAIL = 514 module.exports.OPT_SYNTAX = 1 +module.exports.OPT_SYM_RESOLVER = 2 module.exports.OPT_SYNTAX_INTEL = 1 module.exports.OPT_SYNTAX_ATT = 2 module.exports.OPT_SYNTAX_NASM = 4 diff --git a/bindings/python/keystone/keystone.py b/bindings/python/keystone/keystone.py index ee0e9e8edcd0e9c6e832156f0b600a4fb75a3bcb..c0e7de8efe63bf1f74a9b5f5289997b679f67126 100644 --- a/bindings/python/keystone/keystone.py +++ b/bindings/python/keystone/keystone.py @@ -91,11 +91,12 @@ _setup_prototype(_ks, "ks_open", kserr, c_uint, c_uint, POINTER(ks_engine)) _setup_prototype(_ks, "ks_close", kserr, ks_engine) _setup_prototype(_ks, "ks_strerror", c_char_p, kserr) _setup_prototype(_ks, "ks_errno", kserr, ks_engine) -_setup_prototype(_ks, "ks_option", kserr, ks_engine, c_int, c_size_t) -# int ks_asm(ks_engine *ks, const char *string, uint64_t address, unsigned char **encoding, size_t *encoding_size, size_t *stat_count); +_setup_prototype(_ks, "ks_option", kserr, ks_engine, c_int, c_void_p) _setup_prototype(_ks, "ks_asm", c_int, ks_engine, c_char_p, c_uint64, POINTER(POINTER(c_ubyte)), POINTER(c_size_t), POINTER(c_size_t)) _setup_prototype(_ks, "ks_free", None, POINTER(c_ubyte)) +# callback for OPT_SYM_RESOLVER option +KS_SYM_RESOLVER = CFUNCTYPE(c_bool, c_char_p, POINTER(c_uint64)) # access to error code via @errno of KsError # this also includes the @stat_count returned by ks_asm @@ -184,6 +185,21 @@ class Ks(object): self._syntax = style + @property + def sym_resolver(self): + return + + + @sym_resolver.setter + def sym_resolver(self, resolver): + callback = KS_SYM_RESOLVER(resolver) + status = _ks.ks_option(self._ksh, KS_OPT_SYM_RESOLVER, callback) + if status != KS_ERR_OK: + raise KsError(status) + # save resolver + self._sym_resolver = callback + + # assemble a string of assembly def asm(self, string, addr = 0): encode = POINTER(c_ubyte)() diff --git a/bindings/python/keystone/keystone_const.py b/bindings/python/keystone/keystone_const.py index d81803717966d572bb66443abc80c6a7a50e92d9..5ea12fbb1276e1da27c723643e1c6e8c082f5115 100644 --- a/bindings/python/keystone/keystone_const.py +++ b/bindings/python/keystone/keystone_const.py @@ -78,6 +78,7 @@ KS_ERR_ASM_INVALIDOPERAND = 512 KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 KS_OPT_SYNTAX = 1 +KS_OPT_SYM_RESOLVER = 2 KS_OPT_SYNTAX_INTEL = 1 KS_OPT_SYNTAX_ATT = 2 KS_OPT_SYNTAX_NASM = 4 diff --git a/bindings/python/sample.py b/bindings/python/sample.py index db634147242402373f26c99399355c74e9369412..2e2830eecb771fc565da6a94021887f9e45b8491 100755 --- a/bindings/python/sample.py +++ b/bindings/python/sample.py @@ -20,6 +20,33 @@ def test_ks(arch, mode, code, syntax=0): print("]") +# test symbol resolver +def test_sym_resolver(): + def sym_resolver(symbol, value): + # is this the missing symbol we want to handle? + if symbol == "_l1": + # put value of this symbol in @value + value = 0x1002 + # we handled this symbol, so return true + return True + + # we did not handle this symbol, so return false + return False + + ks = Ks(KS_ARCH_X86, KS_MODE_32) + + # register callback for symbol resolver + ks.sym_resolver = sym_resolver + + CODE = b"jmp _l1; nop; _l1:" + encoding, count = ks.asm(CODE, 0x1000) + + print("%s = [ " % CODE, end='') + for i in encoding: + print("%02x " % i, end='') + print("]") + + if __name__ == '__main__': # X86 test_ks(KS_ARCH_X86, KS_MODE_16, b"add eax, ecx") @@ -66,3 +93,6 @@ if __name__ == '__main__': # SystemZ test_ks(KS_ARCH_SYSTEMZ, KS_MODE_BIG_ENDIAN, b"a %r0, 4095(%r15,%r1)") + + # test symbol resolver + test_sym_resolver() diff --git a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb index fa427c2faa19a8386808f2cb5f79e78c06b0e2a1..5d3ff81f239211e36b7b8310c847bdfdc20bb2ec 100644 --- a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb +++ b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb @@ -80,6 +80,7 @@ module Keystone KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 KS_OPT_SYNTAX = 1 + KS_OPT_SYM_RESOLVER = 2 KS_OPT_SYNTAX_INTEL = 1 KS_OPT_SYNTAX_ATT = 2 KS_OPT_SYNTAX_NASM = 4 diff --git a/bindings/rust/src/keystone_const.rs b/bindings/rust/src/keystone_const.rs index 583579771a710505fc63425d93eb4a72613b42c2..436e875477e4a844629dda9584f039608fa5fb74 100644 --- a/bindings/rust/src/keystone_const.rs +++ b/bindings/rust/src/keystone_const.rs @@ -88,6 +88,7 @@ impl OptionType { bitflags! { pub flags OptionValue : libc::size_t { + const OPT_SYM_RESOLVER = 2, const OPT_SYNTAX_INTEL = 1, const OPT_SYNTAX_ATT = 2, const OPT_SYNTAX_NASM = 4,