From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Contributing LLVM.org patches to gud.el Date: Thu, 05 Feb 2015 09:15:36 -0500 Message-ID: References: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1423146177 24057 80.91.229.3 (5 Feb 2015 14:22:57 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 5 Feb 2015 14:22:57 +0000 (UTC) Cc: emacs-devel@gnu.org To: "Andrew L. Moore" Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Feb 05 15:22:56 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1YJNKZ-0005gY-A0 for ged-emacs-devel@m.gmane.org; Thu, 05 Feb 2015 15:22:55 +0100 Original-Received: from localhost ([::1]:42287 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YJNKY-00025T-E9 for ged-emacs-devel@m.gmane.org; Thu, 05 Feb 2015 09:22:54 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:53583) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YJNDc-0007Pa-6m for emacs-devel@gnu.org; Thu, 05 Feb 2015 09:15:46 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YJNDX-0004Lg-W8 for emacs-devel@gnu.org; Thu, 05 Feb 2015 09:15:44 -0500 Original-Received: from chene.dit.umontreal.ca ([132.204.246.20]:37056) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YJNDX-0004KU-NB for emacs-devel@gnu.org; Thu, 05 Feb 2015 09:15:39 -0500 Original-Received: from pastel.home (lechon.iro.umontreal.ca [132.204.27.242]) by chene.dit.umontreal.ca (8.14.1/8.14.1) with ESMTP id t15EFbSt019121; Thu, 5 Feb 2015 09:15:37 -0500 Original-Received: by pastel.home (Postfix, from userid 20848) id 08C53FB3; Thu, 5 Feb 2015 09:15:37 -0500 (EST) In-Reply-To: (Andrew L. Moore's message of "Thu, 5 Feb 2015 02:46:12 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) X-NAI-Spam-Flag: NO X-NAI-Spam-Threshold: 5 X-NAI-Spam-Score: 0 X-NAI-Spam-Rules: 1 Rules triggered RV5208=0 X-NAI-Spam-Version: 2.3.0.9393 : core <5208> : inlines <2034> : streams <1385182> : uri <1847067> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 132.204.246.20 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:182446 Archived-At: > The LLVM source repository includes a patch adding basic lldb support > to gud.el. The patch adapted to current gud.el (Github-mirror commit > 7e09ef09a479731d01b1ca46e94ddadd73ac98e3) is attached below. Although > I=E2=80=99m not affiliated with llvm.org, I=E2=80=99d be interested to kn= ow if and how > this might be accepted into the Emacs distribution, RMS=E2=80=99s opinion= of > LLVM notwithstanding. Thank you! Thanks, Andrew. I'd be happy to incorporate such a patch. I took a quick look at the code, and seen from afar, there's no problem with it, so all that is really needed is to clear the copyright status of this code. IOW, we need to know who is/are the author(s) (contributors of less than about 15 lines of code don't need to be accounted for), and then make sure they have signed a copyright assignment. Stefan > diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el > index 42c5b20..7f2e9c0 100644 > --- a/lisp/progmodes/gud.el > +++ b/lisp/progmodes/gud.el > @@ -35,7 +35,7 @@ > ;; kluge with the gud-xdb-directories hack producing gud-dbx-directories. > ;; Derek L. Davies added support for jdb (Java > ;; debugger.) Jan Nieuwenhuizen added support for the Guile REPL (Guile > -;; debugger). > +;; debugger). llvm.org added support for lldb. =20 > ;;; Code: =20 > @@ -56,7 +56,7 @@ =20 > (defgroup gud nil > "The \"Grand Unified Debugger\" interface. > -Supported debuggers include gdb, sdb, dbx, xdb, perldb, > +Supported debuggers include lldb, gdb, sdb, dbx, xdb, perldb, > pdb (Python), and jdb." > :group 'processes > :group 'tools) > @@ -141,12 +141,12 @@ Used to gray out relevant toolbar icons.") > (display-graphic-p) > (fboundp 'x-show-tip)) > :visible (memq gud-minor-mode > - '(gdbmi guiler dbx sdb xdb pdb)) > + '(lldb gdbmi guiler dbx sdb xdb pdb)) > :button (:toggle . gud-tooltip-mode)) > ([refresh] "Refresh" . gud-refresh) > ([run] menu-item "Run" gud-run > :enable (not gud-running) > - :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) > + :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx jdb))) > ([go] menu-item (if (bound-and-true-p gdb-active-process) > "Continue" "Run") gud-go > :visible (and (eq gud-minor-mode 'gdbmi) > @@ -164,18 +164,18 @@ Used to gray out relevant toolbar icons.") > ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak > :enable (not gud-running) > :visible (memq gud-minor-mode > - '(gdbmi gdb sdb xdb))) > + '(lldb gdbmi gdb sdb xdb))) > ([break] menu-item "Set Breakpoint" gud-break > :enable (not gud-running) > :visible (gud-tool-bar-item-visible-no-fringe)) > ([up] menu-item "Up Stack" gud-up > :enable (not gud-running) > :visible (memq gud-minor-mode > - '(gdbmi gdb guiler dbx xdb jdb pdb))) > + '(lldb gdbmi gdb guiler dbx xdb jdb pdb))) > ([down] menu-item "Down Stack" gud-down > :enable (not gud-running) > :visible (memq gud-minor-mode > - '(gdbmi gdb guiler dbx xdb jdb pdb))) > + '(lldb gdbmi gdb guiler dbx xdb jdb pdb))) > ([pp] menu-item "Print S-expression" gud-pp > :enable (and (not gud-running) > (bound-and-true-p gdb-active-process)) > @@ -187,7 +187,7 @@ Used to gray out relevant toolbar icons.") > "Dump object" > "Print Dereference") gud-pstar > :enable (not gud-running) > - :visible (memq gud-minor-mode '(gdbmi gdb jdb))) > + :visible (memq gud-minor-mode '(lldb gdbmi gdb jdb))) > ([print] menu-item "Print Expression" gud-print > :enable (not gud-running)) > ([watch] menu-item "Watch Expression" gud-watch > @@ -196,13 +196,13 @@ Used to gray out relevant toolbar icons.") > ([finish] menu-item "Finish Function" gud-finish > :enable (not gud-running) > :visible (memq gud-minor-mode > - '(gdbmi gdb guiler xdb jdb pdb))) > + '(lldb gdbmi gdb guiler xdb jdb pdb))) > ([stepi] menu-item "Step Instruction" gud-stepi > :enable (not gud-running) > - :visible (memq gud-minor-mode '(gdbmi gdb dbx))) > + :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx))) > ([nexti] menu-item "Next Instruction" gud-nexti > :enable (not gud-running) > - :visible (memq gud-minor-mode '(gdbmi gdb dbx))) > + :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx))) > ([step] menu-item "Step Line" gud-step > :enable (not gud-running)) > ([next] menu-item "Next Line" gud-next > @@ -237,7 +237,7 @@ Used to gray out relevant toolbar icons.") > :visible (not (eq gud-minor-mode 'gdbmi))) > ([menu-bar run] menu-item > ,(propertize "run" 'face 'font-lock-doc-face) gud-run > - :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb))) > + :visible (memq gud-minor-mode '(lldb gdbmi gdb dbx jdb))) > ([menu-bar go] menu-item > ,(propertize " go " 'face 'font-lock-doc-face) gud-go > :visible (and (eq gud-minor-mode 'gdbmi) > @@ -356,6 +356,7 @@ are interpreted specially if present. These are: > %l -- Number of current source line. > %e -- Text of the C lvalue or function-call expression surrounding poi= nt. > %a -- Text of the hexadecimal address surrounding point. > + %b -- Text of the most recently created breakpoint id. > %p -- Prefix argument to the command (if any) as a number. > %c -- Fully qualified class name derived from the expression > surrounding point (jdb only). > @@ -964,6 +965,131 @@ SKIP is the number of chars to skip on each line, i= t defaults to 0." =20 > > ;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > +;; lldb functions > + > +;; History of argument lists passed to lldb. > +(defvar gud-lldb-history nil) > + > +;; Keeps track of breakpoint created. In the following case, the id is = "1". > +;; It is used to implement temporary breakpoint. > +;; (lldb) b main.c:39 > +;; breakpoint set --file 'main.c' --line 39 > +;; Breakpoint created: 1: file =3D'main.c', line =3D 39, locations =3D 1 > +(defvar gud-breakpoint-id nil) > + > +(defun lldb-extract-breakpoint-id (string) > + ;; Search for "Breakpoint created: \\([^:\n]*\\):" pattern. > + (if (string-match "Breakpoint created: \\([^:\n]*\\):" string) > + (progn > + (setq gud-breakpoint-id (match-string 1 string)) > + (message "breakpoint id: %s" gud-breakpoint-id))) > +) > + > +(defun gud-lldb-marker-filter (string) > + (setq gud-marker-acc > + (if gud-marker-acc (concat gud-marker-acc string) string)) > + (lldb-extract-breakpoint-id gud-marker-acc) > + (let (start) > + ;; Process all complete markers in this chunk > + (while (or > + ;; (lldb) r > + ;; Process 15408 launched: '/Volumes/data/lldb/svn/trunk/tes= t/conditional_break/a.out' (x86_64) > + ;; (lldb) Process 15408 stopped > + ;; * thread #1: tid =3D 0x2e03, 0x0000000100000de8 a.out`c += 7 at main.c:39, stop reason =3D breakpoint 1.1, queue =3D com.apple.main-t= hread > + (string-match " at \\([^:\n]*\\):\\([0-9]*\\), stop reason = =3D .*\n" > + gud-marker-acc start) > + ;; (lldb) frame select -r 1 > + ;; frame #1: 0x0000000100000e09 a.out`main + 25 at main.c:44 > + (string-match "\nframe.* at \\([^:\n]*\\):\\([0-9]*\\)\n" > + gud-marker-acc start)) > + (setq gud-last-frame > + (cons (match-string 1 gud-marker-acc) > + (string-to-number (match-string 2 gud-marker-acc))) > + start (match-end 0))) > + > + ;; Search for the last incomplete line in this chunk > + (while (string-match "\n" gud-marker-acc start) > + (setq start (match-end 0))) > + > + ;; If we have an incomplete line, store it in gud-marker-acc. > + (setq gud-marker-acc (substring gud-marker-acc (or start 0)))) > + string) > + > +;; Keeps track of whether the Python lldb_oneshot_break function definit= ion has > +;; been exec'ed. > +(defvar lldb-oneshot-break-defined nil) > + > +;;;###autoload > +(defun lldb (command-line) > + "Run lldb on program FILE in buffer *gud-FILE*. > +The directory containing FILE becomes the initial working directory > +and source-file directory for your debugger." > + (interactive (list (gud-query-cmdline 'lldb))) > + > + (gud-common-init command-line nil 'gud-lldb-marker-filter) > + (set (make-local-variable 'gud-minor-mode) 'lldb) > + (setq lldb-oneshot-break-defined nil) > + > + (gud-def gud-listb "breakpoint list" > + "l" "List all breakpoints.") > + (gud-def gud-bt "thread backtrace" > + "b" "Show stack for the current thread.") > + (gud-def gud-bt-all "thread backtrace all" > + "B" "Show stacks for all the threads.") > + > + (gud-def gud-break "breakpoint set -f %f -l %l" > + "\C-b" "Set breakpoint at current line.") > + (gud-def gud-tbreak > + (progn (gud-call "breakpoint set -f %f -l %l") > + (sit-for 1) > + (if (not lldb-oneshot-break-defined) > + (progn > + ;; The "\\n"'s are required to escape the newlin= e chars > + ;; passed to the lldb process. > + (gud-call (concat "script exec \"def lldb_onesho= t_break(frame, bp_loc):\\n" > + " target=3Dfr= ame.GetThread().GetProcess().GetTarget()\\n" > + " bp=3Dbp_loc= .GetBreakpoint()\\n" > + " print 'Dele= ting oneshot breakpoint:', bp\\n" > + " target.Brea= kpointDelete(bp.GetID())\"")) > + (sit-for 1) > + ;; Set the flag since Python knows about the fun= ction def now. > + (setq lldb-oneshot-break-defined t))) > + (gud-call "breakpoint command add -p %b -o 'lldb_onesh= ot_break(frame, bp_loc)'")) > + "\C-t" "Set temporary breakpoint at current line.") > + (gud-def gud-remove "breakpoint clear -f %f -l %l" > + "\C-d" "Remove breakpoint at current line") > + (gud-def gud-step "thread step-in" > + "\C-s" "Step one source line with display.") > + (gud-def gud-stepi "thread step-inst" > + "\C-i" "Step one instruction with display.") > + (gud-def gud-next "thread step-over" > + "\C-n" "Step one line (skip functions).") > + (gud-def gud-nexti "thread step-inst-over" > + nil "Step one instruction (skip functions).") > + (gud-def gud-cont "process continue" > + "\C-r" "Continue with display.") > + (gud-def gud-finish "thread step-out" > + "\C-f" "Finish executing current function.") > + (gud-def gud-up "frame select -r %p" > + "<" "Up 1 stack frame.") > + (gud-def gud-down "frame select -r -%p" > + ">" "Down 1 stack frame.") > + (gud-def gud-print "expression -- %e" > + "\C-p" "Evaluate C expression at point.") > + (gud-def gud-pstar "expression -- *%e" > + nil "Evaluate C dereferenced pointer expression= at point.") > + (gud-def gud-run "run" > + nil "Run the program.") > + (gud-def gud-stop-subjob "process kill" > + nil "Stop the program.") > + > + (setq comint-prompt-regexp "\\(^\\|\n\\)\\*") > + (setq paragraph-start comint-prompt-regexp) > + (run-hooks 'lldb-mode-hook) > + ) > + > + > +;; =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > ;; sdb functions =20 > ;; History of argument lists passed to sdb. > @@ -2499,9 +2625,10 @@ gud, see `gud-mode'." > "Major mode for interacting with an inferior debugger process. =20 > You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx, > -M-x perldb, M-x xdb, or M-x jdb. Each entry point finishes by executing= a > -hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook', > -`perldb-mode-hook', `xdb-mode-hook', or `jdb-mode-hook' respectively. > +M-x perldb, M-x xdb, M-x jdb, or M-x lldb. Each entry point finishes by > +executing a hook; `gdb-mode-hook', `sdb-mode-hook', `dbx-mode-hook', > +`perldb-mode-hook', `xdb-mode-hook', `jdb-mode-hook', or `lldb-mode-hook' > +respectively. =20 > After startup, the following commands are available in both the GUD > interaction buffer and any source buffer GUD visits due to a breakpoint = stop > @@ -2531,7 +2658,7 @@ Under gdb, sdb and xdb, \\[gud-tbreak] behaves exac= tly like \\[gud-break], > except that the breakpoint is temporary; that is, it is removed when > execution stops on it. =20 > -Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack > +Under gdb, dbx, xdb, and lldb, \\[gud-up] pops up through an enclosing s= tack > frame. \\[gud-down] drops back down through one. =20 > If you are using gdb or xdb, \\[gud-finish] runs execution to the return= from > @@ -2858,7 +2985,7 @@ Obeying it means displaying in another window the s= pecified file and line." > result) > (while (and str > (let ((case-fold-search nil)) > - (string-match "\\([^%]*\\)%\\([adefFlpc]\\)" str))) > + (string-match "\\([^%]*\\)%\\([abdefFlpc]\\)" str))) > (let ((key (string-to-char (match-string 2 str))) > subst) > (cond > @@ -2886,6 +3013,8 @@ Obeying it means displaying in another window the s= pecified file and line." > (setq subst (gud-find-expr))) > ((eq key ?a) > (setq subst (gud-read-address))) > + ((eq key ?b) > + (setq subst gud-breakpoint-id)) > ((eq key ?c) > (setq subst > (gud-find-class > @@ -3520,6 +3649,7 @@ With arg, dereference expr if ARG is positive, othe= rwise do not dereference." > (defun gud-tooltip-print-command (expr) > "Return a suitable command to print the expression EXPR." > (pcase gud-minor-mode > + (`lldb (concat "expression -o -- \"" expr "\"")) > (`gdbmi (concat "-data-evaluate-expression \"" expr "\"")) > (`guiler expr) > (`dbx (concat "print " expr))