Re: Define python hooks

nojhan
2014-11-05T16:50:37Z

[-- 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
#