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