)]}'
{
  "commit": "8efed40efd6899e71540f6e2bc7a638c0bceefce",
  "tree": "dbdac19de121a9c34489086fc5d9ae75a72b223e",
  "parents": [
    "a418b1a4700ffdaffab296dc2f2e89dd6fa0b36c"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Thu Mar 27 10:53:43 2025 +0000"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Wed Feb 04 10:35:46 2026 +0000"
  },
  "message": "gdb: fix-up truncated inline function block ranges\n\nThis commit aims to improve GDB\u0027s handling of inline functions.  There\nare two mechanisms which can tell GDB, or the user of GDB, that the\ninferior is within an inline function, these are the block range\nassociated with an inline instance of a function, and also the line\ntable, which associates addresses with source lines in the program.\n\nCurrently, gcc truncates the address range for, at least some, inline\nfunction blocks, such that a given address is considered outside the\ninline function.  However, the line table maps that same address to a\nline within the inline function.\n\nA consequence of this, is that, when using \u0027next\u0027 to move the inferior\nforward, GDB will often stop the inferior believing that the inferior\nhas left an inline function, and indeed, GDB will claim that the\ninferior is in the outer, non-inline function, but GDB will then\ndisplay a source line from the inline function as the current location.\n\nAn example of this problem can be seen with the test\ngdb.cp/step-and-next-inline.exp.  Using the\nstep-and-next-inline-no-header binary that is built as part of the\ntest:\n\n  (gdb) file ./gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header\n  Reading symbols from ./gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header...\n  (gdb) break get_alias_set\n  Breakpoint 1 at 0x401160: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc, line 51.\n  (gdb) run\n  Starting program: /tmp/build/gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header\n\n  Breakpoint 1, get_alias_set (t\u003dt@entry\u003d0x404038 \u003cxx\u003e)\n      at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:51\n  51\t  if (t !\u003d NULL\n  (gdb) next\n  52\t      \u0026\u0026 TREE_TYPE (t).z !\u003d 1\n  (gdb) next\n  43\t  return x;\t\u003c------------- Problem line.\n  (gdb) bt\n  #0  get_alias_set (t\u003dt@entry\u003d0x404038 \u003cxx\u003e) at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:43\n  #1  0x000000000040105e in main () at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:64\n  (gdb)\n\nI\u0027ve labelled the issue as \u0027Problem line\u0027.  After the second \u0027next\u0027\nGDB stopped thinking it was in get_alias_set, but printed a line from\nthe inline function behind the TREE_TYPE macro.  The \u0027Problem line\u0027\nshould have been line 53, not line 43.\n\nThe $pc at which GDB stopped is 0x40116f.  If we then use \u0027objdump\n--dwarf\u003ddecodedline\u0027 to view the line table for the executable, this\nis what we see:\n\n  File name                        Line number    Starting address    View    Stmt\n  ...\n  step-and-next-inline.cc                   38            0x401165               x\n  step-and-next-inline.cc                   40            0x401165       1       x\n  step-and-next-inline.cc                   40            0x401165       2\n  step-and-next-inline.cc                   40            0x401167\n  step-and-next-inline.cc                   42            0x40116f               x\n  step-and-next-inline.cc                   43            0x40116f       1       x\n  step-and-next-inline.cc                   43            0x40116f       2\n  step-and-next-inline.cc                   52            0x40116f       3\n  step-and-next-inline.cc                   52            0x401172\n  step-and-next-inline.cc                   38            0x401177               x\n  step-and-next-inline.cc                   40            0x401177       1       x\n  step-and-next-inline.cc                   40            0x401177       2\n  ...\n\nNOTE: I use objdump to view the line table, not \u0027maintenance info\nline-table\u0027 as GDB drops some line table entries that it sees as\nirrelevant.  Using objdump give a complete view of the line table.\n\nWe can see that address 0x40116f is associated with three line\nnumbers, 42, and 43 are both within the inline function, and 52 is the\nline from which the inline function was called.  Notice too that 52 is\na non-statement line.\n\nIf we now look at the block structure for the previous $pc\nvalue 0x40116e (i.e. $pc - 1), then we see this:\n\n  (gdb) maintenance info blocks 0x40116e\n  ...\n  [(block *) 0x3c62900] 0x401040..0x4011a6\n    entry pc: 0x401160\n    function: get_alias_set(tree*)\n    symbol count: 1\n    address ranges:\n      0x401160..0x4011a6\n      0x401040..0x401046\n  [(block *) 0x3c61260] 0x401041..0x40116f\n    entry pc: 0x401165\n    inline function: tree_check(tree*, int)\n    symbol count: 4\n    address ranges:\n      0x401165..0x40116f\n      0x401041..0x401046\n  (gdb)\n\nHere we see \u0027tree_check\u0027, the inline function that backs the TREE_TYPE\nmacro, this is the inline function we have just stepped out of.  This\nmakes sense as the end-address for the tree_check block is 0x40116f,\nand as the block\u0027s end address is not inclusive, that means that\n0x40116f is the first address outside the block, which, is the current\n$pc value.\n\nAnd so, we can see what\u0027s going on.  When the \u0027next\u0027 starts GDB is in\nget_alias_set, GDB steps forward, entering tree_check.  GDB then uses\nthe extent of the block to figure out where the inline function ends,\nand steps forward to that address (0x40116f).  At this point, GDB\nlooks up the current line in the line table (43), and reports a stop\nat this line.\n\nIn this commit, the fix I propose is to look for the line table\npattern seen above, a sequence of line table entries, that end with a\nnon-statement entry for the calling line of an inline function,\nlocated at the exact end address of an inline function block.\n\nWhen such a pattern is found, then we can extend the inline function\u0027s\naddress range to the next line table address, so long as doing so does\nnot extend the inline function beyond the extent of the containing,\nnon-inline, function.\n\nIn the above example, the block for the tree_check function would be\nextended to end at 0x401172.  With this fix in place, and with the\nsame test binary, GDB now behaves like this:\n\n  (gdb) break get_alias_set\n  Breakpoint 1 at 0x401160: file /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc, line 51.\n  (gdb) run\n  Starting program: /tmp/build/gdb/testsuite/outputs/gdb.cp/step-and-next-inline/step-and-next-inline-no-header\n\n  Breakpoint 1, get_alias_set (t\u003dt@entry\u003d0x404038 \u003cxx\u003e)\n      at /tmp/build/gdb/testsuite/../../../src/gdb/testsuite/gdb.cp/step-and-next-inline.cc:51\n  51\t  if (t !\u003d NULL\n  (gdb) next\n  52\t      \u0026\u0026 TREE_TYPE (t).z !\u003d 1\n  (gdb) next\n  53\t      \u0026\u0026 TREE_TYPE (t).z !\u003d 2\n  (gdb)\n\nThe block for the inline function has been updated, like this:\n\n(gdb) maintenance info blocks 0x40116e\n...\n[(block *) 0x4965530] 0x401040..0x4011a6\n  entry pc: 0x401160\n  function: get_alias_set(tree*)\n  symbol count: 1\n  address ranges:\n    0x401160..0x4011a6\n    0x401040..0x401046\n[(block *) 0x49640b0] 0x401040..0x401172\n  entry pc: 0x401165\n  inline function: tree_check(tree*, int)\n  symbol count: 4\n  address ranges:\n    0x401165..0x401172\n    0x401040..0x401041\n    0x401041..0x401046\n\nThis is my alternative to the patch presented here:\n\n  https://inbox.sourceware.org/gdb-patches/AS1PR01MB946510286FBF2497A6F03E83E4922@AS1PR01MB9465.eurprd01.prod.exchangelabs.com/\n\nThis original patch series from Bernd Edlinger contains a number of\ndifferent fixes, some have already been split out and merged into GDB,\nbut the core idea for how to improve inline function handling by\nextending the inline block range is the same, however, the mechanism\nBernd uses is significantly different.\n\nIn the above series, the approach taken is to mark the line table at\nthe end address of an inline function, and a few addresses beyond\nthat (see the is-weak flag in the above series).  Then, when looking\nup the block for a given address, if the address is within this marked\nregion, then we actually return the previous (inline function) block.\n\nI believe that the above is a fair high-level summary of how the above\npatch solves the inline function range problem.  Any differences are\ndown to my misunderstanding the above patch, for which I apologise.\n\nMy problem with the above patch is that it breaks what I think should\nbe an invariant of GDB, that when looking up a block for a given\naddress, the block returned must contain the address within its\nranges.  I feel that, if we start to break this invariant, then we\nrisk introducing bugs within, e.g. the stepping control code.\n\nIn contrast, my approach solves this problem during the DWARF parsing,\nwhere problem cases are identified, and the DWARF \"fixed\" by extending\nthe block ranges.  After this, no additional changes are needed in\nGDB, the address to block mapping can work as normal, and the stepping\nlogic can continue to work just as it always has.\n\nThe test changes for gdb.cp/step-and-next-inline.exp have been taken\nfrom Bernd\u0027s original patch series, and I\u0027ve added a Co-Author tag for\nBernd to reflect this, as well as for the inspiration that I took from\nhis original series when creating this alternative proposal.\n\nIf/when this patch is merged, I plan to follow up with some cleanup to\nthe test case gdb.cp/step-and-next-inline.exp.  I think this test\nshould really be moved to gdb.opt/, it\u0027s really testing optimisation\ndebug, not C++ features, but also the structure of the test file is a\nbit of a mess.  I think with some restructuring we could make the test\nmore readable, and also, maybe, test some additional compiler\nflags (e.g. more optimisation levels).  I\u0027ve not done the refactoring\nin this patch in order to make it clearer what new tests I\u0027ve added,\nand also, I want to leave the test similar to what\u0027s in Bernd\u0027s\noriginal series, to make comparison easier.\n\nThe gdb.cp/step-and-next-inline.exp test was originally added by me\nback in 2019, so the problems with it are of my own making.\n\nFor testing I\u0027ve obviously run the entire test suite, but of\nparticular interest are these tests:\n\n  gdb.cp/step-and-next-inline.exp\n  gdb.dwarf2/dw2-inline-bt.exp\n  gdb.opt/empty-inline-cxx.exp\n  gdb.opt/empty-inline.exp\n  gdb.opt/inline-bt.exp\n\nI\u0027ve run these tests with a range of different gcc versions:  9.5.0,\n10.5.0, 11.5.0, 12.2.0, 13.3.0, 14.2.0, 15.1.0.  These tests all\nrelate to optimised debug of inline functions, and all passed with all\ncompiler versions listed here.\n\nCo-Authored-By: Bernd Edlinger \u003cbernd.edlinger@hotmail.de\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "c125271aa2ae9a682d8ebfc6b81f5496933f07a0",
      "old_mode": 33188,
      "old_path": "gdb/dwarf2/line-program.c",
      "new_id": "15c4024cb113c98e33abecba667fcee42ca49d50",
      "new_mode": 33188,
      "new_path": "gdb/dwarf2/line-program.c"
    },
    {
      "type": "modify",
      "old_id": "618de570759701e913d30cae9cee8f4cf157fa97",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.cp/step-and-next-inline.exp",
      "new_id": "d5d33856325b5e8d3836cbf160f1437c731112d9",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.cp/step-and-next-inline.exp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "d6becf5d66bfebc582bbb1507b7f4cfbb62674ce",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "f770ccf63be8acb539e00c534b5d6f76d301d6f9",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.dwarf2/dw2-extend-inline-block.exp"
    }
  ]
}
