Changes between Version 4 and Version 5 of CclUnderGdb


Ignore:
Timestamp:
Sep 21, 2008, 12:12:12 AM (11 years ago)
Author:
gz
Comment:

reformat, and add hints for debugging lisp code

Legend:

Unmodified
Added
Removed
Modified
  • CclUnderGdb

    v4 v5  
    11== Running CCL under GDB ==
    22
    3 {{{
    4 > Any tips and tricks to share?
    5 >
    6 > What do I do about segfaults?  What about SIG40?
     3
     4> Any tips and tricks to share?[[br]]
     5> What do I do about segfaults?  What about SIG40?[[br]]
    76
    87You basically want to tell GDB to load (or "source", as a verb) a file
     
    109and defines some macros (most of which have to do with printing
    1110lisp object values)
    12 
     11{{{
    1312(gdb) source ccl/lisp-kernel/linuxx8664/.gdbinint
    14 
     13}}}
    1514That file will be sourced automatically if it (or a link to it)
    1615is in the same directory as the executable (or, IIRC, in your
     
    2120last fall when at least one case was missing from the checked-in
    2221.gdbinit file.  The general idea is to say something like:
    23 
     22{{{
    2423handle SIGQUIT pass nostop noprint
    25 
     24}}}
    2625which tells GDB that if the target process gets a SIGQUIT, it should
    2726let the application handle it (GDB should "pass" it to the application)
     
    3130application.  I sometimes find it useful to be able be able interrupt
    3231the lisp via SIGINT (after entering GDB).  Doing something like
    33 
     32{{{
    3433handle SIGINT pass stop print
    35 
     34}}}
    3635causes GDB to ask for confirmation because "SIGINT is used by the
    3736debugger".  (It's not used in the same way that breakpoints and
     
    3938it the confirmation it craves.)
    4039
    41 As far as other tips and tricks ... I'm not sure what I could
    42 say that'd be meaningful without a long explanation of how the
    43 lisp is implemented.
    44 
    45 <http://ccl.clozure.com/manual/chapter16.html#Implementation-Details-of-CCL>
    46 
    47 actually does explain quite a bit of that.  If you want to use GDB
    48 to step through/set breakpoints in compiled lisp code it's certainly
    49 possible to do that (I do it all the time ...), but explaining the
    50 issues and details might take a while.  (From GDB's point of view,
    51 this is like debugging machine code or debugging C code that you
    52 don't have the source to and don't have symbolic information for;
    53 it's OK at that and there isn't anything better at it widely available
    54 under Linux, but that's not really its primary are of focus.)
    5540
    5641GDB's very good at debugging C code that was compiled with debugging
     
    8772is:
    8873
    89 a) In the kernel debugger do R to display raw (hex) register values
    90   and note the value in RIP (the program counter/instruction pointer.)
    91 b) Drop into GDB (via ^C) and set a breakpoint at that address.
    92   If the address is 0x87654321, the GDB command to set that breakpoint
    93   would be:
     74a) In the kernel debugger do R to display raw (hex) register values and note the value in {{{RIP}}} (the program counter/instruction pointer.)
    9475
     76b) Drop into GDB (via !^C) and set a breakpoint at that address.
     77If the address is 0x87654321, the GDB command to set that breakpoint
     78would be:
     79{{{
    9580(gdb) br *0x87654321
    96 
    97   The leading asterisk is necessary to prevent GDB from interpreting
    98   the integer as a line number.
     81}}}
     82The leading asterisk is necessary to prevent GDB from interpreting
     83the integer as a line number.
    9984
    10085c)  Tell GDB to let the interrupted process continue
    101 
     86{{{
    10287(gdb) continue
    103 
    104    The kernel debugger will likely still be waiting for input.
    105    All other lisp threads should be suspended.
     88}}}
     89The kernel debugger will likely still be waiting for input.
     90All other lisp threads should be suspended.
    10691
    10792d)  In the kernel debugger, use the "x" command, which exits
    108    from the kernel debugger resumes other threads.
     93from the kernel debugger resumes other threads.
    10994
    11095The next time any thread reaches the address of the breakpoint,
     
    11297that reaches that point will be the one that got the exception,
    11398but it's usually very likely (other threads usually require some
    114 time to wake up after being uspended.)
     99time to wake up after being suspended.)
    115100
    116101In GDB at that point,
    117 
     102{{{
    118103(gdb) bt
    119 
     104}}}
    120105will do a backtrace (at least as far back as the foreign function
    121106call from lisp)
    122 
     107{{{
    123108(gdb) info regs
    124 
     109}}}
    125110will show register values.
    126111
     
    134119more quickly than you would otherwise.
    135120
     121
     122As far as other tips and tricks ... I'm not sure what I could
     123say that'd be meaningful without a long explanation of how the
     124lisp is implemented.
     125[http://ccl.clozure.com/manual/chapter16.html#Implementation-Details-of-CCL The manual]
     126actually does explain quite a bit of that.  If you want to use GDB
     127to step through/set breakpoints in compiled lisp code it's certainly
     128possible to do that (I do it all the time ...), but explaining the
     129issues and details might take a while.  (From GDB's point of view,
     130this is like debugging machine code or debugging C code that you
     131don't have the source to and don't have symbolic information for;
     132it's OK at that and there isn't anything better at it widely available
     133under Linux, but that's not really its primary are of focus.)
     134
     135Here are some hints for linuxx8664:
     136
     137To find the address corresponding to a lisp symbol, first tell GDB to call the "find_symbol" function, which walks memory until it finds a symbol with a matching pname and returns the symbol tagged as a vector:
     138{{{
     139(gdb) call find_symbol("FIND-IF-NOT")
     140$1 = 52777632305533
     141}}}
     142You can then look at the slots of the symbol, which are a header followed by the pname, value and function.  You have to subtract the tag from the address returned by find_symbol, which is 13 on x8664:
     143{{{
     144(gdb) x/gx 52777632305533-13  ; subtract fulltag_misc = 13
     1450x300040069170: 0x0000000000000715      ; header
     146(gdb) 0x300040069178:   0x00003000000a995d      ; pname
     147(gdb) 0x300040069180:   0x0000000000000012      ; value
     148(gdb) 0x300040069188:   0x000030004006970f      ; function
     149}}}
     150You can set a breakpoint on entry to the function:
     151{{{
     152(gdb) br *0x000030004006970f
     153}}}
     154Note that you don't need to subtract any tags - the code starts right at the address of the function.
     155
     156To enter GDB when lisp is starting up, set a breakpoint at *_SPfuncall, which is called soon after the image is loaded (and is rarely called thereafter, since funcall is inlined).
     157
     158To cause GC (including the EGC) to run integrity checks on entry, add `-DGC_INTEGRITY_CHECKING` to the CDEFINES in the kernel Makefile and rebuild the kernel.  Alternately you can `(setq ccl::*gc-event-status-bits* 4)` at any time for the same effect.
     159
     160If you look at the .gdbinit file, there are a number of useful lisp-related commands defined there.  Try them...
     161