1 /*
2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "native_thread.h"
28 #include "jni_tools.h"
29 #include "jvmti_tools.h"
30
31 extern "C" {
32
33 /* ============================================================================= */
34
35 /* Be careful: do not build shared library which will be linked with different
36 * agent libs while global variables are used
37 * Now the same source is used to build different agent libs, so these
38 * variables are not shared between agents */
39
40 static jthread agentThread = NULL;
41 static jvmtiStartFunction agentThreadProc = NULL;
42 static void* agentThreadArg = NULL;
43
44
45 typedef enum { NEW, RUNNABLE, WAITING, SUSPENDED, TERMINATED } thread_state_t;
46
47 typedef struct agent_data_t {
48 volatile thread_state_t thread_state;
49 int last_debuggee_status;
50 jrawMonitorID monitor;
51 } agent_data_t;
52
53 static agent_data_t agent_data;
54
55 static jvmtiEnv* jvmti_env = NULL;
56 static JavaVM* jvm = NULL;
57 static JNIEnv* jni_env = NULL;
58
59 static volatile int currentAgentStatus = NSK_STATUS_PASSED;
60
61 /* ============================================================================= */
62
nsk_jvmti_setFailStatus()63 void nsk_jvmti_setFailStatus() {
64 currentAgentStatus = NSK_STATUS_FAILED;
65 }
66
nsk_jvmti_isFailStatus()67 int nsk_jvmti_isFailStatus() {
68 return (nsk_jvmti_getStatus() != NSK_STATUS_PASSED);
69 }
70
nsk_jvmti_getStatus()71 jint nsk_jvmti_getStatus() {
72 return currentAgentStatus;
73 }
74
75 /* ============================================================================= */
init_agent_data(jvmtiEnv * jvmti_env,agent_data_t * data)76 static jvmtiError init_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
77 data->thread_state = NEW;
78 data->last_debuggee_status = NSK_STATUS_PASSED;
79
80 return jvmti_env->CreateRawMonitor("agent_data_monitor", &data->monitor);
81 }
82
83 /** Reset agent data to prepare for another run. */
nsk_jvmti_resetAgentData()84 void nsk_jvmti_resetAgentData() {
85 rawMonitorEnter(jvmti_env, agent_data.monitor);
86 /* wait for agentThreadWrapper() to finish */
87 while (agent_data.thread_state != TERMINATED) {
88 rawMonitorWait(jvmti_env, agent_data.monitor, 10);
89 }
90 agent_data.thread_state = NEW;
91 agent_data.last_debuggee_status = NSK_STATUS_PASSED;
92 rawMonitorExit(jvmti_env, agent_data.monitor);
93 }
94
free_agent_data(jvmtiEnv * jvmti_env,agent_data_t * data)95 static jvmtiError free_agent_data(jvmtiEnv *jvmti_env, agent_data_t *data) {
96 return jvmti_env->DestroyRawMonitor(data->monitor);
97 }
98
99 /** Create JVMTI environment. */
nsk_jvmti_createJVMTIEnv(JavaVM * javaVM,void * reserved)100 jvmtiEnv* nsk_jvmti_createJVMTIEnv(JavaVM* javaVM, void* reserved) {
101 jvm = javaVM;
102 if (!NSK_VERIFY(javaVM->GetEnv((void **)&jvmti_env, JVMTI_VERSION_1_1) == JNI_OK)) {
103 nsk_jvmti_setFailStatus();
104 return NULL;
105 }
106
107 if (!NSK_JVMTI_VERIFY(init_agent_data(jvmti_env, &agent_data))) {
108 nsk_jvmti_setFailStatus();
109 return NULL;
110 }
111
112 return jvmti_env;
113 }
114
115 /** Dispose JVMTI environment */
nsk_jvmti_disposeJVMTIEnv(jvmtiEnv * jvmti_env)116 static int nsk_jvmti_disposeJVMTIEnv(jvmtiEnv* jvmti_env) {
117 if (jvmti_env != NULL) {
118 if (!NSK_JVMTI_VERIFY(jvmti_env->DisposeEnvironment())) {
119 nsk_jvmti_setFailStatus();
120 return NSK_FALSE;
121 }
122
123 if (!NSK_JVMTI_VERIFY(free_agent_data(jvmti_env, &agent_data))) {
124 nsk_jvmti_setFailStatus();
125 return NSK_FALSE;
126 }
127 }
128 return NSK_TRUE;
129 }
130
131 /** Get JNI environment for agent thread. */
nsk_jvmti_getAgentJNIEnv()132 JNIEnv* nsk_jvmti_getAgentJNIEnv() {
133 return jni_env;
134 }
135
136 /** Get JVMTI environment for agent */
nsk_jvmti_getAgentJVMTIEnv()137 jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() {
138 return jvmti_env;
139 }
140
141 /* ============================================================================= */
set_agent_thread_state(thread_state_t value)142 static void set_agent_thread_state(thread_state_t value) {
143 rawMonitorEnter(jvmti_env, agent_data.monitor);
144 agent_data.thread_state = value;
145 rawMonitorNotify(jvmti_env, agent_data.monitor);
146 rawMonitorExit(jvmti_env, agent_data.monitor);
147 }
148
149 /** Wrapper for user agent thread. */
150 static void JNICALL
agentThreadWrapper(jvmtiEnv * jvmti_env,JNIEnv * agentJNI,void * arg)151 agentThreadWrapper(jvmtiEnv* jvmti_env, JNIEnv* agentJNI, void* arg) {
152 jni_env = agentJNI;
153
154 /* run user agent proc */
155 {
156 set_agent_thread_state(RUNNABLE);
157
158 NSK_TRACE((*agentThreadProc)(jvmti_env, agentJNI, agentThreadArg));
159
160 set_agent_thread_state(TERMINATED);
161 }
162
163 /* finalize agent thread */
164 {
165 /* gelete global ref for agent thread */
166 agentJNI->DeleteGlobalRef(agentThread);
167 agentThread = NULL;
168 }
169 }
170
171 /** Start wrapper for user agent thread. */
startAgentThreadWrapper(JNIEnv * jni_env,jvmtiEnv * jvmti_env)172 static jthread startAgentThreadWrapper(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
173 const jint THREAD_PRIORITY = JVMTI_THREAD_MAX_PRIORITY;
174 const char* THREAD_NAME = "JVMTI agent thread";
175 const char* THREAD_CLASS_NAME = "java/lang/Thread";
176 const char* THREAD_CTOR_NAME = "<init>";
177 const char* THREAD_CTOR_SIGNATURE = "(Ljava/lang/String;)V";
178
179 jobject threadName = NULL;
180 jclass threadClass = NULL;
181 jmethodID threadCtor = NULL;
182 jobject threadObject = NULL;
183 jobject threadGlobalRef = NULL;
184
185 if (!NSK_JNI_VERIFY(jni_env, (threadClass = jni_env->FindClass(THREAD_CLASS_NAME)) != NULL)) {
186 return NULL;
187 }
188
189 if (!NSK_JNI_VERIFY(jni_env, (threadCtor =
190 jni_env->GetMethodID(threadClass, THREAD_CTOR_NAME, THREAD_CTOR_SIGNATURE)) != NULL))
191 return NULL;
192
193 if (!NSK_JNI_VERIFY(jni_env, (threadName = jni_env->NewStringUTF(THREAD_NAME)) != NULL))
194 return NULL;
195
196 if (!NSK_JNI_VERIFY(jni_env, (threadObject =
197 jni_env->NewObject(threadClass, threadCtor, threadName)) != NULL))
198 return NULL;
199
200 if (!NSK_JNI_VERIFY(jni_env, (threadGlobalRef =
201 jni_env->NewGlobalRef(threadObject)) != NULL)) {
202 jni_env->DeleteLocalRef(threadObject);
203 return NULL;
204 }
205 agentThread = (jthread)threadGlobalRef;
206
207 if (!NSK_JVMTI_VERIFY(
208 jvmti_env->RunAgentThread(agentThread, &agentThreadWrapper, agentThreadArg, THREAD_PRIORITY))) {
209 jni_env->DeleteGlobalRef(threadGlobalRef);
210 jni_env->DeleteLocalRef(threadObject);
211 return NULL;
212 }
213 return agentThread;
214 }
215
216 /** Register user agent thread with arg. */
nsk_jvmti_setAgentProc(jvmtiStartFunction proc,void * arg)217 int nsk_jvmti_setAgentProc(jvmtiStartFunction proc, void* arg) {
218 agentThreadProc = proc;
219 agentThreadArg = arg;
220 return NSK_TRUE;
221 }
222
223 /** Get agent thread ref. */
nsk_jvmti_getAgentThread()224 jthread nsk_jvmti_getAgentThread() {
225 return agentThread;
226 }
227
228 /** Run registered user agent thread via wrapper. */
nsk_jvmti_runAgentThread(JNIEnv * jni_env,jvmtiEnv * jvmti_env)229 static jthread nsk_jvmti_runAgentThread(JNIEnv *jni_env, jvmtiEnv* jvmti_env) {
230 /* start agent thread wrapper */
231 jthread thread = startAgentThreadWrapper(jni_env, jvmti_env);
232 if (thread == NULL) {
233 nsk_jvmti_setFailStatus();
234 return NULL;
235 }
236
237 return thread;
238 }
239
240 /* ============================================================================= */
241
242 /** Sleep current thread. */
nsk_jvmti_sleep(jlong timeout)243 void nsk_jvmti_sleep(jlong timeout) {
244 int seconds = (int)((timeout + 999) / 1000);
245 THREAD_sleep(seconds);
246 }
247
248 /** Sync point called from Java code. */
syncDebuggeeStatus(JNIEnv * jni_env,jvmtiEnv * jvmti_env,jint debuggeeStatus)249 static jint syncDebuggeeStatus(JNIEnv* jni_env, jvmtiEnv* jvmti_env, jint debuggeeStatus) {
250 jint result = NSK_STATUS_FAILED;
251
252 rawMonitorEnter(jvmti_env, agent_data.monitor);
253
254 /* save last debugee status */
255 agent_data.last_debuggee_status = debuggeeStatus;
256
257 /* we don't enter if-stmt in second call */
258 if (agent_data.thread_state == NEW) {
259 if (nsk_jvmti_runAgentThread(jni_env, jvmti_env) == NULL)
260 goto monitor_exit_and_return;
261
262 /* SP2.2-w - wait for agent thread */
263 while (agent_data.thread_state == NEW) {
264 rawMonitorWait(jvmti_env, agent_data.monitor, 0);
265 }
266 }
267
268 /* wait for sync permit */
269 /* we don't enter loop in first call */
270 while (agent_data.thread_state != WAITING && agent_data.thread_state != TERMINATED) {
271 /* SP4.2-w - second wait for agent thread */
272 rawMonitorWait(jvmti_env, agent_data.monitor, 0);
273 }
274
275 if (agent_data.thread_state != TERMINATED) {
276 agent_data.thread_state = SUSPENDED;
277 /* SP3.2-n - notify to start test */
278 /* SP6.2-n - notify to end test */
279 rawMonitorNotify(jvmti_env, agent_data.monitor);
280 }
281 else {
282 NSK_COMPLAIN0("Debuggee status sync aborted because agent thread has finished\n");
283 goto monitor_exit_and_return;
284 }
285
286 /* update status from debuggee */
287 if (debuggeeStatus != NSK_STATUS_PASSED) {
288 nsk_jvmti_setFailStatus();
289 }
290
291 while (agent_data.thread_state == SUSPENDED) {
292 /* SP5.2-w - wait while testing */
293 /* SP7.2 - wait for agent end */
294 rawMonitorWait(jvmti_env, agent_data.monitor, 0);
295 }
296
297 agent_data.last_debuggee_status = nsk_jvmti_getStatus();
298 result = agent_data.last_debuggee_status;
299
300 monitor_exit_and_return:
301 rawMonitorExit(jvmti_env, agent_data.monitor);
302 return result;
303 }
304
305 /** Wait for sync point with Java code. */
nsk_jvmti_waitForSync(jlong timeout)306 int nsk_jvmti_waitForSync(jlong timeout) {
307 static const int inc_timeout = 1000;
308
309 jlong t = 0;
310 int result = NSK_TRUE;
311
312 rawMonitorEnter(jvmti_env, agent_data.monitor);
313
314 agent_data.thread_state = WAITING;
315
316 /* SP2.2-n - notify agent is waiting and wait */
317 /* SP4.1-n - notify agent is waiting and wait */
318 rawMonitorNotify(jvmti_env, agent_data.monitor);
319
320 while (agent_data.thread_state == WAITING) {
321 /* SP3.2-w - wait to start test */
322 /* SP6.2-w - wait to end test */
323 rawMonitorWait(jvmti_env, agent_data.monitor, inc_timeout);
324
325 if (timeout == 0) continue;
326
327 t += inc_timeout;
328
329 if (t >= timeout) break;
330 }
331
332 if (agent_data.thread_state == WAITING) {
333 NSK_COMPLAIN1("No status sync occured for timeout: %" LL "d ms\n", timeout);
334 nsk_jvmti_setFailStatus();
335 result = NSK_FALSE;
336 }
337
338 rawMonitorExit(jvmti_env, agent_data.monitor);
339
340 return result;
341 }
342
343 /** Resume java code suspended on sync point. */
nsk_jvmti_resumeSync()344 int nsk_jvmti_resumeSync() {
345 int result;
346 rawMonitorEnter(jvmti_env, agent_data.monitor);
347
348 if (agent_data.thread_state == SUSPENDED) {
349 result = NSK_TRUE;
350 agent_data.thread_state = RUNNABLE;
351 /* SP5.2-n - notify suspend done */
352 /* SP7.2-n - notify agent end */
353 rawMonitorNotify(jvmti_env, agent_data.monitor);
354 }
355 else {
356 NSK_COMPLAIN0("Debuggee was not suspended on status sync\n");
357 nsk_jvmti_setFailStatus();
358 result = NSK_FALSE;
359 }
360
361 rawMonitorExit(jvmti_env, agent_data.monitor);
362 return NSK_TRUE;
363 }
364
365 /** Native function for Java code to provide sync point. */
366 JNIEXPORT jint JNICALL
Java_nsk_share_jvmti_DebugeeClass_checkStatus(JNIEnv * jni_env,jclass cls,jint debuggeeStatus)367 Java_nsk_share_jvmti_DebugeeClass_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
368 jint status;
369 NSK_TRACE(status = syncDebuggeeStatus(jni_env, jvmti_env, debuggeeStatus));
370 return status;
371 }
372
373 /** Native function for Java code to reset agent data. */
374 JNIEXPORT void JNICALL
Java_nsk_share_jvmti_DebugeeClass_resetAgentData(JNIEnv * jni_env,jclass cls)375 Java_nsk_share_jvmti_DebugeeClass_resetAgentData(JNIEnv* jni_env, jclass cls) {
376 NSK_TRACE(nsk_jvmti_resetAgentData());
377 }
378
379 /* ============================================================================= */
380
381 /** Find loaded class by signature. */
nsk_jvmti_classBySignature(const char signature[])382 jclass nsk_jvmti_classBySignature(const char signature[]) {
383 jclass* classes = NULL;
384 jint count = 0;
385 jclass foundClass = NULL;
386 int i;
387
388 if (!NSK_VERIFY(signature != NULL)) {
389 nsk_jvmti_setFailStatus();
390 return NULL;
391 }
392
393 if (!NSK_JVMTI_VERIFY(jvmti_env->GetLoadedClasses(&count, &classes))) {
394 nsk_jvmti_setFailStatus();
395 return NULL;
396 }
397
398 for (i = 0; i < count; i++) {
399 char* sig = NULL;
400 char* generic = NULL;
401
402 if (!NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(classes[i], &sig, &generic))) {
403 nsk_jvmti_setFailStatus();
404 break;
405 }
406
407 if (sig != NULL && strcmp(signature, sig) == 0) {
408 foundClass = classes[i];
409 }
410
411 if (!(NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)sig))
412 && NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)generic)))) {
413 nsk_jvmti_setFailStatus();
414 break;
415 }
416
417 if (foundClass != NULL)
418 break;
419 }
420
421 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)classes))) {
422 nsk_jvmti_setFailStatus();
423 return NULL;
424 }
425
426 if (!NSK_JNI_VERIFY(jni_env, (foundClass = (jclass)
427 jni_env->NewGlobalRef(foundClass)) != NULL)) {
428 nsk_jvmti_setFailStatus();
429 return NULL;
430 }
431
432 return foundClass;
433 }
434
435 /** Find alive thread by name. */
nsk_jvmti_threadByName(const char name[])436 jthread nsk_jvmti_threadByName(const char name[]) {
437 jthread* threads = NULL;
438 jint count = 0;
439 jthread foundThread = NULL;
440 int i;
441
442 if (!NSK_VERIFY(name != NULL)) {
443 nsk_jvmti_setFailStatus();
444 return NULL;
445 }
446
447 if (!NSK_JVMTI_VERIFY(jvmti_env->GetAllThreads(&count, &threads))) {
448 nsk_jvmti_setFailStatus();
449 return NULL;
450 }
451
452 for (i = 0; i < count; i++) {
453 jvmtiThreadInfo info;
454
455 if (!NSK_JVMTI_VERIFY(jvmti_env->GetThreadInfo(threads[i], &info))) {
456 nsk_jvmti_setFailStatus();
457 break;
458 }
459
460 if (info.name != NULL && strcmp(name, info.name) == 0) {
461 foundThread = threads[i];
462 break;
463 }
464 }
465
466 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)threads))) {
467 nsk_jvmti_setFailStatus();
468 return NULL;
469 }
470
471 if (!NSK_JNI_VERIFY(jni_env, (foundThread = (jthread)
472 jni_env->NewGlobalRef(foundThread)) != NULL)) {
473 nsk_jvmti_setFailStatus();
474 return NULL;
475 }
476
477 return foundThread;
478 }
479
480
481 /* ============================================================================= */
482
483 /** Add all capabilities for finding line locations. */
nsk_jvmti_addLocationCapabilities()484 int nsk_jvmti_addLocationCapabilities() {
485 jvmtiCapabilities caps;
486
487 memset(&caps, 0, sizeof(caps));
488 caps.can_get_line_numbers = 1;
489 if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))
490 return NSK_FALSE;
491
492 return NSK_TRUE;
493 }
494
495 /** Add all capabilities for using breakpoints. */
nsk_jvmti_addBreakpointCapabilities()496 int nsk_jvmti_addBreakpointCapabilities() {
497 jvmtiCapabilities caps;
498
499 if (!nsk_jvmti_addLocationCapabilities())
500 return NSK_FALSE;
501
502 memset(&caps, 0, sizeof(caps));
503 caps.can_generate_breakpoint_events = 1;
504 if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))
505 return NSK_FALSE;
506
507 return NSK_TRUE;
508 }
509
510 /** Find line location. */
nsk_jvmti_getLineLocation(jclass cls,jmethodID method,int line)511 jlocation nsk_jvmti_getLineLocation(jclass cls, jmethodID method, int line) {
512 jint count = 0;
513 jvmtiLineNumberEntry* table = NULL;
514 jlocation location = NSK_JVMTI_INVALID_JLOCATION;
515 int i;
516
517 if (!NSK_JVMTI_VERIFY(jvmti_env->GetLineNumberTable(method, &count, &table)))
518 return NSK_JVMTI_INVALID_JLOCATION;
519
520 for (i = 0; i < count; i++) {
521 if (table[i].line_number == line) {
522 location = table[i].start_location;
523 break;
524 }
525 }
526
527 if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate((unsigned char*)table)))
528 return NSK_JVMTI_INVALID_JLOCATION;
529
530 return location;
531 }
532
533 /** Set breakpoint to a line. */
nsk_jvmti_setLineBreakpoint(jclass cls,jmethodID method,int line)534 jlocation nsk_jvmti_setLineBreakpoint(jclass cls, jmethodID method, int line) {
535 jlocation location = NSK_JVMTI_INVALID_JLOCATION;
536
537 if (!NSK_VERIFY((location =
538 nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
539 return NSK_JVMTI_INVALID_JLOCATION;
540
541 if (!NSK_JVMTI_VERIFY(jvmti_env->SetBreakpoint(method, location)))
542 return NSK_JVMTI_INVALID_JLOCATION;
543
544 return location;
545 }
546
547 /** Remove breakpoint from a line. */
nsk_jvmti_clearLineBreakpoint(jclass cls,jmethodID method,int line)548 jlocation nsk_jvmti_clearLineBreakpoint(jclass cls, jmethodID method, int line) {
549 jlocation location = NSK_JVMTI_INVALID_JLOCATION;
550
551 if (!NSK_VERIFY((location =
552 nsk_jvmti_getLineLocation(cls, method, line)) != NSK_JVMTI_INVALID_JLOCATION))
553 return NSK_JVMTI_INVALID_JLOCATION;
554
555 if (!NSK_JVMTI_VERIFY(jvmti_env->ClearBreakpoint(method, location)))
556 return NSK_JVMTI_INVALID_JLOCATION;
557
558 return location;
559 }
560
561 /* ============================================================================= */
562
563 /** Enable or disable given events. */
nsk_jvmti_enableEvents(jvmtiEventMode enable,int size,jvmtiEvent list[],jthread thread)564 int nsk_jvmti_enableEvents(jvmtiEventMode enable, int size, jvmtiEvent list[], jthread thread) {
565 int i;
566
567 for (i = 0; i < size; i++) {
568 if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(enable, list[i], thread))) {
569 nsk_jvmti_setFailStatus();
570 return NSK_FALSE;
571 }
572 }
573 return NSK_TRUE;
574 }
575
576 /* ============================================================================= */
577
578 typedef jint (JNICALL *checkStatus_type)(JNIEnv* jni_env, jclass cls, jint debuggeeStatus);
579
580 static checkStatus_type checkStatus_func = NULL;
581
582 /**
583 * Proxy function to gain sequential access to checkStatus of each agent
584 */
585 JNIEXPORT jint JNICALL
MA_checkStatus(JNIEnv * jni_env,jclass cls,jint debuggeeStatus)586 MA_checkStatus(JNIEnv* jni_env, jclass cls, jint debuggeeStatus) {
587 jint status;
588
589 NSK_TRACE(status = syncDebuggeeStatus(jni_env, jvmti_env, debuggeeStatus));
590 return (*checkStatus_func)(jni_env, cls, status);
591 }
592
593 /**
594 * nativeMethodBind callback:
595 * if needed, redirects checkStatus native method call
596 */
nativeMethodBind(jvmtiEnv * jvmti_env,JNIEnv * jni_env,jthread thread,jmethodID mid,void * address,void ** new_address_ptr)597 static void JNICALL nativeMethodBind(jvmtiEnv* jvmti_env, JNIEnv *jni_env,
598 jthread thread, jmethodID mid,
599 void* address, void** new_address_ptr) {
600 const char* BIND_CLASS_NAME = "Lnsk/share/jvmti/DebugeeClass;";
601 const char* BIND_METHOD_NAME = "checkStatus";
602 const char* BIND_METHOD_SIGNATURE = "(I)I";
603
604 jvmtiPhase phase;
605 jclass cls;
606 char *class_sig = NULL;
607 char *name = NULL;
608 char *sig = NULL;
609
610 if (!NSK_JVMTI_VERIFY(jvmti_env->GetPhase(&phase))) {
611 nsk_jvmti_setFailStatus();
612 return;
613 }
614
615 if (phase != JVMTI_PHASE_START && phase != JVMTI_PHASE_LIVE)
616 return;
617
618 if (NSK_JVMTI_VERIFY(jvmti_env->GetMethodName(mid, &name, &sig, NULL))) {
619 if (strcmp(name, BIND_METHOD_NAME) == 0 &&
620 strcmp(sig, BIND_METHOD_SIGNATURE) == 0) {
621
622 if (NSK_JVMTI_VERIFY(jvmti_env->GetMethodDeclaringClass(mid, &cls))
623 && NSK_JVMTI_VERIFY(jvmti_env->GetClassSignature(cls, &class_sig, NULL))
624 && strcmp(class_sig, BIND_CLASS_NAME) == 0
625 && address != (void*)Java_nsk_share_jvmti_DebugeeClass_checkStatus) {
626 checkStatus_func = (checkStatus_type)address;
627 NSK_TRACE(*new_address_ptr = (void*)MA_checkStatus);
628 }
629 }
630 }
631
632 if (name != NULL)
633 jvmti_env->Deallocate((unsigned char*)name);
634
635 if (sig != NULL)
636 jvmti_env->Deallocate((unsigned char*)sig);
637
638 if (class_sig != NULL)
639 jvmti_env->Deallocate((unsigned char*)class_sig);
640 }
641
642 /**
643 * Initialize multiple agent:
644 * establish processing of nativeMethodBind events
645 */
nsk_jvmti_init_MA(jvmtiEventCallbacks * callbacks)646 int nsk_jvmti_init_MA(jvmtiEventCallbacks* callbacks) {
647
648 if (callbacks == NULL) {
649 NSK_COMPLAIN0("callbacks should not be NULL\n");
650 nsk_jvmti_setFailStatus();
651 return NSK_FALSE;
652 }
653
654 if (callbacks->NativeMethodBind != NULL) {
655 NSK_COMPLAIN0("callbacks.NativeMethodBind should be NULL\n");
656 nsk_jvmti_setFailStatus();
657 return NSK_FALSE;
658 }
659
660 {
661 jvmtiCapabilities caps;
662 memset(&caps, 0, sizeof(caps));
663 caps.can_generate_native_method_bind_events = 1;
664 if (!NSK_JVMTI_VERIFY(jvmti_env->AddCapabilities(&caps)))
665 return NSK_FALSE;
666 }
667
668 callbacks->NativeMethodBind = nativeMethodBind;
669 if (!NSK_JVMTI_VERIFY(jvmti_env->SetEventCallbacks(callbacks, sizeof(jvmtiEventCallbacks))))
670 return NSK_FALSE;
671
672 if (!NSK_JVMTI_VERIFY(
673 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, NULL)))
674 return NSK_FALSE;
675
676 return NSK_TRUE;
677 }
678
679 /* ============================================================================= */
680
nsk_jvmti_isOptionalEvent(jvmtiEvent event)681 int nsk_jvmti_isOptionalEvent(jvmtiEvent event) {
682
683 return (event == JVMTI_EVENT_EXCEPTION)
684 || (event == JVMTI_EVENT_EXCEPTION_CATCH)
685 || (event == JVMTI_EVENT_SINGLE_STEP)
686 || (event == JVMTI_EVENT_FRAME_POP)
687 || (event == JVMTI_EVENT_BREAKPOINT)
688 || (event == JVMTI_EVENT_FIELD_ACCESS)
689 || (event == JVMTI_EVENT_FIELD_MODIFICATION)
690 || (event == JVMTI_EVENT_METHOD_ENTRY)
691 || (event == JVMTI_EVENT_METHOD_EXIT)
692 || (event == JVMTI_EVENT_NATIVE_METHOD_BIND)
693 || (event == JVMTI_EVENT_COMPILED_METHOD_LOAD)
694 || (event == JVMTI_EVENT_COMPILED_METHOD_UNLOAD)
695 || (event == JVMTI_EVENT_MONITOR_WAIT)
696 || (event == JVMTI_EVENT_MONITOR_WAITED)
697 || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTER)
698 || (event == JVMTI_EVENT_MONITOR_CONTENDED_ENTERED)
699 || (event == JVMTI_EVENT_GARBAGE_COLLECTION_START)
700 || (event == JVMTI_EVENT_GARBAGE_COLLECTION_FINISH)
701 || (event == JVMTI_EVENT_OBJECT_FREE)
702 || (event == JVMTI_EVENT_VM_OBJECT_ALLOC);
703 }
704
705 /* ============================================================================= */
706
nsk_jvmti_showPossessedCapabilities(jvmtiEnv * jvmti_env)707 void nsk_jvmti_showPossessedCapabilities(jvmtiEnv *jvmti_env) {
708
709 jvmtiCapabilities caps;
710
711 if (!NSK_JVMTI_VERIFY(jvmti_env->GetCapabilities(&caps))) {
712 return;
713 }
714
715 NSK_DISPLAY0("\n");
716 NSK_DISPLAY0("Possessed capabilities:\n");
717 NSK_DISPLAY0("-----------------------\n");
718 if (caps.can_tag_objects)
719 NSK_DISPLAY0("\tcan_tag_objects\n");
720 if (caps.can_generate_field_modification_events)
721 NSK_DISPLAY0("\tcan_generate_field_modification_events\n");
722 if (caps.can_generate_field_access_events)
723 NSK_DISPLAY0("\tcan_generate_field_access_events\n");
724 if (caps.can_get_bytecodes)
725 NSK_DISPLAY0("\tcan_get_bytecodes\n");
726 if (caps.can_get_synthetic_attribute)
727 NSK_DISPLAY0("\tcan_get_synthetic_attribute\n");
728 if (caps.can_get_owned_monitor_info)
729 NSK_DISPLAY0("\tcan_get_owned_monitor_info\n");
730 if (caps.can_get_current_contended_monitor)
731 NSK_DISPLAY0("\tcan_get_current_contended_monitor\n");
732 if (caps.can_get_monitor_info)
733 NSK_DISPLAY0("\tcan_get_monitor_info\n");
734 if (caps.can_pop_frame)
735 NSK_DISPLAY0("\tcan_pop_frame\n");
736 if (caps.can_redefine_classes)
737 NSK_DISPLAY0("\tcan_redefine_classes\n");
738 if (caps.can_signal_thread)
739 NSK_DISPLAY0("\tcan_signal_thread\n");
740 if (caps.can_get_source_file_name)
741 NSK_DISPLAY0("\tcan_get_source_file_name\n");
742 if (caps.can_get_line_numbers)
743 NSK_DISPLAY0("\tcan_get_line_numbers\n");
744 if (caps.can_get_source_debug_extension)
745 NSK_DISPLAY0("\tcan_get_source_debug_extension\n");
746 if (caps.can_access_local_variables)
747 NSK_DISPLAY0("\tcan_access_local_variables\n");
748 if (caps.can_maintain_original_method_order)
749 NSK_DISPLAY0("\tcan_maintain_original_method_order\n");
750 if (caps.can_generate_single_step_events)
751 NSK_DISPLAY0("\tcan_generate_single_step_events\n");
752 if (caps.can_generate_exception_events)
753 NSK_DISPLAY0("\tcan_generate_exception_events\n");
754 if (caps.can_generate_frame_pop_events)
755 NSK_DISPLAY0("\tcan_generate_frame_pop_events\n");
756 if (caps.can_generate_breakpoint_events)
757 NSK_DISPLAY0("\tcan_generate_breakpoint_events\n");
758 if (caps.can_suspend)
759 NSK_DISPLAY0("\tcan_suspend\n");
760 if (caps.can_get_current_thread_cpu_time)
761 NSK_DISPLAY0("\tcan_get_current_thread_cpu_time\n");
762 if (caps.can_get_thread_cpu_time)
763 NSK_DISPLAY0("\tcan_get_thread_cpu_time\n");
764 if (caps.can_generate_method_entry_events)
765 NSK_DISPLAY0("\tcan_generate_method_entry_events\n");
766 if (caps.can_generate_method_exit_events)
767 NSK_DISPLAY0("\tcan_generate_method_exit_events\n");
768 if (caps.can_generate_all_class_hook_events)
769 NSK_DISPLAY0("\tcan_generate_all_class_hook_events\n");
770 if (caps.can_generate_compiled_method_load_events)
771 NSK_DISPLAY0("\tcan_generate_compiled_method_load_events\n");
772 if (caps.can_generate_monitor_events)
773 NSK_DISPLAY0("\tcan_generate_monitor_events\n");
774 if (caps.can_generate_vm_object_alloc_events)
775 NSK_DISPLAY0("\tcan_generate_vm_object_alloc_events\n");
776 if (caps.can_generate_native_method_bind_events)
777 NSK_DISPLAY0("\tcan_generate_native_method_bind_events\n");
778 if (caps.can_generate_garbage_collection_events)
779 NSK_DISPLAY0("\tcan_generate_garbage_collection_events\n");
780 if (caps.can_generate_object_free_events)
781 NSK_DISPLAY0("\tcan_generate_object_free_events\n");
782
783 NSK_DISPLAY0("\n");
784 }
785
786 /* ============================================================================= */
787
788 }
789