diff --git a/make/Hsdis.gmk b/make/Hsdis.gmk new file mode 100644 index 00000000000..2253da90679 --- /dev/null +++ b/make/Hsdis.gmk @@ -0,0 +1,118 @@ +# +# Copyright (c) 2020, 2021, 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# 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. +# + +default: all + +include $(SPEC) +include MakeBase.gmk +include JdkNativeCompilation.gmk + +################################################################################ +# This makefile compiles and installs the hsdis library +# +################################################################################ + +HSDIS_OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/hsdis + +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 + + $(eval $(call DefineNativeToolchain, TOOLCHAIN_MINGW, \ + CC := $(MINGW_BASE)-gcc, \ + LD := $(MINGW_BASE)-ld, \ + OBJCOPY := $(MINGW_BASE)-objcopy, \ + RC := $(RC), \ + SYSROOT_CFLAGS := --sysroot=/usr/$(MINGW_BASE)/sys-root, \ + SYSROOT_LDFLAGS := --sysroot=/usr/$(MINGW_BASE)/sys-root, \ + )) + + 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/usr/lib/gcc/$(MINGW_BASE)/9.2.0 \ + -L/usr/$(MINGW_BASE)/sys-root/mingw/lib + MINGW_DLLCRT := /usr/$(MINGW_BASE)/sys-root/mingw/lib/dllcrt2.o + HSDIS_TOOLCHAIN_LIBS := $(MINGW_DLLCRT) -lmingw32 -lgcc -lgcc_eh -lmoldname \ + -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 +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 +endif + + +$(eval $(call SetupJdkLibrary, BUILD_HSDIS, \ + NAME := hsdis, \ + SRC := $(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), \ + LIBS := $(HSDIS_LIBS) $(HSDIS_TOOLCHAIN_LIBS), \ +)) + +build: $(BUILD_HSDIS) + +TARGETS += build + +INSTALLED_HSDIS_NAME := hsdis-$(OPENJDK_TARGET_CPU_LEGACY_LIB)$(SHARED_LIBRARY_SUFFIX) + +INSTALLED_HSDIS := $(INSTALLED_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.) + $(install-file) + + +install: $(INSTALLED_HSDIS) + +TARGETS += install + +################################################################################ + +all: $(TARGETS) + +.PHONY: all default build install diff --git a/make/Main.gmk b/make/Main.gmk index cad3ecb3203..75eee65ba84 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -526,6 +526,18 @@ $(eval $(call SetupTarget, update-x11wrappers, \ DEPS := java.base-copy buildtools-jdk, \ )) +ifneq ($(HSDIS_BACKEND), none) + $(eval $(call SetupTarget, build-hsdis, \ + MAKEFILE := Hsdis, \ + TARGET := build, \ + )) + + $(eval $(call SetupTarget, install-hsdis, \ + MAKEFILE := Hsdis, \ + TARGET := install, \ + )) +endif + ################################################################################ # Cross compilation support diff --git a/make/autoconf/configure.ac b/make/autoconf/configure.ac index 0faec69738e..29ed3f206aa 100644 --- a/make/autoconf/configure.ac +++ b/make/autoconf/configure.ac @@ -249,6 +249,7 @@ JDKOPT_EXCLUDE_TRANSLATIONS JDKOPT_ENABLE_DISABLE_MANPAGES JDKOPT_ENABLE_DISABLE_CDS_ARCHIVE JDKOPT_ENABLE_DISABLE_COMPATIBLE_CDS_ALIGNMENT +JDKOPT_SETUP_HSDIS ############################################################################### # diff --git a/make/autoconf/help.m4 b/make/autoconf/help.m4 index 924cc425609..f36aa2819df 100644 --- a/make/autoconf/help.m4 +++ b/make/autoconf/help.m4 @@ -80,6 +80,14 @@ cygwin_help() { PKGHANDLER_COMMAND="( cd && cmd /c setup -q -P make )" HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." ;; + i686-w64-mingw32-gcc) + PKGHANDLER_COMMAND="( cd && cmd /c setup -q -P gcc-core i686-w64-mingw32-gcc-core mingw64-i686-glib2.0 )" + HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." + ;; + x86_64-w64-mingw32-gcc) + PKGHANDLER_COMMAND="( cd && cmd /c setup -q -P gcc-core x86_64-w64-mingw32-gcc-core mingw64-x86_64-glib2.0 )" + HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." + ;; esac } diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 299f76bd1e6..c937101c2c7 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -704,3 +704,145 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], AC_SUBST(SOURCE_DATE) AC_SUBST(ENABLE_REPRODUCIBLE_BUILD) ]) + +################################################################################ +# +# Helper function to build binutils from source. +# +AC_DEFUN([JDKOPT_BUILD_BINUTILS], +[ + BINUTILS_SRC="$with_binutils_src" + UTIL_FIXUP_PATH(BINUTILS_SRC) + + if ! test -d $BINUTILS_SRC; then + AC_MSG_ERROR([--with-binutils-src is not pointing to a directory]) + fi + if ! test -x $BINUTILS_SRC/configure; then + AC_MSG_ERROR([--with-binutils-src does not look like a binutils source directory]) + fi + + if test -e $BINUTILS_SRC/bfd/libbfd.a && \ + test -e $BINUTILS_SRC/opcodes/libopcodes.a && \ + test -e $BINUTILS_SRC/libiberty/libiberty.a && \ + test -e $BINUTILS_SRC/zlib/libz.a; then + AC_MSG_NOTICE([Found binutils binaries in binutils source directory -- not building]) + else + # On Windows, we cannot build with the normal Microsoft CL, but must instead use + # a separate mingw toolchain. + if test "x$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_TARGET_CPU" = "xx86"; then + target_base="i686-w64-mingw32" + else + target_base="$OPENJDK_TARGET_CPU-w64-mingw32" + fi + binutils_cc="$target_base-gcc" + binutils_target="--host=$target_base --target=$target_base" + # Somehow the uint typedef is not included when building with mingw + binutils_cflags="-Duint=unsigned" + compiler_version=`$binutils_cc --version 2>&1` + if ! [ [[ "$compiler_version" =~ GCC ]] ]; then + AC_MSG_NOTICE([Could not find correct mingw compiler $binutils_cc.]) + HELP_MSG_MISSING_DEPENDENCY([$binutils_cc]) + AC_MSG_ERROR([Cannot continue. $HELP_MSG]) + else + AC_MSG_NOTICE([Using compiler $binutils_cc with version $compiler_version]) + fi + elif test "x$OPENJDK_BUILD_OS" = xmacosx; then + if test "x$OPENJDK_TARGET_CPU" = "xaarch64"; then + binutils_target="--enable-targets=aarch64-darwin" + else + binutils_target="" + fi + else + binutils_cc="$CC $SYSROOT_CFLAGS" + binutils_target="" + fi + binutils_cflags="$binutils_cflags $MACHINE_FLAG $JVM_PICFLAG $C_O_FLAG_NORM" + + AC_MSG_NOTICE([Running binutils configure]) + AC_MSG_NOTICE([configure command line: ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target]) + saved_dir=`pwd` + cd "$BINUTILS_SRC" + ./configure --disable-nls CFLAGS="$binutils_cflags" CC="$binutils_cc" $binutils_target + if test $? -ne 0 || ! test -e $BINUTILS_SRC/Makefile; then + AC_MSG_NOTICE([Automatic building of binutils failed on configure. Try building it manually]) + AC_MSG_ERROR([Cannot continue]) + fi + AC_MSG_NOTICE([Running binutils make]) + $MAKE all-opcodes + if test $? -ne 0; then + AC_MSG_NOTICE([Automatic building of binutils failed on make. Try building it manually]) + AC_MSG_ERROR([Cannot continue]) + fi + cd $saved_dir + AC_MSG_NOTICE([Building of binutils done]) + fi + + BINUTILS_DIR="$BINUTILS_SRC" +]) + +################################################################################ +# +# Determine if hsdis should be built, and if so, with which backend. +# +AC_DEFUN_ONCE([JDKOPT_SETUP_HSDIS], +[ + AC_ARG_WITH([hsdis], [AS_HELP_STRING([--with-hsdis], + [what hsdis backend to use ('none', 'binutils') @<:@none@:>@])]) + + AC_ARG_WITH([binutils], [AS_HELP_STRING([--with-binutils], + [where to find the binutils files needed for hsdis/binutils])]) + + AC_ARG_WITH([binutils-src], [AS_HELP_STRING([--with-binutils-src], + [where to find the binutils source for building])]) + + AC_MSG_CHECKING([what hsdis backend to use]) + + if test "x$with_hsdis" = xyes; then + AC_MSG_ERROR([--with-hsdis must have a value]) + 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" = xbinutils; then + HSDIS_BACKEND=binutils + AC_MSG_RESULT(['binutils']) + + # We need the binutils static libs and includes. + if test "x$with_binutils_src" != x; then + # Try building the source first. If it succeeds, it sets $BINUTILS_DIR. + JDKOPT_BUILD_BINUTILS + fi + + if test "x$with_binutils" != x; then + BINUTILS_DIR="$with_binutils" + fi + + AC_MSG_CHECKING([for binutils to use with hsdis]) + if test "x$BINUTILS_DIR" != x; then + if test -e $BINUTILS_DIR/bfd/libbfd.a && \ + test -e $BINUTILS_DIR/opcodes/libopcodes.a && \ + test -e $BINUTILS_DIR/libiberty/libiberty.a; then + AC_MSG_RESULT([$BINUTILS_DIR]) + HSDIS_CFLAGS="-I$BINUTILS_DIR/include -I$BINUTILS_DIR/bfd -DLIBARCH_$OPENJDK_TARGET_CPU_LEGACY_LIB" + HSDIS_LIBS="$BINUTILS_DIR/bfd/libbfd.a $BINUTILS_DIR/opcodes/libopcodes.a $BINUTILS_DIR/libiberty/libiberty.a $BINUTILS_DIR/zlib/libz.a" + else + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([$BINUTILS_DIR does not contain a proper binutils installation]) + fi + else + AC_MSG_RESULT([missing]) + AC_MSG_NOTICE([--with-hsdis=binutils requires specifying a binutils installation.]) + AC_MSG_NOTICE([Download binutils from https://www.gnu.org/software/binutils and unpack it,]) + AC_MSG_NOTICE([and point --with-binutils-src to the resulting directory, or use]) + AC_MSG_NOTICE([--with-binutils to point to a pre-built binutils installation.]) + AC_MSG_ERROR([Cannot continue]) + fi + else + AC_MSG_RESULT([invalid]) + AC_MSG_ERROR([Incorrect hsdis backend "$with_hsdis"]) + fi + + AC_SUBST(HSDIS_BACKEND) + AC_SUBST(HSDIS_CFLAGS) + AC_SUBST(HSDIS_LIBS) +]) diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index bb7d63346f4..72be922f103 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -359,6 +359,10 @@ ENABLE_COMPATIBLE_CDS_ALIGNMENT := @ENABLE_COMPATIBLE_CDS_ALIGNMENT@ ALLOW_ABSOLUTE_PATHS_IN_OUTPUT := @ALLOW_ABSOLUTE_PATHS_IN_OUTPUT@ +HSDIS_BACKEND := @HSDIS_BACKEND@ +HSDIS_CFLAGS := @HSDIS_CFLAGS@ +HSDIS_LIBS := @HSDIS_LIBS@ + # The boot jdk to use. This is overridden in bootcycle-spec.gmk. Make sure to keep # it in sync. BOOT_JDK:=@BOOT_JDK@ diff --git a/src/utils/hsdis/README b/src/utils/hsdis/README index f2cf2f48b9f..aee40f6bd27 100644 --- a/src/utils/hsdis/README +++ b/src/utils/hsdis/README @@ -1,4 +1,4 @@ -Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. +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 @@ -43,102 +43,56 @@ questions. ________________________________________________________________________ -'hsdis': A HotSpot plugin for disassembling dynamically generated code. +'hsdis': A HotSpot plugin for disassembling dynamically generated code. -The files in this directory (Makefile, hsdis.[ch], hsdis-demo.c) -are built independently of the HotSpot JVM. - -To use the plugin with a JVM, you need a new version that can load it. -If the product mode of your JVM does not accept -XX:+PrintAssembly, -you do not have a version that is new enough. +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.29.1, 2.30, and 2.31.1. Building -against versions older than 2.29 is no longer supported. Download a -copy of the software from http://directory.fsf.org/project/binutils or -one of its mirrors. Builds targetting windows currently require the -use of a cross compiler. +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. -Binutils should be configured with the '--disable-nls' flag to disable -Native Language Support, otherwise you might get an "undefined -reference to `libintl_gettext'" if you try to load hsdis.so on systems -which don't have NLS by default. It also avoids build problems on -other configurations that don't include the full NLS support. +To build this library, you must enable building in configure by "bash configure +--with-hsdis=binutils". -The makefile looks for the sources in build/binutils or you can -specify its location to the makefile using BINUTILS=path. It will -configure binutils and build it first and then build and link the -disassembly adapter. Make all will build the default target for your -platform. If your platform supports both 32 and 64 simultaneously then -"make both" will build them both at once. "make all64" will -explicitly build the 64 bit version. By default this will build the -disassembler library only. If you build demo it will build a demo -program that attempts to exercise the library. +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=", 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=". -With recent version of binutils (i.e. binutils-2.23.2) you may get the -following build error: +If you have pre-built binutils binaries, you can point to them directly using +"--with-binutils=". -WARNING: `makeinfo' is missing on your system. You should only need it if - you modified a `.texi' or `.texinfo' file, or any other file - ... +When you have created a proper configuration, you can then build the hsdis +library using "make build-hsdis". -This is because of "Bug 15345 - binutils-2.23.2 tarball doesn't build -without makeinfo" [2]. The easiest way to work around this problem is -by doing a "touch $BINUTILS/bfd/doc/bfd.info". +* Building on Windows -Windows - -In theory this should be buildable on Windows but getting a working -GNU build environment on Windows has proven difficult. MINGW should -be able to do it but at the time of this writing I was unable to get -this working. Instead you can use the mingw cross compiler on linux -to produce the windows binaries. For 32-bit windows you can install -mingw32 using your package manager and it will be added to your path -automatically. For 64-bit you need to download the 64 bit mingw from -http://sourceforge.net/projects/mingw-w64. Grab a copy of the -complete toolchain and unpack it somewhere. Put the bin directory of -the toolchain in your path. The mingw installs contain cross compile -versions of gcc that are named with a prefix to indicate what they are -targeting and you must tell the Makefile which one to use. This -should either be i586-mingw32msvc or x86_64-pc-mingw32 depending on -which one you are targeting and there should be a version of gcc in -your path named i586-mingw32msvc-gcc or x86_64-pc-mingw32-gcc. Tell -the makefile what prefix to use to find the mingw tools by using -MINGW=. For example: - -make MINGW=i586-mingw32msvc BINUTILS=build/binutils-2.31.1 - -will build the Win32 cross compiled version of hsdis based on 2.31.1. +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 -Products are named like build/$OS-$LIBARCH/hsdis-$LIBARCH.so. You can -install them next to your libjvm.so inside your JRE/JDK or alternatively -put it anywhere on your LD_LIBRARY_PATH. The search path in the JVM is: +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". -1. /lib//libhsdis-.so -2. /lib//hsdis-.so -3. /lib/hsdis-.so -4. hsdis-.so (using LD_LIBRARY_PATH) +Note: The resulting build may not be distributable. Please get legal advice if +you intend to distribute the result of your build. -Now test: +* Using the library - export LD_LIBRARY_PATH .../hsdis/build/$OS-$LIBARCH:$LD_LIBRARY_PATH - dargs='-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly' - dargs=$dargs' -XX:PrintAssemblyOptions=hsdis-print-bytes' - java $dargs -Xbatch CompileCommand=print,*String.hashCode HelloWorld +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". -If the product mode of the JVM does not accept -XX:+PrintAssembly, -you do not have a version new enough to use the hsdis plugin. - -* Wiki - -More information can be found in the OpenJDK HotSpot Wiki [1]. - - -Resources: - -[1] https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly -[2] http://sourceware.org/bugzilla/show_bug.cgi?id=15345 +More information is available at the wiki +[https://wiki.openjdk.java.net/display/HotSpot/PrintAssembly]. diff --git a/src/utils/hsdis/hsdis-demo.c b/src/utils/hsdis/hsdis-demo.c deleted file mode 100644 index 0ab3018ed2b..00000000000 --- a/src/utils/hsdis/hsdis-demo.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2008, 2012, 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-demo.c -- dump a range of addresses as native instructions - This demonstrates the protocol required by the HotSpot PrintAssembly option. -*/ - -#include -#include -#include -#include - -#include "hsdis.h" - - -void greet(const char*); -void disassemble(uintptr_t, uintptr_t); -void end_of_file(); - -const char* options = NULL; -int raw = 0; -int xml = 0; - -int main(int ac, char** av) { - int greeted = 0; - int i; - for (i = 1; i < ac; i++) { - const char* arg = av[i]; - if (arg[0] == '-') { - if (!strcmp(arg, "-xml")) - xml ^= 1; - else if (!strcmp(arg, "-raw")) - raw ^= 1; - else if (!strncmp(arg, "-options=", 9)) - options = arg+9; - else - { printf("Usage: %s [-xml] [name...]\n", av[0]); exit(2); } - continue; - } - greet(arg); - greeted = 1; - } - if (!greeted) - greet("world"); - printf("...And now for something completely different:\n"); - void *start = (void*) &main; - void *end = (void*) &end_of_file; -#if defined(__ia64) || (defined(__powerpc__) && !defined(ABI_ELFv2)) - /* On IA64 and PPC function pointers are pointers to function descriptors */ - start = *((void**)start); - end = *((void**)end); -#endif - disassemble(start, (end > start) ? end : start + 64); - printf("Cheers!\n"); -} - -void greet(const char* whom) { - printf("Hello, %s!\n", whom); -} - -void end_of_file() { } - -/* don't disassemble after this point... */ - -#include "dlfcn.h" - -#define DECODE_INSTRUCTIONS_VIRTUAL_NAME "decode_instructions_virtual" -#define DECODE_INSTRUCTIONS_NAME "decode_instructions" -#define HSDIS_NAME "hsdis" -static void* decode_instructions_pv = 0; -static void* decode_instructions_sv = 0; -static const char* hsdis_path[] = { - HSDIS_NAME"-"LIBARCH LIB_EXT, - "./" HSDIS_NAME"-"LIBARCH LIB_EXT, -#ifdef TARGET_DIR - TARGET_DIR"/"HSDIS_NAME"-"LIBARCH LIB_EXT, -#endif - NULL -}; - -static const char* load_decode_instructions() { - void* dllib = NULL; - const char* *next_in_path = hsdis_path; - while (1) { - decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_VIRTUAL_NAME); - decode_instructions_sv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME); - if (decode_instructions_pv != NULL || decode_instructions_sv != NULL) - return NULL; - if (dllib != NULL) - return "plugin does not defined "DECODE_INSTRUCTIONS_VIRTUAL_NAME" and "DECODE_INSTRUCTIONS_NAME; - for (dllib = NULL; dllib == NULL; ) { - const char* next_lib = (*next_in_path++); - if (next_lib == NULL) - return "cannot find plugin "HSDIS_NAME LIB_EXT; - dllib = dlopen(next_lib, RTLD_LAZY); - } - } -} - - -static const char* lookup(void* addr) { -#if defined(__ia64) || defined(__powerpc__) - /* On IA64 and PPC function pointers are pointers to function descriptors */ -#define CHECK_NAME(fn) \ - if (addr == *((void**) &fn)) return #fn; -#else -#define CHECK_NAME(fn) \ - if (addr == (void*) &fn) return #fn; -#endif - - CHECK_NAME(main); - CHECK_NAME(greet); - return NULL; -} - -/* does the event match the tag, followed by a null, space, or slash? */ -#define MATCH(event, tag) \ - (!strncmp(event, tag, sizeof(tag)-1) && \ - (!event[sizeof(tag)-1] || strchr(" /", event[sizeof(tag)-1]))) - - -static const char event_cookie[] = "event_cookie"; /* demo placeholder */ -static void* simple_handle_event(void* cookie, const char* event, void* arg) { - if (MATCH(event, "/insn")) { - // follow each complete insn by a nice newline - printf("\n"); - } - return NULL; -} - -static void* handle_event(void* cookie, const char* event, void* arg) { -#define NS_DEMO "demo:" - if (cookie != event_cookie) - printf("*** bad event cookie %p != %p\n", cookie, event_cookie); - - if (xml) { - /* We could almost do a printf(event, arg), - but for the sake of a better demo, - we dress the result up as valid XML. - */ - const char* fmt = strchr(event, ' '); - int evlen = (fmt ? fmt - event : strlen(event)); - if (!fmt) { - if (event[0] != '/') { - printf("<"NS_DEMO"%.*s>", evlen, event); - } else { - printf("", evlen-1, event+1); - } - } else { - if (event[0] != '/') { - printf("<"NS_DEMO"%.*s", evlen, event); - printf(fmt, arg); - printf(">"); - } else { - printf("<"NS_DEMO"%.*s_done", evlen-1, event+1); - printf(fmt, arg); - printf("/>", evlen-1, event+1); - } - } - } - - if (MATCH(event, "insn")) { - const char* name = lookup(arg); - if (name) printf("%s:\n", name); - - /* basic action for : */ - printf(" %p\t", arg); - - } else if (MATCH(event, "/insn")) { - // follow each complete insn by a nice newline - printf("\n"); - } else if (MATCH(event, "mach")) { - printf("Decoding for CPU '%s'\n", (char*) arg); - - } else if (MATCH(event, "addr")) { - /* basic action for : */ - const char* name = lookup(arg); - if (name) { - printf("&%s (%p)", name, arg); - /* return non-null to notify hsdis not to print the addr */ - return arg; - } - } - - /* null return is always safe; can mean "I ignored it" */ - return NULL; -} - -#define fprintf_callback \ - (decode_instructions_printf_callback_ftype)&fprintf - -void disassemble(uintptr_t from, uintptr_t to) { - const char* err = load_decode_instructions(); - if (err != NULL) { - printf("%s: %s\n", err, dlerror()); - exit(1); - } - decode_func_vtype decode_instructions_v - = (decode_func_vtype) decode_instructions_pv; - decode_func_stype decode_instructions_s - = (decode_func_stype) decode_instructions_sv; - void* res; - if (decode_instructions_pv != NULL) { - printf("\nDecoding from %p to %p...with %s\n", from, to, DECODE_INSTRUCTIONS_VIRTUAL_NAME); - if (raw) { - res = (*decode_instructions_v)(from, to, - (unsigned char*)from, to - from, - simple_handle_event, stdout, - NULL, stdout, - options, 0); - } else { - res = (*decode_instructions_v)(from, to, - (unsigned char*)from, to - from, - handle_event, (void*) event_cookie, - fprintf_callback, stdout, - options, 0); - } - if (res != (void*)to) - printf("*** Result was %p!\n", res); - } - void* sres; - if (decode_instructions_sv != NULL) { - printf("\nDecoding from %p to %p...with old decode_instructions\n", from, to, DECODE_INSTRUCTIONS_NAME); - if (raw) { - sres = (*decode_instructions_s)(from, to, - simple_handle_event, stdout, - NULL, stdout, - options); - } else { - sres = (*decode_instructions_s)(from, to, - handle_event, (void*) event_cookie, - fprintf_callback, stdout, - options); - } - if (sres != (void *)to) - printf("*** Result of decode_instructions %p!\n", sres); - } -}