Bug 20395

Summary: -var-update gives incorrect register values for frames 1 and above
Product: gdb Reporter: Don Breazeal <donbreazeal>
Component: miAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: tromey
Priority: P2    
Version: HEAD   
Target Milestone: ---   
Host: Target:
Build: Last reconfirmed:

Description Don Breazeal 2016-07-21 16:44:45 UTC
The -var-update command will return incorrect register values for registers in frames 1 and above, i.e. not the current frame.  This can be reproduced as follows:

* Run a program to a point where there are several frames on the stack
* Create a fixed varobj for $pc in each frame
* Step one instruction to modify the value of $pc in the current frame
* Call -var-update for each of the varobjs

All of the varobjs will have the value of $pc in the current frame.

A proposed patch to fix this issue has been submitted here:
https://sourceware.org/ml/gdb-patches/2016-07/msg00231.html
Comment 1 Sourceware Commits 2018-01-21 15:51:44 UTC
The master branch has been updated by Andrew Burgess <aburgess@sourceware.org>:

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

commit ae45162705fb76ee534336474a67b11373209c62
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Wed Oct 18 20:07:19 2017 +0100

    gdb: PR mi/20395: Fix -var-update for registers in frames 1 and up
    
    This patch fixes a problem with using the MI -var-update command
    to access the values of registers in frames other than the current
    frame.  The patch includes a test that demonstrates the problem:
    
    * run so there are several frames on the stack
    * create a fixed varobj for $pc in each frame, #'s 1 and above
    * step one instruction, to modify the value of $pc
    * call -var-update for each of the previously created varobjs
      to verify that they are not reported as having changed.
    
    Without the patch, the -var-update command reported that $pc for all
    frames 1 and above had changed to the value of $pc in frame 0.
    
    A varobj is created as either fixed, the expression is evaluated within
    the context of a specific frame, or floating, the expression is
    evaluated within the current frame, whatever that may be.
    
    When a varobj is created by -var-create we set two fields of the varobj
    to track the context in which the varobj was created, these two fields
    are varobj->root->frame and var->root->valid_block.
    
    If a varobj is of type fixed, then, when we subsequently try to
    reevaluate the expression associated with the varobj we must determine
    if the original frame (and block) is still available, if it is not then
    the varobj can no longer be evaluated.
    
    The problem is that for register expressions varobj->root->valid_block
    is not set correctly.  This block tracking is done using the global
    'innermost_block' which is set in the various parser files (for example
    c-exp.y).  However, this is not set for register expressions.
    
    The fix then seems like it should be to just update the innermost block
    when parsing register expressions, however, that solution causes several
    test regressions.
    
    The problem is that in some cases we rely on the expression parsing
    code not updating the innermost block for registers, one example is
    when we parse the expression for a 'display' command.  The display
    commands treats registers like floating varobjs, but symbols are
    treated like fixed varobjs.  So 'display $reg_name' will always show
    the value of '$reg_name' even as the user moves from frame to frame,
    while 'display my_variable' will only show 'my_variable' while it is
    in the current frame and/or block, when the user moves to a new frame
    and/or block (even one with a different 'my_variable' in) then the
    display of 'my_variable' stops.  For the case of 'display', without
    the option to force fixed or floating expressions, the current
    behaviour is probably the best choice.  For the varobj system though,
    we can choose between floating and fixed, and we should try to make
    this work for registers.
    
    There's only one existing test case that needs to be updated, in that
    test a fixed varobj is created using a register, the MI output now
    include the thread-id in which the varobj should be evaluated, which I
    believe is correct behaviour.  I also added a new floating test case
    into the same test script, however, right now this also includes the
    thread-id in the expected output, which I believe is an existing gdb
    bug, which I plan to fix next.
    
    Tested on x86_64 Linux native and native-gdbserver, no regressions.
    
    gdb/ChangeLog:
    
    	PR mi/20395
    	* ada-exp.y (write_var_from_sym): Pass extra parameter when
    	updating innermost block.
    	* parse.c (innermost_block_tracker::update): Take extra type
    	parameter, and check types match before updating innermost block.
    	(write_dollar_variable): Update innermost block for registers.
    	* parser-defs.h (enum innermost_block_tracker_type): New enum.
    	(innermost_block_tracker::innermost_block_tracker): Initialise
    	m_types member.
    	(innermost_block_tracker::reset): Take type parameter.
    	(innermost_block_tracker::update): Take type parameter, and pass
    	type through as needed.
    	(innermost_block_tracker::m_types): New member.
    	* varobj.c (varobj_create): Pass type when reseting innermost
    	block.
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.mi/basics.c: Add new global.
    	* gdb.mi/mi-frame-regs.exp: New file.
    	* gdb.mi/mi-var-create-rtti.exp: Update expected results, add new
    	case.
Comment 2 Tom Tromey 2023-08-31 17:27:40 UTC
Seems like this was fixed a while ago.