arximboldi / immer

Postmodern immutable and persistent data structures for C++ — value semantics at scale
https://sinusoid.es/immer
Boost Software License 1.0
2.51k stars 185 forks source link

Add GDB pretty-printing support #255

Closed dhly-etc closed 1 year ago

dhly-etc commented 1 year ago

As discussed in #97, I'm submitting this PR, which adds GDB pretty-printing support. The code is sourced from @dwightguth's original gist, and lightly modified. Dwight very kindly dual-licensed his gist under BSL/BSD to minimize any legal issues with the integration of this code.

I'd welcome any feedback, and would be happy to try and address any concerns.

dwightguth commented 1 year ago

https://sourceware.org/gdb/onlinedocs/gdb/Python-Auto_002dloading.html#Python-Auto_002dloading

https://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-extensions.html#Auto_002dloading-extensions

These documents and the links found in them describe two different ways to make gdb auto load a python script. For security reasons you're still probably going to have to tell gdb that you trust the path containing the script, but once a user does that, they will automatically load the pretty printers contained in this script. Otherwise you would have to manually load the python code each time you start gdb, or else add code to load it to the scripts that run when gdb starts.

dhly-etc commented 1 year ago

If I'm missing something and you've already tested this and it works without needing to be manually loaded, feel free to ignore my comment. I'll look at the code in more detail tomorrow.

Nope, you're not missing anything. I've been testing by manually loading. In my case, I added a source <path/to/autoload.py> line to my .gdbinit file. You can also just type that directly into the gdb prompt to load the printers, if you don't have a .gdbinit file.

I'm looking into the autoloading options now. From a cursory read, the .debug_gdb_scripts method seems most promising given that this is a header-only library, but I haven't quite understood the details of this method yet.

dhly-etc commented 1 year ago

After looking more into .debug_gdb_scripts, I'm somewhat hesitant to try and tackle this form of auto-loading myself. It looks like it can be a bit tricky to get it right, especially across compilers.

I'm wondering if maybe it would be sufficient to add a .gdbinit file to the repo, so that anyone developing the library will get automatic loading, and anyone using the library in another project will at least have a hint as to how to use the printers. What do you think?

arximboldi commented 1 year ago

That approach sounds good to me @dhly-etc !

dhly-etc commented 1 year ago

@arximboldi Okay, in theory now if you open a gdb process from your project directory, you should automatically get the pretty printers. Let me know if this works for you!

Also let me know if you find any issues with the printers themselves. You should get legible output for the container contents. For instance, given a immer::array<std::pair<std::string, int>> v3, you should get output like

(gdb) print v3
$1 = immer::array with 3 elements = {{
    first = "a",
    second = 1
  }, {
    first = "b",
    second = 2
  }, {
    first = "c",
    second = 3
  }}
dwightguth commented 1 year ago

I mean, telling people how to set it up themselves is a workable solution if you're concerned about the platform compatibility of the auto loading process. It can be somewhat finicky so I won't necessarily argue with your approach since it sounds like it's relatively simple to add the script to your gdbinit...

arximboldi commented 1 year ago

This is very cool, thank you both for figuring this out.

CI is failing but for other reasons... let's go! :+1: