* lisp/emacs-lisp/bytecomp.el: Tweak last change
[emacs.git] / etc / emacs-buffer.gdb
blob8a4d6485bf6c4135904fe0fe8df4e2f309c0d0db
1 # emacs-buffer.gdb --- gdb macros for recovering buffers from emacs coredumps
3 # Copyright (C) 2005-2018 Free Software Foundation, Inc.
5 # Author: Noah Friedman <friedman@splode.com>
6 # Created: 2005-04-28
8 # This file is part of GNU Emacs.
10 # GNU Emacs is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
15 # GNU Emacs is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public License
21 # along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
23 # Commentary:
25 # This is a set of gdb macros for recovering the contents of buffers from
26 # an Emacs coredump; they may not always be file-backed or have a recent
27 # autosave.
29 # The Emacs executable must have debugging symbols for this to work.
30 # But you never strip Emacs, right?
32 # The main commands of interest are 'ybuffer-list', 'yfile-buffers',
33 # 'ysave-buffer', and 'ybuffer-contents'.  The 'y' prefix avoids any
34 # namespace collisions with emacs/src/.gdbinit.
36 # Since the internal data structures in Emacs change from time to
37 # time, you should use the version of this file that came with your
38 # particular Emacs version; older versions might not work anymore.
40 # Example usage:
42 #     $ gdb /export/src/emacs/2005-05-02--03-17/src/emacs core.emacs.6.9845
43 #     Current directory is /u/noah/
44 #     GNU gdb (6.1post-1.20040607.43rh)
45 #     ...
46 #     #0  0x400007a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
47 #     (gdb) source emacs-buffer.gdb
48 #     (gdb) ybuffer-list
49 #     B# M       Size Name                 Mode       File
50 #     -- -       ---- ----                 ----       ----
51 #      0 *        556 mail to emacs-devel@gnu.org Mail
52 #      1 *          0  *Minibuf-1*         Fundamental
53 #      2       145769 ChangeLog            Change Log /u/noah/lib/elisp/noahf/ChangeLog
54 #      3         6619 ascii-table.el       Elisp      /u/noah/lib/elisp/noahf/ascii-table.el
55 #      4 *      48396 *Messages*           Fundamental
56 #      5         3191 *Apropos*            Apropos
57 #      6        17642 init-21.el           Elisp      /u/noah/etc/init/emacs/init-21.el
58 #      7          333 cpuid.c              C          /u/noah/cpuid.c
59 #      8          230 src                  Dired
60 #      9          218 noah                 Dired
61 #     10 *         21  *Echo Area 0*       Fundamental
62 #     11 *          0  *Echo Area 1*       Fundamental
63 #     12       319952  *bbdb data*         Text       /u/noah/.bbdb
64 #     (gdb) ysave-buffer 0 mail.save
65 #     [Wrote buffer "mail to emacs-devel@gnu.org" to file mail.save]
66 #     (gdb) quit
67 #     $ ls -l mail.save
68 #     -rw-rw-rw-  1 noah user 556 May  2 04:05 mail.save
69 #     $
71 # Code:
73 # Force loading of symbols, enough to give us VALBITS etc.
74 set $dummy = main + 8
75 # With some compilers, we need this to give us struct Lisp_Symbol etc.:
76 set $dummy = Fmake_symbol + 8
78 # When nonzero, display some extra diagnostics in various commands
79 set $yverbose = 1
80 set $yfile_buffers_only = 0
82 define ygetptr
83   set $ptr = $arg0
84   set $ptr = (CHECK_LISP_OBJECT_TYPE ? $ptr.i : $ptr) & VALMASK
85 end
87 # Get the value of Qnil for comparison.  Needed when
88 # CHECK_LISP_OBJECT_TYPE is non-zero.
89 ygetptr Qnil
90 set $qnil = $ptr
92 define ybuffer-list
93   set $files_only         = $yfile_buffers_only
94   set $yfile_buffers_only = 0
96   if $yverbose
97     printf "B# M       Size Name                 Mode       File\n"
98     printf "-- -       ---- ----                 ----       ----\n"
99   end
101   set $i = 0
102   set $alist = Vbuffer_alist
103   ygetptr $alist
104   set $alist = $ptr
105   while $alist != $qnil
106     set $this  = ((struct Lisp_Cons *) $ptr)->car
107     set $alist = ((struct Lisp_Cons *) $ptr)->u.cdr
109     # Vbuffer_alist elts are pairs of the form (name . buffer)
110     ygetptr $this
111     set $buf  = ((struct Lisp_Cons *) $ptr)->u.cdr
112     ygetptr $buf
113     set $buf = (struct buffer *) $ptr
115     ygetptr $buf->filename_
116     set $fname = $ptr
117     if ! ($files_only && $fname == $qnil)
118       ygetptr $buf->name_
119       set $name = ((struct Lisp_String *) $ptr)->data
120       set $modp = ($buf->text->modiff > $buf->text->save_modiff) ? '*' : ' '
122       ygetptr $buf->mode_name_
123       set $mode = ((struct Lisp_String *) $ptr)->data
125       if $fname != $qnil
126         ygetptr $buf->filename_
127         printf "%2d %c  %9d %-20s %-10s %s\n", \
128                $i, $modp, ($buf->text->z_byte - 1), $name, $mode, \
129                ((struct Lisp_String *) $fname)->data
130       else
131         printf "%2d %c  %9d %-20s %-10s\n", \
132                $i, $modp, ($buf->text->z_byte - 1), $name, $mode
133       end
134     end
136     set $i++
137     ygetptr $alist
138     set $alist = $ptr
139   end
141 document ybuffer-list
142   Display a list of buffer names, sizes, and other attributes.
143   The buffer number in the first column is used as an argument
144   to some other emacs-buffer recovery commands, e.g. 'ysave-buffer'.
147 define yfile-buffers
148   set $yfile_buffers_only = 1
149   ybuffer-list
151 document yfile-buffers
152   Display a list of buffers which are associated with files.
153   This is like 'ybuffer-list', but only buffers that were visiting files
154   are displayed.
157 define yset-buffer
158   set $i = $arg0
160   set $alist = Vbuffer_alist
161   ygetptr $alist
162   set $alist = $ptr
163   while ($alist != $qnil && $i > 0)
164     set $alist = ((struct Lisp_Cons *) $ptr)->u.cdr
165     ygetptr $alist
166     set $alist = $ptr
167     set $i--
168   end
170   # Get car of alist; this is a pair (name . buffer)
171   set $this = ((struct Lisp_Cons *) $alist)->car
173   # Get the buffer object
174   ygetptr $this
175   set $this = ((struct Lisp_Cons *) $ptr)->u.cdr
177   ygetptr $this
178   set $ycurrent_buffer = (struct buffer *) $ptr
180 document yset-buffer
181   Set current buffer (for other emacs-buffer recovery commands) to the ARG'th
182   buffer as displayed by 'ybuffer-list'.
185 define yget-buffer-pointers
186   yset-buffer $arg0
187   set $buf = $ycurrent_buffer->text
189   set $beg     = $buf->beg
190   set $gap     = $beg + $buf->gpt_byte
191   set $gap_end = $gap + $buf->gap_size - 1
192   set $end     = $gap_end + ($buf->z_byte - $buf->gpt_byte)
194   set $modp    = $buf->modiff > $buf->save_modiff
196   #print *$beg@($gap - $beg)
197   #print *$gap_end@($end - $gap_end)
199 document yget-buffer-pointers
200   Update convenience variables with address pointers for the ARG'th buffer
201   as displayed by 'ybuffer-list'.
203   This also sets the current buffer using 'yset-buffer' (which see).
206 define yget-current-buffer-name
207   set $this = $ycurrent_buffer->name_
208   ygetptr $this
209   set $ycurrent_buffer_name = ((struct Lisp_String *) $ptr)->data
211 document yget-current-buffer-name
212   Set $ycurrent_buffer_name to the name of the currently selected buffer.
215 define ycurrent-buffer
216   yget-current-buffer-name
217   printf "%s\n", $ycurrent_buffer_name
219 document ycurrent-buffer
220   Display the currently selected buffer.
223 define ydump-buffer
224   yget-buffer-pointers $arg0
225   if $buf->z_byte > 1
226     if $buf->z_byte <= $buf->gpt_byte
227       set $endptr = $beg + $buf->gpt_byte - 1
228       dump binary memory $arg1 $beg $endptr
229     else
230       if $gap - $beg > 1
231         dump   binary memory $arg1 $beg $gap-1
232         append binary memory $arg1 $gap_end $end
233       else
234         dump   binary memory $arg1 $gap_end $end
235       end
236       set $endptr = $end
237     end
238   end
240 document ydump-buffer
241   Write contents of buffer N (as numbered according to 'ybuffer-list') to
242   file FILE.
244   This is mainly used as an internal subroutine for 'ysave-buffer' and
245   'ybuffer-contents', which see.
248 define ysave-buffer
249   ydump-buffer $arg0 $arg1
250   if $yverbose
251     yget-current-buffer-name
252     if $buf->z_byte <= 1
253       printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
254     else
255       # Output string broken into separate calls as necessary to avoid
256       # requiring a running process for evaluation.
257       printf "[Wrote buffer \"%s\" to file ", $ycurrent_buffer_name
258       echo $arg1]\n
259     end
260   end
262 document ysave-buffer
263   Save contents of buffer N (as numbered according to 'ybuffer-list') to
264   file FILE.
267 define ybuffer-contents
268   ydump-buffer $arg0 /dev/stdout
269   if $yverbose && $buf->z_byte <= 1
270     yget-current-buffer-name
271     printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
272   else
273     if *($endptr-1) != '\n'
274       echo \n
275     end
276   end
278 document ybuffer-contents
279   Write contents of buffer N (numbered according to 'ybuffer-list') to stdout.
282 # local variables:
283 # mode: gdb-script
284 # end: