Skip to content
Snippets Groups Projects
Commit 32c13df6 authored by Ingmar Steen's avatar Ingmar Steen
Browse files

Add nodejs bindings

parent 8ce0261a
No related branches found
No related tags found
No related merge requests found
Showing with 351 additions and 0 deletions
...@@ -29,6 +29,24 @@ template = { ...@@ -29,6 +29,24 @@ template = {
'comment_open': '#', 'comment_open': '#',
'comment_close': '', 'comment_close': '',
}, },
'nodejs': {
'header': "// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.js]\n",
'footer': "",
'line_format': 'module.exports.%s = %s\n',
'out_file': './nodejs/consts/%s.js',
# prefixes for constant filenames of all archs - case sensitive
'arm.h': 'arm',
'arm64.h': 'arm64',
'mips.h': 'mips',
'x86.h': 'x86',
'sparc.h': 'sparc',
'systemz.h': 'systemz',
'ppc.h': 'ppc',
'hexagon.h': 'hexagon',
'keystone.h': 'keystone',
'comment_open': '//',
'comment_close': '',
},
} }
# markup for comments to be added to autogen files # markup for comments to be added to autogen files
......
Copyright (c) 2016 Ingmar Steen
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
# node-keystone
`node-keystone` provides Node.js bindings for the
[Keystone](http://www.keystone-engine.org) assembler library, allowing
text data in to be assembled into `Buffer` objects using any of Keystone's
supported architectures.
### Install
`npm install /path/to/keystone/bindings/nodejs`
#### libkeystone
These bindings require you to have the Keystone library installed as it is
not included.
### Basic usage
```javascript
var keystone = require("keystone");
var assembly = "inc ecx; dec ebx"
var ks = new keystone.Ks(keystone.ARCH_X86, keystone.MODE_64);
console.log(ks.asm(assembly));
ks.close();
```
For other examples, see the `example.js` file.
### License
The source code is hereby released under the MIT License. The full text of the
license appears below.
Copyright (c) 2016 Ingmar Steen
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.js]
module.exports.ERR_ASM_ARM_INVALIDOPERAND = 512
module.exports.ERR_ASM_ARM_MISSINGFEATURE = 513
module.exports.ERR_ASM_ARM_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.js]
module.exports.ERR_ASM_ARM64_INVALIDOPERAND = 512
module.exports.ERR_ASM_ARM64_MISSINGFEATURE = 513
module.exports.ERR_ASM_ARM64_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [hexagon_const.js]
module.exports.ERR_ASM_HEXAGON_INVALIDOPERAND = 512
module.exports.ERR_ASM_HEXAGON_MISSINGFEATURE = 513
module.exports.ERR_ASM_HEXAGON_MNEMONICFAIL = 514
var extend = require('util')._extend,
archs = ['arm64', 'arm', 'hexagon', 'mips', 'ppc', 'sparc', 'systemz', 'x86'],
i
module.exports = require('./keystone')
for (i = 0; i < archs.length; ++i) {
extend(module.exports, require('./' + archs[i]));
}
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystone_const.js]
module.exports.API_MAJOR = 1
module.exports.API_MINOR = 0
module.exports.ARCH_ARM = 1
module.exports.ARCH_ARM64 = 2
module.exports.ARCH_MIPS = 3
module.exports.ARCH_X86 = 4
module.exports.ARCH_PPC = 5
module.exports.ARCH_SPARC = 6
module.exports.ARCH_SYSTEMZ = 7
module.exports.ARCH_HEXAGON = 8
module.exports.ARCH_MAX = 9
module.exports.MODE_LITTLE_ENDIAN = 0
module.exports.MODE_BIG_ENDIAN = 1073741824
module.exports.MODE_ARM = 1
module.exports.MODE_THUMB = 16
module.exports.MODE_V8 = 64
module.exports.MODE_MICRO = 16
module.exports.MODE_MIPS3 = 32
module.exports.MODE_MIPS32R6 = 64
module.exports.MODE_MIPS32 = 4
module.exports.MODE_MIPS64 = 8
module.exports.MODE_16 = 2
module.exports.MODE_32 = 4
module.exports.MODE_64 = 8
module.exports.MODE_PPC32 = 4
module.exports.MODE_PPC64 = 8
module.exports.MODE_QPX = 16
module.exports.MODE_SPARC32 = 4
module.exports.MODE_SPARC64 = 8
module.exports.MODE_V9 = 16
module.exports.ERR_ASM = 128
module.exports.ERR_ASM_ARCH = 512
module.exports.ERR_OK = 0
module.exports.ERR_NOMEM = 1
module.exports.ERR_ARCH = 2
module.exports.ERR_HANDLE = 3
module.exports.ERR_MODE = 4
module.exports.ERR_VERSION = 5
module.exports.ERR_OPT_INVALID = 6
module.exports.ERR_ASM_EXPR_TOKEN = 128
module.exports.ERR_ASM_DIRECTIVE_VALUE_RANGE = 129
module.exports.ERR_ASM_DIRECTIVE_ID = 130
module.exports.ERR_ASM_DIRECTIVE_TOKEN = 131
module.exports.ERR_ASM_DIRECTIVE_STR = 132
module.exports.ERR_ASM_DIRECTIVE_COMMA = 133
module.exports.ERR_ASM_DIRECTIVE_RELOC_NAME = 134
module.exports.ERR_ASM_DIRECTIVE_RELOC_TOKEN = 135
module.exports.ERR_ASM_DIRECTIVE_FPOINT = 136
module.exports.ERR_ASM_VARIANT_INVALID = 137
module.exports.ERR_ASM_EXPR_BRACKET = 138
module.exports.ERR_ASM_SYMBOL_MODIFIER = 139
module.exports.ERR_ASM_RPAREN = 140
module.exports.ERR_ASM_STAT_TOKEN = 141
module.exports.ERR_ASM_UNSUPPORTED = 142
module.exports.ERR_ASM_MACRO_TOKEN = 143
module.exports.ERR_ASM_MACRO_PAREN = 144
module.exports.ERR_ASM_MACRO_EQU = 145
module.exports.ERR_ASM_MACRO_ARGS = 146
module.exports.ERR_ASM_MACRO_LEVELS_EXCEED = 147
module.exports.ERR_ASM_ESC_BACKSLASH = 148
module.exports.ERR_ASM_ESC_OCTAL = 149
module.exports.ERR_ASM_ESC_SEQUENCE = 150
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_SYNTAX_INTEL = 1
module.exports.OPT_SYNTAX_ATT = 2
module.exports.OPT_SYNTAX_NASM = 4
module.exports.OPT_SYNTAX_MASM = 8
module.exports.OPT_SYNTAX_GAS = 16
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.js]
module.exports.ERR_ASM_MIPS_INVALIDOPERAND = 512
module.exports.ERR_ASM_MIPS_MISSINGFEATURE = 513
module.exports.ERR_ASM_MIPS_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.js]
module.exports.ERR_ASM_PPC_INVALIDOPERAND = 512
module.exports.ERR_ASM_PPC_MISSINGFEATURE = 513
module.exports.ERR_ASM_PPC_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.js]
module.exports.ERR_ASM_SPARC_INVALIDOPERAND = 512
module.exports.ERR_ASM_SPARC_MISSINGFEATURE = 513
module.exports.ERR_ASM_SPARC_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [systemz_const.js]
module.exports.ERR_ASM_SYSTEMZ_INVALIDOPERAND = 512
module.exports.ERR_ASM_SYSTEMZ_MISSINGFEATURE = 513
module.exports.ERR_ASM_SYSTEMZ_MNEMONICFAIL = 514
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.js]
module.exports.ERR_ASM_X86_INVALIDOPERAND = 512
module.exports.ERR_ASM_X86_MISSINGFEATURE = 513
module.exports.ERR_ASM_X86_MNEMONICFAIL = 514
var ref = require('ref'),
ffi = require('ffi'),
consts = require('./consts'),
extend = require('util')._extend
var ks_engine = 'void',
ks_enginePtr = ref.refType(ks_engine),
ks_enginePtrPtr = ref.refType(ks_enginePtr),
ks_arch = 'int',
ks_err = 'int',
ks_opt_type = 'int',
uintPtr = ref.refType('uint'),
ucharPtr = ref.refType('uchar'),
ucharPtrPtr = ref.refType(ucharPtr),
size_tPtr = ref.refType('size_t'),
stringPtr = ref.refType('string')
var Keystone = ffi.Library('libkeystone', {
'ks_version': [ 'uint', [ uintPtr, uintPtr ] ],
'ks_arch_supported': [ 'bool', [ ks_arch ] ],
'ks_open': [ ks_err, [ ks_arch, 'int', ks_enginePtrPtr ] ],
'ks_close': [ ks_err, [ ks_enginePtr ] ],
'ks_errno': [ 'int', [ ks_enginePtr ] ],
'ks_strerror': [ 'string', [ ks_err ] ],
'ks_option': [ ks_err, [ ks_enginePtr, ks_opt_type, 'size_t' ] ],
'ks_asm': [ 'int', [ ks_enginePtr, 'string', 'uint64', ucharPtrPtr, size_tPtr, size_tPtr ] ],
'ks_free': [ 'void', [ 'pointer' ] ]
})
function KsError(message, errno, count) {
this.message = message
this.errno = errno
this.count = count
}
function Ks(arch, mode) {
var _ks = ref.alloc(ks_enginePtr),
err = Keystone.ks_open(arch, mode, _ks)
if (err !== consts.ERR_OK) {
this._ks = null
throw new KsError('Error: failed on ks_open()')
}
this._ks = _ks.deref()
this.__defineGetter__('errno', function() {
return Keystone.ks_errno(this._ks)
})
this.__defineSetter__('syntax', function(value) {
this.set_option(consts.OPT_SYNTAX, value)
})
}
Ks.prototype.asm = function(code, addr) {
var encoding = ref.alloc('uchar *'),
size = ref.alloc('size_t'),
count = ref.alloc('size_t'),
err, msg
if (Keystone.ks_asm(this._ks, code, addr || 0, encoding, size, count) !== consts.ERR_OK) {
err = this.errno
msg = Keystone.ks_strerror(err)
throw new KsError(msg, err, count.deref())
}
return {
encoding: ref.reinterpret(encoding.deref(), size.deref(), 0),
count: count.deref()
}
}
Ks.prototype.close = function() {
Keystone.ks_close(this._ks)
this._ks = null
}
Ks.prototype.set_option = function(type, value) {
var err = Keystone.ks_option(this._ks, type, value)
if (err != consts.ERR_OK) {
throw new KsError(Keystone.ks_strerror(err), err)
}
}
module.exports.Ks = Ks
module.exports.is_arch_supported = function(arch) {
return Keystone.ks_arch_supported(arch)
}
module.exports.__defineGetter__('version', function() {
var version = Keystone.ks_version(null, null)
return {
major: version >> 8,
minor: version & 255
}
})
extend(module.exports, consts)
{
"name": "keystone",
"version": "1.0.0",
"description": "Keystone assembler engine",
"homepage": "http://www.keystone-engine.org",
"main": "index.js",
"dependencies": {
"ffi": "^2.0.0",
"ref": "^1.3.2"
},
"devDependencies": {},
"scripts": {
"prepublish": "cd .. && python const_generator.py nodejs",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Ingmar Steen <iksteen@gmail.com>",
"license": "MIT"
}
var keystone = require('.') // Or: require('keystone') if you have installed it
console.log('Using keystone ' + keystone.version.major + '.' + keystone.version.minor)
var ks, assembly, result
// Check if architecture is supported
if (! keystone.is_arch_supported(keystone.ARCH_X86)) {
throw 'Warning: X86 architecture not supported by keystone.'
}
// Create a new Keystone instance for X86 64bit
ks = new keystone.Ks(keystone.ARCH_X86, keystone.MODE_64)
// Assemble some instructions
assembly = 'inc rcx; dec rbx'
result = ks.asm(assembly)
console.log('"' + assembly + '"', ':', result.encoding)
// Change syntax, assemble some more instructions
assembly = 'lea rax, [label1]\nnop\nnop\nlabel1:'
ks.syntax = keystone.OPT_SYNTAX_NASM
result = ks.asm(assembly)
console.log('"' + assembly.replace(/\n/g, '; ') + '"', ':', result.encoding)
// Close Keystone instance to free resources
ks.close()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment