Bug 16280 - Step into an inline function with varargs doesn't stop
Summary: Step into an inline function with varargs doesn't stop
Status: NEW
Alias: None
Product: gdb
Classification: Unclassified
Component: breakpoints (show other bugs)
Version: 7.6
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-01 19:40 UTC by Paul Smith
Modified: 2016-05-16 18:13 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Repro case compressed tarball (477 bytes, application/gzip)
2013-12-01 19:40 UTC, Paul Smith
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Smith 2013-12-01 19:40:09 UTC
Created attachment 7311 [details]
Repro case compressed tarball

I am using GCC 4.8.1 and GDB 7.6.1 built with Python 2.7.6 on my GNU/Linux system.  In a C++ inline function that uses va_list, if I try to step into that inline function it will not stop and just keep running.  If I use "next" to skip over the function, that works properly.  If I use "si" to step by instructions until I get into the inline function, then I can continue to use normal step/next commands and it works properly.

I've also tried this with GCC 4.8.0 / GDB 7.6 / Python 2.7.5, with the same result.

Attached is a tar file containing a repro case.  Compile it like this:

    gcc -g -o step main.cpp Step.cpp

Now debugging:

  $ gdb ./step
  GNU gdb (GDB) 7.6.1
  ...
  Reading symbols from ./step...done.
  (gdb) l
  1       #include "Step.h"
  2       
  3       int main(int argc, const char** argv)
  4       {
  5           Step step;
  6           step.show("hi %s\n", "there");
  7           return 0;
  8       }

  (gdb) br 6
  Breakpoint 1 at 0x4006ff: file main.cpp, line 6.

  (gdb) run
  Starting program: ./step 

  Breakpoint 1, main (argc=1, argv=0x7fffffffe638) at main.cpp:6
  6           step.show("hi %s\n", "there");

  (gdb) step
  hi there
  [Inferior 1 (process 24724) exited normally]
Comment 1 Pedro Alves 2013-12-01 22:03:13 UTC
Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdb38) at main.cpp:6
6           step.show("hi %s\n", "there");
(gdb) set debug infrun 1
(gdb) s
infrun: clear_proceed_status_thread (process 20301)
infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT, step=1)
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20301] at 0x4006bb
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun:   20301 [process 20301],
infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4006c0
infrun: stepping inside range [0x4006bb-0x4006cf]
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20301] at 0x4006c0
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   20301 [process 20301],
infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4006c5
infrun: stepping inside range [0x4006bb-0x4006cf]
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20301] at 0x4006c5
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   20301 [process 20301],
infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4006ca
infrun: stepping inside range [0x4006bb-0x4006cf]
infrun: resume (step=1, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20301] at 0x4006ca
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun:   20301 [process 20301],
infrun:   status->kind = stopped, signal = GDB_SIGNAL_TRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x4006e0
infrun: stepped into subroutine
infrun: inserting step-resume breakpoint at 0x400712
infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20301] at 0x4006e0
infrun: prepare_to_wait
hi there
infrun: target_wait (-1, status) =
infrun:   20301 [process 20301],
infrun:   status->kind = exited, status = 0
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_EXITED
[Inferior 1 (process 20301) exited normally]
infrun: stop_stepping
(gdb)
Comment 2 Pedro Alves 2013-12-01 22:05:40 UTC
> infrun: stop_pc = 0x4006e0
> infrun: stepped into subroutine
> infrun: inserting step-resume breakpoint at 0x400712

GDB detected the program stepped into Step::show, and tried to put a breakpoint past the prologue (0x400712), and run to it.  But, the breakpoint is never hit:

> infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread > [process 20301] at 0x4006e0
> infrun: prepare_to_wait
> hi there
> infrun: target_wait (-1, status) =
> infrun:   20301 [process 20301],
> infrun:   status->kind = exited, status = 0
> infrun: infwait_normal_state
> infrun: TARGET_WAITKIND_EXITED
> [Inferior 1 (process 20301) exited normally]
> infrun: stop_stepping
> (gdb)
Comment 3 Pedro Alves 2013-12-01 22:07:58 UTC
So, a simpler reproducer is to try to set a breakpoint in the function, and run to it, no stepping involved, which fails as well:

...
Temporary breakpoint 4, main (argc=1, argv=0x7fffffffdb38) at main.cpp:6
6           step.show("hi %s\n", "there");
(gdb) b Step::show
Breakpoint 2 at 0x400712: file Step.h, line 15.
(gdb) c
Continuing.
infrun: clear_proceed_status_thread (process 20347)
infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT, step=0)
infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [process 20347] at 0x4006bb
hi there
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun:   20347 [process 20347],
infrun:   status->kind = exited, status = 0
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_EXITED
[Inferior 1 (process 20347) exited normally]
infrun: stop_stepping
(gdb)
Comment 4 Pedro Alves 2013-12-01 22:08:23 UTC
(gdb) disassemble Step::show
Dump of assembler code for function Step::show(char const*, ...):
   0x00000000004006e0 <+0>:     push   %rbp
   0x00000000004006e1 <+1>:     mov    %rsp,%rbp
   0x00000000004006e4 <+4>:     sub    $0xe0,%rsp
   0x00000000004006eb <+11>:    mov    %rsi,-0xa8(%rbp)
   0x00000000004006f2 <+18>:    mov    %rdx,-0xa0(%rbp)
   0x00000000004006f9 <+25>:    mov    %rcx,-0x98(%rbp)
   0x0000000000400700 <+32>:    mov    %r8,-0x90(%rbp)
   0x0000000000400707 <+39>:    mov    %r9,-0x88(%rbp)
   0x000000000040070e <+46>:    test   %al,%al
   0x0000000000400710 <+48>:    je     0x400732 <Step::show(char const*, ...)+82>
   0x0000000000400712 <+50>:    movaps %xmm0,-0x80(%rbp)
   0x0000000000400716 <+54>:    movaps %xmm1,-0x70(%rbp)
   0x000000000040071a <+58>:    movaps %xmm2,-0x60(%rbp)
   0x000000000040071e <+62>:    movaps %xmm3,-0x50(%rbp)
   0x0000000000400722 <+66>:    movaps %xmm4,-0x40(%rbp)
   0x0000000000400726 <+70>:    movaps %xmm5,-0x30(%rbp)
   0x000000000040072a <+74>:    movaps %xmm6,-0x20(%rbp)
   0x000000000040072e <+78>:    movaps %xmm7,-0x10(%rbp)
   0x0000000000400732 <+82>:    mov    %rdi,-0xd8(%rbp)
   0x0000000000400739 <+89>:    movl   $0x8,-0xc8(%rbp)
   0x0000000000400743 <+99>:    movl   $0x30,-0xc4(%rbp)
   0x000000000040074d <+109>:   lea    0x10(%rbp),%rax
   0x0000000000400751 <+113>:   mov    %rax,-0xc0(%rbp)
   0x0000000000400758 <+120>:   lea    -0xb0(%rbp),%rax
   0x000000000040075f <+127>:   mov    %rax,-0xb8(%rbp)
   0x0000000000400766 <+134>:   lea    -0xc8(%rbp),%rdx
   0x000000000040076d <+141>:   mov    -0xd8(%rbp),%rax
   0x0000000000400774 <+148>:   mov    %rdx,%rsi
   0x0000000000400777 <+151>:   mov    %rax,%rdi
   0x000000000040077a <+154>:   callq  0x40078c <Step::vlog(char const*, __va_list_tag*)>
   0x000000000040077f <+159>:   jmp    0x400789 <Step::show(char const*, ...)+169>
   0x0000000000400781 <+161>:   mov    %rax,%rdi
   0x0000000000400784 <+164>:   callq  0x400590 <_Unwind_Resume@plt>
   0x0000000000400789 <+169>:   leaveq 
   0x000000000040078a <+170>:   retq   
End of assembler dump.
(gdb)
Comment 5 Pedro Alves 2013-12-01 22:11:27 UTC
And above we can see why.  0x0000000000400712 is just after the je at 0x0000000000400710.

(gdb) info line Step::show
Line 15 of "Step.h" starts at address 0x4006e0 <Step::show(char const*, ...)> and ends at 0x400712 <Step::show(char const*, ...)+50>.


I'm almost certain I've seen a gcc bug open for this before.
Comment 6 Pedro Alves 2013-12-01 22:23:37 UTC
> I'm almost certain I've seen a gcc bug open for this before.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54533
Comment 7 Pedro Alves 2013-12-01 22:30:09 UTC
BTW, I don't see an issue with -m32.  Please confirm you're seeing this on x86_64.
Comment 9 Paul Smith 2013-12-02 00:14:50 UTC
Yes, x86_64.  Sorry for omitting that information.

Thanks Pedro; I'll look at those bugs.
Comment 10 Paul Smith 2016-05-16 15:39:00 UTC
I'm not sure why this bug is reassigned to the "netresolve" product?