public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Define python hooks
@ 2014-10-25  9:08 nojhan
  2014-10-25 22:57 ` Doug Evans
  0 siblings, 1 reply; 8+ messages in thread
From: nojhan @ 2014-10-25  9:08 UTC (permalink / raw)
  To: gdb

Hello,

I'm currently using several of hook-* and hookpost-* functions with
shell commands.
I was wondering if there was a way to define such hooks in pure python.

For instance, I would like to import a module at startup and use it
across all the hooks to manipulate the output of the hooked commands.

--
nojhan

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

* Re: Define python hooks
  2014-10-25  9:08 Define python hooks nojhan
@ 2014-10-25 22:57 ` Doug Evans
  2014-10-27  9:17   ` nojhan
  0 siblings, 1 reply; 8+ messages in thread
From: Doug Evans @ 2014-10-25 22:57 UTC (permalink / raw)
  To: nojhan; +Cc: gdb

On Sat, Oct 25, 2014 at 2:08 AM, nojhan <nojhan@nojhan.net> wrote:
> Hello,
>
> I'm currently using several of hook-* and hookpost-* functions with
> shell commands.
> I was wondering if there was a way to define such hooks in pure python.
>
> For instance, I would like to import a module at startup and use it
> across all the hooks to manipulate the output of the hooked commands.

Hi.

While one can't directly define hooks in python, one can still invoke
python from hooks.

E.g.

define hookpost-step
python
... python code ...
end
end

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

* Re: Define python hooks
  2014-10-25 22:57 ` Doug Evans
@ 2014-10-27  9:17   ` nojhan
  2014-10-27 23:22     ` Doug Evans
  0 siblings, 1 reply; 8+ messages in thread
From: nojhan @ 2014-10-27  9:17 UTC (permalink / raw)
  To: gdb

Thanks.
I would want to manipulate the output of several existing commands with python.

Is there a way to get the output of the command in python (something
like a gdb.execute that would return the output)?
Or should I use a redirection to a named pipe to communicate with gdb?
Or maybe it would be a better option to overload existing commands
with a python class that would execute them?

--
nojhan

On Sun, Oct 26, 2014 at 12:57 AM, Doug Evans <xdje42@gmail.com> wrote:
> On Sat, Oct 25, 2014 at 2:08 AM, nojhan <nojhan@nojhan.net> wrote:
>> Hello,
>>
>> I'm currently using several of hook-* and hookpost-* functions with
>> shell commands.
>> I was wondering if there was a way to define such hooks in pure python.
>>
>> For instance, I would like to import a module at startup and use it
>> across all the hooks to manipulate the output of the hooked commands.
>
> Hi.
>
> While one can't directly define hooks in python, one can still invoke
> python from hooks.
>
> E.g.
>
> define hookpost-step
> python
> ... python code ...
> end
> end

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

* Re: Define python hooks
  2014-10-27  9:17   ` nojhan
@ 2014-10-27 23:22     ` Doug Evans
  2014-10-28 13:18       ` nojhan
  0 siblings, 1 reply; 8+ messages in thread
From: Doug Evans @ 2014-10-27 23:22 UTC (permalink / raw)
  To: nojhan; +Cc: gdb

gdb.execute (command, to_string=True) will return the output as a python string.

As for what's the best way to go, I'm not sure.

On Mon, Oct 27, 2014 at 2:17 AM, nojhan <nojhan@nojhan.net> wrote:
> Thanks.
> I would want to manipulate the output of several existing commands with python.
>
> Is there a way to get the output of the command in python (something
> like a gdb.execute that would return the output)?
> Or should I use a redirection to a named pipe to communicate with gdb?
> Or maybe it would be a better option to overload existing commands
> with a python class that would execute them?
>
> --
> nojhan
>
> On Sun, Oct 26, 2014 at 12:57 AM, Doug Evans <xdje42@gmail.com> wrote:
>> On Sat, Oct 25, 2014 at 2:08 AM, nojhan <nojhan@nojhan.net> wrote:
>>> Hello,
>>>
>>> I'm currently using several of hook-* and hookpost-* functions with
>>> shell commands.
>>> I was wondering if there was a way to define such hooks in pure python.
>>>
>>> For instance, I would like to import a module at startup and use it
>>> across all the hooks to manipulate the output of the hooked commands.
>>
>> Hi.
>>
>> While one can't directly define hooks in python, one can still invoke
>> python from hooks.
>>
>> E.g.
>>
>> define hookpost-step
>> python
>> ... python code ...
>> end
>> end

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

* Re: Define python hooks
  2014-10-27 23:22     ` Doug Evans
@ 2014-10-28 13:18       ` nojhan
  2014-10-29 18:39         ` Doug Evans
  0 siblings, 1 reply; 8+ messages in thread
From: nojhan @ 2014-10-28 13:18 UTC (permalink / raw)
  To: gdb

The documentation states that "It is valid for a hook to call the
command which it hooks. If this occurs, the hook is not re-executed,
thereby avoiding infinite recursion."
But this does not seems to be true for the python API.

Here what I tried:
1) Defining the hook as a python function that would gdb.execute the
same command. Failed, because then the command is executed twice.
Additionally, I did not find how to access the arguments of the
command.
2) Overload the existing command with a python class binded on the
same command name. Failed because of infinite recursion.
3) Use a named pipe to communicate. Failed (sort of) because one
should sleep a variable amount of time waiting for the pipe to be
consumed before returning to the prompt.

Should I fill a feature request/bug report for points 1 and/or 2?

-- 
nojhan

On Tue, Oct 28, 2014 at 12:22 AM, Doug Evans <xdje42@gmail.com> wrote:
> gdb.execute (command, to_string=True) will return the output as a python string.
>
> As for what's the best way to go, I'm not sure.
>
> On Mon, Oct 27, 2014 at 2:17 AM, nojhan <nojhan@nojhan.net> wrote:
>> Thanks.
>> I would want to manipulate the output of several existing commands with python.
>>
>> Is there a way to get the output of the command in python (something
>> like a gdb.execute that would return the output)?
>> Or should I use a redirection to a named pipe to communicate with gdb?
>> Or maybe it would be a better option to overload existing commands
>> with a python class that would execute them?
>>
>> --
>> nojhan
>>
>> On Sun, Oct 26, 2014 at 12:57 AM, Doug Evans <xdje42@gmail.com> wrote:
>>> On Sat, Oct 25, 2014 at 2:08 AM, nojhan <nojhan@nojhan.net> wrote:
>>>> Hello,
>>>>
>>>> I'm currently using several of hook-* and hookpost-* functions with
>>>> shell commands.
>>>> I was wondering if there was a way to define such hooks in pure python.
>>>>
>>>> For instance, I would like to import a module at startup and use it
>>>> across all the hooks to manipulate the output of the hooked commands.
>>>
>>> Hi.
>>>
>>> While one can't directly define hooks in python, one can still invoke
>>> python from hooks.
>>>
>>> E.g.
>>>
>>> define hookpost-step
>>> python
>>> ... python code ...
>>> end
>>> end

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

* Re: Define python hooks
  2014-10-28 13:18       ` nojhan
@ 2014-10-29 18:39         ` Doug Evans
  2014-11-05 16:50           ` nojhan
  0 siblings, 1 reply; 8+ messages in thread
From: Doug Evans @ 2014-10-29 18:39 UTC (permalink / raw)
  To: nojhan; +Cc: gdb

On Tue, Oct 28, 2014 at 6:17 AM, nojhan <nojhan@nojhan.net> wrote:
> The documentation states that "It is valid for a hook to call the
> command which it hooks. If this occurs, the hook is not re-executed,
> thereby avoiding infinite recursion."
> But this does not seems to be true for the python API.
>
> Here what I tried:
> 1) Defining the hook as a python function that would gdb.execute the
> same command. Failed, because then the command is executed twice.

You mean the hook is executed twice, right?
The docs say the hook won't be executed twice, but executing the
command twice is ok.

I tried a trivial example and couldn't reproduce symptoms of the hook
being executed twice.
This is with current sources and 7.8 (release and branch).

(gdb) define foo
echo Hi there.\n
end
(gdb) define hookpost-foo
echo Me again.\n
python gdb.execute("foo")
end
(gdb) foo
Hi there.
Me again.
Hi there.
(gdb)

> Additionally, I did not find how to access the arguments of the
> command.

I'm not sure what you mean here.
Access the arguments of the command from the hook?
I don't think we support that.

> 2) Overload the existing command with a python class binded on the
> same command name. Failed because of infinite recursion.

Infinite recursion because command -> hook -> command -> hook -> ...
or something else?
Just trying to understand if and how this is different from (1).

If it's easy, providing an example so that we can see it for ourselves
will help.

> 3) Use a named pipe to communicate. Failed (sort of) because one
> should sleep a variable amount of time waiting for the pipe to be
> consumed before returning to the prompt.

I don't understand how this relates to (1) and (2).
Communicate what between whom?

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

* Re: Define python hooks
  2014-10-29 18:39         ` Doug Evans
