Blending Guile and GDB together

Ludovic Courtès ludo@gnu.org
Sun Feb 16 16:22:00 GMT 2014


Hello!

As a gift for Guile 2.0’s third birthday [0], here’s a quick hack to
enhance the debugging experience for Guile hackers in GDB!

The attached code is a GDB extension, written in Guile, using the nice
Guile API that landed into GDB master last week (thanks, Doug!).  Once
you have GDB master (7.8) built with Guile support, just type this at
the GDB prompt:

  (gdb) guile (load "scmpp.scm")

From there on, life in GDB is different.  :-)

The main feature is printing of ‘SCM’ values.  As you know, ‘SCM’ values
are bit patterns, sometimes with pointers in disguise and so on–to the
experienced Guile hacker, “404” is synonymous with #t, not “page not
found”.

So, before:

--8<---------------cut here---------------start------------->8---
Breakpoint 1, scm_display (obj=0xf04310, port=0x6f9f30) at print.c:1437
1437	{
(gdb) bt
#0  scm_display (obj=0xf04310, port=0x6f9f30) at print.c:1437
#1  0x00007ffff7b28ef1 in vm_debug_engine (vm=<optimized out>, program=0x6eb240, argv=<optimized out>, nargs=2)
    at vm-i-system.c:855
#2  0x00007ffff7aaafe3 in scm_primitive_eval (exp=exp@entry=0x8e1440) at eval.c:685
#3  0x00007ffff7aab043 in scm_eval (exp=0x8e1440, module_or_state=module_or_state@entry=0x8a8c60) at eval.c:719
#4  0x00007ffff7afa26d in scm_shell (argc=1, argv=0x7fffffffd118) at script.c:441
#5  0x00007ffff7ac753d in invoke_main_func (body_data=0x7fffffffcfe0) at init.c:337
#6  0x00007ffff7aa14ca in c_body (d=0x7fffffffcf20) at continuations.c:511
#7  0x00007ffff7b33ac8 in vm_regular_engine (vm=<optimized out>, program=0x6f57e0, argv=<optimized out>, nargs=2)
    at vm-i-system.c:855
#8  0x00007ffff7aaaaa3 in scm_call_4 (proc=0x7d2570, arg1=arg1@entry=0x404, arg2=<optimized out>, arg3=<optimized out>, 
    arg4=<optimized out>) at eval.c:507
--8<---------------cut here---------------end--------------->8---

After:

--8<---------------cut here---------------start------------->8---
(gdb) gu (load "scmpp.scm")
(gdb) bt
#0  scm_display (obj=("happy" birthday Guile (2 . 0)), port=#<port file 6f9f30>) at print.c:1437
#1  0x00007ffff7b28ef1 in vm_debug_engine (vm=<optimized out>, program=#<program 6eb240>, argv=<optimized out>, nargs=2)
    at vm-i-system.c:855
#2  0x00007ffff7aaafe3 in scm_primitive_eval (
    exp=exp@entry=((@ (ice-9 control) %) (begin (load-user-init) ((@ (ice-9 top-repl) top-repl))))) at eval.c:685
