aboutsummaryrefslogtreecommitdiff
path: root/src/share/tools
diff options
context:
space:
mode:
authorminqi <none@none>2012-09-24 12:44:00 -0700
committerminqi <none@none>2012-09-24 12:44:00 -0700
commit551e79061790e033b0e3bb7d459a8f6ff32e8491 (patch)
tree8e68390ff1705bb54e4c33642ef9d6061b29f038 /src/share/tools
parent5861f91be900f4946c6ff187d1d5a538bb731ba0 (diff)
downloadjdk8u_hotspot-551e79061790e033b0e3bb7d459a8f6ff32e8491.tar.gz
6879063: SA should use hsdis for disassembly
Summary: We should in SA to use hsdis for it like the JVM does to replace the current java based disassembler. Reviewed-by: twisti, jrose, sla Contributed-by: yumin.qi@oracle.com
Diffstat (limited to 'src/share/tools')
-rw-r--r--src/share/tools/hsdis/Makefile43
-rw-r--r--src/share/tools/hsdis/README10
-rw-r--r--src/share/tools/hsdis/hsdis-demo.c53
-rw-r--r--src/share/tools/hsdis/hsdis.c125
-rw-r--r--src/share/tools/hsdis/hsdis.h23
5 files changed, 177 insertions, 77 deletions
diff --git a/src/share/tools/hsdis/Makefile b/src/share/tools/hsdis/Makefile
index 19f9cdb58..3cfdf57e6 100644
--- a/src/share/tools/hsdis/Makefile
+++ b/src/share/tools/hsdis/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2012, 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
@@ -66,14 +66,18 @@ ARCH=i386
endif
CC = $(MINGW)-gcc
CONFIGURE_ARGS= --host=$(MINGW) --target=$(MINGW)
-else
+else #linux
CPU = $(shell uname -m)
ARCH1=$(CPU:x86_64=amd64)
ARCH=$(ARCH1:i686=i386)
-CFLAGS/i386 += -m32
-CFLAGS/sparc += -m32
+ifdef LP64
CFLAGS/sparcv9 += -m64
CFLAGS/amd64 += -m64
+else
+ARCH=$(ARCH1:amd64=i386)
+CFLAGS/i386 += -m32
+CFLAGS/sparc += -m32
+endif
CFLAGS += $(CFLAGS/$(ARCH))
CFLAGS += -fPIC
OS = linux
@@ -85,16 +89,41 @@ DLDFLAGS += -shared
LDFLAGS += -ldl
OUTFLAGS += -o $@
## OS = Windows ##
-else # !SunOS, !Linux => Windows
+else # !SunOS, !Linux => Darwin or Windows
+ifeq ($(OS),Darwin)
+CPU = $(shell uname -m)
+ARCH1=$(CPU:x86_64=amd64)
+ARCH=$(ARCH1:i686=i386)
+ifdef LP64
+CFLAGS/sparcv9 += -m64
+CFLAGS/amd64 += -m64
+else
+ARCH=$(ARCH1:amd64=i386)
+CFLAGS/i386 += -m32
+CFLAGS/sparc += -m32
+endif # LP64
+CFLAGS += $(CFLAGS/$(ARCH))
+CFLAGS += -fPIC
+OS = macosx
+LIB_EXT = .dylib
+CC = gcc
+CFLAGS += -O
+# CFLAGS += -DZ_PREFIX
+DLDFLAGS += -shared
+DLDFLAGS += -lz
+LDFLAGS += -ldl
+OUTFLAGS += -o $@
+else #Windows
OS = windows
CC = gcc
#CPPFLAGS += /D"WIN32" /D"_WINDOWS" /D"DEBUG" /D"NDEBUG"
CFLAGS += /nologo /MD /W3 /WX /O2 /Fo$(@:.dll=.obj) /Gi-
-CFLAGS += LIBARCH=\"$(LIBARCH)\""
+CFLAGS += LIBARCH=\"$(LIBARCH)\"
DLDFLAGS += /dll /subsystem:windows /incremental:no \
/export:decode_instruction
OUTFLAGS += /link /out:$@
LIB_EXT = .dll
+endif # Darwin
endif # Linux
endif # SunOS
@@ -118,7 +147,7 @@ else
BINUTILSDIR = $(shell cd $(BINUTILS);pwd)
endif
-CPPFLAGS += -I$(BINUTILSDIR)/include -I$(BINUTILS)/bfd -I$(TARGET_DIR)/bfd
+CPPFLAGS += -I$(BINUTILSDIR)/include -I$(BINUTILSDIR)/bfd -I$(TARGET_DIR)/bfd
CPPFLAGS += -DLIBARCH_$(LIBARCH) -DLIBARCH=\"$(LIBARCH)\" -DLIB_EXT=\"$(LIB_EXT)\"
TARGET_DIR = build/$(OS)-$(JDKARCH)
diff --git a/src/share/tools/hsdis/README b/src/share/tools/hsdis/README
index f3080cbfc..51caa4051 100644
--- a/src/share/tools/hsdis/README
+++ b/src/share/tools/hsdis/README
@@ -1,4 +1,4 @@
-Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2008, 2012, 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
@@ -38,8 +38,14 @@ copy of the software from http://directory.fsf.org/project/binutils or
one of it's mirrors. Builds targetting windows should use at least
2.19 and currently requires the use of a cross compiler.
+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.
+
The makefile looks for the sources in build/binutils or you can
-specify it's location to the makefile using BINTUILS=path. It will
+specify it's location to the makefile using BINUTILS=path. It will
configure binutils and build it first and then build and link the
disasembly adapter. Make all will build the default target for your
platform. If you platform support both 32 and 64 simultaneously then
diff --git a/src/share/tools/hsdis/hsdis-demo.c b/src/share/tools/hsdis/hsdis-demo.c
index e83a0425c..2f7b67d36 100644
--- a/src/share/tools/hsdis/hsdis-demo.c
+++ b/src/share/tools/hsdis/hsdis-demo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, 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
@@ -26,14 +26,16 @@
This demonstrates the protocol required by the HotSpot PrintAssembly option.
*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
#include "hsdis.h"
-#include "stdio.h"
-#include "stdlib.h"
-#include "string.h"
void greet(const char*);
-void disassemble(void*, void*);
+void disassemble(uintptr_t, uintptr_t);
void end_of_file();
const char* options = NULL;
@@ -62,7 +64,14 @@ int main(int ac, char** av) {
if (!greeted)
greet("world");
printf("...And now for something completely different:\n");
- disassemble((void*) &main, (void*) &end_of_file);
+ void *start = (void*) &main;
+ void *end = (void*) &end_of_file;
+#if defined(__ia64) || defined(__powerpc__)
+ /* 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");
}
@@ -76,7 +85,7 @@ void end_of_file() { }
#include "dlfcn.h"
-#define DECODE_INSTRUCTIONS_NAME "decode_instructions"
+#define DECODE_INSTRUCTIONS_NAME "decode_instructions_virtual"
#define HSDIS_NAME "hsdis"
static void* decode_instructions_pv = 0;
static const char* hsdis_path[] = {
@@ -108,8 +117,14 @@ static const char* load_decode_instructions() {
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);
@@ -123,6 +138,14 @@ static const char* lookup(void* addr) {
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)
@@ -162,10 +185,8 @@ static void* handle_event(void* cookie, const char* event, void* arg) {
printf(" %p\t", arg);
} else if (MATCH(event, "/insn")) {
- /* basic action for </insn>:
- (none, plugin puts the newline for us
- */
-
+ // follow each complete insn by a nice newline
+ printf("\n");
} else if (MATCH(event, "mach")) {
printf("Decoding for CPU '%s'\n", (char*) arg);
@@ -186,7 +207,7 @@ static void* handle_event(void* cookie, const char* event, void* arg) {
#define fprintf_callback \
(decode_instructions_printf_callback_ftype)&fprintf
-void disassemble(void* from, void* to) {
+void disassemble(uintptr_t from, uintptr_t to) {
const char* err = load_decode_instructions();
if (err != NULL) {
printf("%s: %s\n", err, dlerror());
@@ -197,15 +218,15 @@ void disassemble(void* from, void* to) {
= (decode_instructions_ftype) decode_instructions_pv;
void* res;
if (raw && xml) {
- res = (*decode_instructions)(from, to, NULL, stdout, NULL, stdout, options);
+ res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
} else if (raw) {
- res = (*decode_instructions)(from, to, NULL, NULL, NULL, stdout, options);
+ res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
} else {
- res = (*decode_instructions)(from, to,
+ res = (*decode_instructions)(from, to, (unsigned char*)from, to - from,
handle_event, (void*) event_cookie,
fprintf_callback, stdout,
options);
}
- if (res != to)
+ if (res != (void*)to)
printf("*** Result was %p!\n", res);
}
diff --git a/src/share/tools/hsdis/hsdis.c b/src/share/tools/hsdis/hsdis.c
index 8034ac15a..251344e0c 100644
--- a/src/share/tools/hsdis/hsdis.c
+++ b/src/share/tools/hsdis/hsdis.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, 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
@@ -27,13 +27,13 @@
HotSpot PrintAssembly option.
*/
-#include "hsdis.h"
-
-#include <sysdep.h>
#include <libiberty.h>
#include <bfd.h>
#include <dis-asm.h>
#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include "hsdis.h"
#ifndef bool
#define bool int
@@ -47,11 +47,15 @@ typedef decode_instructions_printf_callback_ftype printf_callback_t;
/* disassemble_info.application_data object */
struct hsdis_app_data {
- /* the arguments to decode_instructions */
- uintptr_t start; uintptr_t end;
+ /* virtual address of data */
+ uintptr_t start_va, end_va;
+ /* the instructions to be decoded */
+ unsigned char* buffer;
+ uintptr_t length;
event_callback_t event_callback; void* event_stream;
printf_callback_t printf_callback; void* printf_stream;
bool losing;
+ bool do_newline;
/* the architecture being disassembled */
const char* arch_name;
@@ -65,6 +69,8 @@ struct hsdis_app_data {
char insn_options[256];
};
+static void* decode(struct hsdis_app_data* app_data, const char* options);
+
#define DECL_APP_DATA(dinfo) \
struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data
@@ -89,59 +95,91 @@ void*
#ifdef DLL_ENTRY
DLL_ENTRY
#endif
-decode_instructions(void* start_pv, void* end_pv,
- event_callback_t event_callback_arg, void* event_stream_arg,
- printf_callback_t printf_callback_arg, void* printf_stream_arg,
- const char* options) {
+decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
+ unsigned char* buffer, uintptr_t length,
+ event_callback_t event_callback_arg, void* event_stream_arg,
+ printf_callback_t printf_callback_arg, void* printf_stream_arg,
+ const char* options) {
struct hsdis_app_data app_data;
memset(&app_data, 0, sizeof(app_data));
- app_data.start = (uintptr_t) start_pv;
- app_data.end = (uintptr_t) end_pv;
+ app_data.start_va = start_va;
+ app_data.end_va = end_va;
+ app_data.buffer = buffer;
+ app_data.length = length;
app_data.event_callback = event_callback_arg;
app_data.event_stream = event_stream_arg;
app_data.printf_callback = printf_callback_arg;
app_data.printf_stream = printf_stream_arg;
+ app_data.do_newline = false;
+
+ return decode(&app_data, options);
+}
+
+/* This is the compatability interface for older version of hotspot */
+void*
+#ifdef DLL_ENTRY
+ DLL_ENTRY
+#endif
+decode_instructions(void* start_pv, void* end_pv,
+ event_callback_t event_callback_arg, void* event_stream_arg,
+ printf_callback_t printf_callback_arg, void* printf_stream_arg,
+ const char* options) {
+ decode_instructions_virtual((uintptr_t)start_pv,
+ (uintptr_t)end_pv,
+ (unsigned char*)start_pv,
+ (uintptr_t)end_pv - (uintptr_t)start_pv,
+ event_callback_arg,
+ event_stream_arg,
+ printf_callback_arg,
+ printf_stream_arg,
+ options);
+}
- setup_app_data(&app_data, options);
+static void* decode(struct hsdis_app_data* app_data, const char* options) {
+ setup_app_data(app_data, options);
char buf[128];
{
/* now reload everything from app_data: */
- DECL_EVENT_CALLBACK(&app_data);
- DECL_PRINTF_CALLBACK(&app_data);
- uintptr_t start = app_data.start;
- uintptr_t end = app_data.end;
+ DECL_EVENT_CALLBACK(app_data);
+ DECL_PRINTF_CALLBACK(app_data);
+ uintptr_t start = app_data->start_va;
+ uintptr_t end = app_data->end_va;
uintptr_t p = start;
(*event_callback)(event_stream, "insns", (void*)start);
(*event_callback)(event_stream, "mach name='%s'",
- (void*) app_data.arch_info->printable_name);
- if (app_data.dinfo.bytes_per_line != 0) {
+ (void*) app_data->arch_info->printable_name);
+ if (app_data->dinfo.bytes_per_line != 0) {
(*event_callback)(event_stream, "format bytes-per-line='%p'/",
- (void*)(intptr_t) app_data.dinfo.bytes_per_line);
+ (void*)(intptr_t) app_data->dinfo.bytes_per_line);
}
- while (p < end && !app_data.losing) {
+ while (p < end && !app_data->losing) {
(*event_callback)(event_stream, "insn", (void*) p);
/* reset certain state, so we can read it with confidence */
- app_data.dinfo.insn_info_valid = 0;
- app_data.dinfo.branch_delay_insns = 0;
- app_data.dinfo.data_size = 0;
- app_data.dinfo.insn_type = 0;
+ app_data->dinfo.insn_info_valid = 0;
+ app_data->dinfo.branch_delay_insns = 0;
+ app_data->dinfo.data_size = 0;
+ app_data->dinfo.insn_type = 0;
- int size = (*app_data.dfn)((bfd_vma) p, &app_data.dinfo);
+ int size = (*app_data->dfn)((bfd_vma) p, &app_data->dinfo);
if (size > 0) p += size;
- else app_data.losing = true;
-
- const char* insn_close = format_insn_close("/insn", &app_data.dinfo,
- buf, sizeof(buf));
- (*event_callback)(event_stream, insn_close, (void*) p);
-
- /* follow each complete insn by a nice newline */
- (*printf_callback)(printf_stream, "\n");
+ else app_data->losing = true;
+
+ if (!app_data->losing) {
+ const char* insn_close = format_insn_close("/insn", &app_data->dinfo,
+ buf, sizeof(buf));
+ (*event_callback)(event_stream, insn_close, (void*) p) != NULL;
+
+ if (app_data->do_newline) {
+ /* follow each complete insn by a nice newline */
+ (*printf_callback)(printf_stream, "\n");
+ }
+ }
}
(*event_callback)(event_stream, "/insns", (void*) p);
@@ -150,7 +188,7 @@ decode_instructions(void* start_pv, void* end_pv,
}
/* take the address of the function, for luck, and also test the typedef: */
-const decode_instructions_ftype decode_instructions_address = &decode_instructions;
+const decode_instructions_ftype decode_instructions_address = &decode_instructions_virtual;
static const char* format_insn_close(const char* close,
disassemble_info* dinfo,
@@ -189,13 +227,14 @@ hsdis_read_memory_func(bfd_vma memaddr,
bfd_byte* myaddr,
unsigned int length,
struct disassemble_info* dinfo) {
- uintptr_t memaddr_p = (uintptr_t) memaddr;
DECL_APP_DATA(dinfo);
- if (memaddr_p + length > app_data->end) {
+ /* convert the virtual address memaddr into an address within memory buffer */
+ uintptr_t offset = ((uintptr_t) memaddr) - app_data->start_va;
+ if (offset + length > app_data->length) {
/* read is out of bounds */
return EIO;
} else {
- memcpy(myaddr, (bfd_byte*) memaddr_p, length);
+ memcpy(myaddr, (bfd_byte*) (app_data->buffer + offset), length);
return 0;
}
}
@@ -407,16 +446,16 @@ static const bfd_arch_info_type* find_arch_info(const char* arch_name) {
static const char* native_arch_name() {
const char* res = NULL;
#ifdef LIBARCH_i386
- res = "i386";
+ res = "i386";
#endif
#ifdef LIBARCH_amd64
- res = "i386:x86-64";
+ res = "i386:x86-64";
#endif
#ifdef LIBARCH_sparc
- res = "sparc:v8plusb";
+ res = "sparc:v8plusb";
#endif
#ifdef LIBARCH_sparcv9
- res = "sparc:v9b";
+ res = "sparc:v9b";
#endif
if (res == NULL)
res = "architecture not set in Makefile!";
@@ -468,7 +507,7 @@ static void parse_fake_insn(disassembler_ftype dfn,
dinfo->fprintf_func = &print_to_dev_null;
(*dfn)(0, dinfo);
- // put it back:
+ /* put it back */
dinfo->read_memory_func = read_memory_func;
dinfo->fprintf_func = fprintf_func;
}
diff --git a/src/share/tools/hsdis/hsdis.h b/src/share/tools/hsdis/hsdis.h
index d1b2dd964..5ab26ef08 100644
--- a/src/share/tools/hsdis/hsdis.h
+++ b/src/share/tools/hsdis/hsdis.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, 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
@@ -25,7 +25,10 @@
/* decode_instructions -- dump a range of addresses as native instructions
This implements the protocol required by the HotSpot PrintAssembly option.
- The starting and ending addresses are within the current process's address space.
+ The start_va, end_va is the virtual address the region of memory to
+ disasemble and buffer contains the instructions to decode,
+ Disassembling instructions in the current address space is done by
+ having start_va == buffer.
The option string, if not empty, is interpreted by the disassembler implementation.
@@ -48,18 +51,20 @@ extern
#ifdef DLL_EXPORT
DLL_EXPORT
#endif
-void* decode_instructions(void* start, void* end,
- void* (*event_callback)(void*, const char*, void*),
- void* event_stream,
- int (*printf_callback)(void*, const char*, ...),
- void* printf_stream,
- const char* options);
+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);
/* convenience typedefs */
typedef void* (*decode_instructions_event_callback_ftype) (void*, const char*, void*);
typedef int (*decode_instructions_printf_callback_ftype) (void*, const char*, ...);
-typedef void* (*decode_instructions_ftype) (void* start, void* end,
+typedef void* (*decode_instructions_ftype) (uintptr_t start_va, uintptr_t end_va,
+ unsigned char* buffer, uintptr_t length,
decode_instructions_event_callback_ftype event_callback,
void* event_stream,
decode_instructions_printf_callback_ftype printf_callback,