)]}'
{
  "commit": "901682e4a4270fbd40ed4bfab0571c98d19c6557",
  "tree": "51b77d4d47c5367bba2df468e3940f39efb48a9b",
  "parents": [
    "ec517d1040bf02e15e9724b14df9dba73665883f"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Thu Mar 23 12:12:38 2023 +0000"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Tue May 30 21:49:21 2023 +0100"
  },
  "message": "gdb: add support for %V to printf command\n\nThis commit adds a new format for the printf and dprintf commands:\n\u0027%V\u0027.  This new format takes any GDB expression and formats it as a\nstring, just as GDB would for a \u0027print\u0027 command, e.g.:\n\n  (gdb) print a1\n  $a \u003d {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}\n  (gdb) printf \"%V\\n\", a1\n  {2, 4, 6, 8, 10, 12, 14, 16, 18, 20}\n  (gdb)\n\nIt is also possible to pass the same options to %V as you might pass\nto the print command, e.g.:\n\n  (gdb) print -elements 3 -- a1\n  $4 \u003d {2, 4, 6...}\n  (gdb) printf \"%V[-elements 3]\\n\", a1\n  {2, 4, 6...}\n  (gdb)\n\nThis new feature would effectively replace an existing feature of GDB,\nthe $_as_string builtin convenience function.  However, the\n$_as_string function has a few problems which this new feature solves:\n\n1. $_as_string doesn\u0027t currently work when the inferior is not\nrunning, e.g:\n\n  (gdb) printf \"%s\", $_as_string(a1)\n  You can\u0027t do that without a process to debug.\n  (gdb)\n\nThe reason for this is that $_as_string returns a value object with\nstring type.  When we try to print this we call value_as_address,\nwhich ends up trying to push the string into the inferior\u0027s address\nspace.\n\nClearly we could solve this problem, the string data exists in GDB, so\nthere\u0027s no reason why we have to push it into the inferior, but this\nis an existing problem that would need solving.\n\n2. $_as_string suffers from the fact that C degrades arrays to\npointers, e.g.:\n\n  (gdb) printf \"%s\\n\", $_as_string(a1)\n  0x404260 \u003ca1\u003e\n  (gdb)\n\nThe implementation of $_as_string is passed a gdb.Value object that is\na pointer, it doesn\u0027t understand that it\u0027s actually an array.  Solving\nthis would be harder than issue #1 I think.  The whole array to\npointer transformation is part of our expression evaluation.  And in\nmost cases this is exactly what we want.  It\u0027s not clear to me how\nwe\u0027d (easily) tell GDB that we didn\u0027t want this reduction in _some_\ncases.  But I\u0027m sure this is solvable if we really wanted to.\n\n3. $_as_string is a gdb.Function sub-class, and as such is passed\ngdb.Value objects.  There\u0027s no super convenient way to pass formatting\noptions to $_as_string.  By this I mean that the new %V feature\nsupports print formatting options.  Ideally, we might want to add this\nfeature to $_as_string, we might imagine it working something like:\n\n  (gdb) printf \"%s\\n\", $_as_string(a1,\n                                   elements \u003d 3,\n                                   array_indexes \u003d True)\n\nwhere the first item is the value to print, while the remaining\noptions are the print formatting options.  However, this relies on\nPython calling syntax, which isn\u0027t something that convenience\nfunctions handle.  We could possibly rely on strictly positional\narguments, like:\n\n  (gdb) printf \"%s\\n\", $_as_string(a1, 3, 1)\n\nBut that\u0027s clearly terrible as there\u0027s far more print formatting\noptions, and if you needed to set the 9th option you\u0027d need to fill in\nall the previous options.\n\nAnd right now, the only way to pass these options to a gdb.Function is\nto have GDB first convert them all into gdb.Value objects, which is\nreally overkill for what we want.\n\nThe new %V format solves all these problems: the string is computed\nand printed entirely on the GDB side, we are able to print arrays as\nactual arrays rather than pointers, and we can pass named format\narguments.\n\nFinally, the $_as_string is sold in the manual as allowing users to\nprint the string representation of flag enums, so given:\n\n  enum flags\n    {\n      FLAG_A \u003d (1 \u003c\u003c 0),\n      FLAG_B \u003d (1 \u003c\u003c 1),\n      FLAG_C \u003d (1 \u003c\u003c 1)\n    };\n\n  enum flags ff \u003d FLAG_B;\n\nWe can:\n\n  (gdb) printf \"%s\\n\", $_as_string(ff)\n  FLAG_B\n\nThis works just fine with %V too:\n\n  (gdb) printf \"%V\\n\", ff\n  FLAG_B\n\nSo all functionality of $_as_string is replaced by %V.  I\u0027m not\nproposing to remove $_as_string, there might be users currently\ndepending on it, but I am proposing that we don\u0027t push $_as_string in\nthe documentation.\n\nAs %V is a feature of printf, GDB\u0027s dprintf breakpoints naturally gain\naccess to this feature too.  dprintf breakpoints can be operated in\nthree different styles \u0027gdb\u0027 (use GDB\u0027s printf), \u0027call\u0027 (call a\nfunction in the inferior), or \u0027agent\u0027 (perform the dprintf on the\nremote).\n\nThe use of \u0027%V\u0027 will work just fine when dprintf-style is \u0027gdb\u0027.\n\nWhen dprintf-style is \u0027call\u0027 the format string and arguments are\npassed to an inferior function (printf by default).  In this case GDB\ndoesn\u0027t prevent use of \u0027%V\u0027, but the documentation makes it clear that\nsupport for \u0027%V\u0027 will depend on the inferior function being called.\n\nI chose this approach because the current implementation doesn\u0027t place\nany restrictions on the format string when operating in \u0027call\u0027 style.\nThat is, the user might already be calling a function that supports\ncustom print format specifiers (maybe including \u0027%V\u0027) so, I claim, it\nwould be wrong to block use of \u0027%V\u0027 in this case.  The documentation\ndoes make it clear that users shouldn\u0027t expect this to \"just work\"\nthough.\n\nWhen dprintf-style is \u0027agent\u0027 then GDB does no support the use of\n\u0027%V\u0027 (right now).  This is handled at the point when GDB tries to\nprocess the format string and send the dprintf command to the remote,\nhere\u0027s an example:\n\n  Reading symbols from /tmp/hello.x...\n  (gdb) dprintf call_me, \"%V\", a1\n  Dprintf 1 at 0x401152: file /tmp/hello.c, line 8.\n  (gdb) set sysroot /\n  (gdb) target remote | gdbserver --once - /tmp/hello.x\n  Remote debugging using | gdbserver --once - /tmp/hello.x\n  stdin/stdout redirected\n  Process /tmp/hello.x created; pid \u003d 3088822\n  Remote debugging using stdio\n  Reading symbols from /lib64/ld-linux-x86-64.so.2...\n  (No debugging symbols found in /lib64/ld-linux-x86-64.so.2)\n  0x00007ffff7fd3110 in _start () from /lib64/ld-linux-x86-64.so.2\n  (gdb) set dprintf-style agent\n  (gdb) c\n  Continuing.\n  Unrecognized format specifier \u0027V\u0027 in printf\n  Command aborted.\n  (gdb)\n\nThis is exactly how GDB would handle any other invalid format\nspecifier, for example:\n\n  Reading symbols from /tmp/hello.x...\n  (gdb) dprintf call_me, \"%Q\", a1\n  Dprintf 1 at 0x401152: file /tmp/hello.c, line 8.\n  (gdb) set sysroot /\n  (gdb) target remote | gdbserver --once - /tmp/hello.x\n  Remote debugging using | gdbserver --once - /tmp/hello.x\n  stdin/stdout redirected\n  Process /tmp/hello.x created; pid \u003d 3089193\n  Remote debugging using stdio\n  Reading symbols from /lib64/ld-linux-x86-64.so.2...\n  (No debugging symbols found in /lib64/ld-linux-x86-64.so.2)\n  0x00007ffff7fd3110 in _start () from /lib64/ld-linux-x86-64.so.2\n  (gdb) set dprintf-style agent\n  (gdb) c\n  Continuing.\n  Unrecognized format specifier \u0027Q\u0027 in printf\n  Command aborted.\n  (gdb)\n\nThe error message isn\u0027t the greatest, but improving that can be put\noff for another day I hope.\n\nReviewed-By: Eli Zaretskii \u003celiz@gnu.org\u003e\nAcked-By: Simon Marchi \u003csimon.marchi@efficios.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "d97e3c15a87d76d335c3f00ce24a44c295febc9d",
      "old_mode": 33188,
      "old_path": "gdb/NEWS",
      "new_id": "649a3a9824a0232a1213fa22b3bf3fbda51db014",
      "new_mode": 33188,
      "new_path": "gdb/NEWS"
    },
    {
      "type": "modify",
      "old_id": "d1059e0cb7fb2dafd2742770ca70336171ef5d7d",
      "old_mode": 33188,
      "old_path": "gdb/doc/gdb.texinfo",
      "new_id": "4bc83ed21688bc49f2d0dd78d3655e8b41d4e274",
      "new_mode": 33188,
      "new_path": "gdb/doc/gdb.texinfo"
    },
    {
      "type": "modify",
      "old_id": "ca0966bebb9488f3fff344f2362b4e0004521d16",
      "old_mode": 33188,
      "old_path": "gdb/printcmd.c",
      "new_id": "f9517e6e086bfaa5b4b0e09389a6785df15a1a39",
      "new_mode": 33188,
      "new_path": "gdb/printcmd.c"
    },
    {
      "type": "modify",
      "old_id": "78291a2803c7b2c9767bf223cc3026e429788c9f",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.base/printcmds.c",
      "new_id": "fa3a62d6cdd729f258b18777afc5e9bbd9a6b766",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/printcmds.c"
    },
    {
      "type": "modify",
      "old_id": "2506f745f20a83578d510852de5767c69a306401",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.base/printcmds.exp",
      "new_id": "73f145c9586fe970890ebf2a43ad51d1bbb802d1",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/printcmds.exp"
    },
    {
      "type": "modify",
      "old_id": "19f37ec8e0c449c9c201c11abf30ea46472abbc1",
      "old_mode": 33188,
      "old_path": "gdbsupport/format.cc",
      "new_id": "6e5a3cb6603d9506f8c54760d408eb742195f625",
      "new_mode": 33188,
      "new_path": "gdbsupport/format.cc"
    },
    {
      "type": "modify",
      "old_id": "342b473c3ed5c8f088a259ed41f1ec183bb92be2",
      "old_mode": 33188,
      "old_path": "gdbsupport/format.h",
      "new_id": "2af34ab9450fcf8e2adb39044e195ec490bdb139",
      "new_mode": 33188,
      "new_path": "gdbsupport/format.h"
    }
  ]
}
