)]}'
{
  "commit": "4de4e48514fc47aeb4ca95cd4091e2a333fbe9e1",
  "tree": "e6af2471378a753f74f665b601f21c15958c5f77",
  "parents": [
    "0af2f233330024e0e9b4697d510c7030e518e64c"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Tue Jan 24 15:35:45 2023 +0000"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Tue May 16 10:30:47 2023 +0100"
  },
  "message": "gdb/python: extend the Python Disassembler API to allow for styling\n\nThis commit extends the Python Disassembler API to allow for styling\nof the instructions.\n\nBefore this commit the Python Disassembler API allowed the user to do\ntwo things:\n\n  - They could intercept instruction disassembly requests and return a\n    string of their choosing, this string then became the disassembled\n    instruction, or\n\n  - They could call builtin_disassemble, which would call back into\n    libopcode to perform the disassembly.  As libopcode printed the\n    instruction GDB would collect these print requests and build a\n    string.  This string was then returned from the builtin_disassemble\n    call, and the user could modify or extend this string as needed.\n\nNeither of these approaches allowed for, or preserved, disassembler\nstyling, which is now available within libopcodes for many of the more\npopular architectures GDB supports.\n\nThis commit aims to fill this gap.  After this commit a user will be\nable to do the following things:\n\n  - Implement a custom instruction disassembler entirely in Python\n    without calling back into libopcodes, the custom disassembler will\n    be able to return styling information such that GDB will display\n    the instruction fully styled.  All of GDB\u0027s existing style\n    settings will affect how instructions coming from the Python\n    disassembler are displayed in the expected manner.\n\n  - Call builtin_disassemble and receive a result that represents how\n    libopcode would like the instruction styled.  The user can then\n    adjust or extend the disassembled instruction before returning the\n    result to GDB.  Again, the instruction will be styled as expected.\n\nTo achieve this I will add two new classes to GDB,\nDisassemblerTextPart and DisassemblerAddressPart.\n\nWithin builtin_disassemble, instead of capturing the print calls from\nlibopcodes and building a single string, we will now create either a\ntext part or address part and store these parts in a vector.\n\nThe DisassemblerTextPart will capture a small piece of text along with\nthe associated style that should be used to display the text.  This\ncorresponds to the disassembler calling\ndisassemble_info::fprintf_styled_func, or for disassemblers that don\u0027t\nsupport styling disassemble_info::fprintf_func.\n\nThe DisassemblerAddressPart is used when libopcodes requests that an\naddress be printed, and takes care of printing the address and\nassociated symbol, this corresponds to the disassembler calling\ndisassemble_info::print_address_func.\n\nThese parts are then placed within the DisassemblerResult when\nbuiltin_disassemble returns.\n\nAlternatively, the user can directly create parts by calling two new\nmethods on the DisassembleInfo class: DisassembleInfo.text_part and\nDisassembleInfo.address_part.\n\nHaving created these parts the user can then pass these parts when\ninitializing a new DisassemblerResult object.\n\nFinally, when we return from Python to gdbpy_print_insn, one way or\nanother, the result being returned will have a list of parts.  Back in\nGDB\u0027s C++ code we walk the list of parts and call back into GDB\u0027s core\nto display the disassembled instruction with the correct styling.\n\nThe new API lives in parallel with the old API.  Any existing code\nthat creates a DisassemblerResult using a single string immediately\ncreates a single DisassemblerTextPart containing the entire\ninstruction and gives this part the default text style.  This is also\nwhat happens if the user calls builtin_disassemble for an architecture\nthat doesn\u0027t (yet) support libopcode styling.\n\nThis matches up with what happens when the Python API is not involved,\nan architecture without disassembler styling support uses the old\nlibopcodes printing API (the API that doesn\u0027t pass style info), and\nGDB just prints everything using the default text style.\n\nThe reason that parts are created by calling methods on\nDisassembleInfo, rather than calling the class constructor directly,\nis DisassemblerAddressPart.  Ideally this part would only hold the\naddress which the part represents, but in order to support backwards\ncompatibility we need to be able to convert the\nDisassemblerAddressPart into a string.  To do that we need to call\nGDB\u0027s internal print_address function, and to do that we need an\ngdbarch.\n\nWhat this means is that the DisassemblerAddressPart needs to take a\ngdb.Architecture object at creation time.  The only valid place a user\ncan pull this from is from the DisassembleInfo object, so having the\nDisassembleInfo act as a factory ensures that the correct gdbarch is\npassed over each time.  I implemented both solutions (the one\npresented here, and an alternative where parts could be constructed\ndirectly), and this felt like the cleanest solution.\n\nReviewed-By: Eli Zaretskii \u003celiz@gnu.org\u003e\nReviewed-By: Tom Tromey \u003ctom@tromey.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "ca164257126f94b5088588dfeea94733e5f58b60",
      "old_mode": 33188,
      "old_path": "gdb/NEWS",
      "new_id": "b82114d80b0c38e42653f30792487ac26aa46b22",
      "new_mode": 33188,
      "new_path": "gdb/NEWS"
    },
    {
      "type": "modify",
      "old_id": "a906c168373cc35a759c36e9703a426618a788c1",
      "old_mode": 33188,
      "old_path": "gdb/doc/python.texi",
      "new_id": "5d714ee1ca32c139e74242d6e91853f77be89309",
      "new_mode": 33188,
      "new_path": "gdb/doc/python.texi"
    },
    {
      "type": "modify",
      "old_id": "f246a09301452a21b88d189f12f5fb86a51e455a",
      "old_mode": 33188,
      "old_path": "gdb/python/py-disasm.c",
      "new_id": "85d936ee4a55fffbbf79f655acab34aedceff568",
      "new_mode": 33188,
      "new_path": "gdb/python/py-disasm.c"
    },
    {
      "type": "modify",
      "old_id": "5cbf02fc9fe1267c1a86e3be76df82d134335d4d",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.python/py-disasm.exp",
      "new_id": "304393f71ab7cc6ba8258801519cd330e8ee2a05",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.python/py-disasm.exp"
    },
    {
      "type": "modify",
      "old_id": "17a7e752935b1386dcc1f08371715ae8468710b0",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.python/py-disasm.py",
      "new_id": "ec6b0e8deca4b8c2886a25b2a059786ef42aca87",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.python/py-disasm.py"
    }
  ]
}
