📄 java_crw_demo.c
字号:
static voidcopy_verification_types(MethodImage *mi, int ntypes){ /* If there were ntypes, we just copy that over, no changes */ if ( ntypes > 0 ) { int j; for ( j = 0 ; j < ntypes ; j++ ) { unsigned tag; tag = copyU1(mi->ci); switch ( tag ) { case JVM_ITEM_Object: (void)copyU2(mi->ci); /* Constant pool entry */ break; case JVM_ITEM_Uninitialized: /* Code offset for 'new' opcode is for this object */ writeUoffset(mi, method_code_map(mi, readUoffset(mi))); break; } } }}/* Process the StackMapTable attribute. We didn't add any basic blocks * so the frame count remains the same but we may need to process the * frame types due to offset changes putting things out of range. */static voidwrite_stackmap_table(MethodImage *mi){ CrwClassImage *ci; CrwPosition save_position; ByteOffset last_pc; ByteOffset last_new_pc; unsigned i; unsigned attr_len; unsigned new_attr_len; unsigned count; unsigned delta_adj; CRW_ASSERT_MI(mi); ci = mi->ci; /* Save the position of the attribute length so we can fix it later */ save_position = ci->output_position; attr_len = copyU4(ci); count = copyUoffset(mi); /* uoffset: number_of_entries */ if ( count == 0 ) { CRW_ASSERT(ci, attr_len==2); return; } /* Process entire stackmap */ last_pc = 0; last_new_pc = 0; delta_adj = 0; for ( i = 0 ; i < count ; i++ ) { ByteOffset new_pc; /* new pc in instrumented code */ unsigned ft; /* frame_type */ int delta; /* pc delta */ int new_delta; /* new pc delta */ ft = readU1(ci); if ( ft <= 63 ) { /* Frame Type: same_frame ([0,63]) */ unsigned new_ft; /* new frame_type */ delta = (delta_adj + ft); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; new_ft = (new_delta - delta_adj); if ( new_ft > 63 ) { /* Change to same_frame_extended (251) */ new_ft = 251; writeU1(ci, new_ft); writeUoffset(mi, (new_delta - delta_adj)); } else { writeU1(ci, new_ft); } } else if ( ft >= 64 && ft <= 127 ) { /* Frame Type: same_locals_1_stack_item_frame ([64,127]) */ unsigned new_ft; /* new frame_type */ delta = (delta_adj + ft - 64); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; if ( (new_delta - delta_adj) > 63 ) { /* Change to same_locals_1_stack_item_frame_extended (247) */ new_ft = 247; writeU1(ci, new_ft); writeUoffset(mi, (new_delta - delta_adj)); } else { new_ft = (new_delta - delta_adj) + 64; writeU1(ci, new_ft); } copy_verification_types(mi, 1); } else if ( ft >= 128 && ft <= 246 ) { /* Frame Type: reserved_for_future_use ([128,246]) */ CRW_FATAL(ci, "Unknown frame type in StackMapTable attribute"); } else if ( ft == 247 ) { /* Frame Type: same_locals_1_stack_item_frame_extended (247) */ delta = (delta_adj + readUoffset(mi)); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; writeU1(ci, ft); writeUoffset(mi, (new_delta - delta_adj)); copy_verification_types(mi, 1); } else if ( ft >= 248 && ft <= 250 ) { /* Frame Type: chop_frame ([248,250]) */ delta = (delta_adj + readUoffset(mi)); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; writeU1(ci, ft); writeUoffset(mi, (new_delta - delta_adj)); } else if ( ft == 251 ) { /* Frame Type: same_frame_extended (251) */ delta = (delta_adj + readUoffset(mi)); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; writeU1(ci, ft); writeUoffset(mi, (new_delta - delta_adj)); } else if ( ft >= 252 && ft <= 254 ) { /* Frame Type: append_frame ([252,254]) */ delta = (delta_adj + readUoffset(mi)); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; writeU1(ci, ft); writeUoffset(mi, (new_delta - delta_adj)); copy_verification_types(mi, (ft - 251)); } else if ( ft == 255 ) { unsigned ntypes; /* Frame Type: full_frame (255) */ delta = (delta_adj + readUoffset(mi)); new_pc = method_code_map(mi, last_pc + delta); new_delta = new_pc - last_new_pc; writeU1(ci, ft); writeUoffset(mi, (new_delta - delta_adj)); ntypes = copyU2(ci); /* ulocalvar */ copy_verification_types(mi, ntypes); ntypes = copyU2(ci); /* ustack */ copy_verification_types(mi, ntypes); } /* Update last_pc and last_new_pc (save on calls to method_code_map) */ CRW_ASSERT(ci, delta >= 0); CRW_ASSERT(ci, new_delta >= 0); last_pc += delta; last_new_pc = new_pc; CRW_ASSERT(ci, last_pc <= mi->code_len); CRW_ASSERT(ci, last_new_pc <= mi->new_code_len); /* Delta adjustment, all deltas are -1 now in attribute */ delta_adj = 1; } /* Update the attribute length */ new_attr_len = ci->output_position - (save_position + 4); CRW_ASSERT(ci, new_attr_len >= attr_len); random_writeU4(ci, save_position, new_attr_len);}/* Process the CLDC StackMap attribute. We didn't add any basic blocks * so the frame count remains the same but we may need to process the * frame types due to offset changes putting things out of range. */static voidwrite_cldc_stackmap_table(MethodImage *mi){ CrwClassImage *ci; CrwPosition save_position; unsigned i; unsigned attr_len; unsigned new_attr_len; unsigned count; CRW_ASSERT_MI(mi); ci = mi->ci; /* Save the position of the attribute length so we can fix it later */ save_position = ci->output_position; attr_len = copyU4(ci); count = copyUoffset(mi); /* uoffset: number_of_entries */ if ( count == 0 ) { CRW_ASSERT(ci, attr_len==2); return; } /* Process entire stackmap */ for ( i = 0 ; i < count ; i++ ) { unsigned ntypes; writeUoffset(mi, method_code_map(mi, readUoffset(mi))); ntypes = copyU2(ci); /* ulocalvar */ copy_verification_types(mi, ntypes); ntypes = copyU2(ci); /* ustack */ copy_verification_types(mi, ntypes); } /* Update the attribute length */ new_attr_len = ci->output_position - (save_position + 4); CRW_ASSERT(ci, new_attr_len >= attr_len); random_writeU4(ci, save_position, new_attr_len);}static voidmethod_write_exception_table(MethodImage *mi){ unsigned i; unsigned count; CrwClassImage * ci; CRW_ASSERT_MI(mi); ci = mi->ci; count = copyU2(ci); for(i=0; i<count; i++) { ByteOffset start_pc; ByteOffset new_start_pc; ByteOffset end_pc; ByteOffset new_end_pc; ByteOffset handler_pc; ByteOffset new_handler_pc; start_pc = readU2(ci); end_pc = readU2(ci); handler_pc = readU2(ci); new_start_pc = method_code_map(mi, start_pc); new_end_pc = method_code_map(mi, end_pc); new_handler_pc = method_code_map(mi, handler_pc); writeU2(ci, new_start_pc); writeU2(ci, new_end_pc); writeU2(ci, new_handler_pc); (void)copyU2(ci); }}static intattribute_match(CrwClassImage *ci, CrwCpoolIndex name_index, const char *name){ CrwConstantPoolEntry cs; int len; CRW_ASSERT_CI(ci); CRW_ASSERT(ci, name!=NULL); len = (int)strlen(name); cs = cpool_entry(ci, name_index); if ( cs.len==len && strncmp(cs.ptr, name, len)==0) { return 1; } return 0;}static void method_write_code_attribute(MethodImage *mi){ CrwClassImage * ci; CrwCpoolIndex name_index; CRW_ASSERT_MI(mi); ci = mi->ci; name_index = copyU2(ci); if ( attribute_match(ci, name_index, "LineNumberTable") ) { write_line_table(mi); } else if ( attribute_match(ci, name_index, "LocalVariableTable") ) { write_var_table(mi); } else if ( attribute_match(ci, name_index, "LocalVariableTypeTable") ) { write_var_table(mi); /* Exact same format as the LocalVariableTable */ } else if ( attribute_match(ci, name_index, "StackMapTable") ) { write_stackmap_table(mi); } else if ( attribute_match(ci, name_index, "StackMap") ) { write_cldc_stackmap_table(mi); } else { unsigned len; len = copyU4(ci); copy(ci, len); }}static intis_init_method(const char *name){ if ( name!=NULL && strcmp(name,"<init>")==0 ) { return JNI_TRUE; } return JNI_FALSE;}static intis_clinit_method(const char *name){ if ( name!=NULL && strcmp(name,"<clinit>")==0 ) { return JNI_TRUE; } return JNI_FALSE;}static intis_finalize_method(const char *name){ if ( name!=NULL && strcmp(name,"finalize")==0 ) { return JNI_TRUE; } return JNI_FALSE;}static intskip_method(CrwClassImage *ci, const char *name, unsigned access_flags, ByteOffset code_len, int system_class, jboolean *pskip_call_return_sites){ *pskip_call_return_sites = JNI_FALSE; if ( system_class ) { if ( code_len == 1 && is_init_method(name) ) { return JNI_TRUE; } else if ( code_len == 1 && is_finalize_method(name) ) { return JNI_TRUE; } else if ( is_clinit_method(name) ) { return JNI_TRUE; } else if ( ci->is_thread_class && strcmp(name,"currentThread")==0 ) { return JNI_TRUE; } /* if ( access_flags & JVM_ACC_PRIVATE ) { *pskip_call_return_sites = JNI_TRUE; } */ } return JNI_FALSE;}/* Process all code attributes */static void method_write_bytecodes(CrwClassImage *ci, unsigned mnum, unsigned access_flags){ CrwPosition output_attr_len_position; CrwPosition output_max_stack_position; CrwPosition output_code_len_position; CrwPosition start_of_output_bytecodes; unsigned i; unsigned attr_len; unsigned max_stack; ByteOffset code_len; unsigned attr_count; unsigned new_attr_len; MethodImage * mi; jboolean object_init_method; jboolean skip_call_return_sites; CRW_ASSERT_CI(ci); /* Attribute Length */ output_attr_len_position = ci->output_position; attr_len = copyU4(ci); /* Max Stack */ output_max_stack_position = ci->output_position; max_stack = copyU2(ci); /* Max Locals */ (void)copyU2(ci); /* Code Length */ output_code_len_position = ci->output_position; code_len = copyU4(ci); start_of_output_bytecodes = ci->output_position; /* Some methods should not be instrumented */ object_init_method = JNI_FALSE; skip_call_return_sites = JNI_FALSE; if ( ci->is_object_class && is_init_method(ci->method_name[mnum]) && strcmp(ci->method_descr[mnum],"()V")==0 ) { object_init_method = JNI_TRUE; skip_call_return_sites = JNI_TRUE; } else if ( skip_method(ci, ci->method_name[mnum], access_flags, code_len, ci->system_class, &skip_call_return_sites) ) { /* Copy remainder minus already copied, the U2 max_stack, * U2 max_locals, and U4 code_length fields have already * been processed. */ copy(ci, attr_len - (2+2+4)); return; } /* Start Injection */ mi = method_init(ci, mnum, code_len); mi->object_init_method = object_init_method; mi->access_flags = access_flags; mi->skip_call_return_sites = skip_call_return_sites; /* Save the current position as the start of the input bytecodes */ mi->start_of_input_bytecodes = ci->input_position; /* The max stack may increase */ mi->max_stack = max_stack; mi->new_max_stack = max_stack; /* Adjust all code offsets */ method_inject_and_write_code(mi); /* Fix up code length (save new_code_len for later attribute processing) */ mi->new_code_len = (int)(ci->output_position - start_of_output_bytecodes); random_writeU4(ci, output_code_len_position, mi->new_code_len); /* Fixup max stack */ CRW_ASSERT(ci, mi->new_max_stack <= 0xFFFF); random_writeU2(ci, output_max_stack_position, mi->new_max_stack); /* Copy exception table */ method_write_exception_table(mi); /* Copy code attributes (needs mi->new_code_len) */ attr_count = copyU2(ci); for (i = 0; i < attr_count; ++i) { method_write_code_attribute(mi); } /* Fix up attribute leng
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -