1 /*
   2  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include "util.h"
  27 #include "VirtualMachineImpl.h"
  28 #include "commonRef.h"
  29 #include "inStream.h"
  30 #include "outStream.h"
  31 #include "eventHandler.h"
  32 #include "eventHelper.h"
  33 #include "threadControl.h"
  34 #include "SDE.h"
  35 #include "FrameID.h"
  36 
  37 static char *versionName = "Java Debug Wire Protocol (Reference Implementation)";
  38 
  39 static jboolean
  40 version(PacketInputStream *in, PacketOutputStream *out)
  41 {
  42     char buf[500];
  43     char *vmName;
  44     char *vmVersion;
  45     char *vmInfo;
  46 
  47     /* Now the JDWP versions are the same as JVMTI versions */
  48     int majorVersion = jvmtiMajorVersion();
  49     int minorVersion = 0;
  50 
  51     if (gdata->vmDead) {
  52         outStream_setError(out, JDWP_ERROR(VM_DEAD));
  53         return JNI_TRUE;
  54     }
  55 
  56     vmVersion = gdata->property_java_version;
  57     if (vmVersion == NULL) {
  58         vmVersion = "<unknown>";
  59     }
  60     vmName = gdata->property_java_vm_name;
  61     if (vmName == NULL) {
  62         vmName = "<unknown>";
  63     }
  64     vmInfo = gdata->property_java_vm_info;
  65     if (vmInfo == NULL) {
  66         vmInfo = "<unknown>";
  67     }
  68 
  69     /*
  70      * Write the descriptive version information
  71      */
  72     (void)snprintf(buf, sizeof(buf),
  73                 "%s version %d.%d\nJVM Debug Interface version %d.%d\n"
  74                  "JVM version %s (%s, %s)",
  75                   versionName, majorVersion, minorVersion,
  76                   jvmtiMajorVersion(), jvmtiMinorVersion(),
  77                   vmVersion, vmName, vmInfo);
  78     (void)outStream_writeString(out, buf);
  79 
  80     /*
  81      * Write the JDWP version numbers
  82      */
  83     (void)outStream_writeInt(out, majorVersion);
  84     (void)outStream_writeInt(out, minorVersion);
  85 
  86     /*
  87      * Write the VM version and name
  88      */
  89     (void)outStream_writeString(out, vmVersion);
  90     (void)outStream_writeString(out, vmName);
  91 
  92     return JNI_TRUE;
  93 }
  94 
  95 static jboolean
  96 classesForSignature(PacketInputStream *in, PacketOutputStream *out)
  97 {
  98     JNIEnv *env;
  99     char *signature;
 100 
 101     if (gdata->vmDead) {
 102         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 103         return JNI_TRUE;
 104     }
 105 
 106     signature = inStream_readString(in);
 107     if (signature == NULL) {
 108         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 109         return JNI_TRUE;
 110     }
 111     if (inStream_error(in)) {
 112         return JNI_TRUE;
 113     }
 114 
 115     env = getEnv();
 116 
 117     WITH_LOCAL_REFS(env, 1) {
 118 
 119         jint classCount;
 120         jclass *theClasses;
 121         jvmtiError error;
 122 
 123         error = allLoadedClasses(&theClasses, &classCount);
 124         if ( error == JVMTI_ERROR_NONE ) {
 125             /* Count classes in theClasses which match signature */
 126             int matchCount = 0;
 127             /* Count classes written to the JDWP connection */
 128             int writtenCount = 0;
 129             int i;
 130 
 131             for (i = 0; i < classCount; i++) {
 132                 jclass clazz = theClasses[i];
 133                 jint status = classStatus(clazz);
 134                 char *candidate_signature = NULL;
 135                 jint wanted =
 136                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY|
 137                      JVMTI_CLASS_STATUS_PRIMITIVE);
 138 
 139                 /* We want prepared classes, primitives, and arrays only */
 140                 if ((status & wanted) == 0) {
 141                     continue;
 142                 }
 143 
 144                 error = classSignature(clazz, &candidate_signature, NULL);
 145                 if (error != JVMTI_ERROR_NONE) {
 146                   // Clazz become invalid since the time we get the class list
 147                   // Skip this entry
 148                   if (error == JVMTI_ERROR_INVALID_CLASS) {
 149                     continue;
 150                   }
 151 
 152                   break;
 153                 }
 154 
 155                 if (strcmp(candidate_signature, signature) == 0) {
 156                     /* Float interesting classes (those that
 157                      * are matching and are prepared) to the
 158                      * beginning of the array.
 159                      */
 160                     theClasses[i] = theClasses[matchCount];
 161                     theClasses[matchCount++] = clazz;
 162                 }
 163                 jvmtiDeallocate(candidate_signature);
 164             }
 165 
 166             /* At this point matching prepared classes occupy
 167              * indicies 0 thru matchCount-1 of theClasses.
 168              */
 169 
 170             if ( error ==  JVMTI_ERROR_NONE ) {
 171                 (void)outStream_writeInt(out, matchCount);
 172                 for (; writtenCount < matchCount; writtenCount++) {
 173                     jclass clazz = theClasses[writtenCount];
 174                     jint status = classStatus(clazz);
 175                     jbyte tag = referenceTypeTag(clazz);
 176                     (void)outStream_writeByte(out, tag);
 177                     (void)outStream_writeObjectRef(env, out, clazz);
 178                     (void)outStream_writeInt(out, map2jdwpClassStatus(status));
 179                     /* No point in continuing if there's an error */
 180                     if (outStream_error(out)) {
 181                         break;
 182                     }
 183                 }
 184             }
 185 
 186             jvmtiDeallocate(theClasses);
 187         }
 188 
 189         if ( error != JVMTI_ERROR_NONE ) {
 190             outStream_setError(out, map2jdwpError(error));
 191         }
 192 
 193     } END_WITH_LOCAL_REFS(env);
 194 
 195     jvmtiDeallocate(signature);
 196 
 197     return JNI_TRUE;
 198 }
 199 
 200 static jboolean
 201 allModules(PacketInputStream *in, PacketOutputStream *out)
 202 {
 203     JNIEnv *env;
 204 
 205     if (gdata->vmDead) {
 206         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 207         return JNI_TRUE;
 208     }
 209 
 210     env = getEnv();
 211 
 212     WITH_LOCAL_REFS(env, 1) {
 213 
 214         jint count = 0;
 215         jint i = 0;
 216         jobject* modules = NULL;
 217         jvmtiError error = JVMTI_ERROR_NONE;
 218 
 219         error = JVMTI_FUNC_PTR(gdata->jvmti, GetAllModules) (gdata->jvmti, &count, &modules);
 220         if (error != JVMTI_ERROR_NONE) {
 221             outStream_setError(out, map2jdwpError(error));
 222         } else {
 223             (void)outStream_writeInt(out, count);
 224             for (i = 0; i < count; i++) {
 225                 (void)outStream_writeModuleRef(env, out, modules[i]);
 226             }
 227             jvmtiDeallocate(modules);
 228         }
 229 
 230     } END_WITH_LOCAL_REFS(env);
 231 
 232     return JNI_TRUE;
 233 }
 234 
 235 static jboolean
 236 allClasses1(PacketInputStream *in, PacketOutputStream *out, int outputGenerics)
 237 {
 238     JNIEnv *env;
 239 
 240     if (gdata->vmDead) {
 241         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 242         return JNI_TRUE;
 243     }
 244 
 245     env = getEnv();
 246 
 247     WITH_LOCAL_REFS(env, 1) {
 248 
 249         jint classCount;
 250         jclass *theClasses;
 251         jvmtiError error;
 252 
 253         error = allLoadedClasses(&theClasses, &classCount);
 254         if ( error != JVMTI_ERROR_NONE ) {
 255             outStream_setError(out, map2jdwpError(error));
 256         } else {
 257             /* Count classes in theClasses which are prepared */
 258             int prepCount = 0;
 259             /* Count classes written to the JDWP connection */
 260             int writtenCount = 0;
 261             int i;
 262 
 263             for (i=0; i<classCount; i++) {
 264                 jclass clazz = theClasses[i];
 265                 jint status = classStatus(clazz);
 266                 jint wanted =
 267                     (JVMTI_CLASS_STATUS_PREPARED|JVMTI_CLASS_STATUS_ARRAY);
 268 
 269                 /* We want prepared classes and arrays only */
 270                 if ((status & wanted) != 0) {
 271                     /* Float interesting classes (those that
 272                      * are prepared) to the beginning of the array.
 273                      */
 274                     theClasses[i] = theClasses[prepCount];
 275                     theClasses[prepCount++] = clazz;
 276                 }
 277             }
 278 
 279             /* At this point prepared classes occupy
 280              * indicies 0 thru prepCount-1 of theClasses.
 281              */
 282 
 283             (void)outStream_writeInt(out, prepCount);
 284             for (; writtenCount < prepCount; writtenCount++) {
 285                 char *signature = NULL;
 286                 char *genericSignature = NULL;
 287                 jclass clazz = theClasses[writtenCount];
 288                 jint status = classStatus(clazz);
 289                 jbyte tag = referenceTypeTag(clazz);
 290                 jvmtiError error;
 291 
 292                 error = classSignature(clazz, &signature, &genericSignature);
 293                 if (error != JVMTI_ERROR_NONE) {
 294                     outStream_setError(out, map2jdwpError(error));
 295                     break;
 296                 }
 297 
 298                 (void)outStream_writeByte(out, tag);
 299                 (void)outStream_writeObjectRef(env, out, clazz);
 300                 (void)outStream_writeString(out, signature);
 301                 if (outputGenerics == 1) {
 302                     writeGenericSignature(out, genericSignature);
 303                 }
 304 
 305                 (void)outStream_writeInt(out, map2jdwpClassStatus(status));
 306                 jvmtiDeallocate(signature);
 307                 if (genericSignature != NULL) {
 308                   jvmtiDeallocate(genericSignature);
 309                 }
 310 
 311                 /* No point in continuing if there's an error */
 312                 if (outStream_error(out)) {
 313                     break;
 314                 }
 315             }
 316             jvmtiDeallocate(theClasses);
 317         }
 318 
 319     } END_WITH_LOCAL_REFS(env);
 320 
 321     return JNI_TRUE;
 322 }
 323 
 324 static jboolean
 325 allClasses(PacketInputStream *in, PacketOutputStream *out)
 326 {
 327     return allClasses1(in, out, 0);
 328 }
 329 
 330 static jboolean
 331 allClassesWithGeneric(PacketInputStream *in, PacketOutputStream *out)
 332 {
 333     return allClasses1(in, out, 1);
 334 }
 335 
 336   /***********************************************************/
 337 
 338 
 339 static jboolean
 340 instanceCounts(PacketInputStream *in, PacketOutputStream *out)
 341 {
 342     jint classCount;
 343     jclass *classes;
 344     JNIEnv *env;
 345     int ii;
 346 
 347     if (gdata->vmDead) {
 348         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 349         return JNI_TRUE;
 350     }
 351 
 352     classCount = inStream_readInt(in);
 353 
 354     if (inStream_error(in)) {
 355         return JNI_TRUE;
 356     }
 357     if (classCount == 0) {
 358         (void)outStream_writeInt(out, 0);
 359         return JNI_TRUE;
 360     }
 361     if (classCount < 0) {
 362         outStream_setError(out, JDWP_ERROR(ILLEGAL_ARGUMENT));
 363         return JNI_TRUE;
 364     }
 365     env = getEnv();
 366     classes = jvmtiAllocate(classCount * (int)sizeof(jclass));
 367     for (ii = 0; ii < classCount; ii++) {
 368         jdwpError errorCode;
 369         classes[ii] = inStream_readClassRef(env, in);
 370         errorCode = inStream_error(in);
 371         if (errorCode != JDWP_ERROR(NONE)) {
 372             /*
 373              * A class could have been unloaded/gc'd so
 374              * if we get an error, just ignore it and keep
 375              * going.  An instanceCount of 0 will be returned.
 376              */
 377             if (errorCode == JDWP_ERROR(INVALID_OBJECT) ||
 378                 errorCode == JDWP_ERROR(INVALID_CLASS)) {
 379                 inStream_clearError(in);
 380                 classes[ii] = NULL;
 381                 continue;
 382             }
 383             jvmtiDeallocate(classes);
 384             return JNI_TRUE;
 385         }
 386     }
 387 
 388     WITH_LOCAL_REFS(env, 1) {
 389         jlong      *counts;
 390         jvmtiError error;
 391 
 392         counts = jvmtiAllocate(classCount * (int)sizeof(jlong));
 393         /* Iterate over heap getting info on these classes */
 394         error = classInstanceCounts(classCount, classes, counts);
 395         if (error != JVMTI_ERROR_NONE) {
 396             outStream_setError(out, map2jdwpError(error));
 397         } else {
 398             (void)outStream_writeInt(out, classCount);
 399             for (ii = 0; ii < classCount; ii++) {
 400                 (void)outStream_writeLong(out, counts[ii]);
 401             }
 402         }
 403         jvmtiDeallocate(counts);
 404     } END_WITH_LOCAL_REFS(env);
 405     jvmtiDeallocate(classes);
 406     return JNI_TRUE;
 407 }
 408 
 409 static jboolean
 410 redefineClasses(PacketInputStream *in, PacketOutputStream *out)
 411 {
 412     jvmtiClassDefinition *classDefs;
 413     jboolean ok = JNI_TRUE;
 414     jint classCount;
 415     jint i;
 416     JNIEnv *env;
 417 
 418     if (gdata->vmDead) {
 419         /* quietly ignore */
 420         return JNI_TRUE;
 421     }
 422 
 423     classCount = inStream_readInt(in);
 424     if (inStream_error(in)) {
 425         return JNI_TRUE;
 426     }
 427     if ( classCount == 0 ) {
 428         return JNI_TRUE;
 429     }
 430     /*LINTED*/
 431     classDefs = jvmtiAllocate(classCount*(int)sizeof(jvmtiClassDefinition));
 432     if (classDefs == NULL) {
 433         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 434         return JNI_TRUE;
 435     }
 436     /*LINTED*/
 437     (void)memset(classDefs, 0, classCount*sizeof(jvmtiClassDefinition));
 438 
 439     env = getEnv();
 440     for (i = 0; i < classCount; ++i) {
 441         int byteCount;
 442         unsigned char * bytes;
 443         jclass clazz;
 444 
 445         clazz = inStream_readClassRef(env, in);
 446         if (inStream_error(in)) {
 447             ok = JNI_FALSE;
 448             break;
 449         }
 450         byteCount = inStream_readInt(in);
 451         if (inStream_error(in)) {
 452             ok = JNI_FALSE;
 453             break;
 454         }
 455         if ( byteCount <= 0 ) {
 456             outStream_setError(out, JDWP_ERROR(INVALID_CLASS_FORMAT));
 457             ok = JNI_FALSE;
 458             break;
 459         }
 460         bytes = (unsigned char *)jvmtiAllocate(byteCount);
 461         if (bytes == NULL) {
 462             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 463             ok = JNI_FALSE;
 464             break;
 465         }
 466         (void)inStream_readBytes(in, byteCount, (jbyte *)bytes);
 467         if (inStream_error(in)) {
 468             ok = JNI_FALSE;
 469             break;
 470         }
 471 
 472         classDefs[i].klass = clazz;
 473         classDefs[i].class_byte_count = byteCount;
 474         classDefs[i].class_bytes = bytes;
 475     }
 476 
 477     if (ok == JNI_TRUE) {
 478         jvmtiError error;
 479 
 480         error = JVMTI_FUNC_PTR(gdata->jvmti,RedefineClasses)
 481                         (gdata->jvmti, classCount, classDefs);
 482         if (error != JVMTI_ERROR_NONE) {
 483             outStream_setError(out, map2jdwpError(error));
 484         } else {
 485             /* zap our BP info */
 486             for ( i = 0 ; i < classCount; i++ ) {
 487                 eventHandler_freeClassBreakpoints(classDefs[i].klass);
 488             }
 489         }
 490     }
 491 
 492     /* free up allocated memory */
 493     for ( i = 0 ; i < classCount; i++ ) {
 494         if ( classDefs[i].class_bytes != NULL ) {
 495             jvmtiDeallocate((void*)classDefs[i].class_bytes);
 496         }
 497     }
 498     jvmtiDeallocate(classDefs);
 499 
 500     return JNI_TRUE;
 501 }
 502 
 503 static jboolean
 504 setDefaultStratum(PacketInputStream *in, PacketOutputStream *out)
 505 {
 506     char *stratumId;
 507 
 508     if (gdata->vmDead) {
 509         /* quietly ignore */
 510         return JNI_TRUE;
 511     }
 512 
 513     stratumId = inStream_readString(in);
 514     if (inStream_error(in)) {
 515         return JNI_TRUE;
 516     } else if (strcmp(stratumId, "") == 0) {
 517         stratumId = NULL;
 518     }
 519     setGlobalStratumId(stratumId);
 520 
 521     return JNI_TRUE;
 522 }
 523 
 524 static jboolean
 525 getAllThreads(PacketInputStream *in, PacketOutputStream *out)
 526 {
 527     JNIEnv *env;
 528 
 529     if (gdata->vmDead) {
 530         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 531         return JNI_TRUE;
 532     }
 533 
 534     env = getEnv();
 535 
 536     WITH_LOCAL_REFS(env, 1) {
 537 
 538         int i;
 539         jint threadCount;
 540         jint fiberCount;
 541         jthread *theThreads;
 542         jthread *theFibers;
 543 
 544         theThreads = allThreads(&threadCount);
 545         theFibers = threadControl_allFibers(&fiberCount);
 546 
 547         if (theThreads == NULL || (theFibers == NULL && fiberCount != 0)) {
 548             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 549         } else {
 550             /* Squish out all of the debugger-spawned threads */
 551             threadCount = filterDebugThreads(theThreads, threadCount);
 552 
 553             (void)outStream_writeInt(out, threadCount + fiberCount);
 554             for (i = 0; i < fiberCount; i++) {
 555                 (void)outStream_writeObjectRef(env, out, theFibers[i]);
 556             }
 557             for (i = 0; i < threadCount; i++) {
 558                 (void)outStream_writeObjectRef(env, out, theThreads[i]);
 559             }
 560 
 561             jvmtiDeallocate(theThreads);
 562             jvmtiDeallocate(theFibers);
 563         }
 564 
 565     } END_WITH_LOCAL_REFS(env);
 566 
 567     return JNI_TRUE;
 568 }
 569 
 570 static jboolean
 571 topLevelThreadGroups(PacketInputStream *in, PacketOutputStream *out)
 572 {
 573     JNIEnv *env;
 574 
 575     if (gdata->vmDead) {
 576         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 577         return JNI_TRUE;
 578     }
 579 
 580     env = getEnv();
 581 
 582     WITH_LOCAL_REFS(env, 1) {
 583 
 584         jvmtiError error;
 585         jint groupCount;
 586         jthreadGroup *groups;
 587 
 588         groups = NULL;
 589         error = JVMTI_FUNC_PTR(gdata->jvmti,GetTopThreadGroups)
 590                     (gdata->jvmti, &groupCount, &groups);
 591         if (error != JVMTI_ERROR_NONE) {
 592             outStream_setError(out, map2jdwpError(error));
 593         } else {
 594             int i;
 595 
 596             (void)outStream_writeInt(out, groupCount);
 597             for (i = 0; i < groupCount; i++) {
 598                 (void)outStream_writeObjectRef(env, out, groups[i]);
 599             }
 600 
 601             jvmtiDeallocate(groups);
 602         }
 603 
 604     } END_WITH_LOCAL_REFS(env);
 605 
 606     return JNI_TRUE;
 607 }
 608 
 609 static jboolean
 610 dispose(PacketInputStream *in, PacketOutputStream *out)
 611 {
 612     return JNI_TRUE;
 613 }
 614 
 615 static jboolean
 616 idSizes(PacketInputStream *in, PacketOutputStream *out)
 617 {
 618     (void)outStream_writeInt(out, sizeof(jfieldID));    /* fields */
 619     (void)outStream_writeInt(out, sizeof(jmethodID));   /* methods */
 620     (void)outStream_writeInt(out, sizeof(jlong));       /* objects */
 621     (void)outStream_writeInt(out, sizeof(jlong));       /* referent types */
 622     (void)outStream_writeInt(out, sizeof(FrameID));    /* frames */
 623     return JNI_TRUE;
 624 }
 625 
 626 static jboolean
 627 suspend(PacketInputStream *in, PacketOutputStream *out)
 628 {
 629     jvmtiError error;
 630 
 631     if (gdata->vmDead) {
 632         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 633         return JNI_TRUE;
 634     }
 635     error = threadControl_suspendAll();
 636     if (error != JVMTI_ERROR_NONE) {
 637         outStream_setError(out, map2jdwpError(error));
 638     }
 639     return JNI_TRUE;
 640 }
 641 
 642 static jboolean
 643 resume(PacketInputStream *in, PacketOutputStream *out)
 644 {
 645     jvmtiError error;
 646 
 647     if (gdata->vmDead) {
 648         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 649         return JNI_TRUE;
 650     }
 651     error = threadControl_resumeAll();
 652     if (error != JVMTI_ERROR_NONE) {
 653         outStream_setError(out, map2jdwpError(error));
 654     }
 655     return JNI_TRUE;
 656 }
 657 
 658 static jboolean
 659 doExit(PacketInputStream *in, PacketOutputStream *out)
 660 {
 661     jint exitCode;
 662 
 663     exitCode = inStream_readInt(in);
 664     if (gdata->vmDead) {
 665         /* quietly ignore */
 666         return JNI_FALSE;
 667     }
 668 
 669     /* We send the reply from here because we are about to exit. */
 670     if (inStream_error(in)) {
 671         outStream_setError(out, inStream_error(in));
 672     }
 673     outStream_sendReply(out);
 674 
 675     forceExit(exitCode);
 676 
 677     /* Shouldn't get here */
 678     JDI_ASSERT(JNI_FALSE);
 679 
 680     /* Shut up the compiler */
 681     return JNI_FALSE;
 682 
 683 }
 684 
 685 static jboolean
 686 createString(PacketInputStream *in, PacketOutputStream *out)
 687 {
 688     JNIEnv *env;
 689     char *cstring;
 690 
 691     if (gdata->vmDead) {
 692         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 693         return JNI_TRUE;
 694     }
 695 
 696     cstring = inStream_readString(in);
 697     if (cstring == NULL) {
 698         outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 699         return JNI_TRUE;
 700     }
 701     if (inStream_error(in)) {
 702         return JNI_TRUE;
 703     }
 704 
 705     env = getEnv();
 706 
 707     WITH_LOCAL_REFS(env, 1) {
 708 
 709         jstring string;
 710 
 711         string = JNI_FUNC_PTR(env,NewStringUTF)(env, cstring);
 712         if (JNI_FUNC_PTR(env,ExceptionOccurred)(env)) {
 713             outStream_setError(out, JDWP_ERROR(OUT_OF_MEMORY));
 714         } else {
 715             (void)outStream_writeObjectRef(env, out, string);
 716         }
 717 
 718     } END_WITH_LOCAL_REFS(env);
 719 
 720     jvmtiDeallocate(cstring);
 721 
 722     return JNI_TRUE;
 723 }
 724 
 725 static jboolean
 726 capabilities(PacketInputStream *in, PacketOutputStream *out)
 727 {
 728     jvmtiCapabilities caps;
 729     jvmtiError error;
 730 
 731     if (gdata->vmDead) {
 732         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 733         return JNI_TRUE;
 734     }
 735     error = jvmtiGetCapabilities(&caps);
 736     if (error != JVMTI_ERROR_NONE) {
 737         outStream_setError(out, map2jdwpError(error));
 738         return JNI_TRUE;
 739     }
 740 
 741     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_modification_events);
 742     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_access_events);
 743     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_bytecodes);
 744     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_synthetic_attribute);
 745     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_info);
 746     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_current_contended_monitor);
 747     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_monitor_info);
 748     return JNI_TRUE;
 749 }
 750 
 751 static jboolean
 752 capabilitiesNew(PacketInputStream *in, PacketOutputStream *out)
 753 {
 754     jvmtiCapabilities caps;
 755     jvmtiError error;
 756 
 757     if (gdata->vmDead) {
 758         outStream_setError(out, JDWP_ERROR(VM_DEAD));
 759         return JNI_TRUE;
 760     }
 761     error = jvmtiGetCapabilities(&caps);
 762     if (error != JVMTI_ERROR_NONE) {
 763         outStream_setError(out, map2jdwpError(error));
 764         return JNI_TRUE;
 765     }
 766 
 767     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_modification_events);
 768     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_field_access_events);
 769     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_bytecodes);
 770     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_synthetic_attribute);
 771     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_info);
 772     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_current_contended_monitor);
 773     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_monitor_info);
 774 
 775     /* new since JDWP version 1.4 */
 776     (void)outStream_writeBoolean(out, (jboolean)caps.can_redefine_classes);
 777     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE /* can_add_method */ );
 778     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE /* can_unrestrictedly_redefine_classes */ );
 779     /* 11: canPopFrames */
 780     (void)outStream_writeBoolean(out, (jboolean)caps.can_pop_frame);
 781     /* 12: canUseInstanceFilters */
 782     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
 783     /* 13: canGetSourceDebugExtension */
 784     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_source_debug_extension);
 785     /* 14: canRequestVMDeathEvent */
 786     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
 787     /* 15: canSetDefaultStratum */
 788     (void)outStream_writeBoolean(out, (jboolean)JNI_TRUE);
 789     /* 16: canGetInstanceInfo */
 790     (void)outStream_writeBoolean(out, (jboolean)caps.can_tag_objects);
 791     /* 17: canRequestMonitorEvents */
 792     (void)outStream_writeBoolean(out, (jboolean)caps.can_generate_monitor_events);
 793     /* 18: canGetMonitorFrameInfo */
 794     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_owned_monitor_stack_depth_info);
 795     /* remaining reserved */
 796     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 19 */
 797     /* 20 Can get constant pool information */
 798     (void)outStream_writeBoolean(out, (jboolean)caps.can_get_constant_pool);
 799     /* 21 Can force early return */
 800     (void)outStream_writeBoolean(out, (jboolean)caps.can_force_early_return);
 801 
 802     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 22 */
 803     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 23 */
 804     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 24 */
 805     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 25 */
 806     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 26 */
 807     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 27 */
 808     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 28 */
 809     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 29 */
 810     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 30 */
 811     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 31 */
 812     (void)outStream_writeBoolean(out, (jboolean)JNI_FALSE); /* 32 */
 813     return JNI_TRUE;
 814 }
 815 
 816 static int
 817 countPaths(char *string) {
 818     int cnt = 1; /* always have one */
 819     char *pos = string;
 820     char *ps;
 821 
 822     ps = gdata->property_path_separator;
 823     if ( ps == NULL ) {
 824         ps = ";";
 825     }
 826     while ((pos = strchr(pos, ps[0])) != NULL) {
 827         ++cnt;
 828         ++pos;
 829     }
 830     return cnt;
 831 }
 832 
 833 static void
 834 writePaths(PacketOutputStream *out, char *string) {
 835     char *pos;
 836     char *ps;
 837     char *buf;
 838     int   npaths;
 839     int   i;
 840 
 841     buf = jvmtiAllocate((int)strlen(string)+1);
 842 
 843     npaths = countPaths(string);
 844     (void)outStream_writeInt(out, npaths);
 845 
 846     ps = gdata->property_path_separator;
 847     if ( ps == NULL ) {
 848         ps = ";";
 849     }
 850 
 851     pos = string;
 852     for ( i = 0 ; i < npaths && pos != NULL; i++ ) {
 853         char *psPos;
 854         int   plen;
 855 
 856         psPos = strchr(pos, ps[0]);
 857         if ( psPos == NULL ) {
 858             plen = (int)strlen(pos);
 859         } else {
 860             plen = (int)(psPos-pos);
 861             psPos++;
 862         }
 863         (void)memcpy(buf, pos, plen);
 864         buf[plen] = 0;
 865         (void)outStream_writeString(out, buf);
 866         pos = psPos;
 867     }
 868 
 869     jvmtiDeallocate(buf);
 870 }
 871 
 872 static jboolean
 873 classPaths(PacketInputStream *in, PacketOutputStream *out)
 874 {
 875     char *ud;
 876     char *cp;
 877 
 878     ud = gdata->property_user_dir;
 879     if ( ud == NULL ) {
 880         ud = "";
 881     }
 882     cp = gdata->property_java_class_path;
 883     if ( cp == NULL ) {
 884         cp = "";
 885     }
 886     (void)outStream_writeString(out, ud);
 887     writePaths(out, cp);
 888     (void)outStream_writeInt(out, 0); // no bootclasspath
 889     return JNI_TRUE;
 890 }
 891 
 892 static jboolean
 893 disposeObjects(PacketInputStream *in, PacketOutputStream *out)
 894 {
 895     int i;
 896     int refCount;
 897     jlong id;
 898     int requestCount;
 899     JNIEnv *env;
 900 
 901     if (gdata->vmDead) {
 902         /* quietly ignore */
 903         return JNI_TRUE;
 904     }
 905 
 906     requestCount = inStream_readInt(in);
 907     if (inStream_error(in)) {
 908         return JNI_TRUE;
 909     }
 910 
 911     env = getEnv();
 912     for (i = 0; i < requestCount; i++) {
 913         id = inStream_readObjectID(in);
 914         refCount = inStream_readInt(in);
 915         if (inStream_error(in)) {
 916             return JNI_TRUE;
 917         }
 918         commonRef_releaseMultiple(env, id, refCount);
 919     }
 920 
 921     return JNI_TRUE;
 922 }
 923 
 924 static jboolean
 925 holdEvents(PacketInputStream *in, PacketOutputStream *out)
 926 {
 927     eventHelper_holdEvents();
 928     return JNI_TRUE;
 929 }
 930 
 931 static jboolean
 932 releaseEvents(PacketInputStream *in, PacketOutputStream *out)
 933 {
 934     eventHelper_releaseEvents();
 935     return JNI_TRUE;
 936 }
 937 
 938 void *VirtualMachine_Cmds[] = { (void *)22
 939     ,(void *)version
 940     ,(void *)classesForSignature
 941     ,(void *)allClasses
 942     ,(void *)getAllThreads
 943     ,(void *)topLevelThreadGroups
 944     ,(void *)dispose
 945     ,(void *)idSizes
 946     ,(void *)suspend
 947     ,(void *)resume
 948     ,(void *)doExit
 949     ,(void *)createString
 950     ,(void *)capabilities
 951     ,(void *)classPaths
 952     ,(void *)disposeObjects
 953     ,(void *)holdEvents
 954     ,(void *)releaseEvents
 955     ,(void *)capabilitiesNew
 956     ,(void *)redefineClasses
 957     ,(void *)setDefaultStratum
 958     ,(void *)allClassesWithGeneric
 959     ,(void *)instanceCounts
 960     ,(void *)allModules
 961 };