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