1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
31 * dlopen/dlsym to find the entry point in hsdis. All the rest is
32 * standard JNI code.
33 */
34
35 #ifdef _WINDOWS
36
37 #define snprintf _snprintf
38 #define vsnprintf _vsnprintf
39
40 #include <windows.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #ifdef _DEBUG
44 #include <crtdbg.h>
45 #endif
46
47 #else
48
49 #include <string.h>
50 #include <dlfcn.h>
51 #include <link.h>
52
53 #endif
54
55 #include <limits.h>
56 #include <stdio.h>
57 #include <stdarg.h>
58 #include <stdlib.h>
59 #include <errno.h>
60
61 #ifdef _WINDOWS
62 static int getLastErrorString(char *buf, size_t len)
63 {
64 long errval;
65
66 if ((errval = GetLastError()) != 0)
67 {
68 /* DOS error */
69 size_t n = (size_t)FormatMessage(
70 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
71 NULL,
92 if (n >= len) n = len - 1;
93 strncpy(buf, s, n);
94 buf[n] = '\0';
95 return (int)n;
96 }
97 return 0;
98 }
99 #endif /* _WINDOWS */
100
101 /*
102 * Class: sun_jvm_hotspot_asm_Disassembler
103 * Method: load_library
104 * Signature: (Ljava/lang/String;)L
105 */
106 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
107 jclass disclass,
108 jstring jrepath_s,
109 jstring libname_s) {
110 uintptr_t func = 0;
111 const char* error_message = NULL;
112 const char* java_home;
113 jboolean isCopy;
114 uintptr_t *handle = NULL;
115
116 const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
117 const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
118 char buffer[128];
119
120 /* Load the hsdis library */
121 #ifdef _WINDOWS
122 HINSTANCE hsdis_handle;
123 hsdis_handle = LoadLibrary(libname);
124 if (hsdis_handle == NULL) {
125 snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
126 hsdis_handle = LoadLibrary(buffer);
127 }
128 if (hsdis_handle != NULL) {
129 func = (uintptr_t)GetProcAddress(hsdis_handle, "decode_instructions_virtual");
130 }
131 if (func == 0) {
132 getLastErrorString(buffer, sizeof(buffer));
133 error_message = buffer;
134 }
150 (*env)->ReleaseStringUTFChars(env, libname_s, libname);
151 (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
152
153 if (func == 0) {
154 /* Couldn't find entry point. error_message should contain some
155 * platform dependent error message.
156 */
157 jclass eclass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
158 (*env)->ThrowNew(env, eclass, error_message);
159 }
160 return (jlong)func;
161 }
162
163 /* signature of decode_instructions_virtual from hsdis.h */
164 typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
165 unsigned char* start, uintptr_t length,
166 void* (*event_callback)(void*, const char*, void*),
167 void* event_stream,
168 int (*printf_callback)(void*, const char*, ...),
169 void* printf_stream,
170 const char* options);
171
172 /* container for call back state when decoding instructions */
173 typedef struct {
174 JNIEnv* env;
175 jobject dis;
176 jobject visitor;
177 jmethodID handle_event;
178 jmethodID raw_print;
179 char buffer[4096];
180 } decode_env;
181
182
183 /* event callback binding to Disassembler.handleEvent */
184 static void* event_to_env(void* env_pv, const char* event, void* arg) {
185 decode_env* denv = (decode_env*)env_pv;
186 JNIEnv* env = denv->env;
187 jstring event_string = (*env)->NewStringUTF(env, event);
188 jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
189 event_string, (jlong) (uintptr_t)arg);
190 if ((*env)->ExceptionOccurred(env) != NULL) {
264 denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
265 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
266 if ((*env)->ExceptionOccurred(env)) {
267 return;
268 }
269
270 /* find Disassembler.rawPrint callback */
271 denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
272 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
273 if ((*env)->ExceptionOccurred(env)) {
274 return;
275 }
276
277 /* decode the buffer */
278 (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
279 startPc + end - start,
280 (unsigned char*)start,
281 end - start,
282 &event_to_env, (void*) &denv,
283 &printf_to_env, (void*) &denv,
284 options);
285
286 /* cleanup */
287 (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
288 (*env)->ReleaseStringUTFChars(env, options_s, options);
289 }
|
1 /*
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
31 * dlopen/dlsym to find the entry point in hsdis. All the rest is
32 * standard JNI code.
33 */
34
35 #ifdef _WINDOWS
36
37 #define snprintf _snprintf
38 #define vsnprintf _vsnprintf
39
40 #include <windows.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #ifdef _DEBUG
44 #include <crtdbg.h>
45 #endif
46
47 #else
48
49 #include <string.h>
50 #include <dlfcn.h>
51
52 #ifndef __APPLE__
53 #include <link.h>
54 #endif
55
56 #endif
57
58 #include <limits.h>
59 #include <stdio.h>
60 #include <stdarg.h>
61 #include <stdlib.h>
62 #include <errno.h>
63
64 #ifdef _WINDOWS
65 static int getLastErrorString(char *buf, size_t len)
66 {
67 long errval;
68
69 if ((errval = GetLastError()) != 0)
70 {
71 /* DOS error */
72 size_t n = (size_t)FormatMessage(
73 FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
74 NULL,
95 if (n >= len) n = len - 1;
96 strncpy(buf, s, n);
97 buf[n] = '\0';
98 return (int)n;
99 }
100 return 0;
101 }
102 #endif /* _WINDOWS */
103
104 /*
105 * Class: sun_jvm_hotspot_asm_Disassembler
106 * Method: load_library
107 * Signature: (Ljava/lang/String;)L
108 */
109 JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
110 jclass disclass,
111 jstring jrepath_s,
112 jstring libname_s) {
113 uintptr_t func = 0;
114 const char* error_message = NULL;
115 jboolean isCopy;
116
117 const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/
118 const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy);
119 char buffer[128];
120
121 /* Load the hsdis library */
122 #ifdef _WINDOWS
123 HINSTANCE hsdis_handle;
124 hsdis_handle = LoadLibrary(libname);
125 if (hsdis_handle == NULL) {
126 snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname);
127 hsdis_handle = LoadLibrary(buffer);
128 }
129 if (hsdis_handle != NULL) {
130 func = (uintptr_t)GetProcAddress(hsdis_handle, "decode_instructions_virtual");
131 }
132 if (func == 0) {
133 getLastErrorString(buffer, sizeof(buffer));
134 error_message = buffer;
135 }
151 (*env)->ReleaseStringUTFChars(env, libname_s, libname);
152 (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath);
153
154 if (func == 0) {
155 /* Couldn't find entry point. error_message should contain some
156 * platform dependent error message.
157 */
158 jclass eclass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException");
159 (*env)->ThrowNew(env, eclass, error_message);
160 }
161 return (jlong)func;
162 }
163
164 /* signature of decode_instructions_virtual from hsdis.h */
165 typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
166 unsigned char* start, uintptr_t length,
167 void* (*event_callback)(void*, const char*, void*),
168 void* event_stream,
169 int (*printf_callback)(void*, const char*, ...),
170 void* printf_stream,
171 const char* options,
172 int newline);
173
174 /* container for call back state when decoding instructions */
175 typedef struct {
176 JNIEnv* env;
177 jobject dis;
178 jobject visitor;
179 jmethodID handle_event;
180 jmethodID raw_print;
181 char buffer[4096];
182 } decode_env;
183
184
185 /* event callback binding to Disassembler.handleEvent */
186 static void* event_to_env(void* env_pv, const char* event, void* arg) {
187 decode_env* denv = (decode_env*)env_pv;
188 JNIEnv* env = denv->env;
189 jstring event_string = (*env)->NewStringUTF(env, event);
190 jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
191 event_string, (jlong) (uintptr_t)arg);
192 if ((*env)->ExceptionOccurred(env) != NULL) {
266 denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent",
267 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J");
268 if ((*env)->ExceptionOccurred(env)) {
269 return;
270 }
271
272 /* find Disassembler.rawPrint callback */
273 denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint",
274 "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V");
275 if ((*env)->ExceptionOccurred(env)) {
276 return;
277 }
278
279 /* decode the buffer */
280 (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc,
281 startPc + end - start,
282 (unsigned char*)start,
283 end - start,
284 &event_to_env, (void*) &denv,
285 &printf_to_env, (void*) &denv,
286 options, 0 /* newline */);
287
288 /* cleanup */
289 (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
290 (*env)->ReleaseStringUTFChars(env, options_s, options);
291 }
|