mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-12-15 04:31:49 +08:00
python: Provide textual representation for Inferior and Objfile
Printing a GDB Python object is notoriously not helpful: >>> print(gdb.selected_inferior()) <gdb.Inferior object at 0x7fea59aed198> >>> print(gdb.objfiles()) [<gdb.Objfile object at 0x7fea59b57c90>] This makes printing debug traces more difficult than it should be. This patch provides some repr() implementation for these two types (more to come if people agree with the idea, but I want to test the water first). Here's the same example as above, but with this patch: >>> print(gdb.selected_inferior()) <gdb.Inferior num=1> >>> print(gdb.objfiles()) [<gdb.Objfile filename=/home/emaisin/build/binutils-gdb-gcc-git/gdb/test>] I implemented repr rather than str, because when printing a list (or another container I suppose), Python calls the repr method of the elements. This is useful when printing a list of inferiors or objfiles. The print(gdb.objfiles()) above would not have worked if I had implemented str. I found this post useful to understand the difference between repr and str: https://stackoverflow.com/questions/1436703/difference-between-str-and-repr gdb/ChangeLog: * python/py-inferior.c (infpy_repr): New. (inferior_object_type): Register infpy_repr. * python/py-objfile.c (objfpy_repr): New. (objfile_object_type): Register objfpy_repr. gdb/testsuite/ChangeLog: * gdb.python/py-inferior.exp: Test repr() of gdb.Inferior. * gdb.python/py-objfile.exp: Test repr() of gdb.Objfile. * gdb.python/py-symtab.exp: Update test printing an objfile. gdb/doc/ChangeLog: * python.texi (Basic Python): Mention the string representation of GDB Python objects.
This commit is contained in:
parent
508d0c9b59
commit
1256af7d1a
@ -1,3 +1,10 @@
|
|||||||
|
2018-09-13 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
|
* python/py-inferior.c (infpy_repr): New.
|
||||||
|
(inferior_object_type): Register infpy_repr.
|
||||||
|
* python/py-objfile.c (objfpy_repr): New.
|
||||||
|
(objfile_object_type): Register objfpy_repr.
|
||||||
|
|
||||||
2018-09-12 John Baldwin <jhb@FreeBSD.org>
|
2018-09-12 John Baldwin <jhb@FreeBSD.org>
|
||||||
|
|
||||||
* fbsd-nat.c (fbsd_nat_target::info_proc): Remove unused variable.
|
* fbsd-nat.c (fbsd_nat_target::info_proc): Remove unused variable.
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
2018-09-13 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
|
* python.texi (Basic Python): Mention the string representation
|
||||||
|
of GDB Python objects.
|
||||||
|
|
||||||
2018-09-12 Simon Marchi <simon.marchi@ericsson.com>
|
2018-09-12 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
* gdb.texinfo (Skipping Over Functions and Files): Document
|
* gdb.texinfo (Skipping Over Functions and Files): Document
|
||||||
|
@ -207,6 +207,10 @@ methods and classes added by @value{GDBN} are placed in this module.
|
|||||||
@value{GDBN} automatically @code{import}s the @code{gdb} module for
|
@value{GDBN} automatically @code{import}s the @code{gdb} module for
|
||||||
use in all scripts evaluated by the @code{python} command.
|
use in all scripts evaluated by the @code{python} command.
|
||||||
|
|
||||||
|
Some types of the @code{gdb} module come with a textual representation
|
||||||
|
(accessible through the @code{repr} or @code{str} functions). These are
|
||||||
|
offered for debugging purposes only, expect them to change over time.
|
||||||
|
|
||||||
@findex gdb.PYTHONDIR
|
@findex gdb.PYTHONDIR
|
||||||
@defvar gdb.PYTHONDIR
|
@defvar gdb.PYTHONDIR
|
||||||
A string containing the python directory (@pxref{Python}).
|
A string containing the python directory (@pxref{Python}).
|
||||||
|
@ -860,6 +860,21 @@ infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement repr() for gdb.Inferior. */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
infpy_repr (PyObject *obj)
|
||||||
|
{
|
||||||
|
inferior_object *self = (inferior_object *) obj;
|
||||||
|
inferior *inf = self->inferior;
|
||||||
|
|
||||||
|
if (inf == nullptr)
|
||||||
|
return PyString_FromString ("<gdb.Inferior (invalid)>");
|
||||||
|
|
||||||
|
return PyString_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
|
||||||
|
inf->num, inf->pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
infpy_dealloc (PyObject *obj)
|
infpy_dealloc (PyObject *obj)
|
||||||
@ -991,7 +1006,7 @@ PyTypeObject inferior_object_type =
|
|||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
0, /* tp_compare */
|
0, /* tp_compare */
|
||||||
0, /* tp_repr */
|
infpy_repr, /* tp_repr */
|
||||||
0, /* tp_as_number */
|
0, /* tp_as_number */
|
||||||
0, /* tp_as_sequence */
|
0, /* tp_as_sequence */
|
||||||
0, /* tp_as_mapping */
|
0, /* tp_as_mapping */
|
||||||
|
@ -456,6 +456,21 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw)
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement repr() for gdb.Objfile. */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
objfpy_repr (PyObject *self_)
|
||||||
|
{
|
||||||
|
objfile_object *self = (objfile_object *) self_;
|
||||||
|
objfile *obj = self->objfile;
|
||||||
|
|
||||||
|
if (obj == nullptr)
|
||||||
|
return PyString_FromString ("<gdb.Objfile (invalid)>");
|
||||||
|
|
||||||
|
return PyString_FromFormat ("<gdb.Objfile filename=%s>",
|
||||||
|
objfile_filename (obj));
|
||||||
|
}
|
||||||
|
|
||||||
/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
|
/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it.
|
||||||
Return non-zero if STRING is a potentially valid build id. */
|
Return non-zero if STRING is a potentially valid build id. */
|
||||||
|
|
||||||
@ -709,7 +724,7 @@ PyTypeObject objfile_object_type =
|
|||||||
0, /*tp_getattr*/
|
0, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
0, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
0, /*tp_repr*/
|
objfpy_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
0, /*tp_as_sequence*/
|
0, /*tp_as_sequence*/
|
||||||
0, /*tp_as_mapping*/
|
0, /*tp_as_mapping*/
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
|
2018-09-13 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
|
* gdb.python/py-inferior.exp: Test repr() of gdb.Inferior.
|
||||||
|
* gdb.python/py-objfile.exp: Test repr() of gdb.Objfile.
|
||||||
|
* gdb.python/py-symtab.exp: Update test printing an objfile.
|
||||||
|
|
||||||
2018-09-12 Simon Marchi <simon.marchi@ericsson.com>
|
2018-09-12 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
* gdb.python/py-inferior.exp: Test using an invalid gdb.Inferior
|
* gdb.python/py-inferior.exp: Test using an invalid gdb.Inferior
|
||||||
|
@ -45,7 +45,8 @@ if ![runto_main] then {
|
|||||||
# Test basic gdb.Inferior attributes and methods.
|
# Test basic gdb.Inferior attributes and methods.
|
||||||
|
|
||||||
gdb_py_test_silent_cmd "python inferiors = gdb.inferiors ()" "get inferiors list" 1
|
gdb_py_test_silent_cmd "python inferiors = gdb.inferiors ()" "get inferiors list" 1
|
||||||
gdb_test "python print (inferiors)" "\\(<gdb.Inferior object at 0x\[\[:xdigit:\]\]+>,\\)" "verify inferiors list"
|
gdb_test "python print (inferiors)" \
|
||||||
|
"\\(<gdb.Inferior num=1, pid=$decimal>,\\)" "verify inferiors list"
|
||||||
gdb_py_test_silent_cmd "python i0 = inferiors\[0\]" "get first inferior" 0
|
gdb_py_test_silent_cmd "python i0 = inferiors\[0\]" "get first inferior" 0
|
||||||
|
|
||||||
gdb_test "python print ('result = %s' % (i0 == inferiors\[0\]))" " = True" "test equality comparison (true)"
|
gdb_test "python print ('result = %s' % (i0 == inferiors\[0\]))" " = True" "test equality comparison (true)"
|
||||||
@ -279,3 +280,17 @@ with_test_prefix "selected_inferior" {
|
|||||||
gdb_test "inferior 1" ".*" "switch back to first inferior"
|
gdb_test "inferior 1" ".*" "switch back to first inferior"
|
||||||
gdb_test_no_output "remove-inferiors 3" "remove second inferior"
|
gdb_test_no_output "remove-inferiors 3" "remove second inferior"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Test repr()/str()
|
||||||
|
with_test_prefix "__repr__" {
|
||||||
|
gdb_test "add-inferior" "Added inferior 4" "add inferior 4"
|
||||||
|
gdb_py_test_silent_cmd "python infs = gdb.inferiors()" "get inferior list" 1
|
||||||
|
gdb_test "python print (infs\[0\])" "<gdb.Inferior num=1, pid=$decimal>"
|
||||||
|
gdb_test "python print (infs)" \
|
||||||
|
"\\\(<gdb.Inferior num=1, pid=$decimal>, <gdb.Inferior num=4, pid=$decimal>\\\)" \
|
||||||
|
"print all inferiors 1"
|
||||||
|
gdb_test_no_output "remove-inferiors 4"
|
||||||
|
gdb_test "python print (infs)" \
|
||||||
|
"\\\(<gdb.Inferior num=1, pid=$decimal>, <gdb.Inferior \\\(invalid\\\)>\\\)" \
|
||||||
|
"print all inferiors 2"
|
||||||
|
}
|
||||||
|
@ -45,6 +45,9 @@ gdb_test "python print (objfile.filename)" "${testfile}" \
|
|||||||
gdb_test "python print (objfile.username)" "${testfile}" \
|
gdb_test "python print (objfile.username)" "${testfile}" \
|
||||||
"Get objfile user name"
|
"Get objfile user name"
|
||||||
|
|
||||||
|
gdb_test "python print (objfile)" \
|
||||||
|
"<gdb.Objfile filename=[string_to_regexp ${binfile}]>"
|
||||||
|
|
||||||
gdb_test_no_output "python dir(objfile)"
|
gdb_test_no_output "python dir(objfile)"
|
||||||
|
|
||||||
gdb_test "python print (gdb.lookup_objfile (\"${testfile}\").filename)" \
|
gdb_test "python print (gdb.lookup_objfile (\"${testfile}\").filename)" \
|
||||||
@ -149,3 +152,9 @@ if [remote_file host exists "${symlink_binary}"] {
|
|||||||
gdb_test "python print (gdb.lookup_objfile (\"${symlink_binary}\").filename)" \
|
gdb_test "python print (gdb.lookup_objfile (\"${symlink_binary}\").filename)" \
|
||||||
"${testfile}" "gdb.lookup_objfile of symlinked binary"
|
"${testfile}" "gdb.lookup_objfile of symlinked binary"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Test printing an Objfile object that is no longer valid.
|
||||||
|
gdb_py_test_silent_cmd "python objfile = gdb.objfiles()\[0\]" \
|
||||||
|
"get first objfile" 1
|
||||||
|
gdb_file_cmd ${binfile}
|
||||||
|
gdb_test "python print(objfile)" "<gdb.Objfile \\\(invalid\\\)>"
|
@ -66,7 +66,8 @@ gdb_test "python print (sal.is_valid())" "True" "test sal.is_valid"
|
|||||||
|
|
||||||
# Test symbol table.
|
# Test symbol table.
|
||||||
gdb_test "python print (symtab.filename)" ".*${py_symbol_c}" "test symtab.filename"
|
gdb_test "python print (symtab.filename)" ".*${py_symbol_c}" "test symtab.filename"
|
||||||
gdb_test "python print (symtab.objfile)" "<gdb.Objfile object at ${hex}>" "test symtab.objfile"
|
gdb_test "python print (symtab.objfile)" "<gdb.Objfile filename=${binfile}>" \
|
||||||
|
"test symtab.objfile"
|
||||||
gdb_test "python print (symtab.fullname())" ".*${full_py_symbol_c}" "test symtab.fullname"
|
gdb_test "python print (symtab.fullname())" ".*${full_py_symbol_c}" "test symtab.fullname"
|
||||||
gdb_test "python print (symtab.is_valid())" "True" "test symtab.is_valid()"
|
gdb_test "python print (symtab.is_valid())" "True" "test symtab.is_valid()"
|
||||||
gdb_test "python print (\"qq\" in global_symbols)" "True" "test qq in global symbols"
|
gdb_test "python print (\"qq\" in global_symbols)" "True" "test qq in global symbols"
|
||||||
|
Loading…
Reference in New Issue
Block a user