Comment 7 for bug 674146

Revision history for this message
Colin Watson (cjwatson) wrote :

Thanks, James! You're right that sometimes optimisation changes can simply expose application bugs, but in this case I agree with you that this appears to be a compiler bug. I did a little bit of single-stepping through parse_warn once you pointed that out as the place where everything was going wrong, and it seems to be setting up the input buffer for vfprintf wrongly. The first few lines of code in that function are:

  parse_error_msg(ps, pigp, _("warning"), buf1);
  q = str_escape_fmt(buf2, buf1);
  strcat(q, fmt);

The strcat is compiled to this assembly (according to 'disas' in gdb):

   0x00010258 <+80>: mov r1, r8
   0x0001025a <+82>: mov r7, r0
   0x0001025c <+84>: blx 0x9a40 <strcat>

r8 is set up earlier, before the call to parse_error_msg, like this:

   0x00010232 <+42>: ldr.w r8, [r6], #4

At that point, according to 'info registers', it's pointing to fmt. But r8 is spilled by the call to parse_error_msg, so strcat is not in fact called with the arguments it's supposed to be called with. You can see even with C-level single-stepping that it's entirely wrong - buf2 ends up with two copies of the error message generated by parse_error_msg, rather than one copy followed by fmt.

As the next step, it might be worth looking in 'info gcc' to find the individual -ffoo optimisation flags enabled by -O2 vs. -O0, and bisect to find which ones generate incorrect assembly. For a compiler bug, in general, we should also be trying to produce a reduced test case, as this will need to be a bit smaller than "compile dpkg" in order to pass to a compiler engineer.