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