1 /* 2 * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include <stdlib.h> 25 #include <string.h> 26 #include "jni_tools.h" 27 #include "jvmti_tools.h" 28 #include "Injector.h" 29 30 /* ========================================================================== */ 31 32 /* Opcode Lengths */ 33 static const u1 opcLengths[] = { 34 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, /* 0- 19 */ 35 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20- 39 */ 36 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1, /* 40- 59 */ 37 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60- 79 */ 38 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80- 99 */ 39 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 100-119 */ 40 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, /* 120-139 */ 41 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, /* 140-159 */ 42 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 0, 0, 1, 1, 1, 1, 1, 1, 3, 3, /* 160-179 */ 43 3, 3, 3, 3, 3, 5, 5, 3, 2, 3, 1, 1, 3, 3, 1, 1, 0, 4, 3, 3, /* 180-199 */ 44 5, 5, 1 /* 200- */ 45 }; 46 47 static const int GROWTH_FACTOR = 2; 48 static const char* codeAttributeName = "Code"; 49 static const char* lineNumberAttributeName = "LineNumberTable"; 50 static const char* localVarAttributeName = "LocalVariableTable"; 51 static const char* localVarTypeAttributeName = "LocalVariableTypeTable"; 52 static const char* stackMapAttributeName= "StackMapTable"; 53 54 static u2 codeAttributeIndex; 55 static u2 lineNumberAttributeIndex; 56 static u2 localVarAttributeIndex; 57 static u2 localVarTypeAttributeIndex; 58 static u2 stackMapAttributeIndex; 59 60 static const u1 SAME_BEGIN = 0; 61 static const u1 SAME_END = 63; 62 63 static const u1 SAME_LOCALS_1_STACK_ITEM_BEGIN = 64; 64 static const u1 SAME_LOCALS_1_STACK_ITEM_END = 127; 65 66 //Tags in the range [128-246] are reserved for future use. 67 68 static const u1 SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247; 69 70 static const u1 CHOP_BEGIN = 248; 71 static const u1 CHOP_END = 250; 72 73 static const u1 SAME_FRAME_EXTENDED = 251; 74 75 static const u1 APPEND_BEGIN = 252; 76 static const u1 APPEND_END = 254; 77 78 static const u1 FULL_FRAME = 255; 79 80 static const u1 ITEM_Object = 7; 81 static const u1 ITEM_Uninitialized = 8; 82 83 static u2 stackFrameOffset = 0; 84 85 static int mode; 86 static const u1* orig; 87 static u1* gen; 88 89 static u1* inputPos; 90 static const u1* endPos; 91 static u1* genPos; 92 static u1* markPos; 93 94 static char** constantPool; 95 static u2 constantPoolSize; 96 static u2 constantPoolCount; 97 98 static u1 callBytes[] = { opc_invokestatic, 0, 0 }; 99 static u1 allocBytes[] = { opc_invokestatic, 0, 0 }; 100 static u1 zeroBytes[] = { 0, 0, 0 }; 101 102 static u4 codeLength; 103 static u4* map; 104 static jbyte* widening; 105 106 /* ========================================================================== */ 107 108 #ifdef __cplusplus 109 extern "C" { 110 #endif 111 112 static u1 get_u1() { 113 return *inputPos++; 114 } 115 116 static u2 get_u2() { 117 u1* p = inputPos; 118 inputPos += 2; 119 return (u2)p[1] | ((u2)p[0]<<8); 120 } 121 122 static u4 get_u4() { 123 u1* p = inputPos; 124 inputPos += 4; 125 return (u4)p[3] | ((u4)p[2]<<8) | ((u4)p[1]<<16) | ((u4)p[0]<<24); 126 } 127 128 static void put_u1(u1 v) { 129 *genPos++ = v; 130 } 131 132 static void put_u2(u2 v) { 133 *genPos++ = (u1)(v>>8); 134 *genPos++ = (u1)(v & 0xFF); 135 } 136 137 static void put_u4(u4 v) { 138 *genPos++ = (u1)(v>>24); 139 *genPos++ = (u1)(v>>16); 140 *genPos++ = (u1)(v>>8); 141 *genPos++ = (u1)(v & 0xFF); 142 } 143 144 static void set_u4(u1* pos, u4 v) { 145 *pos++ = (u1)(v>>24); 146 *pos++ = (u1)(v>>16); 147 *pos++ = (u1)(v>>8); 148 *pos++ = (u1)(v & 0xFF); 149 } 150 151 static u1 copy_u1() { 152 u1 v = get_u1(); 153 put_u1(v); 154 return v; 155 } 156 157 static u2 copy_u2() { 158 u2 v = get_u2(); 159 put_u2(v); 160 return v; 161 } 162 163 static u4 copy_u4() { 164 u4 v = get_u4(); 165 put_u4(v); 166 return v; 167 } 168 169 static void copy(int count) { 170 memcpy(genPos, inputPos, count); 171 inputPos += count; 172 genPos += count; 173 } 174 175 static void skip(int count) { 176 inputPos += count; 177 } 178 179 static void get(u1* bytes, int count) { 180 memcpy(bytes, inputPos, count); 181 inputPos += count; 182 } 183 184 static void put(u1* bytes, int count) { 185 memcpy(genPos, bytes, count); 186 genPos += count; 187 } 188 189 static void markLocalPositionStart() { 190 markPos = inputPos; 191 } 192 193 static u4 localPosition() { 194 return (u4) (inputPos - markPos); 195 } 196 197 void recallPosition() { 198 inputPos = markPos; 199 } 200 201 static u4 generatedPosition() { 202 return (u4) (genPos - gen); 203 } 204 205 static void randomAccessWriteU2(int pos, u2 v) { 206 gen[pos] = (u1)(v>>8); 207 gen[pos+1] = (u1)(v & 0xFF); 208 } 209 210 static void randomAccessWriteU4(int pos, u4 v) { 211 gen[pos] = (u1)(v>>24); 212 gen[pos+1] = (u1)(v>>16); 213 gen[pos+2] = (u1)(v>>8); 214 gen[pos+3] = (u1)(v & 0xFF); 215 } 216 217 static int copyConstantPool(u2 constantPoolCount) { 218 u2 i; 219 u2 len; 220 char* utf8; 221 222 constantPoolSize = constantPoolCount; 223 224 NSK_DISPLAY1("copying ConstantPool: %d\n", constantPoolSize); 225 constantPool = (char**) malloc(constantPoolSize * sizeof(char*)); 226 if (!NSK_VERIFY(constantPool != NULL)) { 227 NSK_COMPLAIN0("out of memory\n"); 228 return NSK_FALSE; 229 } 230 231 memset(constantPool, 0, constantPoolSize * sizeof(char*)); 232 233 codeAttributeIndex = 0; 234 lineNumberAttributeIndex = 0; 235 localVarAttributeIndex = 0; 236 localVarTypeAttributeIndex = 0; 237 stackMapAttributeIndex = 0; 238 239 for (i = 1; i < constantPoolSize; i++) { 240 u1 tag = copy_u1(); 241 switch (tag) { 242 case CONSTANT_Class: 243 case CONSTANT_String: 244 case CONSTANT_MethodType: 245 copy(2); 246 break; 247 case CONSTANT_MethodHandle: 248 copy(3); 249 break; 250 case CONSTANT_Fieldref: 251 case CONSTANT_Methodref: 252 case CONSTANT_InterfaceMethodref: 253 case CONSTANT_Integer: 254 case CONSTANT_Float: 255 case CONSTANT_NameAndType: 256 case CONSTANT_InvokeDynamic: 257 copy(4); 258 break; 259 case CONSTANT_Long: 260 case CONSTANT_Double: 261 copy(8); 262 i++; /* takes two CP entries */ 263 break; 264 case CONSTANT_Utf8: 265 len = copy_u2(); 266 utf8 = (char*) malloc(len + 1); 267 if (!NSK_VERIFY(utf8 != NULL)) { 268 NSK_COMPLAIN0("out of memory\n"); 269 return NSK_FALSE; 270 } 271 get((u1*) utf8, len); 272 utf8[len] = 0; 273 constantPool[i] = utf8; 274 if (strcmp(utf8, codeAttributeName) == 0) { 275 codeAttributeIndex = i; 276 } else if (strcmp(utf8, lineNumberAttributeName) == 0) { 277 lineNumberAttributeIndex = i; 278 } else if (strcmp(utf8, localVarAttributeName) == 0) { 279 localVarAttributeIndex = i; 280 } else if (strcmp(utf8, localVarTypeAttributeName) == 0) { 281 localVarTypeAttributeIndex = i; 282 } else if (strcmp(utf8, stackMapAttributeName) == 0) { 283 stackMapAttributeIndex = i; 284 } 285 put((u1*) utf8, len); 286 break; 287 default: 288 NSK_COMPLAIN2("%d unexpected constant pool tag: %d\n", i, tag); 289 return NSK_FALSE; 290 } 291 } 292 293 return NSK_TRUE; 294 } 295 296 static void freeConstantPool() { 297 u2 i; 298 299 for (i = 1; i < constantPoolSize; i++) { 300 if (constantPool[i] != NULL) { 301 free(constantPool[i]); 302 } 303 } 304 305 free(constantPool); 306 } 307 308 /* ========================================================================== */ 309 310 /* Copy the exception table for this method code */ 311 static void copyExceptionTable() { 312 u2 tableLength; 313 u2 i; 314 315 tableLength = copy_u2(); 316 NSK_DISPLAY1("ExceptionTable length: %d\n", tableLength); 317 for (i = tableLength; i > 0; i--) { 318 put_u2((u2) map[get_u2()]); /* start_pc */ 319 put_u2((u2) map[get_u2()]); /* end_pc */ 320 put_u2((u2) map[get_u2()]); /* handler_pc */ 321 copy(2); /* catch_type */ 322 } 323 } 324 325 /* Copy the line number table for this method code */ 326 static void copyLineNumberAttr() { 327 u2 tableLength; 328 u2 i; 329 330 copy(4); /* attr len */ 331 332 tableLength = copy_u2(); 333 334 NSK_DISPLAY1("LineNumberTable length: %d\n", tableLength); 335 for (i = tableLength; i > 0; i--) { 336 put_u2((u2) map[get_u2()]); /* start_pc */ 337 copy(2); /* line_number */ 338 } 339 } 340 341 /* Copy the local variable table for this method code */ 342 static void copyLocalVarAttr() { 343 u2 tableLength; 344 u2 startPC; 345 u2 i; 346 347 copy(4); /* attr len */ 348 349 tableLength = copy_u2(); 350 351 NSK_DISPLAY1("LocalVariableTable length: %d\n", tableLength); 352 for (i = tableLength; i > 0; i--) { 353 startPC = get_u2(); 354 put_u2((u2) map[startPC]); /* start_pc */ 355 put_u2((u2) (map[startPC + get_u2()] - map[startPC])); /* length */ 356 copy(6); /* name_index, descriptor_index, index */ 357 } 358 } 359 360 /* Copy the local variable type table for this method code */ 361 static void copyLocalVarTypeAttr() { 362 u2 tableLength; 363 u2 startPC; 364 u2 i; 365 366 copy(4); /* attr len */ 367 368 tableLength = copy_u2(); 369 370 NSK_DISPLAY1("LocalVariableTypeTable length: %d\n", tableLength); 371 for (i = tableLength; i > 0; i--) { 372 startPC = get_u2(); 373 put_u2((u2) map[startPC]); /* start_pc */ 374 put_u2((u2) (map[startPC + get_u2()] - map[startPC])); /* length */ 375 copy(6); /* name_index, signature_index, index */ 376 } 377 } 378 379 static u2 calculateOffsetDelta(u2 frameNumber, u2 frameOffsetDelta) { 380 u2 oldOffset; 381 u2 newOffset; 382 if(frameNumber == 0) { 383 stackFrameOffset = frameOffsetDelta; 384 return (u2) map[stackFrameOffset]; 385 } else { 386 oldOffset = (u2) map[stackFrameOffset]; 387 stackFrameOffset = stackFrameOffset + frameOffsetDelta + 1; 388 newOffset = (u2) map[stackFrameOffset - 1]; 389 return newOffset - oldOffset; 390 } 391 } 392 393 static void copyVerificationTypeInfo(u2 count) { 394 u2 i; 395 u2 offset; 396 u1 tag; 397 for(i=0; i<count; i++) { 398 tag = get_u1(); 399 put_u1(tag); 400 if(tag == ITEM_Object) { 401 copy_u2(); 402 } else if (tag == ITEM_Uninitialized) { 403 copy_u2(); 404 offset = get_u2(); 405 put_u2((u2)map[offset]); 406 } 407 } 408 } 409 410 static void copyStackMapAttr() { 411 u2 number_of_entries; 412 u2 i; 413 u4 len; 414 unsigned int frame_type; 415 u2 frameOffsetDelta; 416 u2 number_of_stack_items; 417 u2 number_of_locals; 418 u1* lenPtr = genPos; 419 420 len=copy_u4(); /* attr len */ 421 422 number_of_entries = copy_u2(); 423 424 425 426 for(i=0; i<number_of_entries; i++) { 427 frame_type = get_u1(); 428 429 if((frame_type >= SAME_BEGIN) && (frame_type <= SAME_END)) { 430 // same_frame { 431 // u1 frame_type = SAME; /* 0-63 */ 432 // } 433 434 put_u1(SAME_FRAME_EXTENDED); 435 put_u2(calculateOffsetDelta(i, (u2) frame_type)); 436 437 } else if((frame_type >= SAME_LOCALS_1_STACK_ITEM_BEGIN) && (frame_type<=SAME_LOCALS_1_STACK_ITEM_END)) { 438 // same_locals_1_stack_item_frame { 439 // u1 frame_type = SAME_LOCALS_1_STACK_ITEM;/* 64-127 */ 440 // verification_type_info stack[1]; 441 // } 442 443 put_u1(SAME_LOCALS_1_STACK_ITEM_EXTENDED); 444 put_u2(calculateOffsetDelta(i, (u2) (frame_type-64))); 445 copyVerificationTypeInfo(1); 446 447 // Tags in the range [128-246] are reserved for future use. 448 } else if(frame_type == SAME_LOCALS_1_STACK_ITEM_EXTENDED) { 449 // same_locals_1_stack_item_frame_extended { 450 // u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; /* 247 */ 451 // u2 offset_delta; 452 // verification_type_info stack[1]; 453 // } 454 455 put_u1(SAME_LOCALS_1_STACK_ITEM_EXTENDED); 456 frameOffsetDelta = get_u2(); 457 put_u2(calculateOffsetDelta(i, frameOffsetDelta)); 458 copyVerificationTypeInfo(1); 459 460 } else if((frame_type >= CHOP_BEGIN) && (frame_type <= CHOP_END)) { 461 // chop_frame { 462 // u1 frame_type = CHOP; /* 248-250 */ 463 // u2 offset_delta; 464 // } 465 put_u1((u1)frame_type); 466 frameOffsetDelta = get_u2(); 467 put_u2(calculateOffsetDelta(i, frameOffsetDelta)); 468 469 } else if(frame_type == SAME_FRAME_EXTENDED) { 470 // same_frame_extended { 471 // u1 frame_type = SAME_FRAME_EXTENDED; /* 251 */ 472 // u2 offset_delta; 473 // } 474 475 put_u1(SAME_FRAME_EXTENDED); 476 frameOffsetDelta = get_u2(); 477 put_u2(calculateOffsetDelta(i, frameOffsetDelta)); 478 479 } else if((frame_type >= APPEND_BEGIN) && (frame_type <= APPEND_END)) { 480 // append_frame { 481 // u1 frame_type = APPEND; /* 252-254 */ 482 // u2 offset_delta; 483 // verification_type_info locals[frame_type - 251]; 484 // } 485 486 put_u1((u1)frame_type); 487 frameOffsetDelta = get_u2(); 488 put_u2(calculateOffsetDelta(i, frameOffsetDelta)); 489 copyVerificationTypeInfo((u1)(frame_type - 251)); 490 491 } else if(frame_type == FULL_FRAME) { 492 // sfull_frame { 493 // u1 frame_type = FULL_FRAME; /* 255 */ 494 // u2 offset_delta; 495 // u2 number_of_locals; 496 // verification_type_info locals[number_of_locals]; 497 // u2 number_of_stack_items; 498 // verification_type_info stack[number_of_stack_items]; 499 //} 500 501 put_u1(FULL_FRAME); 502 frameOffsetDelta = get_u2(); 503 put_u2(calculateOffsetDelta(i, frameOffsetDelta)); 504 number_of_locals = copy_u2(); 505 copyVerificationTypeInfo(number_of_locals); 506 number_of_stack_items = copy_u2(); 507 copyVerificationTypeInfo(number_of_stack_items); 508 509 } 510 511 } 512 set_u4(lenPtr,(u4)((genPos-lenPtr) - 4)); 513 514 } 515 516 /* ========================================================================== */ 517 518 static void injectBytes(u4 at, u4 len) { 519 u4 i; 520 521 NSK_DISPLAY2("Injecting %d bytes at %d\n", len, at); 522 for (i = at; i <= codeLength; i++) { 523 map[i] += len; 524 } 525 } 526 527 static void widen(u4 at, jbyte len) { 528 u4 i; 529 jbyte delta = len - widening[at]; 530 531 NSK_DISPLAY2("Widening to %d bytes at %d\n", len, at); 532 /* mark at beginning of instruction */ 533 widening[at] = len; 534 /* inject at end of instruction */ 535 for (i = localPosition(); i <= codeLength; i++) { 536 map[i] += delta; 537 } 538 } 539 540 /* ========================================================================== */ 541 542 /** 543 * Walk one instruction writing the transformed instruction. 544 */ 545 static void writeInstruction() { 546 u4 pos = localPosition(); 547 u4 newPos = map[pos]; 548 u1 opcode = get_u1(); 549 550 switch (opcode) { 551 552 case opc_wide: 553 put_u1(opcode); 554 copy(copy_u1() == opc_iinc ? 4 : 2); 555 break; 556 557 case opc_new: 558 case opc_newarray: 559 case opc_anewarray: 560 case opc_multianewarray: 561 put_u1(opcode); 562 copy(opcLengths[opcode] - 1); 563 if (mode == BCI_MODE_ALLOC) { 564 put(allocBytes, 3); 565 } 566 break; 567 568 case opc_jsr_w: 569 case opc_goto_w: 570 put_u1(opcode); 571 put_u4(map[pos + get_u4()] - newPos); 572 break; 573 574 case opc_jsr: 575 case opc_goto: 576 case opc_ifeq: 577 case opc_ifge: 578 case opc_ifgt: 579 case opc_ifle: 580 case opc_iflt: 581 case opc_ifne: 582 case opc_if_icmpeq: 583 case opc_if_icmpne: 584 case opc_if_icmpge: 585 case opc_if_icmpgt: 586 case opc_if_icmple: 587 case opc_if_icmplt: 588 case opc_if_acmpeq: 589 case opc_if_acmpne: 590 case opc_ifnull: 591 case opc_ifnonnull: { 592 u1 newOpcode = opcode; 593 jbyte widened = widening[pos]; 594 if (widened == 0) { /* not widened */ 595 put_u1(opcode); 596 put_u2((u2) (map[pos + (jshort) get_u2()] - newPos)); 597 } else if (widened == 2) { /* wide form */ 598 if (opcode == opc_jsr) { 599 newOpcode = opc_jsr_w; 600 } else if (opcode == opc_jsr) { 601 newOpcode = opc_goto_w; 602 } else { 603 NSK_COMPLAIN1("unexpected opcode: %d\n", opcode); 604 } 605 put_u1(newOpcode); 606 put_u4(map[pos + (jshort) get_u2()] - newPos); 607 } else if (widened == 5) { /* insert goto_w */ 608 switch (opcode) { 609 case opc_ifeq: 610 newOpcode = opc_ifne; 611 break; 612 case opc_ifge: 613 newOpcode = opc_iflt; 614 break; 615 case opc_ifgt: 616 newOpcode = opc_ifle; 617 break; 618 case opc_ifle: 619 newOpcode = opc_ifgt; 620 break; 621 case opc_iflt: 622 newOpcode = opc_ifge; 623 break; 624 case opc_ifne: 625 newOpcode = opc_ifeq; 626 break; 627 case opc_if_icmpeq: 628 newOpcode = opc_if_icmpne; 629 break; 630 case opc_if_icmpne: 631 newOpcode = opc_if_icmpeq; 632 break; 633 case opc_if_icmpge: 634 newOpcode = opc_if_icmplt; 635 break; 636 case opc_if_icmpgt: 637 newOpcode = opc_if_icmple; 638 break; 639 case opc_if_icmple: 640 newOpcode = opc_if_icmpgt; 641 break; 642 case opc_if_icmplt: 643 newOpcode = opc_if_icmpge; 644 break; 645 case opc_if_acmpeq: 646 newOpcode = opc_if_acmpne; 647 break; 648 case opc_if_acmpne: 649 newOpcode = opc_if_acmpeq; 650 break; 651 case opc_ifnull: 652 newOpcode = opc_ifnonnull; 653 break; 654 case opc_ifnonnull: 655 newOpcode = opc_ifnull; 656 break; 657 default: 658 NSK_COMPLAIN1("unexpected opcode: %d\n", opcode); 659 break; 660 } 661 put_u1(newOpcode); /* write inverse branch */ 662 put_u1(3 + 5); /* beyond if and goto_w */ 663 put_u1(opc_goto_w); /* add a goto_w */ 664 put_u4(map[pos + (jshort) get_u2()] - newPos); 665 } else { 666 NSK_COMPLAIN2("unexpected widening: %d, pos=0x%x\n", 667 widened, pos); 668 } 669 break; 670 } 671 672 case opc_tableswitch: { 673 u4 i, low, high; 674 675 put_u1(opcode); 676 677 /* skip old padding */ 678 skip(((pos+4) & (~3)) - (pos+1)); 679 680 /* write new padding */ 681 put(zeroBytes, ((newPos+4) & (~3)) - (newPos+1)); 682 put_u4(map[pos + get_u4()] - newPos); 683 684 low = copy_u4(); 685 high = copy_u4(); 686 for (i = low; i <= high; i++) { 687 put_u4(map[pos + get_u4()] - newPos); 688 } 689 690 break; 691 } 692 693 case opc_lookupswitch: { 694 u4 i, npairs; 695 696 put_u1(opcode); 697 698 /* skip old padding */ 699 skip(((pos+4) & (~3)) - (pos+1)); 700 701 /* write new padding */ 702 put(zeroBytes, ((newPos+4) & (~3)) - (newPos+1)); 703 put_u4(map[pos + get_u4()] - newPos); 704 705 npairs = copy_u4(); 706 for (i = npairs; i > 0; i--) { 707 copy_u4(); 708 put_u4(map[pos + get_u4()] - newPos); 709 } 710 711 break; 712 } 713 714 default: 715 put_u1(opcode); 716 copy(opcLengths[opcode] - 1); 717 break; 718 } 719 720 } 721 722 /* ========================================================================== */ 723 724 /** 725 * Walk one instruction adjusting for insertions 726 */ 727 static int adjustInstruction() { 728 u4 pos = localPosition(); 729 u4 newPos = map[pos]; 730 u1 opcode = get_u1(); 731 732 switch (opcode) { 733 734 case opc_wide: 735 skip(get_u1() == opc_iinc ? 4 : 2); 736 break; 737 738 case opc_jsr: 739 case opc_goto: 740 case opc_ifeq: 741 case opc_ifge: 742 case opc_ifgt: 743 case opc_ifle: 744 case opc_iflt: 745 case opc_ifne: 746 case opc_if_icmpeq: 747 case opc_if_icmpne: 748 case opc_if_icmpge: 749 case opc_if_icmpgt: 750 case opc_if_icmple: 751 case opc_if_icmplt: 752 case opc_if_acmpeq: 753 case opc_if_acmpne: 754 case opc_ifnull: 755 case opc_ifnonnull: { 756 jbyte widened = widening[pos]; 757 if (widened == 0) { /* not yet widened */ 758 jint delta = (jshort) get_u2(); 759 u4 target = pos + delta; 760 u4 newTarget = map[target]; 761 jint newDelta = newTarget - newPos; 762 if ((newDelta < -32768) || (newDelta > 32767)) { 763 if ((opcode == opc_jsr) || (opcode == opc_goto)) { 764 widen(pos, 2); /* will convert to wide */ 765 } else { 766 widen(pos, 5); /* will inject goto_w */ 767 } 768 return NSK_FALSE; /* cause restart */ 769 } 770 } 771 break; 772 } 773 774 case opc_tableswitch: { 775 jbyte widened = widening[pos]; 776 u4 low; 777 jbyte deltaPadding; 778 779 /* skip old padding and default */ 780 skip(((pos+4) & (~3)) - (pos+1) + 4); 781 low = get_u4(); 782 skip((get_u4() - low + 1) * 4); 783 784 deltaPadding = ((newPos+4) & (~3)) - newPos - ((pos+4) & (~3)) + pos; 785 if (widened != deltaPadding) { 786 widen(pos, deltaPadding); 787 return NSK_FALSE; /* cause restart */ 788 } 789 break; 790 } 791 792 case opc_lookupswitch: { 793 jbyte widened = widening[pos]; 794 jbyte deltaPadding; 795 796 /* skip old padding and default */ 797 skip(((pos+4) & (~3)) - (pos+1) + 4); 798 skip(get_u4() * 8); 799 800 deltaPadding = ((newPos+4) & (~3)) - newPos - ((pos+4) & (~3)) + pos; 801 if (widened != deltaPadding) { 802 widen(pos, deltaPadding); 803 return NSK_FALSE; /* cause restart */ 804 } 805 break; 806 } 807 808 default: 809 skip(opcLengths[opcode] - 1); 810 break; 811 } 812 813 return NSK_TRUE; 814 } 815 816 /* ========================================================================== */ 817 818 /** 819 * Walk one instruction inserting instrumentation at specified instructions 820 */ 821 static void insertAtInstruction() { 822 u4 pos = localPosition(); 823 u1 opcode = get_u1(); 824 825 switch (opcode) { 826 827 case opc_wide: 828 /* no support for instrumenting wide instructions */ 829 skip(get_u1() == opc_iinc ? 4 : 2); 830 break; 831 832 case opc_new: 833 case opc_newarray: 834 case opc_anewarray: 835 case opc_multianewarray: 836 skip(opcLengths[opcode] - 1); 837 injectBytes(localPosition(), 3); 838 break; 839 840 case opc_tableswitch: 841 /* skip 4-byte boundry padding and default */ 842 skip(((pos+4) & (~3)) - (pos+1) + 4); 843 { 844 u4 low = get_u4(); 845 skip((get_u4() - low + 1) * 4); 846 } 847 break; 848 849 case opc_lookupswitch: 850 /* skip 4-byte boundry padding and default */ 851 skip(((pos+4) & (~3)) - (pos+1) + 4); 852 skip(get_u4() * 8); 853 break; 854 855 default: 856 skip(opcLengths[opcode] - 1); 857 break; 858 859 } 860 } 861 862 static void adjustOffsets() { 863 recallPosition(); 864 865 if (mode == BCI_MODE_CALL) { 866 /* instrument calls - method entry */ 867 injectBytes(0, 3); 868 } 869 870 if (mode == BCI_MODE_ALLOC) { 871 /* instrument allocations */ 872 while (localPosition() < codeLength) { 873 insertAtInstruction(); 874 } 875 recallPosition(); 876 } 877 878 NSK_DISPLAY0("Searching for adjustments...\n"); 879 while (localPosition() < codeLength) { 880 if (!adjustInstruction()) { 881 recallPosition(); 882 NSK_DISPLAY0("Restarting adjustments after change...\n"); 883 } 884 } 885 886 NSK_DISPLAY0("Writing new code...\n"); 887 recallPosition(); 888 889 if (mode == BCI_MODE_CALL) { 890 put(callBytes, 3); 891 } 892 893 while (localPosition() < codeLength) { 894 writeInstruction(); 895 } 896 } 897 898 /* ========================================================================== */ 899 900 static void copyAttr() { 901 u4 len; 902 903 copy(2); 904 len = copy_u4(); 905 NSK_DISPLAY1("attr len: %d\n", len); 906 copy(len); 907 } 908 909 static void copyAttrs(u2 attrCount) { 910 u2 i; 911 912 for (i = attrCount; i > 0; i--) { 913 copyAttr(); 914 } 915 } 916 917 static void copyFields() { 918 u2 count; 919 u2 attrCount; 920 u2 i; 921 922 count = copy_u2(); 923 NSK_DISPLAY1("fields count: %d\n", count); 924 for (i = count; i > 0; i--) { 925 /* access, name, descriptor */ 926 copy(2 + 2 + 2); 927 attrCount = copy_u2(); 928 NSK_DISPLAY1("field attrCount: %d\n", attrCount); 929 copyAttrs(attrCount); 930 } 931 } 932 933 static void copyAttrForCode() { 934 u2 nameIndex = copy_u2(); 935 936 /* check for Code attr */ 937 if (nameIndex == lineNumberAttributeIndex) { 938 copyLineNumberAttr(); 939 } else if (nameIndex == localVarAttributeIndex) { 940 copyLocalVarAttr(); 941 } else if (nameIndex == localVarTypeAttributeIndex) { 942 copyLocalVarTypeAttr(); 943 } else if (nameIndex == stackMapAttributeIndex) { 944 copyStackMapAttr(); 945 } else { 946 u4 len = copy_u4(); 947 NSK_DISPLAY1("code attr len: %d\n", len); 948 copy(len); 949 } 950 } 951 952 static void copyCodeAttr(char* name) { 953 u4 attrLengthPos; 954 u4 attrLength; 955 u4 newAttrLength; 956 u4 codeLengthPos; 957 u4 newCodeLength; 958 u2 attrCount; 959 u4 i; 960 961 attrLengthPos = generatedPosition(); 962 attrLength = copy_u4(); 963 964 NSK_DISPLAY2("Code attr found: %s, pos=0x%x\n", name, 965 inputPos - orig - 6); 966 967 /* max_stack, max_locals */ 968 copy(2 + 2); 969 970 codeLengthPos = generatedPosition(); 971 codeLength = copy_u4(); 972 973 if (codeLength == 0) { 974 NSK_COMPLAIN0("code_length must be greater than zero\n"); 975 return; 976 } 977 978 if (mode == BCI_MODE_EMCP) { 979 /* copy remainder minus already copied */ 980 copy(attrLength - 8); 981 return; 982 } 983 984 markLocalPositionStart(); 985 986 map = (u4*) malloc((codeLength + 1) * sizeof(u4)); 987 for (i = 0; i <= codeLength; i++) { 988 map[i] = i; 989 } 990 991 widening = (jbyte*) malloc(codeLength + 1); 992 memset(widening, 0, codeLength + 1); 993 994 adjustOffsets(); 995 996 /* fix up code length */ 997 newCodeLength = generatedPosition() - (codeLengthPos + 4); 998 randomAccessWriteU4(codeLengthPos, newCodeLength); 999 NSK_DISPLAY2("code length old: %d, new: %d\n", 1000 codeLength, newCodeLength); 1001 1002 copyExceptionTable(); 1003 1004 attrCount = copy_u2(); 1005 for (i = attrCount; i > 0; i--) { 1006 copyAttrForCode(); 1007 } 1008 1009 free(map); 1010 free(widening); 1011 1012 /* fix up attr length */ 1013 newAttrLength = generatedPosition() - (attrLengthPos + 4); 1014 randomAccessWriteU4(attrLengthPos, newAttrLength); 1015 NSK_DISPLAY2("attr length old: %d, new: %d\n", 1016 attrLength, newAttrLength); 1017 } 1018 1019 static void copyAttrForMethod(char* name) { 1020 u2 nameIndex; 1021 1022 nameIndex = copy_u2(); 1023 if (nameIndex == codeAttributeIndex) { 1024 copyCodeAttr(name); 1025 } else { 1026 u4 len = copy_u4(); 1027 1028 NSK_DISPLAY1("method attr len: %d\n", len); 1029 copy(len); 1030 } 1031 } 1032 1033 static void copyMethod() { 1034 u2 accessFlags; 1035 u2 methodNameIdx; 1036 char* name; 1037 u2 attrCount; 1038 u2 i; 1039 1040 accessFlags = copy_u2(); 1041 methodNameIdx = copy_u2(); 1042 name = constantPool[methodNameIdx]; 1043 1044 /* descriptor */ 1045 copy(2); 1046 1047 attrCount = copy_u2(); 1048 NSK_DISPLAY1("method attrCount: %d\n", attrCount); 1049 for (i = attrCount; i > 0; i--) { 1050 copyAttrForMethod(name); 1051 } 1052 } 1053 1054 static void copyMethods() { 1055 u2 count; 1056 u2 i; 1057 1058 count = copy_u2(); 1059 NSK_DISPLAY1("methods count: %d\n", count); 1060 for (i = count; i > 0; i--) { 1061 copyMethod(); 1062 } 1063 } 1064 1065 static u2 writeCPEntryUtf8(char* str) { 1066 u2 i; 1067 u2 len = (u2) strlen(str); 1068 put_u1(CONSTANT_Utf8); 1069 put_u2(len); 1070 for (i = 0; i < len; i++) { 1071 put_u1(str[i]); 1072 } 1073 return constantPoolCount++; 1074 } 1075 1076 static u2 writeCPEntryClass(u2 classNameIndex) { 1077 put_u1(CONSTANT_Class); 1078 put_u2(classNameIndex); 1079 return constantPoolCount++; 1080 } 1081 1082 static u2 writeCPEntryNameAndType(u2 nameIndex, u2 descrIndex) { 1083 put_u1(CONSTANT_NameAndType); 1084 put_u2(nameIndex); 1085 put_u2(descrIndex); 1086 return constantPoolCount++; 1087 } 1088 1089 static u2 writeCPEntryMethodRef(u2 classIndex, u2 nameAndTypeIndex) { 1090 put_u1(CONSTANT_Methodref); 1091 put_u2(classIndex); 1092 put_u2(nameAndTypeIndex); 1093 return constantPoolCount++; 1094 } 1095 1096 static u2 writeCPEntryFieldRef(u2 classIndex, u2 nameAndTypeIndex) { 1097 put_u1(CONSTANT_Fieldref); 1098 put_u2(classIndex); 1099 put_u2(nameAndTypeIndex); 1100 return constantPoolCount++; 1101 } 1102 1103 static u2 addFieldToConstantPool(u2 classIndex, char* fieldName, char* descr) { 1104 u2 fieldNameIndex = writeCPEntryUtf8(fieldName); 1105 u2 descrIndex = writeCPEntryUtf8(descr); 1106 u2 nameAndTypeIndex = writeCPEntryNameAndType(fieldNameIndex, descrIndex); 1107 u2 fieldIndex = writeCPEntryFieldRef(classIndex, nameAndTypeIndex); 1108 return fieldIndex; 1109 } 1110 1111 static u2 addMethodToConstantPool(u2 classIndex, char* methodName, char* descr) { 1112 u2 methodNameIndex = writeCPEntryUtf8(methodName); 1113 u2 descrIndex = writeCPEntryUtf8(descr); 1114 u2 nameAndTypeIndex = writeCPEntryNameAndType(methodNameIndex, descrIndex); 1115 u2 methodIndex = writeCPEntryMethodRef(classIndex, nameAndTypeIndex); 1116 return methodIndex; 1117 } 1118 1119 static u2 addClassToConstantPool(char* className) { 1120 u2 classNameIndex = writeCPEntryUtf8(className); 1121 u2 classIndex = writeCPEntryClass(classNameIndex); 1122 return classIndex; 1123 } 1124 1125 /* ========================================================================== */ 1126 1127 int Inject(const u1* old_bytes, const jint old_length, 1128 u1** new_bytes, jint* new_length, int bci_mode) { 1129 u4 constantPoolCountPos; 1130 u2 profiler; 1131 u2 interfaceCount; 1132 u2 attrCount; 1133 1134 //printf("inject\n"); 1135 NSK_DISPLAY3("Injecting bytecodes: mode=%d, bytes=0x%p, len=%d\n", 1136 bci_mode, old_bytes, old_length); 1137 1138 mode = bci_mode; 1139 orig = old_bytes; 1140 inputPos = (u1*) orig; 1141 endPos = orig + old_length; 1142 gen = (u1*) malloc(old_length * GROWTH_FACTOR); 1143 if (!NSK_VERIFY(gen != NULL)) { 1144 NSK_COMPLAIN0("out of memory\n"); 1145 return NSK_FALSE; 1146 } 1147 1148 genPos = gen; 1149 1150 /* magic + minor/major version */ 1151 copy(4 + 2 + 2); 1152 1153 constantPoolCountPos = generatedPosition(); 1154 constantPoolCount = copy_u2(); 1155 1156 /* copy old constant pool */ 1157 if (!copyConstantPool(constantPoolCount)) { 1158 return NSK_FALSE; 1159 } 1160 NSK_DISPLAY1("ConstantPool expanded from: %d\n", constantPoolCount); 1161 1162 profiler = addClassToConstantPool("nsk/share/jvmti/ProfileCollector"); 1163 1164 if (mode == BCI_MODE_ALLOC) { 1165 u2 allocTracker = 1166 addMethodToConstantPool(profiler, "allocTracker", "()V"); 1167 allocBytes[1] = (u1) (allocTracker >> 8); 1168 allocBytes[2] = (u1) (allocTracker & 0xFF); 1169 } 1170 1171 if (mode == BCI_MODE_CALL) { 1172 u2 callTracker = 1173 addMethodToConstantPool(profiler, "callTracker", "()V"); 1174 callBytes[1] = (u1) (callTracker >> 8); 1175 callBytes[2] = (u1) (callTracker & 0xFF); 1176 } 1177 1178 /* access, this, super */ 1179 copy(2 + 2 + 2); 1180 1181 interfaceCount = copy_u2(); 1182 NSK_DISPLAY1("interfaceCount: %d\n", interfaceCount); 1183 copy(interfaceCount * 2); 1184 1185 copyFields(); 1186 copyMethods(); 1187 1188 attrCount = copy_u2(); 1189 NSK_DISPLAY1("class attrCount: %d\n", attrCount); 1190 copyAttrs(attrCount); 1191 1192 randomAccessWriteU2(constantPoolCountPos, constantPoolCount); 1193 NSK_DISPLAY1("New constant pool size: %d\n", constantPoolCount); 1194 1195 *new_length = (jint) (genPos - gen); 1196 *new_bytes = realloc(gen, *new_length); 1197 1198 freeConstantPool(); 1199 1200 return NSK_TRUE; 1201 } 1202 1203 /* ========================================================================== */ 1204 1205 #ifdef __cplusplus 1206 } 1207 #endif