* Python Scripting Question @ 2009-11-08 15:08 Arjun Roy 2009-11-09 17:16 ` Tom Tromey 0 siblings, 1 reply; 10+ messages in thread From: Arjun Roy @ 2009-11-08 15:08 UTC (permalink / raw) To: gdb I have a question regarding the python scripting capabilities for GDB. (running GDB on Fedora 11). I'd like to be able to figure out the instruction mix for an arbitrary program. I know I could step through it using nexti and disassemble, but would like to script it out using python. So a couple of questions: 1. I'm getting some buggy behavior when I do the following: (gdb) run Starting program Breakpoint 1, main () at test.c:3 3 long i = 0; (gdb) python >gdb.execute("disassemble $pc $pc+1") >gdb.execute("disassemble $pc $pc+1") >end Dump of assembler code from 0x400478 to 0x400479: 0x0000000000400478 <main+4>: movq $0x0,-0x8(%rbp) End of assembler dump. Traceback (most recent call last): File "<string>", line 2, in <module> TypeError: argument 1 must be string without null bytes, not str Error while executing Python code. Basically, running gdb.execute on the same disassemble statement (which I assume should just print out the same asm twice, right?) has an issue. But, if I execute this: (gdb) python >gdb.execute("disassemble $pc $pc+1") >gdb.execute("disassemble $pc+1 $pc+2") >end Dump of assembler code from 0x400478 to 0x400479: 0x0000000000400478 <main+4>: movq $0x0,-0x8(%rbp) End of assembler dump. Dump of assembler code from 0x400479 to 0x40047a: 0x0000000000400479 <main+5>: movl $0x0,-0x8(%rbp) End of assembler dump. Then it works. Is this a bug, am I misunderstanding the right way to do it, or what? 2. Ideally, I'd like to write a really simple script that: - starts running a program - steps through each instruction one by one, recording the opcode for each instruction performed - and stops when the program is over. Does gdb-python support that? The issues I'm having are the one I described above, and also not knowing how to check if the program is done (I know it returns an exception when one tries to call nexti on a finished program, but I'd rather do something like a "while programNotDone()" ). Thanks for the read. -Arjun Roy ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-08 15:08 Python Scripting Question Arjun Roy @ 2009-11-09 17:16 ` Tom Tromey 2009-11-09 17:23 ` Tom Tromey 2009-11-09 20:22 ` Arjun Roy 0 siblings, 2 replies; 10+ messages in thread From: Tom Tromey @ 2009-11-09 17:16 UTC (permalink / raw) To: Arjun Roy; +Cc: gdb >>>>> "Arjun" == Arjun Roy <roy.arjun@gmail.com> writes: Arjun> Traceback (most recent call last): Arjun> File "<string>", line 2, in <module> Arjun> TypeError: argument 1 must be string without null bytes, not str Arjun> Error while executing Python code. Arjun> Is this a bug, am I misunderstanding the right way to do it, or what? It is a bug. Arjun> 2. Ideally, I'd like to write a really simple script that: Arjun> - starts running a program Arjun> - steps through each instruction one by one, recording the opcode for Arjun> each instruction performed Arjun> - and stops when the program is over. Arjun> Does gdb-python support that? Not yet. Better execution control is on our wish-list. There was a SoC project to implement some of this; the patches need a bit of reworking though. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 17:16 ` Tom Tromey @ 2009-11-09 17:23 ` Tom Tromey 2009-11-09 17:44 ` Daniel Jacobowitz 2009-11-09 20:22 ` Arjun Roy 1 sibling, 1 reply; 10+ messages in thread From: Tom Tromey @ 2009-11-09 17:23 UTC (permalink / raw) To: Arjun Roy; +Cc: gdb >>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes: Arjun> Traceback (most recent call last): Arjun> File "<string>", line 2, in <module> Arjun> TypeError: argument 1 must be string without null bytes, not str Arjun> Error while executing Python code. Arjun> Is this a bug, am I misunderstanding the right way to do it, or what? Tom> It is a bug. I looked into this a little. The fix is to make python.c:execute_gdb_command copy the command string before passing it to execute_command. This avoids gdb commands trashing Python-owned strings. It isn't clear to me that gdb commands are allowed to overwrite their argument strings, though. Are they? disassemble_command does do this, but it seems wrong to me -- won't it permanently modify the command stored in a command script? I'll check in the python fix after testing. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 17:23 ` Tom Tromey @ 2009-11-09 17:44 ` Daniel Jacobowitz 2009-11-09 18:12 ` Tom Tromey 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2009-11-09 17:44 UTC (permalink / raw) To: Tom Tromey; +Cc: Arjun Roy, gdb On Mon, Nov 09, 2009 at 09:41:54AM -0700, Tom Tromey wrote: > It isn't clear to me that gdb commands are allowed to overwrite their > argument strings, though. Are they? disassemble_command does do this, > but it seems wrong to me -- won't it permanently modify the command > stored in a command script? Is it this bit? /* Two arguments. */ *space_index = '\0'; I don't think we should let commands modify their argument string. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 17:44 ` Daniel Jacobowitz @ 2009-11-09 18:12 ` Tom Tromey 0 siblings, 0 replies; 10+ messages in thread From: Tom Tromey @ 2009-11-09 18:12 UTC (permalink / raw) To: Arjun Roy; +Cc: gdb >>>>> "Daniel" == Daniel Jacobowitz <drow@false.org> writes: Daniel> On Mon, Nov 09, 2009 at 09:41:54AM -0700, Tom Tromey wrote: >> It isn't clear to me that gdb commands are allowed to overwrite their >> argument strings, though. Are they? disassemble_command does do this, >> but it seems wrong to me -- won't it permanently modify the command >> stored in a command script? Daniel> Is it this bit? Daniel> /* Two arguments. */ Daniel> *space_index = '\0'; Yeah. Daniel> I don't think we should let commands modify their argument string. Me neither. For the Python case I think we still have to be defensive, because it seems that a command might temporarily modify its argument (I am pretty sure this happens but I don't know how often), but even this sort of modification could cause problems, if the command itself can cause Python code to be called. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 17:16 ` Tom Tromey 2009-11-09 17:23 ` Tom Tromey @ 2009-11-09 20:22 ` Arjun Roy 2009-11-09 21:12 ` Tom Tromey 1 sibling, 1 reply; 10+ messages in thread From: Arjun Roy @ 2009-11-09 20:22 UTC (permalink / raw) To: tromey; +Cc: gdb On 11/09/2009 08:25 AM, Tom Tromey wrote: > Arjun> Traceback (most recent call last): > Arjun> File "<string>", line 2, in <module> > Arjun> TypeError: argument 1 must be string without null bytes, not str > Arjun> Error while executing Python code. > > Arjun> Is this a bug, am I misunderstanding the right way to do it, or what? > > It is a bug. > > Arjun> 2. Ideally, I'd like to write a really simple script that: > Arjun> - starts running a program > Arjun> - steps through each instruction one by one, recording the opcode for > Arjun> each instruction performed > Arjun> - and stops when the program is over. > > Arjun> Does gdb-python support that? > > Not yet. Better execution control is on our wish-list. There was a SoC > project to implement some of this; the patches need a bit of reworking > though. > > Tom > It looks as though the two main things this would need would be to: 1. Be able to access the output one gets from executing a GDB command. Ideally one would get an object with various fields filled in based on the type of command, but for my purposes even a string would do - as long as the results can be accessed somehow. 2. Some python objects for representing the current execution state of the program, where one could call methods for determining what's going on. Then in my case, a script would be conceptually as simple as: whileProgramStillRunning() nexti op = getopcode from (disassemble at $pc, $pc+1) // do whatever i want with the result How easy to hack in would this be? -Arjun ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 20:22 ` Arjun Roy @ 2009-11-09 21:12 ` Tom Tromey 2009-11-13 14:36 ` scott snyder 0 siblings, 1 reply; 10+ messages in thread From: Tom Tromey @ 2009-11-09 21:12 UTC (permalink / raw) To: Arjun Roy; +Cc: gdb >>>>> "Arjun" == Arjun Roy <roy.arjun@gmail.com> writes: Arjun> It looks as though the two main things this would need would be to: Arjun> 1. Be able to access the output one gets from executing a GDB command. Arjun> Ideally one would get an object with various fields filled in based on Arjun> the type of command, but for my purposes even a string would do - as Arjun> long as the results can be accessed somehow. Yeah, this has been on our wish-list for a while. Basically we need to let python create two kinds of new ui-out objects: one that writes the output to a python string, and another that is mi-like and creates new python objects in response to output. I have a tiny bit of code working toward this direction, but I never finished it. Arjun> 2. Some python objects for representing the current execution Arjun> state of the program, where one could call methods for Arjun> determining what's going on. The SoC project addressed part of this. See the archer list archives for information. Arjun> How easy to hack in would this be? I don't think anything here is too difficult; it just requires someone to actually do it. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-09 21:12 ` Tom Tromey @ 2009-11-13 14:36 ` scott snyder 2009-11-13 23:06 ` Arjun Roy 2009-11-18 20:43 ` Tom Tromey 0 siblings, 2 replies; 10+ messages in thread From: scott snyder @ 2009-11-13 14:36 UTC (permalink / raw) To: Tom Tromey; +Cc: Arjun Roy, gdb >From: Tom Tromey <tromey@redhat.com> >>>>>> "Arjun" == Arjun Roy <roy.arjun@gmail.com> writes: >Arjun> It looks as though the two main things this would need would be to: >Arjun> 1. Be able to access the output one gets from executing a GDB command. >Arjun> Ideally one would get an object with various fields filled in based on >Arjun> the type of command, but for my purposes even a string would do - as >Arjun> long as the results can be accessed somehow. >Yeah, this has been on our wish-list for a while. FWIW, i've been using this patch. This adds a function `gdb.execute_getoutput', which returns the output as a string. This probably isn't really the right way to do this --- I don't think this does the right thing with MI, and it has an ugly special case for TUI, but it's been working for me so far. sss === modified file 'gdb/python/python.c' --- gdb/python/python.c 2009-10-14 16:48:13 +0000 +++ gdb/python/python.c 2009-10-14 22:44:59 +0000 @@ -27,6 +27,7 @@ #include "observer.h" #include "value.h" #include "language.h" +#include "tui/tui-io.h" #include <ctype.h> @@ -321,6 +322,86 @@ \f +/* A Python function which evaluates a string using the gdb CLI + and returns the output as a string. */ + +static +void pyexecute_file_delete (struct ui_file* stream) +{ +} + +static +void pyexecute_file_write (struct ui_file* stream, + const char* buf, + long length_buf) +{ + PyObject* out = (PyObject*)ui_file_data (stream); + PyObject* snew = PyString_FromStringAndSize (buf, length_buf); + PyString_ConcatAndDel (&out, snew); + set_ui_file_data (stream, out, pyexecute_file_delete); +} + +static PyObject * +execute_gdb_command_getoutput (PyObject *self, PyObject *args) +{ + struct cmd_list_element *alias, *prefix, *cmd; + char *arg, *newarg; + PyObject *from_tty_obj = NULL; + int from_tty; + int cmp; + volatile struct gdb_exception except; + struct ui_file* fout; + PyObject* out; + struct ui_file* old_stdout; + struct ui_out* old_uiout; + + if (! PyArg_ParseTuple (args, "s|O!", &arg, &PyBool_Type, &from_tty_obj)) + return NULL; + + from_tty = 0; + if (from_tty_obj) + { + cmp = PyObject_IsTrue (from_tty_obj); + if (cmp < 0) + return NULL; + from_tty = cmp; + } + + fout = ui_file_new(); + out = PyString_FromString (""); + set_ui_file_data (fout, out, pyexecute_file_delete); + set_ui_file_write (fout, pyexecute_file_write); + old_stdout = gdb_stdout; + gdb_stdout = fout; + old_uiout = uiout; + if (uiout == tui_out) + uiout = tui_old_uiout; + if (ui_out_redirect (uiout, gdb_stdout) < 0) + warning (_("Current output protocol does not support redirection")); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + execute_command (arg, from_tty); + } + ui_out_redirect (uiout, 0); + uiout = old_uiout; + gdb_stdout = old_stdout; + out = ui_file_data (fout); + ui_file_delete (fout); + if (except.reason < 0) { + Py_DECREF (out); + out = 0; + } + GDB_PY_HANDLE_EXCEPTION (except); + + /* Do any commands attached to breakpoint we stopped at. */ + bpstat_do_actions (); + + return out; +} + +\f + /* Printing. */ /* A python function to write a single string using gdb's filtered @@ -653,6 +734,8 @@ "Get a value from history" }, { "execute", execute_gdb_command, METH_VARARGS, "Execute a gdb command" }, + { "execute_getoutput", execute_gdb_command_getoutput, METH_VARARGS, + "Execute a gdb command, returning the output as a string" }, { "parameter", gdbpy_parameter, METH_VARARGS, "Return a gdb parameter's value" }, ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-13 14:36 ` scott snyder @ 2009-11-13 23:06 ` Arjun Roy 2009-11-18 20:43 ` Tom Tromey 1 sibling, 0 replies; 10+ messages in thread From: Arjun Roy @ 2009-11-13 23:06 UTC (permalink / raw) To: scott snyder; +Cc: Tom Tromey, gdb Thanks, I'll check it out. In a pinch that should meet what I need. -Arjun On 11/12/2009 12:53 PM, scott snyder wrote: > FWIW, i've been using this patch. This adds a function > `gdb.execute_getoutput', which returns the output as a string. > > This probably isn't really the right way to do this --- > I don't think this does the right thing with MI, and it has an ugly > special case for TUI, but it's been working for me so far. > > sss > > > === modified file 'gdb/python/python.c' > --- gdb/python/python.c 2009-10-14 16:48:13 +0000 > +++ gdb/python/python.c 2009-10-14 22:44:59 +0000 > @@ -27,6 +27,7 @@ > #include "observer.h" > #include "value.h" > #include "language.h" > +#include "tui/tui-io.h" > > #include <ctype.h> > > @@ -321,6 +322,86 @@ > > \f > > +/* A Python function which evaluates a string using the gdb CLI > + and returns the output as a string. */ > + > +static > +void pyexecute_file_delete (struct ui_file* stream) > +{ > +} > + > +static > +void pyexecute_file_write (struct ui_file* stream, > + const char* buf, > + long length_buf) > +{ > + PyObject* out = (PyObject*)ui_file_data (stream); > + PyObject* snew = PyString_FromStringAndSize (buf, length_buf); > + PyString_ConcatAndDel (&out, snew); > + set_ui_file_data (stream, out, pyexecute_file_delete); > +} > + > +static PyObject * > +execute_gdb_command_getoutput (PyObject *self, PyObject *args) > +{ > + struct cmd_list_element *alias, *prefix, *cmd; > + char *arg, *newarg; > + PyObject *from_tty_obj = NULL; > + int from_tty; > + int cmp; > + volatile struct gdb_exception except; > + struct ui_file* fout; > + PyObject* out; > + struct ui_file* old_stdout; > + struct ui_out* old_uiout; > + > + if (! PyArg_ParseTuple (args, "s|O!", &arg, &PyBool_Type, &from_tty_obj)) > + return NULL; > + > + from_tty = 0; > + if (from_tty_obj) > + { > + cmp = PyObject_IsTrue (from_tty_obj); > + if (cmp < 0) > + return NULL; > + from_tty = cmp; > + } > + > + fout = ui_file_new(); > + out = PyString_FromString (""); > + set_ui_file_data (fout, out, pyexecute_file_delete); > + set_ui_file_write (fout, pyexecute_file_write); > + old_stdout = gdb_stdout; > + gdb_stdout = fout; > + old_uiout = uiout; > + if (uiout == tui_out) > + uiout = tui_old_uiout; > + if (ui_out_redirect (uiout, gdb_stdout) < 0) > + warning (_("Current output protocol does not support redirection")); > + > + TRY_CATCH (except, RETURN_MASK_ALL) > + { > + execute_command (arg, from_tty); > + } > + ui_out_redirect (uiout, 0); > + uiout = old_uiout; > + gdb_stdout = old_stdout; > + out = ui_file_data (fout); > + ui_file_delete (fout); > + if (except.reason < 0) { > + Py_DECREF (out); > + out = 0; > + } > + GDB_PY_HANDLE_EXCEPTION (except); > + > + /* Do any commands attached to breakpoint we stopped at. */ > + bpstat_do_actions (); > + > + return out; > +} > + > +\f > + > /* Printing. */ > > /* A python function to write a single string using gdb's filtered > @@ -653,6 +734,8 @@ > "Get a value from history" }, > { "execute", execute_gdb_command, METH_VARARGS, > "Execute a gdb command" }, > + { "execute_getoutput", execute_gdb_command_getoutput, METH_VARARGS, > + "Execute a gdb command, returning the output as a string" }, > { "parameter", gdbpy_parameter, METH_VARARGS, > "Return a gdb parameter's value" }, > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Python Scripting Question 2009-11-13 14:36 ` scott snyder 2009-11-13 23:06 ` Arjun Roy @ 2009-11-18 20:43 ` Tom Tromey 1 sibling, 0 replies; 10+ messages in thread From: Tom Tromey @ 2009-11-18 20:43 UTC (permalink / raw) To: scott snyder; +Cc: Arjun Roy, gdb >>>>> "scott" == scott snyder <snyder@fnal.gov> writes: scott> FWIW, i've been using this patch. This adds a function scott> `gdb.execute_getoutput', which returns the output as a string. scott> This probably isn't really the right way to do this --- scott> I don't think this does the right thing with MI, and it has an ugly scott> special case for TUI, but it's been working for me so far. This looks reasonable. However, I was planning to do it in a different way. In particular what I've been thinking is that we'd have a way to let the user pass any pythonic output stream to gdb; either with explicit commands to override the current output stream, or as an argument to gdb.execute. Handling MI-like output would work in a similar way, just with a way to indicate that the new output stream is MI-like. What do you think? If that is too vague I can try to write up something more documentation-like. scott> + if (uiout == tui_out) scott> + uiout = tui_old_uiout; This sort of redirection probably belongs in a helper function in ui-out. scott> + /* Do any commands attached to breakpoint we stopped at. */ scott> + bpstat_do_actions (); This could produce output. Arguably it should be redirected as well. Tom ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-11-16 17:55 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2009-11-08 15:08 Python Scripting Question Arjun Roy 2009-11-09 17:16 ` Tom Tromey 2009-11-09 17:23 ` Tom Tromey 2009-11-09 17:44 ` Daniel Jacobowitz 2009-11-09 18:12 ` Tom Tromey 2009-11-09 20:22 ` Arjun Roy 2009-11-09 21:12 ` Tom Tromey 2009-11-13 14:36 ` scott snyder 2009-11-13 23:06 ` Arjun Roy 2009-11-18 20:43 ` Tom Tromey
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox