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