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 *=======================================================================*/
38 //#include "winsock2.h"
39 #define ntohl(x) (x)
41 /*=========================================================================
42 * Globals and extern declarations
43 *=======================================================================*/
45 #ifdef DEBUG_VERIFIER
48 #endif
82 bool_t isException);
84 stack_info_type *);
86 register_info_type *);
98 bool_t assignment);
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))
123 #ifdef DEBUG_VERIFIER
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
169 // CCerror(context, "Out of memory");
170 }
173 }
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 *=======================================================================*/
202 // CCerror(context, "Out of memory");
203 }
206 }
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 *=======================================================================*/
220 context_type context_structure;
226 #ifdef DEBUG_VERIFIER
228 #endif
230 /* Initialize the class-wide fields of the context. */
234 /* Zero method block field of the context, in case anyone calls CCerrror */
238 /* Don't call CCerror or anything that can call it above the setjmp! */
264 }
266 /* Look at each method */
284 }
286 /* Cleanup */
289 #ifdef DEBUG_VERIFIER
291 #endif
295 }
298 }
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
315 {
321 // jio_fprintf(stderr, "VERIFIER ERROR %s.%s:\n",
322 // cbName(fieldclass(fb)), fb->name);
323 // jio_fprintf(stderr, "Inconsistent access bits.");
324 }
326 }
327 }
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
344 {
370 // panic("unexpected");
376 }
378 }
379 // default:
380 // panic("bad type");
381 }
383 }
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 *=======================================================================*/
399 {
408 }
412 }
413 }
415 }
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 *=======================================================================*/
430 {
471 }
476 }
477 }
478 {
484 }
486 // panic("bad type code");
488 }
489 }
490 }
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
505 {
516 again:
520 /* CCerror can give method-specific info once this is set */
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
536 // CCerror(context, "Inconsistent access bits.");
537 }
540 /* not much to do for abstract or native methods */
542 }
545 // CCerror(context, "Code of a method longer than 65535 bytes");
546 }
548 /* Run through the code. Mark the start of each instruction, and give
549 * the instruction a number */
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);
561 }
564 /* Allocate a structure to hold info about each instruction. */
567 /* Initialize the heap, and other info in the context structure. */
576 // if (instruction_count == 0)
577 // CCerror(context, "Empty code");
590 /* Added for inlinejsr */
595 /* This also sets up this_data->operand. It also makes the
596 * xload_x and xstore_x instructions look like the generic form. */
599 }
602 /* make sure exception table is reasonable. */
604 /* Set up first instruction, and start of exception handlers. */
606 /* Run data flow analysis on the instructions. */
618 }
619 }
622 }
625 /* verify checked exceptions, if any */
629 /* Make sure the constant pool item is CONSTANT_Class */
632 }
633 }
640 dead_count++;
643 jsr_count++;
644 }
645 }
649 }
655 n_stack_maps++;
656 }
657 }
675 /* We may be allocating too big a structure if there are longs
676 * or doubles on the stack, but that's okay */
685 index++;
688 }
691 }
692 }
701 }
702 new_entries = (struct map_entry *)malloc(mb->stack_maps[n_stack_maps].nstacks * sizeof(struct map_entry));
707 }
711 n_stack_maps++;
712 }
713 }
714 }
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
735 {
750 /* instruction of ret statement */
752 /* FALLTHROUGH */
760 /* Set the ->operand to be the instruction number of the target. */
763 // if (!isLegalTarget(context, target))
764 // CCerror(context, "Illegal target of jump or branch");
767 }
770 /* instruction of ret statement */
772 /* FALLTHROUGH */
774 /* Set the ->operand to be the instruction number of the target. */
779 // if (!isLegalTarget(context, target))
780 // CCerror(context, "Illegal target of jump or branch");
783 }
787 /* Set the ->operand to be a table of possible instruction targets. */
799 /* Make sure that the tableswitch items are sorted */
803 // if (this_key >= next_key) {
804 // CCerror(context, "Unsorted lookup switch");
805 // }
806 }
807 }
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 */
813 // if (!isLegalTarget(context, offset + ntohl(lpc[0])))
814 // CCerror(context, "Illegal default target in switch");
821 // if (!isLegalTarget(context, target))
822 // CCerror(context, "Illegal branch in opc_tableswitch");
824 }
827 }
830 /* Make sure the constant pool item is the right type. */
837 }
840 /* Make sure the constant pool item is the right type. */
847 }
850 /* Make sure the constant pool item is the right type. */
856 }
860 /* Make sure the constant pool item is the right type. */
867 }
873 /* Make sure the constant pool item is the right type. */
876 fullinfo_type clazz_info;
880 /* Make sure the constant pool item is the right type. */
887 // if (opcode != opc_invokespecial)
888 // CCerror(context,
889 // "Must call initializers using invokespecial");
892 // if (methodname[0] == '<')
893 // CCerror(context, "Illegal call to internal method");
901 /* The optimizer make cause this to happen on local code */
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");
908 }
909 }
910 }
911 }
917 // CCerror(context,
918 // "Inconsistent args_size for opc_invokeinterface");
919 }
921 // CCerror(context,
922 // "Fourth operand byte of invokeinterface must be zero");
923 }
928 }
936 /* Make sure the constant pool item is a class */
938 fullinfo_type target;
941 // if (GET_ITEM_TYPE(target) == ITEM_Bogus)
942 // CCerror(context, "Illegal type");
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. */
963 // if ( (this_idata->operand2.i > (int)GET_INDIRECTION(target))
964 // || (this_idata->operand2.i == 0))
965 // CCerror(context, "Illegal dimension argument");
969 }
971 }
974 /* Cache the result of the opc_newarray into the operand slot */
975 fullinfo_type full_info;
995 // CCerror(context, "Bad type passed to opc_newarray");
996 }
999 }
1001 /* Fudge iload_x, aload_x, etc to look like their generic cousin. */
1061 }
1068 check_local_variable:
1069 /* Make sure that the variable number isn't illegal. */
1071 // if (var >= (int)mb->nlocals)
1072 // CCerror(context, "Illegal local variable number");
1077 check_local_variable2:
1078 /* Make sure that the variable number isn't illegal. */
1080 // if ((var + 1) >= (int)mb->nlocals)
1081 // CCerror(context, "Illegal local variable number");
1084 // default:
1085 // if (opcode >= opc_breakpoint)
1086 // CCerror(context, "Quick instructions shouldn't appear yet.");
1089 }
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
1110 {
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;
1123 }
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;
1130 }
1131 }
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;
1140 }
1141 }
1142 return;
1143 }
1144 haveIt:
1145 if (IsProtected(fb->access)) {
1146 if (IsPrivate(fb->access) ||
1147 !IsSameClassPackage(calledClass, context->class))
1148 context->instruction_data[inumber].protected = TRUE;
1149 }
1150 }*/
1151 }
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
1168 //return TRUE;
1175 /* Count the number of superclasses. By counting ourselves, and
1176 * not counting Object, we get the same number. */
1180 /* Can't go on context heap since it survives more than one method */
1184 // CCerror(context, "Out of memory");
1185 }
1191 }
1193 }
1197 }
1199 }
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
1214 {
1232 // CCerror(context, "Illegal exception table range");
1233 }
1235 // CCerror(context, "Illegal exception table handler");
1236 }
1239 /* end may point to one byte beyond the end of bytecodes. */
1255 }
1256 }
1257 }
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 *=======================================================================*/
1270 {
1280 }
1281 }
1288 else
1290 }
1305 }
1308 /* A length of 0 indicates an error. */
1311 }
1312 }
1313 }
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
1328 {
1333 }
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
1348 {
1356 // if ((index <= 0) || (index >= nconstants))
1357 // CCerror(context, "Illegal constant pool index");
1360 // if ((mask & (1 << type)) == 0)
1361 // CCerror(context, "Illegal type in constant pool");
1362 }
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
1378 {
1382 fullinfo_type full_info;
1385 /* Initialize the function entry, since we know everything about it. */
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 */
1408 }
1409 }
1410 /* Fill in each of the arguments into the registers. */
1413 // if (no_floating_point && (fieldchar == 'D' || fieldchar == 'F')) {
1414 // CCerror(context, "Floating point arguments not allowed");
1415 // }
1424 }
1425 }
1432 }
1434 /* Indicate that we need to look at the first instruction. */
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
1456 /* Run through the loop, until there is nothing left to do. */
1462 register_info_type new_register_info;
1463 stack_info_type new_stack_info;
1468 /* Make sure the registers and flags are appropriate */
1472 /* Make sure the stack can deal with this instruction */
1475 /* Update the registers and flags */
1479 /* Update the stack. */
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. */
1490 }
1491 }
1492 }
1493 }
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
1507 {
1532 }
1535 /* Make sure we don't have an illegal register or one with wrong type */
1540 /* the register is obviously of the given type */
1543 /* address type stuff be used on all arrays */
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 */
1561 // CCerror(context, "Register %d contains wrong type", operand);
1562 }
1564 /* Make sure we don't have an illegal register or one with wrong type */
1566 // CCerror(context,
1567 // "Accessing value from uninitialized register pair %d/%d",
1568 // operand, operand+1);
1574 // CCerror(context, "Register pair %d/%d contains wrong type",
1575 // operand, operand+1);
1576 }
1577 }
1578 }
1579 }
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
1593 {
1597 }
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
1613 {
1627 /* For most instructions, we just use a built-in table */
1632 /* The top thing on the stack depends on the signature of
1633 * the object. */
1644 }
1649 /* The top stuff on the stack depends on the method signature */
1656 /* First, push the object */
1660 // if (ip >= buffer + sizeof(buffer) - 1)
1661 // CCerror(context, "Signature %s has too many arguments",
1662 // signature);
1663 }
1667 }
1670 /* Count can't be larger than 255. So can't overflow buffer */
1676 }
1680 /* Run through the list of operands >>backwards<< */
1688 // if (stack == NULL)
1689 // CCerror(context, "Unable to pop operand off an empty stack");
1692 // if (top_type != MAKE_FULLINFO(ITEM_Integer, 0, 0))
1693 // CCerror(context, "Expecting to find integer on stack");
1697 // if (top_type != MAKE_FULLINFO(ITEM_Float, 0, 0))
1698 // CCerror(context, "Expecting to find float on stack");
1704 /* The thing isn't an object or an array. Let's see if it's
1705 * one of the special cases */
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 */
1734 /* NameAndTypeToHash returns 0
1735 * if out of memory
1736 */
1737 // CCerror(context, "Out of memory");
1739 }
1745 }
1746 }
1752 }
1753 }
1754 // CCerror(context, "Expecting to find object/array on stack");
1755 }
1760 // if (item_type != ITEM_NewObject && item_type != ITEM_InitObject)
1761 // CCerror(context,
1762 // "Expecting to find unitialized object on stack");
1764 }
1767 // if (WITH_ZERO_EXTRA_INFO(top_type) !=
1768 // MAKE_FULLINFO(ITEM_Object, 0, 0))
1769 // CCerror(context, "Expecting to find object on stack");
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");
1781 // if (top_type != MAKE_FULLINFO(ITEM_Double, 0, 0))
1782 // CCerror(context, "Expecting to find double on stack");
1786 // if (top_type != MAKE_FULLINFO(ITEM_Long, 0, 0))
1787 // CCerror(context, "Expecting to find long on stack");
1792 /* do nothing */
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");
1802 // if (top_type != MAKE_FULLINFO(ITEM_Long, 1, 0))
1803 // CCerror(context,
1804 // "Expecting to find array of longs on stack");
1808 // if (top_type != MAKE_FULLINFO(ITEM_Float, 1, 0))
1809 // CCerror(context,
1810 // "Expecting to find array of floats on stack");
1814 // if (top_type != MAKE_FULLINFO(ITEM_Double, 1, 0))
1815 // CCerror(context,
1816 // "Expecting to find array of doubles on stack");
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");
1828 }
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");
1838 // if (top_type != MAKE_FULLINFO(ITEM_Byte, 1, 0))
1839 // CCerror(context,
1840 // "Expecting to find array of bytes on stack");
1844 // if (top_type != MAKE_FULLINFO(ITEM_Boolean, 1, 0))
1845 // CCerror(context,
1846 // "Expecting to find array of bytes on stack");
1850 // if (top_type != MAKE_FULLINFO(ITEM_Char, 1, 0))
1851 // CCerror(context,
1852 // "Expecting to find array of chars on stack");
1856 // if (top_type != MAKE_FULLINFO(ITEM_Short, 1, 0))
1857 // CCerror(context,
1858 // "Expecting to find array of shorts on stack");
1862 // if (GET_INDIRECTION(top_type) == 0)
1863 // CCerror(context,
1864 // "Expecting to find array on stack");
1868 // CCerror(context, "Internal error #1");
1871 }
1884 // CCerror(context,
1885 // "Attempt to split long or double on the stack");
1886 }
1891 }
1895 // CCerror(context, "Internal error #2");
1897 }
1899 }
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 */
1913 }
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 */
1923 }
1924 // if (!isAssignableTo(context, object_type, target_type))
1925 // CCerror(context, "Incompatible types for storing into array of "
1926 // "arrays or objects");
1928 }
1937 stack_object,
1939 TRUE))) {
1940 // CCerror(context,
1941 // "Incompatible type for getting or setting field");
1942 }
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 }*/
1950 }
1955 // CCerror(context, "Bad type in putfield/putstatic");
1956 }
1957 }
1959 }
1962 // if (!isAssignableTo(context, stack_extra_info[0],
1963 // context->throwable_info)) {
1964 // CCerror(context, "Can only throw Throwable objects");
1965 // }
1969 /* We need to pass the information to the stack updater */
1973 }
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 */
1996 // if (target_type != init_type) {
1997 // CCerror(context, "Call to wrong initialization method");
1998 // }
2000 /* We better be calling super() or this(). */
2003 // CCerror(context, "Call to wrong initialization method");
2004 }
2006 }
2012 // CCerror(context,
2013 // "Incompatible object argument for function call");
2014 }
2015 /* The specification of the structural constraints for
2016 * invokespecial needs to be more stringent.
2017 *
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 */
2027 /* Make sure object argument is assignment compatible
2028 * to current class
2029 */
2030 // CCerror(context,
2031 // "Incompatible object argument for invokespecial");
2032 }
2037 /* This is ugly. Special dispensation. Arrays pretend to
2038 implement public Object clone() even though they don't */
2044 // CCerror(context, "Bad access to protected data");
2045 }
2046 }
2048 }
2053 // CCerror(context, "Incompatible argument to function");
2054 }
2055 }
2058 }
2061 // if (context->return_type != MAKE_FULLINFO(ITEM_Void, 0, 0))
2062 // CCerror(context, "Wrong return type in function");
2070 // CCerror(context, "Wrong return type in function");
2071 }
2073 }
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 */
2084 // if (item->item == this_idata->operand.fi) {
2085 // CCerror(context,
2086 // "Uninitialized object on stack at creating point");
2087 // }
2088 }
2089 /* Info for update_registers */
2094 }
2095 }
2098 }
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
2111 *
2112 * returns: nothing
2113 *=======================================================================*/
2114 static void
2117 {
2128 /* Use these as default new values. */
2137 /* Remember, we've already verified the type at the top of the stack. */
2148 continue_store: {
2149 /* We have a modification to the registers. Copy them if needed. */
2157 /* No changes have been made to the registers. */
2169 }
2186 /* Do nothing */
2189 new_mask_count++;
2190 }
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 */
2207 /* Found a match */
2209 }
2210 }
2212 /* We have to change registers, and possibly a mask */
2225 mask_count);
2227 }
2229 }
2230 }
2231 }
2232 }
2233 }
2235 }
2249 }
2251 }
2252 }
2253 }
2259 }
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
2272 *
2273 * returns: nothing
2274 *=======================================================================*/
2275 static void
2279 {
2285 /* Set the "we've done a constructor" flag */
2290 }
2293 }
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
2308 *
2309 * returns: nothing
2310 *=======================================================================*/
2311 static void
2313 {
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 */
2337 /* Look to constant pool to determine correct result. */
2354 // CCerror(context, "Internal error #3");
2356 }
2358 }
2361 /* Look to signature to determine correct result. */
2364 #ifdef DEBUG_VERIFIER
2367 }
2368 #endif
2373 }
2378 /* Look to signature to determine correct result. */
2389 }
2391 }
2404 /* Conventionally, this result type is stored here */
2409 // CCerror(context, "Cannot create floating point array");
2410 }
2415 /* pop_stack() saved value for us. */
2421 /* The register hasn't been modified, so we can use its value. */
2435 // if (no_floating_point) {
2436 // CCerror(context, "Floating point result not allowed");
2437 // }
2441 // if (no_floating_point) {
2442 // CCerror(context, "Floating point result not allowed");
2443 // }
2445 stack_size++;
2454 /* Get the info saved in the swap_table */
2460 }
2462 }
2464 /* full_info should have the appropriate value. */
2469 // CCerror(context, "Internal error #4");
2473 stack_size++;
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. */
2489 }
2490 }
2491 }
2495 }
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
2510 *
2511 * returns: nothing
2512 *=======================================================================*/
2513 static void
2518 {
2553 /* FALLTHROUGH */
2564 /* The testing for the returns is handled in pop_stack() */
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 */
2582 count++;
2583 }
2592 }
2593 }
2594 }
2599 }
2608 }
2610 }
2612 }
2629 TRUE);
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 */
2643 TRUE);
2645 register_info,
2648 }
2649 }
2650 }
2653 // if (target >= context->instruction_count)
2654 /// CCerror(context, "Falling off the end of the code");
2657 FALSE);
2658 }
2659 }
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
2674 *
2675 * returns: nothing
2676 *=======================================================================*/
2677 static void
2683 bool_t isException)
2684 {
2686 register_info_type register_info_buf;
2687 stack_info_type stack_info_buf;
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 */
2705 /* This check only succeeds for hand-contrived code.
2706 * Efficiency is not an issue.
2707 */
2716 }
2717 }
2719 }
2720 }
2723 /* This check only succeeds for hand-contrived code.
2724 * Efficiency is not an issue.
2725 */
2727 new_register_count);
2732 }
2739 }
2740 }
2741 }
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 */
2757 // if (jsr_idata->operand2.i != UNKNOWN_RET_INSTRUCTION)
2758 // CCerror(context, "Multiple returns to single jsr");
2760 }
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 */
2766 ;
2775 /* Make sure the place we're returning from is legal! */
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. */
2789 else
2792 }
2801 /* ADDED FOR JSR_INFO. Is this correct?? */
2804 }
2810 }
2813 }
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
2825 *
2826 * returns: nothing
2827 *=======================================================================*/
2828 static void
2831 {
2841 /* First time at this instruction. Just copy. */
2846 // CCerror(context, "Inconsistent stack height %d != %d",
2847 // new_stack_size, stack_size);
2857 }
2858 }
2865 }
2867 FALSE);
2869 // CCerror(context, "Mismatched stack types");
2870 }
2871 }
2873 // CCerror(context, "Mismatched stack types");
2874 }
2877 }
2878 }
2879 }
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
2891 *
2892 * returns: nothing
2893 *=======================================================================*/
2894 static void
2897 {
2915 /* See if we've got new information on the register set. */
2924 /* Any register larger than new_register_count is now bogus */
2928 }
2936 }
2937 }
2940 /* We need a copy. So do it. */
2947 else
2951 }
2952 /* Some of the end items might now be bogus. This step isn't
2953 * necessary, but it may save work later. */
2956 register_count--;
2960 }
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 */
2977 /* We have a match */
2980 matches++;
2981 /* See if new_mask has bits set for "entry" that
2982 * weren't set for mask. If so, need to copy. */
2985 k--)
2990 }
2991 }
2992 }
2994 /* We need to make a copy for the new item, since either the
2995 * size has decreased, or new bits are set. */
2999 }
3015 matches++;
3018 }
3019 }
3020 }
3021 }
3022 }
3023 }
3024 }
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
3037 *
3038 * returns: nothing
3039 *=======================================================================*/
3040 static void
3043 {
3044 /* Set this_idata->and_flags &= new_and_flags
3045 this_idata->or_flags |= new_or_flags
3046 */
3058 }
3059 }
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
3068 *
3069 * returns: pointer to stack_item_type
3070 *=======================================================================*/
3073 {
3077 /* Find the length */
3088 }
3093 }
3094 }
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
3104 *
3105 * returns: pointer to mask_type
3106 *=======================================================================*/
3109 {
3118 }
3120 }
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
3132 *
3133 * returns: pointer to mask_type
3134 *=======================================================================*/
3137 {
3146 }
3151 }
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
3170 };
3173 /*=========================================================================
3174 * FUNCTION: CCinit
3175 * OVERVIEW: Initialize the context's heap.
3176 * INTERFACE:
3177 * parameters: pointer to the context_type
3178 *
3179 * returns: nothing
3180 *=======================================================================*/
3182 {
3184 /* Set context->CCroot to 0 if new == 0 to tell CCdestroy to lay off */
3188 }
3193 }
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
3201 *
3202 * returns: nothing
3203 *=======================================================================*/
3205 {
3210 }
3213 /*=========================================================================
3214 * FUNCTION: CCdestroy
3215 * OVERVIEW: Destroy the context's heap.
3216 * INTERFACE:
3217 * parameters: pointer to the context_type
3218 *
3219 * returns: nothing
3220 *=======================================================================*/
3222 {
3228 }
3229 /* These two aren't necessary. But can't hurt either */
3232 }
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
3242 *
3243 * returns: pointer to void
3244 *=======================================================================*/
3247 {
3250 /* Round CC to the size of a pointer */
3261 }
3271 }
3275 }
3276 }
3280 }
3287 }
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
3297 *
3298 * returns: char * type
3299 *=======================================================================*/
3302 {
3309 }
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
3319 *
3320 * returns: char * type
3321 *=======================================================================*/
3324 {
3330 }
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
3343 *
3344 * returns: fullinfo_type
3345 *=======================================================================*/
3346 static fullinfo_type
3348 {
3353 fullinfo_type result;
3354 /* This make recursively call us, in case of a class array */
3359 }
3360 }
3363 /*=========================================================================
3364 * FUNCTION: CCerror
3365 * OVERVIEW: Error handling
3366 * INTERFACE:
3367 * parameters: pointer to the context_type
3368 * char: pointer to format
3369 *
3370 * returns: nothing
3371 *=======================================================================*/
3372 static void
3374 {
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));
3384 }
3385 va_start(args, format);
3386 jio_vfprintf(stderr, format, args);
3387 va_end(args);
3388 jio_fprintf(stderr, "\n");
3389 exit(1);*/
3390 }
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
3401 *
3402 * returns: char
3403 *=======================================================================*/
3404 static char
3407 {
3469 array_depth++;
3480 // CCerror(context, "Out of memory");
3481 }
3482 }
3491 }
3494 }
3497 /* either not an array, or result is bogus */
3501 // if (array_depth > MAX_ARRAY_DIMENSIONS)
3502 // CCerror(context, "Array with too many dimensions");
3504 array_depth,
3507 }
3508 }
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
3517 *
3518 * returns: fullinfo_type
3519 *=======================================================================*/
3520 static fullinfo_type
3522 {
3533 }
3534 }
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
3545 *
3546 * returns: boolean type
3547 *=======================================================================*/
3550 {
3552 }
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.
3564 *
3565 * INTERFACE:
3566 * parameters: pointer to the context_type
3567 * fullinfo_type: value
3568 * fullinfo_type: target
3569 * bool_t for_assignment
3570 *
3571 * returns: fullinfo_type
3572 *=======================================================================*/
3573 static fullinfo_type
3576 bool_t for_assignment)
3577 {
3579 /* If they're identical, clearly just return what we've got */
3581 }
3583 /* Both must be either arrays or objects to go further */
3589 /* If either is NULL, return the other. */
3595 /* If either is java/lang/Object, that's the result. */
3599 /* Minor hack. For assignments, Interface := Object, return Interface
3600 * rather than Object, so that isAssignableTo() will get the right
3601 * result. */
3607 }
3609 }
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 */
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 */
3625 dimen_value--;
3628 }
3632 dimen_target--;
3634 }
3635 /* Both are now objects or arrays of some sort of object type */
3637 /* Arrays of the same dimension. Merge their base types. */
3640 fullinfo_type result_base =
3642 for_assignment);
3644 /* bogus in, bogus out */
3649 /* Arrays of different sizes. Return Object, with a dimension
3650 * of the smaller of the two.
3651 */
3654 }
3656 /* Both are non-array objects. Neither is java/lang/Object or NULL */
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. */
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 */
3684 }
3685 }
3687 }
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. */
3694 /* Optimization. If either hits the other when going up looking
3695 * for a parent, then might as well return the parent immediately */
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 */
3710 }
3714 }
3716 /* Walk both up, maintaining equal depth, until a join is found. We
3717 * know that we will find one. */
3721 }
3722 /* Get the info for this guy. We know its cb_value, so we should
3723 * fill that in, while we're at it. */
3729 }
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
3740 *
3741 * returns: pointer to the ClassClass type
3742 *=======================================================================*/
3745 {
3755 // if (cb == 0)
3756 // CCerror(context, "Cannot find class %s", classname);
3758 }
3759 }
3762 /*=========================================================================
3763 * The functions below are for debugging the preverifier
3764 *=======================================================================*/
3766 #ifdef DEBUG_VERIFIER
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
3778 *
3779 * returns: nothing
3780 *=======================================================================*/
3781 static void
3783 {
3792 }
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
3803 *
3804 * returns: nothing
3805 *=======================================================================*/
3806 static void
3808 {
3830 }
3832 }
3833 }
3834 }
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
3845 *
3846 * returns: nothing
3847 *=======================================================================*/
3848 static void
3850 {
3853 }
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
3865 *
3866 * returns: nothing
3867 *=======================================================================*/
3868 static void
3870 {
3902 }
3903 }
3918 fullinfo_type real_type =
3923 }
3931 }
3934 }
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
3945 *
3946 * returns: nothing
3947 *=======================================================================*/
3948 static void
3950 {
3967 }