8188073: Add Capstone as backend for hsdis

Co-authored-by: Magnus Ihse Bursie <ihse@openjdk.org>
Co-authored-by: Jorn Vernee <jvernee@openjdk.org>
Reviewed-by: erikj
This commit is contained in:
Magnus Ihse Bursie 2022-02-17 21:18:15 +00:00
parent 69fc273f20
commit f830cbec90
9 changed files with 390 additions and 180 deletions

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -36,89 +36,111 @@ include JdkNativeCompilation.gmk
HSDIS_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/hsdis
HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT
HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB)
HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB)
ifeq ($(call isTargetOs, windows), true)
INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/bin
# On windows, we need to "fake" a completely different toolchain using gcc
# instead of the normal microsoft toolchain. This is quite hacky...
MINGW_BASE := x86_64-w64-mingw32
MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot)
ifeq ($(wildcard $(MINGW_SYSROOT)), )
# Use fallback path
MINGW_SYSROOT := /usr/$(MINGW_BASE)
ifeq ($(wildcard $(MINGW_SYSROOT)), )
$(error mingw sysroot not found)
endif
endif
$(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \
CC := $(MINGW_BASE)-gcc, \
LD := $(MINGW_BASE)-ld, \
OBJCOPY := $(MINGW_BASE)-objcopy, \
RC := $(RC), \
SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \
SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \
))
MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib
ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), )
# Try without mingw
MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib
ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), )
$(error mingw sysroot lib path not found)
endif
endif
MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3)
MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION)
ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), )
# Try using only major version number
MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION)))
MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR)
ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), )
$(error mingw gcc lib path not found)
endif
endif
TOOLCHAIN_TYPE := gcc
OPENJDK_TARGET_OS := linux
CC_OUT_OPTION := -o$(SPACE)
LD_OUT_OPTION := -o$(SPACE)
GENDEPS_FLAGS := -MMD -MF
CFLAGS_DEBUG_SYMBOLS := -g
DISABLED_WARNINGS :=
DISABLE_WARNING_PREFIX := -Wno-
CFLAGS_WARNINGS_ARE_ERRORS := -Werror
SHARED_LIBRARY_FLAGS := -shared
HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW
HSDIS_TOOLCHAIN_CFLAGS :=
HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH)
MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o
HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \
-lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32
IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/bin
else
INSTALLED_HSDIS_DIR := $(JDK_OUTPUTDIR)/lib
HSDIS_TOOLCHAIN := TOOLCHAIN_DEFAULT
HSDIS_TOOLCHAIN_CFLAGS := $(CFLAGS_JDKLIB)
HSDIS_TOOLCHAIN_LDFLAGS := $(LDFLAGS_JDKLIB)
HSDIS_TOOLCHAIN_LIBS := -ldl
IMAGE_HSDIS_DIR := $(JDK_IMAGE_DIR)/lib
endif
ifeq ($(HSDIS_BACKEND), capstone)
ifeq ($(call isTargetCpuArch, x86), true)
CAPSTONE_ARCH := CS_ARCH_X86
CAPSTONE_MODE := CS_MODE_$(OPENJDK_TARGET_CPU_BITS)
else ifeq ($(call isTargetCpuArch, aarch64), true)
CAPSTONE_ARCH := CS_ARCH_ARM64
CAPSTONE_MODE := CS_MODE_ARM
else
$(error No support for Capstone on this platform)
endif
HSDIS_CFLAGS += -DCAPSTONE_ARCH=$(CAPSTONE_ARCH) \
-DCAPSTONE_MODE=$(CAPSTONE_MODE)
endif
ifeq ($(HSDIS_BACKEND), binutils)
ifeq ($(call isTargetOs, windows), true)
# On windows, we need to "fake" a completely different toolchain using gcc
# instead of the normal microsoft toolchain. This is quite hacky...
MINGW_BASE := x86_64-w64-mingw32
MINGW_SYSROOT = $(shell $(MINGW_BASE)-gcc -print-sysroot)
ifeq ($(wildcard $(MINGW_SYSROOT)), )
# Use fallback path
MINGW_SYSROOT := /usr/$(MINGW_BASE)
ifeq ($(wildcard $(MINGW_SYSROOT)), )
$(error mingw sysroot not found)
endif
endif
$(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \
CC := $(MINGW_BASE)-gcc, \
LD := $(MINGW_BASE)-ld, \
OBJCOPY := $(MINGW_BASE)-objcopy, \
RC := $(RC), \
SYSROOT_CFLAGS := --sysroot=$(MINGW_SYSROOT), \
SYSROOT_LDFLAGS := --sysroot=$(MINGW_SYSROOT), \
))
MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/mingw/lib
ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), )
# Try without mingw
MINGW_SYSROOT_LIB_PATH := $(MINGW_SYSROOT)/lib
ifeq ($(wildcard $(MINGW_SYSROOT_LIB_PATH)), )
$(error mingw sysroot lib path not found)
endif
endif
MINGW_VERSION = $(shell $(MINGW_BASE)-gcc -v 2>&1 | $(GREP) "gcc version" | $(CUT) -d " " -f 3)
MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION)
ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), )
# Try using only major version number
MINGW_VERSION_MAJOR := $(firstword $(subst ., , $(MINGW_VERSION)))
MINGW_GCC_LIB_PATH := /usr/lib/gcc/$(MINGW_BASE)/$(MINGW_VERSION_MAJOR)
ifeq ($(wildcard $(MINGW_GCC_LIB_PATH)), )
$(error mingw gcc lib path not found)
endif
endif
TOOLCHAIN_TYPE := gcc
OPENJDK_TARGET_OS := linux
CC_OUT_OPTION := -o$(SPACE)
LD_OUT_OPTION := -o$(SPACE)
GENDEPS_FLAGS := -MMD -MF
CFLAGS_DEBUG_SYMBOLS := -g
DISABLED_WARNINGS :=
DISABLE_WARNING_PREFIX := -Wno-
CFLAGS_WARNINGS_ARE_ERRORS := -Werror
SHARED_LIBRARY_FLAGS := -shared
HSDIS_TOOLCHAIN := TOOLCHAIN_MINGW
HSDIS_TOOLCHAIN_CFLAGS :=
HSDIS_TOOLCHAIN_LDFLAGS := -L$(MINGW_GCC_LIB_PATH) -L$(MINGW_SYSROOT_LIB_PATH)
MINGW_DLLCRT := $(MINGW_SYSROOT_LIB_PATH)/dllcrt2.o
HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \
-lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32
else
HSDIS_TOOLCHAIN_LIBS := -ldl
endif
endif
$(eval $(call SetupJdkLibrary, BUILD_HSDIS, \
NAME := hsdis, \
SRC := $(TOPDIR)/src/utils/hsdis, \
SRC := $(TOPDIR)/src/utils/hsdis/$(HSDIS_BACKEND), \
EXTRA_HEADER_DIRS := $(TOPDIR)/src/utils/hsdis, \
TOOLCHAIN := $(HSDIS_TOOLCHAIN), \
OUTPUT_DIR := $(HSDIS_OUTPUT_DIR), \
OBJECT_DIR := $(HSDIS_OUTPUT_DIR), \
DISABLED_WARNINGS_gcc := undef format-nonliteral sign-compare, \
DISABLED_WARNINGS_clang := undef format-nonliteral, \
CFLAGS := $(HSDIS_TOOLCHAIN_CFLAGS) $(HSDIS_CFLAGS), \
LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \
LDFLAGS := $(HSDIS_TOOLCHAIN_LDFLAGS) $(HSDIS_LDFLAGS) $(SHARED_LIBRARY_FLAGS), \
LIBS := $(HSDIS_LIBS) $(HSDIS_TOOLCHAIN_LIBS), \
))
@ -129,13 +151,18 @@ TARGETS += build
INSTALLED_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX)
INSTALLED_HSDIS := $(INSTALLED_HSDIS_DIR)/$(INSTALLED_HSDIS_NAME)
INSTALLED_HSDIS_IMAGE := $(IMAGE_HSDIS_DIR)/$(INSTALLED_HSDIS_NAME)
$(INSTALLED_HSDIS): $(BUILD_HSDIS_TARGET)
$(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distibuting.)
ifeq ($(HSDIS_BACKEND), binutils)
$(call LogWarn, NOTE: The resulting build might not be redistributable. Seek legal advice before distributing.)
endif
$(install-file)
$(INSTALLED_HSDIS_IMAGE): $(INSTALLED_HSDIS)
$(install-file)
install: $(INSTALLED_HSDIS)
install: $(INSTALLED_HSDIS_IMAGE)
TARGETS += install

