emacs-buffer.gdb 8.5 KB

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