If I use Sun's Java compiler (from JDK 1.4) to compile a .java file containing a try...finally block, then try to use gcj to compile the .class file into executable code, gcj complains with the error message "bad pc in exception_table". Here's what's going on. Recall that a Java .class file contains an exception table for each method. Each entry in the exception table contains a range (from, to) of instructions to protect as well as a target instruction to jump to if an exception occurs within that range. When Sun's Java compiler in JDK 1.4 compiles a try...finally block, it emits a (useless and unused) exception table entry whose target is within the range of protected instructions. There is nothing inherently unsafe with this, but we check for this case and reject it in verify.c. Unfortunately, the fix is apparently not as simple as removing the line which makes this check (the line "|| (handler_pc >= start_pc && handler_pc < end_pc)" in verify_jvm_instructions() in verify.c); I tried that and then gcj complained about a stack overflow in the same .class file. I don't have time to look at the verification code more right now, so I'm filing a bug report in case someone else wants to pick up where I left off. Release: gcc version 3.0.2 20010905 (Red Hat Linux 7.1 3.0.1-3) Environment: Red Hat Linux 7.2 on a Pentium PC How-To-Repeat: $ /usr/java/j2sdk1.4.0/bin/javac Foo.java $ gcj Foo.class Foo.java: In class `Foo': Foo.java: In method `Foo.invoke()': Foo.java:6: bad pc in exception_table $
From: Tom Tromey <tromey@redhat.com> To: adam@medovina.org Cc: gcc-gnats@gcc.gnu.org Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: 28 Feb 2002 17:47:43 -0700 >>>>> "Adam" == adam <adam@medovina.org> writes: Adam> Number: 5794 Adam> Synopsis: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Could you upload the resulting .class file? Just reply to this email and attach it, keeping gcc-gnats on the CC line. Adam> When Sun's Java compiler in JDK 1.4 compiles a try...finally Adam> block, it emits a (useless and unused) exception table entry Adam> whose target is within the range of protected instructions. Adam> There is nothing inherently unsafe with this, but we check for Adam> this case and reject it in verify.c. It seems to me that this must be invalid. Adam> I tried that and then gcj complained about a stack overflow in Adam> the same .class file. Yeah. Suppose the VM encounters an internal error and throws an exception after it has set the PC to the start of the exception handler but before the first instruction of the handler (probably a pop or an astore) is executed. This leads inexorably to a stack overflow. I imagine the gij verifier will die on this too. I'd like to see the class file though. It's possible there are obscure extenuating circumstances. Or perhaps they've tightened the verification spec and I don't yet know about it. Tom
From: Adam Dingle <adam@medovina.org> To: tromey@redhat.com Cc: gcc-gnats@gcc.gnu.org Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: Fri, 01 Mar 2002 00:01:18 -0800 --Boundary_(ID_qN3wNA75EjmM1jjnp01ldQ) Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 7BIT Tom, > Could you upload the resulting .class file? > Just reply to this email and attach it, keeping gcc-gnats on the CC > line. No problem - I've attached the .class file to this reply. > Adam> When Sun's Java compiler in JDK 1.4 compiles a try...finally > Adam> block, it emits a (useless and unused) exception table entry > Adam> whose target is within the range of protected instructions. > Adam> There is nothing inherently unsafe with this, but we check for > Adam> this case and reject it in verify.c. > > It seems to me that this must be invalid. Well, I'm not sure. Section 4.9.5 of the Java Virtual Machine Specification does include the following text: "Java virtual machine code produced by Sun's compiler for the Java programming language always generates exception handlers such that ... The handler for an exception will never be inside the code that is being protected ... These restrictions are not enforced by the class file verifier since they do not pose a threat to the integrity of the Java virtual machine." (see http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html) > Adam> I tried that and then gcj complained about a stack overflow in > Adam> the same .class file. > > Yeah. Suppose the VM encounters an internal error and throws an > exception after it has set the PC to the start of the exception > handler but before the first instruction of the handler (probably a > pop or an astore) is executed. This leads inexorably to a stack > overflow. I imagine the gij verifier will die on this too. That is a scary thought, although it's hard for me to imagine any sort of error that might happen just at that moment. > I'd like to see the class file though. It's possible there are > obscure extenuating circumstances. Or perhaps they've tightened the > verification spec and I don't yet know about it. I'll be curious to see what you think. I do seem to get this kind of unusual exception table entry almost any time I compile a try...finally block with JDK 1.4. -adam --Boundary_(ID_qN3wNA75EjmM1jjnp01ldQ) Content-type: application/java; name=Foo.class Content-transfer-encoding: base64 Content-disposition: attachment; filename=Foo.class yv66vgAAAC4ADwoAAwAMBwANBwAOAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJU YWJsZQEABmludm9rZQEAAygpSQEAClNvdXJjZUZpbGUBAAhGb28uamF2YQwABAAFAQADRm9vAQAQ amF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAgABAAQABQABAAYAAAAdAAEAAQAAAAUqtwABsQAA AAEABwAAAAYAAQAAAAEAAQAIAAkAAQAGAAAAPAABAAQAAAAQBDyoAAsbrE2oAAUsv04FrAACAAAA BQAHAAAABwALAAcAAAABAAcAAAAKAAIAAAAGAAcACAABAAoAAAACAAs= --Boundary_(ID_qN3wNA75EjmM1jjnp01ldQ)--
From: Adam Dingle <adam@medovina.org> To: gcc-gnats@gcc.gnu.org Cc: Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: Sat, 02 Mar 2002 09:20:27 -0800 --Boundary_(ID_SqrWNdAHJp+UIEkskG5ToA) Content-type: text/plain; charset=iso-8859-1 Content-transfer-encoding: 7BIT Another note. I tried compiling the same source file with Sun's JDK 1.3 compiler. It compiled the method differently, and did not generate any exception table entry with a target address inside the range of addresses which the entry itself protects. Nevertheless, GCJ 3.0.2 still fails to verify the class; it reports Foo.java: In class `Foo': Foo.java: In method `Foo.invoke()': Foo.java:6: verification error at PC=11 Foo.java:6: stack overflow The method's disassembly looks like this: Method int invoke() 0 iconst_1 1 istore_1 2 jsr 13 5 iload_1 6 ireturn 7 astore_2 8 jsr 13 11 aload_2 12 athrow 13 astore_3 14 iconst_3 15 ireturn Exception table: from to target type 0 7 7 any I've included the .class file generated by the JDK 1.3 compiler as an attachment to this message. (I found another test case where the compiler generates code which causes GCJ to seg fault, but I'll file a separate bug report for that one.) adam ------------------------------------------------------- --Boundary_(ID_SqrWNdAHJp+UIEkskG5ToA) Content-type: application/java; charset=iso-8859-1; name=Foo.class Content-transfer-encoding: base64 Content-disposition: attachment; filename=Foo.class yv66vgADAC0ADwoAAwAMBwANBwAOAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJU YWJsZQEABmludm9rZQEAAygpSQEAClNvdXJjZUZpbGUBAAhGb28uamF2YQwABAAFAQADRm9vAQAQ amF2YS9sYW5nL09iamVjdAAhAAIAAwAAAAAAAgABAAQABQABAAYAAAAdAAEAAQAAAAUqtwABsQAA AAEABwAAAAYAAQAAAAEAAQAIAAkAAQAGAAAANAABAAQAAAAQBDyoAAsbrE2oAAUsv04FrAABAAAA BwAHAAAAAQAHAAAACgACAAAABgAHAAgAAQAKAAAAAgAL --Boundary_(ID_SqrWNdAHJp+UIEkskG5ToA)--
From: Adam Dingle <adam@medovina.org> To: tromey@redhat.com Cc: gcc-gnats@gcc.gnu.org Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: Sat, 02 Mar 2002 10:40:55 -0800 One more observation: GCJ can't verify the byte code which it itself generates for the method. [adam@localhost foo]$ gcj3 --version 3.0.2 [adam@localhost foo]$ gcj3 -C Foo.java [adam@localhost foo]$ gcj3 Foo.class Foo.java: In class `Foo': Foo.java: In method `Foo.invoke()': Foo.java:6: verification error at PC=11 Foo.java:6: stack overflow [adam@localhost foo]$ -adam
From: Tom Tromey <tromey@redhat.com> To: adam@medovina.org Cc: gcc-gnats@gcc.gnu.org Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: 02 Mar 2002 11:56:48 -0700 >>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes: Tom> Suppose the VM encounters an internal error and throws an Tom> exception after it has set the PC to the start of the exception Tom> handler but before the first instruction of the handler (probably Tom> a pop or an astore) is executed. This leads inexorably to a Tom> stack overflow. I thought about this more and my idea here is just wrong. When an exception is throw the stack is cleared before the exception is pushed. So this scenario can't happen. I'll look into this a bit more soon. Tom
From: Tom Tromey <tromey@redhat.com> To: Adam Dingle <adam@medovina.org> Cc: gcc-gnats@gcc.gnu.org Subject: Re: java/5794: gcj fails to verify .class file generated by Sun JDK 1.4 compiler Date: 02 Mar 2002 18:41:05 -0700 >>>>> "Adam" == Adam Dingle <adam@medovina.org> writes: Adam> I'll be curious to see what you think. I do seem to get this Adam> kind of unusual exception table entry almost any time I compile Adam> a try...finally block with JDK 1.4. Ok, I looked at this class file. The exception range is 0-5, with the handler at 5. One important thing to know is that the upper limit of the exception handler is the address of the instruction *just after* the handled region. I haven't looked at the gcj failure yet. Tom
Responsible-Changed-From-To: unassigned->tromey Responsible-Changed-Why: I'm handling the administrivia
State-Changed-From-To: open->closed State-Changed-Why: Thanks for your report. Andrew recently checked in a fix which allows this bytecode but issues a warning. This will appear in gcc 3.3.
From: tromey@gcc.gnu.org To: gcc-gnats@gcc.gnu.org Cc: Subject: java/5794 Date: 11 Sep 2002 19:37:03 -0000 CVSROOT: /cvs/gcc Module name: gcc Changes by: tromey@gcc.gnu.org 2002-09-11 12:37:03 Modified files: gcc/java : ChangeLog verify.c Log message: 2002-09-03 Jesse Rosenstock <jmr@ugcs.caltech.edu> For PR java/5794: * verify.c (verify_jvm_instructions) [OPCODE_jsr]: Only push the return label if a ret instruction for the jsr has been reached. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/java/ChangeLog.diff?cvsroot=gcc&r1=1.1048&r2=1.1049 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/java/verify.c.diff?cvsroot=gcc&r1=1.49&r2=1.50
From: jakub@gcc.gnu.org To: gcc-gnats@gcc.gnu.org Cc: Subject: java/5794 Date: 16 Oct 2002 21:26:49 -0000 CVSROOT: /cvs/gcc Module name: egcs Branch: gcc-3_2-rhl8-branch Changes by: jakub@gcc.gnu.org 2002-10-16 14:26:48 Modified files: gcc : ChangeLog expr.c langhooks-def.h langhooks.h langhooks.c fold-const.c Makefile.in gcc/java : ChangeLog parse.y lang.c lex.c jcf-write.c expr.c except.c verify.c jcf-dump.c libjava/testsuite/libjava.lang: Array_3.java libjava/testsuite: ChangeLog Added files: libjava/testsuite/libjava.compile: narrow_case.java zeroexp.java libjava/testsuite/libjava.lang: EvaluationOrder.java EvaluationOrder.out utf8concat.java Log message: gcc/ 2002-10-16 Jakub Jelinek <jakub@redhat.com> * fold-const.c: Include langhooks.h. * Makefile.in (fold-const.o): Depend on langhooks.h. 2002-08-21 Tom Tromey <tromey@redhat.com> For PR java/6005 and PR java/7611: * fold-const.c (fold_truthop): Use can_use_bit_fields_p. (fold): Likewise. * langhooks.c (lhd_can_use_bit_fields_p): New function. * langhooks-def.h (lhd_can_use_bit_fields_p): Declare. (LANG_HOOKS_CAN_USE_BIT_FIELDS_P): New define. (LANG_HOOKS_INITIALIZER): Use it. * langhooks.h (struct lang_hooks) [can_use_bit_fields_p]: New field. 2002-07-24 Richard Henderson <rth@redhat.com> * expr.c (expand_expr) [TRY_FINALLY_EXPR]: Use GOTO_SUBROUTINE_EXPR form when not optimizing. 2002-07-21 Richard Henderson <rth@redhat.com> * expr.c (expand_expr) [TRY_FINALLY_EXPR]: Don't use GOTO_SUBROUTINE_EXPR when finally_block can be re-expanded. gcc/java/ 2002-10-15 Andrew Haley <aph@redhat.com> * parse.y (patch_invoke): Call force_evaluation_order on a static arg list. (resolve_qualified_expression_name): Call force_evaluation_order on a arg list that is part of a Qualified Expression Name. 2002-10-09 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> * parse.y (merge_string_cste): Add parentheses around & within |. 2002-10-08 Tom Tromey <tromey@redhat.com> * parse.y (variable_declarator_id): Simplify error path for array declarator error. For PR java/8003. 2002-10-07 Anthony Green <green@redhat.com> * parse.y (merge_string_cste): Fix bug in string concatenation. 2002-10-01 Nathan Sidwell <nathan@codesourcery.com> * jcf-dump.c (print_constant, case CONSTANT_float): Don't fall foul of type-based aliasing. 2002-09-26 Andrew Haley <aph@redhat.com> * expr.c (build_java_array_length_access): Check for null pointer. * expr.c (expand_java_arrayload): Likewise. 2002-09-17 Tom Tromey <tromey@redhat.com> * lex.c (java_read_unicode_collapsing_terminators): Handle case where \r appears at EOF. Fixes PR java/7950. 2002-09-11 Per Bothner <per@bothner.com> * parse.y (fold_constant_for_init): If a VAR_DECL, convert numerical constant to the type of the field. (java_complete_tree): Remove now-redundant code. * parse.y (fold_constant_for_init): 'null' is not a constant expr. 2002-09-03 Jesse Rosenstock <jmr@ugcs.caltech.edu> For PR java/5794: * verify.c (verify_jvm_instructions) [OPCODE_jsr]: Only push the return label if a ret instruction for the jsr has been reached. 2002-08-28 Andrew Haley <aph@redhat.com> * verify.c (verify_jvm_instructions): Allow exception handler inside code that is being protected, but generate a warning. * except.c (link_handler): Initialize `expanded' in new eh_range. (binding_depth, is_class_level, current_pc): Declare extern. 2002-08-26 Tom Tromey <tromey@redhat.com> * parse.y (try_builtin_assignconv): Allow narrowing primitive conversion if RHS_TYPE is byte, short, or char. 2002-08-21 Tom Tromey <tromey@redhat.com> For PR java/6005 and PR java/7611: * lang.c (LANG_HOOKS_CAN_USE_BITFIELDS_P): New define. (java_can_use_bit_fields_p): New function. 2002-08-08 Bryce McKinlay <bryce@waitaki.otago.ac.nz> * jcf-write.c (get_access_flags): Return correct access flags for private and protected inner classes. 2002-07-22 Tom Tromey <tromey@redhat.com> * lex.c (java_lex): Check for `e' or `E' after 0. 2002-07-21 Richard Henderson <rth@redhat.com> * lang.c (java_unsafe_for_reeval): New. (LANG_HOOKS_UNSAFE_FOR_REEVAL): New. 2002-07-01 Tom Tromey <tromey@redhat.com> For PR libgcj/7073: * parse.y (patch_incomplete_class_ref): Handle VOID_TYPE specially. libjava/testsuite/ 2002-10-15 Andrew Haley <aph@redhat.com> * libjava.lang/EvaluationOrder.java (EvaluationOrder): New. * libjava.lang/EvaluationOrder.out (EvaluationOrder): New. 2002-10-03 Andrew Haley <aph@redhat.com> * libjava.lang/Array_3.java (baz): New. (main): Call baz. 2002-09-29 Anthony Green <green@redhat.com> * libjava.lang/utf8concat.java: New file. * libjava.lang/utf8concat.out: Ditto. 2002-08-26 Tom Tromey <tromey@redhat.com> * libjava.compile/narrow_case.java: New file. 2002-07-22 Tom Tromey <tromey@redhat.com> * libjava.compile/zeroexp.java: New file. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.13152.2.657.2.27.2.21&r2=1.13152.2.657.2.27.2.22 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/expr.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.423.2.19.4.1.2.3&r2=1.423.2.19.4.1.2.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/langhooks-def.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.8.10.2.2.1.2.2&r2=1.8.10.2.2.1.2.3 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/langhooks.h.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.15.8.2.2.1.2.2&r2=1.15.8.2.2.1.2.3 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/langhooks.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.16.2.2.4.1.2.2&r2=1.16.2.2.4.1.2.3 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/fold-const.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.185.2.4.4.1&r2=1.185.2.4.4.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/Makefile.in.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.830.2.15.4.3&r2=1.830.2.15.4.4 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.925.2.59.2.2.2.2&r2=1.925.2.59.2.2.2.3 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/parse.y.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.353.2.19&r2=1.353.2.19.4.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/lang.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.85.2.4.4.2&r2=1.85.2.4.4.3 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/lex.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.80.8.4&r2=1.80.8.4.8.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/jcf-write.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.99.2.4&r2=1.99.2.4.4.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/expr.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.132.2.10&r2=1.132.2.10.4.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/except.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.26.20.1&r2=1.26.20.1.8.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/verify.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.47&r2=1.47.14.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/gcc/java/jcf-dump.c.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.42.2.2&r2=1.42.2.2.8.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.compile/narrow_case.java.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.16.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.compile/zeroexp.java.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.18.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.lang/EvaluationOrder.java.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.lang/EvaluationOrder.out.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.lang/utf8concat.java.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=NONE&r2=1.1.10.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/libjava.lang/Array_3.java.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.1&r2=1.1.26.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/egcs/libjava/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_2-rhl8-branch&r1=1.177.2.24.2.2&r2=1.177.2.24.2.2.2.1