[Ecls-list] Debugging compiled code

Juan Jose Garcia-Ripoll worm at arrakis.es
Thu Jan 15 06:19:01 UTC 2004


On Thursday 15 January 2004 14:54, Frederik Fouvry wrote:
> BTW: any hints on debugging (e.g. function calls) apart from the
> artisanal format(), print() and friends?

Are you debugging ECL itself, or some _compiled_ code of your own? If this is 
the case, aside from the usual TRACE and STEP (which only work well with 
interpreted code), GDB is your friend. You can call lisp routines from it. 
For instance, if I am debugging MERGE-PATHNAMES I would set a breakpoint, run 
GDB until it hits it and then maybe inspect the arguments to it. A sample 
session from real life:

--------------------
(gdb) break cl_merge_pathnames
Breakpoint 10 at 0x8077a99: file pathname.d, line 949.
(gdb) run
`/home/jlr/src/ecls-new/build/ecl_min' has changed; re-reading symbols.
Breakpoint 1 at 0x8081b38: file num_sfun.d, line 323.
Breakpoint 10 at 0x8077aa9: file pathname.d, line 949.
;*** Lisp core booted ****
ECLS (Embeddable Common Lisp)  16384 pages
> (load "bare.lsp")
Breakpoint 10, cl_merge_pathnames (narg=1, path=0x80f8c40) at pathname.d:949
(gdb) call cl_print(1, path)
#P"bare.lsp"$1 = (union cl_lispunion *) 0x80f8c40
(gdb) call cl_print(1,path->pathname.name)
"bare"$2 = (union cl_lispunion *) 0x8159de0
------------------

What I also do is insert calls to some useless function (For instance COS) in 
my lisp code, compile it, and then, within GDB, set a breakpoint on that 
function. To debug a lisp function that has been compiled, you will need to 
preserve the C source files. This is a toy session: I first wrote the file 
foo.lsp
----------- foo.lsp
(eval-when (compile)
  (proclaim '(notinline cos)))

(defparameter *foo* 42)

(defun bar ()
  (let ((*foo* 42))
    (cos 1.0)
    (print *foo*)))
------------foo.lsp

Then I compiled it from ECL:

----------- Compiling the file
jlr at mpq3p32:~/src/ecls-new/build> ecl

ECL (Embeddable Common-Lisp) 0.9d
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2000 Juan J. Garcia-Ripoll
	ECL is free software, and you are welcome to redistribute it
under certain conditions; see file 'Copyright' for details.
Type :h for Help.  Top level.
> (compile-file "foo.lsp" :c-file t)
;;; Loading "/home/jlr/lib/ecl/cmp.fas"
;;; Loading "/home/jlr/lib/ecl/sysfun.lsp"
;;; Compiling foo.lsp.
;;; Compiling (EVAL-WHEN (COMPILE) ...).
;;; Compiling (PROGN (SI:*MAKE-SPECIAL '*FOO*) ...).
;;; Compiling (SETQ *FOO* ...).
;;; The variable *FOO* is undefined.
;;; The compiler will assume this variable is a global.
;;; Compiling (EVAL-WHEN (COMPILE) ...).
;;; Compiling (DEFUN BAR ...).
;;; End of Pass 1.  
;;; Emitting code for BAR.
;;; Compiling (DEFUN BAR).
;;; Warning: Emitting linking call for COS
;;; Calling the C compiler... 
;;; Invoking external command: gcc -g -O2 -fPIC -fstrict-aliasing -Dlinux -O 
-I/home/jlr/lib/ecl//h -w -c foo.c -o foo.o
;;; Invoking external command: gcc -o foo.fas -L/home/jlr/lib/ecl/ foo.o  
-Wl,--rpath,/home/jlr/lib/ecl/ -shared   -lecl -ldl -lm
;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3
;;; Finished compiling foo.lsp.
#P"foo.fas"
Top level.
-----------------

And finally I debugged this module file. Notice the "break main". GDB does not 
let us set breakpoints on the function cl_cos() which is on the libecl.so 
library, because it is not loaded until we run the program. This is a minor 
inconvenience which I do not know how to solve:

------------------
(gdb) delete break
(gdb) break main
Breakpoint 8 at 0x8048625: file ecl.c, line 47.
(gdb) run
Starting program: /home/jlr/src/ecls-new/build/ecl 

Breakpoint 8, main (argc=1, argv=0xbffff6c4) at ecl.c:47
47	ecl.c: No such file or directory.
	in ecl.c
(gdb) break cl_cos
Breakpoint 9 at 0x400a4d58: file num_sfun.d, line 323.
(gdb) cont
Continuing.

ECL (Embeddable Common-Lisp) 0.9d
Copyright (C) 1984 Taiichi Yuasa and Masami Hagiya
Copyright (C) 1993 Giuseppe Attardi
Copyright (C) 2000 Juan J. Garcia-Ripoll
	ECL is free software, and you are welcome to redistribute it
under certain conditions; see file 'Copyright' for details.
Type :h for Help.  Top level.
> (load "foo")
;;; Loading "foo.fas"
#P"foo.fas"
Top level.
> (bar)

Breakpoint 9, cl_cos (x=0x812afe0) at num_sfun.d:323
(gdb) up
#1  0x400a15d8 in APPLY_fixed (n=135442400, fn=0x400a4d40 <cl_cos>, 
x=0x808c000)
    at apply.d:677
(gdb) 
#2  0x4003bdc7 in link_call (sym=0x400fefa8, pLK=0x40118abc, cblock=0x80ea690, 
narg=1, 
    args=0xbffff3a0) at eval.d:129
(gdb) up
#3  0x4011799d in LKF0 (narg=1) at foo.c:18
(gdb) l
13		value0=print(MAKE_FIXNUM(42),Cnil); NVALUES=1;
14		return value0;
15		}
16		}
17	}
18	static cl_object LKF0(int narg, ...) {TRAMPOLINK(narg,((cl_object)
(cl_symbols+255)),&LK0,Cblock);}
19		
20	#include "foo.data"
21	#ifdef __cplusplus
22	extern "C"
(gdb) up
#4  0x4011792a in L1 (narg=0) at foo.c:12
(gdb) l
7		cl_object value0;
8		check_arg(0);
9		{
10	TTL:
11		{cl_object V1;                            /*  *FOO*           */
12		(void)(*LK0)(1,VV[1])                     /*  COS             */;
13		value0=print(MAKE_FIXNUM(42),Cnil); NVALUES=1;
14		return value0;
15		}
16		}

---------------------

I must admit it is a bit uncomfortable, but I do not know enough of GDB so as 
to write a better interface. This could be a nice project for people out 
there.

Regard,

Juanjo





More information about the ecl-devel mailing list