mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-29 07:58:28 +00:00
637 lines
25 KiB
Plaintext
637 lines
25 KiB
Plaintext
Debugging GNU Emacs
|
|
Copyright (c) 1985, 2000, 2001 Free Software Foundation, Inc.
|
|
|
|
Permission is granted to anyone to make or distribute verbatim copies
|
|
of this document as received, in any medium, provided that the
|
|
copyright notice and permission notice are preserved,
|
|
and that the distributor grants the recipient permission
|
|
for further redistribution as permitted by this notice.
|
|
|
|
Permission is granted to distribute modified versions
|
|
of this document, or of portions of it,
|
|
under the above conditions, provided also that they
|
|
carry prominent notices stating who last changed them.
|
|
|
|
[People who debug Emacs on Windows using native Windows debuggers
|
|
should read the Windows-specific section near the end of this
|
|
document.]
|
|
|
|
** When you debug Emacs with GDB, you should start it in the directory
|
|
where you built Emacs. That directory has a .gdbinit file that defines
|
|
various "user-defined" commands for debugging Emacs.
|
|
|
|
** It is a good idea to run Emacs under GDB (or some other suitable
|
|
debugger) *all the time*. Then, when Emacs crashes, you will be able
|
|
to debug the live process, not just a core dump. (This is especially
|
|
important on systems which don't support core files, and instead print
|
|
just the registers and some stack addresses.)
|
|
|
|
** If Emacs hangs, or seems to be stuck in some infinite loop, typing
|
|
"kill -TSTP PID", where PID is the Emacs process ID, will cause GDB to
|
|
kick in, provided that you run under GDB.
|
|
|
|
** Getting control to the debugger
|
|
|
|
`Fsignal' is a very useful place to put a breakpoint in.
|
|
All Lisp errors go through there.
|
|
|
|
It is useful, when debugging, to have a guaranteed way to return to
|
|
the debugger at any time. When using X, this is easy: type C-z at the
|
|
window where Emacs is running under GDB, and it will stop Emacs just
|
|
as it would stop any ordinary program. When Emacs is running in a
|
|
terminal, things are not so easy.
|
|
|
|
The src/.gdbinit file in the Emacs distribution arranges for SIGINT
|
|
(C-g in Emacs) to be passed to Emacs and not give control back to GDB.
|
|
On modern POSIX systems, you can override that with this command:
|
|
|
|
handle SIGINT stop nopass
|
|
|
|
After this `handle' command, SIGINT will return control to GDB. If
|
|
you want the C-g to cause a QUIT within Emacs as well, omit the
|
|
`nopass'.
|
|
|
|
A technique that can work when `handle SIGINT' does not is to store
|
|
the code for some character into the variable stop_character. Thus,
|
|
|
|
set stop_character = 29
|
|
|
|
makes Control-] (decimal code 29) the stop character.
|
|
Typing Control-] will cause immediate stop. You cannot
|
|
use the set command until the inferior process has been started.
|
|
Put a breakpoint early in `main', or suspend the Emacs,
|
|
to get an opportunity to do the set command.
|
|
|
|
** Examining Lisp object values.
|
|
|
|
When you have a live process to debug, and it has not encountered a
|
|
fatal error, you can use the GDB command `pr'. First print the value
|
|
in the ordinary way, with the `p' command. Then type `pr' with no
|
|
arguments. This calls a subroutine which uses the Lisp printer.
|
|
|
|
Note: It is not a good idea to try `pr' if you know that Emacs is in
|
|
deep trouble: its stack smashed (e.g., if it encountered SIGSEGV due
|
|
to stack overflow), or crucial data structures, such as `obarray',
|
|
corrupted, etc. In such cases, the Emacs subroutine called by `pr'
|
|
might make more damage, like overwrite some data that is important for
|
|
debugging the original problem.
|
|
|
|
Also, on some systems it is impossible to use `pr' if you stopped
|
|
Emacs while it was inside `select'. This is in fact what happens if
|
|
you stop Emacs while it is waiting. In such a situation, don't try to
|
|
use `pr'. Instead, use `s' to step out of the system call. Then
|
|
Emacs will be between instructions and capable of handling `pr'.
|
|
|
|
If you can't use `pr' command, for whatever reason, you can fall back
|
|
on lower-level commands. Use the `xtype' command to print out the
|
|
data type of the last data value. Once you know the data type, use
|
|
the command that corresponds to that type. Here are these commands:
|
|
|
|
xint xptr xwindow xmarker xoverlay xmiscfree xintfwd xboolfwd xobjfwd
|
|
xbufobjfwd xkbobjfwd xbuflocal xbuffer xsymbol xstring xvector xframe
|
|
xwinconfig xcompiled xcons xcar xcdr xsubr xprocess xfloat xscrollbar
|
|
|
|
Each one of them applies to a certain type or class of types.
|
|
(Some of these types are not visible in Lisp, because they exist only
|
|
internally.)
|
|
|
|
Each x... command prints some information about the value, and
|
|
produces a GDB value (subsequently available in $) through which you
|
|
can get at the rest of the contents.
|
|
|
|
In general, most of the rest of the contents will be additional Lisp
|
|
objects which you can examine in turn with the x... commands.
|
|
|
|
Even with a live process, these x... commands are useful for
|
|
examining the fields in a buffer, window, process, frame or marker.
|
|
Here's an example using concepts explained in the node "Value History"
|
|
of the GDB manual to print the variable frame from this line in
|
|
xmenu.c:
|
|
|
|
buf.frame_or_window = frame;
|
|
|
|
First, use these commands:
|
|
|
|
cd src
|
|
gdb emacs
|
|
b xmenu.c:1296
|
|
r -q
|
|
|
|
Then type C-x 5 2 to create a new frame, and it hits the breakpoint:
|
|
|
|
(gdb) p frame
|
|
$1 = 1077872640
|
|
(gdb) xtype
|
|
Lisp_Vectorlike
|
|
PVEC_FRAME
|
|
(gdb) xframe
|
|
$2 = (struct frame *) 0x3f0800
|
|
(gdb) p *$
|
|
$3 = {
|
|
size = 536871989,
|
|
next = 0x366240,
|
|
name = 809661752,
|
|
[...]
|
|
}
|
|
(gdb) p $3->name
|
|
$4 = 809661752
|
|
|
|
Now we can use `pr' to print the name of the frame:
|
|
|
|
(gdb) pr
|
|
"emacs@steenrod.math.nwu.edu"
|
|
|
|
The Emacs C code heavily uses macros defined in lisp.h. So suppose
|
|
we want the address of the l-value expression near the bottom of
|
|
`add_command_key' from keyboard.c:
|
|
|
|
XVECTOR (this_command_keys)->contents[this_command_key_count++] = key;
|
|
|
|
XVECTOR is a macro, and therefore GDB does not know about it.
|
|
GDB cannot evaluate "p XVECTOR (this_command_keys)".
|
|
|
|
However, you can use the xvector command in GDB to get the same
|
|
result. Here is how:
|
|
|
|
(gdb) p this_command_keys
|
|
$1 = 1078005760
|
|
(gdb) xvector
|
|
$2 = (struct Lisp_Vector *) 0x411000
|
|
0
|
|
(gdb) p $->contents[this_command_key_count]
|
|
$3 = 1077872640
|
|
(gdb) p &$
|
|
$4 = (int *) 0x411008
|
|
|
|
Here's a related example of macros and the GDB `define' command.
|
|
There are many Lisp vectors such as `recent_keys', which contains the
|
|
last 100 keystrokes. We can print this Lisp vector
|
|
|
|
p recent_keys
|
|
pr
|
|
|
|
But this may be inconvenient, since `recent_keys' is much more verbose
|
|
than `C-h l'. We might want to print only the last 10 elements of
|
|
this vector. `recent_keys' is updated in keyboard.c by the command
|
|
|
|
XVECTOR (recent_keys)->contents[recent_keys_index] = c;
|
|
|
|
So we define a GDB command `xvector-elts', so the last 10 keystrokes
|
|
are printed by
|
|
|
|
xvector-elts recent_keys recent_keys_index 10
|
|
|
|
where you can define xvector-elts as follows:
|
|
|
|
define xvector-elts
|
|
set $i = 0
|
|
p $arg0
|
|
xvector
|
|
set $foo = $
|
|
while $i < $arg2
|
|
p $foo->contents[$arg1-($i++)]
|
|
pr
|
|
end
|
|
document xvector-elts
|
|
Prints a range of elements of a Lisp vector.
|
|
xvector-elts v n i
|
|
prints `i' elements of the vector `v' ending at the index `n'.
|
|
end
|
|
|
|
** Getting Lisp-level backtrace information within GDB
|
|
|
|
The most convenient way is to use the `xbacktrace' command. This
|
|
shows the names of the Lisp functions that are currently active.
|
|
|
|
If that doesn't work (e.g., because the `backtrace_list' structure is
|
|
corrupted), type "bt" at the GDB prompt, to produce the C-level
|
|
backtrace, and look for stack frames that call Ffuncall. Select them
|
|
one by one in GDB, by typing "up N", where N is the appropriate number
|
|
of frames to go up, and in each frame that calls Ffuncall type this:
|
|
|
|
p *args
|
|
pr
|
|
|
|
This will print the name of the Lisp function called by that level
|
|
of function calling.
|
|
|
|
By printing the remaining elements of args, you can see the argument
|
|
values. Here's how to print the first argument:
|
|
|
|
p args[1]
|
|
pr
|
|
|
|
If you do not have a live process, you can use xtype and the other
|
|
x... commands such as xsymbol to get such information, albeit less
|
|
conveniently. For example:
|
|
|
|
p *args
|
|
xtype
|
|
|
|
and, assuming that "xtype" says that args[0] is a symbol:
|
|
|
|
xsymbol
|
|
|
|
** Debugging what happens while preloading and dumping Emacs
|
|
|
|
Type `gdb temacs' and start it with `r -batch -l loadup dump'.
|
|
|
|
If temacs actually succeeds when running under GDB in this way, do not
|
|
try to run the dumped Emacs, because it was dumped with the GDB
|
|
breakpoints in it.
|
|
|
|
** Debugging `temacs'
|
|
|
|
Debugging `temacs' is useful when you want to establish whether a
|
|
problem happens in an undumped Emacs. To run `temacs' under a
|
|
debugger, type "gdb temacs", then start it with `r -batch -l loadup'.
|
|
|
|
** If you encounter X protocol errors
|
|
|
|
Try evaluating (x-synchronize t). That puts Emacs into synchronous
|
|
mode, where each Xlib call checks for errors before it returns. This
|
|
mode is much slower, but when you get an error, you will see exactly
|
|
which call really caused the error.
|
|
|
|
You can start Emacs in a synchronous mode by invoking it with the -xrm
|
|
option, like this:
|
|
|
|
emacs -xrm "emacs.synchronous: true"
|
|
|
|
Setting a breakpoint in the function `x_error_quitter' and looking at
|
|
the backtrace when Emacs stops inside that function will show what
|
|
code causes the X protocol errors.
|
|
|
|
Some bugs related to the X protocol disappear when Emacs runs in a
|
|
synchronous mode. To track down those bugs, we suggest the following
|
|
procedure:
|
|
|
|
- Run Emacs under a debugger and put a breakpoint inside the
|
|
primitive function which, when called from Lisp, triggers the X
|
|
protocol errors. For example, if the errors happen when you
|
|
delete a frame, put a breakpoint inside `Fdelete_frame'.
|
|
|
|
- When the breakpoint breaks, step through the code, looking for
|
|
calls to X functions (the ones whose names begin with "X" or
|
|
"Xt" or "Xm").
|
|
|
|
- Insert calls to `XSync' before and after each call to the X
|
|
functions, like this:
|
|
|
|
XSync (f->output_data.x->display_info->display, 0);
|
|
|
|
where `f' is the pointer to the `struct frame' of the selected
|
|
frame, normally available via XFRAME (selected_frame). (Most
|
|
functions which call X already have some variable that holds the
|
|
pointer to the frame, perhaps called `f' or `sf', so you shouldn't
|
|
need to compute it.)
|
|
|
|
If your debugger can call functions in the program being debugged,
|
|
you should be able to issue the calls to `XSync' without recompiling
|
|
Emacs. For example, with GDB, just type:
|
|
|
|
call XSync (f->output_data.x->display_info->display, 0)
|
|
|
|
before and immediately after the suspect X calls. If your
|
|
debugger does not support this, you will need to add these pairs
|
|
of calls in the source and rebuild Emacs.
|
|
|
|
Either way, systematically step through the code and issue these
|
|
calls until you find the first X function called by Emacs after
|
|
which a call to `XSync' winds up in the function
|
|
`x_error_quitter'. The first X function call for which this
|
|
happens is the one that generated the X protocol error.
|
|
|
|
- You should now look around this offending X call and try to figure
|
|
out what is wrong with it.
|
|
|
|
** If the symptom of the bug is that Emacs fails to respond
|
|
|
|
Don't assume Emacs is `hung'--it may instead be in an infinite loop.
|
|
To find out which, make the problem happen under GDB and stop Emacs
|
|
once it is not responding. (If Emacs is using X Windows directly, you
|
|
can stop Emacs by typing C-z at the GDB job.) Then try stepping with
|
|
`step'. If Emacs is hung, the `step' command won't return. If it is
|
|
looping, `step' will return.
|
|
|
|
If this shows Emacs is hung in a system call, stop it again and
|
|
examine the arguments of the call. If you report the bug, it is very
|
|
important to state exactly where in the source the system call is, and
|
|
what the arguments are.
|
|
|
|
If Emacs is in an infinite loop, try to determine where the loop
|
|
starts and ends. The easiest way to do this is to use the GDB command
|
|
`finish'. Each time you use it, Emacs resumes execution until it
|
|
exits one stack frame. Keep typing `finish' until it doesn't
|
|
return--that means the infinite loop is in the stack frame which you
|
|
just tried to finish.
|
|
|
|
Stop Emacs again, and use `finish' repeatedly again until you get back
|
|
to that frame. Then use `next' to step through that frame. By
|
|
stepping, you will see where the loop starts and ends. Also, examine
|
|
the data being used in the loop and try to determine why the loop does
|
|
not exit when it should.
|
|
|
|
** If certain operations in Emacs are slower than they used to be, here
|
|
is some advice for how to find out why.
|
|
|
|
Stop Emacs repeatedly during the slow operation, and make a backtrace
|
|
each time. Compare the backtraces looking for a pattern--a specific
|
|
function that shows up more often than you'd expect.
|
|
|
|
If you don't see a pattern in the C backtraces, get some Lisp
|
|
backtrace information by typing "xbacktrace" or by looking at Ffuncall
|
|
frames (see above), and again look for a pattern.
|
|
|
|
When using X, you can stop Emacs at any time by typing C-z at GDB.
|
|
When not using X, you can do this with C-g. On non-Unix platforms,
|
|
such as MS-DOS, you might need to press C-BREAK instead.
|
|
|
|
** If GDB does not run and your debuggers can't load Emacs.
|
|
|
|
On some systems, no debugger can load Emacs with a symbol table,
|
|
perhaps because they all have fixed limits on the number of symbols
|
|
and Emacs exceeds the limits. Here is a method that can be used
|
|
in such an extremity. Do
|
|
|
|
nm -n temacs > nmout
|
|
strip temacs
|
|
adb temacs
|
|
0xd:i
|
|
0xe:i
|
|
14:i
|
|
17:i
|
|
:r -l loadup (or whatever)
|
|
|
|
It is necessary to refer to the file `nmout' to convert
|
|
numeric addresses into symbols and vice versa.
|
|
|
|
It is useful to be running under a window system.
|
|
Then, if Emacs becomes hopelessly wedged, you can create
|
|
another window to do kill -9 in. kill -ILL is often
|
|
useful too, since that may make Emacs dump core or return
|
|
to adb.
|
|
|
|
|
|
** Debugging incorrect screen updating.
|
|
|
|
To debug Emacs problems that update the screen wrong, it is useful
|
|
to have a record of what input you typed and what Emacs sent to the
|
|
screen. To make these records, do
|
|
|
|
(open-dribble-file "~/.dribble")
|
|
(open-termscript "~/.termscript")
|
|
|
|
The dribble file contains all characters read by Emacs from the
|
|
terminal, and the termscript file contains all characters it sent to
|
|
the terminal. The use of the directory `~/' prevents interference
|
|
with any other user.
|
|
|
|
If you have irreproducible display problems, put those two expressions
|
|
in your ~/.emacs file. When the problem happens, exit the Emacs that
|
|
you were running, kill it, and rename the two files. Then you can start
|
|
another Emacs without clobbering those files, and use it to examine them.
|
|
|
|
An easy way to see if too much text is being redrawn on a terminal is to
|
|
evaluate `(setq inverse-video t)' before you try the operation you think
|
|
will cause too much redrawing. This doesn't refresh the screen, so only
|
|
newly drawn text is in inverse video.
|
|
|
|
The Emacs display code includes special debugging code, but it is
|
|
normally disabled. You can enable it by building Emacs with the
|
|
pre-processing symbol GLYPH_DEBUG defined. Here's one easy way,
|
|
suitable for Unix and GNU systems, to build such a debugging version:
|
|
|
|
MYCPPFLAGS='-DGLYPH_DEBUG=1' make
|
|
|
|
Building Emacs like that activates many assertions which scrutinize
|
|
display code operation more than Emacs does normally. (To see the
|
|
code which tests these assertions, look for calls to the `xassert'
|
|
macros.) Any assertion that is reported to fail should be
|
|
investigated.
|
|
|
|
Building with GLYPH_DEBUG defined also defines several helper
|
|
functions which can help debugging display code. One such function is
|
|
`dump_glyph_matrix'. If you run Emacs under GDB, you can print the
|
|
contents of any glyph matrix by just calling that function with the
|
|
matrix as its argument. For example, the following command will print
|
|
the contents of the current matrix of the window whose pointer is in
|
|
`w':
|
|
|
|
(gdb) p dump_glyph_matrix (w->current_matrix, 2)
|
|
|
|
(The second argument 2 tells dump_glyph_matrix to print the glyphs in
|
|
a long form.) You can dump the selected window's current glyph matrix
|
|
interactively with "M-x dump-glyph-matrix RET"; see the documentation
|
|
of this function for more details.
|
|
|
|
Several more functions for debugging display code are available in
|
|
Emacs compiled with GLYPH_DEBUG defined; type "C-h f dump- TAB" and
|
|
"C-h f trace- TAB" to see the full list.
|
|
|
|
|
|
** Debugging LessTif
|
|
|
|
If you encounter bugs whereby Emacs built with LessTif grabs all mouse
|
|
and keyboard events, or LessTif menus behave weirdly, it might be
|
|
helpful to set the `DEBUGSOURCES' and `DEBUG_FILE' environment
|
|
variables, so that one can see what LessTif was doing at this point.
|
|
For instance
|
|
|
|
export DEBUGSOURCES="RowColumn.c:MenuShell.c:MenuUtil.c"
|
|
export DEBUG_FILE=/usr/tmp/LESSTIF_TRACE
|
|
emacs &
|
|
|
|
causes LessTif to print traces from the three named source files to a
|
|
file in `/usr/tmp' (that file can get pretty large). The above should
|
|
be typed at the shell prompt before invoking Emacs, as shown by the
|
|
last line above.
|
|
|
|
Running GDB from another terminal could also help with such problems.
|
|
You can arrange for GDB to run on one machine, with the Emacs display
|
|
appearing on another. Then, when the bug happens, you can go back to
|
|
the machine where you started GDB and use the debugger from there.
|
|
|
|
|
|
** Debugging problems which happen in GC
|
|
|
|
The array `last_marked' (defined on alloc.c) can be used to display up
|
|
to 500 last objects marked by the garbage collection process.
|
|
Whenever the garbage collector marks a Lisp object, it records the
|
|
pointer to that object in the `last_marked' array. The variable
|
|
`last_marked_index' holds the index into the `last_marked' array one
|
|
place beyond where the pointer to the very last marked object is
|
|
stored.
|
|
|
|
The single most important goal in debugging GC problems is to find the
|
|
Lisp data structure that got corrupted. This is not easy since GC
|
|
changes the tag bits and relocates strings which make it hard to look
|
|
at Lisp objects with commands such as `pr'. It is sometimes necessary
|
|
to convert Lisp_Object variables into pointers to C struct's manually.
|
|
Use the `last_marked' array and the source to reconstruct the sequence
|
|
that objects were marked.
|
|
|
|
Once you discover the corrupted Lisp object or data structure, it is
|
|
useful to look at it in a fresh Emacs session and compare its contents
|
|
with a session that you are debugging.
|
|
|
|
** Debugging problems with non-ASCII characters
|
|
|
|
If you experience problems which seem to be related to non-ASCII
|
|
characters, such as \201 characters appearing in the buffer or in your
|
|
files, set the variable byte-debug-flag to t. This causes Emacs to do
|
|
some extra checks, such as look for broken relations between byte and
|
|
character positions in buffers and strings; the resulting diagnostics
|
|
might pinpoint the cause of the problem.
|
|
|
|
** Debugging the TTY (non-windowed) version
|
|
|
|
The most convenient method of debugging the character-terminal display
|
|
is to do that on a window system such as X. Begin by starting an
|
|
xterm window, then type these commands inside that window:
|
|
|
|
$ tty
|
|
$ echo $TERM
|
|
|
|
Let's say these commands print "/dev/ttyp4" and "xterm", respectively.
|
|
|
|
Now start Emacs (the normal, windowed-display session, i.e. without
|
|
the `-nw' option), and invoke "M-x gdb RET emacs RET" from there. Now
|
|
type these commands at GDB's prompt:
|
|
|
|
(gdb) set args -nw -t /dev/ttyp4
|
|
(gdb) set environment TERM xterm
|
|
(gdb) run
|
|
|
|
The debugged Emacs should now start in no-window mode with its display
|
|
directed to the xterm window you opened above.
|
|
|
|
Similar arrangement is possible on a character terminal by using the
|
|
`screen' package.
|
|
|
|
** Running Emacs built with malloc debugging packages
|
|
|
|
If Emacs exhibits bugs that seem to be related to use of memory
|
|
allocated off the heap, it might be useful to link Emacs with a
|
|
special debugging library, such as Electric Fence (a.k.a. efence) or
|
|
GNU Checker, which helps find such problems.
|
|
|
|
Emacs compiled with such packages might not run without some hacking,
|
|
because Emacs replaces the system's memory allocation functions with
|
|
its own versions, and because the dumping process might be
|
|
incompatible with the way these packages use to track allocated
|
|
memory. Here are some of the changes you might find necessary
|
|
(SYSTEM-NAME and MACHINE-NAME are the names of your OS- and
|
|
CPU-specific headers in the subdirectories of `src'):
|
|
|
|
- In src/s/SYSTEM-NAME.h add "#define SYSTEM_MALLOC".
|
|
|
|
- In src/m/MACHINE-NAME.h add "#define CANNOT_DUMP" and
|
|
"#define CANNOT_UNEXEC".
|
|
|
|
- Configure with a different --prefix= option. If you use GCC,
|
|
version 2.7.2 is preferred, as some malloc debugging packages
|
|
work a lot better with it than with 2.95 or later versions.
|
|
|
|
- Type "make" then "make -k install".
|
|
|
|
- If required, invoke the package-specific command to prepare
|
|
src/temacs for execution.
|
|
|
|
- cd ..; src/temacs
|
|
|
|
(Note that this runs `temacs' instead of the usual `emacs' executable.
|
|
This avoids problems with dumping Emacs mentioned above.)
|
|
|
|
Some malloc debugging libraries might print lots of false alarms for
|
|
bitfields used by Emacs in some data structures. If you want to get
|
|
rid of the false alarms, you will have to hack the definitions of
|
|
these data structures on the respective headers to remove the `:N'
|
|
bitfield definitions (which will cause each such field to use a full
|
|
int).
|
|
|
|
** Some suggestions for debugging on MS Windows:
|
|
|
|
(written by Marc Fleischeuers, Geoff Voelker and Andrew Innes)
|
|
|
|
To debug Emacs with Microsoft Visual C++, you either start emacs from
|
|
the debugger or attach the debugger to a running emacs process.
|
|
|
|
To start emacs from the debugger, you can use the file bin/debug.bat.
|
|
The Microsoft Developer studio will start and under Project, Settings,
|
|
Debug, General you can set the command-line arguments and Emacs's
|
|
startup directory. Set breakpoints (Edit, Breakpoints) at Fsignal and
|
|
other functions that you want to examine. Run the program (Build,
|
|
Start debug). Emacs will start and the debugger will take control as
|
|
soon as a breakpoint is hit.
|
|
|
|
You can also attach the debugger to an already running Emacs process.
|
|
To do this, start up the Microsoft Developer studio and select Build,
|
|
Start debug, Attach to process. Choose the Emacs process from the
|
|
list. Send a break to the running process (Debug, Break) and you will
|
|
find that execution is halted somewhere in user32.dll. Open the stack
|
|
trace window and go up the stack to w32_msg_pump. Now you can set
|
|
breakpoints in Emacs (Edit, Breakpoints). Continue the running Emacs
|
|
process (Debug, Step out) and control will return to Emacs, until a
|
|
breakpoint is hit.
|
|
|
|
To examine the contents of a Lisp variable, you can use the function
|
|
'debug_print'. Right-click on a variable, select QuickWatch (it has
|
|
an eyeglass symbol on its button in the toolbar), and in the text
|
|
field at the top of the window, place 'debug_print(' and ')' around
|
|
the expression. Press 'Recalculate' and the output is sent to stderr,
|
|
and to the debugger via the OutputDebugString routine. The output
|
|
sent to stderr should be displayed in the console window that was
|
|
opened when the emacs.exe executable was started. The output sent to
|
|
the debugger should be displayed in the 'Debug' pane in the Output
|
|
window. If Emacs was started from the debugger, a console window was
|
|
opened at Emacs' startup; this console window also shows the output of
|
|
'debug_print'.
|
|
|
|
For example, start and run Emacs in the debugger until it is waiting
|
|
for user input. Then click on the `Break' button in the debugger to
|
|
halt execution. Emacs should halt in `ZwUserGetMessage' waiting for
|
|
an input event. Use the `Call Stack' window to select the procedure
|
|
`w32_msp_pump' up the call stack (see below for why you have to do
|
|
this). Open the QuickWatch window and enter
|
|
"debug_print(Vexec_path)". Evaluating this expression will then print
|
|
out the contents of the Lisp variable `exec-path'.
|
|
|
|
If QuickWatch reports that the symbol is unknown, then check the call
|
|
stack in the `Call Stack' window. If the selected frame in the call
|
|
stack is not an Emacs procedure, then the debugger won't recognize
|
|
Emacs symbols. Instead, select a frame that is inside an Emacs
|
|
procedure and try using `debug_print' again.
|
|
|
|
If QuickWatch invokes debug_print but nothing happens, then check the
|
|
thread that is selected in the debugger. If the selected thread is
|
|
not the last thread to run (the "current" thread), then it cannot be
|
|
used to execute debug_print. Use the Debug menu to select the current
|
|
thread and try using debug_print again. Note that the debugger halts
|
|
execution (e.g., due to a breakpoint) in the context of the current
|
|
thread, so this should only be a problem if you've explicitly switched
|
|
threads.
|
|
|
|
It is also possible to keep appropriately masked and typecast Lisp
|
|
symbols in the Watch window, this is more convenient when steeping
|
|
though the code. For instance, on entering apply_lambda, you can
|
|
watch (struct Lisp_Symbol *) (0xfffffff & args[0]).
|
|
|
|
Optimizations often confuse the MS debugger. For example, the
|
|
debugger will sometimes report wrong line numbers, e.g., when it
|
|
prints the backtrace for a crash. It is usually best to look at the
|
|
disassembly to determine exactly what code is being run--the
|
|
disassembly will probably show several source lines followed by a
|
|
block of assembler for those lines. The actual point where Emacs
|
|
crashes will be one of those source lines, but not neccesarily the one
|
|
that the debugger reports.
|
|
|
|
Another problematic area with the MS debugger is with variables that
|
|
are stored in registers: it will sometimes display wrong values for
|
|
those variables. Usually you will not be able to see any value for a
|
|
register variable, but if it is only being stored in a register
|
|
temporarily, you will see an old value for it. Again, you need to
|
|
look at the disassembly to determine which registers are being used,
|
|
and look at those registers directly, to see the actual current values
|
|
of these variables.
|