View File

@ -117,6 +117,8 @@ apt_help() {
PKGHANDLER_COMMAND="sudo apt-get install ccache" ;;
dtrace)
PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;;
capstone)
PKGHANDLER_COMMAND="sudo apt-get install libcapstone-dev" ;;
esac
}
@ -168,6 +170,8 @@ brew_help() {
PKGHANDLER_COMMAND="brew install freetype" ;;
ccache)
PKGHANDLER_COMMAND="brew install ccache" ;;
capstone)
PKGHANDLER_COMMAND="brew install capstone" ;;
esac
}

View File

@ -811,7 +811,10 @@ AC_DEFUN([JDKOPT_BUILD_BINUTILS],
AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS],
[
AC_ARG_WITH([hsdis], [AS_HELP_STRING([--with-hsdis],
[what hsdis backend to use ('none', 'binutils') @<:@none@:>@])])
[what hsdis backend to use ('none', 'capstone', 'binutils') @<:@none@:>@])])
AC_ARG_WITH(capstone, [AS_HELP_STRING([--with-capstone],
[where to find the Capstone files needed for hsdis/capstone])])
AC_ARG_WITH([binutils], [AS_HELP_STRING([--with-binutils],
[where to find the binutils files needed for hsdis/binutils])])
@ -826,6 +829,41 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS],
elif test "x$with_hsdis" = xnone || test "x$with_hsdis" = xno || test "x$with_hsdis" = x; then
HSDIS_BACKEND=none
AC_MSG_RESULT(['none', hsdis will not be built])
elif test "x$with_hsdis" = xcapstone; then
HSDIS_BACKEND=capstone
AC_MSG_RESULT(['capstone'])
if test "x$with_capstone" != x; then
AC_MSG_CHECKING([for capstone])
CAPSTONE="$with_capstone"
AC_MSG_RESULT([$CAPSTONE])
HSDIS_CFLAGS="-I${CAPSTONE}/include/capstone"
if test "x$OPENJDK_TARGET_OS" != xwindows; then
HSDIS_LDFLAGS="-L${CAPSTONE}/lib"
HSDIS_LIBS="-lcapstone"
else
HSDIS_LDFLAGS="-nodefaultlib:libcmt.lib"
HSDIS_LIBS="${CAPSTONE}/capstone.lib"
fi
else
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# There is no way to auto-detect capstone on Windowos
AC_MSG_NOTICE([You must specify capstone location using --with-capstone=<path>])
AC_MSG_ERROR([Cannot continue])
fi
PKG_CHECK_MODULES(CAPSTONE, capstone, [CAPSTONE_FOUND=yes], [CAPSTONE_FOUND=no])
if test "x$CAPSTONE_FOUND" = xyes; then
HSDIS_CFLAGS="$CAPSTONE_CFLAGS"
HSDIS_LDFLAGS="$CAPSTONE_LDFLAGS"
HSDIS_LIBS="$CAPSTONE_LIBS"
else
HELP_MSG_MISSING_DEPENDENCY([capstone])
AC_MSG_NOTICE([Cannot locate capstone which is needed for hsdis/capstone. Try using --with-capstone=<path>. $HELP_MSG])
AC_MSG_ERROR([Cannot continue])
fi
fi
elif test "x$with_hsdis" = xbinutils; then
HSDIS_BACKEND=binutils
AC_MSG_RESULT(['binutils'])
@ -853,6 +891,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS],
test -e $BINUTILS_DIR/opcodes/libopcodes.a && \
test -e $BINUTILS_DIR/libiberty/libiberty.a; then
HSDIS_CFLAGS="-I$BINUTILS_DIR/include -I$BINUTILS_DIR/bfd -DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB"
HSDIS_LDFLAGS=""
HSDIS_LIBS="$BINUTILS_DIR/bfd/libbfd.a $BINUTILS_DIR/opcodes/libopcodes.a $BINUTILS_DIR/libiberty/libiberty.a $BINUTILS_DIR/zlib/libz.a"
fi
fi
@ -895,5 +934,6 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS],
AC_SUBST(HSDIS_BACKEND)
AC_SUBST(HSDIS_CFLAGS)
AC_SUBST(HSDIS_LDFLAGS)
AC_SUBST(HSDIS_LIBS)
])

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -361,6 +361,7 @@ ALLOW_ABSOLUTE_PATHS_IN_OUTPUT := @ALLOW_ABSOLUTE_PATHS_IN_OUTPUT@
HSDIS_BACKEND := @HSDIS_BACKEND@
HSDIS_CFLAGS := @HSDIS_CFLAGS@
HSDIS_LDFLAGS := @HSDIS_LDFLAGS@
HSDIS_LIBS := @HSDIS_LIBS@
# The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep

