)]}'
{
  "commit": "bc2cbe815bdbac3bd027bf4acc94c554c29b0189",
  "tree": "82c9378eb3d95cab30c12b0690c576d697af3c47",
  "parents": [
    "d015d3206e11c6926c4afce723d8366afc965b97"
  ],
  "author": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Tue Dec 13 22:34:38 2022 -0500"
  },
  "committer": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Fri Jan 20 14:48:57 2023 -0500"
  },
  "message": "gdb: make it possible to restore selected user-created frames\n\nI would like to improve frame_info_ptr to automatically grab the\ninformation needed to reinflate a frame, and automatically reinflate it\nas needed.  One thing that is in the way is the fact that some frames\ncan be created out of thin air by the create_new_frame function.  These\nframes are not the fruit of unwinding from the target\u0027s current frame.\nThese frames are created by the \"select-frame view\" command.\n\nThese frames are not correctly handled by the frame save/restore\nfunctions, save_selected_frame, restore_selected_frame and\nlookup_selected_frame.  This can be observed here, using the test\nincluded in this patch:\n\n    $ ./gdb --data-directory\u003ddata-directory -nx -q testsuite/outputs/gdb.base/frame-view/frame-view\n    Reading symbols from testsuite/outputs/gdb.base/frame-view/frame-view...\n    (gdb) break thread_func\n    Breakpoint 1 at 0x11a2: file /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c, line 42.\n    (gdb) run\n    Starting program: /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/frame-view/frame-view\n\n    [Thread debugging using libthread_db enabled]\n    Using host libthread_db library \"/usr/lib/../lib/libthread_db.so.1\".\n    [New Thread 0x7ffff7cc46c0 (LWP 4171134)]\n    [Switching to Thread 0x7ffff7cc46c0 (LWP 4171134)]\n\n    Thread 2 \"frame-view\" hit Breakpoint 1, thread_func (p\u003d0x0) at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:42\n    42        foo (11);\n    (gdb) info frame\n    Stack level 0, frame at 0x7ffff7cc3ee0:\n     rip \u003d 0x5555555551a2 in thread_func (/home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:42); saved rip \u003d 0x7ffff7d4e8fd\n     called by frame at 0x7ffff7cc3f80\n     source language c.\n     Arglist at 0x7ffff7cc3ed0, args: p\u003d0x0\n     Locals at 0x7ffff7cc3ed0, Previous frame\u0027s sp is 0x7ffff7cc3ee0\n     Saved registers:\n      rbp at 0x7ffff7cc3ed0, rip at 0x7ffff7cc3ed8\n    (gdb) thread 1\n    [Switching to thread 1 (Thread 0x7ffff7cc5740 (LWP 4171122))]\n    #0  0x00007ffff7d4b4b6 in ?? () from /usr/lib/libc.so.6\n\nHere, we create a custom frame for thread 1 (using the stack from thread\n2, for convenience):\n\n    (gdb) select-frame view 0x7ffff7cc3f80 0x5555555551a2\n\nThe first calls to \"frame\" looks good:\n\n    (gdb) frame\n    #0  thread_func (p\u003d0x7ffff7d4e630) at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:42\n    42        foo (11);\n\nBut not the second one:\n\n    (gdb) frame\n    #0  0x00007ffff7d4b4b6 in ?? () from /usr/lib/libc.so.6\n\nThis second \"frame\" command shows the current target frame instead of\nthe user-created frame.\n\nIt\u0027s not totally clear how the \"select-frame view\" feature is expected\nto behave, especially since it\u0027s not tested.  I heard accounts that it\nused to be possible to select a frame like this and do \"up\" and \"down\"\nto navigate the backtrace starting from that frame.  The fact that\ncreate_new_frame calls frame_unwind_find_by_frame to install the right\nunwinder suggest that it used to be possible.  But that doesn\u0027t work\ntoday:\n\n    (gdb) select-frame view 0x7ffff7cc3f80 0x5555555551a2\n    (gdb) up\n    Initial frame selected; you cannot go up.\n    (gdb) down\n    Bottom (innermost) frame selected; you cannot go down.\n\nand \"backtrace\" always shows the actual thread\u0027s backtrace, it ignores\nthe user-created frame:\n\n    (gdb) bt\n    #0  0x00007ffff7d4b4b6 in ?? () from /usr/lib/libc.so.6\n    #1  0x00007ffff7d50403 in ?? () from /usr/lib/libc.so.6\n    #2  0x000055555555521a in main () at /home/simark/src/binutils-gdb/gdb/testsuite/gdb.base/frame-view.c:56\n\nI don\u0027t want to address all the `select-frame view` issues , but I think\nwe can agree that the \"frame\" command changing the selected frame, as\nshown above, is a bug.  I would expect that command to show the\ncurrently selected frame and not change it.\n\nThis happens because of the scoped_restore_selected_frame object in\nprint_frame_args.  The frame information is saved in the constructor\n(the backtrace below), and restored in the destructor.\n\n    #0  save_selected_frame (frame_id\u003d0x7ffdc0020ad0, frame_level\u003d0x7ffdc0020af0) at /home/simark/src/binutils-gdb/gdb/frame.c:1682\n    #1  0x00005631390242f0 in scoped_restore_selected_frame::scoped_restore_selected_frame (this\u003d0x7ffdc0020ad0) at /home/simark/src/binutils-gdb/gdb/frame.c:324\n    #2  0x000056313993581e in print_frame_args (fp_opts\u003d..., func\u003d0x62100023bde0, frame\u003d..., num\u003d-1, stream\u003d0x60b000000300) at /home/simark/src/binutils-gdb/gdb/stack.c:755\n    #3  0x000056313993ad49 in print_frame (fp_opts\u003d..., frame\u003d..., print_level\u003d1, print_what\u003dSRC_AND_LOC, print_args\u003d1, sal\u003d...) at /home/simark/src/binutils-gdb/gdb/stack.c:1401\n    #4  0x000056313993835d in print_frame_info (fp_opts\u003d..., frame\u003d..., print_level\u003d1, print_what\u003dSRC_AND_LOC, print_args\u003d1, set_current_sal\u003d1) at /home/simark/src/binutils-gdb/gdb/stack.c:1126\n    #5  0x0000563139932e0b in print_stack_frame (frame\u003d..., print_level\u003d1, print_what\u003dSRC_AND_LOC, set_current_sal\u003d1) at /home/simark/src/binutils-gdb/gdb/stack.c:368\n    #6  0x0000563139932bbe in print_stack_frame_to_uiout (uiout\u003d0x611000016840, frame\u003d..., print_level\u003d1, print_what\u003dSRC_AND_LOC, set_current_sal\u003d1) at /home/simark/src/binutils-gdb/gdb/stack.c:346\n    #7  0x0000563139b0641e in print_selected_thread_frame (uiout\u003d0x611000016840, selection\u003d...) at /home/simark/src/binutils-gdb/gdb/thread.c:1993\n    #8  0x0000563139940b7f in frame_command_core (fi\u003d..., ignored\u003dtrue) at /home/simark/src/binutils-gdb/gdb/stack.c:1871\n    #9  0x000056313994db9e in frame_command_helper\u003cframe_command_core\u003e::base_command (arg\u003d0x0, from_tty\u003d1) at /home/simark/src/binutils-gdb/gdb/stack.c:1976\n\nSince the user-created frame has level 0 (identified by the saved level\n-1), lookup_selected_frame just reselects the target\u0027s current frame,\nand the user-created frame is lost.\n\nMy goal here is to fix this particular problem.\n\nCurrently, select_frame does not set selected_frame_id and\nselected_frame_level for frames with level 0.  It leaves them at\nnull_frame_id / -1, indicating to restore_selected_frame to use the\ntarget\u0027s current frame.  User-created frames also have level 0, so add a\nspecial case them such that select_frame saves their selected id and\nlevel.\n\nsave_selected_frame does not need any change.\n\nChange the assertion in restore_selected_frame that checks `frame_level\n!\u003d 0` to account for the fact that we can restore user-created frames,\nwhich have level 0.\n\nFinally, change lookup_selected_frame to make it able to re-create\nuser-created frame_info objects from selected_frame_level and\nselected_frame_id.\n\nAdd a minimal test case for the case described above, that is the\n\"select-frame view\" command followed by the \"frame\" command twice.  In\norder to have a known stack frame to switch to, the test spawns a second\nthread, and tells the first thread to use the other thread\u0027s top frame.\n\nChange-Id: Ifc77848dc465fbd21324b9d44670833e09fe98c7\nReviewed-By: Bruno Larsen \u003cblarsen@redhat.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "0909109c1f4005585cfa6ac45b4f6e98ab5ab9e6",
      "old_mode": 33188,
      "old_path": "gdb/frame.c",
      "new_id": "9ab8fa0310e86092553c7679ac0c162ce520653b",
      "new_mode": 33188,
      "new_path": "gdb/frame.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "7b1cbd6abd42d941bd513dd20ffa18ee41426115",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/frame-view.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d2dba143448d4590d8b1cec0facb8c47aed4bf4b",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/frame-view.exp"
    }
  ]
}
