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 }