commit
095f1b17d0
@ -0,0 +1,10 @@
|
|||||||
|
Checklist for a new release:
|
||||||
|
|
||||||
|
- update ChangeLog
|
||||||
|
- cd bindings; make
|
||||||
|
- update API version in keystone.h
|
||||||
|
- update API version in CMakeLists.txt
|
||||||
|
- change version + dev status in bindings/python/setup.py
|
||||||
|
- push all local commits
|
||||||
|
- tag + push -- tags -> check for new Pypi package
|
||||||
|
|
@ -0,0 +1,33 @@
|
|||||||
|
version: 1.0-{build}
|
||||||
|
|
||||||
|
os:
|
||||||
|
- Visual Studio 2015
|
||||||
|
|
||||||
|
before_build:
|
||||||
|
- call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" amd64
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- ..\nmake-dll.bat
|
||||||
|
- ..\nmake-lib.bat
|
||||||
|
|
||||||
|
after_build:
|
||||||
|
- mkdir keystone-windows-latest
|
||||||
|
- copy llvm\bin\keystone.dll keystone-windows-latest
|
||||||
|
- copy llvm\lib\keystone.lib keystone-windows-latest
|
||||||
|
- copy kstool\kstool.exe keystone-windows-latest
|
||||||
|
- 7z a keystone-windows-latest.zip keystone-windows-latest\*
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: build\keystone-windows-latest.zip
|
||||||
|
name: All Windows binaries
|
||||||
|
|
||||||
|
- path: build\llvm\bin\keystone.dll
|
||||||
|
name: keystone.dll
|
||||||
|
|
||||||
|
- path: build\llvm\lib\keystone.lib
|
||||||
|
name: keystone.lib
|
||||||
|
|
||||||
|
- path: build\kstool\kstool.exe
|
||||||
|
name: kstool.exe
|
@ -0,0 +1,80 @@
|
|||||||
|
name: PyPI 📦 Distribution
|
||||||
|
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||||
|
platform: [x32, x64]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Set up MSVC x86
|
||||||
|
if: matrix.os == 'windows-latest' && matrix.platform == 'x32'
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
with:
|
||||||
|
arch: x86
|
||||||
|
|
||||||
|
- name: Set up MSVC x64
|
||||||
|
if: matrix.os == 'windows-latest' && matrix.platform == 'x64'
|
||||||
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
pip install setuptools wheel
|
||||||
|
|
||||||
|
- name: Build distribution 📦
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'windows-latest' ]; then
|
||||||
|
cd bindings/python && python setup.py build -p win32 bdist_wheel -p win32
|
||||||
|
elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then
|
||||||
|
docker run --rm -v `pwd`/:/work dockcross/manylinux1-x86 > ./dockcross
|
||||||
|
chmod +x ./dockcross
|
||||||
|
./dockcross bindings/python/build_wheel.sh
|
||||||
|
elif [ ${{ matrix.platform }} == 'x64' ] && [ ${{ matrix.os }} == 'ubuntu-latest' ]; then
|
||||||
|
docker run --rm -v `pwd`/:/work dockcross/manylinux1-x64 > ./dockcross
|
||||||
|
chmod +x ./dockcross
|
||||||
|
./dockcross bindings/python/build_wheel.sh
|
||||||
|
elif [ ${{ matrix.platform }} == 'x32' ] && [ ${{ matrix.os }} == 'macos-latest' ]; then
|
||||||
|
cd bindings/python && python setup.py sdist
|
||||||
|
else
|
||||||
|
cd bindings/python && python setup.py bdist_wheel
|
||||||
|
fi
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
path: ${{ github.workspace }}/bindings/python/dist/*
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: [build]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: startsWith(github.ref, 'refs/tags')
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: artifact
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
- name: Publish distribution 📦 to test PyPI
|
||||||
|
uses: pypa/gh-action-pypi-publish@master
|
||||||
|
with:
|
||||||
|
user: __token__
|
||||||
|
password: ${{ secrets.testpypi_pass }}
|
||||||
|
repository_url: https://test.pypi.org/legacy/
|
||||||
|
|
||||||
|
- name: Publish distribution 📦 to PyPI
|
||||||
|
if: ${{ success() }}
|
||||||
|
uses: pypa/gh-action-pypi-publish@master
|
||||||
|
with:
|
||||||
|
user: __token__
|
||||||
|
password: ${{ secrets.pypi_pass }}
|
@ -0,0 +1,29 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.d
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.dSYM
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.exe
|
||||||
|
*.dll
|
||||||
|
*.dylib
|
||||||
|
*.class
|
||||||
|
*.jar
|
||||||
|
*.pyc
|
||||||
|
*.egg-info
|
||||||
|
*.tgz
|
||||||
|
*.tar.gz
|
||||||
|
*.github.io
|
||||||
|
_*.diff
|
||||||
|
|
||||||
|
build*/
|
||||||
|
samples/sample
|
||||||
|
_sample*.txt
|
||||||
|
tmp
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
bindings/python/dist/
|
||||||
|
bindings/python/src/
|
||||||
|
|
@ -0,0 +1,67 @@
|
|||||||
|
language: cpp
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DLLVM_TARGETS_TO_BUILD="all" -G "Unix Makefiles" ..
|
||||||
|
- make -j 8
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
- clang
|
||||||
|
- gcc
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
include:
|
||||||
|
- if: branch = master
|
||||||
|
os: osx
|
||||||
|
osx_image: xcode10.1
|
||||||
|
compiler: clang
|
||||||
|
before_cache:
|
||||||
|
- brew cleanup
|
||||||
|
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/Library/Caches/Homebrew
|
||||||
|
- /usr/local/Homebrew
|
||||||
|
before_install:
|
||||||
|
- cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f
|
||||||
|
script: brew update && brew install --HEAD keystone
|
||||||
|
|
||||||
|
- if: branch = master
|
||||||
|
os: osx
|
||||||
|
osx_image: xcode10.1
|
||||||
|
compiler: gcc
|
||||||
|
before_cache:
|
||||||
|
- brew cleanup
|
||||||
|
- find /usr/local/Homebrew \! -regex ".+\.git.+" -delete;
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/Library/Caches/Homebrew
|
||||||
|
- /usr/local/Homebrew
|
||||||
|
before_install:
|
||||||
|
- cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core && git stash && git clean -d -f
|
||||||
|
script: brew update && brew install --HEAD keystone
|
||||||
|
|
||||||
|
- name: "Windows nmake 32bit"
|
||||||
|
os: windows
|
||||||
|
language: shell
|
||||||
|
script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmd.exe //C 'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat' x86 '&' cmd.exe //C '..\nmake-dll.bat' X86 '&' cmd.exe //c '..\nmake-lib.bat' X86
|
||||||
|
|
||||||
|
- name: "Windows nmake 64bit"
|
||||||
|
os: windows
|
||||||
|
language: shell
|
||||||
|
script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmd.exe //C 'C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat' amd64 '&' cmd.exe //C '..\nmake-dll.bat' '&' cmd.exe //c '..\nmake-lib.bat'
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
Nguyen Anh Quynh <aquynh -at- gmail.com>
|
@ -0,0 +1,123 @@
|
|||||||
|
# Keystone Assembler Engine (www.keystone-engine.org)
|
||||||
|
# By Nguyen Anh Quynh, 2016
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 2.8.7)
|
||||||
|
project(keystone)
|
||||||
|
|
||||||
|
set(KEYSTONE_VERSION_MAJOR 0)
|
||||||
|
set(KEYSTONE_VERSION_MINOR 9)
|
||||||
|
|
||||||
|
option(KEYSTONE_BUILD_STATIC_RUNTIME "Embed static runtime" ON)
|
||||||
|
option(BUILD_LIBS_ONLY "Only build keystone library" 0)
|
||||||
|
|
||||||
|
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||||
|
message(STATUS "No build type selected, default to Debug")
|
||||||
|
set(CMAKE_BUILD_TYPE "Debug")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (POLICY CMP0022)
|
||||||
|
cmake_policy(SET CMP0022 NEW) # automatic when 2.8.12 is required
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (POLICY CMP0051)
|
||||||
|
# CMake 3.1 and higher include generator expressions of the form
|
||||||
|
# $<TARGETLIB:obj> in the SOURCES property. These need to be
|
||||||
|
# stripped everywhere that access the SOURCES property, so we just
|
||||||
|
# defer to the OLD behavior of not including generator expressions
|
||||||
|
# in the output for now.
|
||||||
|
cmake_policy(SET CMP0051 OLD)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (POLICY CMP0063)
|
||||||
|
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # automatic when 3.3.2 is required
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_VERSION VERSION_LESS 3.1.20141117)
|
||||||
|
set(cmake_3_2_USES_TERMINAL)
|
||||||
|
else()
|
||||||
|
set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /EHsc")
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /EHsc")
|
||||||
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /EHsc")
|
||||||
|
else()
|
||||||
|
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||||
|
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||||
|
|
||||||
|
# Use GNUInstallDirs to set LLVM_LIBDIR_SUFFIX. This should automatically
|
||||||
|
# handle cases where the libdir should be lib/, lib64/, or lib/<arch>/
|
||||||
|
# depending on the target system and cmake options.
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
string(REGEX REPLACE "lib(.*)$" "\\1" LLVM_LIBDIR_SUFFIX "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
set(LLVM_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING "Define suffix of library directory name (32/64)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Force static runtime libraries
|
||||||
|
if (KEYSTONE_BUILD_STATIC_RUNTIME)
|
||||||
|
FOREACH(flag
|
||||||
|
CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_DEBUG_INIT
|
||||||
|
CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG_INIT)
|
||||||
|
if (MSVC)
|
||||||
|
STRING(REPLACE "/MD" "/MT" "${flag}" "${${flag}}")
|
||||||
|
SET("${flag}" "${${flag}} /EHsc")
|
||||||
|
endif (MSVC)
|
||||||
|
ENDFOREACH()
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
add_subdirectory(llvm)
|
||||||
|
|
||||||
|
# for Windows, do not build kstool if buiding DLL
|
||||||
|
# TODO: fix this
|
||||||
|
if (${CMAKE_CXX_COMPILER_ID} STREQUAL MSVC)
|
||||||
|
if (NOT BUILD_LIBS_ONLY AND NOT BUILD_SHARED_LIBS)
|
||||||
|
add_subdirectory(kstool)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (NOT BUILD_LIBS_ONLY)
|
||||||
|
add_subdirectory(kstool)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# generate and install pkg-config.pc
|
||||||
|
FIND_PACKAGE(PkgConfig)
|
||||||
|
SET(PKG_CONFIG_FILE_PATH
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||||
|
)
|
||||||
|
SET(PKG_CONFIG_LIBDIR
|
||||||
|
"${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}"
|
||||||
|
)
|
||||||
|
SET(PKG_CONFIG_INCLUDEDIR
|
||||||
|
"${CMAKE_INSTALL_PREFIX}/include"
|
||||||
|
)
|
||||||
|
SET(PKG_CONFIG_LIBS
|
||||||
|
"-L\${libdir} -lkeystone"
|
||||||
|
)
|
||||||
|
SET(PKG_CONFIG_CFLAGS
|
||||||
|
"-I\${includedir}"
|
||||||
|
)
|
||||||
|
CONFIGURE_FILE(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/pkg-config.pc.cmake"
|
||||||
|
"${PKG_CONFIG_FILE_PATH}"
|
||||||
|
)
|
||||||
|
INSTALL(FILES "${PKG_CONFIG_FILE_PATH}"
|
||||||
|
DESTINATION lib${LLVM_LIBDIR_SUFFIX}/pkgconfig)
|
||||||
|
|
||||||
|
# uninstall target
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/CMakeUninstall.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
if(NOT BUILD_LIBS_ONLY)
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/CMakeUninstall.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT BUILD_LIBS_ONLY)
|
||||||
|
add_subdirectory(suite/fuzz)
|
||||||
|
endif()
|
@ -0,0 +1,21 @@
|
|||||||
|
if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
|
||||||
|
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
foreach(file ${files})
|
||||||
|
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||||
|
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
exec_program(
|
||||||
|
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RETURN_VALUE rm_retval
|
||||||
|
)
|
||||||
|
if(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||||
|
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||||
|
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
endforeach(file)
|
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
@ -0,0 +1,54 @@
|
|||||||
|
This file credits all the contributors of Keystone Engine (keystone-engine.org).
|
||||||
|
|
||||||
|
|
||||||
|
Beta testers (in no particular order)
|
||||||
|
=====================================
|
||||||
|
Mike Guidry
|
||||||
|
Eloi Vanderbeken
|
||||||
|
Tim "diff" Strazzere
|
||||||
|
Matt Graeber
|
||||||
|
Edgar Barbosa
|
||||||
|
Loi Anh Tuan
|
||||||
|
Sascha Schirra
|
||||||
|
hugsy
|
||||||
|
Alexander Tereshkin
|
||||||
|
Sébastien Duquette
|
||||||
|
Sergi Alvarez, aka pancake (author of radare)
|
||||||
|
Richo Healey
|
||||||
|
Remco Verhoef (honeytrap.io)
|
||||||
|
Duncan Ogilvie
|
||||||
|
Bruce Dang
|
||||||
|
Dan Caselden
|
||||||
|
Jaime Peñalba
|
||||||
|
Daniel Collin
|
||||||
|
Vitaly Osipov
|
||||||
|
Dang Hoang Vu
|
||||||
|
Paul Rascagneres
|
||||||
|
postmodern
|
||||||
|
Fotis Loukos
|
||||||
|
Peter Geissler
|
||||||
|
Ingmar Steen (CED)
|
||||||
|
Matteo Favaro
|
||||||
|
Julien Legras
|
||||||
|
Anton Kochkov
|
||||||
|
Francisco Alonso
|
||||||
|
rdmz
|
||||||
|
practicalswift
|
||||||
|
Jurriaan Bremer
|
||||||
|
|
||||||
|
|
||||||
|
Contributors (in no particular order)
|
||||||
|
=====================================
|
||||||
|
Ingmar Steen: NodeJS binding.
|
||||||
|
Sascha Schirra: Ruby binding.
|
||||||
|
Remco Verhoef: Go & Rust bindings.
|
||||||
|
Adrian Herrera: Haskell binding.
|
||||||
|
practicalswift: Various cool bugs found by fuzzing.
|
||||||
|
Aziem Chawdhary: OCaml binding.
|
||||||
|
Ruben Boonen: PowerShell binding.
|
||||||
|
Marco Fornaro: C# binding.
|
||||||
|
David Zimmer: VB6 binding.
|
||||||
|
Michael Mohr: Debian packaging.
|
||||||
|
Jämes Ménétrey (ZenLulz): Java binding.
|
||||||
|
Philippe Antoine (Catena cyber): fuzzing.
|
||||||
|
Kevin Foo (chfl4gs): PyPI packaging, Travis-CI, fixes for Python binding.
|
@ -0,0 +1,96 @@
|
|||||||
|
This file details the changelog of Keystone.
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
Version 0.9.2: June 21st, 2020
|
||||||
|
|
||||||
|
- Fix for Python binding (Pypi package)
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Version 0.9.2-rc1: June 13th, 2020
|
||||||
|
|
||||||
|
[ Core & tool ]
|
||||||
|
|
||||||
|
- Default radix set to 16
|
||||||
|
- kstool accepts -b option to print out encoding binary to output
|
||||||
|
- Do not build Universal binaries for Mac
|
||||||
|
- Better installer for Linux
|
||||||
|
- Add Ethereum VM architecture
|
||||||
|
- Better support for older compiler
|
||||||
|
- Add Masm binding
|
||||||
|
- Rename namespace llvm to llvm_ks
|
||||||
|
- Better cross compile with Android NDK
|
||||||
|
- Add KS_VERSION_{MAJOR, MINOR, EXTRA}
|
||||||
|
- Add new option KS_OPT_SYM_RESOLVER
|
||||||
|
- Fix memory leaks in ks_asm()
|
||||||
|
|
||||||
|
[ X86 ]
|
||||||
|
|
||||||
|
- Fix X86 prefix ordering
|
||||||
|
|
||||||
|
[ Arm ]
|
||||||
|
|
||||||
|
- Fix Thumb backward branch
|
||||||
|
- Fix Thumb2 ADR, B.W
|
||||||
|
- Fix BL, BLX in Thumb mode
|
||||||
|
|
||||||
|
[ Arm64 ]
|
||||||
|
|
||||||
|
- Fix ADRP
|
||||||
|
- Fix PC-relative offset for branch instructions
|
||||||
|
|
||||||
|
[ Mips ]
|
||||||
|
|
||||||
|
- Fix JAL IMM
|
||||||
|
|
||||||
|
[ PowerPC ]
|
||||||
|
|
||||||
|
- Remove bound check on branch instructions
|
||||||
|
|
||||||
|
[ Python binding ]
|
||||||
|
|
||||||
|
- Fix module loading issue
|
||||||
|
- Load library versioning
|
||||||
|
- Add as_bytes=True param to asm()
|
||||||
|
|
||||||
|
[ Bindings ]
|
||||||
|
|
||||||
|
- Multiple fixes for Python, Go, Rust, .NET
|
||||||
|
- Add Java, VB6, C#, Powershell, Perl bindings
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
Version 0.9.1: July 27th, 2016
|
||||||
|
|
||||||
|
[ Core & tool ]
|
||||||
|
|
||||||
|
- Fix a segfault in kstool (on missing assembly input).
|
||||||
|
- kstool now allows to specify instruction address.
|
||||||
|
- Build Mac libraries in universal format by default.
|
||||||
|
- Add "lib32" option to cross-compile to 32-bit *nix (on 64-bit system).
|
||||||
|
- Add "lib_only" option to only build libraries (skip kstool).
|
||||||
|
- New bindings: Haskell & OCaml.
|
||||||
|
|
||||||
|
[ X86 ]
|
||||||
|
|
||||||
|
- Fix instructions: LJMP, LCALL, CDQE, SHR, SHL, SAR, SAL, LOOP, LOOPE, LOOPNE
|
||||||
|
- Better handling a lot of tricky input caught by assert() before.
|
||||||
|
- Better support for Nasm syntax.
|
||||||
|
|
||||||
|
[ Arm ]
|
||||||
|
|
||||||
|
- Fix BLX instruction.
|
||||||
|
|
||||||
|
[ Python binding ]
|
||||||
|
|
||||||
|
- Better Python3 support.
|
||||||
|
- Expose @stat_count in KsError class when ks_asm() returns with error.
|
||||||
|
See sample code in bindings/python/sample_asm_count.py
|
||||||
|
|
||||||
|
[ Go binding ]
|
||||||
|
|
||||||
|
- Fix Go binding for 32-bit
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
Version 0.9: May 31th, 2016
|
||||||
|
|
||||||
|
- Initial public release.
|
||||||
|
|
@ -0,0 +1,132 @@
|
|||||||
|
FOSS License Exception
|
||||||
|
|
||||||
|
What is the FOSS License Exception?
|
||||||
|
|
||||||
|
This is based on the Oracle's Free and Open Source Software ("FOSS")
|
||||||
|
License Exception.
|
||||||
|
|
||||||
|
The Free and Open Source Software ("FOSS") License Exception allows
|
||||||
|
developers of FOSS applications to include Keystone Libraries with their
|
||||||
|
FOSS applications. This exception permits distribution of Keystone libraries
|
||||||
|
with a developer's FOSS applications licensed under the terms of another
|
||||||
|
FOSS license listed below, even though such other FOSS license may be
|
||||||
|
incompatible with the GPL.
|
||||||
|
|
||||||
|
The following terms and conditions describe the circumstances under which
|
||||||
|
Oracle's FOSS License Exception applies.
|
||||||
|
|
||||||
|
FOSS License Exception Terms and Conditions
|
||||||
|
|
||||||
|
1. Definitions. "Derivative Work" means a derivative work, as defined
|
||||||
|
under applicable copyright law, formed entirely from the Program and
|
||||||
|
one or more FOSS Applications.
|
||||||
|
|
||||||
|
"FOSS Application" means a free and open source software application
|
||||||
|
distributed subject to a license listed in the section below titled
|
||||||
|
"FOSS License List."
|
||||||
|
|
||||||
|
"FOSS Notice" means a notice put in a copy of Keystone Libraries
|
||||||
|
stating that such copy of Keystone Libraries may be distributed under
|
||||||
|
FOSS License Exception.
|
||||||
|
|
||||||
|
"Independent Work" means portions of the Derivative Work that are not
|
||||||
|
derived from the Program and can reasonably be considered independent
|
||||||
|
and separate works.
|
||||||
|
|
||||||
|
"Program" means a copy of Keystone Libraries that contains
|
||||||
|
a FOSS Notice.
|
||||||
|
|
||||||
|
2. A FOSS application developer ("you" or "your") may distribute a
|
||||||
|
Derivative Work provided that you and the Derivative Work meet all of
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
a. You obey the GPL in all respects for the Program and all portions
|
||||||
|
(including modifications) of the Program included in the
|
||||||
|
Derivative Work (provided that this condition does not apply to
|
||||||
|
Independent Works);
|
||||||
|
b. The Derivative Work does not include any work licensed under the
|
||||||
|
GPL other than the Program;
|
||||||
|
c. You distribute Independent Works subject to a license listed in
|
||||||
|
the section below titled "FOSS License List";
|
||||||
|
d. You distribute Independent Works in object code or executable
|
||||||
|
form with the complete corresponding machine-readable source code
|
||||||
|
on the same medium and under the same FOSS license applying to
|
||||||
|
the object code or executable forms;
|
||||||
|
e. All works that are aggregated with the Program or the Derivative
|
||||||
|
Work on a medium or volume of storage are not derivative works of
|
||||||
|
the Program, Derivative Work or FOSS Application, and must
|
||||||
|
reasonably be considered independent and separate works.
|
||||||
|
|
||||||
|
3. Keystone's authors reserves all rights not expressly granted in these
|
||||||
|
terms and conditions. If all of the above conditions are not met, then
|
||||||
|
this FOSS License Exception does not apply to you/your Derivative Work.
|
||||||
|
|
||||||
|
FOSS License List
|
||||||
|
|
||||||
|
+------------------------------------------------------------------------+
|
||||||
|
|License Name |Version(s)/Copyright Date|
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Academic Free License |2.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Apache Software License |1.0/1.1/2.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Apple Public Source License |2.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Artistic license |From Perl 5.8.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|BSD license |"July 22 1999" |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Common Development and Distribution License |1.0 |
|
||||||
|
|(CDDL) | |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Common Public License |1.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Eclipse Public License |1.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|European Union Public License (EUPL)¹ |1.1 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|GNU Affero General Public License (AGPL) |3.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|GNU Library or "Lesser" General Public License|2.0/2.1/3.0 |
|
||||||
|
|(LGPL) | |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|GNU General Public License (GPL) |3.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|IBM Public License |1.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Jabber Open Source License |1.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|MIT License (As listed in file |- |
|
||||||
|
|MIT-License.txt) | |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Mozilla Public License (MPL) |1.0/1.1 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Open Software License |2.0 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|OpenSSL license (with original SSLeay license)|"2003" ("1998") |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|PHP License |3.0/3.01 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Python license (CNRI Python License) |- |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Python Software Foundation License |2.1.1 |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Sleepycat License |"1999" |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|University of Illinois/NCSA Open Source |- |
|
||||||
|
|License | |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|W3C License |"2001" |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|X11 License |"2001" |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Zlib/libpng License |- |
|
||||||
|
|----------------------------------------------+-------------------------|
|
||||||
|
|Zope Public License |2.0 |
|
||||||
|
+------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
¹) When an Independent Work is licensed under a "Compatible License"
|
||||||
|
pursuant to the EUPL, the Compatible License rather than the EUPL is the
|
||||||
|
applicable license for purposes of these FOSS License Exception Terms and
|
||||||
|
Conditions.
|
||||||
|
|
@ -0,0 +1,8 @@
|
|||||||
|
The commercial license of Keystone allows you to use Keystone libraries & tools
|
||||||
|
in commercial products.
|
||||||
|
|
||||||
|
- The Keystone commercial license is perpetual and royalty-free.
|
||||||
|
- You have the right to distribute the binary and modifications of Keystone.
|
||||||
|
- No source code redistribution is allowed in any way.
|
||||||
|
|
||||||
|
Contact keystone.engine@gmail.com for further information.
|
@ -0,0 +1,63 @@
|
|||||||
|
Keystone Engine
|
||||||
|
==============
|
||||||
|
|
||||||
|
[![Build Status](https://travis-ci.org/keystone-engine/keystone.svg?branch=master)](https://travis-ci.org/keystone-engine/keystone)
|
||||||
|
[![Build Status](https://semaphoreci.com/api/v1/aquynh/keystone/branches/master/badge.svg)](https://semaphoreci.com/aquynh/keystone)
|
||||||
|
[![Build status](https://ci.appveyor.com/api/projects/status/c27slvyrijiejvqs?svg=true)](https://ci.appveyor.com/project/aquynh/keystone)
|
||||||
|
|
||||||
|
Keystone is a lightweight multi-platform, multi-architecture assembler framework.
|
||||||
|
It offers some unparalleled features:
|
||||||
|
|
||||||
|
- Multi-architecture, with support for Arm, Arm64 (AArch64/Armv8), Ethereum Virtual Machine, Hexagon, Mips, PowerPC, Sparc, SystemZ & X86 (include 16/32/64bit).
|
||||||
|
- Clean/simple/lightweight/intuitive architecture-neutral API.
|
||||||
|
- Implemented in C/C++ languages, with bindings for Java, Masm, C#, PowerShell, Perl, Python, NodeJS, Ruby, Go, Rust, Haskell, VB6 & OCaml available.
|
||||||
|
- Native support for Windows & \*nix (with Mac OSX, Linux, \*BSD & Solaris confirmed).
|
||||||
|
- Thread-safe by design.
|
||||||
|
- Open source - with a dual license.
|
||||||
|
|
||||||
|
Keystone is based on LLVM, but it goes much further with [a lot more to offer](/docs/beyond_llvm.md).
|
||||||
|
|
||||||
|
Further information is available at http://www.keystone-engine.org
|
||||||
|
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
Keystone is available under a dual license:
|
||||||
|
|
||||||
|
- Version 2 of the GNU General Public License (GPLv2). (I.e. Without the "any later version" clause.).
|
||||||
|
License information can be found in the [COPYING file](COPYING) and the [EXCEPTIONS-CLIENT file](EXCEPTIONS-CLIENT).
|
||||||
|
|
||||||
|
This combination allows almost all of open source projects to use Keystone without conflicts.
|
||||||
|
|
||||||
|
- For commercial usage in production environments, contact the authors of Keystone to buy a royalty-free license.
|
||||||
|
|
||||||
|
See [LICENSE-COM.TXT](LICENSE-COM.TXT) for more information.
|
||||||
|
|
||||||
|
|
||||||
|
Compilation & Docs
|
||||||
|
------------------
|
||||||
|
|
||||||
|
See [COMPILE.md](docs/COMPILE.md) file for how to compile and install Keystone.
|
||||||
|
|
||||||
|
More documentation is available in [docs/README.md](docs/README.md).
|
||||||
|
|
||||||
|
|
||||||
|
Contact
|
||||||
|
-------
|
||||||
|
|
||||||
|
[Contact us](http://www.keystone-engine.org/contact/) via mailing list, email or twitter for any questions.
|
||||||
|
|
||||||
|
|
||||||
|
Contribute
|
||||||
|
----------
|
||||||
|
|
||||||
|
Keystone is impossible without generous support from [our sponsors](/SPONSORS.TXT). We cannot thank them enough!
|
||||||
|
|
||||||
|
[CREDITS.TXT](CREDITS.TXT) records other important contributors of our project.
|
||||||
|
|
||||||
|
If you want to contribute, please pick up something from our [Github issues](https://github.com/keystone-engine/keystone/issues).
|
||||||
|
|
||||||
|
We also maintain a list of more challenged problems in a [TODO list](https://github.com/keystone-engine/keystone/wiki/TODO).
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
|||||||
|
Version 0.9.2 works quite well for all architectures, but is known to not be able
|
||||||
|
to deal with some malformed craft input. In such a case, Keystone usually exits
|
||||||
|
with some error messages. Report if you experience this issue, so we can fix
|
||||||
|
that in the next release.
|
||||||
|
|
||||||
|
See details of open bugs at https://github.com/keystone-engine/keystone/issues
|
@ -0,0 +1,8 @@
|
|||||||
|
This file lists all the sponsors of Keystone Engine.
|
||||||
|
Thanks a lot for your great support!
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Mike Guidry
|
||||||
|
Synacktiv Digital Security (www.synacktiv.com)
|
||||||
|
Tim "diff" Strazzere
|
||||||
|
Veris Group (www.verisgroup.com)
|
@ -0,0 +1,87 @@
|
|||||||
|
# Keystone Engine
|
||||||
|
# By Nguyen Anh Quynh & Dang Hoang Vu, 2015
|
||||||
|
TMPDIR = /tmp/keystone_sample
|
||||||
|
|
||||||
|
DIFF = diff -u -w
|
||||||
|
|
||||||
|
SAMPLE_ARM = $(TMPDIR)/sample_arm
|
||||||
|
SAMPLE_ARM64 = $(TMPDIR)/sample_arm64
|
||||||
|
SAMPLE_MIPS = $(TMPDIR)/sample_mips
|
||||||
|
SAMPLE_M68K = $(TMPDIR)/sample_m68k
|
||||||
|
SAMPLE_SPARC = $(TMPDIR)/sample_sparc
|
||||||
|
SAMPLE_X86 = $(TMPDIR)/sample_x86
|
||||||
|
|
||||||
|
.PHONY: all expected python rust go nodejs ruby
|
||||||
|
|
||||||
|
all:
|
||||||
|
cd python && $(MAKE) gen_const
|
||||||
|
cd nodejs && $(MAKE) gen_const
|
||||||
|
python const_generator.py rust
|
||||||
|
python const_generator.py go
|
||||||
|
cd ruby && $(MAKE) gen_const
|
||||||
|
python const_generator.py powershell
|
||||||
|
|
||||||
|
samples: expected python
|
||||||
|
|
||||||
|
sample_python: expected python
|
||||||
|
|
||||||
|
expected:
|
||||||
|
cd ../samples && $(MAKE)
|
||||||
|
mkdir -p $(TMPDIR)
|
||||||
|
../samples/sample_arm > $(SAMPLE_ARM)_e
|
||||||
|
../samples/sample_arm64 > $(SAMPLE_ARM64)_e
|
||||||
|
../samples/sample_mips > $(SAMPLE_MIPS)_e
|
||||||
|
../samples/sample_sparc > $(SAMPLE_SPARC)_e
|
||||||
|
../samples/sample_m68k > $(SAMPLE_M68K)_e
|
||||||
|
../samples/sample_x86 > $(SAMPLE_X86)_e
|
||||||
|
|
||||||
|
python: FORCE
|
||||||
|
cd python && $(MAKE)
|
||||||
|
python python/sample_arm.py > $(SAMPLE_ARM)_o
|
||||||
|
python python/sample_arm64.py > $(SAMPLE_ARM64)_o
|
||||||
|
python python/sample_mips.py > $(SAMPLE_MIPS)_o
|
||||||
|
python python/sample_sparc.py > $(SAMPLE_SPARC)_o
|
||||||
|
python python/sample_m68k.py > $(SAMPLE_M68K)_o
|
||||||
|
python python/sample_x86.py > $(SAMPLE_X86)_o
|
||||||
|
$(MAKE) sample_diff
|
||||||
|
|
||||||
|
ruby: FORCE
|
||||||
|
cd ruby && $(MAKE)
|
||||||
|
|
||||||
|
nodejs: FORCE
|
||||||
|
cd nodejs && $(MAKE)
|
||||||
|
|
||||||
|
rust: FORCE
|
||||||
|
cd rust && $(MAKE)
|
||||||
|
|
||||||
|
go: FORCE
|
||||||
|
cd go && $(MAKE)
|
||||||
|
|
||||||
|
ocaml: FORCE
|
||||||
|
cd ocaml && $(MAKE)
|
||||||
|
|
||||||
|
sample_diff: FORCE
|
||||||
|
$(DIFF) $(SAMPLE_ARM)_e $(SAMPLE_ARM)_o
|
||||||
|
$(DIFF) $(SAMPLE_ARM64)_e $(SAMPLE_ARM64)_o
|
||||||
|
$(DIFF) $(SAMPLE_MIPS)_e $(SAMPLE_MIPS)_o
|
||||||
|
$(DIFF) $(SAMPLE_SPARC)_e $(SAMPLE_SPARC)_o
|
||||||
|
$(DIFF) $(SAMPLE_M68K)_e $(SAMPLE_M68K)_o
|
||||||
|
$(DIFF) $(SAMPLE_X86)_e $(SAMPLE_X86)_o
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(TMPDIR)
|
||||||
|
cd python && $(MAKE) clean
|
||||||
|
cd rust && $(MAKE) clean
|
||||||
|
cd go && $(MAKE) clean
|
||||||
|
cd nodejs && $(MAKE) clean
|
||||||
|
cd ruby && $(MAKE) clean
|
||||||
|
cd ocaml && $(MAKE) clean
|
||||||
|
|
||||||
|
check:
|
||||||
|
cd python && $(MAKE) check
|
||||||
|
cd rust && $(MAKE) check
|
||||||
|
cd go && $(MAKE) check
|
||||||
|
cd nodejs && $(MAKE) check
|
||||||
|
cd ruby && $(MAKE) check
|
||||||
|
|
||||||
|
FORCE:
|
@ -0,0 +1,23 @@
|
|||||||
|
This directory contains bindings for Keystone.
|
||||||
|
See <language>/README* for how to install each binding.
|
||||||
|
|
||||||
|
Except Python, all other bindings are contributed by community.
|
||||||
|
|
||||||
|
- NodeJS binding: by Ingmar Steen
|
||||||
|
- Ruby binding: by Sascha Schirra
|
||||||
|
- Go binding: by Remco Verhoef
|
||||||
|
- Rust binding: by Remco Verhoef
|
||||||
|
- Haskell binding: by Adrian Herrera
|
||||||
|
- OCaml binding: by Aziem Chawdhary
|
||||||
|
- PowerShell binding: by Ruben Boonen
|
||||||
|
- C# binding: by Marco Fornaro
|
||||||
|
- VB6 binding: by David Zimmer
|
||||||
|
- Masm binding: by mrfearless
|
||||||
|
- Java binding: by Jämes Ménétrey (ZenLulz)
|
||||||
|
|
||||||
|
Other bindings maintained externally by community:
|
||||||
|
|
||||||
|
- Perl-Keystone: Perl binding made by @t00sh.
|
||||||
|
https://github.com/t00sh/perl-keystone
|
||||||
|
- keystone-rs: Rust binding by @tathanhdinh
|
||||||
|
https://github.com/tathanhdinh/keystone-rs
|
@ -0,0 +1,430 @@
|
|||||||
|
# Keystone Engine
|
||||||
|
# Adapted from the code of Dang Hoang Vu for Capstone Engine, 2013
|
||||||
|
from __future__ import print_function
|
||||||
|
import sys, re, os
|
||||||
|
|
||||||
|
INCL_DIR = os.path.join('..', 'include', 'keystone')
|
||||||
|
|
||||||
|
# NOTE: this reflects the value of KS_ERR_ASM_xxx in keystone.h
|
||||||
|
ks_err_val = { 'KS_ERR_ASM': '128', 'KS_ERR_ASM_ARCH': '512' }
|
||||||
|
|
||||||
|
include = [ 'arm.h', 'arm64.h', 'mips.h', 'x86.h', 'sparc.h', 'ppc.h', 'systemz.h', 'hexagon.h', 'evm.h', 'keystone.h' ]
|
||||||
|
|
||||||
|
def CamelCase(s):
|
||||||
|
# return re.sub(r'(\w)+\_?', lambda m:m.group(0).capitalize(), s)
|
||||||
|
return ''.join(''.join([w[0].upper(), w[1:].lower()]) for w in s.split('_'))
|
||||||
|
|
||||||
|
template = {
|
||||||
|
'powershell': {
|
||||||
|
'header': "/// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_h.cs]\n",
|
||||||
|
'footer': "",
|
||||||
|
'out_file': './powershell/Keystone/Const/%s_h.cs',
|
||||||
|
# prefixes for constant filenames of all archs - case sensitive
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '///',
|
||||||
|
'comment_close': '',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'.*',
|
||||||
|
'line_format': 'KS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'rust': {
|
||||||
|
'header': "#![allow(non_camel_case_types)]\n// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.rs]\nuse ::libc::*;\n",
|
||||||
|
'footer': "",
|
||||||
|
# prefixes for constant filenames of all archs - case sensitive
|
||||||
|
'arm.h': 'keystone',
|
||||||
|
'arm64.h': 'keystone',
|
||||||
|
'mips.h': 'keystone',
|
||||||
|
'x86.h': 'keystone',
|
||||||
|
'sparc.h': 'keystone',
|
||||||
|
'systemz.h': 'keystone',
|
||||||
|
'ppc.h': 'keystone',
|
||||||
|
'hexagon.h': 'keystone',
|
||||||
|
'evm.h': 'keystone',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '/*',
|
||||||
|
'comment_close': '*/',
|
||||||
|
'out_file': './rust/keystone-sys/src/%s_const.rs',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'(API)_.*',
|
||||||
|
'pre': '\n',
|
||||||
|
'line_format': 'pub const {0}: c_uint = {1};\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
{ 'regex': r'MODE_.*',
|
||||||
|
'pre': '\n' +
|
||||||
|
'bitflags! {{\n' +
|
||||||
|
'#[repr(C)]\n' +
|
||||||
|
' pub struct Mode: c_int {{\n',
|
||||||
|
'line_format': ' const {0} = {1};\n',
|
||||||
|
'fn': (lambda x: '_'.join(x.split('_')[1:]) if not re.match(r'MODE_\d+', x) else x),
|
||||||
|
'post': ' }\n}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'ARCH_.*',
|
||||||
|
'pre': '\n' +
|
||||||
|
'#[repr(C)]\n' +
|
||||||
|
'#[derive(Debug, PartialEq, Clone, Copy)]\n' +
|
||||||
|
'pub enum Arch {{\n',
|
||||||
|
'line_format': ' {0} = {1},\n',
|
||||||
|
'fn': (lambda x: '_'.join(x.split('_')[1:])),
|
||||||
|
'post': '}\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'(OPT_([A-Z]+)|OPT_SYM_RESOLVER)$',
|
||||||
|
'pre': '#[repr(C)]\n' +
|
||||||
|
'#[derive(Debug, PartialEq, Clone, Copy)]\n' +
|
||||||
|
'pub enum OptionType {{\n',
|
||||||
|
'line_format': ' {0} = {1},\n',
|
||||||
|
'fn': (lambda x: '_'.join(x.split('_')[1:])),
|
||||||
|
'post': '}\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'OPT_(?!SYM)([A-Z]+\_)+[A-Z]+',
|
||||||
|
'pre': 'bitflags! {{\n'
|
||||||
|
'#[repr(C)]\n' +
|
||||||
|
' pub struct OptionValue: size_t {{\n',
|
||||||
|
'line_format': ' const {0} = {1};\n',
|
||||||
|
'fn': (lambda x: '_'.join(x.split('_')[1:])),
|
||||||
|
'post': ' }\n}\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'ERR_(.*)',
|
||||||
|
'pre': 'bitflags! {{\n' +
|
||||||
|
'#[repr(C)]\n' +
|
||||||
|
' pub struct Error: c_int {{\n',
|
||||||
|
'line_format': ' const {0} = {1};\n',
|
||||||
|
'fn': (lambda x: '_'.join(x.split('_')[1:])),
|
||||||
|
'post': ' }\n}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'go': {
|
||||||
|
'header': "package keystone\n// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.go]\n\n",
|
||||||
|
'footer': "",
|
||||||
|
# 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',
|
||||||
|
'evm.h': 'evm',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '/*',
|
||||||
|
'comment_close': '*/',
|
||||||
|
'out_file': './go/keystone/%s_const.go',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'API_.*',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
{ 'regex': r'MODE_.*',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} Mode = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'ARCH_.*',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} Architecture = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'OPT_([A-Z]+)$',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} OptionType = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'OPT_([A-Z]+\_)+[A-Z]+',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} OptionValue = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'ERR_.*',
|
||||||
|
'pre': 'const (\n',
|
||||||
|
'line_format': '\t{0} Error = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
'post': ')\n',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'python': {
|
||||||
|
'header': "# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.py]\n",
|
||||||
|
'footer': "",
|
||||||
|
'out_file': './python/keystone/%s_const.py',
|
||||||
|
# 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',
|
||||||
|
'evm.h': 'evm',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '#',
|
||||||
|
'comment_close': '',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'.*',
|
||||||
|
'line_format': 'KS_{0} = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'nodejs': {
|
||||||
|
'header': "// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.js]\n",
|
||||||
|
'footer': "",
|
||||||
|
'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',
|
||||||
|
'evm.h': 'evm',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '//',
|
||||||
|
'comment_close': '',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'.*',
|
||||||
|
'line_format': 'module.exports.{0} = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'ruby': {
|
||||||
|
'header': "# For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%s_const.rb]\n\nmodule Keystone\n",
|
||||||
|
'footer': "end",
|
||||||
|
'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',
|
||||||
|
'evm.h': 'evm',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '#',
|
||||||
|
'comment_close': '',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'.*',
|
||||||
|
'line_format': '\tKS_{0} = {1}\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'csharp': {
|
||||||
|
'header': "// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [%sConstants.cs]\nnamespace KeystoneNET\n{",
|
||||||
|
'footer': "}",
|
||||||
|
'out_file': './csharp/KeystoneNET/KeystoneNET/Constants/%sConstants.cs',
|
||||||
|
# prefixes for constant filenames of all archs - case sensitive
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'arm.h': 'arm',
|
||||||
|
'arm64.h': 'arm64',
|
||||||
|
'mips.h': 'mips',
|
||||||
|
'x86.h': 'x86',
|
||||||
|
'sparc.h': 'sparc',
|
||||||
|
'systemz.h': 'systemz',
|
||||||
|
'ppc.h': 'ppc',
|
||||||
|
'hexagon.h': 'hexagon',
|
||||||
|
'evm.h': 'evm',
|
||||||
|
'keystone.h': 'keystone',
|
||||||
|
'comment_open': '//',
|
||||||
|
'comment_close': '',
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'regex': r'(ARCH)_.*',
|
||||||
|
'pre': '\n\tpublic enum KeystoneArchitecture : int\n\t{{\n',
|
||||||
|
'post': '\t}',
|
||||||
|
'line_format': '\t\tKS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'(MODE)_.*',
|
||||||
|
'pre': '\n\tpublic enum KeystoneMode : uint\n\t{{\n',
|
||||||
|
'post': '\t}',
|
||||||
|
'line_format': '\t\tKS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'(ERR)_.*',
|
||||||
|
'pre': '\n\tpublic enum {0}Error : short\n\t{{\n',
|
||||||
|
'post': '\t}',
|
||||||
|
'line_format': '\t\tKS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'((OPT_([A-Z]+))|(OPT_SYM_RESOLVER))$',
|
||||||
|
'pre': '\n\tpublic enum KeystoneOptionType : short\n\t{{\n',
|
||||||
|
'post': '\t}',
|
||||||
|
'line_format': '\t\tKS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'regex': r'OPT_(?!SYM)([A-Z]+\_)+[A-Z]+',
|
||||||
|
'pre': '\n\tpublic enum KeystoneOptionValue : short\n\t{{\n',
|
||||||
|
'post': '\t}',
|
||||||
|
'line_format': '\t\tKS_{0} = {1},\n',
|
||||||
|
'fn': (lambda x: x),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# markup for comments to be added to autogen files
|
||||||
|
MARKUP = '//>'
|
||||||
|
|
||||||
|
def gen(lang):
|
||||||
|
global include, INCL_DIR
|
||||||
|
|
||||||
|
consts = {}
|
||||||
|
|
||||||
|
templ = template[lang]
|
||||||
|
for target in include:
|
||||||
|
if target not in templ:
|
||||||
|
continue
|
||||||
|
prefix = templ[target]
|
||||||
|
if target == 'keystone.h':
|
||||||
|
prefix = 'keystone'
|
||||||
|
lines = open(os.path.join(INCL_DIR, target)).readlines()
|
||||||
|
|
||||||
|
consts[prefix] = []
|
||||||
|
|
||||||
|
previous = {}
|
||||||
|
count = 0
|
||||||
|
for line in lines:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if line.startswith(MARKUP): # markup for comments
|
||||||
|
outfile.write(("\n%s%s%s\n" %(templ['comment_open'], \
|
||||||
|
line.replace(MARKUP, ''), templ['comment_close'])).encode("utf-8"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line == '' or line.startswith('//'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
tmp = line.strip().split(',')
|
||||||
|
for t in tmp:
|
||||||
|
t = t.strip()
|
||||||
|
if not t or t.startswith('//'): continue
|
||||||
|
f = re.split('\s+', t)
|
||||||
|
|
||||||
|
# parse #define KS_TARGET (num)
|
||||||
|
define = False
|
||||||
|
if f[0] == '#define' and len(f) >= 3:
|
||||||
|
define = True
|
||||||
|
f.pop(0)
|
||||||
|
f.insert(1, '=')
|
||||||
|
|
||||||
|
# if f[0].startswith("KS_" + prefix.upper()):
|
||||||
|
if f[0].startswith("KS_"):
|
||||||
|
if len(f) > 1 and f[1] not in ('//', '='):
|
||||||
|
print("WARNING: Unable to convert %s" % f)
|
||||||
|
print(" Line =", line)
|
||||||
|
continue
|
||||||
|
elif len(f) > 1 and f[1] == '=':
|
||||||
|
rhs = ''.join(f[2:])
|
||||||
|
else:
|
||||||
|
rhs = str(count)
|
||||||
|
|
||||||
|
lhs = f[0].strip()
|
||||||
|
# evaluate bitshifts in constants e.g. "KS_X86 = 1 << 1"
|
||||||
|
match = re.match(r'(?P<rhs>\s*\d+\s*<<\s*\d+\s*)', rhs)
|
||||||
|
if match:
|
||||||
|
rhs = str(eval(match.group(1)))
|
||||||
|
else:
|
||||||
|
# evaluate references to other constants e.g. "KS_ARM_REG_X = KS_ARM_REG_SP"
|
||||||
|
match = re.match(r'^([^\d]\w+)$', rhs)
|
||||||
|
if match:
|
||||||
|
try:
|
||||||
|
rhs = previous[match.group(1)]
|
||||||
|
except:
|
||||||
|
rhs = match.group(1)
|
||||||
|
|
||||||
|
if not rhs.isdigit():
|
||||||
|
for k, v in previous.items():
|
||||||
|
rhs = re.sub(r'\b%s\b' % k, v, rhs)
|
||||||
|
try:
|
||||||
|
rhs = str(eval(rhs))
|
||||||
|
except:
|
||||||
|
rhs = ks_err_val[rhs]
|
||||||
|
|
||||||
|
lhs_strip = re.sub(r'^KS_', '', lhs)
|
||||||
|
consts[prefix].append((lhs_strip, rhs))
|
||||||
|
|
||||||
|
count = int(rhs) + 1
|
||||||
|
|
||||||
|
previous[lhs] = str(rhs)
|
||||||
|
|
||||||
|
|
||||||
|
rules = templ['rules']
|
||||||
|
|
||||||
|
for prefix in consts.keys():
|
||||||
|
outfile = open(templ['out_file'] % prefix, 'wb') # open as binary prevents windows newlines
|
||||||
|
outfile.write (templ['header'] % prefix)
|
||||||
|
|
||||||
|
for rule in rules:
|
||||||
|
regex = rule['regex']
|
||||||
|
|
||||||
|
consts2 = []
|
||||||
|
for const in consts.get(prefix):
|
||||||
|
if not (re.match(regex, const[0])):
|
||||||
|
continue
|
||||||
|
|
||||||
|
consts2.append(const)
|
||||||
|
|
||||||
|
if len(consts2) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if rule.get('pre'):
|
||||||
|
outfile.write(rule.get('pre').format(CamelCase(prefix)))
|
||||||
|
|
||||||
|
for const in consts2:
|
||||||
|
lhs_strip = const[0]
|
||||||
|
rhs = const[1]
|
||||||
|
outfile.write(rule['line_format'].format(rule['fn'](lhs_strip), rhs, lhs_strip).encode("utf-8"))
|
||||||
|
|
||||||
|
if rule.get('post'):
|
||||||
|
outfile.write (rule.get('post'))
|
||||||
|
outfile.write ('\n')
|
||||||
|
|
||||||
|
outfile.write (templ['footer'])
|
||||||
|
outfile.close()
|
||||||
|
|
||||||
|
def main():
|
||||||
|
lang = sys.argv[1]
|
||||||
|
if not lang in template:
|
||||||
|
raise RuntimeError("Unsupported binding %s" % lang)
|
||||||
|
gen(sys.argv[1])
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage:", sys.argv[0], " <python>")
|
||||||
|
sys.exit(1)
|
||||||
|
main()
|
@ -0,0 +1,63 @@
|
|||||||
|
###############################################################################
|
||||||
|
# Set default behavior to automatically normalize line endings.
|
||||||
|
###############################################################################
|
||||||
|
* text=auto
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set default behavior for command prompt diff.
|
||||||
|
#
|
||||||
|
# This is need for earlier builds of msysgit that does not have it on by
|
||||||
|
# default for csharp files.
|
||||||
|
# Note: This is only used by command line
|
||||||
|
###############################################################################
|
||||||
|
#*.cs diff=csharp
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Set the merge driver for project and solution files
|
||||||
|
#
|
||||||
|
# Merging from the command prompt will add diff markers to the files if there
|
||||||
|
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||||
|
# the diff markers are never inserted). Diff markers may cause the following
|
||||||
|
# file extensions to fail to load in VS. An alternative would be to treat
|
||||||
|
# these files as binary and thus will always conflict and require user
|
||||||
|
# intervention with every merge. To do so, just uncomment the entries below
|
||||||
|
###############################################################################
|
||||||
|
#*.sln merge=binary
|
||||||
|
#*.csproj merge=binary
|
||||||
|
#*.vbproj merge=binary
|
||||||
|
#*.vcxproj merge=binary
|
||||||
|
#*.vcproj merge=binary
|
||||||
|
#*.dbproj merge=binary
|
||||||
|
#*.fsproj merge=binary
|
||||||
|
#*.lsproj merge=binary
|
||||||
|
#*.wixproj merge=binary
|
||||||
|
#*.modelproj merge=binary
|
||||||
|
#*.sqlproj merge=binary
|
||||||
|
#*.wwaproj merge=binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# behavior for image files
|
||||||
|
#
|
||||||
|
# image files are treated as binary by default.
|
||||||
|
###############################################################################
|
||||||
|
#*.jpg binary
|
||||||
|
#*.png binary
|
||||||
|
#*.gif binary
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# diff behavior for common document formats
|
||||||
|
#
|
||||||
|
# Convert binary document formats to text before diffing them. This feature
|
||||||
|
# is only available from the command line. Turn it on by uncommenting the
|
||||||
|
# entries below.
|
||||||
|
###############################################################################
|
||||||
|
#*.doc diff=astextplain
|
||||||
|
#*.DOC diff=astextplain
|
||||||
|
#*.docx diff=astextplain
|
||||||
|
#*.DOCX diff=astextplain
|
||||||
|
#*.dot diff=astextplain
|
||||||
|
#*.DOT diff=astextplain
|
||||||
|
#*.pdf diff=astextplain
|
||||||
|
#*.PDF diff=astextplain
|
||||||
|
#*.rtf diff=astextplain
|
||||||
|
#*.RTF diff=astextplain
|
@ -0,0 +1,246 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
[Xx]64/
|
||||||
|
[Xx]86/
|
||||||
|
[Bb]uild/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
|
||||||
|
# TODO: Un-comment the next line if you do not want to checkin
|
||||||
|
# your web deploy settings because they may include unencrypted
|
||||||
|
# passwords
|
||||||
|
#*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Microsoft Azure ApplicationInsights config file
|
||||||
|
ApplicationInsights.config
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# LightSwitch generated files
|
||||||
|
GeneratedArtifacts/
|
||||||
|
ModelManifest.xml
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
/keystone/keystone.dll
|
@ -0,0 +1,20 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
|
<RootNamespace>Keystone.Tests</RootNamespace>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="../Keystone.Net/Keystone.Net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
|
||||||
|
<PackageReference Include="NUnit" Version="3.9.0" />
|
||||||
|
<PackageReference Include="NUnit3TestAdapter" Version="3.9.0" />
|
||||||
|
<PackageReference Include="Shouldly" Version="3.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Shouldly;
|
||||||
|
|
||||||
|
namespace Keystone.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ExecutionTests
|
||||||
|
{
|
||||||
|
[OneTimeSetUp]
|
||||||
|
public static void InitializeKeystone()
|
||||||
|
{
|
||||||
|
// Ensures the lib could be loaded
|
||||||
|
Engine.IsArchitectureSupported(Architecture.X86).ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldEmitValidX86Data()
|
||||||
|
{
|
||||||
|
using (Engine engine = new Engine(Architecture.X86, Mode.X32) { ThrowOnError = true })
|
||||||
|
{
|
||||||
|
engine.Assemble("nop", 0).Buffer.ShouldBe(new byte[] { 0x90 });
|
||||||
|
engine.Assemble("add eax, eax", 0).Buffer.ShouldBe(new byte[] { 0x01, 0xC0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldEmitValidARMData()
|
||||||
|
{
|
||||||
|
using (Engine engine = new Engine(Architecture.ARM, Mode.ARM) { ThrowOnError = true })
|
||||||
|
{
|
||||||
|
engine.Assemble("mul r1, r0, r0", 0).Buffer.ShouldBe(new byte[] { 0x90, 0x00, 0x01, 0xE0 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ShouldThrowOnError()
|
||||||
|
{
|
||||||
|
using (Engine engine = new Engine(Architecture.ARM, Mode.ARM) { ThrowOnError = false })
|
||||||
|
{
|
||||||
|
engine.Assemble("push eax, 0x42", 0).ShouldBeNull();
|
||||||
|
engine.Assemble("doesntexist", 0).ShouldBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (Engine engine = new Engine(Architecture.ARM, Mode.ARM) { ThrowOnError = true })
|
||||||
|
{
|
||||||
|
Should.Throw<KeystoneException>(() => engine.Assemble("push eax, 0x42", 0));
|
||||||
|
Should.Throw<KeystoneException>(() => engine.Assemble("doestexist", 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, Ignore("Feature requires Keystone built after October 7th 2016.")]
|
||||||
|
public void ShouldHaveValidExample()
|
||||||
|
{
|
||||||
|
using (Engine keystone = new Engine(Architecture.X86, Mode.X32) { ThrowOnError = true })
|
||||||
|
{
|
||||||
|
ulong address = 0;
|
||||||
|
|
||||||
|
keystone.ResolveSymbol += (string s, ref ulong w) =>
|
||||||
|
{
|
||||||
|
if (s == "_j1")
|
||||||
|
{
|
||||||
|
w = 0x1234abcd;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
EncodedData enc = keystone.Assemble("xor eax, eax; jmp _j1", address);
|
||||||
|
|
||||||
|
enc.Buffer.ShouldBe(new byte[] { 0x00 });
|
||||||
|
enc.Address.ShouldBe(address);
|
||||||
|
enc.StatementCount.ShouldBe(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.27130.2036
|
||||||
|
MinimumVisualStudioVersion = 15.0.26124.0
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Keystone.Net", "Keystone.Net\Keystone.Net.csproj", "{E3579F77-600A-4146-9296-3834B81F16E2}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Keystone.Net.Tests", "Keystone.Net.Tests\Keystone.Net.Tests.csproj", "{377B6FDC-156F-4B8B-B693-2A5C7B604A97}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{E3579F77-600A-4146-9296-3834B81F16E2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{377B6FDC-156F-4B8B-B693-2A5C7B604A97}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {0DA5689F-C570-41D7-93A8-F33F20F4B618}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64Constants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum Arm64Error : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_ARM64_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_ARM64_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_ARM64_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [armConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum ArmError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_ARM_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_ARM_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_ARM_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [hexagonConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum HexagonError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_HEXAGON_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_HEXAGON_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_HEXAGON_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,107 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystoneConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum Architecture : int
|
||||||
|
{
|
||||||
|
ARM = 1,
|
||||||
|
ARM64 = 2,
|
||||||
|
MIPS = 3,
|
||||||
|
X86 = 4,
|
||||||
|
PPC = 5,
|
||||||
|
SPARC = 6,
|
||||||
|
SYSTEMZ = 7,
|
||||||
|
HEXAGON = 8,
|
||||||
|
MAX = 9,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Mode : uint
|
||||||
|
{
|
||||||
|
LITTLE_ENDIAN = 0,
|
||||||
|
BIG_ENDIAN = 1073741824,
|
||||||
|
ARM = 1,
|
||||||
|
THUMB = 16,
|
||||||
|
V8 = 64,
|
||||||
|
MICRO = 16,
|
||||||
|
MIPS3 = 32,
|
||||||
|
MIPS32R6 = 64,
|
||||||
|
MIPS32 = 4,
|
||||||
|
MIPS64 = 8,
|
||||||
|
X16 = 2,
|
||||||
|
X32 = 4,
|
||||||
|
X64 = 8,
|
||||||
|
PPC32 = 4,
|
||||||
|
PPC64 = 8,
|
||||||
|
QPX = 16,
|
||||||
|
SPARC32 = 4,
|
||||||
|
SPARC64 = 8,
|
||||||
|
V9 = 16,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum KeystoneError : short
|
||||||
|
{
|
||||||
|
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_DIRECTIVE_UNKNOWN = 137,
|
||||||
|
KS_ERR_ASM_DIRECTIVE_EQU = 138,
|
||||||
|
KS_ERR_ASM_DIRECTIVE_INVALID = 139,
|
||||||
|
KS_ERR_ASM_VARIANT_INVALID = 140,
|
||||||
|
KS_ERR_ASM_EXPR_BRACKET = 141,
|
||||||
|
KS_ERR_ASM_SYMBOL_MODIFIER = 142,
|
||||||
|
KS_ERR_ASM_SYMBOL_REDEFINED = 143,
|
||||||
|
KS_ERR_ASM_SYMBOL_MISSING = 144,
|
||||||
|
KS_ERR_ASM_RPAREN = 145,
|
||||||
|
KS_ERR_ASM_STAT_TOKEN = 146,
|
||||||
|
KS_ERR_ASM_UNSUPPORTED = 147,
|
||||||
|
KS_ERR_ASM_MACRO_TOKEN = 148,
|
||||||
|
KS_ERR_ASM_MACRO_PAREN = 149,
|
||||||
|
KS_ERR_ASM_MACRO_EQU = 150,
|
||||||
|
KS_ERR_ASM_MACRO_ARGS = 151,
|
||||||
|
KS_ERR_ASM_MACRO_LEVELS_EXCEED = 152,
|
||||||
|
KS_ERR_ASM_MACRO_STR = 153,
|
||||||
|
KS_ERR_ASM_MACRO_INVALID = 154,
|
||||||
|
KS_ERR_ASM_ESC_BACKSLASH = 155,
|
||||||
|
KS_ERR_ASM_ESC_OCTAL = 156,
|
||||||
|
KS_ERR_ASM_ESC_SEQUENCE = 157,
|
||||||
|
KS_ERR_ASM_ESC_STR = 158,
|
||||||
|
KS_ERR_ASM_TOKEN_INVALID = 159,
|
||||||
|
KS_ERR_ASM_INSN_UNSUPPORTED = 160,
|
||||||
|
KS_ERR_ASM_FIXUP_INVALID = 161,
|
||||||
|
KS_ERR_ASM_LABEL_INVALID = 162,
|
||||||
|
KS_ERR_ASM_FRAGMENT_INVALID = 163,
|
||||||
|
KS_ERR_ASM_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_MNEMONICFAIL = 514
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OptionType : int
|
||||||
|
{
|
||||||
|
SYNTAX = 1,
|
||||||
|
SYM_RESOLVER = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OptionValue : short
|
||||||
|
{
|
||||||
|
SYNTAX_INTEL = 1,
|
||||||
|
SYNTAX_ATT = 2,
|
||||||
|
SYNTAX_NASM = 4,
|
||||||
|
SYNTAX_MASM = 8,
|
||||||
|
SYNTAX_GAS = 16,
|
||||||
|
SYNTAX_RADIX16 = 32
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mipsConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum MipsError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_MIPS_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_MIPS_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_MIPS_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppcConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum PpcError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_PPC_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_PPC_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_PPC_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparcConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum SparcError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_SPARC_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_SPARC_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_SPARC_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [systemzConstants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum SystemzError : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_SYSTEMZ_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_SYSTEMZ_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_SYSTEMZ_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86Constants.cs]
|
||||||
|
namespace Keystone
|
||||||
|
{
|
||||||
|
public enum X86Error : short
|
||||||
|
{
|
||||||
|
KS_ERR_ASM_X86_INVALIDOPERAND = 512,
|
||||||
|
KS_ERR_ASM_X86_MISSINGFEATURE = 513,
|
||||||
|
KS_ERR_ASM_X86_MNEMONICFAIL = 514,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.1</TargetFramework>
|
||||||
|
<RootNamespace>Keystone</RootNamespace>
|
||||||
|
|
||||||
|
<Version>1.1.0</Version>
|
||||||
|
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||||
|
<FileVersion>$(Version).0</FileVersion>
|
||||||
|
|
||||||
|
<Description>.NET bindings to the Keystone Engine.</Description>
|
||||||
|
<Authors>Grégoire Geis</Authors>
|
||||||
|
|
||||||
|
<PackageId>Keystone.Net</PackageId>
|
||||||
|
<PackageVersion>$(Version)</PackageVersion>
|
||||||
|
<PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance>
|
||||||
|
<PackageReleaseNotes>- First release.</PackageReleaseNotes>
|
||||||
|
<PackageTags>assembler x86 arm keystone</PackageTags>
|
||||||
|
|
||||||
|
<PackageProjectUrl>https://github.com/keystone-engine/keystone</PackageProjectUrl>
|
||||||
|
<PackageLicenseUrl>$(PackageProjectUrl)/blob/master/COPYING</PackageLicenseUrl>
|
||||||
|
<PackageIconUrl>http://www.keystone-engine.org/images/keystone.png</PackageIconUrl>
|
||||||
|
|
||||||
|
<RepositoryUrl>$(PackageProjectUrl).git</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
@ -0,0 +1,83 @@
|
|||||||
|
# Changes
|
||||||
|
|
||||||
|
### Names
|
||||||
|
- The `KeystoneNET` namespace was renamed to `Keystone`.
|
||||||
|
- The `Keystone` and `KeystoneEncoded` classes were respectively renamed to `Engine` and `EncodedData`.
|
||||||
|
- The `KeystoneArchitecture`, `KeystoneMode`, `KeystoneOptionType` and `KeystoneOptionValue` enums had their names changed, dropping the `Keystone` prefix (ie: `Architecture`, `Mode`, ...). Furthermore, their members were renamed, dropping the `KS_MODE_`, `KS_ARCH_`, and `KS_OPT_` prefixes.
|
||||||
|
|
||||||
|
### The `Engine` class
|
||||||
|
- The `Engine` constructor no longer takes `bool throwOnError`. Instead, the public `ThrowOnError` property now has both a getter and a setter, making it possible to alter the error behavior after initialization.
|
||||||
|
- Errors are no longer reported as `InvalidOperationException`, but instead as `KeystoneException`, a custom class which stores the returned error code.
|
||||||
|
- An error encountered in the constructor or when setting `ResolveSymbol` will throw an exception, regardless of the value of `ThrowOnError`.
|
||||||
|
- `AppendAssemble` was renamed to `Assemble`, and no longer accepts `ICollection<byte>`. Instead it accepts a `byte[]` buffer and an `int` index, and writes much more efficiently into it. A new overload accepting a `Stream` has also been added.
|
||||||
|
- The `out uint statements` parameter has been replaced by an `out int statementCount` parameter. It will always be positive, but better integrates into the C# language.
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
### Namespace
|
||||||
|
```csharp
|
||||||
|
using KeystoneNET;
|
||||||
|
```
|
||||||
|
becomes
|
||||||
|
```csharp
|
||||||
|
using Keystone;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Initialization
|
||||||
|
```csharp
|
||||||
|
using (var ks = new Keystone(KeystoneArchitecture.KS_ARCH_X86,
|
||||||
|
KeystoneMode.KS_MODE_32,
|
||||||
|
throwOnError: false))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
becomes
|
||||||
|
```csharp
|
||||||
|
using (var ks = new Engine(Architecture.X86, Mode.X32)
|
||||||
|
{ ThrowOnError = true })
|
||||||
|
{
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Catching errors
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ks.SymbolResolver += Callback;
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
becomes
|
||||||
|
```csharp
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ks.SymbolResolver += Callback;
|
||||||
|
}
|
||||||
|
catch (KeystoneException e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Assembling data
|
||||||
|
```csharp
|
||||||
|
var data = new List<byte>();
|
||||||
|
|
||||||
|
ks.AppendAssemble("add eax, eax", data);
|
||||||
|
```
|
||||||
|
becomes
|
||||||
|
```csharp
|
||||||
|
var data = new byte[1024];
|
||||||
|
|
||||||
|
ks.Assemble("add eax, eax", data);
|
||||||
|
```
|
||||||
|
or
|
||||||
|
```csharp
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
ks.Assemble("add eax, eax", ms);
|
||||||
|
}
|
||||||
|
```
|
@ -0,0 +1,32 @@
|
|||||||
|
# Keystone.Net
|
||||||
|
.NET Standard bindings for Keystone.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
```csharp
|
||||||
|
using Keystone;
|
||||||
|
|
||||||
|
using (Engine keystone = new Engine(Architecture.X86, Mode.X32) { ThrowOnError = true })
|
||||||
|
{
|
||||||
|
ulong address = 0;
|
||||||
|
|
||||||
|
keystone.ResolveSymbol += (string s, ref ulong w) =>
|
||||||
|
{
|
||||||
|
if (s == "_j1")
|
||||||
|
{
|
||||||
|
w = 0x1234abcd;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
EncodedData enc = keystone.Assemble("xor eax, eax; jmp _j1", address);
|
||||||
|
|
||||||
|
enc.Buffer.ShouldBe(new byte[] { 0x00 });
|
||||||
|
enc.Address.ShouldBe(address);
|
||||||
|
enc.StatementCount.ShouldBe(3);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For those who already used the bindings before their last update, many things have changed.
|
||||||
|
You can migrate your existing code easily using the [migration guide](./MIGRATON.md).
|
@ -0,0 +1,21 @@
|
|||||||
|
# Go binding for Keystone engine. Remco Verhoef <remco@honeytrap.io>
|
||||||
|
|
||||||
|
ifndef BUILDDIR
|
||||||
|
OBJDIR = ./build
|
||||||
|
else
|
||||||
|
OBJDIR = $(abspath $(BUILDDIR))/obj/bindings/go
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: gen_const install clean check
|
||||||
|
|
||||||
|
gen_const:
|
||||||
|
cd .. && python const_generator.py go
|
||||||
|
go fmt
|
||||||
|
|
||||||
|
install:
|
||||||
|
cd keystone && go build
|
||||||
|
|
||||||
|
clean:
|
||||||
|
|
||||||
|
check:
|
||||||
|
cd keystone && go test
|
@ -0,0 +1,43 @@
|
|||||||
|
# keystone
|
||||||
|
Go bindings for the [keystone](http://www.keystone-engine.org/) engine.
|
||||||
|
|
||||||
|
## Sample
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/keystone-engine/keystone/bindings/go/keystone"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
assembly := os.Args[1]
|
||||||
|
|
||||||
|
ks, err := keystone.New(keystone.ARCH_X86, keystone.MODE_32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer ks.Close()
|
||||||
|
|
||||||
|
if err := ks.Option(keystone.OPT_SYNTAX, keystone.OPT_SYNTAX_INTEL); err != nil {
|
||||||
|
panic(fmt.Errorf("Could not set syntax option to intel"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if insn, _, ok := ks.Assemble(assembly, 0); !ok {
|
||||||
|
panic(fmt.Errorf("Could not assemble instruction"))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s: [%x]", assembly, insn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```
|
||||||
|
go test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
- Remco Verhoef (@remco_verhoef)
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm64_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_ARM64_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_ARM64_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_ARM64_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [arm_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_ARM_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_ARM_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_ARM_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [evm_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_EVM_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_EVM_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_EVM_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [hexagon_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_HEXAGON_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_HEXAGON_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_HEXAGON_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,65 @@
|
|||||||
|
/* Keystone Assembler Engine (www.keystone-engine.org) */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
|
||||||
|
/* Golang bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
|
||||||
|
|
||||||
|
// +build darwin,linux,cgo
|
||||||
|
package keystone
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -lkeystone -lstdc++ -lm
|
||||||
|
// #include <keystone/keystone.h>
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func ks_version() (uint, uint) {
|
||||||
|
major := C.uint(0)
|
||||||
|
minor := C.uint(0)
|
||||||
|
C.ks_version(&major, &minor)
|
||||||
|
return uint(major), uint(minor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_arch_supported(a Architecture) bool {
|
||||||
|
return bool(C.ks_arch_supported((C.ks_arch)(a)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_open(a Architecture, m Mode, engine **C.ks_engine) error {
|
||||||
|
if err := C.ks_open((C.ks_arch)(a), (C.int)(m), (**C.ks_engine)(unsafe.Pointer(engine))); err != 0 {
|
||||||
|
return Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_option(engine *C.ks_engine, type_ OptionType, value OptionValue) error {
|
||||||
|
if err := C.ks_option(engine, C.ks_opt_type(type_), C.size_t(value)); err != 0 {
|
||||||
|
return Error(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_errno(engine *C.ks_engine) error {
|
||||||
|
if err := C.ks_errno(engine); err != 0 {
|
||||||
|
return Error(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_asm(engine *C.ks_engine, str string, address uint64, encoding *[]byte, stat_count *uint64) bool {
|
||||||
|
cstr := C.CString(str)
|
||||||
|
defer C.free(unsafe.Pointer(cstr))
|
||||||
|
|
||||||
|
var p_insn unsafe.Pointer
|
||||||
|
defer C.free(unsafe.Pointer(p_insn))
|
||||||
|
|
||||||
|
var count, l_insn C.size_t
|
||||||
|
err := C.ks_asm(engine, cstr, C.uint64_t(address), (**C.uchar)(unsafe.Pointer(&p_insn)), &l_insn, &count)
|
||||||
|
*encoding = C.GoBytes(p_insn, C.int(l_insn))
|
||||||
|
*stat_count = uint64(count)
|
||||||
|
return err == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ks_close(engine *C.ks_engine) error {
|
||||||
|
if err := C.ks_close(engine); err != 0 {
|
||||||
|
return Error(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/* Keystone Assembler Engine (www.keystone-engine.org) */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
|
||||||
|
/* Golang bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
|
||||||
|
|
||||||
|
package keystone
|
||||||
|
|
||||||
|
// #include <keystone/keystone.h>
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type Architecture uint
|
||||||
|
|
||||||
|
type Mode uint
|
||||||
|
|
||||||
|
type OptionType uint
|
||||||
|
|
||||||
|
type OptionValue uint
|
||||||
|
|
||||||
|
type Error uint32
|
||||||
|
|
||||||
|
func (e Error) Error() string {
|
||||||
|
s := C.ks_strerror((C.ks_err)(e))
|
||||||
|
return C.GoString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Architecture) Supported() bool {
|
||||||
|
return ks_arch_supported(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Version() (uint, uint) {
|
||||||
|
return ks_version()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Keystone struct {
|
||||||
|
engine *C.ks_engine
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(a Architecture, m Mode) (*Keystone, error) {
|
||||||
|
ks := &Keystone{}
|
||||||
|
if err := ks_open(a, m, &ks.engine); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return ks, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *Keystone) LastError() error {
|
||||||
|
return ks_errno(ks.engine)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *Keystone) Option(type_ OptionType, value OptionValue) error {
|
||||||
|
if err := ks_option(ks.engine, type_, value); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *Keystone) Assemble(str string, address uint64) ([]byte, uint64, bool) {
|
||||||
|
encoding := []byte{}
|
||||||
|
stat_count := uint64(0)
|
||||||
|
ok := ks_asm(ks.engine, str, address, &encoding, &stat_count)
|
||||||
|
return encoding, stat_count, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ks *Keystone) Close() error {
|
||||||
|
return ks_close(ks.engine)
|
||||||
|
}
|
@ -0,0 +1,108 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [keystone_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
API_MAJOR = 0
|
||||||
|
API_MINOR = 9
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MODE_LITTLE_ENDIAN Mode = 0
|
||||||
|
MODE_BIG_ENDIAN Mode = 1073741824
|
||||||
|
MODE_ARM Mode = 1
|
||||||
|
MODE_THUMB Mode = 16
|
||||||
|
MODE_V8 Mode = 64
|
||||||
|
MODE_MICRO Mode = 16
|
||||||
|
MODE_MIPS3 Mode = 32
|
||||||
|
MODE_MIPS32R6 Mode = 64
|
||||||
|
MODE_MIPS32 Mode = 4
|
||||||
|
MODE_MIPS64 Mode = 8
|
||||||
|
MODE_16 Mode = 2
|
||||||
|
MODE_32 Mode = 4
|
||||||
|
MODE_64 Mode = 8
|
||||||
|
MODE_PPC32 Mode = 4
|
||||||
|
MODE_PPC64 Mode = 8
|
||||||
|
MODE_QPX Mode = 16
|
||||||
|
MODE_SPARC32 Mode = 4
|
||||||
|
MODE_SPARC64 Mode = 8
|
||||||
|
MODE_V9 Mode = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ARCH_ARM Architecture = 1
|
||||||
|
ARCH_ARM64 Architecture = 2
|
||||||
|
ARCH_MIPS Architecture = 3
|
||||||
|
ARCH_X86 Architecture = 4
|
||||||
|
ARCH_PPC Architecture = 5
|
||||||
|
ARCH_SPARC Architecture = 6
|
||||||
|
ARCH_SYSTEMZ Architecture = 7
|
||||||
|
ARCH_HEXAGON Architecture = 8
|
||||||
|
ARCH_EVM Architecture = 9
|
||||||
|
ARCH_MAX Architecture = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OPT_SYNTAX OptionType = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
OPT_SYM_RESOLVER OptionValue = 2
|
||||||
|
OPT_SYNTAX_INTEL OptionValue = 1
|
||||||
|
OPT_SYNTAX_ATT OptionValue = 2
|
||||||
|
OPT_SYNTAX_NASM OptionValue = 4
|
||||||
|
OPT_SYNTAX_MASM OptionValue = 8
|
||||||
|
OPT_SYNTAX_GAS OptionValue = 16
|
||||||
|
OPT_SYNTAX_RADIX16 OptionValue = 32
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM Error = 128
|
||||||
|
ERR_ASM_ARCH Error = 512
|
||||||
|
ERR_OK Error = 0
|
||||||
|
ERR_NOMEM Error = 1
|
||||||
|
ERR_ARCH Error = 2
|
||||||
|
ERR_HANDLE Error = 3
|
||||||
|
ERR_MODE Error = 4
|
||||||
|
ERR_VERSION Error = 5
|
||||||
|
ERR_OPT_INVALID Error = 6
|
||||||
|
ERR_ASM_EXPR_TOKEN Error = 128
|
||||||
|
ERR_ASM_DIRECTIVE_VALUE_RANGE Error = 129
|
||||||
|
ERR_ASM_DIRECTIVE_ID Error = 130
|
||||||
|
ERR_ASM_DIRECTIVE_TOKEN Error = 131
|
||||||
|
ERR_ASM_DIRECTIVE_STR Error = 132
|
||||||
|
ERR_ASM_DIRECTIVE_COMMA Error = 133
|
||||||
|
ERR_ASM_DIRECTIVE_RELOC_NAME Error = 134
|
||||||
|
ERR_ASM_DIRECTIVE_RELOC_TOKEN Error = 135
|
||||||
|
ERR_ASM_DIRECTIVE_FPOINT Error = 136
|
||||||
|
ERR_ASM_DIRECTIVE_UNKNOWN Error = 137
|
||||||
|
ERR_ASM_DIRECTIVE_EQU Error = 138
|
||||||
|
ERR_ASM_DIRECTIVE_INVALID Error = 139
|
||||||
|
ERR_ASM_VARIANT_INVALID Error = 140
|
||||||
|
ERR_ASM_EXPR_BRACKET Error = 141
|
||||||
|
ERR_ASM_SYMBOL_MODIFIER Error = 142
|
||||||
|
ERR_ASM_SYMBOL_REDEFINED Error = 143
|
||||||
|
ERR_ASM_SYMBOL_MISSING Error = 144
|
||||||
|
ERR_ASM_RPAREN Error = 145
|
||||||
|
ERR_ASM_STAT_TOKEN Error = 146
|
||||||
|
ERR_ASM_UNSUPPORTED Error = 147
|
||||||
|
ERR_ASM_MACRO_TOKEN Error = 148
|
||||||
|
ERR_ASM_MACRO_PAREN Error = 149
|
||||||
|
ERR_ASM_MACRO_EQU Error = 150
|
||||||
|
ERR_ASM_MACRO_ARGS Error = 151
|
||||||
|
ERR_ASM_MACRO_LEVELS_EXCEED Error = 152
|
||||||
|
ERR_ASM_MACRO_STR Error = 153
|
||||||
|
ERR_ASM_MACRO_INVALID Error = 154
|
||||||
|
ERR_ASM_ESC_BACKSLASH Error = 155
|
||||||
|
ERR_ASM_ESC_OCTAL Error = 156
|
||||||
|
ERR_ASM_ESC_SEQUENCE Error = 157
|
||||||
|
ERR_ASM_ESC_STR Error = 158
|
||||||
|
ERR_ASM_TOKEN_INVALID Error = 159
|
||||||
|
ERR_ASM_INSN_UNSUPPORTED Error = 160
|
||||||
|
ERR_ASM_FIXUP_INVALID Error = 161
|
||||||
|
ERR_ASM_LABEL_INVALID Error = 162
|
||||||
|
ERR_ASM_FRAGMENT_INVALID Error = 163
|
||||||
|
ERR_ASM_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,66 @@
|
|||||||
|
/* Keystone Assembler Engine (www.keystone-engine.org) */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
|
||||||
|
/* Golang bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
|
||||||
|
|
||||||
|
package keystone
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVersion(t *testing.T) {
|
||||||
|
major, minor := Version()
|
||||||
|
if major == API_MAJOR && minor == API_MINOR {
|
||||||
|
} else {
|
||||||
|
t.Error(fmt.Errorf("Unexpected version: got %d.%d expected %d.%d", major, minor, 1, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArchitectureSupported(t *testing.T) {
|
||||||
|
if !ARCH_ARM.Supported() {
|
||||||
|
t.Error(fmt.Errorf("ARM not supported"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Test struct {
|
||||||
|
Architecture Architecture
|
||||||
|
Mode Mode
|
||||||
|
Address uint64
|
||||||
|
Assembly string
|
||||||
|
ExpectedResult []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Syntax struct {
|
||||||
|
Syntax OptionValue
|
||||||
|
Tests []Test
|
||||||
|
}
|
||||||
|
|
||||||
|
var tests = []Syntax{
|
||||||
|
Syntax{
|
||||||
|
OPT_SYNTAX_INTEL, []Test{
|
||||||
|
Test{ARCH_X86, MODE_32 | MODE_LITTLE_ENDIAN, 0, "mov ah, al", []byte{0x88, 0xc4}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRun(t *testing.T) {
|
||||||
|
for _, st := range tests {
|
||||||
|
for _, tr := range st.Tests {
|
||||||
|
if ks, err := New(tr.Architecture, tr.Mode); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else {
|
||||||
|
defer ks.Close()
|
||||||
|
|
||||||
|
if err := ks.Option(OPT_SYNTAX, st.Syntax); err != nil {
|
||||||
|
t.Error(fmt.Errorf("Could not set syntax option to intel"))
|
||||||
|
} else if insn, _, ok := ks.Assemble(tr.Assembly, tr.Address); !ok {
|
||||||
|
t.Error(fmt.Errorf("Could not assemble instruction"))
|
||||||
|
} else if !reflect.DeepEqual(insn, tr.ExpectedResult) {
|
||||||
|
t.Error(fmt.Errorf("Not expected result: expected %#v got %#v", tr.ExpectedResult, insn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [mips_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_MIPS_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_MIPS_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_MIPS_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [ppc_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_PPC_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_PPC_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_PPC_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
/* Keystone Assembler Engine (www.keystone-engine.org) */
|
||||||
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
|
||||||
|
/* Golang bindings by Remco Verhoef <remco@dutchcoders.io>, 2016 */
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/keystone-engine/keystone/bindings/go/keystone"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
assembly := os.Args[1]
|
||||||
|
|
||||||
|
ks, err := keystone.New(keystone.ARCH_X86, keystone.MODE_32)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer ks.Close()
|
||||||
|
|
||||||
|
if err := ks.Option(keystone.OPT_SYNTAX, keystone.OPT_SYNTAX_INTEL); err != nil {
|
||||||
|
panic(fmt.Errorf("Could not set syntax option to intel"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if insn, _, ok := ks.Assemble(assembly, 0); !ok {
|
||||||
|
panic(fmt.Errorf("Could not assemble instruction"))
|
||||||
|
} else {
|
||||||
|
fmt.Printf("%s: [%x]", assembly, insn)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [sparc_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_SPARC_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_SPARC_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_SPARC_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [systemz_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_SYSTEMZ_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_SYSTEMZ_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_SYSTEMZ_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package keystone
|
||||||
|
// For Keystone Engine. AUTO-GENERATED FILE, DO NOT EDIT [x86_const.go]
|
||||||
|
|
||||||
|
const (
|
||||||
|
ERR_ASM_X86_INVALIDOPERAND Error = 512
|
||||||
|
ERR_ASM_X86_MISSINGFEATURE Error = 513
|
||||||
|
ERR_ASM_X86_MNEMONICFAIL Error = 514
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,17 @@
|
|||||||
|
dist
|
||||||
|
cabal-dev
|
||||||
|
*.o
|
||||||
|
*.hi
|
||||||
|
*.chi
|
||||||
|
*.chs.h
|
||||||
|
*.dyn_o
|
||||||
|
*.dyn_hi
|
||||||
|
.virtualenv
|
||||||
|
.hpc
|
||||||
|
.hsenv
|
||||||
|
.cabal-sandbox/
|
||||||
|
cabal.sandbox.config
|
||||||
|
*.prof
|
||||||
|
*.aux
|
||||||
|
*.hp
|
||||||
|
Sample
|
@ -0,0 +1,27 @@
|
|||||||
|
This documentation explains how to install the Keystone Haskell bindings from
|
||||||
|
source.
|
||||||
|
|
||||||
|
1. Install the core Keystone Assembler as a dependency:
|
||||||
|
|
||||||
|
Follow docs/COMPILE.md in the root directory to compile & install the core.
|
||||||
|
2. Change into the Haskell bindings directory, build and install:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd bindings/haskell
|
||||||
|
$ cabal install
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are installing into a sandbox, run `cabal sandbox init` before
|
||||||
|
installing Keystone's dependencies.
|
||||||
|
|
||||||
|
If the build fails, install c2hs manually `cabal install c2hs` (note that this
|
||||||
|
will probably also require you to run `cabal install alex` and `cabal install
|
||||||
|
happy` as well). If you are NOT using a sandbox, ensure that `$HOME/.cabal/bin`
|
||||||
|
is on your PATH.
|
||||||
|
|
||||||
|
To build a sample (after having built and installed the Haskell bindings):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd bindings/haskell
|
||||||
|
$ ghc --make samples/Sample.hs
|
||||||
|
```
|
@ -0,0 +1,2 @@
|
|||||||
|
import Distribution.Simple
|
||||||
|
main = defaultMain
|
@ -0,0 +1,38 @@
|
|||||||
|
-- Initial keystone.cabal generated by cabal init. For further
|
||||||
|
-- documentation, see http://haskell.org/cabal/users-guide/
|
||||||
|
|
||||||
|
name: keystone
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: Keystone lightweight multi-platform, multi-architecture assembler framework
|
||||||
|
description: Haskell bindings for the Keystone assembler
|
||||||
|
homepage: https://github.com/keystone-engine/keystone
|
||||||
|
license: GPL-2
|
||||||
|
author: Adrian Herrera
|
||||||
|
category: System
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >= 1.10
|
||||||
|
|
||||||
|
library
|
||||||
|
exposed-modules: Keystone.Internal.Core
|
||||||
|
Keystone.Internal.Keystone
|
||||||
|
Keystone.CPU.Arm64
|
||||||
|
Keystone.CPU.Arm
|
||||||
|
Keystone.CPU.Hexagon
|
||||||
|
Keystone.CPU.Mips
|
||||||
|
Keystone.CPU.Ppc
|
||||||
|
Keystone.CPU.Sparc
|
||||||
|
Keystone.CPU.SystemZ
|
||||||
|
Keystone.CPU.X86
|
||||||
|
Keystone
|
||||||
|
other-modules: Keystone.Internal.Util
|
||||||
|
build-depends: base >= 4 && < 5
|
||||||
|
, bytestring >= 0.9.1
|
||||||
|
, transformers < 0.6
|
||||||
|
, either >= 4.4
|
||||||
|
hs-source-dirs: src
|
||||||
|
c-sources: src/cbits/keystone_wrapper.c
|
||||||
|
include-dirs: src/include
|
||||||
|
build-tools: c2hs
|
||||||
|
pkgconfig-depends: keystone
|
||||||
|
default-language: Haskell2010
|
||||||
|
ghc-options: -Wall
|
@ -0,0 +1,74 @@
|
|||||||
|
-- Sample code for Keystone Assembler Engine.
|
||||||
|
|
||||||
|
import Keystone
|
||||||
|
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
import Data.List (intercalate)
|
||||||
|
import qualified Numeric as N (showHex)
|
||||||
|
|
||||||
|
-- Pretty-print byte string as hex.
|
||||||
|
showHexBS :: BS.ByteString
|
||||||
|
-> String
|
||||||
|
showHexBS =
|
||||||
|
concatMap (flip N.showHex " ") . BS.unpack
|
||||||
|
|
||||||
|
testKs :: Architecture
|
||||||
|
-> [Mode]
|
||||||
|
-> [String]
|
||||||
|
-> Maybe OptionValue
|
||||||
|
-> IO ()
|
||||||
|
testKs arch mode assembly maybeSyntax = do
|
||||||
|
result <- runAssembler $ do
|
||||||
|
ks <- open arch mode
|
||||||
|
case maybeSyntax of
|
||||||
|
Just syntax -> option ks OptSyntax syntax
|
||||||
|
Nothing -> return ()
|
||||||
|
(encode, count) <- assemble ks assembly Nothing
|
||||||
|
return (encode, count)
|
||||||
|
case result of
|
||||||
|
Right (encode, count) -> let size = BS.length encode in do
|
||||||
|
putStr $ intercalate ";" assembly ++ " = "
|
||||||
|
putStrLn $ showHexBS encode
|
||||||
|
putStrLn $ "Assembled: " ++ show size ++ " bytes, " ++
|
||||||
|
show count ++ " statements\n"
|
||||||
|
Left err -> putStrLn $ "Failed with error: " ++ show err ++ " (" ++
|
||||||
|
strerror err ++ ")"
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
-- X86
|
||||||
|
testKs ArchX86 [Mode16] ["add eax, ecx"] Nothing
|
||||||
|
testKs ArchX86 [Mode32] ["add eax, ecx"] Nothing
|
||||||
|
testKs ArchX86 [Mode64] ["add rax, rcx"] Nothing
|
||||||
|
testKs ArchX86 [Mode32] ["add %ecx, %eax"] (Just SyntaxAtt)
|
||||||
|
testKs ArchX86 [Mode64] ["add %rcx, %rax"] (Just SyntaxAtt)
|
||||||
|
|
||||||
|
-- ARM
|
||||||
|
testKs ArchArm [ModeArm] ["sub r1, r2, r5"] Nothing
|
||||||
|
testKs ArchArm [ModeArm, ModeBigEndian] ["sub r1, r2, r5"] Nothing
|
||||||
|
testKs ArchArm [ModeThumb] ["movs r4, #0xf0"] Nothing
|
||||||
|
testKs ArchArm [ModeThumb, ModeBigEndian] ["movs r4, #0xf0"] Nothing
|
||||||
|
|
||||||
|
-- ARM64
|
||||||
|
testKs ArchArm64 [ModeLittleEndian] ["ldr w1, [sp, #0x8]"] Nothing
|
||||||
|
|
||||||
|
-- Hexagon
|
||||||
|
testKs ArchHexagon [ModeBigEndian] ["v23.w=vavg(v11.w,v2.w):rnd"] Nothing
|
||||||
|
|
||||||
|
-- MIPS
|
||||||
|
testKs ArchMips [ModeMips32] ["and $9, $6, $7"] Nothing
|
||||||
|
testKs ArchMips [ModeMips32, ModeBigEndian] ["and $9, $6, $7"] Nothing
|
||||||
|
testKs ArchMips [ModeMips64] ["and $9, $6, $7"] Nothing
|
||||||
|
testKs ArchMips [ModeMips64, ModeBigEndian] ["and $9, $6, $7"] Nothing
|
||||||
|
|
||||||
|
-- PowerPC
|
||||||
|
testKs ArchPpc [ModePpc32, ModeBigEndian] ["add 1, 2, 3"] Nothing
|
||||||
|
testKs ArchPpc [ModePpc64] ["add 1, 2, 3"] Nothing
|
||||||
|
testKs ArchPpc [ModePpc64, ModeBigEndian] ["add 1, 2, 3"] Nothing
|
||||||
|
|
||||||
|
-- SPARC
|
||||||
|
testKs ArchSparc [ModeSparc32, ModeLittleEndian] ["add %g1, %g2, %g3"] Nothing
|
||||||
|
testKs ArchSparc [ModeSparc32, ModeBigEndian] ["add %g1, %g2, %g3"] Nothing
|
||||||
|
|
||||||
|
-- SystemZ
|
||||||
|
testKs ArchSystemz [ModeBigEndian] ["a %r0, 4095(%r15,%r1)"] Nothing
|
@ -0,0 +1,128 @@
|
|||||||
|
{-|
|
||||||
|
Module : Keystone
|
||||||
|
Description : The Keystone assembler engine.
|
||||||
|
Copyright : (c) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Keystone is a lightweight multi-platform, multi-architecture assembler
|
||||||
|
framework.
|
||||||
|
|
||||||
|
Further information is available at <http://www.keystone-engine.org>.
|
||||||
|
-}
|
||||||
|
module Keystone
|
||||||
|
( -- * Assembler control
|
||||||
|
Assembler
|
||||||
|
, Engine
|
||||||
|
, Architecture(..)
|
||||||
|
, Mode(..)
|
||||||
|
, OptionType(..)
|
||||||
|
, OptionValue(..)
|
||||||
|
, runAssembler
|
||||||
|
, open
|
||||||
|
, option
|
||||||
|
, assemble
|
||||||
|
|
||||||
|
-- * Error handling
|
||||||
|
, Error(..)
|
||||||
|
, errno
|
||||||
|
, strerror
|
||||||
|
|
||||||
|
-- * Misc.
|
||||||
|
, version
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
import Control.Monad.Trans.Either (left, right, runEitherT)
|
||||||
|
import Data.ByteString (ByteString, packCStringLen)
|
||||||
|
import Data.List (intercalate)
|
||||||
|
import Foreign
|
||||||
|
|
||||||
|
import Keystone.Internal.Core
|
||||||
|
import Keystone.Internal.Keystone
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Assembler control
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | Run the Keystone assembler and return a result on success, or an 'Error'
|
||||||
|
-- on failure.
|
||||||
|
runAssembler :: Assembler a -- ^ The assembler code to execute
|
||||||
|
-> IO (Either Error a) -- ^ A result on success, or an 'Error' on
|
||||||
|
-- failure
|
||||||
|
runAssembler =
|
||||||
|
runEitherT
|
||||||
|
|
||||||
|
-- | Create a new instance of the Keystone assembler.
|
||||||
|
open :: Architecture -- ^ CPU architecture
|
||||||
|
-> [Mode] -- ^ CPU hardware mode
|
||||||
|
-> Assembler Engine -- ^ A 'Keystone' engine on success, or an 'Error'
|
||||||
|
-- on failure
|
||||||
|
open arch mode = do
|
||||||
|
(err, ksPtr) <- lift $ ksOpen arch mode
|
||||||
|
if err == ErrOk then
|
||||||
|
-- Return a pointer to the Keystone engine if ksOpen completed
|
||||||
|
-- successfully
|
||||||
|
lift $ mkEngine ksPtr
|
||||||
|
else
|
||||||
|
-- Otherwise return an error
|
||||||
|
left err
|
||||||
|
|
||||||
|
option :: Engine -- ^ 'Keystone' engine handle
|
||||||
|
-> OptionType -- ^ Type of option to set
|
||||||
|
-> OptionValue -- ^ Option value corresponding with the type
|
||||||
|
-> Assembler () -- ^ An 'Error' on failure
|
||||||
|
option ks optType optValue = do
|
||||||
|
err <- lift $ ksOption ks optType optValue
|
||||||
|
if err == ErrOk then
|
||||||
|
right ()
|
||||||
|
else
|
||||||
|
left err
|
||||||
|
|
||||||
|
-- | Assemble a list of statements.
|
||||||
|
assemble :: Engine -- ^ 'Keystone' engine handle
|
||||||
|
-> [String] -- ^ List of statements to assemble.
|
||||||
|
-> Maybe Word64 -- ^ Optional address of the first
|
||||||
|
-- assembly instruction
|
||||||
|
-> Assembler (ByteString, Int) -- ^ Returns the encoded input assembly
|
||||||
|
-- string and the number of statements
|
||||||
|
-- successfully processed. Returns an
|
||||||
|
-- 'Error' on failure
|
||||||
|
assemble ks stmts addr = do
|
||||||
|
let string = intercalate ";" stmts
|
||||||
|
(res, encPtr, encSize, statCount) <- lift $ ksAsm ks string (maybeZ addr)
|
||||||
|
if res == 0 then do
|
||||||
|
-- If ksAsm completed successfully, pack the encoded bytes into a
|
||||||
|
-- ByteString. Once the encoded bytes have been packed the original
|
||||||
|
-- encoded bytes can be freed. The ByteString is returned with the
|
||||||
|
-- statement count
|
||||||
|
bs <- lift $ packCStringLen (castPtr encPtr, encSize)
|
||||||
|
lift $ ksFree encPtr
|
||||||
|
right (bs, statCount)
|
||||||
|
else do
|
||||||
|
-- On failure, call errno for error code
|
||||||
|
err <- errno ks
|
||||||
|
left err
|
||||||
|
where maybeZ = maybe 0 id
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Misc.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | Combined API version & major and minor version numbers. Returns a
|
||||||
|
-- hexadecimal number as (major << 8 | minor), which encodes both major and
|
||||||
|
-- minor versions.
|
||||||
|
version :: Int
|
||||||
|
version =
|
||||||
|
ksVersion nullPtr nullPtr
|
||||||
|
|
||||||
|
-- | Report the 'Error' number when some API function failed.
|
||||||
|
errno :: Engine -- ^ 'Keystone' engine handle
|
||||||
|
-> Assembler Error -- ^ The last 'Error' code
|
||||||
|
errno =
|
||||||
|
lift . ksErrno
|
||||||
|
|
||||||
|
-- | Return a string describing the given 'Error'.
|
||||||
|
strerror :: Error -- ^ The 'Error' code
|
||||||
|
-> String -- ^ Description of the error code
|
||||||
|
strerror =
|
||||||
|
ksStrerror
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Arm
|
||||||
|
Description : Definitions for the ARM architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the ARM architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Arm
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/arm.h>
|
||||||
|
|
||||||
|
-- | ARM errors.
|
||||||
|
{# enum ks_err_asm_arm as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_ARM_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Arm64
|
||||||
|
Description : Definitions for the ARM64 architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the ARM64 architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Arm64
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/arm64.h>
|
||||||
|
|
||||||
|
-- | ARM64 errors.
|
||||||
|
{# enum ks_err_asm_arm64 as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_ARM64_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Hexagon
|
||||||
|
Description : Definitions for the Hexagon architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the Hexagon architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Hexagon
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/hexagon.h>
|
||||||
|
|
||||||
|
-- | Hexagon errors.
|
||||||
|
{# enum ks_err_asm_hexagon as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_HEXAGON_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Mips
|
||||||
|
Description : Definitions for the MIPS architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the MIPS architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Mips
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/mips.h>
|
||||||
|
|
||||||
|
-- | MIPS errors.
|
||||||
|
{# enum ks_err_asm_mips as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_MIPS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Ppc
|
||||||
|
Description : Definitions for the PPC architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the PPC architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Ppc
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/ppc.h>
|
||||||
|
|
||||||
|
-- | PPC errors.
|
||||||
|
{# enum ks_err_asm_ppc as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_PPC_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,24 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.Sparc
|
||||||
|
Description : Definitions for the SPARC architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the SPARC architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.Sparc
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/sparc.h>
|
||||||
|
|
||||||
|
-- | SPARC errors.
|
||||||
|
{# enum ks_err_asm_sparc as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_SPARC_"
|
||||||
|
deriving (Show, Eq, Bounded) #}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.SystemZ
|
||||||
|
Description : Definitions for the SystemZ architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the SystemZ architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.SystemZ
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/systemz.h>
|
||||||
|
|
||||||
|
-- | SystemZ errors.
|
||||||
|
{# enum ks_err_asm_systemz as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_SYSTEMZ_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,25 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.CPU.X86
|
||||||
|
Description : Definitions for the X86 architecture.
|
||||||
|
Copyright : (C) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Definitions for the X86 architecture.
|
||||||
|
-}
|
||||||
|
module Keystone.CPU.X86
|
||||||
|
(
|
||||||
|
Error(..)
|
||||||
|
) where
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/x86.h>
|
||||||
|
|
||||||
|
-- | X86 errors.
|
||||||
|
{# enum ks_err_asm_x86 as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_ERR_ASM_X86_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
@ -0,0 +1,51 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module
|
||||||
|
Description : Core Keystone components.
|
||||||
|
Copyright : (c) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Defines core Keystone components.
|
||||||
|
|
||||||
|
This module should not be directly imported; it is only exposed because of the
|
||||||
|
way cabal handles ordering of chs files.
|
||||||
|
-}
|
||||||
|
module Keystone.Internal.Core where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import Control.Monad.Trans.Either (EitherT)
|
||||||
|
import Foreign
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/keystone.h>
|
||||||
|
#include "keystone_wrapper.h"
|
||||||
|
|
||||||
|
-- | The Keystone engine.
|
||||||
|
{# pointer *ks_engine as Engine
|
||||||
|
foreign finalizer ks_close_wrapper as close
|
||||||
|
newtype
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | A pointer to the Keystone engine.
|
||||||
|
{# pointer *ks_engine as EnginePtr -> Engine #}
|
||||||
|
|
||||||
|
-- | Make a new Keystone engine out of an engine pointer. The returned Keystone
|
||||||
|
-- engine will automatically call 'ks_close_wrapper' when it goes out of scope.
|
||||||
|
mkEngine :: EnginePtr
|
||||||
|
-> IO Engine
|
||||||
|
mkEngine ptr =
|
||||||
|
liftM Engine (newForeignPtr close ptr)
|
||||||
|
|
||||||
|
-- | Errors encountered by the Keystone API. These values are returned by
|
||||||
|
-- 'errno'.
|
||||||
|
{# enum ks_err as Error
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | The assembler runs in the IO monad and allows for the handling of errors
|
||||||
|
-- "under the hood".
|
||||||
|
type Assembler a = EitherT Error IO a
|
@ -0,0 +1,135 @@
|
|||||||
|
{-# LANGUAGE ForeignFunctionInterface #-}
|
||||||
|
|
||||||
|
{-|
|
||||||
|
Module : Keystone.Internal.Keystone
|
||||||
|
Description : The Keystone assembler engine.
|
||||||
|
Copyright : (c) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
|
||||||
|
Low-level bindings for the Keystone assembler engine.
|
||||||
|
|
||||||
|
This module should not be directly imported; it is only exposed because of the
|
||||||
|
way cabal handles ordering of chs files.
|
||||||
|
-}
|
||||||
|
module Keystone.Internal.Keystone
|
||||||
|
( -- * Types
|
||||||
|
Architecture(..)
|
||||||
|
, Mode(..)
|
||||||
|
, OptionType(..)
|
||||||
|
, OptionValue(..)
|
||||||
|
|
||||||
|
-- * Function bindings
|
||||||
|
, ksOpen
|
||||||
|
, ksOption
|
||||||
|
, ksFree
|
||||||
|
, ksAsm
|
||||||
|
, ksVersion
|
||||||
|
, ksErrno
|
||||||
|
, ksStrerror
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Foreign
|
||||||
|
import Foreign.C
|
||||||
|
|
||||||
|
import Keystone.Internal.Util
|
||||||
|
|
||||||
|
{# import Keystone.Internal.Core #}
|
||||||
|
|
||||||
|
{# context lib = "keystone" #}
|
||||||
|
|
||||||
|
#include <keystone/keystone.h>
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Types
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | CPU architecture.
|
||||||
|
{# enum ks_arch as Architecture
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | CPU hardware mode.
|
||||||
|
{# enum ks_mode as Mode
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | Runtime option types.
|
||||||
|
{# enum ks_opt_type as OptionType
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-- | Runtime option values.
|
||||||
|
{# enum ks_opt_value as OptionValue
|
||||||
|
{ underscoreToCase }
|
||||||
|
with prefix = "KS_OPT_"
|
||||||
|
deriving (Show, Eq, Bounded)
|
||||||
|
#}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Assembler control
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{# fun ks_open as ^
|
||||||
|
{ `Architecture'
|
||||||
|
, combineEnums `[Mode]'
|
||||||
|
, alloca- `EnginePtr' peek*
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun ks_option as ^
|
||||||
|
{ `Engine'
|
||||||
|
, `OptionType'
|
||||||
|
, `OptionValue'
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun ks_asm as ^
|
||||||
|
{ `Engine'
|
||||||
|
, `String'
|
||||||
|
, `Word64'
|
||||||
|
, alloca- `Ptr CUChar' peek*
|
||||||
|
, alloca- `Int' peekToInt*
|
||||||
|
, alloca- `Int' peekToInt*
|
||||||
|
} -> `Int'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun ks_free as ^
|
||||||
|
{ castPtr `Ptr CUChar'
|
||||||
|
} -> `()'
|
||||||
|
#}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Misc.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{# fun pure unsafe ks_version as ^
|
||||||
|
{ id `Ptr CUInt'
|
||||||
|
, id `Ptr CUInt'
|
||||||
|
} -> `Int'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun unsafe ks_errno as ^
|
||||||
|
{ `Engine'
|
||||||
|
} -> `Error'
|
||||||
|
#}
|
||||||
|
|
||||||
|
{# fun pure unsafe ks_strerror as ^
|
||||||
|
{ `Error'
|
||||||
|
} -> `String'
|
||||||
|
#}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- Helper functions
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
peekToInt :: (Storable a, Integral a, Num b)
|
||||||
|
=> Ptr a
|
||||||
|
-> IO b
|
||||||
|
peekToInt ptr =
|
||||||
|
peek ptr >>= (return . fromIntegral)
|
@ -0,0 +1,23 @@
|
|||||||
|
{-|
|
||||||
|
Module : Keystone.Internal.Util
|
||||||
|
Description : Utility (aka helper) functions for the Keystone assembler.
|
||||||
|
Copyright : (c) Adrian Herrera, 2016
|
||||||
|
License : GPL-2
|
||||||
|
-}
|
||||||
|
module Keystone.Internal.Util where
|
||||||
|
|
||||||
|
import Data.Bits
|
||||||
|
|
||||||
|
-- | Combine a list of Enums by performing a bitwise-OR.
|
||||||
|
combineEnums :: (Enum a, Num b, Bits b)
|
||||||
|
=> [a]
|
||||||
|
-> b
|
||||||
|
combineEnums =
|
||||||
|
foldr ((.|.) <$> enumToNum) 0
|
||||||
|
|
||||||
|
-- | Convert an 'Eum' to a 'Num'.
|
||||||
|
enumToNum :: (Enum a, Num b)
|
||||||
|
=> a
|
||||||
|
-> b
|
||||||
|
enumToNum =
|
||||||
|
fromIntegral . fromEnum
|
@ -0,0 +1,5 @@
|
|||||||
|
#include "keystone_wrapper.h"
|
||||||
|
|
||||||
|
void ks_close_wrapper(ks_engine *ks) {
|
||||||
|
ks_close(ks);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef KEYSTONE_WRAPPER_H
|
||||||
|
#define KEYSTONE_WRAPPER_H
|
||||||
|
|
||||||
|
#include <keystone/keystone.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrap Keystone's ks_close function and ignore the returned error code.
|
||||||
|
*/
|
||||||
|
void ks_close_wrapper(ks_engine *ks);
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,3 @@
|
|||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
target/
|
@ -0,0 +1,5 @@
|
|||||||
|
# Changelog of the Java bindings for Keystone
|
||||||
|
|
||||||
|
**Version 0.9.1-0: July 16th, 2018**:
|
||||||
|
|
||||||
|
- Initial public release.
|
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018 Jämes Ménétrey (aka ZenLulz) <james@menetrey.me>
|
||||||
|
|
||||||
|
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.
|
@ -0,0 +1,100 @@
|
|||||||
|
# Java bindings for Keystone
|
||||||
|
|
||||||
|
Java bindings for the [Keystone](http://www.keystone-engine.org/) engine. Require JDK 10+.
|
||||||
|
|
||||||
|
## Sample
|
||||||
|
|
||||||
|
```java
|
||||||
|
import keystone.Keystone;
|
||||||
|
import keystone.KeystoneArchitecture;
|
||||||
|
import keystone.KeystoneMode;
|
||||||
|
import keystone.exceptions.AssembleFailedKeystoneException;
|
||||||
|
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try (Keystone keystone = new Keystone(KeystoneArchitecture.X86, KeystoneMode.Mode32)) {
|
||||||
|
try {
|
||||||
|
var result = keystone.assemble("INC ecx; DEC edx");
|
||||||
|
|
||||||
|
System.out.println("Number of statements encoded: " + result.getNumberOfStatements());
|
||||||
|
System.out.println("Base address: " + String.format("0x%08X", result.getAddress()));
|
||||||
|
System.out.print("Encoded bytes: ");
|
||||||
|
|
||||||
|
for (byte b: result.getMachineCode()) {
|
||||||
|
System.out.print(String.format("%X ", b));
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (AssembleFailedKeystoneException e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Output:
|
||||||
|
|
||||||
|
> Number of statements encoded: 2
|
||||||
|
Base address: 0x00000000
|
||||||
|
Encoded bytes: 41 4A
|
||||||
|
|
||||||
|
Other samples are provided by the unit tests included with the library, which cover most of the code.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Clone the repository locally.
|
||||||
|
2. Download or compile Keystone library and store it in the folder `src/main/resources/{os-prefix}/{keystone-lib}`, according [the specifications of JNA](https://java-native-access.github.io/jna/4.5.0/javadoc/index.html?com/sun/jna/NativeLibrary.html), or [the related unit test](https://github.com/java-native-access/jna/blob/7122be473e5f6179deb1c2b1c2fdeb77d8486fed/test/com/sun/jna/PlatformTest.java#L29).
|
||||||
|
3. Compile the Java bindings and issue the JAR using Maven `mvn package`. The unit tests are automatically while running the goal.
|
||||||
|
4. In your project, include `target/binding-java-{version}.jar` and [JNA](https://github.com/java-native-access/jna) using your favourite dependency manager, or include `target/binding-java-{version}-jar-with-dependencies.jar` that is packaged with JNA.
|
||||||
|
|
||||||
|
### Exception handling
|
||||||
|
|
||||||
|
Each operation that returns the native enumeration `ks_err` is wrapped in an instance of a subclass of `KeystoneException`, thrown when an error occurs. The Javadoc indicates the exceptions thrown by the Java bindings for Keystone.
|
||||||
|
|
||||||
|
### Garbage collection
|
||||||
|
|
||||||
|
Keystone library requires to open and close an handle, that must be collected once an instance of the class `Keystone` is disposed. For that purpose, the class implements the interface `AutoCloseable`. Nonetheless, the Java bindings also implement a cleaning mechanism that automatically collects the handle when the instance of the class is *phantom reachable*, meaning no memory leak can happen, even if the instance is not closed properly.
|
||||||
|
|
||||||
|
|
||||||
|
### Native function calls
|
||||||
|
|
||||||
|
The Java bindings for Keystone rely on [JNA Direct Mapping](https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md) to improve the performances of native calls, approaching that of custom JNI.
|
||||||
|
|
||||||
|
## Found an issue or bug ?
|
||||||
|
|
||||||
|
Feel free to open a GitHub issue on [the official repository of Keystone](https://github.com/keystone-engine/keystone/issues) and ping the contributors.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
Author: Jämes Ménétrey ([@ZenLulz](https://github.com/ZenLulz/))
|
||||||
|
|
||||||
|
Maintainers:
|
||||||
|
|
||||||
|
- Need some people here :) Feel free to contribute !
|
||||||
|
|
||||||
|
### Want to contribute ?
|
||||||
|
|
||||||
|
Hey you! Your help is more than welcome! Things to keep in mind when working on the Java bindings for Keystone:
|
||||||
|
|
||||||
|
- Think about the backward compatibility; while code refactoring is a good practice, changing entirely the API *may* result in struggles.
|
||||||
|
- Elaborate the unit tests that prove your code is working. Test all the paths of the newly-added functions/classes (IntelliJ can show some metrics using Coverage). Keep the code coverage high!
|
||||||
|
- Please; write the required Javadoc, so every developer has the chance to understand your code.
|
||||||
|
- Update the changelog with a summary of your changes.
|
||||||
|
|
||||||
|
#### Version notation
|
||||||
|
|
||||||
|
The version of the Java bindings for Keystone is indicated in the file Maven configuration file (`pom.xml`). The major, minor and incremental versions (w.x.y) match the version of the library Keystone that the bindings is developed with. The build number (the -z in w.x.y-z) is incremented for each newer version of the Java bindings. Please, don't forget to increment this version when you submit a pull request.
|
||||||
|
|
||||||
|
On the last commit for a pull request, please create a tag called `java-bindings-w.x.y-z`.
|
||||||
|
|
||||||
|
#### Pull request submission
|
||||||
|
|
||||||
|
Ping the contributors of the Java bindings when submitting a pull request, so your changes can be peer reviewed.
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
The Java bindings for Keystone is open-sourced software licensed under the MIT license.
|
||||||
|
The license of the library Keystone may be different and is available [at the root of the repository of Keystone](https://github.com/keystone-engine/keystone).
|
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
~
|
||||||
|
~ This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
~ See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>keystone</groupId>
|
||||||
|
<artifactId>java-bindings</artifactId>
|
||||||
|
<version>0.9.1-0</version>
|
||||||
|
|
||||||
|
<name>Keystone Java bindings</name>
|
||||||
|
<description>Keystone assembler framework: Core (Arm, Arm64, Hexagon, Mips, PowerPC, Sparc, SystemZ and X86) orm.</description>
|
||||||
|
<url>https://github.com/keystone-engine/keystone/tree/master/bindings/java</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
||||||
|
<java.version>10</java.version>
|
||||||
|
<jna.version>4.5.1</jna.version>
|
||||||
|
<junit.jupiter.version>5.2.0</junit.jupiter.version>
|
||||||
|
<junit.platform.version>1.2.0</junit.platform.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<email>james@menetrey.me</email>
|
||||||
|
<name>Jämes Ménétrey</name>
|
||||||
|
<url>https://github.com/ZenLulz</url>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.dev.jna</groupId>
|
||||||
|
<artifactId>jna-platform</artifactId>
|
||||||
|
<version>${jna.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Dependencies for testing. -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Configure Maven to compile using Java 10. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.7.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>${java.version}</source>
|
||||||
|
<target>${java.version}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Package the project into a JAR with dependencies. -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<configuration>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>assemble-all</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Unit tests are runnable using maven. -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.21.0</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.ptr.IntByReference;
|
||||||
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
import keystone.exceptions.AssembleFailedKeystoneException;
|
||||||
|
import keystone.exceptions.OpenFailedKeystoneException;
|
||||||
|
import keystone.exceptions.SetOptionFailedKeystoneException;
|
||||||
|
import keystone.natives.CleanerContainer;
|
||||||
|
import keystone.natives.DirectMappingKeystoneNative;
|
||||||
|
import keystone.natives.KeystoneCleanerContainer;
|
||||||
|
import keystone.utilities.Version;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Keystone engine.
|
||||||
|
*/
|
||||||
|
public class Keystone implements AutoCloseable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pointer to the Keystone native resource.
|
||||||
|
*/
|
||||||
|
private final Pointer ksEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cleaner container that frees up the native resource if this object is not properly closed and is
|
||||||
|
* candidate for garbage collection.
|
||||||
|
*/
|
||||||
|
private final CleanerContainer ksEngineCleaner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the current instance of Keystone has been closed.
|
||||||
|
*/
|
||||||
|
private final AtomicBoolean hasBeenClosed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The memory retention of the symbol resolver callback, in order to prevent the garbage collector
|
||||||
|
* to free up the callback, that would result in a crash, as the native library still has a reference to it.
|
||||||
|
*/
|
||||||
|
private SymbolResolverCallback symbolResolverCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of the class {@link Keystone}.
|
||||||
|
* <p>
|
||||||
|
* Some architectures are not supported. Use the static method {@link #isArchitectureSupported} to determine
|
||||||
|
* whether the engine support the architecture.
|
||||||
|
*
|
||||||
|
* @param architecture The architecture of the code generated by Keystone.
|
||||||
|
* @param mode The mode type.
|
||||||
|
* @throws OpenFailedKeystoneException if the Keystone library cannot be opened properly.
|
||||||
|
*/
|
||||||
|
public Keystone(KeystoneArchitecture architecture, KeystoneMode mode) {
|
||||||
|
ksEngine = initializeKeystoneEngine(architecture, mode);
|
||||||
|
ksEngineCleaner = initializeKeystoneCleanerContainer();
|
||||||
|
hasBeenClosed = new AtomicBoolean(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether the given architecture is supported by Keystone.
|
||||||
|
*
|
||||||
|
* @param architecture The architecture type to check.
|
||||||
|
* @return The return value is {@code true} if the architecture is supported, otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
public static boolean isArchitectureSupported(KeystoneArchitecture architecture) {
|
||||||
|
return DirectMappingKeystoneNative.ks_arch_supported(architecture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens an handle of Keystone.
|
||||||
|
*
|
||||||
|
* @param architecture The architecture of the code generated by Keystone.
|
||||||
|
* @param mode The mode type.
|
||||||
|
* @return The return value is a pointer to the handle of Keystone.
|
||||||
|
* @throws OpenFailedKeystoneException if the Keystone library cannot be opened properly.
|
||||||
|
*/
|
||||||
|
private Pointer initializeKeystoneEngine(KeystoneArchitecture architecture, KeystoneMode mode) {
|
||||||
|
var pointerToEngine = new PointerByReference();
|
||||||
|
var openResult = DirectMappingKeystoneNative.ks_open(architecture, mode, pointerToEngine);
|
||||||
|
|
||||||
|
if (openResult != KeystoneError.Ok) {
|
||||||
|
throw new OpenFailedKeystoneException(openResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointerToEngine.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the cleaner object, that is going to close the native handle of Keystone if
|
||||||
|
* the instance is garbage collected.
|
||||||
|
*
|
||||||
|
* @return The return value is a cleaner container.
|
||||||
|
*/
|
||||||
|
private CleanerContainer initializeKeystoneCleanerContainer() {
|
||||||
|
return new KeystoneCleanerContainer(ksEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles a string that contains assembly code.
|
||||||
|
*
|
||||||
|
* @param assembly The assembly instructions. Use ; or \n to separate statements.
|
||||||
|
* @return The return value is the machine code of the assembly instructions.
|
||||||
|
* @throws AssembleFailedKeystoneException if the assembly code cannot be assembled properly.
|
||||||
|
*/
|
||||||
|
public KeystoneEncoded assemble(String assembly) {
|
||||||
|
return assemble(assembly, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles a string that contains assembly code, located at a given address location.
|
||||||
|
*
|
||||||
|
* @param assembly The assembly instructions. Use ; or \n to separate statements.
|
||||||
|
* @param address The address of the first assembly instruction.
|
||||||
|
* @return The return value is the machine code of the assembly instructions.
|
||||||
|
* @throws AssembleFailedKeystoneException if the assembly code cannot be assembled properly.
|
||||||
|
*/
|
||||||
|
public KeystoneEncoded assemble(String assembly, int address) {
|
||||||
|
var pointerToMachineCodeBuffer = new PointerByReference();
|
||||||
|
var pointerToMachineCodeSize = new IntByReference();
|
||||||
|
var pointerToNumberOfStatements = new IntByReference();
|
||||||
|
|
||||||
|
var result = DirectMappingKeystoneNative.ks_asm(ksEngine, assembly, address, pointerToMachineCodeBuffer,
|
||||||
|
pointerToMachineCodeSize, pointerToNumberOfStatements);
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
var errorCode = DirectMappingKeystoneNative.ks_errno(ksEngine);
|
||||||
|
throw new AssembleFailedKeystoneException(errorCode, assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
var machineCodeBuffer = pointerToMachineCodeBuffer.getValue();
|
||||||
|
var machineCode = machineCodeBuffer.getByteArray(0, pointerToMachineCodeSize.getValue());
|
||||||
|
|
||||||
|
DirectMappingKeystoneNative.ks_free(machineCodeBuffer);
|
||||||
|
|
||||||
|
return new KeystoneEncoded(machineCode, address, pointerToNumberOfStatements.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles a string that contains assembly code.
|
||||||
|
*
|
||||||
|
* @param assembly A collection of assembly instructions.
|
||||||
|
* @return The return value is the machine code of the assembly instructions.
|
||||||
|
* @throws AssembleFailedKeystoneException if the assembly code cannot be assembled properly.
|
||||||
|
*/
|
||||||
|
public KeystoneEncoded assemble(Iterable<String> assembly) {
|
||||||
|
return assemble(assembly, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assembles a string that contains assembly code, located at a given address location.
|
||||||
|
*
|
||||||
|
* @param assembly A collection of assembly instructions.
|
||||||
|
* @param address The address of the first assembly instruction.
|
||||||
|
* @return The return value is the machine code of the assembly instructions.
|
||||||
|
* @throws AssembleFailedKeystoneException if the assembly code cannot be assembled properly.
|
||||||
|
*/
|
||||||
|
public KeystoneEncoded assemble(Iterable<String> assembly, int address) {
|
||||||
|
return assemble(String.join(";", assembly), address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the major and minor version numbers.
|
||||||
|
*
|
||||||
|
* @return The returned value is an instance of the class {@link Version}, containing the major and minor version numbers.
|
||||||
|
*/
|
||||||
|
public Version version() {
|
||||||
|
var major = new IntByReference();
|
||||||
|
var minor = new IntByReference();
|
||||||
|
|
||||||
|
DirectMappingKeystoneNative.ks_version(major, minor);
|
||||||
|
|
||||||
|
return new Version(major.getValue(), minor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the syntax of the assembly code used in this instance of Keystone.
|
||||||
|
*
|
||||||
|
* @param syntax The syntax of the assembly code.
|
||||||
|
* @throws SetOptionFailedKeystoneException if the syntax is not supported.
|
||||||
|
* @throws SetOptionFailedKeystoneException if the pair of type and value is not valid.
|
||||||
|
*/
|
||||||
|
public void setAssemblySyntax(KeystoneOptionValue.KeystoneOptionSyntax syntax) {
|
||||||
|
setOption(KeystoneOptionType.Syntax, syntax.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an option for Keystone engine at runtime using a not-strongly typed option value.
|
||||||
|
* <p>
|
||||||
|
* It is suggested to prefer the methods {@link #setAssemblySyntax(KeystoneOptionValue.KeystoneOptionSyntax)},
|
||||||
|
* {@link #setSymbolResolver(SymbolResolverCallback)} or {@link #unsetSymbolResolver()}.
|
||||||
|
*
|
||||||
|
* @param type The type of the option.
|
||||||
|
* @param value The value of the option.
|
||||||
|
* @throws SetOptionFailedKeystoneException if the pair of type and value is not valid.
|
||||||
|
*/
|
||||||
|
public void setOption(KeystoneOptionType type, int value) {
|
||||||
|
var result = DirectMappingKeystoneNative.ks_option(ksEngine, type, value);
|
||||||
|
|
||||||
|
if (result != KeystoneError.Ok) {
|
||||||
|
throw new SetOptionFailedKeystoneException(result, type, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a symbol resolver callback, to resolve unrecognized symbols encountered in the assembly code.
|
||||||
|
* <p>
|
||||||
|
* If the method is called many times, only the last callback will be triggered.
|
||||||
|
*
|
||||||
|
* @param callback The symbol resolver callback.
|
||||||
|
* @throws SetOptionFailedKeystoneException if the pair of type and value is not valid.
|
||||||
|
*/
|
||||||
|
public void setSymbolResolver(SymbolResolverCallback callback) {
|
||||||
|
symbolResolverCallback = callback;
|
||||||
|
DirectMappingKeystoneNative.ks_option(ksEngine, KeystoneOptionType.SymbolResolver, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsets the current symbol resolver. The symbol resolver instance can be freely collected afterwards.
|
||||||
|
*
|
||||||
|
* @throws SetOptionFailedKeystoneException if the pair of type and value is not valid.
|
||||||
|
*/
|
||||||
|
public void unsetSymbolResolver() {
|
||||||
|
DirectMappingKeystoneNative.ks_option(ksEngine, KeystoneOptionType.SymbolResolver, 0);
|
||||||
|
symbolResolverCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this resource, relinquishing any underlying resources.
|
||||||
|
* This method is invoked automatically on objects managed by the
|
||||||
|
* {@code try}-with-resources statement.
|
||||||
|
* <p>
|
||||||
|
* The call to this method is thread-safe.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
var hasBeenAlreadyClosed = hasBeenClosed.getAndSet(true);
|
||||||
|
|
||||||
|
if (!hasBeenAlreadyClosed) {
|
||||||
|
ksEngineCleaner.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import keystone.jna.JnaEnum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported architectures of Keystone.
|
||||||
|
*/
|
||||||
|
public enum KeystoneArchitecture implements JnaEnum {
|
||||||
|
/**
|
||||||
|
* ARM architecture (including Thumb, Thumb-2).
|
||||||
|
*/
|
||||||
|
Arm(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARM-64, also called AArch64.
|
||||||
|
*/
|
||||||
|
Arm64(2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mips architecture.
|
||||||
|
*/
|
||||||
|
Mips(3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X86 architecture (including x86 & x86-64).
|
||||||
|
*/
|
||||||
|
X86(4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PowerPC architecture (currently unsupported).
|
||||||
|
*/
|
||||||
|
Ppc(5),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sparc architecture.
|
||||||
|
*/
|
||||||
|
Sparc(6),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SystemZ architecture (S390X).
|
||||||
|
*/
|
||||||
|
SystemZ(7),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hexagon architecture
|
||||||
|
*/
|
||||||
|
Hexagon(8),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ethereum Virtual Machine architecture.
|
||||||
|
*/
|
||||||
|
Evm(9),
|
||||||
|
|
||||||
|
Max(10);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping table to determine an enumeration value based on an integer with a complexity of θ(1).
|
||||||
|
*/
|
||||||
|
private static Map<Integer, KeystoneArchitecture> intToEnumMapping = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the mapping table.
|
||||||
|
for (KeystoneArchitecture architecture : KeystoneArchitecture.values()) {
|
||||||
|
intToEnumMapping.put(architecture.value(), architecture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the integer value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the enumeration.
|
||||||
|
*
|
||||||
|
* @param value The integer value, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
KeystoneArchitecture(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer value into its corresponding enumeration value.
|
||||||
|
* <p>
|
||||||
|
* The complexity of the conversion is θ(1).
|
||||||
|
*
|
||||||
|
* @param value The integer value.
|
||||||
|
* @return The return value is a value of the enumeration.
|
||||||
|
*/
|
||||||
|
public static KeystoneArchitecture fromValue(Integer value) {
|
||||||
|
return intToEnumMapping.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer value.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the result of an assemble using Keystone.
|
||||||
|
*/
|
||||||
|
public class KeystoneEncoded {
|
||||||
|
/**
|
||||||
|
* The machine code generated by Keystone.
|
||||||
|
*/
|
||||||
|
private final byte[] machineCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The address of the first assembly instruction.
|
||||||
|
*/
|
||||||
|
private final int address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of statements successfully processed.
|
||||||
|
*/
|
||||||
|
private final int numberOfStatements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of the class {@link KeystoneEncoded}.
|
||||||
|
*
|
||||||
|
* @param machineCode The machine code generated by Keystone.
|
||||||
|
* @param address The address of the first assembly instruction.
|
||||||
|
* @param numberOfStatements The number of statements successfully processed.
|
||||||
|
*/
|
||||||
|
public KeystoneEncoded(byte[] machineCode, int address, int numberOfStatements) {
|
||||||
|
this.machineCode = machineCode;
|
||||||
|
this.address = address;
|
||||||
|
this.numberOfStatements = numberOfStatements;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the machine code generated by Keystone.
|
||||||
|
*/
|
||||||
|
public byte[] getMachineCode() {
|
||||||
|
return machineCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the address of the first assembly instruction.
|
||||||
|
*/
|
||||||
|
public int getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of statements successfully processed.
|
||||||
|
*/
|
||||||
|
public int getNumberOfStatements() {
|
||||||
|
return numberOfStatements;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import keystone.jna.JnaEnum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All type of errors encountered by Keystone API.
|
||||||
|
*/
|
||||||
|
public enum KeystoneError implements JnaEnum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No error: everything was fine.
|
||||||
|
*/
|
||||||
|
Ok(0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Out-Of-Memory error: ks_open(), ks_emulate().
|
||||||
|
*/
|
||||||
|
Nomem(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported architecture: ks_open().
|
||||||
|
*/
|
||||||
|
Arch(2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid handle.
|
||||||
|
*/
|
||||||
|
Handle(3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid/unsupported mode: ks_open().
|
||||||
|
*/
|
||||||
|
Mode(4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported version (bindings).
|
||||||
|
*/
|
||||||
|
Version(5),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported option.
|
||||||
|
*/
|
||||||
|
OptInvalid(6),
|
||||||
|
|
||||||
|
// generic input assembly errors - parser specific
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unknown token in expression.
|
||||||
|
*/
|
||||||
|
AsmExprToken(Base.asm),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Literal value out of range for directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveValueRange(Base.asm + 1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected identifier in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveId(Base.asm + 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected token in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveToken(Base.asm + 3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected string in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveStr(Base.asm + 4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected comma in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveComma(Base.asm + 5),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected relocation name in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveRelocName(Base.asm + 6),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected token in .reloc directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveRelocToken(Base.asm + 7),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid floating point in directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveFpoint(Base.asm + 8),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unknown directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveUnknown(Base.asm + 9),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid equal directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveEqu(Base.asm + 10),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Generic) invalid directive.
|
||||||
|
*/
|
||||||
|
AsmDirectiveInvalid(Base.asm + 11),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid variant.
|
||||||
|
*/
|
||||||
|
AsmVariantInvalid(Base.asm + 12),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Brackets expression not supported on this target.
|
||||||
|
*/
|
||||||
|
AsmExprBracket(Base.asm + 13),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected symbol modifier following '@'.
|
||||||
|
*/
|
||||||
|
AsmSymbolModifier(Base.asm + 14),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid symbol redefinition.
|
||||||
|
*/
|
||||||
|
AsmSymbolRedefined(Base.asm + 15),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cannot find a symbol.
|
||||||
|
*/
|
||||||
|
AsmSymbolMissing(Base.asm + 16),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected ')' in parentheses expression.
|
||||||
|
*/
|
||||||
|
AsmRparen(Base.asm + 17),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected token at start of statement.
|
||||||
|
*/
|
||||||
|
AsmStatToken(Base.asm + 18),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsupported token yet.
|
||||||
|
*/
|
||||||
|
AsmUnsupported(Base.asm + 19),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected token in macro instantiation.
|
||||||
|
*/
|
||||||
|
AsmMacroToken(Base.asm + 20),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbalanced parentheses in macro argument.
|
||||||
|
*/
|
||||||
|
AsmMacroParen(Base.asm + 21),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expected '=' after formal parameter identifier.
|
||||||
|
*/
|
||||||
|
AsmMacroEqu(Base.asm + 22),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Too many positional arguments.
|
||||||
|
*/
|
||||||
|
AsmMacroArgs(Base.asm + 23),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macros cannot be nested more than 20 levels deep.
|
||||||
|
*/
|
||||||
|
AsmMacroLevelsExceed(Base.asm + 24),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid macro string.
|
||||||
|
*/
|
||||||
|
AsmMacroStr(Base.asm + 25),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid macro (generic error).
|
||||||
|
*/
|
||||||
|
AsmMacroInvalid(Base.asm + 26),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unexpected backslash at end of escaped string.
|
||||||
|
*/
|
||||||
|
AsmEscBackslash(Base.asm + 27),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid octal escape sequence (out of range).
|
||||||
|
*/
|
||||||
|
AsmEscOctal(Base.asm + 28),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid escape sequence (unrecognized character).
|
||||||
|
*/
|
||||||
|
AsmEscSequence(Base.asm + 29),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broken escape string.
|
||||||
|
*/
|
||||||
|
AsmEscStr(Base.asm + 30),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid token.
|
||||||
|
*/
|
||||||
|
AsmTokenInvalid(Base.asm + 31),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This instruction is unsupported in this mode.
|
||||||
|
*/
|
||||||
|
AsmInsnUnsupported(Base.asm + 32),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid fixup.
|
||||||
|
*/
|
||||||
|
AsmFixupInvalid(Base.asm + 33),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid label.
|
||||||
|
*/
|
||||||
|
AsmLabelInvalid(Base.asm + 34),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalid fragment.
|
||||||
|
*/
|
||||||
|
AsmFragmentInvalid(Base.asm + 35),
|
||||||
|
|
||||||
|
// generic input assembly errors - architecture specific
|
||||||
|
|
||||||
|
AsmInvalidOperand(Base.asmArch),
|
||||||
|
AsmMissingFeature(Base.asmArch + 1),
|
||||||
|
AsmMnemonicFail(Base.asmArch + 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping table to determine an enumeration value based on an integer with a complexity of θ(1).
|
||||||
|
*/
|
||||||
|
private static Map<Integer, KeystoneError> intToEnumMapping = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the mapping table.
|
||||||
|
for (KeystoneError error : KeystoneError.values()) {
|
||||||
|
intToEnumMapping.put(error.value(), error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the integer value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the enumeration.
|
||||||
|
*
|
||||||
|
* @param value The integer value, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
KeystoneError(int value) {
|
||||||
|
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer value into its corresponding enumeration value.
|
||||||
|
* <p>
|
||||||
|
* The complexity of the conversion is θ(1).
|
||||||
|
*
|
||||||
|
* @param value The integer value.
|
||||||
|
* @return The return value is a value of the enumeration.
|
||||||
|
*/
|
||||||
|
public static KeystoneError fromValue(Integer value) {
|
||||||
|
return intToEnumMapping.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer value.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal interface referencing the base error codes.
|
||||||
|
*/
|
||||||
|
interface Base {
|
||||||
|
int asm = 128;
|
||||||
|
int asmArch = 512;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import keystone.jna.JnaEnum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported mode type by Keystone.
|
||||||
|
*/
|
||||||
|
public enum KeystoneMode implements JnaEnum {
|
||||||
|
/**
|
||||||
|
* Little-endian mode (default mode).
|
||||||
|
*/
|
||||||
|
LittleEndian(0),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Big-endian mode.
|
||||||
|
*/
|
||||||
|
BigEndian(1 << 30),
|
||||||
|
|
||||||
|
// arm / arm64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARM mode.
|
||||||
|
*/
|
||||||
|
Arm(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* THUMB mode (including Thumb-2).
|
||||||
|
*/
|
||||||
|
ArmThumb(1 << 4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ARMv8 A32 encodings for ARM.
|
||||||
|
*/
|
||||||
|
ArmV8(1 << 6),
|
||||||
|
|
||||||
|
// mips
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MicroMips mode.
|
||||||
|
*/
|
||||||
|
MipsMicro(1 << 4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mips III ISA.
|
||||||
|
*/
|
||||||
|
Mips3(1 << 5),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mips32r6 ISA.
|
||||||
|
*/
|
||||||
|
Mips32r6(1 << 6),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mips32 ISA.
|
||||||
|
*/
|
||||||
|
Mips32(1 << 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mips64 ISA.
|
||||||
|
*/
|
||||||
|
Mips64(1 << 3),
|
||||||
|
|
||||||
|
// x86 / x64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16-bit mode.
|
||||||
|
*/
|
||||||
|
Mode16(1 << 1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 32-bit mode.
|
||||||
|
*/
|
||||||
|
Mode32(1 << 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 64-bit mode.
|
||||||
|
*/
|
||||||
|
Mode64(1 << 3),
|
||||||
|
|
||||||
|
// ppc
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 32-bit mode.
|
||||||
|
*/
|
||||||
|
Ppc32(1 << 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 64-bit mode.
|
||||||
|
*/
|
||||||
|
Ppc64(1 << 3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quad Processing eXtensions mode.
|
||||||
|
*/
|
||||||
|
PpcQpx(1 << 4),
|
||||||
|
|
||||||
|
// sparc
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 32-bit mode.
|
||||||
|
*/
|
||||||
|
Sparc32(1 << 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 64-bit mode.
|
||||||
|
*/
|
||||||
|
Sparc64(1 << 3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SparcV9 mode.
|
||||||
|
*/
|
||||||
|
SparcV9(1 << 4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping table to determine an enumeration value based on an integer with a complexity of θ(1).
|
||||||
|
*/
|
||||||
|
private static Map<Integer, KeystoneMode> intToEnumMapping = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the mapping table.
|
||||||
|
for (KeystoneMode mode : KeystoneMode.values()) {
|
||||||
|
intToEnumMapping.put(mode.value(), mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the integer value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the enumeration.
|
||||||
|
*
|
||||||
|
* @param value The integer value, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
KeystoneMode(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer value into its corresponding enumeration value.
|
||||||
|
* <p>
|
||||||
|
* The complexity of the conversion is θ(1).
|
||||||
|
*
|
||||||
|
* @param value The integer value.
|
||||||
|
* @return The return value is a value of the enumeration.
|
||||||
|
*/
|
||||||
|
public static KeystoneMode fromValue(Integer value) {
|
||||||
|
return intToEnumMapping.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer value.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import keystone.jna.JnaEnum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public enum KeystoneOptionType implements JnaEnum {
|
||||||
|
/**
|
||||||
|
* Choose syntax for input assembly.
|
||||||
|
*/
|
||||||
|
Syntax(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set symbol resolver callback.
|
||||||
|
*/
|
||||||
|
SymbolResolver(2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping table to determine an enumeration value based on an integer with a complexity of θ(1).
|
||||||
|
*/
|
||||||
|
private static Map<Integer, KeystoneOptionType> intToEnumMapping = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the mapping table.
|
||||||
|
for (KeystoneOptionType type : KeystoneOptionType.values()) {
|
||||||
|
intToEnumMapping.put(type.value(), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the integer value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the enumeration.
|
||||||
|
*
|
||||||
|
* @param value The integer value, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
KeystoneOptionType(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer value into its corresponding enumeration value.
|
||||||
|
* <p>
|
||||||
|
* The complexity of the conversion is θ(1).
|
||||||
|
*
|
||||||
|
* @param value The integer value.
|
||||||
|
* @return The return value is a value of the enumeration.
|
||||||
|
*/
|
||||||
|
public static KeystoneOptionType fromValue(Integer value) {
|
||||||
|
return intToEnumMapping.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer value.
|
||||||
|
*/
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import keystone.jna.JnaEnum;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime option values (associated with {@link KeystoneOptionType}).
|
||||||
|
*/
|
||||||
|
public class KeystoneOptionValue {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime option values associated with the assembly syntax.
|
||||||
|
*
|
||||||
|
* @see KeystoneOptionType#Syntax
|
||||||
|
*/
|
||||||
|
public enum KeystoneOptionSyntax implements JnaEnum {
|
||||||
|
/**
|
||||||
|
* X86 Intel syntax - default on X86 (KS_OPT_SYNTAX).
|
||||||
|
*/
|
||||||
|
Intel(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X86 ATT asm syntax (KS_OPT_SYNTAX).
|
||||||
|
*/
|
||||||
|
Att(1 << 1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X86 Nasm syntax (KS_OPT_SYNTAX).
|
||||||
|
*/
|
||||||
|
Nasm(1 << 2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X86 Masm syntax (KS_OPT_SYNTAX) - unsupported yet.
|
||||||
|
*/
|
||||||
|
Masm(1 << 3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X86 GNU GAS syntax (KS_OPT_SYNTAX).
|
||||||
|
*/
|
||||||
|
Gas(1 << 4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All immediates are in hex format (i.e 12 is 0x12).
|
||||||
|
*/
|
||||||
|
Radix16(1 << 5);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping table to determine an enumeration value based on an integer with a complexity of θ(1).
|
||||||
|
*/
|
||||||
|
private static Map<Integer, KeystoneOptionSyntax> intToEnumMapping = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// Initializes the mapping table.
|
||||||
|
for (KeystoneOptionSyntax syntax : KeystoneOptionSyntax.values()) {
|
||||||
|
intToEnumMapping.put(syntax.value(), syntax);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds the integer value of the enumeration, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor of the enumeration.
|
||||||
|
*
|
||||||
|
* @param value The integer value, that corresponds to the value used in the enumeration in C.
|
||||||
|
*/
|
||||||
|
KeystoneOptionSyntax(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an integer value into its corresponding enumeration value.
|
||||||
|
* <p>
|
||||||
|
* The complexity of the conversion is θ(1).
|
||||||
|
*
|
||||||
|
* @param value The integer value.
|
||||||
|
* @return The return value is a value of the enumeration.
|
||||||
|
*/
|
||||||
|
public static KeystoneOptionSyntax fromValue(Integer value) {
|
||||||
|
return intToEnumMapping.get(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value of an element in the enumeration.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer number, that represents the value in the native library.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone;
|
||||||
|
|
||||||
|
import com.sun.jna.Callback;
|
||||||
|
import com.sun.jna.ptr.LongByReference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that represents a callback to provide a value for a missing symbol.
|
||||||
|
*/
|
||||||
|
public interface SymbolResolverCallback extends Callback {
|
||||||
|
/**
|
||||||
|
* A callback triggered when a unrecognized symbol is found.
|
||||||
|
*
|
||||||
|
* @param symbol The symbol to resolve.
|
||||||
|
* @param value The value to modify if the symbol is resolved.
|
||||||
|
* @return The return value must be {@code true} if the symbol can be resolved; otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
boolean onResolve(String symbol, LongByReference value);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.exceptions;
|
||||||
|
|
||||||
|
import keystone.KeystoneError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception that represents a failure while assembling code.
|
||||||
|
*/
|
||||||
|
public class AssembleFailedKeystoneException extends KeystoneException {
|
||||||
|
/**
|
||||||
|
* The assembly code that generates the error.
|
||||||
|
*/
|
||||||
|
private final String assembly;
|
||||||
|
|
||||||
|
public AssembleFailedKeystoneException(KeystoneError keystoneError, String assembly) {
|
||||||
|
super(keystoneError, "Error while assembling `" + assembly + "`");
|
||||||
|
|
||||||
|
this.assembly = assembly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the assembly code that generates the error.
|
||||||
|
*/
|
||||||
|
public String getAssembly() {
|
||||||
|
return assembly;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.exceptions;
|
||||||
|
|
||||||
|
import keystone.KeystoneError;
|
||||||
|
import keystone.natives.DirectMappingKeystoneNative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base class for all the exceptions thrown by the library Keystone.
|
||||||
|
*/
|
||||||
|
public abstract class KeystoneException extends RuntimeException {
|
||||||
|
/**
|
||||||
|
* The error thrown by Keystone.
|
||||||
|
*/
|
||||||
|
private final KeystoneError keystoneError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance of {@link KeystoneException}.
|
||||||
|
*
|
||||||
|
* @param keystoneError The error code of Keystone.
|
||||||
|
* @param message A human-readable message of the error.
|
||||||
|
*/
|
||||||
|
KeystoneException(KeystoneError keystoneError, String message) {
|
||||||
|
super(message + " : " + DirectMappingKeystoneNative.ks_strerror(keystoneError));
|
||||||
|
|
||||||
|
this.keystoneError = keystoneError;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the error code of Keystone.
|
||||||
|
*/
|
||||||
|
public KeystoneError getKeystoneError() {
|
||||||
|
return keystoneError;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.exceptions;
|
||||||
|
|
||||||
|
import keystone.KeystoneError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception that represents a failure to open the library Keystone.
|
||||||
|
*/
|
||||||
|
public class OpenFailedKeystoneException extends KeystoneException {
|
||||||
|
public OpenFailedKeystoneException(KeystoneError keystoneError) {
|
||||||
|
super(keystoneError, "Keystone library could not be opened");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.exceptions;
|
||||||
|
|
||||||
|
import keystone.KeystoneError;
|
||||||
|
import keystone.KeystoneOptionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An exception that represents an error while setting an option in the Keystone library.
|
||||||
|
*/
|
||||||
|
public class SetOptionFailedKeystoneException extends KeystoneException {
|
||||||
|
/**
|
||||||
|
* The type of the option that generated the exception.
|
||||||
|
*/
|
||||||
|
private final KeystoneOptionType optionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value of the option that generated the exception.
|
||||||
|
*/
|
||||||
|
private final int optionValue;
|
||||||
|
|
||||||
|
public SetOptionFailedKeystoneException(KeystoneError keystoneError, KeystoneOptionType type, int value) {
|
||||||
|
super(keystoneError, createErrorMessage(type, value));
|
||||||
|
this.optionType = type;
|
||||||
|
this.optionValue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String createErrorMessage(KeystoneOptionType type, int value) {
|
||||||
|
return "Error while setting the option `" + type +
|
||||||
|
"` with the value `" + value + "`";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the type of the option that generated the exception.
|
||||||
|
*/
|
||||||
|
public KeystoneOptionType getOptionType() {
|
||||||
|
return optionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the option that generated the exception.
|
||||||
|
*/
|
||||||
|
public int getOptionValue() {
|
||||||
|
return optionValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.jna;
|
||||||
|
|
||||||
|
import com.sun.jna.DefaultTypeMapper;
|
||||||
|
import com.sun.jna.FromNativeContext;
|
||||||
|
import com.sun.jna.ToNativeContext;
|
||||||
|
import com.sun.jna.TypeConverter;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the default type mapper of JNA in order to provide custom bindings for enumerations.
|
||||||
|
*/
|
||||||
|
class EnumTypeMapper extends DefaultTypeMapper {
|
||||||
|
/**
|
||||||
|
* Add a {@link TypeConverter} to provide bidirectional mapping between
|
||||||
|
* a native and Java type.
|
||||||
|
*
|
||||||
|
* @param enumerationType The type of the enumeration to bind.
|
||||||
|
* @param fromNativeInteger A function that converts the native enumeration into the Java enumeration.
|
||||||
|
* @param <T> The type of the Java enumeration.
|
||||||
|
*/
|
||||||
|
<T extends JnaEnum> void addTypeConverter(Class<T> enumerationType, Function<Integer, T> fromNativeInteger) {
|
||||||
|
addTypeConverter(enumerationType, new TypeConverter() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the native enumeration into the Java enumeration.
|
||||||
|
*
|
||||||
|
* @param nativeValue The native element.
|
||||||
|
* @param context The context for converting a native value into a Java type.
|
||||||
|
* @return The return value is a Java enumeration.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object fromNative(Object nativeValue, FromNativeContext context) {
|
||||||
|
return fromNativeInteger.apply((int) nativeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the native type of the conversion. The enumeration are of type {@link Integer}.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Class<?> nativeType() {
|
||||||
|
return Integer.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Java enumeration into a native enumeration.
|
||||||
|
*
|
||||||
|
* @param value The Java element.
|
||||||
|
* @param context The context of converting a Java type into a native value.
|
||||||
|
* @return The return value is a native value from an enumeration.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object toNative(Object value, ToNativeContext context) {
|
||||||
|
return ((JnaEnum) value).value();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.jna;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A contract that represents an JNA enumeration.
|
||||||
|
*/
|
||||||
|
public interface JnaEnum {
|
||||||
|
/**
|
||||||
|
* Retrieves the value of an element in the enumeration.
|
||||||
|
*
|
||||||
|
* @return The return value is an integer number, that represents the value in the native library.
|
||||||
|
*/
|
||||||
|
int value();
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.jna;
|
||||||
|
|
||||||
|
import keystone.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the numeration type mapper in order to register the enumeration used by Keystone.
|
||||||
|
*/
|
||||||
|
public class KeystoneTypeMapper extends EnumTypeMapper {
|
||||||
|
public KeystoneTypeMapper() {
|
||||||
|
addTypeConverter(KeystoneError.class, KeystoneError::fromValue);
|
||||||
|
addTypeConverter(KeystoneArchitecture.class, KeystoneArchitecture::fromValue);
|
||||||
|
addTypeConverter(KeystoneMode.class, KeystoneMode::fromValue);
|
||||||
|
addTypeConverter(KeystoneOptionType.class, KeystoneOptionType::fromValue);
|
||||||
|
addTypeConverter(KeystoneOptionValue.KeystoneOptionSyntax.class, KeystoneOptionValue.KeystoneOptionSyntax::fromValue);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.natives;
|
||||||
|
|
||||||
|
import java.lang.ref.Cleaner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract class that automatically runs the action passed by argument in the constructor once
|
||||||
|
* phantom reachable, thanks to {@link Cleaner}.
|
||||||
|
*
|
||||||
|
* @see Cleaner
|
||||||
|
* @see <a href="https://www.linkedin.com/pulse/java-9-cleaner-illustration-good-encapsulation-pawel-wlodarski/">Java 9 Cleaner as an illustration of good encapsulation</a>
|
||||||
|
*/
|
||||||
|
public abstract class CleanerContainer implements AutoCloseable {
|
||||||
|
/**
|
||||||
|
* Creates a single instance of the cleaner for all the native resources.
|
||||||
|
*/
|
||||||
|
private static final Cleaner cleaner = Cleaner.create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instance of {@link java.lang.ref.Cleaner.Cleanable} that refers to the native resource.
|
||||||
|
*/
|
||||||
|
private final Cleaner.Cleanable cleanable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a cleaning action to run when the object becomes phantom reachable.
|
||||||
|
*
|
||||||
|
* @param action a {@code Runnable} to invoke when the object becomes phantom reachable.
|
||||||
|
*/
|
||||||
|
CleanerContainer(Runnable action) {
|
||||||
|
cleanable = cleaner.register(this, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes this resource, relinquishing any underlying resources.
|
||||||
|
* This method is invoked automatically on objects managed by the
|
||||||
|
* {@code try}-with-resources statement.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
cleanable.clean();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.natives;
|
||||||
|
|
||||||
|
import com.sun.jna.Library;
|
||||||
|
import com.sun.jna.Native;
|
||||||
|
import com.sun.jna.NativeLibrary;
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
import com.sun.jna.ptr.IntByReference;
|
||||||
|
import com.sun.jna.ptr.PointerByReference;
|
||||||
|
import keystone.*;
|
||||||
|
import keystone.jna.KeystoneTypeMapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class providing the native functions of Keystone using the Direct Mapping of JNA for best performance.
|
||||||
|
* <p>
|
||||||
|
* The original function prototypes are declared in the header file <i>keystone.h</i>.
|
||||||
|
*
|
||||||
|
* @see <a href="https://github.com/java-native-access/jna/blob/master/www/DirectMapping.md">JNA: Direct Mapping</a>
|
||||||
|
*/
|
||||||
|
public final class DirectMappingKeystoneNative {
|
||||||
|
|
||||||
|
static {
|
||||||
|
Map<String, Object> options = new HashMap<>();
|
||||||
|
options.put(Library.OPTION_TYPE_MAPPER, new KeystoneTypeMapper());
|
||||||
|
|
||||||
|
// Direct Mapping using JNA
|
||||||
|
Native.register(NativeLibrary.getInstance("keystone", options));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent any instantiation of the class.
|
||||||
|
*/
|
||||||
|
private DirectMappingKeystoneNative() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the given architecture is supported by this library.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>bool ks_arch_supported(ks_arch arch);</i>
|
||||||
|
*
|
||||||
|
* @param architecture architecture type
|
||||||
|
* @return {@code true} if this library supports the given arch.
|
||||||
|
*/
|
||||||
|
public static native boolean ks_arch_supported(KeystoneArchitecture architecture);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assemble a string given its the buffer, size, start address and number
|
||||||
|
* of instructions to be decoded.
|
||||||
|
* This API dynamically allocate memory to contain assembled instruction.
|
||||||
|
* Resulted array of bytes containing the machine code is put into @machineCode.
|
||||||
|
* <p>
|
||||||
|
* On failure, call {@link DirectMappingKeystoneNative#ks_errno} for error code.
|
||||||
|
* <p>
|
||||||
|
* NOTE 1: this API will automatically determine memory needed to contain
|
||||||
|
* output bytes in *encoding.
|
||||||
|
* <p>
|
||||||
|
* NOTE 2: caller must free the allocated memory itself to avoid memory leaking.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>int ks_asm(ks_engine *ks,
|
||||||
|
* const char *string,
|
||||||
|
* uint64_t address,
|
||||||
|
* unsigned char **encoding, size_t *encoding_size,
|
||||||
|
* size_t *stat_count);</i>
|
||||||
|
*
|
||||||
|
* @param engine handle returned by ks_open()
|
||||||
|
* @param assembly NULL-terminated assembly string. Use ; or \n to separate statements.
|
||||||
|
* @param address address of the first assembly instruction, or 0 to ignore.
|
||||||
|
* @param machineCodeBuffer array of bytes containing encoding of input assembly string.
|
||||||
|
* NOTE: *encoding will be allocated by this function, and should be freed
|
||||||
|
* with ks_free() function.
|
||||||
|
* @param machineCodeSize size of machineCode
|
||||||
|
* @param numberOfStatements number of statements successfully processed
|
||||||
|
* @return 0 on success, or -1 on failure.
|
||||||
|
*/
|
||||||
|
public static native int ks_asm(Pointer engine, String assembly, long address, PointerByReference machineCodeBuffer,
|
||||||
|
IntByReference machineCodeSize, IntByReference numberOfStatements);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close KS instance: MUST do to release the handle when it is not used anymore.
|
||||||
|
* NOTE: this must be called only when there is no longer usage of Keystone.
|
||||||
|
* The reason is this API releases some cached memory, thus access to any
|
||||||
|
* Keystone API after ks_close() might crash your application.
|
||||||
|
* After this, @engine is invalid, and no longer usable.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>ks_err ks_close(ks_engine *ks);</i>
|
||||||
|
*
|
||||||
|
* @param engine pointer to a handle returned by ks_open().
|
||||||
|
* @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum for detailed error).
|
||||||
|
*/
|
||||||
|
public static native KeystoneError ks_close(Pointer engine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report the last error number when some API function fail.
|
||||||
|
* Like glibc's errno, ks_errno might not retain its old error once accessed.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>ks_err ks_errno(ks_engine *ks)</i>
|
||||||
|
*
|
||||||
|
* @param engine handle returned by ks_open()
|
||||||
|
* @return error code of ks_err enum type {@link KeystoneError}
|
||||||
|
*/
|
||||||
|
public static native KeystoneError ks_errno(Pointer engine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free memory allocated by ks_asm().
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>void ks_free(unsigned char *p)</i>
|
||||||
|
*
|
||||||
|
* @param machineCodeBuffer memory allocated in @encoding argument of ks_asm()
|
||||||
|
*/
|
||||||
|
public static native void ks_free(Pointer machineCodeBuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new instance of Keystone engine.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>ks_err ks_open(ks_arch arch, int mode, ks_engine **ks);</i>
|
||||||
|
*
|
||||||
|
* @param architecture architecture type (KS_ARCH_*).
|
||||||
|
* @param mode hardware mode. This is combined of KS_MODE_*.
|
||||||
|
* @param engine pointer to ks_engine, which will be updated at return time.
|
||||||
|
* @return KS_ERR_OK on success, or other value on failure (refer to ks_err enum for detailed error).
|
||||||
|
*/
|
||||||
|
public static native KeystoneError ks_open(KeystoneArchitecture architecture, KeystoneMode mode, PointerByReference engine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set option for Keystone engine at runtime.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>err ks_option(ks_engine *ks, ks_opt_type type, size_t value);</i>
|
||||||
|
*
|
||||||
|
* @param engine handle returned by ks_open()
|
||||||
|
* @param type type of option to be set. See {@link KeystoneOptionType}
|
||||||
|
* @param value option value corresponding with @type
|
||||||
|
* @return {@link KeystoneError#Ok} on success, or other value on failure.
|
||||||
|
* Refer to {@link KeystoneError} enum for detailed error.
|
||||||
|
*/
|
||||||
|
public static native KeystoneError ks_option(Pointer engine, KeystoneOptionType type, int value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set option for Keystone engine at runtime
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>err ks_option(ks_engine *ks, ks_opt_type type, size_t value);</i>
|
||||||
|
*
|
||||||
|
* @param engine handle returned by ks_open()
|
||||||
|
* @param type ype of option to be set. See {@link KeystoneOptionType}
|
||||||
|
* @param callback callback to resolve a unrecognized symbol.
|
||||||
|
* @return {@link KeystoneError#Ok} on success, or other value on failure.
|
||||||
|
* Refer to {@link KeystoneError} enum for detailed error.
|
||||||
|
*/
|
||||||
|
public static native KeystoneError ks_option(Pointer engine, KeystoneOptionType type, SymbolResolverCallback callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string describing given error code.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>const char *ks_strerror(ks_err code);</i>
|
||||||
|
*
|
||||||
|
* @param errorCode error code.
|
||||||
|
* @return returns a pointer to a string that describes the error code passed in the argument @errorCode.
|
||||||
|
*/
|
||||||
|
public static native String ks_strerror(KeystoneError errorCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns combined API version & major and minor version numbers.
|
||||||
|
* <p>
|
||||||
|
* Native function prototype: <i>unsigned int ks_version(unsigned int *major, unsigned int *minor);</i>
|
||||||
|
*
|
||||||
|
* @param major The major number of API version.
|
||||||
|
* @param minor The minor number of API version.
|
||||||
|
* @return An hexadecimal number as (major << 8 | minor), which encodes both major & minor versions.
|
||||||
|
*/
|
||||||
|
public static native int ks_version(IntByReference major, IntByReference minor);
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.natives;
|
||||||
|
|
||||||
|
import com.sun.jna.Pointer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cleaner that automatically close the {@code Pointer} of Keystone once the managed object is phantom reachable.
|
||||||
|
*/
|
||||||
|
public class KeystoneCleanerContainer extends CleanerContainer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an object and a cleaning action to run when the object becomes phantom reachable.
|
||||||
|
*/
|
||||||
|
public KeystoneCleanerContainer(Pointer pointerToEngine) {
|
||||||
|
super(new KeystoneState(pointerToEngine));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The internal state that contains the logic to free the native resource.
|
||||||
|
*/
|
||||||
|
static class KeystoneState implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A pointer to the native resource.
|
||||||
|
*/
|
||||||
|
private final Pointer pointerToEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of {@link KeystoneState}.
|
||||||
|
*
|
||||||
|
* @param pointerToEngine The pointer to the Keystone native resource.
|
||||||
|
*/
|
||||||
|
KeystoneState(Pointer pointerToEngine) {
|
||||||
|
|
||||||
|
this.pointerToEngine = pointerToEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the logic to collect the native resource.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
DirectMappingKeystoneNative.ks_close(pointerToEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Jämes Ménétrey <james@menetrey.me>
|
||||||
|
*
|
||||||
|
* This file is part of the Keystone Java bindings which is released under MIT.
|
||||||
|
* See file LICENSE in the Java bindings folder for full license details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package keystone.utilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the version number of Keystone. This class cannot be inherited.
|
||||||
|
*/
|
||||||
|
public final class Version implements Comparable<Version> {
|
||||||
|
private final int major;
|
||||||
|
private final int minor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new instance of the {@link Version} class using the specified major and minor values.
|
||||||
|
*
|
||||||
|
* @param major The major version number.
|
||||||
|
* @param minor The minor version number.
|
||||||
|
*/
|
||||||
|
public Version(int major, int minor) {
|
||||||
|
this.major = major;
|
||||||
|
this.minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the major component of the version number for the current {@link Version} object.
|
||||||
|
*
|
||||||
|
* @return The major version number.
|
||||||
|
*/
|
||||||
|
public int major() {
|
||||||
|
return major;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of the minor component of the version number for the current {@link Version} object.
|
||||||
|
*
|
||||||
|
* @return The minor version number.
|
||||||
|
*/
|
||||||
|
public int minor() {
|
||||||
|
return minor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares this object with the specified object for order. Returns a
|
||||||
|
* negative integer, zero, or a positive integer as this object is less
|
||||||
|
* than, equal to, or greater than the specified object.
|
||||||
|
*
|
||||||
|
* <p>The implementor must ensure <tt>sgn(x.compareTo(y)) ==
|
||||||
|
* -sgn(y.compareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This
|
||||||
|
* implies that <tt>x.compareTo(y)</tt> must throw an exception iff
|
||||||
|
* <tt>y.compareTo(x)</tt> throws an exception.)
|
||||||
|
*
|
||||||
|
* <p>The implementor must also ensure that the relation is transitive:
|
||||||
|
* <tt>(x.compareTo(y)>0 && y.compareTo(z)>0)</tt> implies
|
||||||
|
* <tt>x.compareTo(z)>0</tt>.
|
||||||
|
*
|
||||||
|
* <p>Finally, the implementor must ensure that <tt>x.compareTo(y)==0</tt>
|
||||||
|
* implies that <tt>sgn(x.compareTo(z)) == sgn(y.compareTo(z))</tt>, for
|
||||||
|
* all <tt>z</tt>.
|
||||||
|
*
|
||||||
|
* <p>It is strongly recommended, but <i>not</i> strictly required that
|
||||||
|
* <tt>(x.compareTo(y)==0) == (x.equals(y))</tt>. Generally speaking, any
|
||||||
|
* class that implements the <tt>Comparable</tt> interface and violates
|
||||||
|
* this condition should clearly indicate this fact. The recommended
|
||||||
|
* language is "Note: this class has a natural ordering that is
|
||||||
|
* inconsistent with equals."
|
||||||
|
*
|
||||||
|
* <p>In the foregoing description, the notation
|
||||||
|
* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical
|
||||||
|
* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,
|
||||||
|
* <tt>0</tt>, or <tt>1</tt> according to whether the value of
|
||||||
|
* <i>expression</i> is negative, zero or positive.
|
||||||
|
*
|
||||||
|
* @param o the object to be compared.
|
||||||
|
* @return a negative integer, zero, or a positive integer as this object
|
||||||
|
* is less than, equal to, or greater than the specified object.
|
||||||
|
* @throws NullPointerException if the specified object is null
|
||||||
|
* @throws ClassCastException if the specified object's type prevents it
|
||||||
|
* from being compared to this object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(Version o) {
|
||||||
|
if (o == null) return 1;
|
||||||
|
|
||||||
|
if (major != o.major) {
|
||||||
|
if (major > o.major) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Integer.compare(minor, o.minor);
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue