[Magic-dev] RE: gdb & ddd
R. Timothy Edwards
tim at stravinsky.jhuapl.edu
Sun May 16 16:57:22 EDT 2004
Dear Charles,
> At this point, I want to try to break at the main loop that services
> commands so I can loop at execution of things like box, paint and
> others. But, unfortunately, my notes (normally quite good) leave out
> this all-important last step.
>
> Additionally, I would like to step through the startup code again in
> main.c that services initbeforeargs, doargs and initafterargs.
>
> I am hoping you might be willing to process a paragraph or so and help
> me get back to where I can single step through magic with ddd.
A "better" way to debug the Tcl/Tk-based version of magic 7.2/7.3
(at least with gdb; I don't know if this works with ddd) was taught
me by Stefan Jones: Run magic as usual in one terminal. Then, in
another terminal (although it's probably okay to background magic
and do this in the same terminal):
ps -C wish (returns the process ID <pid> of "magic")
gdb wish
attach <pid> (insert the process ID from the "ps" command)
If the first statement seems odd, it's because magic is an extension
of Tcl, so the actual executable being run is "wish". "magic" itself
is a shell script.
Because magic has already started up by the time you run "gdb",
this method won't allow you to break on the startup procedures like
"mainInitBeforeArgs()", for which you have to revert to the original,
more painstaking method.
To break on specific commands in magic, the best entry point is
probably where the command is called, which is in the commands/
subdirectory and has the routine name Cmd<cmd_name>, where <cmd_name>
is capitalized, as in CmdBox() or CmdGetnode(). Above that level,
there's the level where magic hooks into Tcl, and that's all
defined in tcltk/tclmagic.c (previously found in the magic/
subdirectory). The first hook is _tcl_dispatch(), which is the
routine that Tcl is told to call when encountering a magic
command. That in turn calls TxTclDispatch(), which is defined
in textio/TxCommands.c.
Because the Tcl version of magic is not a standalone executable,
it does not have a main() routine. Its entry point is
Tclmagic_Init() in tcltk/tclmagic.c. This routine actually does
very little; mostly what it does is to define two Tcl commands
"magic::initialize" (calls _magic_initialize()) and
"magic::startup" (calls _magic_startup()) which start the program.
The routine _magic_initialize() calls the magic internal routines
mainInitBeforeArgs(), mainDoArgs(), and mainInitAfterArgs(), while
the routine _magic_startup() calls mainInitFinal(). The reason
that there are two routines is that anything that goes wrong in
_magic_initialize() will prevent magic from starting, whereas
anything that goes wrong in mainInitFinal() won't. For instance,
mainInitFinal() reads in the system and the user's ".magic" files.
There are some notes on the website outlining how you can
get gdb/ddd to break in the initialization routines. The boot-
strapping problem is that you have to load the "tclmagic.so"
file before the debugger knows any of the subroutine names or
entry points for the magic code. If you can't get this to work,
let me know, and I can give a more detailed answer.
Regards,
Tim
More information about the magic-dev
mailing list