[patch] Workaround gcc bug 49906

Aleksandar Ristovski aristovski@qnx.com
Sat Oct 29 01:31:00 GMT 2011


On 11-10-28 05:23 PM, Jan Kratochvil wrote:
> There is no code to produce for that line - for the before-part
> of `for (;; anything)'.

I believe this is in the background of the gcc bug.
> If you think there should be that "nop" I think GCC PR debug/49906 needs to be
> extended (and/or filed a new GCC PR) as GCC PR debug/49906 probably is not
> going to implement this "nop" there.

My point of view is that for source level debugging one would expect to 
start with what appears to be the first "something" in the source. 
Technically, it is correct what you are saying but if we are talking 
about what would be intuitive, then I think the very first line of code 
must be 'for' loop (even if it evaluates to 'nop').

Consider this test (which is what I was concentrating on):

(gdb) b foo
Breakpoint 1 at 0x4004ba: file foo.c, line 8.
(gdb) list foo
1       static int i;
2       static void
3       foo(void)
4       {
5         for (;;)
6               if (i++)
7                 break;
8       }
9
10

Line 8 is totally unintuitive and weird.

But I do not intend to get into discussion over cosmetics, please read 
on (sorry for the lengthy post) I will explain the actual motivation 
behind this patch.

>
>
>> IMO, with the fix, the result is better (beginning of the function
>> block is better IMO than first statement inside 'for' block).
>
> Without the fix it stops on the first executable statement.  This is
> a perfectly defined behavior.  Not if you noticed your patch breaks access to
> function parameters (and probably also affects local variables some way).

Ok, this is acceptable behaviour and if it were not for the issues I 
will describe below, I would not even try to fix anything.

>
> Not sure which part do you look for but including below, it is not so long.
>
>
> Thanks,
> Jan
>

I am looking for line number statements alongside disassembly. From this 
output, I can not argue that it is wrong, at a minimum it is not obvious 
and I don't want to continue with this particular example (maybe on IRC 
later).

> >   Line Number Statements:
>    Extended opcode 2: set Address to 0x400454
>    Special opcode 8: advance Address by 0 to 0x400454 and Line by 3 to 4
>    Special opcode 105: advance Address by 7 to 0x40045b and Line by 2 to 6
>    Advance PC by constant 17 to 0x40046c
>    Special opcode 102: advance Address by 7 to 0x400473 and Line by -1 to 5
>    Special opcode 218: advance Address by 15 to 0x400482 and Line by 3 to 8
>    Special opcode 32: advance Address by 2 to 0x400484 and Line by -1 to 7
>    Special opcode 20: advance Address by 1 to 0x400485 and Line by 1 to 8
>    Special opcode 34: advance Address by 2 to 0x400487 and Line by 1 to 9
>    Special opcode 61: advance Address by 4 to 0x40048b and Line by 0 to 9
>    Advance PC by constant 17 to 0x40049c
>    Extended opcode 1: End of Sequence
>
>


However, I have a real-life example that prompted work on this. On arm, 
with -O0 I have a for (;;) loop. The line information + current skipping 
over prologue in gdb, yields unreachable breakpoint which prevents 
stepping into the function using software single stepping (single step 
breakpoint is never hit) or can cause breakpoint set on the function to 
never be hit.


What follows is the excerpt from this sample I have on hands.


-------------- 8< -------------------
227 void foo() {
228     int rc;
229
230     //
231     for(;;) {
232         void *e = NULL;
233         rc = bar(&e, 0);
...
248     }
249 }

void foo() {
   1029a0:   e92d4800    push    {fp, lr}
   1029a4:   e28db004    add fp, sp, #4  ; 0x4
   1029a8:   e24dd010    sub sp, sp, #16 ; 0x10
   1029ac:   ea000000    b   1029b4 <foo+0x14>
   1029b0:   e1a00000    nop         (mov r0,r0)
   1029b4:   e3a03000    mov r3, #0  ; 0x0
...
   102a64:   eaffffd2    b   1029b4 <foo+0x14>
   102a68:   e24bd004    sub sp, fp, #4  ; 0x4
   102a6c:   e8bd8800    pop {fp, pc}


Line Number Statements:
...
   Special opcode 63: advance Address by 8 to 0x1029a0 and Line by 2 to 227
   Advance Line by 21 to 248
   Special opcode 117: advance Address by 16 to 0x1029b0 and Line by 0 
to 248
   Advance Line by -16 to 232
...
---------------- >8 ----------------------


Currently 'b foo' would yield address 0x1029b0 since gdb will look for 
function sal (0x1029a0, line 227) then look for the next one and find 
(0x1029b0, line 248). Let's leave aside for now the weird result of 
breakpoint for the function appearing at line 248 where function starts 
at line 227 and first statement that does something is at line 232, 
there is far more sinister consequence:

 From the assembly above it is clear that this 'nop' is never reached. 
See branch at 0x102a64 which is the closing of the loop.

This and some other examples I have created on x86 (including the 
testcase proposed here) prompted me to believe that the correct line 
information would always contain line information for the 'for' 
statement, e.g. in the above, there is a line info missing, something like:

   Special opcode 63: advance Address by 8 to 0x1029a0 and Line by 2 to 227
   Special opcode 63: advance Address by 12 to 0x1029ac and Line by 4 to 231
   Advance Line by 21 to 248
   Special opcode 117: advance Address by 14 to 0x1029b0 and Line by 0 
to 248
...

(it appears that on both arm and x86, compiler generates this "jump 
into" branch, which is what I would choose as the end of prologue, that 
is, as the instruction associated with the line where 'for' statement 
appears.)


In any case, I will revisit the whole thing paying attention to your 
test case - maybe there is no generic solution, but then again, I would 
choose the less bad solution over the plain broken one.




Thanks,

Aleksandar



More information about the Gdb-patches mailing list