Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/agent/src/share/native/sadis.c
38806 views
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
*
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
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,
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,
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) {
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,
286
options, 0 /* newline */);
287
288
/* cleanup */
289
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
290
(*env)->ReleaseStringUTFChars(env, options_s, options);
291
}
292
293