]>
Commit | Line | Data |
---|---|---|
94f473ee KS |
1 | // jvmti.cc - JVMTI implementation |
2 | ||
3 | /* Copyright (C) 2006 Free Software Foundation | |
4 | ||
5 | This file is part of libgcj. | |
6 | ||
7 | This software is copyrighted work licensed under the terms of the | |
8 | Libgcj License. Please consult the file "LIBGCJ_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #include <config.h> | |
224aaa41 | 12 | #include <platform.h> |
94f473ee KS |
13 | |
14 | #include <jvm.h> | |
303f32cc KS |
15 | #include <java-threads.h> |
16 | #include <java-gc.h> | |
94f473ee KS |
17 | #include <jvmti.h> |
18 | ||
76b63f3c MW |
19 | #include <gcj/method.h> |
20 | ||
224aaa41 TT |
21 | #include <gnu/classpath/SystemProperties.h> |
22 | #include <gnu/gcj/runtime/BootClassLoader.h> | |
23 | #include <java/lang/Class.h> | |
24 | #include <java/lang/ClassLoader.h> | |
303f32cc | 25 | #include <java/lang/Thread.h> |
224aaa41 TT |
26 | #include <java/lang/Throwable.h> |
27 | #include <java/lang/VMClassLoader.h> | |
28 | #include <java/lang/reflect/Field.h> | |
29 | #include <java/lang/reflect/Modifier.h> | |
30 | #include <java/util/Collection.h> | |
31 | #include <java/util/HashMap.h> | |
32 | #include <java/net/URL.h> | |
33 | ||
34 | extern struct JNINativeInterface _Jv_JNIFunctions; | |
35 | ||
36 | struct _Jv_rawMonitorID | |
37 | { | |
38 | _Jv_Mutex_t mutex; | |
39 | _Jv_ConditionVariable_t condition; | |
40 | }; | |
303f32cc KS |
41 | |
42 | // Some commonly-used checks | |
43 | ||
44 | #define THREAD_DEFAULT_TO_CURRENT(jthread) \ | |
45 | if (jthread == NULL) jthread = java::lang::Thread::currentThread (); | |
46 | ||
47 | #define THREAD_CHECK_VALID(jthread) \ | |
48 | if (!java::lang::Thread::class$.isAssignableFrom (&(jthread->class$))) \ | |
49 | return JVMTI_ERROR_INVALID_THREAD; | |
50 | ||
51 | #define THREAD_CHECK_IS_ALIVE(thread) \ | |
52 | if (!thread->isAlive ()) return JVMTI_ERROR_THREAD_NOT_ALIVE; | |
53 | ||
224aaa41 TT |
54 | // FIXME: if current phase is not set in Phases, |
55 | // return JVMTI_ERROR_WRONG_PHASE | |
56 | #define REQUIRE_PHASE(Env, Phases) | |
57 | ||
58 | #define NULL_CHECK(Ptr) \ | |
59 | if (Ptr == NULL) return JVMTI_ERROR_NULL_POINTER; | |
60 | ||
3201e73d | 61 | static jvmtiError JNICALL |
303f32cc KS |
62 | _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) |
63 | { | |
64 | using namespace java::lang; | |
65 | ||
66 | THREAD_DEFAULT_TO_CURRENT (thread); | |
67 | THREAD_CHECK_VALID (thread); | |
68 | ||
69 | Thread *t = reinterpret_cast<Thread *> (thread); | |
70 | THREAD_CHECK_IS_ALIVE (t); | |
71 | ||
72 | _Jv_Thread_t *data = _Jv_ThreadGetData (t); | |
73 | _Jv_SuspendThread (data); | |
74 | return JVMTI_ERROR_NONE; | |
75 | } | |
76 | ||
3201e73d | 77 | static jvmtiError JNICALL |
303f32cc KS |
78 | _Jv_JVMTI_ResumeThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) |
79 | { | |
80 | using namespace java::lang; | |
81 | ||
82 | THREAD_DEFAULT_TO_CURRENT (thread); | |
83 | THREAD_CHECK_VALID (thread); | |
84 | ||
85 | Thread *t = reinterpret_cast<Thread *> (thread); | |
86 | THREAD_CHECK_IS_ALIVE (t); | |
87 | ||
88 | _Jv_Thread_t *data = _Jv_ThreadGetData (t); | |
89 | _Jv_ResumeThread (data); | |
90 | return JVMTI_ERROR_NONE; | |
91 | } | |
92 | ||
224aaa41 TT |
93 | static jvmtiError JNICALL |
94 | _Jv_JVMTI_InterruptThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) | |
95 | { | |
96 | using namespace java::lang; | |
97 | ||
98 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
99 | // FIXME: capability handling? 'can_signal_thread' | |
100 | if (thread == NULL) | |
101 | return JVMTI_ERROR_INVALID_THREAD; | |
102 | THREAD_CHECK_VALID (thread); | |
103 | Thread *real_thread = reinterpret_cast<Thread *> (thread); | |
104 | THREAD_CHECK_IS_ALIVE (real_thread); | |
105 | real_thread->interrupt(); | |
106 | return JVMTI_ERROR_NONE; | |
107 | } | |
108 | ||
109 | static jvmtiError JNICALL | |
110 | _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name, | |
111 | jrawMonitorID *result) | |
112 | { | |
113 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
114 | NULL_CHECK (name); | |
115 | NULL_CHECK (result); | |
116 | *result = (jrawMonitorID) _Jv_Malloc (sizeof (_Jv_rawMonitorID)); | |
117 | _Jv_MutexInit (&(*result)->mutex); | |
118 | _Jv_CondInit (&(*result)->condition); | |
119 | return JVMTI_ERROR_NONE; | |
120 | } | |
121 | ||
122 | static jvmtiError JNICALL | |
123 | _Jv_JVMTI_DestroyRawMonitor (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
124 | { | |
125 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
126 | // Note we have no better way of knowing whether this object is | |
127 | // really a raw monitor. | |
128 | if (monitor == NULL) | |
129 | return JVMTI_ERROR_INVALID_MONITOR; | |
130 | // FIXME: perform checks on monitor, release it if this thread owns | |
131 | // it. | |
132 | #ifdef _Jv_HaveMutexDestroy | |
133 | _Jv_MutexDestroy (&monitor->mutex); | |
134 | #endif | |
135 | _Jv_Free (monitor); | |
136 | return JVMTI_ERROR_NONE; | |
137 | } | |
138 | ||
139 | static jvmtiError JNICALL | |
140 | _Jv_JVMTI_RawMonitorEnter (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
141 | { | |
142 | if (monitor == NULL) | |
143 | return JVMTI_ERROR_INVALID_MONITOR; | |
144 | _Jv_MutexLock (&monitor->mutex); | |
145 | return JVMTI_ERROR_NONE; | |
146 | } | |
147 | ||
148 | static jvmtiError JNICALL | |
149 | _Jv_JVMTI_RawMonitorExit (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
150 | { | |
151 | if (monitor == NULL) | |
152 | return JVMTI_ERROR_INVALID_MONITOR; | |
153 | if (_Jv_MutexUnlock (&monitor->mutex)) | |
154 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
155 | return JVMTI_ERROR_NONE; | |
156 | } | |
157 | ||
158 | static jvmtiError JNICALL | |
59294c2b KS |
159 | _Jv_JVMTI_RawMonitorWait (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor, |
160 | jlong millis) | |
224aaa41 TT |
161 | { |
162 | if (monitor == NULL) | |
163 | return JVMTI_ERROR_INVALID_MONITOR; | |
59294c2b | 164 | int r = _Jv_CondWait (&monitor->condition, &monitor->mutex, millis, 0); |
224aaa41 TT |
165 | if (r == _JV_NOT_OWNER) |
166 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
167 | if (r == _JV_INTERRUPTED) | |
168 | return JVMTI_ERROR_INTERRUPT; | |
169 | return JVMTI_ERROR_NONE; | |
170 | } | |
171 | ||
172 | static jvmtiError JNICALL | |
173 | _Jv_JVMTI_RawMonitorNotify (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
174 | { | |
175 | if (monitor == NULL) | |
176 | return JVMTI_ERROR_INVALID_MONITOR; | |
177 | if (_Jv_CondNotify (&monitor->condition, &monitor->mutex) == _JV_NOT_OWNER) | |
178 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
179 | return JVMTI_ERROR_NONE; | |
180 | } | |
181 | ||
182 | static jvmtiError JNICALL | |
183 | _Jv_JVMTI_RawMonitorNotifyAll (MAYBE_UNUSED jvmtiEnv *env, | |
184 | jrawMonitorID monitor) | |
185 | { | |
186 | if (monitor == NULL) | |
187 | return JVMTI_ERROR_INVALID_MONITOR; | |
188 | if (_Jv_CondNotifyAll (&monitor->condition, &monitor->mutex) | |
189 | == _JV_NOT_OWNER) | |
190 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
191 | return JVMTI_ERROR_NONE; | |
192 | } | |
193 | ||
194 | static jvmtiError JNICALL | |
195 | _Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size, | |
196 | unsigned char **result) | |
197 | { | |
198 | if (size < 0) | |
199 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
200 | NULL_CHECK (result); | |
201 | if (size == 0) | |
202 | *result = NULL; | |
203 | else | |
204 | { | |
205 | *result = (unsigned char *) _Jv_MallocUnchecked (size); | |
206 | if (*result == NULL) | |
207 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
208 | } | |
209 | return JVMTI_ERROR_NONE; | |
210 | } | |
211 | ||
212 | static jvmtiError JNICALL | |
213 | _Jv_JVMTI_Deallocate (MAYBE_UNUSED jvmtiEnv *env, unsigned char *mem) | |
214 | { | |
215 | if (mem != NULL) | |
216 | _Jv_Free (mem); | |
217 | return JVMTI_ERROR_NONE; | |
218 | } | |
219 | ||
220 | static jvmtiError JNICALL | |
cb86b2b6 TT |
221 | _Jv_JVMTI_GetClassModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
222 | jint *mods) | |
224aaa41 TT |
223 | { |
224 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
225 | // Don't bother checking KLASS' type. | |
226 | if (klass == NULL) | |
227 | return JVMTI_ERROR_INVALID_CLASS; | |
228 | NULL_CHECK (mods); | |
229 | *mods = klass->getModifiers(); | |
230 | return JVMTI_ERROR_NONE; | |
231 | } | |
232 | ||
233 | static jvmtiError JNICALL | |
cb86b2b6 TT |
234 | _Jv_JVMTI_GetClassMethods (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
235 | jint *count_ptr, jmethodID **methods_ptr) | |
224aaa41 TT |
236 | { |
237 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
238 | // FIXME: capability can_maintain_original_method_order | |
239 | // Don't bother checking KLASS' type. | |
240 | if (klass == NULL) | |
241 | return JVMTI_ERROR_INVALID_CLASS; | |
242 | NULL_CHECK (count_ptr); | |
243 | NULL_CHECK (methods_ptr); | |
244 | *count_ptr = JvNumMethods(klass); | |
245 | ||
246 | *methods_ptr = (jmethodID *) _Jv_Malloc (*count_ptr * sizeof (jmethodID)); | |
247 | jmethodID start = JvGetFirstMethod (klass); | |
248 | for (jint i = 0; i < *count_ptr; ++i) | |
249 | // FIXME: correct? | |
250 | (*methods_ptr)[i] = start + i; | |
251 | ||
252 | return JVMTI_ERROR_NONE; | |
253 | } | |
254 | ||
255 | static jvmtiError JNICALL | |
cb86b2b6 TT |
256 | _Jv_JVMTI_IsInterface (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
257 | jboolean *result) | |
224aaa41 TT |
258 | { |
259 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
260 | if (klass == NULL) | |
261 | return JVMTI_ERROR_INVALID_CLASS; | |
262 | NULL_CHECK (result); | |
263 | *result = klass->isInterface(); | |
264 | return JVMTI_ERROR_NONE; | |
265 | } | |
266 | ||
267 | static jvmtiError JNICALL | |
cb86b2b6 TT |
268 | _Jv_JVMTI_IsArrayClass (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
269 | jboolean *result) | |
224aaa41 TT |
270 | { |
271 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
272 | if (klass == NULL) | |
273 | return JVMTI_ERROR_INVALID_CLASS; | |
274 | NULL_CHECK (result); | |
275 | *result = klass->isArray(); | |
276 | return JVMTI_ERROR_NONE; | |
277 | } | |
278 | ||
279 | static jvmtiError JNICALL | |
cb86b2b6 TT |
280 | _Jv_JVMTI_GetClassLoader (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
281 | jobject *result) | |
224aaa41 TT |
282 | { |
283 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
284 | if (klass == NULL) | |
285 | return JVMTI_ERROR_INVALID_CLASS; | |
286 | NULL_CHECK (result); | |
287 | *result = klass->getClassLoaderInternal(); | |
288 | return JVMTI_ERROR_NONE; | |
289 | } | |
290 | ||
291 | static jvmtiError JNICALL | |
cb86b2b6 TT |
292 | _Jv_JVMTI_GetObjectHashCode (MAYBE_UNUSED jvmtiEnv *env, jobject obj, |
293 | jint *result) | |
224aaa41 TT |
294 | { |
295 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
296 | if (obj == NULL) | |
297 | return JVMTI_ERROR_INVALID_OBJECT; | |
298 | NULL_CHECK (result); | |
299 | *result = _Jv_HashCode (obj); | |
300 | return JVMTI_ERROR_NONE; | |
301 | } | |
302 | ||
303 | static jvmtiError JNICALL | |
cb86b2b6 TT |
304 | _Jv_JVMTI_GetFieldModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
305 | jfieldID field, jint *result) | |
224aaa41 TT |
306 | { |
307 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
308 | if (klass == NULL) | |
309 | return JVMTI_ERROR_INVALID_CLASS; | |
310 | if (field == NULL) | |
311 | return JVMTI_ERROR_INVALID_FIELDID; | |
312 | NULL_CHECK (result); | |
313 | *result = field->getModifiers(); | |
314 | return JVMTI_ERROR_NONE; | |
315 | } | |
316 | ||
317 | static jvmtiError JNICALL | |
cb86b2b6 TT |
318 | _Jv_JVMTI_IsFieldSynthetic (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
319 | jfieldID field, jboolean *result) | |
224aaa41 TT |
320 | { |
321 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
322 | if (klass == NULL) | |
323 | return JVMTI_ERROR_INVALID_CLASS; | |
324 | if (field == NULL) | |
325 | return JVMTI_ERROR_INVALID_FIELDID; | |
326 | NULL_CHECK (result); | |
327 | ||
328 | // FIXME: capability can_get_synthetic_attribute | |
329 | *result = ((field->getModifiers() & java::lang::reflect::Modifier::SYNTHETIC) | |
330 | != 0); | |
331 | return JVMTI_ERROR_NONE; | |
332 | } | |
333 | ||
334 | static jvmtiError JNICALL | |
cb86b2b6 TT |
335 | _Jv_JVMTI_GetMethodModifiers (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
336 | jint *result) | |
224aaa41 TT |
337 | { |
338 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
339 | if (method == NULL) | |
340 | return JVMTI_ERROR_INVALID_METHODID; | |
341 | NULL_CHECK (result); | |
342 | ||
343 | // FIXME: mask off some internal bits... | |
344 | *result = method->accflags; | |
345 | return JVMTI_ERROR_NONE; | |
346 | } | |
347 | ||
348 | static jvmtiError JNICALL | |
cb86b2b6 TT |
349 | _Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
350 | jboolean *result) | |
224aaa41 TT |
351 | { |
352 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
353 | if (method == NULL) | |
354 | return JVMTI_ERROR_INVALID_METHODID; | |
355 | NULL_CHECK (result); | |
356 | ||
357 | *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0); | |
358 | return JVMTI_ERROR_NONE; | |
359 | } | |
360 | ||
361 | static jvmtiError JNICALL | |
cb86b2b6 TT |
362 | _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
363 | jboolean *result) | |
224aaa41 TT |
364 | { |
365 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
366 | if (method == NULL) | |
367 | return JVMTI_ERROR_INVALID_METHODID; | |
368 | NULL_CHECK (result); | |
369 | ||
370 | // FIXME capability can_get_synthetic_attribute | |
371 | ||
372 | *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC) | |
373 | != 0); | |
374 | return JVMTI_ERROR_NONE; | |
375 | } | |
376 | ||
377 | static jvmtiError JNICALL | |
cb86b2b6 | 378 | _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
379 | jobject init_loader, |
380 | jint *count_ptr, | |
381 | jclass **result_ptr) | |
382 | { | |
383 | using namespace java::lang; | |
384 | using namespace java::util; | |
385 | ||
386 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
387 | NULL_CHECK (count_ptr); | |
388 | NULL_CHECK (result_ptr); | |
389 | ||
390 | ClassLoader *loader = (ClassLoader *) init_loader; | |
391 | if (loader == NULL) | |
392 | loader = VMClassLoader::bootLoader; | |
393 | ||
394 | Collection *values = loader->loadedClasses->values(); | |
395 | jobjectArray array = values->toArray(); | |
396 | *count_ptr = array->length; | |
397 | jobject *elts = elements (array); | |
398 | jclass *result = (jclass *) _Jv_Malloc (*count_ptr * sizeof (jclass)); | |
399 | // FIXME: JNI references... | |
400 | memcpy (result, elts, *count_ptr * sizeof (jclass)); | |
401 | ||
402 | *result_ptr = result; | |
403 | ||
404 | return JVMTI_ERROR_NONE; | |
405 | } | |
406 | ||
407 | static jvmtiError JNICALL | |
cb86b2b6 | 408 | _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env) |
224aaa41 TT |
409 | { |
410 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
411 | _Jv_RunGC(); | |
412 | return JVMTI_ERROR_NONE; | |
413 | } | |
414 | ||
415 | static jvmtiError JNICALL | |
cb86b2b6 | 416 | _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
417 | const jniNativeInterface *function_table) |
418 | { | |
419 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
420 | NULL_CHECK (function_table); | |
421 | memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface)); | |
422 | return JVMTI_ERROR_NONE; | |
423 | } | |
424 | ||
425 | static jvmtiError JNICALL | |
cb86b2b6 | 426 | _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
427 | jniNativeInterface **function_table) |
428 | { | |
429 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
430 | NULL_CHECK (function_table); | |
431 | *function_table | |
432 | = (jniNativeInterface *) _Jv_Malloc (sizeof (jniNativeInterface)); | |
433 | memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface)); | |
434 | return JVMTI_ERROR_NONE; | |
435 | } | |
94f473ee | 436 | |
3201e73d | 437 | static jvmtiError JNICALL |
326d5132 KS |
438 | _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env) |
439 | { | |
440 | // All we need to do is free memory allocated by _Jv_GetJVMTIEnv | |
441 | _Jv_Free (env); | |
442 | return JVMTI_ERROR_NONE; | |
443 | } | |
444 | ||
224aaa41 | 445 | static jvmtiError JNICALL |
cb86b2b6 | 446 | _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property, |
224aaa41 TT |
447 | char **result) |
448 | { | |
449 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
450 | NULL_CHECK (property); | |
451 | NULL_CHECK (result); | |
452 | ||
453 | jstring name = JvNewStringUTF(property); | |
454 | jstring result_str = gnu::classpath::SystemProperties::getProperty(name); | |
455 | ||
456 | if (result_str == NULL) | |
457 | return JVMTI_ERROR_NOT_AVAILABLE; | |
458 | ||
459 | int len = JvGetStringUTFLength (result_str); | |
460 | *result = (char *) _Jv_Malloc (len + 1); | |
461 | JvGetStringUTFRegion (result_str, 0, result_str->length(), *result); | |
462 | (*result)[len] = '\0'; | |
463 | ||
464 | return JVMTI_ERROR_NONE; | |
465 | } | |
466 | ||
467 | static jvmtiError JNICALL | |
cb86b2b6 | 468 | _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property, |
224aaa41 TT |
469 | const char *value) |
470 | { | |
471 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD); | |
472 | ||
473 | NULL_CHECK (property); | |
474 | if (value == NULL) | |
475 | { | |
476 | // FIXME: When would a property not be writeable? | |
477 | return JVMTI_ERROR_NONE; | |
478 | } | |
479 | ||
480 | jstring prop_str = JvNewStringUTF(property); | |
481 | jstring value_str = JvNewStringUTF(value); | |
482 | gnu::classpath::SystemProperties::setProperty(prop_str, value_str); | |
483 | return JVMTI_ERROR_NONE; | |
484 | } | |
485 | ||
486 | static jvmtiError JNICALL | |
487 | _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr) | |
488 | { | |
489 | NULL_CHECK (nanos_ptr); | |
490 | *nanos_ptr = _Jv_platform_nanotime(); | |
491 | return JVMTI_ERROR_NONE; | |
492 | } | |
493 | ||
494 | static jvmtiError JNICALL | |
495 | _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env, | |
496 | jint *nprocessors_ptr) | |
497 | { | |
498 | NULL_CHECK (nprocessors_ptr); | |
499 | #ifdef _SC_NPROCESSORS_ONLN | |
500 | *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN); | |
501 | #else | |
502 | *nprocessors_ptr = 1; | |
503 | #endif | |
504 | return JVMTI_ERROR_NONE; | |
505 | } | |
506 | ||
507 | static jvmtiError JNICALL | |
cb86b2b6 TT |
508 | _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env, |
509 | const char *segment) | |
224aaa41 TT |
510 | { |
511 | using namespace java::lang; | |
512 | using namespace java::net; | |
513 | using namespace gnu::gcj::runtime; | |
514 | ||
515 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD); | |
516 | NULL_CHECK (segment); | |
517 | ||
518 | jstring str_segment = JvNewStringUTF(segment); | |
519 | URL *url; | |
520 | try | |
521 | { | |
522 | url = new URL(JvNewStringUTF("file"), NULL, str_segment); | |
523 | } | |
524 | catch (jthrowable ignore) | |
525 | { | |
526 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
527 | } | |
528 | ||
529 | BootClassLoader *loader = VMClassLoader::bootLoader; | |
530 | // Don't call this too early. | |
531 | // assert (loader != NULL); | |
532 | loader->addURL(url); | |
533 | return JVMTI_ERROR_NONE; | |
534 | } | |
535 | ||
536 | static jvmtiError JNICALL | |
537 | _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag, | |
538 | jboolean value) | |
539 | { | |
540 | switch (flag) | |
541 | { | |
542 | case JVMTI_VERBOSE_OTHER: | |
543 | case JVMTI_VERBOSE_GC: | |
544 | case JVMTI_VERBOSE_JNI: | |
545 | // Ignore. | |
546 | break; | |
547 | case JVMTI_VERBOSE_CLASS: | |
548 | gcj::verbose_class_flag = value; | |
549 | break; | |
550 | default: | |
551 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
552 | } | |
553 | return JVMTI_ERROR_NONE; | |
554 | } | |
555 | ||
556 | static jvmtiError JNICALL | |
cb86b2b6 TT |
557 | _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object, |
558 | jlong *result) | |
224aaa41 TT |
559 | { |
560 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
561 | if (object == NULL) | |
562 | return JVMTI_ERROR_INVALID_OBJECT; | |
563 | NULL_CHECK (result); | |
564 | ||
565 | jclass klass = object->getClass(); | |
566 | if (klass->isArray()) | |
567 | { | |
568 | jclass comp = klass->getComponentType(); | |
569 | jint base | |
cb86b2b6 TT |
570 | = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL, |
571 | klass->getComponentType()); | |
224aaa41 TT |
572 | // FIXME: correct for primitive types? |
573 | jint compSize = comp->size(); | |
574 | __JArray *array = (__JArray *) object; | |
575 | *result = base + array->length * compSize; | |
576 | } | |
577 | else | |
578 | { | |
579 | // Note that if OBJECT is a String then it may (if | |
580 | // str->data==str) take more space. Do we care? | |
581 | *result = klass->size(); | |
582 | } | |
583 | return JVMTI_ERROR_NONE; | |
584 | } | |
585 | ||
586 | #define RESERVED NULL | |
587 | #define UNIMPLEMENTED NULL | |
588 | ||
94f473ee KS |
589 | struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = |
590 | { | |
591 | RESERVED, // reserved1 | |
592 | UNIMPLEMENTED, // SetEventNotification | |
593 | RESERVED, // reserved3 | |
594 | UNIMPLEMENTED, // GetAllThreads | |
303f32cc KS |
595 | _Jv_JVMTI_SuspendThread, // SuspendThread |
596 | _Jv_JVMTI_ResumeThread, // ResumeThread | |
94f473ee | 597 | UNIMPLEMENTED, // StopThread |
224aaa41 | 598 | _Jv_JVMTI_InterruptThread, // InterruptThread |
94f473ee KS |
599 | UNIMPLEMENTED, // GetThreadInfo |
600 | UNIMPLEMENTED, // GetOwnedMonitorInfo | |
601 | UNIMPLEMENTED, // GetCurrentContendedMonitor | |
602 | UNIMPLEMENTED, // RunAgentThread | |
603 | UNIMPLEMENTED, // GetTopThreadGroups | |
604 | UNIMPLEMENTED, // GetThreadGroupInfo | |
605 | UNIMPLEMENTED, // GetThreadGroupChildren | |
606 | UNIMPLEMENTED, // GetFrameCount | |
607 | UNIMPLEMENTED, // GetThreadState | |
608 | RESERVED, // reserved18 | |
609 | UNIMPLEMENTED, // GetFrameLocation | |
610 | UNIMPLEMENTED, // NotifyPopFrame | |
611 | UNIMPLEMENTED, // GetLocalObject | |
612 | UNIMPLEMENTED, // GetLocalInt | |
613 | UNIMPLEMENTED, // GetLocalLong | |
614 | UNIMPLEMENTED, // GetLocalFloat | |
615 | UNIMPLEMENTED, // GetLocalDouble | |
616 | UNIMPLEMENTED, // SetLocalObject | |
617 | UNIMPLEMENTED, // SetLocalInt | |
618 | UNIMPLEMENTED, // SetLocalLong | |
619 | UNIMPLEMENTED, // SetLocalFloat | |
620 | UNIMPLEMENTED, // SetLocalDouble | |
224aaa41 TT |
621 | _Jv_JVMTI_CreateRawMonitor, // CreateRawMonitor |
622 | _Jv_JVMTI_DestroyRawMonitor, // DestroyRawMonitor | |
623 | _Jv_JVMTI_RawMonitorEnter, // RawMonitorEnter | |
624 | _Jv_JVMTI_RawMonitorExit, // RawMonitorExit | |
625 | _Jv_JVMTI_RawMonitorWait, // RawMonitorWait | |
626 | _Jv_JVMTI_RawMonitorNotify, // RawMonitorNotify | |
627 | _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll | |
94f473ee | 628 | UNIMPLEMENTED, // SetBreakpoint |
224aaa41 | 629 | UNIMPLEMENTED, // ClearBreakpoint |
94f473ee KS |
630 | RESERVED, // reserved40 |
631 | UNIMPLEMENTED, // SetFieldAccessWatch | |
632 | UNIMPLEMENTED, // ClearFieldAccessWatch | |
633 | UNIMPLEMENTED, // SetFieldModificationWatch | |
634 | UNIMPLEMENTED, // ClearFieldModificationWatch | |
635 | RESERVED, // reserved45 | |
224aaa41 TT |
636 | _Jv_JVMTI_Allocate, // Allocate |
637 | _Jv_JVMTI_Deallocate, // Deallocate | |
94f473ee KS |
638 | UNIMPLEMENTED, // GetClassSignature |
639 | UNIMPLEMENTED, // GetClassStatus | |
640 | UNIMPLEMENTED, // GetSourceFileName | |
224aaa41 TT |
641 | _Jv_JVMTI_GetClassModifiers, // GetClassModifiers |
642 | _Jv_JVMTI_GetClassMethods, // GetClassMethods | |
94f473ee KS |
643 | UNIMPLEMENTED, // GetClassFields |
644 | UNIMPLEMENTED, // GetImplementedInterfaces | |
224aaa41 TT |
645 | _Jv_JVMTI_IsInterface, // IsInterface |
646 | _Jv_JVMTI_IsArrayClass, // IsArrayClass | |
647 | _Jv_JVMTI_GetClassLoader, // GetClassLoader | |
648 | _Jv_JVMTI_GetObjectHashCode, // GetObjectHashCode | |
94f473ee KS |
649 | UNIMPLEMENTED, // GetObjectMonitorUsage |
650 | UNIMPLEMENTED, // GetFieldName | |
651 | UNIMPLEMENTED, // GetFieldDeclaringClass | |
224aaa41 TT |
652 | _Jv_JVMTI_GetFieldModifiers, // GetFieldModifiers |
653 | _Jv_JVMTI_IsFieldSynthetic, // IsFieldSynthetic | |
94f473ee KS |
654 | UNIMPLEMENTED, // GetMethodName |
655 | UNIMPLEMENTED, // GetMethodDeclaringClass | |
224aaa41 | 656 | _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers |
94f473ee KS |
657 | RESERVED, // reserved67 |
658 | UNIMPLEMENTED, // GetMaxLocals | |
659 | UNIMPLEMENTED, // GetArgumentsSize | |
660 | UNIMPLEMENTED, // GetLineNumberTable | |
661 | UNIMPLEMENTED, // GetMethodLocation | |
662 | UNIMPLEMENTED, // GetLocalVariableTable | |
663 | RESERVED, // reserved73 | |
664 | RESERVED, // reserved74 | |
665 | UNIMPLEMENTED, // GetBytecodes | |
224aaa41 TT |
666 | _Jv_JVMTI_IsMethodNative, // IsMethodNative |
667 | _Jv_JVMTI_IsMethodSynthetic, // IsMethodSynthetic | |
94f473ee | 668 | UNIMPLEMENTED, // GetLoadedClasses |
224aaa41 | 669 | _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses |
94f473ee KS |
670 | UNIMPLEMENTED, // PopFrame |
671 | RESERVED, // reserved81 | |
672 | RESERVED, // reserved82 | |
673 | RESERVED, // reserved83 | |
674 | RESERVED, // reserved84 | |
675 | RESERVED, // reserved85 | |
676 | RESERVED, // reserved86 | |
677 | UNIMPLEMENTED, // RedefineClasses | |
678 | UNIMPLEMENTED, // GetVersionNumber | |
679 | UNIMPLEMENTED, // GetCapabilities | |
680 | UNIMPLEMENTED, // GetSourceDebugExtension | |
681 | UNIMPLEMENTED, // IsMethodObsolete | |
682 | UNIMPLEMENTED, // SuspendThreadList | |
683 | UNIMPLEMENTED, // ResumeThreadList | |
684 | RESERVED, // reserved94 | |
685 | RESERVED, // reserved95 | |
686 | RESERVED, // reserved96 | |
687 | RESERVED, // reserved97 | |
688 | RESERVED, // reserved98 | |
689 | RESERVED, // reserved99 | |
690 | UNIMPLEMENTED, // GetAllStackTraces | |
691 | UNIMPLEMENTED, // GetThreadListStackTraces | |
692 | UNIMPLEMENTED, // GetThreadLocalStorage | |
693 | UNIMPLEMENTED, // SetThreadLocalStorage | |
694 | UNIMPLEMENTED, // GetStackTrace | |
695 | RESERVED, // reserved105 | |
696 | UNIMPLEMENTED, // GetTag | |
697 | UNIMPLEMENTED, // SetTag | |
224aaa41 | 698 | _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection |
94f473ee KS |
699 | UNIMPLEMENTED, // IterateOverObjectsReachable |
700 | UNIMPLEMENTED, // IterateOverReachableObjects | |
701 | UNIMPLEMENTED, // IterateOverHeap | |
702 | UNIMPLEMENTED, // IterateOverInstanceOfClass | |
703 | RESERVED, // reserved113 | |
704 | UNIMPLEMENTED, // GetObjectsWithTags | |
705 | RESERVED, // reserved115 | |
706 | RESERVED, // reserved116 | |
707 | RESERVED, // reserved117 | |
708 | RESERVED, // reserved118 | |
709 | RESERVED, // reserved119 | |
224aaa41 TT |
710 | _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable |
711 | _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable | |
94f473ee KS |
712 | UNIMPLEMENTED, // SetEventCallbacks |
713 | UNIMPLEMENTED, // GenerateEvents | |
714 | UNIMPLEMENTED, // GetExtensionFunctions | |
715 | UNIMPLEMENTED, // GetExtensionEvents | |
716 | UNIMPLEMENTED, // SetExtensionEventCallback | |
326d5132 | 717 | _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment |
94f473ee KS |
718 | UNIMPLEMENTED, // GetErrorName |
719 | UNIMPLEMENTED, // GetJLocationFormat | |
720 | UNIMPLEMENTED, // GetSystemProperties | |
224aaa41 TT |
721 | _Jv_JVMTI_GetSystemProperty, // GetSystemProperty |
722 | _Jv_JVMTI_SetSystemProperty, // SetSystemProperty | |
94f473ee KS |
723 | UNIMPLEMENTED, // GetPhase |
724 | UNIMPLEMENTED, // GetCurrentThreadCpuTimerInfo | |
725 | UNIMPLEMENTED, // GetCurrentThreadCpuTime | |
726 | UNIMPLEMENTED, // GetThreadCpuTimerInfo | |
727 | UNIMPLEMENTED, // GetThreadCpuTime | |
728 | UNIMPLEMENTED, // GetTimerInfo | |
224aaa41 | 729 | _Jv_JVMTI_GetTime, // GetTime |
94f473ee KS |
730 | UNIMPLEMENTED, // GetPotentialCapabilities |
731 | RESERVED, // reserved141 | |
732 | UNIMPLEMENTED, // AddCapabilities | |
733 | UNIMPLEMENTED, // RelinquishCapabilities | |
224aaa41 | 734 | _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors |
94f473ee KS |
735 | RESERVED, // reserved145 |
736 | RESERVED, // reserved146 | |
737 | UNIMPLEMENTED, // GetEnvironmentLocalStorage | |
738 | UNIMPLEMENTED, // SetEnvironmentLocalStorage | |
224aaa41 TT |
739 | _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch |
740 | _Jv_JVMTI_SetVerboseFlag, // SetVerboseFlag | |
94f473ee KS |
741 | RESERVED, // reserved151 |
742 | RESERVED, // reserved152 | |
743 | RESERVED, // reserved153 | |
224aaa41 | 744 | _Jv_JVMTI_GetObjectSize // GetObjectSize |
94f473ee KS |
745 | }; |
746 | ||
747 | _Jv_JVMTIEnv * | |
748 | _Jv_GetJVMTIEnv (void) | |
749 | { | |
750 | _Jv_JVMTIEnv *env | |
751 | = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv)); | |
752 | env->p = &_Jv_JVMTI_Interface; | |
753 | return env; | |
754 | } |