David Blaikie via llvm-dev
2016-Jun-01 01:09 UTC
[llvm-dev] GDB pretty printers for LLVM ADTs
In r271357 I've committed GDB pretty printer script for the following types - ArrayRef $1 = llvm::ArrayRef of length 3 = {1, 0, 7} - StringRef $2 = "foo\000bar" $3 = "fo" - SmallString $4 = "foo\000bar" - *SmallVector(Impl)* $5 = llvm::SmallVector of length 3, capacity 3 = {1, 0, 7} All of these visualizers are pretty simple, robust, should work when debugging a core dump (ie: non-live/not executing any code in the debug process). Note that the StringRef visualizer now properly terminates the string at the specified length - so it can both include null characters, or terminate prematurely before them. Same with StringPiece. Syntax/styling for ArrayRef and SmallVector are based on the print styling of std::vector. If people feel like the smallness should be included in any of the Small* types, we could include that. And if the element type of sequences is important, we can do that too - but since std::vector doesn't include the element type, I figured that was a good thing to go off and as we improve the pretty printers for more types the elements should be self explanatory. Patches and feedback welcome to add more visualizers, improve existing ones, etc. *How do you access/use these pretty printers?* Currently, the simplest thing to do is: source /path/to/your/llvm/src/utils/gdb-scripts/prettyprinters.py You can put this in your ~/.gdbinit if you want to make it more convenient. *Possible Usability Improvements* Just sourcing in .gdbinit doesn't scale if you have multiple LLVM source trees or debug builds that might be out of sync with one another (the ABI of the ADTs probably doesn't change all that often that this would be very annoying - but Clang's ASTs, LLVM IR nodes, etc might change often enough that this approach would come up for users in this situation). Also having to go in and another line whenever we add other scripts - Clang pretty printers, LLD pretty printers, etc, would be unfortunate. .debug_gdb_scripts <https://sourceware.org/gdb/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html#dotdebug_005fgdb_005fscripts-section> provides a way to load these scripts on demand, which would ensure that we didn't need to update each of our local .gdbinit files every time a new set of pretty printers (probably on a per project basis - one for clang, one for LLVM, one for LLD, etc) was added. Though it does still require a .gdbinit change (or manual command) to adjust the auto-load path to allow the scripts to be automatically loaded. Depending on how it's used, it doesn't entirely fix the "what if I have multiple different LLVM things I'm debugging with incompatible pretty printers". Using just the script name version doesn't help because the paths the scripts are loaded from wouldn't distinguish between which source tree. But if we use the inline script version - the right version is embedded in the binary & available every time. This gets a bit ugly - writing Python inside inline asm isn't really comfortable (even with C++ raw string literals to get past one level of escaping), but we could use incbin assembler directive to include a Python source file straight into the inline asm in the right place. Only problem: Clang's incbin support is buggy <http://llvm.org/PR24811> in a way that makes this not work (disabling the integrated assembler does demonstrate this working successfully). Appendix of debug_gdb_scripts examples, so I don't have to keep these somewhere else for reference. Obviously these aren't terribly portable, but on platforms where they don't work (so long as we #define them away) users are no worse off there - people can still source the python script directly as described above: 1) basic usage: asm(R"(.pushsection ".debug_gdb_scripts", "MS", at progbits,1 .byte 1 .asciz "utils/gdb-scripts/support.py" .popsection )"); 2) annoying inline script version: .byte 4 .ascii "llvmSupport.inlined-script\n" .ascii "import gdb.printing\n" .ascii "class SmallStringPrinter:\n" .ascii " \"\"\"Print an llvm::SmallString object.\"\"\"\n" .ascii "\n" .ascii " def __init__(self, val):\n" .ascii " self.val = val\n" .ascii "\n" .ascii " def to_string(self):\n" .ascii " begin = self.val['BeginX']\n" .ascii " end = self.val['EndX']\n" .ascii " return begin.cast(gdb.lookup_type(\"char\").pointer()).string(length = end - begin)\n" .ascii "\n" .ascii " def display_hint (self):\n" .ascii " return 'string'\n" ... .ascii "pp = gdb.printing.RegexpCollectionPrettyPrinter(\"LLVMSupport\")\n" .ascii "pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)\n" ... .ascii "gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)\n" .byte 0 .popsection )"); 2) incbin inline script version: asm(R"(.pushsection ".debug_gdb_scripts", "MS", at progbits,1 .byte 4 .ascii "llvmSupport.inlined-script\n" .incbin "gdb-support.py" .byte 0 .popsection )"); -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160531/bffdabc4/attachment-0001.html>
Piotr Padlewski via llvm-dev
2016-Jun-01 13:08 UTC
[llvm-dev] GDB pretty printers for LLVM ADTs
Pretty printers was something that I was really missing when debugging. Thanks David! 2016-06-01 3:09 GMT+02:00 David Blaikie via llvm-dev < llvm-dev at lists.llvm.org>:> In r271357 I've committed GDB pretty printer script for the following > types > > - ArrayRef > $1 = llvm::ArrayRef of length 3 = {1, 0, 7} > - StringRef > $2 = "foo\000bar" > $3 = "fo" > - SmallString > $4 = "foo\000bar" > - *SmallVector(Impl)* > $5 = llvm::SmallVector of length 3, capacity 3 = {1, 0, 7} > > All of these visualizers are pretty simple, robust, should work when > debugging a core dump (ie: non-live/not executing any code in the debug > process). > > Note that the StringRef visualizer now properly terminates the string at > the specified length - so it can both include null characters, or terminate > prematurely before them. Same with StringPiece. > > Syntax/styling for ArrayRef and SmallVector are based on the print styling > of std::vector. If people feel like the smallness should be included in any > of the Small* types, we could include that. And if the element type of > sequences is important, we can do that too - but since std::vector doesn't > include the element type, I figured that was a good thing to go off and as > we improve the pretty printers for more types the elements should be self > explanatory. > > Patches and feedback welcome to add more visualizers, improve existing > ones, etc. > > *How do you access/use these pretty printers?* > > Currently, the simplest thing to do is: > > source /path/to/your/llvm/src/utils/gdb-scripts/prettyprinters.py > > You can put this in your ~/.gdbinit if you want to make it more > convenient. > > > *Possible Usability Improvements* > Just sourcing in .gdbinit doesn't scale if you have multiple LLVM source > trees or debug builds that might be out of sync with one another (the ABI > of the ADTs probably doesn't change all that often that this would be very > annoying - but Clang's ASTs, LLVM IR nodes, etc might change often enough > that this approach would come up for users in this situation). Also having > to go in and another line whenever we add other scripts - Clang pretty > printers, LLD pretty printers, etc, would be unfortunate. > > .debug_gdb_scripts > <https://sourceware.org/gdb/onlinedocs/gdb/dotdebug_005fgdb_005fscripts-section.html#dotdebug_005fgdb_005fscripts-section> > provides a way to load these scripts on demand, which would ensure that > we didn't need to update each of our local .gdbinit files every time a new > set of pretty printers (probably on a per project basis - one for clang, > one for LLVM, one for LLD, etc) was added. > > Though it does still require a .gdbinit change (or manual command) to > adjust the auto-load path to allow the scripts to be automatically loaded. > > Depending on how it's used, it doesn't entirely fix the "what if I have > multiple different LLVM things I'm debugging with incompatible pretty > printers". Using just the script name version doesn't help because the > paths the scripts are loaded from wouldn't distinguish between which source > tree. > > But if we use the inline script version - the right version is embedded in > the binary & available every time. This gets a bit ugly - writing Python > inside inline asm isn't really comfortable (even with C++ raw string > literals to get past one level of escaping), but we could use incbin > assembler directive to include a Python source file straight into the > inline asm in the right place. Only problem: Clang's incbin support is > buggy <http://llvm.org/PR24811> in a way that makes this not work > (disabling the integrated assembler does demonstrate this working > successfully). > > Appendix of debug_gdb_scripts examples, so I don't have to keep these > somewhere else for reference. Obviously these aren't terribly portable, but > on platforms where they don't work (so long as we #define them away) users > are no worse off there - people can still source the python script directly > as described above: > > 1) basic usage: > > asm(R"(.pushsection ".debug_gdb_scripts", "MS", at progbits,1 > .byte 1 > .asciz "utils/gdb-scripts/support.py" > .popsection > )"); > 2) annoying inline script version: > > .byte 4 > .ascii "llvmSupport.inlined-script\n" > .ascii "import gdb.printing\n" > .ascii "class SmallStringPrinter:\n" > .ascii " \"\"\"Print an llvm::SmallString object.\"\"\"\n" > .ascii "\n" > .ascii " def __init__(self, val):\n" > .ascii " self.val = val\n" > .ascii "\n" > .ascii " def to_string(self):\n" > .ascii " begin = self.val['BeginX']\n" > .ascii " end = self.val['EndX']\n" > .ascii " return begin.cast(gdb.lookup_type(\"char\").pointer()).string(length = end - begin)\n" > .ascii "\n" > .ascii " def display_hint (self):\n" > .ascii " return 'string'\n" > ... > > .ascii "pp = gdb.printing.RegexpCollectionPrettyPrinter(\"LLVMSupport\")\n" > .ascii "pp.add_printer('llvm::SmallString', '^llvm::SmallString<.*>$', SmallStringPrinter)\n" > ... > .ascii "gdb.printing.register_pretty_printer(gdb.current_objfile(), pp)\n" > .byte 0 > .popsection > )"); > > 2) incbin inline script version: > > asm(R"(.pushsection ".debug_gdb_scripts", "MS", at progbits,1 > .byte 4 > .ascii "llvmSupport.inlined-script\n" > .incbin "gdb-support.py" > .byte 0 > .popsection > )"); > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160601/c374f7f4/attachment.html>