@ 2014-11-05 16:50           ` nojhan
  2014-12-07 19:59             ` Doug Evans
  0 siblings, 1 reply; 8+ messages in thread
From: nojhan @ 2014-11-05 16:50 UTC (permalink / raw)
  To: gdb

[-- Attachment #1: Type: text/plain, Size: 2033 bytes --]

Here are the three complete examples, I hope this will be more clear.

Or in a gist:
https://gist.github.com/nojhan/c3bc28e2fa0608f21551

-- 
nojhan


On Wed, Oct 29, 2014 at 7:39 PM, Doug Evans <xdje42@gmail.com> wrote:
> On Tue, Oct 28, 2014 at 6:17 AM, nojhan <nojhan@nojhan.net> wrote:
>> The documentation states that "It is valid for a hook to call the
>> command which it hooks. If this occurs, the hook is not re-executed,
>> thereby avoiding infinite recursion."
>> But this does not seems to be true for the python API.
>>
>> Here what I tried:
>> 1) Defining the hook as a python function that would gdb.execute the
>> same command. Failed, because then the command is executed twice.
>
> You mean the hook is executed twice, right?
> The docs say the hook won't be executed twice, but executing the
> command twice is ok.
>
> I tried a trivial example and couldn't reproduce symptoms of the hook
> being executed twice.
> This is with current sources and 7.8 (release and branch).
>
> (gdb) define foo
> echo Hi there.\n
> end
> (gdb) define hookpost-foo
> echo Me again.\n
> python gdb.execute("foo")
> end
> (gdb) foo
> Hi there.
> Me again.
> Hi there.
> (gdb)
>
>> Additionally, I did not find how to access the arguments of the
>> command.
>
> I'm not sure what you mean here.
> Access the arguments of the command from the hook?
> I don't think we support that.
>
>> 2) Overload the existing command with a python class binded on the
>> same command name. Failed because of infinite recursion.
>
> Infinite recursion because command -> hook -> command -> hook -> ...
> or something else?
> Just trying to understand if and how this is different from (1).
>
> If it's easy, providing an example so that we can see it for ourselves
> will help.
>
>> 3) Use a named pipe to communicate. Failed (sort of) because one
>> should sleep a variable amount of time waiting for the pipe to be
>> consumed before returning to the prompt.
>
> I don't understand how this relates to (1) and (2).
> Communicate what between whom?

