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