1 /*
   2  * Copyright (c) 2003, 2016, 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 /*
  27  * Copyright 2003 Wily Technology, Inc.
  28  */
  29 
  30 #include    <jni.h>
  31 #include    <jvm.h>
  32 #include    <jvmti.h>
  33 #include    <stdlib.h>
  34 #include    <string.h>
  35 #include    "JPLISAgent.h"
  36 #include    "JPLISAssert.h"
  37 #include    "Utilities.h"
  38 #include    "Reentrancy.h"
  39 #include    "JavaExceptions.h"
  40 
  41 #include    "EncodingSupport.h"
  42 #include    "FileSystemSupport.h"    /* For MAXPATHLEN & uintptr_t */
  43 
  44 #include    "sun_instrument_InstrumentationImpl.h"
  45 
  46 /*
  47  *  The JPLISAgent manages the initialization all of the Java programming language Agents.
  48  *  It also supports the native method bridge between the JPLIS and the JVMTI.
  49  *  It maintains a single JVMTI Env that all JPL agents share.
  50  *  It parses command line requests and creates individual Java agents.
  51  */
  52 
  53 
  54 /*
  55  *  private prototypes
  56  */
  57 
  58 /* Allocates an unformatted JPLIS agent data structure. Returns NULL if allocation fails. */
  59 JPLISAgent *
  60 allocateJPLISAgent(jvmtiEnv *       jvmtiEnv);
  61 
  62 /* Initializes an already-allocated JPLIS agent data structure. */
  63 JPLISInitializationError
  64 initializeJPLISAgent(   JPLISAgent *    agent,
  65                         JavaVM *        vm,
  66                         jvmtiEnv *      jvmtienv);
  67 /* De-allocates a JPLIS agent data structure. Only used in partial-failure cases at startup;
  68  * in normal usage the JPLIS agent lives forever
  69  */
  70 void
  71 deallocateJPLISAgent(   jvmtiEnv *      jvmtienv,
  72                         JPLISAgent *    agent);
  73 
  74 /* Does one-time work to interrogate the JVM about capabilities and cache the answers. */
  75 void
  76 checkCapabilities(JPLISAgent * agent);
  77 
  78 /* Takes the elements of the command string (agent class name and options string) and
  79  * create java strings for them.
  80  * Returns true if a classname was found. Makes no promises beyond the textual; says nothing about whether
  81  * the class exists or can be loaded.
  82  * If return value is true, sets outputClassname to a non-NULL local JNI reference.
  83  * If return value is true, sets outputOptionsString either to NULL or to a non-NULL local JNI reference.
  84  * If return value is false, neither output parameter is set.
  85  */
  86 jboolean
  87 commandStringIntoJavaStrings(  JNIEnv *        jnienv,
  88                                const char *    classname,
  89                                const char *    optionsString,
  90                                jstring *       outputClassname,
  91                                jstring *       outputOptionsString);
  92 
  93 /* Start one Java agent from the supplied parameters.
  94  * Most of the logic lives in a helper function that lives over in Java code--
  95  * we pass parameters out to Java and use our own Java helper to actually
  96  * load the agent and call the premain.
  97  * Returns true if the Java agent class is loaded and the premain/agentmain method completes
  98  * with no exceptions, false otherwise.
  99  */
 100 jboolean
 101 invokeJavaAgentMainMethod( JNIEnv *    jnienv,
 102                            jobject     instrumentationImpl,
 103                            jmethodID   agentMainMethod,
 104                            jstring     className,
 105                            jstring     optionsString);
 106 
 107 /* Once we have loaded the Java agent and called the premain,
 108  * we can release the copies we have been keeping of the command line
 109  * data (agent class name and option strings).
 110  */
 111 void
 112 deallocateCommandLineData(JPLISAgent * agent);
 113 
 114 /*
 115  *  Common support for various class list fetchers.
 116  */
 117 typedef jvmtiError (*ClassListFetcher)
 118     (   jvmtiEnv *  jvmtiEnv,
 119         jobject     classLoader,
 120         jint *      classCount,
 121         jclass **   classes);
 122 
 123 /* Fetcher that ignores the class loader parameter, and uses the JVMTI to get a list of all classes.
 124  * Returns a jvmtiError according to the underlying JVMTI service.
 125  */
 126 jvmtiError
 127 getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
 128                                         jobject     classLoader,
 129                                         jint *      classCount,
 130                                         jclass **   classes);
 131 
 132 /* Fetcher that uses the class loader parameter, and uses the JVMTI to get a list of all classes
 133  * for which the supplied loader is the initiating loader.
 134  * Returns a jvmtiError according to the underlying JVMTI service.
 135  */
 136 jvmtiError
 137 getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtiEnv,
 138                                         jobject     classLoader,
 139                                         jint *      classCount,
 140                                         jclass **   classes);
 141 
 142 /*
 143  * Common guts for two native methods, which are the same except for the policy for fetching
 144  * the list of classes.
 145  * Either returns a local JNI reference to an array of references to java.lang.Class.
 146  * Can throw, if it does will alter the JNIEnv with an outstanding exception.
 147  */
 148 jobjectArray
 149 commonGetClassList( JNIEnv *            jnienv,
 150                     JPLISAgent *        agent,
 151                     jobject             classLoader,
 152                     ClassListFetcher    fetcher);
 153 
 154 
 155 /*
 156  *  Misc. utilities.
 157  */
 158 
 159 /* Checked exception mapper used by the redefine classes implementation.
 160  * Allows ClassNotFoundException or UnmodifiableClassException; maps others
 161  * to InternalError. Can return NULL in an error case.
 162  */
 163 jthrowable
 164 redefineClassMapper(    JNIEnv *    jnienv,
 165                         jthrowable  throwableToMap);
 166 
 167 /* Turns a buffer of jclass * into a Java array whose elements are java.lang.Class.
 168  * Can throw, if it does will alter the JNIEnv with an outstanding exception.
 169  */
 170 jobjectArray
 171 getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount);
 172 
 173 
 174 JPLISEnvironment *
 175 getJPLISEnvironment(jvmtiEnv * jvmtienv) {
 176     JPLISEnvironment * environment  = NULL;
 177     jvmtiError         jvmtierror   = JVMTI_ERROR_NONE;
 178 
 179     jvmtierror = (*jvmtienv)->GetEnvironmentLocalStorage(
 180                                             jvmtienv,
 181                                             (void**)&environment);
 182     /* can be called from any phase */
 183     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 184 
 185     if (jvmtierror == JVMTI_ERROR_NONE) {
 186         jplis_assert(environment != NULL);
 187         jplis_assert(environment->mJVMTIEnv == jvmtienv);
 188     } else {
 189         environment = NULL;
 190     }
 191     return environment;
 192 }
 193 
 194 /*
 195  *  OnLoad processing code.
 196  */
 197 
 198 /*
 199  *  Creates a new JPLISAgent.
 200  *  Returns error if the agent cannot be created and initialized.
 201  *  The JPLISAgent* pointed to by agent_ptr is set to the new broker,
 202  *  or NULL if an error has occurred.
 203  */
 204 JPLISInitializationError
 205 createNewJPLISAgent(JavaVM * vm, JPLISAgent **agent_ptr) {
 206     JPLISInitializationError initerror       = JPLIS_INIT_ERROR_NONE;
 207     jvmtiEnv *               jvmtienv        = NULL;
 208     jint                     jnierror        = JNI_OK;
 209 
 210     *agent_ptr = NULL;
 211     jnierror = (*vm)->GetEnv(  vm,
 212                                (void **) &jvmtienv,
 213                                JVMTI_VERSION_1_1);
 214     if ( jnierror != JNI_OK ) {
 215         initerror = JPLIS_INIT_ERROR_CANNOT_CREATE_NATIVE_AGENT;
 216     } else {
 217         JPLISAgent * agent = allocateJPLISAgent(jvmtienv);
 218         if ( agent == NULL ) {
 219             initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
 220         } else {
 221             initerror = initializeJPLISAgent(  agent,
 222                                                vm,
 223                                                jvmtienv);
 224             if ( initerror == JPLIS_INIT_ERROR_NONE ) {
 225                 *agent_ptr = agent;
 226             } else {
 227                 deallocateJPLISAgent(jvmtienv, agent);
 228             }
 229         }
 230 
 231         /* don't leak envs */
 232         if ( initerror != JPLIS_INIT_ERROR_NONE ) {
 233             jvmtiError jvmtierror = (*jvmtienv)->DisposeEnvironment(jvmtienv);
 234             /* can be called from any phase */
 235             jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 236         }
 237     }
 238 
 239     return initerror;
 240 }
 241 
 242 /*
 243  *  Allocates a JPLISAgent. Returns NULL if it cannot be allocated
 244  */
 245 JPLISAgent *
 246 allocateJPLISAgent(jvmtiEnv * jvmtienv) {
 247   return (JPLISAgent *) allocate( jvmtienv,
 248                                     sizeof(JPLISAgent));
 249 }
 250 
 251 JPLISInitializationError
 252 initializeJPLISAgent(   JPLISAgent *    agent,
 253                         JavaVM *        vm,
 254                         jvmtiEnv *      jvmtienv) {
 255     jvmtiError      jvmtierror = JVMTI_ERROR_NONE;
 256     jvmtiPhase      phase;
 257 
 258     agent->mJVM                                      = vm;
 259     agent->mNormalEnvironment.mJVMTIEnv              = jvmtienv;
 260     agent->mNormalEnvironment.mAgent                 = agent;
 261     agent->mNormalEnvironment.mIsRetransformer       = JNI_FALSE;
 262     agent->mRetransformEnvironment.mJVMTIEnv         = NULL;        /* NULL until needed */
 263     agent->mRetransformEnvironment.mAgent            = agent;
 264     agent->mRetransformEnvironment.mIsRetransformer  = JNI_FALSE;   /* JNI_FALSE until mJVMTIEnv is set */
 265     agent->mAgentmainCaller                          = NULL;
 266     agent->mInstrumentationImpl                      = NULL;
 267     agent->mPremainCaller                            = NULL;
 268     agent->mTransform                                = NULL;
 269     agent->mRedefineAvailable                        = JNI_FALSE;   /* assume no for now */
 270     agent->mRedefineAdded                            = JNI_FALSE;
 271     agent->mNativeMethodPrefixAvailable              = JNI_FALSE;   /* assume no for now */
 272     agent->mNativeMethodPrefixAdded                  = JNI_FALSE;
 273     agent->mAgentClassName                           = NULL;
 274     agent->mOptionsString                            = NULL;
 275     agent->mJarfile                                  = NULL;
 276 
 277     /* make sure we can recover either handle in either direction.
 278      * the agent has a ref to the jvmti; make it mutual
 279      */
 280     jvmtierror = (*jvmtienv)->SetEnvironmentLocalStorage(
 281                                             jvmtienv,
 282                                             &(agent->mNormalEnvironment));
 283     /* can be called from any phase */
 284     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 285 
 286     /* check what capabilities are available */
 287     checkCapabilities(agent);
 288 
 289     /* check phase - if live phase then we don't need the VMInit event */
 290     jvmtierror = (*jvmtienv)->GetPhase(jvmtienv, &phase);
 291     /* can be called from any phase */
 292     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 293     if (phase == JVMTI_PHASE_LIVE) {
 294         return JPLIS_INIT_ERROR_NONE;
 295     }
 296 
 297     if (phase != JVMTI_PHASE_ONLOAD) {
 298         /* called too early or called too late; either way bail out */
 299         return JPLIS_INIT_ERROR_FAILURE;
 300     }
 301 
 302     /* now turn on the VMInit event */
 303     if ( jvmtierror == JVMTI_ERROR_NONE ) {
 304         jvmtiEventCallbacks callbacks;
 305         memset(&callbacks, 0, sizeof(callbacks));
 306         callbacks.VMInit = &eventHandlerVMInit;
 307 
 308         jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
 309                                                      &callbacks,
 310                                                      sizeof(callbacks));
 311         check_phase_ret_blob(jvmtierror, JPLIS_INIT_ERROR_FAILURE);
 312         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 313     }
 314 
 315     if ( jvmtierror == JVMTI_ERROR_NONE ) {
 316         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
 317                                                 jvmtienv,
 318                                                 JVMTI_ENABLE,
 319                                                 JVMTI_EVENT_VM_INIT,
 320                                                 NULL /* all threads */);
 321         check_phase_ret_blob(jvmtierror, JPLIS_INIT_ERROR_FAILURE);
 322         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 323     }
 324 
 325     return (jvmtierror == JVMTI_ERROR_NONE)? JPLIS_INIT_ERROR_NONE : JPLIS_INIT_ERROR_FAILURE;
 326 }
 327 
 328 void
 329 deallocateJPLISAgent(jvmtiEnv * jvmtienv, JPLISAgent * agent) {
 330     deallocate(jvmtienv, agent);
 331 }
 332 
 333 
 334 JPLISInitializationError
 335 recordCommandLineData(  JPLISAgent *    agent,
 336                         const char *    agentClassName,
 337                         const char *    optionsString ) {
 338     JPLISInitializationError    initerror   = JPLIS_INIT_ERROR_NONE;
 339     char *      ourCopyOfAgentClassName     = NULL;
 340     char *      ourCopyOfOptionsString      = NULL;
 341 
 342     /* if no actual params, bail out now */
 343     if ((agentClassName == NULL) || (*agentClassName == 0)) {
 344         initerror = JPLIS_INIT_ERROR_AGENT_CLASS_NOT_SPECIFIED;
 345     } else {
 346         ourCopyOfAgentClassName = allocate(jvmti(agent), strlen(agentClassName)+1);
 347         if (ourCopyOfAgentClassName == NULL) {
 348             initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
 349         } else {
 350             if (optionsString != NULL) {
 351                 ourCopyOfOptionsString = allocate(jvmti(agent), strlen(optionsString)+1);
 352                 if (ourCopyOfOptionsString == NULL) {
 353                     deallocate(jvmti(agent), ourCopyOfAgentClassName);
 354                     initerror = JPLIS_INIT_ERROR_ALLOCATION_FAILURE;
 355                 }
 356             }
 357         }
 358     }
 359 
 360     if (initerror == JPLIS_INIT_ERROR_NONE) {
 361         strcpy(ourCopyOfAgentClassName, agentClassName);
 362         if (optionsString != NULL) {
 363             strcpy(ourCopyOfOptionsString, optionsString);
 364         }
 365         agent->mAgentClassName = ourCopyOfAgentClassName;
 366         agent->mOptionsString = ourCopyOfOptionsString;
 367     }
 368 
 369     return initerror;
 370 }
 371 
 372 /*
 373  *  VMInit processing code.
 374  */
 375 
 376 
 377 /*
 378  * If this call fails, the JVM launch will ultimately be aborted,
 379  * so we don't have to be super-careful to clean up in partial failure
 380  * cases.
 381  */
 382 jboolean
 383 processJavaStart(   JPLISAgent *    agent,
 384                     JNIEnv *        jnienv) {
 385     jboolean    result;
 386 
 387     /*
 388      *  OK, Java is up now. We can start everything that needs Java.
 389      */
 390 
 391     /*
 392      *  First make our emergency fallback InternalError throwable.
 393      */
 394     result = initializeFallbackError(jnienv);
 395     jplis_assert(result);
 396 
 397     /*
 398      *  Now make the InstrumentationImpl instance.
 399      */
 400     if ( result ) {
 401         result = createInstrumentationImpl(jnienv, agent);
 402         jplis_assert(result);
 403     }
 404 
 405 
 406     /*
 407      *  Then turn off the VMInit handler and turn on the ClassFileLoadHook.
 408      *  This way it is on before anyone registers a transformer.
 409      */
 410     if ( result ) {
 411         result = setLivePhaseEventHandlers(agent);
 412         jplis_assert(result);
 413     }
 414 
 415     /*
 416      *  Load the Java agent, and call the premain.
 417      */
 418     if ( result ) {
 419         result = startJavaAgent(agent, jnienv,
 420                                 agent->mAgentClassName, agent->mOptionsString,
 421                                 agent->mPremainCaller);
 422     }
 423 
 424     /*
 425      * Finally surrender all of the tracking data that we don't need any more.
 426      * If something is wrong, skip it, we will be aborting the JVM anyway.
 427      */
 428     if ( result ) {
 429         deallocateCommandLineData(agent);
 430     }
 431 
 432     return result;
 433 }
 434 
 435 jboolean
 436 startJavaAgent( JPLISAgent *    agent,
 437                 JNIEnv *        jnienv,
 438                 const char *    classname,
 439                 const char *    optionsString,
 440                 jmethodID       agentMainMethod) {
 441     jboolean    success = JNI_FALSE;
 442     jstring classNameObject = NULL;
 443     jstring optionsStringObject = NULL;
 444 
 445     success = commandStringIntoJavaStrings(    jnienv,
 446                                                classname,
 447                                                optionsString,
 448                                                &classNameObject,
 449                                                &optionsStringObject);
 450 
 451     if (success) {
 452         success = invokeJavaAgentMainMethod(   jnienv,
 453                                                agent->mInstrumentationImpl,
 454                                                agentMainMethod,
 455                                                classNameObject,
 456                                                optionsStringObject);
 457     }
 458 
 459     return success;
 460 }
 461 
 462 void
 463 deallocateCommandLineData( JPLISAgent * agent) {
 464     deallocate(jvmti(agent), (void*)agent->mAgentClassName);
 465     deallocate(jvmti(agent), (void*)agent->mOptionsString);
 466 
 467     /* zero things out so it is easier to see what is going on */
 468     agent->mAgentClassName = NULL;
 469     agent->mOptionsString = NULL;
 470 }
 471 
 472 /*
 473  * Create the java.lang.instrument.Instrumentation instance
 474  * and access information for it (method IDs, etc)
 475  */
 476 jboolean
 477 createInstrumentationImpl( JNIEnv *        jnienv,
 478                            JPLISAgent *    agent) {
 479     jclass      implClass               = NULL;
 480     jboolean    errorOutstanding        = JNI_FALSE;
 481     jobject     resultImpl              = NULL;
 482     jmethodID   premainCallerMethodID   = NULL;
 483     jmethodID   agentmainCallerMethodID = NULL;
 484     jmethodID   transformMethodID       = NULL;
 485     jmethodID   constructorID           = NULL;
 486     jobject     localReference          = NULL;
 487 
 488     /* First find the class of our implementation */
 489     implClass = (*jnienv)->FindClass(   jnienv,
 490                                         JPLIS_INSTRUMENTIMPL_CLASSNAME);
 491     errorOutstanding = checkForAndClearThrowable(jnienv);
 492     errorOutstanding = errorOutstanding || (implClass == NULL);
 493     jplis_assert_msg(!errorOutstanding, "find class on InstrumentationImpl failed");
 494 
 495     if ( !errorOutstanding ) {
 496         constructorID = (*jnienv)->GetMethodID( jnienv,
 497                                                 implClass,
 498                                                 JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODNAME,
 499                                                 JPLIS_INSTRUMENTIMPL_CONSTRUCTOR_METHODSIGNATURE);
 500         errorOutstanding = checkForAndClearThrowable(jnienv);
 501         errorOutstanding = errorOutstanding || (constructorID == NULL);
 502         jplis_assert_msg(!errorOutstanding, "find constructor on InstrumentationImpl failed");
 503         }
 504 
 505     if ( !errorOutstanding ) {
 506         jlong   peerReferenceAsScalar = (jlong)(intptr_t) agent;
 507         localReference = (*jnienv)->NewObject(  jnienv,
 508                                                 implClass,
 509                                                 constructorID,
 510                                                 peerReferenceAsScalar,
 511                                                 agent->mRedefineAdded,
 512                                                 agent->mNativeMethodPrefixAdded);
 513         errorOutstanding = checkForAndClearThrowable(jnienv);
 514         errorOutstanding = errorOutstanding || (localReference == NULL);
 515         jplis_assert_msg(!errorOutstanding, "call constructor on InstrumentationImpl failed");
 516     }
 517 
 518     if ( !errorOutstanding ) {
 519         resultImpl = (*jnienv)->NewGlobalRef(jnienv, localReference);
 520         errorOutstanding = checkForAndClearThrowable(jnienv);
 521         jplis_assert_msg(!errorOutstanding, "copy local ref to global ref");
 522     }
 523 
 524     /* Now look up the method ID for the pre-main caller (we will need this more than once) */
 525     if ( !errorOutstanding ) {
 526         premainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
 527                                                         implClass,
 528                                                         JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODNAME,
 529                                                         JPLIS_INSTRUMENTIMPL_PREMAININVOKER_METHODSIGNATURE);
 530         errorOutstanding = checkForAndClearThrowable(jnienv);
 531         errorOutstanding = errorOutstanding || (premainCallerMethodID == NULL);
 532         jplis_assert_msg(!errorOutstanding, "can't find premain invoker methodID");
 533     }
 534 
 535     /* Now look up the method ID for the agent-main caller */
 536     if ( !errorOutstanding ) {
 537         agentmainCallerMethodID = (*jnienv)->GetMethodID( jnienv,
 538                                                           implClass,
 539                                                           JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODNAME,
 540                                                           JPLIS_INSTRUMENTIMPL_AGENTMAININVOKER_METHODSIGNATURE);
 541         errorOutstanding = checkForAndClearThrowable(jnienv);
 542         errorOutstanding = errorOutstanding || (agentmainCallerMethodID == NULL);
 543         jplis_assert_msg(!errorOutstanding, "can't find agentmain invoker methodID");
 544     }
 545 
 546     /* Now look up the method ID for the transform method (we will need this constantly) */
 547     if ( !errorOutstanding ) {
 548         transformMethodID = (*jnienv)->GetMethodID( jnienv,
 549                                                     implClass,
 550                                                     JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODNAME,
 551                                                     JPLIS_INSTRUMENTIMPL_TRANSFORM_METHODSIGNATURE);
 552         errorOutstanding = checkForAndClearThrowable(jnienv);
 553         errorOutstanding = errorOutstanding || (transformMethodID == NULL);
 554         jplis_assert_msg(!errorOutstanding, "can't find transform methodID");
 555     }
 556 
 557     if ( !errorOutstanding ) {
 558         agent->mInstrumentationImpl = resultImpl;
 559         agent->mPremainCaller       = premainCallerMethodID;
 560         agent->mAgentmainCaller     = agentmainCallerMethodID;
 561         agent->mTransform           = transformMethodID;
 562     }
 563 
 564     return !errorOutstanding;
 565 }
 566 
 567 jboolean
 568 commandStringIntoJavaStrings(  JNIEnv *        jnienv,
 569                                const char *    classname,
 570                                const char *    optionsString,
 571                                jstring *       outputClassname,
 572                                jstring *       outputOptionsString) {
 573     jstring     classnameJavaString     = NULL;
 574     jstring     optionsJavaString       = NULL;
 575     jboolean    errorOutstanding        = JNI_TRUE;
 576 
 577     classnameJavaString = (*jnienv)->NewStringUTF(jnienv, classname);
 578     errorOutstanding = checkForAndClearThrowable(jnienv);
 579     jplis_assert_msg(!errorOutstanding, "can't create class name java string");
 580 
 581     if ( !errorOutstanding ) {
 582         if ( optionsString != NULL) {
 583             optionsJavaString = (*jnienv)->NewStringUTF(jnienv, optionsString);
 584             errorOutstanding = checkForAndClearThrowable(jnienv);
 585             jplis_assert_msg(!errorOutstanding, "can't create options java string");
 586         }
 587 
 588         if ( !errorOutstanding ) {
 589             *outputClassname        = classnameJavaString;
 590             *outputOptionsString    = optionsJavaString;
 591         }
 592     }
 593 
 594     return !errorOutstanding;
 595 }
 596 
 597 
 598 jboolean
 599 invokeJavaAgentMainMethod( JNIEnv *    jnienv,
 600                            jobject     instrumentationImpl,
 601                            jmethodID   mainCallingMethod,
 602                            jstring     className,
 603                            jstring     optionsString) {
 604     jboolean errorOutstanding = JNI_FALSE;
 605 
 606     jplis_assert(mainCallingMethod != NULL);
 607     if ( mainCallingMethod != NULL ) {
 608         (*jnienv)->CallVoidMethod(  jnienv,
 609                                     instrumentationImpl,
 610                                     mainCallingMethod,
 611                                     className,
 612                                     optionsString);
 613         errorOutstanding = checkForThrowable(jnienv);
 614         if ( errorOutstanding ) {
 615             logThrowable(jnienv);
 616         }
 617         checkForAndClearThrowable(jnienv);
 618     }
 619     return !errorOutstanding;
 620 }
 621 
 622 jboolean
 623 setLivePhaseEventHandlers(  JPLISAgent * agent) {
 624     jvmtiEventCallbacks callbacks;
 625     jvmtiEnv *          jvmtienv = jvmti(agent);
 626     jvmtiError          jvmtierror;
 627 
 628     /* first swap out the handlers (switch from the VMInit handler, which we do not need,
 629      * to the ClassFileLoadHook handler, which is what the agents need from now on)
 630      */
 631     memset(&callbacks, 0, sizeof(callbacks));
 632     callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;
 633 
 634     jvmtierror = (*jvmtienv)->SetEventCallbacks( jvmtienv,
 635                                                  &callbacks,
 636                                                  sizeof(callbacks));
 637     check_phase_ret_false(jvmtierror);
 638     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 639 
 640 
 641     if ( jvmtierror == JVMTI_ERROR_NONE ) {
 642         /* turn off VMInit */
 643         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
 644                                                     jvmtienv,
 645                                                     JVMTI_DISABLE,
 646                                                     JVMTI_EVENT_VM_INIT,
 647                                                     NULL /* all threads */);
 648         check_phase_ret_false(jvmtierror);
 649         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 650     }
 651 
 652     if ( jvmtierror == JVMTI_ERROR_NONE ) {
 653         /* turn on ClassFileLoadHook */
 654         jvmtierror = (*jvmtienv)->SetEventNotificationMode(
 655                                                     jvmtienv,
 656                                                     JVMTI_ENABLE,
 657                                                     JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
 658                                                     NULL /* all threads */);
 659         check_phase_ret_false(jvmtierror);
 660         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 661     }
 662 
 663     return (jvmtierror == JVMTI_ERROR_NONE);
 664 }
 665 
 666 /**
 667  *  Check if the can_redefine_classes capability is available.
 668  */
 669 void
 670 checkCapabilities(JPLISAgent * agent) {
 671     jvmtiEnv *          jvmtienv = jvmti(agent);
 672     jvmtiCapabilities   potentialCapabilities;
 673     jvmtiError          jvmtierror;
 674 
 675     memset(&potentialCapabilities, 0, sizeof(potentialCapabilities));
 676 
 677     jvmtierror = (*jvmtienv)->GetPotentialCapabilities(jvmtienv, &potentialCapabilities);
 678     check_phase_ret(jvmtierror);
 679     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 680 
 681     if ( jvmtierror == JVMTI_ERROR_NONE ) {
 682         if ( potentialCapabilities.can_redefine_classes == 1 ) {
 683             agent->mRedefineAvailable = JNI_TRUE;
 684         }
 685         if ( potentialCapabilities.can_set_native_method_prefix == 1 ) {
 686             agent->mNativeMethodPrefixAvailable = JNI_TRUE;
 687         }
 688     }
 689 }
 690 
 691 /**
 692  * Enable native method prefix in one JVM TI environment
 693  */
 694 void
 695 enableNativeMethodPrefixCapability(jvmtiEnv * jvmtienv) {
 696     jvmtiCapabilities   desiredCapabilities;
 697     jvmtiError          jvmtierror;
 698 
 699         jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
 700         /* can be called from any phase */
 701         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 702         desiredCapabilities.can_set_native_method_prefix = 1;
 703         jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
 704         check_phase_ret(jvmtierror);
 705         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 706 }
 707 
 708 
 709 /**
 710  * Add the can_set_native_method_prefix capability
 711  */
 712 void
 713 addNativeMethodPrefixCapability(JPLISAgent * agent) {
 714     if (agent->mNativeMethodPrefixAvailable && !agent->mNativeMethodPrefixAdded) {
 715         jvmtiEnv * jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
 716         enableNativeMethodPrefixCapability(jvmtienv);
 717 
 718         jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
 719         if (jvmtienv != NULL) {
 720             enableNativeMethodPrefixCapability(jvmtienv);
 721         }
 722         agent->mNativeMethodPrefixAdded = JNI_TRUE;
 723     }
 724 }
 725 
 726 /**
 727  * Add the can_maintain_original_method_order capability (for testing)
 728  */
 729 void
 730 addOriginalMethodOrderCapability(JPLISAgent * agent) {
 731     jvmtiEnv *          jvmtienv = jvmti(agent);
 732     jvmtiCapabilities   desiredCapabilities;
 733     jvmtiError          jvmtierror;
 734 
 735     jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
 736     /* can be called from any phase */
 737     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 738     desiredCapabilities.can_maintain_original_method_order = 1;
 739     jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
 740     check_phase_ret(jvmtierror);
 741     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 742 }
 743 
 744 /**
 745  * Add the can_redefine_classes capability
 746  */
 747 void
 748 addRedefineClassesCapability(JPLISAgent * agent) {
 749     jvmtiEnv *          jvmtienv = jvmti(agent);
 750     jvmtiCapabilities   desiredCapabilities;
 751     jvmtiError          jvmtierror;
 752 
 753     if (agent->mRedefineAvailable && !agent->mRedefineAdded) {
 754         jvmtierror = (*jvmtienv)->GetCapabilities(jvmtienv, &desiredCapabilities);
 755         /* can be called from any phase */
 756         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
 757         desiredCapabilities.can_redefine_classes = 1;
 758         jvmtierror = (*jvmtienv)->AddCapabilities(jvmtienv, &desiredCapabilities);
 759         check_phase_ret(jvmtierror);
 760 
 761         /*
 762          * With mixed premain/agentmain agents then it's possible that the
 763          * capability was potentially available in the onload phase but
 764          * subsequently unavailable in the live phase.
 765          */
 766         jplis_assert(jvmtierror == JVMTI_ERROR_NONE ||
 767                      jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
 768         if (jvmtierror == JVMTI_ERROR_NONE) {
 769             agent->mRedefineAdded = JNI_TRUE;
 770         }
 771     }
 772 }
 773 
 774 static jobject
 775 getModuleObject(jvmtiEnv*               jvmti,
 776                 jobject                 loaderObject,
 777                 const char*             cname) {
 778     jvmtiError err = JVMTI_ERROR_NONE;
 779     jobject moduleObject = NULL;
 780 
 781     /* find last slash in the class name */
 782     char* last_slash = (cname == NULL) ? NULL : strrchr(cname, '/');
 783     int len = (last_slash == NULL) ? 0 : (int)(last_slash - cname);
 784     char* pkg_name_buf = (char*)malloc(len + 1);
 785 
 786     jplis_assert_msg(pkg_name_buf != NULL, "OOM error in native tmp buffer allocation");
 787     if (last_slash != NULL) {
 788         strncpy(pkg_name_buf, cname, len);
 789     }
 790     pkg_name_buf[len] = '\0';
 791 
 792     err = (*jvmti)->GetNamedModule(jvmti, loaderObject, pkg_name_buf, &moduleObject);
 793     jplis_assert_msg(err == JVMTI_ERROR_NONE, "error in the JVMTI GetNamedModule");
 794 
 795     free((void*)pkg_name_buf);
 796     return moduleObject;
 797 }
 798 
 799 /*
 800  *  Support for the JVMTI callbacks
 801  */
 802 
 803 void
 804 transformClassFile(             JPLISAgent *            agent,
 805                                 JNIEnv *                jnienv,
 806                                 jobject                 loaderObject,
 807                                 const char*             name,
 808                                 jclass                  classBeingRedefined,
 809                                 jobject                 protectionDomain,
 810                                 jint                    class_data_len,
 811                                 const unsigned char*    class_data,
 812                                 jint*                   new_class_data_len,
 813                                 unsigned char**         new_class_data,
 814                                 jboolean                is_retransformer) {
 815     jboolean        errorOutstanding        = JNI_FALSE;
 816     jstring         classNameStringObject   = NULL;
 817     jarray          classFileBufferObject   = NULL;
 818     jarray          transformedBufferObject = NULL;
 819     jsize           transformedBufferSize   = 0;
 820     unsigned char * resultBuffer            = NULL;
 821     jboolean        shouldRun               = JNI_FALSE;
 822 
 823     /* only do this if we aren't already in the middle of processing a class on this thread */
 824     shouldRun = tryToAcquireReentrancyToken(
 825                                 jvmti(agent),
 826                                 NULL);  /* this thread */
 827 
 828     if ( shouldRun ) {
 829         /* first marshall all the parameters */
 830         classNameStringObject = (*jnienv)->NewStringUTF(jnienv,
 831                                                         name);
 832         errorOutstanding = checkForAndClearThrowable(jnienv);
 833         jplis_assert_msg(!errorOutstanding, "can't create name string");
 834 
 835         if ( !errorOutstanding ) {
 836             classFileBufferObject = (*jnienv)->NewByteArray(jnienv,
 837                                                             class_data_len);
 838             errorOutstanding = checkForAndClearThrowable(jnienv);
 839             jplis_assert_msg(!errorOutstanding, "can't create byte array");
 840         }
 841 
 842         if ( !errorOutstanding ) {
 843             jbyte * typedBuffer = (jbyte *) class_data; /* nasty cast, dumb JNI interface, const missing */
 844                                                         /* The sign cast is safe. The const cast is dumb. */
 845             (*jnienv)->SetByteArrayRegion(  jnienv,
 846                                             classFileBufferObject,
 847                                             0,
 848                                             class_data_len,
 849                                             typedBuffer);
 850             errorOutstanding = checkForAndClearThrowable(jnienv);
 851             jplis_assert_msg(!errorOutstanding, "can't set byte array region");
 852         }
 853 
 854         /*  now call the JPL agents to do the transforming */
 855         /*  potential future optimization: may want to skip this if there are none */
 856         if ( !errorOutstanding ) {
 857             jobject moduleObject = NULL;
 858 
 859             if (classBeingRedefined == NULL) {
 860                 moduleObject = getModuleObject(jvmti(agent), loaderObject, name);
 861             } else {
 862                 // Redefine or retransform, InstrumentationImpl.transform() will use
 863                 // classBeingRedefined.getModule() to get the module.
 864             }
 865             jplis_assert(agent->mInstrumentationImpl != NULL);
 866             jplis_assert(agent->mTransform != NULL);
 867             transformedBufferObject = (*jnienv)->CallObjectMethod(
 868                                                 jnienv,
 869                                                 agent->mInstrumentationImpl,
 870                                                 agent->mTransform,
 871                                                 moduleObject,
 872                                                 loaderObject,
 873                                                 classNameStringObject,
 874                                                 classBeingRedefined,
 875                                                 protectionDomain,
 876                                                 classFileBufferObject,
 877                                                 is_retransformer);
 878             errorOutstanding = checkForAndClearThrowable(jnienv);
 879             jplis_assert_msg(!errorOutstanding, "transform method call failed");
 880         }
 881 
 882         /* Finally, unmarshall the parameters (if someone touched the buffer, tell the JVM) */
 883         if ( !errorOutstanding ) {
 884             if ( transformedBufferObject != NULL ) {
 885                 transformedBufferSize = (*jnienv)->GetArrayLength(  jnienv,
 886                                                                     transformedBufferObject);
 887                 errorOutstanding = checkForAndClearThrowable(jnienv);
 888                 jplis_assert_msg(!errorOutstanding, "can't get array length");
 889 
 890                 if ( !errorOutstanding ) {
 891                     /* allocate the response buffer with the JVMTI allocate call.
 892                      *  This is what the JVMTI spec says to do for Class File Load hook responses
 893                      */
 894                     jvmtiError  allocError = (*(jvmti(agent)))->Allocate(jvmti(agent),
 895                                                                              transformedBufferSize,
 896                                                                              &resultBuffer);
 897                     errorOutstanding = (allocError != JVMTI_ERROR_NONE);
 898                     jplis_assert_msg(!errorOutstanding, "can't allocate result buffer");
 899                 }
 900 
 901                 if ( !errorOutstanding ) {
 902                     (*jnienv)->GetByteArrayRegion(  jnienv,
 903                                                     transformedBufferObject,
 904                                                     0,
 905                                                     transformedBufferSize,
 906                                                     (jbyte *) resultBuffer);
 907                     errorOutstanding = checkForAndClearThrowable(jnienv);
 908                     jplis_assert_msg(!errorOutstanding, "can't get byte array region");
 909 
 910                     /* in this case, we will not return the buffer to the JVMTI,
 911                      * so we need to deallocate it ourselves
 912                      */
 913                     if ( errorOutstanding ) {
 914                         deallocate( jvmti(agent),
 915                                    (void*)resultBuffer);
 916                     }
 917                 }
 918 
 919                 if ( !errorOutstanding ) {
 920                     *new_class_data_len = (transformedBufferSize);
 921                     *new_class_data     = resultBuffer;
 922                 }
 923             }
 924         }
 925 
 926         /* release the token */
 927         releaseReentrancyToken( jvmti(agent),
 928                                 NULL);      /* this thread */
 929 
 930     }
 931 
 932     return;
 933 }
 934 
 935 /*
 936  *  Misc. internal utilities.
 937  */
 938 
 939 /*
 940  *  The only checked exceptions we can throw are ClassNotFoundException and
 941  *  UnmodifiableClassException. All others map to InternalError.
 942  */
 943 jthrowable
 944 redefineClassMapper(    JNIEnv *    jnienv,
 945                         jthrowable  throwableToMap) {
 946     jthrowable  mappedThrowable = NULL;
 947 
 948     jplis_assert(isSafeForJNICalls(jnienv));
 949     jplis_assert(!isUnchecked(jnienv, throwableToMap));
 950 
 951     if ( isInstanceofClassName( jnienv,
 952                                 throwableToMap,
 953                                 "java/lang/ClassNotFoundException") ) {
 954         mappedThrowable = throwableToMap;
 955     } else {
 956         if ( isInstanceofClassName( jnienv,
 957                                 throwableToMap,
 958                                 "java/lang/instrument/UnmodifiableClassException")) {
 959             mappedThrowable = throwableToMap;
 960         } else {
 961             jstring message = NULL;
 962 
 963             message = getMessageFromThrowable(jnienv, throwableToMap);
 964             mappedThrowable = createInternalError(jnienv, message);
 965         }
 966     }
 967 
 968     jplis_assert(isSafeForJNICalls(jnienv));
 969     return mappedThrowable;
 970 }
 971 
 972 jobjectArray
 973 getObjectArrayFromClasses(JNIEnv* jnienv, jclass* classes, jint classCount) {
 974     jclass          classArrayClass = NULL;
 975     jobjectArray    localArray      = NULL;
 976     jint            classIndex      = 0;
 977     jboolean        errorOccurred   = JNI_FALSE;
 978 
 979     /* get the class array class */
 980     classArrayClass = (*jnienv)->FindClass(jnienv, "java/lang/Class");
 981     errorOccurred = checkForThrowable(jnienv);
 982 
 983     if (!errorOccurred) {
 984         jplis_assert_msg(classArrayClass != NULL, "FindClass returned null class");
 985 
 986         /* create the array for the classes */
 987         localArray = (*jnienv)->NewObjectArray(jnienv, classCount, classArrayClass, NULL);
 988         errorOccurred = checkForThrowable(jnienv);
 989 
 990         if (!errorOccurred) {
 991             jplis_assert_msg(localArray != NULL, "NewObjectArray returned null array");
 992 
 993             /* now copy refs to all the classes and put them into the array */
 994             for (classIndex = 0; classIndex < classCount; classIndex++) {
 995                 /* put class into array */
 996                 (*jnienv)->SetObjectArrayElement(jnienv, localArray, classIndex, classes[classIndex]);
 997                 errorOccurred = checkForThrowable(jnienv);
 998 
 999                 if (errorOccurred) {
1000                     localArray = NULL;
1001                     break;
1002                 }
1003             }
1004         }
1005     }
1006 
1007     return localArray;
1008 }
1009 
1010 
1011 /* Return the environment with the retransformation capability.
1012  * Create it if it doesn't exist.
1013  * Return NULL if it can't be created.
1014  */
1015 jvmtiEnv *
1016 retransformableEnvironment(JPLISAgent * agent) {
1017     jvmtiEnv *          retransformerEnv     = NULL;
1018     jint                jnierror             = JNI_OK;
1019     jvmtiCapabilities   desiredCapabilities;
1020     jvmtiEventCallbacks callbacks;
1021     jvmtiError          jvmtierror;
1022 
1023     if (agent->mRetransformEnvironment.mJVMTIEnv != NULL) {
1024         return agent->mRetransformEnvironment.mJVMTIEnv;
1025     }
1026     jnierror = (*agent->mJVM)->GetEnv(  agent->mJVM,
1027                                (void **) &retransformerEnv,
1028                                JVMTI_VERSION_1_1);
1029     if ( jnierror != JNI_OK ) {
1030         return NULL;
1031     }
1032     jvmtierror = (*retransformerEnv)->GetCapabilities(retransformerEnv, &desiredCapabilities);
1033     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1034     desiredCapabilities.can_retransform_classes = 1;
1035     if (agent->mNativeMethodPrefixAdded) {
1036         desiredCapabilities.can_set_native_method_prefix = 1;
1037     }
1038 
1039     jvmtierror = (*retransformerEnv)->AddCapabilities(retransformerEnv, &desiredCapabilities);
1040     if (jvmtierror != JVMTI_ERROR_NONE) {
1041          /* cannot get the capability, dispose of the retransforming environment */
1042         jvmtierror = (*retransformerEnv)->DisposeEnvironment(retransformerEnv);
1043         jplis_assert(jvmtierror == JVMTI_ERROR_NOT_AVAILABLE);
1044         return NULL;
1045     }
1046     memset(&callbacks, 0, sizeof(callbacks));
1047     callbacks.ClassFileLoadHook = &eventHandlerClassFileLoadHook;
1048 
1049     jvmtierror = (*retransformerEnv)->SetEventCallbacks(retransformerEnv,
1050                                                         &callbacks,
1051                                                         sizeof(callbacks));
1052     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1053     if (jvmtierror == JVMTI_ERROR_NONE) {
1054         // install the retransforming environment
1055         agent->mRetransformEnvironment.mJVMTIEnv = retransformerEnv;
1056         agent->mRetransformEnvironment.mIsRetransformer = JNI_TRUE;
1057 
1058         // Make it for ClassFileLoadHook handling
1059         jvmtierror = (*retransformerEnv)->SetEnvironmentLocalStorage(
1060                                                        retransformerEnv,
1061                                                        &(agent->mRetransformEnvironment));
1062         jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1063         if (jvmtierror == JVMTI_ERROR_NONE) {
1064             return retransformerEnv;
1065         }
1066     }
1067     return NULL;
1068 }
1069 
1070 
1071 /*
1072  *  Underpinnings for native methods
1073  */
1074 
1075 jboolean
1076 isModifiableClass(JNIEnv * jnienv, JPLISAgent * agent, jclass clazz) {
1077     jvmtiEnv *          jvmtienv = jvmti(agent);
1078     jvmtiError          jvmtierror;
1079     jboolean            is_modifiable = JNI_FALSE;
1080 
1081     jvmtierror = (*jvmtienv)->IsModifiableClass( jvmtienv,
1082                                                  clazz,
1083                                                  &is_modifiable);
1084     check_phase_ret_false(jvmtierror);
1085     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1086 
1087     return is_modifiable;
1088 }
1089 
1090 jboolean
1091 isRetransformClassesSupported(JNIEnv * jnienv, JPLISAgent * agent) {
1092     return agent->mRetransformEnvironment.mIsRetransformer;
1093 }
1094 
1095 void
1096 setHasRetransformableTransformers(JNIEnv * jnienv, JPLISAgent * agent, jboolean has) {
1097     jvmtiEnv *          retransformerEnv     = retransformableEnvironment(agent);
1098     jvmtiError          jvmtierror;
1099 
1100     jplis_assert(retransformerEnv != NULL);
1101     jvmtierror = (*retransformerEnv)->SetEventNotificationMode(
1102                                                     retransformerEnv,
1103                                                     has? JVMTI_ENABLE : JVMTI_DISABLE,
1104                                                     JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
1105                                                     NULL /* all threads */);
1106     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1107 }
1108 
1109 void
1110 retransformClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classes) {
1111     jvmtiEnv *  retransformerEnv     = retransformableEnvironment(agent);
1112     jboolean    errorOccurred        = JNI_FALSE;
1113     jvmtiError  errorCode            = JVMTI_ERROR_NONE;
1114     jsize       numClasses           = 0;
1115     jclass *    classArray           = NULL;
1116 
1117     /* This is supposed to be checked by caller, but just to be sure */
1118     if (retransformerEnv == NULL) {
1119         jplis_assert(retransformerEnv != NULL);
1120         errorOccurred = JNI_TRUE;
1121         errorCode = JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
1122     }
1123 
1124     /* This was supposed to be checked by caller too */
1125     if (!errorOccurred && classes == NULL) {
1126         jplis_assert(classes != NULL);
1127         errorOccurred = JNI_TRUE;
1128         errorCode = JVMTI_ERROR_NULL_POINTER;
1129     }
1130 
1131     if (!errorOccurred) {
1132         numClasses = (*jnienv)->GetArrayLength(jnienv, classes);
1133         errorOccurred = checkForThrowable(jnienv);
1134         jplis_assert(!errorOccurred);
1135 
1136         if (!errorOccurred && numClasses == 0) {
1137             jplis_assert(numClasses != 0);
1138             errorOccurred = JNI_TRUE;
1139             errorCode = JVMTI_ERROR_NULL_POINTER;
1140         }
1141     }
1142 
1143     if (!errorOccurred) {
1144         classArray = (jclass *) allocate(retransformerEnv,
1145                                          numClasses * sizeof(jclass));
1146         errorOccurred = (classArray == NULL);
1147         jplis_assert(!errorOccurred);
1148         if (errorOccurred) {
1149             errorCode = JVMTI_ERROR_OUT_OF_MEMORY;
1150         }
1151     }
1152 
1153     if (!errorOccurred) {
1154         jint index;
1155         for (index = 0; index < numClasses; index++) {
1156             classArray[index] = (*jnienv)->GetObjectArrayElement(jnienv, classes, index);
1157             errorOccurred = checkForThrowable(jnienv);
1158             jplis_assert(!errorOccurred);
1159             if (errorOccurred) {
1160                 break;
1161             }
1162 
1163             if (classArray[index] == NULL) {
1164                 jplis_assert(classArray[index] != NULL);
1165                 errorOccurred = JNI_TRUE;
1166                 errorCode = JVMTI_ERROR_NULL_POINTER;
1167                 break;
1168             }
1169         }
1170     }
1171 
1172     if (!errorOccurred) {
1173         errorCode = (*retransformerEnv)->RetransformClasses(retransformerEnv,
1174                                                             numClasses, classArray);
1175         errorOccurred = (errorCode != JVMTI_ERROR_NONE);
1176     }
1177 
1178     /* Give back the buffer if we allocated it.  Throw any exceptions after.
1179      */
1180     if (classArray != NULL) {
1181         deallocate(retransformerEnv, (void*)classArray);
1182     }
1183 
1184     if (errorCode != JVMTI_ERROR_NONE) {
1185         createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
1186     }
1187 
1188     mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
1189 }
1190 
1191 /*
1192  *  Java code must not call this with a null list or a zero-length list.
1193  */
1194 void
1195 redefineClasses(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray classDefinitions) {
1196     jvmtiEnv*   jvmtienv                        = jvmti(agent);
1197     jboolean    errorOccurred                   = JNI_FALSE;
1198     jclass      classDefClass                   = NULL;
1199     jmethodID   getDefinitionClassMethodID      = NULL;
1200     jmethodID   getDefinitionClassFileMethodID  = NULL;
1201     jvmtiClassDefinition* classDefs             = NULL;
1202     jbyteArray* targetFiles                     = NULL;
1203     jsize       numDefs                         = 0;
1204 
1205     jplis_assert(classDefinitions != NULL);
1206 
1207     numDefs = (*jnienv)->GetArrayLength(jnienv, classDefinitions);
1208     errorOccurred = checkForThrowable(jnienv);
1209     jplis_assert(!errorOccurred);
1210 
1211     if (!errorOccurred) {
1212         jplis_assert(numDefs > 0);
1213         /* get method IDs for methods to call on class definitions */
1214         classDefClass = (*jnienv)->FindClass(jnienv, "java/lang/instrument/ClassDefinition");
1215         errorOccurred = checkForThrowable(jnienv);
1216         jplis_assert(!errorOccurred);
1217     }
1218 
1219     if (!errorOccurred) {
1220         getDefinitionClassMethodID = (*jnienv)->GetMethodID(    jnienv,
1221                                                 classDefClass,
1222                                                 "getDefinitionClass",
1223                                                 "()Ljava/lang/Class;");
1224         errorOccurred = checkForThrowable(jnienv);
1225         jplis_assert(!errorOccurred);
1226     }
1227 
1228     if (!errorOccurred) {
1229         getDefinitionClassFileMethodID = (*jnienv)->GetMethodID(    jnienv,
1230                                                     classDefClass,
1231                                                     "getDefinitionClassFile",
1232                                                     "()[B");
1233         errorOccurred = checkForThrowable(jnienv);
1234         jplis_assert(!errorOccurred);
1235     }
1236 
1237     if (!errorOccurred) {
1238         classDefs = (jvmtiClassDefinition *) allocate(
1239                                                 jvmtienv,
1240                                                 numDefs * sizeof(jvmtiClassDefinition));
1241         errorOccurred = (classDefs == NULL);
1242         jplis_assert(!errorOccurred);
1243         if ( errorOccurred ) {
1244             createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
1245         }
1246 
1247         else {
1248             /*
1249              * We have to save the targetFile values that we compute so
1250              * that we can release the class_bytes arrays that are
1251              * returned by GetByteArrayElements(). In case of a JNI
1252              * error, we can't (easily) recompute the targetFile values
1253              * and we still want to free any memory we allocated.
1254              */
1255             targetFiles = (jbyteArray *) allocate(jvmtienv,
1256                                                   numDefs * sizeof(jbyteArray));
1257             errorOccurred = (targetFiles == NULL);
1258             jplis_assert(!errorOccurred);
1259             if ( errorOccurred ) {
1260                 deallocate(jvmtienv, (void*)classDefs);
1261                 createAndThrowThrowableFromJVMTIErrorCode(jnienv,
1262                     JVMTI_ERROR_OUT_OF_MEMORY);
1263             }
1264             else {
1265                 jint i, j;
1266 
1267                 // clear classDefs so we can correctly free memory during errors
1268                 memset(classDefs, 0, numDefs * sizeof(jvmtiClassDefinition));
1269 
1270                 for (i = 0; i < numDefs; i++) {
1271                     jclass      classDef    = NULL;
1272 
1273                     classDef = (*jnienv)->GetObjectArrayElement(jnienv, classDefinitions, i);
1274                     errorOccurred = checkForThrowable(jnienv);
1275                     jplis_assert(!errorOccurred);
1276                     if (errorOccurred) {
1277                         break;
1278                     }
1279 
1280                     classDefs[i].klass = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassMethodID);
1281                     errorOccurred = checkForThrowable(jnienv);
1282                     jplis_assert(!errorOccurred);
1283                     if (errorOccurred) {
1284                         break;
1285                     }
1286 
1287                     targetFiles[i] = (*jnienv)->CallObjectMethod(jnienv, classDef, getDefinitionClassFileMethodID);
1288                     errorOccurred = checkForThrowable(jnienv);
1289                     jplis_assert(!errorOccurred);
1290                     if (errorOccurred) {
1291                         break;
1292                     }
1293 
1294                     classDefs[i].class_byte_count = (*jnienv)->GetArrayLength(jnienv, targetFiles[i]);
1295                     errorOccurred = checkForThrowable(jnienv);
1296                     jplis_assert(!errorOccurred);
1297                     if (errorOccurred) {
1298                         break;
1299                     }
1300 
1301                     /*
1302                      * Allocate class_bytes last so we don't have to free
1303                      * memory on a partial row error.
1304                      */
1305                     classDefs[i].class_bytes = (unsigned char*)(*jnienv)->GetByteArrayElements(jnienv, targetFiles[i], NULL);
1306                     errorOccurred = checkForThrowable(jnienv);
1307                     jplis_assert(!errorOccurred);
1308                     if (errorOccurred) {
1309                         break;
1310                     }
1311                 }
1312 
1313                 if (!errorOccurred) {
1314                     jvmtiError  errorCode = JVMTI_ERROR_NONE;
1315                     errorCode = (*jvmtienv)->RedefineClasses(jvmtienv, numDefs, classDefs);
1316                     if (errorCode == JVMTI_ERROR_WRONG_PHASE) {
1317                         /* insulate caller from the wrong phase error */
1318                         errorCode = JVMTI_ERROR_NONE;
1319                     } else {
1320                         errorOccurred = (errorCode != JVMTI_ERROR_NONE);
1321                         if ( errorOccurred ) {
1322                             createAndThrowThrowableFromJVMTIErrorCode(jnienv, errorCode);
1323                         }
1324                     }
1325                 }
1326 
1327                 /*
1328                  * Cleanup memory that we allocated above. If we had a
1329                  * JNI error, a JVM/TI error or no errors, index 'i'
1330                  * tracks how far we got in processing the classDefs
1331                  * array. Note:  ReleaseByteArrayElements() is safe to
1332                  * call with a JNI exception pending.
1333                  */
1334                 for (j = 0; j < i; j++) {
1335                     if ((jbyte *)classDefs[j].class_bytes != NULL) {
1336                         (*jnienv)->ReleaseByteArrayElements(jnienv,
1337                             targetFiles[j], (jbyte *)classDefs[j].class_bytes,
1338                             0 /* copy back and free */);
1339                         /*
1340                          * Only check for error if we didn't already have one
1341                          * so we don't overwrite errorOccurred.
1342                          */
1343                         if (!errorOccurred) {
1344                             errorOccurred = checkForThrowable(jnienv);
1345                             jplis_assert(!errorOccurred);
1346                         }
1347                     }
1348                 }
1349                 deallocate(jvmtienv, (void*)targetFiles);
1350                 deallocate(jvmtienv, (void*)classDefs);
1351             }
1352         }
1353     }
1354 
1355     mapThrownThrowableIfNecessary(jnienv, redefineClassMapper);
1356 }
1357 
1358 /* Cheesy sharing. ClassLoader may be null. */
1359 jobjectArray
1360 commonGetClassList( JNIEnv *            jnienv,
1361                     JPLISAgent *        agent,
1362                     jobject             classLoader,
1363                     ClassListFetcher    fetcher) {
1364     jvmtiEnv *      jvmtienv        = jvmti(agent);
1365     jboolean        errorOccurred   = JNI_FALSE;
1366     jvmtiError      jvmtierror      = JVMTI_ERROR_NONE;
1367     jint            classCount      = 0;
1368     jclass *        classes         = NULL;
1369     jobjectArray    localArray      = NULL;
1370 
1371     /* retrieve the classes from the JVMTI agent */
1372     jvmtierror = (*fetcher)( jvmtienv,
1373                         classLoader,
1374                         &classCount,
1375                         &classes);
1376     check_phase_ret_blob(jvmtierror, localArray);
1377     errorOccurred = (jvmtierror != JVMTI_ERROR_NONE);
1378     jplis_assert(!errorOccurred);
1379 
1380     if ( errorOccurred ) {
1381         createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
1382     } else {
1383         localArray = getObjectArrayFromClasses( jnienv,
1384                                                 classes,
1385                                                 classCount);
1386         errorOccurred = checkForThrowable(jnienv);
1387         jplis_assert(!errorOccurred);
1388 
1389         /* do this whether or not we saw a problem */
1390         deallocate(jvmtienv, (void*)classes);
1391     }
1392 
1393     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
1394     return localArray;
1395 
1396 }
1397 
1398 jvmtiError
1399 getAllLoadedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
1400                                         jobject     classLoader,
1401                                         jint *      classCount,
1402                                         jclass **   classes) {
1403     return (*jvmtienv)->GetLoadedClasses(jvmtienv, classCount, classes);
1404 }
1405 
1406 jobjectArray
1407 getAllLoadedClasses(JNIEnv * jnienv, JPLISAgent * agent) {
1408     return commonGetClassList(  jnienv,
1409                                 agent,
1410                                 NULL,
1411                                 getAllLoadedClassesClassListFetcher);
1412 }
1413 
1414 jvmtiError
1415 getInitiatedClassesClassListFetcher(    jvmtiEnv *  jvmtienv,
1416                                         jobject     classLoader,
1417                                         jint *      classCount,
1418                                         jclass **   classes) {
1419     return (*jvmtienv)->GetClassLoaderClasses(jvmtienv, classLoader, classCount, classes);
1420 }
1421 
1422 
1423 jobjectArray
1424 getInitiatedClasses(JNIEnv * jnienv, JPLISAgent * agent, jobject classLoader) {
1425     return commonGetClassList(  jnienv,
1426                                 agent,
1427                                 classLoader,
1428                                 getInitiatedClassesClassListFetcher);
1429 }
1430 
1431 jlong
1432 getObjectSize(JNIEnv * jnienv, JPLISAgent * agent, jobject objectToSize) {
1433     jvmtiEnv *  jvmtienv    = jvmti(agent);
1434     jlong       objectSize  = -1;
1435     jvmtiError  jvmtierror  = JVMTI_ERROR_NONE;
1436 
1437     jvmtierror = (*jvmtienv)->GetObjectSize(jvmtienv, objectToSize, &objectSize);
1438     check_phase_ret_0(jvmtierror);
1439     jplis_assert(jvmtierror == JVMTI_ERROR_NONE);
1440     if ( jvmtierror != JVMTI_ERROR_NONE ) {
1441         createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
1442     }
1443 
1444     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
1445     return objectSize;
1446 }
1447 
1448 void
1449 appendToClassLoaderSearch(JNIEnv * jnienv, JPLISAgent * agent, jstring jarFile, jboolean isBootLoader)
1450 {
1451     jvmtiEnv *  jvmtienv    = jvmti(agent);
1452     jboolean    errorOutstanding;
1453     jvmtiError  jvmtierror;
1454     const char* utf8Chars;
1455     jsize       utf8Len;
1456     jboolean    isCopy;
1457     char        platformChars[MAXPATHLEN];
1458     int         platformLen;
1459 
1460     utf8Len = (*jnienv)->GetStringUTFLength(jnienv, jarFile);
1461     errorOutstanding = checkForAndClearThrowable(jnienv);
1462 
1463     if (!errorOutstanding) {
1464         utf8Chars = (*jnienv)->GetStringUTFChars(jnienv, jarFile, &isCopy);
1465         errorOutstanding = checkForAndClearThrowable(jnienv);
1466 
1467         if (!errorOutstanding && utf8Chars != NULL) {
1468             /*
1469              * JVMTI spec'ed to use modified UTF8. At this time this is not implemented
1470              * the platform encoding is used.
1471              */
1472             platformLen = convertUft8ToPlatformString((char*)utf8Chars, utf8Len, platformChars, MAXPATHLEN);
1473             if (platformLen < 0) {
1474                 createAndThrowInternalError(jnienv);
1475                 return;
1476             }
1477 
1478             (*jnienv)->ReleaseStringUTFChars(jnienv, jarFile, utf8Chars);
1479             errorOutstanding = checkForAndClearThrowable(jnienv);
1480 
1481             if (!errorOutstanding) {
1482 
1483                 if (isBootLoader) {
1484                     jvmtierror = (*jvmtienv)->AddToBootstrapClassLoaderSearch(jvmtienv, platformChars);
1485                 } else {
1486                     jvmtierror = (*jvmtienv)->AddToSystemClassLoaderSearch(jvmtienv, platformChars);
1487                 }
1488                 check_phase_ret(jvmtierror);
1489 
1490                 if ( jvmtierror != JVMTI_ERROR_NONE ) {
1491                     createAndThrowThrowableFromJVMTIErrorCode(jnienv, jvmtierror);
1492                 }
1493             }
1494         }
1495     }
1496 
1497     mapThrownThrowableIfNecessary(jnienv, mapAllCheckedToInternalErrorMapper);
1498 }
1499 
1500 /*
1501  *  Set the prefixes used to wrap native methods (so they can be instrumented).
1502  *  Each transform can set a prefix, any that have been set come in as prefixArray.
1503  *  Convert them in native strings in a native array then call JVM TI.
1504  *  One a given call, this function handles either the prefixes for retransformable
1505  *  transforms or for normal transforms.
1506  */
1507 void
1508 setNativeMethodPrefixes(JNIEnv * jnienv, JPLISAgent * agent, jobjectArray prefixArray,
1509                         jboolean isRetransformable) {
1510     jvmtiEnv*   jvmtienv;
1511     jvmtiError  err                             = JVMTI_ERROR_NONE;
1512     jsize       arraySize;
1513     jboolean    errorOccurred                   = JNI_FALSE;
1514 
1515     jplis_assert(prefixArray != NULL);
1516 
1517     if (isRetransformable) {
1518         jvmtienv = agent->mRetransformEnvironment.mJVMTIEnv;
1519     } else {
1520         jvmtienv = agent->mNormalEnvironment.mJVMTIEnv;
1521     }
1522     arraySize = (*jnienv)->GetArrayLength(jnienv, prefixArray);
1523     errorOccurred = checkForThrowable(jnienv);
1524     jplis_assert(!errorOccurred);
1525 
1526     if (!errorOccurred) {
1527         /* allocate the native to hold the native prefixes */
1528         const char** prefixes = (const char**) allocate(jvmtienv,
1529                                                         arraySize * sizeof(char*));
1530         /* since JNI ReleaseStringUTFChars needs the jstring from which the native
1531          * string was allocated, we store them in a parallel array */
1532         jstring* originForRelease = (jstring*) allocate(jvmtienv,
1533                                                         arraySize * sizeof(jstring));
1534         errorOccurred = (prefixes == NULL || originForRelease == NULL);
1535         jplis_assert(!errorOccurred);
1536         if ( errorOccurred ) {
1537             createAndThrowThrowableFromJVMTIErrorCode(jnienv, JVMTI_ERROR_OUT_OF_MEMORY);
1538         }
1539         else {
1540             jint inx = 0;
1541             jint i;
1542             for (i = 0; i < arraySize; i++) {
1543                 jstring      prefixStr  = NULL;
1544                 const char*  prefix;
1545                 jsize        prefixLen;
1546                 jboolean     isCopy;
1547 
1548                 prefixStr = (jstring) ((*jnienv)->GetObjectArrayElement(jnienv,
1549                                                                         prefixArray, i));
1550                 errorOccurred = checkForThrowable(jnienv);
1551                 jplis_assert(!errorOccurred);
1552                 if (errorOccurred) {
1553                     break;
1554                 }
1555                 if (prefixStr == NULL) {
1556                     continue;
1557                 }
1558 
1559                 prefixLen = (*jnienv)->GetStringUTFLength(jnienv, prefixStr);
1560                 errorOccurred = checkForThrowable(jnienv);
1561                 jplis_assert(!errorOccurred);
1562                 if (errorOccurred) {
1563                     break;
1564                 }
1565 
1566                 if (prefixLen > 0) {
1567                     prefix = (*jnienv)->GetStringUTFChars(jnienv, prefixStr, &isCopy);
1568                     errorOccurred = checkForThrowable(jnienv);
1569                     jplis_assert(!errorOccurred);
1570                     if (!errorOccurred && prefix != NULL) {
1571                         prefixes[inx] = prefix;
1572                         originForRelease[inx] = prefixStr;
1573                         ++inx;
1574                     }
1575                 }
1576             }
1577 
1578             err = (*jvmtienv)->SetNativeMethodPrefixes(jvmtienv, inx, (char**)prefixes);
1579             /* can be called from any phase */
1580             jplis_assert(err == JVMTI_ERROR_NONE);
1581 
1582             for (i = 0; i < inx; i++) {
1583               (*jnienv)->ReleaseStringUTFChars(jnienv, originForRelease[i], prefixes[i]);
1584             }
1585         }
1586         deallocate(jvmtienv, (void*)prefixes);
1587         deallocate(jvmtienv, (void*)originForRelease);
1588     }
1589 }