📄 java_crw_demo.c
字号:
static ByteOffsetentry_injection_code(MethodImage *mi, ByteCode *bytecodes, ByteOffset len){ CrwClassImage * ci; ByteOffset nbytes = 0; CRW_ASSERT_MI(mi); ci = mi->ci; if ( mi->object_init_method ) { nbytes = injection_template(mi, bytecodes, len, ci->object_init_tracker_index); } if ( !mi->skip_call_return_sites ) { nbytes += injection_template(mi, bytecodes+nbytes, len-nbytes, ci->call_tracker_index); } return nbytes;}/* Called to create injection code before an opcode */static ByteOffsetbefore_injection_code(MethodImage *mi, ClassOpcode opcode, ByteCode *bytecodes, ByteOffset len){ ByteOffset nbytes = 0; CRW_ASSERT_MI(mi); switch ( opcode ) { case JVM_OPC_return: case JVM_OPC_ireturn: case JVM_OPC_lreturn: case JVM_OPC_freturn: case JVM_OPC_dreturn: case JVM_OPC_areturn: if ( !mi->skip_call_return_sites ) { nbytes = injection_template(mi, bytecodes, len, mi->ci->return_tracker_index); } break; default: break; } return nbytes;}/* Called to create injection code after an opcode */static ByteOffsetafter_injection_code(MethodImage *mi, ClassOpcode opcode, ByteCode *bytecodes, ByteOffset len){ CrwClassImage* ci; ByteOffset nbytes; ci = mi->ci; nbytes = 0; CRW_ASSERT_MI(mi); switch ( opcode ) { case JVM_OPC_new: /* Can't inject here cannot pass around uninitialized object */ break; case JVM_OPC_newarray: case JVM_OPC_anewarray: case JVM_OPC_multianewarray: nbytes = injection_template(mi, bytecodes, len, ci->newarray_tracker_index); break; default: break; } return nbytes;}/* Actually inject the bytecodes */static void inject_bytecodes(MethodImage *mi, ByteOffset at, ByteCode *bytecodes, ByteOffset len) { Injection injection; CrwClassImage *ci; ci = mi->ci; CRW_ASSERT_MI(mi); CRW_ASSERT(ci, at <= mi->code_len); injection = mi->injections[at]; CRW_ASSERT(ci, len <= LARGEST_INJECTION/2); CRW_ASSERT(ci, injection.len+len <= LARGEST_INJECTION); /* Either start an injection area or concatenate to what is there */ if ( injection.code == NULL ) { CRW_ASSERT(ci, injection.len==0); injection.code = (ByteCode *)allocate_clean(ci, LARGEST_INJECTION+1); } (void)memcpy(injection.code+injection.len, bytecodes, len); injection.len += len; injection.code[injection.len] = 0; mi->injections[at] = injection; ci->injection_count++;}/* ----------------------------------------------------------------- *//* Method handling functions */static MethodImage *method_init(CrwClassImage *ci, unsigned mnum, ByteOffset code_len){ MethodImage * mi; ByteOffset i; mi = (MethodImage*)allocate_clean(ci, (int)sizeof(MethodImage)); mi->ci = ci; mi->name = ci->method_name[mnum]; mi->descr = ci->method_descr[mnum]; mi->code_len = code_len; mi->map = (ByteOffset*)allocate_clean(ci, (int)((code_len+1)*sizeof(ByteOffset))); for(i=0; i<=code_len; i++) { mi->map[i] = i; } mi->widening = (signed char*)allocate_clean(ci, code_len+1); mi->injections = (Injection *)allocate_clean(ci, (int)((code_len+1)*sizeof(Injection))); mi->number = mnum; ci->current_mi = mi; return mi;}static voidmethod_term(MethodImage *mi){ CrwClassImage *ci; ci = mi->ci; CRW_ASSERT_MI(mi); if ( mi->map != NULL ) { deallocate(ci, (void*)mi->map); mi->map = NULL; } if ( mi->widening != NULL ) { deallocate(ci, (void*)mi->widening); mi->widening = NULL; } if ( mi->injections != NULL ) { ByteOffset i; for(i=0; i<= mi->code_len; i++) { if ( mi->injections[i].code != NULL ) { deallocate(ci, (void*)mi->injections[i].code); mi->injections[i].code = NULL; } } deallocate(ci, (void*)mi->injections); mi->injections = NULL; } ci->current_mi = NULL; deallocate(ci, (void*)mi);}static ByteOffsetinput_code_offset(MethodImage *mi){ CRW_ASSERT_MI(mi); return (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes);}static voidrewind_to_beginning_of_input_bytecodes(MethodImage *mi){ CRW_ASSERT_MI(mi); mi->ci->input_position = mi->start_of_input_bytecodes;}/* Starting at original byte position 'at', add 'offset' to it's new * location. This may be a negative value. * NOTE: That this map is not the new bytecode location of the opcode * but the new bytecode location that should be used when * a goto or jump instruction was targeting the old bytecode * location. */static void adjust_map(MethodImage *mi, ByteOffset at, ByteOffset offset) { ByteOffset i; CRW_ASSERT_MI(mi); for (i = at; i <= mi->code_len; ++i) { mi->map[i] += offset; }}static void widen(MethodImage *mi, ByteOffset at, ByteOffset len) { int delta; CRW_ASSERT(mi->ci, at <= mi->code_len); delta = len - mi->widening[at]; /* Adjust everything from the current input location by delta */ adjust_map(mi, input_code_offset(mi), delta); /* Mark at beginning of instruction */ mi->widening[at] = (signed char)len;}static voidverify_opc_wide(CrwClassImage *ci, ClassOpcode wopcode){ switch (wopcode) { case JVM_OPC_aload: case JVM_OPC_astore: case JVM_OPC_fload: case JVM_OPC_fstore: case JVM_OPC_iload: case JVM_OPC_istore: case JVM_OPC_lload: case JVM_OPC_lstore: case JVM_OPC_dload: case JVM_OPC_dstore: case JVM_OPC_ret: case JVM_OPC_iinc: break; default: CRW_FATAL(ci, "Invalid opcode supplied to wide opcode"); break; }}static unsignedopcode_length(CrwClassImage *ci, ClassOpcode opcode){ /* Define array that holds length of an opcode */ static unsigned char _opcode_length[JVM_OPC_MAX+1] = JVM_OPCODE_LENGTH_INITIALIZER; if ( opcode > JVM_OPC_MAX ) { CRW_FATAL(ci, "Invalid opcode supplied to opcode_length()"); } return _opcode_length[opcode];} /* Walk one instruction and inject instrumentation */static void inject_for_opcode(MethodImage *mi) { CrwClassImage * ci; ClassOpcode opcode; int pos; CRW_ASSERT_MI(mi); ci = mi->ci; pos = input_code_offset(mi); opcode = readU1(ci); if (opcode == JVM_OPC_wide) { ClassOpcode wopcode; wopcode = readU1(ci); /* lvIndex not used */ (void)readU2(ci); verify_opc_wide(ci, wopcode); if ( wopcode==JVM_OPC_iinc ) { (void)readU1(ci); (void)readU1(ci); } } else { ByteCode bytecodes[LARGEST_INJECTION+1]; int header; int instr_len; int low; int high; int npairs; ByteOffset len; /* Get bytecodes to inject before this opcode */ len = before_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes)); if ( len > 0 ) { inject_bytecodes(mi, pos, bytecodes, len); /* Adjust map after processing this opcode */ } /* Process this opcode */ switch (opcode) { case JVM_OPC_tableswitch: header = NEXT_4BYTE_BOUNDARY(pos); skip(ci, header - (pos+1)); (void)readU4(ci); low = readU4(ci); high = readU4(ci); skip(ci, (high+1-low) * 4); break; case JVM_OPC_lookupswitch: header = NEXT_4BYTE_BOUNDARY(pos); skip(ci, header - (pos+1)); (void)readU4(ci); npairs = readU4(ci); skip(ci, npairs * 8); break; default: instr_len = opcode_length(ci, opcode); skip(ci, instr_len-1); break; } /* Get position after this opcode is processed */ pos = input_code_offset(mi); /* Adjust for any before_injection_code() */ if ( len > 0 ) { /* Adjust everything past this opcode. * Why past it? Because we want any jumps to this bytecode loc * to go to the injected code, not where the opcode * was moved too. * Consider a 'return' opcode that is jumped too. * NOTE: This may not be correct in all cases, but will * when we are only dealing with non-variable opcodes * like the return opcodes. Be careful if the * before_injection_code() changes to include other * opcodes that have variable length. */ adjust_map(mi, pos, len); } /* Get bytecodes to inject after this opcode */ len = after_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes)); if ( len > 0 ) { inject_bytecodes(mi, pos, bytecodes, len); /* Adjust for any after_injection_code() */ adjust_map(mi, pos, len); } }}/* Map original bytecode location to it's new location. (See adjust_map()). */static ByteOffsetmethod_code_map(MethodImage *mi, ByteOffset pos){ CRW_ASSERT_MI(mi); CRW_ASSERT(mi->ci, pos <= mi->code_len); return mi->map[pos];}static int adjust_instruction(MethodImage *mi) { CrwClassImage * ci; ClassOpcode opcode; int pos; int new_pos; CRW_ASSERT_MI(mi); ci = mi->ci; pos = input_code_offset(mi); new_pos = method_code_map(mi,pos); opcode = readU1(ci); if (opcode == JVM_OPC_wide) { ClassOpcode wopcode; wopcode = readU1(ci); /* lvIndex not used */ (void)readU2(ci); verify_opc_wide(ci, wopcode); if ( wopcode==JVM_OPC_iinc ) { (void)readU1(ci); (void)readU1(ci); } } else { int widened; int header; int newHeader; int low; int high; int new_pad; int old_pad; int delta; int new_delta; int delta_pad; int npairs; int instr_len; switch (opcode) { case JVM_OPC_tableswitch: widened = mi->widening[pos]; header = NEXT_4BYTE_BOUNDARY(pos); newHeader = NEXT_4BYTE_BOUNDARY(new_pos); skip(ci, header - (pos+1)); delta = readU4(ci); low = readU4(ci); high = readU4(ci); skip(ci, (high+1-low) * 4); new_pad = newHeader - new_pos; old_pad = header - pos; delta_pad = new_pad - old_pad; if (widened != delta_pad) { widen(mi, pos, delta_pad); return 0; } break; case JVM_OPC_lookupswitch: widened = mi->widening[pos]; header = NEXT_4BYTE_BOUNDARY(pos); newHeader = NEXT_4BYTE_BOUNDARY(new_pos); skip(ci, header - (pos+1)); delta = readU4(ci); npairs = readU4(ci); skip(ci, npairs * 8); new_pad = newHeader - new_pos; old_pad = header - pos; delta_pad = new_pad - old_pad; if (widened != delta_pad) { widen(mi, pos, delta_pad); return 0; } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -