ij-16.png   inspectorJ -- JavaTM Profiler
sf project site browse source checkout source
SourceForge.net Logo



src/inspectorj/agent/java_crw_demo.cpp

00001 /*
00002  * @(#)java_crw_demo.c  1.27 06/02/02
00003  * 
00004  * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  * 
00009  * -Redistribution of source code must retain the above copyright notice, this
00010  *  list of conditions and the following disclaimer.
00011  * 
00012  * -Redistribution in binary form must reproduce the above copyright notice, 
00013  *  this list of conditions and the following disclaimer in the documentation
00014  *  and/or other materials provided with the distribution.
00015  * 
00016  * Neither the name of Sun Microsystems, Inc. or the names of contributors may 
00017  * be used to endorse or promote products derived from this software without 
00018  * specific prior written permission.
00019  * 
00020  * This software is provided "AS IS," without a warranty of any kind. ALL 
00021  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
00022  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
00023  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
00024  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
00025  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
00026  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST 
00027  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
00028  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY 
00029  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 
00030  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00031  * 
00032  * You acknowledge that this software is not designed, licensed or intended
00033  * for use in the design, construction, operation or maintenance of any
00034  * nuclear facility.
00035  */
00036 
00037 /* Class reader writer (java_crw_demo) for instrumenting bytecodes */
00038 
00039 /*
00040  * As long as the callbacks allow for it and the class number is unique,
00041  *     this code is completely re-entrant and any number of classfile 
00042  *     injections can happen at the same time.
00043  *
00044  *     The current logic requires a unique number for this class instance
00045  *     or (jclass,jobject loader) pair, this is done via the ClassIndex
00046  *     in hprof, which is passed in as the 'unsigned cnum' to java_crw_demo().
00047  *     It's up to the user of this interface if it wants to use this
00048  *     feature.
00049  *
00050  * Example Usage: See file test_crw.c.
00051  *
00052  */
00053 
00054 #include <stdio.h>
00055 #include <stdlib.h>
00056 #include <string.h>
00057 
00058 /* Get Java and class file and bytecode information. */
00059 
00060 #include <jni.h>
00061 
00062 #include "classfile_constants.h"
00063 
00064 
00065 /* Include our own interface for cross check */
00066 
00067 #include "java_crw_demo.h"
00068 
00069 /* Macros over error functions to capture line numbers */
00070 
00071 #define CRW_FATAL(ci, message) fatal_error(ci, message, __FILE__, __LINE__)
00072 
00073 #if defined(DEBUG) || !defined(NDEBUG)
00074 
00075   #define CRW_ASSERT(ci, cond) \
00076         ((cond)?(void)0:assert_error(ci, #cond, __FILE__, __LINE__))
00077   
00078 #else
00079   
00080   #define CRW_ASSERT(ci, cond)
00081   
00082 #endif
00083 
00084 #define CRW_ASSERT_MI(mi) CRW_ASSERT((mi)?(mi)->ci:NULL,(mi)!=NULL)
00085 
00086 #define CRW_ASSERT_CI(ci) CRW_ASSERT(ci, ( (ci) != NULL && \
00087                          (ci)->input_position <= (ci)->input_len && \
00088                          (ci)->output_position <= (ci)->output_len) )
00089 
00090 /* Typedefs for various integral numbers, just for code clarity */
00091 
00092 typedef unsigned       ClassOpcode;             /* One opcode */
00093 typedef unsigned char  ByteCode;                /* One byte from bytecodes */
00094 typedef int            ByteOffset;              /* Byte offset */
00095 typedef int            ClassConstant;           /* Constant pool kind */
00096 typedef long           CrwPosition;             /* Position in class image */
00097 typedef unsigned short CrwCpoolIndex;           /* Index into constant pool */
00098 
00099 /* Misc support macros */
00100 
00101 /* Given the position of an opcode, find the next 4byte boundary position */
00102 #define NEXT_4BYTE_BOUNDARY(opcode_pos) (((opcode_pos)+4) & (~3))
00103 
00104 #define LARGEST_INJECTION               (12*3) /* 3 injections at same site */
00105 #define MAXIMUM_NEW_CPOOL_ENTRIES       64 /* don't add more than 32 entries */
00106 
00107 /* Constant Pool Entry (internal table that mirrors pool in file image) */
00108 
00109 typedef struct {
00110     const char *        ptr;            /* Pointer to any string */
00111     unsigned short      len;            /* Length of string */
00112     unsigned int        index1;         /* 1st 16 bit index or 32bit value. */
00113     unsigned int        index2;         /* 2nd 16 bit index or 32bit value. */
00114     ClassConstant       tag;            /* Tag or kind of entry. */
00115 } CrwConstantPoolEntry;
00116 
00117 struct MethodImage;
00118 
00119 /* Class file image storage structure */
00120 
00121 typedef struct CrwClassImage {
00122     
00123     /* Unique class number for this class */
00124     unsigned                    number;
00125    
00126     /* Name of class, given or gotten out of class image */
00127     const char *                name;
00128    
00129     /* Input and Output class images tracking */
00130     const unsigned char *       input;
00131     unsigned char *             output;
00132     CrwPosition                 input_len;
00133     CrwPosition                 output_len;
00134     CrwPosition                 input_position;
00135     CrwPosition                 output_position;
00136    
00137     /* Mirrored constant pool */
00138     CrwConstantPoolEntry *      cpool;
00139     CrwCpoolIndex               cpool_max_elements;             /* Max count */
00140     CrwCpoolIndex               cpool_count_plus_one;
00141    
00142     /* Input flags about class (e.g. is it a system class) */
00143     int                         system_class;
00144 
00145     /* Class access flags gotten from file. */
00146     unsigned                    access_flags;
00147    
00148     /* Names of classes and methods. */
00149     char* tclass_name;          /* Name of class that has tracker methods. */
00150     char* tclass_sig;           /* Signature of class */
00151     char* call_name;            /* Method name to call at offset 0 */
00152     char* call_sig;             /* Signature of this method */
00153     char* return_name;          /* Method name to call before any return */
00154     char* return_sig;           /* Signature of this method */
00155     char* obj_init_name;        /* Method name to call in Object <init> */
00156     char* obj_init_sig;         /* Signature of this method */
00157     char* newarray_name;        /* Method name to call after newarray opcodes */
00158     char* newarray_sig;         /* Signature of this method */
00159 
00160     /* Constant pool index values for new entries */
00161     CrwCpoolIndex               tracker_class_index;
00162     CrwCpoolIndex               object_init_tracker_index;
00163     CrwCpoolIndex               newarray_tracker_index;
00164     CrwCpoolIndex               call_tracker_index;
00165     CrwCpoolIndex               return_tracker_index;
00166     CrwCpoolIndex               class_number_index; /* Class number in pool */
00167     
00168     /* Count of injections made into this class */
00169     int                         injection_count;
00170 
00171     /* This class must be the java.lang.Object class */
00172     jboolean                    is_object_class;
00173     
00174     /* This class must be the java.lang.Thread class */
00175     jboolean                    is_thread_class;
00176     
00177     /* Callback functions */
00178     FatalErrorHandler           fatal_error_handler;
00179     MethodNumberRegister        mnum_callback;
00180 
00181     /* Table of method names and descr's */
00182     int                         method_count;
00183     const char **               method_name;
00184     const char **               method_descr;
00185     struct MethodImage *        current_mi;
00186 
00187 } CrwClassImage;
00188 
00189 /* Injection bytecodes (holds injected bytecodes for each code position) */
00190 
00191 typedef struct {
00192     ByteCode *  code;
00193     ByteOffset  len;
00194 } Injection;
00195 
00196 /* Method transformation data (allocated/freed as each method is processed) */
00197 
00198 typedef struct MethodImage {
00199     
00200     /* Back reference to Class image data. */
00201     CrwClassImage *     ci;
00202 
00203     /* Unique method number for this class. */
00204     unsigned            number;
00205 
00206     /* Method name and descr */
00207     const char *        name;
00208     const char *        descr;
00209 
00210     /* Map of input bytecode offsets to output bytecode offsets */
00211     ByteOffset *        map;
00212 
00213     /* Bytecode injections for each input bytecode offset */
00214     Injection *         injections;
00215 
00216     /* Widening setting for each input bytecode offset */
00217     signed char *       widening;
00218 
00219     /* Length of original input bytecodes. */
00220     ByteOffset          code_len;
00221 
00222     /* Location in input where bytecodes are located. */
00223     CrwPosition         start_of_input_bytecodes;
00224 
00225     /* Original max_stack and new max stack */
00226     unsigned            max_stack;
00227     unsigned            new_max_stack;
00228     
00229     jboolean            object_init_method;
00230     jboolean            skip_call_return_sites;
00231 
00232     /* Method access flags gotten from file. */
00233     unsigned            access_flags;
00234    
00235 } MethodImage;
00236 
00237 /* ----------------------------------------------------------------- */
00238 /* General support functions (memory and error handling) */
00239 
00240 static void 
00241 fatal_error(CrwClassImage *ci, const char *message, const char *file, int line)
00242 {
00243     if ( ci != NULL && ci->fatal_error_handler != NULL ) {
00244         (*ci->fatal_error_handler)(message, file, line);
00245     } else {
00246         /* Normal operation should NEVER reach here */
00247         /* NO CRW FATAL ERROR HANDLER! */
00248         (void)fprintf(stderr, "CRW: %s [%s:%d]\n", message, file, line);
00249         abort();
00250     }
00251 }
00252 
00253 #if defined(DEBUG) || !defined(NDEBUG)
00254 static void
00255 assert_error(CrwClassImage *ci, const char *condition, 
00256                  const char *file, int line)
00257 {
00258     char buf[512];
00259     MethodImage *mi;
00260     ByteOffset byte_code_offset;
00261 
00262     mi = ci->current_mi;
00263     if ( mi != NULL ) {
00264         byte_code_offset = (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes);
00265     } else {
00266         byte_code_offset=-1;
00267     }
00268     
00269     (void)sprintf(buf,
00270                 "CRW ASSERTION FAILURE: %s (%s:%s:%d)",
00271                 condition, 
00272                 ci->name==0?"?":ci->name,
00273                 mi->name==0?"?":mi->name,
00274                 byte_code_offset);
00275     fatal_error(ci, buf, file, line);
00276 }
00277 #endif
00278 
00279 static void *
00280 allocate(CrwClassImage *ci, int nbytes)
00281 {
00282     void * ptr;
00283    
00284     ptr = malloc(nbytes);
00285     if ( ptr == NULL ) {
00286         CRW_FATAL(ci, "Ran out of malloc memory"); 
00287     }
00288     return ptr;
00289 }
00290 
00291 static void *
00292 reallocate(CrwClassImage *ci, void *optr, int nbytes)
00293 {
00294     void * ptr;
00295    
00296     ptr = realloc(optr, nbytes);
00297     if ( ptr == NULL ) {
00298         CRW_FATAL(ci, "Ran out of malloc memory"); 
00299     }
00300     return ptr;
00301 }
00302 
00303 static void *
00304 allocate_clean(CrwClassImage *ci, int nbytes)
00305 {
00306     void * ptr;
00307    
00308     ptr = calloc(nbytes, 1);
00309     if ( ptr == NULL ) {
00310         CRW_FATAL(ci, "Ran out of malloc memory"); 
00311     }
00312     return ptr;
00313 }
00314 
00315 static const char *
00316 duplicate(CrwClassImage *ci, const char *str, int len)
00317 {
00318     char *copy;
00319     
00320     copy = (char*)allocate(ci, len+1);
00321     (void)memcpy(copy, str, len);
00322     copy[len] = 0;
00323     return (const char *)copy;
00324 }
00325 
00326 static void
00327 deallocate(CrwClassImage *ci, void *ptr)
00328 {
00329     (void)free(ptr);
00330 }
00331 
00332 /* ----------------------------------------------------------------- */
00333 /* Functions for reading/writing bytes to/from the class images */
00334 
00335 static unsigned 
00336 readU1(CrwClassImage *ci) 
00337 {
00338     CRW_ASSERT_CI(ci);
00339     return ((unsigned)(ci->input[ci->input_position++])) & 0xFF;
00340 }
00341 
00342 static unsigned 
00343 readU2(CrwClassImage *ci) 
00344 {
00345     unsigned res;
00346     
00347     res = readU1(ci);
00348     return (res << 8) + readU1(ci);
00349 }
00350 
00351 static signed short
00352 readS2(CrwClassImage *ci) 
00353 {
00354     unsigned res;
00355     
00356     res = readU1(ci);
00357     return ((res << 8) + readU1(ci)) & 0xFFFF;
00358 }
00359 
00360 static unsigned 
00361 readU4(CrwClassImage *ci) 
00362 {
00363     unsigned res;
00364     
00365     res = readU2(ci);
00366     return (res << 16) + readU2(ci);
00367 }
00368 
00369 static void 
00370 writeU1(CrwClassImage *ci, unsigned val)  /* Only writes out lower 8 bits */
00371 {
00372     CRW_ASSERT_CI(ci);
00373     if ( ci->output != NULL ) {
00374         ci->output[ci->output_position++] = val & 0xFF;
00375     }
00376 }
00377 
00378 static void 
00379 writeU2(CrwClassImage *ci, unsigned val) 
00380 {
00381     writeU1(ci, val >> 8);
00382     writeU1(ci, val);
00383 }
00384 
00385 static void 
00386 writeU4(CrwClassImage *ci, unsigned val) 
00387 {
00388     writeU2(ci, val >> 16);
00389     writeU2(ci, val);
00390 }
00391 
00392 static unsigned 
00393 copyU1(CrwClassImage *ci) 
00394 {
00395     unsigned value;
00396     
00397     value = readU1(ci);
00398     writeU1(ci, value);
00399     return value;
00400 }
00401 
00402 static unsigned 
00403 copyU2(CrwClassImage *ci) 
00404 {
00405     unsigned value;
00406     
00407     value = readU2(ci);
00408     writeU2(ci, value);
00409     return value;
00410 }
00411 
00412 static unsigned 
00413 copyU4(CrwClassImage *ci) 
00414 {
00415     unsigned value;
00416     
00417     value = readU4(ci);
00418     writeU4(ci, value);
00419     return value;
00420 }
00421 
00422 static void 
00423 copy(CrwClassImage *ci, unsigned count) 
00424 {
00425     CRW_ASSERT_CI(ci);
00426     if ( ci->output != NULL ) {
00427         (void)memcpy(ci->output+ci->output_position, 
00428                      ci->input+ci->input_position, count);
00429         ci->output_position += count;
00430     }
00431     ci->input_position += count;
00432     CRW_ASSERT_CI(ci);
00433 }
00434 
00435 static void 
00436 skip(CrwClassImage *ci, unsigned count) 
00437 {
00438     CRW_ASSERT_CI(ci);
00439     ci->input_position += count;
00440 }
00441 
00442 static void
00443 read_bytes(CrwClassImage *ci, void *bytes, unsigned count) 
00444 {
00445     CRW_ASSERT_CI(ci);
00446     CRW_ASSERT(ci, bytes!=NULL);
00447     (void)memcpy(bytes, ci->input+ci->input_position, count);
00448     ci->input_position += count;
00449 }
00450 
00451 static void 
00452 write_bytes(CrwClassImage *ci, void *bytes, unsigned count) 
00453 {
00454     CRW_ASSERT_CI(ci);
00455     CRW_ASSERT(ci, bytes!=NULL);
00456     if ( ci->output != NULL ) {
00457         (void)memcpy(ci->output+ci->output_position, bytes, count);
00458         ci->output_position += count;
00459     }
00460 }
00461 
00462 static void 
00463 random_writeU2(CrwClassImage *ci, CrwPosition pos, unsigned val) 
00464 {
00465     CrwPosition save_position;
00466     
00467     CRW_ASSERT_CI(ci);
00468     save_position = ci->output_position;
00469     ci->output_position = pos;
00470     writeU2(ci, val);
00471     ci->output_position = save_position;
00472 }
00473 
00474 static void 
00475 random_writeU4(CrwClassImage *ci, CrwPosition pos, unsigned val) 
00476 {
00477     CrwPosition save_position;
00478     
00479     CRW_ASSERT_CI(ci);
00480     save_position = ci->output_position;
00481     ci->output_position = pos;
00482     writeU4(ci, val);
00483     ci->output_position = save_position;
00484 }
00485 
00486 /* ----------------------------------------------------------------- */
00487 /* Constant Pool handling functions. */
00488 
00489 static void
00490 fillin_cpool_entry(CrwClassImage *ci, CrwCpoolIndex i,
00491                    ClassConstant tag,
00492                    unsigned int index1, unsigned int index2,
00493                    const char *ptr, int len)
00494 {
00495     CRW_ASSERT_CI(ci);
00496     CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one);
00497     ci->cpool[i].tag    = tag;
00498     ci->cpool[i].index1 = index1;
00499     ci->cpool[i].index2 = index2;
00500     ci->cpool[i].ptr    = ptr;
00501     ci->cpool[i].len    = (unsigned short)len;
00502 }
00503 
00504 static CrwCpoolIndex 
00505 add_new_cpool_entry(CrwClassImage *ci, ClassConstant tag, 
00506                     unsigned int index1, unsigned int index2, 
00507                     const char *str, int len)
00508 {
00509     CrwCpoolIndex i;
00510     char *utf8 = NULL;
00511     
00512     CRW_ASSERT_CI(ci);
00513     i = ci->cpool_count_plus_one++;
00514 
00515     /* NOTE: This implementation does not automatically expand the
00516      *       constant pool table beyond the expected number needed
00517      *       to handle this particular CrwTrackerInterface injections.
00518      *       See MAXIMUM_NEW_CPOOL_ENTRIES
00519      */
00520     CRW_ASSERT(ci,  ci->cpool_count_plus_one < ci->cpool_max_elements );
00521     
00522     writeU1(ci, tag);
00523     switch (tag) {
00524         case JVM_CONSTANT_Class: 
00525             writeU2(ci, index1);
00526             break;
00527         case JVM_CONSTANT_String:  
00528             writeU2(ci, index1);
00529             break;
00530         case JVM_CONSTANT_Fieldref: 
00531         case JVM_CONSTANT_Methodref: 
00532         case JVM_CONSTANT_InterfaceMethodref: 
00533         case JVM_CONSTANT_Integer:  
00534         case JVM_CONSTANT_Float:  
00535         case JVM_CONSTANT_NameAndType: 
00536             writeU2(ci, index1);
00537             writeU2(ci, index2);
00538             break;
00539         case JVM_CONSTANT_Long:  
00540         case JVM_CONSTANT_Double: 
00541             writeU4(ci, index1);
00542             writeU4(ci, index2);
00543             ci->cpool_count_plus_one++;
00544             CRW_ASSERT(ci,  ci->cpool_count_plus_one < ci->cpool_max_elements );
00545             break;
00546         case JVM_CONSTANT_Utf8:  
00547             CRW_ASSERT(ci, len==(len & 0xFFFF));
00548             writeU2(ci, len);
00549             write_bytes(ci, (void*)str, len);
00550             utf8 = (char*)duplicate(ci, str, len);
00551             break;
00552         default: 
00553             CRW_FATAL(ci, "Unknown constant"); 
00554             break;
00555     }
00556     fillin_cpool_entry(ci, i, tag, index1, index2, (const char *)utf8, len);
00557     CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one);
00558     return i;
00559 }
00560 
00561 static CrwCpoolIndex
00562 add_new_class_cpool_entry(CrwClassImage *ci, const char *class_name) 
00563 {
00564     CrwCpoolIndex name_index;
00565     CrwCpoolIndex class_index;
00566     int           len;
00567     
00568     CRW_ASSERT_CI(ci);
00569     CRW_ASSERT(ci, class_name!=NULL);
00570         
00571     len = (int)strlen(class_name);
00572     name_index = add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, 
00573                         class_name, len);
00574     class_index = add_new_cpool_entry(ci, JVM_CONSTANT_Class, name_index, 0, 
00575                         NULL, 0);
00576     return class_index;
00577 }
00578 
00579 static CrwCpoolIndex
00580 add_new_method_cpool_entry(CrwClassImage *ci, CrwCpoolIndex class_index,
00581                      const char *name, const char *descr) 
00582 {
00583     CrwCpoolIndex name_index;
00584     CrwCpoolIndex descr_index;
00585     CrwCpoolIndex name_type_index;
00586     int len;
00587     
00588     CRW_ASSERT_CI(ci);
00589     CRW_ASSERT(ci, name!=NULL);
00590     CRW_ASSERT(ci, descr!=NULL);
00591     len = (int)strlen(name);
00592     name_index = 
00593         add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, name, len);
00594     len = (int)strlen(descr);
00595     descr_index = 
00596         add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, descr, len);
00597     name_type_index = 
00598         add_new_cpool_entry(ci, JVM_CONSTANT_NameAndType, 
00599                                 name_index, descr_index, NULL, 0);
00600     return add_new_cpool_entry(ci, JVM_CONSTANT_Methodref, 
00601                                 class_index, name_type_index, NULL, 0);
00602 }
00603 
00604 static CrwConstantPoolEntry 
00605 cpool_entry(CrwClassImage *ci, CrwCpoolIndex c_index) 
00606 {
00607     CRW_ASSERT_CI(ci);
00608     CRW_ASSERT(ci, c_index > 0 && c_index < ci->cpool_count_plus_one);
00609     return ci->cpool[c_index];
00610 }
00611 
00612 static void 
00613 cpool_setup(CrwClassImage *ci)
00614 {
00615     CrwCpoolIndex i;
00616     CrwPosition cpool_output_position;
00617     int count_plus_one;
00618  
00619     CRW_ASSERT_CI(ci);
00620     cpool_output_position = ci->output_position;
00621     count_plus_one = copyU2(ci);
00622     CRW_ASSERT(ci, count_plus_one>1);
00623     ci->cpool_max_elements = count_plus_one+MAXIMUM_NEW_CPOOL_ENTRIES;
00624     ci->cpool = (CrwConstantPoolEntry*)allocate_clean(ci,
00625                 (int)((ci->cpool_max_elements)*sizeof(CrwConstantPoolEntry)));
00626     ci->cpool_count_plus_one = (CrwCpoolIndex)count_plus_one;
00627   
00628     /* Index zero not in class file */
00629     for (i = 1; i < count_plus_one; ++i) {
00630         CrwCpoolIndex   ipos;
00631         ClassConstant   tag;
00632         unsigned int    index1;
00633         unsigned int    index2;
00634         unsigned        len;
00635         char *          utf8;
00636         
00637         ipos    = i;
00638         index1  = 0;
00639         index2  = 0;
00640         len     = 0;
00641         utf8    = NULL;
00642         
00643         tag = copyU1(ci);
00644         switch (tag) {
00645             case JVM_CONSTANT_Class: 
00646                 index1 = copyU2(ci); 
00647                 break;
00648             case JVM_CONSTANT_String:  
00649                 index1 = copyU2(ci); 
00650                 break;
00651             case JVM_CONSTANT_Fieldref: 
00652             case JVM_CONSTANT_Methodref: 
00653             case JVM_CONSTANT_InterfaceMethodref: 
00654             case JVM_CONSTANT_Integer:  
00655             case JVM_CONSTANT_Float:  
00656             case JVM_CONSTANT_NameAndType: 
00657                 index1 = copyU2(ci); 
00658                 index2 = copyU2(ci); 
00659                 break;
00660             case JVM_CONSTANT_Long:  
00661             case JVM_CONSTANT_Double: 
00662                 index1 = copyU4(ci); 
00663                 index2 = copyU4(ci); 
00664                 ++i;  /* // these take two CP entries - duh! */
00665                 break;
00666             case JVM_CONSTANT_Utf8:  
00667                 len     = copyU2(ci); 
00668                 index1  = (unsigned short)len;
00669                 utf8    = (char*)allocate(ci, len+1);
00670                 read_bytes(ci, (void*)utf8, len);
00671                 utf8[len] = 0;
00672                 write_bytes(ci, (void*)utf8, len);
00673                 break;
00674             default: 
00675                 CRW_FATAL(ci, "Unknown constant"); 
00676                 break;
00677         }
00678         fillin_cpool_entry(ci, ipos, tag, index1, index2, (const char *)utf8, len);
00679     }
00680 
00681     if (ci->call_name != NULL || ci->return_name != NULL) {
00682         if ( ci->number != (ci->number & 0x7FFF) ) {
00683             ci->class_number_index = 
00684                 add_new_cpool_entry(ci, JVM_CONSTANT_Integer, 
00685                     (ci->number>>16) & 0xFFFF, ci->number & 0xFFFF, NULL, 0);
00686         }
00687     }
00688 
00689     if (  ci->tclass_name != NULL ) {
00690         ci->tracker_class_index = 
00691                 add_new_class_cpool_entry(ci, ci->tclass_name);
00692     }
00693     if (ci->obj_init_name != NULL) {
00694         ci->object_init_tracker_index = add_new_method_cpool_entry(ci, 
00695                     ci->tracker_class_index, 
00696                     ci->obj_init_name, 
00697                     ci->obj_init_sig);
00698     }
00699     if (ci->newarray_name != NULL) {
00700         ci->newarray_tracker_index = add_new_method_cpool_entry(ci, 
00701                     ci->tracker_class_index, 
00702                     ci->newarray_name, 
00703                     ci->newarray_sig);
00704     }
00705     if (ci->call_name != NULL) {
00706         ci->call_tracker_index = add_new_method_cpool_entry(ci, 
00707                     ci->tracker_class_index, 
00708                     ci->call_name, 
00709                     ci->call_sig);
00710     }
00711     if (ci->return_name != NULL) {
00712         ci->return_tracker_index = add_new_method_cpool_entry(ci, 
00713                     ci->tracker_class_index, 
00714                     ci->return_name, 
00715                     ci->return_sig);
00716     }
00717     
00718     random_writeU2(ci, cpool_output_position, ci->cpool_count_plus_one);
00719 }
00720 
00721 /* ----------------------------------------------------------------- */
00722 /* Functions that create the bytecodes to inject */
00723 
00724 static ByteOffset
00725 push_pool_constant_bytecodes(ByteCode *bytecodes, CrwCpoolIndex index)
00726 {
00727     ByteOffset nbytes = 0;
00728     
00729     if ( index == (index&0x7F) ) {
00730         bytecodes[nbytes++] = (ByteCode)opc_ldc;
00731     } else {
00732         bytecodes[nbytes++] = (ByteCode)opc_ldc_w;
00733         bytecodes[nbytes++] = (ByteCode)((index >> 8) & 0xFF); 
00734     }
00735     bytecodes[nbytes++] = (ByteCode)(index & 0xFF);
00736     return nbytes;
00737 }
00738 
00739 static ByteOffset
00740 push_short_constant_bytecodes(ByteCode *bytecodes, unsigned number)
00741 {
00742     ByteOffset nbytes = 0;
00743     
00744     if ( number <= 5 ) {
00745         bytecodes[nbytes++] = (ByteCode)(opc_iconst_0+number);
00746     } else if ( number == (number&0x7F) ) {
00747         bytecodes[nbytes++] = (ByteCode)opc_bipush;
00748         bytecodes[nbytes++] = (ByteCode)(number & 0xFF);
00749     } else {
00750         bytecodes[nbytes++] = (ByteCode)opc_sipush;
00751         bytecodes[nbytes++] = (ByteCode)((number >> 8) & 0xFF); 
00752         bytecodes[nbytes++] = (ByteCode)(number & 0xFF);
00753     }
00754     return nbytes;
00755 }
00756 
00757 static ByteOffset
00758 injection_template(MethodImage *mi, ByteCode *bytecodes, ByteOffset max_nbytes, 
00759                         CrwCpoolIndex method_index)
00760 {
00761     CrwClassImage *     ci;
00762     ByteOffset nbytes = 0;
00763     unsigned max_stack;
00764     int add_dup;
00765     int add_aload;
00766     int push_cnum;
00767     int push_mnum;
00768     
00769     ci = mi->ci;
00770     
00771     CRW_ASSERT(ci, bytecodes!=NULL);
00772     
00773     if ( method_index == 0 )  {
00774         return 0;
00775     }
00776 
00777     if ( method_index == ci->newarray_tracker_index) {
00778         max_stack       = mi->max_stack + 1;
00779         add_dup         = JNI_TRUE;
00780         add_aload       = JNI_FALSE;
00781         push_cnum       = JNI_FALSE;
00782         push_mnum       = JNI_FALSE;
00783     } else if ( method_index == ci->object_init_tracker_index) {
00784         max_stack       = mi->max_stack + 1;
00785         add_dup         = JNI_FALSE;
00786         add_aload       = JNI_TRUE;
00787         push_cnum       = JNI_FALSE;
00788         push_mnum       = JNI_FALSE;
00789     } else {
00790         max_stack       = mi->max_stack + 2;
00791         add_dup         = JNI_FALSE;
00792         add_aload       = JNI_FALSE;
00793         push_cnum       = JNI_TRUE;
00794         push_mnum       = JNI_TRUE;
00795     }
00796     
00797     if ( add_dup ) {
00798         bytecodes[nbytes++] = (ByteCode)opc_dup;
00799     }
00800     if ( add_aload ) {
00801         bytecodes[nbytes++] = (ByteCode)opc_aload_0;
00802     }
00803     if ( push_cnum ) {
00804         if ( ci->number == (ci->number & 0x7FFF) ) {
00805             nbytes += push_short_constant_bytecodes(bytecodes+nbytes, 
00806                                                 ci->number);
00807         } else {
00808             CRW_ASSERT(ci, ci->class_number_index!=0);
00809             nbytes += push_pool_constant_bytecodes(bytecodes+nbytes, 
00810                                                 ci->class_number_index);
00811         }
00812     }
00813     if ( push_mnum ) {
00814         nbytes += push_short_constant_bytecodes(bytecodes+nbytes, 
00815                                             mi->number);
00816     }
00817     bytecodes[nbytes++] = (ByteCode)opc_invokestatic;
00818     bytecodes[nbytes++] = (ByteCode)(method_index >> 8);
00819     bytecodes[nbytes++] = (ByteCode)method_index;
00820     bytecodes[nbytes]   = 0;
00821     CRW_ASSERT(ci, nbytes<max_nbytes);
00822 
00823     /* Make sure the new max_stack is appropriate */
00824     if ( max_stack > mi->new_max_stack ) {
00825         mi->new_max_stack = max_stack;
00826     }
00827     return nbytes;
00828 }
00829 
00830 /* Called to create injection code at entry to a method */
00831 static ByteOffset
00832 entry_injection_code(MethodImage *mi, ByteCode *bytecodes, ByteOffset len)
00833 {
00834     CrwClassImage *     ci;
00835     ByteOffset nbytes = 0;
00836     
00837     CRW_ASSERT_MI(mi);
00838 
00839     ci = mi->ci;
00840 
00841     if ( mi->object_init_method ) {
00842         nbytes = injection_template(mi,
00843                             bytecodes, len, ci->object_init_tracker_index);
00844     }
00845     if ( !mi->skip_call_return_sites ) {
00846         nbytes += injection_template(mi,
00847                     bytecodes+nbytes, len-nbytes, ci->call_tracker_index);
00848     }
00849     return nbytes;
00850 }
00851 
00852 /* Called to create injection code before an opcode */
00853 static ByteOffset
00854 before_injection_code(MethodImage *mi, ClassOpcode opcode, 
00855                       ByteCode *bytecodes, ByteOffset len)
00856 {
00857     ByteOffset nbytes = 0;
00858 
00859     
00860     CRW_ASSERT_MI(mi);
00861     switch ( opcode ) {
00862         case opc_return:
00863         case opc_ireturn:
00864         case opc_lreturn:
00865         case opc_freturn:
00866         case opc_dreturn:
00867         case opc_areturn:
00868             if ( !mi->skip_call_return_sites ) {
00869                 nbytes = injection_template(mi,
00870                             bytecodes, len, mi->ci->return_tracker_index);
00871             }
00872             break;
00873         default:
00874             break;
00875     }
00876     return nbytes;
00877 }
00878 
00879 /* Called to create injection code after an opcode */
00880 static ByteOffset
00881 after_injection_code(MethodImage *mi, ClassOpcode opcode, 
00882                      ByteCode *bytecodes, ByteOffset len)
00883 {
00884     CrwClassImage* ci;
00885     ByteOffset nbytes;
00886     
00887     ci = mi->ci;
00888     nbytes = 0;
00889    
00890     CRW_ASSERT_MI(mi);
00891     switch ( opcode ) {
00892         case opc_new:
00893             /* Can't inject here cannot pass around uninitialized object */
00894             break;
00895         case opc_newarray:
00896         case opc_anewarray:
00897         case opc_multianewarray:
00898             nbytes = injection_template(mi,
00899                                 bytecodes, len, ci->newarray_tracker_index);
00900             break;
00901         default:
00902             break;
00903     }
00904     return nbytes;
00905 }
00906 
00907 /* Actually inject the bytecodes */
00908 static void 
00909 inject_bytecodes(MethodImage *mi, ByteOffset at, 
00910                  ByteCode *bytecodes, ByteOffset len) 
00911 {
00912     Injection injection;
00913     CrwClassImage *ci;
00914     
00915     ci = mi->ci;
00916     CRW_ASSERT_MI(mi);
00917     CRW_ASSERT(ci, at <= mi->code_len);
00918     
00919     injection = mi->injections[at];
00920     
00921     CRW_ASSERT(ci, len <= LARGEST_INJECTION/2);
00922     CRW_ASSERT(ci, injection.len+len <= LARGEST_INJECTION);
00923 
00924     /* Either start an injection area or concatenate to what is there */
00925     if ( injection.code == NULL ) {
00926         CRW_ASSERT(ci, injection.len==0);
00927         injection.code = (ByteCode *)allocate_clean(ci, LARGEST_INJECTION+1);
00928     }
00929     
00930     (void)memcpy(injection.code+injection.len, bytecodes, len);
00931     injection.len += len;
00932     injection.code[injection.len] = 0;
00933     mi->injections[at] = injection;
00934     ci->injection_count++;
00935 }
00936 
00937 /* ----------------------------------------------------------------- */
00938 /* Method handling functions */
00939 
00940 static MethodImage *
00941 method_init(CrwClassImage *ci, unsigned mnum, ByteOffset code_len)
00942 {
00943     MethodImage *       mi;
00944     ByteOffset          i;
00945     
00946     mi                  = (MethodImage*)allocate_clean(ci, (int)sizeof(MethodImage));
00947     mi->ci              = ci;
00948     mi->name            = ci->method_name[mnum];
00949     mi->descr           = ci->method_descr[mnum];
00950     mi->code_len        = code_len;
00951     mi->map             = (ByteOffset*)allocate_clean(ci, 
00952                                 (int)((code_len+1)*sizeof(ByteOffset)));
00953     for(i=0; i<=code_len; i++) {
00954         mi->map[i] = i;
00955     }
00956     mi->widening        = (signed char*)allocate_clean(ci, code_len+1);
00957     mi->injections      = (Injection *)allocate_clean(ci, 
00958                                 (int)((code_len+1)*sizeof(Injection)));
00959     mi->number          = mnum;
00960     ci->current_mi      = mi;
00961     return mi;
00962 }
00963 
00964 static void
00965 method_term(MethodImage *mi)
00966 {
00967     CrwClassImage *ci;
00968     
00969     ci = mi->ci;
00970     CRW_ASSERT_MI(mi);
00971     if ( mi->map != NULL ) {
00972         deallocate(ci, (void*)mi->map);
00973         mi->map = NULL;
00974     }
00975     if ( mi->widening != NULL ) {
00976         deallocate(ci, (void*)mi->widening);
00977         mi->widening = NULL;
00978     }
00979     if ( mi->injections != NULL ) {
00980         ByteOffset i;
00981         for(i=0; i<= mi->code_len; i++) {
00982             if ( mi->injections[i].code != NULL ) {
00983                 deallocate(ci, (void*)mi->injections[i].code);
00984                 mi->injections[i].code = NULL;
00985             }
00986         }
00987         deallocate(ci, (void*)mi->injections);
00988         mi->injections = NULL;
00989     }
00990     ci->current_mi = NULL;
00991     deallocate(ci, (void*)mi);
00992 }
00993 
00994 static ByteOffset
00995 input_code_offset(MethodImage *mi)
00996 {
00997     CRW_ASSERT_MI(mi);
00998     return (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes);
00999 }
01000 
01001 static void
01002 rewind_to_beginning_of_input_bytecodes(MethodImage *mi)
01003 {
01004     CRW_ASSERT_MI(mi);
01005     mi->ci->input_position = mi->start_of_input_bytecodes;
01006 }
01007 
01008 /* Starting at original byte position 'at', add 'offset' to it's new
01009  *   location. This may be a negative value.
01010  *   NOTE: That this map is not the new bytecode location of the opcode
01011  *         but the new bytecode location that should be used when
01012  *         a goto or jump instruction was targeting the old bytecode
01013  *         location.
01014  */
01015 static void 
01016 adjust_map(MethodImage *mi, ByteOffset at, ByteOffset offset) 
01017 {
01018     ByteOffset i;
01019     
01020     CRW_ASSERT_MI(mi);
01021     for (i = at; i <= mi->code_len; ++i) {
01022         mi->map[i] += offset;
01023     }
01024 }
01025 
01026 static void 
01027 widen(MethodImage *mi, ByteOffset at, ByteOffset len) 
01028 {
01029     int delta;
01030    
01031     CRW_ASSERT(mi->ci, at <= mi->code_len);
01032     delta = len - mi->widening[at];
01033     /* Adjust everything from the current input location by delta */
01034     adjust_map(mi, input_code_offset(mi), delta);
01035     /* Mark at beginning of instruction */
01036     mi->widening[at] = (signed char)len;
01037 }
01038 
01039 static void
01040 verify_opc_wide(CrwClassImage *ci, ClassOpcode wopcode)
01041 {
01042     switch (wopcode) {
01043         case opc_aload: case opc_astore:
01044         case opc_fload: case opc_fstore:
01045         case opc_iload: case opc_istore:
01046         case opc_lload: case opc_lstore:
01047         case opc_dload: case opc_dstore:
01048         case opc_ret:   case opc_iinc:
01049             break;
01050         default:
01051             CRW_FATAL(ci, "Invalid opcode supplied to opc_wide");
01052             break;
01053     }
01054 }
01055 
01056 static unsigned
01057 opcode_length(CrwClassImage *ci, ClassOpcode opcode)
01058 {
01059     /* Define array that holds length of an opcode */
01060     static unsigned char _opcode_length[opc_MAX+1] = 
01061                           JVM_OPCODE_LENGTH_INITIALIZER;
01062     
01063     if ( opcode > opc_MAX ) {
01064         CRW_FATAL(ci, "Invalid opcode supplied to opcode_length()");
01065     }
01066     return _opcode_length[opcode];
01067 }
01068     
01069 /* Walk one instruction and inject instrumentation */
01070 static void 
01071 inject_for_opcode(MethodImage *mi) 
01072 {
01073     CrwClassImage *  ci;
01074     ClassOpcode      opcode;
01075     int              pos;
01076 
01077     CRW_ASSERT_MI(mi);
01078     ci = mi->ci;
01079     pos = input_code_offset(mi);
01080     opcode = readU1(ci);
01081     
01082     if (opcode == opc_wide) {
01083         ClassOpcode     wopcode;
01084         
01085         wopcode = readU1(ci);
01086         /* lvIndex not used */
01087         (void)readU2(ci);
01088         verify_opc_wide(ci, wopcode);
01089         if ( wopcode==opc_iinc ) {
01090             (void)readU1(ci);
01091             (void)readU1(ci);
01092         }
01093     } else {
01094         
01095         ByteCode        bytecodes[LARGEST_INJECTION+1];
01096         int             header;
01097         int             instr_len;
01098         int             low;
01099         int             high;
01100         int             npairs;
01101         ByteOffset      len;
01102 
01103         /* Get bytecodes to inject before this opcode */
01104         len = before_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
01105         if ( len > 0 ) {
01106             inject_bytecodes(mi, pos, bytecodes, len);
01107             /* Adjust map after processing this opcode */
01108         }
01109 
01110         /* Process this opcode */
01111         switch (opcode) {
01112             case opc_tableswitch:
01113                 header = NEXT_4BYTE_BOUNDARY(pos);
01114                 skip(ci, header - (pos+1));
01115                 (void)readU4(ci);
01116                 low = readU4(ci);
01117                 high = readU4(ci);
01118                 skip(ci, (high+1-low) * 4);
01119                 break;
01120             case opc_lookupswitch:
01121                 header = NEXT_4BYTE_BOUNDARY(pos);
01122                 skip(ci, header - (pos+1));
01123                 (void)readU4(ci);
01124                 npairs = readU4(ci);
01125                 skip(ci, npairs * 8);
01126                 break;
01127             default:
01128                 instr_len = opcode_length(ci, opcode);
01129                 skip(ci, instr_len-1);
01130                 break;
01131         }
01132 
01133         /* Get position after this opcode is processed */
01134         pos = input_code_offset(mi);
01135 
01136         /* Adjust for any before_injection_code() */
01137         if ( len > 0 ) {
01138             /* Adjust everything past this opcode.
01139              *   Why past it? Because we want any jumps to this bytecode loc
01140              *   to go to the injected code, not where the opcode
01141              *   was moved too.
01142              *   Consider a 'return' opcode that is jumped too.
01143              *   NOTE: This may not be correct in all cases, but will
01144              *         when we are only dealing with non-variable opcodes
01145              *         like the return opcodes. Be careful if the
01146              *         before_injection_code() changes to include other
01147              *         opcodes that have variable length.
01148              */
01149             adjust_map(mi, pos, len);
01150         }
01151 
01152         /* Get bytecodes to inject after this opcode */
01153         len = after_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
01154         if ( len > 0 ) {
01155             inject_bytecodes(mi, pos, bytecodes, len);
01156         
01157             /* Adjust for any after_injection_code() */
01158             adjust_map(mi, pos, len);
01159         }
01160     
01161     }
01162 }
01163 
01164 /* Map original bytecode location to it's new location. (See adjust_map()). */
01165 static ByteOffset
01166 method_code_map(MethodImage *mi, ByteOffset pos)
01167 {
01168     CRW_ASSERT_MI(mi);
01169     CRW_ASSERT(mi->ci, pos <= mi->code_len);
01170     return mi->map[pos];
01171 }
01172 
01173 static int 
01174 adjust_instruction(MethodImage *mi) 
01175 {
01176     CrwClassImage *     ci;
01177     ClassOpcode         opcode;
01178     int                 pos;
01179     int                 new_pos;
01180 
01181     CRW_ASSERT_MI(mi);
01182     ci = mi->ci;
01183     pos = input_code_offset(mi);
01184     new_pos = method_code_map(mi,pos);
01185     
01186     opcode = readU1(ci);
01187     
01188     if (opcode == opc_wide) {
01189         ClassOpcode wopcode;
01190         
01191         wopcode = readU1(ci);
01192         /* lvIndex not used */
01193         (void)readU2(ci);
01194         verify_opc_wide(ci, wopcode);
01195         if ( wopcode==opc_iinc ) {
01196             (void)readU1(ci);
01197             (void)readU1(ci);
01198         }
01199     } else {
01200         
01201         int widened;
01202         int header;
01203         int newHeader;
01204         int low;
01205         int high;
01206         int new_pad;
01207         int old_pad;
01208         int delta;
01209         int new_delta;
01210         int delta_pad;
01211         int npairs;
01212         int instr_len;
01213         
01214         switch (opcode) {
01215 
01216         case opc_tableswitch:
01217             widened     = mi->widening[pos];
01218             header      = NEXT_4BYTE_BOUNDARY(pos);
01219             newHeader   = NEXT_4BYTE_BOUNDARY(new_pos);
01220 
01221             skip(ci, header - (pos+1));
01222 
01223             delta       = readU4(ci);
01224             low         = readU4(ci);
01225             high        = readU4(ci);
01226             skip(ci, (high+1-low) * 4);
01227             new_pad     = newHeader - new_pos;
01228             old_pad     = header - pos;
01229             delta_pad   = new_pad - old_pad;
01230             if (widened != delta_pad) {
01231                 widen(mi, pos, delta_pad);
01232                 return 0;
01233             }
01234             break;
01235 
01236         case opc_lookupswitch:
01237             widened     = mi->widening[pos];
01238             header      = NEXT_4BYTE_BOUNDARY(pos);
01239             newHeader   = NEXT_4BYTE_BOUNDARY(new_pos);
01240 
01241             skip(ci, header - (pos+1));
01242 
01243             delta       = readU4(ci);
01244             npairs      = readU4(ci);
01245             skip(ci, npairs * 8);
01246             new_pad     = newHeader - new_pos;
01247             old_pad     = header - pos;
01248             delta_pad   = new_pad - old_pad;
01249             if (widened != delta_pad) {
01250                 widen(mi, pos, delta_pad);
01251                 return 0;
01252             }
01253             break;
01254 
01255         case opc_jsr: case opc_goto:
01256         case opc_ifeq: case opc_ifge: case opc_ifgt:
01257         case opc_ifle: case opc_iflt: case opc_ifne:
01258         case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
01259         case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
01260         case opc_if_acmpeq: case opc_if_acmpne:
01261         case opc_ifnull: case opc_ifnonnull:
01262             widened     = mi->widening[pos];
01263             delta       = readS2(ci);
01264             if (widened == 0) {
01265                 new_delta = method_code_map(mi,pos+delta) - new_pos;
01266                 if ((new_delta < -32768) || (new_delta > 32767)) {
01267                     switch (opcode) {
01268                         case opc_jsr: case opc_goto:
01269                             widen(mi, pos, 2);
01270                             break;
01271                         default:
01272                             widen(mi, pos, 5);
01273                             break;
01274                     }
01275                     return 0;
01276                 }
01277             }
01278             break;
01279 
01280         case opc_jsr_w:
01281         case opc_goto_w:
01282             (void)readU4(ci);
01283             break;
01284                     
01285         default:
01286             instr_len = opcode_length(ci, opcode);
01287             skip(ci, instr_len-1);
01288             break;
01289         }
01290     }
01291     return 1;
01292 }
01293 
01294 static void 
01295 write_instruction(MethodImage *mi) 
01296 {
01297     CrwClassImage *     ci;
01298     ClassOpcode         opcode;
01299     ByteOffset          new_code_len;
01300     int                 pos;
01301     int                 new_pos;
01302     
01303     CRW_ASSERT_MI(mi);
01304     ci = mi->ci;
01305     pos = input_code_offset(mi);
01306     new_pos = method_code_map(mi,pos);
01307     new_code_len = mi->injections[pos].len;
01308     if (new_code_len > 0) {
01309         write_bytes(ci, (void*)mi->injections[pos].code, new_code_len);
01310     }
01311     
01312     opcode = readU1(ci);
01313     if (opcode == opc_wide) {
01314         ClassOpcode     wopcode;
01315         
01316         writeU1(ci, opcode);
01317         
01318         wopcode = copyU1(ci);
01319         /* lvIndex not used */
01320         (void)copyU2(ci);
01321         verify_opc_wide(ci, wopcode);
01322         if ( wopcode==opc_iinc ) {
01323             (void)copyU1(ci);
01324             (void)copyU1(ci);
01325         }
01326     } else {
01327         
01328         ClassOpcode new_opcode;
01329         int             header;
01330         int             newHeader;
01331         int             low;
01332         int             high;
01333         int             i;
01334         int             npairs;
01335         int             widened;
01336         int             instr_len;
01337         int             delta;
01338         int             new_delta;
01339 
01340         switch (opcode) {
01341 
01342             case opc_tableswitch:
01343                 header = NEXT_4BYTE_BOUNDARY(pos);
01344                 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
01345 
01346                 skip(ci, header - (pos+1));
01347 
01348                 delta = readU4(ci);
01349                 new_delta = method_code_map(mi,pos+delta) - new_pos;
01350                 low = readU4(ci);
01351                 high = readU4(ci);
01352 
01353                 writeU1(ci, opcode);
01354                 for (i = new_pos+1; i < newHeader; ++i) {
01355                     writeU1(ci, 0);
01356                 }
01357                 writeU4(ci, new_delta);
01358                 writeU4(ci, low);
01359                 writeU4(ci, high);
01360 
01361                 for (i = low; i <= high; ++i) {
01362                     delta = readU4(ci);
01363                     new_delta = method_code_map(mi,pos+delta) - new_pos;
01364                     writeU4(ci, new_delta);
01365                 }
01366                 break;
01367 
01368             case opc_lookupswitch:
01369                 header = NEXT_4BYTE_BOUNDARY(pos);
01370                 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
01371 
01372                 skip(ci, header - (pos+1));
01373 
01374                 delta = readU4(ci);
01375                 new_delta = method_code_map(mi,pos+delta) - new_pos;
01376                 npairs = readU4(ci);
01377                 writeU1(ci, opcode);
01378                 for (i = new_pos+1; i < newHeader; ++i) {
01379                     writeU1(ci, 0);
01380                 }
01381                 writeU4(ci, new_delta);
01382                 writeU4(ci, npairs);
01383                 for (i = 0; i< npairs; ++i) {
01384                     unsigned match = readU4(ci);
01385                     delta = readU4(ci);
01386                     new_delta = method_code_map(mi,pos+delta) - new_pos;
01387                     writeU4(ci, match);
01388                     writeU4(ci, new_delta);
01389                 }
01390                 break;
01391 
01392             case opc_jsr: case opc_goto:
01393             case opc_ifeq: case opc_ifge: case opc_ifgt:
01394             case opc_ifle: case opc_iflt: case opc_ifne:
01395             case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
01396             case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
01397             case opc_if_acmpeq: case opc_if_acmpne:
01398             case opc_ifnull: case opc_ifnonnull:
01399                 widened = mi->widening[pos];
01400                 delta = readS2(ci);
01401                 new_delta = method_code_map(mi,pos+delta) - new_pos;
01402                 new_opcode = opcode;
01403                 if (widened == 0) {
01404                     writeU1(ci, opcode);
01405                     writeU2(ci, new_delta);
01406                 } else if (widened == 2) {
01407                     switch (opcode) {
01408                         case opc_jsr:
01409                             new_opcode = opc_jsr_w;
01410                             break;
01411                         case opc_goto:
01412                             new_opcode = opc_goto_w;
01413                             break;
01414                         default:
01415                             CRW_FATAL(ci, "unexpected opcode");
01416                             break;
01417                     }
01418                     writeU1(ci, new_opcode);
01419                     writeU4(ci, new_delta);
01420                 } else if (widened == 5) {
01421                     switch (opcode) {
01422                         case opc_ifeq: 
01423                             new_opcode = opc_ifne;
01424                             break;
01425                         case opc_ifge: 
01426                             new_opcode = opc_iflt;
01427                             break;
01428                         case opc_ifgt:
01429                             new_opcode = opc_ifle;
01430                             break;
01431                         case opc_ifle: 
01432                             new_opcode = opc_ifgt;
01433                             break;
01434                         case opc_iflt: 
01435                             new_opcode = opc_ifge;
01436                             break;
01437                         case opc_ifne:
01438                             new_opcode = opc_ifeq;
01439                             break;
01440                         case opc_if_icmpeq: 
01441                             new_opcode = opc_if_icmpne;
01442                             break;
01443                         case opc_if_icmpne: 
01444                             new_opcode = opc_if_icmpeq;
01445                             break;
01446                         case opc_if_icmpge:
01447                             new_opcode = opc_if_icmplt;
01448                             break;
01449                         case opc_if_icmpgt: 
01450                             new_opcode = opc_if_icmple;
01451                             break;
01452                         case opc_if_icmple: 
01453                             new_opcode = opc_if_icmpgt;
01454                             break;
01455                         case opc_if_icmplt:
01456                             new_opcode = opc_if_icmpge;
01457                             break;
01458                         case opc_if_acmpeq: 
01459                             new_opcode = opc_if_acmpne;
01460                             break;
01461                         case opc_if_acmpne:
01462                             new_opcode = opc_if_acmpeq;
01463                             break;
01464                         case opc_ifnull: 
01465                             new_opcode = opc_ifnonnull;
01466                             break;
01467                         case opc_ifnonnull:
01468                             new_opcode = opc_ifnull;
01469                             break;
01470                         default:
01471                             CRW_FATAL(ci, "Unexpected opcode");
01472                         break;
01473                     }
01474                     writeU1(ci, new_opcode);    /* write inverse branch */
01475                     writeU2(ci, 3 + 5);         /* beyond if and goto_w */
01476                     writeU1(ci, opc_goto_w);    /* add a goto_w */
01477                     writeU4(ci, new_delta-3); /* write new and wide delta */
01478                 } else {
01479                     CRW_FATAL(ci, "Unexpected widening");
01480                 }
01481                 break;
01482 
01483             case opc_jsr_w:
01484             case opc_goto_w:
01485                 delta = readU4(ci);
01486                 new_delta = method_code_map(mi,pos+delta) - new_pos;
01487                 writeU1(ci, opcode);
01488                 writeU4(ci, new_delta);
01489                 break;
01490                         
01491             default:
01492                 instr_len = opcode_length(ci, opcode);
01493                 writeU1(ci, opcode); 
01494                 copy(ci, instr_len-1);
01495                 break;
01496         }
01497     }
01498 }
01499 
01500 static void 
01501 method_inject_and_write_code(MethodImage *mi) 
01502 {
01503     ByteCode bytecodes[LARGEST_INJECTION+1];
01504     ByteOffset   len;
01505     
01506     CRW_ASSERT_MI(mi);
01507    
01508     /* Do injections */
01509     rewind_to_beginning_of_input_bytecodes(mi);   
01510     len = entry_injection_code(mi, bytecodes, (int)sizeof(bytecodes));
01511     if ( len > 0 ) {
01512         int pos;
01513 
01514         pos = 0;
01515         inject_bytecodes(mi, pos, bytecodes, len);
01516         /* Adjust pos 0 to map to new pos 0, you never want to
01517          *  jump into this entry code injection. So the new pos 0
01518          *  will be past this entry_injection_code().
01519          */
01520         adjust_map(mi, pos, len); /* Inject before behavior */
01521     }
01522     while (input_code_offset(mi) < mi->code_len) {
01523         inject_for_opcode(mi);
01524     }
01525    
01526     /* Adjust instructions */
01527     rewind_to_beginning_of_input_bytecodes(mi);
01528     while (input_code_offset(mi) < mi->code_len) {
01529         if (!adjust_instruction(mi)) {
01530             rewind_to_beginning_of_input_bytecodes(mi);
01531         }
01532     }
01533 
01534     /* Write new instructions */
01535     rewind_to_beginning_of_input_bytecodes(mi); 
01536     while (input_code_offset(mi) < mi->code_len) {
01537         write_instruction(mi);
01538     }
01539 }
01540 
01541 static void 
01542 copy_attribute(CrwClassImage *ci) 
01543 {
01544     int len;
01545     
01546     (void)copyU2(ci);
01547     len = copyU4(ci);
01548     copy(ci, len);
01549 }
01550 
01551 static void 
01552 copy_attributes(CrwClassImage *ci) 
01553 {
01554     unsigned i;
01555     unsigned count;
01556    
01557     count = copyU2(ci);
01558     for (i = 0; i < count; ++i) {
01559         copy_attribute(ci);
01560     }
01561 }
01562 
01563 static void 
01564 copy_all_fields(CrwClassImage *ci)
01565 {
01566     unsigned i;
01567     unsigned count;
01568     
01569     count = copyU2(ci);
01570     for (i = 0; i < count; ++i) {
01571         /* access, name, descriptor */
01572         copy(ci, 6);
01573         copy_attributes(ci);
01574     }
01575 }
01576 
01577 static void
01578 write_line_table(MethodImage *mi)
01579 {
01580     unsigned             i;
01581     unsigned             count;
01582     CrwClassImage *      ci;
01583     
01584     CRW_ASSERT_MI(mi);
01585     ci = mi->ci;
01586     (void)copyU4(ci);
01587     count = copyU2(ci);
01588     for(i=0; i<count; i++) {
01589         ByteOffset start_pc;
01590         ByteOffset new_start_pc;
01591         
01592         start_pc = readU2(ci);
01593         
01594         if ( start_pc == 0 ) {
01595             new_start_pc = 0; /* Don't skip entry injection code. */
01596         } else {
01597             new_start_pc = method_code_map(mi, start_pc);
01598         }
01599         
01600         writeU2(ci, new_start_pc);
01601         (void)copyU2(ci);
01602     }
01603 }
01604 
01605 /* Used for LocalVariableTable and LocalVariableTypeTable attributes */
01606 static void
01607 write_var_table(MethodImage *mi)
01608 {
01609     unsigned             i;
01610     unsigned             count;
01611     CrwClassImage *      ci;
01612     
01613     CRW_ASSERT_MI(mi);
01614     ci = mi->ci;
01615     (void)copyU4(ci);
01616     count = copyU2(ci);
01617     for(i=0; i<count; i++) {
01618         ByteOffset start_pc;
01619         ByteOffset new_start_pc;
01620         ByteOffset length;
01621         ByteOffset new_length;
01622         ByteOffset end_pc;
01623         ByteOffset new_end_pc;
01624         
01625         start_pc        = readU2(ci);
01626         length          = readU2(ci);
01627 
01628         if ( start_pc == 0 ) {
01629             new_start_pc = 0; /* Don't skip entry injection code. */
01630         } else {
01631             new_start_pc = method_code_map(mi, start_pc);
01632         }
01633         end_pc          = start_pc + length;
01634         new_end_pc      = method_code_map(mi, end_pc);
01635         new_length      = new_end_pc - new_start_pc;
01636         
01637         writeU2(ci, new_start_pc);
01638         writeU2(ci, new_length);
01639         (void)copyU2(ci);
01640         (void)copyU2(ci);
01641         (void)copyU2(ci);
01642     }
01643 }
01644 
01645 static void
01646 method_write_exception_table(MethodImage *mi)
01647 {
01648     unsigned            i;
01649     unsigned            count;
01650     CrwClassImage *     ci;
01651     
01652     CRW_ASSERT_MI(mi);
01653     ci = mi->ci;
01654     count = copyU2(ci);
01655     for(i=0; i<count; i++) {
01656         ByteOffset start_pc;
01657         ByteOffset new_start_pc;
01658         ByteOffset end_pc;
01659         ByteOffset new_end_pc;
01660         ByteOffset handler_pc;
01661         ByteOffset new_handler_pc;
01662         
01663         start_pc        = readU2(ci);
01664         end_pc          = readU2(ci);
01665         handler_pc      = readU2(ci);
01666         
01667         new_start_pc    = method_code_map(mi, start_pc);
01668         new_end_pc      = method_code_map(mi, end_pc);
01669         new_handler_pc  = method_code_map(mi, handler_pc);
01670         
01671         writeU2(ci, new_start_pc);
01672         writeU2(ci, new_end_pc);
01673         writeU2(ci, new_handler_pc);
01674         (void)copyU2(ci);
01675     }
01676 }
01677 
01678 static int
01679 attribute_match(CrwClassImage *ci, CrwCpoolIndex name_index, const char *name)
01680 {
01681     CrwConstantPoolEntry cs;
01682     int                  len;
01683     
01684     CRW_ASSERT_CI(ci);
01685     CRW_ASSERT(ci, name!=NULL);
01686     len = (int)strlen(name);
01687     cs = cpool_entry(ci, name_index);
01688     if ( cs.len==len && strncmp(cs.ptr, name, len)==0) {
01689        return 1;
01690     }
01691     return 0;
01692 }
01693 
01694 static void 
01695 method_write_code_attribute(MethodImage *mi)
01696 {
01697     CrwClassImage *     ci;
01698     CrwCpoolIndex       name_index;
01699     
01700     CRW_ASSERT_MI(mi);
01701     ci = mi->ci;
01702     name_index = copyU2(ci);
01703     if ( attribute_match(ci, name_index, "LineNumberTable") ) {
01704         write_line_table(mi);
01705     } else if ( attribute_match(ci, name_index, "LocalVariableTable") ) {
01706         write_var_table(mi);
01707     } else if ( attribute_match(ci, name_index, "LocalVariableTypeTable") ) {
01708         write_var_table(mi); /* Exact same format as the LocalVariableTable */
01709     } else {
01710         unsigned len;
01711         len = copyU4(ci);
01712         copy(ci, len);
01713     }
01714 }
01715 
01716 static int
01717 is_init_method(const char *name)
01718 {
01719     if ( name!=NULL && strcmp(name,"<init>")==0 ) {
01720         return JNI_TRUE;
01721     }
01722     return JNI_FALSE;
01723 }
01724 
01725 static int
01726 is_clinit_method(const char *name)
01727 {
01728     if ( name!=NULL && strcmp(name,"<clinit>")==0 ) {
01729         return JNI_TRUE;
01730     }
01731     return JNI_FALSE;
01732 }
01733 
01734 static int
01735 is_finalize_method(const char *name)
01736 {
01737     if ( name!=NULL && strcmp(name,"finalize")==0 ) {
01738         return JNI_TRUE;
01739     }
01740     return JNI_FALSE;
01741 }
01742 
01743 static int
01744 skip_method(CrwClassImage *ci, const char *name, 
01745                 unsigned access_flags, ByteOffset code_len, 
01746                 int system_class, jboolean *pskip_call_return_sites)
01747 {
01748     *pskip_call_return_sites = JNI_FALSE;
01749     if ( system_class ) {
01750         if ( code_len == 1 && is_init_method(name) ) {
01751             return JNI_TRUE;
01752         } else if ( code_len == 1 && is_finalize_method(name) ) {
01753             return JNI_TRUE;
01754         } else if ( is_clinit_method(name) ) {
01755             return JNI_TRUE;
01756         } else if ( ci->is_thread_class && strcmp(name,"currentThread")==0 ) {
01757             return JNI_TRUE;
01758         }
01759         /*
01760         if ( access_flags & JVM_ACC_PRIVATE ) {
01761             *pskip_call_return_sites = JNI_TRUE;
01762         }
01763         */
01764     }
01765     return JNI_FALSE;
01766 }
01767 
01768 /* Process all code attributes */
01769 static void 
01770 method_write_bytecodes(CrwClassImage *ci, unsigned mnum, unsigned access_flags)
01771 {
01772     CrwPosition         output_attr_len_position;
01773     CrwPosition         output_max_stack_position;
01774     CrwPosition         output_code_len_position;
01775     CrwPosition         start_of_output_bytecodes;
01776     unsigned            i;
01777     unsigned            attr_len;
01778     unsigned            max_stack;
01779     ByteOffset          code_len;
01780     ByteOffset          new_code_len;
01781     unsigned            attr_count;
01782     unsigned            new_attr_len;
01783     MethodImage *       mi;
01784     jboolean            object_init_method;
01785     jboolean            skip_call_return_sites;
01786 
01787     CRW_ASSERT_CI(ci);
01788     
01789     /* Attribute Length */
01790     output_attr_len_position = ci->output_position;
01791     attr_len = copyU4(ci);
01792     
01793     /* Max Stack */
01794     output_max_stack_position = ci->output_position;
01795     max_stack = copyU2(ci);
01796     
01797     /* Max Locals */
01798     (void)copyU2(ci);
01799     
01800     /* Code Length */
01801     output_code_len_position = ci->output_position;
01802     code_len = copyU4(ci);
01803     start_of_output_bytecodes = ci->output_position;
01804    
01805     /* Some methods should not be instrumented */
01806     object_init_method = JNI_FALSE;
01807     skip_call_return_sites = JNI_FALSE;
01808     if ( ci->is_object_class &&
01809          is_init_method(ci->method_name[mnum]) &&
01810          strcmp(ci->method_descr[mnum],"()V")==0 ) {
01811         object_init_method = JNI_TRUE;
01812         skip_call_return_sites = JNI_TRUE;
01813     } else if ( skip_method(ci, ci->method_name[mnum], access_flags, 
01814                 code_len, ci->system_class, &skip_call_return_sites) ) {
01815         /* Copy remainder minus already copied, the U2 max_stack, 
01816          *   U2 max_locals, and U4 code_length fields have already 
01817          *   been processed.
01818          */
01819         copy(ci, attr_len - (2+2+4));
01820         return;
01821     }
01822    
01823     /* Start Injection */
01824     mi = method_init(ci, mnum, code_len);
01825     mi->object_init_method = object_init_method;
01826     mi->access_flags = access_flags;
01827     mi->skip_call_return_sites = skip_call_return_sites;
01828 
01829     /* Save the current position as the start of the input bytecodes */
01830     mi->start_of_input_bytecodes = ci->input_position;
01831 
01832     /* The max stack may increase */
01833     mi->max_stack = max_stack;
01834     mi->new_max_stack = max_stack;
01835 
01836     /* Adjust all code offsets */
01837     method_inject_and_write_code(mi);
01838 
01839     /* Fix up code length */
01840     new_code_len = (int)(ci->output_position - start_of_output_bytecodes);
01841     random_writeU4(ci, output_code_len_position, new_code_len);
01842 
01843     /* Fixup max stack */
01844     CRW_ASSERT(ci, mi->new_max_stack <= 0xFFFF);
01845     random_writeU2(ci, output_max_stack_position, mi->new_max_stack);
01846     
01847     /* Copy exception table */
01848     method_write_exception_table(mi);
01849 
01850     /* Copy code attributes */
01851     attr_count = copyU2(ci);
01852     for (i = 0; i < attr_count; ++i) {
01853         method_write_code_attribute(mi);
01854     }
01855 
01856     /* Fix up attribute length */
01857     new_attr_len = (int)(ci->output_position - (output_attr_len_position + 4));
01858     random_writeU4(ci, output_attr_len_position, new_attr_len);
01859 
01860     /* Free method data */
01861     method_term(mi);
01862     mi = NULL;
01863 
01864 }        
01865 
01866 static void 
01867 method_write(CrwClassImage *ci, unsigned mnum) 
01868 {
01869     unsigned            i;
01870     unsigned            access_flags;
01871     CrwCpoolIndex       name_index;
01872     CrwCpoolIndex       descr_index;
01873     unsigned            attr_count;
01874     
01875     access_flags = copyU2(ci);
01876     name_index = copyU2(ci);
01877     ci->method_name[mnum] = cpool_entry(ci, name_index).ptr;
01878     descr_index = copyU2(ci);
01879     ci->method_descr[mnum] = cpool_entry(ci, descr_index).ptr;
01880     attr_count = copyU2(ci);
01881     
01882     for (i = 0; i < attr_count; ++i) {
01883         CrwCpoolIndex name_index;
01884         
01885         name_index = copyU2(ci);
01886         if ( attribute_match(ci, name_index, "Code") ) {
01887             method_write_bytecodes(ci, mnum, access_flags);
01888         } else {
01889             unsigned len;
01890             len = copyU4(ci);
01891             copy(ci, len);
01892         }
01893     }
01894 }
01895 
01896 static void 
01897 method_write_all(CrwClassImage *ci) 
01898 {
01899     unsigned i;
01900     unsigned count;
01901     
01902     count = copyU2(ci);
01903     ci->method_count = count;
01904     if ( count > 0 ) {
01905         ci->method_name = (const char **)allocate_clean(ci, count*(int)sizeof(const char*));
01906         ci->method_descr = (const char **)allocate_clean(ci, count*(int)sizeof(const char*));
01907     }
01908     
01909     for (i = 0; i < count; ++i) {
01910         method_write(ci, i);
01911     }
01912     
01913     if ( ci->mnum_callback != NULL ) {
01914         (*(ci->mnum_callback))(ci->number, ci->method_name, ci->method_descr, 
01915                          count);
01916     }
01917 }
01918 
01919 /* ------------------------------------------------------------------- */
01920 /* Cleanup function. */
01921 
01922 static void
01923 cleanup(CrwClassImage *ci)
01924 {
01925     CRW_ASSERT_CI(ci);
01926     if ( ci->name != NULL ) {
01927         deallocate(ci, (void*)ci->name);
01928         ci->name = NULL;
01929     }
01930     if ( ci->method_name != NULL ) {
01931         deallocate(ci, (void*)ci->method_name);
01932         ci->method_name = NULL;
01933     }
01934     if ( ci->method_descr != NULL ) {
01935         deallocate(ci, (void*)ci->method_descr);
01936         ci->method_descr = NULL;
01937     }
01938     if ( ci->cpool != NULL ) {
01939         CrwCpoolIndex i;
01940         for(i=0; i<ci->cpool_count_plus_one; i++) {
01941             if ( ci->cpool[i].ptr != NULL ) {
01942                 deallocate(ci, (void*)(ci->cpool[i].ptr));
01943                 ci->cpool[i].ptr = NULL;
01944             }
01945         }
01946         deallocate(ci, (void*)ci->cpool);
01947         ci->cpool = NULL;
01948     }
01949 }
01950 
01951 static jboolean
01952 skip_class(unsigned access_flags)
01953 {
01954     if ( access_flags & JVM_ACC_INTERFACE ) {
01955         return JNI_TRUE;
01956     }
01957     return JNI_FALSE;
01958 }
01959 
01960 static long 
01961 inject_class(struct CrwClassImage *ci, 
01962                  int system_class,
01963                  char* tclass_name,     
01964                  char* tclass_sig,      
01965                  char* call_name,       
01966                  char* call_sig,        
01967                  char* return_name,     
01968                  char* return_sig,      
01969                  char* obj_init_name,   
01970                  char* obj_init_sig,    
01971                  char* newarray_name,   
01972                  char* newarray_sig,    
01973                  unsigned char *buf, 
01974                  long buf_len)
01975 {
01976     CrwConstantPoolEntry        cs;
01977     CrwCpoolIndex               this_class;
01978     CrwCpoolIndex               super_class;
01979     unsigned                    magic;
01980     unsigned                    classfileVersion;
01981     unsigned                    interface_count;
01982 
01983     CRW_ASSERT_CI(ci);
01984     CRW_ASSERT(ci, buf!=NULL);
01985     CRW_ASSERT(ci, buf_len!=0);
01986     
01987     CRW_ASSERT(ci, strchr(tclass_name,'.')==NULL); /* internal qualified name */
01988     
01989     ci->injection_count         = 0;
01990     ci->system_class            = system_class;
01991     ci->tclass_name             = tclass_name;
01992     ci->tclass_sig              = tclass_sig;
01993     ci->call_name               = call_name;
01994     ci->call_sig                = call_sig;
01995     ci->return_name             = return_name;
01996     ci->return_sig              = return_sig;
01997     ci->obj_init_name           = obj_init_name;
01998     ci->obj_init_sig            = obj_init_sig;
01999     ci->newarray_name           = newarray_name;
02000     ci->newarray_sig            = newarray_sig;
02001     ci->output                  = buf;
02002     ci->output_len              = buf_len;
02003     
02004     magic = copyU4(ci);
02005     CRW_ASSERT(ci, magic==0xCAFEBABE);
02006     if ( magic != 0xCAFEBABE ) {
02007         return (long)0;
02008     }
02009 
02010     /* minor version number not used */
02011     (void)copyU2(ci);
02012     /* major version number not used */
02013     classfileVersion = copyU2(ci);
02014     CRW_ASSERT(ci, classfileVersion <= 49); /* Tiger class files or less */
02015 
02016     cpool_setup(ci);
02017 
02018     ci->access_flags        = copyU2(ci);
02019     if ( skip_class(ci->access_flags) ) {
02020         return (long)0;
02021     }
02022     
02023     this_class          = copyU2(ci);
02024     
02025     cs = cpool_entry(ci, (CrwCpoolIndex)(cpool_entry(ci, this_class).index1));
02026     if ( ci->name == NULL ) {
02027         ci->name = duplicate(ci, cs.ptr, cs.len);
02028         CRW_ASSERT(ci, strchr(ci->name,'.')==NULL); /* internal qualified name */
02029     }
02030     CRW_ASSERT(ci, (int)strlen(ci->name)==cs.len && strncmp(ci->name, cs.ptr, cs.len)==0);
02031     
02032     super_class         = copyU2(ci);
02033     if ( super_class == 0 ) {
02034         ci->is_object_class = JNI_TRUE;
02035         CRW_ASSERT(ci, strcmp(ci->name,"java/lang/Object")==0);
02036     }
02037 
02038     interface_count     = copyU2(ci);
02039     copy(ci, interface_count * 2);
02040 
02041     copy_all_fields(ci);
02042 
02043     method_write_all(ci);
02044     
02045     if ( ci->injection_count == 0 ) {
02046         return (long)0;
02047     }
02048     
02049     copy_attributes(ci);
02050 
02051     return (long)ci->output_position;
02052 }
02053 
02054 /* ------------------------------------------------------------------- */
02055 /* Exported interfaces */
02056 
02057 JNIEXPORT void JNICALL 
02058 java_crw_demo(unsigned class_number,
02059          const char *name,
02060          const unsigned char *file_image,
02061          long file_len, 
02062          int system_class,
02063          char* tclass_name,     /* Name of class that has tracker methods. */
02064          char* tclass_sig,      /* Signature of tclass */
02065          char* call_name,       /* Method name to call at offset 0 */
02066          char* call_sig,        /* Signature of this method */
02067          char* return_name,     /* Method name to call before any return */
02068          char* return_sig,      /* Signature of this method */
02069          char* obj_init_name,   /* Method name to call in Object <init> */
02070          char* obj_init_sig,    /* Signature of this method */
02071          char* newarray_name,   /* Method name to call after newarray opcodes */
02072          char* newarray_sig,    /* Signature of this method */
02073          unsigned char **pnew_file_image, 
02074          long *pnew_file_len,
02075          FatalErrorHandler fatal_error_handler,
02076          MethodNumberRegister mnum_callback)
02077 {
02078     CrwClassImage ci;
02079     long          max_length;
02080     long          new_length;
02081     void         *new_image;
02082     int           len;
02083 
02084     /* Initial setup of the CrwClassImage structure */
02085     (void)memset(&ci, 0, (int)sizeof(CrwClassImage));
02086     ci.fatal_error_handler = fatal_error_handler;
02087     ci.mnum_callback       = mnum_callback;
02088     
02089     /* Do some interface error checks */
02090     if ( pnew_file_image==NULL ) {
02091         CRW_FATAL(&ci, "pnew_file_image==NULL");
02092     }
02093     if ( pnew_file_len==NULL ) {
02094         CRW_FATAL(&ci, "pnew_file_len==NULL");
02095     }
02096     
02097     /* No file length means do nothing */
02098     *pnew_file_image = NULL;
02099     *pnew_file_len = 0;
02100     if ( file_len==0 ) {
02101         return;
02102     }
02103 
02104     /* Do some more interface error checks */
02105     if ( file_image == NULL ) {
02106         CRW_FATAL(&ci, "file_image == NULL");
02107     }
02108     if ( file_len < 0 ) {
02109         CRW_FATAL(&ci, "file_len < 0");
02110     }
02111     if ( system_class != 0 && system_class != 1 ) {
02112         CRW_FATAL(&ci, "system_class is not 0 or 1");
02113     }
02114     if ( tclass_name == NULL ) {
02115         CRW_FATAL(&ci, "tclass_name == NULL");
02116     }
02117     if ( tclass_sig == NULL || tclass_sig[0]!='L' ) {
02118         CRW_FATAL(&ci, "tclass_sig is not a valid class signature");
02119     }
02120     len = (int)strlen(tclass_sig);
02121     if ( tclass_sig[len-1]!=';' ) {
02122         CRW_FATAL(&ci, "tclass_sig is not a valid class signature");
02123     }
02124     if ( call_name != NULL ) {
02125         if ( call_sig == NULL || strcmp(call_sig, "(II)V") != 0 ) {
02126             CRW_FATAL(&ci, "call_sig is not (II)V");
02127         }
02128     }
02129     if ( return_name != NULL ) {
02130         if ( return_sig == NULL || strcmp(return_sig, "(II)V") != 0 ) {
02131             CRW_FATAL(&ci, "return_sig is not (II)V");
02132         }
02133     }
02134     if ( obj_init_name != NULL ) {
02135         if ( obj_init_sig == NULL || strcmp(obj_init_sig, "(Ljava/lang/Object;)V") != 0 ) {
02136             CRW_FATAL(&ci, "obj_init_sig is not (Ljava/lang/Object;)V");
02137         }
02138     }
02139     if ( newarray_name != NULL ) {
02140         if ( newarray_sig == NULL || strcmp(newarray_sig, "(Ljava/lang/Object;)V") != 0 ) {
02141             CRW_FATAL(&ci, "newarray_sig is not (Ljava/lang/Object;)V");
02142         }
02143     }
02144     
02145     /* Finish setup the CrwClassImage structure */
02146     ci.is_thread_class = JNI_FALSE; 
02147     if ( name != NULL ) {
02148         CRW_ASSERT(&ci, strchr(name,'.')==NULL); /* internal qualified name */
02149     
02150         ci.name = duplicate(&ci, name, (int)strlen(name));
02151         if ( strcmp(name, "java/lang/Thread")==0 ) {
02152             ci.is_thread_class = JNI_TRUE; 
02153         }
02154     }
02155     ci.number = class_number;
02156     ci.input = file_image;
02157     ci.input_len = file_len;
02158 
02159     /* Do the injection */
02160     max_length = file_len*2 + 512; /* Twice as big + 512 */
02161     new_image = allocate(&ci, (int)max_length);
02162     new_length = inject_class(&ci, 
02163                                  system_class, 
02164                                  tclass_name,     
02165                                  tclass_sig,      
02166                                  call_name,       
02167                                  call_sig,        
02168                                  return_name,     
02169                                  return_sig,      
02170                                  obj_init_name,   
02171                                  obj_init_sig,    
02172                                  newarray_name,   
02173                                  newarray_sig,    
02174                                  static_cast<unsigned char*>(new_image), 
02175                                  max_length);
02176    
02177     /* Dispose or shrink the space to be returned. */
02178     if ( new_length == 0 ) {
02179         deallocate(&ci, (void*)new_image);
02180         new_image = NULL;
02181     } else {
02182         new_image = (void*)reallocate(&ci, (void*)new_image, (int)new_length);
02183     }
02184    
02185     /* Return the new class image */
02186     *pnew_file_image = (unsigned char *)new_image;
02187     *pnew_file_len = (long)new_length;
02188 
02189     /* Cleanup before we leave. */
02190     cleanup(&ci);
02191 }
02192 
02193 /* Return the classname for this class which is inside the classfile image. */
02194 JNIEXPORT char * JNICALL 
02195 java_crw_demo_classname(const unsigned char *file_image, long file_len,
02196         FatalErrorHandler fatal_error_handler)
02197 {
02198     CrwClassImage               ci;
02199     CrwConstantPoolEntry        cs;
02200     CrwCpoolIndex               this_class;
02201     unsigned                    magic;
02202     char *                      name;
02203 
02204     name = NULL;
02205     
02206     if ( file_len==0 || file_image==NULL ) {
02207         return name;
02208     }
02209 
02210     /* The only fields we need filled in are the image pointer and the error
02211      *    handler.
02212      *    By not adding an output buffer pointer, no output is created.
02213      */
02214     (void)memset(&ci, 0, (int)sizeof(CrwClassImage));
02215     ci.input     = file_image;
02216     ci.input_len = file_len;
02217     ci.fatal_error_handler = fatal_error_handler;
02218 
02219     /* Read out the bytes from the classfile image */
02220 
02221     magic = readU4(&ci); /* magic number */
02222     CRW_ASSERT(&ci, magic==0xCAFEBABE);
02223     if ( magic != 0xCAFEBABE ) {
02224         return name;
02225     }
02226     (void)readU2(&ci); /* minor version number */
02227     (void)readU2(&ci); /* major version number */
02228    
02229     /* Read in constant pool. Since no output setup, writes are NOP's */
02230     cpool_setup(&ci);
02231 
02232     (void)readU2(&ci); /* access flags */
02233     this_class = readU2(&ci); /* 'this' class */
02234    
02235     /* Get 'this' constant pool entry */
02236     cs = cpool_entry(&ci, (CrwCpoolIndex)(cpool_entry(&ci, this_class).index1));
02237     
02238     /* Duplicate the name */
02239     name = (char *)duplicate(&ci, cs.ptr, cs.len);
02240     
02241     /* Cleanup before we leave. */
02242     cleanup(&ci);
02243 
02244     /* Return malloc space */
02245     return name;
02246 }

Generated on Sun Aug 19 17:07:53 2007 for inspectorJ by  doxygen 1.5.1