Mercurial > hg > truffle
annotate agent/src/share/native/sadis.c @ 9670:86fa3d9f9fdd
replaced RegisterFinalizerStub with use of RuntimeStubCall
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 13 May 2013 14:28:00 +0200 |
parents | 39432a1cefdd |
children |
rev | line source |
---|---|
6782 | 1 /* |
8750 | 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
6782 | 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 * | |
23 */ | |
24 | |
25 #include "sun_jvm_hotspot_asm_Disassembler.h" | |
26 | |
27 /* | |
28 * This file implements a binding between Java and the hsdis | |
29 * dissasembler. It should compile on Linux/Solaris and Windows. | |
30 * The only platform dependent pieces of the code for doing | |
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 | |
6838
7a40901e0d5c
8000332: SA ClassDump throws exception after permgen removal
minqi
parents:
6782
diff
changeset
|
49 #include <string.h> |
6782 | 50 #include <dlfcn.h> |
8750 | 51 |
52 #ifndef __APPLE__ | |
6782 | 53 #include <link.h> |
8750 | 54 #endif |
6782 | 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, | |
75 errval, | |
76 0, | |
77 buf, | |
78 (DWORD)len, | |
79 NULL); | |
80 if (n > 3) { | |
81 /* Drop final '.', CR, LF */ | |
82 if (buf[n - 1] == '\n') n--; | |
83 if (buf[n - 1] == '\r') n--; | |
84 if (buf[n - 1] == '.') n--; | |
85 buf[n] = '\0'; | |
86 } | |
87 return (int)n; | |
88 } | |
89 | |
90 if (errno != 0) | |
91 { | |
92 /* C runtime error that has no corresponding DOS error code */ | |
93 const char *s = strerror(errno); | |
94 size_t n = strlen(s); | |
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 } | |
136 #else | |
137 void* hsdis_handle; | |
138 hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); | |
139 if (hsdis_handle == NULL) { | |
140 snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname); | |
141 hsdis_handle = dlopen(buffer, RTLD_LAZY | RTLD_GLOBAL); | |
142 } | |
143 if (hsdis_handle != NULL) { | |
144 func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual"); | |
145 } | |
146 if (func == 0) { | |
147 error_message = dlerror(); | |
148 } | |
149 #endif | |
150 | |
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, | |
8750 | 171 const char* options, |
172 int newline); | |
6782 | 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) { | |
193 /* ignore exceptions for now */ | |
194 (*env)->ExceptionClear(env); | |
195 result = 0; | |
196 } | |
197 return (void*)(uintptr_t)result; | |
198 } | |
199 | |
200 /* printing callback binding to Disassembler.rawPrint */ | |
201 static int printf_to_env(void* env_pv, const char* format, ...) { | |
202 jstring output; | |
203 va_list ap; | |
204 int cnt; | |
205 decode_env* denv = (decode_env*)env_pv; | |
206 JNIEnv* env = denv->env; | |
207 size_t flen = strlen(format); | |
208 const char* raw = NULL; | |
209 | |
210 if (flen == 0) return 0; | |
211 if (flen < 2 || | |
212 strchr(format, '%') == NULL) { | |
213 raw = format; | |
214 } else if (format[0] == '%' && format[1] == '%' && | |
215 strchr(format+2, '%') == NULL) { | |
216 // happens a lot on machines with names like %foo | |
217 flen--; | |
218 raw = format+1; | |
219 } | |
220 if (raw != NULL) { | |
221 jstring output = (*env)->NewStringUTF(env, raw); | |
222 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); | |
223 if ((*env)->ExceptionOccurred(env) != NULL) { | |
224 /* ignore exceptions for now */ | |
225 (*env)->ExceptionClear(env); | |
226 } | |
227 return (int) flen; | |
228 } | |
229 va_start(ap, format); | |
230 cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap); | |
231 va_end(ap); | |
232 | |
233 output = (*env)->NewStringUTF(env, denv->buffer); | |
234 (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); | |
235 if ((*env)->ExceptionOccurred(env) != NULL) { | |
236 /* ignore exceptions for now */ | |
237 (*env)->ExceptionClear(env); | |
238 } | |
239 return cnt; | |
240 } | |
241 | |
242 /* | |
243 * Class: sun_jvm_hotspot_asm_Disassembler | |
244 * Method: decode | |
245 * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V | |
246 */ | |
247 JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env, | |
248 jobject dis, | |
249 jobject visitor, | |
250 jlong startPc, | |
251 jbyteArray code, | |
252 jstring options_s, | |
253 jlong decode_instructions_virtual) { | |
254 jboolean isCopy; | |
255 jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy); | |
256 jbyte* end = start + (*env)->GetArrayLength(env, code); | |
257 const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy); | |
258 jclass disclass = (*env)->GetObjectClass(env, dis); | |
259 | |
260 decode_env denv; | |
261 denv.env = env; | |
262 denv.dis = dis; | |
263 denv.visitor = visitor; | |
264 | |
265 /* find Disassembler.handleEvent callback */ | |
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, | |
8750 | 286 options, 0 /* newline */); |
6782 | 287 |
288 /* cleanup */ | |
289 (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT); | |
290 (*env)->ReleaseStringUTFChars(env, options_s, options); | |
291 } |