Posted to tcl by miguel at Sun Mar 27 12:05:31 GMT 2011view pretty

** run the patched-to-crash
** patch -p0 < tclCrash.diff
** cd unix
** ./configure --disable-shared --enable-symbols
** make

** Now let us crash it and get a dump

mig@ant:/home/fossil/tcl-core/trunk/unix$ ulimit -c unlimited
mig@ant:/home/fossil/tcl-core/trunk/unix$ ./tclsh
% proc a {} {tailcall a}; a
FOO!
Aborted (core dumped)

mig@ant:/home/fossil/tcl-core/trunk/unix$ gdb ./tclsh core
...
Core was generated by `./tclsh'.
Program terminated with signal 6, Aborted.
#0  0x00212832 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2

** let me see the C call stack
(gdb) bt 10
#0  0x00212832 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x00c0a651 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0x00c0da82 in *__GI_abort () at abort.c:92
#3  0x0807343d in Tcl_PanicVA (format=0x8195dd0 "FOO!", 
    argList=0xbf9a3534 "\364\217\032\bx5\232\277\210\205\r\b\036\b\002")
    at /home/fossil/tcl-core/trunk/generic/tclPanic.c:115
#4  0x0807345b in Tcl_Panic (format=0x8195dd0 "FOO!") at /home/fossil/tcl-core/trunk/generic/tclPanic.c:144
#5  0x080d6223 in TclNRRunCallbacks (interp=0x81e8fc8, result=2, rootPtr=0x0)
    at /home/fossil/tcl-core/trunk/generic/tclBasic.c:4330
#6  0x080d8588 in TclEvalObjEx (interp=0x81e8fc8, objPtr=0x6, flags=131072, invoker=0x0, word=0)
    at /home/fossil/tcl-core/trunk/generic/tclBasic.c:5907
#7  0x080d8527 in Tcl_EvalObjEx (interp=0x81e8fc8, objPtr=0x6, flags=131072)
    at /home/fossil/tcl-core/trunk/generic/tclBasic.c:5888
#8  0x081632aa in Tcl_RecordAndEvalObj (interp=0x81e8fc8, cmdPtr=0x81ef898, flags=131072)
    at /home/fossil/tcl-core/trunk/generic/tclHistory.c:190
#9  0x08068740 in Tcl_MainEx (argc=-1, argv=0xbf9a3798, appInitProc=0x804b4e2 <Tcl_AppInit>, interp=0x81e8fc8)
    at /home/fossil/tcl-core/trunk/generic/tclMain.c:515
(More stack frames follow...)

** Let's get to where I can look at the NRE stack!
(gdb) f 5
#5  0x080d6223 in TclNRRunCallbacks (interp=0x81e8fc8, result=2, rootPtr=0x0)
    at /home/fossil/tcl-core/trunk/generic/tclBasic.c:4330
4330	            Tcl_Panic("FOO!");

** ... and start navigating it
(gdb) p *callbackPtr
$1 = {procPtr = 0x814b734 <TEBCresume>, data = {0x81f00f0, 0x1, 0x0, 0x821e270}, nextPtr = 0x821e0d8}
** ... OK, we are running some bytecode, this is the BC engine cleanup callback

(gdb) p *callbackPtr->nextPtr
$2 = {procPtr = 0x807d752 <InterpProcNR2>, data = {0x81efe50, 0x807db0f, 0x0, 0x0}, nextPtr = 0x821dec8}
** ... aha, it is the body of a proc, this is the proc cleanup callback

(gdb) p *callbackPtr->nextPtr->nextPtr
$3 = {procPtr = 0x80d6742 <TEOV_Exception>, data = {0x0, 0x0, 0x0, 0x0}, nextPtr = 0x821df70}
(gdb) p *callbackPtr->nextPtr->nextPtr->nextPtr
$4 = {procPtr = 0x80d67c7 <TEOV_Error>, data = {0x1, 0x823b8f0, 0x0, 0x0}, nextPtr = 0x81ef9d0}
** ... thes are TclNREvalObjv cleanup

(gdb) p *callbackPtr->nextPtr->nextPtr->nextPtr->nextPtr
$5 = {procPtr = 0x80db84f <TailcallCleanup>, data = {0x81ef9b8, 0x821e1c8, 0x0, 0x0}, nextPtr = 0x821d8f8}
** ... this identifies that we are in a tailcall - shoot, that will make it harder :(

(gdb) p *callbackPtr->nextPtr->nextPtr->nextPtr->nextPtr->nextPtr
$6 = {procPtr = 0x80d62dc <NRCommand>, data = {0x8236bd8, 0x0, 0x0, 0x0}, nextPtr = 0x821dee0}
** ... AHA! Finally, the command cleanup! Now we'll know what was really happening there

** ... so the Command is ...
(gdb) p *(Command *)callbackPtr->nextPtr->nextPtr->nextPtr->nextPtr->nextPtr->data[0]
$7 = {hPtr = 0x824e8c8, nsPtr = 0x81e35c0, refCount = 3, cmdEpoch = 0, compileProc = 0, 
  objProc = 0x807d555 <TclObjInterpProc>, objClientData = 0x8235358, 
  proc = 0x80d3a90 <TclInvokeObjectCommand>, clientData = 0x8236bd8, 
  deleteProc = 0x807dbb1 <TclProcDeleteProc>, deleteData = 0x8235358, flags = 0, importRefPtr = 0x0, 
  tracePtr = 0x0, nreProc = 0x807d597 <TclNRInterpProc>}

** a proc! Which one? Now I can look at body, name, etc ...
(gdb) p *(Proc *) ((Command *)callbackPtr->nextPtr->nextPtr->nextPtr->nextPtr->nextPtr->data[0])->objClientData
$8 = {iPtr = 0x81e8fc8, refCount = 2, cmdPtr = 0x8236bd8, bodyPtr = 0x821e240, numArgs = 0, 
  numCompiledLocals = 0, firstLocalPtr = 0x0, lastLocalPtr = 0x0}
(gdb) p *((Command *)callbackPtr->nextPtr->nextPtr->nextPtr->nextPtr->nextPtr->data[0])->hPtr$9 = {nextPtr = 0x81e9e88, tablePtr = 0x81e3620, hash = 0x61, clientData = 0x8236bd8, key = {
    oneWordValue = 0x61 <Address 0x61 out of bounds>, objPtr = 0x61, words = {97}, string = "a"}}
(gdb)