1 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: typecheck.c 3369 2005-10-06 10:29:43Z edwin $
37 What's the purpose of the `typechecker`?
38 ----------------------------------------
40 The typechecker analyses (the intermediate repr. of) the bytecode of
41 each method and ensures that for each instruction the values on the
42 stack and in local variables are of the correct type whenever the
43 instruction is executed.
45 type checking is a mandatory part of bytecode verification.
48 How does the typechecker work?
49 ------------------------------
51 The JVM stack and the local variables are not statically typed, so the
52 typechecker has to *infer* the static types of stack slots and local
53 variables at each point of the method. The JVM spec imposes a lot of
54 restrictions on the bytecode in order to guarantee that this is always
57 Basically the typechecker solves the data flow equations of the method.
58 This is done in the usual way for a forward data flow analysis: Starting
59 from the entry point of the method the typechecker follows the CFG and
60 records the type of each stack slot and local variable at each point[1].
61 When two or more control flow paths merge at a point, the union of the
62 types for each slot/variable is taken. The algorithm continues to follow
63 all possible paths[2] until the recorded types do not change anymore (ie.
64 the equations have been solved).
66 If the solution has been reached and the resulting types are valid for
67 all instructions, then type checking terminates with success, otherwise
68 an exception is thrown.
71 Why is this code so damn complicated?
72 -------------------------------------
74 Short answer: The devil's in the details.
76 While the basic operation of the typechecker is no big deal, there are
77 many properties of Java bytecode which make type checking hard. Some of
78 them are not even addressed in the JVM spec. Some problems and their
81 *) Finding a good representation of the union of two reference types is
82 difficult because of multiple inheritance of interfaces.
84 Solution: The typeinfo system can represent such "merged" types by a
85 list of proper subclasses of a class. Example:
87 typeclass=java.lang.Object merged={ InterfaceA, InterfaceB }
89 represents the result of merging two interface types "InterfaceA"
92 *) When the code of a method is verified, there may still be unresolved
93 references to classes/methods/fields in the code, which we may not force
94 to be resolved eagerly. (A similar problem arises because of the special
95 checks for protected members.)
97 Solution: The typeinfo system knows how to deal with unresolved
98 class references. Whenever a check has to be performed for an
99 unresolved type, the type is annotated with constraints representing
100 the check. Later, when the type is resolved, the constraints are
101 checked. (See the constrain_unresolved_... and the resolve_...
104 *) The boundaries of jsr subroutines are not well-defined. For a given
105 instruction it may be impossible to tell whether it is part of a
106 subroutine, or to which subroutine it belongs.
108 Solution: The typechecker implements a method developed by
109 Alessandro Coglio[4] which treats each returnAddress as a distinct
110 type that is not merged with other returnAddresses. This way, when a
111 RET instruction is reached, we know exactly which types to propagate
112 to which return target among the possible targets of the RET. The
113 downside of this method is, that for each slot/variable we must
114 store not just one type, but one type *for each possible use of the
115 returnAddresses* that currently are in a slot/variable.[5]
117 *) Checks for uninitialized object instances are hard because after the
118 invocation of <init> on an uninitialized object *all* slots/variables
119 referring to this object (and exactly those slots/variables) must be
120 marked as initialized.
122 Solution: The JVM spec describes a solution, which has been
123 implemented in this typechecker.
128 [1] Actually only the types of slots/variables at the start of each
129 basic block are remembered. Within a basic block the algorithm only keeps
130 the types of the slots/variables for the "current" instruction which is
133 [2] Actually the algorithm iterates through the basic block list until
134 there are no more changes. Theoretically it would be wise to sort the
135 basic blocks topologically beforehand, but the number of average/max
136 iterations observed is so low, that this was not deemed necessary.
138 [3] This is similar to a method proposed by: Alessandro Coglio et al., A
139 Formal Specification of Java Class Loading, Technical Report, Kestrel
140 Institute April 2000, revised July 2000
141 http://www.kestrel.edu/home/people/coglio/loading.pdf
142 An important difference is that Coglio's subtype constraints are checked
143 after loading, while our constraints are checked when the field/method
144 is accessed for the first time, so we can guarantee lexically correct
147 [4] Alessandro Coglio, Simple Verification Technique for Complex Java
148 Bytecode Subroutines, 4th ECOOP Workshop on Formal Techniques for
149 Java-like Programs, June 2002
150 http://www.kestrel.edu/home/people/coglio/ftjp02.pdf
152 [5] This is a major source of code complexity. The main data structures
153 dealing with this are the "typevector set" and the typestack. The
154 "typevector set" is a set of alternative typevectors, such that each
155 typevector specifies the types of the local variables for a single
156 combination of returnAddresses used. Thus we support full polymorphism
157 of subroutines over the types of local variables. The typestack,
158 however, does not support polymorphism, both for historical and JVM-spec
159 reasons. A slot of the typestack may, however, contain multiple
160 alternative returnAddresses, which is realized by a linked list hanging
161 of the typeinfo of the stack slot.
168 #include "vm/types.h"
170 #include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
172 #ifdef CACAO_TYPECHECK
174 #include "mm/memory.h"
175 #include "toolbox/logging.h"
176 #include "native/native.h"
177 #include "vm/builtin.h"
178 #include "vm/jit/patcher.h"
179 #include "vm/loader.h"
180 #include "vm/options.h"
181 #include "vm/tables.h"
182 #include "vm/jit/jit.h"
183 #include "vm/jit/stack.h"
184 #include "vm/access.h"
185 #include "vm/resolve.h"
188 /****************************************************************************/
190 /****************************************************************************/
192 #ifdef TYPECHECK_DEBUG
193 #define TYPECHECK_ASSERT(cond) assert(cond)
195 #define TYPECHECK_ASSERT(cond)
198 #ifdef TYPECHECK_VERBOSE_OPT
199 bool typecheckverbose = false;
200 #define DOLOG(action) do { if (typecheckverbose) {action;} } while(0)
202 #define DOLOG(action)
205 #ifdef TYPECHECK_VERBOSE
206 #define TYPECHECK_VERBOSE_IMPORTANT
207 #define LOG(str) DOLOG(log_text(str))
208 #define LOG1(str,a) DOLOG(dolog(str,a))
209 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
210 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
211 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
212 #ifdef TYPEINFO_DEBUG
213 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(get_logfile(),(info));log_plain("\n");} while(0))
215 #define LOGINFO(info)
216 #define typevectorset_print(x,y,z)
218 #define LOGFLUSH DOLOG(fflush(get_logfile()))
219 #define LOGNL DOLOG(log_plain("\n"))
220 #define LOGSTR(str) DOLOG(log_plain(str))
221 #define LOGSTR1(str,a) DOLOG(dolog_plain(str,a))
222 #define LOGSTR2(str,a,b) DOLOG(dolog_plain(str,a,b))
223 #define LOGSTR3(str,a,b,c) DOLOG(dolog_plain(str,a,b,c))
224 #define LOGSTRu(utf) DOLOG(log_plain_utf(utf))
225 #define LOGNAME(c) DOLOG(do {log_plain_utf(IS_CLASSREF(c) ? c.ref->name : c.cls->name);} while(0))
229 #define LOG2(str,a,b)
230 #define LOG3(str,a,b,c)
231 #define LOGIF(cond,str)
232 #define LOGINFO(info)
236 #define LOGSTR1(str,a)
237 #define LOGSTR2(str,a,b)
238 #define LOGSTR3(str,a,b,c)
243 #ifdef TYPECHECK_VERBOSE_IMPORTANT
244 #define LOGimp(str) DOLOG(log_text(str))
245 #define LOGimpSTR(str) DOLOG(log_plain(str))
246 #define LOGimpSTRu(utf) DOLOG(log_plain_utf(utf))
249 #define LOGimpSTR(str)
250 #define LOGimpSTRu(utf)
253 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
259 typestack_print(FILE *file,stackptr stack)
261 #ifdef TYPEINFO_DEBUG
263 /*fprintf(file,"<%p>",stack);*/
264 typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
266 if (stack) fprintf(file," ");
273 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
275 fprintf(file,"Stack: ");
276 typestack_print(file,instack);
277 fprintf(file," Locals:");
278 typevectorset_print(file,localset,size);
283 /****************************************************************************/
285 /****************************************************************************/
287 #ifdef TYPECHECK_DEBUG
288 /*#define TYPECHECK_STATISTICS*/
291 #ifdef TYPECHECK_STATISTICS
292 #define STAT_ITERATIONS 10
293 #define STAT_BLOCKS 10
294 #define STAT_LOCALS 16
296 static int stat_typechecked = 0;
297 static int stat_typechecked_jsr = 0;
298 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
299 static int stat_reached = 0;
300 static int stat_copied = 0;
301 static int stat_merged = 0;
302 static int stat_merging_changed = 0;
303 static int stat_backwards = 0;
304 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
305 static int stat_locals[STAT_LOCALS+1] = { 0 };
306 static int stat_ins = 0;
307 static int stat_ins_field = 0;
308 static int stat_ins_invoke = 0;
309 static int stat_ins_primload = 0;
310 static int stat_ins_aload = 0;
311 static int stat_ins_builtin = 0;
312 static int stat_ins_builtin_gen = 0;
313 static int stat_ins_branch = 0;
314 static int stat_ins_switch = 0;
315 static int stat_ins_unchecked = 0;
316 static int stat_handlers_reached = 0;
317 static int stat_savedstack = 0;
319 #define TYPECHECK_COUNT(cnt) (cnt)++
320 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
321 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
323 if ((val) < (limit)) (array)[val]++; \
324 else (array)[limit]++; \
327 static void print_freq(FILE *file,int *array,int limit)
330 for (i=0; i<limit; ++i)
331 fprintf(file," %3d: %8d\n",i,array[i]);
332 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
335 void typecheck_print_statistics(FILE *file) {
336 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
337 fprintf(file,"methods with JSR : %8d\n",stat_typechecked_jsr);
338 fprintf(file,"reached blocks : %8d\n",stat_reached);
339 fprintf(file,"copied states : %8d\n",stat_copied);
340 fprintf(file,"merged states : %8d\n",stat_merged);
341 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
342 fprintf(file,"backwards branches : %8d\n",stat_backwards);
343 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
344 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
345 fprintf(file,"instructions : %8d\n",stat_ins);
346 fprintf(file," field access : %8d\n",stat_ins_field);
347 fprintf(file," invocations : %8d\n",stat_ins_invoke);
348 fprintf(file," load primitive : %8d\n",stat_ins_primload);
349 fprintf(file," load address : %8d\n",stat_ins_aload);
350 fprintf(file," builtins : %8d\n",stat_ins_builtin);
351 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
352 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
353 fprintf(file," branches : %8d\n",stat_ins_branch);
354 fprintf(file," switches : %8d\n",stat_ins_switch);
355 fprintf(file,"iterations used:\n");
356 print_freq(file,stat_iterations,STAT_ITERATIONS);
357 fprintf(file,"basic blocks per method / 10:\n");
358 print_freq(file,stat_blocks,STAT_BLOCKS);
359 fprintf(file,"locals:\n");
360 print_freq(file,stat_locals,STAT_LOCALS);
365 #define TYPECHECK_COUNT(cnt)
366 #define TYPECHECK_COUNTIF(cond,cnt)
367 #define TYPECHECK_COUNT_FREQ(array,val,limit)
370 /****************************************************************************/
371 /* MACROS FOR THROWING EXCEPTIONS */
372 /****************************************************************************/
374 #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
376 *exceptionptr = new_verifyerror((m), (msg)); \
380 #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
381 #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
383 /****************************************************************************/
384 /* MACROS FOR STACK SLOT TYPE CHECKING */
385 /****************************************************************************/
387 #define TYPECHECK_CHECK_TYPE(sp,tp,msg) \
389 if ((sp)->type != (tp)) { \
390 *exceptionptr = new_verifyerror(state->m, (msg)); \
395 #define TYPECHECK_INT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_INT,"Expected to find integer on stack")
396 #define TYPECHECK_LNG(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_LNG,"Expected to find long on stack")
397 #define TYPECHECK_FLT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_FLT,"Expected to find float on stack")
398 #define TYPECHECK_DBL(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_DBL,"Expected to find double on stack")
399 #define TYPECHECK_ADR(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_ADR,"Expected to find object on stack")
401 /****************************************************************************/
402 /* VERIFIER STATE STRUCT */
403 /****************************************************************************/
405 /* verifier_state - This structure keeps the current state of the */
406 /* bytecode verifier for passing it between verifier functions. */
408 typedef struct verifier_state {
409 stackptr curstack; /* input stack top for current instruction */
410 instruction *iptr; /* pointer to current instruction */
411 basicblock *bptr; /* pointer to current basic block */
413 methodinfo *m; /* the current method */
414 codegendata *cd; /* codegendata for current method */
415 registerdata *rd; /* registerdata for current method */
417 s4 numlocals; /* number of local variables */
418 s4 validlocals; /* number of Java-accessible locals */
419 void *localbuf; /* local variable types for each block start */
420 typevector *localset; /* typevector set for local variables */
421 typedescriptor returntype; /* return type of the current method */
423 stackptr savedstackbuf; /* buffer for saving the stack */
424 stackptr savedstack; /* saved instack of current block */
426 exceptiontable **handlers; /* active exception handlers */
427 stackelement excstack; /* instack for exception handlers */
429 bool repeat; /* if true, blocks are iterated over again */
430 bool initmethod; /* true if this is an "<init>" method */
431 bool jsrencountered; /* true if we there was a JSR */
434 /****************************************************************************/
435 /* TYPESTACK MACROS AND FUNCTIONS */
437 /* These macros and functions act on the 'type stack', which is a shorthand */
438 /* for the types of the stackslots of the current stack. The type of a */
439 /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
440 /* -- by the typeinfo of the slot. The only thing that makes the type stack */
441 /* more complicated are returnAddresses of local subroutines, because a */
442 /* single stack slot may contain a set of more than one possible return */
443 /* address. This is handled by 'return address sets'. A return address set */
444 /* is kept as a linked list dangling off the typeinfo of the stack slot. */
445 /****************************************************************************/
447 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
448 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
450 #define TYPESTACK_IS_REFERENCE(sptr) \
451 TYPE_IS_REFERENCE((sptr)->type,(sptr)->typeinfo)
453 #define TYPESTACK_RETURNADDRESSSET(sptr) \
454 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
456 #define RETURNADDRESSSET_SEEK(set,pos) \
457 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
459 #define TYPESTACK_COPY(sp,copy) \
460 do {for(; sp; sp=sp->prev, copy=copy->prev) { \
461 copy->type = sp->type; \
462 TYPEINFO_COPY(sp->typeinfo,copy->typeinfo); \
465 /* typestack_copy **************************************************************
467 Copy the types on the given stack to the destination stack.
469 This function does a straight forward copy except for returnAddress types.
470 For returnAddress slots only the return addresses corresponding to
471 typevectors in the SELECTED set are copied.
474 state............current verifier state
475 y................stack with types to copy
476 selected.........set of selected typevectors
479 *dst.............the destination stack
482 true.............success
483 false............an exception has been thrown
485 *******************************************************************************/
488 typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selected)
491 typeinfo_retaddr_set *sety;
492 typeinfo_retaddr_set *new;
493 typeinfo_retaddr_set **next;
496 for (;dst; dst=dst->prev, y=y->prev) {
498 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
501 if (dst->type != y->type) {
502 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
505 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
506 if (dst->type == TYPE_ADDRESS) {
507 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
508 /* We copy the returnAddresses from the selected
511 LOG("copying returnAddress");
512 sety = TYPESTACK_RETURNADDRESSSET(y);
514 for (k=0,sel=selected; sel; sel=sel->alt) {
515 LOG1("selected k=%d",sel->k);
520 *next = DNEW(typeinfo_retaddr_set);
521 (*next)->addr = sety->addr;
522 next = &((*next)->alt);
525 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
528 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
533 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
539 /* typestack_put_retaddr *******************************************************
541 Put a returnAddress into a stack slot.
543 The stack slot receives a set of return addresses with as many members as
544 there are typevectors in the local variable set.
547 retaddr..........the returnAddress to set (a basicblock *)
548 loc..............the local variable typevector set
551 *dst.............the destination stack slot
553 *******************************************************************************/
556 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
558 TYPECHECK_ASSERT(dst->type == TYPE_ADDRESS);
560 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
561 for (;loc; loc=loc->alt) {
562 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
564 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
565 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
569 /* typestack_collapse **********************************************************
571 Collapse the given stack by shortening all return address sets to a single
575 *dst.............the destination stack to collapse
577 *******************************************************************************/
580 typestack_collapse(stackptr dst)
582 for (; dst; dst = dst->prev) {
583 if (TYPESTACK_IS_RETURNADDRESS(dst))
584 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
588 /* typestack_merge *************************************************************
590 Merge the types on one stack into the destination stack.
593 state............current state of the verifier
594 dst..............the destination stack
595 y................the second stack
598 *dst.............receives the result of the stack merge
601 typecheck_TRUE...*dst has been modified
602 typecheck_FALSE..*dst has not been modified
603 typecheck_FAIL...an exception has been thrown
605 *******************************************************************************/
607 static typecheck_result
608 typestack_merge(verifier_state *state,stackptr dst,stackptr y)
611 bool changed = false;
613 for (; dst; dst = dst->prev, y=y->prev) {
615 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
616 return typecheck_FAIL;
618 if (dst->type != y->type) {
619 *exceptionptr = new_verifyerror(state->m,"Stack type mismatch");
620 return typecheck_FAIL;
622 if (dst->type == TYPE_ADDRESS) {
623 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
624 /* dst has returnAddress type */
625 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
626 *exceptionptr = new_verifyerror(state->m,"Merging returnAddress with reference");
627 return typecheck_FAIL;
631 /* dst has reference type */
632 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
633 *exceptionptr = new_verifyerror(state->m,"Merging reference with returnAddress");
634 return typecheck_FAIL;
636 r = typeinfo_merge(state->m,&(dst->typeinfo),&(y->typeinfo));
637 if (r == typecheck_FAIL)
644 *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
645 return typecheck_FAIL;
650 /* typestack_add ***************************************************************
652 Add the return addresses in the given stack at a given k-index to the
653 corresponding return address sets in the destination stack.
656 dst..............the destination stack
657 y................the second stack
658 ky...............the k-index which should be selected from the Y stack
661 *dst.............receives the result of adding the addresses
663 *******************************************************************************/
666 typestack_add(stackptr dst,stackptr y,int ky)
668 typeinfo_retaddr_set *setd;
669 typeinfo_retaddr_set *sety;
671 for (; dst; dst = dst->prev, y=y->prev) {
672 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
673 setd = TYPESTACK_RETURNADDRESSSET(dst);
674 sety = TYPESTACK_RETURNADDRESSSET(y);
675 RETURNADDRESSSET_SEEK(sety,ky);
678 setd->alt = DNEW(typeinfo_retaddr_set);
679 setd->alt->addr = sety->addr;
680 setd->alt->alt = NULL;
685 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
687 typestack_separable_with(stackptr a,stackptr b,int kb)
689 typeinfo_retaddr_set *seta;
690 typeinfo_retaddr_set *setb;
692 for (; a; a = a->prev, b = b->prev) {
694 if (TYPESTACK_IS_RETURNADDRESS(a)) {
695 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
696 seta = TYPESTACK_RETURNADDRESSSET(a);
697 setb = TYPESTACK_RETURNADDRESSSET(b);
698 RETURNADDRESSSET_SEEK(setb,kb);
700 for (;seta;seta=seta->alt)
701 if (seta->addr != setb->addr) return true;
704 TYPECHECK_ASSERT(!b);
708 /* 'a' and 'b' are assumed to have passed typestack_canmerge! */
710 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
712 typeinfo_retaddr_set *seta;
713 typeinfo_retaddr_set *setb;
715 for (; a; a = a->prev, b = b->prev) {
717 if (TYPESTACK_IS_RETURNADDRESS(a)) {
718 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
719 seta = TYPESTACK_RETURNADDRESSSET(a);
720 setb = TYPESTACK_RETURNADDRESSSET(b);
721 RETURNADDRESSSET_SEEK(seta,ka);
722 RETURNADDRESSSET_SEEK(setb,kb);
724 if (seta->addr != setb->addr) return true;
727 TYPECHECK_ASSERT(!b);
731 /****************************************************************************/
732 /* TYPESTATE FUNCTIONS */
734 /* These functions act on the 'type state', which comprises: */
735 /* - the types of the stack slots of the current stack */
736 /* - the set of type vectors describing the local variables */
737 /****************************************************************************/
739 /* typestate_merge *************************************************************
741 Merge the types of one state into the destination state.
744 state............current state of the verifier
745 deststack........the destination stack
746 destloc..........the destination set of local variable typevectors
747 ystack...........the second stack
748 yloc.............the second set of local variable typevectors
751 *deststack.......receives the result of the stack merge
752 *destloc.........receives the result of the local variable merge
755 typecheck_TRUE...destination state has been modified
756 typecheck_FALSE..destination state has not been modified
757 typecheck_FAIL...an exception has been thrown
759 *******************************************************************************/
761 static typecheck_result
762 typestate_merge(verifier_state *state,
763 stackptr deststack,typevector *destloc,
764 stackptr ystack,typevector *yloc)
766 typevector *dvec,*yvec;
768 bool changed = false;
772 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
773 LOGSTR("ystack: "); DOLOG(typestack_print(get_logfile(),ystack)); LOGNL;
774 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
775 LOGSTR("yloc : "); DOLOG(typevectorset_print(get_logfile(),yloc,state->numlocals)); LOGNL;
778 /* The stack is always merged. If there are returnAddresses on
779 * the stack they are ignored in this step. */
781 r = typestack_merge(state,deststack,ystack);
782 if (r == typecheck_FAIL)
786 /* If there have not been any JSRs we just have a single typevector merge */
787 if (!state->jsrencountered) {
788 r = typevector_merge(state->m,destloc,yloc,state->numlocals);
789 if (r == typecheck_FAIL)
794 for (yvec=yloc; yvec; yvec=yvec->alt) {
797 /* Check if the typestates (deststack,destloc) will be
798 * separable when (ystack,yvec) is added. */
800 if (!typestack_separable_with(deststack,ystack,ky)
801 && !typevectorset_separable_with(destloc,yvec,state->numlocals))
803 /* No, the resulting set won't be separable, thus we
804 * may merge all states in (deststack,destloc) and
807 typestack_collapse(deststack);
808 if (typevectorset_collapse(state->m,destloc,state->numlocals) == typecheck_FAIL)
809 return typecheck_FAIL;
810 if (typevector_merge(state->m,destloc,yvec,state->numlocals) == typecheck_FAIL)
811 return typecheck_FAIL;
814 /* Yes, the resulting set will be separable. Thus we check
815 * if we may merge (ystack,yvec) with a single state in
816 * (deststack,destloc). */
818 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
819 if (!typestack_separable_from(ystack,ky,deststack,kd)
820 && !typevector_separable_from(yvec,dvec,state->numlocals))
822 /* The typestate (ystack,yvec) is not separable from
823 * (deststack,dvec) by any returnAddress. Thus we may
824 * merge the states. */
826 r = typevector_merge(state->m,dvec,yvec,state->numlocals);
827 if (r == typecheck_FAIL)
835 /* The typestate (ystack,yvec) is separable from all typestates
836 * (deststack,destloc). Thus we must add this state to the
839 typestack_add(deststack,ystack,ky);
840 typevectorset_add(destloc,yvec,state->numlocals);
849 LOGSTR("dstack: "); DOLOG(typestack_print(get_logfile(),deststack)); LOGNL;
850 LOGSTR("dloc : "); DOLOG(typevectorset_print(get_logfile(),destloc,state->numlocals)); LOGNL;
856 /* typestate_reach *************************************************************
858 Reach a destination block and propagate stack and local variable types
861 state............current state of the verifier
862 destblock........destination basic block
863 ystack...........stack to propagate
864 yloc.............set of local variable typevectors to propagate
867 state->repeat....set to true if the verifier must iterate again
868 over the basic blocks
871 true.............success
872 false............an exception has been thrown
874 *******************************************************************************/
877 typestate_reach(verifier_state *state,
878 basicblock *destblock,
879 stackptr ystack,typevector *yloc)
883 bool changed = false;
886 LOG1("reaching block L%03d",destblock->debug_nr);
887 TYPECHECK_COUNT(stat_reached);
889 destidx = destblock - state->cd->method->basicblocks;
890 destloc = MGET_TYPEVECTOR(state->localbuf,destidx,state->numlocals);
892 /* When branching backwards we have to check for uninitialized objects */
894 if (destblock <= state->bptr) {
898 /* XXX FIXME FOR INLINING */
901 TYPECHECK_COUNT(stat_backwards);
903 for (sp = ystack; sp; sp=sp->prev)
904 if (sp->type == TYPE_ADR &&
905 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
906 /*printf("current: %d, dest: %d\n", state->bptr->debug_nr, destblock->debug_nr);*/
907 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object on stack");
911 for (i=0; i<state->numlocals; ++i)
912 if (yloc->td[i].type == TYPE_ADR &&
913 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info)) {
914 *exceptionptr = new_verifyerror(state->m,"Branching backwards with uninitialized object in local variable");
920 if (destblock->flags == BBTYPECHECK_UNDEF) {
921 /* The destblock has never been reached before */
923 TYPECHECK_COUNT(stat_copied);
924 LOG1("block (index %04d) reached first time",destidx);
926 if (!typestack_copy(state,destblock->instack,ystack,yloc))
928 COPY_TYPEVECTORSET(yloc,destloc,state->numlocals);
932 /* The destblock has already been reached before */
934 TYPECHECK_COUNT(stat_merged);
935 LOG1("block (index %04d) reached before",destidx);
937 r = typestate_merge(state,destblock->instack,destloc,ystack,yloc);
938 if (r == typecheck_FAIL)
941 TYPECHECK_COUNTIF(changed,stat_merging_changed);
946 destblock->flags = BBTYPECHECK_REACHED;
947 if (destblock <= state->bptr) {
949 state->repeat = true;
955 /* typestate_ret ***************************************************************
957 Reach the destinations of a RET instruction.
960 state............current state of the verifier
961 retindex.........index of local variable containing the returnAddress
964 state->repeat....set to true if the verifier must iterate again
965 over the basic blocks
968 true.............success
969 false............an exception has been thrown
971 *******************************************************************************/
974 typestate_ret(verifier_state *state,int retindex)
977 typevector *selected;
978 basicblock *destblock;
980 for (yvec=state->localset; yvec; ) {
981 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex])) {
982 *exceptionptr = new_verifyerror(state->m,"Illegal instruction: RET on non-returnAddress");
986 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
988 selected = typevectorset_select(&yvec,retindex,destblock);
990 if (!typestate_reach(state,destblock,state->curstack,selected))
996 /****************************************************************************/
997 /* MACROS FOR LOCAL VARIABLE CHECKING */
998 /****************************************************************************/
1000 #define INDEX_ONEWORD(num) \
1001 do { if((num)<0 || (num)>=state->validlocals) \
1002 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
1003 #define INDEX_TWOWORD(num) \
1004 do { if((num)<0 || ((num)+1)>=state->validlocals) \
1005 TYPECHECK_VERIFYERROR_bool("Invalid local variable index"); } while (0)
1007 #define STORE_ONEWORD(num,type) \
1008 do {typevectorset_store(state->localset,num,type,NULL);} while(0)
1010 #define STORE_TWOWORD(num,type) \
1011 do {typevectorset_store_twoword(state->localset,num,type);} while(0)
1014 #ifdef TYPECHECK_VERBOSE
1015 #define WORDCHECKFAULT \
1017 dolog("localset->td index: %ld\ninstruction belongs to:%s.%s, outermethod:%s.%s\n", \
1018 state->iptr->op1,state->iptr->method->class->name->text, \
1019 state->iptr->method->name->text,state->m->class->name->text,state->m->name->text); \
1020 show_icmd(state->iptr++, false); \
1021 show_icmd(state->iptr, false); \
1024 #define WORDCHECKFAULT
1028 #define CHECK_ONEWORD(num,tp) \
1029 do {TYPECHECK_COUNT(stat_ins_primload); \
1030 if (state->jsrencountered) { \
1031 if (!typevectorset_checktype(state->localset,num,tp)) { \
1033 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
1037 if (state->localset->td[num].type != tp) { \
1038 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
1044 #define CHECK_TWOWORD(num,type) \
1045 do {TYPECHECK_COUNT(stat_ins_primload); \
1046 if (!typevectorset_checktype(state->localset,num,type)) { \
1048 TYPECHECK_VERIFYERROR_bool("Variable type mismatch"); \
1053 /****************************************************************************/
1055 /****************************************************************************/
1057 #define COPYTYPE(source,dest) \
1058 {if ((source)->type == TYPE_ADR) \
1059 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
1061 #define ISBUILTIN(v) (bte->fp == (functionptr) (v))
1063 /* TYPECHECK_LEAVE: executed when the method is exited non-abruptly
1065 * class........class of the current method
1066 * state........verifier state
1068 #define TYPECHECK_LEAVE \
1070 if (state->initmethod && state->m->class != class_java_lang_Object) { \
1071 /* check the marker variable */ \
1072 LOG("Checking <init> marker"); \
1073 if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))\
1074 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'"); \
1078 /* verify_invocation ***********************************************************
1080 Verify an ICMD_INVOKE* instruction.
1083 state............the current state of the verifier
1086 true.............successful verification,
1087 false............an exception has been thrown.
1089 *******************************************************************************/
1092 verify_invocation(verifier_state *state)
1094 unresolved_method *um; /* struct describing the called method */
1095 constant_FMIref *mref; /* reference to the called method */
1096 methoddesc *md; /* descriptor of the called method */
1097 bool specialmethod; /* true if a <...> method is called */
1098 int opcode; /* invocation opcode */
1099 bool callinginit; /* true if <init> is called */
1101 classref_or_classinfo initclass;
1103 stackelement *stack; /* temporary stack pointer */
1104 stackelement *dst; /* result stack of the invocation */
1105 int i; /* counter */
1106 u1 rtype; /* return type of called method */
1108 um = (unresolved_method *) state->iptr[0].target;
1109 mref = um->methodref;
1110 md = mref->parseddesc.md;
1111 specialmethod = (mref->name->text[0] == '<');
1112 opcode = state->iptr[0].opc;
1113 dst = state->iptr->dst;
1115 /* prevent compiler warnings */
1119 /* check whether we are calling <init> */
1121 callinginit = (opcode == ICMD_INVOKESPECIAL && mref->name == utf_init);
1122 if (specialmethod && !callinginit)
1123 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
1125 /* allocate parameters if necessary */
1128 if (!descriptor_params_from_paramtypes(md,
1129 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
1132 /* check parameter types */
1134 stack = state->curstack;
1135 i = md->paramcount; /* number of parameters including 'this'*/
1138 td = md->paramtypes + i;
1139 if (stack->type != td->type)
1140 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
1141 if (stack->type == TYPE_ADR) {
1142 LOGINFO(&(stack->typeinfo));
1143 if (i==0 && callinginit)
1145 /* first argument to <init> method */
1146 if (!TYPEINFO_IS_NEWOBJECT(stack->typeinfo))
1147 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
1149 /* get the address of the NEW instruction */
1150 LOGINFO(&(stack->typeinfo));
1151 ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo);
1153 initclass = CLASSREF_OR_CLASSINFO(ins[-1].val.a);
1155 initclass.cls = state->m->class;
1156 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
1162 stack = stack->prev;
1165 LOG("checking return type");
1166 rtype = md->returntype.type;
1167 if (rtype != TYPE_VOID) {
1168 if (rtype != dst->type)
1169 TYPECHECK_VERIFYERROR_bool("Return type mismatch in method invocation");
1170 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1175 LOG("replacing uninitialized object");
1176 /* replace uninitialized object type on stack */
1179 if (stack->type == TYPE_ADR
1180 && TYPEINFO_IS_NEWOBJECT(stack->typeinfo)
1181 && TYPEINFO_NEWOBJECT_INSTRUCTION(stack->typeinfo) == ins)
1183 LOG("replacing uninitialized type on stack");
1185 /* If this stackslot is in the instack of
1186 * this basic block we must save the type(s)
1187 * we are going to replace.
1189 if (stack <= state->bptr->instack && !state->savedstack)
1193 LOG("saving input stack types");
1194 if (!state->savedstackbuf) {
1195 LOG("allocating savedstack buffer");
1196 state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
1197 state->savedstackbuf->prev = NULL;
1198 for (i = 1; i < state->cd->maxstack; ++i)
1199 state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
1201 sp = state->savedstack = state->bptr->instack;
1202 copy = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
1203 TYPESTACK_COPY(sp,copy);
1206 if (!typeinfo_init_class(&(stack->typeinfo),initclass))
1209 stack = stack->prev;
1211 /* replace uninitialized object type in locals */
1212 if (!typevectorset_init_object(state->localset,ins,initclass,state->numlocals))
1215 /* initializing the 'this' reference? */
1218 TYPECHECK_ASSERT(state->initmethod);
1219 /* { we are initializing the 'this' reference } */
1220 /* must be <init> of current class or direct superclass */
1221 /* the current class is linked, so must be its superclass. thus we can be */
1222 /* sure that resolving will be trivial. */
1223 if (!resolve_classref(state->m,mref->classref,resolveLazy,false,true,&cls))
1224 return false; /* exception */
1226 /* if lazy resolving did not succeed, it's not one of the allowed classes */
1227 /* otherwise we check it directly */
1228 if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
1229 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
1232 /* set our marker variable to type int */
1233 LOG("setting <init> marker");
1234 typevectorset_store(state->localset,state->numlocals-1,TYPE_INT,NULL);
1237 /* { we are initializing an instance created with NEW } */
1238 if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mref->classref->name) {
1239 TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
1244 /* record subtype constraints for parameters */
1246 if (!constrain_unresolved_method(um,state->m->class,state->m,state->iptr,state->curstack))
1247 return false; /* XXX maybe wrap exception */
1249 /* try to resolve the method lazily */
1251 if (!resolve_method(um,resolveLazy,(methodinfo **) &(state->iptr[0].val.a)))
1257 /* verify_generic_builtin ******************************************************
1259 Verify the call of a generic builtin method.
1262 state............the current state of the verifier
1265 true.............successful verification,
1266 false............an exception has been thrown.
1268 *******************************************************************************/
1271 verify_generic_builtin(verifier_state *state)
1273 builtintable_entry *bte;
1279 TYPECHECK_COUNT(stat_ins_builtin_gen);
1281 bte = (builtintable_entry *) state->iptr[0].val.a;
1285 /* check the types of the arguments on the stack */
1287 sp = state->curstack;
1288 for (i--; i >= 0; i--) {
1289 if (sp->type != md->paramtypes[i].type) {
1290 TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
1293 #ifdef TYPECHECK_DEBUG
1294 /* generic builtins may only take primitive types and java.lang.Object references */
1295 if (sp->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
1296 *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
1304 /* check the return type */
1306 rtype = md->returntype.type;
1307 if (rtype != TYPE_VOID) {
1310 dst = state->iptr->dst;
1311 if (rtype != dst->type)
1312 TYPECHECK_VERIFYERROR_bool("Return type mismatch in generic builtin invocation");
1313 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1320 /* verify_builtin **************************************************************
1322 Verify the call of a builtin method.
1325 state............the current state of the verifier
1328 true.............successful verification,
1329 false............an exception has been thrown.
1331 *******************************************************************************/
1334 verify_builtin(verifier_state *state)
1336 builtintable_entry *bte;
1337 classref_or_classinfo cls;
1338 stackptr dst; /* output stack of current instruction */
1340 bte = (builtintable_entry *) state->iptr[0].val.a;
1341 dst = state->iptr->dst;
1343 /* XXX this is an ugly if-chain but twisti did not want a function */
1344 /* pointer in builtintable_entry for this, so here you go.. ;) */
1346 if (ISBUILTIN(BUILTIN_new) || ISBUILTIN(PATCHER_builtin_new)) {
1347 if (state->iptr[-1].opc != ICMD_ACONST)
1348 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
1349 cls.any = state->iptr[-1].val.a;
1350 if (cls.any && !IS_CLASSREF(cls)) {
1351 /* The following check also forbids array classes and interfaces: */
1352 if ((cls.cls->flags & ACC_ABSTRACT) != 0)
1353 TYPECHECK_VERIFYERROR_bool("Invalid instruction: NEW creating instance of abstract class");
1356 /* in this case, the patcher will perform the non-abstract check */
1357 TYPECHECK_ASSERT(ISBUILTIN(PATCHER_builtin_new));
1359 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
1361 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1362 TYPECHECK_INT(state->curstack);
1363 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1365 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1366 TYPECHECK_INT(state->curstack);
1367 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1369 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1370 TYPECHECK_INT(state->curstack);
1371 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1373 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1374 TYPECHECK_INT(state->curstack);
1375 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1377 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1378 TYPECHECK_INT(state->curstack);
1379 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1381 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1382 TYPECHECK_INT(state->curstack);
1383 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1385 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1386 TYPECHECK_INT(state->curstack);
1387 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1389 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1390 TYPECHECK_INT(state->curstack);
1391 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1393 else if (ISBUILTIN(BUILTIN_newarray))
1396 TYPECHECK_INT(state->curstack->prev);
1397 if (state->iptr[-1].opc != ICMD_ACONST)
1398 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1399 vft = (vftbl_t *)state->iptr[-1].val.a;
1401 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1402 if (!vft->arraydesc)
1403 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1404 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1406 else if (ISBUILTIN(PATCHER_builtin_newarray))
1408 TYPECHECK_INT(state->curstack->prev);
1409 if (state->iptr[-1].opc != ICMD_ACONST)
1410 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1411 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[-1].val.a)))
1414 else if (ISBUILTIN(BUILTIN_newarray))
1417 TYPECHECK_INT(state->curstack->prev);
1418 if (state->iptr[-1].opc != ICMD_ACONST)
1419 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without classinfo");
1420 vft = (vftbl_t *)state->iptr[-1].val.a;
1422 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with unlinked class");
1423 if (!vft->arraydesc)
1424 TYPECHECK_VERIFYERROR_bool("ANEWARRAY with non-array class");
1425 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,vft->class);
1427 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1430 TYPECHECK_ADR(state->curstack->prev);
1431 if (state->iptr[-1].opc != ICMD_ACONST)
1432 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without classinfo");
1433 vft = (vftbl_t *)state->iptr[-1].val.a;
1435 TYPECHECK_VERIFYERROR_bool("INSTANCEOF with unlinked class");
1436 if (!vft->arraydesc)
1437 TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class");
1439 else if (ISBUILTIN(PATCHER_builtin_arrayinstanceof)) {
1440 constant_classref *cr;
1442 TYPECHECK_ADR(state->curstack->prev);
1443 if (state->iptr[-1].opc != ICMD_ACONST)
1444 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
1445 cr = (constant_classref *) state->iptr[-1].val.a;
1446 if (cr->name->text[0] != '[')
1447 TYPECHECK_VERIFYERROR_bool("internal error: builtin_arrayinstanceof with non-array class refernce");
1450 return verify_generic_builtin(state);
1455 /* verify_multianewarray *******************************************************
1457 Verify a MULTIANEWARRAY instruction.
1460 state............the current state of the verifier
1463 true.............successful verification,
1464 false............an exception has been thrown.
1466 *******************************************************************************/
1469 verify_multianewarray(verifier_state *state)
1472 vftbl_t *arrayvftbl;
1473 arraydescriptor *desc;
1476 /* check the array lengths on the stack */
1477 i = state->iptr[0].op1;
1479 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1481 sp = state->curstack;
1484 TYPECHECK_VERIFYERROR_bool("Unable to pop operand off an empty stack");
1489 /* check array descriptor */
1490 if (state->iptr[0].target == NULL) {
1491 /* the array class reference has already been resolved */
1492 arrayvftbl = (vftbl_t*) state->iptr[0].val.a;
1494 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1495 if ((desc = arrayvftbl->arraydesc) == NULL)
1496 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1497 if (desc->dimension < state->iptr[0].op1)
1498 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1500 /* set the array type of the result */
1501 TYPEINFO_INIT_CLASSINFO(state->iptr->dst->typeinfo,arrayvftbl->class);
1505 constant_classref *cr;
1507 /* the array class reference is still unresolved */
1508 /* check that the reference indicates an array class of correct dimension */
1509 cr = (constant_classref *) state->iptr[0].val.a;
1514 /* { the dimension of the array class == i } */
1516 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1517 if (i < state->iptr[0].op1)
1518 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1520 /* set the array type of the result */
1521 if (!typeinfo_init_class(&(state->iptr->dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].val.a)))
1529 /* verify_basic_block **********************************************************
1531 Perform bytecode verification of a basic block.
1534 state............the current state of the verifier
1537 true.............successful verification,
1538 false............an exception has been thrown.
1540 *******************************************************************************/
1543 verify_basic_block(verifier_state *state)
1545 int opcode; /* current opcode */
1546 int len; /* for counting instructions, etc. */
1547 bool superblockend; /* true if no fallthrough to next block */
1548 basicblock *tbptr; /* temporary for target block */
1549 stackptr dst; /* output stack of current instruction */
1550 basicblock **tptr; /* pointer into target list of switch instr. */
1551 classinfo *cls; /* temporary */
1552 bool maythrow; /* true if this instruction may throw */
1554 unresolved_field *uf; /* for field accesses */
1555 fieldinfo **fieldinfop; /* for field accesses */
1560 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->debug_nr);
1563 superblockend = false;
1564 state->bptr->flags = BBFINISHED;
1565 b_index = state->bptr - state->m->basicblocks;
1567 /* init stack at the start of this block */
1568 state->curstack = state->bptr->instack;
1570 /* prevent compiler warnings */
1574 /* determine the active exception handlers for this block */
1575 /* XXX could use a faster algorithm with sorted lists or */
1578 for (i = 0; i < state->cd->exceptiontablelength; ++i) {
1579 if ((state->cd->exceptiontable[i].start <= state->bptr) && (state->cd->exceptiontable[i].end > state->bptr)) {
1580 LOG1("active handler L%03d", state->cd->exceptiontable[i].handler->debug_nr);
1581 state->handlers[len++] = state->cd->exceptiontable + i;
1584 state->handlers[len] = NULL;
1586 /* init variable types at the start of this block */
1587 COPY_TYPEVECTORSET(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
1588 state->localset,state->numlocals);
1590 /* XXX FIXME FOR INLINING */
1592 if (state->handlers[0])
1593 for (i=0; i<state->numlocals; ++i)
1594 if (state->localset->td[i].type == TYPE_ADR
1595 && TYPEINFO_IS_NEWOBJECT(state->localset->td[i].info)) {
1596 /* XXX we do not check this for the uninitialized 'this' instance in */
1597 /* <init> methods. Otherwise there are problems with try blocks in */
1598 /* <init>. The spec seems to indicate that we should perform the test*/
1599 /* in all cases, but this fails with real code. */
1600 /* Example: org/eclipse/ui/internal/PerspectiveBarNewContributionItem*/
1601 /* of eclipse 3.0.2 */
1602 if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
1603 /*show_icmd_method(state->m, state->cd, state->rd);*/
1604 printf("Uninitialized variale: %d, block: %d\n", i, state->bptr->debug_nr);
1605 TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
1609 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1612 /* loop over the instructions */
1613 len = state->bptr->icount;
1614 state->iptr = state->bptr->iinstr;
1615 while (--len >= 0) {
1616 TYPECHECK_COUNT(stat_ins);
1618 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
1621 DOLOG(show_icmd(state->iptr,false)); LOGNL; LOGFLUSH;
1623 opcode = state->iptr->opc;
1624 myclass = state->iptr->method->class;
1625 dst = state->iptr->dst;
1630 /****************************************/
1631 /* STACK MANIPULATIONS */
1633 /* We just need to copy the typeinfo */
1634 /* for slots containing addresses. */
1636 /* CAUTION: We assume that the destination stack
1637 * slots were continuously allocated in
1638 * memory! (The current implementation in
1643 COPYTYPE(state->curstack,dst);
1647 COPYTYPE(state->curstack,dst);
1648 COPYTYPE(state->curstack,dst-2);
1649 COPYTYPE(state->curstack->prev,dst-1);
1653 COPYTYPE(state->curstack,dst);
1654 COPYTYPE(state->curstack,dst-3);
1655 COPYTYPE(state->curstack->prev,dst-1);
1656 COPYTYPE(state->curstack->prev->prev,dst-2);
1660 COPYTYPE(state->curstack,dst);
1661 COPYTYPE(state->curstack->prev,dst-1);
1665 COPYTYPE(state->curstack,dst);
1666 COPYTYPE(state->curstack->prev,dst-1);
1667 COPYTYPE(state->curstack,dst-3);
1668 COPYTYPE(state->curstack->prev,dst-4);
1669 COPYTYPE(state->curstack->prev->prev,dst-2);
1673 COPYTYPE(state->curstack,dst);
1674 COPYTYPE(state->curstack->prev,dst-1);
1675 COPYTYPE(state->curstack,dst-4);
1676 COPYTYPE(state->curstack->prev,dst-5);
1677 COPYTYPE(state->curstack->prev->prev,dst-2);
1678 COPYTYPE(state->curstack->prev->prev->prev,dst-3);
1682 COPYTYPE(state->curstack,dst-1);
1683 COPYTYPE(state->curstack->prev,dst);
1686 /****************************************/
1687 /* PRIMITIVE VARIABLE ACCESS */
1689 case ICMD_ILOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1690 case ICMD_FLOAD: CHECK_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1691 case ICMD_IINC: CHECK_ONEWORD(state->iptr->op1,TYPE_INT); break;
1692 case ICMD_LLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1693 case ICMD_DLOAD: CHECK_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1695 case ICMD_FSTORE: STORE_ONEWORD(state->iptr->op1,TYPE_FLOAT); break;
1696 case ICMD_ISTORE: STORE_ONEWORD(state->iptr->op1,TYPE_INT); break;
1697 case ICMD_LSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_LONG); break;
1698 case ICMD_DSTORE: STORE_TWOWORD(state->iptr->op1,TYPE_DOUBLE); break;
1700 /****************************************/
1701 /* LOADING ADDRESS FROM VARIABLE */
1704 TYPECHECK_COUNT(stat_ins_aload);
1706 /* loading a returnAddress is not allowed */
1707 if (state->jsrencountered) {
1708 if (!typevectorset_checkreference(state->localset,state->iptr->op1)) {
1709 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1711 if (typevectorset_copymergedtype(state->m,state->localset,state->iptr->op1,&(dst->typeinfo)) == -1)
1715 if (!TYPEDESC_IS_REFERENCE(state->localset->td[state->iptr->op1])) {
1716 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1718 TYPEINFO_COPY(state->localset->td[state->iptr->op1].info,dst->typeinfo);
1722 /****************************************/
1723 /* STORING ADDRESS TO VARIABLE */
1726 if (state->handlers[0] && TYPEINFO_IS_NEWOBJECT(state->curstack->typeinfo)) {
1727 TYPECHECK_VERIFYERROR_bool("Storing uninitialized object in local variable inside try block");
1730 if (TYPESTACK_IS_RETURNADDRESS(state->curstack)) {
1731 typevectorset_store_retaddr(state->localset,state->iptr->op1,&(state->curstack->typeinfo));
1734 typevectorset_store(state->localset,state->iptr->op1,TYPE_ADDRESS,
1735 &(state->curstack->typeinfo));
1739 /****************************************/
1740 /* LOADING ADDRESS FROM ARRAY */
1743 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->typeinfo))
1744 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1746 if (!typeinfo_init_component(&state->curstack->prev->typeinfo,&dst->typeinfo))
1751 /****************************************/
1754 case ICMD_PUTFIELDCONST:
1755 case ICMD_PUTSTATICCONST:
1756 TYPECHECK_COUNT(stat_ins_field);
1758 uf = INSTRUCTION_PUTCONST_FIELDREF(state->iptr);
1759 fieldinfop = INSTRUCTION_PUTCONST_FIELDINFO_PTR(state->iptr);
1761 goto fieldaccess_tail;
1764 case ICMD_PUTSTATIC:
1765 TYPECHECK_COUNT(stat_ins_field);
1767 uf = (unresolved_field *) state->iptr[0].target;
1768 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1770 goto fieldaccess_tail;
1773 case ICMD_GETSTATIC:
1774 TYPECHECK_COUNT(stat_ins_field);
1776 uf = (unresolved_field *) state->iptr[0].target;
1777 fieldinfop = (fieldinfo **) &(state->iptr[0].val.a);
1779 /* the result is pushed on the stack */
1780 if (dst->type == TYPE_ADR) {
1781 if (!typeinfo_init_from_typedesc(uf->fieldref->parseddesc.fd,NULL,&(dst->typeinfo)))
1786 /* record the subtype constraints for this field access */
1787 if (!constrain_unresolved_field(uf,state->m->class,state->m,state->iptr,state->curstack))
1788 return false; /* XXX maybe wrap exception? */
1790 /* try to resolve the field reference */
1791 if (!resolve_field(uf,resolveLazy,fieldinfop))
1794 /* we need a patcher, so this is not a leafmethod */
1795 #if defined(__MIPS__) || defined(__POWERPC__)
1796 if (!*fieldinfop || !(*fieldinfop)->class->initialized)
1797 state->cd->method->isleafmethod = false;
1803 /****************************************/
1804 /* PRIMITIVE ARRAY ACCESS */
1806 case ICMD_ARRAYLENGTH:
1807 if (!TYPEINFO_MAYBE_ARRAY(state->curstack->typeinfo)
1808 && state->curstack->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1809 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1814 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1815 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_BYTE))
1816 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1820 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_CHAR))
1821 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1825 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_DOUBLE))
1826 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1830 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_FLOAT))
1831 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1835 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_INT))
1836 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1840 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_SHORT))
1841 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1845 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo,ARRAYTYPE_LONG))
1846 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1851 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BOOLEAN)
1852 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_BYTE))
1853 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1857 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_CHAR))
1858 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1862 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_DOUBLE))
1863 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1867 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_FLOAT))
1868 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1872 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_INT))
1873 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1877 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_SHORT))
1878 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1882 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->prev->typeinfo,ARRAYTYPE_LONG))
1883 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1888 /* we just check the basic input types and that the */
1889 /* destination is an array of references. Assignability to */
1890 /* the actual array must be checked at runtime, each time the */
1891 /* instruction is performed. (See builtin_canstore.) */
1892 TYPECHECK_ADR(state->curstack);
1893 TYPECHECK_INT(state->curstack->prev);
1894 TYPECHECK_ADR(state->curstack->prev->prev);
1895 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->curstack->prev->prev->typeinfo))
1896 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1900 case ICMD_IASTORECONST:
1901 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_INT))
1902 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1906 case ICMD_LASTORECONST:
1907 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_LONG))
1908 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1912 case ICMD_BASTORECONST:
1913 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BOOLEAN)
1914 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_BYTE))
1915 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1919 case ICMD_CASTORECONST:
1920 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_CHAR))
1921 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1925 case ICMD_SASTORECONST:
1926 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->curstack->prev->typeinfo, ARRAYTYPE_SHORT))
1927 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1931 /****************************************/
1932 /* ADDRESS CONSTANTS */
1935 if (state->iptr->val.a == NULL)
1936 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
1938 /* string constant (or constant for builtin function) */
1939 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,class_java_lang_String);
1942 /****************************************/
1943 /* CHECKCAST AND INSTANCEOF */
1945 case ICMD_CHECKCAST:
1946 TYPECHECK_ADR(state->curstack);
1947 /* returnAddress is not allowed */
1948 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1949 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
1951 cls = (classinfo *) state->iptr[0].val.a;
1953 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1955 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1960 case ICMD_ARRAYCHECKCAST:
1961 TYPECHECK_ADR(state->curstack);
1962 /* returnAddress is not allowed */
1963 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1964 TYPECHECK_VERIFYERROR_bool("Illegal instruction: ARRAYCHECKCAST on non-reference");
1966 if (state->iptr[0].op1) {
1967 /* a resolved array class */
1968 cls = ((vftbl_t *)state->iptr[0].target)->class;
1969 TYPEINFO_INIT_CLASSINFO(dst->typeinfo,cls);
1972 /* an unresolved array class reference */
1973 if (!typeinfo_init_class(&(dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
1979 case ICMD_INSTANCEOF:
1980 TYPECHECK_ADR(state->curstack);
1981 /* returnAddress is not allowed */
1982 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
1983 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
1986 /****************************************/
1987 /* BRANCH INSTRUCTIONS */
1990 superblockend = true;
1993 case ICMD_IFNONNULL:
2000 case ICMD_IF_ICMPEQ:
2001 case ICMD_IF_ICMPNE:
2002 case ICMD_IF_ICMPLT:
2003 case ICMD_IF_ICMPGE:
2004 case ICMD_IF_ICMPGT:
2005 case ICMD_IF_ICMPLE:
2006 case ICMD_IF_ACMPEQ:
2007 case ICMD_IF_ACMPNE:
2014 case ICMD_IF_LCMPEQ:
2015 case ICMD_IF_LCMPNE:
2016 case ICMD_IF_LCMPLT:
2017 case ICMD_IF_LCMPGE:
2018 case ICMD_IF_LCMPGT:
2019 case ICMD_IF_LCMPLE:
2020 TYPECHECK_COUNT(stat_ins_branch);
2021 tbptr = (basicblock *) state->iptr->target;
2023 /* propagate stack and variables to the target block */
2024 if (!typestate_reach(state,tbptr,dst,state->localset))
2028 /****************************************/
2031 case ICMD_TABLESWITCH:
2032 TYPECHECK_COUNT(stat_ins_switch);
2034 s4 *s4ptr = state->iptr->val.a;
2035 s4ptr++; /* skip default */
2036 i = *s4ptr++; /* low */
2037 i = *s4ptr++ - i + 2; /* +1 for default target */
2039 goto switch_instruction_tail;
2041 case ICMD_LOOKUPSWITCH:
2042 TYPECHECK_COUNT(stat_ins_switch);
2044 s4 *s4ptr = state->iptr->val.a;
2045 s4ptr++; /* skip default */
2046 i = *s4ptr++ + 1; /* count +1 for default */
2048 switch_instruction_tail:
2049 tptr = (basicblock **)state->iptr->target;
2053 LOG2("target %d is block %04d",(tptr-(basicblock **)state->iptr->target)-1,tbptr->debug_nr);
2054 if (!typestate_reach(state,tbptr,dst,state->localset))
2058 superblockend = true;
2061 /****************************************/
2062 /* ADDRESS RETURNS AND THROW */
2065 r = typeinfo_is_assignable_to_class(&state->curstack->typeinfo,
2066 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
2067 if (r == typecheck_FALSE)
2068 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
2069 if (r == typecheck_FAIL)
2071 /* XXX handle typecheck_MAYBE */
2072 superblockend = true;
2077 if (!TYPEINFO_IS_REFERENCE(state->curstack->typeinfo))
2078 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
2080 if (state->returntype.type != TYPE_ADDRESS
2081 || (r = typeinfo_is_assignable(&state->curstack->typeinfo,&(state->returntype.info)))
2083 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2084 if (r == typecheck_FAIL)
2086 /* XXX handle typecheck_MAYBE */
2089 /****************************************/
2090 /* PRIMITIVE RETURNS */
2093 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2097 if (state->returntype.type != TYPE_LONG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2101 if (state->returntype.type != TYPE_FLOAT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2105 if (state->returntype.type != TYPE_DOUBLE) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2109 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2112 superblockend = true;
2116 /****************************************/
2117 /* SUBROUTINE INSTRUCTIONS */
2121 state->jsrencountered = true;
2123 /* This is a dirty hack. It is needed
2124 * because of the special handling of
2125 * ICMD_JSR in stack.c
2127 dst = (stackptr) state->iptr->val.a;
2129 tbptr = (basicblock *) state->iptr->target;
2130 if (state->bptr + 1 == (state->m->basicblocks + state->m->basicblockcount + 1))
2131 TYPECHECK_VERIFYERROR_bool("Illegal instruction: JSR at end of bytecode");
2132 typestack_put_retaddr(dst,state->bptr+1,state->localset);
2133 if (!typestate_reach(state,tbptr,dst,state->localset))
2136 superblockend = true;
2140 /* check returnAddress variable */
2141 if (!typevectorset_checkretaddr(state->localset,state->iptr->op1))
2142 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
2144 if (!typestate_ret(state,state->iptr->op1))
2147 superblockend = true;
2150 /****************************************/
2153 case ICMD_INVOKEVIRTUAL:
2154 case ICMD_INVOKESPECIAL:
2155 case ICMD_INVOKESTATIC:
2156 case ICMD_INVOKEINTERFACE:
2157 TYPECHECK_COUNT(stat_ins_invoke);
2158 if (!verify_invocation(state))
2163 /****************************************/
2164 /* MULTIANEWARRAY */
2166 case ICMD_MULTIANEWARRAY:
2167 if (!verify_multianewarray(state))
2172 /****************************************/
2176 TYPECHECK_COUNT(stat_ins_builtin);
2177 if (!verify_builtin(state))
2182 /****************************************/
2183 /* SIMPLE EXCEPTION THROWING TESTS */
2185 case ICMD_CHECKNULL:
2186 /* CHECKNULL just requires that the stack top
2187 * is an address. This is checked in stack.c */
2191 /****************************************/
2192 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
2193 /* REPLACED BY OTHER OPCODES */
2195 #ifdef TYPECHECK_DEBUG
2198 case ICMD_ANEWARRAY:
2199 case ICMD_MONITORENTER:
2200 case ICMD_MONITOREXIT:
2201 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2202 LOG("Should have been converted to builtin function call.");
2203 TYPECHECK_ASSERT(false);
2206 case ICMD_READONLY_ARG:
2207 case ICMD_CLEAR_ARGREN:
2208 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2209 LOG("Should have been replaced in stack.c.");
2210 TYPECHECK_ASSERT(false);
2214 /****************************************/
2215 /* UNCHECKED OPERATIONS */
2217 /*********************************************
2218 * Instructions below...
2219 * *) don't operate on local variables,
2220 * *) don't operate on references,
2221 * *) don't operate on returnAddresses.
2223 * (These instructions are typechecked in
2225 ********************************************/
2227 /* Instructions which may throw a runtime exception: */
2237 /* Instructions which never throw a runtime exception: */
2238 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
2248 case ICMD_IFEQ_ICONST:
2249 case ICMD_IFNE_ICONST:
2250 case ICMD_IFLT_ICONST:
2251 case ICMD_IFGE_ICONST:
2252 case ICMD_IFGT_ICONST:
2253 case ICMD_IFLE_ICONST:
2254 case ICMD_ELSE_ICONST:
2277 case ICMD_IREM0X10001:
2278 case ICMD_LREM0X10001:
2284 case ICMD_IADDCONST:
2285 case ICMD_ISUBCONST:
2286 case ICMD_IMULCONST:
2287 case ICMD_IANDCONST:
2289 case ICMD_IXORCONST:
2290 case ICMD_ISHLCONST:
2291 case ICMD_ISHRCONST:
2292 case ICMD_IUSHRCONST:
2294 case ICMD_LADDCONST:
2295 case ICMD_LSUBCONST:
2296 case ICMD_LMULCONST:
2297 case ICMD_LANDCONST:
2299 case ICMD_LXORCONST:
2300 case ICMD_LSHLCONST:
2301 case ICMD_LSHRCONST:
2302 case ICMD_LUSHRCONST:
2319 case ICMD_INT2SHORT:
2322 case ICMD_LCMPCONST:
2342 /*XXX What shall we do with the following ?*/
2343 case ICMD_AASTORECONST:
2344 TYPECHECK_COUNT(stat_ins_unchecked);
2347 /****************************************/
2350 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2351 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2355 /* the output of this instruction becomes the current stack */
2356 state->curstack = dst;
2358 /* reach exception handlers for this instruction */
2360 LOG("reaching exception handlers");
2362 while (state->handlers[i]) {
2363 TYPECHECK_COUNT(stat_handlers_reached);
2364 if (state->handlers[i]->catchtype.any)
2365 state->excstack.typeinfo.typeclass = state->handlers[i]->catchtype;
2367 state->excstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
2368 if (!typestate_reach(state,
2369 state->handlers[i]->handler,
2370 &(state->excstack),state->localset))
2376 LOG("next instruction");
2378 } /* while instructions */
2380 LOG("instructions done");
2381 LOGSTR("RESULT=> ");
2382 DOLOG(typestate_print(get_logfile(),state->curstack,state->localset,state->numlocals));
2385 /* propagate stack and variables to the following block */
2386 if (!superblockend) {
2387 LOG("reaching following block");
2388 tbptr = state->bptr + 1;
2389 while (tbptr->flags == BBDELETED) {
2391 #ifdef TYPECHECK_DEBUG
2392 /* this must be checked in parse.c */
2393 if ((tbptr->debug_nr) >= state->m->basicblockcount)
2394 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2397 if (!typestate_reach(state,tbptr,dst,state->localset))
2401 /* We may have to restore the types of the instack slots. They
2402 * have been saved if an <init> call inside the block has
2403 * modified the instack types. (see INVOKESPECIAL) */
2405 if (state->savedstack) {
2406 stackptr sp = state->bptr->instack;
2407 stackptr copy = state->savedstack;
2408 TYPECHECK_COUNT(stat_savedstack);
2409 LOG("restoring saved instack");
2410 TYPESTACK_COPY(sp,copy);
2411 state->bptr->instack = state->savedstack;
2412 state->savedstack = NULL;
2417 /* verify_init_locals **********************************************************
2419 Initialize the local variables in the verifier state.
2422 state............the current state of the verifier
2425 true.............success,
2426 false............an exception has been thrown.
2428 *******************************************************************************/
2431 verify_init_locals(verifier_state *state)
2437 /* initialize the variable types of the first block */
2438 /* to the types of the arguments */
2440 lset = MGET_TYPEVECTOR(state->localbuf,0,state->numlocals);
2444 i = state->validlocals;
2446 /* allocate parameter descriptors if necessary */
2448 if (!state->m->parseddesc->params)
2449 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2452 /* if this is an instance method initialize the "this" ref type */
2454 if (!(state->m->flags & ACC_STATIC)) {
2456 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2457 td->type = TYPE_ADDRESS;
2458 if (state->initmethod)
2459 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
2461 TYPEINFO_INIT_CLASSINFO(td->info, state->m->class);
2466 LOG("'this' argument set.\n");
2468 /* the rest of the arguments and the return type */
2470 i = typedescriptors_init_from_methoddesc(td, state->m->parseddesc,
2472 true, /* two word types use two slots */
2473 (td - lset->td), /* skip 'this' pointer */
2474 &state->returntype);
2479 /* variables not used for arguments are initialized to TYPE_VOID */
2481 i = state->numlocals - (td - lset->td);
2483 td->type = TYPE_VOID;
2487 LOG("Arguments set.\n");
2491 /* typecheck_init_flags ********************************************************
2493 Initialize the basic block flags for the following CFG traversal.
2496 state............the current state of the verifier
2498 *******************************************************************************/
2501 typecheck_init_flags(verifier_state *state)
2506 /* set all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2508 i = state->m->basicblockcount;
2509 block = state->m->basicblocks;
2513 #ifdef TYPECHECK_DEBUG
2514 /* check for invalid flags */
2515 if (block->flags != BBFINISHED && block->flags != BBDELETED && block->flags != BBUNDEF)
2517 /*show_icmd_method(state->cd->method,state->cd,state->rd);*/
2518 LOGSTR1("block flags: %d\n",block->flags); LOGFLUSH;
2519 TYPECHECK_ASSERT(false);
2523 if (block->flags >= BBFINISHED) {
2524 block->flags = BBTYPECHECK_UNDEF;
2529 /* the first block is always reached */
2531 if (state->m->basicblockcount && state->m->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2532 state->m->basicblocks[0].flags = BBTYPECHECK_REACHED;
2535 /* typecheck_reset_flags *******************************************************
2537 Reset the flags of basic blocks we have not reached.
2540 state............the current state of the verifier
2542 *******************************************************************************/
2545 typecheck_reset_flags(verifier_state *state)
2549 /* check for invalid flags at exit */
2551 #ifdef TYPECHECK_DEBUG
2552 for (i=0; i<state->m->basicblockcount; ++i) {
2553 if (state->m->basicblocks[i].flags != BBDELETED
2554 && state->m->basicblocks[i].flags != BBUNDEF
2555 && state->m->basicblocks[i].flags != BBFINISHED
2556 && state->m->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2557 * some exception handlers,
2560 LOG2("block L%03d has invalid flags after typecheck: %d",
2561 state->m->basicblocks[i].debug_nr,state->m->basicblocks[i].flags);
2562 TYPECHECK_ASSERT(false);
2567 /* Reset blocks we never reached */
2569 for (i=0; i<state->m->basicblockcount; ++i) {
2570 if (state->m->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2571 state->m->basicblocks[i].flags = BBFINISHED;
2575 /****************************************************************************/
2577 /* This is the main function of the bytecode verifier. It is called */
2578 /* directly after analyse_stack. */
2581 /* meth.............the method to verify */
2582 /* cdata............codegendata for the method */
2583 /* rdata............registerdata for the method */
2586 /* m................successful verification */
2587 /* NULL.............an exception has been thrown */
2590 /* Bytecode verification has not been tested with inlining and */
2591 /* probably does not work correctly with inlining. */
2592 /****************************************************************************/
2594 #define MAXPARAMS 255
2596 methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
2598 verifier_state state; /* current state of the verifier */
2599 int i; /* temporary counter */
2601 /* collect statistics */
2603 #ifdef TYPECHECK_STATISTICS
2604 int count_iterations = 0;
2605 TYPECHECK_COUNT(stat_typechecked);
2606 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2607 TYPECHECK_COUNT_FREQ(stat_blocks,meth->basicblockcount/10,STAT_BLOCKS);
2610 /* some logging on entry */
2612 LOGSTR("\n==============================================================================\n");
2613 /*DOLOG( show_icmd_method(cdata->method,cdata,rdata));*/
2614 LOGSTR("\n==============================================================================\n");
2615 LOGimpSTR("Entering typecheck: ");
2616 LOGimpSTRu(cdata->method->name);
2618 LOGimpSTRu(cdata->method->descriptor);
2619 LOGimpSTR(" (class ");
2620 LOGimpSTRu(cdata->method->class->name);
2624 /* initialize the verifier state */
2626 state.savedstackbuf = NULL;
2627 state.savedstack = NULL;
2628 state.jsrencountered = false;
2633 /* check if this method is an instance initializer method */
2635 state.initmethod = (state.m->name == utf_init);
2637 /* initialize the basic block flags for the following CFG traversal */
2639 typecheck_init_flags(&state);
2641 /* number of local variables */
2643 /* In <init> methods we use an extra local variable to indicate whether */
2644 /* the 'this' reference has been initialized. */
2645 /* TYPE_VOID...means 'this' has not been initialized, */
2646 /* TYPE_INT....means 'this' has been initialized. */
2647 state.numlocals = state.cd->maxlocals;
2648 state.validlocals = state.numlocals;
2649 if (state.initmethod) state.numlocals++;
2651 /* allocate the buffers for local variables */
2653 state.localbuf = DMNEW_TYPEVECTOR(state.m->basicblockcount+1, state.numlocals);
2654 state.localset = MGET_TYPEVECTOR(state.localbuf,state.m->basicblockcount,state.numlocals);
2656 LOG("Variable buffer allocated.\n");
2658 /* allocate the buffer of active exception handlers */
2660 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2662 /* initialized local variables of first block */
2664 if (!verify_init_locals(&state))
2667 /* initialize the input stack of exception handlers */
2669 state.excstack.prev = NULL;
2670 state.excstack.type = TYPE_ADR;
2671 TYPEINFO_INIT_CLASSINFO(state.excstack.typeinfo,
2672 class_java_lang_Throwable); /* changed later */
2674 LOG("Exception handler stacks set.\n");
2676 /* loop while there are still blocks to be checked */
2678 TYPECHECK_COUNT(count_iterations);
2680 state.repeat = false;
2682 i = state.m->basicblockcount;
2683 state.bptr = state.m->basicblocks;
2686 LOGSTR1("---- BLOCK %04d, ",state.bptr->debug_nr);
2687 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2690 /* verify reached block */
2691 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2692 if (!verify_basic_block(&state))
2696 } /* while blocks */
2698 LOGIF(state.repeat,"state.repeat == true");
2699 } while (state.repeat);
2703 #ifdef TYPECHECK_STATISTICS
2704 LOG1("Typechecker did %4d iterations",count_iterations);
2705 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2706 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2709 /* reset the flags of blocks we haven't reached */
2711 typecheck_reset_flags(&state);
2713 /* just return methodinfo* to indicate everything was ok */
2714 LOGimp("exiting typecheck");
2718 #endif /* CACAO_TYPECHECK */
2721 * These are local overrides for various environment variables in Emacs.
2722 * Please do not remove this and leave it at the end of the file, where
2723 * Emacs will automagically detect them.
2724 * ---------------------------------------------------------------------
2727 * indent-tabs-mode: t
2731 * vim:noexpandtab:sw=4:ts=4: