This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug debug/84550] [8 Regression] stepping through gcc does not work with gdb 8.0.1
- From: "kevinb at redhat dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 07 Mar 2018 00:17:22 +0000
- Subject: [Bug debug/84550] [8 Regression] stepping through gcc does not work with gdb 8.0.1
- Auto-submitted: auto-generated
- References: <bug-84550-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84550
--- Comment #11 from Kevin Buettner <kevinb at redhat dot com> ---
I've simplified Jakub's example slightly:
--- vau2.c ---
struct A { int a; };
struct B { struct A *b; };
struct C { struct B *c; };
__attribute__((noipa)) bool
foo (struct A *p)
{
return false;
}
__attribute__((noipa)) int
baz (int x)
{
return 0;
}
__attribute__((noipa)) void
qux (struct C *p)
{
struct A *a;
bool b;
int c;
if (!p->c) __builtin_abort ();
a = p->c->b;
b = (a->a == 4)
&& (foo (a));
c = baz (0);
baz (b);
}
int
main ()
{
struct A a = { 4 };
struct B b = { &a };
struct C c = { &b };
qux (&c);
return 0;
}
--- end vau2.c ---
When I compile this via "g++ -O2 -g vau2.c -o vau2", and load it into gdb, it
exhibits the same behavior shown by Jakub. I.e. the following sequence...
b qux
run
s
s
s
... does not stop in foo as expected. The program instead exits.
It turns out that qux consists of two disjoint pieces which, for some reason,
are separated by a lot of other code, e.g. main, _start, foo, baz, and a lot of
other stuff too. Here's what it looks like:
0x400460 <qux(C*)>: callq 0x400430 <abort@plt>
0x400465: nopw %cs:0x0(%rax,%rax,1)
0x40046f: nop
0x400470 <main()>: sub $0x28,%rsp
0x400474 <main()+4>: lea 0xc(%rsp),%rax
0x400479 <main()+9>: lea 0x18(%rsp),%rdi
0x40047e <main()+14>: movl $0x4,0xc(%rsp)
0x400486 <main()+22>: mov %rax,0x10(%rsp)
0x40048b <main()+27>: lea 0x10(%rsp),%rax
0x400490 <main()+32>: mov %rax,0x18(%rsp)
0x400495 <main()+37>: callq 0x4005b0 <_Z3quxP1C>
0x40049a <main()+42>: xor %eax,%eax
0x40049c <main()+44>: add $0x28,%rsp
0x4004a0 <main()+48>: retq
0x4004a1: nopw %cs:0x0(%rax,%rax,1)
0x4004ab: nopl 0x0(%rax,%rax,1)
0x4004b0 <_start>: xor %ebp,%ebp
0x4004b2 <_start+2>: mov %rdx,%r9
0x4004b5 <_start+5>: pop %rsi
0x4004b6 <_start+6>: mov %rsp,%rdx
0x4004b9 <_start+9>: and $0xfffffffffffffff0,%rsp
0x4004bd <_start+13>: push %rax
0x4004be <_start+14>: push %rsp
0x4004bf <_start+15>: mov $0x400660,%r8
0x4004c6 <_start+22>: mov $0x4005f0,%rcx
0x4004cd <_start+29>: mov $0x400470,%rdi
0x4004d4 <_start+36>: callq 0x400440 <__libc_start_main@plt>
0x4004d9 <_start+41>: hlt
...
0x400590 <foo(A*)>: xor %eax,%eax
0x400592 <foo(A*)+2>: retq
0x400593: nopl (%rax)
0x400596: nopw %cs:0x0(%rax,%rax,1)
0x4005a0 <baz(int)>: xor %eax,%eax
0x4005a2 <baz(int)+2>: retq
0x4005a3: nopl (%rax)
0x4005a6: nopw %cs:0x0(%rax,%rax,1)
0x4005b0 <_Z3quxP1C>: push %rbx
0x4005b1 <_Z3quxP1C+1>: mov (%rdi),%rax
0x4005b4 <_Z3quxP1C+4>: test %rax,%rax
0x4005b7 <_Z3quxP1C+7>: je 0x400460 <qux(C*)>
0x4005bd <_Z3quxP1C+13>: mov (%rax),%rdi
0x4005c0 <_Z3quxP1C+16>: xor %ebx,%ebx
0x4005c2 <_Z3quxP1C+18>: cmpl $0x4,(%rdi)
0x4005c5 <_Z3quxP1C+21>: je 0x4005d8 <_Z3quxP1C+40>
0x4005c7 <_Z3quxP1C+23>: xor %edi,%edi
0x4005c9 <_Z3quxP1C+25>: callq 0x4005a0 <baz(int)>
0x4005ce <_Z3quxP1C+30>: mov %ebx,%edi
0x4005d0 <_Z3quxP1C+32>: pop %rbx
0x4005d1 <_Z3quxP1C+33>: jmp 0x4005a0 <baz(int)>
0x4005d3 <_Z3quxP1C+35>: nopl 0x0(%rax,%rax,1)
0x4005d8 <_Z3quxP1C+40>: callq 0x400590 <foo(A*)>
0x4005dd <_Z3quxP1C+45>: xor %edi,%edi
0x4005df <_Z3quxP1C+47>: movzbl %al,%ebx
0x4005e2 <_Z3quxP1C+50>: callq 0x4005a0 <baz(int)>
0x4005e7 <_Z3quxP1C+55>: mov %ebx,%edi
0x4005e9 <_Z3quxP1C+57>: pop %rbx
0x4005ea <_Z3quxP1C+58>: jmp 0x4005a0 <baz(int)>
0x4005ec: nopl 0x0(%rax)
Within GDB, this is where things go wrong:
top-gdb> bt 4
#0 find_pc_partial_function_gnu_ifunc (pc=4195728, name=0x7fffffffdd28,
address=0x7fffffffdd18, endaddr=0x7fffffffdd20, is_gnu_ifunc_p=0x0)
at
/ironwood1/sourceware-git/mesquite-native-thread_handle_to_thread_info/bld/../../binutils-gdb/gdb/blockframe.c:213
#1 0x0000000000553281 in find_pc_partial_function (pc=4195728,
name=0x7fffffffdd28, address=0x7fffffffdd18, endaddr=0x7fffffffdd20)
at
/ironwood1/sourceware-git/mesquite-native-thread_handle_to_thread_info/bld/../../binutils-gdb/gdb/blockframe.c:323
#2 0x00000000006b6aec in fill_in_stop_func (gdbarch=0x1249170,
ecs=0x7fffffffdcd0)
at
/ironwood1/sourceware-git/mesquite-native-thread_handle_to_thread_info/bld/../../binutils-gdb/gdb/infrun.c:4303
#3 0x00000000006baf13 in process_event_stop_test (ecs=0x7fffffffdcd0)
at
/ironwood1/sourceware-git/mesquite-native-thread_handle_to_thread_info/bld/../../binutils-gdb/gdb/infrun.c:6494
That pc value is actually the first address for foo(), which is what we want:
top-gdb> p/x pc
$22 = 0x400590
(Refer to my disassembly above to verify this.)
This code, which is in find_pc_partial_function_gnu_ifunc(), incorrectly
identifies this address, 0x400590, as belonging to qux:
if (mapped_pc >= cache_pc_function_low
&& mapped_pc < cache_pc_function_high
&& section == cache_pc_function_section)
goto return_cached_value;
top-gdb> p/x cache_pc_function_low
$30 = 0x400460
top-gdb> p/x cache_pc_function_high
$31 = 0x4005ec
Note that these high and low addresses include not only qux, but foo, baz,
main, and _start. This is due to the fact that qux consists of two separate
parts separated by a lot of other code.
So far as I can tell, prologue analysis is not at fault here.
I'm now trying to figure out how this might be fixed.