88155
|
1 # emacs-buffer.gdb --- gdb macros for recovering buffers from emacs coredumps
|
|
2
|
|
3 # Copyright (C) 2005 Free Software Foundation, Inc.
|
|
4
|
|
5 # Maintainer: Noah Friedman <friedman@splode.com>
|
|
6 # Status: tested with Emacs 22
|
|
7 # Created: 2005-04-28
|
|
8
|
|
9 # This file is part of GNU Emacs.
|
|
10 #
|
|
11 # GNU Emacs is free software; you can redistribute it and/or modify
|
|
12 # it under the terms of the GNU General Public License as published by
|
|
13 # the Free Software Foundation; either version 2, or (at your option)
|
|
14 # any later version.
|
|
15 #
|
|
16 # GNU Emacs is distributed in the hope that it will be useful,
|
|
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 # GNU General Public License for more details.
|
|
20 #
|
|
21 # You should have received a copy of the GNU General Public License
|
|
22 # along with GNU Emacs; see the file COPYING. If not, write to the
|
|
23 # Free Software Foundation, Inc.; 51 Franklin Street, Fifth Floor;
|
|
24 # Boston, MA 02110-1301, USA.
|
|
25
|
|
26 # Commentary:
|
|
27
|
|
28 # This is a set of gdb macros for recovering the contents of buffers from
|
|
29 # an Emacs coredump; they may not always be file-backed or have a recent
|
|
30 # autosave.
|
|
31 #
|
|
32 # The Emacs executable must have debugging symbols for this to work. But
|
|
33 # you never strip Emacs, right? Right!
|
|
34 #
|
|
35 # The main commands of interest are `ybuffer-list', `yfile-buffers',
|
|
36 # `ysave-buffer', and `ybuffer-contents'. The `y' prefix avoids any
|
|
37 # namespace collisions with emacs/src/.gdbinit.
|
|
38
|
|
39 # Example usage:
|
|
40 #
|
|
41 # $ gdb /export/src/emacs/2005-05-02--03-17/src/emacs core.emacs.6.9845
|
|
42 # Current directory is /u/noah/
|
|
43 # GNU gdb (6.1post-1.20040607.43rh)
|
|
44 # ...
|
|
45 # #0 0x400007a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
|
|
46 # (gdb) source emacs-buffer.gdb
|
|
47 # (gdb) ybuffer-list
|
|
48 # B# M Size Name Mode File
|
|
49 # -- - ---- ---- ---- ----
|
|
50 # 0 * 556 mail to emacs-devel@gnu.org Mail
|
|
51 # 1 * 0 *Minibuf-1* Fundamental
|
|
52 # 2 145769 ChangeLog Change Log /u/noah/lib/elisp/noahf/ChangeLog
|
|
53 # 3 6619 ascii-table.el Elisp /u/noah/lib/elisp/noahf/ascii-table.el
|
|
54 # 4 * 48396 *Messages* Fundamental
|
|
55 # 5 3191 *Apropos* Apropos
|
|
56 # 6 17642 init-21.el Elisp /u/noah/etc/init/emacs/init-21.el
|
|
57 # 7 333 cpuid.c C /u/noah/cpuid.c
|
|
58 # 8 230 src Dired
|
|
59 # 9 218 noah Dired
|
|
60 # 10 * 21 *Echo Area 0* Fundamental
|
|
61 # 11 * 0 *Echo Area 1* Fundamental
|
|
62 # 12 319952 *bbdb data* Text /u/noah/.bbdb
|
|
63 # (gdb) ysave-buffer 0 mail.save
|
|
64 # [Wrote buffer "mail to emacs-devel@gnu.org" to file mail.save]
|
|
65 # (gdb) quit
|
|
66 # $ ls -l mail.save
|
|
67 # -rw-rw-rw- 1 noah user 556 May 2 04:05 mail.save
|
|
68 # $
|
|
69
|
|
70 # Code:
|
|
71
|
|
72 # Force loading of symbols, enough to give us gdb_valbits etc.
|
|
73 set main
|
|
74
|
|
75 # When nonzero, display some extra diagnostics in various commands
|
|
76 set $yverbose = 1
|
|
77 set $yfile_buffers_only = 0
|
|
78
|
|
79 set $tagmask = (((long)1 << gdb_gctypebits) - 1)
|
|
80 set $valmask = gdb_use_lsb ? ~($tagmask) : ((long)1 << gdb_valbits) - 1
|
|
81
|
|
82 define ygetptr
|
|
83 set $ptr = $arg0
|
|
84 set $ptr = (gdb_use_union ? $ptr.u.val : $ptr & $valmask) | gdb_data_seg_bits
|
|
85 end
|
|
86
|
|
87 define ybuffer-list
|
|
88 set $files_only = $yfile_buffers_only
|
|
89 set $yfile_buffers_only = 0
|
|
90
|
|
91 if $yverbose
|
|
92 printf "B# M Size Name Mode File\n"
|
|
93 printf "-- - ---- ---- ---- ----\n"
|
|
94 end
|
|
95
|
|
96 set $i = 0
|
|
97 set $alist = Vbuffer_alist
|
|
98 while $alist != Qnil
|
|
99 ygetptr $alist
|
|
100 set $this = ((struct Lisp_Cons *) $ptr)->car
|
|
101 set $alist = ((struct Lisp_Cons *) $ptr)->cdr
|
|
102
|
|
103 # Vbuffer_alist elts are pairs of the form (name . buffer)
|
|
104 ygetptr $this
|
|
105 set $buf = ((struct Lisp_Cons *) $ptr)->cdr
|
|
106 ygetptr $buf
|
|
107 set $buf = (struct buffer *) $ptr
|
|
108
|
|
109 if ! ($files_only && $buf->filename == Qnil)
|
|
110 ygetptr $buf->name
|
|
111 set $name = ((struct Lisp_String *) $ptr)->data
|
|
112 set $modp = ($buf->text->modiff > $buf->text->save_modiff) ? '*' : ' '
|
|
113
|
|
114 ygetptr $buf->mode_name
|
|
115 set $mode = ((struct Lisp_String *) $ptr)->data
|
|
116
|
|
117 if $buf->filename != Qnil
|
|
118 ygetptr $buf->filename
|
|
119 printf "%2d %c %9d %-20s %-10s %s\n", \
|
|
120 $i, $modp, ($buf->text->z_byte - 1), $name, $mode, \
|
|
121 ((struct Lisp_String *) $ptr)->data
|
|
122 else
|
|
123 printf "%2d %c %9d %-20s %-10s\n", \
|
|
124 $i, $modp, ($buf->text->z_byte - 1), $name, $mode
|
|
125 end
|
|
126 end
|
|
127
|
|
128 set $i++
|
|
129 end
|
|
130 end
|
|
131 document ybuffer-list
|
|
132 Display a list of buffer names, sizes, and other attributes.
|
|
133 The buffer number in the first column is used as an argument
|
|
134 to some other emacs-buffer recovery commands, e.g. `ysave-buffer'.
|
|
135 end
|
|
136
|
|
137 define yfile-buffers
|
|
138 set $yfile_buffers_only = 1
|
|
139 ybuffer-list
|
|
140 end
|
|
141 document yfile-buffers
|
|
142 Display a list of buffers which are associated with files.
|
|
143 This is like `ybuffer-list', but only buffers that were visiting files
|
|
144 are displayed.
|
|
145 end
|
|
146
|
|
147 define yset-buffer
|
|
148 set $i = $arg0
|
|
149
|
|
150 set $alist = Vbuffer_alist
|
|
151 while ($alist != Qnil && $i > 0)
|
|
152 ygetptr $alist
|
|
153 set $alist = ((struct Lisp_Cons *) $ptr)->cdr
|
|
154 set $i--
|
|
155 end
|
|
156
|
|
157 # Get car of alist; this is a pair (name . buffer)
|
|
158 ygetptr $alist
|
|
159 set $this = ((struct Lisp_Cons *) $ptr)->car
|
|
160
|
|
161 # Get the buffer object
|
|
162 ygetptr $this
|
|
163 set $this = ((struct Lisp_Cons *) $ptr)->cdr
|
|
164
|
|
165 ygetptr $this
|
|
166 set $ycurrent_buffer = (struct buffer *) $ptr
|
|
167 end
|
|
168 document yset-buffer
|
|
169 Set current buffer (for other emacs-buffer recovery commands) to the ARG'th
|
|
170 buffer as displayed by `ybuffer-list'.
|
|
171 end
|
|
172
|
|
173 define yget-buffer-pointers
|
|
174 yset-buffer $arg0
|
|
175 set $buf = $ycurrent_buffer->text
|
|
176
|
|
177 set $beg = $buf->beg
|
|
178 set $gap = $beg + $buf->gpt_byte
|
|
179 set $gap_end = $gap + $buf->gap_size - 1
|
|
180 set $end = $gap_end + ($buf->z_byte - $buf->gpt_byte)
|
|
181
|
|
182 set $modp = $buf->modiff > $buf->save_modiff
|
|
183
|
|
184 #print *$beg@($gap - $beg)
|
|
185 #print *$gap_end@($end - $gap_end)
|
|
186 end
|
|
187 document yget-buffer-pointers
|
|
188 Update convenience variables with address pointers for the ARG'th buffer
|
|
189 as displayed by `ybuffer-list'.
|
|
190
|
|
191 This also sets the current buffer using `yset-buffer' (which see).
|
|
192 end
|
|
193
|
|
194 define yget-current-buffer-name
|
|
195 set $this = $ycurrent_buffer->name
|
|
196 ygetptr $this
|
|
197 set $ycurrent_buffer_name = ((struct Lisp_String *) $ptr)->data
|
|
198 end
|
|
199 document yget-current-buffer-name
|
|
200 Set $ycurrent_buffer_name to the name of the currently selected buffer.
|
|
201 end
|
|
202
|
|
203 define ycurrent-buffer
|
|
204 yget-current-buffer-name
|
|
205 printf "%s\n", $ycurrent_buffer_name
|
|
206 end
|
|
207 document ycurrent-buffer
|
|
208 Display the currently selected buffer.
|
|
209 end
|
|
210
|
|
211 define ydump-buffer
|
|
212 yget-buffer-pointers $arg0
|
|
213 if $buf->z_byte > 1
|
|
214 if $buf->z_byte <= $buf->gpt_byte
|
|
215 set $endptr = $beg + $buf->gpt_byte - 1
|
|
216 dump binary memory $arg1 $beg $endptr
|
|
217 else
|
|
218 dump binary memory $arg1 $beg $gap-1
|
|
219 append binary memory $arg1 $gap_end $end
|
|
220 set $endptr = $end
|
|
221 end
|
|
222 end
|
|
223 end
|
|
224 document ydump-buffer
|
|
225 Write contents of buffer N (as numbered according to `ybuffer-list') to
|
|
226 file FILE.
|
|
227
|
|
228 This is mainly used as an internal subroutine for `ysave-buffer' and
|
|
229 `ybuffer-contents', which see.
|
|
230 end
|
|
231
|
|
232 define ysave-buffer
|
|
233 ydump-buffer $arg0 $arg1
|
|
234 if $yverbose
|
|
235 yget-current-buffer-name
|
|
236 if $buf->z_byte <= 1
|
|
237 printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
|
|
238 else
|
|
239 # Output string broken into separate calls as necessary to avoid
|
|
240 # requiring a running process for evaluation.
|
|
241 printf "[Wrote buffer \"%s\" to file ", $ycurrent_buffer_name
|
|
242 echo $arg1]\n
|
|
243 end
|
|
244 end
|
|
245 end
|
|
246 document ysave-buffer
|
|
247 Save contents of buffer N (as numbered according to `ybuffer-list') to
|
|
248 file FILE.
|
|
249 end
|
|
250
|
|
251 define ybuffer-contents
|
|
252 ydump-buffer $arg0 /dev/stdout
|
|
253 if $yverbose && $buf->z_byte <= 1
|
|
254 yget-current-buffer-name
|
|
255 printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
|
|
256 else
|
|
257 if *($endptr-1) != '\n'
|
|
258 echo \n
|
|
259 end
|
|
260 end
|
|
261 end
|
|
262 document ybuffer-contents
|
|
263 Write contents of buffer N (numbered according to `ybuffer-list') to stdout.
|
|
264 end
|
|
265
|
|
266 # local variables:
|
|
267 # mode: gdb-script
|
|
268 # end:
|
|
269
|
|
270 # arch-tag: 02087f62-2663-4868-977a-1fbb2fc2e7ef
|