public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@polymtl.ca>
To: Andrew Burgess <andrew.burgess@embecosm.com>, gdb-patches@sourceware.org
Subject: Re: [RFC 1/2] gdb: enable [] to find children using pretty-printers
Date: Thu, 13 May 2021 12:28:34 -0400	[thread overview]
Message-ID: <9ef877a2-88db-dce8-f8ef-a53f66cd266d@polymtl.ca> (raw)
In-Reply-To: <b2e090efad6608ba35069a80492ba51bcf47f2de.1619100478.git.andrew.burgess@embecosm.com>

On 2021-04-22 10:10 a.m., Andrew Burgess wrote:
> This commit allows GDB to make use of an available pretty-printer to
> provide [] indexing into a type.
> 
> Consider the following example before any pretty-printer is loaded:
> 
>   (gdb) p obj_int
>   $1 = {
>     m_name = 0x4052a0 "first int array",
>     m_nitems = 4,
>     m_items = 0x4052c0
>   }
>   (gdb) p obj_int[3]
>   Structure has no component named operator[].
> 
> Now, after loading a pretty-printer:
> 
>   (gdb) p obj_int
>   $2 = int array "first int array" with 4 elements = {3, 6, 4, 2}
>   (gdb) p obj_int[3]
>   $3 = 2

When reading this, I thought: isn't what pretty printers already do?
But apparently not.

It sounds at first like there's an overlap with xmethods, but maybe not
completely.  From what I understand, you would only write an xmethod to
replicate a method that exists in the program, but which may not be
available to call.  If writing a pretty printer for an array-like
structure in C, then there's no concept of method at all, so you
couldn't write an xmethod I suppose.  So this is where I can see your
feature becoming handy.

> diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
> index 7c0fdaa9e70..effbfcbfe28 100644
> --- a/gdb/python/py-prettyprint.c
> +++ b/gdb/python/py-prettyprint.c
> @@ -684,3 +684,173 @@ gdbpy_default_visualizer (PyObject *self, PyObject *args)
>  
>    return find_pretty_printer (val_obj).release ();
>  }
> +
> +/* See ext_lang_pretty_printer_find_child in extension.h for details.  */
> +
> +struct value *
> +gdbpy_val_pretty_printer_find_child (const extension_language_defn *extlang,
> +				     struct value *object,
> +				     struct value *idx,
> +				     const language_defn *language)
> +{
> +  /* A simple wrapper to make returning easier.  If we got an error then
> +     print the Python stack, and return nullptr.  Otherwise, return the
> +     value passed in.  */
> +  auto print_errors_before_return = [] (struct value *ret) -> struct value *
> +  {
> +    if (PyErr_Occurred ())
> +      {
> +	if (!PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
> +	  {
> +	    ret = nullptr;
> +	    gdbpy_print_stack ();
> +	  }
> +      }
> +    return ret;
> +  };
> +
> +  struct gdbarch *gdbarch = value_type (object)->arch ();
> +
> +  gdbpy_enter enter_py (gdbarch, language);
> +
> +  /* Prepare the value to be passed to the pretty printer.  */
> +  gdbpy_ref<> val_obj (value_to_value_object_no_release (object));
> +  if (val_obj == nullptr)
> +    return print_errors_before_return (nullptr);
> +
> +  /* Find the pretty-printer constructor.  */
> +  gdbpy_ref<> printer (find_pretty_printer (val_obj.get ()));
> +  if (printer == nullptr || printer == Py_None)
> +    return print_errors_before_return (nullptr);
> +
> +  /* If the pretty printer has no 'children' method then we're not going to
> +     be able to lookup any children.  */
> +  if (!PyObject_HasAttr (printer.get (), gdbpy_children_cst))
> +    return print_errors_before_return (nullptr);
> +
> +  /* If we get here then the pretty printer has no 'child' method, but does
> +     have the 'children' method.  We can manually walk the children and
> +     find one that matches IDX.  First, find out how the children are
> +     represented by the children method.  */

Here, you talk about the child method, but I couldn't find any doc /
code about that.

While reading the commit message, I had that thought, maybe you had the
same.  If you do:

  (gdb) print myobject[50000]

That kind sucks that we have to call the "children" method and consume
/ create 49999 values that we are not going to use.  It would be much
better if we could ask the pretty printer, give me the item at index
50000.  Reading the documented API [1], that doesn't seem possible.

[1] https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing-API.html#Pretty-Printing-API

Simon

  parent reply	other threads:[~2021-05-13 16:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-22 14:10 [RFC 0/2] Using pretty-printers for [] indexing Andrew Burgess
2021-04-22 14:10 ` [RFC 1/2] gdb: enable [] to find children using pretty-printers Andrew Burgess
2021-04-22 14:18   ` Eli Zaretskii
2021-05-13 16:28   ` Simon Marchi [this message]
2021-04-22 14:10 ` [RFC 2/2] gdb: improve equal check used by the pretty-printer [] support Andrew Burgess
2021-05-13 10:35 ` [RFC 0/2] Using pretty-printers for [] indexing Andrew Burgess
2021-06-17 18:37   ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9ef877a2-88db-dce8-f8ef-a53f66cd266d@polymtl.ca \
    --to=simon.marchi@polymtl.ca \
    --cc=andrew.burgess@embecosm.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).