)]}'
{
  "commit": "6d088eb92ee42e05a4fbe797515229cf2acd0d99",
  "tree": "b662dd8772412a70b78f3a92d9ab1d6952744b29",
  "parents": [
    "477904ca751c50d243ee3cba3f12cf75e8ba12b3"
  ],
  "author": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Mon Apr 04 17:45:59 2022 -0400"
  },
  "committer": {
    "name": "Simon Marchi",
    "email": "simon.marchi@polymtl.ca",
    "time": "Wed Apr 06 16:11:13 2022 -0400"
  },
  "message": "gdb: don\u0027t copy entirely optimized out values in value_copy\n\nBug 28980 shows that trying to value_copy an entirely optimized out\nvalue causes an internal error.  The original bug report involves MI and\nsome Python pretty printer, and is quite difficult to reproduce, but\nanother easy way to reproduce (that is believed to be equivalent) was\nproposed:\n\n    $ ./gdb -q -nx --data-directory\u003ddata-directory -ex \"py print(gdb.Value(gdb.Value(5).type.optimized_out()))\"\n    /home/smarchi/src/binutils-gdb/gdb/value.c:1731: internal-error: value_copy: Assertion `arg-\u003econtents !\u003d nullptr\u0027 failed.\n\nThis is caused by 5f8ab46bc691 (\"gdb: constify parameter of\nvalue_copy\").  It added an assertion that the contents buffer is\nallocated if the value is not lazy:\n\n  if (!value_lazy (val))\n    {\n      gdb_assert (arg-\u003econtents !\u003d nullptr);\n\nThis was based on the comment on value::contents, which suggest that\nthis is the case:\n\n  /* Actual contents of the value.  Target byte-order.  NULL or not\n     valid if lazy is nonzero.  */\n  gdb::unique_xmalloc_ptr\u003cgdb_byte\u003e contents;\n\nHowever, it turns out that it can also be nullptr also if the value is\nentirely optimized out, for example on exit of\nallocate_optimized_out_value.  That function creates a lazy value, marks\nthe entire value as optimized out, and then clears the lazy flag.  But\ncontents remains nullptr.\n\nThis wasn\u0027t a problem for value_copy before, because it was calling\nvalue_contents_all_raw on the input value, which caused contents to be\nallocated before doing the copy.  This means that the input value to\nvalue_copy did not have its contents allocated on entry, but had it\nallocated on exit.  The result value had it allocated on exit.  And that\nwe copied bytes for an entirely optimized out value (i.e. meaningless\nbytes).\n\nFrom here I see two choices:\n\n 1. respect the documented invariant that contents is nullptr only and\n    only if the value is lazy, which means making\n    allocate_optimized_out_value allocate contents\n 2. extend the cases where contents can be nullptr to also include\n    values that are entirely optimized out (note that you could still\n    have some entirely optimized out values that do have contents\n    allocated, it depends on how they were created) and adjust\n    value_copy accordingly\n\nChoice #1 is safe, but less efficient: it\u0027s not very useful to allocate\na buffer for an entirely optimized out value.  It\u0027s even a bit less\nefficient than what we had initially, because values coming out of\nallocate_optimized_out_value would now always get their contents\nallocated.\n\nChoice #2 would be more efficient than what we had before: giving an\noptimized out value without allocated contents to value_copy would\nresult in an optimized out value without allocated contents (and the\ninput value would still be without allocated contents on exit).  But\nit\u0027s more risky, since it\u0027s difficult to ensure that all users of the\ncontents (through the various_contents* accessors) are all fine with\nthat new invariant.\n\nIn this patch, I opt for choice #2, since I think it is a better\ndirection than choice #1.  #1 would be a pessimization, and if we go\nthis way, I doubt that it will ever be revisited, it will just stay that\nway forever.\n\nAdd a selftest to test this.  I initially started to write it as a\nPython test (since the reproducer is in Python), but a selftest is more\nstraightforward.\n\nBug: https://sourceware.org/bugzilla/show_bug.cgi?id\u003d28980\nChange-Id: I6e2f5c0ea804fafa041fcc4345d47064b5900ed7\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "5d77b0ccc3c5e80356861ef4ddda5bcf1302d764",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.python/py-value.exp",
      "new_id": "b88c4515c8ce60b9854a6568c937b9684fc132c9",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.python/py-value.exp"
    },
    {
      "type": "modify",
      "old_id": "482abcee1c18eaf753a798489405fb9302fb5e4d",
      "old_mode": 33188,
      "old_path": "gdb/value.c",
      "new_id": "24f1151c03f0d2fd485a8899773c19f170f6e22f",
      "new_mode": 33188,
      "new_path": "gdb/value.c"
    }
  ]
}
