Mercurial > emacs
comparison lisp/progmodes/gdb-mi.el @ 103752:dcd3d86fcf81
* progmodes/gdb-mi.el (gdb-init-1): Disassembly buffer mode name
may contain frame information, so `string-match' should be used.
(gdb-update): Disassembly is invalidated through
`gdb-get-selected-frame'.
(gdb-pad-string): New function to pad string with spaces.
(gdb-invalidate-disassembly): Invalidate only if the buffer
exists.
(gdb-disassembly-handler-custom): Column alignment.
(gdb-disassembly-place-breakpoints): Clear old breakpoints before
placing new ones.
(gdb-toggle-breakpoint, gdb-delete-breakpoint): Now work from the
end of line, too.
(gdb-frame-handler): Match convention to for disassembly buffer
mode name.
author | Dmitry Dzhus <dima@sphinx.net.ru> |
---|---|
date | Tue, 07 Jul 2009 17:36:42 +0000 |
parents | 47e338b0e07b |
children | bd7c204d425b |
comparison
equal
deleted
inserted
replaced
103751:47e338b0e07b | 103752:dcd3d86fcf81 |
---|---|
5 ;; Author: Nick Roberts <nickrob@gnu.org> | 5 ;; Author: Nick Roberts <nickrob@gnu.org> |
6 ;; Maintainer: FSF | 6 ;; Maintainer: FSF |
7 ;; Keywords: unix, tools | 7 ;; Keywords: unix, tools |
8 | 8 |
9 ;; This file is part of GNU Emacs. | 9 ;; This file is part of GNU Emacs. |
10 | |
11 ;; Homepage: http://www.emacswiki.org/emacs/GDB-MI | |
10 | 12 |
11 ;; GNU Emacs is free software: you can redistribute it and/or modify | 13 ;; GNU Emacs is free software: you can redistribute it and/or modify |
12 ;; it under the terms of the GNU General Public License as published by | 14 ;; it under the terms of the GNU General Public License as published by |
13 ;; the Free Software Foundation, either version 3 of the License, or | 15 ;; the Free Software Foundation, either version 3 of the License, or |
14 ;; (at your option) any later version. | 16 ;; (at your option) any later version. |
386 (setq gud-running nil) | 388 (setq gud-running nil) |
387 (gdb-update) | 389 (gdb-update) |
388 (run-hooks 'gdb-mode-hook)) | 390 (run-hooks 'gdb-mode-hook)) |
389 | 391 |
390 (defun gdb-init-1 () | 392 (defun gdb-init-1 () |
391 (gud-def gud-break (if (not (string-equal mode-name "Disassembly")) | 393 (gud-def gud-break (if (not (string-match "Disassembly" mode-name)) |
392 (gud-call "break %f:%l" arg) | 394 (gud-call "break %f:%l" arg) |
393 (save-excursion | 395 (save-excursion |
394 (beginning-of-line) | 396 (beginning-of-line) |
395 (forward-char 2) | 397 (forward-char 2) |
396 (gud-call "break *%a" arg))) | 398 (gud-call "break *%a" arg))) |
397 "\C-b" "Set breakpoint at current line or address.") | 399 "\C-b" "Set breakpoint at current line or address.") |
398 ;; | 400 ;; |
399 (gud-def gud-remove (if (not (string-equal mode-name "Disassembly")) | 401 (gud-def gud-remove (if (not (string-match "Disassembly" mode-name)) |
400 (gud-call "clear %f:%l" arg) | 402 (gud-call "clear %f:%l" arg) |
401 (save-excursion | 403 (save-excursion |
402 (beginning-of-line) | 404 (beginning-of-line) |
403 (forward-char 2) | 405 (forward-char 2) |
404 (gud-call "clear *%a" arg))) | 406 (gud-call "clear *%a" arg))) |
405 "\C-d" "Remove breakpoint at current line or address.") | 407 "\C-d" "Remove breakpoint at current line or address.") |
406 ;; | 408 ;; |
407 (gud-def gud-until (if (not (string-equal mode-name "Disassembly")) | 409 (gud-def gud-until (if (not (string-match "Disassembly" mode-name)) |
408 (gud-call "-exec-until %f:%l" arg) | 410 (gud-call "-exec-until %f:%l" arg) |
409 (save-excursion | 411 (save-excursion |
410 (beginning-of-line) | 412 (beginning-of-line) |
411 (forward-char 2) | 413 (forward-char 2) |
412 (gud-call "-exec-until *%a" arg))) | 414 (gud-call "-exec-until *%a" arg))) |
1218 (gdb-invalidate-breakpoints) | 1220 (gdb-invalidate-breakpoints) |
1219 (gdb-invalidate-threads) | 1221 (gdb-invalidate-threads) |
1220 (gdb-get-changed-registers) | 1222 (gdb-get-changed-registers) |
1221 (gdb-invalidate-registers) | 1223 (gdb-invalidate-registers) |
1222 (gdb-invalidate-locals) | 1224 (gdb-invalidate-locals) |
1223 (gdb-invalidate-disassembly) | |
1224 (gdb-invalidate-memory) | 1225 (gdb-invalidate-memory) |
1225 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) | 1226 (when (and (boundp 'speedbar-frame) (frame-live-p speedbar-frame)) |
1226 (dolist (var gdb-var-list) | 1227 (dolist (var gdb-var-list) |
1227 (setcar (nthcdr 5 var) nil)) | 1228 (setcar (nthcdr 5 var) nil)) |
1228 (gdb-var-update))) | 1229 (gdb-var-update))) |
1464 (insert "}") | 1465 (insert "}") |
1465 (goto-char (point-min)) | 1466 (goto-char (point-min)) |
1466 (let ((json-array-type 'list)) | 1467 (let ((json-array-type 'list)) |
1467 (json-read)))) | 1468 (json-read)))) |
1468 | 1469 |
1470 (defun gdb-pad-string (string padding) | |
1471 (format (concat "%" (number-to-string padding) "s") string)) | |
1472 | |
1469 (defalias 'gdb-get-field 'bindat-get-field) | 1473 (defalias 'gdb-get-field 'bindat-get-field) |
1470 | 1474 |
1471 (defun gdb-get-many-fields (struct &rest fields) | 1475 (defun gdb-get-many-fields (struct &rest fields) |
1472 "Return a list of FIELDS values from STRUCT." | 1476 "Return a list of FIELDS values from STRUCT." |
1473 (let ((values)) | 1477 (let ((values)) |
1500 (delq ',trigger | 1504 (delq ',trigger |
1501 gdb-pending-triggers)) | 1505 gdb-pending-triggers)) |
1502 (let ((buf (gdb-get-buffer ',buf-key))) | 1506 (let ((buf (gdb-get-buffer ',buf-key))) |
1503 (and buf | 1507 (and buf |
1504 (with-current-buffer buf | 1508 (with-current-buffer buf |
1505 (let* ((window (get-buffer-window buf 0)) | 1509 (let*((buffer-read-only nil)) |
1506 (start (window-start window)) | |
1507 (p (window-point window)) | |
1508 (buffer-read-only nil)) | |
1509 (erase-buffer) | 1510 (erase-buffer) |
1510 (set-window-start window start) | |
1511 (set-window-point window p) | |
1512 (,custom-defun))))))) | 1511 (,custom-defun))))))) |
1513 | 1512 |
1514 (defmacro def-gdb-auto-updated-buffer (buf-key | 1513 (defmacro def-gdb-auto-updated-buffer (buf-key |
1515 trigger-name gdb-command | 1514 trigger-name gdb-command |
1516 output-handler-name custom-defun) | 1515 output-handler-name custom-defun) |
1567 (insert | 1566 (insert |
1568 (concat " in " | 1567 (concat " in " |
1569 (propertize (gdb-get-field breakpoint 'func) | 1568 (propertize (gdb-get-field breakpoint 'func) |
1570 'face font-lock-function-name-face))) | 1569 'face font-lock-function-name-face))) |
1571 (gdb-insert-frame-location breakpoint))) | 1570 (gdb-insert-frame-location breakpoint))) |
1572 (at (insert at)) | 1571 (at (insert (concat " " at))) |
1573 (t (insert (gdb-get-field breakpoint 'original-location))))) | 1572 (t (insert (gdb-get-field breakpoint 'original-location))))) |
1574 (add-text-properties (line-beginning-position) | 1573 (add-text-properties (line-beginning-position) |
1575 (line-end-position) | 1574 (line-end-position) |
1576 `(gdb-breakpoint ,breakpoint | 1575 `(gdb-breakpoint ,breakpoint |
1577 mouse-face highlight | 1576 mouse-face highlight |
1901 gdb-memory-rows | 1900 gdb-memory-rows |
1902 gdb-memory-columns) | 1901 gdb-memory-columns) |
1903 gdb-read-memory-handler | 1902 gdb-read-memory-handler |
1904 gdb-read-memory-custom) | 1903 gdb-read-memory-custom) |
1905 | 1904 |
1905 (defun gdb-memory-column-width (size format) | |
1906 "Return length of string with memory unit of SIZE in FORMAT. | |
1907 | |
1908 SIZE is in bytes, as in `gdb-memory-unit'. FORMAT is a string as | |
1909 in `gdb-memory-format'." | |
1910 (let ((format-base (cdr (assoc format | |
1911 '(("x" . 16) | |
1912 ("d" . 10) ("u" . 10) | |
1913 ("o" . 8) | |
1914 ("t" . 2)))))) | |
1915 (if format-base | |
1916 (let ((res (ceiling (log (expt 2.0 (* size 8)) format-base)))) | |
1917 (cond ((string-equal format "x") | |
1918 (+ 2 res)) ; hexadecimal numbers have 0x in front | |
1919 ((or (string-equal format "d") | |
1920 (string-equal format "o")) | |
1921 (1+ res)) | |
1922 (t res))) | |
1923 (error "Unknown format")))) | |
1924 | |
1906 (defun gdb-read-memory-custom () | 1925 (defun gdb-read-memory-custom () |
1907 (let* ((res (json-partial-output)) | 1926 (let* ((res (json-partial-output)) |
1908 (err-msg (gdb-get-field res 'msg))) | 1927 (err-msg (gdb-get-field res 'msg))) |
1909 (if (not err-msg) | 1928 (if (not err-msg) |
1910 (let ((memory (gdb-get-field res 'memory))) | 1929 (let ((memory (gdb-get-field res 'memory))) |
1911 (setq gdb-memory-address (gdb-get-field res 'addr)) | 1930 (setq gdb-memory-address (gdb-get-field res 'addr)) |
1912 (setq gdb-memory-next-page (gdb-get-field res 'next-page)) | 1931 (setq gdb-memory-next-page (gdb-get-field res 'next-page)) |
1913 (setq gdb-memory-prev-page (gdb-get-field res 'prev-page)) | 1932 (setq gdb-memory-prev-page (gdb-get-field res 'prev-page)) |
1914 (setq gdb-memory-last-address gdb-memory-address) | 1933 (setq gdb-memory-last-address gdb-memory-address) |
1915 (dolist (row memory) | 1934 (dolist (row memory) |
1916 (insert (concat (gdb-get-field row 'addr) ": ")) | 1935 (insert (concat (gdb-get-field row 'addr) ":")) |
1917 (dolist (column (gdb-get-field row 'data)) | 1936 (dolist (column (gdb-get-field row 'data)) |
1918 (insert (concat column "\t"))) | 1937 (insert (gdb-pad-string column |
1938 (+ 2 (gdb-memory-column-width | |
1939 gdb-memory-unit | |
1940 gdb-memory-format))))) | |
1919 (newline))) | 1941 (newline))) |
1920 ;; Show last page instead of empty buffer when out of bounds | 1942 ;; Show last page instead of empty buffer when out of bounds |
1921 (progn | 1943 (progn |
1922 (let ((gdb-memory-address gdb-memory-last-address)) | 1944 (let ((gdb-memory-address gdb-memory-last-address)) |
1923 (gdb-invalidate-memory) | 1945 (gdb-invalidate-memory) |
2253 (gdb-set-buffer-rules 'gdb-disassembly-buffer | 2275 (gdb-set-buffer-rules 'gdb-disassembly-buffer |
2254 'gdb-disassembly-buffer-name | 2276 'gdb-disassembly-buffer-name |
2255 'gdb-disassembly-mode) | 2277 'gdb-disassembly-mode) |
2256 | 2278 |
2257 (def-gdb-auto-update-trigger gdb-invalidate-disassembly | 2279 (def-gdb-auto-update-trigger gdb-invalidate-disassembly |
2258 (gdb-get-buffer-create 'gdb-disassembly-buffer) | 2280 (gdb-get-buffer 'gdb-disassembly-buffer) |
2259 (let ((file (or gdb-selected-file gdb-main-file)) | 2281 (let ((file (or gdb-selected-file gdb-main-file)) |
2260 (line (or gdb-selected-line 1))) | 2282 (line (or gdb-selected-line 1))) |
2261 (if file | 2283 (if (not file) (error "Disassembly invalidated with no file selected.") |
2262 (format "-data-disassemble -f %s -l %d -n -1 -- 0\n" file line) | 2284 (format "-data-disassemble -f %s -l %d -n -1 -- 0\n" file line))) |
2263 "")) | |
2264 gdb-disassembly-handler) | 2285 gdb-disassembly-handler) |
2265 | 2286 |
2266 (def-gdb-auto-update-handler | 2287 (def-gdb-auto-update-handler |
2267 gdb-disassembly-handler | 2288 gdb-disassembly-handler |
2268 gdb-invalidate-disassembly | 2289 gdb-invalidate-disassembly |
2306 (run-mode-hooks 'gdb-disassembly-mode-hook) | 2327 (run-mode-hooks 'gdb-disassembly-mode-hook) |
2307 'gdb-invalidate-disassembly) | 2328 'gdb-invalidate-disassembly) |
2308 | 2329 |
2309 (defun gdb-disassembly-handler-custom () | 2330 (defun gdb-disassembly-handler-custom () |
2310 (let* ((res (json-partial-output)) | 2331 (let* ((res (json-partial-output)) |
2311 (instructions (gdb-get-field res 'asm_insns))) | 2332 (instructions (gdb-get-field res 'asm_insns)) |
2312 (dolist (instr instructions) | 2333 (pos 1)) |
2334 (let* ((last-instr (car (last instructions))) | |
2335 (column-padding (+ 2 (string-width | |
2336 (apply 'format | |
2337 `("<%s+%s>:" | |
2338 ,@(gdb-get-many-fields last-instr 'func-name 'offset))))))) | |
2339 (dolist (instr instructions) | |
2313 ;; Put overlay arrow | 2340 ;; Put overlay arrow |
2314 (when (string-equal (gdb-get-field instr 'address) | 2341 (when (string-equal (gdb-get-field instr 'address) |
2315 gdb-pc-address) | 2342 gdb-pc-address) |
2316 (progn | 2343 (progn |
2344 (setq pos (point)) | |
2317 (setq fringe-indicator-alist | 2345 (setq fringe-indicator-alist |
2318 (if (string-equal gdb-frame-number "0") | 2346 (if (string-equal gdb-frame-number "0") |
2319 nil | 2347 nil |
2320 '((overlay-arrow . hollow-right-triangle)))) | 2348 '((overlay-arrow . hollow-right-triangle)))) |
2321 (set-marker gdb-overlay-arrow-position (point)))) | 2349 (set-marker gdb-overlay-arrow-position (point)))) |
2322 (insert (apply 'format `("%s <%s+%s>:\t%s\n" | 2350 (insert |
2323 ,@(gdb-get-many-fields instr 'address 'func-name 'offset 'inst)))))) | 2351 (concat |
2324 (gdb-disassembly-place-breakpoints)) | 2352 (gdb-get-field instr 'address) |
2353 " " | |
2354 (gdb-pad-string (apply 'format `("<%s+%s>:" ,@(gdb-get-many-fields instr 'func-name 'offset))) | |
2355 (- column-padding)) | |
2356 (gdb-get-field instr 'inst) | |
2357 "\n"))) | |
2358 (gdb-disassembly-place-breakpoints) | |
2359 (let ((window (get-buffer-window (current-buffer) 0))) | |
2360 (set-window-point window pos))))) | |
2325 | 2361 |
2326 (defun gdb-disassembly-place-breakpoints () | 2362 (defun gdb-disassembly-place-breakpoints () |
2363 (gdb-remove-breakpoint-icons (point-min) (point-max)) | |
2327 (dolist (breakpoint gdb-breakpoints-list) | 2364 (dolist (breakpoint gdb-breakpoints-list) |
2328 (let ((bptno (gdb-get-field breakpoint 'number)) | 2365 (let ((bptno (gdb-get-field breakpoint 'number)) |
2329 (flag (gdb-get-field breakpoint 'enabled)) | 2366 (flag (gdb-get-field breakpoint 'enabled)) |
2330 (address (gdb-get-field breakpoint 'addr))) | 2367 (address (gdb-get-field breakpoint 'addr))) |
2331 (save-excursion | 2368 (save-excursion |
2384 | 2421 |
2385 (defun gdb-toggle-breakpoint () | 2422 (defun gdb-toggle-breakpoint () |
2386 "Enable/disable breakpoint at current line of breakpoints buffer." | 2423 "Enable/disable breakpoint at current line of breakpoints buffer." |
2387 (interactive) | 2424 (interactive) |
2388 (save-excursion | 2425 (save-excursion |
2426 (beginning-of-line) | |
2389 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) | 2427 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) |
2390 (if breakpoint | 2428 (if breakpoint |
2391 (gud-basic-call | 2429 (gud-basic-call |
2392 (concat (if (string-equal "y" (gdb-get-field breakpoint 'enabled)) | 2430 (concat (if (string-equal "y" (gdb-get-field breakpoint 'enabled)) |
2393 "-break-disable " | 2431 "-break-disable " |
2396 (error "Not recognized as break/watchpoint line"))))) | 2434 (error "Not recognized as break/watchpoint line"))))) |
2397 | 2435 |
2398 (defun gdb-delete-breakpoint () | 2436 (defun gdb-delete-breakpoint () |
2399 "Delete the breakpoint at current line of breakpoints buffer." | 2437 "Delete the breakpoint at current line of breakpoints buffer." |
2400 (interactive) | 2438 (interactive) |
2439 (save-excursion | |
2440 (beginning-of-line) | |
2401 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) | 2441 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) |
2402 (if breakpoint | 2442 (if breakpoint |
2403 (gud-basic-call (concat "-break-delete " (gdb-get-field breakpoint 'number))) | 2443 (gud-basic-call (concat "-break-delete " (gdb-get-field breakpoint 'number))) |
2404 (error "Not recognized as break/watchpoint line")))) | 2444 (error "Not recognized as break/watchpoint line"))))) |
2405 | 2445 |
2406 (defun gdb-goto-breakpoint (&optional event) | 2446 (defun gdb-goto-breakpoint (&optional event) |
2407 "Go to the location of breakpoint at current line of | 2447 "Go to the location of breakpoint at current line of |
2408 breakpoints buffer." | 2448 breakpoints buffer." |
2409 (interactive (list last-input-event)) | 2449 (interactive (list last-input-event)) |
2410 (if event (posn-set-point (event-end event))) | 2450 (if event (posn-set-point (event-end event))) |
2411 ;; Hack to stop gdb-goto-breakpoint displaying in GUD buffer. | 2451 ;; Hack to stop gdb-goto-breakpoint displaying in GUD buffer. |
2412 (let ((window (get-buffer-window gud-comint-buffer))) | 2452 (let ((window (get-buffer-window gud-comint-buffer))) |
2413 (if window (save-selected-window (select-window window)))) | 2453 (if window (save-selected-window (select-window window)))) |
2454 (save-excursion | |
2455 (beginning-of-line) | |
2414 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) | 2456 (let ((breakpoint (get-text-property (point) 'gdb-breakpoint))) |
2415 (if breakpoint | 2457 (if breakpoint |
2416 (let ((bptno (gdb-get-field breakpoint 'number)) | 2458 (let ((bptno (gdb-get-field breakpoint 'number)) |
2417 (file (gdb-get-field breakpoint 'file)) | 2459 (file (gdb-get-field breakpoint 'file)) |
2418 (line (gdb-get-field breakpoint 'line))) | 2460 (line (gdb-get-field breakpoint 'line))) |
2424 (display-buffer buffer)))) | 2466 (display-buffer buffer)))) |
2425 (setq gdb-source-window window) | 2467 (setq gdb-source-window window) |
2426 (with-current-buffer buffer | 2468 (with-current-buffer buffer |
2427 (goto-line (string-to-number line)) | 2469 (goto-line (string-to-number line)) |
2428 (set-window-point window (point)))))) | 2470 (set-window-point window (point)))))) |
2429 (error "Not recognized as break/watchpoint line")))) | 2471 (error "Not recognized as break/watchpoint line"))))) |
2430 | 2472 |
2431 | 2473 |
2432 ;; Frames buffer. This displays a perpetually correct bactrack trace. | 2474 ;; Frames buffer. This displays a perpetually correct bactrack trace. |
2433 ;; | 2475 ;; |
2434 (gdb-set-buffer-rules 'gdb-stack-buffer | 2476 (gdb-set-buffer-rules 'gdb-stack-buffer |
2870 (if (gdb-get-buffer 'gdb-locals-buffer) | 2912 (if (gdb-get-buffer 'gdb-locals-buffer) |
2871 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer) | 2913 (with-current-buffer (gdb-get-buffer 'gdb-locals-buffer) |
2872 (setq mode-name (concat "Locals:" gdb-selected-frame)))) | 2914 (setq mode-name (concat "Locals:" gdb-selected-frame)))) |
2873 (if (gdb-get-buffer 'gdb-disassembly-buffer) | 2915 (if (gdb-get-buffer 'gdb-disassembly-buffer) |
2874 (with-current-buffer (gdb-get-buffer 'gdb-disassembly-buffer) | 2916 (with-current-buffer (gdb-get-buffer 'gdb-disassembly-buffer) |
2875 (setq mode-name (concat "Machine:" gdb-selected-frame)))) | 2917 (setq mode-name (concat "Disassembly:" gdb-selected-frame)))) |
2876 (if gud-overlay-arrow-position | 2918 (if gud-overlay-arrow-position |
2877 (let ((buffer (marker-buffer gud-overlay-arrow-position)) | 2919 (let ((buffer (marker-buffer gud-overlay-arrow-position)) |
2878 (position (marker-position gud-overlay-arrow-position))) | 2920 (position (marker-position gud-overlay-arrow-position))) |
2879 (when buffer | 2921 (when buffer |
2880 (with-current-buffer buffer | 2922 (with-current-buffer buffer |