Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/native/libsaproc/sadis.c
41152 views
1
/*
2
* Copyright (c) 2012, 2021, 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
* disassembler. It should compile on Linux 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
// Disable CRT security warning against _snprintf
37
#pragma warning (disable : 4996)
38
39
#define snprintf _snprintf
40
#define vsnprintf _vsnprintf
41
42
#include <windows.h>
43
#include <sys/types.h>
44
#include <sys/stat.h>
45
#ifdef _DEBUG
46
#include <crtdbg.h>
47
#endif
48
49
#else
50
51
#include <string.h>
52
#include <dlfcn.h>
53
54
#ifndef __APPLE__
55
#include <link.h>
56
#endif
57
58
#endif
59
60
#include <limits.h>
61
#include <stdio.h>
62
#include <stdarg.h>
63
#include <stdlib.h>
64
#include <errno.h>
65
66
#ifdef _WINDOWS
67
#define JVM_MAXPATHLEN _MAX_PATH
68
#else
69
#include <sys/param.h>
70
#define JVM_MAXPATHLEN MAXPATHLEN
71
#endif
72
73
#include "jni_util.h"
74
75
76
/*
77
* Class: sun_jvm_hotspot_asm_Disassembler
78
* Method: load_library
79
* Signature: (Ljava/lang/String;)J
80
*/
81
JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env,
82
jclass disclass,
83
jstring libname_s) {
84
uintptr_t func = 0;
85
const char *error_message = NULL;
86
const char *libname = NULL;
87
88
#ifdef _WINDOWS
89
char buffer[JVM_MAXPATHLEN];
90
HINSTANCE hsdis_handle = (HINSTANCE) NULL;
91
#else
92
void* hsdis_handle = NULL;
93
#endif
94
95
libname = (*env)->GetStringUTFChars(env, libname_s, NULL);
96
if (libname == NULL || (*env)->ExceptionOccurred(env)) {
97
return 0;
98
}
99
100
/* Load the hsdis library */
101
#ifdef _WINDOWS
102
hsdis_handle = LoadLibrary(libname);
103
if (hsdis_handle != NULL) {
104
func = (uintptr_t)GetProcAddress(hsdis_handle, "decode_instructions_virtual");
105
}
106
if (func == 0) {
107
getLastErrorString(buffer, sizeof(buffer));
108
error_message = buffer;
109
}
110
#else
111
hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL);
112
if (hsdis_handle != NULL) {
113
func = (uintptr_t)dlsym(hsdis_handle, "decode_instructions_virtual");
114
}
115
if (func == 0) {
116
error_message = dlerror();
117
}
118
#endif
119
120
(*env)->ReleaseStringUTFChars(env, libname_s, libname);
121
122
if (func == 0) {
123
/* Couldn't find entry point. error_message should contain some
124
* platform dependent error message.
125
*/
126
jstring s = JNU_NewStringPlatform(env, error_message);
127
if (s != NULL) {
128
jobject x = JNU_NewObjectByName(env, "sun/jvm/hotspot/debugger/DebuggerException", "(Ljava/lang/String;)V", s);
129
if (x != NULL) {
130
(*env)->Throw(env, x);
131
}
132
}
133
}
134
return (jlong)func;
135
}
136
137
/* signature of decode_instructions_virtual from hsdis.h */
138
typedef void* (*decode_func)(uintptr_t start_va, uintptr_t end_va,
139
unsigned char* start, uintptr_t length,
140
void* (*event_callback)(void*, const char*, void*),
141
void* event_stream,
142
int (*printf_callback)(void*, const char*, ...),
143
void* printf_stream,
144
const char* options,
145
int newline);
146
147
/* container for call back state when decoding instructions */
148
typedef struct {
149
JNIEnv* env;
150
jobject dis;
151
jobject visitor;
152
jmethodID handle_event;
153
jmethodID raw_print;
154
char buffer[4096];
155
} decode_env;
156
157
158
/* event callback binding to Disassembler.handleEvent */
159
static void* event_to_env(void* env_pv, const char* event, void* arg) {
160
jlong result = 0;
161
decode_env* denv = (decode_env*)env_pv;
162
JNIEnv* env = denv->env;
163
jstring event_string = (*env)->NewStringUTF(env, event);
164
if ((*env)->ExceptionOccurred(env)) {
165
return NULL;
166
}
167
168
result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor,
169
event_string, (jlong) (uintptr_t)arg);
170
if ((*env)->ExceptionOccurred(env)) {
171
/* ignore exceptions for now */
172
(*env)->ExceptionClear(env);
173
return NULL;
174
}
175
176
return (void*)(uintptr_t)result;
177
}
178
179
/* printing callback binding to Disassembler.rawPrint */
180
static int printf_to_env(void* env_pv, const char* format, ...) {
181
jstring output;
182
va_list ap;
183
int cnt;
184
decode_env* denv = (decode_env*)env_pv;
185
JNIEnv* env = denv->env;
186
size_t flen = strlen(format);
187
const char* raw = NULL;
188
189
if (flen == 0) return 0;
190
if (flen < 2 ||
191
strchr(format, '%') == NULL) {
192
raw = format;
193
} else if (format[0] == '%' && format[1] == '%' &&
194
strchr(format+2, '%') == NULL) {
195
// happens a lot on machines with names like %foo
196
flen--;
197
raw = format+1;
198
}
199
if (raw != NULL) {
200
jstring output = (*env)->NewStringUTF(env, raw);
201
if (!(*env)->ExceptionOccurred(env)) {
202
/* make sure that UTF allocation doesn't cause OOM */
203
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
204
}
205
if ((*env)->ExceptionOccurred(env)) {
206
/* ignore exceptions for now */
207
(*env)->ExceptionClear(env);
208
}
209
return (int) flen;
210
}
211
va_start(ap, format);
212
cnt = vsnprintf(denv->buffer, sizeof(denv->buffer), format, ap);
213
va_end(ap);
214
215
output = (*env)->NewStringUTF(env, denv->buffer);
216
if (!(*env)->ExceptionOccurred(env)) {
217
/* make sure that UTF allocation doesn't cause OOM */
218
(*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output);
219
}
220
221
if ((*env)->ExceptionOccurred(env)) {
222
/* ignore exceptions for now */
223
(*env)->ExceptionClear(env);
224
}
225
226
return cnt;
227
}
228
229
/*
230
* Class: sun_jvm_hotspot_asm_Disassembler
231
* Method: decode
232
* Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V
233
*/
234
JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env,
235
jobject dis,
236
jobject visitor,
237
jlong startPc,
238
jbyteArray code,
239
jstring options_s,
240
jlong decode_instructions_virtual) {
241
jbyte *start = NULL;
242
jbyte *end = NULL;
243
jclass disclass = NULL;
244
const char *options = NULL;
245
decode_env denv;
246
247
start = (*env)->GetByteArrayElements(env, code, NULL);
248
if ((*env)->ExceptionOccurred(env)) {
249
return;
250
}
251
end = start + (*env)->GetArrayLength(env, code);
252
options = (*env)->GetStringUTFChars(env, options_s, NULL);
253
if ((*env)->ExceptionOccurred(env)) {
254
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
255
return;
256
}
257
disclass = (*env)->GetObjectClass(env, dis);
258
259
denv.env = env;
260
denv.dis = dis;
261
denv.visitor = visitor;
262
263
/* find Disassembler.handleEvent callback */
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
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
268
(*env)->ReleaseStringUTFChars(env, options_s, options);
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
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
277
(*env)->ReleaseStringUTFChars(env, options_s, options);
278
return;
279
}
280
281
/* decode the buffer */
282
(*(decode_func)(uintptr_t)decode_instructions_virtual)((uintptr_t) startPc,
283
startPc + end - start,
284
(unsigned char*)start,
285
end - start,
286
&event_to_env, (void*) &denv,
287
&printf_to_env, (void*) &denv,
288
options, 0 /* newline */);
289
290
/* cleanup */
291
(*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT);
292
(*env)->ReleaseStringUTFChars(env, options_s, options);
293
}
294
295