emacs-buffer.gdb 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. # emacs-buffer.gdb --- gdb macros for recovering buffers from emacs coredumps
  2. # Copyright (C) 2005-2012 Free Software Foundation, Inc.
  3. # Maintainer: 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 occasionally 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 gdb_valbits etc.
  62. set main
  63. # When nonzero, display some extra diagnostics in various commands
  64. set $yverbose = 1
  65. set $yfile_buffers_only = 0
  66. set $tagmask = (((long)1 << gdb_gctypebits) - 1)
  67. # The consing_since_gc business widens the 1 to EMACS_INT,
  68. # a symbol not directly visible to GDB.
  69. set $valmask = gdb_use_lsb ? ~($tagmask) : ((consing_since_gc - consing_since_gc + 1) << gdb_valbits) - 1
  70. define ygetptr
  71. set $ptr = $arg0
  72. set $ptr = (gdb_use_union ? $ptr.u.val : $ptr & $valmask) | gdb_data_seg_bits
  73. end
  74. define ybuffer-list
  75. set $files_only = $yfile_buffers_only
  76. set $yfile_buffers_only = 0
  77. if $yverbose
  78. printf "B# M Size Name Mode File\n"
  79. printf "-- - ---- ---- ---- ----\n"
  80. end
  81. set $i = 0
  82. set $alist = Vbuffer_alist
  83. while $alist != Qnil
  84. ygetptr $alist
  85. set $this = ((struct Lisp_Cons *) $ptr)->car
  86. set $alist = ((struct Lisp_Cons *) $ptr)->u.cdr
  87. # Vbuffer_alist elts are pairs of the form (name . buffer)
  88. ygetptr $this
  89. set $buf = ((struct Lisp_Cons *) $ptr)->u.cdr
  90. ygetptr $buf
  91. set $buf = (struct buffer *) $ptr
  92. if ! ($files_only && $buf->filename_ == Qnil)
  93. ygetptr $buf->name_
  94. set $name = ((struct Lisp_String *) $ptr)->data
  95. set $modp = ($buf->text->modiff > $buf->text->save_modiff) ? '*' : ' '
  96. ygetptr $buf->mode_name_
  97. set $mode = ((struct Lisp_String *) $ptr)->data
  98. if $buf->filename_ != Qnil
  99. ygetptr $buf->filename_
  100. printf "%2d %c %9d %-20s %-10s %s\n", \
  101. $i, $modp, ($buf->text->z_byte - 1), $name, $mode, \
  102. ((struct Lisp_String *) $ptr)->data
  103. else
  104. printf "%2d %c %9d %-20s %-10s\n", \
  105. $i, $modp, ($buf->text->z_byte - 1), $name, $mode
  106. end
  107. end
  108. set $i++
  109. end
  110. end
  111. document ybuffer-list
  112. Display a list of buffer names, sizes, and other attributes.
  113. The buffer number in the first column is used as an argument
  114. to some other emacs-buffer recovery commands, e.g. `ysave-buffer'.
  115. end
  116. define yfile-buffers
  117. set $yfile_buffers_only = 1
  118. ybuffer-list
  119. end
  120. document yfile-buffers
  121. Display a list of buffers which are associated with files.
  122. This is like `ybuffer-list', but only buffers that were visiting files
  123. are displayed.
  124. end
  125. define yset-buffer
  126. set $i = $arg0
  127. set $alist = Vbuffer_alist
  128. while ($alist != Qnil && $i > 0)
  129. ygetptr $alist
  130. set $alist = ((struct Lisp_Cons *) $ptr)->u.cdr
  131. set $i--
  132. end
  133. # Get car of alist; this is a pair (name . buffer)
  134. ygetptr $alist
  135. set $this = ((struct Lisp_Cons *) $ptr)->car
  136. # Get the buffer object
  137. ygetptr $this
  138. set $this = ((struct Lisp_Cons *) $ptr)->u.cdr
  139. ygetptr $this
  140. set $ycurrent_buffer = (struct buffer *) $ptr
  141. end
  142. document yset-buffer
  143. Set current buffer (for other emacs-buffer recovery commands) to the ARG'th
  144. buffer as displayed by `ybuffer-list'.
  145. end
  146. define yget-buffer-pointers
  147. yset-buffer $arg0
  148. set $buf = $ycurrent_buffer->text
  149. set $beg = $buf->beg
  150. set $gap = $beg + $buf->gpt_byte
  151. set $gap_end = $gap + $buf->gap_size - 1
  152. set $end = $gap_end + ($buf->z_byte - $buf->gpt_byte)
  153. set $modp = $buf->modiff > $buf->save_modiff
  154. #print *$beg@($gap - $beg)
  155. #print *$gap_end@($end - $gap_end)
  156. end
  157. document yget-buffer-pointers
  158. Update convenience variables with address pointers for the ARG'th buffer
  159. as displayed by `ybuffer-list'.
  160. This also sets the current buffer using `yset-buffer' (which see).
  161. end
  162. define yget-current-buffer-name
  163. set $this = $ycurrent_buffer->name_
  164. ygetptr $this
  165. set $ycurrent_buffer_name = ((struct Lisp_String *) $ptr)->data
  166. end
  167. document yget-current-buffer-name
  168. Set $ycurrent_buffer_name to the name of the currently selected buffer.
  169. end
  170. define ycurrent-buffer
  171. yget-current-buffer-name
  172. printf "%s\n", $ycurrent_buffer_name
  173. end
  174. document ycurrent-buffer
  175. Display the currently selected buffer.
  176. end
  177. define ydump-buffer
  178. yget-buffer-pointers $arg0
  179. if $buf->z_byte > 1
  180. if $buf->z_byte <= $buf->gpt_byte
  181. set $endptr = $beg + $buf->gpt_byte - 1
  182. dump binary memory $arg1 $beg $endptr
  183. else
  184. dump binary memory $arg1 $beg $gap-1
  185. append binary memory $arg1 $gap_end $end
  186. set $endptr = $end
  187. end
  188. end
  189. end
  190. document ydump-buffer
  191. Write contents of buffer N (as numbered according to `ybuffer-list') to
  192. file FILE.
  193. This is mainly used as an internal subroutine for `ysave-buffer' and
  194. `ybuffer-contents', which see.
  195. end
  196. define ysave-buffer
  197. ydump-buffer $arg0 $arg1
  198. if $yverbose
  199. yget-current-buffer-name
  200. if $buf->z_byte <= 1
  201. printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
  202. else
  203. # Output string broken into separate calls as necessary to avoid
  204. # requiring a running process for evaluation.
  205. printf "[Wrote buffer \"%s\" to file ", $ycurrent_buffer_name
  206. echo $arg1]\n
  207. end
  208. end
  209. end
  210. document ysave-buffer
  211. Save contents of buffer N (as numbered according to `ybuffer-list') to
  212. file FILE.
  213. end
  214. define ybuffer-contents
  215. ydump-buffer $arg0 /dev/stdout
  216. if $yverbose && $buf->z_byte <= 1
  217. yget-current-buffer-name
  218. printf "[Buffer \"%s\" is empty.]\n", $ycurrent_buffer_name
  219. else
  220. if *($endptr-1) != '\n'
  221. echo \n
  222. end
  223. end
  224. end
  225. document ybuffer-contents
  226. Write contents of buffer N (numbered according to `ybuffer-list') to stdout.
  227. end
  228. # local variables:
  229. # mode: gdb-script
  230. # end: