From 2d8863a9ee84fcbd55df481d59da6d6577b2de18 Mon Sep 17 00:00:00 2001
From: Sascha Schirra <sashs@scoding.de>
Date: Sun, 15 May 2016 00:07:39 +0200
Subject: [PATCH] added bindings for ruby

---
 bindings/const_generator.py                   |  18 +++
 bindings/ruby/Makefile                        |  11 ++
 bindings/ruby/README.md                       |  24 ++++
 bindings/ruby/keystone_gem/Gemfile            |   3 +
 bindings/ruby/keystone_gem/Rakefile           |   2 +
 bindings/ruby/keystone_gem/ext/extconf.rb     |   8 ++
 bindings/ruby/keystone_gem/ext/keystone.c     | 113 ++++++++++++++++++
 bindings/ruby/keystone_gem/ext/keystone.h     |  24 ++++
 bindings/ruby/keystone_gem/keystone.gemspec   |  21 ++++
 .../keystone_gem/lib/keystone/arm64_const.rb  |   7 ++
 .../keystone_gem/lib/keystone/arm_const.rb    |   7 ++
 .../lib/keystone/hexagon_const.rb             |   7 ++
 .../lib/keystone/keystone_const.rb            |  78 ++++++++++++
 .../keystone_gem/lib/keystone/mips_const.rb   |   7 ++
 .../keystone_gem/lib/keystone/ppc_const.rb    |   7 ++
 .../keystone_gem/lib/keystone/sparc_const.rb  |   7 ++
 .../lib/keystone/systemz_const.rb             |   7 ++
 .../ruby/keystone_gem/lib/keystone/version.rb |   3 +
 .../keystone_gem/lib/keystone/x86_const.rb    |   7 ++
 bindings/ruby/keystone_gem/pkg/.gitignore     |  10 ++
 bindings/ruby/sample.rb                       |  60 ++++++++++
 21 files changed, 431 insertions(+)
 create mode 100644 bindings/ruby/Makefile
 create mode 100644 bindings/ruby/README.md
 create mode 100644 bindings/ruby/keystone_gem/Gemfile
 create mode 100644 bindings/ruby/keystone_gem/Rakefile
 create mode 100644 bindings/ruby/keystone_gem/ext/extconf.rb
 create mode 100644 bindings/ruby/keystone_gem/ext/keystone.c
 create mode 100644 bindings/ruby/keystone_gem/ext/keystone.h
 create mode 100644 bindings/ruby/keystone_gem/keystone.gemspec
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/arm64_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/arm_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/hexagon_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/mips_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/ppc_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/sparc_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/systemz_const.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/version.rb
 create mode 100644 bindings/ruby/keystone_gem/lib/keystone/x86_const.rb
 create mode 100644 bindings/ruby/keystone_gem/pkg/.gitignore
 create mode 100755 bindings/ruby/sample.rb

diff --git a/bindings/const_generator.py b/bindings/const_generator.py
index 96db7cb..beababa 100644
--- a/bindings/const_generator.py
+++ b/bindings/const_generator.py
@@ -47,6 +47,24 @@ template = {
             'comment_open': '//',
             'comment_close': '',
     },
+    'ruby': {
+            'header': "# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.rb]\n\nmodule Keystone\n",
+            'footer': "end",
+            'line_format': '\tKS_%s = %s\n',
+            'out_file': './ruby/keystone_gem/lib/keystone/%s_const.rb',
+            # 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
diff --git a/bindings/ruby/Makefile b/bindings/ruby/Makefile
new file mode 100644
index 0000000..467ec95
--- /dev/null
+++ b/bindings/ruby/Makefile
@@ -0,0 +1,11 @@
+# Ruby binding for Unicorn engine. Sascha Schirra <sashs@scoding.de>
+
+.PHONY: gen_const
+
+install:
+	$(MAKE) gen_const
+	C_INCLUDE_PATH=/usr/local/ cd keystone_gem && rake build
+	cd keystone_gem && gem install --local pkg/keystone-1.0.0.gem
+
+gen_const:
+	cd .. && python const_generator.py ruby
diff --git a/bindings/ruby/README.md b/bindings/ruby/README.md
new file mode 100644
index 0000000..82903b7
--- /dev/null
+++ b/bindings/ruby/README.md
@@ -0,0 +1,24 @@
+# Installation
+
+## Software requirements
+
+### Linux
+- ruby >= 1.9.3
+- rubygems
+- make
+- gcc
+
+### Mac OS
+- ruby >= 1.9.3
+- rubygems
+- make
+- XCode
+
+## Install keystone
+ * cd path_to_keystone
+ * ./make.sh install
+
+## Install ruby binding
+ * cd bindings/ruby
+ * make install
+    
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/Gemfile b/bindings/ruby/keystone_gem/Gemfile
new file mode 100644
index 0000000..fa75df1
--- /dev/null
+++ b/bindings/ruby/keystone_gem/Gemfile
@@ -0,0 +1,3 @@
+source 'https://rubygems.org'
+
+gemspec
diff --git a/bindings/ruby/keystone_gem/Rakefile b/bindings/ruby/keystone_gem/Rakefile
new file mode 100644
index 0000000..43022f7
--- /dev/null
+++ b/bindings/ruby/keystone_gem/Rakefile
@@ -0,0 +1,2 @@
+require "bundler/gem_tasks"
+task :default => :spec
diff --git a/bindings/ruby/keystone_gem/ext/extconf.rb b/bindings/ruby/keystone_gem/ext/extconf.rb
new file mode 100644
index 0000000..557251e
--- /dev/null
+++ b/bindings/ruby/keystone_gem/ext/extconf.rb
@@ -0,0 +1,8 @@
+require 'mkmf'
+
+extension_name = 'keystone'
+
+dir_config(extension_name)
+have_library('keystone')
+
+create_makefile(extension_name)
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/ext/keystone.c b/bindings/ruby/keystone_gem/ext/keystone.c
new file mode 100644
index 0000000..fe25e6d
--- /dev/null
+++ b/bindings/ruby/keystone_gem/ext/keystone.c
@@ -0,0 +1,113 @@
+/*
+
+Ruby bindings for the Keystone Engine
+
+Copyright(c) 2016 Sascha Schirra
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+*/
+#include "ruby.h"
+#include <keystone/keystone.h>
+#include "keystone.h"
+
+VALUE KeystoneModule = Qnil;
+VALUE KsClass = Qnil;
+VALUE KsError = Qnil;
+
+
+void Init_keystone() {
+    rb_require("keystone/keystone_const");
+    KeystoneModule = rb_define_module("Keystone");
+    KsError = rb_define_class_under(KeystoneModule, "KsError", rb_eStandardError);
+
+    KsClass = rb_define_class_under(KeystoneModule, "Ks", rb_cObject);
+    rb_define_method(KsClass, "initialize", m_ks_initialize, 2);
+    rb_define_method(KsClass, "asm", m_ks_asm, -1);
+    rb_define_method(KsClass, "syntax", m_ks_get_syntax, 0);
+    rb_define_method(KsClass, "syntax=", m_ks_set_syntax, 1);
+}
+
+VALUE m_ks_initialize(VALUE self, VALUE arch, VALUE mode) {
+    ks_engine *_ks;
+    ks_err err;
+    err = ks_open(NUM2INT(arch), NUM2INT(mode), &_ks);
+    if (err != KS_ERR_OK) {
+      rb_raise(KsError, "%d", err);
+    }
+
+    VALUE ks = Data_Wrap_Struct(KsClass, 0, ks_close, _ks);
+    rb_iv_set(self, "@ksh", ks);
+
+    if(NUM2INT(arch) == KS_ARCH_X86){
+      rb_iv_set(self, "@syntax", INT2NUM(KS_OPT_SYNTAX_INTEL));
+    }
+    else{
+      rb_iv_set(self, "@syntax", Qnil);
+    }
+
+    return self;
+}
+
+VALUE m_ks_asm(int argc, VALUE* argv, VALUE self){
+    VALUE string;
+    VALUE addr;
+
+    size_t count;
+    unsigned char *encode;
+    size_t size;
+
+    ks_err err;
+    ks_engine *_ks;
+
+    VALUE to_return = rb_ary_new();
+
+    Data_Get_Struct(rb_iv_get(self,"@ksh"), ks_engine, _ks);
+
+    rb_scan_args(argc, argv, "11", &string, &addr);
+    if (NIL_P(addr))
+        addr = INT2NUM(0);
+
+    err = ks_asm(_ks, StringValuePtr(string), NUM2INT(addr), &encode, &size, &count);
+    if (err != KS_ERR_OK) {
+      rb_raise(KsError, "%d", err);
+    }
+
+    if (count == 0){
+        rb_ary_store(to_return, 0, Qnil);
+        rb_ary_store(to_return, 1, INT2NUM(0));
+    }
+    else{
+        rb_ary_store(to_return, 0, rb_str_new(encode, size));
+        rb_ary_store(to_return, 1, INT2NUM(count));
+    }
+    ks_free(encode);
+    return to_return;
+}
+
+VALUE m_ks_get_syntax(VALUE self){
+  return rb_iv_get(self, "@syntax");
+}
+
+VALUE m_ks_set_syntax(VALUE self, VALUE val){
+  ks_err err;
+  ks_engine *_ks;
+
+  Data_Get_Struct(rb_iv_get(self,"@ksh"), ks_engine, _ks);
+
+  ks_option(_ks, KS_OPT_SYNTAX, NUM2INT(val));
+  rb_iv_set(self, "@syntax", val);
+
+  return Qnil;
+}
diff --git a/bindings/ruby/keystone_gem/ext/keystone.h b/bindings/ruby/keystone_gem/ext/keystone.h
new file mode 100644
index 0000000..50241e5
--- /dev/null
+++ b/bindings/ruby/keystone_gem/ext/keystone.h
@@ -0,0 +1,24 @@
+/*
+
+Ruby bindings for the Keystone Engine
+
+Copyright(c) 2016 Sascha Schirra
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+version 2 as published by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+*/
+VALUE m_ks_initialize(VALUE self, VALUE arch, VALUE mode);
+VALUE m_ks_asm(int argc, VALUE* argv, VALUE self);
+VALUE m_ks_get_syntax(VALUE self);
+VALUE m_ks_set_syntax(VALUE self, VALUE val);
diff --git a/bindings/ruby/keystone_gem/keystone.gemspec b/bindings/ruby/keystone_gem/keystone.gemspec
new file mode 100644
index 0000000..299d9fe
--- /dev/null
+++ b/bindings/ruby/keystone_gem/keystone.gemspec
@@ -0,0 +1,21 @@
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'keystone/version'
+
+Gem::Specification.new do |spec|
+  spec.name          = "keystone"
+  spec.version       = Keystone::VERSION
+  spec.authors       = ["Sascha Schirra"]
+  spec.email         = ["sashs@scoding.de"]
+  spec.license       = 'GPL-2.0'
+  spec.summary       = %q{Ruby binding for Keystone}
+  spec.description   = %q{Ruby binding for Keystone <Keystone-engine.org>}
+  spec.homepage      = "https://keystone-engine.org"
+
+  spec.files         = Dir["lib/keystone/*.rb"] + Dir["ext/keystone.c"] + Dir["ext/keystone.h"] + Dir["ext/extconf.rb"]
+  spec.require_paths = ["lib","ext"]
+  spec.extensions    = ["ext/extconf.rb"]
+  spec.add_development_dependency "bundler", "~> 1.11"
+  spec.add_development_dependency "rake", "~> 10.0"
+end
diff --git a/bindings/ruby/keystone_gem/lib/keystone/arm64_const.rb b/bindings/ruby/keystone_gem/lib/keystone/arm64_const.rb
new file mode 100644
index 0000000..324cc16
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/arm64_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.rb]
+
+module Keystone
+	KS_ERR_ASM_ARM64_INVALIDOPERAND = 512
+	KS_ERR_ASM_ARM64_MISSINGFEATURE = 513
+	KS_ERR_ASM_ARM64_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/arm_const.rb b/bindings/ruby/keystone_gem/lib/keystone/arm_const.rb
new file mode 100644
index 0000000..76c1261
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/arm_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.rb]
+
+module Keystone
+	KS_ERR_ASM_ARM_INVALIDOPERAND = 512
+	KS_ERR_ASM_ARM_MISSINGFEATURE = 513
+	KS_ERR_ASM_ARM_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/hexagon_const.rb b/bindings/ruby/keystone_gem/lib/keystone/hexagon_const.rb
new file mode 100644
index 0000000..9f04db2
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/hexagon_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [hexagon_const.rb]
+
+module Keystone
+	KS_ERR_ASM_HEXAGON_INVALIDOPERAND = 512
+	KS_ERR_ASM_HEXAGON_MISSINGFEATURE = 513
+	KS_ERR_ASM_HEXAGON_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
new file mode 100644
index 0000000..5d88e69
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb
@@ -0,0 +1,78 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystone_const.rb]
+
+module Keystone
+	KS_API_MAJOR = 1
+
+	KS_API_MINOR = 0
+	KS_ARCH_ARM = 1
+	KS_ARCH_ARM64 = 2
+	KS_ARCH_MIPS = 3
+	KS_ARCH_X86 = 4
+	KS_ARCH_PPC = 5
+	KS_ARCH_SPARC = 6
+	KS_ARCH_SYSTEMZ = 7
+	KS_ARCH_HEXAGON = 8
+	KS_ARCH_MAX = 9
+
+	KS_MODE_LITTLE_ENDIAN = 0
+	KS_MODE_BIG_ENDIAN = 1073741824
+	KS_MODE_ARM = 1
+	KS_MODE_THUMB = 16
+	KS_MODE_V8 = 64
+	KS_MODE_MICRO = 16
+	KS_MODE_MIPS3 = 32
+	KS_MODE_MIPS32R6 = 64
+	KS_MODE_MIPS32 = 4
+	KS_MODE_MIPS64 = 8
+	KS_MODE_16 = 2
+	KS_MODE_32 = 4
+	KS_MODE_64 = 8
+	KS_MODE_PPC32 = 4
+	KS_MODE_PPC64 = 8
+	KS_MODE_QPX = 16
+	KS_MODE_SPARC32 = 4
+	KS_MODE_SPARC64 = 8
+	KS_MODE_V9 = 16
+	KS_ERR_ASM = 128
+	KS_ERR_ASM_ARCH = 512
+
+	KS_ERR_OK = 0
+	KS_ERR_NOMEM = 1
+	KS_ERR_ARCH = 2
+	KS_ERR_HANDLE = 3
+	KS_ERR_MODE = 4
+	KS_ERR_VERSION = 5
+	KS_ERR_OPT_INVALID = 6
+	KS_ERR_ASM_EXPR_TOKEN = 128
+	KS_ERR_ASM_DIRECTIVE_VALUE_RANGE = 129
+	KS_ERR_ASM_DIRECTIVE_ID = 130
+	KS_ERR_ASM_DIRECTIVE_TOKEN = 131
+	KS_ERR_ASM_DIRECTIVE_STR = 132
+	KS_ERR_ASM_DIRECTIVE_COMMA = 133
+	KS_ERR_ASM_DIRECTIVE_RELOC_NAME = 134
+	KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN = 135
+	KS_ERR_ASM_DIRECTIVE_FPOINT = 136
+	KS_ERR_ASM_VARIANT_INVALID = 137
+	KS_ERR_ASM_EXPR_BRACKET = 138
+	KS_ERR_ASM_SYMBOL_MODIFIER = 139
+	KS_ERR_ASM_RPAREN = 140
+	KS_ERR_ASM_STAT_TOKEN = 141
+	KS_ERR_ASM_UNSUPPORTED = 142
+	KS_ERR_ASM_MACRO_TOKEN = 143
+	KS_ERR_ASM_MACRO_PAREN = 144
+	KS_ERR_ASM_MACRO_EQU = 145
+	KS_ERR_ASM_MACRO_ARGS = 146
+	KS_ERR_ASM_MACRO_LEVELS_EXCEED = 147
+	KS_ERR_ASM_ESC_BACKSLASH = 148
+	KS_ERR_ASM_ESC_OCTAL = 149
+	KS_ERR_ASM_ESC_SEQUENCE = 150
+	KS_ERR_ASM_INVALIDOPERAND = 512
+	KS_ERR_ASM_MISSINGFEATURE = 513
+	KS_ERR_ASM_MNEMONICFAIL = 514
+	KS_OPT_SYNTAX = 1
+	KS_OPT_SYNTAX_INTEL = 1
+	KS_OPT_SYNTAX_ATT = 2
+	KS_OPT_SYNTAX_NASM = 4
+	KS_OPT_SYNTAX_MASM = 8
+	KS_OPT_SYNTAX_GAS = 16
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/mips_const.rb b/bindings/ruby/keystone_gem/lib/keystone/mips_const.rb
new file mode 100644
index 0000000..85990e9
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/mips_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.rb]
+
+module Keystone
+	KS_ERR_ASM_MIPS_INVALIDOPERAND = 512
+	KS_ERR_ASM_MIPS_MISSINGFEATURE = 513
+	KS_ERR_ASM_MIPS_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/ppc_const.rb b/bindings/ruby/keystone_gem/lib/keystone/ppc_const.rb
new file mode 100644
index 0000000..ee518dd
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/ppc_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.rb]
+
+module Keystone
+	KS_ERR_ASM_PPC_INVALIDOPERAND = 512
+	KS_ERR_ASM_PPC_MISSINGFEATURE = 513
+	KS_ERR_ASM_PPC_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/sparc_const.rb b/bindings/ruby/keystone_gem/lib/keystone/sparc_const.rb
new file mode 100644
index 0000000..2053907
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/sparc_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.rb]
+
+module Keystone
+	KS_ERR_ASM_SPARC_INVALIDOPERAND = 512
+	KS_ERR_ASM_SPARC_MISSINGFEATURE = 513
+	KS_ERR_ASM_SPARC_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/systemz_const.rb b/bindings/ruby/keystone_gem/lib/keystone/systemz_const.rb
new file mode 100644
index 0000000..2d93464
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/systemz_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [systemz_const.rb]
+
+module Keystone
+	KS_ERR_ASM_SYSTEMZ_INVALIDOPERAND = 512
+	KS_ERR_ASM_SYSTEMZ_MISSINGFEATURE = 513
+	KS_ERR_ASM_SYSTEMZ_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/lib/keystone/version.rb b/bindings/ruby/keystone_gem/lib/keystone/version.rb
new file mode 100644
index 0000000..74c6872
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/version.rb
@@ -0,0 +1,3 @@
+module Keystone
+  VERSION = "1.0.0"
+end
diff --git a/bindings/ruby/keystone_gem/lib/keystone/x86_const.rb b/bindings/ruby/keystone_gem/lib/keystone/x86_const.rb
new file mode 100644
index 0000000..1444012
--- /dev/null
+++ b/bindings/ruby/keystone_gem/lib/keystone/x86_const.rb
@@ -0,0 +1,7 @@
+# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.rb]
+
+module Keystone
+	KS_ERR_ASM_X86_INVALIDOPERAND = 512
+	KS_ERR_ASM_X86_MISSINGFEATURE = 513
+	KS_ERR_ASM_X86_MNEMONICFAIL = 514
+end
\ No newline at end of file
diff --git a/bindings/ruby/keystone_gem/pkg/.gitignore b/bindings/ruby/keystone_gem/pkg/.gitignore
new file mode 100644
index 0000000..b7e7725
--- /dev/null
+++ b/bindings/ruby/keystone_gem/pkg/.gitignore
@@ -0,0 +1,10 @@
+/.bundle/
+/.yardoc
+/Gemfile.lock
+/_yardoc/
+/coverage/
+/doc/
+/pkg/
+/spec/reports/
+/tmp/
+*.gem
diff --git a/bindings/ruby/sample.rb b/bindings/ruby/sample.rb
new file mode 100755
index 0000000..61411db
--- /dev/null
+++ b/bindings/ruby/sample.rb
@@ -0,0 +1,60 @@
+#!/usr/bin/env ruby
+
+# Sample code for Keystone assembler engine.
+# By Sascha Schirra <sashs82@gmail.com>, 2016
+
+require 'keystone'
+
+include Keystone
+
+def test_ks(arch, mode, code, syntax=0)
+    ks = Ks.new(arch, mode)
+    if syntax != 0
+        ks.syntax = syntax
+    end
+    encoding, count = ks.asm(code)
+
+    print("%s = [ " % code)
+    encoding.each_char do |i|
+        print("%02x " % i.ord)
+    end
+    puts("]")
+end
+
+
+# X86
+test_ks(KS_ARCH_X86, KS_MODE_16, "add eax, ecx")
+test_ks(KS_ARCH_X86, KS_MODE_32, "add eax, ecx")
+test_ks(KS_ARCH_X86, KS_MODE_64, "add rax, rcx")
+test_ks(KS_ARCH_X86, KS_MODE_32, "add %ecx, %eax", KS_OPT_SYNTAX_ATT)
+test_ks(KS_ARCH_X86, KS_MODE_64, "add %rcx, %rax", KS_OPT_SYNTAX_ATT)
+
+# ARM
+test_ks(KS_ARCH_ARM, KS_MODE_ARM, "sub r1, r2, r5")
+test_ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_BIG_ENDIAN, "sub r1, r2, r5")
+test_ks(KS_ARCH_ARM, KS_MODE_THUMB, "movs r4, #0xf0")
+test_ks(KS_ARCH_ARM, KS_MODE_THUMB + KS_MODE_BIG_ENDIAN, "movs r4, #0xf0")
+
+# ARM64
+test_ks(KS_ARCH_ARM64, KS_MODE_BIG_ENDIAN, "ldr w1, [sp, #0x8]")
+
+# Hexagon
+test_ks(KS_ARCH_HEXAGON, KS_MODE_BIG_ENDIAN, "v23.w=vavg(v11.w,v2.w):rnd")
+
+# Mips
+test_ks(KS_ARCH_MIPS, KS_MODE_MIPS32, "and $9, $6, $7")
+test_ks(KS_ARCH_MIPS, KS_MODE_MIPS32 + KS_MODE_BIG_ENDIAN, "and $9, $6, $7")
+test_ks(KS_ARCH_MIPS, KS_MODE_MIPS64, "and $9, $6, $7")
+test_ks(KS_ARCH_MIPS, KS_MODE_MIPS64 + KS_MODE_BIG_ENDIAN, "and $9, $6, $7")
+
+# PowerPC
+test_ks(KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN, "add 1, 2, 3")
+test_ks(KS_ARCH_PPC, KS_MODE_PPC64, "add 1, 2, 3")
+test_ks(KS_ARCH_PPC, KS_MODE_PPC64 + KS_MODE_BIG_ENDIAN, "add 1, 2, 3")
+
+# Sparc
+test_ks(KS_ARCH_SPARC, KS_MODE_SPARC32 + KS_MODE_LITTLE_ENDIAN, "add %g1, %g2, %g3")
+test_ks(KS_ARCH_SPARC, KS_MODE_SPARC32 + KS_MODE_BIG_ENDIAN, "add %g1, %g2, %g3")
+
+# SystemZ
+test_ks(KS_ARCH_SYSTEMZ, KS_MODE_BIG_ENDIAN, "a %r0, 4095(%r15,%r1)")
-- 
GitLab