|
Link Here
|
|
|
1 |
$FreeBSD$ |
| 2 |
|
| 3 |
This diff is retrieved from http://lists.gnu.org/archive/html/emacs-devel/2015-02/msg00274.html |
| 4 |
|
| 5 |
And traces its origin back to https://gitorious.org/lldb/lldb/commit/40e4dbf |
| 6 |
|
| 7 |
It's also present on Apple's OS site: |
| 8 |
|
| 9 |
http://www.opensource.apple.com/source/lldb/lldb-76/utils/emacs/ |
| 10 |
|
| 11 |
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el |
| 12 |
index 42c5b20..7f2e9c0 100644 |
| 13 |
--- lisp/progmodes/gud.el |
| 14 |
+++ lisp/progmodes/gud.el |
| 15 |
@@ -35,7 +35,7 @@ |
| 16 |
;; kluge with the gud-xdb-directories hack producing gud-dbx-directories. |
| 17 |
;; Derek L. Davies <ddavies@world.std.com> added support for jdb (Java |
| 18 |
;; debugger.) Jan Nieuwenhuizen added support for the Guile REPL (Guile |
| 19 |
-;; debugger). |
| 20 |
+;; debugger). llvm.org added support for lldb. |
| 21 |
|
| 22 |
;;; Code: |
| 23 |
|
| 24 |
@@ -56,7 +56,7 @@ |
| 25 |
|
| 26 |
(defgroup gud nil |
| 27 |
"The \"Grand Unified Debugger\" interface. |
| 28 |
-Supported debuggers include gdb, sdb, dbx, xdb, perldb, |
| 29 |
+Supported debuggers include lldb, gdb, sdb, dbx, xdb, perldb, |
| 30 |
pdb (Python), and jdb." |
| 31 |
:group 'processes |
| 32 |
:group 'tools) |
| 33 |
@@ -141,12 +141,12 @@ Used to gray out relevant toolbar icons.") |
| 34 |
(display-graphic-p) |
| 35 |
(fboundp 'x-show-tip)) |
| 36 |
:visible (memq gud-minor-mode |
| 37 |
- '(gdbmi guiler dbx sdb xdb pdb)) |
| 38 |
+ '(lldb gdbmi guiler dbx sdb xdb pdb)) |
| 39 |
:button (:toggle . gud-tooltip-mode)) |
| 40 |
([refresh] "Refresh" . gud-refresh) |
| 41 |
([run] menu-item "Run" gud-run |
| 42 |
:enable (not gud-running) |
| 43 |
- :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) |
| 44 |
+ :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx jdb))) |
| 45 |
([go] menu-item (if (bound-and-true-p gdb-active-process) |
| 46 |
"Continue" "Run") gud-go |
| 47 |
:visible (and (eq gud-minor-mode 'gdbmi) |
| 48 |
@@ -164,18 +164,18 @@ Used to gray out relevant toolbar icons.") |
| 49 |
([tbreak] menu-item "Temporary Breakpoint" gud-tbreak |
| 50 |
:enable (not gud-running) |
| 51 |
:visible (memq gud-minor-mode |
| 52 |
- '(gdbmi gdb sdb xdb))) |
| 53 |
+ '(lldb gdbmi gdb sdb xdb))) |
| 54 |
([break] menu-item "Set Breakpoint" gud-break |
| 55 |
:enable (not gud-running) |
| 56 |
:visible (gud-tool-bar-item-visible-no-fringe)) |
| 57 |
([up] menu-item "Up Stack" gud-up |
| 58 |
:enable (not gud-running) |
| 59 |
:visible (memq gud-minor-mode |
| 60 |
- '(gdbmi gdb guiler dbx xdb jdb pdb))) |
| 61 |
+ '(lldb gdbmi gdb guiler dbx xdb jdb pdb))) |
| 62 |
([down] menu-item "Down Stack" gud-down |
| 63 |
:enable (not gud-running) |
| 64 |
:visible (memq gud-minor-mode |
| 65 |
- '(gdbmi gdb guiler dbx xdb jdb pdb))) |
| 66 |
+ '(lldb gdbmi gdb guiler dbx xdb jdb pdb))) |
| 67 |
([pp] menu-item "Print S-expression" gud-pp |
| 68 |
:enable (and (not gud-running) |
| 69 |
(bound-and-true-p gdb-active-process)) |
| 70 |
@@ -187,7 +187,7 @@ Used to gray out relevant toolbar icons.") |
| 71 |
"Dump object" |
| 72 |
"Print Dereference") gud-pstar |
| 73 |
:enable (not gud-running) |
| 74 |
- :visible (memq gud-minor-mode '(gdbmi gdb jdb))) |
| 75 |
+ :visible (memq gud-minor-mode '(lldb gdbmi gdb jdb))) |
| 76 |
([print] menu-item "Print Expression" gud-print |
| 77 |
:enable (not gud-running)) |
| 78 |
([watch] menu-item "Watch Expression" gud-watch |
| 79 |
@@ -196,13 +196,13 @@ Used to gray out relevant toolbar icons.") |
| 80 |
([finish] menu-item "Finish Function" gud-finish |
| 81 |
:enable (not gud-running) |
| 82 |
:visible (memq gud-minor-mode |
| 83 |
- '(gdbmi gdb guiler xdb jdb pdb))) |
| 84 |
+ '(lldb gdbmi gdb guiler xdb jdb pdb))) |
| 85 |
([stepi] menu-item "Step Instruction" gud-stepi |
| 86 |
:enable (not gud-running) |
| 87 |
- :visible (memq gud-minor-mode '(gdbmi gdb dbx))) |
| 88 |
+ :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx))) |
| 89 |
([nexti] menu-item "Next Instruction" gud-nexti |
| 90 |
:enable (not gud-running) |
| 91 |
- :visible (memq gud-minor-mode '(gdbmi gdb dbx))) |
| 92 |
+ :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx))) |
| 93 |
([step] menu-item "Step Line" gud-step |
| 94 |
:enable (not gud-running)) |
| 95 |
([next] menu-item "Next Line" gud-next |
| 96 |
@@ -237,7 +237,7 @@ Used to gray out relevant toolbar icons.") |
| 97 |
:visible (not (eq gud-minor-mode 'gdbmi))) |
| 98 |
([menu-bar run] menu-item |
| 99 |
,(propertize "run" 'face 'font-lock-doc-face) gud-run |
| 100 |
- :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) |
| 101 |
+ :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx jdb))) |
| 102 |
([menu-bar go] menu-item |
| 103 |
,(propertize " go " 'face 'font-lock-doc-face) gud-go |
| 104 |
:visible (and (eq gud-minor-mode 'gdbmi) |
| 105 |
@@ -356,6 +356,7 @@ are interpreted specially if present. These are: |
| 106 |
%l -- Number of current source line. |
| 107 |
%e -- Text of the C lvalue or function-call expression surrounding point. |
| 108 |
%a -- Text of the hexadecimal address surrounding point. |
| 109 |
+ %b -- Text of the most recently created breakpoint id. |
| 110 |
%p -- Prefix argument to the command (if any) as a number. |
| 111 |
%c -- Fully qualified class name derived from the expression |
| 112 |
surrounding point (jdb only). |
| 113 |
@@ -964,6 +965,131 @@ SKIP is the number of chars to skip on each line, it defaults to 0." |
| 114 |
|
| 115 |
|
| 116 |
;; ====================================================================== |
| 117 |
+;; lldb functions |
| 118 |
+ |
| 119 |
+;; History of argument lists passed to lldb. |
| 120 |
+(defvar gud-lldb-history nil) |
| 121 |
+ |
| 122 |
+;; Keeps track of breakpoint created. In the following case, the id is "1". |
| 123 |
+;; It is used to implement temporary breakpoint. |
| 124 |
+;; (lldb) b main.c:39 |
| 125 |
+;; breakpoint set --file 'main.c' --line 39 |
| 126 |
+;; Breakpoint created: 1: file ='main.c', line = 39, locations = 1 |
| 127 |
+(defvar gud-breakpoint-id nil) |
| 128 |
+ |
| 129 |
+(defun lldb-extract-breakpoint-id (string) |
| 130 |
+ ;; Search for "Breakpoint created: \\([^:\n]*\\):" pattern. |
| 131 |
+ (if (string-match "Breakpoint created: \\([^:\n]*\\):" string) |
| 132 |
+ (progn |
| 133 |
+ (setq gud-breakpoint-id (match-string 1 string)) |
| 134 |
+ (message "breakpoint id: %s" gud-breakpoint-id))) |
| 135 |
+) |
| 136 |
+ |
| 137 |
+(defun gud-lldb-marker-filter (string) |
| 138 |
+ (setq gud-marker-acc |
| 139 |
+ (if gud-marker-acc (concat gud-marker-acc string) string)) |
| 140 |
+ (lldb-extract-breakpoint-id gud-marker-acc) |
| 141 |
+ (let (start) |
| 142 |
+ ;; Process all complete markers in this chunk |
| 143 |
+ (while (or |
| 144 |
+ ;; (lldb) r |
| 145 |
+ ;; Process 15408 launched: '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) |
| 146 |
+ ;; (lldb) Process 15408 stopped |
| 147 |
+ ;; * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread |
| 148 |
+ (string-match " at \\([^:\n]*\\):\\([0-9]*\\), stop reason = .*\n" |
| 149 |
+ gud-marker-acc start) |
| 150 |
+ ;; (lldb) frame select -r 1 |
| 151 |
+ ;; frame #1: 0x0000000100000e09 a.out`main + 25 at main.c:44 |
| 152 |
+ (string-match "\nframe.* at \\([^:\n]*\\):\\([0-9]*\\)\n" |
| 153 |
+ gud-marker-acc start)) |
| 154 |
+ (setq gud-last-frame |
| 155 |
+ (cons (match-string 1 gud-marker-acc) |
| 156 |
+ (string-to-number (match-string 2 gud-marker-acc))) |
| 157 |
+ start (match-end 0))) |
| 158 |
+ |
| 159 |
+ ;; Search for the last incomplete line in this chunk |
| 160 |
+ (while (string-match "\n" gud-marker-acc start) |
| 161 |
+ (setq start (match-end 0))) |
| 162 |
+ |
| 163 |
+ ;; If we have an incomplete line, store it in gud-marker-acc. |
| 164 |
+ (setq gud-marker-acc (substring gud-marker-acc (or start 0)))) |
| 165 |
+ string) |
| 166 |
+ |
| 167 |
+;; Keeps track of whether the Python lldb_oneshot_break function definition has |
| 168 |
+;; been exec'ed. |
| 169 |
+(defvar lldb-oneshot-break-defined nil) |
| 170 |
+ |
| 171 |
+;;;###autoload |
| 172 |
+(defun lldb (command-line) |
| 173 |
+ "Run lldb on program FILE in buffer *gud-FILE*. |
| 174 |
+The directory containing FILE becomes the initial working directory |
| 175 |
+and source-file directory for your debugger." |
| 176 |
+ (interactive (list (gud-query-cmdline 'lldb))) |
| 177 |
+ |
| 178 |
+ (gud-common-init command-line nil 'gud-lldb-marker-filter) |
| 179 |
+ (set (make-local-variable 'gud-minor-mode) 'lldb) |
| 180 |
+ (setq lldb-oneshot-break-defined nil) |
| 181 |
+ |
| 182 |
+ (gud-def gud-listb "breakpoint list" |
| 183 |
+ "l" "List all breakpoints.") |
| 184 |
+ (gud-def gud-bt "thread backtrace" |
| 185 |
+ "b" "Show stack for the current thread.") |
| 186 |
+ (gud-def gud-bt-all "thread backtrace all" |
| 187 |
+ "B" "Show stacks for all the threads.") |
| 188 |
+ |
| 189 |
+ (gud-def gud-break "breakpoint set -f %f -l %l" |
| 190 |
+ "\C-b" "Set breakpoint at current line.") |
| 191 |
+ (gud-def gud-tbreak |
| 192 |
+ (progn (gud-call "breakpoint set -f %f -l %l") |
| 193 |
+ (sit-for 1) |
| 194 |
+ (if (not lldb-oneshot-break-defined) |
| 195 |
+ (progn |
| 196 |
+ ;; The "\\n"'s are required to escape the newline chars |
| 197 |
+ ;; passed to the lldb process. |
| 198 |
+ (gud-call (concat "script exec \"def lldb_oneshot_break(frame, bp_loc):\\n" |
| 199 |
+ " target=frame.GetThread().GetProcess().GetTarget()\\n" |
| 200 |
+ " bp=bp_loc.GetBreakpoint()\\n" |
| 201 |
+ " print 'Deleting oneshot breakpoint:', bp\\n" |
| 202 |
+ " target.BreakpointDelete(bp.GetID())\"")) |
| 203 |
+ (sit-for 1) |
| 204 |
+ ;; Set the flag since Python knows about the function def now. |
| 205 |
+ (setq lldb-oneshot-break-defined t))) |
| 206 |
+ (gud-call "breakpoint command add -p %b -o 'lldb_oneshot_break(frame, bp_loc)'")) |
| 207 |
+ "\C-t" "Set temporary breakpoint at current line.") |
| 208 |
+ (gud-def gud-remove "breakpoint clear -f %f -l %l" |
| 209 |
+ "\C-d" "Remove breakpoint at current line") |
| 210 |
+ (gud-def gud-step "thread step-in" |
| 211 |
+ "\C-s" "Step one source line with display.") |
| 212 |
+ (gud-def gud-stepi "thread step-inst" |
| 213 |
+ "\C-i" "Step one instruction with display.") |
| 214 |
+ (gud-def gud-next "thread step-over" |
| 215 |
+ "\C-n" "Step one line (skip functions).") |
| 216 |
+ (gud-def gud-nexti "thread step-inst-over" |
| 217 |
+ nil "Step one instruction (skip functions).") |
| 218 |
+ (gud-def gud-cont "process continue" |
| 219 |
+ "\C-r" "Continue with display.") |
| 220 |
+ (gud-def gud-finish "thread step-out" |
| 221 |
+ "\C-f" "Finish executing current function.") |
| 222 |
+ (gud-def gud-up "frame select -r %p" |
| 223 |
+ "<" "Up 1 stack frame.") |
| 224 |
+ (gud-def gud-down "frame select -r -%p" |
| 225 |
+ ">" "Down 1 stack frame.") |
| 226 |
+ (gud-def gud-print "expression -- %e" |
| 227 |
+ "\C-p" "Evaluate C expression at point.") |
| 228 |
+ (gud-def gud-pstar "expression -- *%e" |
| 229 |
+ nil "Evaluate C dereferenced pointer expression at point.") |
| 230 |
+ (gud-def gud-run "run" |
| 231 |
+ nil "Run the program.") |
| 232 |
+ (gud-def gud-stop-subjob "process kill" |
| 233 |
+ nil "Stop the program.") |
| 234 |
+ |
| 235 |
+ (setq comint-prompt-regexp "\\(^\\|\n\\)\\*") |
| 236 |
+ (setq paragraph-start comint-prompt-regexp) |
| 237 |
+ (run-hooks 'lldb-mode-hook) |
| 238 |
+ ) |
| 239 |
+ |
| 240 |
+ |
| 241 |
+;; ====================================================================== |
| 242 |
;; sdb functions |
| 243 |
|
| 244 |
;; History of argument lists passed to sdb. |
| 245 |
@@ -2499,9 +2625,10 @@ gud, see `gud-mode'." |
| 246 |
"Major mode for interacting with an inferior debugger process. |
| 247 |
|
| 248 |
You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx, |
| 249 |
-M-x perldb, M-x xdb, or M-x jdb. Each entry point finishes by executing a |
| 250 |
-hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook', |
| 251 |
-`perldb-mode-hook', `xdb-mode-hook', or `jdb-mode-hook' respectively. |
| 252 |
+M-x perldb, M-x xdb, M-x jdb, or M-x lldb. Each entry point finishes by |
| 253 |
+executing a hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook', |
| 254 |
+`perldb-mode-hook', `xdb-mode-hook', `jdb-mode-hook', or `lldb-mode-hook' |
| 255 |
+respectively. |
| 256 |
|
| 257 |
After startup, the following commands are available in both the GUD |
| 258 |
interaction buffer and any source buffer GUD visits due to a breakpoint stop |
| 259 |
@@ -2531,7 +2658,7 @@ Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break], |
| 260 |
except that the breakpoint is temporary; that is, it is removed when |
| 261 |
execution stops on it. |
| 262 |
|
| 263 |
-Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack |
| 264 |
+Under gdb, dbx, xdb, and lldb, \\[gud-up] pops up through an enclosing stack |
| 265 |
frame. \\[gud-down] drops back down through one. |
| 266 |
|
| 267 |
If you are using gdb or xdb, \\[gud-finish] runs execution to the return from |
| 268 |
@@ -2858,7 +2985,7 @@ Obeying it means displaying in another window the specified file and line." |
| 269 |
result) |
| 270 |
(while (and str |
| 271 |
(let ((case-fold-search nil)) |
| 272 |
- (string-match "\\([^%]*\\)%\\([adefFlpc]\\)" str))) |
| 273 |
+ (string-match "\\([^%]*\\)%\\([abdefFlpc]\\)" str))) |
| 274 |
(let ((key (string-to-char (match-string 2 str))) |
| 275 |
subst) |
| 276 |
(cond |
| 277 |
@@ -2886,6 +3013,8 @@ Obeying it means displaying in another window the specified file and line." |
| 278 |
(setq subst (gud-find-expr))) |
| 279 |
((eq key ?a) |
| 280 |
(setq subst (gud-read-address))) |
| 281 |
+ ((eq key ?b) |
| 282 |
+ (setq subst gud-breakpoint-id)) |
| 283 |
((eq key ?c) |
| 284 |
(setq subst |
| 285 |
(gud-find-class |
| 286 |
@@ -3520,6 +3649,7 @@ With arg, dereference expr if ARG is positive, otherwise do not dereference." |
| 287 |
(defun gud-tooltip-print-command (expr) |
| 288 |
"Return a suitable command to print the expression EXPR." |
| 289 |
(pcase gud-minor-mode |
| 290 |
+ (`lldb (concat "expression -o -- \"" expr "\"")) |
| 291 |
(`gdbmi (concat "-data-evaluate-expression \"" expr "\"")) |
| 292 |
(`guiler expr) |
| 293 |
(`dbx (concat "print " expr)) |