📄 java_crw_demo.c
字号:
/* * @(#)java_crw_demo.c 1.39 06/01/27 * * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * -Redistribution of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Sun Microsystems, Inc. or the names of contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. ALL * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or intended * for use in the design, construction, operation or maintenance of any * nuclear facility. *//* Class reader writer (java_crw_demo) for instrumenting bytecodes *//* * As long as the callbacks allow for it and the class number is unique, * this code is completely re-entrant and any number of classfile * injections can happen at the same time. * * The current logic requires a unique number for this class instance * or (jclass,jobject loader) pair, this is done via the ClassIndex * in hprof, which is passed in as the 'unsigned cnum' to java_crw_demo(). * It's up to the user of this interface if it wants to use this * feature. * * Example Usage: See file test_crw.c. * */#include <stdio.h>#include <stdlib.h>#include <string.h>/* Get Java and class file and bytecode information. */#include <jni.h>#include "classfile_constants.h"/* Include our own interface for cross check */#include "java_crw_demo.h"/* Macros over error functions to capture line numbers */#define CRW_FATAL(ci, message) fatal_error(ci, message, __FILE__, __LINE__)#if defined(DEBUG) || !defined(NDEBUG) #define CRW_ASSERT(ci, cond) \ ((cond)?(void)0:assert_error(ci, #cond, __FILE__, __LINE__)) #else #define CRW_ASSERT(ci, cond) #endif#define CRW_ASSERT_MI(mi) CRW_ASSERT((mi)?(mi)->ci:NULL,(mi)!=NULL)#define CRW_ASSERT_CI(ci) CRW_ASSERT(ci, ( (ci) != NULL && \ (ci)->input_position <= (ci)->input_len && \ (ci)->output_position <= (ci)->output_len) )/* Typedefs for various integral numbers, just for code clarity */typedef unsigned ClassOpcode; /* One opcode */typedef unsigned char ByteCode; /* One byte from bytecodes */typedef int ByteOffset; /* Byte offset */typedef int ClassConstant; /* Constant pool kind */typedef long CrwPosition; /* Position in class image */typedef unsigned short CrwCpoolIndex; /* Index into constant pool *//* Misc support macros *//* Given the position of an opcode, find the next 4byte boundary position */#define NEXT_4BYTE_BOUNDARY(opcode_pos) (((opcode_pos)+4) & (~3))#define LARGEST_INJECTION (12*3) /* 3 injections at same site */#define MAXIMUM_NEW_CPOOL_ENTRIES 64 /* don't add more than 32 entries *//* Constant Pool Entry (internal table that mirrors pool in file image) */typedef struct { const char * ptr; /* Pointer to any string */ unsigned short len; /* Length of string */ unsigned int index1; /* 1st 16 bit index or 32bit value. */ unsigned int index2; /* 2nd 16 bit index or 32bit value. */ ClassConstant tag; /* Tag or kind of entry. */} CrwConstantPoolEntry;struct MethodImage;/* Class file image storage structure */typedef struct CrwClassImage { /* Unique class number for this class */ unsigned number; /* Name of class, given or gotten out of class image */ const char * name; /* Input and Output class images tracking */ const unsigned char * input; unsigned char * output; CrwPosition input_len; CrwPosition output_len; CrwPosition input_position; CrwPosition output_position; /* Mirrored constant pool */ CrwConstantPoolEntry * cpool; CrwCpoolIndex cpool_max_elements; /* Max count */ CrwCpoolIndex cpool_count_plus_one; /* Input flags about class (e.g. is it a system class) */ int system_class; /* Class access flags gotten from file. */ unsigned access_flags; /* Names of classes and methods. */ char* tclass_name; /* Name of class that has tracker methods. */ char* tclass_sig; /* Signature of class */ char* call_name; /* Method name to call at offset 0 */ char* call_sig; /* Signature of this method */ char* return_name; /* Method name to call before any return */ char* return_sig; /* Signature of this method */ char* obj_init_name; /* Method name to call in Object <init> */ char* obj_init_sig; /* Signature of this method */ char* newarray_name; /* Method name to call after newarray opcodes */ char* newarray_sig; /* Signature of this method */ /* Constant pool index values for new entries */ CrwCpoolIndex tracker_class_index; CrwCpoolIndex object_init_tracker_index; CrwCpoolIndex newarray_tracker_index; CrwCpoolIndex call_tracker_index; CrwCpoolIndex return_tracker_index; CrwCpoolIndex class_number_index; /* Class number in pool */ /* Count of injections made into this class */ int injection_count; /* This class must be the java.lang.Object class */ jboolean is_object_class; /* This class must be the java.lang.Thread class */ jboolean is_thread_class; /* Callback functions */ FatalErrorHandler fatal_error_handler; MethodNumberRegister mnum_callback; /* Table of method names and descr's */ int method_count; const char ** method_name; const char ** method_descr; struct MethodImage * current_mi;} CrwClassImage;/* Injection bytecodes (holds injected bytecodes for each code position) */typedef struct { ByteCode * code; ByteOffset len;} Injection;/* Method transformation data (allocated/freed as each method is processed) */typedef struct MethodImage { /* Back reference to Class image data. */ CrwClassImage * ci; /* Unique method number for this class. */ unsigned number; /* Method name and descr */ const char * name; const char * descr; /* Map of input bytecode offsets to output bytecode offsets */ ByteOffset * map; /* Bytecode injections for each input bytecode offset */ Injection * injections; /* Widening setting for each input bytecode offset */ signed char * widening; /* Length of original input bytecodes, and new bytecodes. */ ByteOffset code_len; ByteOffset new_code_len; /* Location in input where bytecodes are located. */ CrwPosition start_of_input_bytecodes; /* Original max_stack and new max stack */ unsigned max_stack; unsigned new_max_stack; jboolean object_init_method; jboolean skip_call_return_sites; /* Method access flags gotten from file. */ unsigned access_flags; } MethodImage;/* ----------------------------------------------------------------- *//* General support functions (memory and error handling) */static void fatal_error(CrwClassImage *ci, const char *message, const char *file, int line){ if ( ci != NULL && ci->fatal_error_handler != NULL ) { (*ci->fatal_error_handler)(message, file, line); } else { /* Normal operation should NEVER reach here */ /* NO CRW FATAL ERROR HANDLER! */ (void)fprintf(stderr, "CRW: %s [%s:%d]\n", message, file, line); abort(); }}#if defined(DEBUG) || !defined(NDEBUG)static voidassert_error(CrwClassImage *ci, const char *condition, const char *file, int line){ char buf[512]; MethodImage *mi; ByteOffset byte_code_offset; mi = ci->current_mi; if ( mi != NULL ) { byte_code_offset = (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes); } else { byte_code_offset=-1; } (void)sprintf(buf, "CRW ASSERTION FAILURE: %s (%s:%s:%d)", condition, ci->name==0?"?":ci->name, mi->name==0?"?":mi->name, byte_code_offset); fatal_error(ci, buf, file, line);}#endifstatic void *allocate(CrwClassImage *ci, int nbytes){ void * ptr; if ( nbytes <= 0 ) { CRW_FATAL(ci, "Cannot allocate <= 0 bytes"); } ptr = malloc(nbytes); if ( ptr == NULL ) { CRW_FATAL(ci, "Ran out of malloc memory"); } return ptr;}static void *reallocate(CrwClassImage *ci, void *optr, int nbytes){ void * ptr; if ( optr == NULL ) { CRW_FATAL(ci, "Cannot deallocate NULL"); } if ( nbytes <= 0 ) { CRW_FATAL(ci, "Cannot reallocate <= 0 bytes"); } ptr = realloc(optr, nbytes); if ( ptr == NULL ) { CRW_FATAL(ci, "Ran out of malloc memory"); } return ptr;}static void *allocate_clean(CrwClassImage *ci, int nbytes){ void * ptr; if ( nbytes <= 0 ) { CRW_FATAL(ci, "Cannot allocate <= 0 bytes"); } ptr = calloc(nbytes, 1); if ( ptr == NULL ) { CRW_FATAL(ci, "Ran out of malloc memory"); } return ptr;}static const char *duplicate(CrwClassImage *ci, const char *str, int len){ char *copy; copy = (char*)allocate(ci, len+1); (void)memcpy(copy, str, len); copy[len] = 0; return (const char *)copy;}static voiddeallocate(CrwClassImage *ci, void *ptr){ if ( ptr == NULL ) { CRW_FATAL(ci, "Cannot deallocate NULL"); } (void)free(ptr);}/* ----------------------------------------------------------------- *//* Functions for reading/writing bytes to/from the class images */static unsigned readU1(CrwClassImage *ci) { CRW_ASSERT_CI(ci); return ((unsigned)(ci->input[ci->input_position++])) & 0xFF;}static unsigned readU2(CrwClassImage *ci) { unsigned res; res = readU1(ci); return (res << 8) + readU1(ci);}static signed shortreadS2(CrwClassImage *ci) { unsigned res; res = readU1(ci); return ((res << 8) + readU1(ci)) & 0xFFFF;}static unsigned readU4(CrwClassImage *ci) { unsigned res; res = readU2(ci); return (res << 16) + readU2(ci);}static void writeU1(CrwClassImage *ci, unsigned val) /* Only writes out lower 8 bits */{ CRW_ASSERT_CI(ci); if ( ci->output != NULL ) { ci->output[ci->output_position++] = val & 0xFF; }}static void writeU2(CrwClassImage *ci, unsigned val) { writeU1(ci, val >> 8); writeU1(ci, val);}static void writeU4(CrwClassImage *ci, unsigned val) { writeU2(ci, val >> 16); writeU2(ci, val);}static unsigned copyU1(CrwClassImage *ci) { unsigned value; value = readU1(ci); writeU1(ci, value); return value;}static unsigned copyU2(CrwClassImage *ci) { unsigned value; value = readU2(ci);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -