From 1256af7d1afb123c15ae3935de4470becdf7c512 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Thu, 13 Sep 2018 11:53:22 -0400 Subject: [PATCH] python: Provide textual representation for Inferior and Objfile Printing a GDB Python object is notoriously not helpful: >>> print(gdb.selected_inferior()) >>> print(gdb.objfiles()) [] 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()) >>> print(gdb.objfiles()) [] 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. --- gdb/ChangeLog | 7 +++++++ gdb/doc/ChangeLog | 5 +++++ gdb/doc/python.texi | 4 ++++ gdb/python/py-inferior.c | 17 ++++++++++++++++- gdb/python/py-objfile.c | 17 ++++++++++++++++- gdb/testsuite/ChangeLog | 6 ++++++ gdb/testsuite/gdb.python/py-inferior.exp | 17 ++++++++++++++++- gdb/testsuite/gdb.python/py-objfile.exp | 9 +++++++++ gdb/testsuite/gdb.python/py-symtab.exp | 3 ++- 9 files changed, 81 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 454c45f..50a6519 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-09-13 Simon Marchi + + * 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 * fbsd-nat.c (fbsd_nat_target::info_proc): Remove unused variable. diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index f04dca4..1c96508 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2018-09-13 Simon Marchi + + * python.texi (Basic Python): Mention the string representation + of GDB Python objects. + 2018-09-12 Simon Marchi * gdb.texinfo (Skipping Over Functions and Files): Document diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 5e2ab76..6e2bf5c 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -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 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 @defvar gdb.PYTHONDIR A string containing the python directory (@pxref{Python}). diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c index 1cf3729..56019bf 100644 --- a/gdb/python/py-inferior.c +++ b/gdb/python/py-inferior.c @@ -860,6 +860,21 @@ infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw) 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 (""); + + return PyString_FromFormat ("", + inf->num, inf->pid); +} + static void infpy_dealloc (PyObject *obj) @@ -991,7 +1006,7 @@ PyTypeObject inferior_object_type = 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ - 0, /* tp_repr */ + infpy_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index c2b40ff..61d3a15 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -456,6 +456,21 @@ objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw) 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 (""); + + return PyString_FromFormat ("", + objfile_filename (obj)); +} + /* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it. Return non-zero if STRING is a potentially valid build id. */ @@ -709,7 +724,7 @@ PyTypeObject objfile_object_type = 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, /*tp_compare*/ - 0, /*tp_repr*/ + objfpy_repr, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 949f1ae..db9c214 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-09-13 Simon Marchi + + * 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 * gdb.python/py-inferior.exp: Test using an invalid gdb.Inferior diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp index 055dd87..7ec8193 100644 --- a/gdb/testsuite/gdb.python/py-inferior.exp +++ b/gdb/testsuite/gdb.python/py-inferior.exp @@ -45,7 +45,8 @@ if ![runto_main] then { # Test basic gdb.Inferior attributes and methods. gdb_py_test_silent_cmd "python inferiors = gdb.inferiors ()" "get inferiors list" 1 -gdb_test "python print (inferiors)" "\\(,\\)" "verify inferiors list" +gdb_test "python print (inferiors)" \ + "\\(,\\)" "verify inferiors list" 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)" @@ -279,3 +280,17 @@ with_test_prefix "selected_inferior" { gdb_test "inferior 1" ".*" "switch back to first 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_test "python print (infs)" \ + "\\\(, \\\)" \ + "print all inferiors 1" + gdb_test_no_output "remove-inferiors 4" + gdb_test "python print (infs)" \ + "\\\(, \\\)" \ + "print all inferiors 2" +} diff --git a/gdb/testsuite/gdb.python/py-objfile.exp b/gdb/testsuite/gdb.python/py-objfile.exp index 6e81750..ce24b56 100644 --- a/gdb/testsuite/gdb.python/py-objfile.exp +++ b/gdb/testsuite/gdb.python/py-objfile.exp @@ -45,6 +45,9 @@ gdb_test "python print (objfile.filename)" "${testfile}" \ gdb_test "python print (objfile.username)" "${testfile}" \ "Get objfile user name" +gdb_test "python print (objfile)" \ + "" + gdb_test_no_output "python dir(objfile)" 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)" \ "${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)" "" \ No newline at end of file diff --git a/gdb/testsuite/gdb.python/py-symtab.exp b/gdb/testsuite/gdb.python/py-symtab.exp index f504362..545fe95 100644 --- a/gdb/testsuite/gdb.python/py-symtab.exp +++ b/gdb/testsuite/gdb.python/py-symtab.exp @@ -66,7 +66,8 @@ gdb_test "python print (sal.is_valid())" "True" "test sal.is_valid" # Test symbol table. gdb_test "python print (symtab.filename)" ".*${py_symbol_c}" "test symtab.filename" -gdb_test "python print (symtab.objfile)" "" "test symtab.objfile" +gdb_test "python print (symtab.objfile)" "" \ + "test symtab.objfile" 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 (\"qq\" in global_symbols)" "True" "test qq in global symbols" -- 2.7.4