)]}'
{
  "commit": "b3245ceff0e1e5e85257f4e703e839b45510f39e",
  "tree": "8bb68e5a59c0240e5a4065902f3fe9a5aafd1fe8",
  "parents": [
    "6831f2cd547e6e18b2245a4f325f9960b1e732ec"
  ],
  "author": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Fri Dec 01 11:27:27 2023 -0500"
  },
  "committer": {
    "name": "Simon Marchi",
    "email": "simon.marchi@efficios.com",
    "time": "Thu Dec 14 16:04:49 2023 +0000"
  },
  "message": "gdb: read pseudo register through frame\n\nChange gdbarch_pseudo_register_read_value to take a frame instead of a\nregcache.  The frame (and formerly the regcache) is used to read raw\nregisters needed to make up the pseudo register value.  The problem with\nusing the regcache is that it always provides raw register values for\nthe current frame (frame 0).\n\nLet\u0027s say the user wants to read the ebx register on amd64.  ebx is a pseudo\nregister, obtained by reading the bottom half (bottom 4 bytes) of the\nrbx register, which is a raw register.  If the currently selected frame\nis frame 0, it works fine:\n\n    (gdb) frame 0\n    #0  break_here_asm () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:36\n    36      in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S\n    (gdb) p/x $ebx\n    $1 \u003d 0x24252627\n    (gdb) p/x $rbx\n    $2 \u003d 0x2021222324252627\n\nBut if the user is looking at another frame, and the raw register behind\nthe pseudo register has been saved at some point in the call stack, then\nwe get a wrong answer:\n\n    (gdb) frame 1\n    #1  0x000055555555517d in caller () at /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S:56\n    56      in /home/smarchi/src/binutils-gdb/gdb/testsuite/gdb.arch/amd64-pseudo-unwind-asm.S\n    (gdb) p/x $ebx\n    $3 \u003d 0x24252627\n    (gdb) p/x $rbx\n    $4 \u003d 0x1011121314151617\n\nHere, the value of ebx was computed using the value of rbx in frame 0\n(through the regcache), it should have been computed using the value of\nrbx in frame 1.\n\nIn other to make this work properly, make the following changes:\n\n - Make dwarf2_frame_prev_register return nullptr if it doesn\u0027t know how\n   to unwind a register and that register is a pseudo register.\n   Previously, it returned `frame_unwind_got_register`, meaning, in our\n   example, \"the value of ebx in frame 1 is the same as the value of ebx\n   in frame 0\", which is obviously false.  Return nullptr as a way to\n   say \"I don\u0027t know\".\n\n - In frame_unwind_register_value, when prev_register (for instance\n   dwarf2_frame_prev_register) returns nullptr, and we are trying to\n   read a pseudo register, try to get the register value through\n   gdbarch_pseudo_register_read_value or gdbarch_pseudo_register_read.\n   If using gdbarch_pseudo_register_read, the behavior is known to be\n   broken.  Implementations should be migrated to use\n   gdbarch_pseudo_register_read_value to fix that.\n\n - Change gdbarch_pseudo_register_read_value to take a frame_info\n   instead of a regcache, update implementations (aarch64, amd64, i386).\n   In i386-tdep.c, I made a copy of i386_mmx_regnum_to_fp_regnum that\n   uses a frame instead of a regcache.  The version using the regcache\n   is still used by i386_pseudo_register_write.  It will get removed in\n   a subsequent patch.\n\n - Add some helpers in value.{c,h} to implement the common cases of\n   pseudo registers: taking part of a raw register and concatenating\n   multiple raw registers.\n\n - Update readable_regcache::{cooked_read,cooked_read_value} to pass the\n   current frame to gdbarch_pseudo_register_read_value.  Passing the\n   current frame will give the same behavior as before: for frame 0, raw\n   registers will be read from the current thread\u0027s regcache.\n\nNotes:\n\n - I do not plan on changing gdbarch_pseudo_register_read to receive a\n   frame instead of a regcache. That method is considered deprecated.\n   Instead, we should be working on migrating implementations to use\n   gdbarch_pseudo_register_read_value instead.\n\n - In frame_unwind_register_value, we still ask the unwinder to try to\n   unwind pseudo register values.  It\u0027s apparently possible for the\n   debug info to provide information about [1] pseudo registers, so we\n   want to try that first, before falling back to computing them\n   ourselves.\n\n[1] https://inbox.sourceware.org/gdb-patches/20180528174715.A954AD804AD@oc3748833570.ibm.com/\n\nChange-Id: Id6ef1c64e19090a183dec050e4034d8c2394e7ca\nReviewed-by: John Baldwin \u003cjhb@FreeBSD.org\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "b0aee191d71f09278bd9d3aca1f510db93f51a6f",
      "old_mode": 33188,
      "old_path": "gdb/aarch64-tdep.c",
      "new_id": "d901b69ce11d7cbad29003239c7fd988f6816726",
      "new_mode": 33188,
      "new_path": "gdb/aarch64-tdep.c"
    },
    {
      "type": "modify",
      "old_id": "e6feee677b3de392464fe036540eef60112f4e89",
      "old_mode": 33188,
      "old_path": "gdb/amd64-tdep.c",
      "new_id": "955a6860631d0712eadcc02471870c294d921fdb",
      "new_mode": 33188,
      "new_path": "gdb/amd64-tdep.c"
    },
    {
      "type": "modify",
      "old_id": "d72dd0ad971d1eaad17e7c4c789394057bac731c",
      "old_mode": 33188,
      "old_path": "gdb/dwarf2/frame.c",
      "new_id": "d3d1ecdf1f5b6dfa65223003dc546d7ead288a4a",
      "new_mode": 33188,
      "new_path": "gdb/dwarf2/frame.c"
    },
    {
      "type": "modify",
      "old_id": "d260e8c28f3fc5b083a72fb07dc0676c89ecc604",
      "old_mode": 33188,
      "old_path": "gdb/frame.c",
      "new_id": "a9cad1dca8fb97c428f11b2ff30a9a94f0b6c2d2",
      "new_mode": 33188,
      "new_path": "gdb/frame.c"
    },
    {
      "type": "modify",
      "old_id": "9f468bd1f61842332d771354e5113d7d9afad6cc",
      "old_mode": 33188,
      "old_path": "gdb/gdbarch-gen.h",
      "new_id": "c70bfc97634a7d2c78f781c3a87cdf9cbfb4d8e4",
      "new_mode": 33188,
      "new_path": "gdb/gdbarch-gen.h"
    },
    {
      "type": "modify",
      "old_id": "ea6e4c647b10b9b266ad2dbb0a624b74ee142b5b",
      "old_mode": 33188,
      "old_path": "gdb/gdbarch.c",
      "new_id": "06ff52576bdfe85b356f2e367db27a03a783edb8",
      "new_mode": 33188,
      "new_path": "gdb/gdbarch.c"
    },
    {
      "type": "modify",
      "old_id": "694ac366023535b26a768f01c20da0ecd16ab85c",
      "old_mode": 33188,
      "old_path": "gdb/gdbarch_components.py",
      "new_id": "c597b38ad5a977be00296f83f6256fc6bc5a2fea",
      "new_mode": 33188,
      "new_path": "gdb/gdbarch_components.py"
    },
    {
      "type": "modify",
      "old_id": "7a13a414543ac248464458fe0eff17a86d130391",
      "old_mode": 33188,
      "old_path": "gdb/i386-tdep.c",
      "new_id": "cb24a7353bff314eeba3ed46078124b2e7d487d0",
      "new_mode": 33188,
      "new_path": "gdb/i386-tdep.c"
    },
    {
      "type": "modify",
      "old_id": "4283a52c92923e3cb5577cb9c7daaf268e49b734",
      "old_mode": 33188,
      "old_path": "gdb/i386-tdep.h",
      "new_id": "970dc8904f2acdc3213fa380b8534f87ae7aa707",
      "new_mode": 33188,
      "new_path": "gdb/i386-tdep.h"
    },
    {
      "type": "modify",
      "old_id": "9b3fd4f060c7ad48832a069108ff102d576fdb1c",
      "old_mode": 33188,
      "old_path": "gdb/regcache.c",
      "new_id": "9575988760bab0b5b272df73f903b03de8930923",
      "new_mode": 33188,
      "new_path": "gdb/regcache.c"
    },
    {
      "type": "modify",
      "old_id": "5e48a4c86487c0d87cb7c6426908d5486bdc2f68",
      "old_mode": 33188,
      "old_path": "gdb/value.c",
      "new_id": "20f8dccdd55ab0dd815c7f7b5ca0d892d4bb466e",
      "new_mode": 33188,
      "new_path": "gdb/value.c"
    },
    {
      "type": "modify",
      "old_id": "2f3b41e26ea44aadfca13a1566c074755f9c1cb4",
      "old_mode": 33188,
      "old_path": "gdb/value.h",
      "new_id": "935d9ebfd8c964f2d5691b3753d3d5e19f8756be",
      "new_mode": 33188,
      "new_path": "gdb/value.h"
    }
  ]
}
