blob: 5781ffe2494d61191d48c53994795e63fa46bd5f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/* Class reader writer (java_crw_demo) for instrumenting bytecodes */
33
34/*
35 * As long as the callbacks allow for it and the class number is unique,
36 * this code is completely re-entrant and any number of classfile
37 * injections can happen at the same time.
38 *
39 * The current logic requires a unique number for this class instance
40 * or (jclass,jobject loader) pair, this is done via the ClassIndex
41 * in hprof, which is passed in as the 'unsigned cnum' to java_crw_demo().
42 * It's up to the user of this interface if it wants to use this
43 * feature.
44 *
45 */
46
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50
51/* Get Java and class file and bytecode information. */
52
53#include <jni.h>
54
55#include "classfile_constants.h"
56
57
58/* Include our own interface for cross check */
59
60#include "java_crw_demo.h"
61
62/* Macros over error functions to capture line numbers */
63
64#define CRW_FATAL(ci, message) fatal_error(ci, message, __FILE__, __LINE__)
65
66#if defined(DEBUG) || !defined(NDEBUG)
67
68 #define CRW_ASSERT(ci, cond) \
69 ((cond)?(void)0:assert_error(ci, #cond, __FILE__, __LINE__))
70
71#else
72
73 #define CRW_ASSERT(ci, cond)
74
75#endif
76
77#define CRW_ASSERT_MI(mi) CRW_ASSERT((mi)?(mi)->ci:NULL,(mi)!=NULL)
78
79#define CRW_ASSERT_CI(ci) CRW_ASSERT(ci, ( (ci) != NULL && \
80 (ci)->input_position <= (ci)->input_len && \
81 (ci)->output_position <= (ci)->output_len) )
82
83/* Typedefs for various integral numbers, just for code clarity */
84
85typedef unsigned ClassOpcode; /* One opcode */
86typedef unsigned char ByteCode; /* One byte from bytecodes */
87typedef int ByteOffset; /* Byte offset */
88typedef int ClassConstant; /* Constant pool kind */
89typedef long CrwPosition; /* Position in class image */
90typedef unsigned short CrwCpoolIndex; /* Index into constant pool */
91
92/* Misc support macros */
93
94/* Given the position of an opcode, find the next 4byte boundary position */
95#define NEXT_4BYTE_BOUNDARY(opcode_pos) (((opcode_pos)+4) & (~3))
96
97#define LARGEST_INJECTION (12*3) /* 3 injections at same site */
98#define MAXIMUM_NEW_CPOOL_ENTRIES 64 /* don't add more than 32 entries */
99
100/* Constant Pool Entry (internal table that mirrors pool in file image) */
101
102typedef struct {
103 const char * ptr; /* Pointer to any string */
104 unsigned short len; /* Length of string */
105 unsigned int index1; /* 1st 16 bit index or 32bit value. */
106 unsigned int index2; /* 2nd 16 bit index or 32bit value. */
107 ClassConstant tag; /* Tag or kind of entry. */
108} CrwConstantPoolEntry;
109
110struct MethodImage;
111
112/* Class file image storage structure */
113
114typedef struct CrwClassImage {
115
116 /* Unique class number for this class */
117 unsigned number;
118
119 /* Name of class, given or gotten out of class image */
120 const char * name;
121
122 /* Input and Output class images tracking */
123 const unsigned char * input;
124 unsigned char * output;
125 CrwPosition input_len;
126 CrwPosition output_len;
127 CrwPosition input_position;
128 CrwPosition output_position;
129
130 /* Mirrored constant pool */
131 CrwConstantPoolEntry * cpool;
132 CrwCpoolIndex cpool_max_elements; /* Max count */
133 CrwCpoolIndex cpool_count_plus_one;
134
135 /* Input flags about class (e.g. is it a system class) */
136 int system_class;
137
138 /* Class access flags gotten from file. */
139 unsigned access_flags;
140
141 /* Names of classes and methods. */
142 char* tclass_name; /* Name of class that has tracker methods. */
143 char* tclass_sig; /* Signature of class */
144 char* call_name; /* Method name to call at offset 0 */
145 char* call_sig; /* Signature of this method */
146 char* return_name; /* Method name to call before any return */
147 char* return_sig; /* Signature of this method */
148 char* obj_init_name; /* Method name to call in Object <init> */
149 char* obj_init_sig; /* Signature of this method */
150 char* newarray_name; /* Method name to call after newarray opcodes */
151 char* newarray_sig; /* Signature of this method */
152
153 /* Constant pool index values for new entries */
154 CrwCpoolIndex tracker_class_index;
155 CrwCpoolIndex object_init_tracker_index;
156 CrwCpoolIndex newarray_tracker_index;
157 CrwCpoolIndex call_tracker_index;
158 CrwCpoolIndex return_tracker_index;
159 CrwCpoolIndex class_number_index; /* Class number in pool */
160
161 /* Count of injections made into this class */
162 int injection_count;
163
164 /* This class must be the java.lang.Object class */
165 jboolean is_object_class;
166
167 /* This class must be the java.lang.Thread class */
168 jboolean is_thread_class;
169
170 /* Callback functions */
171 FatalErrorHandler fatal_error_handler;
172 MethodNumberRegister mnum_callback;
173
174 /* Table of method names and descr's */
175 int method_count;
176 const char ** method_name;
177 const char ** method_descr;
178 struct MethodImage * current_mi;
179
180} CrwClassImage;
181
182/* Injection bytecodes (holds injected bytecodes for each code position) */
183
184typedef struct {
185 ByteCode * code;
186 ByteOffset len;
187} Injection;
188
189/* Method transformation data (allocated/freed as each method is processed) */
190
191typedef struct MethodImage {
192
193 /* Back reference to Class image data. */
194 CrwClassImage * ci;
195
196 /* Unique method number for this class. */
197 unsigned number;
198
199 /* Method name and descr */
200 const char * name;
201 const char * descr;
202
203 /* Map of input bytecode offsets to output bytecode offsets */
204 ByteOffset * map;
205
206 /* Bytecode injections for each input bytecode offset */
207 Injection * injections;
208
209 /* Widening setting for each input bytecode offset */
210 signed char * widening;
211
212 /* Length of original input bytecodes, and new bytecodes. */
213 ByteOffset code_len;
214 ByteOffset new_code_len;
215
216 /* Location in input where bytecodes are located. */
217 CrwPosition start_of_input_bytecodes;
218
219 /* Original max_stack and new max stack */
220 unsigned max_stack;
221 unsigned new_max_stack;
222
223 jboolean object_init_method;
224 jboolean skip_call_return_sites;
225
226 /* Method access flags gotten from file. */
227 unsigned access_flags;
228
229} MethodImage;
230
231/* ----------------------------------------------------------------- */
232/* General support functions (memory and error handling) */
233
234static void
235fatal_error(CrwClassImage *ci, const char *message, const char *file, int line)
236{
237 if ( ci != NULL && ci->fatal_error_handler != NULL ) {
238 (*ci->fatal_error_handler)(message, file, line);
239 } else {
240 /* Normal operation should NEVER reach here */
241 /* NO CRW FATAL ERROR HANDLER! */
242 (void)fprintf(stderr, "CRW: %s [%s:%d]\n", message, file, line);
243 abort();
244 }
245}
246
247#if defined(DEBUG) || !defined(NDEBUG)
248static void
249assert_error(CrwClassImage *ci, const char *condition,
250 const char *file, int line)
251{
252 char buf[512];
253 MethodImage *mi;
254 ByteOffset byte_code_offset;
255
256 mi = ci->current_mi;
257 if ( mi != NULL ) {
258 byte_code_offset = (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes);
259 } else {
260 byte_code_offset=-1;
261 }
262
263 (void)sprintf(buf,
264 "CRW ASSERTION FAILURE: %s (%s:%s:%d)",
265 condition,
266 ci->name==0?"?":ci->name,
267 mi->name==0?"?":mi->name,
268 byte_code_offset);
269 fatal_error(ci, buf, file, line);
270}
271#endif
272
273static void *
274allocate(CrwClassImage *ci, int nbytes)
275{
276 void * ptr;
277
278 if ( nbytes <= 0 ) {
279 CRW_FATAL(ci, "Cannot allocate <= 0 bytes");
280 }
281 ptr = malloc(nbytes);
282 if ( ptr == NULL ) {
283 CRW_FATAL(ci, "Ran out of malloc memory");
284 }
285 return ptr;
286}
287
288static void *
289reallocate(CrwClassImage *ci, void *optr, int nbytes)
290{
291 void * ptr;
292
293 if ( optr == NULL ) {
294 CRW_FATAL(ci, "Cannot deallocate NULL");
295 }
296 if ( nbytes <= 0 ) {
297 CRW_FATAL(ci, "Cannot reallocate <= 0 bytes");
298 }
299 ptr = realloc(optr, nbytes);
300 if ( ptr == NULL ) {
301 CRW_FATAL(ci, "Ran out of malloc memory");
302 }
303 return ptr;
304}
305
306static void *
307allocate_clean(CrwClassImage *ci, int nbytes)
308{
309 void * ptr;
310
311 if ( nbytes <= 0 ) {
312 CRW_FATAL(ci, "Cannot allocate <= 0 bytes");
313 }
314 ptr = calloc(nbytes, 1);
315 if ( ptr == NULL ) {
316 CRW_FATAL(ci, "Ran out of malloc memory");
317 }
318 return ptr;
319}
320
321static const char *
322duplicate(CrwClassImage *ci, const char *str, int len)
323{
324 char *copy;
325
326 copy = (char*)allocate(ci, len+1);
327 (void)memcpy(copy, str, len);
328 copy[len] = 0;
329 return (const char *)copy;
330}
331
332static void
333deallocate(CrwClassImage *ci, void *ptr)
334{
335 if ( ptr == NULL ) {
336 CRW_FATAL(ci, "Cannot deallocate NULL");
337 }
338 (void)free(ptr);
339}
340
341/* ----------------------------------------------------------------- */
342/* Functions for reading/writing bytes to/from the class images */
343
344static unsigned
345readU1(CrwClassImage *ci)
346{
347 CRW_ASSERT_CI(ci);
348 return ((unsigned)(ci->input[ci->input_position++])) & 0xFF;
349}
350
351static unsigned
352readU2(CrwClassImage *ci)
353{
354 unsigned res;
355
356 res = readU1(ci);
357 return (res << 8) + readU1(ci);
358}
359
360static signed short
361readS2(CrwClassImage *ci)
362{
363 unsigned res;
364
365 res = readU1(ci);
366 return ((res << 8) + readU1(ci)) & 0xFFFF;
367}
368
369static unsigned
370readU4(CrwClassImage *ci)
371{
372 unsigned res;
373
374 res = readU2(ci);
375 return (res << 16) + readU2(ci);
376}
377
378static void
379writeU1(CrwClassImage *ci, unsigned val) /* Only writes out lower 8 bits */
380{
381 CRW_ASSERT_CI(ci);
382 if ( ci->output != NULL ) {
383 ci->output[ci->output_position++] = val & 0xFF;
384 }
385}
386
387static void
388writeU2(CrwClassImage *ci, unsigned val)
389{
390 writeU1(ci, val >> 8);
391 writeU1(ci, val);
392}
393
394static void
395writeU4(CrwClassImage *ci, unsigned val)
396{
397 writeU2(ci, val >> 16);
398 writeU2(ci, val);
399}
400
401static unsigned
402copyU1(CrwClassImage *ci)
403{
404 unsigned value;
405
406 value = readU1(ci);
407 writeU1(ci, value);
408 return value;
409}
410
411static unsigned
412copyU2(CrwClassImage *ci)
413{
414 unsigned value;
415
416 value = readU2(ci);
417 writeU2(ci, value);
418 return value;
419}
420
421static unsigned
422copyU4(CrwClassImage *ci)
423{
424 unsigned value;
425
426 value = readU4(ci);
427 writeU4(ci, value);
428 return value;
429}
430
431static void
432copy(CrwClassImage *ci, unsigned count)
433{
434 CRW_ASSERT_CI(ci);
435 if ( ci->output != NULL ) {
436 (void)memcpy(ci->output+ci->output_position,
437 ci->input+ci->input_position, count);
438 ci->output_position += count;
439 }
440 ci->input_position += count;
441 CRW_ASSERT_CI(ci);
442}
443
444static void
445skip(CrwClassImage *ci, unsigned count)
446{
447 CRW_ASSERT_CI(ci);
448 ci->input_position += count;
449}
450
451static void
452read_bytes(CrwClassImage *ci, void *bytes, unsigned count)
453{
454 CRW_ASSERT_CI(ci);
455 CRW_ASSERT(ci, bytes!=NULL);
456 (void)memcpy(bytes, ci->input+ci->input_position, count);
457 ci->input_position += count;
458}
459
460static void
461write_bytes(CrwClassImage *ci, void *bytes, unsigned count)
462{
463 CRW_ASSERT_CI(ci);
464 CRW_ASSERT(ci, bytes!=NULL);
465 if ( ci->output != NULL ) {
466 (void)memcpy(ci->output+ci->output_position, bytes, count);
467 ci->output_position += count;
468 }
469}
470
471static void
472random_writeU2(CrwClassImage *ci, CrwPosition pos, unsigned val)
473{
474 CrwPosition save_position;
475
476 CRW_ASSERT_CI(ci);
477 save_position = ci->output_position;
478 ci->output_position = pos;
479 writeU2(ci, val);
480 ci->output_position = save_position;
481}
482
483static void
484random_writeU4(CrwClassImage *ci, CrwPosition pos, unsigned val)
485{
486 CrwPosition save_position;
487
488 CRW_ASSERT_CI(ci);
489 save_position = ci->output_position;
490 ci->output_position = pos;
491 writeU4(ci, val);
492 ci->output_position = save_position;
493}
494
495/* ----------------------------------------------------------------- */
496/* Constant Pool handling functions. */
497
498static void
499fillin_cpool_entry(CrwClassImage *ci, CrwCpoolIndex i,
500 ClassConstant tag,
501 unsigned int index1, unsigned int index2,
502 const char *ptr, int len)
503{
504 CRW_ASSERT_CI(ci);
505 CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one);
506 ci->cpool[i].tag = tag;
507 ci->cpool[i].index1 = index1;
508 ci->cpool[i].index2 = index2;
509 ci->cpool[i].ptr = ptr;
510 ci->cpool[i].len = (unsigned short)len;
511}
512
513static CrwCpoolIndex
514add_new_cpool_entry(CrwClassImage *ci, ClassConstant tag,
515 unsigned int index1, unsigned int index2,
516 const char *str, int len)
517{
518 CrwCpoolIndex i;
519 char *utf8 = NULL;
520
521 CRW_ASSERT_CI(ci);
522 i = ci->cpool_count_plus_one++;
523
524 /* NOTE: This implementation does not automatically expand the
525 * constant pool table beyond the expected number needed
526 * to handle this particular CrwTrackerInterface injections.
527 * See MAXIMUM_NEW_CPOOL_ENTRIES
528 */
529 CRW_ASSERT(ci, ci->cpool_count_plus_one < ci->cpool_max_elements );
530
531 writeU1(ci, tag);
532 switch (tag) {
533 case JVM_CONSTANT_Class:
534 writeU2(ci, index1);
535 break;
536 case JVM_CONSTANT_String:
537 writeU2(ci, index1);
538 break;
539 case JVM_CONSTANT_Fieldref:
540 case JVM_CONSTANT_Methodref:
541 case JVM_CONSTANT_InterfaceMethodref:
542 case JVM_CONSTANT_Integer:
543 case JVM_CONSTANT_Float:
544 case JVM_CONSTANT_NameAndType:
545 writeU2(ci, index1);
546 writeU2(ci, index2);
547 break;
548 case JVM_CONSTANT_Long:
549 case JVM_CONSTANT_Double:
550 writeU4(ci, index1);
551 writeU4(ci, index2);
552 ci->cpool_count_plus_one++;
553 CRW_ASSERT(ci, ci->cpool_count_plus_one < ci->cpool_max_elements );
554 break;
555 case JVM_CONSTANT_Utf8:
556 CRW_ASSERT(ci, len==(len & 0xFFFF));
557 writeU2(ci, len);
558 write_bytes(ci, (void*)str, len);
559 utf8 = (char*)duplicate(ci, str, len);
560 break;
561 default:
562 CRW_FATAL(ci, "Unknown constant");
563 break;
564 }
565 fillin_cpool_entry(ci, i, tag, index1, index2, (const char *)utf8, len);
566 CRW_ASSERT(ci, i > 0 && i < ci->cpool_count_plus_one);
567 return i;
568}
569
570static CrwCpoolIndex
571add_new_class_cpool_entry(CrwClassImage *ci, const char *class_name)
572{
573 CrwCpoolIndex name_index;
574 CrwCpoolIndex class_index;
575 int len;
576
577 CRW_ASSERT_CI(ci);
578 CRW_ASSERT(ci, class_name!=NULL);
579
580 len = (int)strlen(class_name);
581 name_index = add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0,
582 class_name, len);
583 class_index = add_new_cpool_entry(ci, JVM_CONSTANT_Class, name_index, 0,
584 NULL, 0);
585 return class_index;
586}
587
588static CrwCpoolIndex
589add_new_method_cpool_entry(CrwClassImage *ci, CrwCpoolIndex class_index,
590 const char *name, const char *descr)
591{
592 CrwCpoolIndex name_index;
593 CrwCpoolIndex descr_index;
594 CrwCpoolIndex name_type_index;
595 int len;
596
597 CRW_ASSERT_CI(ci);
598 CRW_ASSERT(ci, name!=NULL);
599 CRW_ASSERT(ci, descr!=NULL);
600 len = (int)strlen(name);
601 name_index =
602 add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, name, len);
603 len = (int)strlen(descr);
604 descr_index =
605 add_new_cpool_entry(ci, JVM_CONSTANT_Utf8, len, 0, descr, len);
606 name_type_index =
607 add_new_cpool_entry(ci, JVM_CONSTANT_NameAndType,
608 name_index, descr_index, NULL, 0);
609 return add_new_cpool_entry(ci, JVM_CONSTANT_Methodref,
610 class_index, name_type_index, NULL, 0);
611}
612
613static CrwConstantPoolEntry
614cpool_entry(CrwClassImage *ci, CrwCpoolIndex c_index)
615{
616 CRW_ASSERT_CI(ci);
617 CRW_ASSERT(ci, c_index > 0 && c_index < ci->cpool_count_plus_one);
618 return ci->cpool[c_index];
619}
620
621static void
622cpool_setup(CrwClassImage *ci)
623{
624 CrwCpoolIndex i;
625 CrwPosition cpool_output_position;
626 int count_plus_one;
627
628 CRW_ASSERT_CI(ci);
629 cpool_output_position = ci->output_position;
630 count_plus_one = copyU2(ci);
631 CRW_ASSERT(ci, count_plus_one>1);
632 ci->cpool_max_elements = count_plus_one+MAXIMUM_NEW_CPOOL_ENTRIES;
633 ci->cpool = (CrwConstantPoolEntry*)allocate_clean(ci,
634 (int)((ci->cpool_max_elements)*sizeof(CrwConstantPoolEntry)));
635 ci->cpool_count_plus_one = (CrwCpoolIndex)count_plus_one;
636
637 /* Index zero not in class file */
638 for (i = 1; i < count_plus_one; ++i) {
639 CrwCpoolIndex ipos;
640 ClassConstant tag;
641 unsigned int index1;
642 unsigned int index2;
643 unsigned len;
644 char * utf8;
645
646 ipos = i;
647 index1 = 0;
648 index2 = 0;
649 len = 0;
650 utf8 = NULL;
651
652 tag = copyU1(ci);
653 switch (tag) {
654 case JVM_CONSTANT_Class:
655 index1 = copyU2(ci);
656 break;
657 case JVM_CONSTANT_String:
658 index1 = copyU2(ci);
659 break;
660 case JVM_CONSTANT_Fieldref:
661 case JVM_CONSTANT_Methodref:
662 case JVM_CONSTANT_InterfaceMethodref:
663 case JVM_CONSTANT_Integer:
664 case JVM_CONSTANT_Float:
665 case JVM_CONSTANT_NameAndType:
666 index1 = copyU2(ci);
667 index2 = copyU2(ci);
668 break;
669 case JVM_CONSTANT_Long:
670 case JVM_CONSTANT_Double:
671 index1 = copyU4(ci);
672 index2 = copyU4(ci);
673 ++i; /* // these take two CP entries - duh! */
674 break;
675 case JVM_CONSTANT_Utf8:
676 len = copyU2(ci);
677 index1 = (unsigned short)len;
678 utf8 = (char*)allocate(ci, len+1);
679 read_bytes(ci, (void*)utf8, len);
680 utf8[len] = 0;
681 write_bytes(ci, (void*)utf8, len);
682 break;
683 default:
684 CRW_FATAL(ci, "Unknown constant");
685 break;
686 }
687 fillin_cpool_entry(ci, ipos, tag, index1, index2, (const char *)utf8, len);
688 }
689
690 if (ci->call_name != NULL || ci->return_name != NULL) {
691 if ( ci->number != (ci->number & 0x7FFF) ) {
692 ci->class_number_index =
693 add_new_cpool_entry(ci, JVM_CONSTANT_Integer,
694 (ci->number>>16) & 0xFFFF, ci->number & 0xFFFF, NULL, 0);
695 }
696 }
697
698 if ( ci->tclass_name != NULL ) {
699 ci->tracker_class_index =
700 add_new_class_cpool_entry(ci, ci->tclass_name);
701 }
702 if (ci->obj_init_name != NULL) {
703 ci->object_init_tracker_index = add_new_method_cpool_entry(ci,
704 ci->tracker_class_index,
705 ci->obj_init_name,
706 ci->obj_init_sig);
707 }
708 if (ci->newarray_name != NULL) {
709 ci->newarray_tracker_index = add_new_method_cpool_entry(ci,
710 ci->tracker_class_index,
711 ci->newarray_name,
712 ci->newarray_sig);
713 }
714 if (ci->call_name != NULL) {
715 ci->call_tracker_index = add_new_method_cpool_entry(ci,
716 ci->tracker_class_index,
717 ci->call_name,
718 ci->call_sig);
719 }
720 if (ci->return_name != NULL) {
721 ci->return_tracker_index = add_new_method_cpool_entry(ci,
722 ci->tracker_class_index,
723 ci->return_name,
724 ci->return_sig);
725 }
726
727 random_writeU2(ci, cpool_output_position, ci->cpool_count_plus_one);
728}
729
730/* ----------------------------------------------------------------- */
731/* Functions that create the bytecodes to inject */
732
733static ByteOffset
734push_pool_constant_bytecodes(ByteCode *bytecodes, CrwCpoolIndex index)
735{
736 ByteOffset nbytes = 0;
737
738 if ( index == (index&0x7F) ) {
739 bytecodes[nbytes++] = (ByteCode)JVM_OPC_ldc;
740 } else {
741 bytecodes[nbytes++] = (ByteCode)JVM_OPC_ldc_w;
742 bytecodes[nbytes++] = (ByteCode)((index >> 8) & 0xFF);
743 }
744 bytecodes[nbytes++] = (ByteCode)(index & 0xFF);
745 return nbytes;
746}
747
748static ByteOffset
749push_short_constant_bytecodes(ByteCode *bytecodes, unsigned number)
750{
751 ByteOffset nbytes = 0;
752
753 if ( number <= 5 ) {
754 bytecodes[nbytes++] = (ByteCode)(JVM_OPC_iconst_0+number);
755 } else if ( number == (number&0x7F) ) {
756 bytecodes[nbytes++] = (ByteCode)JVM_OPC_bipush;
757 bytecodes[nbytes++] = (ByteCode)(number & 0xFF);
758 } else {
759 bytecodes[nbytes++] = (ByteCode)JVM_OPC_sipush;
760 bytecodes[nbytes++] = (ByteCode)((number >> 8) & 0xFF);
761 bytecodes[nbytes++] = (ByteCode)(number & 0xFF);
762 }
763 return nbytes;
764}
765
766static ByteOffset
767injection_template(MethodImage *mi, ByteCode *bytecodes, ByteOffset max_nbytes,
768 CrwCpoolIndex method_index)
769{
770 CrwClassImage * ci;
771 ByteOffset nbytes = 0;
772 unsigned max_stack;
773 int add_dup;
774 int add_aload;
775 int push_cnum;
776 int push_mnum;
777
778 ci = mi->ci;
779
780 CRW_ASSERT(ci, bytecodes!=NULL);
781
782 if ( method_index == 0 ) {
783 return 0;
784 }
785
786 if ( method_index == ci->newarray_tracker_index) {
787 max_stack = mi->max_stack + 1;
788 add_dup = JNI_TRUE;
789 add_aload = JNI_FALSE;
790 push_cnum = JNI_FALSE;
791 push_mnum = JNI_FALSE;
792 } else if ( method_index == ci->object_init_tracker_index) {
793 max_stack = mi->max_stack + 1;
794 add_dup = JNI_FALSE;
795 add_aload = JNI_TRUE;
796 push_cnum = JNI_FALSE;
797 push_mnum = JNI_FALSE;
798 } else {
799 max_stack = mi->max_stack + 2;
800 add_dup = JNI_FALSE;
801 add_aload = JNI_FALSE;
802 push_cnum = JNI_TRUE;
803 push_mnum = JNI_TRUE;
804 }
805
806 if ( add_dup ) {
807 bytecodes[nbytes++] = (ByteCode)JVM_OPC_dup;
808 }
809 if ( add_aload ) {
810 bytecodes[nbytes++] = (ByteCode)JVM_OPC_aload_0;
811 }
812 if ( push_cnum ) {
813 if ( ci->number == (ci->number & 0x7FFF) ) {
814 nbytes += push_short_constant_bytecodes(bytecodes+nbytes,
815 ci->number);
816 } else {
817 CRW_ASSERT(ci, ci->class_number_index!=0);
818 nbytes += push_pool_constant_bytecodes(bytecodes+nbytes,
819 ci->class_number_index);
820 }
821 }
822 if ( push_mnum ) {
823 nbytes += push_short_constant_bytecodes(bytecodes+nbytes,
824 mi->number);
825 }
826 bytecodes[nbytes++] = (ByteCode)JVM_OPC_invokestatic;
827 bytecodes[nbytes++] = (ByteCode)(method_index >> 8);
828 bytecodes[nbytes++] = (ByteCode)method_index;
829 bytecodes[nbytes] = 0;
830 CRW_ASSERT(ci, nbytes<max_nbytes);
831
832 /* Make sure the new max_stack is appropriate */
833 if ( max_stack > mi->new_max_stack ) {
834 mi->new_max_stack = max_stack;
835 }
836 return nbytes;
837}
838
839/* Called to create injection code at entry to a method */
840static ByteOffset
841entry_injection_code(MethodImage *mi, ByteCode *bytecodes, ByteOffset len)
842{
843 CrwClassImage * ci;
844 ByteOffset nbytes = 0;
845
846 CRW_ASSERT_MI(mi);
847
848 ci = mi->ci;
849
850 if ( mi->object_init_method ) {
851 nbytes = injection_template(mi,
852 bytecodes, len, ci->object_init_tracker_index);
853 }
854 if ( !mi->skip_call_return_sites ) {
855 nbytes += injection_template(mi,
856 bytecodes+nbytes, len-nbytes, ci->call_tracker_index);
857 }
858 return nbytes;
859}
860
861/* Called to create injection code before an opcode */
862static ByteOffset
863before_injection_code(MethodImage *mi, ClassOpcode opcode,
864 ByteCode *bytecodes, ByteOffset len)
865{
866 ByteOffset nbytes = 0;
867
868
869 CRW_ASSERT_MI(mi);
870 switch ( opcode ) {
871 case JVM_OPC_return:
872 case JVM_OPC_ireturn:
873 case JVM_OPC_lreturn:
874 case JVM_OPC_freturn:
875 case JVM_OPC_dreturn:
876 case JVM_OPC_areturn:
877 if ( !mi->skip_call_return_sites ) {
878 nbytes = injection_template(mi,
879 bytecodes, len, mi->ci->return_tracker_index);
880 }
881 break;
882 default:
883 break;
884 }
885 return nbytes;
886}
887
888/* Called to create injection code after an opcode */
889static ByteOffset
890after_injection_code(MethodImage *mi, ClassOpcode opcode,
891 ByteCode *bytecodes, ByteOffset len)
892{
893 CrwClassImage* ci;
894 ByteOffset nbytes;
895
896 ci = mi->ci;
897 nbytes = 0;
898
899 CRW_ASSERT_MI(mi);
900 switch ( opcode ) {
901 case JVM_OPC_new:
902 /* Can't inject here cannot pass around uninitialized object */
903 break;
904 case JVM_OPC_newarray:
905 case JVM_OPC_anewarray:
906 case JVM_OPC_multianewarray:
907 nbytes = injection_template(mi,
908 bytecodes, len, ci->newarray_tracker_index);
909 break;
910 default:
911 break;
912 }
913 return nbytes;
914}
915
916/* Actually inject the bytecodes */
917static void
918inject_bytecodes(MethodImage *mi, ByteOffset at,
919 ByteCode *bytecodes, ByteOffset len)
920{
921 Injection injection;
922 CrwClassImage *ci;
923
924 ci = mi->ci;
925 CRW_ASSERT_MI(mi);
926 CRW_ASSERT(ci, at <= mi->code_len);
927
928 injection = mi->injections[at];
929
930 CRW_ASSERT(ci, len <= LARGEST_INJECTION/2);
931 CRW_ASSERT(ci, injection.len+len <= LARGEST_INJECTION);
932
933 /* Either start an injection area or concatenate to what is there */
934 if ( injection.code == NULL ) {
935 CRW_ASSERT(ci, injection.len==0);
936 injection.code = (ByteCode *)allocate_clean(ci, LARGEST_INJECTION+1);
937 }
938
939 (void)memcpy(injection.code+injection.len, bytecodes, len);
940 injection.len += len;
941 injection.code[injection.len] = 0;
942 mi->injections[at] = injection;
943 ci->injection_count++;
944}
945
946/* ----------------------------------------------------------------- */
947/* Method handling functions */
948
949static MethodImage *
950method_init(CrwClassImage *ci, unsigned mnum, ByteOffset code_len)
951{
952 MethodImage * mi;
953 ByteOffset i;
954
955 mi = (MethodImage*)allocate_clean(ci, (int)sizeof(MethodImage));
956 mi->ci = ci;
957 mi->name = ci->method_name[mnum];
958 mi->descr = ci->method_descr[mnum];
959 mi->code_len = code_len;
960 mi->map = (ByteOffset*)allocate_clean(ci,
961 (int)((code_len+1)*sizeof(ByteOffset)));
962 for(i=0; i<=code_len; i++) {
963 mi->map[i] = i;
964 }
965 mi->widening = (signed char*)allocate_clean(ci, code_len+1);
966 mi->injections = (Injection *)allocate_clean(ci,
967 (int)((code_len+1)*sizeof(Injection)));
968 mi->number = mnum;
969 ci->current_mi = mi;
970 return mi;
971}
972
973static void
974method_term(MethodImage *mi)
975{
976 CrwClassImage *ci;
977
978 ci = mi->ci;
979 CRW_ASSERT_MI(mi);
980 if ( mi->map != NULL ) {
981 deallocate(ci, (void*)mi->map);
982 mi->map = NULL;
983 }
984 if ( mi->widening != NULL ) {
985 deallocate(ci, (void*)mi->widening);
986 mi->widening = NULL;
987 }
988 if ( mi->injections != NULL ) {
989 ByteOffset i;
990 for(i=0; i<= mi->code_len; i++) {
991 if ( mi->injections[i].code != NULL ) {
992 deallocate(ci, (void*)mi->injections[i].code);
993 mi->injections[i].code = NULL;
994 }
995 }
996 deallocate(ci, (void*)mi->injections);
997 mi->injections = NULL;
998 }
999 ci->current_mi = NULL;
1000 deallocate(ci, (void*)mi);
1001}
1002
1003static ByteOffset
1004input_code_offset(MethodImage *mi)
1005{
1006 CRW_ASSERT_MI(mi);
1007 return (ByteOffset)(mi->ci->input_position - mi->start_of_input_bytecodes);
1008}
1009
1010static void
1011rewind_to_beginning_of_input_bytecodes(MethodImage *mi)
1012{
1013 CRW_ASSERT_MI(mi);
1014 mi->ci->input_position = mi->start_of_input_bytecodes;
1015}
1016
1017/* Starting at original byte position 'at', add 'offset' to it's new
1018 * location. This may be a negative value.
1019 * NOTE: That this map is not the new bytecode location of the opcode
1020 * but the new bytecode location that should be used when
1021 * a goto or jump instruction was targeting the old bytecode
1022 * location.
1023 */
1024static void
1025adjust_map(MethodImage *mi, ByteOffset at, ByteOffset offset)
1026{
1027 ByteOffset i;
1028
1029 CRW_ASSERT_MI(mi);
1030 for (i = at; i <= mi->code_len; ++i) {
1031 mi->map[i] += offset;
1032 }
1033}
1034
1035static void
1036widen(MethodImage *mi, ByteOffset at, ByteOffset len)
1037{
1038 int delta;
1039
1040 CRW_ASSERT(mi->ci, at <= mi->code_len);
1041 delta = len - mi->widening[at];
1042 /* Adjust everything from the current input location by delta */
1043 adjust_map(mi, input_code_offset(mi), delta);
1044 /* Mark at beginning of instruction */
1045 mi->widening[at] = (signed char)len;
1046}
1047
1048static void
1049verify_opc_wide(CrwClassImage *ci, ClassOpcode wopcode)
1050{
1051 switch (wopcode) {
1052 case JVM_OPC_aload: case JVM_OPC_astore:
1053 case JVM_OPC_fload: case JVM_OPC_fstore:
1054 case JVM_OPC_iload: case JVM_OPC_istore:
1055 case JVM_OPC_lload: case JVM_OPC_lstore:
1056 case JVM_OPC_dload: case JVM_OPC_dstore:
1057 case JVM_OPC_ret: case JVM_OPC_iinc:
1058 break;
1059 default:
1060 CRW_FATAL(ci, "Invalid opcode supplied to wide opcode");
1061 break;
1062 }
1063}
1064
1065static unsigned
1066opcode_length(CrwClassImage *ci, ClassOpcode opcode)
1067{
1068 /* Define array that holds length of an opcode */
1069 static unsigned char _opcode_length[JVM_OPC_MAX+1] =
1070 JVM_OPCODE_LENGTH_INITIALIZER;
1071
1072 if ( opcode > JVM_OPC_MAX ) {
1073 CRW_FATAL(ci, "Invalid opcode supplied to opcode_length()");
1074 }
1075 return _opcode_length[opcode];
1076}
1077
1078/* Walk one instruction and inject instrumentation */
1079static void
1080inject_for_opcode(MethodImage *mi)
1081{
1082 CrwClassImage * ci;
1083 ClassOpcode opcode;
1084 int pos;
1085
1086 CRW_ASSERT_MI(mi);
1087 ci = mi->ci;
1088 pos = input_code_offset(mi);
1089 opcode = readU1(ci);
1090
1091 if (opcode == JVM_OPC_wide) {
1092 ClassOpcode wopcode;
1093
1094 wopcode = readU1(ci);
1095 /* lvIndex not used */
1096 (void)readU2(ci);
1097 verify_opc_wide(ci, wopcode);
1098 if ( wopcode==JVM_OPC_iinc ) {
1099 (void)readU1(ci);
1100 (void)readU1(ci);
1101 }
1102 } else {
1103
1104 ByteCode bytecodes[LARGEST_INJECTION+1];
1105 int header;
1106 int instr_len;
1107 int low;
1108 int high;
1109 int npairs;
1110 ByteOffset len;
1111
1112 /* Get bytecodes to inject before this opcode */
1113 len = before_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
1114 if ( len > 0 ) {
1115 inject_bytecodes(mi, pos, bytecodes, len);
1116 /* Adjust map after processing this opcode */
1117 }
1118
1119 /* Process this opcode */
1120 switch (opcode) {
1121 case JVM_OPC_tableswitch:
1122 header = NEXT_4BYTE_BOUNDARY(pos);
1123 skip(ci, header - (pos+1));
1124 (void)readU4(ci);
1125 low = readU4(ci);
1126 high = readU4(ci);
1127 skip(ci, (high+1-low) * 4);
1128 break;
1129 case JVM_OPC_lookupswitch:
1130 header = NEXT_4BYTE_BOUNDARY(pos);
1131 skip(ci, header - (pos+1));
1132 (void)readU4(ci);
1133 npairs = readU4(ci);
1134 skip(ci, npairs * 8);
1135 break;
1136 default:
1137 instr_len = opcode_length(ci, opcode);
1138 skip(ci, instr_len-1);
1139 break;
1140 }
1141
1142 /* Get position after this opcode is processed */
1143 pos = input_code_offset(mi);
1144
1145 /* Adjust for any before_injection_code() */
1146 if ( len > 0 ) {
1147 /* Adjust everything past this opcode.
1148 * Why past it? Because we want any jumps to this bytecode loc
1149 * to go to the injected code, not where the opcode
1150 * was moved too.
1151 * Consider a 'return' opcode that is jumped too.
1152 * NOTE: This may not be correct in all cases, but will
1153 * when we are only dealing with non-variable opcodes
1154 * like the return opcodes. Be careful if the
1155 * before_injection_code() changes to include other
1156 * opcodes that have variable length.
1157 */
1158 adjust_map(mi, pos, len);
1159 }
1160
1161 /* Get bytecodes to inject after this opcode */
1162 len = after_injection_code(mi, opcode, bytecodes, (int)sizeof(bytecodes));
1163 if ( len > 0 ) {
1164 inject_bytecodes(mi, pos, bytecodes, len);
1165
1166 /* Adjust for any after_injection_code() */
1167 adjust_map(mi, pos, len);
1168 }
1169
1170 }
1171}
1172
1173/* Map original bytecode location to it's new location. (See adjust_map()). */
1174static ByteOffset
1175method_code_map(MethodImage *mi, ByteOffset pos)
1176{
1177 CRW_ASSERT_MI(mi);
1178 CRW_ASSERT(mi->ci, pos <= mi->code_len);
1179 return mi->map[pos];
1180}
1181
1182static int
1183adjust_instruction(MethodImage *mi)
1184{
1185 CrwClassImage * ci;
1186 ClassOpcode opcode;
1187 int pos;
1188 int new_pos;
1189
1190 CRW_ASSERT_MI(mi);
1191 ci = mi->ci;
1192 pos = input_code_offset(mi);
1193 new_pos = method_code_map(mi,pos);
1194
1195 opcode = readU1(ci);
1196
1197 if (opcode == JVM_OPC_wide) {
1198 ClassOpcode wopcode;
1199
1200 wopcode = readU1(ci);
1201 /* lvIndex not used */
1202 (void)readU2(ci);
1203 verify_opc_wide(ci, wopcode);
1204 if ( wopcode==JVM_OPC_iinc ) {
1205 (void)readU1(ci);
1206 (void)readU1(ci);
1207 }
1208 } else {
1209
1210 int widened;
1211 int header;
1212 int newHeader;
1213 int low;
1214 int high;
1215 int new_pad;
1216 int old_pad;
1217 int delta;
1218 int new_delta;
1219 int delta_pad;
1220 int npairs;
1221 int instr_len;
1222
1223 switch (opcode) {
1224
1225 case JVM_OPC_tableswitch:
1226 widened = mi->widening[pos];
1227 header = NEXT_4BYTE_BOUNDARY(pos);
1228 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
1229
1230 skip(ci, header - (pos+1));
1231
1232 delta = readU4(ci);
1233 low = readU4(ci);
1234 high = readU4(ci);
1235 skip(ci, (high+1-low) * 4);
1236 new_pad = newHeader - new_pos;
1237 old_pad = header - pos;
1238 delta_pad = new_pad - old_pad;
1239 if (widened != delta_pad) {
1240 widen(mi, pos, delta_pad);
1241 return 0;
1242 }
1243 break;
1244
1245 case JVM_OPC_lookupswitch:
1246 widened = mi->widening[pos];
1247 header = NEXT_4BYTE_BOUNDARY(pos);
1248 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
1249
1250 skip(ci, header - (pos+1));
1251
1252 delta = readU4(ci);
1253 npairs = readU4(ci);
1254 skip(ci, npairs * 8);
1255 new_pad = newHeader - new_pos;
1256 old_pad = header - pos;
1257 delta_pad = new_pad - old_pad;
1258 if (widened != delta_pad) {
1259 widen(mi, pos, delta_pad);
1260 return 0;
1261 }
1262 break;
1263
1264 case JVM_OPC_jsr: case JVM_OPC_goto:
1265 case JVM_OPC_ifeq: case JVM_OPC_ifge: case JVM_OPC_ifgt:
1266 case JVM_OPC_ifle: case JVM_OPC_iflt: case JVM_OPC_ifne:
1267 case JVM_OPC_if_icmpeq: case JVM_OPC_if_icmpne: case JVM_OPC_if_icmpge:
1268 case JVM_OPC_if_icmpgt: case JVM_OPC_if_icmple: case JVM_OPC_if_icmplt:
1269 case JVM_OPC_if_acmpeq: case JVM_OPC_if_acmpne:
1270 case JVM_OPC_ifnull: case JVM_OPC_ifnonnull:
1271 widened = mi->widening[pos];
1272 delta = readS2(ci);
1273 if (widened == 0) {
1274 new_delta = method_code_map(mi,pos+delta) - new_pos;
1275 if ((new_delta < -32768) || (new_delta > 32767)) {
1276 switch (opcode) {
1277 case JVM_OPC_jsr: case JVM_OPC_goto:
1278 widen(mi, pos, 2);
1279 break;
1280 default:
1281 widen(mi, pos, 5);
1282 break;
1283 }
1284 return 0;
1285 }
1286 }
1287 break;
1288
1289 case JVM_OPC_jsr_w:
1290 case JVM_OPC_goto_w:
1291 (void)readU4(ci);
1292 break;
1293
1294 default:
1295 instr_len = opcode_length(ci, opcode);
1296 skip(ci, instr_len-1);
1297 break;
1298 }
1299 }
1300 return 1;
1301}
1302
1303static void
1304write_instruction(MethodImage *mi)
1305{
1306 CrwClassImage * ci;
1307 ClassOpcode opcode;
1308 ByteOffset new_code_len;
1309 int pos;
1310 int new_pos;
1311
1312 CRW_ASSERT_MI(mi);
1313 ci = mi->ci;
1314 pos = input_code_offset(mi);
1315 new_pos = method_code_map(mi,pos);
1316 new_code_len = mi->injections[pos].len;
1317 if (new_code_len > 0) {
1318 write_bytes(ci, (void*)mi->injections[pos].code, new_code_len);
1319 }
1320
1321 opcode = readU1(ci);
1322 if (opcode == JVM_OPC_wide) {
1323 ClassOpcode wopcode;
1324
1325 writeU1(ci, opcode);
1326
1327 wopcode = copyU1(ci);
1328 /* lvIndex not used */
1329 (void)copyU2(ci);
1330 verify_opc_wide(ci, wopcode);
1331 if ( wopcode==JVM_OPC_iinc ) {
1332 (void)copyU1(ci);
1333 (void)copyU1(ci);
1334 }
1335 } else {
1336
1337 ClassOpcode new_opcode;
1338 int header;
1339 int newHeader;
1340 int low;
1341 int high;
1342 int i;
1343 int npairs;
1344 int widened;
1345 int instr_len;
1346 int delta;
1347 int new_delta;
1348
1349 switch (opcode) {
1350
1351 case JVM_OPC_tableswitch:
1352 header = NEXT_4BYTE_BOUNDARY(pos);
1353 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
1354
1355 skip(ci, header - (pos+1));
1356
1357 delta = readU4(ci);
1358 new_delta = method_code_map(mi,pos+delta) - new_pos;
1359 low = readU4(ci);
1360 high = readU4(ci);
1361
1362 writeU1(ci, opcode);
1363 for (i = new_pos+1; i < newHeader; ++i) {
1364 writeU1(ci, 0);
1365 }
1366 writeU4(ci, new_delta);
1367 writeU4(ci, low);
1368 writeU4(ci, high);
1369
1370 for (i = low; i <= high; ++i) {
1371 delta = readU4(ci);
1372 new_delta = method_code_map(mi,pos+delta) - new_pos;
1373 writeU4(ci, new_delta);
1374 }
1375 break;
1376
1377 case JVM_OPC_lookupswitch:
1378 header = NEXT_4BYTE_BOUNDARY(pos);
1379 newHeader = NEXT_4BYTE_BOUNDARY(new_pos);
1380
1381 skip(ci, header - (pos+1));
1382
1383 delta = readU4(ci);
1384 new_delta = method_code_map(mi,pos+delta) - new_pos;
1385 npairs = readU4(ci);
1386 writeU1(ci, opcode);
1387 for (i = new_pos+1; i < newHeader; ++i) {
1388 writeU1(ci, 0);
1389 }
1390 writeU4(ci, new_delta);
1391 writeU4(ci, npairs);
1392 for (i = 0; i< npairs; ++i) {
1393 unsigned match = readU4(ci);
1394 delta = readU4(ci);
1395 new_delta = method_code_map(mi,pos+delta) - new_pos;
1396 writeU4(ci, match);
1397 writeU4(ci, new_delta);
1398 }
1399 break;
1400
1401 case JVM_OPC_jsr: case JVM_OPC_goto:
1402 case JVM_OPC_ifeq: case JVM_OPC_ifge: case JVM_OPC_ifgt:
1403 case JVM_OPC_ifle: case JVM_OPC_iflt: case JVM_OPC_ifne:
1404 case JVM_OPC_if_icmpeq: case JVM_OPC_if_icmpne: case JVM_OPC_if_icmpge:
1405 case JVM_OPC_if_icmpgt: case JVM_OPC_if_icmple: case JVM_OPC_if_icmplt:
1406 case JVM_OPC_if_acmpeq: case JVM_OPC_if_acmpne:
1407 case JVM_OPC_ifnull: case JVM_OPC_ifnonnull:
1408 widened = mi->widening[pos];
1409 delta = readS2(ci);
1410 new_delta = method_code_map(mi,pos+delta) - new_pos;
1411 new_opcode = opcode;
1412 if (widened == 0) {
1413 writeU1(ci, opcode);
1414 writeU2(ci, new_delta);
1415 } else if (widened == 2) {
1416 switch (opcode) {
1417 case JVM_OPC_jsr:
1418 new_opcode = JVM_OPC_jsr_w;
1419 break;
1420 case JVM_OPC_goto:
1421 new_opcode = JVM_OPC_goto_w;
1422 break;
1423 default:
1424 CRW_FATAL(ci, "unexpected opcode");
1425 break;
1426 }
1427 writeU1(ci, new_opcode);
1428 writeU4(ci, new_delta);
1429 } else if (widened == 5) {
1430 switch (opcode) {
1431 case JVM_OPC_ifeq:
1432 new_opcode = JVM_OPC_ifne;
1433 break;
1434 case JVM_OPC_ifge:
1435 new_opcode = JVM_OPC_iflt;
1436 break;
1437 case JVM_OPC_ifgt:
1438 new_opcode = JVM_OPC_ifle;
1439 break;
1440 case JVM_OPC_ifle:
1441 new_opcode = JVM_OPC_ifgt;
1442 break;
1443 case JVM_OPC_iflt:
1444 new_opcode = JVM_OPC_ifge;
1445 break;
1446 case JVM_OPC_ifne:
1447 new_opcode = JVM_OPC_ifeq;
1448 break;
1449 case JVM_OPC_if_icmpeq:
1450 new_opcode = JVM_OPC_if_icmpne;
1451 break;
1452 case JVM_OPC_if_icmpne:
1453 new_opcode = JVM_OPC_if_icmpeq;
1454 break;
1455 case JVM_OPC_if_icmpge:
1456 new_opcode = JVM_OPC_if_icmplt;
1457 break;
1458 case JVM_OPC_if_icmpgt:
1459 new_opcode = JVM_OPC_if_icmple;
1460 break;
1461 case JVM_OPC_if_icmple:
1462 new_opcode = JVM_OPC_if_icmpgt;
1463 break;
1464 case JVM_OPC_if_icmplt:
1465 new_opcode = JVM_OPC_if_icmpge;
1466 break;
1467 case JVM_OPC_if_acmpeq:
1468 new_opcode = JVM_OPC_if_acmpne;
1469 break;
1470 case JVM_OPC_if_acmpne:
1471 new_opcode = JVM_OPC_if_acmpeq;
1472 break;
1473 case JVM_OPC_ifnull:
1474 new_opcode = JVM_OPC_ifnonnull;
1475 break;
1476 case JVM_OPC_ifnonnull:
1477 new_opcode = JVM_OPC_ifnull;
1478 break;
1479 default:
1480 CRW_FATAL(ci, "Unexpected opcode");
1481 break;
1482 }
1483 writeU1(ci, new_opcode); /* write inverse branch */
1484 writeU2(ci, 3 + 5); /* beyond if and goto_w */
1485 writeU1(ci, JVM_OPC_goto_w); /* add a goto_w */
1486 writeU4(ci, new_delta-3); /* write new and wide delta */
1487 } else {
1488 CRW_FATAL(ci, "Unexpected widening");
1489 }
1490 break;
1491
1492 case JVM_OPC_jsr_w:
1493 case JVM_OPC_goto_w:
1494 delta = readU4(ci);
1495 new_delta = method_code_map(mi,pos+delta) - new_pos;
1496 writeU1(ci, opcode);
1497 writeU4(ci, new_delta);
1498 break;
1499
1500 default:
1501 instr_len = opcode_length(ci, opcode);
1502 writeU1(ci, opcode);
1503 copy(ci, instr_len-1);
1504 break;
1505 }
1506 }
1507}
1508
1509static void
1510method_inject_and_write_code(MethodImage *mi)
1511{
1512 ByteCode bytecodes[LARGEST_INJECTION+1];
1513 ByteOffset len;
1514
1515 CRW_ASSERT_MI(mi);
1516
1517 /* Do injections */
1518 rewind_to_beginning_of_input_bytecodes(mi);
1519 len = entry_injection_code(mi, bytecodes, (int)sizeof(bytecodes));
1520 if ( len > 0 ) {
1521 int pos;
1522
1523 pos = 0;
1524 inject_bytecodes(mi, pos, bytecodes, len);
1525 /* Adjust pos 0 to map to new pos 0, you never want to
1526 * jump into this entry code injection. So the new pos 0
1527 * will be past this entry_injection_code().
1528 */
1529 adjust_map(mi, pos, len); /* Inject before behavior */
1530 }
1531 while (input_code_offset(mi) < mi->code_len) {
1532 inject_for_opcode(mi);
1533 }
1534
1535 /* Adjust instructions */
1536 rewind_to_beginning_of_input_bytecodes(mi);
1537 while (input_code_offset(mi) < mi->code_len) {
1538 if (!adjust_instruction(mi)) {
1539 rewind_to_beginning_of_input_bytecodes(mi);
1540 }
1541 }
1542
1543 /* Write new instructions */
1544 rewind_to_beginning_of_input_bytecodes(mi);
1545 while (input_code_offset(mi) < mi->code_len) {
1546 write_instruction(mi);
1547 }
1548}
1549
1550static void
1551copy_attribute(CrwClassImage *ci)
1552{
1553 int len;
1554
1555 (void)copyU2(ci);
1556 len = copyU4(ci);
1557 copy(ci, len);
1558}
1559
1560static void
1561copy_attributes(CrwClassImage *ci)
1562{
1563 unsigned i;
1564 unsigned count;
1565
1566 count = copyU2(ci);
1567 for (i = 0; i < count; ++i) {
1568 copy_attribute(ci);
1569 }
1570}
1571
1572static void
1573copy_all_fields(CrwClassImage *ci)
1574{
1575 unsigned i;
1576 unsigned count;
1577
1578 count = copyU2(ci);
1579 for (i = 0; i < count; ++i) {
1580 /* access, name, descriptor */
1581 copy(ci, 6);
1582 copy_attributes(ci);
1583 }
1584}
1585
1586static void
1587write_line_table(MethodImage *mi)
1588{
1589 unsigned i;
1590 unsigned count;
1591 CrwClassImage * ci;
1592
1593 CRW_ASSERT_MI(mi);
1594 ci = mi->ci;
1595 (void)copyU4(ci);
1596 count = copyU2(ci);
1597 for(i=0; i<count; i++) {
1598 ByteOffset start_pc;
1599 ByteOffset new_start_pc;
1600
1601 start_pc = readU2(ci);
1602
1603 if ( start_pc == 0 ) {
1604 new_start_pc = 0; /* Don't skip entry injection code. */
1605 } else {
1606 new_start_pc = method_code_map(mi, start_pc);
1607 }
1608
1609 writeU2(ci, new_start_pc);
1610 (void)copyU2(ci);
1611 }
1612}
1613
1614/* Used for LocalVariableTable and LocalVariableTypeTable attributes */
1615static void
1616write_var_table(MethodImage *mi)
1617{
1618 unsigned i;
1619 unsigned count;
1620 CrwClassImage * ci;
1621
1622 CRW_ASSERT_MI(mi);
1623 ci = mi->ci;
1624 (void)copyU4(ci);
1625 count = copyU2(ci);
1626 for(i=0; i<count; i++) {
1627 ByteOffset start_pc;
1628 ByteOffset new_start_pc;
1629 ByteOffset length;
1630 ByteOffset new_length;
1631 ByteOffset end_pc;
1632 ByteOffset new_end_pc;
1633
1634 start_pc = readU2(ci);
1635 length = readU2(ci);
1636
1637 if ( start_pc == 0 ) {
1638 new_start_pc = 0; /* Don't skip entry injection code. */
1639 } else {
1640 new_start_pc = method_code_map(mi, start_pc);
1641 }
1642 end_pc = start_pc + length;
1643 new_end_pc = method_code_map(mi, end_pc);
1644 new_length = new_end_pc - new_start_pc;
1645
1646 writeU2(ci, new_start_pc);
1647 writeU2(ci, new_length);
1648 (void)copyU2(ci);
1649 (void)copyU2(ci);
1650 (void)copyU2(ci);
1651 }
1652}
1653
1654/* The uoffset field is u2 or u4 depending on the code_len.
1655 * Note that the code_len is likely changing, so be careful here.
1656 */
1657static unsigned
1658readUoffset(MethodImage *mi)
1659{
1660 if ( mi->code_len > 65535 ) {
1661 return readU4(mi->ci);
1662 }
1663 return readU2(mi->ci);
1664}
1665
1666static void
1667writeUoffset(MethodImage *mi, unsigned val)
1668{
1669 if ( mi->new_code_len > 65535 ) {
1670 writeU4(mi->ci, val);
1671 }
1672 writeU2(mi->ci, val);
1673}
1674
1675static unsigned
1676copyUoffset(MethodImage *mi)
1677{
1678 unsigned uoffset;
1679
1680 uoffset = readUoffset(mi);
1681 writeUoffset(mi, uoffset);
1682 return uoffset;
1683}
1684
1685/* Copy over verification_type_info structure */
1686static void
1687copy_verification_types(MethodImage *mi, int ntypes)
1688{
1689 /* If there were ntypes, we just copy that over, no changes */
1690 if ( ntypes > 0 ) {
1691 int j;
1692
1693 for ( j = 0 ; j < ntypes ; j++ ) {
1694 unsigned tag;
1695
1696 tag = copyU1(mi->ci);
1697 switch ( tag ) {
1698 case JVM_ITEM_Object:
1699 (void)copyU2(mi->ci); /* Constant pool entry */
1700 break;
1701 case JVM_ITEM_Uninitialized:
1702 /* Code offset for 'new' opcode is for this object */
1703 writeUoffset(mi, method_code_map(mi, readUoffset(mi)));
1704 break;
1705 }
1706 }
1707 }
1708}
1709
1710/* Process the StackMapTable attribute. We didn't add any basic blocks
1711 * so the frame count remains the same but we may need to process the
1712 * frame types due to offset changes putting things out of range.
1713 */
1714static void
1715write_stackmap_table(MethodImage *mi)
1716{
1717 CrwClassImage *ci;
1718 CrwPosition save_position;
1719 ByteOffset last_pc;
1720 ByteOffset last_new_pc;
1721 unsigned i;
1722 unsigned attr_len;
1723 unsigned new_attr_len;
1724 unsigned count;
1725 unsigned delta_adj;
1726
1727 CRW_ASSERT_MI(mi);
1728 ci = mi->ci;
1729
1730 /* Save the position of the attribute length so we can fix it later */
1731 save_position = ci->output_position;
1732 attr_len = copyU4(ci);
1733 count = copyUoffset(mi); /* uoffset: number_of_entries */
1734 if ( count == 0 ) {
1735 CRW_ASSERT(ci, attr_len==2);
1736 return;
1737 }
1738
1739 /* Process entire stackmap */
1740 last_pc = 0;
1741 last_new_pc = 0;
1742 delta_adj = 0;
1743 for ( i = 0 ; i < count ; i++ ) {
1744 ByteOffset new_pc=0; /* new pc in instrumented code */
1745 unsigned ft; /* frame_type */
1746 int delta=0; /* pc delta */
1747 int new_delta=0; /* new pc delta */
1748
1749 ft = readU1(ci);
1750 if ( ft <= 63 ) {
1751 /* Frame Type: same_frame ([0,63]) */
1752 unsigned new_ft; /* new frame_type */
1753
1754 delta = (delta_adj + ft);
1755 new_pc = method_code_map(mi, last_pc + delta);
1756 new_delta = new_pc - last_new_pc;
1757 new_ft = (new_delta - delta_adj);
1758 if ( new_ft > 63 ) {
1759 /* Change to same_frame_extended (251) */
1760 new_ft = 251;
1761 writeU1(ci, new_ft);
1762 writeUoffset(mi, (new_delta - delta_adj));
1763 } else {
1764 writeU1(ci, new_ft);
1765 }
1766 } else if ( ft >= 64 && ft <= 127 ) {
1767 /* Frame Type: same_locals_1_stack_item_frame ([64,127]) */
1768 unsigned new_ft; /* new frame_type */
1769
1770 delta = (delta_adj + ft - 64);
1771 new_pc = method_code_map(mi, last_pc + delta);
1772 new_delta = new_pc - last_new_pc;
1773 if ( (new_delta - delta_adj) > 63 ) {
1774 /* Change to same_locals_1_stack_item_frame_extended (247) */
1775 new_ft = 247;
1776 writeU1(ci, new_ft);
1777 writeUoffset(mi, (new_delta - delta_adj));
1778 } else {
1779 new_ft = (new_delta - delta_adj) + 64;
1780 writeU1(ci, new_ft);
1781 }
1782 copy_verification_types(mi, 1);
1783 } else if ( ft >= 128 && ft <= 246 ) {
1784 /* Frame Type: reserved_for_future_use ([128,246]) */
1785 CRW_FATAL(ci, "Unknown frame type in StackMapTable attribute");
1786 } else if ( ft == 247 ) {
1787 /* Frame Type: same_locals_1_stack_item_frame_extended (247) */
1788 delta = (delta_adj + readUoffset(mi));
1789 new_pc = method_code_map(mi, last_pc + delta);
1790 new_delta = new_pc - last_new_pc;
1791 writeU1(ci, ft);
1792 writeUoffset(mi, (new_delta - delta_adj));
1793 copy_verification_types(mi, 1);
1794 } else if ( ft >= 248 && ft <= 250 ) {
1795 /* Frame Type: chop_frame ([248,250]) */
1796 delta = (delta_adj + readUoffset(mi));
1797 new_pc = method_code_map(mi, last_pc + delta);
1798 new_delta = new_pc - last_new_pc;
1799 writeU1(ci, ft);
1800 writeUoffset(mi, (new_delta - delta_adj));
1801 } else if ( ft == 251 ) {
1802 /* Frame Type: same_frame_extended (251) */
1803 delta = (delta_adj + readUoffset(mi));
1804 new_pc = method_code_map(mi, last_pc + delta);
1805 new_delta = new_pc - last_new_pc;
1806 writeU1(ci, ft);
1807 writeUoffset(mi, (new_delta - delta_adj));
1808 } else if ( ft >= 252 && ft <= 254 ) {
1809 /* Frame Type: append_frame ([252,254]) */
1810 delta = (delta_adj + readUoffset(mi));
1811 new_pc = method_code_map(mi, last_pc + delta);
1812 new_delta = new_pc - last_new_pc;
1813 writeU1(ci, ft);
1814 writeUoffset(mi, (new_delta - delta_adj));
1815 copy_verification_types(mi, (ft - 251));
1816 } else if ( ft == 255 ) {
1817 unsigned ntypes;
1818
1819 /* Frame Type: full_frame (255) */
1820 delta = (delta_adj + readUoffset(mi));
1821 new_pc = method_code_map(mi, last_pc + delta);
1822 new_delta = new_pc - last_new_pc;
1823 writeU1(ci, ft);
1824 writeUoffset(mi, (new_delta - delta_adj));
1825 ntypes = copyU2(ci); /* ulocalvar */
1826 copy_verification_types(mi, ntypes);
1827 ntypes = copyU2(ci); /* ustack */
1828 copy_verification_types(mi, ntypes);
1829 }
1830
1831 /* Update last_pc and last_new_pc (save on calls to method_code_map) */
1832 CRW_ASSERT(ci, delta >= 0);
1833 CRW_ASSERT(ci, new_delta >= 0);
1834 last_pc += delta;
1835 last_new_pc = new_pc;
1836 CRW_ASSERT(ci, last_pc <= mi->code_len);
1837 CRW_ASSERT(ci, last_new_pc <= mi->new_code_len);
1838
1839 /* Delta adjustment, all deltas are -1 now in attribute */
1840 delta_adj = 1;
1841 }
1842
1843 /* Update the attribute length */
1844 new_attr_len = ci->output_position - (save_position + 4);
1845 CRW_ASSERT(ci, new_attr_len >= attr_len);
1846 random_writeU4(ci, save_position, new_attr_len);
1847}
1848
1849/* Process the CLDC StackMap attribute. We didn't add any basic blocks
1850 * so the frame count remains the same but we may need to process the
1851 * frame types due to offset changes putting things out of range.
1852 */
1853static void
1854write_cldc_stackmap_table(MethodImage *mi)
1855{
1856 CrwClassImage *ci;
1857 CrwPosition save_position;
1858 unsigned i;
1859 unsigned attr_len;
1860 unsigned new_attr_len;
1861 unsigned count;
1862
1863 CRW_ASSERT_MI(mi);
1864 ci = mi->ci;
1865
1866 /* Save the position of the attribute length so we can fix it later */
1867 save_position = ci->output_position;
1868 attr_len = copyU4(ci);
1869 count = copyUoffset(mi); /* uoffset: number_of_entries */
1870 if ( count == 0 ) {
1871 CRW_ASSERT(ci, attr_len==2);
1872 return;
1873 }
1874
1875 /* Process entire stackmap */
1876 for ( i = 0 ; i < count ; i++ ) {
1877 unsigned ntypes;
1878
1879 writeUoffset(mi, method_code_map(mi, readUoffset(mi)));
1880 ntypes = copyU2(ci); /* ulocalvar */
1881 copy_verification_types(mi, ntypes);
1882 ntypes = copyU2(ci); /* ustack */
1883 copy_verification_types(mi, ntypes);
1884 }
1885
1886 /* Update the attribute length */
1887 new_attr_len = ci->output_position - (save_position + 4);
1888 CRW_ASSERT(ci, new_attr_len >= attr_len);
1889 random_writeU4(ci, save_position, new_attr_len);
1890}
1891
1892static void
1893method_write_exception_table(MethodImage *mi)
1894{
1895 unsigned i;
1896 unsigned count;
1897 CrwClassImage * ci;
1898
1899 CRW_ASSERT_MI(mi);
1900 ci = mi->ci;
1901 count = copyU2(ci);
1902 for(i=0; i<count; i++) {
1903 ByteOffset start_pc;
1904 ByteOffset new_start_pc;
1905 ByteOffset end_pc;
1906 ByteOffset new_end_pc;
1907 ByteOffset handler_pc;
1908 ByteOffset new_handler_pc;
1909
1910 start_pc = readU2(ci);
1911 end_pc = readU2(ci);
1912 handler_pc = readU2(ci);
1913
1914 new_start_pc = method_code_map(mi, start_pc);
1915 new_end_pc = method_code_map(mi, end_pc);
1916 new_handler_pc = method_code_map(mi, handler_pc);
1917
1918 writeU2(ci, new_start_pc);
1919 writeU2(ci, new_end_pc);
1920 writeU2(ci, new_handler_pc);
1921 (void)copyU2(ci);
1922 }
1923}
1924
1925static int
1926attribute_match(CrwClassImage *ci, CrwCpoolIndex name_index, const char *name)
1927{
1928 CrwConstantPoolEntry cs;
1929 int len;
1930
1931 CRW_ASSERT_CI(ci);
1932 CRW_ASSERT(ci, name!=NULL);
1933 len = (int)strlen(name);
1934 cs = cpool_entry(ci, name_index);
1935 if ( cs.len==len && strncmp(cs.ptr, name, len)==0) {
1936 return 1;
1937 }
1938 return 0;
1939}
1940
1941static void
1942method_write_code_attribute(MethodImage *mi)
1943{
1944 CrwClassImage * ci;
1945 CrwCpoolIndex name_index;
1946
1947 CRW_ASSERT_MI(mi);
1948 ci = mi->ci;
1949 name_index = copyU2(ci);
1950 if ( attribute_match(ci, name_index, "LineNumberTable") ) {
1951 write_line_table(mi);
1952 } else if ( attribute_match(ci, name_index, "LocalVariableTable") ) {
1953 write_var_table(mi);
1954 } else if ( attribute_match(ci, name_index, "LocalVariableTypeTable") ) {
1955 write_var_table(mi); /* Exact same format as the LocalVariableTable */
1956 } else if ( attribute_match(ci, name_index, "StackMapTable") ) {
1957 write_stackmap_table(mi);
1958 } else if ( attribute_match(ci, name_index, "StackMap") ) {
1959 write_cldc_stackmap_table(mi);
1960 } else {
1961 unsigned len;
1962 len = copyU4(ci);
1963 copy(ci, len);
1964 }
1965}
1966
1967static int
1968is_init_method(const char *name)
1969{
1970 if ( name!=NULL && strcmp(name,"<init>")==0 ) {
1971 return JNI_TRUE;
1972 }
1973 return JNI_FALSE;
1974}
1975
1976static int
1977is_clinit_method(const char *name)
1978{
1979 if ( name!=NULL && strcmp(name,"<clinit>")==0 ) {
1980 return JNI_TRUE;
1981 }
1982 return JNI_FALSE;
1983}
1984
1985static int
1986is_finalize_method(const char *name)
1987{
1988 if ( name!=NULL && strcmp(name,"finalize")==0 ) {
1989 return JNI_TRUE;
1990 }
1991 return JNI_FALSE;
1992}
1993
1994static int
1995skip_method(CrwClassImage *ci, const char *name,
1996 unsigned access_flags, ByteOffset code_len,
1997 int system_class, jboolean *pskip_call_return_sites)
1998{
1999 *pskip_call_return_sites = JNI_FALSE;
2000 if ( system_class ) {
2001 if ( code_len == 1 && is_init_method(name) ) {
2002 return JNI_TRUE;
2003 } else if ( code_len == 1 && is_finalize_method(name) ) {
2004 return JNI_TRUE;
2005 } else if ( is_clinit_method(name) ) {
2006 return JNI_TRUE;
2007 } else if ( ci->is_thread_class && strcmp(name,"currentThread")==0 ) {
2008 return JNI_TRUE;
2009 }
2010 /*
2011 if ( access_flags & JVM_ACC_PRIVATE ) {
2012 *pskip_call_return_sites = JNI_TRUE;
2013 }
2014 */
2015 }
2016 return JNI_FALSE;
2017}
2018
2019/* Process all code attributes */
2020static void
2021method_write_bytecodes(CrwClassImage *ci, unsigned mnum, unsigned access_flags)
2022{
2023 CrwPosition output_attr_len_position;
2024 CrwPosition output_max_stack_position;
2025 CrwPosition output_code_len_position;
2026 CrwPosition start_of_output_bytecodes;
2027 unsigned i;
2028 unsigned attr_len;
2029 unsigned max_stack;
2030 ByteOffset code_len;
2031 unsigned attr_count;
2032 unsigned new_attr_len;
2033 MethodImage * mi;
2034 jboolean object_init_method;
2035 jboolean skip_call_return_sites;
2036
2037 CRW_ASSERT_CI(ci);
2038
2039 /* Attribute Length */
2040 output_attr_len_position = ci->output_position;
2041 attr_len = copyU4(ci);
2042
2043 /* Max Stack */
2044 output_max_stack_position = ci->output_position;
2045 max_stack = copyU2(ci);
2046
2047 /* Max Locals */
2048 (void)copyU2(ci);
2049
2050 /* Code Length */
2051 output_code_len_position = ci->output_position;
2052 code_len = copyU4(ci);
2053 start_of_output_bytecodes = ci->output_position;
2054
2055 /* Some methods should not be instrumented */
2056 object_init_method = JNI_FALSE;
2057 skip_call_return_sites = JNI_FALSE;
2058 if ( ci->is_object_class &&
2059 is_init_method(ci->method_name[mnum]) &&
2060 strcmp(ci->method_descr[mnum],"()V")==0 ) {
2061 object_init_method = JNI_TRUE;
2062 skip_call_return_sites = JNI_TRUE;
2063 } else if ( skip_method(ci, ci->method_name[mnum], access_flags,
2064 code_len, ci->system_class, &skip_call_return_sites) ) {
2065 /* Copy remainder minus already copied, the U2 max_stack,
2066 * U2 max_locals, and U4 code_length fields have already
2067 * been processed.
2068 */
2069 copy(ci, attr_len - (2+2+4));
2070 return;
2071 }
2072
2073 /* Start Injection */
2074 mi = method_init(ci, mnum, code_len);
2075 mi->object_init_method = object_init_method;
2076 mi->access_flags = access_flags;
2077 mi->skip_call_return_sites = skip_call_return_sites;
2078
2079 /* Save the current position as the start of the input bytecodes */
2080 mi->start_of_input_bytecodes = ci->input_position;
2081
2082 /* The max stack may increase */
2083 mi->max_stack = max_stack;
2084 mi->new_max_stack = max_stack;
2085
2086 /* Adjust all code offsets */
2087 method_inject_and_write_code(mi);
2088
2089 /* Fix up code length (save new_code_len for later attribute processing) */
2090 mi->new_code_len = (int)(ci->output_position - start_of_output_bytecodes);
2091 random_writeU4(ci, output_code_len_position, mi->new_code_len);
2092
2093 /* Fixup max stack */
2094 CRW_ASSERT(ci, mi->new_max_stack <= 0xFFFF);
2095 random_writeU2(ci, output_max_stack_position, mi->new_max_stack);
2096
2097 /* Copy exception table */
2098 method_write_exception_table(mi);
2099
2100 /* Copy code attributes (needs mi->new_code_len) */
2101 attr_count = copyU2(ci);
2102 for (i = 0; i < attr_count; ++i) {
2103 method_write_code_attribute(mi);
2104 }
2105
2106 /* Fix up attribute length */
2107 new_attr_len = (int)(ci->output_position - (output_attr_len_position + 4));
2108 random_writeU4(ci, output_attr_len_position, new_attr_len);
2109
2110 /* Free method data */
2111 method_term(mi);
2112 mi = NULL;
2113
2114}
2115
2116static void
2117method_write(CrwClassImage *ci, unsigned mnum)
2118{
2119 unsigned i;
2120 unsigned access_flags;
2121 CrwCpoolIndex name_index;
2122 CrwCpoolIndex descr_index;
2123 unsigned attr_count;
2124
2125 access_flags = copyU2(ci);
2126 name_index = copyU2(ci);
2127 ci->method_name[mnum] = cpool_entry(ci, name_index).ptr;
2128 descr_index = copyU2(ci);
2129 ci->method_descr[mnum] = cpool_entry(ci, descr_index).ptr;
2130 attr_count = copyU2(ci);
2131
2132 for (i = 0; i < attr_count; ++i) {
2133 CrwCpoolIndex name_index;
2134
2135 name_index = copyU2(ci);
2136 if ( attribute_match(ci, name_index, "Code") ) {
2137 method_write_bytecodes(ci, mnum, access_flags);
2138 } else {
2139 unsigned len;
2140 len = copyU4(ci);
2141 copy(ci, len);
2142 }
2143 }
2144}
2145
2146static void
2147method_write_all(CrwClassImage *ci)
2148{
2149 unsigned i;
2150 unsigned count;
2151
2152 count = copyU2(ci);
2153 ci->method_count = count;
2154 if ( count > 0 ) {
2155 ci->method_name = (const char **)allocate_clean(ci, count*(int)sizeof(const char*));
2156 ci->method_descr = (const char **)allocate_clean(ci, count*(int)sizeof(const char*));
2157 }
2158
2159 for (i = 0; i < count; ++i) {
2160 method_write(ci, i);
2161 }
2162
2163 if ( ci->mnum_callback != NULL ) {
2164 (*(ci->mnum_callback))(ci->number, ci->method_name, ci->method_descr,
2165 count);
2166 }
2167}
2168
2169/* ------------------------------------------------------------------- */
2170/* Cleanup function. */
2171
2172static void
2173cleanup(CrwClassImage *ci)
2174{
2175 CRW_ASSERT_CI(ci);
2176 if ( ci->name != NULL ) {
2177 deallocate(ci, (void*)ci->name);
2178 ci->name = NULL;
2179 }
2180 if ( ci->method_name != NULL ) {
2181 deallocate(ci, (void*)ci->method_name);
2182 ci->method_name = NULL;
2183 }
2184 if ( ci->method_descr != NULL ) {
2185 deallocate(ci, (void*)ci->method_descr);
2186 ci->method_descr = NULL;
2187 }
2188 if ( ci->cpool != NULL ) {
2189 CrwCpoolIndex i;
2190 for(i=0; i<ci->cpool_count_plus_one; i++) {
2191 if ( ci->cpool[i].ptr != NULL ) {
2192 deallocate(ci, (void*)(ci->cpool[i].ptr));
2193 ci->cpool[i].ptr = NULL;
2194 }
2195 }
2196 deallocate(ci, (void*)ci->cpool);
2197 ci->cpool = NULL;
2198 }
2199}
2200
2201static jboolean
2202skip_class(unsigned access_flags)
2203{
2204 if ( access_flags & JVM_ACC_INTERFACE ) {
2205 return JNI_TRUE;
2206 }
2207 return JNI_FALSE;
2208}
2209
2210static long
2211inject_class(struct CrwClassImage *ci,
2212 int system_class,
2213 char* tclass_name,
2214 char* tclass_sig,
2215 char* call_name,
2216 char* call_sig,
2217 char* return_name,
2218 char* return_sig,
2219 char* obj_init_name,
2220 char* obj_init_sig,
2221 char* newarray_name,
2222 char* newarray_sig,
2223 unsigned char *buf,
2224 long buf_len)
2225{
2226 CrwConstantPoolEntry cs;
2227 CrwCpoolIndex this_class;
2228 CrwCpoolIndex super_class;
2229 unsigned magic;
2230 unsigned classfileVersion;
2231 unsigned interface_count;
2232
2233 CRW_ASSERT_CI(ci);
2234 CRW_ASSERT(ci, buf!=NULL);
2235 CRW_ASSERT(ci, buf_len!=0);
2236
2237 CRW_ASSERT(ci, strchr(tclass_name,'.')==NULL); /* internal qualified name */
2238
2239 ci->injection_count = 0;
2240 ci->system_class = system_class;
2241 ci->tclass_name = tclass_name;
2242 ci->tclass_sig = tclass_sig;
2243 ci->call_name = call_name;
2244 ci->call_sig = call_sig;
2245 ci->return_name = return_name;
2246 ci->return_sig = return_sig;
2247 ci->obj_init_name = obj_init_name;
2248 ci->obj_init_sig = obj_init_sig;
2249 ci->newarray_name = newarray_name;
2250 ci->newarray_sig = newarray_sig;
2251 ci->output = buf;
2252 ci->output_len = buf_len;
2253
2254 magic = copyU4(ci);
2255 CRW_ASSERT(ci, magic==0xCAFEBABE);
2256 if ( magic != 0xCAFEBABE ) {
2257 return (long)0;
2258 }
2259
2260 /* minor version number not used */
2261 (void)copyU2(ci);
2262 /* major version number not used */
2263 classfileVersion = copyU2(ci);
2264 CRW_ASSERT(ci, classfileVersion <= 50); /* Mustang class files or less */
2265
2266 cpool_setup(ci);
2267
2268 ci->access_flags = copyU2(ci);
2269 if ( skip_class(ci->access_flags) ) {
2270 return (long)0;
2271 }
2272
2273 this_class = copyU2(ci);
2274
2275 cs = cpool_entry(ci, (CrwCpoolIndex)(cpool_entry(ci, this_class).index1));
2276 if ( ci->name == NULL ) {
2277 ci->name = duplicate(ci, cs.ptr, cs.len);
2278 CRW_ASSERT(ci, strchr(ci->name,'.')==NULL); /* internal qualified name */
2279 }
2280 CRW_ASSERT(ci, (int)strlen(ci->name)==cs.len && strncmp(ci->name, cs.ptr, cs.len)==0);
2281
2282 super_class = copyU2(ci);
2283 if ( super_class == 0 ) {
2284 ci->is_object_class = JNI_TRUE;
2285 CRW_ASSERT(ci, strcmp(ci->name,"java/lang/Object")==0);
2286 }
2287
2288 interface_count = copyU2(ci);
2289 copy(ci, interface_count * 2);
2290
2291 copy_all_fields(ci);
2292
2293 method_write_all(ci);
2294
2295 if ( ci->injection_count == 0 ) {
2296 return (long)0;
2297 }
2298
2299 copy_attributes(ci);
2300
2301 return (long)ci->output_position;
2302}
2303
2304/* ------------------------------------------------------------------- */
2305/* Exported interfaces */
2306
2307JNIEXPORT void JNICALL
2308java_crw_demo(unsigned class_number,
2309 const char *name,
2310 const unsigned char *file_image,
2311 long file_len,
2312 int system_class,
2313 char* tclass_name, /* Name of class that has tracker methods. */
2314 char* tclass_sig, /* Signature of tclass */
2315 char* call_name, /* Method name to call at offset 0 */
2316 char* call_sig, /* Signature of this method */
2317 char* return_name, /* Method name to call before any return */
2318 char* return_sig, /* Signature of this method */
2319 char* obj_init_name, /* Method name to call in Object <init> */
2320 char* obj_init_sig, /* Signature of this method */
2321 char* newarray_name, /* Method name to call after newarray opcodes */
2322 char* newarray_sig, /* Signature of this method */
2323 unsigned char **pnew_file_image,
2324 long *pnew_file_len,
2325 FatalErrorHandler fatal_error_handler,
2326 MethodNumberRegister mnum_callback)
2327{
2328 CrwClassImage ci;
2329 long max_length;
2330 long new_length;
2331 void *new_image;
2332 int len;
2333
2334 /* Initial setup of the CrwClassImage structure */
2335 (void)memset(&ci, 0, (int)sizeof(CrwClassImage));
2336 ci.fatal_error_handler = fatal_error_handler;
2337 ci.mnum_callback = mnum_callback;
2338
2339 /* Do some interface error checks */
2340 if ( pnew_file_image==NULL ) {
2341 CRW_FATAL(&ci, "pnew_file_image==NULL");
2342 }
2343 if ( pnew_file_len==NULL ) {
2344 CRW_FATAL(&ci, "pnew_file_len==NULL");
2345 }
2346
2347 /* No file length means do nothing */
2348 *pnew_file_image = NULL;
2349 *pnew_file_len = 0;
2350 if ( file_len==0 ) {
2351 return;
2352 }
2353
2354 /* Do some more interface error checks */
2355 if ( file_image == NULL ) {
2356 CRW_FATAL(&ci, "file_image == NULL");
2357 }
2358 if ( file_len < 0 ) {
2359 CRW_FATAL(&ci, "file_len < 0");
2360 }
2361 if ( system_class != 0 && system_class != 1 ) {
2362 CRW_FATAL(&ci, "system_class is not 0 or 1");
2363 }
2364 if ( tclass_name == NULL ) {
2365 CRW_FATAL(&ci, "tclass_name == NULL");
2366 }
2367 if ( tclass_sig == NULL || tclass_sig[0]!='L' ) {
2368 CRW_FATAL(&ci, "tclass_sig is not a valid class signature");
2369 }
2370 len = (int)strlen(tclass_sig);
2371 if ( tclass_sig[len-1]!=';' ) {
2372 CRW_FATAL(&ci, "tclass_sig is not a valid class signature");
2373 }
2374 if ( call_name != NULL ) {
2375 if ( call_sig == NULL || strcmp(call_sig, "(II)V") != 0 ) {
2376 CRW_FATAL(&ci, "call_sig is not (II)V");
2377 }
2378 }
2379 if ( return_name != NULL ) {
2380 if ( return_sig == NULL || strcmp(return_sig, "(II)V") != 0 ) {
2381 CRW_FATAL(&ci, "return_sig is not (II)V");
2382 }
2383 }
2384 if ( obj_init_name != NULL ) {
2385 if ( obj_init_sig == NULL || strcmp(obj_init_sig, "(Ljava/lang/Object;)V") != 0 ) {
2386 CRW_FATAL(&ci, "obj_init_sig is not (Ljava/lang/Object;)V");
2387 }
2388 }
2389 if ( newarray_name != NULL ) {
2390 if ( newarray_sig == NULL || strcmp(newarray_sig, "(Ljava/lang/Object;)V") != 0 ) {
2391 CRW_FATAL(&ci, "newarray_sig is not (Ljava/lang/Object;)V");
2392 }
2393 }
2394
2395 /* Finish setup the CrwClassImage structure */
2396 ci.is_thread_class = JNI_FALSE;
2397 if ( name != NULL ) {
2398 CRW_ASSERT(&ci, strchr(name,'.')==NULL); /* internal qualified name */
2399
2400 ci.name = duplicate(&ci, name, (int)strlen(name));
2401 if ( strcmp(name, "java/lang/Thread")==0 ) {
2402 ci.is_thread_class = JNI_TRUE;
2403 }
2404 }
2405 ci.number = class_number;
2406 ci.input = file_image;
2407 ci.input_len = file_len;
2408
2409 /* Do the injection */
2410 max_length = file_len*2 + 512; /* Twice as big + 512 */
2411 new_image = allocate(&ci, (int)max_length);
2412 new_length = inject_class(&ci,
2413 system_class,
2414 tclass_name,
2415 tclass_sig,
2416 call_name,
2417 call_sig,
2418 return_name,
2419 return_sig,
2420 obj_init_name,
2421 obj_init_sig,
2422 newarray_name,
2423 newarray_sig,
2424 new_image,
2425 max_length);
2426
2427 /* Dispose or shrink the space to be returned. */
2428 if ( new_length == 0 ) {
2429 deallocate(&ci, (void*)new_image);
2430 new_image = NULL;
2431 } else {
2432 new_image = (void*)reallocate(&ci, (void*)new_image, (int)new_length);
2433 }
2434
2435 /* Return the new class image */
2436 *pnew_file_image = (unsigned char *)new_image;
2437 *pnew_file_len = (long)new_length;
2438
2439 /* Cleanup before we leave. */
2440 cleanup(&ci);
2441}
2442
2443/* Return the classname for this class which is inside the classfile image. */
2444JNIEXPORT char * JNICALL
2445java_crw_demo_classname(const unsigned char *file_image, long file_len,
2446 FatalErrorHandler fatal_error_handler)
2447{
2448 CrwClassImage ci;
2449 CrwConstantPoolEntry cs;
2450 CrwCpoolIndex this_class;
2451 unsigned magic;
2452 char * name;
2453
2454 name = NULL;
2455
2456 if ( file_len==0 || file_image==NULL ) {
2457 return name;
2458 }
2459
2460 /* The only fields we need filled in are the image pointer and the error
2461 * handler.
2462 * By not adding an output buffer pointer, no output is created.
2463 */
2464 (void)memset(&ci, 0, (int)sizeof(CrwClassImage));
2465 ci.input = file_image;
2466 ci.input_len = file_len;
2467 ci.fatal_error_handler = fatal_error_handler;
2468
2469 /* Read out the bytes from the classfile image */
2470
2471 magic = readU4(&ci); /* magic number */
2472 CRW_ASSERT(&ci, magic==0xCAFEBABE);
2473 if ( magic != 0xCAFEBABE ) {
2474 return name;
2475 }
2476 (void)readU2(&ci); /* minor version number */
2477 (void)readU2(&ci); /* major version number */
2478
2479 /* Read in constant pool. Since no output setup, writes are NOP's */
2480 cpool_setup(&ci);
2481
2482 (void)readU2(&ci); /* access flags */
2483 this_class = readU2(&ci); /* 'this' class */
2484
2485 /* Get 'this' constant pool entry */
2486 cs = cpool_entry(&ci, (CrwCpoolIndex)(cpool_entry(&ci, this_class).index1));
2487
2488 /* Duplicate the name */
2489 name = (char *)duplicate(&ci, cs.ptr, cs.len);
2490
2491 /* Cleanup before we leave. */
2492 cleanup(&ci);
2493
2494 /* Return malloc space */
2495 return name;
2496}