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