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