Mercurial > emacs
comparison lisp/progmodes/gdb-ui.el @ 91204:53108e6cea98
Merge from emacs--devo--0
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-294
author | Miles Bader <miles@gnu.org> |
---|---|
date | Thu, 06 Dec 2007 09:51:45 +0000 |
parents | 880960b70474 f43509daf0ee |
children | 606f2d163a64 |
comparison
equal
deleted
inserted
replaced
91203:db40129142b2 | 91204:53108e6cea98 |
---|---|
41 ;; You don't need to know about annotations to use this mode as a debugger, | 41 ;; You don't need to know about annotations to use this mode as a debugger, |
42 ;; but if you are interested developing the mode itself, see the Annotations | 42 ;; but if you are interested developing the mode itself, see the Annotations |
43 ;; section in the GDB info manual. | 43 ;; section in the GDB info manual. |
44 | 44 |
45 ;; GDB developers plan to make the annotation interface obsolete. A new | 45 ;; GDB developers plan to make the annotation interface obsolete. A new |
46 ;; interface called GDB/MI (machine interface) has been designed to replace | 46 ;; interface called GDB/MI (machine interface) has been designed to replace it. |
47 ;; it. Some GDB/MI commands are used in this file through the CLI command | 47 ;; Some GDB/MI commands are used in this file through the CLI command |
48 ;; 'interpreter mi <mi-command>'. A file called gdb-mi.el is included with | 48 ;; 'interpreter mi <mi-command>'. To help with the process of fully migrating |
49 ;; GDB (6.2 onwards) that uses GDB/MI as the primary interface to GDB. It is | 49 ;; Emacs from annotations to GDB/MI, there is an experimental package called |
50 ;; still under development and is part of a process to migrate Emacs from | 50 ;; gdb-mi in the Emacs Lisp Package Archive ("http://tromey.com/elpa/"). It |
51 ;; annotations to GDB/MI. | 51 ;; comprises of modified gud.el and a file called gdb-mi.el which replaces |
52 ;; gdb-ui.el. When installed, this overrides the current files and invoking | |
53 ;; M-x gdb will use GDB/MI directly (starts with "gdb -i=mi"). When deleted | |
54 ;; ('d' followed by 'x' in Package Menu mode), the files are deleted and old | |
55 ;; functionality restored. This provides a convenient way to review the | |
56 ;; current status/contribute to its improvement. For someone who just wants to | |
57 ;; use GDB, however, the current mode in Emacs 22 is a much better option. | |
58 ;; There is also a file, also called gdb-mi.el, a version of which is included | |
59 ;; the GDB distribution. This will probably only work with versions | |
60 ;; distributed with GDB 6.5 or later. Unlike the version in ELPA it works on | |
61 ;; top of gdb-ui.el and you can only start it with M-x gdbmi. | |
52 | 62 |
53 ;; This mode SHOULD WORK WITH GDB 5.0 or later but you will NEED AT LEAST | 63 ;; This mode SHOULD WORK WITH GDB 5.0 or later but you will NEED AT LEAST |
54 ;; GDB 6.0 to use watch expressions. It works best with GDB 6.4 or later | 64 ;; GDB 6.0 to use watch expressions. It works best with GDB 6.4 or later |
55 ;; where watch expressions will update more quickly. | 65 ;; where watch expressions will update more quickly. |
56 | 66 |
67 | 77 |
68 ;; and compiling with -DUNBUFFERED while debugging. | 78 ;; and compiling with -DUNBUFFERED while debugging. |
69 | 79 |
70 ;;; Known Bugs: | 80 ;;; Known Bugs: |
71 | 81 |
72 ;; 1) Strings that are watched don't update in the speedbar when their | 82 ;; 1) Cannot handle multiple debug sessions. |
73 ;; contents change unless the first character changes. | 83 ;; 2) If you wish to call procedures from your program in GDB |
74 ;; 2) Cannot handle multiple debug sessions. | |
75 ;; 3) M-x gdb doesn't work with "run" command in .gdbinit, use M-x gdba instead. | |
76 ;; 4) M-x gdb doesn't work if the corefile is specified in the command in the | |
77 ;; minibuffer, use M-x gdba instead (or specify the core in the GUD buffer). | |
78 ;; 5) If you wish to call procedures from your program in GDB | |
79 ;; e.g "call myproc ()", "p mysquare (5)" then use level 2 annotations | 84 ;; e.g "call myproc ()", "p mysquare (5)" then use level 2 annotations |
80 ;; "gdb --annotate=2 myprog" to keep source buffer/selected frame fixed. | 85 ;; "gdb --annotate=2 myprog" to keep source buffer/selected frame fixed. |
81 ;; 6) After detaching from a process, clicking on the "GO" icon on toolbar | 86 ;; 3) After detaching from a process, clicking on the "GO" icon on toolbar |
82 ;; (gud-go) sends "continue" to GDB (should be "run"). | 87 ;; (gud-go) sends "continue" to GDB (should be "run"). |
83 | |
84 ;;; Problems with watch expressions, GDB/MI: | |
85 | |
86 ;; 1) They go out of scope when the inferior is re-run. | |
87 ;; 2) -stack-list-locals has a type field but also prints type in values field. | |
88 ;; 3) VARNUM increments even when variable object is not created | |
89 ;; (maybe trivial). | |
90 | 88 |
91 ;;; TODO: | 89 ;;; TODO: |
92 | 90 |
93 ;; 1) Use MI command -data-read-memory for memory window. | 91 ;; 1) Use MI command -data-read-memory for memory window. |
94 ;; 2) Use tree-widget.el instead of the speedbar for watch-expressions? | 92 ;; 2) Use tree-widget.el instead of the speedbar for watch-expressions? |
136 (defvar gdb-continuation nil) | 134 (defvar gdb-continuation nil) |
137 (defvar gdb-look-up-stack nil) | 135 (defvar gdb-look-up-stack nil) |
138 (defvar gdb-frame-begin nil | 136 (defvar gdb-frame-begin nil |
139 "Non-nil when GDB generates frame-begin annotation.") | 137 "Non-nil when GDB generates frame-begin annotation.") |
140 (defvar gdb-printing t) | 138 (defvar gdb-printing t) |
139 (defvar gdb-parent-bptno-enabled nil) | |
141 | 140 |
142 (defvar gdb-buffer-type nil | 141 (defvar gdb-buffer-type nil |
143 "One of the symbols bound in `gdb-buffer-rules'.") | 142 "One of the symbols bound in `gdb-buffer-rules'.") |
144 (make-variable-buffer-local 'gdb-buffer-type) | 143 (make-variable-buffer-local 'gdb-buffer-type) |
145 | 144 |
219 ;;;###autoload | 218 ;;;###autoload |
220 (defun gdb (command-line) | 219 (defun gdb (command-line) |
221 "Run gdb on program FILE in buffer *gud-FILE*. | 220 "Run gdb on program FILE in buffer *gud-FILE*. |
222 The directory containing FILE becomes the initial working | 221 The directory containing FILE becomes the initial working |
223 directory and source-file directory for your debugger. | 222 directory and source-file directory for your debugger. |
224 | |
225 | 223 |
226 If `gdb-many-windows' is nil (the default value) then gdb just | 224 If `gdb-many-windows' is nil (the default value) then gdb just |
227 pops up the GUD buffer unless `gdb-show-main' is t. In this case | 225 pops up the GUD buffer unless `gdb-show-main' is t. In this case |
228 it starts with two windows: one displaying the GUD buffer and the | 226 it starts with two windows: one displaying the GUD buffer and the |
229 other with the source file with the main routine of the inferior. | 227 other with the source file with the main routine of the inferior. |
1858 (t :background "gray")) | 1856 (t :background "gray")) |
1859 "Face for disabled breakpoint icon in fringe." | 1857 "Face for disabled breakpoint icon in fringe." |
1860 :group 'gud) | 1858 :group 'gud) |
1861 | 1859 |
1862 (defconst gdb-breakpoint-regexp | 1860 (defconst gdb-breakpoint-regexp |
1863 "\\([0-9]+\\).*?\\(?:point\\|catch\\s-+\\S-+\\)\\s-+\\S-+\\s-+\\(.\\)\\s-+") | 1861 "\\(?:\\([0-9]+\\).*?\\(?:point\\|catch\\s-+\\S-+\\)\\s-+\\S-+\\|\\([0-9]+\\.[0-9]+\\)\\)\\s-+\\(.\\)\\s-+") |
1864 | 1862 |
1865 ;; Put breakpoint icons in relevant margins (even those set in the GUD buffer). | 1863 ;; Put breakpoint icons in relevant margins (even those set in the GUD buffer). |
1866 (defun gdb-info-breakpoints-custom () | 1864 (defun gdb-info-breakpoints-custom () |
1867 (let ((flag) (bptno)) | 1865 (let ((flag) (bptno)) |
1868 ;; Remove all breakpoint-icons in source buffers but not assembler buffer. | 1866 ;; Remove all breakpoint-icons in source buffers but not assembler buffer. |
1877 (goto-char (point-min)) | 1875 (goto-char (point-min)) |
1878 (while (< (point) (- (point-max) 1)) | 1876 (while (< (point) (- (point-max) 1)) |
1879 (forward-line 1) | 1877 (forward-line 1) |
1880 (if (looking-at gdb-breakpoint-regexp) | 1878 (if (looking-at gdb-breakpoint-regexp) |
1881 (progn | 1879 (progn |
1882 (setq bptno (match-string 1)) | 1880 (setq bptno (or (match-string 1) (match-string 2))) |
1883 (setq flag (char-after (match-beginning 2))) | 1881 (setq flag (char-after (match-beginning 3))) |
1882 (if (match-string 1) | |
1883 (setq gdb-parent-bptno-enabled (eq flag ?y))) | |
1884 (add-text-properties | 1884 (add-text-properties |
1885 (match-beginning 2) (match-end 2) | 1885 (match-beginning 3) (match-end 3) |
1886 (if (eq flag ?y) | 1886 (if (eq flag ?y) |
1887 '(face font-lock-warning-face) | 1887 '(face font-lock-warning-face) |
1888 '(face font-lock-type-face))) | 1888 '(face font-lock-type-face))) |
1889 (let ((bl (point)) | 1889 (let ((bl (point)) |
1890 (el (line-end-position))) | 1890 (el (line-end-position))) |
1936 (match-beginning 1) (match-end 1) | 1936 (match-beginning 1) (match-end 1) |
1937 '(face font-lock-variable-name-face))))))) | 1937 '(face font-lock-variable-name-face))))))) |
1938 (end-of-line)))))) | 1938 (end-of-line)))))) |
1939 (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))) | 1939 (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom))) |
1940 | 1940 |
1941 (declare-function gud-remove "gdb-ui" t t) ; gud-def | |
1942 (declare-function gud-break "gdb-ui" t t) ; gud-def | |
1943 | |
1941 (defun gdb-mouse-set-clear-breakpoint (event) | 1944 (defun gdb-mouse-set-clear-breakpoint (event) |
1942 "Set/clear breakpoint in left fringe/margin with mouse click." | 1945 "Set/clear breakpoint in left fringe/margin with mouse click." |
1943 (interactive "e") | 1946 (interactive "e") |
1944 (mouse-minibuffer-check event) | 1947 (mouse-minibuffer-check event) |
1945 (let ((posn (event-end event))) | 1948 (let ((posn (event-end event))) |
1961 (if (numberp (posn-point posn)) | 1964 (if (numberp (posn-point posn)) |
1962 (with-selected-window (posn-window posn) | 1965 (with-selected-window (posn-window posn) |
1963 (save-excursion | 1966 (save-excursion |
1964 (goto-char (posn-point posn)) | 1967 (goto-char (posn-point posn)) |
1965 (if (posn-object posn) | 1968 (if (posn-object posn) |
1966 (gdb-enqueue-input | 1969 (let* ((bptno (get-text-property |
1967 (list | 1970 0 'gdb-bptno (car (posn-string posn))))) |
1968 (let ((bptno (get-text-property | 1971 (string-match "\\([0-9+]\\)*" bptno) |
1969 0 'gdb-bptno (car (posn-string posn))))) | 1972 (gdb-enqueue-input |
1973 (list | |
1970 (concat gdb-server-prefix | 1974 (concat gdb-server-prefix |
1971 (if (get-text-property | 1975 (if (get-text-property |
1972 0 'gdb-enabled (car (posn-string posn))) | 1976 0 'gdb-enabled (car (posn-string posn))) |
1973 "disable " | 1977 "disable " |
1974 "enable ") | 1978 "enable ") |
1975 bptno "\n")) | 1979 (match-string 1 bptno) "\n") |
1976 'ignore)))))))) | 1980 'ignore))))))))) |
1977 | 1981 |
1978 (defun gdb-mouse-toggle-breakpoint-fringe (event) | 1982 (defun gdb-mouse-toggle-breakpoint-fringe (event) |
1979 "Enable/disable breakpoint in left fringe with mouse click." | 1983 "Enable/disable breakpoint in left fringe with mouse click." |
1980 (interactive "e") | 1984 (interactive "e") |
1981 (mouse-minibuffer-check event) | 1985 (mouse-minibuffer-check event) |
1989 (goto-char pos) | 1993 (goto-char pos) |
1990 (dolist (overlay (overlays-in pos pos)) | 1994 (dolist (overlay (overlays-in pos pos)) |
1991 (when (overlay-get overlay 'put-break) | 1995 (when (overlay-get overlay 'put-break) |
1992 (setq obj (overlay-get overlay 'before-string)))) | 1996 (setq obj (overlay-get overlay 'before-string)))) |
1993 (when (stringp obj) | 1997 (when (stringp obj) |
1994 (gdb-enqueue-input | 1998 (let* ((bptno (get-text-property 0 'gdb-bptno obj))) |
1995 (list | 1999 (string-match "\\([0-9+]\\)*" bptno) |
1996 (concat gdb-server-prefix | 2000 (gdb-enqueue-input |
1997 (if (get-text-property 0 'gdb-enabled obj) | 2001 (list |
1998 "disable " | 2002 (concat gdb-server-prefix |
1999 "enable ") | 2003 (if (get-text-property 0 'gdb-enabled obj) |
2000 (get-text-property 0 'gdb-bptno obj) "\n") | 2004 "disable " |
2001 'ignore)))))))) | 2005 "enable ") |
2006 (match-string 1 bptno) "\n") | |
2007 'ignore))))))))) | |
2002 | 2008 |
2003 (defun gdb-breakpoints-buffer-name () | 2009 (defun gdb-breakpoints-buffer-name () |
2004 (with-current-buffer gud-comint-buffer | 2010 (with-current-buffer gud-comint-buffer |
2005 (concat "*breakpoints of " (gdb-get-target-string) "*"))) | 2011 (concat "*breakpoints of " (gdb-get-target-string) "*"))) |
2006 | 2012 |
2062 (beginning-of-line 1) | 2068 (beginning-of-line 1) |
2063 (if (looking-at gdb-breakpoint-regexp) | 2069 (if (looking-at gdb-breakpoint-regexp) |
2064 (gdb-enqueue-input | 2070 (gdb-enqueue-input |
2065 (list | 2071 (list |
2066 (concat gdb-server-prefix | 2072 (concat gdb-server-prefix |
2067 (if (eq ?y (char-after (match-beginning 2))) | 2073 (if (eq ?y (char-after (match-beginning 3))) |
2068 "disable " | 2074 "disable " |
2069 "enable ") | 2075 "enable ") |
2070 (match-string 1) "\n") 'ignore)) | 2076 (or (match-string 1) (match-string 2)) "\n") 'ignore)) |
2071 (error "Not recognized as break/watchpoint line")))) | 2077 (error "Not recognized as break/watchpoint line")))) |
2072 | 2078 |
2073 (defun gdb-delete-breakpoint () | 2079 (defun gdb-delete-breakpoint () |
2074 "Delete the breakpoint at current line." | 2080 "Delete the breakpoint at current line." |
2075 (interactive) | 2081 (interactive) |
2076 (beginning-of-line 1) | 2082 (save-excursion |
2077 (if (looking-at gdb-breakpoint-regexp) | 2083 (beginning-of-line 1) |
2078 (gdb-enqueue-input | 2084 (if (looking-at gdb-breakpoint-regexp) |
2079 (list | 2085 (if (match-string 1) |
2080 (concat gdb-server-prefix "delete " (match-string 1) "\n") 'ignore)) | 2086 (gdb-enqueue-input |
2081 (error "Not recognized as break/watchpoint line"))) | 2087 (list |
2088 (concat gdb-server-prefix "delete " (match-string 1) "\n") | |
2089 'ignore)) | |
2090 (message-box "This breakpoint cannot be deleted on its own.")) | |
2091 (error "Not recognized as break/watchpoint line")))) | |
2082 | 2092 |
2083 (defun gdb-goto-breakpoint (&optional event) | 2093 (defun gdb-goto-breakpoint (&optional event) |
2084 "Display the breakpoint location specified at current line." | 2094 "Display the breakpoint location specified at current line." |
2085 (interactive (list last-input-event)) | 2095 (interactive (list last-input-event)) |
2086 (if event (posn-set-point (event-end event))) | 2096 (if event (posn-set-point (event-end event))) |
2087 (save-excursion | 2097 (save-excursion |
2088 (beginning-of-line 1) | 2098 (beginning-of-line 1) |
2089 (if (looking-at "\\([0-9]+\\) .+ in .+ at\\s-+\\(\\S-+\\):\\([0-9]+\\)") | 2099 (if (looking-at "\\([0-9]+\\.?[0-9]*\\) .+ in .+ at\\s-+\\(\\S-+\\):\\([0-9]+\\)") |
2090 (let ((bptno (match-string 1)) | 2100 (let ((bptno (match-string 1)) |
2091 (file (match-string 2)) | 2101 (file (match-string 2)) |
2092 (line (match-string 3))) | 2102 (line (match-string 3))) |
2093 (save-selected-window | 2103 (save-selected-window |
2094 (let* ((buffer (find-file-noselect | 2104 (let* ((buffer (find-file-noselect |
3154 (dolist (overlay (overlays-in start end)) | 3164 (dolist (overlay (overlays-in start end)) |
3155 (when (overlay-get overlay 'put-break) | 3165 (when (overlay-get overlay 'put-break) |
3156 (delete-overlay overlay)))) | 3166 (delete-overlay overlay)))) |
3157 | 3167 |
3158 (defun gdb-put-breakpoint-icon (enabled bptno) | 3168 (defun gdb-put-breakpoint-icon (enabled bptno) |
3169 (if (string-match "[0-9+]+\\." bptno) | |
3170 (setq enabled gdb-parent-bptno-enabled)) | |
3159 (let ((start (- (line-beginning-position) 1)) | 3171 (let ((start (- (line-beginning-position) 1)) |
3160 (end (+ (line-end-position) 1)) | 3172 (end (+ (line-end-position) 1)) |
3161 (putstring (if enabled "B" "b")) | 3173 (putstring (if enabled "B" "b")) |
3162 (source-window (get-buffer-window (current-buffer) 0))) | 3174 (source-window (get-buffer-window (current-buffer) 0))) |
3163 (add-text-properties | 3175 (add-text-properties |
3213 (when (< left-margin-width 2) | 3225 (when (< left-margin-width 2) |
3214 (save-current-buffer | 3226 (save-current-buffer |
3215 (setq left-margin-width 2) | 3227 (setq left-margin-width 2) |
3216 (let ((window (get-buffer-window (current-buffer) 0))) | 3228 (let ((window (get-buffer-window (current-buffer) 0))) |
3217 (if window | 3229 (if window |
3218 (set-window-margins | 3230 (set-window-margins |
3219 window left-margin-width right-margin-width))))) | 3231 window left-margin-width right-margin-width))))) |
3220 (gdb-put-string | 3232 (gdb-put-string |
3221 (propertize putstring | 3233 (propertize putstring |
3222 'face (if enabled 'breakpoint-enabled 'breakpoint-disabled)) | 3234 'face (if enabled 'breakpoint-enabled 'breakpoint-disabled)) |
3223 (1+ start))))) | 3235 (1+ start))))) |
3224 | 3236 |
3284 (gdb-remove-breakpoint-icons (point-min) (point-max)))) | 3296 (gdb-remove-breakpoint-icons (point-min) (point-max)))) |
3285 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer) | 3297 (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer) |
3286 (goto-char (point-min)) | 3298 (goto-char (point-min)) |
3287 (while (< (point) (- (point-max) 1)) | 3299 (while (< (point) (- (point-max) 1)) |
3288 (forward-line 1) | 3300 (forward-line 1) |
3289 (if (looking-at "[^\t].*?breakpoint") | 3301 (when (looking-at |
3290 (progn | 3302 "\\([0-9]+\\.?[0-9]*\\).*?\\s-+\\(.\\)\\s-+0x0*\\(\\S-+\\)") |
3291 (looking-at | 3303 (setq bptno (match-string 1)) |
3292 "\\([0-9]+\\)\\s-+\\S-+\\s-+\\S-+\\s-+\\(.\\)\\s-+0x0*\\(\\S-+\\)") | 3304 (setq flag (char-after (match-beginning 2))) |
3293 (setq bptno (match-string 1)) | 3305 (setq address (match-string 3)) |
3294 (setq flag (char-after (match-beginning 2))) | 3306 (with-current-buffer buffer |
3295 (setq address (match-string 3)) | 3307 (save-excursion |
3296 (with-current-buffer buffer | 3308 (goto-char (point-min)) |
3297 (save-excursion | 3309 (if (search-forward address nil t) |
3298 (goto-char (point-min)) | 3310 (gdb-put-breakpoint-icon (eq flag ?y) bptno))))))) |
3299 (if (search-forward address nil t) | |
3300 (gdb-put-breakpoint-icon (eq flag ?y) bptno)))))))) | |
3301 (if (not (equal gdb-pc-address "main")) | 3311 (if (not (equal gdb-pc-address "main")) |
3302 (with-current-buffer buffer | 3312 (with-current-buffer buffer |
3303 (set-window-point (get-buffer-window buffer 0) pos))))) | 3313 (set-window-point (get-buffer-window buffer 0) pos))))) |
3304 | 3314 |
3305 (defvar gdb-assembler-mode-map | 3315 (defvar gdb-assembler-mode-map |
3456 (gdb-create-define-alist) | 3466 (gdb-create-define-alist) |
3457 (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))) | 3467 (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))) |
3458 (gdb-force-mode-line-update | 3468 (gdb-force-mode-line-update |
3459 (propertize "ready" 'face font-lock-variable-name-face))) | 3469 (propertize "ready" 'face font-lock-variable-name-face))) |
3460 | 3470 |
3461 ; Uses "-var-list-children --all-values". Needs GDB 6.1 onwards. | 3471 ; Uses "-var-list-children --all-values". Needs GDB 6.4 onwards. |
3462 (defun gdb-var-list-children-1 (varnum) | 3472 (defun gdb-var-list-children-1 (varnum) |
3463 (gdb-enqueue-input | 3473 (gdb-enqueue-input |
3464 (list | 3474 (list |
3465 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) | 3475 (if (eq (buffer-local-value 'gud-minor-mode gud-comint-buffer) 'gdba) |
3466 (concat "server interpreter mi \"-var-list-children --all-values " | 3476 (concat "server interpreter mi \"-var-list-children --all-values " |