#3  0x00007ffff7aab043 in scm_eval (exp=((@ (ice-9 control) %) (begin (load-user-init) ((@ (ice-9 top-repl) top-repl)))), 
    module_or_state=module_or_state@entry=#<struct module #<hash-table 8b5240> (#<struct module #<hash-table 66df80> (#<struct module #<hash-table 871ac0> () #f #f #<program 824700> (ice-9 deprecated) interface #f #<hash-table 871aa0> () #<hash-table 871a80> #f #<hash-table 871a40> #f #f #f300b840> #<struct module #<hash-table 891180> () #f #f #<program 824700> (srfi srfi-4) interface #f #<hash-table 891160> () #<hash-table 891140> #f #<hash-table 891100> #f #f #f300b0e0>) #f #f #<program 824700> (guile) interface #f #<hash-table 846740> () #<hash-table 846720> #f #<hash-table 8466e0> #f #<cycle 822ab0> #f3055dc0> #<struct module #<hash-table 883660> () #f #f #<program 824700> (system base compile) interface #f #<hash-table 883640> () #<hash-table 883620> #f #<hash-table 8835e0> #f #f #f30554a0> #<struct module #<hash-table bb6a00> () #f #f #<program 824700> (ice-9 readline) interface #f #<hash-table bb69e0> () #<hash-table bb69c0> #f #<hash-table bb6980> #f #f #f30626c0> #<struct module #<hash-table b0e580> () #f #f #<program 824700> (ice-9 history) interface #f #<hash-table b0e560> () #<hash-table b0e540> #f #<hash-table b0e500> #f #f #f3063540> #<struct module #<hash-table 6b1e20> () #f #f #<program 824700> (srfi srfi-1) interface #f #<hash-table 6b1e00> () #<hash-table 6b1de0> #f #<hash-table 6b17a0> #f #f #f3066500> #<struct module #<hash-table a7a2a0> () #f #f #<program 824700> (srfi srfi-26) interface #f #<hash-table a7a280> () #<hash-table a7a260> #f #<hash-table a7a220> #f #f #f3075b00> #<struct module #<hash-table bdd440> () #f #f #<program 824700> (texinfo reflection) interface #f #<hash-table bdd420> () #<hash-table bdd400> #f #<hash-table bdd3c0> #f #f #f3075360> #<struct module #<hash-table d99ba0> (#<struct module #<hash-table da07a0> (#<struct module #<hash-table dbc0a0> () #f #f #<program 824700> (ice-9 null) interface #f #<hash-table dbc060> () #<hash-table dbc020> #f #<hash-table dbec40> #f #f #f3083560>) #f #f #<program 824700> (ice-9 safe-r5rs) interface #f #<hash-table da0780> () #<hash-table da0660> #f #<hash-table da0520> #f #f #f30830e0>) #f #f #<program 824700> (ice-9 r5rs) interface #f #<hash-table d99ae0> () #<hash-table d99ac0> #f #<hash-table d999e0> #f #f #f3088120> #<struct module #<hash-table b47040> () #f #f #<program 824700> (ice-9 session) interface #f #<hash-table b47020> () #<hash-table b47000> #f #<hash-table b57c60> #f #f #f3094160> #<struct module #<hash-table 9819c0> () #f #f #<program 824700> (ice-9 regex) interface #f #<hash-table 9819a0> () #<hash-table 981980> #f #<hash-table 9818c0> #f #f #f30987c0> #<struct module #<hash-table de0280> () #f #f #<program 824700> (ice-9 threads) interface #f #<hash-table de0140> () #<hash-table de0120> #f #<hash-table de0060> #f #f #f309bd20> #<struct module #<hash-table b0e220> () #f #f #<program 824700> (value-history) interface #f #<hash-table b0e200> () #<hash-table b0e1e0> #f #<hash-table b0e1a0> #f #f #f309b680>) #f #f #<program 824700> (guile-user) directory #f #<hash-table 8b5220> () #<hash-table 8b5200> #f #<hash-table 8b51c0> #f #<struct module #<hash-table 8b5160> () #f #f #<program 824700> (guile-user) interface #f #<hash-table 8b5140> () #<hash-table 8b5120> #f #<hash-table 8b50e0> #f #f #f30b3d20> #f30b3d00>) at eval.c:719
#4  0x00007ffff7afa26d in scm_shell (argc=1, argv=0x7fffffffd118) at script.c:441
#5  0x00007ffff7ac753d in invoke_main_func (body_data=0x7fffffffcfe0) at init.c:337
#6  0x00007ffff7aa14ca in c_body (d=0x7fffffffcf20) at continuations.c:511
#7  0x00007ffff7b33ac8 in vm_regular_engine (vm=<optimized out>, program=#<program 6f57e0>, argv=<optimized out>, nargs=2)
    at vm-i-system.c:855
#8  0x00007ffff7aaaaa3 in scm_call_4 (proc=#<program 7d2570>, arg1=arg1@entry=#t, arg2=<optimized out>, arg3=<optimized out>, 
    arg4=<optimized out>) at eval.c:507
--8<---------------cut here---------------end--------------->8---

(I hear some say: “is this huge dump of ‘module_or_state’ really an
improvement?”  Well, granted, this one is a bit annoying, we’ll have to
think of a way to truncate it, maybe.  But it shows that many data types
are pretty-printed, including all the structure fields.  :-))

Traditionally, people would typically type ‘call scm_write(x, 0x204)’ to
print the value of ‘x’.  But in addition to being tedious, this won’t
work on a core file, and can otherwise destabilize the Guile process
being debugged.

So scmpp.scm teaches GDB about Guile’s type tagging so that it can print
‘SCM’ values.

A decade ago or so, an SCM value printer was available in GDB itself
(with ‘set language scheme’).  But that was tricky C code, and since it
was maintained outside of Guile, it inevitably went out of sync.

The good thing is that scmpp.scm can be maintained within Guile itself.
This one is for Guile 2.0, but it shouldn’t be difficult to adjust it
to 2.2.

The printing-value code in scmpp.scm uses a tailored pattern matcher
that makes the bit-fiddling code easier to read.  Furthermore, it can
use one of two back-ends: GDB, or the FFI.  The GDB back-end fiddles
with values from an inferior process, while the FFI back-end touches
values of the running process.

The whole point of the FFI back-end is to allow for testing: we can run
a test suite for the SCM-decoding code without having to run GDB itself.

There’s also a simple VM stack walker at the end of the file, which is
quite handy.  When GDB stack filters are supported, we might be able to
arrange so that ‘bt’ shows both stacks interleaved.

Happy hacking, and happy birthday Guile 2.0!

Thanks,
Ludo’.

[0] http://lists.gnu.org/archive/html/guile-user/2014-02/msg00008.html

-------------- next part --------------
A non-text attachment was scrubbed...
Name: scmpp.scm
Type: text/x-scheme-src
Size: 21913 bytes
Desc: the code!
URL: <http://sourceware.org/pipermail/gdb/attachments/20140216/377daf49/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/gdb/attachments/20140216/377daf49/attachment.sig>


More information about the Gdb mailing list