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