New symbolic debugger support in Allegro CL 8.1

The Allegro CL gdb interface is a mixture of gdb call commands and other low-level gdb commands to produce debugging output useful for lisp debugging. Some other debuggers, such as the dbx that is available on Tru64 alpha system, and windbg on XP systems, also provide a call command (it is called .call on windbg) and can thus also be used with this interface.

You must be familiar with these products to use them properly. We are not providing instructions here on how they work. The interface is not supported on all platforms. At the moment, it has been tested on the following:

  • linux (x86 and amd64)
  • freebsd (x86)
  • Tru64 (32 and 64-bit, dbx only)
  • Windows XP/64 (windbg .call instruction)
  • Solaris (sparc 32-bit only, dbx only)
  • MacOSX (intel 32-bit only)

The interface is available in Allegro CL 8.1.

The interface is described in gdb (or dbx or windbg) interface in debugging.htm. (The link is to the 8.1 documentation.) The example we give here is taken from that section.

The interface has five functions: lisp_output_object (print a representation of an object), lisp_zo (a :zoom like function), lisp_cur (a :current like function), lisp_up and lisp_dn (:dn and :up like functions). There are also two variables: lisp_print_level and lisp_print_length, which control the depth and length of printing.

Here is an example, starting at a prompt on a linux 32-bit lisp:

(gdb) call lisp_zo($ebp,0)
0xbf83a538: <unknown C name>
0xbf83a870: (read-octets <stream: 0x71208f92> nil 0 4096 peek)
0xbf83a8d8: (funcall #'(((method) . device-read) terminal-simple-stream t t t t) <stream: 0x71208f92> nil 0 nil peek)
0xbf83a958: (funcall #'(((internal) (((#))) . t) . 0) <stream: 0x71208f92> nil 0 nil peek)
0xbf83a9a0: (erroring-device-read <stream: 0x71208f92> nil 0 nil peek)
0xbf83aa38: #'(((efft) . dc-read-char) . latin1-base)
0xbf83aa90: (simple-stream-peek-char nil <stream: 0x71208f92> nil eof)
0xbf83aae8: (peek-char nil <stream: 0x71208f92> nil eof)
0xbf83ab28: (peek-char-non-whitespace <stream: 0x71208f92>)
0xbf83ac68: (read-top-level-command <stream: 0x71208f92>)
0xbf83af40: (read-eval-print-one-command nil nil)
0xbf83b2a0: (read-eval-print-loop continue-error-string nil condition <standard-instance: 0x71a9b802>)
0xbf83b560: (internal-invoke-debugger "Error" <standard-instance: 0x71a9b802> t)
0xbf83b640: (error <standard-instance: 0x71a9b802>)
0xbf83b8b8: (unbound-variable-handler a)
0xbf83b900: (general-error-handler 5 a t t)
0xbf83b938: (cer-general-error-handler-one 5 a)
0xbf83ba08: rs: stopped at "unbound+158"
0xbf83bab0: (%eval a)
0xbf83bb20: (eval a)
0xbf83bdf8: (read-eval-print-one-command nil nil)
0xbf83c158: (read-eval-print-loop level 0)
0xbf83c1d0: (top-level-read-eval-print-loop1)
0xbf83c228: (top-level-read-eval-print-loop)
0xbf83c270: rs: stopped at "apply+311"
0xbf83c300: (start-interactive-top-level <stream: 0x71208f92> 
    #'top-level-read-eval-print-loop nil)
0xbf83c5a0: (start-lisp-execution t)
0xbf83c5f0: rs: stopped at "apply+311"
0xbf83c6b8: (thread-reset-catcher)
0xbf83c7e8: (setup-required-thread-bindings)
0xbf83c8d8: (run-initial-thread t)
0xbf83c980: (lisp-thread-start #S(thread:0xa0001822 <bad object: 
    0x845972> <bad object: 0x845972> "Initial Lisp Listener" 
    <standard-instance: 
    0x71a6a1e2> nil #'start-lisp-execution-0 (t) nil nil...) 1)
0xbf83c9d8: rs: stopped at "start_reborn_lisp+76"
0xbf83ca48: rs: stopped at "startup_lisp+11"
0xbf83ca68: stopped at "cont_setstack+371"
0xbf83cac0: rs: stopped at "first_lisp_thread_init+274"
0xbf83cb18: stopped at "setupstack_within_xhandler+16"
(gdb) 

We can move down a few frames:

(gdb) call lisp_dn(2)
0xbf83a8d8: (funcall #'(((method) . device-read) terminal-simple-stream t t t t) <stream: 0x71208f92> nil 0 nil peek)
(gdb) call lisp_dn(1)
0xbf83a958: (funcall #'(((internal) (((#))) . t) . 0) <stream: 0x71208f92> nil 0 nil peek)
(gdb) 

Here, we've selected a frame to print, and asked for two frames.

(gdb) call lisp_zo(0xbf83a958,2)
0xbf83a958: (funcall #'(((internal) (((#))) . t) . 0) <stream: 0x71208f92> nil 0 nil peek)
0xbf83a9a0: (erroring-device-read <stream: 0x71208f92> nil 0 nil peek)
(gdb) 

Note above that not all of the first frame's name is printed. If we grab the function object from the frame, print it, and then print it after increasing the lisp_print_level, then we see the whole name:

(gdb) x/16x 0xbf83a958-16
0xbf83a948:	0xfffffffa	0x719ed7f2	0x00000570	0x711d0a42
0xbf83a958:	0xbf83a9a0	0x71259d71	0x71208f92	0x71000685
0xbf83a968:	0x00000000	0x71000685	0x711c48ff	0x00000040
0xbf83a978:	0x71208f92	0xa0001822	0x71000685	0xa0001822
(gdb) call lisp_output_object(0x711d0a42)
#'(((internal) (((#))) . t) . 0)
(gdb) p lisp_print_level
$1 = 5
(gdb) set lisp_print_level=10
(gdb) call lisp_output_object(0x711d0a42)
#'(((internal) (((((effective-method) . 5)))) . t) . 0)
(gdb) 

This example is continued in gdb (or dbx or windbg) interface in debugging.htm. Here we are trying to give a flavor of the interface.

Copyright © 2023 Franz Inc., All Rights Reserved | Privacy Statement Twitter