[-- Attachment #2: test.gdbinit --]
[-- Type: application/octet-stream, Size: 3236 bytes --]


# We want to be able to manipulate the output of GDB with a python function.

#######################################################################
# Example 1: Defining the hook as a python function that would gdb.execute the same command
# Problem: The command is executed twice and we can't access args in the hook.
#######################################################################

python

import gdb

class Run_py(gdb.Command):
    def __init__ (self):
        # Bind to run as if we wanted to replace it
        super (Run_py, self).__init__ ("run_py", gdb.COMMAND_SUPPORT, gdb.COMPLETE_FILENAME)

    def invoke (self, arg, from_tty):
        print("invoke run_py")
        # Call the underlying native command...
        res = gdb.execute("run "+arg, to_string=True)
        # Let's pretend we have a pythonic grep
        # print(pygrep(res))

Run_py()
end

define hook-run
python
# Problem: How to access args?
print("execute run")
res = gdb.execute("run_py", to_string=True)
print(res)
end
end




#######################################################################
# Example 2: overload the command with a python class
# Problem: maximum recursion depth exceeded while calling a Python object
#######################################################################

# python
#
# import gdb
#
# class Run_py(gdb.Command):
#     def __init__ (self):
#         # Bind to run as if we wanted to replace it
#         super (Run_py, self).__init__ ("run", gdb.COMMAND_SUPPORT, gdb.COMPLETE_FILENAME)
#
#     def invoke (self, arg, from_tty):
#         # Call the underlying native command...
#         # ... fails in a recursive trap.
#         res = gdb.execute("run "+arg, to_string=True)
#         # Let's pretend we have a pythonic grep
#         #print(pygrep(res))
#
# Run_py()
# end

#######################################################################
# Example 3: use pipe to communicate with a python program
# Problem: the time taken to load and execute the external python program
#          and thus the ugly sleep hack.
#######################################################################

# # Don't wrap line or the coloring regexp won't work.
# set width 0
#
# # Create a named pipe to get outputs from gdb
# shell test -e /tmp/gdbpipe && rm /tmp/gdbpipe
# shell mkfifo /tmp/gdbpipe
#
# define logging_on
#   # Instead of printing on stdout only, log everything...
#   set logging redirect on
#   # ... in our named pipe.
#   set logging on /tmp/gdbpipe
# end
#
# define logging_off
#   set logging off
#   set logging redirect off
#   # Because both gdb and our commands are writing on the same pipe at the same
#   # time, it is more than probable that gdb will end before our (higher level)
#   # commands.  The gdb prompt will thus render before the result of the command,
#   # which is highly akward. To prevent this, we need to wait before displaying
#   # the prompt again.  The more your commands are complex, the higher you will
#   # need to set this.
#   shell sleep 0.4s
# end
#
# define hook-run
#     # Let's pretend we have a pythonic grep
#     shell cat /tmp/gdbpipe | pygrep "Program received signal" &
#     logging_on
# end
# define hookpost-run
#     logging_off
# end
#



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

* Re: Define python hooks
  2014-11-05 16:50           ` nojhan
@ 2014-12-07 19:59             ` Doug Evans
  0 siblings, 0 replies; 8+ messages in thread
From: Doug Evans @ 2014-12-07 19:59 UTC (permalink / raw)
  To: nojhan; +Cc: gdb

On Wed, Nov 5, 2014 at 8:50 AM, nojhan <nojhan@nojhan.net> wrote:
> Here are the three complete examples, I hope this will be more clear.
>
> Or in a gist:
> https://gist.github.com/nojhan/c3bc28e2fa0608f21551

Hi.

I looked at examples 1 and 2.
Re: #1: The command is executed twice, as expected, but the hook isn't
executed twice,
also as expected

Re: #2: We currently don't provide a way to access the "previous" version
of a command if it is overridden.  That would be a good enhancement alright.

I didn't have time to look at #3.

> On Wed, Oct 29, 2014 at 7:39 PM, Doug Evans <xdje42@gmail.com> wrote:
>> On Tue, Oct 28, 2014 at 6:17 AM, nojhan <nojhan@nojhan.net> wrote:
>>> The documentation states that "It is valid for a hook to call the
>>> command which it hooks. If this occurs, the hook is not re-executed,
>>> thereby avoiding infinite recursion."
>>> But this does not seems to be true for the python API.
>>>
>>> Here what I tried:
>>> 1) Defining the hook as a python function that would gdb.execute the
>>> same command. Failed, because then the command is executed twice.
>>
>> You mean the hook is executed twice, right?
>> The docs say the hook won't be executed twice, but executing the
>> command twice is ok.
>>
>> I tried a trivial example and couldn't reproduce symptoms of the hook
>> being executed twice.
>> This is with current sources and 7.8 (release and branch).
>>
>> (gdb) define foo
>> echo Hi there.\n
>> end
>> (gdb) define hookpost-foo
>> echo Me again.\n
>> python gdb.execute("foo")
>> end
>> (gdb) foo
>> Hi there.
>> Me again.
>> Hi there.
>> (gdb)
>>
>>> Additionally, I did not find how to access the arguments of the
>>> command.
>>
>> I'm not sure what you mean here.
>> Access the arguments of the command from the hook?
>> I don't think we support that.
>>
>>> 2) Overload the existing command with a python class binded on the
>>> same command name. Failed because of infinite recursion.
>>
>> Infinite recursion because command -> hook -> command -> hook -> ...
>> or something else?
>> Just trying to understand if and how this is different from (1).
>>
>> If it's easy, providing an example so that we can see it for ourselves
>> will help.
>>
>>> 3) Use a named pipe to communicate. Failed (sort of) because one
>>> should sleep a variable amount of time waiting for the pipe to be
>>> consumed before returning to the prompt.
>>
>> I don't understand how this relates to (1) and (2).
>> Communicate what between whom?

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

end of thread, other threads:[~2014-12-07 19:59 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-25  9:08 Define python hooks nojhan
2014-10-25 22:57 ` Doug Evans
2014-10-27  9:17   ` nojhan
2014-10-27 23:22     ` Doug Evans
2014-10-28 13:18       ` nojhan
2014-10-29 18:39         ` Doug Evans
2014-11-05 16:50           ` nojhan
2014-12-07 19:59             ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).