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