Bug#648016: Some analysis

2011-11-14 Thread Matthias Klose
On 11/13/2011 01:31 PM, Jurij Smakov wrote:
> reassign 648016 gcc-4.6
> found 648016 4.6.2-4
> thanks
> 
> This bug really is in gcc-4.6, because it is currently the default sid 
> gcc and it is used to (mis)compile src/build/genrecog.c during 
> gcc-avr build, which later crashes. I'm fairly certain that this is 
> gcc problem, because if the binary is compiled with -O0, the problem 
> goes away. All debugging output below was obtained on a sparc machine 
> running up-to-date sid, invoking build/genrecog under gdb with a 
> single argument of '../../src/gcc/config/avr/avr.md'.

I don't plan to work on this.

for what reason is the cross compiler built for anything besides x86?



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org



Bug#648016: Some analysis

2011-11-13 Thread Jurij Smakov
reassign 648016 gcc-4.6
found 648016 4.6.2-4
thanks

This bug really is in gcc-4.6, because it is currently the default sid 
gcc and it is used to (mis)compile src/build/genrecog.c during 
gcc-avr build, which later crashes. I'm fairly certain that this is 
gcc problem, because if the binary is compiled with -O0, the problem 
goes away. All debugging output below was obtained on a sparc machine 
running up-to-date sid, invoking build/genrecog under gdb with a 
single argument of '../../src/gcc/config/avr/avr.md'.

Tracing the execution is somewhat tricky, since failure happens within 
write_tree(), and most of the functions write_tree() calls 
(write_tree_1, write_switch, write_node, write_action, etc) are
optimized out. The output generated by 

build/genrecog ../../src/gcc/config/avr/avr.md

is the same as the one produced on an amd64 system until we hit the 
following code in genrecog.c/write_switch(): 

  else if (type == DT_mode
   || type == DT_veclen
   || type == DT_elt_zero_int
   || type == DT_elt_one_int
   || type == DT_elt_zero_wide_safe)
{
  const char *indent = "";

  /* We cast switch parameter to integer, so we must ensure that the value
 fits.  */
  if (type == DT_elt_zero_wide_safe)
{
  indent = "  ";
  printf("  if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
}
  printf ("%s  switch (", indent);
  switch (type)
{
case DT_mode:
  printf ("GET_MODE (x%d)", depth);
  break;
case DT_veclen:
  printf ("XVECLEN (x%d, 0)", depth);
  break;
case DT_elt_zero_int:
  printf ("XINT (x%d, 0)", depth);
  break;
case DT_elt_one_int:
  printf ("XINT (x%d, 1)", depth);
  break;
case DT_elt_zero_wide_safe:
  /* Convert result of XWINT to int for portability since some C
 compilers won't do it and some will.  */
  printf ("(int) XWINT (x%d, 0)", depth);
  break;
default:
  gcc_unreachable ();
}

The problem appears after executing the 

printf ("%s  switch (", indent);

statetement. It looks like compiler generates a number of small stubs 
within write_tree() for calling printf with all possible format 
statements. Here's how the generated assembler code looks for this 
particular one, starting at 0x00013e60:

Dump of assembler code from 0x13e40 to 0x13ea0:
   0x00013e40 :ld  [ %i5 + 0x1c ], %o2
   0x00013e44 :sethi  %hi(0x1e800), %o0
   0x00013e48 :or  %l1, 0x110, %o1
   0x00013e4c :call  0x3510c 
   0x00013e50 :or  %o0, 0x258, %o0
   0x00013e54 :b  %xcc, 0x13bf4 
   0x00013e58 :ld  [ %i0 ], %i5
   0x00013e5c :be,pn   %icc, 0x13850 
=> 0x00013e60 :sethi  %hi(0x1f400), %i3
   0x00013e64 :sethi  %hi(0x1e800), %o0
   0x00013e68 :or  %o0, 0x2b0, %o0 ! 0x1eab0
   0x00013e6c :call  0x3510c 
   0x00013e70 :or  %i3, 0xe8, %o1
   0x00013e74 :cmp  %l7, 7
   0x00013e78 :sll  %l7, 2, %g1
   0x00013e7c :sethi  %hi(0x1e800), %o0
   0x00013e80 :mov  %l6, %o1
   0x00013e84 :call  0x3510c 
   0x00013e88 :or  %o0, 0x3e8, %o0
   0x00013e8c :b  %xcc, 0x13bac 
   0x00013e90 :ld  [ %fp + -192 ], %g3
   0x00013e94 :b  %xcc, 0x13ad0 
   0x00013e98 :st  %g2, [ %fp + -188 ]
   0x00013e9c :cmp  %g0, %i3
End of assembler dump.

Confirmation that 0x1eab0 contains the correct format statement 
(passed to printf in %o0):

(gdb) printf "%s\n", (char *) 0x1eab0
%s  switch (
(gdb)

A remarkable feature of this stub is that it does not have a return 
branch statement, like others do (see 0x00013e54, for example). So, 
instead of returning to the correct location where the stub was 
invoked in write_switch(), we fall through to 0x00013e74, and start 
executing the next stub, which invokes printf with a format 
statement at 0x1ebe8 (== 0x1e800 | 0x3e8):

(gdb) printf "%s\n", (char *) 0x1ebe8
%sreturn gen_split_%d (insn, operands);

(gdb) 

This is completely unrelated code, normally invoked by 
write_action(), line 2182. Once it's done, we jump back to completely 
wrong location at 0x00013e8c, eventually causing a crash.

Best regards,
-- 
Jurij Smakov   ju...@wooyd.org
Key: http://www.wooyd.org/pgpkey/  KeyID: C99E03CC



-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org