* [patch] Workaround gcc bug 49906
@ 2011-10-25 18:12 Aleksandar Ristovski
2011-10-28 21:00 ` Jan Kratochvil
0 siblings, 1 reply; 7+ messages in thread
From: Aleksandar Ristovski @ 2011-10-25 18:12 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1490 bytes --]
Hello,
Apparently gcc has quite a bit of issues generating proper line
information. One of particularly harmful ones are described in gcc bug
49906. While on x86 they appear to be benign (save the odd line where
breakpoint ends up being set), on arm it may cause gdb to not be able to
step into such function (when software single stepping) or, worse even,
breakpoint set on such function using "break <fnname>" syntax may be set
on non reachable instruction thus never being hit.
The patch attached addresses this issue by performing further sanity
checking and discarding results of skipping over prologue if there is
any suspicion that the line information may be bogus/invalid/buggy.
In addition to the patch, I'm attaching new test. Full regression test
shows no regressions (that is, the new test FAILs on current code, and
passes with the patch).
Thanks,
Aleksandar Ristovski
QNX Software Systems
gdb/ChangeLog:
2011-10-25 Aleksandar Ristovski <aristovski@qnx.com>
* symtab.c (skip_prologue_sal): Introduced start_sal_orig to keep
entry value. Added check for line after the prologue. If line
information for the next line exists but appears to be before in
the code, discard skip over prologue work and revert original sal.
gdb/testsuite/ChangeLog:
2011-10-25 Aleksandar Ristovski <aristovski@qnx.com>
* prologue-gccbug49906.exp: New test.
* prologue.c (f_gccbuf49906): New function, call new function.
[-- Attachment #2: gccpr49906-workaround-lineinfo-HEAD-201110251328.patch --]
[-- Type: text/x-patch, Size: 2825 bytes --]
Index: gdb/symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.283
diff -u -p -r1.283 symtab.c
--- gdb/symtab.c 21 Jul 2011 15:13:29 -0000 1.283
+++ gdb/symtab.c 25 Oct 2011 17:28:46 -0000
@@ -2474,6 +2474,7 @@ skip_prologue_sal (struct symtab_and_lin
struct gdbarch *gdbarch;
struct block *b, *function_block;
int force_skip, skip;
+ const struct symtab_and_line start_sal_orig = *sal;
/* Do not change the SAL is PC was specified explicitly. */
if (sal->explicit_pc)
@@ -2627,6 +2628,29 @@ skip_prologue_sal (struct symtab_and_lin
sal->line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
sal->symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block));
}
+ else
+ {
+ /* Check if line number of apparent prologue end comes after
+ the next line information. If so, do not skip prologue
+ as something odd has happened. Probably gcc bug 49906.
+ Instead of giving awkward location for the function start,
+ give the previous good line (fuction start). */
+ const struct symtab_and_line prologue_sal_next
+ = find_pc_line (sal->end, 0);
+
+ if ((sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= prologue_sal_next.end
+ && prologue_sal_next.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
+ : (lookup_minimal_symbol_by_pc_section (prologue_sal_next.end,
+ section)
+ == lookup_minimal_symbol_by_pc_section (sal->pc, section)))
+ && prologue_sal_next.line != 0
+ && prologue_sal_next.symtab == sal->symtab
+ && prologue_sal_next.line >= start_sal_orig.line
+ && prologue_sal_next.line < sal->line)
+ {
+ *sal = start_sal_orig;
+ }
+ }
}
/* If P is of the form "operator[ \t]+..." where `...' is
@@ -4432,7 +4456,24 @@ skip_prologue_using_sal (struct gdbarch
/* Assume that a consecutive SAL for the same (or larger)
line mark the prologue -> body transition. */
if (sal.line >= prologue_sal.line)
- break;
+ {
+ /* If the sal following SAL has line number lower than
+ SAL.LINE, then something is fishy.
+ Possibly gcc bug 49906 */
+ const struct symtab_and_line prologue_sal_next
+ = find_pc_line (sal.end, 0);
+
+ if (prologue_sal_next.end < end_pc
+ && prologue_sal_next.line != 0
+ && prologue_sal_next.symtab == sal.symtab
+ && prologue_sal_next.line >= prologue_sal.line
+ && prologue_sal_next.line < sal.line)
+ /* Fishy: we have something past prologue that appears
+ in the source as before. Be conservative and return
+ start of the prologue. That's the best guess anyway. */
+ prologue_sal.end = prologue_sal.pc;
+ break;
+ }
/* The line number is smaller. Check that it's from the
same function, not something inlined. If it's inlined,
[-- Attachment #3: gccpr49906-workaround-lineinfo-HEAD-test-201110251329.patch --]
[-- Type: text/x-patch, Size: 2817 bytes --]
Index: gdb/testsuite/gdb.base/prologue-gccbug49906.exp
===================================================================
RCS file: gdb/testsuite/gdb.base/prologue-gccbug49906.exp
diff -N gdb/testsuite/gdb.base/prologue-gccbug49906.exp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ gdb/testsuite/gdb.base/prologue-gccbug49906.exp 25 Oct 2011 17:29:12 -0000
@@ -0,0 +1,45 @@
+# Test for prologue skipping in minimal symbols with line info when
+# compiled with -O0. Test workaround gcc bug 49906.
+# Copyright 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+set testfile "prologue"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug optimize=-O0}] != "" } {
+ untested prologue.exp
+ return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
+set loc_end_of_prologue_workaround [gdb_get_line_number "end of prologue workaround"]
+set loc_end_of_prologue_broken [gdb_get_line_number "end of prologue broken"]
+
+# Test less human-confusing breakpoint location in case weirdness is
+# encountered.
+gdb_test "break f_gccbug49906"\
+ "Breakpoint.*at.*file.*$srcfile,.*line.*$loc_end_of_prologue_workaround\\."\
+ "Workaround gcc bug 49906 worked"
+
Index: gdb/testsuite/gdb.base/prologue.c
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/prologue.c,v
retrieving revision 1.6
diff -u -p -r1.6 prologue.c
--- gdb/testsuite/gdb.base/prologue.c 1 Jan 2011 15:33:42 -0000 1.6
+++ gdb/testsuite/gdb.base/prologue.c 25 Oct 2011 17:29:12 -0000
@@ -16,6 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+static int i;
+static void
+f_gccbug49906 (void)
+{ for (;;) /* end of prologue workaround - Weird style intended! */
+ if (i++)
+ break;
+} /* end of prologue broken */
+
int leaf (void)
{
return 1;
@@ -33,6 +42,7 @@ int main(void)
{
marker (0);
marker (0);
+ f_gccbug49906 (); /* set breakpoint here */
return 0;
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-25 18:12 [patch] Workaround gcc bug 49906 Aleksandar Ristovski
@ 2011-10-28 21:00 ` Jan Kratochvil
2011-10-28 21:23 ` Aleksandar Ristovski
0 siblings, 1 reply; 7+ messages in thread
From: Jan Kratochvil @ 2011-10-28 21:00 UTC (permalink / raw)
To: Aleksandar Ristovski; +Cc: gdb-patches
Hello Aleksandar,
the problem is that for this testcase:
/*1*/ static int i;
/*2*/ static void
/*3*/ f (int q)
/*4*/ {
/*5*/ for (;; i--)
/*6*/ if (i++)
/*7*/ break;
/*8*/ }
/*9*/ int main (void) { f (5); return 0; }
Built with:
gcc -o f2 f2.c -Wall -g -Werror
gcc (GCC) 4.6.3 20111028 (prerelease) -- the version should not matter
x86_64
it has a regression
gdb ./f2 -ex 'b f' -ex r
FSF GDB HEAD:
Breakpoint 1, f (q=5) at f2.c:6
^
6 if (i++)
with your patch:
Breakpoint 1, f (q=0) at f2.c:4
^
4 {
For reader's convenience attaching objdump at the bottom of this mail.
After GCC PR/49906 gets fixed the regression would stay there I think as this
testcase has already fully correct .debug_line now; unless this work around
gets protected by some DW_AT_producer based GCC version check.
I do not say how to fix it but I do not find the regression acceptable as is.
On Tue, 25 Oct 2011 19:43:14 +0200, Aleksandar Ristovski wrote:
> In addition to the patch, I'm attaching new test.
As discussed on IRC to make such testcase useful with future fixed GCCs (and
to make it meaningful for future GCC debug changes in general) it should be
placed into gdb.dwarf2/ and either prepared by gcc -S -dA (FSF GCC preferred)
while making it unfortunatelt arch-dependent or best (but not required and
very time consuming to prepare) building it by hand such as:
gdb.dwarf2/dw2-unresolved-main.c
gdb.dwarf2/dw2-unresolved.S
> 2011-10-25 Aleksandar Ristovski <aristovski@qnx.com>
>
> * symtab.c (skip_prologue_sal): Introduced start_sal_orig to keep
> entry value. Added check for line after the prologue. If line
> information for the next line exists but appears to be before in
> the code, discard skip over prologue work and revert original sal.
The modified skip_prologue_using_sal function should be in ChangeLog.
> gdb/testsuite/ChangeLog:
>
> 2011-10-25 Aleksandar Ristovski <aristovski@qnx.com>
>
> * prologue-gccbug49906.exp: New test.
> * prologue.c (f_gccbuf49906): New function, call new function.
Here should be gdb.base/ prefix. Please give the testfile any name you find
but not just the 49906 number.
> --- gdb/symtab.c 21 Jul 2011 15:13:29 -0000 1.283
> +++ gdb/symtab.c 25 Oct 2011 17:28:46 -0000
> @@ -2474,6 +2474,7 @@ skip_prologue_sal (struct symtab_and_lin
> struct gdbarch *gdbarch;
> struct block *b, *function_block;
> int force_skip, skip;
> + const struct symtab_and_line start_sal_orig = *sal;
>
> /* Do not change the SAL is PC was specified explicitly. */
> if (sal->explicit_pc)
> @@ -2627,6 +2628,29 @@ skip_prologue_sal (struct symtab_and_lin
> sal->line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
> sal->symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block));
> }
> + else
> + {
> + /* Check if line number of apparent prologue end comes after
> + the next line information. If so, do not skip prologue
> + as something odd has happened. Probably gcc bug 49906.
> + Instead of giving awkward location for the function start,
> + give the previous good line (fuction start). */
> + const struct symtab_and_line prologue_sal_next
> + = find_pc_line (sal->end, 0);
> +
> + if ((sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= prologue_sal_next.end
Code formatting: sym ? (...
(I understand it is copy paste.)
> + && prologue_sal_next.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
here was incorrect indentation.
> + : (lookup_minimal_symbol_by_pc_section (prologue_sal_next.end,
> + section)
> + == lookup_minimal_symbol_by_pc_section (sal->pc, section)))
> + && prologue_sal_next.line != 0
> + && prologue_sal_next.symtab == sal->symtab
> + && prologue_sal_next.line >= start_sal_orig.line
> + && prologue_sal_next.line < sal->line)
Thanks,
Jan
0000000000400474 <f>:
f():
f2.c:4
400474: 55 push %rbp
400475: 48 89 e5 mov %rsp,%rbp
400478: 89 7d fc mov %edi,-0x4(%rbp)
f2.c:6
40047b: 8b 05 2f 04 20 00 mov 0x20042f(%rip),%eax # 6008b0 <i>
400481: 85 c0 test %eax,%eax
400483: 0f 95 c2 setne %dl
400486: 83 c0 01 add $0x1,%eax
400489: 89 05 21 04 20 00 mov %eax,0x200421(%rip) # 6008b0 <i>
40048f: 84 d2 test %dl,%dl
400491: 75 11 jne 4004a4 <f+0x30>
f2.c:5
400493: 8b 05 17 04 20 00 mov 0x200417(%rip),%eax # 6008b0 <i>
400499: 83 e8 01 sub $0x1,%eax
40049c: 89 05 0e 04 20 00 mov %eax,0x20040e(%rip) # 6008b0 <i>
f2.c:8
4004a2: eb d7 jmp 40047b <f+0x7>
f2.c:7
4004a4: 90 nop
f2.c:8
4004a5: 5d pop %rbp
4004a6: c3 retq
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-28 21:00 ` Jan Kratochvil
@ 2011-10-28 21:23 ` Aleksandar Ristovski
2011-10-28 22:15 ` Jan Kratochvil
0 siblings, 1 reply; 7+ messages in thread
From: Aleksandar Ristovski @ 2011-10-28 21:23 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
On 11-10-28 04:51 PM, Jan Kratochvil wrote:
> Hello Aleksandar,
>
> the problem is that for this testcase:
> /*1*/ static int i;
> /*2*/ static void
> /*3*/ f (int q)
> /*4*/ {
> /*5*/ for (;; i--)
> /*6*/ if (i++)
> /*7*/ break;
> /*8*/ }
> /*9*/ int main (void) { f (5); return 0; }
>
> Built with:
> gcc -o f2 f2.c -Wall -g -Werror
> gcc (GCC) 4.6.3 20111028 (prerelease) -- the version should not matter
> x86_64
>
> it has a regression
> gdb ./f2 -ex 'b f' -ex r
> FSF GDB HEAD:
> Breakpoint 1, f (q=5) at f2.c:6
> ^
> 6 if (i++)
> with your patch:
> Breakpoint 1, f (q=0) at f2.c:4
> ^
> 4 {
>
I think that if you dump line info for your test you will find that line
info is broken as well. Correct line info would yield answer "line 5"
after skipping prologue.
Your result looks slightly better because you did not put {..} for the
'for' block, but it is not correct.
IMO, with the fix, the result is better (beginning of the function block
is better IMO than first statement inside 'for' block).
> For reader's convenience attaching objdump at the bottom of this mail.
Could you do
objdump -W
and post the output?
---
Aleksandar
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-28 21:23 ` Aleksandar Ristovski
@ 2011-10-28 22:15 ` Jan Kratochvil
2011-10-29 0:10 ` Aleksandar Ristovski
2011-10-29 1:31 ` Aleksandar Ristovski
0 siblings, 2 replies; 7+ messages in thread
From: Jan Kratochvil @ 2011-10-28 22:15 UTC (permalink / raw)
To: Aleksandar Ristovski; +Cc: gdb-patches
On Fri, 28 Oct 2011 22:59:48 +0200, Aleksandar Ristovski wrote:
> On 11-10-28 04:51 PM, Jan Kratochvil wrote:
> >Hello Aleksandar,
> >
> >the problem is that for this testcase:
> >/*1*/ static int i;
> >/*2*/ static void
> >/*3*/ f (int q)
> >/*4*/ {
> >/*5*/ for (;; i--)
> >/*6*/ if (i++)
> >/*7*/ break;
> >/*8*/ }
> >/*9*/ int main (void) { f (5); return 0; }
> >
> >Built with:
> > gcc -o f2 f2.c -Wall -g -Werror
> > gcc (GCC) 4.6.3 20111028 (prerelease) -- the version should not matter
> > x86_64
> >
> >it has a regression
> > gdb ./f2 -ex 'b f' -ex r
> >FSF GDB HEAD:
> > Breakpoint 1, f (q=5) at f2.c:6
> > ^
> > 6 if (i++)
> >with your patch:
> > Breakpoint 1, f (q=0) at f2.c:4
> > ^
> > 4 {
> >
>
> I think that if you dump line info for your test you will find that
> line info is broken as well. Correct line info would yield answer
> "line 5" after skipping prologue.
There is no code to produce for that line - for the before-part
of `for (;; anything)'.
If "line 5" should have code (="nop") after prologue even the "do {" line
should have "nop" in:
void f (void)
{
do /* It seems you suggest a "nop" here. */
{
i++; /* The first line after prologue is here now. */
}
while (i--);
}
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.
> 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).
> >For reader's convenience attaching objdump at the bottom of this mail.
>
> Could you do
>
> objdump -W
>
> and post the output?
Not sure which part do you look for but including below, it is not so long.
Thanks,
Jan
------------------------------------------------------------------------------
static int i;
static void
f (int q)
{
for (;; i--)
if (i++)
break;
}
int main (void) { f (5); return 0; }
------------------------------------------------------------------------------
0000000000400454 <f>:
f():
/home/jkratoch/t/f2.c:4
400454: 55 push %rbp
400455: 48 89 e5 mov %rsp,%rbp
400458: 89 7d fc mov %edi,-0x4(%rbp)
/home/jkratoch/t/f2.c:6
40045b: 8b 05 27 04 20 00 mov 0x200427(%rip),%eax # 600888 <i>
400461: 85 c0 test %eax,%eax
400463: 0f 95 c2 setne %dl
400466: 83 c0 01 add $0x1,%eax
400469: 89 05 19 04 20 00 mov %eax,0x200419(%rip) # 600888 <i>
40046f: 84 d2 test %dl,%dl
400471: 75 11 jne 400484 <f+0x30>
/home/jkratoch/t/f2.c:5
400473: 8b 05 0f 04 20 00 mov 0x20040f(%rip),%eax # 600888 <i>
400479: 83 e8 01 sub $0x1,%eax
40047c: 89 05 06 04 20 00 mov %eax,0x200406(%rip) # 600888 <i>
/home/jkratoch/t/f2.c:8
400482: eb d7 jmp 40045b <f+0x7>
/home/jkratoch/t/f2.c:7
400484: 90 nop
/home/jkratoch/t/f2.c:8
400485: 5d pop %rbp
400486: c3 retq
------------------------------------------------------------------------------
f2: file format elf64-x86-64
Contents of the .eh_frame section:
00000000 00000014 00000000 CIE
Version: 1
Augmentation: "zR"
Code alignment factor: 1
Data alignment factor: -8
Return address column: 16
Augmentation data: 1b
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_offset: r16 (rip) at cfa-8
DW_CFA_nop
DW_CFA_nop
00000018 00000024 0000001c FDE cie=00000000 pc=fffffffffffffd90..fffffffffffffdb0
DW_CFA_def_cfa_offset: 16
DW_CFA_advance_loc: 6 to fffffffffffffd96
DW_CFA_def_cfa_offset: 24
DW_CFA_advance_loc: 10 to fffffffffffffda0
DW_CFA_def_cfa_expression (DW_OP_breg7 (rsp): 8; DW_OP_breg16 (rip): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3; DW_OP_shl; DW_OP_plus)
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000040 0000001c 00000044 FDE cie=00000000 pc=fffffffffffffe94..fffffffffffffec7
DW_CFA_advance_loc: 1 to fffffffffffffe95
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to fffffffffffffe98
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 46 to fffffffffffffec6
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000060 0000001c 00000064 FDE cie=00000000 pc=fffffffffffffec7..fffffffffffffedc
DW_CFA_advance_loc: 1 to fffffffffffffec8
DW_CFA_def_cfa_offset: 16
DW_CFA_offset: r6 (rbp) at cfa-16
DW_CFA_advance_loc: 3 to fffffffffffffecb
DW_CFA_def_cfa_register: r6 (rbp)
DW_CFA_advance_loc: 16 to fffffffffffffedb
DW_CFA_def_cfa: r7 (rsp) ofs 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000080 00000024 00000084 FDE cie=00000000 pc=fffffffffffffee0..ffffffffffffff69
DW_CFA_advance_loc: 17 to fffffffffffffef1
DW_CFA_offset: r12 (r12) at cfa-40
DW_CFA_offset: r6 (rbp) at cfa-48
DW_CFA_advance_loc: 31 to ffffffffffffff10
DW_CFA_def_cfa_offset: 64
DW_CFA_offset: r3 (rbx) at cfa-56
DW_CFA_offset: r15 (r15) at cfa-16
DW_CFA_offset: r14 (r14) at cfa-24
DW_CFA_offset: r13 (r13) at cfa-32
DW_CFA_advance_loc1: 88 to ffffffffffffff68
DW_CFA_def_cfa_offset: 8
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
000000a8 00000014 000000ac FDE cie=00000000 pc=ffffffffffffff70..ffffffffffffff72
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
000000c0 ZERO terminator
Contents of the .debug_aranges section:
Length: 44
Version: 2
Offset into .debug_info: 0x0
Pointer Size: 8
Segment Size: 0
Address Length
0000000000400454 0000000000000048
0000000000000000 0000000000000000
Contents of the .debug_info section:
Compilation Unit @ offset 0x0:
Length: 0x90 (32-bit)
Version: 2
Abbrev Offset: 0
Pointer Size: 8
<0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
<c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.6.3 20111028 (prerelease)
<10> DW_AT_language : 1 (ANSI C)
<11> DW_AT_name : (indirect string, offset: 0x22): f2.c
<15> DW_AT_comp_dir : (indirect string, offset: 0x27): /home/jkratoch/t
<19> DW_AT_low_pc : 0x400454
<21> DW_AT_high_pc : 0x40049c
<29> DW_AT_stmt_list : 0x0
<1><2d>: Abbrev Number: 2 (DW_TAG_subprogram)
<2e> DW_AT_name : f
<30> DW_AT_decl_file : 1
<31> DW_AT_decl_line : 3
<32> DW_AT_prototyped : 1
<33> DW_AT_low_pc : 0x400454
<3b> DW_AT_high_pc : 0x400487
<43> DW_AT_frame_base : 0x0 (location list)
<47> DW_AT_sibling : <0x58>
<2><4b>: Abbrev Number: 3 (DW_TAG_formal_parameter)
<4c> DW_AT_name : q
<4e> DW_AT_decl_file : 1
<4f> DW_AT_decl_line : 3
<50> DW_AT_type : <0x58>
<54> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
<1><58>: Abbrev Number: 4 (DW_TAG_base_type)
<59> DW_AT_byte_size : 4
<5a> DW_AT_encoding : 5 (signed)
<5b> DW_AT_name : int
<1><5f>: Abbrev Number: 5 (DW_TAG_subprogram)
<60> DW_AT_external : 1
<61> DW_AT_name : (indirect string, offset: 0x38): main
<65> DW_AT_decl_file : 1
<66> DW_AT_decl_line : 9
<67> DW_AT_prototyped : 1
<68> DW_AT_type : <0x58>
<6c> DW_AT_low_pc : 0x400487
<74> DW_AT_high_pc : 0x40049c
<7c> DW_AT_frame_base : 0x60 (location list)
<1><80>: Abbrev Number: 6 (DW_TAG_variable)
<81> DW_AT_name : i
<83> DW_AT_decl_file : 1
<84> DW_AT_decl_line : 1
<85> DW_AT_type : <0x58>
<89> DW_AT_location : 9 byte block: 3 88 8 60 0 0 0 0 0 (DW_OP_addr: 600888)
Contents of the .debug_abbrev section:
Number TAG
1 DW_TAG_compile_unit [has children]
DW_AT_producer DW_FORM_strp
DW_AT_language DW_FORM_data1
DW_AT_name DW_FORM_strp
DW_AT_comp_dir DW_FORM_strp
DW_AT_low_pc DW_FORM_addr
DW_AT_high_pc DW_FORM_addr
DW_AT_stmt_list DW_FORM_data4
2 DW_TAG_subprogram [has children]
DW_AT_name DW_FORM_string
DW_AT_decl_file DW_FORM_data1
DW_AT_decl_line DW_FORM_data1
DW_AT_prototyped DW_FORM_flag
DW_AT_low_pc DW_FORM_addr
DW_AT_high_pc DW_FORM_addr
DW_AT_frame_base DW_FORM_data4
DW_AT_sibling DW_FORM_ref4
3 DW_TAG_formal_parameter [no children]
DW_AT_name DW_FORM_string
DW_AT_decl_file DW_FORM_data1
DW_AT_decl_line DW_FORM_data1
DW_AT_type DW_FORM_ref4
DW_AT_location DW_FORM_block1
4 DW_TAG_base_type [no children]
DW_AT_byte_size DW_FORM_data1
DW_AT_encoding DW_FORM_data1
DW_AT_name DW_FORM_string
5 DW_TAG_subprogram [no children]
DW_AT_external DW_FORM_flag
DW_AT_name DW_FORM_strp
DW_AT_decl_file DW_FORM_data1
DW_AT_decl_line DW_FORM_data1
DW_AT_prototyped DW_FORM_flag
DW_AT_type DW_FORM_ref4
DW_AT_low_pc DW_FORM_addr
DW_AT_high_pc DW_FORM_addr
DW_AT_frame_base DW_FORM_data4
6 DW_TAG_variable [no children]
DW_AT_name DW_FORM_string
DW_AT_decl_file DW_FORM_data1
DW_AT_decl_line DW_FORM_data1
DW_AT_type DW_FORM_ref4
DW_AT_location DW_FORM_block1
Raw dump of debug contents of section .debug_line:
Offset: 0x0
Length: 57
DWARF Version: 2
Prologue Length: 27
Minimum Instruction Length: 1
Initial value of 'is_stmt': 1
Line Base: -5
Line Range: 14
Opcode Base: 13
Opcodes:
Opcode 1 has 0 args
Opcode 2 has 1 args
Opcode 3 has 1 args
Opcode 4 has 1 args
Opcode 5 has 1 args
Opcode 6 has 0 args
Opcode 7 has 0 args
Opcode 8 has 0 args
Opcode 9 has 1 args
Opcode 10 has 0 args
Opcode 11 has 0 args
Opcode 12 has 1 args
The Directory Table is empty.
The File Name Table:
Entry Dir Time Size Name
1 0 0 0 f2.c
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
Contents of the .debug_str section:
0x00000000 474e5520 4320342e 362e3320 32303131 GNU C 4.6.3 2011
0x00000010 31303238 20287072 6572656c 65617365 1028 (prerelease
0x00000020 29006632 2e63002f 686f6d65 2f6a6b72 ).f2.c./home/jkr
0x00000030 61746f63 682f7400 6d61696e 00 atoch/t.main.
Contents of the .debug_loc section:
Offset Begin End Expression
00000000 0000000000400454 0000000000400455 (DW_OP_breg7 (rsp): 8)
00000000 0000000000400455 0000000000400458 (DW_OP_breg7 (rsp): 16)
00000000 0000000000400458 0000000000400486 (DW_OP_breg6 (rbp): 16)
00000000 0000000000400486 0000000000400487 (DW_OP_breg7 (rsp): 8)
00000000 <End of list>
00000060 0000000000400487 0000000000400488 (DW_OP_breg7 (rsp): 8)
00000060 0000000000400488 000000000040048b (DW_OP_breg7 (rsp): 16)
00000060 000000000040048b 000000000040049b (DW_OP_breg6 (rbp): 16)
00000060 000000000040049b 000000000040049c (DW_OP_breg7 (rsp): 8)
00000060 <End of list>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-28 22:15 ` Jan Kratochvil
@ 2011-10-29 0:10 ` Aleksandar Ristovski
2011-10-29 9:21 ` Jan Kratochvil
2011-10-29 1:31 ` Aleksandar Ristovski
1 sibling, 1 reply; 7+ messages in thread
From: Aleksandar Ristovski @ 2011-10-29 0:10 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-28 22:15 ` Jan Kratochvil
2011-10-29 0:10 ` Aleksandar Ristovski
@ 2011-10-29 1:31 ` Aleksandar Ristovski
1 sibling, 0 replies; 7+ messages in thread
From: Aleksandar Ristovski @ 2011-10-29 1:31 UTC (permalink / raw)
To: gdb-patches
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
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [patch] Workaround gcc bug 49906
2011-10-29 0:10 ` Aleksandar Ristovski
@ 2011-10-29 9:21 ` Jan Kratochvil
0 siblings, 0 replies; 7+ messages in thread
From: Jan Kratochvil @ 2011-10-29 9:21 UTC (permalink / raw)
To: Aleksandar Ristovski; +Cc: gdb-patches
On Sat, 29 Oct 2011 02:08:04 +0200, Aleksandar Ristovski wrote:
> 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.
I agree line 8 is wrong, this is what is filed as GCC PR debug/49906.
The question is whether the right line is 6 or whether it should be 5.
If it is 5 with so many nops everywhere I am not sure the debugging is more
comfortable. IMO when one does "step" one expects some changes in the
inferior happen.
> 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.
It is questionable how hard it should be pushed for in GDB when the right fix
should be done in GCC anyway (I pinged Dodji Seketeli for it yesterday).
My most serious concern is the workaround should not affect any correctly
produced debuginfo (by non-GCC or future GCC compilers). If there is no other
way than a hack with side-effects then it is IMHO more suitable for vendor
branches of GDB (I make sometimes such hacks in Fedora Rawhide for fresh
GCCs).
There is for example a possibility to make the workaround arch-dependent
finding the last jump instruction and breaking on it, I made a similar
.debug_line workaround recently which should have no side-effects:
[patch] workaround gcc46: prologue skip skips too far (PR 12435) #2
http://sourceware.org/ml/gdb-patches/2011-07/msg00645.html
Thanks,
Jan
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2011-10-29 8:23 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-25 18:12 [patch] Workaround gcc bug 49906 Aleksandar Ristovski
2011-10-28 21:00 ` Jan Kratochvil
2011-10-28 21:23 ` Aleksandar Ristovski
2011-10-28 22:15 ` Jan Kratochvil
2011-10-29 0:10 ` Aleksandar Ristovski
2011-10-29 9:21 ` Jan Kratochvil
2011-10-29 1:31 ` Aleksandar Ristovski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox