all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Executing Emacs commands when a gdb breakpoint is hit
@ 2020-01-21 18:02 Skip Montanaro
  2020-01-21 18:39 ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Skip Montanaro @ 2020-01-21 18:02 UTC (permalink / raw)
  To: Help GNU Emacs

It's straightforward to create user-defined GDB commands which trigger upon
hitting a breakpoint. I'd like to also execute some ELisp though. That
seems not so obvious. Is this doable?

Here's a concrete example. I'm working on the Python bytecode compiler. The
primary compiler struct contains the name of the file being compiled (along
with much other stuff), and one of its fields refers to a compile_unit
which holds the current line number of the Python file as the compilation
progresses.

The compiler_setlineno function is a perfect place to break. I'd like to
switch to the buffer holding the file being compiled and set point to the
current line number, thus updating my view of the where the compilation is.

On a more basic topic, I actually seem unable to cleanly terminate the
series of commands to execute upon hitting a breakpoint. For example, this
is what I see now (within an Emacs *gud-python* buffer):

(gdb) comm 2
Type commands for breakpoint(s) 2, one per line.
End with a line saying just "end".
>p c->c_filename
>p c->u->u_lineno
>end
>
>end
>  C-c C-cQuit

That is, I do what it says, end with a line saying just "end", but it
doesn't terminate. After trying that a second time, I gave up and I broke
back to the (gdb) prompt with C-c C-c. Seems like a bug to me. I'm using
25.2.2 on Ubuntu 18.04.

Skip


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-21 18:02 Executing Emacs commands when a gdb breakpoint is hit Skip Montanaro
@ 2020-01-21 18:39 ` Eli Zaretskii
  2020-01-22 13:48   ` Skip Montanaro
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2020-01-21 18:39 UTC (permalink / raw)
  To: help-gnu-emacs

> From: Skip Montanaro <skip.montanaro@gmail.com>
> Date: Tue, 21 Jan 2020 12:02:49 -0600
> 
> On a more basic topic, I actually seem unable to cleanly terminate the
> series of commands to execute upon hitting a breakpoint. For example, this
> is what I see now (within an Emacs *gud-python* buffer):
> 
> (gdb) comm 2
> Type commands for breakpoint(s) 2, one per line.
> End with a line saying just "end".
> >p c->c_filename
> >p c->u->u_lineno
> >end
> >
> >end
> >  C-c C-cQuit
> 
> That is, I do what it says, end with a line saying just "end", but it
> doesn't terminate. After trying that a second time, I gave up and I broke
> back to the (gdb) prompt with C-c C-c. Seems like a bug to me. I'm using
> 25.2.2 on Ubuntu 18.04.

Upgrade to a newer Emacs.  This problem was fixed in Emacs 26.2.  A
workaround is to use "commands" instead of its short form "comm".



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-21 18:39 ` Eli Zaretskii
@ 2020-01-22 13:48   ` Skip Montanaro
  2020-01-22 17:04     ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Skip Montanaro @ 2020-01-22 13:48 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Help GNU Emacs

>
> Upgrade to a newer Emacs.  This problem was fixed in Emacs 26.2.  A
> workaround is to use "commands" instead of its short form "comm".
>

Thanks. That's taken care of. Now, is it possible to trigger an Emacs Lisp
function of some sort when a GDB breakpoint is hit? I see the
gdb-stopped-functions variable. This simple function seems to execute when
my compiler_set_lineno breakpoint is hit:

(defun stopped (reason)
  (message "%s" reason))

