summaryrefslogtreecommitdiff
path: root/lisp/progmodes/gdb-ui.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/gdb-ui.el')
-rw-r--r--lisp/progmodes/gdb-ui.el161
1 files changed, 100 insertions, 61 deletions
diff --git a/lisp/progmodes/gdb-ui.el b/lisp/progmodes/gdb-ui.el
index f5d08d533fd..bb821907aa8 100644
--- a/lisp/progmodes/gdb-ui.el
+++ b/lisp/progmodes/gdb-ui.el
@@ -71,11 +71,11 @@
;;; Known Bugs:
;; 1) Strings that are watched don't update in the speedbar when their
-;; contents change unless the first character changes.
+;; contents change unless the first character changes.
;; 2) Cannot handle multiple debug sessions.
-;; 3) Initially, the assembler buffer does not display the cursor at the
-;; current line if the line is not visible in the window (but when testing
-;; gdb-assembler-custom with a lisp debugger it does!).
+;; 3) M-x gdb doesn't work with "run" command in .gdbinit, use M-x gdba instead.
+;; 4) M-x gdb doesn't work if the corefile is specified in the command in the
+;; minibuffer, use M-x gdba instead (or specify the core in the GUD buffer).
;;; Problems with watch expressions, GDB/MI:
;; 1) They go out of scope when the inferior is re-run.
@@ -83,15 +83,10 @@
;; 3) VARNUM increments even when variable object is not created
;; (maybe trivial).
-;; Known Bugs:
-;; 1) M-x gdb doesn't work with "run" command in .gdbinit, use M-x gdba instead.
-
;;; TODO:
;; 1) Use MI command -data-read-memory for memory window.
;; 2) Use tree-widget.el instead of the speedbar for watch-expressions?
;; 3) Mark breakpoint locations on scroll-bar of source buffer?
-;; 4) With gud-print and gud-pstar, print the variable name in the GUD
-;; buffer instead of the value's history number.
;;; Code:
@@ -130,6 +125,7 @@ and #define directives otherwise.")
(defvar gdb-source-window nil)
(defvar gdb-inferior-status nil)
(defvar gdb-continuation nil)
+(defvar gdb-look-up-stack nil)
(defvar gdb-buffer-type nil
"One of the symbols bound in `gdb-buffer-rules'.")
@@ -430,7 +426,8 @@ With arg, use separate IO iff arg is positive."
(when gud-tooltip-mode
(make-local-variable 'gdb-define-alist)
(gdb-create-define-alist)
- (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))))
+ (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))
+ (gdb-force-mode-line-update "ready"))
(defun gdb-find-watch-expression ()
(let* ((var (nth (- (line-number-at-pos (point)) 2) gdb-var-list))
@@ -493,26 +490,28 @@ With arg, use separate IO iff arg is positive."
'gdb-mouse-set-clear-breakpoint)
(define-key gud-minor-mode-map [left-fringe mouse-1]
'gdb-mouse-set-clear-breakpoint)
- (define-key gud-minor-mode-map [left-fringe mouse-2]
- 'gdb-mouse-until)
+ (define-key gud-minor-mode-map [left-margin C-mouse-1]
+ 'gdb-mouse-toggle-breakpoint-margin)
+ (define-key gud-minor-mode-map [left-fringe C-mouse-1]
+ 'gdb-mouse-toggle-breakpoint-fringe)
+
(define-key gud-minor-mode-map [left-margin drag-mouse-1]
'gdb-mouse-until)
(define-key gud-minor-mode-map [left-fringe drag-mouse-1]
'gdb-mouse-until)
- (define-key gud-minor-mode-map [left-margin mouse-2]
+ (define-key gud-minor-mode-map [left-margin mouse-3]
+ 'gdb-mouse-until)
+ (define-key gud-minor-mode-map [left-fringe mouse-3]
'gdb-mouse-until)
+
(define-key gud-minor-mode-map [left-margin C-drag-mouse-1]
'gdb-mouse-jump)
(define-key gud-minor-mode-map [left-fringe C-drag-mouse-1]
'gdb-mouse-jump)
- (define-key gud-minor-mode-map [left-fringe C-mouse-2]
+ (define-key gud-minor-mode-map [left-fringe C-mouse-3]
'gdb-mouse-jump)
- (define-key gud-minor-mode-map [left-margin C-mouse-2]
+ (define-key gud-minor-mode-map [left-margin C-mouse-3]
'gdb-mouse-jump)
- (define-key gud-minor-mode-map [left-margin mouse-3]
- 'gdb-mouse-toggle-breakpoint-margin)
- (define-key gud-minor-mode-map [left-fringe mouse-3]
- 'gdb-mouse-toggle-breakpoint-fringe)
(setq comint-input-sender 'gdb-send)
@@ -543,7 +542,8 @@ With arg, use separate IO iff arg is positive."
gdb-signalled nil
gdb-source-window nil
gdb-inferior-status nil
- gdb-continuation nil)
+ gdb-continuation nil
+ gdb-look-up-stack nil)
(setq gdb-buffer-type 'gdba)
@@ -738,7 +738,7 @@ With arg, enter name of variable to be watched in the minibuffer."
`(lambda () (gdb-var-evaluate-expression-handler
,(car var) nil)))))
(if (search-forward "Undefined command" nil t)
- (message-box "Watching expressions requires gdb 6.0 onwards")
+ (message-box "Watching expressions requires GDB 6.0 onwards")
(message-box "No symbol \"%s\" in current context." expr))))
(defun gdb-speedbar-update ()
@@ -1106,7 +1106,8 @@ This filter may simply queue input for a later time."
(let ((item (concat string "\n")))
(if gdb-enable-debug (push (cons 'send item) gdb-debug-ring))
(process-send-string proc item)))
- (if (string-match "\\\\$" string)
+ (if (and (string-match "\\\\$" string)
+ (not comint-input-sender-no-newline)) ;;Try to catch C-d.
(setq gdb-continuation (concat gdb-continuation string "\n"))
(let ((item (concat gdb-continuation string "\n")))
(gdb-enqueue-input item)
@@ -1238,6 +1239,7 @@ happens to be in effect."
"An annotation handler for `prompt'.
This sends the next command (if any) to gdb."
(when gdb-first-prompt
+ (gdb-force-mode-line-update "initializing...")
(gdb-init-1)
(setq gdb-first-prompt nil))
(let ((sink gdb-output-sink))
@@ -1334,9 +1336,20 @@ directives."
It is just like `gdb-stopping', except that if we already set the output
sink to `user' in `gdb-stopping', that is fine."
(setq gud-running nil)
- (unless (or gud-overlay-arrow-position gud-last-frame
- (not gud-last-last-frame))
- (gud-display-line (car gud-last-last-frame) (cdr gud-last-last-frame)))
+ (unless (or gud-overlay-arrow-position gud-last-frame)
+ ;;Pop up GUD buffer to display current frame when it doesn't have source
+ ;;information i.e id not compiled with -g as with libc routines generally.
+ (let ((special-display-regexps (append special-display-regexps '(".*")))
+ (special-display-frame-alist gdb-frame-parameters)
+ (same-window-regexps nil))
+ (display-buffer gud-comint-buffer))
+ ;;Try to find source further up stack e.g after signal.
+ (setq gdb-look-up-stack
+ (if (gdb-get-buffer 'gdb-stack-buffer) 'keep
+ (progn
+ (gdb-get-buffer-create 'gdb-stack-buffer)
+ (gdb-invalidate-frames)
+ 'delete))))
(unless (member gdb-inferior-status '("exited" "signal"))
(setq gdb-inferior-status "stopped")
(gdb-force-mode-line-update gdb-inferior-status))
@@ -1945,36 +1958,57 @@ static char *magick[] = {
(defun gdb-info-stack-custom ()
(with-current-buffer (gdb-get-buffer 'gdb-stack-buffer)
(save-excursion
- (let ((buffer-read-only nil)
- bl el)
- (goto-char (point-min))
- (while (< (point) (point-max))
- (setq bl (line-beginning-position)
- el (line-end-position))
- (when (looking-at "#")
- (add-text-properties bl el
- '(mouse-face highlight
- help-echo "mouse-2, RET: Select frame")))
- (goto-char bl)
- (when (looking-at "^#\\([0-9]+\\)")
- (when (string-equal (match-string 1) gdb-frame-number)
+ (unless (eq gdb-look-up-stack 'delete)
+ (let ((buffer-read-only nil)
+ bl el)
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (setq bl (line-beginning-position)
+ el (line-end-position))
+ (when (looking-at "#")
+ (add-text-properties bl el
+ '(mouse-face highlight
+ help-echo "mouse-2, RET: Select frame")))
+ (goto-char bl)
+ (when (looking-at "^#\\([0-9]+\\)")
+ (when (string-equal (match-string 1) gdb-frame-number)
(put-text-property bl (+ bl 4)
'face '(:inverse-video t)))
- (when (re-search-forward
- (concat
- (if (string-equal (match-string 1) "0") "" " in ")
- "\\([^ ]+\\) (") el t)
- (put-text-property (match-beginning 1) (match-end 1)
- 'face font-lock-function-name-face)
- (setq bl (match-end 0))
- (while (re-search-forward "<\\([^>]+\\)>" el t)
+ (when (re-search-forward
+ (concat
+ (if (string-equal (match-string 1) "0") "" " in ")
+ "\\([^ ]+\\) (") el t)
(put-text-property (match-beginning 1) (match-end 1)
+ 'face font-lock-function-name-face)
+ (setq bl (match-end 0))
+ (while (re-search-forward "<\\([^>]+\\)>" el t)
+ (put-text-property (match-beginning 1) (match-end 1)
'face font-lock-function-name-face))
- (goto-char bl)
- (while (re-search-forward "\\(\\(\\sw\\|[_.]\\)+\\)=" el t)
- (put-text-property (match-beginning 1) (match-end 1)
- 'face font-lock-variable-name-face))))
- (forward-line 1))))))
+ (goto-char bl)
+ (while (re-search-forward "\\(\\(\\sw\\|[_.]\\)+\\)=" el t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'face font-lock-variable-name-face))))
+ (forward-line 1))))
+ (when gdb-look-up-stack
+ (goto-char (point-min))
+ (when (re-search-forward "\\(\\S-+?\\):\\([0-9]+\\)" nil t)
+ (let ((start (line-beginning-position))
+ (file (match-string 1))
+ (line (match-string 2)))
+ (re-search-backward "^#*\\([0-9]+\\)" start t)
+ (gdb-enqueue-input
+ (list (concat gdb-server-prefix "frame "
+ (match-string 1) "\n") 'gdb-set-hollow))
+ (gdb-enqueue-input
+ (list (concat gdb-server-prefix "frame 0\n") 'ignore)))))))
+ (if (eq gdb-look-up-stack 'delete)
+ (kill-buffer (gdb-get-buffer 'gdb-stack-buffer)))
+ (setq gdb-look-up-stack nil))
+
+(defun gdb-set-hollow ()
+ (with-current-buffer (gud-find-file (car gud-last-last-frame))
+ (setq fringe-indicator-alist
+ '((overlay-arrow . hollow-right-triangle)))))
(defun gdb-stack-buffer-name ()
(with-current-buffer gud-comint-buffer
@@ -2030,8 +2064,7 @@ static char *magick[] = {
(if event (posn-set-point (event-end event)))
(gdb-enqueue-input
(list (concat gdb-server-prefix "frame "
- (gdb-get-frame-number) "\n") 'ignore))
- (gud-display-frame))
+ (gdb-get-frame-number) "\n") 'ignore)))
;; Threads buffer. This displays a selectable thread list.
@@ -2049,13 +2082,14 @@ static char *magick[] = {
(defun gdb-info-threads-custom ()
(with-current-buffer (gdb-get-buffer 'gdb-threads-buffer)
(let ((buffer-read-only nil))
- (goto-char (point-min))
- (while (< (point) (point-max))
- (unless (looking-at "No ")
- (add-text-properties (line-beginning-position) (line-end-position)
- '(mouse-face highlight
+ (save-excursion
+ (goto-char (point-min))
+ (while (< (point) (point-max))
+ (unless (looking-at "No ")
+ (add-text-properties (line-beginning-position) (line-end-position)
+ '(mouse-face highlight
help-echo "mouse-2, RET: select thread")))
- (forward-line 1)))))
+ (forward-line 1))))))
(defun gdb-threads-buffer-name ()
(with-current-buffer gud-comint-buffer
@@ -2868,7 +2902,11 @@ of the current session."
gud-comint-buffer
(memq (buffer-local-value 'gud-minor-mode gud-comint-buffer)
'(gdba gdbmi)))
- (if (member buffer-file-name gdb-source-file-list)
+ ;;Pre GDB 6.3 "info sources" doesn't give absolute file name.
+ (if (member (if (string-equal gdb-version "pre-6.4")
+ (file-name-nondirectory buffer-file-name)
+ buffer-file-name)
+ gdb-source-file-list)
(with-current-buffer (find-buffer-visiting buffer-file-name)
(set (make-local-variable 'gud-minor-mode)
(buffer-local-value 'gud-minor-mode gud-comint-buffer))
@@ -3203,7 +3241,8 @@ is set in them."
(when gud-tooltip-mode
(make-local-variable 'gdb-define-alist)
(gdb-create-define-alist)
- (add-hook 'after-save-hook 'gdb-create-define-alist nil t))))))
+ (add-hook 'after-save-hook 'gdb-create-define-alist nil t)))))
+ (gdb-force-mode-line-update "ready"))
; Uses "-var-list-children --all-values". Needs GDB 6.1 onwards.
(defun gdb-var-list-children-1 (varnum)