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