View File

@ -1,102 +0,0 @@
Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
The Universal Permissive License (UPL), Version 1.0
Subject to the condition set forth below, permission is hereby granted to
any person obtaining a copy of this software, associated documentation
and/or data (collectively the "Software"), free of charge and under any
and all copyright rights in the Software, and any and all patent rights
owned or freely licensable by each licensor hereunder covering either (i)
the unmodified Software as contributed to or provided by such licensor,
or (ii) the Larger Works (as defined below), to deal in both
(a) the Software, and
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file
if one is included with the Software (each a "Larger Work" to which the
Software is contributed by such licensors),
without restriction, including without limitation the rights to copy,
create derivative works of, display, perform, and distribute the Software
and make, use, sell, offer for sale, import, export, have made, and have
sold the Software and the Larger Work(s), and to sublicense the foregoing
rights on either these or other terms.
This license is subject to the following condition:
The above copyright notice and either this complete permission notice or
at a minimum a reference to the UPL must 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.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
________________________________________________________________________
'hsdis': A HotSpot plugin for disassembling dynamically generated code.
The files in this directory are built independently of the HotSpot JVM.
* Building
To build this project you need a copy of GNU binutils to build against. It is
known to work with binutils 2.37. Building against versions older than 2.29 is
not supported. Download a copy of the software from
http://directory.fsf.org/project/binutils or one of its mirrors.
To build this library, you must enable building in configure by "bash configure
--with-hsdis=binutils".
You must also specify where binutils is located. To facilitate building, you can
point to a place where the (unpacked) binutils sources are located using
"--with-binutils-src=<location>", and configure will build binutils for you. On
repeated runs, you can keep this command line option, since configure will
figure out that the binutils binaries are already present and skip building, or
you can replace it with "--with-binutils=<location>".
If you have pre-built binutils binaries, you can point to them directly using
"--with-binutils=<location>".
If you want to build hsdis with binutils provided by system
(e.g. binutils-devel from Fedora, binutils-dev from Ubuntu), you can pass
"--with-binutils=system". "system" is available on Linux only.
When you have created a proper configuration, you can then build the hsdis
library using "make build-hsdis".
* Building on Windows
On Windows, the normal Microsoft Visual Studio toolchain cannot build binutils.
Instead we need to use the mingw compiler. This is available as a cygwin
package. You need to install the "gcc-core" and "mingw64-x86_64-gcc-core"
packages (or "mingw64-i686-gcc-core", if you want the 32-bit version) and
"mingw64-x86_64-glib2.0".
* Installing
To build the hsdis library, run "make build-hsdis". This will build the library
in a separate directory, but not make it available to the JDK in the
configuration. To actually install it in the JDK, run "make install-hsdis".
Note: The resulting build may not be distributable. Please get legal advice if
you intend to distribute the result of your build.
* Using the library
The hsdis library will be automatically loaded by Hotspot when you use the
diagnostic option "-XX:+PrintAssembly". Note that since this is a diagnostic
option, you need to unlock these first, so in practice you activate it using
"-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly".
More information is available at the wiki
[https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly].

