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 
  63 void nsk_jvmti_setFailStatus() {
  64     currentAgentStatus = NSK_STATUS_FAILED;
  65 }
  66 
  67 int nsk_jvmti_isFailStatus() {
  68     return (nsk_jvmti_getStatus() != NSK_STATUS_PASSED);
  69 }
  70 
  71 jint nsk_jvmti_getStatus() {
  72     return currentAgentStatus;
  73 }
  74 
  75 /* ============================================================================= */
  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. */
  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 
  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. */
 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 */
 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. */
 132 JNIEnv* nsk_jvmti_getAgentJNIEnv() {
 133     return jni_env;
 134 }
 135 
 136 /** Get JVMTI environment for agent */
 137 jvmtiEnv* nsk_jvmti_getAgentJVMTIEnv() {
 138     return jvmti_env;
 139 }
 140 
 141 /* ============================================================================= */
 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
 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. */
 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. */
 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. */
 224 jthread nsk_jvmti_getAgentThread() {
 225     return agentThread;
 226 }
 227 
 228 /** Run registered user agent thread via wrapper. */
 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. */
 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. */
 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. */
 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. */
 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
 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
 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. */
 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. */
 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. */
 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. */
 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. */
 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. */
 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. */
 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. */
 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
 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  */
 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  */
 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 
 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 
 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 }