Mercurial > emacs
comparison lisp/progmodes/gdb-mi.el @ 104145:ff7110a449a4
(gdb-thread-number): New variable.
(gdb-current-context-command): New macro which adds --thread
option to command.
(gdb-threads-mode-map): Select thread with SPC
(gdb-thread-list-handler-custom): Mark current thread with overlay
arrow. Synchronize GDB thread and Emacs thread.
(gdb-select-thread): New command which selects current thread.
(gdb-invalidate-frames, gdb-invalidate-locals)
(gdb-invalidate-registers): Use --thread option.
author | Dmitry Dzhus <dima@sphinx.net.ru> |
---|---|
date | Tue, 04 Aug 2009 12:46:26 +0000 |
parents | 335df621bc5c |
children | 907e635649e5 |
comparison
equal
deleted
inserted
replaced
104144:f60678899ee6 | 104145:ff7110a449a4 |
---|---|
115 (defvar gdb-memory-next-page nil | 115 (defvar gdb-memory-next-page nil |
116 "Address of next memory page for program memory buffer.") | 116 "Address of next memory page for program memory buffer.") |
117 (defvar gdb-memory-prev-page nil | 117 (defvar gdb-memory-prev-page nil |
118 "Address of previous memory page for program memory buffer.") | 118 "Address of previous memory page for program memory buffer.") |
119 | 119 |
120 (defvar gdb-frame-number "0") | |
121 (defvar gdb-thread-number "1" | |
122 "Main current thread. | |
123 | |
124 Invalidation triggers use this variable to query GDB for | |
125 information on the specified thread. | |
126 | |
127 This variable may be updated implicitly by GDB via | |
128 `gdb-thread-list-handler-custom' or explicitly by | |
129 `gdb-select-thread'.") | |
130 | |
120 (defvar gdb-selected-frame nil) | 131 (defvar gdb-selected-frame nil) |
121 (defvar gdb-selected-file nil) | 132 (defvar gdb-selected-file nil) |
122 (defvar gdb-selected-line nil) | 133 (defvar gdb-selected-line nil) |
123 (defvar gdb-frame-number nil) | |
124 (defvar gdb-current-language nil) | 134 (defvar gdb-current-language nil) |
125 (defvar gdb-var-list nil | 135 (defvar gdb-var-list nil |
126 "List of variables in watch window. | 136 "List of variables in watch window. |
127 Each element has the form (VARNUM EXPRESSION NUMCHILD TYPE VALUE STATUS) where | 137 Each element has the form (VARNUM EXPRESSION NUMCHILD TYPE VALUE STATUS) where |
128 STATUS is nil (unchanged), `changed' or `out-of-scope'.") | 138 STATUS is nil (unchanged), `changed' or `out-of-scope'.") |
1189 (setq gdb-token-number (1+ gdb-token-number)) | 1199 (setq gdb-token-number (1+ gdb-token-number)) |
1190 (setcar item (concat (number-to-string gdb-token-number) (car item))) | 1200 (setcar item (concat (number-to-string gdb-token-number) (car item))) |
1191 (push (cons gdb-token-number (car (cdr item))) gdb-handler-alist) | 1201 (push (cons gdb-token-number (car (cdr item))) gdb-handler-alist) |
1192 (process-send-string (get-buffer-process gud-comint-buffer) | 1202 (process-send-string (get-buffer-process gud-comint-buffer) |
1193 (concat (car item) "\n"))) | 1203 (concat (car item) "\n"))) |
1204 | |
1205 (defmacro gdb-current-context-command (command) | |
1206 "Add --thread option to gdb COMMAND. | |
1207 | |
1208 Option value is taken from `gdb-thread-number'." | |
1209 (concat command " --thread " gdb-thread-number)) | |
1194 | 1210 |
1195 | 1211 |
1196 (defcustom gud-gdb-command-name "gdb -i=mi" | 1212 (defcustom gud-gdb-command-name "gdb -i=mi" |
1197 "Default command to execute an executable under the GDB debugger." | 1213 "Default command to execute an executable under the GDB debugger." |
1198 :type 'string | 1214 :type 'string |
1208 (when gdb-first-prompt | 1224 (when gdb-first-prompt |
1209 (gdb-force-mode-line-update | 1225 (gdb-force-mode-line-update |
1210 (propertize "initializing..." 'face font-lock-variable-name-face)) | 1226 (propertize "initializing..." 'face font-lock-variable-name-face)) |
1211 (gdb-init-1) | 1227 (gdb-init-1) |
1212 (setq gdb-first-prompt nil)) | 1228 (setq gdb-first-prompt nil)) |
1229 ;; We may need to update gdb-thread-number, so we call threads buffer | |
1230 (gdb-get-buffer-create 'gdb-threads-buffer) | |
1231 (gdb-invalidate-threads) | |
1213 (gdb-get-selected-frame) | 1232 (gdb-get-selected-frame) |
1214 (gdb-invalidate-frames) | 1233 (gdb-invalidate-frames) |
1215 ;; Regenerate breakpoints buffer in case it has been inadvertantly deleted. | 1234 ;; Regenerate breakpoints buffer in case it has been inadvertantly deleted. |
1216 (gdb-get-buffer-create 'gdb-breakpoints-buffer) | 1235 (gdb-get-buffer-create 'gdb-breakpoints-buffer) |
1217 (gdb-invalidate-breakpoints) | 1236 (gdb-invalidate-breakpoints) |
1218 (gdb-invalidate-threads) | |
1219 (gdb-get-changed-registers) | 1237 (gdb-get-changed-registers) |
1220 (gdb-invalidate-registers) | 1238 (gdb-invalidate-registers) |
1221 (gdb-invalidate-locals) | 1239 (gdb-invalidate-locals) |
1222 (gdb-invalidate-memory) | 1240 (gdb-invalidate-memory) |
1223 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) | 1241 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) |
1885 (" \\(stopped\\) in " (1 font-lock-warning-face)) | 1903 (" \\(stopped\\) in " (1 font-lock-warning-face)) |
1886 ("\\(\\(\\sw\\|[_.]\\)+\\)=" (1 font-lock-variable-name-face))) | 1904 ("\\(\\(\\sw\\|[_.]\\)+\\)=" (1 font-lock-variable-name-face))) |
1887 "Font lock keywords used in `gdb-threads-mode'.") | 1905 "Font lock keywords used in `gdb-threads-mode'.") |
1888 | 1906 |
1889 (defvar gdb-threads-mode-map | 1907 (defvar gdb-threads-mode-map |
1890 ;; TODO | 1908 (let ((map (make-sparse-keymap))) |
1891 (make-sparse-keymap)) | 1909 (define-key map " " 'gdb-select-thread) |
1910 map)) | |
1892 | 1911 |
1893 (defvar gdb-breakpoints-header | 1912 (defvar gdb-breakpoints-header |
1894 (list | 1913 (list |
1895 (gdb-propertize-header "Breakpoints" gdb-breakpoints-buffer | 1914 (gdb-propertize-header "Breakpoints" gdb-breakpoints-buffer |
1896 nil nil mode-line) | 1915 nil nil mode-line) |
1906 (setq major-mode 'gdb-threads-mode) | 1925 (setq major-mode 'gdb-threads-mode) |
1907 (setq mode-name "Threads") | 1926 (setq mode-name "Threads") |
1908 (use-local-map gdb-threads-mode-map) | 1927 (use-local-map gdb-threads-mode-map) |
1909 (setq buffer-read-only t) | 1928 (setq buffer-read-only t) |
1910 (buffer-disable-undo) | 1929 (buffer-disable-undo) |
1930 (setq gdb-thread-position (make-marker)) | |
1931 (add-to-list 'overlay-arrow-variable-list 'gdb-thread-position) | |
1911 (setq header-line-format gdb-breakpoints-header) | 1932 (setq header-line-format gdb-breakpoints-header) |
1912 (set (make-local-variable 'font-lock-defaults) | 1933 (set (make-local-variable 'font-lock-defaults) |
1913 '(gdb-threads-font-lock-keywords)) | 1934 '(gdb-threads-font-lock-keywords)) |
1914 (run-mode-hooks 'gdb-threads-mode-hook) | 1935 (run-mode-hooks 'gdb-threads-mode-hook) |
1915 'gdb-invalidate-threads) | 1936 'gdb-invalidate-threads) |
1916 | 1937 |
1917 (defun gdb-thread-list-handler-custom () | 1938 (defun gdb-thread-list-handler-custom () |
1918 (let* ((res (json-partial-output)) | 1939 (let* ((res (json-partial-output)) |
1919 (threads-list (gdb-get-field res 'threads))) | 1940 (threads-list (gdb-get-field res 'threads)) |
1941 (current-thread (gdb-get-field res 'current-thread-id))) | |
1942 (when (and current-thread | |
1943 (not (string-equal current-thread gdb-thread-number))) | |
1944 ;; Implicitly switch thread (in case previous one dies) | |
1945 (message (concat "GDB switched to another thread: " current-thread)) | |
1946 (setq gdb-thread-number current-thread)) | |
1947 (set-marker gdb-thread-position nil) | |
1920 (dolist (thread threads-list) | 1948 (dolist (thread threads-list) |
1921 (insert (apply 'format `("%s (%s) %s in %s " | 1949 (insert (apply 'format `("%s (%s) %s in %s " |
1922 ,@(gdb-get-many-fields thread 'id 'target-id 'state) | 1950 ,@(gdb-get-many-fields thread 'id 'target-id 'state) |
1923 ,(gdb-get-field thread 'frame 'func)))) | 1951 ,(gdb-get-field thread 'frame 'func)))) |
1924 ;; Arguments | 1952 ;; Arguments |
1927 (dolist (arg args) | 1955 (dolist (arg args) |
1928 (insert (apply 'format `("%s=%s" ,@(gdb-get-many-fields arg 'name 'value))))) | 1956 (insert (apply 'format `("%s=%s" ,@(gdb-get-many-fields arg 'name 'value))))) |
1929 (when args (kill-backward-chars 1))) | 1957 (when args (kill-backward-chars 1))) |
1930 (insert ")") | 1958 (insert ")") |
1931 (gdb-insert-frame-location (gdb-get-field thread 'frame)) | 1959 (gdb-insert-frame-location (gdb-get-field thread 'frame)) |
1932 (insert (format " at %s\n" (gdb-get-field thread 'frame 'addr)))))) | 1960 (insert (format " at %s" (gdb-get-field thread 'frame 'addr))) |
1961 (add-text-properties (line-beginning-position) | |
1962 (line-end-position) | |
1963 `(gdb-thread ,thread)) | |
1964 (when (string-equal gdb-thread-number | |
1965 (gdb-get-field thread 'id)) | |
1966 (set-marker gdb-thread-position (line-beginning-position))) | |
1967 (newline)))) | |
1968 | |
1969 (defun gdb-select-thread () | |
1970 "Select the thread at current line of threads buffer." | |
1971 (interactive) | |
1972 (save-excursion | |
1973 (beginning-of-line) | |
1974 (let ((thread (get-text-property (point) 'gdb-thread))) | |
1975 (if thread | |
1976 (if (string-equal (gdb-get-field thread 'state) "running") | |
1977 (error "Cannot select running thread") | |
1978 (let ((new-id (gdb-get-field thread 'id))) | |
1979 (setq gdb-thread-number new-id) | |
1980 (gud-basic-call (concat "-thread-select " new-id)))) | |
1981 (error "Not recognized as thread line"))))) | |
1933 | 1982 |
1934 | 1983 |
1935 ;;; Memory view | 1984 ;;; Memory view |
1936 | 1985 |
1937 (defcustom gdb-memory-rows 8 | 1986 (defcustom gdb-memory-rows 8 |
2515 'gdb-stack-buffer-name | 2564 'gdb-stack-buffer-name |
2516 'gdb-frames-mode) | 2565 'gdb-frames-mode) |
2517 | 2566 |
2518 (def-gdb-auto-updated-buffer gdb-stack-buffer | 2567 (def-gdb-auto-updated-buffer gdb-stack-buffer |
2519 gdb-invalidate-frames | 2568 gdb-invalidate-frames |
2520 "-stack-list-frames" | 2569 (gdb-current-context-command "-stack-list-frames") |
2521 gdb-stack-list-frames-handler | 2570 gdb-stack-list-frames-handler |
2522 gdb-stack-list-frames-custom) | 2571 gdb-stack-list-frames-custom) |
2523 | 2572 |
2524 (defun gdb-insert-frame-location (frame) | 2573 (defun gdb-insert-frame-location (frame) |
2525 "Insert \"of file:line\" button or library name for structure FRAME. | 2574 "Insert \"of file:line\" button or library name for structure FRAME. |
2629 'gdb-locals-buffer-name | 2678 'gdb-locals-buffer-name |
2630 'gdb-locals-mode) | 2679 'gdb-locals-mode) |
2631 | 2680 |
2632 (def-gdb-auto-update-trigger gdb-invalidate-locals | 2681 (def-gdb-auto-update-trigger gdb-invalidate-locals |
2633 (gdb-get-buffer 'gdb-locals-buffer) | 2682 (gdb-get-buffer 'gdb-locals-buffer) |
2634 "-stack-list-locals --simple-values" | 2683 (concat (gdb-current-context-command "-stack-list-locals") " --simple-values") |
2635 gdb-stack-list-locals-handler) | 2684 gdb-stack-list-locals-handler) |
2636 | 2685 |
2637 (defconst gdb-stack-list-locals-regexp | 2686 (defconst gdb-stack-list-locals-regexp |
2638 (concat "name=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")) | 2687 (concat "name=\"\\(.*?\\)\",type=\"\\(.*?\\)\"")) |
2639 | 2688 |
2757 'gdb-registers-buffer-name | 2806 'gdb-registers-buffer-name |
2758 'gdb-registers-mode) | 2807 'gdb-registers-mode) |
2759 | 2808 |
2760 (def-gdb-auto-update-trigger gdb-invalidate-registers | 2809 (def-gdb-auto-update-trigger gdb-invalidate-registers |
2761 (gdb-get-buffer 'gdb-registers-buffer) | 2810 (gdb-get-buffer 'gdb-registers-buffer) |
2762 "-data-list-register-values x" | 2811 (concat (gdb-current-context-command "-data-list-register-values") " x") |
2763 gdb-data-list-register-values-handler) | 2812 gdb-data-list-register-values-handler) |
2764 | 2813 |
2765 (defconst gdb-data-list-register-values-regexp | 2814 (defconst gdb-data-list-register-values-regexp |
2766 "number=\"\\(.*?\\)\",value=\"\\(.*?\\)\"") | 2815 "number=\"\\(.*?\\)\",value=\"\\(.*?\\)\"") |
2767 | 2816 |
2891 | 2940 |
2892 (defun gdb-get-selected-frame () | 2941 (defun gdb-get-selected-frame () |
2893 (if (not (member 'gdb-get-selected-frame gdb-pending-triggers)) | 2942 (if (not (member 'gdb-get-selected-frame gdb-pending-triggers)) |
2894 (progn | 2943 (progn |
2895 (gdb-input | 2944 (gdb-input |
2896 (list "-stack-info-frame" 'gdb-frame-handler)) | 2945 (list (gdb-current-context-command "-stack-info-frame") 'gdb-frame-handler)) |
2897 (push 'gdb-get-selected-frame | 2946 (push 'gdb-get-selected-frame |
2898 gdb-pending-triggers)))) | 2947 gdb-pending-triggers)))) |
2899 | 2948 |
2900 (defun gdb-frame-handler () | 2949 (defun gdb-frame-handler () |
2901 (setq gdb-pending-triggers | 2950 (setq gdb-pending-triggers |