Bug 29178 - GDB wont print frame when reverse stepping out of recursive function
Summary: GDB wont print frame when reverse stepping out of recursive function
Status: REOPENED
Alias: None
Product: gdb
Classification: Unclassified
Component: record (show other bugs)
Version: unknown
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-05-25 13:08 UTC by Guinevere Larsen
Modified: 2024-05-09 20:07 UTC (History)
0 users

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


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Guinevere Larsen 2022-05-25 13:08:03 UTC
GDB won't print the frame information when reverse stepping out of a reverse function, despite printing the information when it enters the functions, or when it leaves non-recursive functions.

Reproducer:

int factorial(int n){
    int result;
    if(n <= 1) result = 1;
    result = n * factorial(n - 1);
    return result;
}

int main(){
    factorial(5);
    return 0;
}

And using the following commands:

(gdb) start
25          factorial(5);
(gdb) record
(gdb) n
27          return 0;                                                                                                                                                                                              
(gdb) rs                                                                                                                                                                                                           
factorial (x=5) at 16678.c:10                                                                                                                                                                                      
10      }                                                                                                                                                                                                          
(gdb)                                                                                                                                                                                                              
9           return result;                                                                                                                                                                                         
(gdb)                                                                                                                                                                                                              
8           else result = x * factorial(x-1);                                                                                                                                                                      
(gdb)                                                                                                                                                                                                              
factorial (x=4) at 16678.c:10                                                                                                                                                                                      
10      }                                                                                                                                                                                                          
(gdb)                                                                                                                                                                                                              
9           return result;                                                                                                                                                                                         
(gdb)                                                                                                                                                                                                              
8           else result = x * factorial(x-1);                                                                                                                                                                      
(gdb)                                                                                                                                                                                                              
factorial (x=3) at 16678.c:10                                                                                                                                                                                      
10      }                                                                                                                                                                                                          
(gdb)                                                                                                                                                                                                              
9           return result;                                                                                                                                                                                         
(gdb)                                                                                                                                                                                                              
8           else result = x * factorial(x-1);                                                                                                                                                                      
(gdb)                                                                                                                                                                                                              
factorial (x=2) at 16678.c:10
10      }
(gdb)
9           return result;
(gdb)
8           else result = x * factorial(x-1);
(gdb)
factorial (x=1) at 16678.c:10
10      }
(gdb)
9           return result;
(gdb)
7           if(x <= 1) result = 1;
(gdb)
8           else result = x * factorial(x-1);
7           if(x <= 1) result = 1;
(gdb)
8           else result = x * factorial(x-1);
(gdb)
7           if(x <= 1) result = 1;
(gdb)
8           else result = x * factorial(x-1);
(gdb)
7           if(x <= 1) result = 1;
(gdb) rn
8           else result = x * factorial(x-1);
(gdb)
7           if(x <= 1) result = 1;

As can be seen, we don't get information about the depth when reverse stepping out.
Comment 1 Sourceware Commits 2023-11-20 09:54:39 UTC
The master branch has been updated by Bruno Larsen <blarsen@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=bf2813aff8f2988ad3d53e819a0415abf295c91f

commit bf2813aff8f2988ad3d53e819a0415abf295c91f
Author: Guinevere Larsen <blarsen@redhat.com>
Date:   Fri Sep 1 13:47:32 2023 +0200

    gdb/record: print frame information when exiting a recursive call
    
    Currently,  when GDB is reverse stepping out of a function into the same
    function due to a recursive call, it doesn't print frame information, as
    reported by PR record/29178. This happens because when the inferior
    leaves the current frame, GDB decides to refresh the step information,
    clobbering the original step_frame_id, making it impossible to figure
    out later on that the frame has been changed.
    
    This commit changes GDB so that, if we notice we're in this exact
    situation, we won't refresh the step information.
    
    Because of implementation details, this change can cause some debug
    information to be read when it normally wouldn't before, which showed up
    as a regression on gdb.dwarf2/dw2-out-of-range-end-of-seq. Since that
    isn't a problem, the test was changed to allow for the new output.
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29178
    Approved-By: Tom Tromey <tom@tromey.com>
Comment 2 Guinevere Larsen 2023-11-20 10:01:27 UTC
Closed by that commit
Comment 3 Sourceware Commits 2024-01-21 16:25:38 UTC
The master branch has been updated by Lancelot SIX <lsix@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=5266f5c25b20ed6411b263952f52032afafd280d

commit 5266f5c25b20ed6411b263952f52032afafd280d
Author: Lancelot SIX <lancelot.six@amd.com>
Date:   Thu Dec 28 11:51:31 2023 +0000

    gdb/infrun: lazily load curr_frame_id in process_event_stop_test
    
    A recent(ish) change in gdb/infrun.c made process_event_stop_test load
    debug information where it would not have done so previously.  The
    change is:
    
        commit bf2813aff8f2988ad3d53e819a0415abf295c91f
        AuthorDate: Fri Sep 1 13:47:32 2023 +0200
        CommitDate: Mon Nov 20 10:54:03 2023 +0100
    
            gdb/record: print frame information when exiting a recursive call
    
            Currently,  when GDB is reverse stepping out of a function into the same
            function due to a recursive call, it doesn't print frame information, as
            reported by PR record/29178. This happens because when the inferior
            leaves the current frame, GDB decides to refresh the step information,
            clobbering the original step_frame_id, making it impossible to figure
            out later on that the frame has been changed.
    
            This commit changes GDB so that, if we notice we're in this exact
            situation, we won't refresh the step information.
    
            Because of implementation details, this change can cause some debug
            information to be read when it normally wouldn't before, which showed up
            as a regression on gdb.dwarf2/dw2-out-of-range-end-of-seq. Since that
            isn't a problem, the test was changed to allow for the new output.
    
            Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29178
    
    Although there is nothing wrong with this change in principle, it
    happens to break most of the tests in gdb/testsuite/gdb.rocm/*.exp.
    This is because those tests do rely on GDB not loading debug
    information.  This is necessary because the debug information produced
    for AMDGPU code is using DWARF extensions which are not supported by GDB
    at this point.
    
    In this patch, I propose to use a lazy loading mechanism so the frame_id
    for the current frame is only computed when required instead of when
    entering process_event_stop_test.  The lazy_loader class is currently
    defined locally in infrun.c, but if it turns out to be useful elsewhere,
    it could go somewhere under gdbsupport.
    
    This patch should restore the behavior GDB had before
    bf2813aff8f2988ad3d53e819a0415abf295c91f when it comes to load debug
    info.
    
    Another approach could have been to revert
    fb84fbf8a51f5be2e78765508ebd9753af96b492 (gdb/infrun: simplify
    process_event_stop_test) and adjust the implementation of
    bf2813aff8f2988ad3d53e819a0415abf295c91f (gdb/record: print frame
    information when exiting a recursive call).  However, I think that the
    lazy loading works well with the simplification done recently, so I went
    down that route.
    
    Regression tested on x86_64-linux (Ubuntu 22.04) with AMDGPU support.
    
    Change-Id: Ib63a162128130d1786a77c98623e9e3dcbc363b7
    Approved-by: Kevin Buettner <kevinb@redhat.com>
Comment 4 Guinevere Larsen 2024-05-09 20:07:34 UTC
This is still happening for clang-compiled binaries.