View | Details | Raw Unified | Return to bug 198022 | Differences between
and this patch

Collapse All | Expand All

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

Return to bug 198022