DEADSOFTWARE

Remove exception catching in main module
[mp3cc.git] / mpc / preverifier / check_code.c
1 /*
2 * @(#)check_code.c 1.26 02/09/27
3 *
4 * Copyright 1995-1999 by Sun Microsystems, Inc.,
5 * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
6 * All rights reserved.
7 *
8 * This software is the confidential and proprietary information
9 * of Sun Microsystems, Inc. ("Confidential Information"). You
10 * shall not disclose such Confidential Information and shall use
11 * it only in accordance with the terms of the license agreement
12 * you entered into with Sun.
13 * Use is subject to license terms.
14 */
17 /*=========================================================================
18 * SYSTEM: Verifier
19 * SUBSYSTEM: Verifies codes within a method block.
20 * FILE: check_code.c
21 * OVERVIEW: Verifies that the code within a method block does not
22 * exploit any security holes.
23 * AUTHOR: Sheng Liang, Consumer & Embedded
24 * Initial implementation based on the Classic VM Verifier.
25 * Edited by Tasneem Sayeed, Java Consumer Technologies
26 *=======================================================================*/
29 /*=========================================================================
30 * Include files
31 *=======================================================================*/
33 #include "check_code.h"
35 #include "opcodes.length"
36 #include "opcodes.in_out"
38 //#include "winsock2.h"
39 #define ntohl(x) (x)
41 /*=========================================================================
42 * Globals and extern declarations
43 *=======================================================================*/
45 #ifdef DEBUG_VERIFIER
46 int verify_verbose = 0;
47 static struct context_type *GlobalContext;
48 #endif
50 void rewriteCode(context_type *vcontext, struct methodblock *mb);
51 static void verify_method(context_type *context, struct methodblock *mb);
52 static void verify_field(context_type *context, struct fieldblock *fb);
54 static void verify_opcode_operands (context_type *, int inumber, int offset);
55 static void set_protected(context_type *, int inumber, int key, opcode_type);
56 static bool_t isSuperClass(context_type *, fullinfo_type);
58 static void initialize_exception_table(context_type *);
59 static int instruction_length(unsigned char *iptr);
60 static bool_t isLegalTarget(context_type *, int offset);
61 static void verify_constant_pool_type(context_type *, int, unsigned);
63 static void initialize_dataflow(context_type *);
64 static void run_dataflow(context_type *context);
65 static void check_register_values(context_type *context, int inumber);
66 static void check_flags(context_type *context, int inumber);
67 static void pop_stack(context_type *, int inumber, stack_info_type *);
68 static void update_registers(context_type *, int inumber, register_info_type *);
69 static void update_flags(context_type *, int inumber,
70 flag_type *new_and_flags, flag_type *new_or_flags);
71 static void push_stack(context_type *, int inumber, stack_info_type *stack);
73 static void merge_into_successors(context_type *, int inumber,
74 register_info_type *register_info,
75 stack_info_type *stack_info,
76 flag_type and_flags, flag_type or_flags);
77 static void merge_into_one_successor(context_type *context,
78 int from_inumber, int inumber,
79 register_info_type *register_info,
80 stack_info_type *stack_info,
81 flag_type and_flags, flag_type or_flags,
82 bool_t isException);
83 static void merge_stack(context_type *, int inumber, int to_inumber,
84 stack_info_type *);
85 static void merge_registers(context_type *, int inumber, int to_inumber,
86 register_info_type *);
87 static void merge_flags(context_type *context, int from_inumber, int to_inumber,
88 flag_type new_and_flags, flag_type new_or_flags);
90 static stack_item_type *copy_stack(context_type *, stack_item_type *);
91 static mask_type *copy_masks(context_type *, mask_type *masks, int mask_count);
92 static mask_type *add_to_masks(context_type *, mask_type *, int , int);
94 static fullinfo_type decrement_indirection(fullinfo_type);
96 static fullinfo_type merge_fullinfo_types(context_type *context,
97 fullinfo_type a, fullinfo_type b,
98 bool_t assignment);
99 static bool_t isAssignableTo(context_type *,fullinfo_type a, fullinfo_type b);
101 static ClassClass *object_fullinfo_to_classclass(context_type *, fullinfo_type);
104 #define NEW(type, count) \
105 ((type *)CCalloc(context, (count)*(sizeof(type)), FALSE))
106 #define ZNEW(type, count) \
107 ((type *)CCalloc(context, (count)*(sizeof(type)), TRUE))
109 static void CCinit(context_type *context);
110 static void CCreinit(context_type *context);
111 static void CCdestroy(context_type *context);
112 static void *CCalloc(context_type *context, int size, bool_t zero);
114 static char *cp_index_to_fieldname(context_type *context, int cp_index);
115 static char *cp_index_to_signature(context_type *context, int cp_index);
116 static fullinfo_type cp_index_to_class_fullinfo(context_type *, int, bool_t);
118 static char signature_to_fieldtype(context_type *context,
119 char **signature_p, fullinfo_type *info);
121 static void CCerror (context_type *, char *format, ...);
123 #ifdef DEBUG_VERIFIER
124 static void print_stack (context_type *, stack_info_type *stack_info);
125 static void print_registers(context_type *, register_info_type *register_info);
126 static void print_flags(context_type *, flag_type, flag_type);
127 static void print_formatted_fieldname(context_type *context, int index);
128 #endif
131 /*
132 * Access local hash tables without locking. This extra level
133 * of naming is intended to emphasize the fact that locks are
134 * not held and also to do error handling. Although it is not
135 * strictly necessary, one should always use the "_Local"
136 * versions of these functions on the verifier's local hash
137 * tables.
138 */
139 #define Str2IDFree_Local(localHashRoot) Str2IDFree(localHashRoot)
142 /*=========================================================================
143 * FUNCTION: Str2ID_Local
144 * OVERVIEW: Access local hash tables without locking
145 * This extra level of naming is intended to emphasize the
146 * fact that locks are not held and also to do error handling.
147 * These functions could all be macros like Str2IDFree_Local(),
148 * except that Str2ID() and ID2Str() can run out of memory,
149 * and the code in this file makes it inconvenient to check
150 * for that. As an expedient, rather than throwing exceptions,
151 * Str2ID_Local() is a function that calls CCerror() if
152 * necessary.
153 * Returns the index given the string which corresponds to the
154 * hash table entry.
155 * INTERFACE:
156 * parameters: context_type *: context
157 * struct StrIDhash **: hash_ptr
158 * char *: s
159 * void ***: param
160 * int: Copy
161 *
162 * returns: unsigned short
163 *=======================================================================*/
164 unsigned short
165 Str2ID_Local(context_type *context, struct StrIDhash **hash_ptr, char *s,
166 void ***param, int Copy) {
167 unsigned short ret;
168 if ((ret = Str2ID(hash_ptr, s, param, Copy)) == 0) {
169 // CCerror(context, "Out of memory");
172 return ret;
176 /*=========================================================================
177 * FUNCTION: ID2Str_Local
178 * OVERVIEW: Access local hash tables without locking
179 * This extra level of naming is intended to emphasize the
180 * fact that locks are not held and also to do error handling.
181 * These functions could all be macros like Str2IDFree_Local(),
182 * except that Str2ID() and ID2Str() can run out of memory,
183 * and the code in this file makes it inconvenient to check
184 * for that. As an expedient, rather than throwing exceptions,
185 * ID2Str_Local() is a function that calls CCerror() if
186 * necessary.
187 * Returns the string given the index which corresponds to the
188 * hash table entry.
189 * INTERFACE:
190 * parameters: context_type *: context
191 * struct StrIDhash *: h
192 * unsigned short: ID
193 * void ***: param
194 *
195 * returns: char *
196 *=======================================================================*/
197 char *
198 ID2Str_Local(context_type *context, struct StrIDhash *h, unsigned short ID,
199 void ***param) {
200 char *ret;
201 if ((ret = ID2Str(h, ID, param)) == 0) {
202 // CCerror(context, "Out of memory");
205 return ret;
209 /*=========================================================================
210 * FUNCTION: verify_class_codes
211 * OVERVIEW: Verifies the code for each of the methods in a class.
212 * Invoked by verify_class().
213 * Returns true if the class codes are ok.
214 * INTERFACE:
215 * parameters: pointer to the ClassClass structure.
216 *
217 * returns: boolean type
218 *=======================================================================*/
219 bool_t verify_class_codes(ClassClass *cb) {
220 context_type context_structure;
221 context_type *context = &context_structure;
222 bool_t result = TRUE;
223 void **addr;
224 int i;
226 #ifdef DEBUG_VERIFIER
227 GlobalContext = context;
228 #endif
230 /* Initialize the class-wide fields of the context. */
231 context->class = cb;
233 context->classHash = 0;
234 /* Zero method block field of the context, in case anyone calls CCerrror */
235 context->mb = 0;
236 context->superClasses = NULL; /* filled in later */
238 /* Don't call CCerror or anything that can call it above the setjmp! */
239 if (!setjmp(context->jump_buffer)) {
240 struct methodblock *mb;
241 struct fieldblock *fb;
243 CCinit(context); /* initialize heap; may throw */
245 context->object_info =
246 MAKE_CLASSNAME_INFO(context, JAVAPKG "Object", &addr);
247 *addr = classJavaLangObject;
248 context->string_info =
249 MAKE_CLASSNAME_INFO(context, JAVAPKG "String", &addr);
250 *addr = classJavaLangString;
251 context->throwable_info =
252 MAKE_CLASSNAME_INFO(context, JAVAPKG "Throwable", &addr);
253 *addr = classJavaLangThrowable;
254 context->currentclass_info =
255 MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), &addr);
256 *addr = cb;
257 if (cbSuperclass(cb) != 0) {
258 ClassClass *super = cbSuperclass(cb);
259 context->superclass_info =
260 MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(super), &addr);
261 *addr = super;
262 } else {
263 context->superclass_info = 0;
266 /* Look at each method */
267 for (i = cbFieldsCount(cb), fb = cbFields(cb); --i >= 0; fb++)
268 verify_field(context, fb);
270 unhand(context->class)->new_class_entries =
271 (char **)malloc((cbConstantPoolCount(context->class) * 3 + 100) * sizeof(char *));
272 unhand(context->class)->n_new_class_entries = 0;
274 for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++)
275 verify_method(context, mb);
277 unhand(context->class)->new_class_entries =
278 (char **)realloc(unhand(context->class)->new_class_entries,
279 unhand(context->class)->n_new_class_entries * sizeof(char *));
281 result = TRUE;
282 } else {
283 result = FALSE;
286 /* Cleanup */
287 Str2IDFree_Local(&context->classHash);
289 #ifdef DEBUG_VERIFIER
290 GlobalContext = 0;
291 #endif
293 if (context->superClasses != NULL) {
294 sysFree(context->superClasses);
296 CCdestroy(context); /* destroy heap */
297 return result;
301 /*=========================================================================
302 * FUNCTION: verify_field
303 * OVERVIEW: Verifies the field block within each method of a class
304 * file.
305 * Invoked by verify_class_codes().
306 * Returns true if the field block is ok.
307 * INTERFACE:
308 * parameters: pointer to the context_type structure.
309 * pointer to the field block
310 *
311 * returns: boolean type
312 *=======================================================================*/
313 static void
314 verify_field(context_type *context, struct fieldblock *fb)
316 int access_bits = fb->access;
318 if ( ((access_bits & ACC_PUBLIC) != 0) &&
319 ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) {
320 if (verbose) {
321 // jio_fprintf(stderr, "VERIFIER ERROR %s.%s:\n",
322 // cbName(fieldclass(fb)), fb->name);
323 // jio_fprintf(stderr, "Inconsistent access bits.");
325 longjmp(context->jump_buffer, 1);
326 }
330 /*=========================================================================
331 * FUNCTION: get_type_name
332 * OVERVIEW: Retrieves the type name information given the item type.
333 * Used by get_type_code() which is invoked by verify_method()
334 * to retrieve the type code for the stack map entries.
335 * INTERFACE:
336 * parameters: pointer to the context_type structure.
337 * fullinfo_type: type
338 * char *: buf
339 *
340 * returns: nothing
341 *=======================================================================*/
342 static void
343 get_type_name(context_type *context, fullinfo_type type, char *buf)
345 int i;
346 int indirection = GET_INDIRECTION(type);
347 for (i = indirection; i-- > 0; )
348 *buf++ = '[';
349 switch (GET_ITEM_TYPE(type)) {
350 case ITEM_Integer:
351 *buf++ = 'I'; break;
352 case ITEM_Float:
353 *buf++ = 'F'; break;
354 case ITEM_Double:
355 *buf++ = 'D'; break;
356 case ITEM_Long:
357 *buf++ = 'J'; break;
358 case ITEM_Char:
359 *buf++ = 'C'; break;
360 case ITEM_Short:
361 *buf++ = 'S'; break;
362 case ITEM_Byte:
363 *buf++ = 'B'; break;
364 case ITEM_Boolean:
365 *buf++ = 'Z'; break;
366 case ITEM_Object: {
367 unsigned short extra = GET_EXTRA_INFO(type);
368 if (indirection) *buf++ = 'L';
369 if (extra == 0) {
370 // panic("unexpected");
371 } else {
372 char *name = ID2Str_Local(context, context->classHash,
373 extra, 0);
374 strcpy(buf, name);
375 if (indirection) strcat(buf, ";");
377 return;
379 // default:
380 // panic("bad type");
382 *buf = '\0';
386 /*=========================================================================
387 * FUNCTION: check_class_constant
388 * OVERVIEW: Checks and returns the index corresponding to the given
389 * UTF8 constant entry within the constant pool.
390 * Returns -1 if none was found.
391 * Invoked by get_type_code().
392 * INTERFACE:
393 * parameters: pointer to the ClassClass structure.
394 * char *: utf8
395 *
396 * returns: long type
397 *=======================================================================*/
398 long check_class_constant(ClassClass *cb, char *utf8)
400 int i;
401 cp_item_type *constant_pool = cbConstantPool(cb);
402 unsigned char *type_table =
403 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
404 for (i = 0; i < cbConstantPoolCount(cb); i++) {
405 if (type_table[i] == (CONSTANT_Class | CONSTANT_POOL_ENTRY_RESOLVED) &&
406 strcmp(utf8, cbName(constant_pool[i].clazz)) == 0) {
407 return i;
409 if (type_table[i] == CONSTANT_Class &&
410 strcmp(utf8, constant_pool[constant_pool[i].i].cp) == 0) {
411 return i;
414 return -1;
418 /*=========================================================================
419 * FUNCTION: get_type_code
420 * OVERVIEW: Retrieves the type code entry given the item type.
421 * Invoked by verify_method() to retrieve the type code
422 * for the stack map entries.
423 * INTERFACE:
424 * parameters: pointer to the context_type structure.
425 * fullinfo_type: type
426 *
427 * returns: struct map_entry
428 *=======================================================================*/
429 struct map_entry get_type_code(context_type *context, fullinfo_type type)
431 struct map_entry result = {0,0};
432 switch (type) {
433 case ITEM_Double_2:
434 case ITEM_Long_2:
435 case ITEM_Bogus:
436 result.type = CF_ITEM_Bogus;
437 return result;
438 case ITEM_Integer:
439 result.type = CF_ITEM_Integer;
440 return result;
441 case ITEM_Float:
442 result.type = CF_ITEM_Float;
443 return result;
444 case ITEM_Double:
445 result.type = CF_ITEM_Double;
446 return result;
447 case ITEM_Long:
448 result.type = CF_ITEM_Long;
449 return result;
450 case ITEM_InitObject:
451 result.type = CF_ITEM_InitObject;
452 return result;
453 default:
454 if (GET_ITEM_TYPE(type) == ITEM_NewObject) {
455 int inum = GET_EXTRA_INFO(type);
456 result.type = CF_ITEM_NewObject;
457 result.info = context->instruction_data[inum].offset;
458 return result;
459 } else if (GET_ITEM_TYPE(type) == ITEM_Object && GET_EXTRA_INFO(type) == 0) {
460 result.type = CF_ITEM_Null;
461 return result;
462 } else if (GET_ITEM_TYPE(type) == ITEM_Object || GET_INDIRECTION(type) > 0) {
463 char type_name[1024];
464 int i;
465 result.type = CF_ITEM_Object;
466 get_type_name(context, type, type_name);
467 i = check_class_constant(context->class, type_name);
468 if (i >= 0) {
469 result.info = i;
470 return result;
472 for (i = 0; i < unhand(context->class)->n_new_class_entries; i++) {
473 if (strcmp(type_name, unhand(context->class)->new_class_entries[i]) == 0) {
474 result.info = ~i;
475 return result;
478 {
479 int entries = unhand(context->class)->n_new_class_entries;
480 unhand(context->class)->new_class_entries[entries] = strdup(type_name);
481 result.info = ~entries;
482 unhand(context->class)->n_new_class_entries = entries + 1;
483 return result;
485 } else {
486 // panic("bad type code");
487 return result; /* not reached */
493 /*=========================================================================
494 * FUNCTION: verify_method
495 * OVERVIEW: Verifies the code for one method within a class file.
496 * Invoked by verify_class_codes().
497 * INTERFACE:
498 * parameters: pointer to the context_type structure.
499 * struct methodblock*: mb
500 *
501 * returns: nothing
502 *=======================================================================*/
503 static void
504 verify_method(context_type *context, struct methodblock *mb)
506 int access_bits = mb->fb.access;
507 unsigned char *code;
508 int code_length;
509 short *code_data;
510 instruction_data_type *idata = 0;
511 int instruction_count;
512 int i, offset, inumber;
513 int exception_count;
514 int n_stack_maps, dead_count, jsr_count;
516 again:
517 code = mb->code;
518 code_length = mb->code_length;
520 /* CCerror can give method-specific info once this is set */
521 context->mb = mb;
523 CCreinit(context); /* initial heap */
524 code_data = NEW(short, code_length);
526 #ifdef DEBUG_VERIFIER
527 // if (verify_verbose) {
528 // jio_fprintf(stdout, "Looking at %s.%s%s 0x%x\n",
529 // cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature,
530 // (long)mb);
531 // }
532 #endif
534 if (((access_bits & ACC_PUBLIC) != 0) &&
535 ((access_bits & (ACC_PRIVATE | ACC_PROTECTED)) != 0)) {
536 // CCerror(context, "Inconsistent access bits.");
537 }
539 if ((access_bits & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
540 /* not much to do for abstract or native methods */
541 return;
542 }
544 if (code_length >= 65535) {
545 // CCerror(context, "Code of a method longer than 65535 bytes");
548 /* Run through the code. Mark the start of each instruction, and give
549 * the instruction a number */
550 for (i = 0, offset = 0; offset < code_length; i++) {
551 int length = instruction_length(&code[offset]);
552 int next_offset = offset + length;
553 // if (length <= 0)
554 // CCerror(context, "Illegal instruction found at offset %d", offset);
555 // if (next_offset > code_length)
556 // CCerror(context, "Code stops in the middle of instruction "
557 // " starting at offset %d", offset);
558 code_data[offset] = i;
559 while (++offset < next_offset)
560 code_data[offset] = -1; /* illegal location */
562 instruction_count = i; /* number of instructions in code */
564 /* Allocate a structure to hold info about each instruction. */
565 idata = NEW(instruction_data_type, instruction_count);
567 /* Initialize the heap, and other info in the context structure. */
568 context->code = code;
569 context->instruction_data = idata;
570 context->code_data = code_data;
571 context->instruction_count = instruction_count;
572 context->handler_info = NEW(struct handler_info_type,
573 mb->exception_table_length);
574 context->bitmask_size = (mb->nlocals + (BITS_PER_INT - 1))/BITS_PER_INT;
576 // if (instruction_count == 0)
577 // CCerror(context, "Empty code");
579 for (inumber = 0, offset = 0; offset < code_length; inumber++) {
580 int length = instruction_length(&code[offset]);
581 instruction_data_type *this_idata = &idata[inumber];
582 this_idata->opcode = code[offset];
583 this_idata->offset = offset;
584 this_idata->length = length;
585 this_idata->stack_info.stack = NULL;
586 this_idata->stack_info.stack_size = UNKNOWN_STACK_SIZE;
587 this_idata->register_info.register_count = UNKNOWN_REGISTER_COUNT;
588 this_idata->changed = FALSE; /* no need to look at it yet. */
589 this_idata->protected = FALSE; /* no need to look at it yet. */
590 /* Added for inlinejsr */
591 this_idata->is_target = FALSE; /* no need to look at it yet. */
592 this_idata->and_flags = (flag_type) -1; /* "bottom" and value */
593 this_idata->or_flags = 0; /* "bottom" or value*/
595 /* This also sets up this_data->operand. It also makes the
596 * xload_x and xstore_x instructions look like the generic form. */
597 verify_opcode_operands(context, inumber, offset);
598 offset += length;
602 /* make sure exception table is reasonable. */
603 initialize_exception_table(context);
604 /* Set up first instruction, and start of exception handlers. */
605 initialize_dataflow(context);
606 /* Run data flow analysis on the instructions. */
607 context->redoJsr = FALSE;
608 run_dataflow(context);
610 for (inumber = 0; inumber < instruction_count; inumber++) {
611 instruction_data_type *this_idata = &idata[inumber];
612 if ( (this_idata->or_flags & FLAG_REACHED) &&
613 ((this_idata->opcode == opc_jsr) ||
614 (this_idata->opcode == opc_jsr_w)) &&
615 (this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION)) {
616 this_idata->changed = TRUE;
617 context->redoJsr = TRUE;
620 if (context->redoJsr) {
621 run_dataflow(context);
625 /* verify checked exceptions, if any */
626 if ((exception_count = mb->nexceptions) > 0) {
627 unsigned short *exceptions = mb->exceptions;
628 for (i = 0; i < (int)exception_count; i++) {
629 /* Make sure the constant pool item is CONSTANT_Class */
630 verify_constant_pool_type(context, (int)exceptions[i],
631 1 << CONSTANT_Class);
636 dead_count = jsr_count = 0;
637 for (inumber = 0; inumber < instruction_count; inumber++) {
638 instruction_data_type *this_idata = &idata[inumber];
639 if ((this_idata->or_flags & FLAG_REACHED) == 0) {
640 dead_count++;
641 } else if (this_idata->opcode == opc_jsr ||
642 this_idata->opcode == opc_jsr_w) {
643 jsr_count++;
646 if (dead_count > 0 || jsr_count > 0) {
647 rewriteCode(context, mb);
648 goto again;
651 n_stack_maps = 0;
652 for (inumber = 0; inumber < instruction_count; inumber++) {
653 instruction_data_type *this_idata = &idata[inumber];
654 if (this_idata->is_target) {
655 n_stack_maps++;
659 mb->n_stack_maps = n_stack_maps;
660 mb->stack_maps =
661 (struct stack_map *)malloc(n_stack_maps * sizeof(struct stack_map));
663 n_stack_maps = 0;
664 for (inumber = 0; inumber < instruction_count; inumber++) {
665 instruction_data_type *this_idata = &idata[inumber];
666 if (this_idata->is_target) {
667 struct stack_info_type *stack_info = &this_idata->stack_info;
668 struct register_info_type *register_info = &this_idata->register_info;
669 int register_count = register_info->register_count;
670 struct stack_item_type *stack;
671 struct map_entry *new_entries;
672 int index, index2;
675 /* We may be allocating too big a structure if there are longs
676 * or doubles on the stack, but that's okay */
677 new_entries = (struct map_entry *)malloc(register_count * sizeof(struct map_entry));
679 for (index2 = 0, index = 0; index < register_count; index++) {
680 fullinfo_type info = register_info->registers[index];
681 if (info == ITEM_Double || info == ITEM_Long) {
682 if (index + 1 < register_count &&
683 register_info->registers[index + 1] == info+1) {
684 new_entries[index2++] = get_type_code(context, info);
685 index++;
686 } else {
687 new_entries[index2++] = get_type_code(context, ITEM_Bogus);
689 } else {
690 new_entries[index2++] = get_type_code(context, info);
693 mb->stack_maps[n_stack_maps].offset = this_idata->offset;
694 mb->stack_maps[n_stack_maps].locals = new_entries;
695 mb->stack_maps[n_stack_maps].nlocals = index2;
698 mb->stack_maps[n_stack_maps].nstacks = 0;
699 for (stack = stack_info->stack; stack; stack = stack->next) {
700 mb->stack_maps[n_stack_maps].nstacks++;
702 new_entries = (struct map_entry *)malloc(mb->stack_maps[n_stack_maps].nstacks * sizeof(struct map_entry));
703 index = 0;
704 for (stack = stack_info->stack; stack; stack = stack->next) {
705 new_entries[mb->stack_maps[n_stack_maps].nstacks - (++index)] =
706 get_type_code(context, stack->item);
708 mb->stack_maps[n_stack_maps].stacks = new_entries;
710 unhand(context->class)->has_stack_maps = 1;
711 n_stack_maps++;
717 /*=========================================================================
718 * FUNCTION: verify_opcode_operands
719 * OVERVIEW: Verifies the operands of a single instruction given an
720 * instruction number and an offset.
721 * Also, for simplicity, move the operand into the ->operand
722 * field.
723 * Make sure that branches do not go into the middle
724 * of nowhere.
725 * Invoked by verify_method().
726 * INTERFACE:
727 * parameters: context_type *: context
728 * int: inumber
729 * int: offset
730 *
731 * returns: nothing
732 *=======================================================================*/
733 static void
734 verify_opcode_operands(context_type *context, int inumber, int offset)
736 instruction_data_type *idata = context->instruction_data;
737 instruction_data_type *this_idata = &idata[inumber];
738 short *code_data = context->code_data;
739 struct methodblock *mb = context->mb;
740 unsigned char *code = context->code;
741 opcode_type opcode = this_idata->opcode;
742 int var;
744 this_idata->operand.i = 0;
745 this_idata->operand2.i = 0;
747 switch (opcode) {
749 case opc_jsr:
750 /* instruction of ret statement */
751 this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION;
752 /* FALLTHROUGH */
753 case opc_ifeq: case opc_ifne: case opc_iflt:
754 case opc_ifge: case opc_ifgt: case opc_ifle:
755 case opc_ifnull: case opc_ifnonnull:
756 case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmplt:
757 case opc_if_icmpge: case opc_if_icmpgt: case opc_if_icmple:
758 case opc_if_acmpeq: case opc_if_acmpne:
759 case opc_goto: {
760 /* Set the ->operand to be the instruction number of the target. */
761 int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];
762 int target = offset + jump;
763 // if (!isLegalTarget(context, target))
764 // CCerror(context, "Illegal target of jump or branch");
765 this_idata->operand.i = code_data[target];
766 break;
769 case opc_jsr_w:
770 /* instruction of ret statement */
771 this_idata->operand2.i = UNKNOWN_RET_INSTRUCTION;
772 /* FALLTHROUGH */
773 case opc_goto_w: {
774 /* Set the ->operand to be the instruction number of the target. */
775 int jump = (((signed char)(code[offset+1])) << 24) +
776 (code[offset+2] << 16) + (code[offset+3] << 8) +
777 (code[offset + 4]);
778 int target = offset + jump;
779 // if (!isLegalTarget(context, target))
780 // CCerror(context, "Illegal target of jump or branch");
781 this_idata->operand.i = code_data[target];
782 break;
785 case opc_tableswitch:
786 case opc_lookupswitch: {
787 /* Set the ->operand to be a table of possible instruction targets. */
788 long *lpc = (long *) UCALIGN(code + offset + 1);
789 long *lptr;
790 int *saved_operand;
791 int keys;
792 int k, delta;
793 if (opcode == opc_tableswitch) {
794 keys = ntohl(lpc[2]) - ntohl(lpc[1]) + 1;
795 delta = 1;
796 } else {
797 keys = ntohl(lpc[1]); /* number of pairs */
798 delta = 2;
799 /* Make sure that the tableswitch items are sorted */
800 for (k = keys - 1, lptr = &lpc[2]; --k >= 0; lptr += 2) {
801 long this_key = ntohl(lptr[0]); /* NB: ntohl may be unsigned */
802 long next_key = ntohl(lptr[2]);
803 // if (this_key >= next_key) {
804 // CCerror(context, "Unsorted lookup switch");
805 // }
808 /* This code has been changed for inlining. We know have the keys
809 * in the same order that they occur in the code, with the default
810 * key being the first one.
811 */
812 saved_operand = NEW(int, keys + 2);
813 // if (!isLegalTarget(context, offset + ntohl(lpc[0])))
814 // CCerror(context, "Illegal default target in switch");
816 saved_operand[0] = keys + 1; /* number of successors */
817 saved_operand[1] = code_data[offset + ntohl(lpc[0])]; /* default */
819 for (k = 0, lptr = &lpc[3]; k < keys; lptr += delta, k++) {
820 int target = offset + ntohl(lptr[0]);
821 // if (!isLegalTarget(context, target))
822 // CCerror(context, "Illegal branch in opc_tableswitch");
823 saved_operand[k + 2] = code_data[target];
825 this_idata->operand.ip = saved_operand;
826 break;
829 case opc_ldc: {
830 /* Make sure the constant pool item is the right type. */
831 int key = code[offset + 1];
832 int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) |
833 (1 << CONSTANT_String);
834 this_idata->operand.i = key;
835 verify_constant_pool_type(context, key, types);
836 break;
839 case opc_ldc_w: {
840 /* Make sure the constant pool item is the right type. */
841 int key = (code[offset + 1] << 8) + code[offset + 2];
842 int types = (1 << CONSTANT_Integer) | (1 << CONSTANT_Float) |
843 (1 << CONSTANT_String);
844 this_idata->operand.i = key;
845 verify_constant_pool_type(context, key, types);
846 break;
849 case opc_ldc2_w: {
850 /* Make sure the constant pool item is the right type. */
851 int key = (code[offset + 1] << 8) + code[offset + 2];
852 int types = (1 << CONSTANT_Double) | (1 << CONSTANT_Long);
853 this_idata->operand.i = key;
854 verify_constant_pool_type(context, key, types);
855 break;
858 case opc_getfield: case opc_putfield:
859 case opc_getstatic: case opc_putstatic: {
860 /* Make sure the constant pool item is the right type. */
861 int key = (code[offset + 1] << 8) + code[offset + 2];
862 this_idata->operand.i = key;
863 verify_constant_pool_type(context, key, 1 << CONSTANT_Fieldref);
864 if (opcode == opc_getfield || opcode == opc_putfield)
865 set_protected(context, inumber, key, opcode);
866 break;
869 case opc_invokevirtual:
870 case opc_invokespecial:
871 case opc_invokestatic:
872 case opc_invokeinterface: {
873 /* Make sure the constant pool item is the right type. */
874 int key = (code[offset + 1] << 8) + code[offset + 2];
875 char *methodname;
876 fullinfo_type clazz_info;
877 int kind = (opcode == opc_invokeinterface
878 ? 1 << CONSTANT_InterfaceMethodref
879 : 1 << CONSTANT_Methodref);
880 /* Make sure the constant pool item is the right type. */
881 verify_constant_pool_type(context, key, kind);
882 methodname = cp_index_to_fieldname(context, key);
883 clazz_info = cp_index_to_class_fullinfo(context, key, TRUE);
884 this_idata->operand.i = key;
885 this_idata->operand2.fi = clazz_info;
886 if (strcmp(methodname, "<init>") == 0) {
887 // if (opcode != opc_invokespecial)
888 // CCerror(context,
889 // "Must call initializers using invokespecial");
890 this_idata->opcode = opc_invokeinit;
891 } else {
892 // if (methodname[0] == '<')
893 // CCerror(context, "Illegal call to internal method");
894 if (opcode == opc_invokespecial
895 && clazz_info != context->currentclass_info
896 && clazz_info != context->superclass_info) {
897 ClassClass *cb = context->class;
898 for (; ; cb = cbSuperclass(cb)) {
899 if (clazz_info == MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), 0))
900 break;
901 /* The optimizer make cause this to happen on local code */
902 if (cbSuperclass(cb) == 0) {
903 /* optimizer make cause this to happen on local code */
904 // if (cbLoader(cb) != 0)
905 // CCerror(context,
906 // "Illegal use of nonvirtual function call");
907 break;
912 if (opcode == opc_invokeinterface) {
913 char *signature = cp_index_to_signature(context, key);
914 unsigned int args1 = Signature2ArgsSize(signature) + 1;
915 unsigned int args2 = code[offset + 3];
916 if (args1 != args2) {
917 // CCerror(context,
918 // "Inconsistent args_size for opc_invokeinterface");
919 }
920 if (code[offset + 4] != 0) {
921 // CCerror(context,
922 // "Fourth operand byte of invokeinterface must be zero");
924 } else if (opcode == opc_invokevirtual
925 || opcode == opc_invokespecial)
926 set_protected(context, inumber, key, opcode);
927 break;
931 case opc_instanceof:
932 case opc_checkcast:
933 case opc_new:
934 case opc_anewarray:
935 case opc_multianewarray: {
936 /* Make sure the constant pool item is a class */
937 int key = (code[offset + 1] << 8) + code[offset + 2];
938 fullinfo_type target;
939 verify_constant_pool_type(context, key, 1 << CONSTANT_Class);
940 target = cp_index_to_class_fullinfo(context, key, FALSE);
941 // if (GET_ITEM_TYPE(target) == ITEM_Bogus)
942 // CCerror(context, "Illegal type");
943 switch(opcode) {
944 case opc_anewarray:
945 if ((GET_INDIRECTION(target)) >= MAX_ARRAY_DIMENSIONS)
946 CCerror(context, "Array with too many dimensions");
947 this_idata->operand.fi = MAKE_FULLINFO(GET_ITEM_TYPE(target),
948 GET_INDIRECTION(target) + 1,
949 GET_EXTRA_INFO(target));
950 break;
951 case opc_new:
952 // if (WITH_ZERO_EXTRA_INFO(target) !=
953 // MAKE_FULLINFO(ITEM_Object, 0, 0))
954 // CCerror(context, "Illegal creation of multi-dimensional array");
955 /* operand gets set to the "unitialized object". operand2 gets
956 * set to what the value will be after it's initialized. */
957 this_idata->operand.fi = MAKE_FULLINFO(ITEM_NewObject, 0, inumber);
958 this_idata->operand2.fi = target;
959 break;
960 case opc_multianewarray:
961 this_idata->operand.fi = target;
962 this_idata->operand2.i = code[offset + 3];
963 // if ( (this_idata->operand2.i > (int)GET_INDIRECTION(target))
964 // || (this_idata->operand2.i == 0))
965 // CCerror(context, "Illegal dimension argument");
966 break;
967 default:
968 this_idata->operand.fi = target;
970 break;
973 case opc_newarray: {
974 /* Cache the result of the opc_newarray into the operand slot */
975 fullinfo_type full_info;
976 switch (code[offset + 1]) {
977 case T_INT:
978 full_info = MAKE_FULLINFO(ITEM_Integer, 1, 0); break;
979 case T_LONG:
980 full_info = MAKE_FULLINFO(ITEM_Long, 1, 0); break;
981 case T_FLOAT:
982 full_info = MAKE_FULLINFO(ITEM_Float, 1, 0); break;
983 case T_DOUBLE:
984 full_info = MAKE_FULLINFO(ITEM_Double, 1, 0); break;
985 case T_BYTE:
986 full_info = MAKE_FULLINFO(ITEM_Byte, 1, 0); break;
987 case T_BOOLEAN:
988 full_info = MAKE_FULLINFO(ITEM_Boolean, 1, 0); break;
989 case T_CHAR:
990 full_info = MAKE_FULLINFO(ITEM_Char, 1, 0); break;
991 case T_SHORT:
992 full_info = MAKE_FULLINFO(ITEM_Short, 1, 0); break;
993 default:
994 full_info = 0; /* make GCC happy */
995 // CCerror(context, "Bad type passed to opc_newarray");
997 this_idata->operand.fi = full_info;
998 break;
1001 /* Fudge iload_x, aload_x, etc to look like their generic cousin. */
1002 case opc_iload_0: case opc_iload_1: case opc_iload_2: case opc_iload_3:
1003 this_idata->opcode = opc_iload;
1004 var = opcode - opc_iload_0;
1005 goto check_local_variable;
1007 case opc_fload_0: case opc_fload_1: case opc_fload_2: case opc_fload_3:
1008 this_idata->opcode = opc_fload;
1009 var = opcode - opc_fload_0;
1010 goto check_local_variable;
1012 case opc_aload_0: case opc_aload_1: case opc_aload_2: case opc_aload_3:
1013 this_idata->opcode = opc_aload;
1014 var = opcode - opc_aload_0;
1015 goto check_local_variable;
1017 case opc_lload_0: case opc_lload_1: case opc_lload_2: case opc_lload_3:
1018 this_idata->opcode = opc_lload;
1019 var = opcode - opc_lload_0;
1020 goto check_local_variable2;
1022 case opc_dload_0: case opc_dload_1: case opc_dload_2: case opc_dload_3:
1023 this_idata->opcode = opc_dload;
1024 var = opcode - opc_dload_0;
1025 goto check_local_variable2;
1027 case opc_istore_0: case opc_istore_1: case opc_istore_2: case opc_istore_3:
1028 this_idata->opcode = opc_istore;
1029 var = opcode - opc_istore_0;
1030 goto check_local_variable;
1032 case opc_fstore_0: case opc_fstore_1: case opc_fstore_2: case opc_fstore_3:
1033 this_idata->opcode = opc_fstore;
1034 var = opcode - opc_fstore_0;
1035 goto check_local_variable;
1037 case opc_astore_0: case opc_astore_1: case opc_astore_2: case opc_astore_3:
1038 this_idata->opcode = opc_astore;
1039 var = opcode - opc_astore_0;
1040 goto check_local_variable;
1042 case opc_lstore_0: case opc_lstore_1: case opc_lstore_2: case opc_lstore_3:
1043 this_idata->opcode = opc_lstore;
1044 var = opcode - opc_lstore_0;
1045 goto check_local_variable2;
1047 case opc_dstore_0: case opc_dstore_1: case opc_dstore_2: case opc_dstore_3:
1048 this_idata->opcode = opc_dstore;
1049 var = opcode - opc_dstore_0;
1050 goto check_local_variable2;
1052 case opc_wide:
1053 this_idata->opcode = code[offset + 1];
1054 var = (code[offset + 2] << 8) + code[offset + 3];
1055 switch(this_idata->opcode) {
1056 case opc_lload: case opc_dload:
1057 case opc_lstore: case opc_dstore:
1058 goto check_local_variable2;
1059 default:
1060 goto check_local_variable;
1063 case opc_iinc: /* the increment amount doesn't matter */
1064 case opc_ret:
1065 case opc_aload: case opc_iload: case opc_fload:
1066 case opc_astore: case opc_istore: case opc_fstore:
1067 var = code[offset + 1];
1068 check_local_variable:
1069 /* Make sure that the variable number isn't illegal. */
1070 this_idata->operand.i = var;
1071 // if (var >= (int)mb->nlocals)
1072 // CCerror(context, "Illegal local variable number");
1073 break;
1075 case opc_lload: case opc_dload: case opc_lstore: case opc_dstore:
1076 var = code[offset + 1];
1077 check_local_variable2:
1078 /* Make sure that the variable number isn't illegal. */
1079 this_idata->operand.i = var;
1080 // if ((var + 1) >= (int)mb->nlocals)
1081 // CCerror(context, "Illegal local variable number");
1082 break;
1084 // default:
1085 // if (opcode >= opc_breakpoint)
1086 // CCerror(context, "Quick instructions shouldn't appear yet.");
1087 break;
1088 } /* of switch */
1092 /*=========================================================================
1093 * FUNCTION: set_protected
1094 * OVERVIEW: Checks the field access to see if the instruction is
1095 * protected, is private and is in the same class package,
1096 * then the protected bit for the given instruction is set.
1097 * Invoked by verify_operands_opcodes() to set protected bit
1098 * for instructions of the following opcode types:
1099 * opc_getfield, opc_putfield, and opc_invokevirtual.
1100 * INTERFACE:
1101 * parameters: context_type *: context
1102 * int: instruction number
1103 * int: key
1104 * opcode_type: opcode
1105 *
1106 * returns: nothing
1107 *=======================================================================*/
1108 static void
1109 set_protected(context_type *context, int inumber, int key, opcode_type opcode)
1111 /* fullinfo_type clazz_info = cp_index_to_class_fullinfo(context, key, TRUE);
1112 if (isSuperClass(context, clazz_info)) {
1113 char *name = cp_index_to_fieldname(context, key);
1114 char *signature = cp_index_to_signature(context, key);
1115 unsigned ID = NameAndTypeToHash(name, signature);
1116 ClassClass *calledClass =
1117 object_fullinfo_to_classclass(context, clazz_info);
1118 struct fieldblock *fb;
1120 if (ID == 0) { // NameAndTypeToHash returns 0 if out of memory
1121 // CCerror(context, "Out of memory");
1122 return;
1124 if (opcode != opc_invokevirtual && opcode != opc_invokespecial) {
1125 int n = cbFieldsCount(calledClass);
1126 fb = cbFields(calledClass);
1127 for (; --n >= 0; fb++) {
1128 if (fb->ID == ID) {
1129 goto haveIt;
1132 return;
1133 } else {
1134 struct methodblock *mb = cbMethods(calledClass);
1135 int n = cbMethodsCount(calledClass);
1136 for (; --n >= 0; mb++) {
1137 if (mb->fb.ID == ID) {
1138 fb = &mb->fb;
1139 goto haveIt;
1142 return;
1144 haveIt:
1145 if (IsProtected(fb->access)) {
1146 if (IsPrivate(fb->access) ||
1147 !IsSameClassPackage(calledClass, context->class))
1148 context->instruction_data[inumber].protected = TRUE;
1150 }*/
1154 /*=========================================================================
1155 * FUNCTION: isSuperClass
1156 * OVERVIEW: Determines which of the classes are superclasses.
1157 * Returns true if the given clazz_info corresponds to a
1158 * a superclass.
1159 * INTERFACE:
1160 * parameters: context_type* : context
1161 * fullinfo_type: clazz_info
1162 *
1163 * returns: boolean type
1164 *=======================================================================*/
1165 static bool_t
1166 isSuperClass(context_type *context, fullinfo_type clazz_info) {
1168 //return TRUE;
1170 fullinfo_type *fptr = context->superClasses;
1171 if (fptr == NULL) {
1172 ClassClass *cb;
1173 fullinfo_type *gptr;
1174 int i;
1175 /* Count the number of superclasses. By counting ourselves, and
1176 * not counting Object, we get the same number. */
1177 for (i = 0, cb = context->class;
1178 cb != classJavaLangObject;
1179 i++, cb = cbSuperclass(cb));
1180 /* Can't go on context heap since it survives more than one method */
1181 context->superClasses = fptr
1182 = sysMalloc(sizeof(fullinfo_type)*(i + 1));
1183 if (fptr == 0) {
1184 // CCerror(context, "Out of memory");
1186 for (gptr = fptr, cb = context->class; cb != classJavaLangObject; ) {
1187 void **addr;
1188 cb = cbSuperclass(cb);
1189 *gptr++ = MAKE_CLASSNAME_INFO_WITH_COPY(context, cbName(cb), &addr);
1190 *addr = cb;
1192 *gptr = 0;
1193 }
1194 for (; *fptr != 0; fptr++) {
1195 if (*fptr == clazz_info)
1196 return TRUE;
1198 return FALSE;
1202 /*=========================================================================
1203 * FUNCTION: initialize_exception_table
1204 * OVERVIEW: Initializes the exception table.
1205 * Looks through each item on the exception table and ensures
1206 * that each of the fields refers to a legal instruction.
1207 * INTERFACE:
1208 * parameters: pointer to the context_type structure.
1209 *
1210 * returns: nothing
1211 *=======================================================================*/
1212 static void
1213 initialize_exception_table(context_type *context)
1215 struct methodblock *mb = context->mb;
1216 struct CatchFrame *exception_table = mb->exception_table;
1217 struct handler_info_type *handler_info = context->handler_info;
1218 short *code_data = context->code_data;
1219 unsigned long code_length = mb->code_length;
1221 int i;
1222 for (i = mb->exception_table_length;
1223 --i >= 0; exception_table++, handler_info++) {
1224 unsigned long start = exception_table->start_pc;
1225 unsigned long end = exception_table->end_pc;
1226 unsigned long handler = exception_table->handler_pc;
1227 unsigned catchType = exception_table->catchType;
1228 stack_item_type *stack_item = NEW(stack_item_type, 1);
1229 if (!( start < end && start >= 0
1230 && isLegalTarget(context, start)
1231 && (end == code_length || isLegalTarget(context, end)))) {
1232 // CCerror(context, "Illegal exception table range");
1234 if (!((handler > 0) && isLegalTarget(context, handler))) {
1235 // CCerror(context, "Illegal exception table handler");
1238 handler_info->start = code_data[start];
1239 /* end may point to one byte beyond the end of bytecodes. */
1240 handler_info->end = (end == context->mb->code_length) ?
1241 context->instruction_count : code_data[end];
1242 handler_info->handler = code_data[handler];
1243 handler_info->stack_info.stack = stack_item;
1244 handler_info->stack_info.stack_size = 1;
1246 stack_item->next = NULL;
1247 if (catchType != 0) {
1248 union cp_item_type *cp = cbConstantPool(context->class);
1249 char *classname;
1250 verify_constant_pool_type(context, catchType, 1 << CONSTANT_Class);
1251 classname = GetClassConstantClassName(cp, catchType);
1252 stack_item->item = MAKE_CLASSNAME_INFO_WITH_COPY(context, classname, 0);
1253 } else {
1254 stack_item->item = context->throwable_info;
1260 /*=========================================================================
1261 * FUNCTION: instruction_length
1262 * OVERVIEW: Given a pointer to an instruction, return its length.
1263 * Use the table opcode_length[] which is automatically built.
1264 * INTERFACE:
1265 * parameters: pointer to the instruction
1266 *
1267 * returns: int type
1268 *=======================================================================*/
1269 static int instruction_length(unsigned char *iptr)
1271 int instruction = *iptr;
1272 switch (instruction) {
1273 case opc_tableswitch: {
1274 long *lpc = (long *) UCALIGN(iptr + 1);
1275 int index = ntohl(lpc[2]) - ntohl(lpc[1]);
1276 if ((index < 0) || (index > 65535)) {
1277 return -1; /* illegal */
1278 } else {
1279 return (unsigned char *)(&lpc[index + 4]) - iptr;
1283 case opc_lookupswitch: {
1284 long *lpc = (long *) UCALIGN(iptr + 1);
1285 int npairs = ntohl(lpc[1]);
1286 if (npairs < 0 || npairs >= 8192)
1287 return -1;
1288 else
1289 return (unsigned char *)(&lpc[2 * (npairs + 1)]) - iptr;
1292 case opc_wide:
1293 switch(iptr[1]) {
1294 case opc_ret:
1295 case opc_iload: case opc_istore:
1296 case opc_fload: case opc_fstore:
1297 case opc_aload: case opc_astore:
1298 case opc_lload: case opc_lstore:
1299 case opc_dload: case opc_dstore:
1300 return 4;
1301 case opc_iinc:
1302 return 6;
1303 default:
1304 return -1;
1307 default: {
1308 /* A length of 0 indicates an error. */
1309 int length = opcode_length[instruction];
1310 return (length <= 0) ? -1 : length;
1316 /*=========================================================================
1317 * FUNCTION: isLegalTarget
1318 * OVERVIEW: Given the target of a branch, make sure that it is a legal
1319 * target. Returns true if it is a legal target of a branch.
1320 * INTERFACE:
1321 * parameters: pointer to the context_type
1322 * int: offset
1323 *
1324 * returns: boolean type
1325 *=======================================================================*/
1326 static bool_t
1327 isLegalTarget(context_type *context, int offset)
1329 struct methodblock *mb = context->mb;
1330 int code_length = mb->code_length;
1331 short *code_data = context->code_data;
1332 return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
1336 /*=========================================================================
1337 * FUNCTION: verify_constant_pool_type
1338 * OVERVIEW: Make sure that an element of the constant pool is really
1339 * of the indicated type.
1340 * INTERFACE:
1341 * parameters: pointer to the context_type
1342 * int: index
1343 * unsigned: mask
1344 * returns: nothing
1345 *=======================================================================*/
1346 static void
1347 verify_constant_pool_type(context_type *context, int index, unsigned mask)
1349 ClassClass *cb = context->class;
1350 union cp_item_type *constant_pool = cbConstantPool(cb);
1351 int nconstants = cbConstantPoolCount(cb);
1352 unsigned char *type_table =
1353 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
1354 unsigned type;
1356 // if ((index <= 0) || (index >= nconstants))
1357 // CCerror(context, "Illegal constant pool index");
1359 type = CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index);
1360 // if ((mask & (1 << type)) == 0)
1361 // CCerror(context, "Illegal type in constant pool");
1365 /*=========================================================================
1366 * Functions for Data Flow Analysis
1367 *=======================================================================*/
1369 /*=========================================================================
1370 * FUNCTION: initialize_dataflow
1371 * OVERVIEW: Initialize for data flow analysis.
1372 * INTERFACE:
1373 * parameters: pointer to the context_type
1374 * returns: nothing
1375 *=======================================================================*/
1376 static void
1377 initialize_dataflow(context_type *context)
1379 instruction_data_type *idata = context->instruction_data;
1380 struct methodblock *mb = context->mb;
1381 fullinfo_type *reg_ptr;
1382 fullinfo_type full_info;
1383 char *p;
1385 /* Initialize the function entry, since we know everything about it. */
1386 idata[0].stack_info.stack_size = 0;
1387 idata[0].stack_info.stack = NULL;
1388 idata[0].register_info.register_count = mb->args_size;
1389 idata[0].register_info.registers = NEW(fullinfo_type, mb->args_size);
1390 idata[0].register_info.mask_count = 0;
1391 idata[0].register_info.masks = NULL;
1392 idata[0].and_flags = 0; /* nothing needed */
1393 idata[0].or_flags = FLAG_REACHED; /* instruction reached */
1394 reg_ptr = idata[0].register_info.registers;
1396 if ((mb->fb.access & ACC_STATIC) == 0) {
1397 /* A non static method. If this is an <init> method, the first
1398 * argument is an uninitialized object. Otherwise it is an object of
1399 * the given class type. java.lang.Object.<init> is special since
1400 * we don't call its superclass <init> method.
1401 */
1402 if (strcmp(mb->fb.name, "<init>") == 0
1403 && context->currentclass_info != context->object_info) {
1404 *reg_ptr++ = MAKE_FULLINFO(ITEM_InitObject, 0, 0);
1405 idata[0].or_flags |= FLAG_NEED_CONSTRUCTOR;
1406 } else {
1407 *reg_ptr++ = context->currentclass_info;
1410 /* Fill in each of the arguments into the registers. */
1411 for (p = mb->fb.signature + 1; *p != SIGNATURE_ENDFUNC; ) {
1412 char fieldchar = signature_to_fieldtype(context, &p, &full_info);
1413 // if (no_floating_point && (fieldchar == 'D' || fieldchar == 'F')) {
1414 // CCerror(context, "Floating point arguments not allowed");
1415 // }
1416 switch (fieldchar) {
1417 case 'D': case 'L':
1418 *reg_ptr++ = full_info;
1419 *reg_ptr++ = full_info + 1;
1420 break;
1421 default:
1422 *reg_ptr++ = full_info;
1423 break;
1426 p++; /* skip over right parenthesis */
1427 if (*p == 'V') {
1428 context->return_type = MAKE_FULLINFO(ITEM_Void, 0, 0);
1429 } else {
1430 signature_to_fieldtype(context, &p, &full_info);
1431 context->return_type = full_info;
1434 /* Indicate that we need to look at the first instruction. */
1435 idata[0].changed = TRUE;
1436 }
1439 /*=========================================================================
1440 * FUNCTION: run_dataflow
1441 * OVERVIEW: Execute the data flow analysis as long as there are things
1442 * to change.
1443 * INTERFACE:
1444 * parameters: pointer to the context_type
1445 * returns: nothing
1446 *=======================================================================*/
1447 static void
1448 run_dataflow(context_type *context) {
1449 struct methodblock *mb = context->mb;
1450 int max_stack_size = mb->maxstack;
1451 instruction_data_type *idata = context->instruction_data;
1452 int icount = context->instruction_count;
1453 bool_t work_to_do = TRUE;
1454 int inumber;
1456 /* Run through the loop, until there is nothing left to do. */
1457 while (work_to_do) {
1458 work_to_do = FALSE;
1459 for (inumber = 0; inumber < icount; inumber++) {
1460 instruction_data_type *this_idata = &idata[inumber];
1461 if (this_idata->changed) {
1462 register_info_type new_register_info;
1463 stack_info_type new_stack_info;
1464 flag_type new_and_flags, new_or_flags;
1466 this_idata->changed = FALSE;
1467 work_to_do = TRUE;
1468 /* Make sure the registers and flags are appropriate */
1469 check_register_values(context, inumber);
1470 check_flags(context, inumber);
1472 /* Make sure the stack can deal with this instruction */
1473 pop_stack(context, inumber, &new_stack_info);
1475 /* Update the registers and flags */
1476 update_registers(context, inumber, &new_register_info);
1477 update_flags(context, inumber, &new_and_flags, &new_or_flags);
1479 /* Update the stack. */
1480 push_stack(context, inumber, &new_stack_info);
1482 // if (new_stack_info.stack_size > max_stack_size)
1483 // CCerror(context, "Stack size too large");
1485 /* Add the new stack and register information to any
1486 * instructions that can follow this instruction. */
1487 merge_into_successors(context, inumber,
1488 &new_register_info, &new_stack_info,
1489 new_and_flags, new_or_flags);
1496 /*=========================================================================
1497 * FUNCTION: check_register_values
1498 * OVERVIEW: Make sure that the registers contain a legitimate value
1499 * for the given instruction.
1500 * INTERFACE:
1501 * parameters: pointer to the context_type
1502 * int inumber
1503 * returns: nothing
1504 *=======================================================================*/
1505 static void
1506 check_register_values(context_type *context, int inumber)
1508 instruction_data_type *idata = context->instruction_data;
1509 instruction_data_type *this_idata = &idata[inumber];
1510 opcode_type opcode = this_idata->opcode;
1511 int operand = this_idata->operand.i;
1512 int register_count = this_idata->register_info.register_count;
1513 fullinfo_type *registers = this_idata->register_info.registers;
1514 bool_t double_word = FALSE; /* default value */
1515 int type;
1517 switch (opcode) {
1518 default:
1519 return;
1520 case opc_iload: case opc_iinc:
1521 type = ITEM_Integer; break;
1522 case opc_fload:
1523 type = ITEM_Float; break;
1524 case opc_aload:
1525 type = ITEM_Object; break;
1526 case opc_ret:
1527 type = ITEM_ReturnAddress; break;
1528 case opc_lload:
1529 type = ITEM_Long; double_word = TRUE; break;
1530 case opc_dload:
1531 type = ITEM_Double; double_word = TRUE; break;
1533 if (!double_word) {
1534 fullinfo_type reg = registers[operand];
1535 /* Make sure we don't have an illegal register or one with wrong type */
1536 if (operand >= register_count) {
1537 CCerror(context,
1538 "Accessing value from uninitialized register %d", operand);
1539 } else if (WITH_ZERO_EXTRA_INFO(reg) == MAKE_FULLINFO(type, 0, 0)) {
1540 /* the register is obviously of the given type */
1541 return;
1542 } else if (GET_INDIRECTION(reg) > 0 && type == ITEM_Object) {
1543 /* address type stuff be used on all arrays */
1544 return;
1545 } else if (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress) {
1546 // CCerror(context, "Cannot load return address from register %d",
1547 // operand);
1548 /* alternatively
1549 (GET_ITEM_TYPE(reg) == ITEM_ReturnAddress)
1550 && (opcode == opc_iload)
1551 && (type == ITEM_Object || type == ITEM_Integer)
1552 but this never occurs
1553 */
1554 } else if (reg == ITEM_InitObject && type == ITEM_Object) {
1555 return;
1556 } else if (WITH_ZERO_EXTRA_INFO(reg) ==
1557 MAKE_FULLINFO(ITEM_NewObject, 0, 0) &&
1558 type == ITEM_Object) {
1559 return;
1560 } else {
1561 // CCerror(context, "Register %d contains wrong type", operand);
1563 } else {
1564 /* Make sure we don't have an illegal register or one with wrong type */
1565 if ((operand + 1) >= register_count) {
1566 // CCerror(context,
1567 // "Accessing value from uninitialized register pair %d/%d",
1568 // operand, operand+1);
1569 } else {
1570 if ((registers[operand] == MAKE_FULLINFO(type, 0, 0)) &&
1571 (registers[operand + 1] == MAKE_FULLINFO(type + 1, 0, 0))) {
1572 return;
1573 } else {
1574 // CCerror(context, "Register pair %d/%d contains wrong type",
1575 // operand, operand+1);
1578 }
1582 /*=========================================================================
1583 * FUNCTION: check_flags
1584 * OVERVIEW: Make sure that the flags contain legitimate values for this
1585 * instruction.
1586 * INTERFACE:
1587 * parameters: pointer to the context_type
1588 * int: instruction number
1589 * returns: nothing
1590 *=======================================================================*/
1591 static void
1592 check_flags(context_type *context, int inumber)
1594 instruction_data_type *idata = context->instruction_data;
1595 instruction_data_type *this_idata = &idata[inumber];
1596 opcode_type opcode = this_idata->opcode;
1600 /*=========================================================================
1601 * FUNCTION: pop_stack
1602 * OVERVIEW: Make sure that the top of the stack contains reasonable
1603 * values for the given instruction. The post-pop values of
1604 * the stack and its size are returned in *new_stack_info.
1605 * INTERFACE:
1606 * parameters: pointer to the context_type
1607 * int: instruction number
1608 * stack_info_type: *new_stack_info
1609 * returns: nothing
1610 *=======================================================================*/
1611 static void
1612 pop_stack(context_type *context, int inumber, stack_info_type *new_stack_info)
1614 instruction_data_type *idata = context->instruction_data;
1615 instruction_data_type *this_idata = &idata[inumber];
1616 opcode_type opcode = this_idata->opcode;
1617 stack_item_type *stack = this_idata->stack_info.stack;
1618 int stack_size = this_idata->stack_info.stack_size;
1619 char *stack_operands, *p;
1620 char buffer[257]; /* for holding manufactured argument lists */
1621 fullinfo_type stack_extra_info_buffer[256]; /* save info popped off stack */
1622 fullinfo_type *stack_extra_info = &stack_extra_info_buffer[256];
1623 fullinfo_type full_info, put_full_info;
1625 switch(opcode) {
1626 default:
1627 /* For most instructions, we just use a built-in table */
1628 stack_operands = opcode_in_out[opcode][0];
1629 break;
1631 case opc_putstatic: case opc_putfield: {
1632 /* The top thing on the stack depends on the signature of
1633 * the object. */
1634 int operand = this_idata->operand.i;
1635 char *signature = cp_index_to_signature(context, operand);
1636 char *ip = buffer;
1638 if (opcode == opc_putfield)
1639 *ip++ = 'A'; /* object for putfield */
1640 *ip++ = signature_to_fieldtype(context, &signature, &put_full_info);
1641 *ip = '\0';
1642 stack_operands = buffer;
1643 break;
1646 case opc_invokevirtual: case opc_invokespecial:
1647 case opc_invokeinit: /* invokespecial call to <init> */
1648 case opc_invokestatic: case opc_invokeinterface: {
1649 /* The top stuff on the stack depends on the method signature */
1650 int operand = this_idata->operand.i;
1651 char *signature = cp_index_to_signature(context, operand);
1652 char *ip = buffer;
1653 char *p;
1655 if (opcode != opc_invokestatic)
1656 /* First, push the object */
1657 *ip++ = (opcode == opc_invokeinit ? '@' : 'A');
1658 for (p = signature + 1; *p != SIGNATURE_ENDFUNC; ) {
1659 *ip++ = signature_to_fieldtype(context, &p, &full_info);
1660 // if (ip >= buffer + sizeof(buffer) - 1)
1661 // CCerror(context, "Signature %s has too many arguments",
1662 // signature);
1664 *ip = 0;
1665 stack_operands = buffer;
1666 break;
1669 case opc_multianewarray: {
1670 /* Count can't be larger than 255. So can't overflow buffer */
1671 int count = this_idata->operand2.i; /* number of ints on stack */
1672 memset(buffer, 'I', count);
1673 buffer[count] = '\0';
1674 stack_operands = buffer;
1675 break;
1678 } /* of switch */
1680 /* Run through the list of operands >>backwards<< */
1681 for ( p = stack_operands + strlen(stack_operands);
1682 p > stack_operands;
1683 stack = stack->next) {
1684 int type = *--p;
1685 fullinfo_type top_type = stack ? stack->item : 0;
1686 int size = (type == 'D' || type == 'L') ? 2 : 1;
1687 *--stack_extra_info = top_type;
1688 // if (stack == NULL)
1689 // CCerror(context, "Unable to pop operand off an empty stack");
1690 switch (type) {
1691 case 'I':
1692 // if (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0))
1693 // CCerror(context, "Expecting to find integer on stack");
1694 break;
1696 case 'F':
1697 // if (top_type != MAKE_FULLINFO(ITEM_Float, 0, 0))
1698 // CCerror(context, "Expecting to find float on stack");
1699 break;
1701 case 'A': /* object or array */
1702 if ( (GET_ITEM_TYPE(top_type) != ITEM_Object)
1703 && (GET_INDIRECTION(top_type) == 0)) {
1704 /* The thing isn't an object or an array. Let's see if it's
1705 * one of the special cases */
1706 if ( (WITH_ZERO_EXTRA_INFO(top_type) ==
1707 MAKE_FULLINFO(ITEM_ReturnAddress, 0, 0))
1708 && (opcode == opc_astore))
1709 break;
1710 if ( (GET_ITEM_TYPE(top_type) == ITEM_NewObject
1711 || (GET_ITEM_TYPE(top_type) == ITEM_InitObject))
1712 && ((opcode == opc_astore) || (opcode == opc_aload)))
1713 break;
1715 /* The 2nd edition VM of the specification allows field
1716 * initializations before the superclass initializer,
1717 * if the field is defined within the current class.
1718 */
1719 if ( (GET_ITEM_TYPE(top_type) == ITEM_InitObject)
1720 && (opcode == opc_putfield)) {
1722 int num_fields;
1723 int key = this_idata->operand.i;
1724 fullinfo_type clazz_info = cp_index_to_class_fullinfo(
1725 context, key, TRUE);
1726 char *name = cp_index_to_fieldname(context, key);
1727 char *signature = cp_index_to_signature(context, key);
1728 unsigned ID = NameAndTypeToHash(name, signature);
1730 ClassClass *calledClass =
1731 object_fullinfo_to_classclass(context, clazz_info);
1732 struct fieldblock *fb;
1733 if (ID == 0) {
1734 /* NameAndTypeToHash returns 0
1735 * if out of memory
1736 */
1737 // CCerror(context, "Out of memory");
1738 break;
1740 num_fields = cbFieldsCount(calledClass);
1741 fb = cbFields(calledClass);
1742 for (; --num_fields >= 0; fb++) {
1743 if (fb->ID == ID) {
1744 break;
1748 if (num_fields != -1) {
1749 top_type = context->currentclass_info;
1750 *stack_extra_info = top_type;
1751 break;
1754 // CCerror(context, "Expecting to find object/array on stack");
1756 break;
1758 case '@': { /* unitialized object, for call to <init> */
1759 int item_type = GET_ITEM_TYPE(top_type);
1760 // if (item_type != ITEM_NewObject && item_type != ITEM_InitObject)
1761 // CCerror(context,
1762 // "Expecting to find unitialized object on stack");
1763 break;
1766 case 'O': /* object, not array */
1767 // if (WITH_ZERO_EXTRA_INFO(top_type) !=
1768 // MAKE_FULLINFO(ITEM_Object, 0, 0))
1769 // CCerror(context, "Expecting to find object on stack");
1770 break;
1772 case 'a': /* integer, object, or array */
1773 // if ( (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0))
1774 // && (GET_ITEM_TYPE(top_type) != ITEM_Object)
1775 // && (GET_INDIRECTION(top_type) == 0))
1776 // CCerror(context,
1777 // "Expecting to find object, array, or int on stack");
1778 break;
1780 case 'D': /* double */
1781 // if (top_type != MAKE_FULLINFO(ITEM_Double, 0, 0))
1782 // CCerror(context, "Expecting to find double on stack");
1783 break;
1785 case 'L': /* long */
1786 // if (top_type != MAKE_FULLINFO(ITEM_Long, 0, 0))
1787 // CCerror(context, "Expecting to find long on stack");
1788 break;
1790 case ']': /* array of some type */
1791 if (top_type == NULL_FULLINFO) {
1792 /* do nothing */
1793 } else switch(p[-1]) {
1794 case 'I': /* array of integers */
1795 // if (top_type != MAKE_FULLINFO(ITEM_Integer, 1, 0) &&
1796 // top_type != NULL_FULLINFO)
1797 // CCerror(context,
1798 // "Expecting to find array of ints on stack");
1799 break;
1801 case 'L': /* array of longs */
1802 // if (top_type != MAKE_FULLINFO(ITEM_Long, 1, 0))
1803 // CCerror(context,
1804 // "Expecting to find array of longs on stack");
1805 break;
1807 case 'F': /* array of floats */
1808 // if (top_type != MAKE_FULLINFO(ITEM_Float, 1, 0))
1809 // CCerror(context,
1810 // "Expecting to find array of floats on stack");
1811 break;
1813 case 'D': /* array of doubles */
1814 // if (top_type != MAKE_FULLINFO(ITEM_Double, 1, 0))
1815 // CCerror(context,
1816 // "Expecting to find array of doubles on stack");
1817 break;
1819 case 'A': { /* array of addresses (arrays or objects) */
1820 // int indirection = GET_INDIRECTION(top_type);
1821 // if ((indirection == 0) ||
1822 // ((indirection == 1) &&
1823 // (GET_ITEM_TYPE(top_type) != ITEM_Object)))
1824 // CCerror(context,
1825 // "Expecting to find array of objects or arrays "
1826 // "on stack");
1827 break;
1830 case 'b': /* array of bytes or boolean */
1831 // if (top_type != MAKE_FULLINFO(ITEM_Byte, 1, 0) &&
1832 // top_type != MAKE_FULLINFO(ITEM_Boolean, 1, 0))
1833 // CCerror(context,
1834 // "Expecting to find array of bytes or booleans on stack");
1835 break;
1837 case 'B': /* array of bytes */
1838 // if (top_type != MAKE_FULLINFO(ITEM_Byte, 1, 0))
1839 // CCerror(context,
1840 // "Expecting to find array of bytes on stack");
1841 break;
1843 case 'Z': /* array of boolean */
1844 // if (top_type != MAKE_FULLINFO(ITEM_Boolean, 1, 0))
1845 // CCerror(context,
1846 // "Expecting to find array of bytes on stack");
1847 break;
1849 case 'C': /* array of characters */
1850 // if (top_type != MAKE_FULLINFO(ITEM_Char, 1, 0))
1851 // CCerror(context,
1852 // "Expecting to find array of chars on stack");
1853 break;
1855 case 'S': /* array of shorts */
1856 // if (top_type != MAKE_FULLINFO(ITEM_Short, 1, 0))
1857 // CCerror(context,
1858 // "Expecting to find array of shorts on stack");
1859 break;
1861 case '?': /* any type of array is okay */
1862 // if (GET_INDIRECTION(top_type) == 0)
1863 // CCerror(context,
1864 // "Expecting to find array on stack");
1865 break;
1867 default:
1868 // CCerror(context, "Internal error #1");
1869 sysAssert(FALSE);
1870 break;
1872 p -= 2; /* skip over [ <char> */
1873 break;
1875 case '1': case '2': case '3': case '4': /* stack swapping */
1876 if (top_type == MAKE_FULLINFO(ITEM_Double, 0, 0)
1877 || top_type == MAKE_FULLINFO(ITEM_Long, 0, 0)) {
1878 if ((p > stack_operands) && (p[-1] == '+')) {
1879 context->swap_table[type - '1'] = top_type + 1;
1880 context->swap_table[p[-2] - '1'] = top_type;
1881 size = 2;
1882 p -= 2;
1883 } else {
1884 // CCerror(context,
1885 // "Attempt to split long or double on the stack");
1887 } else {
1888 context->swap_table[type - '1'] = stack->item;
1889 if ((p > stack_operands) && (p[-1] == '+'))
1890 p--; /* ignore */
1892 break;
1893 case '+': /* these should have been caught. */
1894 default:
1895 // CCerror(context, "Internal error #2");
1896 sysAssert(FALSE);
1898 stack_size -= size;
1901 /* For many of the opcodes that had an "A" in their field, we really
1902 * need to go back and do a little bit more accurate testing. We can, of
1903 * course, assume that the minimal type checking has already been done.
1904 */
1905 switch (opcode) {
1906 default: break;
1907 case opc_aastore: { /* array index object */
1908 fullinfo_type array_type = stack_extra_info[0];
1909 fullinfo_type object_type = stack_extra_info[2];
1910 fullinfo_type target_type = decrement_indirection(array_type);
1911 if (array_type == NULL_FULLINFO) {
1912 break;
1914 if ((WITH_ZERO_EXTRA_INFO(target_type) ==
1915 MAKE_FULLINFO(ITEM_Object, 0, 0)) &&
1916 (WITH_ZERO_EXTRA_INFO(object_type) ==
1917 MAKE_FULLINFO(ITEM_Object, 0, 0))) {
1918 /* I disagree. But other's seem to think that we should allow
1919 * an assignment of any Object to any array of any Object type.
1920 * There will be an runtime error if the types are wrong.
1921 */
1922 break;
1924 // if (!isAssignableTo(context, object_type, target_type))
1925 // CCerror(context, "Incompatible types for storing into array of "
1926 // "arrays or objects");
1927 break;
1930 case opc_putfield:
1931 case opc_getfield:
1932 case opc_putstatic: {
1933 int operand = this_idata->operand.i;
1934 fullinfo_type stack_object = stack_extra_info[0];
1935 if (opcode == opc_putfield || opcode == opc_getfield) {
1936 if (!isAssignableTo(context,
1937 stack_object,
1938 cp_index_to_class_fullinfo(context, operand,
1939 TRUE))) {
1940 // CCerror(context,
1941 // "Incompatible type for getting or setting field");
1943 /* FY: Why is this commented out?? */
1944 /*
1945 if (this_idata->protected &&
1946 !isAssignableTo(context, stack_object,
1947 context->currentclass_info)) {
1948 CCerror(context, "Bad access to protected data");
1949 }*/
1951 if (opcode == opc_putfield || opcode == opc_putstatic) {
1952 int item = (opcode == opc_putfield ? 1 : 0);
1953 if (!isAssignableTo(context,
1954 stack_extra_info[item], put_full_info)) {
1955 // CCerror(context, "Bad type in putfield/putstatic");
1958 break;
1961 case opc_athrow:
1962 // if (!isAssignableTo(context, stack_extra_info[0],
1963 // context->throwable_info)) {
1964 // CCerror(context, "Can only throw Throwable objects");
1965 // }
1966 break;
1968 case opc_aaload: { /* array index */
1969 /* We need to pass the information to the stack updater */
1970 fullinfo_type array_type = stack_extra_info[0];
1971 context->swap_table[0] = decrement_indirection(array_type);
1972 break;
1975 case opc_invokevirtual: case opc_invokespecial:
1976 case opc_invokeinit:
1977 case opc_invokeinterface: case opc_invokestatic: {
1978 int operand = this_idata->operand.i;
1979 char *signature = cp_index_to_signature(context, operand);
1980 int item;
1981 char *p;
1982 if (opcode == opc_invokestatic) {
1983 item = 0;
1984 } else if (opcode == opc_invokeinit) {
1985 fullinfo_type init_type = this_idata->operand2.fi;
1986 fullinfo_type object_type = stack_extra_info[0];
1987 context->swap_table[0] = object_type; /* save value */
1988 if (GET_ITEM_TYPE(stack_extra_info[0]) == ITEM_NewObject) {
1989 /* We better be calling the appropriate init. Find the
1990 * inumber of the "opc_new" instruction", and figure
1991 * out what the type really is.
1992 */
1993 int new_inumber = GET_EXTRA_INFO(stack_extra_info[0]);
1994 fullinfo_type target_type = idata[new_inumber].operand2.fi;
1995 context->swap_table[1] = target_type;
1996 // if (target_type != init_type) {
1997 // CCerror(context, "Call to wrong initialization method");
1998 // }
1999 } else {
2000 /* We better be calling super() or this(). */
2001 if (init_type != context->superclass_info &&
2002 init_type != context->currentclass_info) {
2003 // CCerror(context, "Call to wrong initialization method");
2005 context->swap_table[1] = context->currentclass_info;
2007 item = 1;
2008 } else {
2009 fullinfo_type target_type = this_idata->operand2.fi;
2010 fullinfo_type object_type = stack_extra_info[0];
2011 if (!isAssignableTo(context, object_type, target_type)){
2012 // CCerror(context,
2013 // "Incompatible object argument for function call");
2015 /* The specification of the structural constraints for
2016 * invokespecial needs to be more stringent.
2018 * If invokespecial is used to invoke an instance method
2019 * that is not an instance initialization method, then the
2020 * type of the class instance, which is the target of method
2021 * invocation, must be assignment compatible with the
2022 * current class.
2023 */
2024 if (opcode == opc_invokespecial
2025 && !isAssignableTo(context, object_type,
2026 context->currentclass_info)) {
2027 /* Make sure object argument is assignment compatible
2028 * to current class
2029 */
2030 // CCerror(context,
2031 // "Incompatible object argument for invokespecial");
2034 if (this_idata->protected
2035 && !isAssignableTo(context, object_type,
2036 context->currentclass_info)) {
2037 /* This is ugly. Special dispensation. Arrays pretend to
2038 implement public Object clone() even though they don't */
2039 if ((target_type == context->object_info) &&
2040 (GET_INDIRECTION(object_type) > 0) &&
2041 (strcmp(cp_index_to_fieldname(context, this_idata->operand.i),
2042 "clone") == 0)) {
2043 } else {
2044 // CCerror(context, "Bad access to protected data");
2047 item = 1;
2049 for (p = signature + 1; *p != SIGNATURE_ENDFUNC; item++)
2050 if (signature_to_fieldtype(context, &p, &full_info) == 'A') {
2051 if (!isAssignableTo(context,
2052 stack_extra_info[item], full_info)) {
2053 // CCerror(context, "Incompatible argument to function");
2057 break;
2060 case opc_return:
2061 // if (context->return_type != MAKE_FULLINFO(ITEM_Void, 0, 0))
2062 // CCerror(context, "Wrong return type in function");
2063 break;
2065 case opc_ireturn: case opc_lreturn: case opc_freturn:
2066 case opc_dreturn: case opc_areturn: {
2067 fullinfo_type target_type = context->return_type;
2068 fullinfo_type object_type = stack_extra_info[0];
2069 if (!isAssignableTo(context, object_type, target_type)) {
2070 // CCerror(context, "Wrong return type in function");
2072 break;
2075 case opc_new: {
2076 /* Make sure that nothing on the stack already looks like what
2077 * we want to create. I can't image how this could possibly happen
2078 * but we should test for it anyway, since if it could happen, the
2079 * result would be an unitialized object being able to masquerade
2080 * as an initialized one.
2081 */
2082 stack_item_type *item;
2083 for (item = stack; item != NULL; item = item->next) {
2084 // if (item->item == this_idata->operand.fi) {
2085 // CCerror(context,
2086 // "Uninitialized object on stack at creating point");
2087 // }
2089 /* Info for update_registers */
2090 context->swap_table[0] = this_idata->operand.fi;
2091 context->swap_table[1] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2093 break;
2096 new_stack_info->stack = stack;
2097 new_stack_info->stack_size = stack_size;
2101 /*=========================================================================
2102 * FUNCTION: update_registers
2103 * OVERVIEW: Perform the operation on the registers, and return the
2104 * updated results in new_register_count_p and new_registers.
2105 * Note that the instruction has already been determined
2106 * to be legal.
2107 * INTERFACE:
2108 * parameters: pointer to the context_type
2109 * int: instruction number
2110 * register_info_type: pointer to new register info
2112 * returns: nothing
2113 *=======================================================================*/
2114 static void
2115 update_registers(context_type *context, int inumber,
2116 register_info_type *new_register_info)
2118 instruction_data_type *idata = context->instruction_data;
2119 instruction_data_type *this_idata = &idata[inumber];
2120 opcode_type opcode = this_idata->opcode;
2121 int operand = this_idata->operand.i;
2122 int register_count = this_idata->register_info.register_count;
2123 fullinfo_type *registers = this_idata->register_info.registers;
2124 stack_item_type *stack = this_idata->stack_info.stack;
2125 int mask_count = this_idata->register_info.mask_count;
2126 mask_type *masks = this_idata->register_info.masks;
2128 /* Use these as default new values. */
2129 int new_register_count = register_count;
2130 int new_mask_count = mask_count;
2131 fullinfo_type *new_registers = registers;
2132 mask_type *new_masks = masks;
2134 enum { NONE, SINGLE, DOUBLE } access = NONE;
2135 int i;
2137 /* Remember, we've already verified the type at the top of the stack. */
2138 switch (opcode) {
2139 default: break;
2140 case opc_istore: case opc_fstore: case opc_astore:
2141 access = SINGLE;
2142 goto continue_store;
2144 case opc_lstore: case opc_dstore:
2145 access = DOUBLE;
2146 goto continue_store;
2148 continue_store: {
2149 /* We have a modification to the registers. Copy them if needed. */
2150 fullinfo_type stack_top_type = stack->item;
2151 int max_operand = operand + ((access == DOUBLE) ? 1 : 0);
2153 if ( max_operand < register_count
2154 && registers[operand] == stack_top_type
2155 && ((access == SINGLE) ||
2156 (registers[operand + 1]== stack_top_type + 1)))
2157 /* No changes have been made to the registers. */
2158 break;
2159 new_register_count = MAX(max_operand + 1, register_count);
2160 new_registers = NEW(fullinfo_type, new_register_count);
2161 for (i = 0; i < register_count; i++)
2162 new_registers[i] = registers[i];
2163 for (i = register_count; i < new_register_count; i++)
2164 new_registers[i] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2165 new_registers[operand] = stack_top_type;
2166 if (access == DOUBLE)
2167 new_registers[operand + 1] = stack_top_type + 1;
2168 break;
2171 case opc_iload: case opc_fload: case opc_aload:
2172 case opc_iinc: case opc_ret:
2173 access = SINGLE;
2174 break;
2176 case opc_lload: case opc_dload:
2177 access = DOUBLE;
2178 break;
2180 case opc_jsr: case opc_jsr_w:
2181 for (i = 0; i < new_mask_count; i++)
2182 if (new_masks[i].entry == operand)
2183 CCerror(context, "Recursive call to jsr entry");
2184 if (context->redoJsr
2185 && this_idata->operand2.i == UNKNOWN_RET_INSTRUCTION) {
2186 /* Do nothing */
2187 } else {
2188 new_masks = add_to_masks(context, masks, mask_count, operand);
2189 new_mask_count++;
2191 break;
2193 case opc_invokeinit:
2194 case opc_new: {
2195 /* For invokeinit, an uninitialized object has been initialized.
2196 * For new, all previous occurrences of an uninitialized object
2197 * from the same instruction must be made bogus.
2198 * We find all occurrences of swap_table[0] in the registers, and
2199 * replace them with swap_table[1];
2200 */
2201 fullinfo_type from = context->swap_table[0];
2202 fullinfo_type to = context->swap_table[1];
2204 int i;
2205 for (i = 0; i < register_count; i++) {
2206 if (new_registers[i] == from) {
2207 /* Found a match */
2208 break;
2211 if (i < register_count) { /* We broke out loop for match */
2212 /* We have to change registers, and possibly a mask */
2213 bool_t copied_mask = FALSE;
2214 int k;
2215 new_registers = NEW(fullinfo_type, register_count);
2216 memcpy(new_registers, registers,
2217 register_count * sizeof(registers[0]));
2218 for ( ; i < register_count; i++) {
2219 if (new_registers[i] == from) {
2220 new_registers[i] = to;
2221 for (k = 0; k < new_mask_count; k++) {
2222 if (!IS_BIT_SET(new_masks[k].modifies, i)) {
2223 if (!copied_mask) {
2224 new_masks = copy_masks(context, new_masks,
2225 mask_count);
2226 copied_mask = TRUE;
2228 SET_BIT(new_masks[k].modifies, i);
2234 break;
2235 }
2236 } /* of switch */
2238 if ((access != NONE) && (new_mask_count > 0)) {
2239 int i, j;
2240 for (i = 0; i < new_mask_count; i++) {
2241 int *mask = new_masks[i].modifies;
2242 if ((!IS_BIT_SET(mask, operand)) ||
2243 ((access == DOUBLE) && !IS_BIT_SET(mask, operand + 1))) {
2244 new_masks = copy_masks(context, new_masks, mask_count);
2245 for (j = i; j < new_mask_count; j++) {
2246 SET_BIT(new_masks[j].modifies, operand);
2247 if (access == DOUBLE)
2248 SET_BIT(new_masks[j].modifies, operand + 1);
2249 }
2250 break;
2255 new_register_info->register_count = new_register_count;
2256 new_register_info->registers = new_registers;
2257 new_register_info->masks = new_masks;
2258 new_register_info->mask_count = new_mask_count;
2262 /*=========================================================================
2263 * FUNCTION: update_flags
2264 * OVERVIEW: Update the flags now that we have already determined
2265 * the instruction to be legal and have already updated the
2266 * registers.
2267 * INTERFACE:
2268 * parameters: pointer to the context_type
2269 * int: instruction number
2270 * flag_type: pointer to new_and_flags
2271 * flag_type: pointer to new_or_flags
2273 * returns: nothing
2274 *=======================================================================*/
2275 static void
2276 update_flags(context_type *context, int inumber,
2277 flag_type *new_and_flags, flag_type *new_or_flags)
2280 instruction_data_type *idata = context->instruction_data;
2281 instruction_data_type *this_idata = &idata[inumber];
2282 flag_type and_flags = this_idata->and_flags;
2283 flag_type or_flags = this_idata->or_flags;
2285 /* Set the "we've done a constructor" flag */
2286 if (this_idata->opcode == opc_invokeinit) {
2287 fullinfo_type from = context->swap_table[0];
2288 if (from == MAKE_FULLINFO(ITEM_InitObject, 0, 0))
2289 and_flags |= FLAG_CONSTRUCTED;
2291 *new_and_flags = and_flags;
2292 *new_or_flags = or_flags;
2296 /*=========================================================================
2297 * FUNCTION: push_stack
2298 * OVERVIEW: Perform the operation on the stack.
2299 * Note that the instruction has already been determined
2300 * to be legal.
2301 * new_stack_size_p and new_stack_p point to the results after
2302 * the pops have already been done. Do the pushes, and then
2303 * put the results back there.
2304 * INTERFACE:
2305 * parameters: pointer to the context_type
2306 * int: instruction number
2307 * stack_info_type: pointer to new stack info
2309 * returns: nothing
2310 *=======================================================================*/
2311 static void
2312 push_stack(context_type *context, int inumber, stack_info_type *new_stack_info)
2314 instruction_data_type *idata = context->instruction_data;
2315 instruction_data_type *this_idata = &idata[inumber];
2316 opcode_type opcode = this_idata->opcode;
2317 int operand = this_idata->operand.i;
2319 int stack_size = new_stack_info->stack_size;
2320 stack_item_type *stack = new_stack_info->stack;
2321 char *stack_results;
2323 fullinfo_type full_info = 0;
2324 char buffer[5], *p; /* actually [2] is big enough */
2326 /* We need to look at all those opcodes in which either we can't tell the
2327 * value pushed onto the stack from the opcode, or in which the value
2328 * pushed onto the stack is an object or array. For the latter, we need
2329 * to make sure that full_info is set to the right value.
2330 */
2331 switch(opcode) {
2332 default:
2333 stack_results = opcode_in_out[opcode][1];
2334 break;
2336 case opc_ldc: case opc_ldc_w: case opc_ldc2_w: {
2337 /* Look to constant pool to determine correct result. */
2338 union cp_item_type *cp = cbConstantPool(context->class);
2339 unsigned char *type_table = cp[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
2340 switch (CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, operand)) {
2341 case CONSTANT_Integer:
2342 stack_results = "I"; break;
2343 case CONSTANT_Float:
2344 stack_results = "F"; break;
2345 case CONSTANT_Double:
2346 stack_results = "D"; break;
2347 case CONSTANT_Long:
2348 stack_results = "L"; break;
2349 case CONSTANT_String:
2350 stack_results = "A";
2351 full_info = context->string_info;
2352 break;
2353 default:
2354 // CCerror(context, "Internal error #3");
2355 sysAssert(FALSE);
2357 break;
2360 case opc_getstatic: case opc_getfield: {
2361 /* Look to signature to determine correct result. */
2362 int operand = this_idata->operand.i;
2363 char *signature = cp_index_to_signature(context, operand);
2364 #ifdef DEBUG_VERIFIER
2365 if (verify_verbose) {
2366 print_formatted_fieldname(context, operand);
2368 #endif
2369 buffer[0] = signature_to_fieldtype(context, &signature, &full_info);
2370 buffer[1] = '\0';
2371 stack_results = buffer;
2372 break;
2375 case opc_invokevirtual: case opc_invokespecial:
2376 case opc_invokeinit:
2377 case opc_invokestatic: case opc_invokeinterface: {
2378 /* Look to signature to determine correct result. */
2379 int operand = this_idata->operand.i;
2380 char *signature = cp_index_to_signature(context, operand);
2381 char *result_signature = strchr(signature, SIGNATURE_ENDFUNC) + 1;
2382 if (result_signature[0] == SIGNATURE_VOID) {
2383 stack_results = "";
2384 } else {
2385 buffer[0] = signature_to_fieldtype(context, &result_signature,
2386 &full_info);
2387 buffer[1] = '\0';
2388 stack_results = buffer;
2390 break;
2393 case opc_aconst_null:
2394 stack_results = opcode_in_out[opcode][1];
2395 full_info = NULL_FULLINFO; /* special NULL */
2396 break;
2398 case opc_new:
2399 case opc_checkcast:
2400 case opc_newarray:
2401 case opc_anewarray:
2402 case opc_multianewarray:
2403 stack_results = opcode_in_out[opcode][1];
2404 /* Conventionally, this result type is stored here */
2405 full_info = this_idata->operand.fi;
2406 if (no_floating_point && (opcode == opc_newarray)
2407 && (full_info == MAKE_FULLINFO(ITEM_Float, 1, 0) ||
2408 full_info == MAKE_FULLINFO(ITEM_Double, 1, 0))) {
2409 // CCerror(context, "Cannot create floating point array");
2411 break;
2413 case opc_aaload:
2414 stack_results = opcode_in_out[opcode][1];
2415 /* pop_stack() saved value for us. */
2416 full_info = context->swap_table[0];
2417 break;
2419 case opc_aload:
2420 stack_results = opcode_in_out[opcode][1];
2421 /* The register hasn't been modified, so we can use its value. */
2422 full_info = this_idata->register_info.registers[operand];
2423 break;
2424 } /* of switch */
2426 for (p = stack_results; *p != 0; p++) {
2427 int type = *p;
2428 stack_item_type *new_item = NEW(stack_item_type, 1);
2429 new_item->next = stack;
2430 stack = new_item;
2431 switch (type) {
2432 case 'I':
2433 stack->item = MAKE_FULLINFO(ITEM_Integer, 0, 0); break;
2434 case 'F':
2435 // if (no_floating_point) {
2436 // CCerror(context, "Floating point result not allowed");
2437 // }
2438 stack->item = MAKE_FULLINFO(ITEM_Float, 0, 0);
2439 break;
2440 case 'D':
2441 // if (no_floating_point) {
2442 // CCerror(context, "Floating point result not allowed");
2443 // }
2444 stack->item = MAKE_FULLINFO(ITEM_Double, 0, 0);
2445 stack_size++;
2446 break;
2447 case 'L':
2448 stack->item = MAKE_FULLINFO(ITEM_Long, 0, 0);
2449 stack_size++; break;
2450 case 'R':
2451 stack->item = MAKE_FULLINFO(ITEM_ReturnAddress, 0, operand);
2452 break;
2453 case '1': case '2': case '3': case '4': {
2454 /* Get the info saved in the swap_table */
2455 fullinfo_type stype = context->swap_table[type - '1'];
2456 stack->item = stype;
2457 if (stype == MAKE_FULLINFO(ITEM_Long, 0, 0) ||
2458 stype == MAKE_FULLINFO(ITEM_Double, 0, 0)) {
2459 stack_size++; p++;
2461 break;
2463 case 'A':
2464 /* full_info should have the appropriate value. */
2465 sysAssert(full_info != 0);
2466 stack->item = full_info;
2467 break;
2468 default:
2469 // CCerror(context, "Internal error #4");
2470 sysAssert(FALSE);
2472 } /* switch type */
2473 stack_size++;
2474 } /* outer for loop */
2476 if (opcode == opc_invokeinit) {
2477 /* If there are any instances of "from" on the stack, we need to
2478 * replace it with "to", since calling <init> initializes all versions
2479 * of the object, obviously. */
2480 fullinfo_type from = context->swap_table[0];
2481 stack_item_type *ptr;
2482 for (ptr = stack; ptr != NULL; ptr = ptr->next) {
2483 if (ptr->item == from) {
2484 fullinfo_type to = context->swap_table[1];
2485 stack = copy_stack(context, stack);
2486 for (ptr = stack; ptr != NULL; ptr = ptr->next)
2487 if (ptr->item == from) ptr->item = to;
2488 break;
2493 new_stack_info->stack_size = stack_size;
2494 new_stack_info->stack = stack;
2498 /*=========================================================================
2499 * FUNCTION: merge_into_successors
2500 * OVERVIEW: Executed an instruction, and have determined the new
2501 * registers and stack values. Look at all of the possibly
2502 * subsequent instructions, and merge this stack value into
2503 * theirs.
2504 * INTERFACE:
2505 * parameters: pointer to the context_type
2506 * int: instruction number
2507 * stack_info_type: pointer to stack_info
2508 * flag_type: and_flags
2509 * flag_type: or_flags
2511 * returns: nothing
2512 *=======================================================================*/
2513 static void
2514 merge_into_successors(context_type *context, int inumber,
2515 register_info_type *register_info,
2516 stack_info_type *stack_info,
2517 flag_type and_flags, flag_type or_flags)
2519 instruction_data_type *idata = context->instruction_data;
2520 instruction_data_type *this_idata = &idata[inumber];
2521 opcode_type opcode = this_idata->opcode;
2522 int operand = this_idata->operand.i;
2523 struct handler_info_type *handler_info = context->handler_info;
2524 int handler_info_length = context->mb->exception_table_length;
2527 int buffer[2]; /* default value for successors */
2528 int *successors = buffer; /* table of successors */
2529 int successors_count;
2530 int i;
2532 switch (opcode) {
2533 default:
2534 successors_count = 1;
2535 buffer[0] = inumber + 1;
2536 break;
2538 case opc_ifeq: case opc_ifne: case opc_ifgt:
2539 case opc_ifge: case opc_iflt: case opc_ifle:
2540 case opc_ifnull: case opc_ifnonnull:
2541 case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpgt:
2542 case opc_if_icmpge: case opc_if_icmplt: case opc_if_icmple:
2543 case opc_if_acmpeq: case opc_if_acmpne:
2544 successors_count = 2;
2545 buffer[0] = inumber + 1;
2546 buffer[1] = operand;
2547 idata[operand].is_target = TRUE; /* inlinejsr */
2548 break;
2550 case opc_jsr: case opc_jsr_w:
2551 if (this_idata->operand2.i != UNKNOWN_RET_INSTRUCTION)
2552 idata[this_idata->operand2.i].changed = TRUE;
2553 /* FALLTHROUGH */
2554 case opc_goto: case opc_goto_w:
2555 successors_count = 1;
2556 buffer[0] = operand;
2557 idata[operand].is_target = TRUE; /* inlinejsr */
2558 break;
2561 case opc_ireturn: case opc_lreturn: case opc_return:
2562 case opc_freturn: case opc_dreturn: case opc_areturn:
2563 case opc_athrow:
2564 /* The testing for the returns is handled in pop_stack() */
2565 successors_count = 0;
2566 break;
2568 case opc_ret: {
2569 /* This is slightly slow, but good enough for a seldom used instruction.
2570 * The EXTRA_ITEM_INFO of the ITEM_ReturnAddress indicates the
2571 * address of the first instruction of the subroutine. We can return
2572 * to 1 after any instruction that jsr's to that instruction.
2573 */
2574 if (this_idata->operand2.ip == NULL) {
2575 fullinfo_type *registers = this_idata->register_info.registers;
2576 int called_instruction = GET_EXTRA_INFO(registers[operand]);
2577 int i, count, *ptr;;
2578 for (i = context->instruction_count, count = 0; --i >= 0; ) {
2579 if (((idata[i].opcode == opc_jsr) ||
2580 (idata[i].opcode == opc_jsr_w)) &&
2581 (idata[i].operand.i == called_instruction))
2582 count++;
2584 this_idata->operand2.ip = ptr = NEW(int, count + 1);
2585 *ptr++ = count;
2586 for (i = context->instruction_count, count = 0; --i >= 0; ) {
2587 if (((idata[i].opcode == opc_jsr) ||
2588 (idata[i].opcode == opc_jsr_w)) &&
2589 (idata[i].operand.i == called_instruction)) {
2590 *ptr++ = i + 1;
2591 idata[i + 1].is_target = TRUE; /* inlinejsr */
2595 successors = this_idata->operand2.ip; /* use this instead */
2596 successors_count = *successors++;
2597 break;
2601 case opc_tableswitch:
2602 case opc_lookupswitch: {
2603 int i;
2604 successors = this_idata->operand.ip; /* use this instead */
2605 successors_count = *successors++;
2606 for (i = 0; i < successors_count; i++) {
2607 idata[successors[i]].is_target = TRUE; /* inlinejsr */
2609 break;
2616 handler_info = context->handler_info;
2617 for (i = handler_info_length; --i >= 0; handler_info++) {
2618 if (handler_info->start <= inumber && handler_info->end > inumber) {
2619 int handler = handler_info->handler;
2620 idata[handler].is_target = TRUE; /* inlinejsr */
2621 if (opcode != opc_invokeinit) {
2622 merge_into_one_successor(context, inumber, handler,
2623 &this_idata->register_info, /* old */
2624 &handler_info->stack_info,
2625 (flag_type) (and_flags
2626 & this_idata->and_flags),
2627 (flag_type) (or_flags
2628 | this_idata->or_flags),
2629 TRUE);
2630 } else {
2631 /* We need to be a little bit more careful with this
2632 * instruction. Things could either be in the state before
2633 * the instruction or in the state afterwards */
2634 fullinfo_type from = context->swap_table[0];
2635 flag_type temp_or_flags = or_flags;
2636 if (from == MAKE_FULLINFO(ITEM_InitObject, 0, 0))
2637 temp_or_flags |= FLAG_NO_RETURN;
2638 merge_into_one_successor(context, inumber, handler,
2639 &this_idata->register_info, /* old */
2640 &handler_info->stack_info,
2641 this_idata->and_flags,
2642 this_idata->or_flags,
2643 TRUE);
2644 merge_into_one_successor(context, inumber, handler,
2645 register_info,
2646 &handler_info->stack_info,
2647 and_flags, temp_or_flags, TRUE);
2651 for (i = 0; i < successors_count; i++) {
2652 int target = successors[i];
2653 // if (target >= context->instruction_count)
2654 /// CCerror(context, "Falling off the end of the code");
2655 merge_into_one_successor(context, inumber, target,
2656 register_info, stack_info, and_flags, or_flags,
2657 FALSE);
2662 /*=========================================================================
2663 * FUNCTION: merge_into_one_successor
2664 * OVERVIEW: Executed an instruction, and have determined a new
2665 * set of registers and stack values for a given instruction.
2666 * Merge this new set into the values that are already there.
2667 * INTERFACE:
2668 * parameters: pointer to the context_type
2669 * int: instruction number
2670 * stack_info_type: pointer to stack_info
2671 * flag_type: new_and_flags
2672 * flag_type: new_or_flags
2673 * boolean type: isException
2675 * returns: nothing
2676 *=======================================================================*/
2677 static void
2678 merge_into_one_successor(context_type *context,
2679 int from_inumber, int to_inumber,
2680 register_info_type *new_register_info,
2681 stack_info_type *new_stack_info,
2682 flag_type new_and_flags, flag_type new_or_flags,
2683 bool_t isException)
2685 instruction_data_type *idata = context->instruction_data;
2686 register_info_type register_info_buf;
2687 stack_info_type stack_info_buf;
2688 instruction_data_type *this_idata = &idata[to_inumber];
2691 /* All uninitialized objects are set to "bogus" when jsr and
2692 * ret are executed. Thus uninitialized objects can't propagate
2693 * into or out of a subroutine.
2694 */
2695 if (idata[from_inumber].opcode == opc_ret ||
2696 idata[from_inumber].opcode == opc_jsr ||
2697 idata[from_inumber].opcode == opc_jsr_w) {
2698 int new_register_count = new_register_info->register_count;
2699 fullinfo_type *new_registers = new_register_info->registers;
2700 int i;
2701 stack_item_type *item;
2703 for (item = new_stack_info->stack; item != NULL; item = item->next) {
2704 if (GET_ITEM_TYPE(item->item) == ITEM_NewObject) {
2705 /* This check only succeeds for hand-contrived code.
2706 * Efficiency is not an issue.
2707 */
2708 stack_info_buf.stack = copy_stack(context,
2709 new_stack_info->stack);
2710 stack_info_buf.stack_size = new_stack_info->stack_size;
2711 new_stack_info = &stack_info_buf;
2712 for (item = new_stack_info->stack; item != NULL;
2713 item = item->next) {
2714 if (GET_ITEM_TYPE(item->item) == ITEM_NewObject) {
2715 item->item = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2718 break;
2721 for (i = 0; i < new_register_count; i++) {
2722 if (GET_ITEM_TYPE(new_registers[i]) == ITEM_NewObject) {
2723 /* This check only succeeds for hand-contrived code.
2724 * Efficiency is not an issue.
2725 */
2726 fullinfo_type *new_set = NEW(fullinfo_type,
2727 new_register_count);
2728 for (i = 0; i < new_register_count; i++) {
2729 fullinfo_type t = new_registers[i];
2730 new_set[i] = GET_ITEM_TYPE(t) != ITEM_NewObject ?
2731 t : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2733 register_info_buf.register_count = new_register_count;
2734 register_info_buf.registers = new_set;
2735 register_info_buf.mask_count = new_register_info->mask_count;
2736 register_info_buf.masks = new_register_info->masks;
2737 new_register_info = &register_info_buf;
2738 break;
2743 /* Returning from a subroutine is somewhat ugly. The actual thing
2744 * that needs to get merged into the new instruction is a joining
2745 * of info from the ret instruction with stuff in the jsr instruction
2746 */
2747 if (idata[from_inumber].opcode == opc_ret && !isException) {
2748 int new_register_count = new_register_info->register_count;
2749 fullinfo_type *new_registers = new_register_info->registers;
2750 int new_mask_count = new_register_info->mask_count;
2751 mask_type *new_masks = new_register_info->masks;
2752 int operand = idata[from_inumber].operand.i;
2753 int called_instruction = GET_EXTRA_INFO(new_registers[operand]);
2754 instruction_data_type *jsr_idata = &idata[to_inumber - 1];
2755 register_info_type *jsr_reginfo = &jsr_idata->register_info;
2756 if (jsr_idata->operand2.i != from_inumber) {
2757 // if (jsr_idata->operand2.i != UNKNOWN_RET_INSTRUCTION)
2758 // CCerror(context, "Multiple returns to single jsr");
2759 jsr_idata->operand2.i = from_inumber;
2761 if (jsr_reginfo->register_count == UNKNOWN_REGISTER_COUNT) {
2762 /* We don't want to handle the returned-to instruction until
2763 * we've dealt with the jsr instruction. When we get to the
2764 * jsr instruction (if ever), we'll re-mark the ret instruction
2765 */
2767 } else {
2768 int register_count = jsr_reginfo->register_count;
2769 fullinfo_type *registers = jsr_reginfo->registers;
2770 int max_registers = MAX(register_count, new_register_count);
2771 fullinfo_type *new_set = NEW(fullinfo_type, max_registers);
2772 int *return_mask;
2773 struct register_info_type new_new_register_info;
2774 int i;
2775 /* Make sure the place we're returning from is legal! */
2776 for (i = new_mask_count; --i >= 0; )
2777 if (new_masks[i].entry == called_instruction)
2778 break;
2779 // if (i < 0)
2780 // CCerror(context, "Illegal return from subroutine");
2781 /* pop the masks down to the indicated one. Remember the mask
2782 * we're popping off. */
2783 return_mask = new_masks[i].modifies;
2784 new_mask_count = i;
2785 for (i = 0; i < max_registers; i++) {
2786 if (IS_BIT_SET(return_mask, i))
2787 new_set[i] = i < new_register_count ?
2788 new_registers[i] : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2789 else
2790 new_set[i] = i < register_count ?
2791 registers[i] : MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2793 new_new_register_info.register_count = max_registers;
2794 new_new_register_info.registers = new_set;
2795 new_new_register_info.mask_count = new_mask_count;
2796 new_new_register_info.masks = new_masks;
2798 merge_stack(context, to_inumber - 1, to_inumber, new_stack_info);
2799 merge_registers(context, to_inumber - 1, to_inumber,
2800 &new_new_register_info);
2801 /* ADDED FOR JSR_INFO. Is this correct?? */
2802 merge_flags(context, from_inumber, to_inumber,
2803 new_and_flags, new_or_flags);
2805 } else {
2806 merge_stack(context, from_inumber, to_inumber, new_stack_info);
2807 merge_registers(context, from_inumber, to_inumber, new_register_info);
2808 merge_flags(context, from_inumber, to_inumber,
2809 new_and_flags, new_or_flags);
2816 /*=========================================================================
2817 * FUNCTION: merge_stack
2818 * OVERVIEW: Used by merge_into_one_successor() for merging stack values
2819 * from a given instruction to another specified instruction.
2820 * INTERFACE:
2821 * parameters: pointer to the context_type
2822 * int: from instruction number
2823 * int: to instruction number
2824 * stack_info_type: pointer to new_stack_info
2826 * returns: nothing
2827 *=======================================================================*/
2828 static void
2829 merge_stack(context_type *context, int from_inumber, int to_inumber,
2830 stack_info_type *new_stack_info)
2832 instruction_data_type *idata = context->instruction_data;
2833 instruction_data_type *this_idata = &idata[to_inumber];
2835 int new_stack_size = new_stack_info->stack_size;
2836 stack_item_type *new_stack = new_stack_info->stack;
2838 int stack_size = this_idata->stack_info.stack_size;
2840 if (stack_size == UNKNOWN_STACK_SIZE) {
2841 /* First time at this instruction. Just copy. */
2842 this_idata->stack_info.stack_size = new_stack_size;
2843 this_idata->stack_info.stack = new_stack;
2844 this_idata->changed = TRUE;
2845 } else if (new_stack_size != stack_size) {
2846 // CCerror(context, "Inconsistent stack height %d != %d",
2847 // new_stack_size, stack_size);
2848 } else {
2849 stack_item_type *stack = this_idata->stack_info.stack;
2850 stack_item_type *old, *new;
2851 bool_t change = FALSE;
2852 for (old = stack, new = new_stack; old != NULL;
2853 old = old->next, new = new->next) {
2854 if (!isAssignableTo(context, new->item, old->item)) {
2855 change = TRUE;
2856 break;
2859 if (change) {
2860 stack = copy_stack(context, stack);
2861 for (old = stack, new = new_stack; old != NULL;
2862 old = old->next, new = new->next) {
2863 if (new == NULL) {
2864 break;
2866 old->item = merge_fullinfo_types(context, old->item, new->item,
2867 FALSE);
2868 if (GET_ITEM_TYPE(old->item) == ITEM_Bogus) {
2869 // CCerror(context, "Mismatched stack types");
2872 if (old != NULL || new != NULL) {
2873 // CCerror(context, "Mismatched stack types");
2875 this_idata->stack_info.stack = stack;
2876 this_idata->changed = TRUE;
2882 /*=========================================================================
2883 * FUNCTION: merge_registers
2884 * OVERVIEW: Used by merge_into_one_successor() for merging registers
2885 * from a given instruction to another specified instruction.
2886 * INTERFACE:
2887 * parameters: pointer to the context_type
2888 * int: from instruction number
2889 * int: to instruction number
2890 * stack_info_type: pointer to new_stack_info
2892 * returns: nothing
2893 *=======================================================================*/
2894 static void
2895 merge_registers(context_type *context, int from_inumber, int to_inumber,
2896 register_info_type *new_register_info)
2898 instruction_data_type *idata = context->instruction_data;
2899 instruction_data_type *this_idata = &idata[to_inumber];
2900 register_info_type *this_reginfo = &this_idata->register_info;
2902 int new_register_count = new_register_info->register_count;
2903 fullinfo_type *new_registers = new_register_info->registers;
2904 int new_mask_count = new_register_info->mask_count;
2905 mask_type *new_masks = new_register_info->masks;
2908 if (this_reginfo->register_count == UNKNOWN_REGISTER_COUNT) {
2909 this_reginfo->register_count = new_register_count;
2910 this_reginfo->registers = new_registers;
2911 this_reginfo->mask_count = new_mask_count;
2912 this_reginfo->masks = new_masks;
2913 this_idata->changed = TRUE;
2914 } else {
2915 /* See if we've got new information on the register set. */
2916 int register_count = this_reginfo->register_count;
2917 fullinfo_type *registers = this_reginfo->registers;
2918 int mask_count = this_reginfo->mask_count;
2919 mask_type *masks = this_reginfo->masks;
2921 bool_t copy = FALSE;
2922 int i, j;
2923 if (register_count > new_register_count) {
2924 /* Any register larger than new_register_count is now bogus */
2925 this_reginfo->register_count = new_register_count;
2926 register_count = new_register_count;
2927 this_idata->changed = TRUE;
2929 for (i = 0; i < register_count; i++) {
2930 fullinfo_type prev_value = registers[i];
2931 if ((i < new_register_count)
2932 ? (!isAssignableTo(context, new_registers[i], prev_value))
2933 : (prev_value != MAKE_FULLINFO(ITEM_Bogus, 0, 0))) {
2934 copy = TRUE;
2935 break;
2939 if (copy) {
2940 /* We need a copy. So do it. */
2941 fullinfo_type *new_set = NEW(fullinfo_type, register_count);
2942 for (j = 0; j < i; j++)
2943 new_set[j] = registers[j];
2944 for (j = i; j < register_count; j++) {
2945 if (i >= new_register_count)
2946 new_set[j] = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
2947 else
2948 new_set[j] = merge_fullinfo_types(context,
2949 new_registers[j],
2950 registers[j], FALSE);
2952 /* Some of the end items might now be bogus. This step isn't
2953 * necessary, but it may save work later. */
2954 while ( register_count > 0
2955 && GET_ITEM_TYPE(new_set[register_count-1]) == ITEM_Bogus)
2956 register_count--;
2957 this_reginfo->register_count = register_count;
2958 this_reginfo->registers = new_set;
2959 this_idata->changed = TRUE;
2961 if (mask_count > 0) {
2962 /* If the target instruction already has a sequence of masks, then
2963 * we need to merge new_masks into it. We want the entries on
2964 * the mask to be the longest common substring of the two.
2965 * (e.g. a->b->d merged with a->c->d should give a->d)
2966 * The bits set in the mask should be the or of the corresponding
2967 * entries in each of the original masks.
2968 */
2969 int i, j, k;
2970 int matches = 0;
2971 int last_match = -1;
2972 bool_t copy_needed = FALSE;
2973 for (i = 0; i < mask_count; i++) {
2974 int entry = masks[i].entry;
2975 for (j = last_match + 1; j < new_mask_count; j++) {
2976 if (new_masks[j].entry == entry) {
2977 /* We have a match */
2978 int *prev = masks[i].modifies;
2979 int *new = new_masks[j].modifies;
2980 matches++;
2981 /* See if new_mask has bits set for "entry" that
2982 * weren't set for mask. If so, need to copy. */
2983 for (k = context->bitmask_size - 1;
2984 !copy_needed && k >= 0;
2985 k--)
2986 if (~prev[k] & new[k])
2987 copy_needed = TRUE;
2988 last_match = j;
2989 break;
2993 if ((matches < mask_count) || copy_needed) {
2994 /* We need to make a copy for the new item, since either the
2995 * size has decreased, or new bits are set. */
2996 mask_type *copy = NEW(mask_type, matches);
2997 for (i = 0; i < matches; i++) {
2998 copy[i].modifies = NEW(int, context->bitmask_size);
3000 this_reginfo->masks = copy;
3001 this_reginfo->mask_count = matches;
3002 this_idata->changed = TRUE;
3003 matches = 0;
3004 last_match = -1;
3005 for (i = 0; i < mask_count; i++) {
3006 int entry = masks[i].entry;
3007 for (j = last_match + 1; j < new_mask_count; j++) {
3008 if (new_masks[j].entry == entry) {
3009 int *prev1 = masks[i].modifies;
3010 int *prev2 = new_masks[j].modifies;
3011 int *new = copy[matches].modifies;
3012 copy[matches].entry = entry;
3013 for (k = context->bitmask_size - 1; k >= 0; k--)
3014 new[k] = prev1[k] | prev2[k];
3015 matches++;
3016 last_match = j;
3017 break;
3027 /*=========================================================================
3028 * FUNCTION: merge_flags
3029 * OVERVIEW: Used by merge_into_one_successor() for merging flags
3030 * from a given instruction to a specified instruction.
3031 * INTERFACE:
3032 * parameters: pointer to the context_type
3033 * int: from instruction number
3034 * int: to instruction number
3035 * flag_type: new_and_flags
3036 * flag_type: new_or_flags
3038 * returns: nothing
3039 *=======================================================================*/
3040 static void
3041 merge_flags(context_type *context, int from_inumber, int to_inumber,
3042 flag_type new_and_flags, flag_type new_or_flags)
3044 /* Set this_idata->and_flags &= new_and_flags
3045 this_idata->or_flags |= new_or_flags
3046 */
3047 instruction_data_type *idata = context->instruction_data;
3048 instruction_data_type *this_idata = &idata[to_inumber];
3049 flag_type this_and_flags = this_idata->and_flags;
3050 flag_type this_or_flags = this_idata->or_flags;
3051 flag_type merged_and = this_and_flags & new_and_flags;
3052 flag_type merged_or = this_or_flags | new_or_flags;
3054 if ((merged_and != this_and_flags) || (merged_or != this_or_flags)) {
3055 this_idata->and_flags = merged_and;
3056 this_idata->or_flags = merged_or;
3057 this_idata->changed = TRUE;
3062 /*=========================================================================
3063 * FUNCTION: copy_stack
3064 * OVERVIEW: Make a copy of a stack.
3065 * INTERFACE:
3066 * parameters: pointer to the context_type
3067 * stack_item_type: pointer to stack
3069 * returns: pointer to stack_item_type
3070 *=======================================================================*/
3071 static stack_item_type *
3072 copy_stack(context_type *context, stack_item_type *stack)
3074 int length;
3075 stack_item_type *ptr;
3077 /* Find the length */
3078 for (ptr = stack, length = 0; ptr != NULL; ptr = ptr->next, length++);
3080 if (length > 0) {
3081 stack_item_type *new_stack = NEW(stack_item_type, length);
3082 stack_item_type *new_ptr;
3083 for ( ptr = stack, new_ptr = new_stack;
3084 ptr != NULL;
3085 ptr = ptr->next, new_ptr++) {
3086 new_ptr->item = ptr->item;
3087 new_ptr->next = new_ptr + 1;
3089 new_stack[length - 1].next = NULL;
3090 return new_stack;
3091 } else {
3092 return NULL;
3097 /*=========================================================================
3098 * FUNCTION: copy_masks
3099 * OVERVIEW: Make a copy of the masks.
3100 * INTERFACE:
3101 * parameters: pointer to the context_type
3102 * mask_type: pointer to masks
3103 * int: mask count
3105 * returns: pointer to mask_type
3106 *=======================================================================*/
3107 static mask_type *
3108 copy_masks(context_type *context, mask_type *masks, int mask_count)
3110 mask_type *result = NEW(mask_type, mask_count);
3111 int bitmask_size = context->bitmask_size;
3112 int *bitmaps = NEW(int, mask_count * bitmask_size);
3113 int i;
3114 for (i = 0; i < mask_count; i++) {
3115 result[i].entry = masks[i].entry;
3116 result[i].modifies = &bitmaps[i * bitmask_size];
3117 memcpy(result[i].modifies, masks[i].modifies, bitmask_size * sizeof(int));
3119 return result;
3123 /*=========================================================================
3124 * FUNCTION: add_to_masks
3125 * OVERVIEW: Used by Update_registers for adding entries to masks for
3126 * JSR instructions.
3127 * INTERFACE:
3128 * parameters: pointer to the context_type
3129 * mask_type: pointer to masks
3130 * int: mask count
3131 * int: d
3133 * returns: pointer to mask_type
3134 *=======================================================================*/
3135 static mask_type *
3136 add_to_masks(context_type *context, mask_type *masks, int mask_count, int d)
3138 mask_type *result = NEW(mask_type, mask_count + 1);
3139 int bitmask_size = context->bitmask_size;
3140 int *bitmaps = NEW(int, (mask_count + 1) * bitmask_size);
3141 int i;
3142 for (i = 0; i < mask_count; i++) {
3143 result[i].entry = masks[i].entry;
3144 result[i].modifies = &bitmaps[i * bitmask_size];
3145 memcpy(result[i].modifies, masks[i].modifies, bitmask_size * sizeof(int));
3147 result[mask_count].entry = d;
3148 result[mask_count].modifies = &bitmaps[mask_count * bitmask_size];
3149 memset(result[mask_count].modifies, 0, bitmask_size * sizeof(int));
3150 return result;
3154 /*=========================================================================
3155 * Storage Management Operations
3156 *=======================================================================*/
3158 /* We create our own storage manager, since we malloc lots of little items,
3159 * and we do not want to keep track of them when they become free.
3160 * It would have been nice if we had heaps, which could all be freed when
3161 * done.
3162 */
3164 #define CCSegSize 2000
3166 struct CCpool { /* a segment of allocated memory in the pool */
3167 struct CCpool *next;
3168 int segSize; /* almost always CCSegSize */
3169 char space[CCSegSize];
3170 };
3173 /*=========================================================================
3174 * FUNCTION: CCinit
3175 * OVERVIEW: Initialize the context's heap.
3176 * INTERFACE:
3177 * parameters: pointer to the context_type
3179 * returns: nothing
3180 *=======================================================================*/
3181 static void CCinit(context_type *context)
3183 struct CCpool *new = (struct CCpool *) sysMalloc(sizeof(struct CCpool));
3184 /* Set context->CCroot to 0 if new == 0 to tell CCdestroy to lay off */
3185 context->CCroot = context->CCcurrent = new;
3186 if (new == 0) {
3187 CCerror(context, "Out of memory");
3189 new->next = NULL;
3190 new->segSize = CCSegSize;
3191 context->CCfree_size = CCSegSize;
3192 context->CCfree_ptr = &new->space[0];
3196 /*=========================================================================
3197 * FUNCTION: CCreinit
3198 * OVERVIEW: Reuse all the space that we have in the context's heap.
3199 * INTERFACE:
3200 * parameters: pointer to the context_type
3202 * returns: nothing
3203 *=======================================================================*/
3204 static void CCreinit(context_type *context)
3206 struct CCpool *first = context->CCroot;
3207 context->CCcurrent = first;
3208 context->CCfree_size = CCSegSize;
3209 context->CCfree_ptr = &first->space[0];
3213 /*=========================================================================
3214 * FUNCTION: CCdestroy
3215 * OVERVIEW: Destroy the context's heap.
3216 * INTERFACE:
3217 * parameters: pointer to the context_type
3219 * returns: nothing
3220 *=======================================================================*/
3221 static void CCdestroy(context_type *context)
3223 struct CCpool *this = context->CCroot;
3224 while (this) {
3225 struct CCpool *next = this->next;
3226 sysFree(this);
3227 this = next;
3229 /* These two aren't necessary. But can't hurt either */
3230 context->CCroot = context->CCcurrent = NULL;
3231 context->CCfree_ptr = 0;
3235 /*=========================================================================
3236 * FUNCTION: CCalloc
3237 * OVERVIEW: Allocate an object of the given size from the context's heap.
3238 * INTERFACE:
3239 * parameters: pointer to the context_type
3240 * int: size
3241 * bool_t: zero
3243 * returns: pointer to void
3244 *=======================================================================*/
3245 static void *
3246 CCalloc(context_type *context, int size, bool_t zero)
3249 register char *p;
3250 /* Round CC to the size of a pointer */
3251 size = (size + (sizeof(void *) - 1)) & ~(sizeof(void *) - 1);
3253 if (context->CCfree_size < size) {
3254 struct CCpool *current = context->CCcurrent;
3255 struct CCpool *new;
3256 if (size > CCSegSize) { /* we need to allocate a special block */
3257 new = (struct CCpool *)sysMalloc(sizeof(struct CCpool) +
3258 (size - CCSegSize));
3259 if (new == 0) {
3260 CCerror(context, "Out of memory");
3262 new->next = current->next;
3263 new->segSize = size;
3264 current->next = new;
3265 } else {
3266 new = current->next;
3267 if (new == NULL) {
3268 new = (struct CCpool *) sysMalloc(sizeof(struct CCpool));
3269 if (new == 0) {
3270 CCerror(context, "Out of memory");
3272 current->next = new;
3273 new->next = NULL;
3274 new->segSize = CCSegSize;
3277 context->CCcurrent = new;
3278 context->CCfree_ptr = &new->space[0];
3279 context->CCfree_size = new->segSize;
3281 p = context->CCfree_ptr;
3282 context->CCfree_ptr += size;
3283 context->CCfree_size -= size;
3284 if (zero)
3285 memset(p, 0, size);
3286 return p;
3290 /*=========================================================================
3291 * FUNCTION: cp_index_to_signature
3292 * OVERVIEW: Get the signature associated with a particular field or
3293 * method in the constant pool.
3294 * INTERFACE:
3295 * parameters: pointer to the context_type
3296 * int: constant pool index
3298 * returns: char * type
3299 *=======================================================================*/
3300 static char *
3301 cp_index_to_signature(context_type *context, int cp_index)
3303 union cp_item_type *cp = cbConstantPool(context->class);
3304 int index = cp[cp_index].i; /* value of Fieldref field */
3305 int key2 = index & 0xFFFF; /* index to NameAndType */
3306 int signature_index = cp[key2].i & 0xFFFF;
3307 char *signature = cp[signature_index].cp;
3308 return signature;
3312 /*=========================================================================
3313 * FUNCTION: cp_index_to_fieldname
3314 * OVERVIEW: Get the fieldname for the specific index within the
3315 * constant pool.
3316 * INTERFACE:
3317 * parameters: pointer to the context_type
3318 * int: constant pool index
3320 * returns: char * type
3321 *=======================================================================*/
3322 static char *
3323 cp_index_to_fieldname(context_type *context, int cp_index)
3325 union cp_item_type *cp = cbConstantPool(context->class);
3326 int index = cp[cp_index].i; /* value of Fieldref field */
3327 int key2 = index & 0xFFFF; /* index to NameAndType */
3328 int name_index = cp[key2].i >> 16;
3329 return cp[name_index].cp;
3333 /*=========================================================================
3334 * FUNCTION: cp_index_to_class_fullinfo
3335 * OVERVIEW: Get the class associated with a particular field or
3336 * method or class in the constant pool. If is_field is true,
3337 * then it is a field or method. Otherwise, if false, it is a
3338 * class.
3339 * INTERFACE:
3340 * parameters: pointer to the context_type
3341 * int: constant pool index
3342 * bool_t: is_field
3344 * returns: fullinfo_type
3345 *=======================================================================*/
3346 static fullinfo_type
3347 cp_index_to_class_fullinfo(context_type *context, int cp_index, bool_t is_field)
3349 union cp_item_type *cp = cbConstantPool(context->class);
3350 unsigned classkey = is_field ? (cp[cp_index].i >> 16) : cp_index;
3351 char *classname = GetClassConstantClassName(cp, classkey);
3352 if (classname[0] == SIGNATURE_ARRAY) {
3353 fullinfo_type result;
3354 /* This make recursively call us, in case of a class array */
3355 signature_to_fieldtype(context, &classname, &result);
3356 return result;
3357 } else {
3358 return MAKE_CLASSNAME_INFO_WITH_COPY(context, classname, 0);
3363 /*=========================================================================
3364 * FUNCTION: CCerror
3365 * OVERVIEW: Error handling
3366 * INTERFACE:
3367 * parameters: pointer to the context_type
3368 * char: pointer to format
3370 * returns: nothing
3371 *=======================================================================*/
3372 static void
3373 CCerror (context_type *context, char *format, ...)
3375 /* va_list args;
3376 struct methodblock *mb = context->mb;
3377 printCurrentClassName();
3378 if (mb != 0) {
3379 jio_fprintf(stderr, "VERIFIER ERROR %s.%s%s:\n",
3380 cbName(fieldclass(&mb->fb)), mb->fb.name, mb->fb.signature);
3381 } else {
3382 jio_fprintf(stderr, "VERIFIER ERROR class %s (mb uninitialized):\n",
3383 cbName(context->class));
3385 va_start(args, format);
3386 jio_vfprintf(stderr, format, args);
3387 va_end(args);
3388 jio_fprintf(stderr, "\n");
3389 exit(1);*/
3393 /*=========================================================================
3394 * FUNCTION: signature_to_fieldtype
3395 * OVERVIEW: Given the full info type for a field, returns the field type
3396 * which corresponds to this signature.
3397 * INTERFACE:
3398 * parameters: pointer to the context_type
3399 * char: **signature_p
3400 * fullinfo_type: *full_info_p
3402 * returns: char
3403 *=======================================================================*/
3404 static char
3405 signature_to_fieldtype(context_type *context,
3406 char **signature_p, fullinfo_type *full_info_p)
3408 char *p = *signature_p;
3409 fullinfo_type full_info = MAKE_FULLINFO(0, 0, 0);
3410 char result;
3411 int array_depth = 0;
3413 for (;;) {
3414 switch(*p++) {
3415 default:
3416 full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3417 result = 0;
3418 break;
3420 case SIGNATURE_BYTE:
3421 full_info = (array_depth > 0)
3422 ? MAKE_FULLINFO(ITEM_Byte, 0, 0)
3423 : MAKE_FULLINFO(ITEM_Integer, 0, 0);
3424 result = 'I';
3425 break;
3427 case SIGNATURE_BOOLEAN:
3428 full_info = (array_depth > 0)
3429 ? MAKE_FULLINFO(ITEM_Boolean, 0, 0)
3430 : MAKE_FULLINFO(ITEM_Integer, 0, 0);
3431 result = 'I';
3432 break;
3434 case SIGNATURE_CHAR:
3435 full_info = (array_depth > 0)
3436 ? MAKE_FULLINFO(ITEM_Char, 0, 0)
3437 : MAKE_FULLINFO(ITEM_Integer, 0, 0);
3438 result = 'I';
3439 break;
3441 case SIGNATURE_SHORT:
3442 full_info = (array_depth > 0)
3443 ? MAKE_FULLINFO(ITEM_Short, 0, 0)
3444 : MAKE_FULLINFO(ITEM_Integer, 0, 0);
3445 result = 'I';
3446 break;
3448 case SIGNATURE_INT:
3449 full_info = MAKE_FULLINFO(ITEM_Integer, 0, 0);
3450 result = 'I';
3451 break;
3453 case SIGNATURE_FLOAT:
3454 full_info = MAKE_FULLINFO(ITEM_Float, 0, 0);
3455 result = 'F';
3456 break;
3458 case SIGNATURE_DOUBLE:
3459 full_info = MAKE_FULLINFO(ITEM_Double, 0, 0);
3460 result = 'D';
3461 break;
3463 case SIGNATURE_LONG:
3464 full_info = MAKE_FULLINFO(ITEM_Long, 0, 0);
3465 result = 'L';
3466 break;
3468 case SIGNATURE_ARRAY:
3469 array_depth++;
3470 continue; /* only time we ever do the loop > 1 */
3472 case SIGNATURE_CLASS: {
3473 char buffer_space[256];
3474 char *buffer = buffer_space;
3475 char *finish = strchr(p, SIGNATURE_ENDCLASS);
3476 int length = finish - p;
3477 if (length + 1 > sizeof(buffer_space)) {
3478 buffer = sysMalloc(length + 1);
3479 if (buffer == 0) {
3480 // CCerror(context, "Out of memory");
3483 memcpy(buffer, p, length);
3484 buffer[length] = '\0';
3485 full_info = MAKE_CLASSNAME_INFO_WITH_COPY(context, buffer, 0);
3486 result = 'A';
3487 p = finish + 1;
3488 if (buffer != buffer_space)
3489 sysFree(buffer);
3490 break;
3492 } /* end of switch */
3493 break;
3495 *signature_p = p;
3496 if (array_depth == 0 || result == 0) {
3497 /* either not an array, or result is bogus */
3498 *full_info_p = full_info;
3499 return result;
3500 } else {
3501 // if (array_depth > MAX_ARRAY_DIMENSIONS)
3502 // CCerror(context, "Array with too many dimensions");
3503 *full_info_p = MAKE_FULLINFO(GET_ITEM_TYPE(full_info),
3504 array_depth,
3505 GET_EXTRA_INFO(full_info));
3506 return 'A';
3511 /*=========================================================================
3512 * FUNCTION: decrement_indirection
3513 * OVERVIEW: Given an array type, create the type that has one less
3514 * level of indirection.
3515 * INTERFACE:
3516 * parameters: fullinfo_type array_info
3518 * returns: fullinfo_type
3519 *=======================================================================*/
3520 static fullinfo_type
3521 decrement_indirection(fullinfo_type array_info)
3523 if (array_info == NULL_FULLINFO) {
3524 return NULL_FULLINFO;
3525 } else {
3526 int type = GET_ITEM_TYPE(array_info);
3527 int indirection = GET_INDIRECTION(array_info) - 1;
3528 int extra_info = GET_EXTRA_INFO(array_info);
3529 if ( (indirection == 0)
3530 && ((type == ITEM_Short || type == ITEM_Byte || type == ITEM_Boolean || type == ITEM_Char)))
3531 type = ITEM_Integer;
3532 return MAKE_FULLINFO(type, indirection, extra_info);
3537 /*=========================================================================
3538 * FUNCTION: isAssignableTo
3539 * OVERVIEW: Given an object of the "from" type, determine if it can be
3540 * assigned to an object of the "to" type.
3541 * INTERFACE:
3542 * parameters: pointer to the context_type
3543 * fullinfo_type: from
3544 * fullinfo_type: to
3546 * returns: boolean type
3547 *=======================================================================*/
3548 static bool_t isAssignableTo(context_type *context,
3549 fullinfo_type from, fullinfo_type to)
3551 return (merge_fullinfo_types(context, from, to, TRUE) == to);
3555 /*=========================================================================
3556 * FUNCTION: merge_fullinfo_types
3557 * OVERVIEW: Given two fullinfo_types, find their lowest common deno-
3558 * minator. If the assignable_p argument is non-null, we are
3559 * really just calling to find out if "<target> := <value>"
3560 * is a legitimate assignment.
3561 * We treat all interfaces as if they were of type '
3562 * java/lang/Object, since the runtime will do the full
3563 * checking.
3565 * INTERFACE:
3566 * parameters: pointer to the context_type
3567 * fullinfo_type: value
3568 * fullinfo_type: target
3569 * bool_t for_assignment
3571 * returns: fullinfo_type
3572 *=======================================================================*/
3573 static fullinfo_type
3574 merge_fullinfo_types(context_type *context,
3575 fullinfo_type value, fullinfo_type target,
3576 bool_t for_assignment)
3578 if (value == target) {
3579 /* If they're identical, clearly just return what we've got */
3580 return value;
3583 /* Both must be either arrays or objects to go further */
3584 if (GET_INDIRECTION(value) == 0 && GET_ITEM_TYPE(value) != ITEM_Object)
3585 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3586 if (GET_INDIRECTION(target) == 0 && GET_ITEM_TYPE(target) != ITEM_Object)
3587 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3589 /* If either is NULL, return the other. */
3590 if (value == NULL_FULLINFO)
3591 return target;
3592 else if (target == NULL_FULLINFO)
3593 return value;
3595 /* If either is java/lang/Object, that's the result. */
3596 if (target == context->object_info)
3597 return target;
3598 else if (value == context->object_info) {
3599 /* Minor hack. For assignments, Interface := Object, return Interface
3600 * rather than Object, so that isAssignableTo() will get the right
3601 * result. */
3602 if (for_assignment && (WITH_ZERO_EXTRA_INFO(target) ==
3603 MAKE_FULLINFO(ITEM_Object, 0, 0))) {
3604 ClassClass *cb = object_fullinfo_to_classclass(context, target);
3605 if (cb && cbIsInterface(cb))
3606 return target;
3608 return value;
3610 if (GET_INDIRECTION(value) > 0 || GET_INDIRECTION(target) > 0) {
3611 /* At least one is an array. Neither is java/lang/Object or NULL.
3612 * Moreover, the types are not identical.
3613 * The result must either be Object, or an array of some object type.
3614 */
3615 int dimen_value = GET_INDIRECTION(value);
3616 int dimen_target = GET_INDIRECTION(target);
3618 /* First, if either item's base type isn't ITEM_Object, promote it up
3619 * to an object or array of object. If either is elemental, we can
3620 * punt.
3621 */
3622 if (GET_ITEM_TYPE(value) != ITEM_Object) {
3623 if (dimen_value == 0)
3624 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3625 dimen_value--;
3626 value = MAKE_Object_ARRAY(dimen_value);
3629 if (GET_ITEM_TYPE(target) != ITEM_Object) {
3630 if (dimen_target == 0)
3631 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3632 dimen_target--;
3633 target = MAKE_Object_ARRAY(dimen_target);
3635 /* Both are now objects or arrays of some sort of object type */
3636 if (dimen_value == dimen_target) {
3637 /* Arrays of the same dimension. Merge their base types. */
3638 fullinfo_type value_base = WITH_ZERO_INDIRECTION(value);
3639 fullinfo_type target_base = WITH_ZERO_INDIRECTION(target);
3640 fullinfo_type result_base =
3641 merge_fullinfo_types(context, value_base, target_base,
3642 for_assignment);
3643 if (result_base == MAKE_FULLINFO(ITEM_Bogus, 0, 0))
3644 /* bogus in, bogus out */
3645 return result_base;
3646 return MAKE_FULLINFO(ITEM_Object, dimen_value,
3647 GET_EXTRA_INFO(result_base));
3648 } else {
3649 /* Arrays of different sizes. Return Object, with a dimension
3650 * of the smaller of the two.
3651 */
3652 int dimen = dimen_value < dimen_target ? dimen_value : dimen_target;
3653 return MAKE_Object_ARRAY(dimen);
3655 } else {
3656 /* Both are non-array objects. Neither is java/lang/Object or NULL */
3657 ClassClass *cb_value, *cb_target, *cb_super_value, *cb_super_target;
3658 void **addr;
3659 int value_info;
3661 /* Let's get the classes corresponding to each of these. Treat
3662 * interfaces as if they were java/lang/Object. See hack note above. */
3663 cb_target = object_fullinfo_to_classclass(context, target);
3664 if (cb_target == 0)
3665 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3666 if (cbIsInterface(cb_target))
3667 return for_assignment ? target : context->object_info;
3668 cb_value = object_fullinfo_to_classclass(context, value);
3669 if (cb_value == 0)
3670 return MAKE_FULLINFO(ITEM_Bogus, 0, 0);
3671 if (cbIsInterface(cb_value))
3672 return context->object_info;
3674 /* If this is for assignment of target := value, we just need to see if
3675 * cb_target is a superclass of cb_value. Save ourselves a lot of
3676 * work.
3677 */
3678 if (for_assignment) {
3679 for (cb_super_value = cb_value;
3680 cbSuperclass(cb_super_value) != NULL;
3681 cb_super_value = cbSuperclass(cb_super_value)) {
3682 if (cb_super_value == cb_target) {
3683 return target;
3686 return context->object_info;
3689 /* Find out whether cb_value or cb_target is deeper in the class
3690 * tree by moving both toward the root, and seeing who gets there
3691 * first. */
3692 for (cb_super_value = cb_value, cb_super_target = cb_target;
3693 cbSuperclass(cb_super_value) && cbSuperclass(cb_super_target); ) {
3694 /* Optimization. If either hits the other when going up looking
3695 * for a parent, then might as well return the parent immediately */
3696 if (cb_super_value == cb_target)
3697 return target;
3698 if (cb_super_target == cb_value)
3699 return value;
3700 cb_super_value= cbSuperclass(cb_super_value);
3701 cb_super_target = cbSuperclass(cb_super_target);
3702 }
3703 /* At most one of the following two while clauses will be executed.
3704 * Bring the deeper of cb_target and cb_value to the depth of the
3705 * shallower one.
3706 */
3707 while (cbSuperclass(cb_super_value)) { /* cb_value is deeper */
3708 cb_super_value= cbSuperclass(cb_super_value);
3709 cb_value= cbSuperclass(cb_value);
3711 while (cbSuperclass(cb_super_target)) { /* cb_target is deeper */
3712 cb_super_target= cbSuperclass(cb_super_target);
3713 cb_target = cbSuperclass(cb_target);
3716 /* Walk both up, maintaining equal depth, until a join is found. We
3717 * know that we will find one. */
3718 while (cb_value != cb_target) {
3719 cb_value = cbSuperclass(cb_value);
3720 cb_target = cbSuperclass(cb_target);
3722 /* Get the info for this guy. We know its cb_value, so we should
3723 * fill that in, while we're at it. */
3724 value_info = Str2ID_Local(context, &context->classHash,
3725 cbName(cb_value), &addr, TRUE);
3726 *addr = cb_value;
3727 return MAKE_FULLINFO(ITEM_Object, 0, value_info);
3728 } /* both items are classes */
3732 /*=========================================================================
3733 * FUNCTION: object_fullinfo_to_classclass
3734 * OVERVIEW: Given a fullinfo_type corresponding to an Object, return the
3735 * pointer to the ClassClass structure of that type.
3736 * Returns 0 for an illegal class.
3737 * INTERFACE:
3738 * parameters: pointer to the context_type
3739 * fullinfo_type: classinfo
3741 * returns: pointer to the ClassClass type
3742 *=======================================================================*/
3743 static ClassClass *
3744 object_fullinfo_to_classclass(context_type *context, fullinfo_type classinfo)
3746 void **addr;
3747 ClassClass *cb;
3749 unsigned short info = GET_EXTRA_INFO(classinfo);
3750 char *classname = ID2Str_Local(context, context->classHash, info, &addr);
3751 if ((cb = *addr) != 0) {
3752 return cb;
3753 } else {
3754 *addr = cb = FindClassFromClass(0, classname, FALSE, context->class);
3755 // if (cb == 0)
3756 // CCerror(context, "Cannot find class %s", classname);
3757 return cb;
3762 /*=========================================================================
3763 * The functions below are for debugging the preverifier
3764 *=======================================================================*/
3766 #ifdef DEBUG_VERIFIER
3768 static void print_fullinfo_type(context_type *, fullinfo_type, bool_t);
3771 /*=========================================================================
3772 * FUNCTION: print_stack
3773 * OVERVIEW: Prints stack information.
3774 *
3775 * INTERFACE:
3776 * parameters: pointer to the context_type
3777 * stack_info: pointer to stack_info
3779 * returns: nothing
3780 *=======================================================================*/
3781 static void
3782 print_stack(context_type *context, stack_info_type *stack_info)
3784 stack_item_type *stack = stack_info->stack;
3785 if (stack_info->stack_size == UNKNOWN_STACK_SIZE) {
3786 jio_fprintf(stdout, "x");
3787 } else {
3788 jio_fprintf(stdout, "(");
3789 for ( ; stack != 0; stack = stack->next)
3790 print_fullinfo_type(context, stack->item, verify_verbose > 1);
3791 jio_fprintf(stdout, ")");
3793 }
3796 /*=========================================================================
3797 * FUNCTION: print_registers
3798 * OVERVIEW: Prints registers.
3799 *
3800 * INTERFACE:
3801 * parameters: pointer to the context_type
3802 * register_info_type: pointer to register_info
3804 * returns: nothing
3805 *=======================================================================*/
3806 static void
3807 print_registers(context_type *context, register_info_type *register_info)
3809 int register_count = register_info->register_count;
3810 if (register_count == UNKNOWN_REGISTER_COUNT) {
3811 jio_fprintf(stdout, "x");
3812 } else {
3813 fullinfo_type *registers = register_info->registers;
3814 int mask_count = register_info->mask_count;
3815 mask_type *masks = register_info->masks;
3816 int i, j;
3818 jio_fprintf(stdout, "{");
3819 for (i = 0; i < register_count; i++)
3820 print_fullinfo_type(context, registers[i], verify_verbose > 1);
3821 jio_fprintf(stdout, "}");
3822 for (i = 0; i < mask_count; i++) {
3823 char *separator = "";
3824 int *modifies = masks[i].modifies;
3825 jio_fprintf(stdout, "<%d: ", masks[i].entry);
3826 for (j = 0; j < context->mb->nlocals; j++)
3827 if (IS_BIT_SET(modifies, j)) {
3828 jio_fprintf(stdout, "%s%d", separator, j);
3829 separator = ",";
3831 jio_fprintf(stdout, ">");
3837 /*=========================================================================
3838 * FUNCTION: print_flags
3839 * OVERVIEW: Prints flags.
3840 *
3841 * INTERFACE:
3842 * parameters: pointer to the context_type
3843 * flag_type: and_flags
3844 * flag_type: or_flags
3846 * returns: nothing
3847 *=======================================================================*/
3848 static void
3849 print_flags(context_type *context, flag_type and_flags, flag_type or_flags)
3850 {
3851 if (and_flags != ((flag_type)-1) || or_flags != 0) {
3852 jio_fprintf(stdout, "<%x %x>", and_flags, or_flags);
3854 }
3857 /*=========================================================================
3858 * FUNCTION: print_fullinfo_type
3859 * OVERVIEW: Prints fullinfo_type information.
3860 *
3861 * INTERFACE:
3862 * parameters: pointer to the context_type
3863 * fullinfo_type: type
3864 * bool_t verbose
3866 * returns: nothing
3867 *=======================================================================*/
3868 static void
3869 print_fullinfo_type(context_type *context, fullinfo_type type, bool_t verbose)
3871 int i;
3872 int indirection = GET_INDIRECTION(type);
3873 for (i = indirection; i-- > 0; )
3874 jio_fprintf(stdout, "[");
3875 switch (GET_ITEM_TYPE(type)) {
3876 case ITEM_Integer:
3877 jio_fprintf(stdout, "I"); break;
3878 case ITEM_Float:
3879 jio_fprintf(stdout, "F"); break;
3880 case ITEM_Double:
3881 jio_fprintf(stdout, "D"); break;
3882 case ITEM_Double_2:
3883 jio_fprintf(stdout, "d"); break;
3884 case ITEM_Long:
3885 jio_fprintf(stdout, "L"); break;
3886 case ITEM_Long_2:
3887 jio_fprintf(stdout, "l"); break;
3888 case ITEM_ReturnAddress:
3889 jio_fprintf(stdout, "a"); break;
3890 case ITEM_Object:
3891 if (!verbose) {
3892 jio_fprintf(stdout, "A");
3893 } else {
3894 unsigned short extra = GET_EXTRA_INFO(type);
3895 if (extra == 0) {
3896 jio_fprintf(stdout, "/Null/");
3897 } else {
3898 char *name = ID2Str_Local(context, context->classHash,
3899 extra, 0);
3900 char *name2 = strrchr(name, '/');
3901 jio_fprintf(stdout, "/%s/", name2 ? name2 + 1 : name);
3904 break;
3905 case ITEM_Char:
3906 jio_fprintf(stdout, "C"); break;
3907 case ITEM_Short:
3908 jio_fprintf(stdout, "S"); break;
3909 case ITEM_Byte:
3910 jio_fprintf(stdout, "B"); break;
3911 case ITEM_Boolean:
3912 jio_fprintf(stdout, "Z"); break;
3913 case ITEM_NewObject:
3914 if (!verbose) {
3915 jio_fprintf(stdout, "@");
3916 } else {
3917 int inum = GET_EXTRA_INFO(type);
3918 fullinfo_type real_type =
3919 context->instruction_data[inum].operand2.fi;
3920 jio_fprintf(stdout, ">");
3921 print_fullinfo_type(context, real_type, TRUE);
3922 jio_fprintf(stdout, "<");
3924 break;
3925 case ITEM_InitObject:
3926 jio_fprintf(stdout, verbose ? ">/this/<" : "@");
3927 break;
3929 default:
3930 jio_fprintf(stdout, "?"); break;
3932 for (i = indirection; i-- > 0; )
3933 jio_fprintf(stdout, "]");
3937 /*=========================================================================
3938 * FUNCTION: print_formatted_fieldname
3939 * OVERVIEW: Prints formatted fieldname associated with the given
3940 * index within the constant pool.
3941 *
3942 * INTERFACE:
3943 * parameters: pointer to the context_type
3944 * int: index
3946 * returns: nothing
3947 *=======================================================================*/
3948 static void
3949 print_formatted_fieldname(context_type *context, int index)
3951 union cp_item_type *constant_pool = cbConstantPool(context->class);
3952 unsigned char *type_table =
3953 constant_pool[CONSTANT_POOL_TYPE_TABLE_INDEX].type;
3954 unsigned type = CONSTANT_POOL_TYPE_TABLE_GET_TYPE(type_table, index);
3956 unsigned key = constant_pool[index].i;
3957 unsigned classkey = key >> 16;
3958 unsigned nametypekey = key & 0xFFFF;
3959 unsigned nametypeindex = constant_pool[nametypekey].i;
3960 unsigned fieldnameindex = nametypeindex >> 16;
3961 unsigned fieldtypeindex = nametypeindex & 0xFFFF;
3962 jio_fprintf(stdout, " <%s.%s%s%s>",
3963 GetClassConstantClassName(constant_pool, classkey),
3964 constant_pool[fieldnameindex].cp,
3965 type == CONSTANT_Fieldref ? " " : "",
3966 constant_pool[fieldtypeindex].cp);
3969 #endif /*DEBUG_VERIFIER*/