1 /* 2 * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of Oracle nor the names of its 16 * contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * This source code is provided to illustrate the usage of a given feature 34 * or technique and has been deliberately simplified. Additional steps 35 * required for a production-quality application, such as security checks, 36 * input validation and proper error handling, might not be present in 37 * this sample code. 38 */ 39 40 41 /* Class reader writer (java_crw_demo) for instrumenting bytecodes */ 42 43 /* 44 * As long as the callbacks allow for it and the class number is unique, 45 * this code is completely re-entrant and any number of classfile 46 * injections can happen at the same time. 47 * 48 * The current logic requires a unique number for this class instance 49 * or (jclass,jobject loader) pair, this is done via the ClassIndex 50 * in hprof, which is passed in as the 'unsigned cnum' to java_crw_demo(). 51 * It's up to the user of this interface if it wants to use this 52 * feature. 53 * 54 */ 55 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <string.h> 59 60 /* Get Java and class file and bytecode information. */ 61 62 #include <jni.h> 63 64 #include "classfile_constants.h" 65 66 67 /* Include our own interface for cross check */ 68 69 #include "java_crw_demo.h" 70 71 /* Macros over error functions to capture line numbers */ 72 73 /* Fatal error used in all builds. */ 74 75 /* Use THIS_FILE when it is available. */ 76 #ifndef THIS_FILE 77 #define THIS_FILE "java_crw.demo.c" /* Never use __FILE__ */ 78 #endif 79 80 #define CRW_FATAL(ci, message) fatal_error(ci, message, THIS_FILE, __LINE__) 81 82 #if defined(DEBUG) || !defined(NDEBUG) 83 84 /* This assert macro is only used in the debug builds. */ 85 #define CRW_ASSERT(ci, cond) \ 86 ((cond)?(void)0:assert_error(ci, #cond, THIS_FILE, __LINE__)) 87 88 #else 89 90 #define CRW_ASSERT(ci, cond) 91 92 #endif 93 94 #define CRW_ASSERT_MI(mi) CRW_ASSERT((mi)?(mi)->ci:NULL,(mi)!=NULL) 95 96 #define CRW_ASSERT_CI(ci) CRW_ASSERT(ci, ( (ci) != NULL && \ 97 (ci)->input_position <= (ci)->input_len && \ 98 (ci)->output_position <= (ci)->output_len) ) 99 100 #define BUFSIZE 256 101 102 #ifdef _WIN32 103 #define snprintf(buffer, count, format, ...) _snprintf_s(buffer, count, _TRUNCATE, format, ##__VA_ARGS__) 104 #endif 105 106 /* Typedefs for various integral numbers, just for code clarity */ 107 108 typedef unsigned ClassOpcode; /* One opcode */ 109 typedef unsigned char ByteCode; /* One byte from bytecodes */ 110 typedef int ByteOffset; /* Byte offset */ 111 typedef int ClassConstant; /* Constant pool kind */ 112 typedef long CrwPosition; /* Position in class image */ 113 typedef unsigned short CrwCpoolIndex; /* Index into constant pool */ 114 115 /* Misc support macros */ 116 117 /* Given the position of an opcode, find the next 4byte boundary position */ 118 #define NEXT_4BYTE_BOUNDARY(opcode_pos) (((opcode_pos)+4) & (~3)) 119 120 #define LARGEST_INJECTION (12*3) /* 3 injections at same site */ 121 #define MAXIMUM_NEW_CPOOL_ENTRIES 64 /* don't add more than 32 entries */ 122 123 /* Constant Pool Entry (internal table that mirrors pool in file image) */ 124 125 typedef struct { 126 const char * ptr; /* Pointer to any string */ 127 unsigned short len; /* Length of string */ 128 unsigned int index1; /* 1st 16 bit index or 32bit value. */ 129 unsigned int index2; /* 2nd 16 bit index or 32bit value. */ 130 ClassConstant tag; /* Tag or kind of entry. */ 131 } CrwConstantPoolEntry; 132 133 struct MethodImage; 134 135 /* Class file image storage structure */ 136 137 typedef struct CrwClassImage { 138 139 /* Unique class number for this class */ 140 unsigned number; 141 142 /* Name of class, given or gotten out of class image */ 143 const char * name; 144 145 /* Input and Output class images tracking */ 146 const unsigned char * input; 147 unsigned char * output; 148 CrwPosition input_len; 149 CrwPosition output_len; 150 CrwPosition input_position; 151 CrwPosition output_position; 152 153 /* Mirrored constant pool */ 154 CrwConstantPoolEntry * cpool; 155 CrwCpoolIndex cpool_max_elements; /* Max count */ 156 CrwCpoolIndex cpool_count_plus_one; 157 158 /* Input flags about class (e.g. is it a system class) */ 159 int system_class; 160 161 /* Class access flags gotten from file. */ 162 unsigned access_flags; 163 164 /* Names of classes and methods. */ 165 char* tclass_name; /* Name of class that has tracker methods. */ 166 char* tclass_sig; /* Signature of class */ 167 char* call_name; /* Method name to call at offset 0 */ 168 char* call_sig; /* Signature of this method */ 169 char* return_name; /* Method name to call before any return */ 170 char* return_sig; /* Signature of this method */ 171 char* obj_init_name; /* Method name to call in Object <init> */ 172 char* obj_init_sig; /* Signature of this method */ 173 char* newarray_name; /* Method name to call after newarray opcodes */ 174 char* newarray_sig; /* Signature of this method */ 175 176 /* Constant pool index values for new entries */ 177 CrwCpoolIndex tracker_class_index; 178 CrwCpoolIndex object_init_tracker_index; 179 CrwCpoolIndex newarray_tracker_index; 180 CrwCpoolIndex call_tracker_index; 181 CrwCpoolIndex return_tracker_index; 182 CrwCpoolIndex class_number_index; /* Class number in pool */ 183 184 /* Count of injections made into this class */ 185 int injection_count; 186 187 /* This class must be the java.lang.Object class */ 188 jboolean is_object_class; 189 190 /* This class must be the java.lang.Thread class */ 191 jboolean is_thread_class; 192 193 /* Callback functions */ 194 FatalErrorHandler fatal_error_handler; 195 MethodNumberRegister mnum_callback; 196 197 /* Table of method names and descr's */ 198 int method_count; 199 const char ** method_name; 200 const char ** method_descr; 201 struct MethodImage * current_mi; 202 203 } CrwClassImage; 204 205 /* Injection bytecodes (holds injected bytecodes for each code position) */ 206 207 typedef struct { 208 ByteCode * code; 209 ByteOffset len; 210 } Injection; 211 212 /* Method transformation data (allocated/freed as each method is processed) */ 213 214 typedef struct MethodImage { 215 216 /* Back reference to Class image data. */ 217 CrwClassImage * ci; 218 219 /* Unique method number for this class. */ 220 unsigned number; 221 222 /* Method name and descr */ 223 const char * name; 224 const char * descr; 225 226 /* Map of input bytecode offsets to output bytecode offsets */ 227 ByteOffset * map; 228 229 /* Bytecode injections for each input bytecode offset */ 230 Injection * injections; 231 232 /* Widening setting for each input bytecode offset */ 233 signed char * widening; 234 235 /* Length of original input bytecodes, and new bytecodes. */ 236 ByteOffset code_len; 237 ByteOffset new_code_len; 238 239 /* Location in input where bytecodes are located. */ 240 CrwPosition start_of_input_bytecodes; 241 242 /* Original max_stack and new max stack */ 243 unsigned max_stack; 244 unsigned new_max_stack; 245 246 jboolean object_init_method; 247 jboolean skip_call_return_sites; 248 249 /* Method access flags gotten from file. */ 250 unsigned access_flags; 251 252 } MethodImage; 253 254 /* ----------------------------------------------------------------- */ 255 /* General support functions (memory and error handling) */ 256 257 static void 258 fatal_error(CrwClassImage *ci, const char *message, const char *file, int line) 259 { 260 if ( ci != NULL && ci->fatal_error_handler != NULL ) { 261 (*ci->fatal_error_handler)(message, file, line); 262 } else { 263 /* Normal operation should NEVER reach here */ 264 /* NO CRW FATAL ERROR HANDLER! */ 265 (void)fprintf(stderr, "CRW: %s [%s:%d]\n", message, file, line); 266 abort(); 267 } 268 } 269 270 #if defined(DEBUG) || !defined(NDEBUG) 271 static void 272 assert_error(CrwClassImage *ci, const char *condition, 273 const char *file, int line) 274 { 275 char buf[512]; 276 MethodImage *mi; 277 ByteOffset byte_code_offset; 278 279 mi = ci->current_mi; 280 if ( mi != NULL ) { 281 byte_code_offset = (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes); 282 } else { 283 byte_code_offset=-1; 284 } 285 286 (void)sprintf(buf, 287 "CRW ASSERTION FAILURE: %s (%s:%s:%d)", 288 condition, 289 ci->name==NULL?"?":ci->name, 290 (mi==NULL||mi->name==NULL)?"?":mi->name, 291 byte_code_offset); 292 fatal_error(ci, buf, file, line); 293 } 294 #endif 295 296 static void * 297 allocate(CrwClassImage *ci, int nbytes) 298 { 299 void * ptr; 300 301 if ( nbytes <= 0 ) { 302 CRW_FATAL(ci, "Cannot allocate <= 0 bytes"); 303 } 304 ptr = malloc(nbytes); 305 if ( ptr == NULL ) { 306 CRW_FATAL(ci, "Ran out of malloc memory"); 307 } 308 return ptr; 309 } 310 311 static void * 312 reallocate(CrwClassImage *ci, void *optr, int nbytes) 313 { 314 void * ptr; 315 316 if ( optr == NULL ) { 317 CRW_FATAL(ci, "Cannot deallocate NULL"); 318 } 319 if ( nbytes <= 0 ) { 320 CRW_FATAL(ci, "Cannot reallocate <= 0 bytes"); 321 } 322 ptr = realloc(optr, nbytes); 323 if ( ptr == NULL ) { 324 CRW_FATAL(ci, "Ran out of malloc memory"); 325 } 326 return ptr; 327 } 328 329 static void * 330 allocate_clean(CrwClassImage *ci, int nbytes) 331 { 332 void * ptr; 333 334 if ( nbytes <= 0 ) { 335 CRW_FATAL(ci, "Cannot allocate <= 0 bytes"); 336 } 337 ptr = calloc(nbytes, 1); 338 if ( ptr == NULL ) { 339 CRW_FATAL(ci, "Ran out of malloc memory"); 340 } 341 return ptr; 342 } 343 344 static const char * 345 duplicate(CrwClassImage *ci, const char *str, int len) 346 { 347 char *copy; 348 349 copy = (char*)allocate(ci, len+1); 350 (void)memcpy(copy, str, len); 351 copy[len] = 0; 352 return (const char *)copy; 353 } 354 355 static void 356 deallocate(CrwClassImage *ci, void *ptr) 357 { 358 if ( ptr == NULL ) { 359 CRW_FATAL(ci, "Cannot deallocate NULL"); 360 } 361 (void)free(ptr); 362 } 363 364 /* ----------------------------------------------------------------- */ 365 /* Functions for reading/writing bytes to/from the class images */ 366 367 static unsigned 368 readU1(CrwClassImage *ci) 369 { 370 CRW_ASSERT_CI(ci); 371 return ((unsigned)(ci->input[ci->input_position++])) & 0xFF; 372 } 373 374 static unsigned 375 readU2(CrwClassImage *ci) 376 { 377 unsigned res; 378 379 res = readU1(ci); 380 return (res << 8) + readU1(ci); 381 } 382 383 static signed short 384 readS2(CrwClassImage *ci) 385 { 386 unsigned res; 387 388 res = readU1(ci); 389 return ((res << 8) + readU1(ci)) & 0xFFFF; 390 } 391 392 static unsigned 393 readU4(CrwClassImage *ci) 394 { 395 unsigned res; 396 397 res = readU2(ci); 398 return (res << 16) + readU2(ci); 399 } 400 401 static void 402 writeU1(CrwClassImage *ci, unsigned val) /* Only writes out lower 8 bits */ 403 { 404 CRW_ASSERT_CI(ci); 405 if ( ci->output != NULL ) { 406 ci->output[ci->output_position++] = val & 0xFF; 407 } 408 } 409 410 static void 411 writeU2(CrwClassImage *ci, unsigned val) 412 { 413 writeU1(ci, val >> 8); 414 writeU1(ci, val); 415 } 416 417 static void 418 writeU4(CrwClassImage *ci, unsigned val) 419 { 420 writeU2(ci, val >> 16); 421 writeU2(ci, val); 422 } 423 424 static unsigned 425 copyU1(CrwClassImage *ci) 426 { 427 unsigned value; 428 429 value = readU1(ci); 430 writeU1(ci, value); 431 return value; 432 } 433 434 static unsigned 435 copyU2(CrwClassImage *ci) 436 { 437 unsigned value; 438 439 value = readU2(ci); 440 writeU2(ci, value); 441 return value; 442 } 443 444 static unsigned 445 copyU4(CrwClassImage *ci) 446 { 447 unsigned value; 448 449 value = readU4(ci); 450 writeU4(ci, value); 451 return value; 452 } 453 454 static void 455 copy(CrwClassImage *ci, unsigned count) 456 { 457 CRW_ASSERT_CI(ci); 458 if ( ci->output != NULL ) { 459 (void)memcpy(ci->output+ci->output_position, 460 ci->input+ci->input_position, count); 461 ci->output_position += count; 462 } 463 ci->input_position += count; 464 CRW_ASSERT_CI(ci); 465 } 466 467 static void 468 skip(CrwClassImage *ci, unsigned count) 469 { 470 CRW_ASSERT_CI(ci); 471 ci->input_position += count; 472 } 473 474 static void 475 read_bytes(CrwClassImage *ci, void *bytes, unsigned count) 476 { 477 CRW_ASSERT_CI(ci); 478 CRW_ASSERT(ci, bytes!=NULL); 479 (void)memcpy(bytes, ci->input+ci->input_position, count); 480 ci->input_position += count; 481 } 482 483 static void 484 write_bytes(CrwClassImage *ci, void *bytes, unsigned count) 485 { 486 CRW_ASSERT_CI(ci); 487 CRW_ASSERT(ci, bytes!=NULL); 488 if ( ci->output != NULL ) { 489 (void)memcpy(ci->output+ci->output_position, bytes, count); 490 ci->output_position += count; 491 } 492 } 493 494 static void 495 random_writeU2(CrwClassImage *ci, CrwPosition pos, unsigned val) 496 { 497 CrwPosition save_position; 498 499 CRW_ASSERT_CI(ci); 500 save_position = ci->output_position; 501 ci->output_position = pos; 502 writeU2(ci, val); 503 ci->output_position = save_position; 504 } 505 506 static void 507 random_writeU4(CrwClassImage *ci, CrwPosition pos, unsigned val) 508 { 509 CrwPosition save_position; 510 511 CRW_ASSERT_CI(ci); 512 save_position = ci->output_position; 513 ci->output_position = pos; 514 writeU4(ci, val); 515 ci->output_position = save_position; 516 } 517 518 /* ----------------------------------------------------------------- */ 519 /* Constant Pool handling functions. */ 520 521 static void 522 fillin_cpool_entry(CrwClassImage *ci, CrwCpoolIndex i, 523 ClassConstant tag, 524 unsigned int index1, unsigned int index2, 525 const char *ptr, int len) 526 { 527 CRW_ASSERT_CI(ci); 528 CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one); 529 ci->cpool[i].tag = tag; 530 ci->cpool[i].index1 = index1; 531 ci->cpool[i].index2 = index2; 532 ci->cpool[i].ptr = ptr; 533 ci->cpool[i].len = (unsigned short)len; 534 } 535 536 static CrwCpoolIndex 537 add_new_cpool_entry(CrwClassImage *ci, ClassConstant tag, 538 unsigned int index1, unsigned int index2, 539 const char *str, int len) 540 { 541 CrwCpoolIndex i; 542 char *utf8 = NULL; 543 544 CRW_ASSERT_CI(ci); 545 i = ci->cpool_count_plus_one++; 546 547 /* NOTE: This implementation does not automatically expand the 548 * constant pool table beyond the expected number needed 549 * to handle this particular CrwTrackerInterface injections. 550 * See MAXIMUM_NEW_CPOOL_ENTRIES 551 */ 552 CRW_ASSERT(ci, ci->cpool_count_plus_one < ci->cpool_max_elements ); 553 554 writeU1(ci, tag); 555 switch (tag) { 556 case JVM_CONSTANT_Class: 557 writeU2(ci, index1); 558 break; 559 case JVM_CONSTANT_String: 560 writeU2(ci, index1); 561 break; 562 case JVM_CONSTANT_Fieldref: 563 case JVM_CONSTANT_Methodref: 564 case JVM_CONSTANT_InterfaceMethodref: 565 case JVM_CONSTANT_Integer: 566 case JVM_CONSTANT_Float: 567 case JVM_CONSTANT_NameAndType: 568 writeU2(ci, index1); 569 writeU2(ci, index2); 570 break; 571 case JVM_CONSTANT_Long: 572 case JVM_CONSTANT_Double: 573 writeU4(ci, index1); 574 writeU4(ci, index2); 575 ci->cpool_count_plus_one++; 576 CRW_ASSERT(ci, ci->cpool_count_plus_one < ci->cpool_max_elements ); 577 break; 578 case JVM_CONSTANT_Utf8: 579 CRW_ASSERT(ci, len==(len & 0xFFFF)); 580 writeU2(ci, len); 581 write_bytes(ci, (void*)str, len); 582 utf8 = (char*)duplicate(ci, str, len); 583 break; 584 default: 585 CRW_FATAL(ci, "Unknown constant"); 586 break; 587 } 588 fillin_cpool_entry(ci, i, tag, index1, index2, (const char *)utf8, len); 589 CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one); 590 return i; 591 } 592 593 static CrwCpoolIndex 594 add_new_class_cpool_entry(CrwClassImage *ci, const char *class_name) 595 { 596 CrwCpoolIndex name_index; 597 CrwCpoolIndex class_index; 598 int len; 599 600 CRW_ASSERT_CI(ci); 601 CRW_ASSERT(ci, class_name!=NULL); 602 603 len = (int)strlen(class_name); 604 name_index = add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, 605 class_name, len); 606 class_index = add_new_cpool_entry(ci, JVM_CONSTANT_Class, name_index, 0, 607 NULL, 0); 608 return class_index; 609 } 610 611 static CrwCpoolIndex 612 add_new_method_cpool_entry(CrwClassImage *ci, CrwCpoolIndex class_index, 613 const char *name, const char *descr) 614 { 615 CrwCpoolIndex name_index; 616 CrwCpoolIndex descr_index; 617 CrwCpoolIndex name_type_index; 618 int len; 619 620 CRW_ASSERT_CI(ci); 621 CRW_ASSERT(ci, name!=NULL); 622 CRW_ASSERT(ci, descr!=NULL); 623 len = (int)strlen(name); 624 name_index = 625 add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, name, len); 626 len = (int)strlen(descr); 627 descr_index = 628 add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, descr, len); 629 name_type_index = 630 add_new_cpool_entry(ci, JVM_CONSTANT_NameAndType, 631 name_index, descr_index, NULL, 0); 632 return add_new_cpool_entry(ci, JVM_CONSTANT_Methodref, 633 class_index, name_type_index, NULL, 0); 634 } 635 636 static CrwConstantPoolEntry 637 cpool_entry(CrwClassImage *ci, CrwCpoolIndex c_index) 638 { 639 CRW_ASSERT_CI(ci); 640 CRW_ASSERT(ci, c_index > 0 && c_index < ci->cpool_count_plus_one); 641 return ci->cpool[c_index]; 642 } 643 644 static void 645 cpool_setup(CrwClassImage *ci) 646 { 647 CrwCpoolIndex i; 648 CrwPosition cpool_output_position; 649 int count_plus_one; 650 651 CRW_ASSERT_CI(ci); 652 cpool_output_position = ci->output_position; 653 count_plus_one = copyU2(ci); 654 CRW_ASSERT(ci, count_plus_one>1); 655 ci->cpool_max_elements = count_plus_one+MAXIMUM_NEW_CPOOL_ENTRIES; 656 ci->cpool = (CrwConstantPoolEntry*)allocate_clean(ci, 657 (int)((ci->cpool_max_elements)*sizeof(CrwConstantPoolEntry))); 658 ci->cpool_count_plus_one = (CrwCpoolIndex)count_plus_one; 659 660 /* Index zero not in class file */ 661 for (i = 1; i < count_plus_one; ++i) { 662 CrwCpoolIndex ipos; 663 ClassConstant tag; 664 unsigned int index1; 665 unsigned int index2; 666 unsigned len; 667 char * utf8; 668 char message[BUFSIZE]; 669 670 ipos = i; 671 index1 = 0; 672 index2 = 0; 673 len = 0; 674 utf8 = NULL; 675 676 tag = copyU1(ci); 677 switch (tag) { 678 case JVM_CONSTANT_Class: 679 index1 = copyU2(ci); 680 break; 681 case JVM_CONSTANT_String: 682 index1 = copyU2(ci); 683 break; 684 case JVM_CONSTANT_Fieldref: 685 case JVM_CONSTANT_Methodref: 686 case JVM_CONSTANT_InterfaceMethodref: 687 case JVM_CONSTANT_Integer: 688 case JVM_CONSTANT_Float: 689 case JVM_CONSTANT_NameAndType: 690 index1 = copyU2(ci); 691 index2 = copyU2(ci); 692 break; 693 case JVM_CONSTANT_Long: 694 case JVM_CONSTANT_Double: 695 index1 = copyU4(ci); 696 index2 = copyU4(ci); 697 ++i; /* // these take two CP entries - duh! */ 698 break; 699 case JVM_CONSTANT_Utf8: 700 len = copyU2(ci); 701 index1 = (unsigned short)len; 702 utf8 = (char*)allocate(ci, len+1); 703 read_bytes(ci, (void*)utf8, len); 704 utf8[len] = 0; 705 write_bytes(ci, (void*)utf8, len); 706 break; 707 case JVM_CONSTANT_MethodType: 708 index1 = copyU2(ci); 709 break; 710 case JVM_CONSTANT_MethodHandle: 711 index1 = copyU1(ci); 712 index2 = copyU2(ci); 713 break; 714 case JVM_CONSTANT_InvokeDynamic: 715 index1 = copyU2(ci); 716 index2 = copyU2(ci); 717 break; 718 default: 719 snprintf(message, BUFSIZE, "Unknown tag: %d, at ipos %hu", tag, ipos); 720 CRW_FATAL(ci, message); 721 break; 722 } 723 fillin_cpool_entry(ci, ipos, tag, index1, index2, (const char *)utf8, len); 724 } 725 726 if (ci->call_name != NULL || ci->return_name != NULL) { 727 if ( ci->number != (ci->number & 0x7FFF) ) { 728 ci->class_number_index = 729 add_new_cpool_entry(ci, JVM_CONSTANT_Integer, 730 (ci->number>>16) & 0xFFFF, ci->number & 0xFFFF, NULL, 0); 731 } 732 } 733 734 if ( ci->tclass_name != NULL ) { 735 ci->tracker_class_index = 736 add_new_class_cpool_entry(ci, ci->tclass_name); 737 } 738 if (ci->obj_init_name != NULL) { 739 ci->object_init_tracker_index = add_new_method_cpool_entry(ci, 740 ci->tracker_class_index, 741 ci->obj_init_name, 742 ci->obj_init_sig); 743 } 744 if (ci->newarray_name != NULL) { 745 ci->newarray_tracker_index = add_new_method_cpool_entry(ci, 746 ci->tracker_class_index, 747 ci->newarray_name, 748 ci->newarray_sig); 749 } 750 if (ci->call_name != NULL) { 751 ci->call_tracker_index = add_new_method_cpool_entry(ci, 752 ci->tracker_class_index, 753 ci->call_name, 754 ci->call_sig); 755 } 756 if (ci->return_name != NULL) { 757 ci->return_tracker_index = add_new_method_cpool_entry(ci, 758 ci->tracker_class_index, 759 ci->return_name, 760 ci->return_sig); 761 } 762 763 random_writeU2(ci, cpool_output_position, ci->cpool_count_plus_one); 764 } 765 766 /* ----------------------------------------------------------------- */ 767 /* Functions that create the bytecodes to inject */ 768 769 static ByteOffset 770 push_pool_constant_bytecodes(ByteCode *bytecodes, CrwCpoolIndex index) 771 { 772 ByteOffset nbytes = 0; 773 774 if ( index == (index&0x7F) ) { 775 bytecodes[nbytes++] = (ByteCode)JVM_OPC_ldc; 776 } else { 777 bytecodes[nbytes++] = (ByteCode)JVM_OPC_ldc_w; 778 bytecodes[nbytes++] = (ByteCode)((index >> 8) & 0xFF); 779 } 780 bytecodes[nbytes++] = (ByteCode)(index & 0xFF); 781 return nbytes; 782 } 783 784 static ByteOffset 785 push_short_constant_bytecodes(ByteCode *bytecodes, unsigned number) 786 { 787 ByteOffset nbytes = 0; 788 789 if ( number <= 5 ) { 790 bytecodes[nbytes++] = (ByteCode)(JVM_OPC_iconst_0+number); 791 } else if ( number == (number&0x7F) ) { 792 bytecodes[nbytes++] = (ByteCode)JVM_OPC_bipush; 793 bytecodes[nbytes++] = (ByteCode)(number & 0xFF); 794 } else { 795 bytecodes[nbytes++] = (ByteCode)JVM_OPC_sipush; 796 bytecodes[nbytes++] = (ByteCode)((number >> 8) & 0xFF); 797 bytecodes[nbytes++] = (ByteCode)(number & 0xFF); 798 } 799 return nbytes; 800 } 801 802 static ByteOffset 803 injection_template(MethodImage *mi, ByteCode *bytecodes, ByteOffset max_nbytes, 804 CrwCpoolIndex method_index) 805 { 806 CrwClassImage * ci; 807 ByteOffset nbytes = 0; 808 unsigned max_stack; 809 int add_dup; 810 int add_aload; 811 int push_cnum; 812 int push_mnum; 813 814 ci = mi->ci; 815 816 CRW_ASSERT(ci, bytecodes!=NULL); 817 818 if ( method_index == 0 ) { 819 return 0; 820 } 821 822 if ( method_index == ci->newarray_tracker_index) { 823 max_stack = mi->max_stack + 1; 824 add_dup = JNI_TRUE; 825 add_aload = JNI_FALSE; 826 push_cnum = JNI_FALSE; 827 push_mnum = JNI_FALSE; 828 } else if ( method_index == ci->object_init_tracker_index) { 829 max_stack = mi->max_stack + 1; 830 add_dup = JNI_FALSE; 831 add_aload = JNI_TRUE; 832 push_cnum = JNI_FALSE; 833 push_mnum = JNI_FALSE; 834 } else { 835 max_stack = mi->max_stack + 2; 836 add_dup = JNI_FALSE; 837 add_aload = JNI_FALSE; 838 push_cnum = JNI_TRUE; 839 push_mnum = JNI_TRUE; 840 } 841 842 if ( add_dup ) { 843 bytecodes[nbytes++] = (ByteCode)JVM_OPC_dup; 844 } 845 if ( add_aload ) { 846 bytecodes[nbytes++] = (ByteCode)JVM_OPC_aload_0; 847 } 848 if ( push_cnum ) { 849 if ( ci->number == (ci->number & 0x7FFF) ) { 850 nbytes += push_short_constant_bytecodes(bytecodes+nbytes, 851 ci->number); 852 } else { 853 CRW_ASSERT(ci, ci->class_number_index!=0); 854 nbytes += push_pool_constant_bytecodes(bytecodes+nbytes, 855 ci->class_number_index); 856 } 857 } 858 if ( push_mnum ) { 859 nbytes += push_short_constant_bytecodes(bytecodes+nbytes, 860 mi->number); 861 } 862 bytecodes[nbytes++] = (ByteCode)JVM_OPC_invokestatic; 863 bytecodes[nbytes++] = (ByteCode)(method_index >> 8); 864 bytecodes[nbytes++] = (ByteCode)method_index; 865 bytecodes[nbytes] = 0; 866 CRW_ASSERT(ci, nbytes<max_nbytes); 867 868 /* Make sure the new max_stack is appropriate */ 869 if ( max_stack > mi->new_max_stack ) { 870 mi->new_max_stack = max_stack; 871 } 872 return nbytes; 873 } 874 875 /* Called to create injection code at entry to a method */ 876 static ByteOffset 877 entry_injection_code(MethodImage *mi, ByteCode *bytecodes, ByteOffset len) 878 { 879 CrwClassImage * ci; 880 ByteOffset nbytes = 0; 881 882 CRW_ASSERT_MI(mi); 883 884 ci = mi->ci; 885 886 if ( mi->object_init_method ) { 887 nbytes = injection_template(mi, 888 bytecodes, len, ci->object_init_tracker_index); 889 } 890 if ( !mi->skip_call_return_sites ) { 891 nbytes += injection_template(mi, 892 bytecodes+nbytes, len-nbytes, ci->call_tracker_index); 893 } 894 return nbytes; 895 } 896 897 /* Called to create injection code before an opcode */ 898 static ByteOffset 899 before_injection_code(MethodImage *mi, ClassOpcode opcode, 900 ByteCode *bytecodes, ByteOffset len) 901 { 902 ByteOffset nbytes = 0; 903 904 905 CRW_ASSERT_MI(mi); 906 switch ( opcode ) { 907 case JVM_OPC_return: 908 case JVM_OPC_ireturn: 909 case JVM_OPC_lreturn: 910 case JVM_OPC_freturn: 911 case JVM_OPC_dreturn: 912 case JVM_OPC_areturn: 913 if ( !mi->skip_call_return_sites ) { 914 nbytes = injection_template(mi, 915 bytecodes, len, mi->ci->return_tracker_index); 916 } 917 break; 918 default: 919 break; 920 } 921 return nbytes; 922 } 923 924 /* Called to create injection code after an opcode */ 925 static ByteOffset 926 after_injection_code(MethodImage *mi, ClassOpcode opcode, 927 ByteCode *bytecodes, ByteOffset len) 928 { 929 CrwClassImage* ci; 930 ByteOffset nbytes; 931 932 ci = mi->ci; 933 nbytes = 0; 934 935 CRW_ASSERT_MI(mi); 936 switch ( opcode ) { 937 case JVM_OPC_new: 938 /* Can't inject here cannot pass around uninitialized object */ 939 break; 940 case JVM_OPC_newarray: 941 case JVM_OPC_anewarray: 942 case JVM_OPC_multianewarray: 943 nbytes = injection_template(mi, 944 bytecodes, len, ci->newarray_tracker_index); 945 break; 946 default: 947 break; 948 } 949 return nbytes; 950 } 951 952 /* Actually inject the bytecodes */ 953 static void 954 inject_bytecodes(MethodImage *mi, ByteOffset at, 955 ByteCode *bytecodes, ByteOffset len) 956 { 957 Injection injection; 958 CrwClassImage *ci; 959 960 ci = mi->ci; 961 CRW_ASSERT_MI(mi); 962 CRW_ASSERT(ci, at <= mi->code_len); 963 964 injection = mi->injections[at]; 965 966 CRW_ASSERT(ci, len <= LARGEST_INJECTION/2); 967 CRW_ASSERT(ci, injection.len+len <= LARGEST_INJECTION); 968 969 /* Either start an injection area or concatenate to what is there */ 970 if ( injection.code == NULL ) { 971 CRW_ASSERT(ci, injection.len==0); 972 injection.code = (ByteCode *)allocate_clean(ci, LARGEST_INJECTION+1); 973 } 974 975 (void)memcpy(injection.code+injection.len, bytecodes, len); 976 injection.len += len; 977 injection.code[injection.len] = 0; 978 mi->injections[at] = injection; 979 ci->injection_count++; 980 } 981 982 /* ----------------------------------------------------------------- */ 983 /* Method handling functions */ 984 985 static MethodImage * 986 method_init(CrwClassImage *ci, unsigned mnum, ByteOffset code_len) 987 { 988 MethodImage * mi; 989 ByteOffset i; 990 991 mi = (MethodImage*)allocate_clean(ci, (int)sizeof(MethodImage)); 992 mi->ci = ci; 993 mi->name = ci->method_name[mnum]; 994 mi->descr = ci->method_descr[mnum]; 995 mi->code_len = code_len; 996 mi->map = (ByteOffset*)allocate_clean(ci, 997 (int)((code_len+1)*sizeof(ByteOffset))); 998 for(i=0; i<=code_len; i++) { 999 mi->map[i] = i; 1000 } 1001 mi->widening = (signed char*)allocate_clean(ci, code_len+1); 1002 mi->injections = (Injection *)allocate_clean(ci, 1003 (int)((code_len+1)*sizeof(Injection))); 1004 mi->number = mnum; 1005 ci->current_mi = mi; 1006 return mi; 1007 } 1008 1009 static void 1010 method_term(MethodImage *mi) 1011 { 1012 CrwClassImage *ci; 1013 1014 ci = mi->ci; 1015 CRW_ASSERT_MI(mi); 1016 if ( mi->map != NULL ) { 1017 deallocate(ci, (void*)mi->map); 1018 mi->map = NULL; 1019 } 1020 if ( mi->widening != NULL ) { 1021 deallocate(ci, (void*)mi->widening); 1022 mi->widening = NULL; 1023 } 1024 if ( mi->injections != NULL ) { 1025 ByteOffset i; 1026 for(i=0; i<= mi->code_len; i++) { 1027 if ( mi->injections[i].code != NULL ) { 1028 deallocate(ci, (void*)mi->injections[i].code); 1029 mi->injections[i].code = NULL; 1030 } 1031 } 1032 deallocate(ci, (void*)mi->injections); 1033 mi->injections = NULL; 1034 } 1035 ci->current_mi = NULL; 1036 deallocate(ci, (void*)mi); 1037 } 1038 1039 static ByteOffset 1040 input_code_offset(MethodImage *mi) 1041 { 1042 CRW_ASSERT_MI(mi); 1043 return (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes); 1044 } 1045 1046 static void 1047 rewind_to_beginning_of_input_bytecodes(MethodImage *mi) 1048 { 1049 CRW_ASSERT_MI(mi); 1050 mi->ci->input_position = mi->start_of_input_bytecodes; 1051 } 1052 1053 /* Starting at original byte position 'at', add 'offset' to it's new 1054 * location. This may be a negative value. 1055 * NOTE: That this map is not the new bytecode location of the opcode 1056 * but the new bytecode location that should be used when 1057 * a goto or jump instruction was targeting the old bytecode 1058 * location. 1059 */ 1060 static void 1061 adjust_map(MethodImage *mi, ByteOffset at, ByteOffset offset) 1062 { 1063 ByteOffset i; 1064 1065 CRW_ASSERT_MI(mi); 1066 for (i = at; i <= mi->code_len; ++i) { 1067 mi->map[i] += offset; 1068 } 1069 } 1070 1071 static void 1072 widen(MethodImage *mi, ByteOffset at, ByteOffset len) 1073 { 1074 int delta; 1075 1076 CRW_ASSERT(mi->ci, at <= mi->code_len); 1077 delta = len - mi->widening[at]; 1078 /* Adjust everything from the current input location by delta */ 1079 adjust_map(mi, input_code_offset(mi), delta); 1080 /* Mark at beginning of instruction */ 1081 mi->widening[at] = (signed char)len; 1082 } 1083 1084 static void 1085 verify_opc_wide(CrwClassImage *ci, ClassOpcode wopcode) 1086 { 1087 switch (wopcode) { 1088 case JVM_OPC_aload: case JVM_OPC_astore: 1089 case JVM_OPC_fload: case JVM_OPC_fstore: 1090 case JVM_OPC_iload: case JVM_OPC_istore: 1091 case JVM_OPC_lload: case JVM_OPC_lstore: 1092 case JVM_OPC_dload: case JVM_OPC_dstore: 1093 case JVM_OPC_ret: case JVM_OPC_iinc: 1094 break; 1095 default: 1096 CRW_FATAL(ci, "Invalid opcode supplied to wide opcode"); 1097 break; 1098 } 1099 } 1100 1101 static unsigned 1102 opcode_length(CrwClassImage *ci, ClassOpcode opcode) 1103 { 1104 /* Define array that holds length of an opcode */ 1105 static unsigned char _opcode_length[JVM_OPC_MAX+1] = 1106 JVM_OPCODE_LENGTH_INITIALIZER; 1107 1108 if ( opcode > JVM_OPC_MAX ) { 1109 CRW_FATAL(ci, "Invalid opcode supplied to opcode_length()"); 1110 } 1111 return _opcode_length[opcode]; 1112 } 1113 1114 /* Walk one instruction and inject instrumentation */ 1115 static void 1116 inject_for_opcode(MethodImage *mi) 1117 { 1118 CrwClassImage * ci; 1119 ClassOpcode opcode; 1120 int pos; 1121 1122 CRW_ASSERT_MI(mi); 1123 ci = mi->ci; 1124 pos = input_code_offset(mi); 1125 opcode = readU1(ci); 1126 1127 if (opcode == JVM_OPC_wide) { 1128 ClassOpcode wopcode; 1129 1130 wopcode = readU1(ci); 1131 /* lvIndex not used */ 1132 (void)readU2(ci); 1133 verify_opc_wide(ci, wopcode); 1134 if ( wopcode==JVM_OPC_iinc ) { 1135 (void)readU1(ci); 1136 (void)readU1(ci); 1137 } 1138 } else { 1139 1140 ByteCode bytecodes[LARGEST_INJECTION+1]; 1141 int header; 1142 int instr_len; 1143 int low; 1144 int high; 1145 int npairs; 1146 ByteOffset len; 1147 1148 /* Get bytecodes to inject before this opcode */ 1149 len = before_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes)); 1150 if ( len > 0 ) { 1151 inject_bytecodes(mi, pos, bytecodes, len); 1152 /* Adjust map after processing this opcode */ 1153 } 1154 1155 /* Process this opcode */ 1156 switch (opcode) { 1157 case JVM_OPC_tableswitch: 1158 header = NEXT_4BYTE_BOUNDARY(pos); 1159 skip(ci, header - (pos+1)); 1160 (void)readU4(ci); 1161 low = readU4(ci); 1162 high = readU4(ci); 1163 skip(ci, (high+1-low) * 4); 1164 break; 1165 case JVM_OPC_lookupswitch: 1166 header = NEXT_4BYTE_BOUNDARY(pos); 1167 skip(ci, header - (pos+1)); 1168 (void)readU4(ci); 1169 npairs = readU4(ci); 1170 skip(ci, npairs * 8); 1171 break; 1172 default: 1173 instr_len = opcode_length(ci, opcode); 1174 skip(ci, instr_len-1); 1175 break; 1176 } 1177 1178 /* Get position after this opcode is processed */ 1179 pos = input_code_offset(mi); 1180 1181 /* Adjust for any before_injection_code() */ 1182 if ( len > 0 ) { 1183 /* Adjust everything past this opcode. 1184 * Why past it? Because we want any jumps to this bytecode loc 1185 * to go to the injected code, not where the opcode 1186 * was moved too. 1187 * Consider a 'return' opcode that is jumped too. 1188 * NOTE: This may not be correct in all cases, but will 1189 * when we are only dealing with non-variable opcodes 1190 * like the return opcodes. Be careful if the 1191 * before_injection_code() changes to include other 1192 * opcodes that have variable length. 1193 */ 1194 adjust_map(mi, pos, len); 1195 } 1196 1197 /* Get bytecodes to inject after this opcode */ 1198 len = after_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes)); 1199 if ( len > 0 ) { 1200 inject_bytecodes(mi, pos, bytecodes, len); 1201 1202 /* Adjust for any after_injection_code() */ 1203 adjust_map(mi, pos, len); 1204 } 1205 1206 } 1207 } 1208 1209 /* Map original bytecode location to it's new location. (See adjust_map()). */ 1210 static ByteOffset 1211 method_code_map(MethodImage *mi, ByteOffset pos) 1212 { 1213 CRW_ASSERT_MI(mi); 1214 CRW_ASSERT(mi->ci, pos <= mi->code_len); 1215 return mi->map[pos]; 1216 } 1217 1218 static int 1219 adjust_instruction(MethodImage *mi) 1220 { 1221 CrwClassImage * ci; 1222 ClassOpcode opcode; 1223 int pos; 1224 int new_pos; 1225 1226 CRW_ASSERT_MI(mi); 1227 ci = mi->ci; 1228 pos = input_code_offset(mi); 1229 new_pos = method_code_map(mi,pos); 1230 1231 opcode = readU1(ci); 1232 1233 if (opcode == JVM_OPC_wide) { 1234 ClassOpcode wopcode; 1235 1236 wopcode = readU1(ci); 1237 /* lvIndex not used */ 1238 (void)readU2(ci); 1239 verify_opc_wide(ci, wopcode); 1240 if ( wopcode==JVM_OPC_iinc ) { 1241 (void)readU1(ci); 1242 (void)readU1(ci); 1243 } 1244 } else { 1245 1246 int widened; 1247 int header; 1248 int newHeader; 1249 int low; 1250 int high; 1251 int new_pad; 1252 int old_pad; 1253 int delta; 1254 int new_delta; 1255 int delta_pad; 1256 int npairs; 1257 int instr_len; 1258 1259 switch (opcode) { 1260 1261 case JVM_OPC_tableswitch: 1262 widened = mi->widening[pos]; 1263 header = NEXT_4BYTE_BOUNDARY(pos); 1264 newHeader = NEXT_4BYTE_BOUNDARY(new_pos); 1265 1266 skip(ci, header - (pos+1)); 1267 1268 delta = readU4(ci); 1269 low = readU4(ci); 1270 high = readU4(ci); 1271 skip(ci, (high+1-low) * 4); 1272 new_pad = newHeader - new_pos; 1273 old_pad = header - pos; 1274 delta_pad = new_pad - old_pad; 1275 if (widened != delta_pad) { 1276 widen(mi, pos, delta_pad); 1277 return 0; 1278 } 1279 break; 1280 1281 case JVM_OPC_lookupswitch: 1282 widened = mi->widening[pos]; 1283 header = NEXT_4BYTE_BOUNDARY(pos); 1284 newHeader = NEXT_4BYTE_BOUNDARY(new_pos); 1285 1286 skip(ci, header - (pos+1)); 1287 1288 delta = readU4(ci); 1289 npairs = readU4(ci); 1290 skip(ci, npairs * 8); 1291 new_pad = newHeader - new_pos; 1292 old_pad = header - pos; 1293 delta_pad = new_pad - old_pad; 1294 if (widened != delta_pad) { 1295 widen(mi, pos, delta_pad); 1296 return 0; 1297 } 1298 break; 1299 1300 case JVM_OPC_jsr: case JVM_OPC_goto: 1301 case JVM_OPC_ifeq: case JVM_OPC_ifge: case JVM_OPC_ifgt: 1302 case JVM_OPC_ifle: case JVM_OPC_iflt: case JVM_OPC_ifne: 1303 case JVM_OPC_if_icmpeq: case JVM_OPC_if_icmpne: case JVM_OPC_if_icmpge: 1304 case JVM_OPC_if_icmpgt: case JVM_OPC_if_icmple: case JVM_OPC_if_icmplt: 1305 case JVM_OPC_if_acmpeq: case JVM_OPC_if_acmpne: 1306 case JVM_OPC_ifnull: case JVM_OPC_ifnonnull: 1307 widened = mi->widening[pos]; 1308 delta = readS2(ci); 1309 if (widened == 0) { 1310 new_delta = method_code_map(mi,pos+delta) - new_pos; 1311 if ((new_delta < -32768) || (new_delta > 32767)) { 1312 switch (opcode) { 1313 case JVM_OPC_jsr: case JVM_OPC_goto: 1314 widen(mi, pos, 2); 1315 break; 1316 default: 1317 widen(mi, pos, 5); 1318 break; 1319 } 1320 return 0; 1321 } 1322 } 1323 break; 1324 1325 case JVM_OPC_jsr_w: 1326 case JVM_OPC_goto_w: 1327 (void)readU4(ci); 1328 break; 1329 1330 default: 1331 instr_len = opcode_length(ci, opcode); 1332 skip(ci, instr_len-1); 1333 break; 1334 } 1335 } 1336 return 1; 1337 } 1338 1339 static void 1340 write_instruction(MethodImage *mi) 1341 { 1342 CrwClassImage * ci; 1343 ClassOpcode opcode; 1344 ByteOffset new_code_len; 1345 int pos; 1346 int new_pos; 1347 1348 CRW_ASSERT_MI(mi); 1349 ci = mi->ci; 1350 pos = input_code_offset(mi); 1351 new_pos = method_code_map(mi,pos); 1352 new_code_len = mi->injections[pos].len; 1353 if (new_code_len > 0) { 1354 write_bytes(ci, (void*)mi->injections[pos].code, new_code_len); 1355 } 1356 1357 opcode = readU1(ci); 1358 if (opcode == JVM_OPC_wide) { 1359 ClassOpcode wopcode; 1360 1361 writeU1(ci, opcode); 1362 1363 wopcode = copyU1(ci); 1364 /* lvIndex not used */ 1365 (void)copyU2(ci); 1366 verify_opc_wide(ci, wopcode); 1367 if ( wopcode==JVM_OPC_iinc ) { 1368 (void)copyU1(ci); 1369 (void)copyU1(ci); 1370 } 1371 } else { 1372 1373 ClassOpcode new_opcode; 1374 int header; 1375 int newHeader; 1376 int low; 1377 int high; 1378 int i; 1379 int npairs; 1380 int widened; 1381 int instr_len; 1382 int delta; 1383 int new_delta; 1384 1385 switch (opcode) { 1386 1387 case JVM_OPC_tableswitch: 1388 header = NEXT_4BYTE_BOUNDARY(pos); 1389 newHeader = NEXT_4BYTE_BOUNDARY(new_pos); 1390 1391 skip(ci, header - (pos+1)); 1392 1393 delta = readU4(ci); 1394 new_delta = method_code_map(mi,pos+delta) - new_pos; 1395 low = readU4(ci); 1396 high = readU4(ci); 1397 1398 writeU1(ci, opcode); 1399 for (i = new_pos+1; i < newHeader; ++i) { 1400 writeU1(ci, 0); 1401 } 1402 writeU4(ci, new_delta); 1403 writeU4(ci, low); 1404 writeU4(ci, high); 1405 1406 for (i = low; i <= high; ++i) { 1407 delta = readU4(ci); 1408 new_delta = method_code_map(mi,pos+delta) - new_pos; 1409 writeU4(ci, new_delta); 1410 } 1411 break; 1412 1413 case JVM_OPC_lookupswitch: 1414 header = NEXT_4BYTE_BOUNDARY(pos); 1415 newHeader = NEXT_4BYTE_BOUNDARY(new_pos); 1416 1417 skip(ci, header - (pos+1)); 1418 1419 delta = readU4(ci); 1420 new_delta = method_code_map(mi,pos+delta) - new_pos; 1421 npairs = readU4(ci); 1422 writeU1(ci, opcode); 1423 for (i = new_pos+1; i < newHeader; ++i) { 1424 writeU1(ci, 0); 1425 } 1426 writeU4(ci, new_delta); 1427 writeU4(ci, npairs); 1428 for (i = 0; i< npairs; ++i) { 1429 unsigned match = readU4(ci); 1430 delta = readU4(ci); 1431 new_delta = method_code_map(mi,pos+delta) - new_pos; 1432 writeU4(ci, match); 1433 writeU4(ci, new_delta); 1434 } 1435 break; 1436 1437 case JVM_OPC_jsr: case JVM_OPC_goto: 1438 case JVM_OPC_ifeq: case JVM_OPC_ifge: case JVM_OPC_ifgt: 1439 case JVM_OPC_ifle: case JVM_OPC_iflt: case JVM_OPC_ifne: 1440 case JVM_OPC_if_icmpeq: case JVM_OPC_if_icmpne: case JVM_OPC_if_icmpge: 1441 case JVM_OPC_if_icmpgt: case JVM_OPC_if_icmple: case JVM_OPC_if_icmplt: 1442 case JVM_OPC_if_acmpeq: case JVM_OPC_if_acmpne: 1443 case JVM_OPC_ifnull: case JVM_OPC_ifnonnull: 1444 widened = mi->widening[pos]; 1445 delta = readS2(ci); 1446 new_delta = method_code_map(mi,pos+delta) - new_pos; 1447 new_opcode = opcode; 1448 if (widened == 0) { 1449 writeU1(ci, opcode); 1450 writeU2(ci, new_delta); 1451 } else if (widened == 2) { 1452 switch (opcode) { 1453 case JVM_OPC_jsr: 1454 new_opcode = JVM_OPC_jsr_w; 1455 break; 1456 case JVM_OPC_goto: 1457 new_opcode = JVM_OPC_goto_w; 1458 break; 1459 default: 1460 CRW_FATAL(ci, "unexpected opcode"); 1461 break; 1462 } 1463 writeU1(ci, new_opcode); 1464 writeU4(ci, new_delta); 1465 } else if (widened == 5) { 1466 switch (opcode) { 1467 case JVM_OPC_ifeq: 1468 new_opcode = JVM_OPC_ifne; 1469 break; 1470 case JVM_OPC_ifge: 1471 new_opcode = JVM_OPC_iflt; 1472 break; 1473 case JVM_OPC_ifgt: 1474 new_opcode = JVM_OPC_ifle; 1475 break; 1476 case JVM_OPC_ifle: 1477 new_opcode = JVM_OPC_ifgt; 1478 break; 1479 case JVM_OPC_iflt: 1480 new_opcode = JVM_OPC_ifge; 1481 break; 1482 case JVM_OPC_ifne: 1483 new_opcode = JVM_OPC_ifeq; 1484 break; 1485 case JVM_OPC_if_icmpeq: 1486 new_opcode = JVM_OPC_if_icmpne; 1487 break; 1488 case JVM_OPC_if_icmpne: 1489 new_opcode = JVM_OPC_if_icmpeq; 1490 break; 1491 case JVM_OPC_if_icmpge: 1492 new_opcode = JVM_OPC_if_icmplt; 1493 break; 1494 case JVM_OPC_if_icmpgt: 1495 new_opcode = JVM_OPC_if_icmple; 1496 break; 1497 case JVM_OPC_if_icmple: 1498 new_opcode = JVM_OPC_if_icmpgt; 1499 break; 1500 case JVM_OPC_if_icmplt: 1501 new_opcode = JVM_OPC_if_icmpge; 1502 break; 1503 case JVM_OPC_if_acmpeq: 1504 new_opcode = JVM_OPC_if_acmpne; 1505 break; 1506 case JVM_OPC_if_acmpne: 1507 new_opcode = JVM_OPC_if_acmpeq; 1508 break; 1509 case JVM_OPC_ifnull: 1510 new_opcode = JVM_OPC_ifnonnull; 1511 break; 1512 case JVM_OPC_ifnonnull: 1513 new_opcode = JVM_OPC_ifnull; 1514 break; 1515 default: 1516 CRW_FATAL(ci, "Unexpected opcode"); 1517 break; 1518 } 1519 writeU1(ci, new_opcode); /* write inverse branch */ 1520 writeU2(ci, 3 + 5); /* beyond if and goto_w */ 1521 writeU1(ci, JVM_OPC_goto_w); /* add a goto_w */ 1522 writeU4(ci, new_delta-3); /* write new and wide delta */ 1523 } else { 1524 CRW_FATAL(ci, "Unexpected widening"); 1525 } 1526 break; 1527 1528 case JVM_OPC_jsr_w: 1529 case JVM_OPC_goto_w: 1530 delta = readU4(ci); 1531 new_delta = method_code_map(mi,pos+delta) - new_pos; 1532 writeU1(ci, opcode); 1533 writeU4(ci, new_delta); 1534 break; 1535 1536 default: 1537 instr_len = opcode_length(ci, opcode); 1538 writeU1(ci, opcode); 1539 copy(ci, instr_len-1); 1540 break; 1541 } 1542 } 1543 } 1544 1545 static void 1546 method_inject_and_write_code(MethodImage *mi) 1547 { 1548 ByteCode bytecodes[LARGEST_INJECTION+1]; 1549 ByteOffset len; 1550 1551 CRW_ASSERT_MI(mi); 1552 1553 /* Do injections */ 1554 rewind_to_beginning_of_input_bytecodes(mi); 1555 len = entry_injection_code(mi, bytecodes, (int)sizeof(bytecodes)); 1556 if ( len > 0 ) { 1557 int pos; 1558 1559 pos = 0; 1560 inject_bytecodes(mi, pos, bytecodes, len); 1561 /* Adjust pos 0 to map to new pos 0, you never want to 1562 * jump into this entry code injection. So the new pos 0 1563 * will be past this entry_injection_code(). 1564 */ 1565 adjust_map(mi, pos, len); /* Inject before behavior */ 1566 } 1567 while (input_code_offset(mi) < mi->code_len) { 1568 inject_for_opcode(mi); 1569 } 1570 1571 /* Adjust instructions */ 1572 rewind_to_beginning_of_input_bytecodes(mi); 1573 while (input_code_offset(mi) < mi->code_len) { 1574 if (!adjust_instruction(mi)) { 1575 rewind_to_beginning_of_input_bytecodes(mi); 1576 } 1577 } 1578 1579 /* Write new instructions */ 1580 rewind_to_beginning_of_input_bytecodes(mi); 1581 while (input_code_offset(mi) < mi->code_len) { 1582 write_instruction(mi); 1583 } 1584 } 1585 1586 static void 1587 copy_attribute(CrwClassImage *ci) 1588 { 1589 int len; 1590 1591 (void)copyU2(ci); 1592 len = copyU4(ci); 1593 copy(ci, len); 1594 } 1595 1596 static void 1597 copy_attributes(CrwClassImage *ci) 1598 { 1599 unsigned i; 1600 unsigned count; 1601 1602 count = copyU2(ci); 1603 for (i = 0; i < count; ++i) { 1604 copy_attribute(ci); 1605 } 1606 } 1607 1608 static void 1609 copy_all_fields(CrwClassImage *ci) 1610 { 1611 unsigned i; 1612 unsigned count; 1613 1614 count = copyU2(ci); 1615 for (i = 0; i < count; ++i) { 1616 /* access, name, descriptor */ 1617 copy(ci, 6); 1618 copy_attributes(ci); 1619 } 1620 } 1621 1622 static void 1623 write_line_table(MethodImage *mi) 1624 { 1625 unsigned i; 1626 unsigned count; 1627 CrwClassImage * ci; 1628 1629 CRW_ASSERT_MI(mi); 1630 ci = mi->ci; 1631 (void)copyU4(ci); 1632 count = copyU2(ci); 1633 for(i=0; i<count; i++) { 1634 ByteOffset start_pc; 1635 ByteOffset new_start_pc; 1636 1637 start_pc = readU2(ci); 1638 1639 if ( start_pc == 0 ) { 1640 new_start_pc = 0; /* Don't skip entry injection code. */ 1641 } else { 1642 new_start_pc = method_code_map(mi, start_pc); 1643 } 1644 1645 writeU2(ci, new_start_pc); 1646 (void)copyU2(ci); 1647 } 1648 } 1649 1650 /* Used for LocalVariableTable and LocalVariableTypeTable attributes */ 1651 static void 1652 write_var_table(MethodImage *mi) 1653 { 1654 unsigned i; 1655 unsigned count; 1656 CrwClassImage * ci; 1657 1658 CRW_ASSERT_MI(mi); 1659 ci = mi->ci; 1660 (void)copyU4(ci); 1661 count = copyU2(ci); 1662 for(i=0; i<count; i++) { 1663 ByteOffset start_pc; 1664 ByteOffset new_start_pc; 1665 ByteOffset length; 1666 ByteOffset new_length; 1667 ByteOffset end_pc; 1668 ByteOffset new_end_pc; 1669 1670 start_pc = readU2(ci); 1671 length = readU2(ci); 1672 1673 if ( start_pc == 0 ) { 1674 new_start_pc = 0; /* Don't skip entry injection code. */ 1675 } else { 1676 new_start_pc = method_code_map(mi, start_pc); 1677 } 1678 end_pc = start_pc + length; 1679 new_end_pc = method_code_map(mi, end_pc); 1680 new_length = new_end_pc - new_start_pc; 1681 1682 writeU2(ci, new_start_pc); 1683 writeU2(ci, new_length); 1684 (void)copyU2(ci); 1685 (void)copyU2(ci); 1686 (void)copyU2(ci); 1687 } 1688 } 1689 1690 /* The uoffset field is u2 or u4 depending on the code_len. 1691 * Note that the code_len is likely changing, so be careful here. 1692 */ 1693 static unsigned 1694 readUoffset(MethodImage *mi) 1695 { 1696 if ( mi->code_len > 65535 ) { 1697 return readU4(mi->ci); 1698 } 1699 return readU2(mi->ci); 1700 } 1701 1702 static void 1703 writeUoffset(MethodImage *mi, unsigned val) 1704 { 1705 if ( mi->new_code_len > 65535 ) { 1706 writeU4(mi->ci, val); 1707 } 1708 writeU2(mi->ci, val); 1709 } 1710 1711 static unsigned 1712 copyUoffset(MethodImage *mi) 1713 { 1714 unsigned uoffset; 1715 1716 uoffset = readUoffset(mi); 1717 writeUoffset(mi, uoffset); 1718 return uoffset; 1719 } 1720 1721 /* Copy over verification_type_info structure */ 1722 static void 1723 copy_verification_types(MethodImage *mi, int ntypes) 1724 { 1725 /* If there were ntypes, we just copy that over, no changes */ 1726 if ( ntypes > 0 ) { 1727 int j; 1728 1729 for ( j = 0 ; j < ntypes ; j++ ) { 1730 unsigned tag; 1731 1732 tag = copyU1(mi->ci); 1733 switch ( tag ) { 1734 case JVM_ITEM_Object: 1735 (void)copyU2(mi->ci); /* Constant pool entry */ 1736 break; 1737 case JVM_ITEM_Uninitialized: 1738 /* Code offset for 'new' opcode is for this object */ 1739 writeUoffset(mi, method_code_map(mi, readUoffset(mi))); 1740 break; 1741 } 1742 } 1743 } 1744 } 1745 1746 /* Process the StackMapTable attribute. We didn't add any basic blocks 1747 * so the frame count remains the same but we may need to process the 1748 * frame types due to offset changes putting things out of range. 1749 */ 1750 static void 1751 write_stackmap_table(MethodImage *mi) 1752 { 1753 CrwClassImage *ci; 1754 CrwPosition save_position; 1755 ByteOffset last_pc; 1756 ByteOffset last_new_pc; 1757 unsigned i; 1758 unsigned attr_len; 1759 unsigned new_attr_len; 1760 unsigned count; 1761 unsigned delta_adj; 1762 1763 CRW_ASSERT_MI(mi); 1764 ci = mi->ci; 1765 1766 /* Save the position of the attribute length so we can fix it later */ 1767 save_position = ci->output_position; 1768 attr_len = copyU4(ci); 1769 count = copyUoffset(mi); /* uoffset: number_of_entries */ 1770 if ( count == 0 ) { 1771 CRW_ASSERT(ci, attr_len==2); 1772 return; 1773 } 1774 1775 /* Process entire stackmap */ 1776 last_pc = 0; 1777 last_new_pc = 0; 1778 delta_adj = 0; 1779 for ( i = 0 ; i < count ; i++ ) { 1780 ByteOffset new_pc=0; /* new pc in instrumented code */ 1781 unsigned ft; /* frame_type */ 1782 int delta=0; /* pc delta */ 1783 int new_delta=0; /* new pc delta */ 1784 1785 ft = readU1(ci); 1786 if ( ft <= 63 ) { 1787 /* Frame Type: same_frame ([0,63]) */ 1788 unsigned new_ft; /* new frame_type */ 1789 1790 delta = (delta_adj + ft); 1791 new_pc = method_code_map(mi, last_pc + delta); 1792 new_delta = new_pc - last_new_pc; 1793 new_ft = (new_delta - delta_adj); 1794 if ( new_ft > 63 ) { 1795 /* Change to same_frame_extended (251) */ 1796 new_ft = 251; 1797 writeU1(ci, new_ft); 1798 writeUoffset(mi, (new_delta - delta_adj)); 1799 } else { 1800 writeU1(ci, new_ft); 1801 } 1802 } else if ( ft >= 64 && ft <= 127 ) { 1803 /* Frame Type: same_locals_1_stack_item_frame ([64,127]) */ 1804 unsigned new_ft; /* new frame_type */ 1805 1806 delta = (delta_adj + ft - 64); 1807 new_pc = method_code_map(mi, last_pc + delta); 1808 new_delta = new_pc - last_new_pc; 1809 if ( (new_delta - delta_adj) > 63 ) { 1810 /* Change to same_locals_1_stack_item_frame_extended (247) */ 1811 new_ft = 247; 1812 writeU1(ci, new_ft); 1813 writeUoffset(mi, (new_delta - delta_adj)); 1814 } else { 1815 new_ft = (new_delta - delta_adj) + 64; 1816 writeU1(ci, new_ft); 1817 } 1818 copy_verification_types(mi, 1); 1819 } else if ( ft >= 128 && ft <= 246 ) { 1820 /* Frame Type: reserved_for_future_use ([128,246]) */ 1821 CRW_FATAL(ci, "Unknown frame type in StackMapTable attribute"); 1822 } else if ( ft == 247 ) { 1823 /* Frame Type: same_locals_1_stack_item_frame_extended (247) */ 1824 delta = (delta_adj + readUoffset(mi)); 1825 new_pc = method_code_map(mi, last_pc + delta); 1826 new_delta = new_pc - last_new_pc; 1827 writeU1(ci, ft); 1828 writeUoffset(mi, (new_delta - delta_adj)); 1829 copy_verification_types(mi, 1); 1830 } else if ( ft >= 248 && ft <= 250 ) { 1831 /* Frame Type: chop_frame ([248,250]) */ 1832 delta = (delta_adj + readUoffset(mi)); 1833 new_pc = method_code_map(mi, last_pc + delta); 1834 new_delta = new_pc - last_new_pc; 1835 writeU1(ci, ft); 1836 writeUoffset(mi, (new_delta - delta_adj)); 1837 } else if ( ft == 251 ) { 1838 /* Frame Type: same_frame_extended (251) */ 1839 delta = (delta_adj + readUoffset(mi)); 1840 new_pc = method_code_map(mi, last_pc + delta); 1841 new_delta = new_pc - last_new_pc; 1842 writeU1(ci, ft); 1843 writeUoffset(mi, (new_delta - delta_adj)); 1844 } else if ( ft >= 252 && ft <= 254 ) { 1845 /* Frame Type: append_frame ([252,254]) */ 1846 delta = (delta_adj + readUoffset(mi)); 1847 new_pc = method_code_map(mi, last_pc + delta); 1848 new_delta = new_pc - last_new_pc; 1849 writeU1(ci, ft); 1850 writeUoffset(mi, (new_delta - delta_adj)); 1851 copy_verification_types(mi, (ft - 251)); 1852 } else if ( ft == 255 ) { 1853 unsigned ntypes; 1854 1855 /* Frame Type: full_frame (255) */ 1856 delta = (delta_adj + readUoffset(mi)); 1857 new_pc = method_code_map(mi, last_pc + delta); 1858 new_delta = new_pc - last_new_pc; 1859 writeU1(ci, ft); 1860 writeUoffset(mi, (new_delta - delta_adj)); 1861 ntypes = copyU2(ci); /* ulocalvar */ 1862 copy_verification_types(mi, ntypes); 1863 ntypes = copyU2(ci); /* ustack */ 1864 copy_verification_types(mi, ntypes); 1865 } 1866 1867 /* Update last_pc and last_new_pc (save on calls to method_code_map) */ 1868 CRW_ASSERT(ci, delta >= 0); 1869 CRW_ASSERT(ci, new_delta >= 0); 1870 last_pc += delta; 1871 last_new_pc = new_pc; 1872 CRW_ASSERT(ci, last_pc <= mi->code_len); 1873 CRW_ASSERT(ci, last_new_pc <= mi->new_code_len); 1874 1875 /* Delta adjustment, all deltas are -1 now in attribute */ 1876 delta_adj = 1; 1877 } 1878 1879 /* Update the attribute length */ 1880 new_attr_len = ci->output_position - (save_position + 4); 1881 CRW_ASSERT(ci, new_attr_len >= attr_len); 1882 random_writeU4(ci, save_position, new_attr_len); 1883 } 1884 1885 /* Process the CLDC StackMap attribute. We didn't add any basic blocks 1886 * so the frame count remains the same but we may need to process the 1887 * frame types due to offset changes putting things out of range. 1888 */ 1889 static void 1890 write_cldc_stackmap_table(MethodImage *mi) 1891 { 1892 CrwClassImage *ci; 1893 CrwPosition save_position; 1894 unsigned i; 1895 unsigned attr_len; 1896 unsigned new_attr_len; 1897 unsigned count; 1898 1899 CRW_ASSERT_MI(mi); 1900 ci = mi->ci; 1901 1902 /* Save the position of the attribute length so we can fix it later */ 1903 save_position = ci->output_position; 1904 attr_len = copyU4(ci); 1905 count = copyUoffset(mi); /* uoffset: number_of_entries */ 1906 if ( count == 0 ) { 1907 CRW_ASSERT(ci, attr_len==2); 1908 return; 1909 } 1910 1911 /* Process entire stackmap */ 1912 for ( i = 0 ; i < count ; i++ ) { 1913 unsigned ntypes; 1914 1915 writeUoffset(mi, method_code_map(mi, readUoffset(mi))); 1916 ntypes = copyU2(ci); /* ulocalvar */ 1917 copy_verification_types(mi, ntypes); 1918 ntypes = copyU2(ci); /* ustack */ 1919 copy_verification_types(mi, ntypes); 1920 } 1921 1922 /* Update the attribute length */ 1923 new_attr_len = ci->output_position - (save_position + 4); 1924 CRW_ASSERT(ci, new_attr_len >= attr_len); 1925 random_writeU4(ci, save_position, new_attr_len); 1926 } 1927 1928 static void 1929 method_write_exception_table(MethodImage *mi) 1930 { 1931 unsigned i; 1932 unsigned count; 1933 CrwClassImage * ci; 1934 1935 CRW_ASSERT_MI(mi); 1936 ci = mi->ci; 1937 count = copyU2(ci); 1938 for(i=0; i<count; i++) { 1939 ByteOffset start_pc; 1940 ByteOffset new_start_pc; 1941 ByteOffset end_pc; 1942 ByteOffset new_end_pc; 1943 ByteOffset handler_pc; 1944 ByteOffset new_handler_pc; 1945 1946 start_pc = readU2(ci); 1947 end_pc = readU2(ci); 1948 handler_pc = readU2(ci); 1949 1950 new_start_pc = method_code_map(mi, start_pc); 1951 new_end_pc = method_code_map(mi, end_pc); 1952 new_handler_pc = method_code_map(mi, handler_pc); 1953 1954 writeU2(ci, new_start_pc); 1955 writeU2(ci, new_end_pc); 1956 writeU2(ci, new_handler_pc); 1957 (void)copyU2(ci); 1958 } 1959 } 1960 1961 static int 1962 attribute_match(CrwClassImage *ci, CrwCpoolIndex name_index, const char *name) 1963 { 1964 CrwConstantPoolEntry cs; 1965 int len; 1966 1967 CRW_ASSERT_CI(ci); 1968 CRW_ASSERT(ci, name!=NULL); 1969 len = (int)strlen(name); 1970 cs = cpool_entry(ci, name_index); 1971 if ( cs.len==len && strncmp(cs.ptr, name, len)==0) { 1972 return 1; 1973 } 1974 return 0; 1975 } 1976 1977 static void 1978 method_write_code_attribute(MethodImage *mi) 1979 { 1980 CrwClassImage * ci; 1981 CrwCpoolIndex name_index; 1982 1983 CRW_ASSERT_MI(mi); 1984 ci = mi->ci; 1985 name_index = copyU2(ci); 1986 if ( attribute_match(ci, name_index, "LineNumberTable") ) { 1987 write_line_table(mi); 1988 } else if ( attribute_match(ci, name_index, "LocalVariableTable") ) { 1989 write_var_table(mi); 1990 } else if ( attribute_match(ci, name_index, "LocalVariableTypeTable") ) { 1991 write_var_table(mi); /* Exact same format as the LocalVariableTable */ 1992 } else if ( attribute_match(ci, name_index, "StackMapTable") ) { 1993 write_stackmap_table(mi); 1994 } else if ( attribute_match(ci, name_index, "StackMap") ) { 1995 write_cldc_stackmap_table(mi); 1996 } else { 1997 unsigned len; 1998 len = copyU4(ci); 1999 copy(ci, len); 2000 } 2001 } 2002 2003 static int 2004 is_init_method(const char *name) 2005 { 2006 if ( name!=NULL && strcmp(name,"<init>")==0 ) { 2007 return JNI_TRUE; 2008 } 2009 return JNI_FALSE; 2010 } 2011 2012 static int 2013 is_clinit_method(const char *name) 2014 { 2015 if ( name!=NULL && strcmp(name,"<clinit>")==0 ) { 2016 return JNI_TRUE; 2017 } 2018 return JNI_FALSE; 2019 } 2020 2021 static int 2022 is_finalize_method(const char *name) 2023 { 2024 if ( name!=NULL && strcmp(name,"finalize")==0 ) { 2025 return JNI_TRUE; 2026 } 2027 return JNI_FALSE; 2028 } 2029 2030 static int 2031 skip_method(CrwClassImage *ci, const char *name, 2032 unsigned access_flags, ByteOffset code_len, 2033 int system_class, jboolean *pskip_call_return_sites) 2034 { 2035 *pskip_call_return_sites = JNI_FALSE; 2036 if ( system_class ) { 2037 if ( code_len == 1 && is_init_method(name) ) { 2038 return JNI_TRUE; 2039 } else if ( code_len == 1 && is_finalize_method(name) ) { 2040 return JNI_TRUE; 2041 } else if ( is_clinit_method(name) ) { 2042 return JNI_TRUE; 2043 } else if ( ci->is_thread_class && strcmp(name,"currentThread")==0 ) { 2044 return JNI_TRUE; 2045 } 2046 /* 2047 if ( access_flags & JVM_ACC_PRIVATE ) { 2048 *pskip_call_return_sites = JNI_TRUE; 2049 } 2050 */ 2051 } 2052 return JNI_FALSE; 2053 } 2054 2055 /* Process all code attributes */ 2056 static void 2057 method_write_bytecodes(CrwClassImage *ci, unsigned mnum, unsigned access_flags) 2058 { 2059 CrwPosition output_attr_len_position; 2060 CrwPosition output_max_stack_position; 2061 CrwPosition output_code_len_position; 2062 CrwPosition start_of_output_bytecodes; 2063 unsigned i; 2064 unsigned attr_len; 2065 unsigned max_stack; 2066 ByteOffset code_len; 2067 unsigned attr_count; 2068 unsigned new_attr_len; 2069 MethodImage * mi; 2070 jboolean object_init_method; 2071 jboolean skip_call_return_sites; 2072 2073 CRW_ASSERT_CI(ci); 2074 2075 /* Attribute Length */ 2076 output_attr_len_position = ci->output_position; 2077 attr_len = copyU4(ci); 2078 2079 /* Max Stack */ 2080 output_max_stack_position = ci->output_position; 2081 max_stack = copyU2(ci); 2082 2083 /* Max Locals */ 2084 (void)copyU2(ci); 2085 2086 /* Code Length */ 2087 output_code_len_position = ci->output_position; 2088 code_len = copyU4(ci); 2089 start_of_output_bytecodes = ci->output_position; 2090 2091 /* Some methods should not be instrumented */ 2092 object_init_method = JNI_FALSE; 2093 skip_call_return_sites = JNI_FALSE; 2094 if ( ci->is_object_class && 2095 is_init_method(ci->method_name[mnum]) && 2096 strcmp(ci->method_descr[mnum],"()V")==0 ) { 2097 object_init_method = JNI_TRUE; 2098 skip_call_return_sites = JNI_TRUE; 2099 } else if ( skip_method(ci, ci->method_name[mnum], access_flags, 2100 code_len, ci->system_class, &skip_call_return_sites) ) { 2101 /* Copy remainder minus already copied, the U2 max_stack, 2102 * U2 max_locals, and U4 code_length fields have already 2103 * been processed. 2104 */ 2105 copy(ci, attr_len - (2+2+4)); 2106 return; 2107 } 2108 2109 /* Start Injection */ 2110 mi = method_init(ci, mnum, code_len); 2111 mi->object_init_method = object_init_method; 2112 mi->access_flags = access_flags; 2113 mi->skip_call_return_sites = skip_call_return_sites; 2114 2115 /* Save the current position as the start of the input bytecodes */ 2116 mi->start_of_input_bytecodes = ci->input_position; 2117 2118 /* The max stack may increase */ 2119 mi->max_stack = max_stack; 2120 mi->new_max_stack = max_stack; 2121 2122 /* Adjust all code offsets */ 2123 method_inject_and_write_code(mi); 2124 2125 /* Fix up code length (save new_code_len for later attribute processing) */ 2126 mi->new_code_len = (int)(ci->output_position - start_of_output_bytecodes); 2127 random_writeU4(ci, output_code_len_position, mi->new_code_len); 2128 2129 /* Fixup max stack */ 2130 CRW_ASSERT(ci, mi->new_max_stack <= 0xFFFF); 2131 random_writeU2(ci, output_max_stack_position, mi->new_max_stack); 2132 2133 /* Copy exception table */ 2134 method_write_exception_table(mi); 2135 2136 /* Copy code attributes (needs mi->new_code_len) */ 2137 attr_count = copyU2(ci); 2138 for (i = 0; i < attr_count; ++i) { 2139 method_write_code_attribute(mi); 2140 } 2141 2142 /* Fix up attribute length */ 2143 new_attr_len = (int)(ci->output_position - (output_attr_len_position + 4)); 2144 random_writeU4(ci, output_attr_len_position, new_attr_len); 2145 2146 /* Free method data */ 2147 method_term(mi); 2148 mi = NULL; 2149 2150 } 2151 2152 static void 2153 method_write(CrwClassImage *ci, unsigned mnum) 2154 { 2155 unsigned i; 2156 unsigned access_flags; 2157 CrwCpoolIndex name_index; 2158 CrwCpoolIndex descr_index; 2159 unsigned attr_count; 2160 2161 access_flags = copyU2(ci); 2162 name_index = copyU2(ci); 2163 ci->method_name[mnum] = cpool_entry(ci, name_index).ptr; 2164 descr_index = copyU2(ci); 2165 ci->method_descr[mnum] = cpool_entry(ci, descr_index).ptr; 2166 attr_count = copyU2(ci); 2167 2168 for (i = 0; i < attr_count; ++i) { 2169 CrwCpoolIndex name_index; 2170 2171 name_index = copyU2(ci); 2172 if ( attribute_match(ci, name_index, "Code") ) { 2173 method_write_bytecodes(ci, mnum, access_flags); 2174 } else { 2175 unsigned len; 2176 len = copyU4(ci); 2177 copy(ci, len); 2178 } 2179 } 2180 } 2181 2182 static void 2183 method_write_all(CrwClassImage *ci) 2184 { 2185 unsigned i; 2186 unsigned count; 2187 2188 count = copyU2(ci); 2189 ci->method_count = count; 2190 if ( count > 0 ) { 2191 ci->method_name = (const char **)allocate_clean(ci, count*(int)sizeof(const char*)); 2192 ci->method_descr = (const char **)allocate_clean(ci, count*(int)sizeof(const char*)); 2193 } 2194 2195 for (i = 0; i < count; ++i) { 2196 method_write(ci, i); 2197 } 2198 2199 if ( ci->mnum_callback != NULL ) { 2200 (*(ci->mnum_callback))(ci->number, ci->method_name, ci->method_descr, 2201 count); 2202 } 2203 } 2204 2205 /* ------------------------------------------------------------------- */ 2206 /* Cleanup function. */ 2207 2208 static void 2209 cleanup(CrwClassImage *ci) 2210 { 2211 CRW_ASSERT_CI(ci); 2212 if ( ci->name != NULL ) { 2213 deallocate(ci, (void*)ci->name); 2214 ci->name = NULL; 2215 } 2216 if ( ci->method_name != NULL ) { 2217 deallocate(ci, (void*)ci->method_name); 2218 ci->method_name = NULL; 2219 } 2220 if ( ci->method_descr != NULL ) { 2221 deallocate(ci, (void*)ci->method_descr); 2222 ci->method_descr = NULL; 2223 } 2224 if ( ci->cpool != NULL ) { 2225 CrwCpoolIndex i; 2226 for(i=0; i<ci->cpool_count_plus_one; i++) { 2227 if ( ci->cpool[i].ptr != NULL ) { 2228 deallocate(ci, (void*)(ci->cpool[i].ptr)); 2229 ci->cpool[i].ptr = NULL; 2230 } 2231 } 2232 deallocate(ci, (void*)ci->cpool); 2233 ci->cpool = NULL; 2234 } 2235 } 2236 2237 static jboolean 2238 skip_class(unsigned access_flags) 2239 { 2240 if ( access_flags & JVM_ACC_INTERFACE ) { 2241 return JNI_TRUE; 2242 } 2243 return JNI_FALSE; 2244 } 2245 2246 static long 2247 inject_class(struct CrwClassImage *ci, 2248 int system_class, 2249 char* tclass_name, 2250 char* tclass_sig, 2251 char* call_name, 2252 char* call_sig, 2253 char* return_name, 2254 char* return_sig, 2255 char* obj_init_name, 2256 char* obj_init_sig, 2257 char* newarray_name, 2258 char* newarray_sig, 2259 unsigned char *buf, 2260 long buf_len) 2261 { 2262 CrwConstantPoolEntry cs; 2263 CrwCpoolIndex this_class; 2264 CrwCpoolIndex super_class; 2265 unsigned magic; 2266 unsigned classfileMajorVersion; 2267 unsigned classfileMinorVersion; 2268 unsigned interface_count; 2269 2270 CRW_ASSERT_CI(ci); 2271 CRW_ASSERT(ci, buf!=NULL); 2272 CRW_ASSERT(ci, buf_len!=0); 2273 2274 CRW_ASSERT(ci, strchr(tclass_name,'.')==NULL); /* internal qualified name */ 2275 2276 ci->injection_count = 0; 2277 ci->system_class = system_class; 2278 ci->tclass_name = tclass_name; 2279 ci->tclass_sig = tclass_sig; 2280 ci->call_name = call_name; 2281 ci->call_sig = call_sig; 2282 ci->return_name = return_name; 2283 ci->return_sig = return_sig; 2284 ci->obj_init_name = obj_init_name; 2285 ci->obj_init_sig = obj_init_sig; 2286 ci->newarray_name = newarray_name; 2287 ci->newarray_sig = newarray_sig; 2288 ci->output = buf; 2289 ci->output_len = buf_len; 2290 2291 magic = copyU4(ci); 2292 CRW_ASSERT(ci, magic==0xCAFEBABE); 2293 if ( magic != 0xCAFEBABE ) { 2294 return (long)0; 2295 } 2296 2297 /* minor version number not used */ 2298 classfileMinorVersion = copyU2(ci); 2299 /* major version number not used */ 2300 classfileMajorVersion = copyU2(ci); 2301 CRW_ASSERT(ci, (classfileMajorVersion <= JVM_CLASSFILE_MAJOR_VERSION) || 2302 ((classfileMajorVersion == JVM_CLASSFILE_MAJOR_VERSION) && 2303 (classfileMinorVersion <= JVM_CLASSFILE_MINOR_VERSION))); 2304 2305 cpool_setup(ci); 2306 2307 ci->access_flags = copyU2(ci); 2308 if ( skip_class(ci->access_flags) ) { 2309 return (long)0; 2310 } 2311 2312 this_class = copyU2(ci); 2313 2314 cs = cpool_entry(ci, (CrwCpoolIndex)(cpool_entry(ci, this_class).index1)); 2315 if ( ci->name == NULL ) { 2316 ci->name = duplicate(ci, cs.ptr, cs.len); 2317 CRW_ASSERT(ci, strchr(ci->name,'.')==NULL); /* internal qualified name */ 2318 } 2319 CRW_ASSERT(ci, (int)strlen(ci->name)==cs.len && strncmp(ci->name, cs.ptr, cs.len)==0); 2320 2321 super_class = copyU2(ci); 2322 if ( super_class == 0 ) { 2323 ci->is_object_class = JNI_TRUE; 2324 CRW_ASSERT(ci, strcmp(ci->name,"java/lang/Object")==0); 2325 } 2326 2327 interface_count = copyU2(ci); 2328 copy(ci, interface_count * 2); 2329 2330 copy_all_fields(ci); 2331 2332 method_write_all(ci); 2333 2334 if ( ci->injection_count == 0 ) { 2335 return (long)0; 2336 } 2337 2338 copy_attributes(ci); 2339 2340 return (long)ci->output_position; 2341 } 2342 2343 /* ------------------------------------------------------------------- */ 2344 /* Exported interfaces */ 2345 2346 JNIEXPORT void JNICALL 2347 java_crw_demo(unsigned class_number, 2348 const char *name, 2349 const unsigned char *file_image, 2350 long file_len, 2351 int system_class, 2352 char* tclass_name, /* Name of class that has tracker methods. */ 2353 char* tclass_sig, /* Signature of tclass */ 2354 char* call_name, /* Method name to call at offset 0 */ 2355 char* call_sig, /* Signature of this method */ 2356 char* return_name, /* Method name to call before any return */ 2357 char* return_sig, /* Signature of this method */ 2358 char* obj_init_name, /* Method name to call in Object <init> */ 2359 char* obj_init_sig, /* Signature of this method */ 2360 char* newarray_name, /* Method name to call after newarray opcodes */ 2361 char* newarray_sig, /* Signature of this method */ 2362 unsigned char **pnew_file_image, 2363 long *pnew_file_len, 2364 FatalErrorHandler fatal_error_handler, 2365 MethodNumberRegister mnum_callback) 2366 { 2367 CrwClassImage ci; 2368 long max_length; 2369 long new_length; 2370 void *new_image; 2371 int len; 2372 2373 /* Initial setup of the CrwClassImage structure */ 2374 (void)memset(&ci, 0, (int)sizeof(CrwClassImage)); 2375 ci.fatal_error_handler = fatal_error_handler; 2376 ci.mnum_callback = mnum_callback; 2377 2378 /* Do some interface error checks */ 2379 if ( pnew_file_image==NULL ) { 2380 CRW_FATAL(&ci, "pnew_file_image==NULL"); 2381 } 2382 if ( pnew_file_len==NULL ) { 2383 CRW_FATAL(&ci, "pnew_file_len==NULL"); 2384 } 2385 2386 /* No file length means do nothing */ 2387 *pnew_file_image = NULL; 2388 *pnew_file_len = 0; 2389 if ( file_len==0 ) { 2390 return; 2391 } 2392 2393 /* Do some more interface error checks */ 2394 if ( file_image == NULL ) { 2395 CRW_FATAL(&ci, "file_image == NULL"); 2396 } 2397 if ( file_len < 0 ) { 2398 CRW_FATAL(&ci, "file_len < 0"); 2399 } 2400 if ( system_class != 0 && system_class != 1 ) { 2401 CRW_FATAL(&ci, "system_class is not 0 or 1"); 2402 } 2403 if ( tclass_name == NULL ) { 2404 CRW_FATAL(&ci, "tclass_name == NULL"); 2405 } 2406 if ( tclass_sig == NULL || tclass_sig[0]!='L' ) { 2407 CRW_FATAL(&ci, "tclass_sig is not a valid class signature"); 2408 } 2409 len = (int)strlen(tclass_sig); 2410 if ( tclass_sig[len-1]!=';' ) { 2411 CRW_FATAL(&ci, "tclass_sig is not a valid class signature"); 2412 } 2413 if ( call_name != NULL ) { 2414 if ( call_sig == NULL || strcmp(call_sig, "(II)V") != 0 ) { 2415 CRW_FATAL(&ci, "call_sig is not (II)V"); 2416 } 2417 } 2418 if ( return_name != NULL ) { 2419 if ( return_sig == NULL || strcmp(return_sig, "(II)V") != 0 ) { 2420 CRW_FATAL(&ci, "return_sig is not (II)V"); 2421 } 2422 } 2423 if ( obj_init_name != NULL ) { 2424 if ( obj_init_sig == NULL || strcmp(obj_init_sig, "(Ljava/lang/Object;)V") != 0 ) { 2425 CRW_FATAL(&ci, "obj_init_sig is not (Ljava/lang/Object;)V"); 2426 } 2427 } 2428 if ( newarray_name != NULL ) { 2429 if ( newarray_sig == NULL || strcmp(newarray_sig, "(Ljava/lang/Object;)V") != 0 ) { 2430 CRW_FATAL(&ci, "newarray_sig is not (Ljava/lang/Object;)V"); 2431 } 2432 } 2433 2434 /* Finish setup the CrwClassImage structure */ 2435 ci.is_thread_class = JNI_FALSE; 2436 if ( name != NULL ) { 2437 CRW_ASSERT(&ci, strchr(name,'.')==NULL); /* internal qualified name */ 2438 2439 ci.name = duplicate(&ci, name, (int)strlen(name)); 2440 if ( strcmp(name, "java/lang/Thread")==0 ) { 2441 ci.is_thread_class = JNI_TRUE; 2442 } 2443 } 2444 ci.number = class_number; 2445 ci.input = file_image; 2446 ci.input_len = file_len; 2447 2448 /* Do the injection */ 2449 max_length = file_len*2 + 512; /* Twice as big + 512 */ 2450 new_image = allocate(&ci, (int)max_length); 2451 new_length = inject_class(&ci, 2452 system_class, 2453 tclass_name, 2454 tclass_sig, 2455 call_name, 2456 call_sig, 2457 return_name, 2458 return_sig, 2459 obj_init_name, 2460 obj_init_sig, 2461 newarray_name, 2462 newarray_sig, 2463 new_image, 2464 max_length); 2465 2466 /* Dispose or shrink the space to be returned. */ 2467 if ( new_length == 0 ) { 2468 deallocate(&ci, (void*)new_image); 2469 new_image = NULL; 2470 } else { 2471 new_image = (void*)reallocate(&ci, (void*)new_image, (int)new_length); 2472 } 2473 2474 /* Return the new class image */ 2475 *pnew_file_image = (unsigned char *)new_image; 2476 *pnew_file_len = (long)new_length; 2477 2478 /* Cleanup before we leave. */ 2479 cleanup(&ci); 2480 } 2481 2482 /* Return the classname for this class which is inside the classfile image. */ 2483 JNIEXPORT char * JNICALL 2484 java_crw_demo_classname(const unsigned char *file_image, long file_len, 2485 FatalErrorHandler fatal_error_handler) 2486 { 2487 CrwClassImage ci; 2488 CrwConstantPoolEntry cs; 2489 CrwCpoolIndex this_class; 2490 unsigned magic; 2491 char * name; 2492 2493 name = NULL; 2494 2495 if ( file_len==0 || file_image==NULL ) { 2496 return name; 2497 } 2498 2499 /* The only fields we need filled in are the image pointer and the error 2500 * handler. 2501 * By not adding an output buffer pointer, no output is created. 2502 */ 2503 (void)memset(&ci, 0, (int)sizeof(CrwClassImage)); 2504 ci.input = file_image; 2505 ci.input_len = file_len; 2506 ci.fatal_error_handler = fatal_error_handler; 2507 2508 /* Read out the bytes from the classfile image */ 2509 2510 magic = readU4(&ci); /* magic number */ 2511 CRW_ASSERT(&ci, magic==0xCAFEBABE); 2512 if ( magic != 0xCAFEBABE ) { 2513 return name; 2514 } 2515 (void)readU2(&ci); /* minor version number */ 2516 (void)readU2(&ci); /* major version number */ 2517 2518 /* Read in constant pool. Since no output setup, writes are NOP's */ 2519 cpool_setup(&ci); 2520 2521 (void)readU2(&ci); /* access flags */ 2522 this_class = readU2(&ci); /* 'this' class */ 2523 2524 /* Get 'this' constant pool entry */ 2525 cs = cpool_entry(&ci, (CrwCpoolIndex)(cpool_entry(&ci, this_class).index1)); 2526 2527 /* Duplicate the name */ 2528 name = (char *)duplicate(&ci, cs.ptr, cs.len); 2529 2530 /* Cleanup before we leave. */ 2531 cleanup(&ci); 2532 2533 /* Return malloc space */ 2534 return name; 2535 }