133
src/utils/hsdis/README.md Normal file
View File

@ -0,0 +1,133 @@
```
Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
The Universal Permissive License (UPL), Version 1.0
Subject to the condition set forth below, permission is hereby granted to
any person obtaining a copy of this software, associated documentation
and/or data (collectively the "Software"), free of charge and under any
and all copyright rights in the Software, and any and all patent rights
owned or freely licensable by each licensor hereunder covering either (i)
the unmodified Software as contributed to or provided by such licensor,
or (ii) the Larger Works (as defined below), to deal in both
(a) the Software, and
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file
if one is included with the Software (each a "Larger Work" to which the
Software is contributed by such licensors),
without restriction, including without limitation the rights to copy,
create derivative works of, display, perform, and distribute the Software
and make, use, sell, offer for sale, import, export, have made, and have
sold the Software and the Larger Work(s), and to sublicense the foregoing
rights on either these or other terms.
This license is subject to the following condition:
The above copyright notice and either this complete permission notice or
at a minimum a reference to the UPL must 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.
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
or visit www.oracle.com if you need additional information or have any
questions.
```
---
# hsdis - a HotSpot plugin for disassembling dynamically generated code
The files in this directory are built independently of the HotSpot JVM.
hsdis is an interface exposed by Hotspot. There are several backends that
implement this interface, using different disassembly engines. Included in the
JDK is support for building hsdis with Capstone or GNU binutils. The interface
is fairly straightforward and easy to implement using other backends.
## Building and installing
To compile hsdis, you need to activate hsdis support, and select the proper
backend to use. This is done with the configure switch `--with-hsdis=<backend>`,
where `<backend>` is either `capstone` or `binutils`. For details, see the
sections on the respective backends below.
To build the hsdis library, run `make build-hsdis`. This will build the library
in a separate directory, but not make it available to the JDK in the
configuration. To actually install it in the JDK, run `make install-hsdis`.
**NOTE:** If you do this using the binutils backend, the resulting build may not
be distributable. Please get legal advice if you intend to distribute the result
of your build.
## Using the library
The hsdis library will be automatically loaded by Hotspot when you use the
diagnostic option `-XX:+PrintAssembly`. Note that since this is a diagnostic
option, you need to unlock these first, so in practice you activate it using
`-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly`.
More information is available at the [HotSpot
wiki](https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly).
## Building with Capstone
To build this project using Capstone you need to have Capstone installed.
Typical ways of installation can be `sudo apt install libcapstone-dev` (on
Debian and derivatives), or `brew install capstone` (on macOS with Homebrew).
For Windows, you need to download the "Core Engine", and unzip it. See the
[Capstone Download
page](https://www.capstone-engine.org/download.html#windows---core-engine-) for
up-to-date download links.
This has been tested with Capstone v4.0.2, but earlier (and later) versions are
also likely to work.
To build hsdis using Capstone, you must enable it in configure by `bash
configure --with-hsdis=capstone`.
On Linux and macOS, the location Capstone can most often be auto-detected. If
this fails, or if you are building on Windows, you need to specify where
Capstone is located using `--with-capstone=<path>`. This path should point to
where you have extracted the Core Engine zip file.
## Building with binutils
To build this project using binutils you need a copy of GNU binutils to build
against. It is known to work with binutils 2.37. Building against versions older
than 2.29 is not supported. Download a copy of the software from [FSF binutils
page](http://directory.fsf.org/project/binutils) or one of its mirrors.
To build this library, you must enable building in configure by `bash configure
--with-hsdis=binutils`.
You must also specify where binutils is located. To facilitate building, you can
point to a place where the (unpacked) binutils sources are located using
`--with-binutils-src=<location>`, and configure will build binutils for you. On
repeated runs, you can keep this command line option, since configure will
figure out that the binutils binaries are already present and skip building, or
you can replace it with `--with-binutils=<location>`.
If you have pre-built binutils binaries, you can point to them directly using
`--with-binutils=<location>`.
If you want to build hsdis with binutils provided by system (e.g. binutils-devel
from Fedora, binutils-dev from Ubuntu), you can pass `--with-binutils=system`.
`system` is available on Linux only.
### Building with binutils on Windows
On Windows, the normal Microsoft Visual Studio toolchain cannot build binutils.
Instead we need to use the mingw compiler. This is available as a cygwin
package. You need to install the `gcc-core` and `mingw64-x86_64-gcc-core`
packages (or `mingw64-i686-gcc-core`, if you want the 32-bit version) and
`mingw64-x86_64-glib2.0`.

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to
* any person obtaining a copy of this software, associated documentation
* and/or data (collectively the "Software"), free of charge and under any
* and all copyright rights in the Software, and any and all patent rights
* owned or freely licensable by each licensor hereunder covering either (i)
* the unmodified Software as contributed to or provided by such licensor,
* or (ii) the Larger Works (as defined below), to deal in both
*
* (a) the Software, and
*
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file
* if one is included with the Software (each a "Larger Work" to which the
* Software is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy,
* create derivative works of, display, perform, and distribute the Software
* and make, use, sell, offer for sale, import, export, have made, and have
* sold the Software and the Larger Work(s), and to sublicense the foregoing
* rights on either these or other terms.
*
* This license is subject to the following condition:
*
* The above copyright notice and either this complete permission notice or
* at a minimum a reference to the UPL must 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.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/* hsdis.c -- dump a range of addresses as native instructions
This implements the plugin protocol required by the
HotSpot PrintAssembly option.
*/
#include <inttypes.h>
#include <capstone.h>
#include "hsdis.h"
/* short names for stuff in hsdis.h */
typedef decode_instructions_event_callback_ftype event_callback_t;
typedef decode_instructions_printf_callback_ftype printf_callback_t;
#define print(...) (*printf_callback) (printf_stream, __VA_ARGS__)
#ifdef _WIN32
__declspec(dllexport)
#endif
void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
unsigned char* buffer, uintptr_t length,
void* (*event_callback)(void*, const char*, void*),
void* event_stream,
int (*printf_callback)(void*, const char*, ...),
void* printf_stream,
const char* options,
int newline /* bool value for nice new line */) {
csh cs_handle;
if (cs_open(CAPSTONE_ARCH, CAPSTONE_MODE, &cs_handle) != CS_ERR_OK) {
print("Could not open cs_handle");
return NULL;
}
// TODO: Support intel syntax
cs_option(cs_handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
cs_insn *insn;
size_t count = cs_disasm(cs_handle, buffer, length, (uintptr_t) buffer, 0 , &insn);
if (count) {
for (unsigned int j = 0; j < count; j++) {
print(" 0x%" PRIx64 ":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
}
cs_free(insn, count);
}
cs_close(&cs_handle);
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@ -72,9 +72,14 @@
#ifndef SHARED_TOOLS_HSDIS_H
#define SHARED_TOOLS_HSDIS_H
#ifdef __cplusplus
extern "C"
{
#endif
extern
#ifdef DLL_EXPORT
DLL_EXPORT
#ifdef _WIN32
__declspec(dllexport)
#endif
void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
unsigned char* buffer, uintptr_t length,
@ -87,8 +92,8 @@ void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
/* This is the compatability interface for older versions of hotspot */
extern
#ifdef DLL_ENTRY
DLL_ENTRY
#ifdef _WIN32
__declspec(dllexport)
#endif
void* decode_instructions(void* start_pv, void* end_pv,
void* (*event_callback)(void*, const char*, void*),
@ -115,4 +120,9 @@ typedef void* (*decode_func_stype) (void* start_pv, void* end_pv,
decode_instructions_printf_callback_ftype printf_callback,
void* printf_stream,
const char* options);
#ifdef __cplusplus
}
#endif
#endif /* SHARED_TOOLS_HSDIS_H */