)]}'
{
  "commit": "1e9bd86ccda976c0f7ef513cb5e9ee3eff460768",
  "tree": "60bd79ce4c792df44514d8691a0e59e6a09e34c7",
  "parents": [
    "f40b59b91240886003b679ff4a3fd51b6b60696a"
  ],
  "author": {
    "name": "Tom de Vries",
    "email": "tdevries@suse.de",
    "time": "Wed Jan 29 11:21:02 2025 +0100"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Tue Feb 25 10:56:36 2025 +0000"
  },
  "message": "gdb: don\u0027t show incorrect source file in source window\n\nConsider the test-case sources main.c and foo.c:\n\n  $ cat main.c\n  extern int foo (void);\n\n  int\n  main (void)\n  {\n    return foo ();\n  }\n  $ cat foo.c\n  extern int foo (void);\n\n  int\n  foo (void)\n  {\n    return 0;\n  }\n\nand main.c compiled with debug info, and foo.c without:\n\n  $ gcc -g main.c -c\n  $ gcc foo.c -c\n  $ gcc -g main.o foo.o\n\nIn TUI mode, if we run to foo:\n\n  $ gdb -q a.out -tui -ex \"b foo\" -ex run\n\nit gets us \"[ No Source Available ]\":\n\n  ┌─main.c─────────────────────────────────────────┐\n  │                                                │\n  │                                                │\n  │                                                │\n  │            [ No Source Available ]             │\n  │                                                │\n  │                                                │\n  └────────────────────────────────────────────────┘\n  (src) In: foo                  L??   PC: 0x400566\n  ...\n  Breakpoint 1, 0x0000000000400566 in foo ()\n  (gdb)\n\nBut after resizing (pressing ctrl-\u003cminus\u003e in the gnome-terminal), we\nget instead the source for main.c:\n\n  ┌─main.c─────────────────────────────────────────┐\n  │        3 int                                   │\n  │        4 main (void)                           │\n  │        5 {                                     │\n  │        6   return foo ();                      │\n  │        7 }                                     │\n  │                                                │\n  │                                                │\n  └────────────────────────────────────────────────┘\n  (src) In: foo                   L??   PC: 0x400566\n  ...\n  Breakpoint 1, 0x0000000000400566 in foo ()\n  (gdb)\n\nwhich is inappropriate because we\u0027re stopped in function foo, which is\nnot in main.c.\n\nThe problem is that, when the window is resized, GDB ends up calling\ntui_source_window_base::rerender.  The rerender function has three\ncases, one for when the window already has some source code\ncontent (which is not the case here), a case for when the inferior is\nactive, and we have a selected frame (which is the case that applies\nhere), and a final case for when the inferior is not running.\n\nFor the case which we end up in, the source code window has no\ncontent, but the inferior is running, so we have a selected frame, GDB\ncalls the get_current_source_symtab_and_line() function to get the\nsymtab_and_line for the current location.\n\nThe get_current_source_symtab_and_line() will actually return the last\nrecorded symtab and line location, not the current symtab and line\nlocation.\n\nWhat this means, is that, if the current location has no debug\ninformation, get_current_source_symtab_and_line() will return any\npreviously recorded location, or failing that, the default (main)\nlocation.\n\nThis behaviour of get_current_source_symtab_and_line() also causes\nproblems for the \u0027list\u0027 command.  Consider this pure CLI session:\n\n  (gdb) break foo\n  Breakpoint 1 at 0x40110a\n  (gdb) run\n  Starting program: /tmp/a.out\n\n  Breakpoint 1, 0x000000000040110a in foo ()\n  (gdb) list\n  1\textern int foo (void);\n  2\n  3\tint\n  4\tmain (void)\n  5\t{\n  6\t  return foo ();\n  7\t}\n  (gdb) list .\n  Insufficient debug info for showing source lines at current PC (0x40110a).\n  (gdb)\n\nHowever, if we look at how GDB\u0027s TUI updates the source window during\na normal stop, we see that GDB does a better job of displaying the\nexpected contents.  Going back to our original example, when we start\nGDB with:\n\n  $ gdb -q a.out -tui -ex \"b foo\" -ex run\n\nwe do get the \"[ No Source Available ]\" message as expected.  Why is\nthat?\n\nThe answer is that, in this case GDB uses tui_show_frame_info to\nupdate the source window, tui_show_frame_info is called each time a\nprompt is displayed, like this:\n\n  #0  tui_show_frame_info (fi\u003d...) at ../../src/gdb/tui/tui-status.c:269\n  #1  0x0000000000f55975 in tui_refresh_frame_and_register_information () at ../../src/gdb/tui/tui-hooks.c:118\n  #2  0x0000000000f55ae8 in tui_before_prompt (current_gdb_prompt\u003d0x31ef930 \u003ctop_prompt+16\u003e \"(gdb) \") at ../../src/gdb/tui/tui-hooks.c:165\n  #3  0x000000000090ea45 in std::_Function_handler\u003cvoid(char const*), void (*)(char const*)\u003e::_M_invoke (__functor\u003d..., __args#0\u003d@0x7ffc955106b0: 0x31ef930 \u003ctop_prompt+16\u003e \"(gdb) \") at /usr/include/c++/9/bits/std_function.h:300\n  #4  0x00000000009020df in std::function\u003cvoid(char const*)\u003e::operator() (this\u003d0x5281260, __args#0\u003d0x31ef930 \u003ctop_prompt+16\u003e \"(gdb) \") at /usr/include/c++/9/bits/std_function.h:688\n  #5  0x0000000000901c35 in gdb::observers::observable\u003cchar const*\u003e::notify (this\u003d0x31dda00 \u003cgdb::observers::before_prompt\u003e, args#0\u003d0x31ef930 \u003ctop_prompt+16\u003e \"(gdb) \") at ../../src/gdb/../gdbsupport/observable.h:166\n  #6  0x00000000008ffed8 in notify_before_prompt (prompt\u003d0x31ef930 \u003ctop_prompt+16\u003e \"(gdb) \") at ../../src/gdb/event-top.c:518\n  #7  0x00000000008fff08 in top_level_prompt () at ../../src/gdb/event-top.c:534\n  #8  0x00000000008ffdeb in display_gdb_prompt (new_prompt\u003d0x0) at ../../src/gdb/event-top.c:487\n\nIf we look at how tui_show_frame_info figures out what source to\ndisplay, it doesn\u0027t use get_current_source_symtab_and_line(), instead,\nit finds a symtab_and_line directly from a frame_info_pt.  This means\nwe are not dependent on get_current_source_symtab_and_line() returning\nthe current location (which it does not).\n\nI propose that we change tui_source_window_base::rerender() so that,\nfor the case we are discussing here (the inferior has a selected\nframe, but the source window has no contents), we move away from using\nget_current_source_symtab_and_line(), and instead use find_frame_sal\ninstead, like tui_show_frame_info does.\n\nThis means that we will always use the inferior\u0027s current location.\n\nTested on x86_64-linux.\n\nReviewed-By: Tom de Vries \u003ctdevries@suse.de\u003e\nReported-By: Andrew Burgess \u003caburgess@redhat.com\u003e\nCo-Authored-By: Andrew Burgess \u003caburgess@redhat.com\u003e\nBug: https://sourceware.org/bugzilla/show_bug.cgi?id\u003d32614\n",
  "tree_diff": [
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "653b24ba92b8ad48040f7068470931317022ac06",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.tui/resize-3-foo.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "95fdd3b6ba0fbbcf899ebe81d0be1dc81e159597",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.tui/resize-3-main.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "fcda407c9fd1163d1e0f6fac29ad055c237a210a",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.tui/resize-3.exp"
    },
    {
      "type": "modify",
      "old_id": "1cf2baecffa933466fe23dbd75595f7dda56ca04",
      "old_mode": 33188,
      "old_path": "gdb/tui/tui-winsource.c",
      "new_id": "b5889a81edfaf48602c815c32ea1e32468c68cff",
      "new_mode": 33188,
      "new_path": "gdb/tui/tui-winsource.c"
    }
  ]
}
