00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #include <stdio.h>
00055 #include <stdlib.h>
00056 #include <string.h>
00057
00058
00059
00060 #include <jni.h>
00061
00062 #include "classfile_constants.h"
00063
00064
00065
00066
00067 #include "java_crw_demo.h"
00068
00069
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
00091
00092 typedef unsigned ClassOpcode;
00093 typedef unsigned char ByteCode;
00094 typedef int ByteOffset;
00095 typedef int ClassConstant;
00096 typedef long CrwPosition;
00097 typedef unsigned short CrwCpoolIndex;
00098
00099
00100
00101
00102 #define NEXT_4BYTE_BOUNDARY(opcode_pos) (((opcode_pos)+4) & (~3))
00103
00104 #define LARGEST_INJECTION (12*3)
00105 #define MAXIMUM_NEW_CPOOL_ENTRIES 64
00106
00107
00108
00109 typedef struct {
00110 const char * ptr;
00111 unsigned short len;
00112 unsigned int index1;
00113 unsigned int index2;
00114 ClassConstant tag;
00115 } CrwConstantPoolEntry;
00116
00117 struct MethodImage;
00118
00119
00120
00121 typedef struct CrwClassImage {
00122
00123
00124 unsigned number;
00125
00126
00127 const char * name;
00128
00129
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
00138 CrwConstantPoolEntry * cpool;
00139 CrwCpoolIndex cpool_max_elements;
00140 CrwCpoolIndex cpool_count_plus_one;
00141
00142
00143 int system_class;
00144
00145
00146 unsigned access_flags;
00147
00148
00149 char* tclass_name;
00150 char* tclass_sig;
00151 char* call_name;
00152 char* call_sig;
00153 char* return_name;
00154 char* return_sig;
00155 char* obj_init_name;
00156 char* obj_init_sig;
00157 char* newarray_name;
00158 char* newarray_sig;
00159
00160
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;
00167
00168
00169 int injection_count;
00170
00171
00172 jboolean is_object_class;
00173
00174
00175 jboolean is_thread_class;
00176
00177
00178 FatalErrorHandler fatal_error_handler;
00179 MethodNumberRegister mnum_callback;
00180
00181
00182 int method_count;
00183 const char ** method_name;
00184 const char ** method_descr;
00185 struct MethodImage * current_mi;
00186
00187 } CrwClassImage;
00188
00189
00190
00191 typedef struct {
00192 ByteCode * code;
00193 ByteOffset len;
00194 } Injection;
00195
00196
00197
00198 typedef struct MethodImage {
00199
00200
00201 CrwClassImage * ci;
00202
00203
00204 unsigned number;
00205
00206
00207 const char * name;
00208 const char * descr;
00209
00210
00211 ByteOffset * map;
00212
00213
00214 Injection * injections;
00215
00216
00217 signed char * widening;
00218
00219
00220 ByteOffset code_len;
00221
00222
00223 CrwPosition start_of_input_bytecodes;
00224
00225
00226 unsigned max_stack;
00227 unsigned new_max_stack;
00228
00229 jboolean object_init_method;
00230 jboolean skip_call_return_sites;
00231
00232
00233 unsigned access_flags;
00234
00235 } MethodImage;
00236
00237
00238
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
00247
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
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)
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
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
00516
00517
00518
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
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;
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
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
00824 if ( max_stack > mi->new_max_stack ) {
00825 mi->new_max_stack = max_stack;
00826 }
00827 return nbytes;
00828 }
00829
00830
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
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
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
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
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
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
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
01009
01010
01011
01012
01013
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
01034 adjust_map(mi, input_code_offset(mi), delta);
01035
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
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
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
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
01104 len = before_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
01105 if ( len > 0 ) {
01106 inject_bytecodes(mi, pos, bytecodes, len);
01107
01108 }
01109
01110
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
01134 pos = input_code_offset(mi);
01135
01136
01137 if ( len > 0 ) {
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149 adjust_map(mi, pos, len);
01150 }
01151
01152
01153 len = after_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
01154 if ( len > 0 ) {
01155 inject_bytecodes(mi, pos, bytecodes, len);
01156
01157
01158 adjust_map(mi, pos, len);
01159 }
01160
01161 }
01162 }
01163
01164
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
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
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);
01475 writeU2(ci, 3 + 5);
01476 writeU1(ci, opc_goto_w);
01477 writeU4(ci, new_delta-3);
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
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
01517
01518
01519
01520 adjust_map(mi, pos, len);
01521 }
01522 while (input_code_offset(mi) < mi->code_len) {
01523 inject_for_opcode(mi);
01524 }
01525
01526
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
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
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;
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
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;
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);
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
01761
01762
01763
01764 }
01765 return JNI_FALSE;
01766 }
01767
01768
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
01790 output_attr_len_position = ci->output_position;
01791 attr_len = copyU4(ci);
01792
01793
01794 output_max_stack_position = ci->output_position;
01795 max_stack = copyU2(ci);
01796
01797
01798 (void)copyU2(ci);
01799
01800
01801 output_code_len_position = ci->output_position;
01802 code_len = copyU4(ci);
01803 start_of_output_bytecodes = ci->output_position;
01804
01805
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
01816
01817
01818
01819 copy(ci, attr_len - (2+2+4));
01820 return;
01821 }
01822
01823
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
01830 mi->start_of_input_bytecodes = ci->input_position;
01831
01832
01833 mi->max_stack = max_stack;
01834 mi->new_max_stack = max_stack;
01835
01836
01837 method_inject_and_write_code(mi);
01838
01839
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
01844 CRW_ASSERT(ci, mi->new_max_stack <= 0xFFFF);
01845 random_writeU2(ci, output_max_stack_position, mi->new_max_stack);
01846
01847
01848 method_write_exception_table(mi);
01849
01850
01851 attr_count = copyU2(ci);
01852 for (i = 0; i < attr_count; ++i) {
01853 method_write_code_attribute(mi);
01854 }
01855
01856
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
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
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);
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
02011 (void)copyU2(ci);
02012
02013 classfileVersion = copyU2(ci);
02014 CRW_ASSERT(ci, classfileVersion <= 49);
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);
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
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,
02064 char* tclass_sig,
02065 char* call_name,
02066 char* call_sig,
02067 char* return_name,
02068 char* return_sig,
02069 char* obj_init_name,
02070 char* obj_init_sig,
02071 char* newarray_name,
02072 char* newarray_sig,
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
02085 (void)memset(&ci, 0, (int)sizeof(CrwClassImage));
02086 ci.fatal_error_handler = fatal_error_handler;
02087 ci.mnum_callback = mnum_callback;
02088
02089
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
02098 *pnew_file_image = NULL;
02099 *pnew_file_len = 0;
02100 if ( file_len==0 ) {
02101 return;
02102 }
02103
02104
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
02146 ci.is_thread_class = JNI_FALSE;
02147 if ( name != NULL ) {
02148 CRW_ASSERT(&ci, strchr(name,'.')==NULL);
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
02160 max_length = file_len*2 + 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
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
02186 *pnew_file_image = (unsigned char *)new_image;
02187 *pnew_file_len = (long)new_length;
02188
02189
02190 cleanup(&ci);
02191 }
02192
02193
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
02211
02212
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
02220
02221 magic = readU4(&ci);
02222 CRW_ASSERT(&ci, magic==0xCAFEBABE);
02223 if ( magic != 0xCAFEBABE ) {
02224 return name;
02225 }
02226 (void)readU2(&ci);
02227 (void)readU2(&ci);
02228
02229
02230 cpool_setup(&ci);
02231
02232 (void)readU2(&ci);
02233 this_class = readU2(&ci);
02234
02235
02236 cs = cpool_entry(&ci, (CrwCpoolIndex)(cpool_entry(&ci, this_class).index1));
02237
02238
02239 name = (char *)duplicate(&ci, cs.ptr, cs.len);
02240
02241
02242 cleanup(&ci);
02243
02244
02245 return name;
02246 }