]>
Commit | Line | Data |
---|---|---|
94f473ee KS |
1 | // jvmti.cc - JVMTI implementation |
2 | ||
70686a71 | 3 | /* Copyright (C) 2006, 2007 Free Software Foundation |
94f473ee KS |
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> | |
444dd946 | 17 | #include <java-interp.h> |
94f473ee | 18 | #include <jvmti.h> |
ebf29cf6 | 19 | #include "jvmti-int.h" |
94f473ee | 20 | |
76b63f3c MW |
21 | #include <gcj/method.h> |
22 | ||
224aaa41 TT |
23 | #include <gnu/classpath/SystemProperties.h> |
24 | #include <gnu/gcj/runtime/BootClassLoader.h> | |
444dd946 KS |
25 | #include <gnu/gcj/jvmti/Breakpoint.h> |
26 | #include <gnu/gcj/jvmti/BreakpointManager.h> | |
27 | ||
224aaa41 TT |
28 | #include <java/lang/Class.h> |
29 | #include <java/lang/ClassLoader.h> | |
05794ce8 | 30 | #include <java/lang/OutOfMemoryError.h> |
303f32cc | 31 | #include <java/lang/Thread.h> |
05794ce8 | 32 | #include <java/lang/ThreadGroup.h> |
22099c59 | 33 | #include <java/lang/Thread$State.h> |
224aaa41 TT |
34 | #include <java/lang/Throwable.h> |
35 | #include <java/lang/VMClassLoader.h> | |
36 | #include <java/lang/reflect/Field.h> | |
37 | #include <java/lang/reflect/Modifier.h> | |
38 | #include <java/util/Collection.h> | |
39 | #include <java/util/HashMap.h> | |
d6df67ef KS |
40 | #include <java/util/concurrent/locks/Lock.h> |
41 | #include <java/util/concurrent/locks/ReentrantReadWriteLock.h> | |
224aaa41 TT |
42 | #include <java/net/URL.h> |
43 | ||
ebf29cf6 KS |
44 | static void check_enabled_events (void); |
45 | static void check_enabled_event (jvmtiEvent); | |
46 | ||
dc0aeb60 KS |
47 | namespace JVMTI |
48 | { | |
c6923d93 KS |
49 | // Is JVMTI enabled? (i.e., any jvmtiEnv created?) |
50 | bool enabled; | |
51 | ||
52 | // Event notifications | |
dc0aeb60 KS |
53 | bool VMInit = false; |
54 | bool VMDeath = false; | |
55 | bool ThreadStart = false; | |
56 | bool ThreadEnd = false; | |
57 | bool ClassFileLoadHook = false; | |
58 | bool ClassLoad = false; | |
59 | bool ClassPrepare = false; | |
60 | bool VMStart = false; | |
61 | bool Exception = false; | |
62 | bool ExceptionCatch = false; | |
63 | bool SingleStep = false; | |
64 | bool FramePop = false; | |
65 | bool Breakpoint = false; | |
66 | bool FieldAccess = false; | |
67 | bool FieldModification = false; | |
68 | bool MethodEntry = false; | |
69 | bool MethodExit = false; | |
70 | bool NativeMethodBind = false; | |
71 | bool CompiledMethodLoad = false; | |
72 | bool CompiledMethodUnload = false; | |
73 | bool DynamicCodeGenerated = false; | |
74 | bool DataDumpRequest = false; | |
75 | bool reserved72 = false; | |
76 | bool MonitorWait = false; | |
77 | bool MonitorWaited = false; | |
78 | bool MonitorContendedEnter = false; | |
79 | bool MonitorContendedEntered = false; | |
80 | bool reserved77 = false; | |
81 | bool reserved78 = false; | |
82 | bool reserved79 = false; | |
83 | bool reserved80 = false; | |
84 | bool GarbageCollectionStart = false; | |
85 | bool GarbageCollectionFinish = false; | |
86 | bool ObjectFree = false; | |
87 | bool VMObjectAlloc = false; | |
88 | }; | |
89 | ||
224aaa41 TT |
90 | extern struct JNINativeInterface _Jv_JNIFunctions; |
91 | ||
92 | struct _Jv_rawMonitorID | |
93 | { | |
94 | _Jv_Mutex_t mutex; | |
95 | _Jv_ConditionVariable_t condition; | |
96 | }; | |
303f32cc | 97 | |
e6789bef KS |
98 | /* A simple linked list of all JVMTI environments. Since |
99 | events must be delivered to environments in the order | |
100 | in which the environments were created, new environments | |
101 | are added to the end of the list. */ | |
102 | struct jvmti_env_list | |
103 | { | |
104 | jvmtiEnv *env; | |
105 | struct jvmti_env_list *next; | |
106 | }; | |
107 | static struct jvmti_env_list *_jvmtiEnvironments = NULL; | |
d6df67ef KS |
108 | static java::util::concurrent::locks:: |
109 | ReentrantReadWriteLock *_envListLock = NULL; | |
e6789bef KS |
110 | #define FOREACH_ENVIRONMENT(Ele) \ |
111 | for (Ele = _jvmtiEnvironments; Ele != NULL; Ele = Ele->next) | |
112 | ||
303f32cc KS |
113 | // Some commonly-used checks |
114 | ||
af91f02d | 115 | #define THREAD_DEFAULT_TO_CURRENT(Ajthread) \ |
a56913dd KS |
116 | do \ |
117 | { \ | |
af91f02d KS |
118 | if (Ajthread == NULL) \ |
119 | Ajthread = java::lang::Thread::currentThread (); \ | |
a56913dd KS |
120 | } \ |
121 | while (0) | |
303f32cc | 122 | |
af91f02d | 123 | #define THREAD_CHECK_VALID(Athread) \ |
a56913dd KS |
124 | do \ |
125 | { \ | |
af91f02d | 126 | if (!java::lang::Thread::class$.isAssignableFrom (&(Athread->class$))) \ |
a56913dd KS |
127 | return JVMTI_ERROR_INVALID_THREAD; \ |
128 | } \ | |
129 | while (0) | |
130 | ||
af91f02d | 131 | #define THREAD_CHECK_IS_ALIVE(Athread) \ |
a56913dd KS |
132 | do \ |
133 | { \ | |
af91f02d | 134 | if (!Athread->isAlive ()) \ |
a56913dd KS |
135 | return JVMTI_ERROR_THREAD_NOT_ALIVE; \ |
136 | } \ | |
137 | while (0) | |
303f32cc | 138 | |
224aaa41 TT |
139 | // FIXME: if current phase is not set in Phases, |
140 | // return JVMTI_ERROR_WRONG_PHASE | |
141 | #define REQUIRE_PHASE(Env, Phases) | |
142 | ||
a56913dd KS |
143 | #define NULL_CHECK(Ptr) \ |
144 | do \ | |
145 | { \ | |
146 | if (Ptr == NULL) \ | |
147 | return JVMTI_ERROR_NULL_POINTER; \ | |
148 | } \ | |
149 | while (0) | |
150 | ||
151 | #define ILLEGAL_ARGUMENT(Cond) \ | |
152 | do \ | |
153 | { \ | |
154 | if ((Cond)) \ | |
155 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; \ | |
156 | } \ | |
157 | while (0) | |
e6789bef | 158 | |
04ab4573 KG |
159 | #define CHECK_FOR_NATIVE_METHOD(AjmethodID) \ |
160 | do \ | |
161 | { \ | |
162 | jboolean is_native; \ | |
163 | jvmtiError jerr = env->IsMethodNative (AjmethodID, &is_native); \ | |
164 | if (jerr != JVMTI_ERROR_NONE) \ | |
165 | return jerr; \ | |
166 | if (is_native) \ | |
167 | return JVMTI_ERROR_NATIVE_METHOD; \ | |
168 | } \ | |
169 | while (0) | |
170 | ||
3201e73d | 171 | static jvmtiError JNICALL |
303f32cc KS |
172 | _Jv_JVMTI_SuspendThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) |
173 | { | |
174 | using namespace java::lang; | |
175 | ||
176 | THREAD_DEFAULT_TO_CURRENT (thread); | |
68254f23 KS |
177 | THREAD_CHECK_VALID (thread); |
178 | THREAD_CHECK_IS_ALIVE (thread); | |
303f32cc | 179 | |
68254f23 | 180 | _Jv_Thread_t *data = _Jv_ThreadGetData (thread); |
303f32cc KS |
181 | _Jv_SuspendThread (data); |
182 | return JVMTI_ERROR_NONE; | |
183 | } | |
184 | ||
3201e73d | 185 | static jvmtiError JNICALL |
303f32cc KS |
186 | _Jv_JVMTI_ResumeThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) |
187 | { | |
188 | using namespace java::lang; | |
189 | ||
190 | THREAD_DEFAULT_TO_CURRENT (thread); | |
68254f23 KS |
191 | THREAD_CHECK_VALID (thread); |
192 | THREAD_CHECK_IS_ALIVE (thread); | |
303f32cc | 193 | |
68254f23 | 194 | _Jv_Thread_t *data = _Jv_ThreadGetData (thread); |
303f32cc KS |
195 | _Jv_ResumeThread (data); |
196 | return JVMTI_ERROR_NONE; | |
197 | } | |
198 | ||
224aaa41 TT |
199 | static jvmtiError JNICALL |
200 | _Jv_JVMTI_InterruptThread (MAYBE_UNUSED jvmtiEnv *env, jthread thread) | |
201 | { | |
202 | using namespace java::lang; | |
203 | ||
204 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
205 | // FIXME: capability handling? 'can_signal_thread' | |
206 | if (thread == NULL) | |
207 | return JVMTI_ERROR_INVALID_THREAD; | |
af91f02d | 208 | |
68254f23 KS |
209 | THREAD_CHECK_VALID (thread); |
210 | THREAD_CHECK_IS_ALIVE (thread); | |
211 | thread->interrupt(); | |
224aaa41 TT |
212 | return JVMTI_ERROR_NONE; |
213 | } | |
214 | ||
ce359ed9 KG |
215 | // This method performs the common tasks to get and set variables of all types. |
216 | // It is called by the _Jv_JVMTI_Get/SetLocalInt/Object/.... methods. | |
217 | static jvmtiError | |
218 | getLocalFrame (jvmtiEnv *env, jthread thread, jint depth, jint slot, char type, | |
219 | _Jv_InterpFrame **iframe) | |
220 | { | |
221 | using namespace java::lang; | |
222 | ||
223 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
224 | ||
225 | ILLEGAL_ARGUMENT (depth < 0); | |
226 | ||
227 | THREAD_DEFAULT_TO_CURRENT (thread); | |
228 | THREAD_CHECK_VALID (thread); | |
229 | THREAD_CHECK_IS_ALIVE (thread); | |
230 | ||
231 | _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); | |
232 | ||
233 | for (int i = 0; i < depth; i++) | |
234 | { | |
235 | frame = frame->next; | |
236 | ||
237 | if (frame == NULL) | |
238 | return JVMTI_ERROR_NO_MORE_FRAMES; | |
239 | } | |
240 | ||
241 | if (frame->frame_type == frame_native) | |
242 | return JVMTI_ERROR_OPAQUE_FRAME; | |
243 | ||
244 | jint max_locals; | |
245 | jvmtiError jerr = env->GetMaxLocals (reinterpret_cast<jmethodID> | |
246 | (frame->self->get_method ()), | |
247 | &max_locals); | |
248 | if (jerr != JVMTI_ERROR_NONE) | |
249 | return jerr; | |
250 | ||
251 | _Jv_InterpFrame *tmp_iframe = reinterpret_cast<_Jv_InterpFrame *> (frame); | |
252 | ||
253 | // The second slot taken up by a long type is marked as type 'x' meaning it | |
254 | // is not valid for access since it holds only the 4 low bytes of the value. | |
255 | if (tmp_iframe->locals_type[slot] == 'x') | |
256 | return JVMTI_ERROR_INVALID_SLOT; | |
257 | ||
258 | if (tmp_iframe->locals_type[slot] != type) | |
259 | return JVMTI_ERROR_TYPE_MISMATCH; | |
260 | ||
261 | // Check for invalid slots, if the type is a long type, we must check that | |
262 | // the next slot is valid as well. | |
263 | if (slot < 0 || slot >= max_locals | |
264 | || ((type == 'l' || type == 'd') && slot + 1 >= max_locals)) | |
265 | return JVMTI_ERROR_INVALID_SLOT; | |
266 | ||
267 | *iframe = tmp_iframe; | |
268 | ||
269 | return JVMTI_ERROR_NONE; | |
270 | } | |
271 | ||
272 | static jvmtiError JNICALL | |
273 | _Jv_JVMTI_GetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
274 | jobject *value) | |
275 | { | |
276 | NULL_CHECK (value); | |
277 | ||
278 | _Jv_InterpFrame *frame; | |
279 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame); | |
280 | ||
281 | if (jerr != JVMTI_ERROR_NONE) | |
282 | return jerr; | |
283 | ||
284 | *value = frame->locals[slot].o; | |
285 | ||
286 | return JVMTI_ERROR_NONE; | |
287 | } | |
288 | ||
289 | static jvmtiError JNICALL | |
290 | _Jv_JVMTI_SetLocalObject (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
291 | jobject value) | |
292 | { | |
293 | _Jv_InterpFrame *frame; | |
294 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'o', &frame); | |
295 | ||
296 | if (jerr != JVMTI_ERROR_NONE) | |
297 | return jerr; | |
298 | ||
299 | frame->locals[slot].o = value; | |
300 | ||
301 | return JVMTI_ERROR_NONE; | |
302 | } | |
303 | ||
304 | static jvmtiError JNICALL | |
305 | _Jv_JVMTI_GetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
306 | jint *value) | |
307 | { | |
308 | NULL_CHECK (value); | |
309 | ||
310 | _Jv_InterpFrame *frame; | |
311 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame); | |
312 | ||
313 | if (jerr != JVMTI_ERROR_NONE) | |
314 | return jerr; | |
315 | ||
316 | *value = frame->locals[slot].i; | |
317 | ||
318 | return JVMTI_ERROR_NONE; | |
319 | } | |
320 | ||
321 | static jvmtiError JNICALL | |
322 | _Jv_JVMTI_SetLocalInt (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
323 | jint value) | |
324 | { | |
325 | _Jv_InterpFrame *frame; | |
326 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'i', &frame); | |
327 | ||
328 | if (jerr != JVMTI_ERROR_NONE) | |
329 | return jerr; | |
330 | ||
331 | frame->locals[slot].i = value; | |
332 | ||
333 | return JVMTI_ERROR_NONE; | |
334 | } | |
335 | ||
336 | static jvmtiError JNICALL | |
337 | _Jv_JVMTI_GetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
338 | jlong *value) | |
339 | { | |
340 | NULL_CHECK (value); | |
341 | ||
342 | _Jv_InterpFrame *frame; | |
343 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame); | |
344 | ||
345 | if (jerr != JVMTI_ERROR_NONE) | |
346 | return jerr; | |
347 | ||
348 | #if SIZEOF_VOID_P==8 | |
349 | *value = frame->locals[slot].l; | |
350 | #else | |
351 | _Jv_word2 val; | |
352 | val.ia[0] = frame->locals[slot].ia[0]; | |
353 | val.ia[1] = frame->locals[slot + 1].ia[0]; | |
354 | *value = val.l; | |
355 | #endif | |
356 | ||
357 | return JVMTI_ERROR_NONE; | |
358 | } | |
359 | ||
360 | static jvmtiError JNICALL | |
361 | _Jv_JVMTI_SetLocalLong (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
362 | jlong value) | |
363 | { | |
364 | _Jv_InterpFrame *frame; | |
365 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'l', &frame); | |
366 | ||
367 | if (jerr != JVMTI_ERROR_NONE) | |
368 | return jerr; | |
369 | ||
370 | #if SIZEOF_VOID_P==8 | |
371 | frame->locals[slot].l = value; | |
372 | #else | |
373 | _Jv_word2 val; | |
374 | val.l = value; | |
375 | frame->locals[slot].ia[0] = val.ia[0]; | |
376 | frame->locals[slot + 1].ia[0] = val.ia[1]; | |
377 | #endif | |
378 | ||
379 | return JVMTI_ERROR_NONE; | |
380 | } | |
381 | ||
382 | ||
383 | static jvmtiError JNICALL | |
384 | _Jv_JVMTI_GetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
385 | jfloat *value) | |
386 | { | |
387 | NULL_CHECK (value); | |
388 | ||
389 | _Jv_InterpFrame *frame; | |
390 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame); | |
391 | ||
392 | if (jerr != JVMTI_ERROR_NONE) | |
393 | return jerr; | |
394 | ||
395 | *value = frame->locals[slot].f; | |
396 | ||
397 | return JVMTI_ERROR_NONE; | |
398 | } | |
399 | ||
400 | static jvmtiError JNICALL | |
401 | _Jv_JVMTI_SetLocalFloat (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
402 | jfloat value) | |
403 | { | |
404 | _Jv_InterpFrame *frame; | |
405 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'f', &frame); | |
406 | ||
407 | if (jerr != JVMTI_ERROR_NONE) | |
408 | return jerr; | |
409 | ||
410 | frame->locals[slot].f = value; | |
411 | ||
412 | return JVMTI_ERROR_NONE; | |
413 | } | |
414 | ||
415 | ||
416 | static jvmtiError JNICALL | |
417 | _Jv_JVMTI_GetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
418 | jdouble *value) | |
419 | { | |
420 | NULL_CHECK (value); | |
421 | ||
422 | _Jv_InterpFrame *frame; | |
423 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame); | |
424 | ||
425 | if (jerr != JVMTI_ERROR_NONE) | |
426 | return jerr; | |
427 | ||
428 | #if SIZEOF_VOID_P==8 | |
429 | *value = frame->locals[slot].d; | |
430 | #else | |
431 | _Jv_word2 val; | |
432 | val.ia[0] = frame->locals[slot].ia[0]; | |
433 | val.ia[1] = frame->locals[slot + 1].ia[0]; | |
434 | *value = val.d; | |
435 | #endif | |
436 | ||
437 | return JVMTI_ERROR_NONE; | |
438 | } | |
439 | ||
440 | static jvmtiError JNICALL | |
441 | _Jv_JVMTI_SetLocalDouble (jvmtiEnv *env, jthread thread, jint depth, jint slot, | |
442 | jdouble value) | |
443 | { | |
444 | _Jv_InterpFrame *frame; | |
445 | jvmtiError jerr = getLocalFrame (env, thread, depth, slot, 'd', &frame); | |
446 | ||
447 | if (jerr != JVMTI_ERROR_NONE) | |
448 | return jerr; | |
449 | ||
450 | #if SIZEOF_VOID_P==8 | |
451 | frame->locals[slot].d = value; | |
452 | #else | |
453 | _Jv_word2 val; | |
454 | val.d = value; | |
455 | frame->locals[slot].ia[0] = val.ia[0]; | |
456 | frame->locals[slot + 1].ia[0] = val.ia[1]; | |
457 | #endif | |
458 | ||
459 | return JVMTI_ERROR_NONE; | |
460 | } | |
461 | ||
70686a71 | 462 | static jvmtiError JNICALL |
05794ce8 KG |
463 | _Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt, |
464 | jthread **threads) | |
465 | { | |
466 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
467 | NULL_CHECK (thread_cnt); | |
468 | NULL_CHECK (threads); | |
469 | ||
470 | using namespace java::lang; | |
05794ce8 KG |
471 | |
472 | ThreadGroup *root_grp = ThreadGroup::root; | |
473 | jint estimate = root_grp->activeCount (); | |
474 | ||
475 | JArray<Thread *> *thr_arr; | |
476 | ||
477 | // Allocate some extra space since threads can be created between calls | |
478 | try | |
479 | { | |
70686a71 MT |
480 | thr_arr = reinterpret_cast<JArray<Thread *> *> (JvNewObjectArray |
481 | ((estimate * 2), | |
482 | &Thread::class$, NULL)); | |
05794ce8 KG |
483 | } |
484 | catch (java::lang::OutOfMemoryError *err) | |
485 | { | |
486 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
487 | } | |
488 | ||
489 | *thread_cnt = root_grp->enumerate (thr_arr); | |
490 | ||
491 | jvmtiError jerr = env->Allocate ((jlong) ((*thread_cnt) * sizeof (jthread)), | |
492 | (unsigned char **) threads); | |
493 | ||
494 | if (jerr != JVMTI_ERROR_NONE) | |
495 | return jerr; | |
496 | ||
497 | // Transfer the threads to the result array | |
498 | jthread *tmp_arr = reinterpret_cast<jthread *> (elements (thr_arr)); | |
499 | ||
500 | memcpy ((*threads), tmp_arr, (*thread_cnt)); | |
501 | ||
502 | return JVMTI_ERROR_NONE; | |
503 | } | |
504 | ||
39273131 KG |
505 | static jvmtiError JNICALL |
506 | _Jv_JVMTI_GetFrameCount (MAYBE_UNUSED jvmtiEnv *env, jthread thread, | |
9606c9dd | 507 | jint *frame_count) |
39273131 KG |
508 | { |
509 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
510 | ||
511 | NULL_CHECK (frame_count); | |
512 | ||
513 | using namespace java::lang; | |
514 | ||
515 | THREAD_DEFAULT_TO_CURRENT (thread); | |
9606c9dd KS |
516 | THREAD_CHECK_VALID (thread); |
517 | THREAD_CHECK_IS_ALIVE (thread); | |
39273131 | 518 | |
9606c9dd | 519 | _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); |
896b1c87 | 520 | (*frame_count) = frame->depth (); |
39273131 KG |
521 | return JVMTI_ERROR_NONE; |
522 | } | |
523 | ||
22099c59 KS |
524 | static jvmtiError JNICALL |
525 | _Jv_JVMTI_GetThreadState (MAYBE_UNUSED jvmtiEnv *env, jthread thread, | |
526 | jint *thread_state_ptr) | |
527 | { | |
528 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
529 | ||
530 | THREAD_DEFAULT_TO_CURRENT (thread); | |
531 | THREAD_CHECK_VALID (thread); | |
532 | NULL_CHECK (thread_state_ptr); | |
533 | ||
534 | jint state = 0; | |
535 | if (thread->isAlive ()) | |
536 | { | |
537 | state |= JVMTI_THREAD_STATE_ALIVE; | |
538 | ||
539 | _Jv_Thread_t *data = _Jv_ThreadGetData (thread); | |
540 | if (_Jv_IsThreadSuspended (data)) | |
541 | state |= JVMTI_THREAD_STATE_SUSPENDED; | |
542 | ||
543 | if (thread->isInterrupted ()) | |
544 | state |= JVMTI_THREAD_STATE_INTERRUPTED; | |
545 | ||
546 | _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); | |
547 | if (frame != NULL && frame->frame_type == frame_native) | |
548 | state |= JVMTI_THREAD_STATE_IN_NATIVE; | |
549 | ||
550 | using namespace java::lang; | |
551 | Thread$State *ts = thread->getState (); | |
552 | if (ts == Thread$State::RUNNABLE) | |
553 | state |= JVMTI_THREAD_STATE_RUNNABLE; | |
554 | else if (ts == Thread$State::BLOCKED) | |
555 | state |= JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER; | |
556 | else if (ts == Thread$State::TIMED_WAITING | |
557 | || ts == Thread$State::WAITING) | |
558 | { | |
559 | state |= JVMTI_THREAD_STATE_WAITING; | |
560 | state |= ((ts == Thread$State::WAITING) | |
561 | ? JVMTI_THREAD_STATE_WAITING_INDEFINITELY | |
562 | : JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT); | |
563 | ||
564 | /* FIXME: We don't have a way to tell | |
565 | the caller why the thread is suspended, | |
566 | i.e., JVMTI_THREAD_STATE_SLEEPING, | |
567 | JVMTI_THREAD_STATE_PARKED, and | |
568 | JVMTI_THREAD_STATE_IN_OBJECT_WAIT | |
569 | are never set. */ | |
570 | } | |
571 | } | |
572 | else | |
573 | { | |
574 | using namespace java::lang; | |
575 | Thread$State *ts = thread->getState (); | |
576 | if (ts == Thread$State::TERMINATED) | |
577 | state |= JVMTI_THREAD_STATE_TERMINATED; | |
578 | } | |
579 | ||
580 | *thread_state_ptr = state; | |
581 | return JVMTI_ERROR_NONE; | |
582 | } | |
583 | ||
224aaa41 TT |
584 | static jvmtiError JNICALL |
585 | _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name, | |
586 | jrawMonitorID *result) | |
587 | { | |
588 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
589 | NULL_CHECK (name); | |
590 | NULL_CHECK (result); | |
e853e26e KS |
591 | *result = (jrawMonitorID) _Jv_MallocUnchecked (sizeof (_Jv_rawMonitorID)); |
592 | if (*result == NULL) | |
593 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
224aaa41 TT |
594 | _Jv_MutexInit (&(*result)->mutex); |
595 | _Jv_CondInit (&(*result)->condition); | |
596 | return JVMTI_ERROR_NONE; | |
597 | } | |
598 | ||
599 | static jvmtiError JNICALL | |
600 | _Jv_JVMTI_DestroyRawMonitor (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
601 | { | |
602 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
603 | // Note we have no better way of knowing whether this object is | |
604 | // really a raw monitor. | |
605 | if (monitor == NULL) | |
606 | return JVMTI_ERROR_INVALID_MONITOR; | |
607 | // FIXME: perform checks on monitor, release it if this thread owns | |
608 | // it. | |
609 | #ifdef _Jv_HaveMutexDestroy | |
610 | _Jv_MutexDestroy (&monitor->mutex); | |
611 | #endif | |
612 | _Jv_Free (monitor); | |
613 | return JVMTI_ERROR_NONE; | |
614 | } | |
615 | ||
616 | static jvmtiError JNICALL | |
617 | _Jv_JVMTI_RawMonitorEnter (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
618 | { | |
619 | if (monitor == NULL) | |
620 | return JVMTI_ERROR_INVALID_MONITOR; | |
621 | _Jv_MutexLock (&monitor->mutex); | |
622 | return JVMTI_ERROR_NONE; | |
623 | } | |
624 | ||
625 | static jvmtiError JNICALL | |
626 | _Jv_JVMTI_RawMonitorExit (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
627 | { | |
628 | if (monitor == NULL) | |
629 | return JVMTI_ERROR_INVALID_MONITOR; | |
630 | if (_Jv_MutexUnlock (&monitor->mutex)) | |
631 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
632 | return JVMTI_ERROR_NONE; | |
633 | } | |
634 | ||
635 | static jvmtiError JNICALL | |
59294c2b KS |
636 | _Jv_JVMTI_RawMonitorWait (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor, |
637 | jlong millis) | |
224aaa41 TT |
638 | { |
639 | if (monitor == NULL) | |
640 | return JVMTI_ERROR_INVALID_MONITOR; | |
59294c2b | 641 | int r = _Jv_CondWait (&monitor->condition, &monitor->mutex, millis, 0); |
224aaa41 TT |
642 | if (r == _JV_NOT_OWNER) |
643 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
644 | if (r == _JV_INTERRUPTED) | |
645 | return JVMTI_ERROR_INTERRUPT; | |
646 | return JVMTI_ERROR_NONE; | |
647 | } | |
648 | ||
649 | static jvmtiError JNICALL | |
650 | _Jv_JVMTI_RawMonitorNotify (MAYBE_UNUSED jvmtiEnv *env, jrawMonitorID monitor) | |
651 | { | |
652 | if (monitor == NULL) | |
653 | return JVMTI_ERROR_INVALID_MONITOR; | |
654 | if (_Jv_CondNotify (&monitor->condition, &monitor->mutex) == _JV_NOT_OWNER) | |
655 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
656 | return JVMTI_ERROR_NONE; | |
657 | } | |
658 | ||
659 | static jvmtiError JNICALL | |
660 | _Jv_JVMTI_RawMonitorNotifyAll (MAYBE_UNUSED jvmtiEnv *env, | |
661 | jrawMonitorID monitor) | |
662 | { | |
663 | if (monitor == NULL) | |
664 | return JVMTI_ERROR_INVALID_MONITOR; | |
665 | if (_Jv_CondNotifyAll (&monitor->condition, &monitor->mutex) | |
666 | == _JV_NOT_OWNER) | |
667 | return JVMTI_ERROR_NOT_MONITOR_OWNER; | |
668 | return JVMTI_ERROR_NONE; | |
669 | } | |
670 | ||
444dd946 KS |
671 | static jvmtiError JNICALL |
672 | _Jv_JVMTI_SetBreakpoint (jvmtiEnv *env, jmethodID method, jlocation location) | |
673 | { | |
674 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
675 | ||
676 | using namespace gnu::gcj::jvmti; | |
677 | Breakpoint *bp | |
678 | = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method), | |
679 | location); | |
680 | if (bp == NULL) | |
681 | { | |
682 | jclass klass; | |
683 | jvmtiError err = env->GetMethodDeclaringClass (method, &klass); | |
684 | if (err != JVMTI_ERROR_NONE) | |
685 | return err; | |
686 | ||
687 | if (!_Jv_IsInterpretedClass (klass)) | |
688 | return JVMTI_ERROR_INVALID_CLASS; | |
689 | ||
690 | _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method); | |
691 | if (base == NULL) | |
692 | return JVMTI_ERROR_INVALID_METHODID; | |
693 | ||
694 | jint flags; | |
695 | err = env->GetMethodModifiers (method, &flags); | |
696 | if (err != JVMTI_ERROR_NONE) | |
697 | return err; | |
698 | ||
699 | if (flags & java::lang::reflect::Modifier::NATIVE) | |
700 | return JVMTI_ERROR_NATIVE_METHOD; | |
701 | ||
702 | _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base); | |
703 | if (imeth->get_insn (location) == NULL) | |
704 | return JVMTI_ERROR_INVALID_LOCATION; | |
705 | ||
706 | // Now the breakpoint can be safely installed | |
707 | bp = BreakpointManager::newBreakpoint (reinterpret_cast<jlong> (method), | |
708 | location); | |
709 | } | |
710 | else | |
711 | { | |
712 | // Duplicate breakpoints are not permitted by JVMTI | |
713 | return JVMTI_ERROR_DUPLICATE; | |
714 | } | |
715 | ||
716 | return JVMTI_ERROR_NONE; | |
717 | } | |
718 | ||
719 | static jvmtiError JNICALL | |
720 | _Jv_JVMTI_ClearBreakpoint (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, | |
721 | jlocation location) | |
722 | { | |
723 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
724 | ||
725 | using namespace gnu::gcj::jvmti; | |
726 | ||
727 | Breakpoint *bp | |
728 | = BreakpointManager::getBreakpoint (reinterpret_cast<jlong> (method), | |
729 | location); | |
730 | if (bp == NULL) | |
731 | return JVMTI_ERROR_NOT_FOUND; | |
732 | ||
733 | BreakpointManager::deleteBreakpoint (reinterpret_cast<jlong> (method), location); | |
734 | return JVMTI_ERROR_NONE; | |
735 | } | |
736 | ||
224aaa41 TT |
737 | static jvmtiError JNICALL |
738 | _Jv_JVMTI_Allocate (MAYBE_UNUSED jvmtiEnv *env, jlong size, | |
739 | unsigned char **result) | |
740 | { | |
e6789bef | 741 | ILLEGAL_ARGUMENT (size < 0); |
224aaa41 TT |
742 | NULL_CHECK (result); |
743 | if (size == 0) | |
744 | *result = NULL; | |
745 | else | |
746 | { | |
747 | *result = (unsigned char *) _Jv_MallocUnchecked (size); | |
748 | if (*result == NULL) | |
749 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
750 | } | |
751 | return JVMTI_ERROR_NONE; | |
752 | } | |
753 | ||
754 | static jvmtiError JNICALL | |
755 | _Jv_JVMTI_Deallocate (MAYBE_UNUSED jvmtiEnv *env, unsigned char *mem) | |
756 | { | |
757 | if (mem != NULL) | |
758 | _Jv_Free (mem); | |
759 | return JVMTI_ERROR_NONE; | |
760 | } | |
761 | ||
2b3c6788 KS |
762 | static jvmtiError JNICALL |
763 | _Jv_JVMTI_GetClassStatus (MAYBE_UNUSED jvmtiEnv *env, jclass klass, | |
764 | jint *status_ptr) | |
765 | { | |
766 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
767 | NULL_CHECK (status_ptr); | |
768 | if (klass == NULL) | |
769 | return JVMTI_ERROR_INVALID_CLASS; | |
770 | ||
771 | if (klass->isArray ()) | |
772 | *status_ptr = JVMTI_CLASS_STATUS_ARRAY; | |
773 | else if (klass->isPrimitive ()) | |
774 | *status_ptr = JVMTI_CLASS_STATUS_PRIMITIVE; | |
775 | else | |
776 | { | |
777 | jbyte state = _Jv_GetClassState (klass); | |
778 | *status_ptr = 0; | |
779 | if (state >= JV_STATE_LINKED) | |
780 | (*status_ptr) |= JVMTI_CLASS_STATUS_VERIFIED; | |
781 | if (state >= JV_STATE_PREPARED) | |
782 | (*status_ptr) |= JVMTI_CLASS_STATUS_PREPARED; | |
783 | if (state == JV_STATE_ERROR || state == JV_STATE_PHANTOM) | |
784 | (*status_ptr) |= JVMTI_CLASS_STATUS_ERROR; | |
785 | else if (state == JV_STATE_DONE) | |
786 | (*status_ptr) |= JVMTI_CLASS_STATUS_INITIALIZED; | |
787 | } | |
788 | ||
789 | return JVMTI_ERROR_NONE; | |
790 | } | |
791 | ||
224aaa41 | 792 | static jvmtiError JNICALL |
cb86b2b6 TT |
793 | _Jv_JVMTI_GetClassModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
794 | jint *mods) | |
224aaa41 TT |
795 | { |
796 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
797 | // Don't bother checking KLASS' type. | |
798 | if (klass == NULL) | |
799 | return JVMTI_ERROR_INVALID_CLASS; | |
800 | NULL_CHECK (mods); | |
801 | *mods = klass->getModifiers(); | |
802 | return JVMTI_ERROR_NONE; | |
803 | } | |
804 | ||
805 | static jvmtiError JNICALL | |
cb86b2b6 TT |
806 | _Jv_JVMTI_GetClassMethods (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
807 | jint *count_ptr, jmethodID **methods_ptr) | |
224aaa41 TT |
808 | { |
809 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
810 | // FIXME: capability can_maintain_original_method_order | |
811 | // Don't bother checking KLASS' type. | |
812 | if (klass == NULL) | |
813 | return JVMTI_ERROR_INVALID_CLASS; | |
814 | NULL_CHECK (count_ptr); | |
815 | NULL_CHECK (methods_ptr); | |
816 | *count_ptr = JvNumMethods(klass); | |
817 | ||
e853e26e KS |
818 | *methods_ptr |
819 | = (jmethodID *) _Jv_MallocUnchecked (*count_ptr * sizeof (jmethodID)); | |
820 | if (*methods_ptr == NULL) | |
821 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
822 | ||
224aaa41 TT |
823 | jmethodID start = JvGetFirstMethod (klass); |
824 | for (jint i = 0; i < *count_ptr; ++i) | |
825 | // FIXME: correct? | |
826 | (*methods_ptr)[i] = start + i; | |
827 | ||
828 | return JVMTI_ERROR_NONE; | |
829 | } | |
830 | ||
831 | static jvmtiError JNICALL | |
cb86b2b6 TT |
832 | _Jv_JVMTI_IsInterface (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
833 | jboolean *result) | |
224aaa41 TT |
834 | { |
835 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
836 | if (klass == NULL) | |
837 | return JVMTI_ERROR_INVALID_CLASS; | |
838 | NULL_CHECK (result); | |
839 | *result = klass->isInterface(); | |
840 | return JVMTI_ERROR_NONE; | |
841 | } | |
842 | ||
843 | static jvmtiError JNICALL | |
cb86b2b6 TT |
844 | _Jv_JVMTI_IsArrayClass (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
845 | jboolean *result) | |
224aaa41 TT |
846 | { |
847 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
848 | if (klass == NULL) | |
849 | return JVMTI_ERROR_INVALID_CLASS; | |
850 | NULL_CHECK (result); | |
851 | *result = klass->isArray(); | |
852 | return JVMTI_ERROR_NONE; | |
853 | } | |
854 | ||
855 | static jvmtiError JNICALL | |
cb86b2b6 TT |
856 | _Jv_JVMTI_GetClassLoader (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
857 | jobject *result) | |
224aaa41 TT |
858 | { |
859 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
860 | if (klass == NULL) | |
861 | return JVMTI_ERROR_INVALID_CLASS; | |
862 | NULL_CHECK (result); | |
863 | *result = klass->getClassLoaderInternal(); | |
864 | return JVMTI_ERROR_NONE; | |
865 | } | |
866 | ||
867 | static jvmtiError JNICALL | |
cb86b2b6 TT |
868 | _Jv_JVMTI_GetObjectHashCode (MAYBE_UNUSED jvmtiEnv *env, jobject obj, |
869 | jint *result) | |
224aaa41 TT |
870 | { |
871 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
872 | if (obj == NULL) | |
873 | return JVMTI_ERROR_INVALID_OBJECT; | |
874 | NULL_CHECK (result); | |
875 | *result = _Jv_HashCode (obj); | |
876 | return JVMTI_ERROR_NONE; | |
877 | } | |
878 | ||
879 | static jvmtiError JNICALL | |
cb86b2b6 TT |
880 | _Jv_JVMTI_GetFieldModifiers (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
881 | jfieldID field, jint *result) | |
224aaa41 TT |
882 | { |
883 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
884 | if (klass == NULL) | |
885 | return JVMTI_ERROR_INVALID_CLASS; | |
886 | if (field == NULL) | |
887 | return JVMTI_ERROR_INVALID_FIELDID; | |
888 | NULL_CHECK (result); | |
889 | *result = field->getModifiers(); | |
890 | return JVMTI_ERROR_NONE; | |
891 | } | |
892 | ||
893 | static jvmtiError JNICALL | |
cb86b2b6 TT |
894 | _Jv_JVMTI_IsFieldSynthetic (MAYBE_UNUSED jvmtiEnv *env, jclass klass, |
895 | jfieldID field, jboolean *result) | |
224aaa41 TT |
896 | { |
897 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
898 | if (klass == NULL) | |
899 | return JVMTI_ERROR_INVALID_CLASS; | |
900 | if (field == NULL) | |
901 | return JVMTI_ERROR_INVALID_FIELDID; | |
902 | NULL_CHECK (result); | |
903 | ||
904 | // FIXME: capability can_get_synthetic_attribute | |
905 | *result = ((field->getModifiers() & java::lang::reflect::Modifier::SYNTHETIC) | |
906 | != 0); | |
907 | return JVMTI_ERROR_NONE; | |
908 | } | |
909 | ||
ff393407 KS |
910 | static jvmtiError JNICALL |
911 | _Jv_JVMTI_GetMethodName (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, | |
912 | char **name_ptr, char **signature_ptr, | |
913 | char **generic_ptr) | |
914 | { | |
915 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
916 | ||
917 | if (method == NULL) | |
918 | return JVMTI_ERROR_INVALID_METHODID; | |
919 | ||
920 | if (name_ptr != NULL) | |
921 | { | |
922 | int len = static_cast<int> (method->name->len ()); | |
923 | *name_ptr = (char *) _Jv_MallocUnchecked (len + 1); | |
924 | if (*name_ptr == NULL) | |
925 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
926 | strncpy (*name_ptr, method->name->chars (), len); | |
927 | (*name_ptr)[len] = '\0'; | |
928 | } | |
929 | ||
930 | if (signature_ptr != NULL) | |
931 | { | |
932 | int len = static_cast<int> (method->signature->len ()); | |
933 | *signature_ptr = (char *) _Jv_MallocUnchecked (len + 1); | |
934 | if (*signature_ptr == NULL) | |
935 | { | |
936 | if (name_ptr != NULL) | |
937 | _Jv_Free (*name_ptr); | |
938 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
939 | } | |
940 | strncpy (*signature_ptr, method->signature->chars (), len); | |
941 | (*signature_ptr)[len] = '\0'; | |
942 | } | |
943 | ||
944 | if (generic_ptr != NULL) | |
945 | { | |
946 | *generic_ptr = NULL; | |
947 | } | |
948 | ||
949 | return JVMTI_ERROR_NONE; | |
950 | } | |
951 | ||
224aaa41 | 952 | static jvmtiError JNICALL |
cb86b2b6 TT |
953 | _Jv_JVMTI_GetMethodModifiers (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
954 | jint *result) | |
224aaa41 TT |
955 | { |
956 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
957 | if (method == NULL) | |
958 | return JVMTI_ERROR_INVALID_METHODID; | |
959 | NULL_CHECK (result); | |
960 | ||
961 | // FIXME: mask off some internal bits... | |
962 | *result = method->accflags; | |
963 | return JVMTI_ERROR_NONE; | |
964 | } | |
965 | ||
08107015 KS |
966 | static jvmtiError JNICALL |
967 | _Jv_JVMTI_GetLineNumberTable (jvmtiEnv *env, jmethodID method, | |
968 | jint *entry_count_ptr, | |
969 | jvmtiLineNumberEntry **table_ptr) | |
970 | { | |
971 | NULL_CHECK (entry_count_ptr); | |
972 | NULL_CHECK (table_ptr); | |
973 | ||
974 | jclass klass; | |
975 | jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass); | |
976 | if (jerr != JVMTI_ERROR_NONE) | |
977 | return jerr; | |
978 | ||
979 | _Jv_MethodBase *base = _Jv_FindInterpreterMethod (klass, method); | |
980 | if (base == NULL) | |
981 | return JVMTI_ERROR_INVALID_METHODID; | |
982 | ||
983 | if (java::lang::reflect::Modifier::isNative (method->accflags) | |
984 | || !_Jv_IsInterpretedClass (klass)) | |
985 | return JVMTI_ERROR_NATIVE_METHOD; | |
986 | ||
987 | _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> (base); | |
988 | jlong start, end; | |
989 | jintArray lines = NULL; | |
990 | jlongArray indices = NULL; | |
991 | imeth->get_line_table (start, end, lines, indices); | |
992 | if (lines == NULL) | |
993 | return JVMTI_ERROR_ABSENT_INFORMATION; | |
994 | ||
995 | jvmtiLineNumberEntry *table; | |
996 | jsize len = lines->length * sizeof (jvmtiLineNumberEntry); | |
997 | table = (jvmtiLineNumberEntry *) _Jv_MallocUnchecked (len); | |
998 | if (table == NULL) | |
999 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
1000 | ||
1001 | jint *line = elements (lines); | |
1002 | jlong *index = elements (indices); | |
1003 | for (int i = 0; i < lines->length; ++i) | |
1004 | { | |
1005 | table[i].start_location = index[i]; | |
1006 | table[i].line_number = line[i]; | |
1007 | } | |
1008 | ||
1009 | *table_ptr = table; | |
1010 | *entry_count_ptr = lines->length; | |
1011 | return JVMTI_ERROR_NONE; | |
1012 | } | |
1013 | ||
fe60528e KG |
1014 | static jvmtiError JNICALL |
1015 | _Jv_JVMTI_GetLocalVariableTable (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, | |
1016 | jint *num_locals, | |
1017 | jvmtiLocalVariableEntry **locals) | |
1018 | { | |
1019 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
1020 | NULL_CHECK (num_locals); | |
1021 | NULL_CHECK (locals); | |
1022 | ||
1023 | CHECK_FOR_NATIVE_METHOD(method); | |
1024 | ||
1025 | jclass klass; | |
1026 | jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass); | |
1027 | if (jerr != JVMTI_ERROR_NONE) | |
1028 | return jerr; | |
1029 | ||
1030 | _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> | |
1031 | (_Jv_FindInterpreterMethod (klass, method)); | |
1032 | ||
1033 | if (imeth == NULL) | |
1034 | return JVMTI_ERROR_INVALID_METHODID; | |
1035 | ||
1036 | jerr = env->GetMaxLocals (method, num_locals); | |
1037 | if (jerr != JVMTI_ERROR_NONE) | |
1038 | return jerr; | |
1039 | ||
1040 | jerr = env->Allocate (static_cast<jlong> | |
1041 | ((*num_locals) * sizeof (jvmtiLocalVariableEntry)), | |
1042 | reinterpret_cast<unsigned char **> (locals)); | |
1043 | ||
1044 | if (jerr != JVMTI_ERROR_NONE) | |
1045 | return jerr; | |
1046 | ||
1047 | //the slot in the methods local_var_table to get | |
1048 | int table_slot = 0; | |
1049 | char *name; | |
1050 | char *sig; | |
1051 | char *generic_sig; | |
1052 | ||
1053 | while (table_slot < *num_locals | |
1054 | && imeth->get_local_var_table (&name, &sig, &generic_sig, | |
1055 | &((((*locals)[table_slot].start_location))), | |
1056 | &((*locals)[table_slot].length), | |
1057 | &((*locals)[table_slot].slot), | |
1058 | table_slot) | |
1059 | >= 0) | |
1060 | { | |
61a36e0d | 1061 | char **str_ptr = &(*locals)[table_slot].name; |
fe60528e | 1062 | jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1), |
61a36e0d | 1063 | reinterpret_cast<unsigned char **> (str_ptr)); |
fe60528e KG |
1064 | if (jerr != JVMTI_ERROR_NONE) |
1065 | return jerr; | |
1066 | strcpy ((*locals)[table_slot].name, name); | |
61a36e0d KG |
1067 | |
1068 | str_ptr = &(*locals)[table_slot].signature; | |
1069 | jerr = env->Allocate (static_cast<jlong> (strlen (sig) + 1), | |
1070 | reinterpret_cast<unsigned char **> (str_ptr)); | |
fe60528e KG |
1071 | if (jerr != JVMTI_ERROR_NONE) |
1072 | return jerr; | |
1073 | strcpy ((*locals)[table_slot].signature, sig); | |
61a36e0d KG |
1074 | |
1075 | str_ptr = &(*locals)[table_slot].generic_signature; | |
1076 | jerr = env->Allocate (static_cast<jlong> (strlen (generic_sig) + 1), | |
1077 | reinterpret_cast<unsigned char **> (str_ptr)); | |
fe60528e KG |
1078 | if (jerr != JVMTI_ERROR_NONE) |
1079 | return jerr; | |
1080 | strcpy ((*locals)[table_slot].generic_signature, generic_sig); | |
1081 | ||
1082 | table_slot++; | |
1083 | } | |
1084 | ||
1085 | if (table_slot == 0) | |
1086 | return JVMTI_ERROR_ABSENT_INFORMATION; | |
1087 | ||
1088 | // If there are double or long variables in the table, the the table will be | |
1089 | // smaller than the max number of slots, so correct for this here. | |
1090 | if ((table_slot) < *num_locals) | |
1091 | *num_locals = table_slot; | |
1092 | ||
1093 | return JVMTI_ERROR_NONE; | |
1094 | } | |
1095 | ||
224aaa41 | 1096 | static jvmtiError JNICALL |
cb86b2b6 TT |
1097 | _Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
1098 | jboolean *result) | |
224aaa41 TT |
1099 | { |
1100 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1101 | if (method == NULL) | |
1102 | return JVMTI_ERROR_INVALID_METHODID; | |
1103 | NULL_CHECK (result); | |
1104 | ||
1105 | *result = ((method->accflags & java::lang::reflect::Modifier::NATIVE) != 0); | |
1106 | return JVMTI_ERROR_NONE; | |
1107 | } | |
1108 | ||
1109 | static jvmtiError JNICALL | |
cb86b2b6 TT |
1110 | _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method, |
1111 | jboolean *result) | |
224aaa41 TT |
1112 | { |
1113 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1114 | if (method == NULL) | |
1115 | return JVMTI_ERROR_INVALID_METHODID; | |
1116 | NULL_CHECK (result); | |
1117 | ||
1118 | // FIXME capability can_get_synthetic_attribute | |
1119 | ||
1120 | *result = ((method->accflags & java::lang::reflect::Modifier::SYNTHETIC) | |
1121 | != 0); | |
1122 | return JVMTI_ERROR_NONE; | |
1123 | } | |
1124 | ||
04ab4573 | 1125 | static jvmtiError JNICALL |
fe60528e | 1126 | _Jv_JVMTI_GetMaxLocals (jvmtiEnv *env, jmethodID method, jint *max_locals) |
04ab4573 KG |
1127 | { |
1128 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1129 | NULL_CHECK (max_locals); | |
1130 | ||
1131 | CHECK_FOR_NATIVE_METHOD (method); | |
1132 | ||
1133 | jclass klass; | |
1134 | jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass); | |
1135 | if (jerr != JVMTI_ERROR_NONE) | |
1136 | return jerr; | |
1137 | ||
1138 | _Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *> | |
1139 | (_Jv_FindInterpreterMethod (klass, method)); | |
1140 | ||
1141 | if (imeth == NULL) | |
1142 | return JVMTI_ERROR_INVALID_METHODID; | |
1143 | ||
1144 | *max_locals = imeth->get_max_locals (); | |
1145 | ||
1146 | return JVMTI_ERROR_NONE; | |
1147 | } | |
1148 | ||
532e9fe7 KG |
1149 | static jvmtiError JNICALL |
1150 | _Jv_JVMTI_GetArgumentsSize (jvmtiEnv *env, jmethodID method, jint *size) | |
1151 | { | |
1152 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1153 | NULL_CHECK (size); | |
1154 | ||
1155 | CHECK_FOR_NATIVE_METHOD (method); | |
1156 | ||
1157 | jvmtiError jerr; | |
1158 | char *sig; | |
1159 | jint num_slots = 0; | |
1160 | ||
1161 | jerr = env->GetMethodName (method, NULL, &sig, NULL); | |
1162 | if (jerr != JVMTI_ERROR_NONE) | |
1163 | return jerr; | |
1164 | ||
1165 | // If the method is non-static add a slot for the "this" pointer. | |
1166 | if ((method->accflags & java::lang::reflect::Modifier::STATIC) == 0) | |
1167 | num_slots++; | |
1168 | ||
1169 | for (int i = 0; sig[i] != ')'; i++) | |
1170 | { | |
1171 | if (sig[i] == 'Z' || sig[i] == 'B' || sig[i] == 'C' || sig[i] == 'S' | |
1172 | || sig[i] == 'I' || sig[i] == 'F') | |
1173 | num_slots++; | |
1174 | else if (sig[i] == 'J' || sig[i] == 'D') | |
b389f63b KG |
1175 | { |
1176 | // If this is an array of wide types it uses a single slot | |
814bcb14 | 1177 | if (i > 0 && sig[i - 1] == '[') |
b389f63b KG |
1178 | num_slots++; |
1179 | else | |
1180 | num_slots += 2; | |
1181 | } | |
532e9fe7 KG |
1182 | else if (sig[i] == 'L') |
1183 | { | |
1184 | num_slots++; | |
1185 | while (sig[i] != ';') | |
1186 | i++; | |
1187 | } | |
1188 | } | |
1189 | ||
1190 | *size = num_slots; | |
1191 | return JVMTI_ERROR_NONE; | |
1192 | } | |
1193 | ||
f356a436 KS |
1194 | static jvmtiError JNICALL |
1195 | _Jv_JVMTI_GetMethodDeclaringClass (MAYBE_UNUSED jvmtiEnv *env, | |
1196 | jmethodID method, | |
1197 | jclass *declaring_class_ptr) | |
1198 | { | |
1199 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
1200 | NULL_CHECK (declaring_class_ptr); | |
1201 | ||
1202 | jclass klass = _Jv_GetMethodDeclaringClass (method); | |
1203 | if (klass != NULL) | |
1204 | { | |
1205 | *declaring_class_ptr = klass; | |
1206 | return JVMTI_ERROR_NONE; | |
1207 | } | |
1208 | ||
1209 | return JVMTI_ERROR_INVALID_METHODID; | |
1210 | } | |
1211 | ||
224aaa41 | 1212 | static jvmtiError JNICALL |
cb86b2b6 | 1213 | _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
1214 | jobject init_loader, |
1215 | jint *count_ptr, | |
1216 | jclass **result_ptr) | |
1217 | { | |
1218 | using namespace java::lang; | |
1219 | using namespace java::util; | |
1220 | ||
1221 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
1222 | NULL_CHECK (count_ptr); | |
1223 | NULL_CHECK (result_ptr); | |
1224 | ||
1225 | ClassLoader *loader = (ClassLoader *) init_loader; | |
1226 | if (loader == NULL) | |
1227 | loader = VMClassLoader::bootLoader; | |
1228 | ||
1229 | Collection *values = loader->loadedClasses->values(); | |
1230 | jobjectArray array = values->toArray(); | |
1231 | *count_ptr = array->length; | |
1232 | jobject *elts = elements (array); | |
e853e26e KS |
1233 | jclass *result |
1234 | = (jclass *) _Jv_MallocUnchecked (*count_ptr * sizeof (jclass)); | |
1235 | if (result == NULL) | |
1236 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
1237 | ||
224aaa41 TT |
1238 | // FIXME: JNI references... |
1239 | memcpy (result, elts, *count_ptr * sizeof (jclass)); | |
1240 | ||
1241 | *result_ptr = result; | |
1242 | ||
1243 | return JVMTI_ERROR_NONE; | |
1244 | } | |
1245 | ||
39273131 KG |
1246 | static jvmtiError JNICALL |
1247 | _Jv_JVMTI_GetStackTrace (MAYBE_UNUSED jvmtiEnv *env, jthread thread, | |
1248 | jint start_depth, jint max_frames, | |
1249 | jvmtiFrameInfo *frames, jint *frame_count) | |
1250 | { | |
1251 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
1252 | ||
1253 | ILLEGAL_ARGUMENT (max_frames < 0); | |
1254 | ||
1255 | NULL_CHECK (frames); | |
1256 | NULL_CHECK (frame_count); | |
1257 | ||
1258 | using namespace java::lang; | |
1259 | ||
1260 | THREAD_DEFAULT_TO_CURRENT (thread); | |
9606c9dd KS |
1261 | THREAD_CHECK_VALID (thread); |
1262 | THREAD_CHECK_IS_ALIVE (thread); | |
39273131 KG |
1263 | |
1264 | jvmtiError jerr = env->GetFrameCount (thread, frame_count); | |
1265 | if (jerr != JVMTI_ERROR_NONE) | |
1266 | return jerr; | |
1267 | ||
1268 | // start_depth can be either a positive number, indicating the depth of the | |
1269 | // stack at which to begin the trace, or a negative number indicating the | |
1270 | // number of frames at the bottom of the stack to exclude. These checks | |
1271 | // ensure that it is a valid value in either case | |
1272 | ||
1273 | ILLEGAL_ARGUMENT (start_depth >= (*frame_count)); | |
1274 | ILLEGAL_ARGUMENT (start_depth < (-(*frame_count))); | |
1275 | ||
9606c9dd | 1276 | _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); |
39273131 KG |
1277 | |
1278 | // If start_depth is negative use this to determine at what depth to start | |
1279 | // the trace by adding it to the length of the call stack. This allows the | |
1280 | // use of the same frame "discarding" mechanism as for a positive start_depth | |
1281 | if (start_depth < 0) | |
1282 | start_depth = *frame_count + start_depth; | |
1283 | ||
1284 | // If start_depth > 0 "remove" start_depth frames from the beginning | |
1285 | // of the stack before beginning the trace by moving along the frame list. | |
1286 | while (start_depth > 0) | |
1287 | { | |
1288 | frame = frame->next; | |
1289 | start_depth--; | |
1290 | (*frame_count)--; | |
1291 | } | |
1292 | ||
1293 | // Now check to see if the array supplied by the agent is large enough to | |
1294 | // hold frame_count frames, after adjustment for start_depth. | |
1295 | if ((*frame_count) > max_frames) | |
1296 | (*frame_count) = max_frames; | |
1297 | ||
1298 | for (int i = 0; i < (*frame_count); i++) | |
1299 | { | |
1300 | frames[i].method = frame->self->get_method (); | |
1301 | ||
1302 | // Set the location in the frame, native frames have location = -1 | |
1303 | if (frame->frame_type == frame_interpreter) | |
1304 | { | |
1305 | _Jv_InterpMethod *imeth | |
1306 | = static_cast<_Jv_InterpMethod *> (frame->self); | |
1307 | _Jv_InterpFrame *interp_frame | |
1308 | = static_cast<_Jv_InterpFrame *> (frame); | |
d7647361 | 1309 | frames[i].location = imeth->insn_index (interp_frame->get_pc ()); |
39273131 KG |
1310 | } |
1311 | else | |
1312 | frames[i].location = -1; | |
1313 | ||
1314 | frame = frame->next; | |
1315 | } | |
1316 | ||
1317 | return JVMTI_ERROR_NONE; | |
1318 | } | |
1319 | ||
224aaa41 | 1320 | static jvmtiError JNICALL |
cb86b2b6 | 1321 | _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env) |
224aaa41 TT |
1322 | { |
1323 | REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); | |
1324 | _Jv_RunGC(); | |
1325 | return JVMTI_ERROR_NONE; | |
1326 | } | |
1327 | ||
1328 | static jvmtiError JNICALL | |
cb86b2b6 | 1329 | _Jv_JVMTI_SetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
1330 | const jniNativeInterface *function_table) |
1331 | { | |
1332 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1333 | NULL_CHECK (function_table); | |
1334 | memcpy (&_Jv_JNIFunctions, function_table, sizeof (jniNativeInterface)); | |
1335 | return JVMTI_ERROR_NONE; | |
1336 | } | |
1337 | ||
1338 | static jvmtiError JNICALL | |
cb86b2b6 | 1339 | _Jv_JVMTI_GetJNIFunctionTable (MAYBE_UNUSED jvmtiEnv *env, |
224aaa41 TT |
1340 | jniNativeInterface **function_table) |
1341 | { | |
1342 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1343 | NULL_CHECK (function_table); | |
1344 | *function_table | |
e853e26e KS |
1345 | = (jniNativeInterface *) _Jv_MallocUnchecked (sizeof (jniNativeInterface)); |
1346 | if (*function_table == NULL) | |
1347 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
224aaa41 TT |
1348 | memcpy (*function_table, &_Jv_JNIFunctions, sizeof (jniNativeInterface)); |
1349 | return JVMTI_ERROR_NONE; | |
1350 | } | |
94f473ee | 1351 | |
3201e73d | 1352 | static jvmtiError JNICALL |
326d5132 KS |
1353 | _Jv_JVMTI_DisposeEnvironment (jvmtiEnv *env) |
1354 | { | |
e6789bef KS |
1355 | NULL_CHECK (env); |
1356 | ||
1357 | if (_jvmtiEnvironments == NULL) | |
1358 | return JVMTI_ERROR_INVALID_ENVIRONMENT; | |
1359 | else | |
1360 | { | |
d6df67ef | 1361 | _envListLock->writeLock ()->lock (); |
e6789bef KS |
1362 | if (_jvmtiEnvironments->env == env) |
1363 | { | |
af91f02d | 1364 | struct jvmti_env_list *next = _jvmtiEnvironments->next; |
e6789bef | 1365 | _Jv_Free (_jvmtiEnvironments); |
af91f02d | 1366 | _jvmtiEnvironments = next; |
e6789bef KS |
1367 | } |
1368 | else | |
1369 | { | |
1370 | struct jvmti_env_list *e = _jvmtiEnvironments; | |
1371 | while (e->next != NULL && e->next->env != env) | |
1372 | e = e->next; | |
1373 | if (e->next == NULL) | |
d6df67ef KS |
1374 | { |
1375 | _envListLock->writeLock ()->unlock (); | |
1376 | return JVMTI_ERROR_INVALID_ENVIRONMENT; | |
1377 | } | |
e6789bef KS |
1378 | |
1379 | struct jvmti_env_list *next = e->next->next; | |
1380 | _Jv_Free (e->next); | |
1381 | e->next = next; | |
1382 | } | |
d6df67ef | 1383 | _envListLock->writeLock ()->unlock (); |
e6789bef KS |
1384 | } |
1385 | ||
326d5132 | 1386 | _Jv_Free (env); |
ebf29cf6 KS |
1387 | |
1388 | check_enabled_events (); | |
1389 | ||
326d5132 KS |
1390 | return JVMTI_ERROR_NONE; |
1391 | } | |
1392 | ||
224aaa41 | 1393 | static jvmtiError JNICALL |
cb86b2b6 | 1394 | _Jv_JVMTI_GetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property, |
224aaa41 TT |
1395 | char **result) |
1396 | { | |
1397 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
1398 | NULL_CHECK (property); | |
1399 | NULL_CHECK (result); | |
1400 | ||
1401 | jstring name = JvNewStringUTF(property); | |
1402 | jstring result_str = gnu::classpath::SystemProperties::getProperty(name); | |
1403 | ||
1404 | if (result_str == NULL) | |
1405 | return JVMTI_ERROR_NOT_AVAILABLE; | |
1406 | ||
1407 | int len = JvGetStringUTFLength (result_str); | |
e853e26e KS |
1408 | *result = (char *) _Jv_MallocUnchecked (len + 1); |
1409 | if (*result == NULL) | |
1410 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
224aaa41 TT |
1411 | JvGetStringUTFRegion (result_str, 0, result_str->length(), *result); |
1412 | (*result)[len] = '\0'; | |
1413 | ||
1414 | return JVMTI_ERROR_NONE; | |
1415 | } | |
1416 | ||
1417 | static jvmtiError JNICALL | |
cb86b2b6 | 1418 | _Jv_JVMTI_SetSystemProperty (MAYBE_UNUSED jvmtiEnv *env, const char *property, |
224aaa41 TT |
1419 | const char *value) |
1420 | { | |
1421 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD); | |
1422 | ||
1423 | NULL_CHECK (property); | |
1424 | if (value == NULL) | |
1425 | { | |
1426 | // FIXME: When would a property not be writeable? | |
1427 | return JVMTI_ERROR_NONE; | |
1428 | } | |
1429 | ||
1430 | jstring prop_str = JvNewStringUTF(property); | |
1431 | jstring value_str = JvNewStringUTF(value); | |
1432 | gnu::classpath::SystemProperties::setProperty(prop_str, value_str); | |
1433 | return JVMTI_ERROR_NONE; | |
1434 | } | |
1435 | ||
1436 | static jvmtiError JNICALL | |
1437 | _Jv_JVMTI_GetTime (MAYBE_UNUSED jvmtiEnv *env, jlong *nanos_ptr) | |
1438 | { | |
1439 | NULL_CHECK (nanos_ptr); | |
1440 | *nanos_ptr = _Jv_platform_nanotime(); | |
1441 | return JVMTI_ERROR_NONE; | |
1442 | } | |
1443 | ||
1444 | static jvmtiError JNICALL | |
1445 | _Jv_JVMTI_GetAvailableProcessors (MAYBE_UNUSED jvmtiEnv *env, | |
1446 | jint *nprocessors_ptr) | |
1447 | { | |
1448 | NULL_CHECK (nprocessors_ptr); | |
1449 | #ifdef _SC_NPROCESSORS_ONLN | |
1450 | *nprocessors_ptr = sysconf(_SC_NPROCESSORS_ONLN); | |
1451 | #else | |
1452 | *nprocessors_ptr = 1; | |
1453 | #endif | |
1454 | return JVMTI_ERROR_NONE; | |
1455 | } | |
1456 | ||
1457 | static jvmtiError JNICALL | |
cb86b2b6 TT |
1458 | _Jv_JVMTI_AddToBootstrapClassLoaderSearch (MAYBE_UNUSED jvmtiEnv *env, |
1459 | const char *segment) | |
224aaa41 TT |
1460 | { |
1461 | using namespace java::lang; | |
1462 | using namespace java::net; | |
1463 | using namespace gnu::gcj::runtime; | |
1464 | ||
1465 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD); | |
1466 | NULL_CHECK (segment); | |
1467 | ||
1468 | jstring str_segment = JvNewStringUTF(segment); | |
1469 | URL *url; | |
1470 | try | |
1471 | { | |
1472 | url = new URL(JvNewStringUTF("file"), NULL, str_segment); | |
1473 | } | |
1474 | catch (jthrowable ignore) | |
1475 | { | |
1476 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
1477 | } | |
1478 | ||
1479 | BootClassLoader *loader = VMClassLoader::bootLoader; | |
1480 | // Don't call this too early. | |
1481 | // assert (loader != NULL); | |
1482 | loader->addURL(url); | |
1483 | return JVMTI_ERROR_NONE; | |
1484 | } | |
1485 | ||
1486 | static jvmtiError JNICALL | |
1487 | _Jv_JVMTI_SetVerboseFlag (MAYBE_UNUSED jvmtiEnv *env, jvmtiVerboseFlag flag, | |
1488 | jboolean value) | |
1489 | { | |
1490 | switch (flag) | |
1491 | { | |
1492 | case JVMTI_VERBOSE_OTHER: | |
1493 | case JVMTI_VERBOSE_GC: | |
1494 | case JVMTI_VERBOSE_JNI: | |
1495 | // Ignore. | |
1496 | break; | |
1497 | case JVMTI_VERBOSE_CLASS: | |
1498 | gcj::verbose_class_flag = value; | |
1499 | break; | |
1500 | default: | |
1501 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
1502 | } | |
1503 | return JVMTI_ERROR_NONE; | |
1504 | } | |
1505 | ||
1506 | static jvmtiError JNICALL | |
cb86b2b6 TT |
1507 | _Jv_JVMTI_GetObjectSize (MAYBE_UNUSED jvmtiEnv *env, jobject object, |
1508 | jlong *result) | |
224aaa41 TT |
1509 | { |
1510 | REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE); | |
1511 | if (object == NULL) | |
1512 | return JVMTI_ERROR_INVALID_OBJECT; | |
1513 | NULL_CHECK (result); | |
1514 | ||
1515 | jclass klass = object->getClass(); | |
1516 | if (klass->isArray()) | |
1517 | { | |
1518 | jclass comp = klass->getComponentType(); | |
1519 | jint base | |
cb86b2b6 TT |
1520 | = (jint) (_Jv_uintptr_t) _Jv_GetArrayElementFromElementType(NULL, |
1521 | klass->getComponentType()); | |
224aaa41 TT |
1522 | // FIXME: correct for primitive types? |
1523 | jint compSize = comp->size(); | |
1524 | __JArray *array = (__JArray *) object; | |
1525 | *result = base + array->length * compSize; | |
1526 | } | |
1527 | else | |
1528 | { | |
1529 | // Note that if OBJECT is a String then it may (if | |
1530 | // str->data==str) take more space. Do we care? | |
1531 | *result = klass->size(); | |
1532 | } | |
1533 | return JVMTI_ERROR_NONE; | |
1534 | } | |
1535 | ||
ebf29cf6 KS |
1536 | /* An event is enabled only if it has both an event handler |
1537 | and it is enabled in the environment. */ | |
1538 | static void | |
1539 | check_enabled_event (jvmtiEvent type) | |
1540 | { | |
1541 | bool *enabled; | |
1542 | int offset; | |
1543 | ||
1544 | #define GET_OFFSET(Event) \ | |
1545 | do \ | |
1546 | { \ | |
1547 | enabled = &JVMTI::Event; \ | |
1548 | offset = offsetof (jvmtiEventCallbacks, Event); \ | |
1549 | } \ | |
1550 | while (0) | |
1551 | ||
1552 | switch (type) | |
1553 | { | |
1554 | case JVMTI_EVENT_VM_INIT: | |
1555 | GET_OFFSET (VMInit); | |
1556 | break; | |
1557 | ||
1558 | case JVMTI_EVENT_VM_DEATH: | |
1559 | GET_OFFSET (VMDeath); | |
1560 | break; | |
1561 | ||
1562 | case JVMTI_EVENT_THREAD_START: | |
1563 | GET_OFFSET (ThreadStart); | |
1564 | break; | |
1565 | ||
1566 | case JVMTI_EVENT_THREAD_END: | |
1567 | GET_OFFSET (ThreadEnd); | |
1568 | break; | |
1569 | ||
1570 | case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK: | |
1571 | GET_OFFSET (ClassFileLoadHook); | |
1572 | break; | |
1573 | ||
1574 | case JVMTI_EVENT_CLASS_LOAD: | |
1575 | GET_OFFSET (ClassLoad); | |
1576 | break; | |
1577 | ||
1578 | case JVMTI_EVENT_CLASS_PREPARE: | |
1579 | GET_OFFSET (ClassPrepare); | |
1580 | break; | |
1581 | ||
1582 | case JVMTI_EVENT_VM_START: | |
1583 | GET_OFFSET (VMStart); | |
1584 | break; | |
1585 | ||
1586 | case JVMTI_EVENT_EXCEPTION: | |
1587 | GET_OFFSET (Exception); | |
1588 | break; | |
1589 | ||
1590 | case JVMTI_EVENT_EXCEPTION_CATCH: | |
1591 | GET_OFFSET (ExceptionCatch); | |
1592 | break; | |
1593 | ||
1594 | case JVMTI_EVENT_SINGLE_STEP: | |
1595 | GET_OFFSET (SingleStep); | |
1596 | break; | |
1597 | ||
1598 | case JVMTI_EVENT_FRAME_POP: | |
1599 | GET_OFFSET (FramePop); | |
1600 | break; | |
1601 | ||
1602 | case JVMTI_EVENT_BREAKPOINT: | |
1603 | GET_OFFSET (Breakpoint); | |
1604 | break; | |
1605 | ||
1606 | case JVMTI_EVENT_FIELD_ACCESS: | |
1607 | GET_OFFSET (FieldAccess); | |
1608 | break; | |
1609 | ||
1610 | case JVMTI_EVENT_FIELD_MODIFICATION: | |
1611 | GET_OFFSET (FieldModification); | |
1612 | break; | |
1613 | ||
1614 | case JVMTI_EVENT_METHOD_ENTRY: | |
1615 | GET_OFFSET (MethodEntry); | |
1616 | break; | |
1617 | ||
1618 | case JVMTI_EVENT_METHOD_EXIT: | |
1619 | GET_OFFSET (MethodExit); | |
1620 | break; | |
1621 | ||
1622 | case JVMTI_EVENT_NATIVE_METHOD_BIND: | |
1623 | GET_OFFSET (NativeMethodBind); | |
1624 | break; | |
1625 | ||
1626 | case JVMTI_EVENT_COMPILED_METHOD_LOAD: | |
1627 | GET_OFFSET (CompiledMethodLoad); | |
1628 | break; | |
1629 | ||
1630 | case JVMTI_EVENT_COMPILED_METHOD_UNLOAD: | |
1631 | GET_OFFSET (CompiledMethodUnload); | |
1632 | break; | |
1633 | ||
1634 | case JVMTI_EVENT_DYNAMIC_CODE_GENERATED: | |
1635 | GET_OFFSET (DynamicCodeGenerated); | |
1636 | break; | |
1637 | ||
1638 | case JVMTI_EVENT_DATA_DUMP_REQUEST: | |
1639 | GET_OFFSET (DataDumpRequest); | |
1640 | break; | |
1641 | ||
1642 | case JVMTI_EVENT_MONITOR_WAIT: | |
1643 | GET_OFFSET (MonitorWait); | |
1644 | break; | |
1645 | ||
1646 | case JVMTI_EVENT_MONITOR_WAITED: | |
1647 | GET_OFFSET (MonitorWaited); | |
1648 | break; | |
1649 | ||
1650 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: | |
1651 | GET_OFFSET (MonitorContendedEnter); | |
1652 | break; | |
1653 | ||
1654 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: | |
1655 | GET_OFFSET (MonitorContendedEntered); | |
1656 | break; | |
1657 | ||
1658 | case JVMTI_EVENT_GARBAGE_COLLECTION_START: | |
1659 | GET_OFFSET (GarbageCollectionStart); | |
1660 | break; | |
1661 | ||
1662 | case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH: | |
1663 | GET_OFFSET (GarbageCollectionFinish); | |
1664 | break; | |
1665 | ||
1666 | case JVMTI_EVENT_OBJECT_FREE: | |
1667 | GET_OFFSET (ObjectFree); | |
1668 | break; | |
1669 | ||
1670 | case JVMTI_EVENT_VM_OBJECT_ALLOC: | |
1671 | GET_OFFSET (VMObjectAlloc); | |
1672 | break; | |
1673 | ||
1674 | default: | |
1675 | fprintf (stderr, | |
1676 | "libgcj: check_enabled_event for unknown JVMTI event (%d)\n", | |
1677 | (int) type); | |
1678 | return; | |
1679 | } | |
1680 | #undef GET_OFFSET | |
1681 | ||
1682 | int index = EVENT_INDEX (type); // safe since caller checks this | |
1683 | ||
d6df67ef | 1684 | if (_jvmtiEnvironments != NULL) |
ebf29cf6 | 1685 | { |
d6df67ef KS |
1686 | _envListLock->readLock ()->lock (); |
1687 | struct jvmti_env_list *e; | |
1688 | FOREACH_ENVIRONMENT (e) | |
ebf29cf6 | 1689 | { |
d6df67ef KS |
1690 | char *addr |
1691 | = reinterpret_cast<char *> (&e->env->callbacks) + offset; | |
1692 | void **callback = reinterpret_cast<void **> (addr); | |
1693 | if (e->env->enabled[index] && *callback != NULL) | |
1694 | { | |
1695 | *enabled = true; | |
1696 | _envListLock->readLock ()->unlock (); | |
1697 | return; | |
1698 | } | |
ebf29cf6 | 1699 | } |
d6df67ef KS |
1700 | |
1701 | _envListLock->readLock ()->unlock (); | |
ebf29cf6 KS |
1702 | } |
1703 | ||
1704 | *enabled = false; | |
1705 | } | |
1706 | ||
1707 | static void | |
1708 | check_enabled_events () | |
1709 | { | |
1710 | check_enabled_event (JVMTI_EVENT_VM_INIT); | |
1711 | check_enabled_event (JVMTI_EVENT_VM_DEATH); | |
1712 | check_enabled_event (JVMTI_EVENT_THREAD_START); | |
1713 | check_enabled_event (JVMTI_EVENT_THREAD_END); | |
1714 | check_enabled_event (JVMTI_EVENT_CLASS_FILE_LOAD_HOOK); | |
1715 | check_enabled_event (JVMTI_EVENT_CLASS_LOAD); | |
1716 | check_enabled_event (JVMTI_EVENT_CLASS_PREPARE); | |
1717 | check_enabled_event (JVMTI_EVENT_VM_START); | |
1718 | check_enabled_event (JVMTI_EVENT_EXCEPTION); | |
1719 | check_enabled_event (JVMTI_EVENT_EXCEPTION_CATCH); | |
1720 | check_enabled_event (JVMTI_EVENT_SINGLE_STEP); | |
1721 | check_enabled_event (JVMTI_EVENT_FRAME_POP); | |
1722 | check_enabled_event (JVMTI_EVENT_BREAKPOINT); | |
1723 | check_enabled_event (JVMTI_EVENT_FIELD_ACCESS); | |
1724 | check_enabled_event (JVMTI_EVENT_FIELD_MODIFICATION); | |
1725 | check_enabled_event (JVMTI_EVENT_METHOD_ENTRY); | |
1726 | check_enabled_event (JVMTI_EVENT_METHOD_EXIT); | |
1727 | check_enabled_event (JVMTI_EVENT_NATIVE_METHOD_BIND); | |
1728 | check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_LOAD); | |
1729 | check_enabled_event (JVMTI_EVENT_COMPILED_METHOD_UNLOAD); | |
1730 | check_enabled_event (JVMTI_EVENT_DYNAMIC_CODE_GENERATED); | |
1731 | check_enabled_event (JVMTI_EVENT_DATA_DUMP_REQUEST); | |
1732 | check_enabled_event (JVMTI_EVENT_MONITOR_WAIT); | |
1733 | check_enabled_event (JVMTI_EVENT_MONITOR_WAITED); | |
1734 | check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTER); | |
1735 | check_enabled_event (JVMTI_EVENT_MONITOR_CONTENDED_ENTERED); | |
1736 | check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_START); | |
1737 | check_enabled_event (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH); | |
1738 | check_enabled_event (JVMTI_EVENT_OBJECT_FREE); | |
1739 | check_enabled_event (JVMTI_EVENT_VM_OBJECT_ALLOC); | |
1740 | } | |
1741 | ||
1742 | static jvmtiError JNICALL | |
1743 | _Jv_JVMTI_SetEventNotificationMode (jvmtiEnv *env, jvmtiEventMode mode, | |
1744 | jvmtiEvent type, jthread event_thread, ...) | |
1745 | { | |
1746 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
1747 | ||
1748 | if (event_thread != NULL) | |
1749 | { | |
68254f23 KS |
1750 | THREAD_CHECK_VALID (event_thread); |
1751 | THREAD_CHECK_IS_ALIVE (event_thread); | |
ebf29cf6 KS |
1752 | } |
1753 | ||
1754 | bool enabled; | |
1755 | switch (mode) | |
1756 | { | |
1757 | case JVMTI_DISABLE: | |
1758 | enabled = false; | |
1759 | break; | |
1760 | case JVMTI_ENABLE: | |
1761 | enabled = true; | |
1762 | break; | |
1763 | ||
1764 | default: | |
1765 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
1766 | } | |
1767 | ||
1768 | switch (type) | |
1769 | { | |
1770 | case JVMTI_EVENT_VM_INIT: | |
1771 | case JVMTI_EVENT_VM_DEATH: | |
1772 | case JVMTI_EVENT_THREAD_START: | |
1773 | case JVMTI_EVENT_VM_START: | |
1774 | case JVMTI_EVENT_COMPILED_METHOD_LOAD: | |
1775 | case JVMTI_EVENT_COMPILED_METHOD_UNLOAD: | |
1776 | case JVMTI_EVENT_DYNAMIC_CODE_GENERATED: | |
1777 | case JVMTI_EVENT_DATA_DUMP_REQUEST: | |
1778 | ILLEGAL_ARGUMENT (event_thread != NULL); | |
1779 | break; | |
1780 | ||
1781 | case JVMTI_EVENT_THREAD_END: | |
1782 | case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK: | |
1783 | case JVMTI_EVENT_CLASS_LOAD: | |
1784 | case JVMTI_EVENT_CLASS_PREPARE: | |
1785 | case JVMTI_EVENT_EXCEPTION: | |
1786 | case JVMTI_EVENT_EXCEPTION_CATCH: | |
1787 | case JVMTI_EVENT_SINGLE_STEP: | |
1788 | case JVMTI_EVENT_FRAME_POP: | |
1789 | case JVMTI_EVENT_BREAKPOINT: | |
1790 | case JVMTI_EVENT_FIELD_ACCESS: | |
1791 | case JVMTI_EVENT_FIELD_MODIFICATION: | |
1792 | case JVMTI_EVENT_METHOD_ENTRY: | |
1793 | case JVMTI_EVENT_METHOD_EXIT: | |
1794 | case JVMTI_EVENT_NATIVE_METHOD_BIND: | |
1795 | case JVMTI_EVENT_MONITOR_WAIT: | |
1796 | case JVMTI_EVENT_MONITOR_WAITED: | |
1797 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: | |
1798 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: | |
1799 | case JVMTI_EVENT_GARBAGE_COLLECTION_START: | |
1800 | case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH: | |
1801 | case JVMTI_EVENT_OBJECT_FREE: | |
1802 | case JVMTI_EVENT_VM_OBJECT_ALLOC: | |
1803 | break; | |
1804 | ||
1805 | default: | |
1806 | return JVMTI_ERROR_INVALID_EVENT_TYPE; | |
1807 | } | |
1808 | ||
1809 | env->thread[EVENT_INDEX(type)] = event_thread; | |
1810 | env->enabled[EVENT_INDEX(type)] = enabled; | |
1811 | check_enabled_event (type); | |
1812 | return JVMTI_ERROR_NONE; | |
1813 | } | |
1814 | ||
1815 | static jvmtiError JNICALL | |
1816 | _Jv_JVMTI_SetEventCallbacks (jvmtiEnv *env, | |
1817 | const jvmtiEventCallbacks *callbacks, | |
1818 | jint size_of_callbacks) | |
1819 | { | |
1820 | REQUIRE_PHASE (env, JVMTI_PHASE_ONLOAD | JVMTI_PHASE_LIVE); | |
1821 | ILLEGAL_ARGUMENT (size_of_callbacks < 0); | |
1822 | ||
1823 | // Copy the list of callbacks into the environment | |
1824 | memcpy (&env->callbacks, callbacks, sizeof (jvmtiEventCallbacks)); | |
1825 | ||
1826 | /* Check which events are now enabeld (JVMTI makes no requirements | |
1827 | about the order in which SetEventCallbacks and SetEventNotifications | |
1828 | are called. So we must check all events here. */ | |
1829 | check_enabled_events (); | |
1830 | ||
1831 | return JVMTI_ERROR_NONE; | |
1832 | } | |
1833 | ||
f8e04884 | 1834 | static jvmtiError JNICALL |
19289614 KS |
1835 | _Jv_JVMTI_GetErrorName (MAYBE_UNUSED jvmtiEnv *env, jvmtiError error, |
1836 | char **name_ptr) | |
1837 | { | |
1838 | NULL_CHECK (name_ptr); | |
1839 | ||
1840 | const char *name; | |
1841 | switch (error) | |
1842 | { | |
1843 | case JVMTI_ERROR_NONE: | |
1844 | name = "none"; | |
1845 | break; | |
1846 | ||
1847 | case JVMTI_ERROR_NULL_POINTER: | |
1848 | name = "null pointer"; | |
1849 | break; | |
1850 | ||
1851 | case JVMTI_ERROR_OUT_OF_MEMORY: | |
1852 | name = "out of memory"; | |
1853 | break; | |
1854 | ||
1855 | case JVMTI_ERROR_ACCESS_DENIED: | |
1856 | name = "access denied"; | |
1857 | break; | |
1858 | ||
1859 | case JVMTI_ERROR_WRONG_PHASE: | |
1860 | name = "wrong phase"; | |
1861 | break; | |
1862 | ||
1863 | case JVMTI_ERROR_INTERNAL: | |
1864 | name = "internal error"; | |
1865 | break; | |
1866 | ||
1867 | case JVMTI_ERROR_UNATTACHED_THREAD: | |
1868 | name = "unattached thread"; | |
1869 | break; | |
1870 | ||
1871 | case JVMTI_ERROR_INVALID_ENVIRONMENT: | |
1872 | name = "invalid environment"; | |
1873 | break; | |
1874 | ||
1875 | case JVMTI_ERROR_INVALID_PRIORITY: | |
1876 | name = "invalid priority"; | |
1877 | break; | |
1878 | ||
1879 | case JVMTI_ERROR_THREAD_NOT_SUSPENDED: | |
1880 | name = "thread not suspended"; | |
1881 | break; | |
1882 | ||
1883 | case JVMTI_ERROR_THREAD_SUSPENDED: | |
1884 | name = "thread suspended"; | |
1885 | break; | |
1886 | ||
1887 | case JVMTI_ERROR_THREAD_NOT_ALIVE: | |
1888 | name = "thread not alive"; | |
1889 | break; | |
1890 | ||
1891 | case JVMTI_ERROR_CLASS_NOT_PREPARED: | |
1892 | name = "class not prepared"; | |
1893 | break; | |
1894 | ||
1895 | case JVMTI_ERROR_NO_MORE_FRAMES: | |
1896 | name = "no more frames"; | |
1897 | break; | |
1898 | ||
1899 | case JVMTI_ERROR_OPAQUE_FRAME: | |
1900 | name = "opaque frame"; | |
1901 | break; | |
1902 | ||
1903 | case JVMTI_ERROR_DUPLICATE: | |
1904 | name = "duplicate"; | |
1905 | break; | |
1906 | ||
1907 | case JVMTI_ERROR_NOT_FOUND: | |
1908 | name = "not found"; | |
1909 | break; | |
1910 | ||
1911 | case JVMTI_ERROR_NOT_MONITOR_OWNER: | |
1912 | name = "not monitor owner"; | |
1913 | break; | |
1914 | ||
1915 | case JVMTI_ERROR_INTERRUPT: | |
1916 | name = "interrupted"; | |
1917 | break; | |
1918 | ||
1919 | case JVMTI_ERROR_UNMODIFIABLE_CLASS: | |
1920 | name = "unmodifiable class"; | |
1921 | break; | |
1922 | ||
1923 | case JVMTI_ERROR_NOT_AVAILABLE: | |
1924 | name = "not available"; | |
1925 | break; | |
1926 | ||
1927 | case JVMTI_ERROR_ABSENT_INFORMATION: | |
1928 | name = "absent information"; | |
1929 | break; | |
1930 | ||
1931 | case JVMTI_ERROR_INVALID_EVENT_TYPE: | |
1932 | name = "invalid event type"; | |
1933 | break; | |
1934 | ||
1935 | case JVMTI_ERROR_NATIVE_METHOD: | |
1936 | name = "native method"; | |
1937 | break; | |
1938 | ||
1939 | case JVMTI_ERROR_INVALID_THREAD: | |
1940 | name = "invalid thread"; | |
1941 | break; | |
1942 | ||
1943 | case JVMTI_ERROR_INVALID_THREAD_GROUP: | |
1944 | name = "invalid thread group"; | |
1945 | break; | |
1946 | ||
1947 | case JVMTI_ERROR_INVALID_OBJECT: | |
1948 | name = "invalid object"; | |
1949 | break; | |
1950 | ||
1951 | case JVMTI_ERROR_INVALID_CLASS: | |
1952 | name = "invalid class"; | |
1953 | break; | |
1954 | ||
1955 | case JVMTI_ERROR_INVALID_METHODID: | |
1956 | name = "invalid method ID"; | |
1957 | break; | |
1958 | ||
1959 | case JVMTI_ERROR_INVALID_LOCATION: | |
1960 | name = "invalid location"; | |
1961 | break; | |
1962 | ||
1963 | case JVMTI_ERROR_INVALID_FIELDID: | |
1964 | name = "invalid field ID"; | |
1965 | break; | |
1966 | ||
1967 | case JVMTI_ERROR_TYPE_MISMATCH: | |
1968 | name = "type mismatch"; | |
1969 | break; | |
1970 | ||
1971 | case JVMTI_ERROR_INVALID_SLOT: | |
1972 | name = "invalid slot"; | |
1973 | break; | |
1974 | ||
1975 | case JVMTI_ERROR_INVALID_MONITOR: | |
1976 | name = "invalid monitor"; | |
1977 | break; | |
1978 | ||
1979 | case JVMTI_ERROR_INVALID_CLASS_FORMAT: | |
1980 | name = "invalid class format"; | |
1981 | break; | |
1982 | ||
1983 | case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION: | |
1984 | name = "circular class definition"; | |
1985 | break; | |
1986 | ||
1987 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED: | |
1988 | name = "unsupported redefinition: method added"; | |
1989 | break; | |
1990 | ||
1991 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED: | |
1992 | name = "unsupported redefinition: schema changed"; | |
1993 | break; | |
1994 | ||
1995 | case JVMTI_ERROR_INVALID_TYPESTATE: | |
1996 | name = "invalid type state"; | |
1997 | break; | |
1998 | ||
1999 | case JVMTI_ERROR_FAILS_VERIFICATION: | |
2000 | name = "fails verification"; | |
2001 | break; | |
2002 | ||
2003 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED: | |
2004 | name = "unsupported redefinition: hierarchy changed"; | |
2005 | break; | |
2006 | ||
2007 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED: | |
2008 | name = "unsupported redefinition: method deleted"; | |
2009 | break; | |
2010 | ||
2011 | case JVMTI_ERROR_UNSUPPORTED_VERSION: | |
2012 | name = "unsupported version"; | |
2013 | break; | |
2014 | ||
2015 | case JVMTI_ERROR_NAMES_DONT_MATCH: | |
2016 | name = "names do not match"; | |
2017 | break; | |
2018 | ||
2019 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED: | |
2020 | name = "unsupported redefinition: class modifiers changed"; | |
2021 | break; | |
2022 | ||
2023 | case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED: | |
2024 | name = "unsupported redefinition: method modifiers changed"; | |
2025 | break; | |
2026 | ||
2027 | case JVMTI_ERROR_MUST_POSSESS_CAPABILITY: | |
2028 | name = "must possess capability"; | |
2029 | break; | |
2030 | ||
2031 | case JVMTI_ERROR_ILLEGAL_ARGUMENT: | |
2032 | name = "illegal argument"; | |
2033 | break; | |
2034 | ||
2035 | default: | |
2036 | return JVMTI_ERROR_ILLEGAL_ARGUMENT; | |
2037 | } | |
2038 | ||
2039 | *name_ptr = (char *) _Jv_MallocUnchecked (strlen (name) + 1); | |
2040 | if (*name_ptr == NULL) | |
2041 | return JVMTI_ERROR_OUT_OF_MEMORY; | |
2042 | ||
2043 | strcpy (*name_ptr, name); | |
2044 | return JVMTI_ERROR_NONE; | |
2045 | } | |
2046 | ||
224aaa41 TT |
2047 | #define RESERVED NULL |
2048 | #define UNIMPLEMENTED NULL | |
2049 | ||
94f473ee KS |
2050 | struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = |
2051 | { | |
2052 | RESERVED, // reserved1 | |
ebf29cf6 | 2053 | _Jv_JVMTI_SetEventNotificationMode, // SetEventNotificationMode |
94f473ee | 2054 | RESERVED, // reserved3 |
05794ce8 | 2055 | _Jv_JVMTI_GetAllThreads, // GetAllThreads |
303f32cc KS |
2056 | _Jv_JVMTI_SuspendThread, // SuspendThread |
2057 | _Jv_JVMTI_ResumeThread, // ResumeThread | |
94f473ee | 2058 | UNIMPLEMENTED, // StopThread |
224aaa41 | 2059 | _Jv_JVMTI_InterruptThread, // InterruptThread |
94f473ee KS |
2060 | UNIMPLEMENTED, // GetThreadInfo |
2061 | UNIMPLEMENTED, // GetOwnedMonitorInfo | |
2062 | UNIMPLEMENTED, // GetCurrentContendedMonitor | |
2063 | UNIMPLEMENTED, // RunAgentThread | |
2064 | UNIMPLEMENTED, // GetTopThreadGroups | |
2065 | UNIMPLEMENTED, // GetThreadGroupInfo | |
2066 | UNIMPLEMENTED, // GetThreadGroupChildren | |
39273131 | 2067 | _Jv_JVMTI_GetFrameCount, // GetFrameCount |
22099c59 | 2068 | _Jv_JVMTI_GetThreadState, // GetThreadState |
94f473ee KS |
2069 | RESERVED, // reserved18 |
2070 | UNIMPLEMENTED, // GetFrameLocation | |
2071 | UNIMPLEMENTED, // NotifyPopFrame | |
ce359ed9 KG |
2072 | _Jv_JVMTI_GetLocalObject, // GetLocalObject |
2073 | _Jv_JVMTI_GetLocalInt, // GetLocalInt | |
2074 | _Jv_JVMTI_GetLocalLong, // GetLocalLong | |
2075 | _Jv_JVMTI_GetLocalFloat, // GetLocalFloat | |
2076 | _Jv_JVMTI_GetLocalDouble, // GetLocalDouble | |
2077 | _Jv_JVMTI_SetLocalObject, // SetLocalObject | |
2078 | _Jv_JVMTI_SetLocalInt, // SetLocalInt | |
2079 | _Jv_JVMTI_SetLocalLong, // SetLocalLong | |
2080 | _Jv_JVMTI_SetLocalFloat, // SetLocalFloat | |
2081 | _Jv_JVMTI_SetLocalDouble, // SetLocalDouble | |
224aaa41 TT |
2082 | _Jv_JVMTI_CreateRawMonitor, // CreateRawMonitor |
2083 | _Jv_JVMTI_DestroyRawMonitor, // DestroyRawMonitor | |
2084 | _Jv_JVMTI_RawMonitorEnter, // RawMonitorEnter | |
2085 | _Jv_JVMTI_RawMonitorExit, // RawMonitorExit | |
2086 | _Jv_JVMTI_RawMonitorWait, // RawMonitorWait | |
2087 | _Jv_JVMTI_RawMonitorNotify, // RawMonitorNotify | |
2088 | _Jv_JVMTI_RawMonitorNotifyAll, // RawMonitorNotifyAll | |
444dd946 KS |
2089 | _Jv_JVMTI_SetBreakpoint, // SetBreakpoint |
2090 | _Jv_JVMTI_ClearBreakpoint, // ClearBreakpoint | |
94f473ee KS |
2091 | RESERVED, // reserved40 |
2092 | UNIMPLEMENTED, // SetFieldAccessWatch | |
2093 | UNIMPLEMENTED, // ClearFieldAccessWatch | |
2094 | UNIMPLEMENTED, // SetFieldModificationWatch | |
2095 | UNIMPLEMENTED, // ClearFieldModificationWatch | |
2096 | RESERVED, // reserved45 | |
224aaa41 TT |
2097 | _Jv_JVMTI_Allocate, // Allocate |
2098 | _Jv_JVMTI_Deallocate, // Deallocate | |
94f473ee | 2099 | UNIMPLEMENTED, // GetClassSignature |
2b3c6788 | 2100 | _Jv_JVMTI_GetClassStatus, // GetClassStatus |
94f473ee | 2101 | UNIMPLEMENTED, // GetSourceFileName |
224aaa41 TT |
2102 | _Jv_JVMTI_GetClassModifiers, // GetClassModifiers |
2103 | _Jv_JVMTI_GetClassMethods, // GetClassMethods | |
94f473ee KS |
2104 | UNIMPLEMENTED, // GetClassFields |
2105 | UNIMPLEMENTED, // GetImplementedInterfaces | |
224aaa41 TT |
2106 | _Jv_JVMTI_IsInterface, // IsInterface |
2107 | _Jv_JVMTI_IsArrayClass, // IsArrayClass | |
2108 | _Jv_JVMTI_GetClassLoader, // GetClassLoader | |
2109 | _Jv_JVMTI_GetObjectHashCode, // GetObjectHashCode | |
94f473ee KS |
2110 | UNIMPLEMENTED, // GetObjectMonitorUsage |
2111 | UNIMPLEMENTED, // GetFieldName | |
2112 | UNIMPLEMENTED, // GetFieldDeclaringClass | |
224aaa41 TT |
2113 | _Jv_JVMTI_GetFieldModifiers, // GetFieldModifiers |
2114 | _Jv_JVMTI_IsFieldSynthetic, // IsFieldSynthetic | |
ff393407 | 2115 | _Jv_JVMTI_GetMethodName, // GetMethodName |
f356a436 | 2116 | _Jv_JVMTI_GetMethodDeclaringClass, // GetMethodDeclaringClass |
224aaa41 | 2117 | _Jv_JVMTI_GetMethodModifiers, // GetMethodModifers |
94f473ee | 2118 | RESERVED, // reserved67 |
04ab4573 | 2119 | _Jv_JVMTI_GetMaxLocals, // GetMaxLocals |
532e9fe7 | 2120 | _Jv_JVMTI_GetArgumentsSize, // GetArgumentsSize |
08107015 | 2121 | _Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable |
94f473ee | 2122 | UNIMPLEMENTED, // GetMethodLocation |
fe60528e | 2123 | _Jv_JVMTI_GetLocalVariableTable, // GetLocalVariableTable |
94f473ee KS |
2124 | RESERVED, // reserved73 |
2125 | RESERVED, // reserved74 | |
2126 | UNIMPLEMENTED, // GetBytecodes | |
224aaa41 TT |
2127 | _Jv_JVMTI_IsMethodNative, // IsMethodNative |
2128 | _Jv_JVMTI_IsMethodSynthetic, // IsMethodSynthetic | |
94f473ee | 2129 | UNIMPLEMENTED, // GetLoadedClasses |
224aaa41 | 2130 | _Jv_JVMTI_GetClassLoaderClasses, // GetClassLoaderClasses |
94f473ee KS |
2131 | UNIMPLEMENTED, // PopFrame |
2132 | RESERVED, // reserved81 | |
2133 | RESERVED, // reserved82 | |
2134 | RESERVED, // reserved83 | |
2135 | RESERVED, // reserved84 | |
2136 | RESERVED, // reserved85 | |
2137 | RESERVED, // reserved86 | |
2138 | UNIMPLEMENTED, // RedefineClasses | |
2139 | UNIMPLEMENTED, // GetVersionNumber | |
2140 | UNIMPLEMENTED, // GetCapabilities | |
2141 | UNIMPLEMENTED, // GetSourceDebugExtension | |
2142 | UNIMPLEMENTED, // IsMethodObsolete | |
2143 | UNIMPLEMENTED, // SuspendThreadList | |
2144 | UNIMPLEMENTED, // ResumeThreadList | |
2145 | RESERVED, // reserved94 | |
2146 | RESERVED, // reserved95 | |
2147 | RESERVED, // reserved96 | |
2148 | RESERVED, // reserved97 | |
2149 | RESERVED, // reserved98 | |
2150 | RESERVED, // reserved99 | |
2151 | UNIMPLEMENTED, // GetAllStackTraces | |
2152 | UNIMPLEMENTED, // GetThreadListStackTraces | |
2153 | UNIMPLEMENTED, // GetThreadLocalStorage | |
2154 | UNIMPLEMENTED, // SetThreadLocalStorage | |
39273131 | 2155 | _Jv_JVMTI_GetStackTrace, // GetStackTrace |
94f473ee KS |
2156 | RESERVED, // reserved105 |
2157 | UNIMPLEMENTED, // GetTag | |
2158 | UNIMPLEMENTED, // SetTag | |
224aaa41 | 2159 | _Jv_JVMTI_ForceGarbageCollection, // ForceGarbageCollection |
94f473ee KS |
2160 | UNIMPLEMENTED, // IterateOverObjectsReachable |
2161 | UNIMPLEMENTED, // IterateOverReachableObjects | |
2162 | UNIMPLEMENTED, // IterateOverHeap | |
2163 | UNIMPLEMENTED, // IterateOverInstanceOfClass | |
2164 | RESERVED, // reserved113 | |
2165 | UNIMPLEMENTED, // GetObjectsWithTags | |
2166 | RESERVED, // reserved115 | |
2167 | RESERVED, // reserved116 | |
2168 | RESERVED, // reserved117 | |
2169 | RESERVED, // reserved118 | |
2170 | RESERVED, // reserved119 | |
224aaa41 TT |
2171 | _Jv_JVMTI_SetJNIFunctionTable, // SetJNIFunctionTable |
2172 | _Jv_JVMTI_GetJNIFunctionTable, // GetJNIFunctionTable | |
ebf29cf6 | 2173 | _Jv_JVMTI_SetEventCallbacks, // SetEventCallbacks |
94f473ee KS |
2174 | UNIMPLEMENTED, // GenerateEvents |
2175 | UNIMPLEMENTED, // GetExtensionFunctions | |
2176 | UNIMPLEMENTED, // GetExtensionEvents | |
2177 | UNIMPLEMENTED, // SetExtensionEventCallback | |
326d5132 | 2178 | _Jv_JVMTI_DisposeEnvironment, // DisposeEnvironment |
19289614 | 2179 | _Jv_JVMTI_GetErrorName, // GetErrorName |
94f473ee KS |
2180 | UNIMPLEMENTED, // GetJLocationFormat |
2181 | UNIMPLEMENTED, // GetSystemProperties | |
224aaa41 TT |
2182 | _Jv_JVMTI_GetSystemProperty, // GetSystemProperty |
2183 | _Jv_JVMTI_SetSystemProperty, // SetSystemProperty | |
94f473ee KS |
2184 | UNIMPLEMENTED, // GetPhase |
2185 | UNIMPLEMENTED, // GetCurrentThreadCpuTimerInfo | |
2186 | UNIMPLEMENTED, // GetCurrentThreadCpuTime | |
2187 | UNIMPLEMENTED, // GetThreadCpuTimerInfo | |
2188 | UNIMPLEMENTED, // GetThreadCpuTime | |
2189 | UNIMPLEMENTED, // GetTimerInfo | |
224aaa41 | 2190 | _Jv_JVMTI_GetTime, // GetTime |
94f473ee KS |
2191 | UNIMPLEMENTED, // GetPotentialCapabilities |
2192 | RESERVED, // reserved141 | |
2193 | UNIMPLEMENTED, // AddCapabilities | |
2194 | UNIMPLEMENTED, // RelinquishCapabilities | |
224aaa41 | 2195 | _Jv_JVMTI_GetAvailableProcessors, // GetAvailableProcessors |
94f473ee KS |
2196 | RESERVED, // reserved145 |
2197 | RESERVED, // reserved146 | |
2198 | UNIMPLEMENTED, // GetEnvironmentLocalStorage | |
2199 | UNIMPLEMENTED, // SetEnvironmentLocalStorage | |
224aaa41 TT |
2200 | _Jv_JVMTI_AddToBootstrapClassLoaderSearch, // AddToBootstrapClassLoaderSearch |
2201 | _Jv_JVMTI_SetVerboseFlag, // SetVerboseFlag | |
94f473ee KS |
2202 | RESERVED, // reserved151 |
2203 | RESERVED, // reserved152 | |
2204 | RESERVED, // reserved153 | |
224aaa41 | 2205 | _Jv_JVMTI_GetObjectSize // GetObjectSize |
94f473ee KS |
2206 | }; |
2207 | ||
2208 | _Jv_JVMTIEnv * | |
2209 | _Jv_GetJVMTIEnv (void) | |
2210 | { | |
2211 | _Jv_JVMTIEnv *env | |
2212 | = (_Jv_JVMTIEnv *) _Jv_MallocUnchecked (sizeof (_Jv_JVMTIEnv)); | |
2213 | env->p = &_Jv_JVMTI_Interface; | |
d6df67ef KS |
2214 | struct jvmti_env_list *element |
2215 | = (struct jvmti_env_list *) _Jv_MallocUnchecked (sizeof (struct jvmti_env_list)); | |
2216 | element->env = env; | |
2217 | element->next = NULL; | |
e6789bef | 2218 | |
d6df67ef KS |
2219 | _envListLock->writeLock ()->lock (); |
2220 | if (_jvmtiEnvironments == NULL) | |
2221 | _jvmtiEnvironments = element; | |
2222 | else | |
2223 | { | |
2224 | struct jvmti_env_list *e; | |
2225 | for (e = _jvmtiEnvironments; e->next != NULL; e = e->next) | |
2226 | ; | |
2227 | e->next = element; | |
2228 | } | |
2229 | _envListLock->writeLock ()->unlock (); | |
e6789bef | 2230 | |
c6923d93 KS |
2231 | /* Mark JVMTI active. This is used to force the interpreter |
2232 | to use either debugging or non-debugging code. Once JVMTI | |
2233 | has been enabled, the non-debug interpreter cannot be used. */ | |
2234 | JVMTI::enabled = true; | |
94f473ee KS |
2235 | return env; |
2236 | } | |
e6789bef KS |
2237 | |
2238 | void | |
2239 | _Jv_JVMTI_Init () | |
2240 | { | |
2241 | _jvmtiEnvironments = NULL; | |
d6df67ef KS |
2242 | _envListLock |
2243 | = new java::util::concurrent::locks::ReentrantReadWriteLock (); | |
ebf29cf6 KS |
2244 | |
2245 | // No environments, so this should set all JVMTI:: members to false | |
2246 | check_enabled_events (); | |
2247 | } | |
2248 | ||
2249 | static void | |
2250 | post_event (jvmtiEnv *env, jvmtiEvent type, jthread event_thread, va_list args) | |
2251 | { | |
2252 | #define ARG(Type,Name) Type Name = (Type) va_arg (args, Type) | |
2253 | ||
2254 | #define GET_BOOLEAN_ARG(Name) \ | |
2255 | ARG (int, b); \ | |
2256 | jboolean Name = (b == 0) ? false : true | |
2257 | ||
2258 | #define GET_CHAR_ARG(Name) \ | |
2259 | ARG (int, c); \ | |
2260 | char Name = static_cast<char> (c) | |
2261 | ||
2262 | switch (type) | |
2263 | { | |
2264 | case JVMTI_EVENT_VM_INIT: | |
2265 | if (env->callbacks.VMInit != NULL) | |
2266 | { | |
2267 | ARG (JNIEnv *, jni_env); | |
2268 | env->callbacks.VMInit (env, jni_env, event_thread); | |
2269 | } | |
2270 | break; | |
2271 | ||
2272 | case JVMTI_EVENT_VM_DEATH: | |
2273 | if (env->callbacks.VMDeath != NULL) | |
2274 | { | |
2275 | ARG (JNIEnv *, jni_env); | |
2276 | env->callbacks.VMDeath (env, jni_env); | |
2277 | } | |
2278 | break; | |
2279 | ||
2280 | case JVMTI_EVENT_THREAD_START: | |
2281 | if (env->callbacks.ThreadStart != NULL) | |
2282 | { | |
2283 | ARG (JNIEnv *, jni_env); | |
2284 | env->callbacks.ThreadStart (env, jni_env, event_thread); | |
2285 | } | |
2286 | break; | |
2287 | ||
2288 | case JVMTI_EVENT_THREAD_END: | |
2289 | if (env->callbacks.ThreadEnd != NULL) | |
2290 | { | |
2291 | ARG (JNIEnv *, jni_env); | |
2292 | env->callbacks.ThreadEnd (env, jni_env, event_thread); | |
2293 | } | |
2294 | break; | |
2295 | ||
2296 | case JVMTI_EVENT_CLASS_FILE_LOAD_HOOK: | |
2297 | if (env->callbacks.ClassFileLoadHook != NULL) | |
2298 | { | |
2299 | ARG (JNIEnv *, jni_env); | |
2300 | ARG (jclass, class_being_redefined); | |
2301 | ARG (jobject, loader); | |
2302 | ARG (const char *, name); | |
2303 | ARG (jobject, protection_domain); | |
2304 | ARG (jint, class_data_len); | |
2305 | ARG (const unsigned char *, class_data); | |
2306 | ARG (jint *, new_class_data_len); | |
2307 | ARG (unsigned char **, new_class_data); | |
2308 | env->callbacks.ClassFileLoadHook (env, jni_env, | |
2309 | class_being_redefined, loader, | |
2310 | name, protection_domain, | |
2311 | class_data_len, class_data, | |
2312 | new_class_data_len, | |
2313 | new_class_data); | |
2314 | } | |
2315 | break; | |
2316 | ||
2317 | case JVMTI_EVENT_CLASS_LOAD: | |
2318 | if (env->callbacks.ClassLoad != NULL) | |
2319 | { | |
2320 | ARG (JNIEnv *, jni_env); | |
2321 | ARG (jclass, klass); | |
2322 | env->callbacks.ClassLoad (env, jni_env, event_thread, klass); | |
2323 | } | |
2324 | break; | |
2325 | ||
2326 | case JVMTI_EVENT_CLASS_PREPARE: | |
2327 | if (env->callbacks.ClassPrepare != NULL) | |
2328 | { | |
2329 | ARG (JNIEnv *, jni_env); | |
2330 | ARG (jclass, klass); | |
2331 | env->callbacks.ClassPrepare (env, jni_env, event_thread, klass); | |
2332 | } | |
2333 | break; | |
2334 | ||
2335 | case JVMTI_EVENT_VM_START: | |
2336 | if (env->callbacks.VMStart != NULL) | |
2337 | { | |
2338 | ARG (JNIEnv *, jni_env); | |
2339 | env->callbacks.VMStart (env, jni_env); | |
2340 | } | |
2341 | break; | |
2342 | ||
2343 | case JVMTI_EVENT_EXCEPTION: | |
2344 | if (env->callbacks.Exception != NULL) | |
2345 | { | |
2346 | ARG (JNIEnv *, jni_env); | |
2347 | ARG (jmethodID, method); | |
2348 | ARG (jlocation, location); | |
2349 | ARG (jobject, exception); | |
2350 | ARG (jmethodID, catch_method); | |
2351 | ARG (jlocation, catch_location); | |
2352 | env->callbacks.Exception (env, jni_env, event_thread, method, | |
2353 | location, exception, catch_method, | |
2354 | catch_location); | |
2355 | } | |
2356 | break; | |
2357 | ||
2358 | case JVMTI_EVENT_EXCEPTION_CATCH: | |
2359 | if (env->callbacks.ExceptionCatch != NULL) | |
2360 | { | |
2361 | ARG (JNIEnv *, jni_env); | |
2362 | ARG (jmethodID, method); | |
2363 | ARG (jlocation, location); | |
2364 | ARG (jobject, exception); | |
2365 | env->callbacks.ExceptionCatch (env, jni_env, event_thread, method, | |
2366 | location, exception); | |
2367 | } | |
2368 | break; | |
2369 | ||
2370 | case JVMTI_EVENT_SINGLE_STEP: | |
2371 | if (env->callbacks.SingleStep != NULL) | |
2372 | { | |
2373 | ARG (JNIEnv *, jni_env); | |
2374 | ARG (jmethodID, method); | |
2375 | ARG (jlocation, location); | |
2376 | env->callbacks.SingleStep (env, jni_env, event_thread, method, | |
2377 | location); | |
2378 | } | |
2379 | break; | |
2380 | ||
2381 | case JVMTI_EVENT_FRAME_POP: | |
2382 | if (env->callbacks.FramePop != NULL) | |
2383 | { | |
2384 | ARG (JNIEnv *, jni_env); | |
2385 | ARG (jmethodID, method); | |
2386 | GET_BOOLEAN_ARG (was_popped_by_exception); | |
2387 | env->callbacks.FramePop (env, jni_env, event_thread, method, | |
2388 | was_popped_by_exception); | |
2389 | } | |
2390 | break; | |
2391 | ||
2392 | case JVMTI_EVENT_BREAKPOINT: | |
2393 | if (env->callbacks.Breakpoint != NULL) | |
2394 | { | |
2395 | ARG (JNIEnv *, jni_env); | |
2396 | ARG (jmethodID, method); | |
2397 | ARG (jlocation, location); | |
2398 | env->callbacks.Breakpoint (env, jni_env, event_thread, method, | |
2399 | location); | |
2400 | } | |
2401 | break; | |
2402 | ||
2403 | case JVMTI_EVENT_FIELD_ACCESS: | |
2404 | if (env->callbacks.FieldAccess != NULL) | |
2405 | { | |
2406 | ARG (JNIEnv *, jni_env); | |
2407 | ARG (jmethodID, method); | |
2408 | ARG (jlocation, location); | |
2409 | ARG (jclass, field_class); | |
2410 | ARG (jobject, object); | |
2411 | ARG (jfieldID, field); | |
2412 | env->callbacks.FieldAccess (env, jni_env, event_thread, method, | |
2413 | location, field_class, object, field); | |
2414 | } | |
2415 | break; | |
2416 | ||
2417 | case JVMTI_EVENT_FIELD_MODIFICATION: | |
2418 | if (env->callbacks.FieldModification != NULL) | |
2419 | { | |
2420 | ARG (JNIEnv *, jni_env); | |
2421 | ARG (jmethodID, method); | |
2422 | ARG (jlocation, location); | |
2423 | ARG (jclass, field_class); | |
2424 | ARG (jobject, object); | |
2425 | ARG (jfieldID, field); | |
2426 | GET_CHAR_ARG (signature_type); | |
2427 | ARG (jvalue, new_value); | |
2428 | env->callbacks.FieldModification (env, jni_env, event_thread, method, | |
2429 | location, field_class, object, | |
2430 | field, signature_type, new_value); | |
2431 | } | |
2432 | break; | |
2433 | ||
2434 | case JVMTI_EVENT_METHOD_ENTRY: | |
2435 | if (env->callbacks.MethodEntry != NULL) | |
2436 | { | |
2437 | ARG (JNIEnv *, jni_env); | |
2438 | ARG (jmethodID, method); | |
2439 | env->callbacks.MethodEntry (env, jni_env, event_thread, method); | |
2440 | } | |
2441 | break; | |
2442 | ||
2443 | case JVMTI_EVENT_METHOD_EXIT: | |
2444 | if (env->callbacks.MethodExit != NULL) | |
2445 | { | |
2446 | ARG (JNIEnv *, jni_env); | |
2447 | ARG (jmethodID, method); | |
2448 | GET_BOOLEAN_ARG (was_popped_by_exception); | |
2449 | ARG (jvalue, return_value); | |
2450 | env->callbacks.MethodExit (env, jni_env, event_thread, method, | |
2451 | was_popped_by_exception, return_value); | |
2452 | } | |
2453 | break; | |
2454 | ||
2455 | case JVMTI_EVENT_NATIVE_METHOD_BIND: | |
2456 | if (env->callbacks.NativeMethodBind != NULL) | |
2457 | { | |
2458 | ARG (JNIEnv *, jni_env); | |
2459 | ARG (jmethodID, method); | |
2460 | ARG (void *, address); | |
2461 | ARG (void **, new_address_ptr); | |
2462 | env->callbacks.NativeMethodBind (env, jni_env, event_thread, method, | |
2463 | address, new_address_ptr); | |
2464 | } | |
2465 | break; | |
2466 | ||
2467 | case JVMTI_EVENT_COMPILED_METHOD_LOAD: | |
2468 | if (env->callbacks.CompiledMethodLoad != NULL) | |
2469 | { | |
2470 | ARG (jmethodID, method); | |
2471 | ARG (jint, code_size); | |
2472 | ARG (const void *, code_addr); | |
2473 | ARG (jint, map_length); | |
2474 | ARG (const jvmtiAddrLocationMap *, map); | |
2475 | ARG (const void *, compile_info); | |
2476 | env->callbacks.CompiledMethodLoad (env, method, code_size, code_addr, | |
2477 | map_length, map, compile_info); | |
2478 | } | |
2479 | break; | |
2480 | ||
2481 | case JVMTI_EVENT_COMPILED_METHOD_UNLOAD: | |
2482 | if (env->callbacks.CompiledMethodUnload != NULL) | |
2483 | { | |
2484 | ARG (jmethodID, method); | |
2485 | ARG (const void *, code_addr); | |
2486 | env->callbacks.CompiledMethodUnload (env, method, code_addr); | |
2487 | } | |
2488 | break; | |
2489 | ||
2490 | case JVMTI_EVENT_DYNAMIC_CODE_GENERATED: | |
2491 | if (env->callbacks.DynamicCodeGenerated != NULL) | |
2492 | { | |
2493 | ARG (const char *, name); | |
2494 | ARG (const void *, address); | |
2495 | ARG (jint, length); | |
2496 | env->callbacks.DynamicCodeGenerated (env, name, address, length); | |
2497 | } | |
2498 | break; | |
2499 | ||
2500 | case JVMTI_EVENT_DATA_DUMP_REQUEST: | |
2501 | if (env->callbacks.DataDumpRequest != NULL) | |
2502 | { | |
2503 | env->callbacks.DataDumpRequest (env); | |
2504 | } | |
2505 | break; | |
2506 | ||
2507 | case JVMTI_EVENT_MONITOR_WAIT: | |
2508 | if (env->callbacks.MonitorWait != NULL) | |
2509 | { | |
2510 | ARG (JNIEnv *, jni_env); | |
2511 | ARG (jobject, object); | |
2512 | ARG (jlong, timeout); | |
2513 | env->callbacks.MonitorWait (env, jni_env, event_thread, object, | |
2514 | timeout); | |
2515 | } | |
2516 | break; | |
2517 | ||
2518 | case JVMTI_EVENT_MONITOR_WAITED: | |
2519 | if (env->callbacks.MonitorWaited != NULL) | |
2520 | { | |
2521 | ARG (JNIEnv *, jni_env); | |
2522 | ARG (jobject, object); | |
2523 | GET_BOOLEAN_ARG (timed_out); | |
2524 | env->callbacks.MonitorWaited (env, jni_env, event_thread, object, | |
2525 | timed_out); | |
2526 | } | |
2527 | break; | |
2528 | ||
2529 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: | |
2530 | if (env->callbacks.MonitorContendedEnter != NULL) | |
2531 | { | |
2532 | ARG (JNIEnv *, jni_env); | |
2533 | ARG (jobject, object); | |
2534 | env->callbacks.MonitorContendedEnter (env, jni_env, event_thread, | |
2535 | object); | |
2536 | } | |
2537 | break; | |
2538 | ||
2539 | case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: | |
2540 | if (env->callbacks.MonitorContendedEntered != NULL) | |
2541 | { | |
2542 | ARG (JNIEnv *, jni_env); | |
2543 | ARG (jobject, object); | |
2544 | env->callbacks.MonitorContendedEntered (env, jni_env, event_thread, | |
2545 | object); | |
2546 | } | |
2547 | break; | |
2548 | ||
2549 | case JVMTI_EVENT_GARBAGE_COLLECTION_START: | |
2550 | if (env->callbacks.GarbageCollectionStart != NULL) | |
2551 | { | |
2552 | env->callbacks.GarbageCollectionStart (env); | |
2553 | } | |
2554 | break; | |
2555 | ||
2556 | case JVMTI_EVENT_GARBAGE_COLLECTION_FINISH: | |
2557 | if (env->callbacks.GarbageCollectionFinish != NULL) | |
2558 | { | |
2559 | env->callbacks.GarbageCollectionFinish (env); | |
2560 | } | |
2561 | break; | |
2562 | ||
2563 | case JVMTI_EVENT_OBJECT_FREE: | |
2564 | if (env->callbacks.ObjectFree != NULL) | |
2565 | { | |
2566 | ARG (jlong, tag); | |
2567 | env->callbacks.ObjectFree (env, tag); | |
2568 | } | |
2569 | break; | |
2570 | ||
2571 | case JVMTI_EVENT_VM_OBJECT_ALLOC: | |
2572 | if (env->callbacks.VMObjectAlloc != NULL) | |
2573 | { | |
2574 | ARG (JNIEnv *, jni_env); | |
2575 | ARG (jobject, object); | |
2576 | ARG (jclass, object_class); | |
2577 | ARG (jlong, size); | |
2578 | env->callbacks.VMObjectAlloc (env, jni_env, event_thread, | |
2579 | object, object_class, size); | |
2580 | } | |
2581 | break; | |
2582 | ||
2583 | default: | |
2584 | fprintf (stderr, "libgcj: post of unknown JVMTI event (%d)\n", | |
2585 | (int) type); | |
2586 | break; | |
2587 | } | |
2588 | va_end (args); | |
2589 | #undef ARG | |
2590 | #undef GET_BOOLEAN_ARG | |
2591 | #undef GET_CHAR_ARG | |
2592 | } | |
2593 | ||
2594 | /* Post an event to requesting JVMTI environments | |
2595 | * | |
2596 | * This function should not be called without consulting the | |
2597 | * JVMTI_REQUESTED_EVENT macro first (for speed). It does no real | |
2598 | * harm (other than kill speed), since this function will still | |
2599 | * only send the event if it was properly requested by an environment. | |
2600 | */ | |
2601 | void | |
2602 | _Jv_JVMTI_PostEvent (jvmtiEvent type, jthread event_thread, ...) | |
2603 | { | |
2604 | va_list args; | |
2605 | va_start (args, event_thread); | |
2606 | ||
d6df67ef | 2607 | _envListLock->readLock ()->lock (); |
ebf29cf6 KS |
2608 | struct jvmti_env_list *e; |
2609 | FOREACH_ENVIRONMENT (e) | |
2610 | { | |
2611 | /* Events are only posted if the event was explicitly enabled, | |
2612 | it has a registered event handler, and the event thread | |
2613 | matches (either globally or restricted to a specific thread). | |
2614 | Here we check all but the event handler, which will be handled | |
2615 | by post_event. */ | |
2616 | if (e->env->enabled[EVENT_INDEX(type)] | |
2617 | && (e->env->thread[EVENT_INDEX(type)] == NULL | |
2618 | || e->env->thread[EVENT_INDEX(type)] == event_thread)) | |
2619 | { | |
2620 | post_event (e->env, type, event_thread, args); | |
2621 | } | |
2622 | } | |
d6df67ef | 2623 | _envListLock->readLock ()->unlock (); |
ebf29cf6 | 2624 | va_end (args); |
e6789bef | 2625 | } |