(setq gdb-stopped-functions '(stopped))

I worked out a more complex stopped function which was supposed to get the
filename and current line number of the Python file being compiled. I was
able to execute the bits interactively to get the values I needed.
Unfortunately, the function is called before *gud-python* has a prompt
(it's not really ready for input). This is the key function which plucks
expression values from the *gud-python* session:

(defun get-gdb-value (expr)
  "evaluate EXPR in *gud-python* buffer and return as a string"
  (with-current-buffer "*gud-python*"
    (save-excursion
      (goto-char (point-max))
      (insert (concat "print " expr))
      (comint-send-input)
      (goto-char (point-max))
      (forward-line -1)
      (move-beginning-of-line nil)
      (search-forward " = '")
      (push-mark)
      (search-forward "'")
      (backward-char 1)
      (buffer-substring-no-properties (mark) (point))
      (pop-mark))))

It's called from my registered stop function like so:

    ...
     (let ((fname (get-gdb-value "c->c_filename"))
            (lineno (string-to-number (get-gdb-value "c->u->u_lineno")))
    ...

I tried sticking in a short sleep, but that didn't help. Is there a way to
force the *gud-python* to be ready for user input before calling
get-gdb-value?

Thanks,

Skip


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-22 13:48   ` Skip Montanaro
@ 2020-01-22 17:04     ` Eli Zaretskii
  2020-01-22 19:55       ` otadmor .
  2020-01-22 21:07       ` Skip Montanaro
  0 siblings, 2 replies; 10+ messages in thread
From: Eli Zaretskii @ 2020-01-22 17:04 UTC (permalink / raw)
  To: help-gnu-emacs

> From: Skip Montanaro <skip.montanaro@gmail.com>
> Date: Wed, 22 Jan 2020 07:48:17 -0600
> Cc: Help GNU Emacs <help-gnu-emacs@gnu.org>
> 
> Now, is it possible to trigger an Emacs Lisp function of some sort when a GDB
> breakpoint is hit? I see the gdb-stopped-functions variable. This simple function seems to execute when my
> compiler_set_lineno breakpoint is hit:
> 
> (defun stopped (reason)
>   (message "%s" reason))
> 
> (setq gdb-stopped-functions '(stopped))

So you already have the answer to that question: gdb-stopped-functions.

> I tried sticking in a short sleep, but that didn't help. Is there a way to force the *gud-python* to be ready for
> user input before calling get-gdb-value?

I don't think I understand what you are trying to do and what are the
difficulties, sorry.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-22 17:04     ` Eli Zaretskii
@ 2020-01-22 19:55       ` otadmor .
  2020-01-22 21:07       ` Skip Montanaro
  1 sibling, 0 replies; 10+ messages in thread
From: otadmor . @ 2020-01-22 19:55 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: help-gnu-emacs

I would like to suggest a bit different approach.
I have a code allowing auto-completions from external programs running
inside a comint buffer.
It uses epc server running in emacs (elisp) and python-epc client. It
allows me to complete, for example, gdb commands for the gdb running
inside the comint buffer. The same code can call other server methods
to notify a gdb stop event.
The python code is loaded automatically into gdb using ~/.gdbinit, and
the elisp code is stored in ~/.emacs.d.
The completion code supports auto-complete, company and
complete-at-point frontends and support python and frida backends.
It seems easy to add the support for gdb stop events and I actually
planned on doing it in the future when I will have time, I just dont
have the time :-)

On Wed, Jan 22, 2020 at 7:05 PM Eli Zaretskii <eliz@gnu.org> wrote:
>
> > From: Skip Montanaro <skip.montanaro@gmail.com>
> > Date: Wed, 22 Jan 2020 07:48:17 -0600
> > Cc: Help GNU Emacs <help-gnu-emacs@gnu.org>
> >
> > Now, is it possible to trigger an Emacs Lisp function of some sort when a GDB
> > breakpoint is hit? I see the gdb-stopped-functions variable. This simple function seems to execute when my
> > compiler_set_lineno breakpoint is hit:
> >
> > (defun stopped (reason)
> >   (message "%s" reason))
> >
> > (setq gdb-stopped-functions '(stopped))
>
> So you already have the answer to that question: gdb-stopped-functions.
>
> > I tried sticking in a short sleep, but that didn't help. Is there a way to force the *gud-python* to be ready for
> > user input before calling get-gdb-value?
>
> I don't think I understand what you are trying to do and what are the
> difficulties, sorry.
>


-- 
Gretz,
Ofir Tadmor

ICQ: 77685691
Mail: otadmor@gmail.com



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-22 17:04     ` Eli Zaretskii
  2020-01-22 19:55       ` otadmor .
@ 2020-01-22 21:07       ` Skip Montanaro
  2020-01-23 14:45         ` Eli Zaretskii
  1 sibling, 1 reply; 10+ messages in thread
From: Skip Montanaro @ 2020-01-22 21:07 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Help GNU Emacs

> I don't think I understand what you are trying to do and what are the
> difficulties, sorry.

My apologies. As is so often true with things we work on, it's easy to
forget that others aren't as steeped in our problems. It's easy to
assume more of one's audience. Here's some more detail.

I'm working on the Python bytecode compiler. It's written in C. As I
work my way through the process, I want to know where the compiler is
currently working. The compiler maintains a number of C structs
throughout the process. At the top level is the compiler struct. Here
I've only displayed the two fields of interest to me. The c_filename
field names the file being compiled. The compiler_unit * field refers
to a subsidiary struct which contains (among other bits) the current
line and column offset of the current statement being compiled.

struct compiler {
    PyObject *c_filename;
    ...
    struct compiler_unit *u; /* compiler state for current block */
    ...
};

struct compiler_unit {
    ...
    int u_lineno;          /* the lineno for the current stmt */
    int u_col_offset;      /* the offset of the current stmt */
    ...
};

So, I run Python under control of gdb and set a breakpoint in a
specific function, compiler_set_lineno. When this breakpoint is
reached, I want to query gdb for the current values of c->c_filename
and c->u->u_lineno. The first argument to that function is struct
compiler *c. Eventually, I will likely be interested in more fields of
either of these structs, but for the purposes of interacting with gdb,
this is sufficient.

I wrote an ELisp function which is an element of the
gdb-stopped-functions list. It gets called at the appropriate place
when the breakpoint is encountered. I get a useful reason argument for
the stoppage and, in particular, can tell whether or not the stoppage
occurred in compiler_set_lineno. When this is the case (I might have
breakpoints set elsewhere, so would want to bail out if that was the
case), I want to evaluate the current Python filename, line number and
column. That allows me to update display of the Python file within
Emacs and so get a bit of visual context for where the compiler is
working. (It works from an abstract syntax tree which is pretty low
level. Viewing the compilation context in the source file is quite
useful.)

The problem I encounter is that the underlying gdb process doesn't
seem to be ready to receive input when my stop function is executed.
It appears to have been stopped, but the (gdb) prompt isn't visible in
the *gud-python* buffer. I want to print the desired expression with
(comint-send-input), then read the result. Perhaps I should just set a
gdb-level command to print the desired expressions instead. My ELisp
code would only then need to read the values from *gud-python*. The
advantage of doing everything from within my ELisp stop function is
that everything relevant to this display lives in one place. I don't
have to synchronize my ELisp with user-level gdb commands.

Perhaps there is a comint function which will update the *gud-python*
buffer so the (gdb) prompt is visible and the underlying gdb process
is truly ready for (comint-send-input)?

Skip



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-22 21:07       ` Skip Montanaro
@ 2020-01-23 14:45         ` Eli Zaretskii
  2020-01-23 21:00           ` Skip Montanaro
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2020-01-23 14:45 UTC (permalink / raw)
  To: help-gnu-emacs

> From: Skip Montanaro <skip.montanaro@gmail.com>
> Date: Wed, 22 Jan 2020 15:07:57 -0600
> Cc: Help GNU Emacs <help-gnu-emacs@gnu.org>
> 
> The problem I encounter is that the underlying gdb process doesn't
> seem to be ready to receive input when my stop function is executed.
> It appears to have been stopped, but the (gdb) prompt isn't visible in
> the *gud-python* buffer. I want to print the desired expression with
> (comint-send-input), then read the result. Perhaps I should just set a
> gdb-level command to print the desired expressions instead. My ELisp
> code would only then need to read the values from *gud-python*. The
> advantage of doing everything from within my ELisp stop function is
> that everything relevant to this display lives in one place. I don't
> have to synchronize my ELisp with user-level gdb commands.
> 
> Perhaps there is a comint function which will update the *gud-python*
> buffer so the (gdb) prompt is visible and the underlying gdb process
> is truly ready for (comint-send-input)?

You could define a timer that runs your function after some small
delay, maybe it could work.

But in general, I must admit I find this design somewhat strange.  GDB
offers you 3 extension languages: the CLI scripting, Python, and Guile
Scheme.  Why not use one of these to do what you want? this is how the
GDB developers intended for you to extend the debugger for doing these
kinds of jobs.  If you use Guile, you could even write code that is
almost Emacs Lisp ;-)




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-23 14:45         ` Eli Zaretskii
@ 2020-01-23 21:00           ` Skip Montanaro
  2020-01-24  8:01             ` Eli Zaretskii
  0 siblings, 1 reply; 10+ messages in thread
From: Skip Montanaro @ 2020-01-23 21:00 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Help GNU Emacs

>
> You could define a timer that runs your function after some small
> delay, maybe it could work.
>

A quarter-second sleep didn't help. I'll poke around a bit more.

> But in general, I must admit I find this design somewhat strange.  GDB
> offers you 3 extension languages: the CLI scripting, Python, and Guile
> Scheme.  Why not use one of these to do what you want? this is how the
> GDB developers intended for you to extend the debugger for doing these
> kinds of jobs.  If you use Guile, you could even write code that is
> almost Emacs Lisp ;-)
>

Note that I'm not really trying to script GDB. I'm trying to adjust the
display in Emacs of the file which is being compiled. It seems to me that
the proper language for that is ELisp.

It seems that the shortest route to something which will/might work will be
adding commands for GDB to execute when the breakpoint is hit. Something
like this:

(gdb) comm N
> p c->c_filename
> p c->u->u_lineno
> end

When my stop function gets called, all I need to do is search back in
*gud-python* for the printed line number and filename. I initially
dispensed with that idea though, since doing things that way means I need
an ELisp component (to grab the details I want and adjust the Emacs
display) and a GDB component. If I had (for example) two different stop
functions in my list (I don't currently), it's not clear how I'd guarantee
the two functions didn't step on one anothers' toes.

Skip


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-23 21:00           ` Skip Montanaro
@ 2020-01-24  8:01             ` Eli Zaretskii
  2020-04-07 20:21               ` otadmor .
  0 siblings, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2020-01-24  8:01 UTC (permalink / raw)
  To: help-gnu-emacs

> From: Skip Montanaro <skip.montanaro@gmail.com>
> Date: Thu, 23 Jan 2020 15:00:16 -0600
> Cc: Help GNU Emacs <help-gnu-emacs@gnu.org>
> 
>  But in general, I must admit I find this design somewhat strange.  GDB
>  offers you 3 extension languages: the CLI scripting, Python, and Guile
>  Scheme.  Why not use one of these to do what you want? this is how the
>  GDB developers intended for you to extend the debugger for doing these
>  kinds of jobs.  If you use Guile, you could even write code that is
>  almost Emacs Lisp ;-)
> 
> Note that I'm not really trying to script GDB. I'm trying to adjust the display in Emacs of the file which is being
> compiled. It seems to me that the proper language for that is ELisp.

Emacs displays stuff by following the responses from GDB.  So
injecting such responses (by scripting GDB) will eventually allow you
to solve your problem, either entirely in the scripting commands, or
if customizing what Emacs does via the existing hooks.

My point is that you shouldn't ask yourself "how do I run an Emacs
function when a breakpoint is hit", because there's no way of doing
that.  This question encourages the line of thinking that leads you to
write code that cannot work well, because this line of thinking is
based on incorrect assumptions.

> If I had (for
> example) two different stop functions in my list (I don't currently), it's not clear how I'd guarantee the two
> functions didn't step on one anothers' toes.

The hook function receives the parsed MI response as its argument, so
each function can decide whether it does anything in each case.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Executing Emacs commands when a gdb breakpoint is hit
  2020-01-24  8:01             ` Eli Zaretskii
@ 2020-04-07 20:21               ` otadmor .
  0 siblings, 0 replies; 10+ messages in thread
From: otadmor . @ 2020-04-07 20:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: help-gnu-emacs

See example in
https://github.com/otadmor/emacs-conf/blob/master/gdb.gif

On Fri, Jan 24, 2020 at 10:01 AM Eli Zaretskii <eliz@gnu.org> wrote:
>
> > From: Skip Montanaro <skip.montanaro@gmail.com>
> > Date: Thu, 23 Jan 2020 15:00:16 -0600
> > Cc: Help GNU Emacs <help-gnu-emacs@gnu.org>
> >
> >  But in general, I must admit I find this design somewhat strange.  GDB
> >  offers you 3 extension languages: the CLI scripting, Python, and Guile
> >  Scheme.  Why not use one of these to do what you want? this is how the
> >  GDB developers intended for you to extend the debugger for doing these
> >  kinds of jobs.  If you use Guile, you could even write code that is
> >  almost Emacs Lisp ;-)
> >
> > Note that I'm not really trying to script GDB. I'm trying to adjust the display in Emacs of the file which is being
> > compiled. It seems to me that the proper language for that is ELisp.
>
> Emacs displays stuff by following the responses from GDB.  So
> injecting such responses (by scripting GDB) will eventually allow you
> to solve your problem, either entirely in the scripting commands, or
> if customizing what Emacs does via the existing hooks.
>
> My point is that you shouldn't ask yourself "how do I run an Emacs
> function when a breakpoint is hit", because there's no way of doing
> that.  This question encourages the line of thinking that leads you to
> write code that cannot work well, because this line of thinking is
> based on incorrect assumptions.
>
> > If I had (for
> > example) two different stop functions in my list (I don't currently), it's not clear how I'd guarantee the two
> > functions didn't step on one anothers' toes.
>
> The hook function receives the parsed MI response as its argument, so
> each function can decide whether it does anything in each case.
>


-- 
Gretz,
Ofir Tadmor

ICQ: 77685691
Mail: otadmor@gmail.com



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-04-07 20:21 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-01-21 18:02 Executing Emacs commands when a gdb breakpoint is hit Skip Montanaro
2020-01-21 18:39 ` Eli Zaretskii
2020-01-22 13:48   ` Skip Montanaro
2020-01-22 17:04     ` Eli Zaretskii
2020-01-22 19:55       ` otadmor .
2020-01-22 21:07       ` Skip Montanaro
2020-01-23 14:45         ` Eli Zaretskii
2020-01-23 21:00           ` Skip Montanaro
2020-01-24  8:01             ` Eli Zaretskii
2020-04-07 20:21               ` otadmor .

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.