In article <OFBB03BF8A.CEB4306F-ONC2257023.00278DA1-C2257023.0028E0B6 / stonesoft.com>, ville.mattila / stonesoft.com writes: > I binary searched the offending change it is: I investigated the problem. | % gdb miniruby | GNU gdb 6.3 | Copyright 2004 Free Software Foundation, Inc. | GDB is free software, covered by the GNU General Public License, and you are | welcome to change it and/or distribute copies of it under certain conditions. | Type "show copying" to see the conditions. | There is absolutely no warranty for GDB. Type "show warranty" for details. | This GDB was configured as "sparc-sun-solaris2.8"... | (gdb) display/i $pc | (gdb) run -e '1.times do next end' '1.times do next end' is a minimized script to reproduce the problem. | Starting program: /home/akr/y/ruby/miniruby -e '1.times do next end' | [New LWP 1] | [New LWP 2] | [New LWP 3] | | Program received signal SIGSEGV, Segmentation fault. | 0x00027c00 in rb_yield_0 (val=1, self=1116224, klass=0, flags=0, avalue=0) at defines.h:213 | 213 asm | 1: x/i $pc 0x27c00 <rb_yield_0+956>: ld [ %o3 + 0x1c0 ], %i3 | (gdb) p $o3 | $1 = 0 SEGV is caused by access around 0. | (gdb) disassemble | Dump of assembler code for function rb_yield_0: | 0x00027844 <rb_yield_0+0>: save %sp, -712, %sp ... | 0x00027bec <rb_yield_0+936>: sethi %hi(0xc8400), %o0 | 0x00027bf0 <rb_yield_0+940>: sethi %hi(0xd4400), %l1 | 0x00027bf4 <rb_yield_0+944>: call 0xc6f7c <getcontext> | 0x00027bf8 <rb_yield_0+948>: ld [ %l1 + 0x1f4 ], %o0 ! 0xd45f4 <prot_tag> | 0x00027bfc <rb_yield_0+952>: ld [ %l1 + 0x1f4 ], %o3 | 0x00027c00 <rb_yield_0+956>: ld [ %o3 + 0x1c0 ], %i3 | 0x00027c04 <rb_yield_0+960>: cmp %i3, 0 ... | 0x00028250 <rb_yield_0+2572>: restore | End of assembler dump. | (gdb) break *0x00027bf4 | Breakpoint 1 at 0x27bf4: file defines.h, line 213. A breakpoint is set before calling getcontext. | (gdb) break *0x00027bfc | Breakpoint 2 at 0x27bfc: file defines.h, line 213. A breakpoint is set after calling getcontext. | (gdb) run -e '1.times do next end' | The program being debugged has been started already. | Start it from the beginning? (y or n) y | Starting program: /home/akr/y/ruby/miniruby -e '1.times do next end' | [New LWP 1] | [New LWP 2] | [New LWP 3] | | Breakpoint 1, 0x00027bf4 in rb_yield_0 (val=1, self=1116224, klass=0, flags=0, avalue=0) at defines.h:213 | 213 asm | 1: x/i $pc 0x27bf4 <rb_yield_0+944>: call 0xc6f7c <getcontext> | (gdb) p $l1 | $2 = 869376 | (gdb) x $l1 + 0x1f4 | 0xd45f4 <prot_tag>: 0xffbed520 The register l1 is 869376 before getcontext is called. | (gdb) c | Continuing. | | Breakpoint 2, 0x00027bfc in rb_yield_0 (val=1, self=1116224, klass=0, flags=0, avalue=0) at defines.h:213 | 213 asm | 1: x/i $pc 0x27bfc <rb_yield_0+952>: ld [ %l1 + 0x1f4 ], %o3 | (gdb) p $l1 | $3 = 869376 | (gdb) x $l1 + 0x1f4 | 0xd45f4 <prot_tag>: 0xffbed520 | (gdb) si | 0x00027c00 213 asm | 1: x/i $pc 0x27c00 <rb_yield_0+956>: ld [ %o3 + 0x1c0 ], %i3 | (gdb) p $o3 | $4 = -4270816 | (gdb) si | 0x00027c04 213 asm | 1: x/i $pc 0x27c04 <rb_yield_0+960>: cmp %i3, 0 The register l1 is not changed after first getcontext return. | (gdb) c | Continuing. | | Breakpoint 2, 0x00027bfc in rb_yield_0 (val=1, self=1116224, klass=0, flags=0, avalue=0) at defines.h:213 | 213 asm | 1: x/i $pc 0x27bfc <rb_yield_0+952>: ld [ %l1 + 0x1f4 ], %o3 | (gdb) p $l1 | $5 = 1040288 The register l1 is changed after second getcontext return. | (gdb) x $l1 + 0x1f4 | 0xfe194: 0x00000000 | (gdb) x 869376 + 0x1f4 | 0xd45f4 <prot_tag>: 0xffbed520 | (gdb) si | 0x00027c00 213 asm | 1: x/i $pc 0x27c00 <rb_yield_0+956>: ld [ %o3 + 0x1c0 ], %i3 | (gdb) p $o3 | $6 = 0 The register o3 is 0 because l1 is changed. | (gdb) si | | Program received signal SIGSEGV, Segmentation fault. | 0x00027c00 in rb_yield_0 (val=1, self=1116224, klass=0, flags=0, avalue=0) at defines.h:213 | 213 asm | 1: x/i $pc 0x27c00 <rb_yield_0+956>: ld [ %o3 + 0x1c0 ], %i3 | (gdb) This is very similar to IA64 register stack problem. [ruby-talk:144939] It's not curious because SPARC has register window which is similar to IA64 register stack. But I'm curious because following change is intend to avoid the problem. > Changes since revision 1.2673.2.1064: +10 -0 lines > * eval.c (ruby_longjmp): new macro to call longjmp, setcontext, etc. > (ruby_setjmp): new macro to call setjmp, getcontext, etc. > (ruby_setjmp): call setjmp before getcontext to avoid IA64 register > stack problem. > [ruby-talk:144939] Although I'm not sure why the change doesn't avoid the problem on SPARC, I think following patch fix the problem. Index: eval.c =================================================================== RCS file: /src/ruby/eval.c,v retrieving revision 1.616.2.101 diff -u -r1.616.2.101 eval.c --- eval.c 12 Jun 2005 16:58:41 -0000 1.616.2.101 +++ eval.c 19 Jun 2005 08:03:33 -0000 @@ -133,9 +133,17 @@ * It is not required that setjmp is called at run time, since the problem is * register usage. */ +#if defined (__GNUC__) && (defined(sparc) || defined(__sparc__)) +#define DUMMY_SETJMP \ + ({ __asm__ volatile ("" : : : \ + "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", \ + "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7", \ + "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i7"); }) +#else static jmp_buf dummy_setjmp_jmp_buf; int dummy_setjmp_false = 0; #define DUMMY_SETJMP (dummy_setjmp_false ? setjmp(dummy_setjmp_jmp_buf) : 0) +#endif #define ruby_longjmp(env, val) rb_jump_context(env, val) #define ruby_setjmp(j) ((j)->status = 0, DUMMY_SETJMP, getcontext(&(j)->context), (j)->status) #else -- Tanaka Akira