1 /* 2 * Copyright (c) 1998, 2024, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <ctype.h> 27 28 #include "util.h" 29 #include "utf_util.h" 30 #include "transport.h" 31 #include "eventHandler.h" 32 #include "threadControl.h" 33 #include "outStream.h" 34 #include "inStream.h" 35 #include "invoker.h" 36 #include "signature.h" 37 38 39 /* Global data area */ 40 BackendGlobalData *gdata = NULL; 41 42 /* Forward declarations */ 43 static jboolean isInterface(jclass clazz); 44 static jboolean isArrayClass(jclass clazz); 45 static char * getPropertyUTF8(JNIEnv *env, char *propertyName); 46 47 /* Save an object reference for use later (create a NewGlobalRef) */ 48 void 49 saveGlobalRef(JNIEnv *env, jobject obj, jobject *pobj) 50 { 51 jobject newobj; 52 53 if ( pobj == NULL ) { 54 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef pobj"); 55 } 56 if ( *pobj != NULL ) { 57 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef *pobj"); 58 } 59 if ( env == NULL ) { 60 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef env"); 61 } 62 if ( obj == NULL ) { 63 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"saveGlobalRef obj"); 64 } 65 newobj = JNI_FUNC_PTR(env,NewGlobalRef)(env, obj); 66 if ( newobj == NULL ) { 67 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"NewGlobalRef"); 68 } 69 *pobj = newobj; 70 } 71 72 /* Toss a previously saved object reference */ 73 void 74 tossGlobalRef(JNIEnv *env, jobject *pobj) 75 { 76 jobject obj; 77 78 if ( pobj == NULL ) { 79 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"tossGlobalRef pobj"); 80 } 81 obj = *pobj; 82 if ( env == NULL ) { 83 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"tossGlobalRef env"); 84 } 85 if ( obj == NULL ) { 86 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"tossGlobalRef obj"); 87 } 88 JNI_FUNC_PTR(env,DeleteGlobalRef)(env, obj); 89 *pobj = NULL; 90 } 91 92 jclass 93 findClass(JNIEnv *env, const char * name) 94 { 95 jclass x; 96 97 if ( env == NULL ) { 98 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"findClass env"); 99 } 100 if ( name == NULL || name[0] == 0 ) { 101 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"findClass name"); 102 } 103 x = JNI_FUNC_PTR(env,FindClass)(env, name); 104 if (x == NULL) { 105 ERROR_MESSAGE(("JDWP Can't find class %s", name)); 106 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 107 } 108 if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) { 109 ERROR_MESSAGE(("JDWP Exception occurred finding class %s", name)); 110 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 111 } 112 return x; 113 } 114 115 jmethodID 116 getMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature) 117 { 118 jmethodID method; 119 120 if ( env == NULL ) { 121 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod env"); 122 } 123 if ( clazz == NULL ) { 124 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod clazz"); 125 } 126 if ( name == NULL || name[0] == 0 ) { 127 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod name"); 128 } 129 if ( signature == NULL || signature[0] == 0 ) { 130 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getMethod signature"); 131 } 132 method = JNI_FUNC_PTR(env,GetMethodID)(env, clazz, name, signature); 133 if (method == NULL) { 134 ERROR_MESSAGE(("JDWP Can't find method %s with signature %s", 135 name, signature)); 136 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 137 } 138 if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) { 139 ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s", 140 name, signature)); 141 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 142 } 143 return method; 144 } 145 146 static jmethodID 147 getStaticMethod(JNIEnv *env, jclass clazz, const char * name, const char *signature) 148 { 149 jmethodID method; 150 151 if ( env == NULL ) { 152 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod env"); 153 } 154 if ( clazz == NULL ) { 155 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod clazz"); 156 } 157 if ( name == NULL || name[0] == 0 ) { 158 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod name"); 159 } 160 if ( signature == NULL || signature[0] == 0 ) { 161 EXIT_ERROR(AGENT_ERROR_ILLEGAL_ARGUMENT,"getStaticMethod signature"); 162 } 163 method = JNI_FUNC_PTR(env,GetStaticMethodID)(env, clazz, name, signature); 164 if (method == NULL) { 165 ERROR_MESSAGE(("JDWP Can't find method %s with signature %s", 166 name, signature)); 167 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 168 } 169 if ( JNI_FUNC_PTR(env,ExceptionOccurred)(env) ) { 170 ERROR_MESSAGE(("JDWP Exception occurred finding method %s with signature %s", 171 name, signature)); 172 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 173 } 174 return method; 175 } 176 177 178 179 void 180 util_initialize(JNIEnv *env) 181 { 182 WITH_LOCAL_REFS(env, 6) { 183 184 jvmtiError error; 185 jclass localClassClass; 186 jclass localThreadClass; 187 jclass localThreadGroupClass; 188 jclass localClassLoaderClass; 189 jclass localStringClass; 190 jclass localSystemClass; 191 jclass localPropertiesClass; 192 jclass localVMSupportClass; 193 jobject localAgentProperties; 194 jmethodID getAgentProperties; 195 jint groupCount; 196 jthreadGroup *groups; 197 jthreadGroup localSystemThreadGroup; 198 199 /* Find some standard classes */ 200 201 localClassClass = findClass(env,"java/lang/Class"); 202 localThreadClass = findClass(env,"java/lang/Thread"); 203 localThreadGroupClass = findClass(env,"java/lang/ThreadGroup"); 204 localClassLoaderClass = findClass(env,"java/lang/ClassLoader"); 205 localStringClass = findClass(env,"java/lang/String"); 206 localSystemClass = findClass(env,"java/lang/System"); 207 localPropertiesClass = findClass(env,"java/util/Properties"); 208 209 /* Save references */ 210 211 saveGlobalRef(env, localClassClass, &(gdata->classClass)); 212 saveGlobalRef(env, localThreadClass, &(gdata->threadClass)); 213 saveGlobalRef(env, localThreadGroupClass, &(gdata->threadGroupClass)); 214 saveGlobalRef(env, localClassLoaderClass, &(gdata->classLoaderClass)); 215 saveGlobalRef(env, localStringClass, &(gdata->stringClass)); 216 saveGlobalRef(env, localSystemClass, &(gdata->systemClass)); 217 218 /* Find some standard methods */ 219 220 gdata->threadConstructor = 221 getMethod(env, gdata->threadClass, 222 "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"); 223 gdata->threadSetDaemon = 224 getMethod(env, gdata->threadClass, "setDaemon", "(Z)V"); 225 gdata->systemGetProperty = 226 getStaticMethod(env, gdata->systemClass, 227 "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"); 228 gdata->setProperty = 229 getMethod(env, localPropertiesClass, 230 "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"); 231 232 /* Find the system thread group */ 233 234 groups = NULL; 235 groupCount = 0; 236 error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups) 237 (gdata->jvmti, &groupCount, &groups); 238 if (error != JVMTI_ERROR_NONE ) { 239 EXIT_ERROR(error, "Can't get system thread group"); 240 } 241 if ( groupCount == 0 ) { 242 EXIT_ERROR(AGENT_ERROR_NULL_POINTER, "Can't get system thread group"); 243 } 244 localSystemThreadGroup = groups[0]; 245 saveGlobalRef(env, localSystemThreadGroup, &(gdata->systemThreadGroup)); 246 jvmtiDeallocate(groups); 247 248 /* Get some basic Java property values we will need at some point */ 249 gdata->property_java_version 250 = getPropertyUTF8(env, "java.version"); 251 gdata->property_java_vm_name 252 = getPropertyUTF8(env, "java.vm.name"); 253 gdata->property_java_vm_info 254 = getPropertyUTF8(env, "java.vm.info"); 255 gdata->property_java_class_path 256 = getPropertyUTF8(env, "java.class.path"); 257 gdata->property_sun_boot_library_path 258 = getPropertyUTF8(env, "sun.boot.library.path"); 259 gdata->property_path_separator 260 = getPropertyUTF8(env, "path.separator"); 261 gdata->property_user_dir 262 = getPropertyUTF8(env, "user.dir"); 263 264 /* Get agent properties: invoke VMSupport.getAgentProperties */ 265 localVMSupportClass = JNI_FUNC_PTR(env,FindClass) 266 (env, "jdk/internal/vm/VMSupport"); 267 if (localVMSupportClass == NULL) { 268 gdata->agent_properties = NULL; 269 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 270 JNI_FUNC_PTR(env,ExceptionClear)(env); 271 } 272 } else { 273 getAgentProperties = 274 getStaticMethod(env, localVMSupportClass, 275 "getAgentProperties", "()Ljava/util/Properties;"); 276 localAgentProperties = 277 JNI_FUNC_PTR(env,CallStaticObjectMethod) 278 (env, localVMSupportClass, getAgentProperties); 279 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 280 JNI_FUNC_PTR(env,ExceptionClear)(env); 281 EXIT_ERROR(AGENT_ERROR_INTERNAL, 282 "Exception occurred calling VMSupport.getAgentProperties"); 283 } 284 saveGlobalRef(env, localAgentProperties, &(gdata->agent_properties)); 285 } 286 287 } END_WITH_LOCAL_REFS(env); 288 289 } 290 291 void 292 util_reset(void) 293 { 294 } 295 296 jboolean 297 isObjectTag(jbyte tag) { 298 return (tag == JDWP_TAG(OBJECT)) || 299 (tag == JDWP_TAG(STRING)) || 300 (tag == JDWP_TAG(THREAD)) || 301 (tag == JDWP_TAG(THREAD_GROUP)) || 302 (tag == JDWP_TAG(CLASS_LOADER)) || 303 (tag == JDWP_TAG(CLASS_OBJECT)) || 304 (tag == JDWP_TAG(ARRAY)); 305 } 306 307 jbyte 308 specificTypeKey(JNIEnv *env, jobject object) 309 { 310 if (object == NULL) { 311 return JDWP_TAG(OBJECT); 312 } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->stringClass)) { 313 return JDWP_TAG(STRING); 314 } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadClass)) { 315 return JDWP_TAG(THREAD); 316 } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadGroupClass)) { 317 return JDWP_TAG(THREAD_GROUP); 318 } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classLoaderClass)) { 319 return JDWP_TAG(CLASS_LOADER); 320 } else if (JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classClass)) { 321 return JDWP_TAG(CLASS_OBJECT); 322 } else { 323 jboolean classIsArray; 324 325 WITH_LOCAL_REFS(env, 1) { 326 jclass clazz; 327 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object); 328 classIsArray = isArrayClass(clazz); 329 } END_WITH_LOCAL_REFS(env); 330 331 return (classIsArray ? JDWP_TAG(ARRAY) : JDWP_TAG(OBJECT)); 332 } 333 } 334 335 static void 336 writeFieldValue(JNIEnv *env, PacketOutputStream *out, jobject object, 337 jfieldID field) 338 { 339 jclass clazz; 340 char *signature = NULL; 341 jvmtiError error; 342 jbyte typeKey; 343 344 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object); 345 error = fieldSignature(clazz, field, NULL, &signature, NULL); 346 if (error != JVMTI_ERROR_NONE) { 347 outStream_setError(out, map2jdwpError(error)); 348 return; 349 } 350 typeKey = jdwpTag(signature); 351 jvmtiDeallocate(signature); 352 353 if (isReferenceTag(typeKey)) { 354 355 jobject value = JNI_FUNC_PTR(env,GetObjectField)(env, object, field); 356 (void)outStream_writeByte(out, specificTypeKey(env, value)); 357 (void)outStream_writeObjectRef(env, out, value); 358 return; 359 360 } 361 362 /* 363 * For primitive types, the type key is bounced back as is. 364 */ 365 366 (void)outStream_writeByte(out, typeKey); 367 368 switch (typeKey) { 369 case JDWP_TAG(BYTE): 370 (void)outStream_writeByte(out, 371 JNI_FUNC_PTR(env,GetByteField)(env, object, field)); 372 break; 373 374 case JDWP_TAG(CHAR): 375 (void)outStream_writeChar(out, 376 JNI_FUNC_PTR(env,GetCharField)(env, object, field)); 377 break; 378 379 case JDWP_TAG(FLOAT): 380 (void)outStream_writeFloat(out, 381 JNI_FUNC_PTR(env,GetFloatField)(env, object, field)); 382 break; 383 384 case JDWP_TAG(DOUBLE): 385 (void)outStream_writeDouble(out, 386 JNI_FUNC_PTR(env,GetDoubleField)(env, object, field)); 387 break; 388 389 case JDWP_TAG(INT): 390 (void)outStream_writeInt(out, 391 JNI_FUNC_PTR(env,GetIntField)(env, object, field)); 392 break; 393 394 case JDWP_TAG(LONG): 395 (void)outStream_writeLong(out, 396 JNI_FUNC_PTR(env,GetLongField)(env, object, field)); 397 break; 398 399 case JDWP_TAG(SHORT): 400 (void)outStream_writeShort(out, 401 JNI_FUNC_PTR(env,GetShortField)(env, object, field)); 402 break; 403 404 case JDWP_TAG(BOOLEAN): 405 (void)outStream_writeBoolean(out, 406 JNI_FUNC_PTR(env,GetBooleanField)(env, object, field)); 407 break; 408 } 409 } 410 411 static void 412 writeStaticFieldValue(JNIEnv *env, PacketOutputStream *out, jclass clazz, 413 jfieldID field) 414 { 415 jvmtiError error; 416 char *signature = NULL; 417 jbyte typeKey; 418 419 error = fieldSignature(clazz, field, NULL, &signature, NULL); 420 if (error != JVMTI_ERROR_NONE) { 421 outStream_setError(out, map2jdwpError(error)); 422 return; 423 } 424 typeKey = jdwpTag(signature); 425 jvmtiDeallocate(signature); 426 427 428 if (isReferenceTag(typeKey)) { 429 430 jobject value = JNI_FUNC_PTR(env,GetStaticObjectField)(env, clazz, field); 431 (void)outStream_writeByte(out, specificTypeKey(env, value)); 432 (void)outStream_writeObjectRef(env, out, value); 433 434 return; 435 } 436 437 /* 438 * For primitive types, the type key is bounced back as is. 439 */ 440 (void)outStream_writeByte(out, typeKey); 441 switch (typeKey) { 442 case JDWP_TAG(BYTE): 443 (void)outStream_writeByte(out, 444 JNI_FUNC_PTR(env,GetStaticByteField)(env, clazz, field)); 445 break; 446 447 case JDWP_TAG(CHAR): 448 (void)outStream_writeChar(out, 449 JNI_FUNC_PTR(env,GetStaticCharField)(env, clazz, field)); 450 break; 451 452 case JDWP_TAG(FLOAT): 453 (void)outStream_writeFloat(out, 454 JNI_FUNC_PTR(env,GetStaticFloatField)(env, clazz, field)); 455 break; 456 457 case JDWP_TAG(DOUBLE): 458 (void)outStream_writeDouble(out, 459 JNI_FUNC_PTR(env,GetStaticDoubleField)(env, clazz, field)); 460 break; 461 462 case JDWP_TAG(INT): 463 (void)outStream_writeInt(out, 464 JNI_FUNC_PTR(env,GetStaticIntField)(env, clazz, field)); 465 break; 466 467 case JDWP_TAG(LONG): 468 (void)outStream_writeLong(out, 469 JNI_FUNC_PTR(env,GetStaticLongField)(env, clazz, field)); 470 break; 471 472 case JDWP_TAG(SHORT): 473 (void)outStream_writeShort(out, 474 JNI_FUNC_PTR(env,GetStaticShortField)(env, clazz, field)); 475 break; 476 477 case JDWP_TAG(BOOLEAN): 478 (void)outStream_writeBoolean(out, 479 JNI_FUNC_PTR(env,GetStaticBooleanField)(env, clazz, field)); 480 break; 481 } 482 } 483 484 void 485 sharedGetFieldValues(PacketInputStream *in, PacketOutputStream *out, 486 jboolean isStatic) 487 { 488 JNIEnv *env = getEnv(); 489 jint length; 490 jobject object; 491 jclass clazz; 492 493 object = NULL; 494 clazz = NULL; 495 496 if (isStatic) { 497 clazz = inStream_readClassRef(env, in); 498 } else { 499 object = inStream_readObjectRef(env, in); 500 } 501 502 length = inStream_readInt(in); 503 if (inStream_error(in)) { 504 return; 505 } 506 507 WITH_LOCAL_REFS(env, length + 1) { /* +1 for class with instance fields */ 508 509 int i; 510 511 (void)outStream_writeInt(out, length); 512 for (i = 0; (i < length) && !outStream_error(out); i++) { 513 jfieldID field = inStream_readFieldID(in); 514 515 if (isStatic) { 516 writeStaticFieldValue(env, out, clazz, field); 517 } else { 518 writeFieldValue(env, out, object, field); 519 } 520 } 521 522 } END_WITH_LOCAL_REFS(env); 523 } 524 525 jboolean 526 sharedInvoke(PacketInputStream *in, PacketOutputStream *out) 527 { 528 jvalue *arguments = NULL; 529 jint options; 530 jvmtiError error; 531 jbyte invokeType; 532 jclass clazz; 533 jmethodID method; 534 jint argumentCount; 535 jobject instance; 536 jthread thread; 537 JNIEnv *env; 538 539 /* 540 * Instance methods start with the instance, thread and class, 541 * and statics and constructors start with the class and then the 542 * thread. 543 */ 544 env = getEnv(); 545 if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) { 546 instance = inStream_readObjectRef(env, in); 547 thread = inStream_readThreadRef(env, in); 548 clazz = inStream_readClassRef(env, in); 549 } else { /* static method or constructor */ 550 instance = NULL; 551 clazz = inStream_readClassRef(env, in); 552 thread = inStream_readThreadRef(env, in); 553 } 554 555 /* 556 * ... and the rest of the packet is identical for all commands 557 */ 558 method = inStream_readMethodID(in); 559 argumentCount = inStream_readInt(in); 560 if (inStream_error(in)) { 561 return JNI_TRUE; 562 } 563 564 /* If count == 0, don't try and allocate 0 bytes, you'll get NULL */ 565 if ( argumentCount > 0 ) { 566 int i; 567 /*LINTED*/ 568 arguments = jvmtiAllocate(argumentCount * (jint)sizeof(*arguments)); 569 if (arguments == NULL) { 570 outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY)); 571 return JNI_TRUE; 572 } 573 for (i = 0; (i < argumentCount) && !inStream_error(in); i++) { 574 arguments[i] = inStream_readValue(in); 575 } 576 if (inStream_error(in)) { 577 return JNI_TRUE; 578 } 579 } 580 581 options = inStream_readInt(in); 582 if (inStream_error(in)) { 583 if ( arguments != NULL ) { 584 jvmtiDeallocate(arguments); 585 } 586 return JNI_TRUE; 587 } 588 589 if (inStream_command(in) == JDWP_COMMAND(ClassType, NewInstance)) { 590 invokeType = INVOKE_CONSTRUCTOR; 591 } else if (inStream_command(in) == JDWP_COMMAND(ClassType, InvokeMethod)) { 592 invokeType = INVOKE_STATIC; 593 } else if (inStream_command(in) == JDWP_COMMAND(InterfaceType, InvokeMethod)) { 594 invokeType = INVOKE_STATIC; 595 } else if (inStream_command(in) == JDWP_COMMAND(ObjectReference, InvokeMethod)) { 596 invokeType = INVOKE_INSTANCE; 597 } else { 598 outStream_setError(out, JDWP_ERROR(INTERNAL)); 599 if ( arguments != NULL ) { 600 jvmtiDeallocate(arguments); 601 } 602 return JNI_TRUE; 603 } 604 605 /* 606 * Request the invoke. If there are no errors in the request, 607 * the interrupting thread will actually do the invoke and a 608 * reply will be generated subsequently, so we don't reply here. 609 */ 610 error = invoker_requestInvoke(invokeType, (jbyte)options, inStream_id(in), 611 thread, clazz, method, 612 instance, arguments, argumentCount); 613 if (error != JVMTI_ERROR_NONE) { 614 outStream_setError(out, map2jdwpError(error)); 615 if ( arguments != NULL ) { 616 jvmtiDeallocate(arguments); 617 } 618 return JNI_TRUE; 619 } 620 621 return JNI_FALSE; /* Don't reply */ 622 } 623 624 jint 625 uniqueID(void) 626 { 627 static jint currentID = 0; 628 return currentID++; 629 } 630 631 int 632 filterDebugThreads(jthread *threads, int count) 633 { 634 int i; 635 int current; 636 637 /* Squish out all of the debugger-spawned threads */ 638 for (i = 0, current = 0; i < count; i++) { 639 jthread thread = threads[i]; 640 if (!threadControl_isDebugThread(thread)) { 641 if (i > current) { 642 threads[current] = thread; 643 } 644 current++; 645 } 646 } 647 return current; 648 } 649 650 jbyte 651 referenceTypeTag(jclass clazz) 652 { 653 jbyte tag; 654 655 if (isInterface(clazz)) { 656 tag = JDWP_TYPE_TAG(INTERFACE); 657 } else if (isArrayClass(clazz)) { 658 tag = JDWP_TYPE_TAG(ARRAY); 659 } else { 660 tag = JDWP_TYPE_TAG(CLASS); 661 } 662 663 return tag; 664 } 665 666 /** 667 * Get field modifiers 668 */ 669 jvmtiError 670 fieldModifiers(jclass clazz, jfieldID field, jint *pmodifiers) 671 { 672 jvmtiError error; 673 674 *pmodifiers = 0; 675 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldModifiers) 676 (gdata->jvmti, clazz, field, pmodifiers); 677 return error; 678 } 679 680 /** 681 * Get method modifiers 682 */ 683 jvmtiError 684 methodModifiers(jmethodID method, jint *pmodifiers) 685 { 686 jvmtiError error; 687 688 *pmodifiers = 0; 689 error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodModifiers) 690 (gdata->jvmti, method, pmodifiers); 691 return error; 692 } 693 694 /* Returns a local ref to the declaring class for a method, or NULL. */ 695 jvmtiError 696 methodClass(jmethodID method, jclass *pclazz) 697 { 698 jvmtiError error; 699 700 *pclazz = NULL; 701 error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodDeclaringClass) 702 (gdata->jvmti, method, pclazz); 703 return error; 704 } 705 706 /* Returns the start and end locations of the specified method. */ 707 jvmtiError 708 methodLocation(jmethodID method, jlocation *ploc1, jlocation *ploc2) 709 { 710 jvmtiError error; 711 712 error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodLocation) 713 (gdata->jvmti, method, ploc1, ploc2); 714 return error; 715 } 716 717 /** 718 * Get method signature 719 */ 720 jvmtiError 721 methodSignature(jmethodID method, 722 char **pname, char **psignature, char **pgeneric_signature) 723 { 724 jvmtiError error; 725 char *name = NULL; 726 char *signature = NULL; 727 char *generic_signature = NULL; 728 729 error = JVMTI_FUNC_PTR(gdata->jvmti,GetMethodName) 730 (gdata->jvmti, method, &name, &signature, &generic_signature); 731 732 if ( pname != NULL ) { 733 *pname = name; 734 } else if ( name != NULL ) { 735 jvmtiDeallocate(name); 736 } 737 if ( psignature != NULL ) { 738 *psignature = signature; 739 } else if ( signature != NULL ) { 740 jvmtiDeallocate(signature); 741 } 742 if ( pgeneric_signature != NULL ) { 743 *pgeneric_signature = generic_signature; 744 } else if ( generic_signature != NULL ) { 745 jvmtiDeallocate(generic_signature); 746 } 747 return error; 748 } 749 750 /* 751 * Get the return type key of the method 752 * V or B C D F I J S Z L [ 753 */ 754 jvmtiError 755 methodReturnType(jmethodID method, char *typeKey) 756 { 757 char *signature; 758 jvmtiError error; 759 760 signature = NULL; 761 error = methodSignature(method, NULL, &signature, NULL); 762 if (error == JVMTI_ERROR_NONE) { 763 if (signature == NULL ) { 764 error = AGENT_ERROR_INVALID_TAG; 765 } else { 766 char * xx; 767 768 xx = strchr(signature, ')'); 769 if (xx == NULL || *(xx + 1) == 0) { 770 error = AGENT_ERROR_INVALID_TAG; 771 } else { 772 *typeKey = *(xx + 1); 773 } 774 jvmtiDeallocate(signature); 775 } 776 } 777 return error; 778 } 779 780 781 /** 782 * Return class loader for a class (must be inside a WITH_LOCAL_REFS) 783 */ 784 jvmtiError 785 classLoader(jclass clazz, jobject *pclazz) 786 { 787 jvmtiError error; 788 789 *pclazz = NULL; 790 error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoader) 791 (gdata->jvmti, clazz, pclazz); 792 return error; 793 } 794 795 /** 796 * Get field signature 797 */ 798 jvmtiError 799 fieldSignature(jclass clazz, jfieldID field, 800 char **pname, char **psignature, char **pgeneric_signature) 801 { 802 jvmtiError error; 803 char *name = NULL; 804 char *signature = NULL; 805 char *generic_signature = NULL; 806 807 error = JVMTI_FUNC_PTR(gdata->jvmti,GetFieldName) 808 (gdata->jvmti, clazz, field, &name, &signature, &generic_signature); 809 810 if ( pname != NULL ) { 811 *pname = name; 812 } else if ( name != NULL ) { 813 jvmtiDeallocate(name); 814 } 815 if ( psignature != NULL ) { 816 *psignature = signature; 817 } else if ( signature != NULL ) { 818 jvmtiDeallocate(signature); 819 } 820 if ( pgeneric_signature != NULL ) { 821 *pgeneric_signature = generic_signature; 822 } else if ( generic_signature != NULL ) { 823 jvmtiDeallocate(generic_signature); 824 } 825 return error; 826 } 827 828 JNIEnv * 829 getEnv(void) 830 { 831 JNIEnv *env = NULL; 832 jint rc; 833 834 rc = FUNC_PTR(gdata->jvm,GetEnv) 835 (gdata->jvm, (void **)&env, JNI_VERSION_1_2); 836 if (rc != JNI_OK) { 837 ERROR_MESSAGE(("JDWP Unable to get JNI 1.2 environment, jvm->GetEnv() return code = %d", 838 rc)); 839 EXIT_ERROR(AGENT_ERROR_NO_JNI_ENV,NULL); 840 } 841 return env; 842 } 843 844 jvmtiError 845 spawnNewThread(jvmtiStartFunction func, void *arg, char *name) 846 { 847 JNIEnv *env = getEnv(); 848 jvmtiError error; 849 850 LOG_MISC(("Spawning new thread: %s", name)); 851 852 WITH_LOCAL_REFS(env, 3) { 853 854 jthread thread; 855 jstring nameString; 856 857 nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, name); 858 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 859 JNI_FUNC_PTR(env,ExceptionClear)(env); 860 error = AGENT_ERROR_OUT_OF_MEMORY; 861 goto err; 862 } 863 864 thread = JNI_FUNC_PTR(env,NewObject) 865 (env, gdata->threadClass, gdata->threadConstructor, 866 gdata->systemThreadGroup, nameString); 867 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 868 JNI_FUNC_PTR(env,ExceptionClear)(env); 869 error = AGENT_ERROR_OUT_OF_MEMORY; 870 goto err; 871 } 872 873 /* 874 * Make the debugger thread a daemon 875 */ 876 JNI_FUNC_PTR(env,CallVoidMethod) 877 (env, thread, gdata->threadSetDaemon, JNI_TRUE); 878 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 879 JNI_FUNC_PTR(env,ExceptionClear)(env); 880 error = AGENT_ERROR_JNI_EXCEPTION; 881 goto err; 882 } 883 884 error = threadControl_addDebugThread(thread); 885 if (error == JVMTI_ERROR_NONE) { 886 /* 887 * Debugger threads need cycles in all sorts of strange 888 * situations (e.g. infinite cpu-bound loops), so give the 889 * thread a high priority. Note that if the VM has an application 890 * thread running at the max priority, there is still a chance 891 * that debugger threads will be starved. (There needs to be 892 * a way to give debugger threads a priority higher than any 893 * application thread). 894 */ 895 error = JVMTI_FUNC_PTR(gdata->jvmti,RunAgentThread) 896 (gdata->jvmti, thread, func, arg, 897 JVMTI_THREAD_MAX_PRIORITY); 898 } 899 900 err: ; 901 902 } END_WITH_LOCAL_REFS(env); 903 904 return error; 905 } 906 907 jvmtiError 908 jvmtiGetCapabilities(jvmtiCapabilities *caps) 909 { 910 if ( gdata->vmDead ) { 911 return AGENT_ERROR_VM_DEAD; 912 } 913 if (!gdata->haveCachedJvmtiCapabilities) { 914 jvmtiError error; 915 916 error = JVMTI_FUNC_PTR(gdata->jvmti,GetCapabilities) 917 (gdata->jvmti, &(gdata->cachedJvmtiCapabilities)); 918 if (error != JVMTI_ERROR_NONE) { 919 return error; 920 } 921 gdata->haveCachedJvmtiCapabilities = JNI_TRUE; 922 } 923 924 *caps = gdata->cachedJvmtiCapabilities; 925 926 return JVMTI_ERROR_NONE; 927 } 928 929 static jint 930 jvmtiVersion(void) 931 { 932 if (gdata->cachedJvmtiVersion == 0) { 933 jvmtiError error; 934 error = JVMTI_FUNC_PTR(gdata->jvmti,GetVersionNumber) 935 (gdata->jvmti, &(gdata->cachedJvmtiVersion)); 936 if (error != JVMTI_ERROR_NONE) { 937 EXIT_ERROR(error, "on getting the JVMTI version number"); 938 } 939 } 940 return gdata->cachedJvmtiVersion; 941 } 942 943 jint 944 jvmtiMajorVersion(void) 945 { 946 return (jvmtiVersion() & JVMTI_VERSION_MASK_MAJOR) 947 >> JVMTI_VERSION_SHIFT_MAJOR; 948 } 949 950 jint 951 jvmtiMinorVersion(void) 952 { 953 return (jvmtiVersion() & JVMTI_VERSION_MASK_MINOR) 954 >> JVMTI_VERSION_SHIFT_MINOR; 955 } 956 957 jint 958 jvmtiMicroVersion(void) 959 { 960 return (jvmtiVersion() & JVMTI_VERSION_MASK_MICRO) 961 >> JVMTI_VERSION_SHIFT_MICRO; 962 } 963 964 jvmtiError 965 getSourceDebugExtension(jclass clazz, char **extensionPtr) 966 { 967 return JVMTI_FUNC_PTR(gdata->jvmti,GetSourceDebugExtension) 968 (gdata->jvmti, clazz, extensionPtr); 969 } 970 971 972 static void 973 handleInterrupt(void) 974 { 975 /* 976 * An interrupt is handled: 977 * 978 * 1) for running application threads by deferring the interrupt 979 * until the current event handler has concluded. 980 * 981 * 2) for debugger threads by ignoring the interrupt; this is the 982 * most robust solution since debugger threads don't use interrupts 983 * to signal any condition. 984 * 985 * 3) for application threads that have not started or already 986 * ended by ignoring the interrupt. In the former case, the application 987 * is relying on timing to determine whether or not the thread sees 988 * the interrupt; in the latter case, the interrupt is meaningless. 989 */ 990 jthread thread = threadControl_currentThread(); 991 if ((thread != NULL) && (!threadControl_isDebugThread(thread))) { 992 threadControl_setPendingInterrupt(thread); 993 } 994 } 995 996 static jvmtiError 997 ignore_vm_death(jvmtiError error) 998 { 999 if (error == JVMTI_ERROR_WRONG_PHASE) { 1000 LOG_MISC(("VM_DEAD, in debugMonitor*()?")); 1001 return JVMTI_ERROR_NONE; /* JVMTI does this, not JVMDI? */ 1002 } 1003 return error; 1004 } 1005 1006 void 1007 debugMonitorEnter(jrawMonitorID monitor) 1008 { 1009 jvmtiError error; 1010 error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorEnter) 1011 (gdata->jvmti, monitor); 1012 error = ignore_vm_death(error); 1013 if (error != JVMTI_ERROR_NONE) { 1014 EXIT_ERROR(error, "on raw monitor enter"); 1015 } 1016 } 1017 1018 void 1019 debugMonitorExit(jrawMonitorID monitor) 1020 { 1021 jvmtiError error; 1022 1023 error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorExit) 1024 (gdata->jvmti, monitor); 1025 error = ignore_vm_death(error); 1026 if (error != JVMTI_ERROR_NONE) { 1027 EXIT_ERROR(error, "on raw monitor exit"); 1028 } 1029 } 1030 1031 void 1032 debugMonitorWait(jrawMonitorID monitor) 1033 { 1034 jvmtiError error; 1035 error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorWait) 1036 (gdata->jvmti, monitor, ((jlong)(-1))); 1037 1038 /* 1039 * According to the JLS (17.8), here we have 1040 * either : 1041 * a- been notified 1042 * b- gotten a spurious wakeup 1043 * c- been interrupted 1044 * If both a and c have happened, the VM must choose 1045 * which way to return - a or c. If it chooses c 1046 * then the notify is gone - either to some other 1047 * thread that is also waiting, or it is dropped 1048 * on the floor. 1049 * 1050 * a is what we expect. b won't hurt us any - 1051 * callers should be programmed to handle 1052 * spurious wakeups. In case of c, 1053 * then the interrupt has been cleared, but 1054 * we don't want to consume it. It came from 1055 * user code and is intended for user code, not us. 1056 * So, we will remember that the interrupt has 1057 * occurred and re-activate it when this thread 1058 * goes back into user code. 1059 * That being said, what do we do here? Since 1060 * we could have been notified too, here we will 1061 * just pretend that we have been. It won't hurt 1062 * anything to return in the same way as if 1063 * we were notified since callers have to be able to 1064 * handle spurious wakeups anyway. 1065 */ 1066 if (error == JVMTI_ERROR_INTERRUPT) { 1067 handleInterrupt(); 1068 error = JVMTI_ERROR_NONE; 1069 } 1070 error = ignore_vm_death(error); 1071 if (error != JVMTI_ERROR_NONE) { 1072 EXIT_ERROR(error, "on raw monitor wait"); 1073 } 1074 } 1075 1076 void 1077 debugMonitorNotify(jrawMonitorID monitor) 1078 { 1079 jvmtiError error; 1080 1081 error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorNotify) 1082 (gdata->jvmti, monitor); 1083 error = ignore_vm_death(error); 1084 if (error != JVMTI_ERROR_NONE) { 1085 EXIT_ERROR(error, "on raw monitor notify"); 1086 } 1087 } 1088 1089 void 1090 debugMonitorNotifyAll(jrawMonitorID monitor) 1091 { 1092 jvmtiError error; 1093 1094 error = JVMTI_FUNC_PTR(gdata->jvmti,RawMonitorNotifyAll) 1095 (gdata->jvmti, monitor); 1096 error = ignore_vm_death(error); 1097 if (error != JVMTI_ERROR_NONE) { 1098 EXIT_ERROR(error, "on raw monitor notify all"); 1099 } 1100 } 1101 1102 jrawMonitorID 1103 debugMonitorCreate(char *name) 1104 { 1105 jrawMonitorID monitor; 1106 jvmtiError error; 1107 1108 error = JVMTI_FUNC_PTR(gdata->jvmti,CreateRawMonitor) 1109 (gdata->jvmti, name, &monitor); 1110 if (error != JVMTI_ERROR_NONE) { 1111 EXIT_ERROR(error, "on creation of a raw monitor"); 1112 } 1113 return monitor; 1114 } 1115 1116 void 1117 debugMonitorDestroy(jrawMonitorID monitor) 1118 { 1119 jvmtiError error; 1120 1121 error = JVMTI_FUNC_PTR(gdata->jvmti,DestroyRawMonitor) 1122 (gdata->jvmti, monitor); 1123 error = ignore_vm_death(error); 1124 if (error != JVMTI_ERROR_NONE) { 1125 EXIT_ERROR(error, "on destruction of raw monitor"); 1126 } 1127 } 1128 1129 /** 1130 * Return array of all threads (must be inside a WITH_LOCAL_REFS) 1131 */ 1132 jthread * 1133 allThreads(jint *count) 1134 { 1135 jthread *threads; 1136 jvmtiError error; 1137 1138 *count = 0; 1139 threads = NULL; 1140 error = JVMTI_FUNC_PTR(gdata->jvmti,GetAllThreads) 1141 (gdata->jvmti, count, &threads); 1142 if (error == AGENT_ERROR_OUT_OF_MEMORY) { 1143 return NULL; /* Let caller deal with no memory? */ 1144 } 1145 if (error != JVMTI_ERROR_NONE) { 1146 EXIT_ERROR(error, "getting all threads"); 1147 } 1148 return threads; 1149 } 1150 1151 /** 1152 * Fill the passed in structure with thread group info. 1153 * name field is JVMTI allocated. parent is global ref. 1154 */ 1155 void 1156 threadGroupInfo(jthreadGroup group, jvmtiThreadGroupInfo *info) 1157 { 1158 jvmtiError error; 1159 1160 error = JVMTI_FUNC_PTR(gdata->jvmti,GetThreadGroupInfo) 1161 (gdata->jvmti, group, info); 1162 if (error != JVMTI_ERROR_NONE) { 1163 EXIT_ERROR(error, "on getting thread group info"); 1164 } 1165 } 1166 1167 /** 1168 * Return class signature string 1169 */ 1170 jvmtiError 1171 classSignature(jclass clazz, char **psignature, char **pgeneric_signature) 1172 { 1173 jvmtiError error; 1174 char *signature = NULL; 1175 1176 /* 1177 * pgeneric_signature can be NULL, and GetClassSignature 1178 * accepts NULL. 1179 */ 1180 error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassSignature) 1181 (gdata->jvmti, clazz, &signature, pgeneric_signature); 1182 1183 if ( psignature != NULL ) { 1184 *psignature = signature; 1185 } else if ( signature != NULL ) { 1186 jvmtiDeallocate(signature); 1187 } 1188 return error; 1189 } 1190 1191 /* Get class name (not signature) */ 1192 char * 1193 getClassname(jclass clazz) 1194 { 1195 char *classname; 1196 1197 classname = NULL; 1198 if ( clazz != NULL ) { 1199 if (classSignature(clazz, &classname, NULL) != JVMTI_ERROR_NONE) { 1200 classname = NULL; 1201 } else { 1202 /* Convert in place */ 1203 convertSignatureToClassname(classname); 1204 } 1205 } 1206 return classname; /* Caller must free this memory */ 1207 } 1208 1209 void 1210 writeGenericSignature(PacketOutputStream *out, char *genericSignature) 1211 { 1212 if (genericSignature == NULL) { 1213 (void)outStream_writeString(out, ""); 1214 } else { 1215 (void)outStream_writeString(out, genericSignature); 1216 } 1217 } 1218 1219 jint 1220 classStatus(jclass clazz) 1221 { 1222 jint status; 1223 jvmtiError error; 1224 1225 error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassStatus) 1226 (gdata->jvmti, clazz, &status); 1227 if (error != JVMTI_ERROR_NONE) { 1228 EXIT_ERROR(error, "on getting class status"); 1229 } 1230 return status; 1231 } 1232 1233 static jboolean 1234 isArrayClass(jclass clazz) 1235 { 1236 jboolean isArray = JNI_FALSE; 1237 jvmtiError error; 1238 1239 error = JVMTI_FUNC_PTR(gdata->jvmti,IsArrayClass) 1240 (gdata->jvmti, clazz, &isArray); 1241 if (error != JVMTI_ERROR_NONE) { 1242 EXIT_ERROR(error, "on checking for an array class"); 1243 } 1244 return isArray; 1245 } 1246 1247 static jboolean 1248 isInterface(jclass clazz) 1249 { 1250 jboolean isInterface = JNI_FALSE; 1251 jvmtiError error; 1252 1253 error = JVMTI_FUNC_PTR(gdata->jvmti,IsInterface) 1254 (gdata->jvmti, clazz, &isInterface); 1255 if (error != JVMTI_ERROR_NONE) { 1256 EXIT_ERROR(error, "on checking for an interface"); 1257 } 1258 return isInterface; 1259 } 1260 1261 jvmtiError 1262 isFieldSynthetic(jclass clazz, jfieldID field, jboolean *psynthetic) 1263 { 1264 jvmtiError error; 1265 1266 error = JVMTI_FUNC_PTR(gdata->jvmti,IsFieldSynthetic) 1267 (gdata->jvmti, clazz, field, psynthetic); 1268 if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) { 1269 /* If the query is not supported, we assume it is not synthetic. */ 1270 *psynthetic = JNI_FALSE; 1271 return JVMTI_ERROR_NONE; 1272 } 1273 return error; 1274 } 1275 1276 jvmtiError 1277 isMethodSynthetic(jmethodID method, jboolean *psynthetic) 1278 { 1279 jvmtiError error; 1280 1281 error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodSynthetic) 1282 (gdata->jvmti, method, psynthetic); 1283 if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY ) { 1284 /* If the query is not supported, we assume it is not synthetic. */ 1285 *psynthetic = JNI_FALSE; 1286 return JVMTI_ERROR_NONE; 1287 } 1288 return error; 1289 } 1290 1291 jboolean 1292 isMethodNative(jmethodID method) 1293 { 1294 jboolean isNative = JNI_FALSE; 1295 jvmtiError error; 1296 1297 error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodNative) 1298 (gdata->jvmti, method, &isNative); 1299 if (error != JVMTI_ERROR_NONE) { 1300 EXIT_ERROR(error, "on checking for a native interface"); 1301 } 1302 return isNative; 1303 } 1304 1305 jboolean 1306 isSameObject(JNIEnv *env, jobject o1, jobject o2) 1307 { 1308 if ( o1==o2 ) { 1309 return JNI_TRUE; 1310 } 1311 return FUNC_PTR(env,IsSameObject)(env, o1, o2); 1312 } 1313 1314 jint 1315 objectHashCode(jobject object) 1316 { 1317 jint hashCode = 0; 1318 jvmtiError error; 1319 1320 if ( object!=NULL ) { 1321 error = JVMTI_FUNC_PTR(gdata->jvmti,GetObjectHashCode) 1322 (gdata->jvmti, object, &hashCode); 1323 if (error != JVMTI_ERROR_NONE) { 1324 EXIT_ERROR(error, "on getting an object hash code"); 1325 } 1326 } 1327 return hashCode; 1328 } 1329 1330 /* Get all implemented interfaces (must be inside a WITH_LOCAL_REFS) */ 1331 jvmtiError 1332 allInterfaces(jclass clazz, jclass **ppinterfaces, jint *pcount) 1333 { 1334 jvmtiError error; 1335 1336 *pcount = 0; 1337 *ppinterfaces = NULL; 1338 error = JVMTI_FUNC_PTR(gdata->jvmti,GetImplementedInterfaces) 1339 (gdata->jvmti, clazz, pcount, ppinterfaces); 1340 return error; 1341 } 1342 1343 /* Get all loaded classes (must be inside a WITH_LOCAL_REFS) */ 1344 jvmtiError 1345 allLoadedClasses(jclass **ppclasses, jint *pcount) 1346 { 1347 jvmtiError error; 1348 1349 *pcount = 0; 1350 *ppclasses = NULL; 1351 error = JVMTI_FUNC_PTR(gdata->jvmti,GetLoadedClasses) 1352 (gdata->jvmti, pcount, ppclasses); 1353 return error; 1354 } 1355 1356 /* Get all loaded classes for a loader (must be inside a WITH_LOCAL_REFS) */ 1357 jvmtiError 1358 allClassLoaderClasses(jobject loader, jclass **ppclasses, jint *pcount) 1359 { 1360 jvmtiError error; 1361 1362 *pcount = 0; 1363 *ppclasses = NULL; 1364 error = JVMTI_FUNC_PTR(gdata->jvmti,GetClassLoaderClasses) 1365 (gdata->jvmti, loader, pcount, ppclasses); 1366 return error; 1367 } 1368 1369 static jboolean 1370 is_a_nested_class(char *outer_sig, int outer_sig_len, char *sig, int sep) 1371 { 1372 char *inner; 1373 1374 /* Assumed outer class signature is "LOUTERCLASSNAME;" 1375 * inner class signature is "LOUTERCLASSNAME$INNERNAME;" 1376 * 1377 * INNERNAME can take the form: 1378 * [0-9][1-9]* anonymous class somewhere in the file 1379 * [0-9][1-9]*NAME local class somewhere in the OUTER class 1380 * NAME nested class in OUTER 1381 * 1382 * If NAME itself contains a $ (sep) then classname is further nested 1383 * inside another class. 1384 * 1385 */ 1386 1387 /* Check prefix first */ 1388 if ( strncmp(sig, outer_sig, outer_sig_len-1) != 0 ) { 1389 return JNI_FALSE; 1390 } 1391 1392 /* Prefix must be followed by a $ (sep) */ 1393 if ( sig[outer_sig_len-1] != sep ) { 1394 return JNI_FALSE; /* No sep follows the match, must not be nested. */ 1395 } 1396 1397 /* Walk past any digits, if we reach the end, must be pure anonymous */ 1398 inner = sig + outer_sig_len; 1399 #if 1 /* We want to return local classes */ 1400 while ( *inner && isdigit(*inner) ) { 1401 inner++; 1402 } 1403 /* But anonymous class names can't be trusted. */ 1404 if ( *inner == ';' ) { 1405 return JNI_FALSE; /* A pure anonymous class */ 1406 } 1407 #else 1408 if ( *inner && isdigit(*inner) ) { 1409 return JNI_FALSE; /* A pure anonymous or local class */ 1410 } 1411 #endif 1412 1413 /* Nested deeper? */ 1414 if ( strchr(inner, sep) != NULL ) { 1415 return JNI_FALSE; /* Nested deeper than we want? */ 1416 } 1417 return JNI_TRUE; 1418 } 1419 1420 /* Get all nested classes for a class (must be inside a WITH_LOCAL_REFS) */ 1421 jvmtiError 1422 allNestedClasses(jclass parent_clazz, jclass **ppnested, jint *pcount) 1423 { 1424 jvmtiError error; 1425 jobject parent_loader; 1426 jclass *classes; 1427 char *signature; 1428 size_t len; 1429 jint count; 1430 jint ncount; 1431 int i; 1432 1433 *ppnested = NULL; 1434 *pcount = 0; 1435 1436 parent_loader = NULL; 1437 classes = NULL; 1438 signature = NULL; 1439 count = 0; 1440 ncount = 0; 1441 1442 error = classLoader(parent_clazz, &parent_loader); 1443 if (error != JVMTI_ERROR_NONE) { 1444 return error; 1445 } 1446 error = classSignature(parent_clazz, &signature, NULL); 1447 if (error != JVMTI_ERROR_NONE) { 1448 return error; 1449 } 1450 len = strlen(signature); 1451 1452 error = allClassLoaderClasses(parent_loader, &classes, &count); 1453 if ( error != JVMTI_ERROR_NONE ) { 1454 jvmtiDeallocate(signature); 1455 return error; 1456 } 1457 1458 for (i=0; i<count; i++) { 1459 jclass clazz; 1460 char *candidate_signature; 1461 1462 clazz = classes[i]; 1463 candidate_signature = NULL; 1464 error = classSignature(clazz, &candidate_signature, NULL); 1465 if (error != JVMTI_ERROR_NONE) { 1466 break; 1467 } 1468 1469 if ( is_a_nested_class(signature, (int)len, candidate_signature, '$') || 1470 is_a_nested_class(signature, (int)len, candidate_signature, '#') ) { 1471 /* Float nested classes to top */ 1472 classes[i] = classes[ncount]; 1473 classes[ncount++] = clazz; 1474 } 1475 jvmtiDeallocate(candidate_signature); 1476 } 1477 1478 jvmtiDeallocate(signature); 1479 1480 if ( count != 0 && ncount == 0 ) { 1481 jvmtiDeallocate(classes); 1482 classes = NULL; 1483 } 1484 1485 *ppnested = classes; 1486 *pcount = ncount; 1487 return error; 1488 } 1489 1490 void 1491 createLocalRefSpace(JNIEnv *env, jint capacity) 1492 { 1493 /* 1494 * Save current exception since it might get overwritten by 1495 * the calls below. Note we must depend on space in the existing 1496 * frame because asking for a new frame may generate an exception. 1497 */ 1498 jobject throwable = JNI_FUNC_PTR(env,ExceptionOccurred)(env); 1499 1500 /* 1501 * Use the current frame if necessary; otherwise create a new one 1502 */ 1503 if (JNI_FUNC_PTR(env,PushLocalFrame)(env, capacity) < 0) { 1504 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"PushLocalFrame: Unable to push JNI frame"); 1505 } 1506 1507 /* 1508 * TO DO: This could be more efficient if it used EnsureLocalCapacity, 1509 * but that would not work if two functions on the call stack 1510 * use this function. We would need to either track reserved 1511 * references on a per-thread basis or come up with a convention 1512 * that would prevent two functions from depending on this function 1513 * at the same time. 1514 */ 1515 1516 /* 1517 * Restore exception state from before call 1518 */ 1519 if (throwable != NULL) { 1520 JNI_FUNC_PTR(env,Throw)(env, throwable); 1521 } else { 1522 JNI_FUNC_PTR(env,ExceptionClear)(env); 1523 } 1524 } 1525 1526 jboolean 1527 isClass(jobject object) 1528 { 1529 JNIEnv *env = getEnv(); 1530 return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classClass); 1531 } 1532 1533 jboolean 1534 isVThread(jobject object) 1535 { 1536 JNIEnv *env = getEnv(); 1537 return JNI_FUNC_PTR(env,IsVirtualThread)(env, object); 1538 } 1539 1540 jboolean 1541 isThread(jobject object) 1542 { 1543 JNIEnv *env = getEnv(); 1544 return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadClass); 1545 } 1546 1547 jboolean 1548 isThreadGroup(jobject object) 1549 { 1550 JNIEnv *env = getEnv(); 1551 return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->threadGroupClass); 1552 } 1553 1554 jboolean 1555 isString(jobject object) 1556 { 1557 JNIEnv *env = getEnv(); 1558 return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->stringClass); 1559 } 1560 1561 jboolean 1562 isClassLoader(jobject object) 1563 { 1564 JNIEnv *env = getEnv(); 1565 return JNI_FUNC_PTR(env,IsInstanceOf)(env, object, gdata->classLoaderClass); 1566 } 1567 1568 jboolean 1569 isArray(jobject object) 1570 { 1571 JNIEnv *env = getEnv(); 1572 jboolean is; 1573 1574 WITH_LOCAL_REFS(env, 1) { 1575 jclass clazz; 1576 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, object); 1577 is = isArrayClass(clazz); 1578 } END_WITH_LOCAL_REFS(env); 1579 1580 return is; 1581 } 1582 1583 /** 1584 * Return property value as jstring 1585 */ 1586 static jstring 1587 getPropertyValue(JNIEnv *env, char *propertyName) 1588 { 1589 jstring valueString; 1590 jstring nameString; 1591 1592 valueString = NULL; 1593 1594 /* Create new String object to hold the property name */ 1595 nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName); 1596 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 1597 JNI_FUNC_PTR(env,ExceptionClear)(env); 1598 /* NULL will be returned below */ 1599 } else { 1600 /* Call valueString = System.getProperty(nameString) */ 1601 valueString = JNI_FUNC_PTR(env,CallStaticObjectMethod) 1602 (env, gdata->systemClass, gdata->systemGetProperty, nameString); 1603 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 1604 JNI_FUNC_PTR(env,ExceptionClear)(env); 1605 valueString = NULL; 1606 } 1607 } 1608 return valueString; 1609 } 1610 1611 /** 1612 * Set an agent property 1613 */ 1614 void 1615 setAgentPropertyValue(JNIEnv *env, char *propertyName, char* propertyValue) 1616 { 1617 jstring nameString; 1618 jstring valueString; 1619 1620 if (gdata->agent_properties == NULL) { 1621 /* VMSupport doesn't exist; so ignore */ 1622 return; 1623 } 1624 1625 /* Create jstrings for property name and value */ 1626 nameString = JNI_FUNC_PTR(env,NewStringUTF)(env, propertyName); 1627 if (nameString != NULL) { 1628 /* convert the value to UTF8 */ 1629 int len; 1630 char *utf8value; 1631 int utf8maxSize; 1632 1633 len = (int)strlen(propertyValue); 1634 utf8maxSize = len * 4 + 1; 1635 utf8value = (char *)jvmtiAllocate(utf8maxSize); 1636 if (utf8value != NULL) { 1637 utf8FromPlatform(propertyValue, len, (jbyte *)utf8value, utf8maxSize); 1638 valueString = JNI_FUNC_PTR(env, NewStringUTF)(env, utf8value); 1639 jvmtiDeallocate(utf8value); 1640 1641 if (valueString != NULL) { 1642 /* invoke Properties.setProperty */ 1643 JNI_FUNC_PTR(env,CallObjectMethod) 1644 (env, gdata->agent_properties, 1645 gdata->setProperty, 1646 nameString, valueString); 1647 } 1648 } 1649 } 1650 if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) { 1651 JNI_FUNC_PTR(env,ExceptionClear)(env); 1652 } 1653 } 1654 1655 /** 1656 * Return property value as JDWP allocated string in UTF8 encoding 1657 */ 1658 static char * 1659 getPropertyUTF8(JNIEnv *env, char *propertyName) 1660 { 1661 jvmtiError error; 1662 char *value; 1663 1664 value = NULL; 1665 error = JVMTI_FUNC_PTR(gdata->jvmti,GetSystemProperty) 1666 (gdata->jvmti, (const char *)propertyName, &value); 1667 if (error != JVMTI_ERROR_NONE) { 1668 jstring valueString; 1669 1670 value = NULL; 1671 valueString = getPropertyValue(env, propertyName); 1672 1673 if (valueString != NULL) { 1674 const char *utf; 1675 1676 /* Get the UTF8 encoding for this property value string */ 1677 utf = JNI_FUNC_PTR(env,GetStringUTFChars)(env, valueString, NULL); 1678 /* Make a copy for returning, release the JNI copy */ 1679 value = jvmtiAllocate((int)strlen(utf) + 1); 1680 if (value != NULL) { 1681 (void)strcpy(value, utf); 1682 } 1683 JNI_FUNC_PTR(env,ReleaseStringUTFChars)(env, valueString, utf); 1684 } 1685 } 1686 if ( value == NULL ) { 1687 ERROR_MESSAGE(("JDWP Can't get property value for %s", propertyName)); 1688 EXIT_ERROR(AGENT_ERROR_NULL_POINTER,NULL); 1689 } 1690 return value; 1691 } 1692 1693 jboolean 1694 isMethodObsolete(jmethodID method) 1695 { 1696 jvmtiError error; 1697 jboolean obsolete = JNI_TRUE; 1698 1699 if ( method != NULL ) { 1700 error = JVMTI_FUNC_PTR(gdata->jvmti,IsMethodObsolete) 1701 (gdata->jvmti, method, &obsolete); 1702 if (error != JVMTI_ERROR_NONE) { 1703 obsolete = JNI_TRUE; 1704 } 1705 } 1706 return obsolete; 1707 } 1708 1709 /* Get the jvmti environment to be used with tags */ 1710 jvmtiEnv * 1711 getSpecialJvmti(void) 1712 { 1713 jvmtiEnv *jvmti; 1714 jvmtiError error; 1715 int rc; 1716 1717 /* Get one time use JVMTI Env */ 1718 jvmtiCapabilities caps; 1719 1720 rc = JVM_FUNC_PTR(gdata->jvm,GetEnv) 1721 (gdata->jvm, (void **)&jvmti, JVMTI_VERSION); 1722 if (rc != JNI_OK) { 1723 return NULL; 1724 } 1725 (void)memset(&caps, 0, (int)sizeof(caps)); 1726 caps.can_tag_objects = 1; 1727 error = JVMTI_FUNC_PTR(jvmti,AddCapabilities)(jvmti, &caps); 1728 if ( error != JVMTI_ERROR_NONE ) { 1729 return NULL; 1730 } 1731 return jvmti; 1732 } 1733 1734 void 1735 writeCodeLocation(PacketOutputStream *out, jclass clazz, 1736 jmethodID method, jlocation location) 1737 { 1738 jbyte tag; 1739 1740 if (clazz != NULL) { 1741 tag = referenceTypeTag(clazz); 1742 } else { 1743 tag = JDWP_TYPE_TAG(CLASS); 1744 } 1745 (void)outStream_writeByte(out, tag); 1746 (void)outStream_writeObjectRef(getEnv(), out, clazz); 1747 (void)outStream_writeMethodID(out, isMethodObsolete(method)?NULL:method); 1748 (void)outStream_writeLocation(out, location); 1749 } 1750 1751 void * 1752 jvmtiAllocate(jint numBytes) 1753 { 1754 void *ptr; 1755 jvmtiError error; 1756 if ( numBytes == 0 ) { 1757 return NULL; 1758 } 1759 error = JVMTI_FUNC_PTR(gdata->jvmti,Allocate) 1760 (gdata->jvmti, numBytes, (unsigned char**)&ptr); 1761 if (error != JVMTI_ERROR_NONE ) { 1762 EXIT_ERROR(error, "Can't allocate jvmti memory"); 1763 } 1764 return ptr; 1765 } 1766 1767 void 1768 jvmtiDeallocate(void *ptr) 1769 { 1770 jvmtiError error; 1771 if ( ptr == NULL ) { 1772 return; 1773 } 1774 error = JVMTI_FUNC_PTR(gdata->jvmti,Deallocate) 1775 (gdata->jvmti, ptr); 1776 if (error != JVMTI_ERROR_NONE ) { 1777 EXIT_ERROR(error, "Can't deallocate jvmti memory"); 1778 } 1779 } 1780 1781 /* Rarely needed, transport library uses JDWP errors, only use? */ 1782 jvmtiError 1783 map2jvmtiError(jdwpError error) 1784 { 1785 switch ( error ) { 1786 case JDWP_ERROR(NONE): 1787 return JVMTI_ERROR_NONE; 1788 case JDWP_ERROR(INVALID_THREAD): 1789 return JVMTI_ERROR_INVALID_THREAD; 1790 case JDWP_ERROR(INVALID_THREAD_GROUP): 1791 return JVMTI_ERROR_INVALID_THREAD_GROUP; 1792 case JDWP_ERROR(INVALID_PRIORITY): 1793 return JVMTI_ERROR_INVALID_PRIORITY; 1794 case JDWP_ERROR(THREAD_NOT_SUSPENDED): 1795 return JVMTI_ERROR_THREAD_NOT_SUSPENDED; 1796 case JDWP_ERROR(THREAD_SUSPENDED): 1797 return JVMTI_ERROR_THREAD_SUSPENDED; 1798 case JDWP_ERROR(INVALID_OBJECT): 1799 return JVMTI_ERROR_INVALID_OBJECT; 1800 case JDWP_ERROR(INVALID_CLASS): 1801 return JVMTI_ERROR_INVALID_CLASS; 1802 case JDWP_ERROR(CLASS_NOT_PREPARED): 1803 return JVMTI_ERROR_CLASS_NOT_PREPARED; 1804 case JDWP_ERROR(INVALID_METHODID): 1805 return JVMTI_ERROR_INVALID_METHODID; 1806 case JDWP_ERROR(INVALID_LOCATION): 1807 return JVMTI_ERROR_INVALID_LOCATION; 1808 case JDWP_ERROR(INVALID_FIELDID): 1809 return JVMTI_ERROR_INVALID_FIELDID; 1810 case JDWP_ERROR(INVALID_FRAMEID): 1811 return AGENT_ERROR_INVALID_FRAMEID; 1812 case JDWP_ERROR(NO_MORE_FRAMES): 1813 return JVMTI_ERROR_NO_MORE_FRAMES; 1814 case JDWP_ERROR(OPAQUE_FRAME): 1815 return JVMTI_ERROR_OPAQUE_FRAME; 1816 case JDWP_ERROR(NOT_CURRENT_FRAME): 1817 return AGENT_ERROR_NOT_CURRENT_FRAME; 1818 case JDWP_ERROR(TYPE_MISMATCH): 1819 return JVMTI_ERROR_TYPE_MISMATCH; 1820 case JDWP_ERROR(INVALID_SLOT): 1821 return JVMTI_ERROR_INVALID_SLOT; 1822 case JDWP_ERROR(DUPLICATE): 1823 return JVMTI_ERROR_DUPLICATE; 1824 case JDWP_ERROR(NOT_FOUND): 1825 return JVMTI_ERROR_NOT_FOUND; 1826 case JDWP_ERROR(INVALID_MONITOR): 1827 return JVMTI_ERROR_INVALID_MONITOR; 1828 case JDWP_ERROR(NOT_MONITOR_OWNER): 1829 return JVMTI_ERROR_NOT_MONITOR_OWNER; 1830 case JDWP_ERROR(INTERRUPT): 1831 return JVMTI_ERROR_INTERRUPT; 1832 case JDWP_ERROR(INVALID_CLASS_FORMAT): 1833 return JVMTI_ERROR_INVALID_CLASS_FORMAT; 1834 case JDWP_ERROR(CIRCULAR_CLASS_DEFINITION): 1835 return JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION; 1836 case JDWP_ERROR(FAILS_VERIFICATION): 1837 return JVMTI_ERROR_FAILS_VERIFICATION; 1838 case JDWP_ERROR(ADD_METHOD_NOT_IMPLEMENTED): 1839 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED; 1840 case JDWP_ERROR(SCHEMA_CHANGE_NOT_IMPLEMENTED): 1841 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED; 1842 case JDWP_ERROR(INVALID_TYPESTATE): 1843 return JVMTI_ERROR_INVALID_TYPESTATE; 1844 case JDWP_ERROR(HIERARCHY_CHANGE_NOT_IMPLEMENTED): 1845 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED; 1846 case JDWP_ERROR(DELETE_METHOD_NOT_IMPLEMENTED): 1847 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED; 1848 case JDWP_ERROR(UNSUPPORTED_VERSION): 1849 return JVMTI_ERROR_UNSUPPORTED_VERSION; 1850 case JDWP_ERROR(NAMES_DONT_MATCH): 1851 return JVMTI_ERROR_NAMES_DONT_MATCH; 1852 case JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED): 1853 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED; 1854 case JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED): 1855 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED; 1856 case JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED): 1857 return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED; 1858 case JDWP_ERROR(NOT_IMPLEMENTED): 1859 return JVMTI_ERROR_NOT_AVAILABLE; 1860 case JDWP_ERROR(NULL_POINTER): 1861 return JVMTI_ERROR_NULL_POINTER; 1862 case JDWP_ERROR(ABSENT_INFORMATION): 1863 return JVMTI_ERROR_ABSENT_INFORMATION; 1864 case JDWP_ERROR(INVALID_EVENT_TYPE): 1865 return JVMTI_ERROR_INVALID_EVENT_TYPE; 1866 case JDWP_ERROR(ILLEGAL_ARGUMENT): 1867 return JVMTI_ERROR_ILLEGAL_ARGUMENT; 1868 case JDWP_ERROR(OUT_OF_MEMORY): 1869 return JVMTI_ERROR_OUT_OF_MEMORY; 1870 case JDWP_ERROR(ACCESS_DENIED): 1871 return JVMTI_ERROR_ACCESS_DENIED; 1872 case JDWP_ERROR(VM_DEAD): 1873 return JVMTI_ERROR_WRONG_PHASE; 1874 case JDWP_ERROR(UNATTACHED_THREAD): 1875 return JVMTI_ERROR_UNATTACHED_THREAD; 1876 case JDWP_ERROR(INVALID_TAG): 1877 return AGENT_ERROR_INVALID_TAG; 1878 case JDWP_ERROR(ALREADY_INVOKING): 1879 return AGENT_ERROR_ALREADY_INVOKING; 1880 case JDWP_ERROR(INVALID_INDEX): 1881 return AGENT_ERROR_INVALID_INDEX; 1882 case JDWP_ERROR(INVALID_LENGTH): 1883 return AGENT_ERROR_INVALID_LENGTH; 1884 case JDWP_ERROR(INVALID_STRING): 1885 return AGENT_ERROR_INVALID_STRING; 1886 case JDWP_ERROR(INVALID_CLASS_LOADER): 1887 return AGENT_ERROR_INVALID_CLASS_LOADER; 1888 case JDWP_ERROR(INVALID_ARRAY): 1889 return AGENT_ERROR_INVALID_ARRAY; 1890 case JDWP_ERROR(TRANSPORT_LOAD): 1891 return AGENT_ERROR_TRANSPORT_LOAD; 1892 case JDWP_ERROR(TRANSPORT_INIT): 1893 return AGENT_ERROR_TRANSPORT_INIT; 1894 case JDWP_ERROR(NATIVE_METHOD): 1895 return AGENT_ERROR_NATIVE_METHOD; 1896 case JDWP_ERROR(INVALID_COUNT): 1897 return AGENT_ERROR_INVALID_COUNT; 1898 case JDWP_ERROR(INTERNAL): 1899 return AGENT_ERROR_JDWP_INTERNAL; 1900 } 1901 return AGENT_ERROR_INTERNAL; 1902 } 1903 1904 static jvmtiEvent index2jvmti[EI_max-EI_min+1]; 1905 static jdwpEvent index2jdwp [EI_max-EI_min+1]; 1906 1907 void 1908 eventIndexInit(void) 1909 { 1910 (void)memset(index2jvmti, 0, (int)sizeof(index2jvmti)); 1911 (void)memset(index2jdwp, 0, (int)sizeof(index2jdwp)); 1912 1913 index2jvmti[EI_SINGLE_STEP -EI_min] = JVMTI_EVENT_SINGLE_STEP; 1914 index2jvmti[EI_BREAKPOINT -EI_min] = JVMTI_EVENT_BREAKPOINT; 1915 index2jvmti[EI_FRAME_POP -EI_min] = JVMTI_EVENT_FRAME_POP; 1916 index2jvmti[EI_EXCEPTION -EI_min] = JVMTI_EVENT_EXCEPTION; 1917 index2jvmti[EI_THREAD_START -EI_min] = JVMTI_EVENT_THREAD_START; 1918 index2jvmti[EI_THREAD_END -EI_min] = JVMTI_EVENT_THREAD_END; 1919 index2jvmti[EI_CLASS_PREPARE -EI_min] = JVMTI_EVENT_CLASS_PREPARE; 1920 index2jvmti[EI_CLASS_UNLOAD -EI_min] = 0; // No mapping to JVMTI event 1921 index2jvmti[EI_CLASS_LOAD -EI_min] = JVMTI_EVENT_CLASS_LOAD; 1922 index2jvmti[EI_FIELD_ACCESS -EI_min] = JVMTI_EVENT_FIELD_ACCESS; 1923 index2jvmti[EI_FIELD_MODIFICATION -EI_min] = JVMTI_EVENT_FIELD_MODIFICATION; 1924 index2jvmti[EI_EXCEPTION_CATCH -EI_min] = JVMTI_EVENT_EXCEPTION_CATCH; 1925 index2jvmti[EI_METHOD_ENTRY -EI_min] = JVMTI_EVENT_METHOD_ENTRY; 1926 index2jvmti[EI_METHOD_EXIT -EI_min] = JVMTI_EVENT_METHOD_EXIT; 1927 index2jvmti[EI_MONITOR_CONTENDED_ENTER -EI_min] = JVMTI_EVENT_MONITOR_CONTENDED_ENTER; 1928 index2jvmti[EI_MONITOR_CONTENDED_ENTERED -EI_min] = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED; 1929 index2jvmti[EI_MONITOR_WAIT -EI_min] = JVMTI_EVENT_MONITOR_WAIT; 1930 index2jvmti[EI_MONITOR_WAITED -EI_min] = JVMTI_EVENT_MONITOR_WAITED; 1931 index2jvmti[EI_VM_INIT -EI_min] = JVMTI_EVENT_VM_INIT; 1932 index2jvmti[EI_VM_DEATH -EI_min] = JVMTI_EVENT_VM_DEATH; 1933 index2jvmti[EI_VIRTUAL_THREAD_START -EI_min] = JVMTI_EVENT_VIRTUAL_THREAD_START; 1934 index2jvmti[EI_VIRTUAL_THREAD_END -EI_min] = JVMTI_EVENT_VIRTUAL_THREAD_END; 1935 1936 index2jdwp[EI_SINGLE_STEP -EI_min] = JDWP_EVENT(SINGLE_STEP); 1937 index2jdwp[EI_BREAKPOINT -EI_min] = JDWP_EVENT(BREAKPOINT); 1938 index2jdwp[EI_FRAME_POP -EI_min] = JDWP_EVENT(FRAME_POP); 1939 index2jdwp[EI_EXCEPTION -EI_min] = JDWP_EVENT(EXCEPTION); 1940 index2jdwp[EI_THREAD_START -EI_min] = JDWP_EVENT(THREAD_START); 1941 index2jdwp[EI_THREAD_END -EI_min] = JDWP_EVENT(THREAD_END); 1942 index2jdwp[EI_CLASS_PREPARE -EI_min] = JDWP_EVENT(CLASS_PREPARE); 1943 index2jdwp[EI_CLASS_UNLOAD -EI_min] = JDWP_EVENT(CLASS_UNLOAD); 1944 index2jdwp[EI_CLASS_LOAD -EI_min] = JDWP_EVENT(CLASS_LOAD); 1945 index2jdwp[EI_FIELD_ACCESS -EI_min] = JDWP_EVENT(FIELD_ACCESS); 1946 index2jdwp[EI_FIELD_MODIFICATION -EI_min] = JDWP_EVENT(FIELD_MODIFICATION); 1947 index2jdwp[EI_EXCEPTION_CATCH -EI_min] = JDWP_EVENT(EXCEPTION_CATCH); 1948 index2jdwp[EI_METHOD_ENTRY -EI_min] = JDWP_EVENT(METHOD_ENTRY); 1949 index2jdwp[EI_METHOD_EXIT -EI_min] = JDWP_EVENT(METHOD_EXIT); 1950 index2jdwp[EI_MONITOR_CONTENDED_ENTER -EI_min] = JDWP_EVENT(MONITOR_CONTENDED_ENTER); 1951 index2jdwp[EI_MONITOR_CONTENDED_ENTERED -EI_min] = JDWP_EVENT(MONITOR_CONTENDED_ENTERED); 1952 index2jdwp[EI_MONITOR_WAIT -EI_min] = JDWP_EVENT(MONITOR_WAIT); 1953 index2jdwp[EI_MONITOR_WAITED -EI_min] = JDWP_EVENT(MONITOR_WAITED); 1954 index2jdwp[EI_VM_INIT -EI_min] = JDWP_EVENT(VM_INIT); 1955 index2jdwp[EI_VM_DEATH -EI_min] = JDWP_EVENT(VM_DEATH); 1956 /* Just map VIRTUAL_THREAD_START/END to THREAD_START/END. */ 1957 index2jdwp[EI_VIRTUAL_THREAD_START -EI_min] = JDWP_EVENT(THREAD_START); 1958 index2jdwp[EI_VIRTUAL_THREAD_END -EI_min] = JDWP_EVENT(THREAD_END); 1959 } 1960 1961 jdwpEvent 1962 eventIndex2jdwp(EventIndex ei) 1963 { 1964 jdwpEvent event = 0; 1965 if (ei >= EI_min && ei <= EI_max) { 1966 event = index2jdwp[ei - EI_min]; 1967 } 1968 if (event == 0) { 1969 EXIT_ERROR(AGENT_ERROR_INVALID_INDEX, "bad EventIndex"); 1970 } 1971 return event; 1972 } 1973 1974 jvmtiEvent 1975 eventIndex2jvmti(EventIndex ei) 1976 { 1977 jvmtiEvent event = 0; 1978 if (ei >= EI_min && ei <= EI_max) { 1979 event = index2jvmti[ei - EI_min]; 1980 } 1981 if (event == 0) { 1982 EXIT_ERROR(AGENT_ERROR_INVALID_INDEX, "bad EventIndex"); 1983 } 1984 return event; 1985 } 1986 1987 #ifdef DEBUG 1988 1989 char* 1990 eventIndex2EventName(EventIndex ei) 1991 { 1992 switch ( ei ) { 1993 case EI_SINGLE_STEP: 1994 return "EI_SINGLE_STEP"; 1995 case EI_BREAKPOINT: 1996 return "EI_BREAKPOINT"; 1997 case EI_FRAME_POP: 1998 return "EI_FRAME_POP"; 1999 case EI_EXCEPTION: 2000 return "EI_EXCEPTION"; 2001 case EI_THREAD_START: 2002 return "EI_THREAD_START"; 2003 case EI_THREAD_END: 2004 return "EI_THREAD_END"; 2005 case EI_CLASS_PREPARE: 2006 return "EI_CLASS_PREPARE"; 2007 case EI_CLASS_UNLOAD: 2008 return "EI_CLASS_UNLOAD"; 2009 case EI_CLASS_LOAD: 2010 return "EI_CLASS_LOAD"; 2011 case EI_FIELD_ACCESS: 2012 return "EI_FIELD_ACCESS"; 2013 case EI_FIELD_MODIFICATION: 2014 return "EI_FIELD_MODIFICATION"; 2015 case EI_EXCEPTION_CATCH: 2016 return "EI_EXCEPTION_CATCH"; 2017 case EI_METHOD_ENTRY: 2018 return "EI_METHOD_ENTRY"; 2019 case EI_METHOD_EXIT: 2020 return "EI_METHOD_EXIT"; 2021 case EI_MONITOR_CONTENDED_ENTER: 2022 return "EI_MONITOR_CONTENDED_ENTER"; 2023 case EI_MONITOR_CONTENDED_ENTERED: 2024 return "EI_MONITOR_CONTENDED_ENTERED"; 2025 case EI_MONITOR_WAIT: 2026 return "EI_MONITOR_WAIT"; 2027 case EI_MONITOR_WAITED: 2028 return "EI_MONITOR_WAITED"; 2029 case EI_VM_INIT: 2030 return "EI_VM_INIT"; 2031 case EI_VM_DEATH: 2032 return "EI_VM_DEATH"; 2033 case EI_VIRTUAL_THREAD_START: 2034 return "EI_VIRTUAL_THREAD_START"; 2035 case EI_VIRTUAL_THREAD_END: 2036 return "EI_VIRTUAL_THREAD_END"; 2037 default: 2038 JDI_ASSERT(JNI_FALSE); 2039 return "Bad EI"; 2040 } 2041 } 2042 2043 #endif 2044 2045 EventIndex 2046 jdwp2EventIndex(jdwpEvent eventType) 2047 { 2048 switch ( eventType ) { 2049 case JDWP_EVENT(SINGLE_STEP): 2050 return EI_SINGLE_STEP; 2051 case JDWP_EVENT(BREAKPOINT): 2052 return EI_BREAKPOINT; 2053 case JDWP_EVENT(FRAME_POP): 2054 return EI_FRAME_POP; 2055 case JDWP_EVENT(EXCEPTION): 2056 return EI_EXCEPTION; 2057 case JDWP_EVENT(THREAD_START): 2058 return EI_THREAD_START; 2059 case JDWP_EVENT(THREAD_END): 2060 return EI_THREAD_END; 2061 case JDWP_EVENT(CLASS_PREPARE): 2062 return EI_CLASS_PREPARE; 2063 case JDWP_EVENT(CLASS_UNLOAD): 2064 return EI_CLASS_UNLOAD; 2065 case JDWP_EVENT(CLASS_LOAD): 2066 return EI_CLASS_LOAD; 2067 case JDWP_EVENT(FIELD_ACCESS): 2068 return EI_FIELD_ACCESS; 2069 case JDWP_EVENT(FIELD_MODIFICATION): 2070 return EI_FIELD_MODIFICATION; 2071 case JDWP_EVENT(EXCEPTION_CATCH): 2072 return EI_EXCEPTION_CATCH; 2073 case JDWP_EVENT(METHOD_ENTRY): 2074 return EI_METHOD_ENTRY; 2075 case JDWP_EVENT(METHOD_EXIT): 2076 return EI_METHOD_EXIT; 2077 case JDWP_EVENT(METHOD_EXIT_WITH_RETURN_VALUE): 2078 return EI_METHOD_EXIT; 2079 case JDWP_EVENT(MONITOR_CONTENDED_ENTER): 2080 return EI_MONITOR_CONTENDED_ENTER; 2081 case JDWP_EVENT(MONITOR_CONTENDED_ENTERED): 2082 return EI_MONITOR_CONTENDED_ENTERED; 2083 case JDWP_EVENT(MONITOR_WAIT): 2084 return EI_MONITOR_WAIT; 2085 case JDWP_EVENT(MONITOR_WAITED): 2086 return EI_MONITOR_WAITED; 2087 case JDWP_EVENT(VM_INIT): 2088 return EI_VM_INIT; 2089 case JDWP_EVENT(VM_DEATH): 2090 return EI_VM_DEATH; 2091 default: 2092 break; 2093 } 2094 2095 /* 2096 * Event type not recognized - don't exit with error as caller 2097 * may wish to return error to debugger. 2098 */ 2099 return (EventIndex)0; 2100 } 2101 2102 EventIndex 2103 jvmti2EventIndex(jvmtiEvent kind) 2104 { 2105 switch ( kind ) { 2106 case JVMTI_EVENT_SINGLE_STEP: 2107 return EI_SINGLE_STEP; 2108 case JVMTI_EVENT_BREAKPOINT: 2109 return EI_BREAKPOINT; 2110 case JVMTI_EVENT_FRAME_POP: 2111 return EI_FRAME_POP; 2112 case JVMTI_EVENT_EXCEPTION: 2113 return EI_EXCEPTION; 2114 case JVMTI_EVENT_THREAD_START: 2115 return EI_THREAD_START; 2116 case JVMTI_EVENT_THREAD_END: 2117 return EI_THREAD_END; 2118 case JVMTI_EVENT_CLASS_PREPARE: 2119 return EI_CLASS_PREPARE; 2120 case JVMTI_EVENT_CLASS_LOAD: 2121 return EI_CLASS_LOAD; 2122 case JVMTI_EVENT_FIELD_ACCESS: 2123 return EI_FIELD_ACCESS; 2124 case JVMTI_EVENT_FIELD_MODIFICATION: 2125 return EI_FIELD_MODIFICATION; 2126 case JVMTI_EVENT_EXCEPTION_CATCH: 2127 return EI_EXCEPTION_CATCH; 2128 case JVMTI_EVENT_METHOD_ENTRY: 2129 return EI_METHOD_ENTRY; 2130 case JVMTI_EVENT_METHOD_EXIT: 2131 return EI_METHOD_EXIT; 2132 /* 2133 * There is no JVMTI_EVENT_METHOD_EXIT_WITH_RETURN_VALUE. 2134 * The normal JVMTI_EVENT_METHOD_EXIT always contains the return value. 2135 */ 2136 case JVMTI_EVENT_MONITOR_CONTENDED_ENTER: 2137 return EI_MONITOR_CONTENDED_ENTER; 2138 case JVMTI_EVENT_MONITOR_CONTENDED_ENTERED: 2139 return EI_MONITOR_CONTENDED_ENTERED; 2140 case JVMTI_EVENT_MONITOR_WAIT: 2141 return EI_MONITOR_WAIT; 2142 case JVMTI_EVENT_MONITOR_WAITED: 2143 return EI_MONITOR_WAITED; 2144 case JVMTI_EVENT_VM_INIT: 2145 return EI_VM_INIT; 2146 case JVMTI_EVENT_VM_DEATH: 2147 return EI_VM_DEATH; 2148 /* vthread events */ 2149 case JVMTI_EVENT_VIRTUAL_THREAD_START: 2150 return EI_VIRTUAL_THREAD_START; 2151 case JVMTI_EVENT_VIRTUAL_THREAD_END: 2152 return EI_VIRTUAL_THREAD_END; 2153 2154 default: 2155 EXIT_ERROR(AGENT_ERROR_INVALID_INDEX,"JVMTI to EventIndex mapping"); 2156 break; 2157 } 2158 return (EventIndex)0; 2159 } 2160 2161 /* This routine is commonly used, maps jvmti and agent errors to the best 2162 * jdwp error code we can map to. 2163 */ 2164 jdwpError 2165 map2jdwpError(jvmtiError error) 2166 { 2167 switch ( (int)error ) { 2168 case JVMTI_ERROR_NONE: 2169 return JDWP_ERROR(NONE); 2170 case AGENT_ERROR_INVALID_THREAD: 2171 case JVMTI_ERROR_INVALID_THREAD: 2172 return JDWP_ERROR(INVALID_THREAD); 2173 case JVMTI_ERROR_INVALID_THREAD_GROUP: 2174 return JDWP_ERROR(INVALID_THREAD_GROUP); 2175 case JVMTI_ERROR_INVALID_PRIORITY: 2176 return JDWP_ERROR(INVALID_PRIORITY); 2177 case JVMTI_ERROR_THREAD_NOT_SUSPENDED: 2178 return JDWP_ERROR(THREAD_NOT_SUSPENDED); 2179 case JVMTI_ERROR_THREAD_SUSPENDED: 2180 return JDWP_ERROR(THREAD_SUSPENDED); 2181 case JVMTI_ERROR_THREAD_NOT_ALIVE: 2182 return JDWP_ERROR(INVALID_THREAD); 2183 case AGENT_ERROR_INVALID_OBJECT: 2184 case JVMTI_ERROR_INVALID_OBJECT: 2185 return JDWP_ERROR(INVALID_OBJECT); 2186 case JVMTI_ERROR_INVALID_CLASS: 2187 return JDWP_ERROR(INVALID_CLASS); 2188 case JVMTI_ERROR_CLASS_NOT_PREPARED: 2189 return JDWP_ERROR(CLASS_NOT_PREPARED); 2190 case JVMTI_ERROR_INVALID_METHODID: 2191 return JDWP_ERROR(INVALID_METHODID); 2192 case JVMTI_ERROR_INVALID_LOCATION: 2193 return JDWP_ERROR(INVALID_LOCATION); 2194 case JVMTI_ERROR_INVALID_FIELDID: 2195 return JDWP_ERROR(INVALID_FIELDID); 2196 case AGENT_ERROR_NO_MORE_FRAMES: 2197 case JVMTI_ERROR_NO_MORE_FRAMES: 2198 return JDWP_ERROR(NO_MORE_FRAMES); 2199 case JVMTI_ERROR_OPAQUE_FRAME: 2200 return JDWP_ERROR(OPAQUE_FRAME); 2201 case JVMTI_ERROR_TYPE_MISMATCH: 2202 return JDWP_ERROR(TYPE_MISMATCH); 2203 case JVMTI_ERROR_INVALID_SLOT: 2204 return JDWP_ERROR(INVALID_SLOT); 2205 case JVMTI_ERROR_DUPLICATE: 2206 return JDWP_ERROR(DUPLICATE); 2207 case JVMTI_ERROR_NOT_FOUND: 2208 return JDWP_ERROR(NOT_FOUND); 2209 case JVMTI_ERROR_INVALID_MONITOR: 2210 return JDWP_ERROR(INVALID_MONITOR); 2211 case JVMTI_ERROR_NOT_MONITOR_OWNER: 2212 return JDWP_ERROR(NOT_MONITOR_OWNER); 2213 case JVMTI_ERROR_INTERRUPT: 2214 return JDWP_ERROR(INTERRUPT); 2215 case JVMTI_ERROR_INVALID_CLASS_FORMAT: 2216 return JDWP_ERROR(INVALID_CLASS_FORMAT); 2217 case JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION: 2218 return JDWP_ERROR(CIRCULAR_CLASS_DEFINITION); 2219 case JVMTI_ERROR_FAILS_VERIFICATION: 2220 return JDWP_ERROR(FAILS_VERIFICATION); 2221 case JVMTI_ERROR_INVALID_TYPESTATE: 2222 return JDWP_ERROR(INVALID_TYPESTATE); 2223 case JVMTI_ERROR_UNSUPPORTED_VERSION: 2224 return JDWP_ERROR(UNSUPPORTED_VERSION); 2225 case JVMTI_ERROR_NAMES_DONT_MATCH: 2226 return JDWP_ERROR(NAMES_DONT_MATCH); 2227 case AGENT_ERROR_NULL_POINTER: 2228 case JVMTI_ERROR_NULL_POINTER: 2229 return JDWP_ERROR(NULL_POINTER); 2230 case JVMTI_ERROR_ABSENT_INFORMATION: 2231 return JDWP_ERROR(ABSENT_INFORMATION); 2232 case AGENT_ERROR_INVALID_EVENT_TYPE: 2233 case JVMTI_ERROR_INVALID_EVENT_TYPE: 2234 return JDWP_ERROR(INVALID_EVENT_TYPE); 2235 case AGENT_ERROR_ILLEGAL_ARGUMENT: 2236 case JVMTI_ERROR_ILLEGAL_ARGUMENT: 2237 return JDWP_ERROR(ILLEGAL_ARGUMENT); 2238 case JVMTI_ERROR_OUT_OF_MEMORY: 2239 case AGENT_ERROR_OUT_OF_MEMORY: 2240 return JDWP_ERROR(OUT_OF_MEMORY); 2241 case JVMTI_ERROR_ACCESS_DENIED: 2242 return JDWP_ERROR(ACCESS_DENIED); 2243 case JVMTI_ERROR_WRONG_PHASE: 2244 case AGENT_ERROR_VM_DEAD: 2245 case AGENT_ERROR_NO_JNI_ENV: 2246 return JDWP_ERROR(VM_DEAD); 2247 case AGENT_ERROR_JNI_EXCEPTION: 2248 case JVMTI_ERROR_UNATTACHED_THREAD: 2249 return JDWP_ERROR(UNATTACHED_THREAD); 2250 case JVMTI_ERROR_NOT_AVAILABLE: 2251 case JVMTI_ERROR_MUST_POSSESS_CAPABILITY: 2252 return JDWP_ERROR(NOT_IMPLEMENTED); 2253 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED: 2254 return JDWP_ERROR(HIERARCHY_CHANGE_NOT_IMPLEMENTED); 2255 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED: 2256 return JDWP_ERROR(DELETE_METHOD_NOT_IMPLEMENTED); 2257 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED: 2258 return JDWP_ERROR(ADD_METHOD_NOT_IMPLEMENTED); 2259 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED: 2260 return JDWP_ERROR(SCHEMA_CHANGE_NOT_IMPLEMENTED); 2261 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED: 2262 return JDWP_ERROR(CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED); 2263 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED: 2264 return JDWP_ERROR(METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED); 2265 case JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED: 2266 return JDWP_ERROR(CLASS_ATTRIBUTE_CHANGE_NOT_IMPLEMENTED); 2267 case JVMTI_ERROR_UNSUPPORTED_OPERATION: 2268 return JDWP_ERROR(NOT_IMPLEMENTED); 2269 case AGENT_ERROR_NOT_CURRENT_FRAME: 2270 return JDWP_ERROR(NOT_CURRENT_FRAME); 2271 case AGENT_ERROR_INVALID_TAG: 2272 return JDWP_ERROR(INVALID_TAG); 2273 case AGENT_ERROR_ALREADY_INVOKING: 2274 return JDWP_ERROR(ALREADY_INVOKING); 2275 case AGENT_ERROR_INVALID_INDEX: 2276 return JDWP_ERROR(INVALID_INDEX); 2277 case AGENT_ERROR_INVALID_LENGTH: 2278 return JDWP_ERROR(INVALID_LENGTH); 2279 case AGENT_ERROR_INVALID_STRING: 2280 return JDWP_ERROR(INVALID_STRING); 2281 case AGENT_ERROR_INVALID_CLASS_LOADER: 2282 return JDWP_ERROR(INVALID_CLASS_LOADER); 2283 case AGENT_ERROR_INVALID_ARRAY: 2284 return JDWP_ERROR(INVALID_ARRAY); 2285 case AGENT_ERROR_TRANSPORT_LOAD: 2286 return JDWP_ERROR(TRANSPORT_LOAD); 2287 case AGENT_ERROR_TRANSPORT_INIT: 2288 return JDWP_ERROR(TRANSPORT_INIT); 2289 case AGENT_ERROR_NATIVE_METHOD: 2290 return JDWP_ERROR(NATIVE_METHOD); 2291 case AGENT_ERROR_INVALID_COUNT: 2292 return JDWP_ERROR(INVALID_COUNT); 2293 case AGENT_ERROR_INVALID_FRAMEID: 2294 return JDWP_ERROR(INVALID_FRAMEID); 2295 case JVMTI_ERROR_INTERNAL: 2296 case JVMTI_ERROR_INVALID_ENVIRONMENT: 2297 case AGENT_ERROR_INTERNAL: 2298 case AGENT_ERROR_JVMTI_INTERNAL: 2299 case AGENT_ERROR_JDWP_INTERNAL: 2300 return JDWP_ERROR(INTERNAL); 2301 default: 2302 break; 2303 } 2304 return JDWP_ERROR(INTERNAL); 2305 } 2306 2307 jint 2308 map2jdwpSuspendStatus(jint state) 2309 { 2310 jint status = 0; 2311 if ( ( state & JVMTI_THREAD_STATE_SUSPENDED ) != 0 ) { 2312 status = JDWP_SUSPEND_STATUS(SUSPENDED); 2313 } 2314 return status; 2315 } 2316 2317 jdwpThreadStatus 2318 map2jdwpThreadStatus(jint state) 2319 { 2320 jdwpThreadStatus status; 2321 2322 status = (jdwpThreadStatus)(-1); 2323 2324 if ( ! ( state & JVMTI_THREAD_STATE_ALIVE ) ) { 2325 if ( state & JVMTI_THREAD_STATE_TERMINATED ) { 2326 status = JDWP_THREAD_STATUS(ZOMBIE); 2327 } else { 2328 /* FIXUP? New JDWP #define for not started? */ 2329 status = (jdwpThreadStatus)(-1); 2330 } 2331 } else { 2332 if ( state & JVMTI_THREAD_STATE_SLEEPING ) { 2333 status = JDWP_THREAD_STATUS(SLEEPING); 2334 } else if ( state & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER ) { 2335 status = JDWP_THREAD_STATUS(MONITOR); 2336 } else if ( state & JVMTI_THREAD_STATE_WAITING ) { 2337 status = JDWP_THREAD_STATUS(WAIT); 2338 } else if ( state & JVMTI_THREAD_STATE_RUNNABLE ) { 2339 status = JDWP_THREAD_STATUS(RUNNING); 2340 } 2341 } 2342 return status; 2343 } 2344 2345 jint 2346 map2jdwpClassStatus(jint classStatus) 2347 { 2348 jint status = 0; 2349 if ( ( classStatus & JVMTI_CLASS_STATUS_VERIFIED ) != 0 ) { 2350 status |= JDWP_CLASS_STATUS(VERIFIED); 2351 } 2352 if ( ( classStatus & JVMTI_CLASS_STATUS_PREPARED ) != 0 ) { 2353 status |= JDWP_CLASS_STATUS(PREPARED); 2354 } 2355 if ( ( classStatus & JVMTI_CLASS_STATUS_INITIALIZED ) != 0 ) { 2356 status |= JDWP_CLASS_STATUS(INITIALIZED); 2357 } 2358 if ( ( classStatus & JVMTI_CLASS_STATUS_ERROR ) != 0 ) { 2359 status |= JDWP_CLASS_STATUS(ERROR); 2360 } 2361 return status; 2362 } 2363 2364 void 2365 log_debugee_location(const char *func, 2366 jthread thread, jmethodID method, jlocation location) 2367 { 2368 int logging_locations = LOG_TEST(JDWP_LOG_LOC); 2369 2370 if ( logging_locations ) { 2371 char *method_name; 2372 char *class_sig; 2373 jvmtiError error; 2374 jvmtiThreadInfo info; 2375 jint state; 2376 2377 /* Get thread information */ 2378 info.name = NULL; 2379 error = FUNC_PTR(gdata->jvmti,GetThreadInfo) 2380 (gdata->jvmti, thread, &info); 2381 if ( error != JVMTI_ERROR_NONE) { 2382 info.name = NULL; 2383 } 2384 error = FUNC_PTR(gdata->jvmti,GetThreadState) 2385 (gdata->jvmti, thread, &state); 2386 if ( error != JVMTI_ERROR_NONE) { 2387 state = 0; 2388 } 2389 2390 /* Get method if necessary */ 2391 if ( method==NULL ) { 2392 error = FUNC_PTR(gdata->jvmti,GetFrameLocation) 2393 (gdata->jvmti, thread, 0, &method, &location); 2394 if ( error != JVMTI_ERROR_NONE ) { 2395 method = NULL; 2396 location = 0; 2397 } 2398 } 2399 2400 /* Get method name */ 2401 method_name = NULL; 2402 if ( method != NULL ) { 2403 error = methodSignature(method, &method_name, NULL, NULL); 2404 if ( error != JVMTI_ERROR_NONE ) { 2405 method_name = NULL; 2406 } 2407 } 2408 2409 /* Get class signature */ 2410 class_sig = NULL; 2411 if ( method != NULL ) { 2412 jclass clazz; 2413 2414 error = methodClass(method, &clazz); 2415 if ( error == JVMTI_ERROR_NONE ) { 2416 error = classSignature(clazz, &class_sig, NULL); 2417 if ( error != JVMTI_ERROR_NONE ) { 2418 class_sig = NULL; 2419 } 2420 } 2421 } 2422 2423 /* Issue log message */ 2424 LOG_LOC(("%s: debuggee: thread=%p(%s:0x%x),method=%p(%s@%d;%s)", 2425 func, 2426 thread, info.name==NULL ? "?" : info.name, state, 2427 method, method_name==NULL ? "?" : method_name, 2428 (int)location, class_sig==NULL ? "?" : class_sig)); 2429 2430 /* Free memory */ 2431 if ( class_sig != NULL ) { 2432 jvmtiDeallocate(class_sig); 2433 } 2434 if ( method_name != NULL ) { 2435 jvmtiDeallocate(method_name); 2436 } 2437 if ( info.name != NULL ) { 2438 jvmtiDeallocate(info.name); 2439 } 2440 } 2441 } 2442 2443 /* ********************************************************************* */ 2444 /* JDK 6.0: Use of new Heap Iteration functions */ 2445 /* ********************************************************************* */ 2446 2447 /* ********************************************************************* */ 2448 /* Instances */ 2449 2450 /* Structure to hold class instances heap iteration data (arg user_data) */ 2451 typedef struct ClassInstancesData { 2452 jint instCount; 2453 jint maxInstances; 2454 jlong objTag; 2455 jvmtiError error; 2456 } ClassInstancesData; 2457 2458 /* Callback for instance object tagging (heap_reference_callback). */ 2459 static jint JNICALL 2460 cbObjectTagInstance(jvmtiHeapReferenceKind reference_kind, 2461 const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, 2462 jlong referrer_class_tag, jlong size, 2463 jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data) 2464 { 2465 ClassInstancesData *data; 2466 2467 /* Check data structure */ 2468 data = (ClassInstancesData*)user_data; 2469 if (data == NULL) { 2470 return JVMTI_VISIT_ABORT; 2471 } 2472 2473 /* If we have tagged enough objects, just abort */ 2474 if ( data->maxInstances != 0 && data->instCount >= data->maxInstances ) { 2475 return JVMTI_VISIT_ABORT; 2476 } 2477 2478 /* If tagged already, just continue */ 2479 if ( (*tag_ptr) != (jlong)0 ) { 2480 return JVMTI_VISIT_OBJECTS; 2481 } 2482 2483 /* Tag the object so we don't count it again, and so we can retrieve it */ 2484 (*tag_ptr) = data->objTag; 2485 data->instCount++; 2486 return JVMTI_VISIT_OBJECTS; 2487 } 2488 2489 /* Get instances for one class */ 2490 jvmtiError 2491 classInstances(jclass klass, ObjectBatch *instances, int maxInstances) 2492 { 2493 ClassInstancesData data; 2494 jvmtiHeapCallbacks heap_callbacks; 2495 jvmtiError error; 2496 jvmtiEnv *jvmti; 2497 2498 /* Check interface assumptions */ 2499 2500 if (klass == NULL) { 2501 return AGENT_ERROR_INVALID_OBJECT; 2502 } 2503 2504 if ( maxInstances < 0 || instances == NULL) { 2505 return AGENT_ERROR_ILLEGAL_ARGUMENT; 2506 } 2507 2508 /* Initialize return information */ 2509 instances->count = 0; 2510 instances->objects = NULL; 2511 2512 /* Get jvmti environment to use */ 2513 jvmti = getSpecialJvmti(); 2514 if ( jvmti == NULL ) { 2515 return AGENT_ERROR_INTERNAL; 2516 } 2517 2518 /* Setup data to passed around the callbacks */ 2519 data.instCount = 0; 2520 data.maxInstances = maxInstances; 2521 data.objTag = (jlong)1; 2522 data.error = JVMTI_ERROR_NONE; 2523 2524 /* Clear out callbacks structure */ 2525 (void)memset(&heap_callbacks,0,sizeof(heap_callbacks)); 2526 2527 /* Set the callbacks we want */ 2528 heap_callbacks.heap_reference_callback = &cbObjectTagInstance; 2529 2530 /* Follow references, no initiating object, just this class, all objects */ 2531 error = JVMTI_FUNC_PTR(jvmti,FollowReferences) 2532 (jvmti, 0, klass, NULL, &heap_callbacks, &data); 2533 if ( error == JVMTI_ERROR_NONE ) { 2534 error = data.error; 2535 } 2536 2537 /* Get all the instances now that they are tagged */ 2538 if ( error == JVMTI_ERROR_NONE ) { 2539 error = JVMTI_FUNC_PTR(jvmti,GetObjectsWithTags) 2540 (jvmti, 1, &(data.objTag), &(instances->count), 2541 &(instances->objects), NULL); 2542 /* Verify we got the count we expected */ 2543 if ( data.instCount != instances->count ) { 2544 error = AGENT_ERROR_INTERNAL; 2545 } 2546 } 2547 2548 /* Dispose of any special jvmti environment */ 2549 (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti); 2550 return error; 2551 } 2552 2553 /* ********************************************************************* */ 2554 /* Instance counts. */ 2555 2556 /* Macros to convert a class or instance tag to an index and back again */ 2557 #define INDEX2CLASSTAG(i) ((jlong)((i)+1)) 2558 #define CLASSTAG2INDEX(t) (((int)(t))-1) 2559 #define JLONG_ABS(x) (((x)<(jlong)0)?-(x):(x)) 2560 2561 /* Structure to hold class count heap traversal data (arg user_data) */ 2562 typedef struct ClassCountData { 2563 int classCount; 2564 jlong *counts; 2565 jlong negObjTag; 2566 jvmtiError error; 2567 } ClassCountData; 2568 2569 /* Two different cbObjectCounter's, one for FollowReferences, one for 2570 * IterateThroughHeap. Pick a card, any card. 2571 */ 2572 2573 /* Callback for object count heap traversal (heap_reference_callback) */ 2574 static jint JNICALL 2575 cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind, 2576 const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, 2577 jlong referrer_class_tag, jlong size, 2578 jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data) 2579 { 2580 ClassCountData *data; 2581 int index; 2582 jlong jindex; 2583 jlong tag; 2584 2585 /* Check data structure */ 2586 data = (ClassCountData*)user_data; 2587 if (data == NULL) { 2588 return JVMTI_VISIT_ABORT; 2589 } 2590 2591 /* Classes with no class_tag should have been filtered out. */ 2592 if ( class_tag == (jlong)0 ) { 2593 data->error = AGENT_ERROR_INTERNAL; 2594 return JVMTI_VISIT_ABORT; 2595 } 2596 2597 /* Class tag not one we really want (jclass not in supplied list) */ 2598 if ( class_tag == data->negObjTag ) { 2599 return JVMTI_VISIT_OBJECTS; 2600 } 2601 2602 /* If object tag is negative, just continue, we counted it */ 2603 tag = (*tag_ptr); 2604 if ( tag < (jlong)0 ) { 2605 return JVMTI_VISIT_OBJECTS; 2606 } 2607 2608 /* Tag the object with a negative value just so we don't count it again */ 2609 if ( tag == (jlong)0 ) { 2610 /* This object had no tag value, so we give it the negObjTag value */ 2611 (*tag_ptr) = data->negObjTag; 2612 } else { 2613 /* If this object had a positive tag value, it must be one of the 2614 * jclass objects we tagged. We need to preserve the value of 2615 * this tag for later objects that might have this as a class 2616 * tag, so we just make the existing tag value negative. 2617 */ 2618 (*tag_ptr) = -tag; 2619 } 2620 2621 /* Absolute value of class tag is an index into the counts[] array */ 2622 jindex = JLONG_ABS(class_tag); 2623 index = CLASSTAG2INDEX(jindex); 2624 if (index < 0 || index >= data->classCount) { 2625 data->error = AGENT_ERROR_ILLEGAL_ARGUMENT; 2626 return JVMTI_VISIT_ABORT; 2627 } 2628 2629 /* Bump instance count on this class */ 2630 data->counts[index]++; 2631 return JVMTI_VISIT_OBJECTS; 2632 } 2633 2634 /* Callback for instance count heap traversal (heap_iteration_callback) */ 2635 static jint JNICALL 2636 cbObjectCounter(jlong class_tag, jlong size, jlong* tag_ptr, jint length, 2637 void* user_data) 2638 { 2639 ClassCountData *data; 2640 int index; 2641 2642 /* Check data structure */ 2643 data = (ClassCountData*)user_data; 2644 if (data == NULL) { 2645 return JVMTI_VISIT_ABORT; 2646 } 2647 2648 /* Classes with no tag should be filtered out. */ 2649 if ( class_tag == (jlong)0 ) { 2650 data->error = AGENT_ERROR_INTERNAL; 2651 return JVMTI_VISIT_ABORT; 2652 } 2653 2654 /* Class tag is actually an index into data arrays */ 2655 index = CLASSTAG2INDEX(class_tag); 2656 if (index < 0 || index >= data->classCount) { 2657 data->error = AGENT_ERROR_ILLEGAL_ARGUMENT; 2658 return JVMTI_VISIT_ABORT; 2659 } 2660 2661 /* Bump instance count on this class */ 2662 data->counts[index]++; 2663 return JVMTI_VISIT_OBJECTS; 2664 } 2665 2666 /* Get instance counts for a set of classes */ 2667 jvmtiError 2668 classInstanceCounts(jint classCount, jclass *classes, jlong *counts) 2669 { 2670 jvmtiHeapCallbacks heap_callbacks; 2671 ClassCountData data; 2672 jvmtiError error; 2673 jvmtiEnv *jvmti; 2674 int i; 2675 2676 /* Check interface assumptions */ 2677 if ( classes == NULL || classCount <= 0 || counts == NULL ) { 2678 return AGENT_ERROR_ILLEGAL_ARGUMENT; 2679 } 2680 2681 /* Initialize return information */ 2682 for ( i = 0 ; i < classCount ; i++ ) { 2683 counts[i] = (jlong)0; 2684 } 2685 2686 /* Get jvmti environment to use */ 2687 jvmti = getSpecialJvmti(); 2688 if ( jvmti == NULL ) { 2689 return AGENT_ERROR_INTERNAL; 2690 } 2691 2692 /* Setup class data structure */ 2693 data.error = JVMTI_ERROR_NONE; 2694 data.classCount = classCount; 2695 data.counts = counts; 2696 2697 error = JVMTI_ERROR_NONE; 2698 /* Set tags on classes, use index in classes[] as the tag value. */ 2699 error = JVMTI_ERROR_NONE; 2700 for ( i = 0 ; i < classCount ; i++ ) { 2701 if (classes[i] != NULL) { 2702 jlong tag; 2703 2704 tag = INDEX2CLASSTAG(i); 2705 error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, classes[i], tag); 2706 if ( error != JVMTI_ERROR_NONE ) { 2707 break; 2708 } 2709 } 2710 } 2711 2712 /* Traverse heap, two ways to do this for instance counts. */ 2713 if ( error == JVMTI_ERROR_NONE ) { 2714 2715 /* Clear out callbacks structure */ 2716 (void)memset(&heap_callbacks,0,sizeof(heap_callbacks)); 2717 2718 /* Check debug flags to see how to do this. */ 2719 if ( (gdata->debugflags & USE_ITERATE_THROUGH_HEAP) == 0 ) { 2720 2721 /* Using FollowReferences only gives us live objects, but we 2722 * need to tag the objects to avoid counting them twice since 2723 * the callback is per reference. 2724 * The jclass objects have been tagged with their index in the 2725 * supplied list, and that tag may flip to negative if it 2726 * is also an object of interest. 2727 * All other objects being counted that weren't in the 2728 * supplied classes list will have a negative classCount 2729 * tag value. So all objects counted will have negative tags. 2730 * If the absolute tag value is an index in the supplied 2731 * list, then it's one of the supplied classes. 2732 */ 2733 data.negObjTag = -INDEX2CLASSTAG(classCount); 2734 2735 /* Setup callbacks, only using object reference callback */ 2736 heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef; 2737 2738 /* Follow references, no initiating object, tagged classes only */ 2739 error = JVMTI_FUNC_PTR(jvmti,FollowReferences) 2740 (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, 2741 NULL, NULL, &heap_callbacks, &data); 2742 2743 } else { 2744 2745 /* Using IterateThroughHeap means that we will visit each object 2746 * once, so no special tag tricks here. Just simple counting. 2747 * However in this case the object might not be live, so we do 2748 * a GC beforehand to make sure we minimize this. 2749 */ 2750 2751 /* FIXUP: Need some kind of trigger here to avoid excessive GC's? */ 2752 error = JVMTI_FUNC_PTR(jvmti,ForceGarbageCollection)(jvmti); 2753 if ( error != JVMTI_ERROR_NONE ) { 2754 2755 /* Setup callbacks, just need object callback */ 2756 heap_callbacks.heap_iteration_callback = &cbObjectCounter; 2757 2758 /* Iterate through entire heap, tagged classes only */ 2759 error = JVMTI_FUNC_PTR(jvmti,IterateThroughHeap) 2760 (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, 2761 NULL, &heap_callbacks, &data); 2762 2763 } 2764 } 2765 2766 /* Use data error if needed */ 2767 if ( error == JVMTI_ERROR_NONE ) { 2768 error = data.error; 2769 } 2770 2771 } 2772 2773 /* Dispose of any special jvmti environment */ 2774 (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti); 2775 return error; 2776 } 2777 2778 /* ********************************************************************* */ 2779 /* Referrers */ 2780 2781 /* Structure to hold object referrer heap traversal data (arg user_data) */ 2782 typedef struct ReferrerData { 2783 int refCount; 2784 int maxObjects; 2785 jlong refTag; 2786 jlong objTag; 2787 jboolean selfRef; 2788 jvmtiError error; 2789 } ReferrerData; 2790 2791 /* Callback for referrers object tagging (heap_reference_callback). */ 2792 static jint JNICALL 2793 cbObjectTagReferrer(jvmtiHeapReferenceKind reference_kind, 2794 const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, 2795 jlong referrer_class_tag, jlong size, 2796 jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data) 2797 { 2798 ReferrerData *data; 2799 2800 /* Check data structure */ 2801 data = (ReferrerData*)user_data; 2802 if (data == NULL) { 2803 return JVMTI_VISIT_ABORT; 2804 } 2805 2806 /* If we have tagged enough objects, just abort */ 2807 if ( data->maxObjects != 0 && data->refCount >= data->maxObjects ) { 2808 return JVMTI_VISIT_ABORT; 2809 } 2810 2811 /* If not of interest, just continue */ 2812 if ( (*tag_ptr) != data->objTag ) { 2813 return JVMTI_VISIT_OBJECTS; 2814 } 2815 2816 /* Self reference that we haven't counted? */ 2817 if ( tag_ptr == referrer_tag_ptr ) { 2818 if ( data->selfRef == JNI_FALSE ) { 2819 data->selfRef = JNI_TRUE; 2820 data->refCount++; 2821 } 2822 return JVMTI_VISIT_OBJECTS; 2823 } 2824 2825 /* If the referrer can be tagged, and hasn't been tagged, tag it */ 2826 if ( referrer_tag_ptr != NULL ) { 2827 if ( (*referrer_tag_ptr) == (jlong)0 ) { 2828 *referrer_tag_ptr = data->refTag; 2829 data->refCount++; 2830 } 2831 } 2832 return JVMTI_VISIT_OBJECTS; 2833 } 2834 2835 /* Heap traversal to find referrers of an object */ 2836 jvmtiError 2837 objectReferrers(jobject obj, ObjectBatch *referrers, int maxObjects) 2838 { 2839 jvmtiHeapCallbacks heap_callbacks; 2840 ReferrerData data; 2841 jvmtiError error; 2842 jvmtiEnv *jvmti; 2843 2844 /* Check interface assumptions */ 2845 if (obj == NULL) { 2846 return AGENT_ERROR_INVALID_OBJECT; 2847 } 2848 if (referrers == NULL || maxObjects < 0 ) { 2849 return AGENT_ERROR_ILLEGAL_ARGUMENT; 2850 } 2851 2852 /* Initialize return information */ 2853 referrers->count = 0; 2854 referrers->objects = NULL; 2855 2856 /* Get jvmti environment to use */ 2857 jvmti = getSpecialJvmti(); 2858 if ( jvmti == NULL ) { 2859 return AGENT_ERROR_INTERNAL; 2860 } 2861 2862 /* Fill in the data structure passed around the callbacks */ 2863 data.refCount = 0; 2864 data.maxObjects = maxObjects; 2865 data.objTag = (jlong)1; 2866 data.refTag = (jlong)2; 2867 data.selfRef = JNI_FALSE; 2868 data.error = JVMTI_ERROR_NONE; 2869 2870 /* Tag the object of interest */ 2871 error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, obj, data.objTag); 2872 2873 /* No need to go any further if we can't tag the object */ 2874 if ( error == JVMTI_ERROR_NONE ) { 2875 2876 /* Clear out callbacks structure */ 2877 (void)memset(&heap_callbacks,0,sizeof(heap_callbacks)); 2878 2879 /* Setup callbacks we want */ 2880 heap_callbacks.heap_reference_callback = &cbObjectTagReferrer; 2881 2882 /* Follow references, no initiating object, all classes, 1 tagged objs */ 2883 error = JVMTI_FUNC_PTR(jvmti,FollowReferences) 2884 (jvmti, JVMTI_HEAP_FILTER_UNTAGGED, 2885 NULL, NULL, &heap_callbacks, &data); 2886 2887 /* Use data error if needed */ 2888 if ( error == JVMTI_ERROR_NONE ) { 2889 error = data.error; 2890 } 2891 2892 } 2893 2894 /* Watch out for self-reference */ 2895 if ( error == JVMTI_ERROR_NONE && data.selfRef == JNI_TRUE ) { 2896 /* Tag itself as a referer */ 2897 error = JVMTI_FUNC_PTR(jvmti,SetTag) (jvmti, obj, data.refTag); 2898 } 2899 2900 /* Get the jobjects for the tagged referrer objects. */ 2901 if ( error == JVMTI_ERROR_NONE ) { 2902 error = JVMTI_FUNC_PTR(jvmti,GetObjectsWithTags) 2903 (jvmti, 1, &(data.refTag), &(referrers->count), 2904 &(referrers->objects), NULL); 2905 /* Verify we got the count we expected */ 2906 if ( data.refCount != referrers->count ) { 2907 error = AGENT_ERROR_INTERNAL; 2908 } 2909 } 2910 2911 /* Dispose of any special jvmti environment */ 2912 (void)JVMTI_FUNC_PTR(jvmti,DisposeEnvironment)(jvmti); 2913 return error; 2914 }