public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
From: Jim Blandy <jimb@red-bean.com>
To: gdb ml <gdb@sourceware.org>
Subject: Fwd: Addresses in pretty-printing
Date: Mon, 19 Nov 2012 07:11:00 -0000	[thread overview]
Message-ID: <CAHgb+0mRE449yJwRN9OBuDMhXTdRmuH_pq0CfFd2JoJAWf4XJg@mail.gmail.com> (raw)
In-Reply-To: <CAHgb+0=pttEZ2uOcO6xfqJ4yvnzCCTJs0DTAZgLKKKwgZiocQQ@mail.gmail.com>

Quick summary: the patch discussed and approved in this long-ago
thread: http://sourceware.org/ml/gdb/2009-11/msg00105.html
causes silly output like this:

(gdb) print a
$1 = {ptr = }
(gdb) print s
$1 =

One particular patch is responsible. I suggest an extension to GDB's
Python interface that allows a cleaner solution.

In detail:

The original problem was that GDB showed string addresses where they
weren't wanted, according to gdb.python/py-prettyprint.exp. The test
wants the pretty-printer for this structure:

typedef struct string_repr
{
  struct whybother
  {
    const char *contents;
  } whybother;
} string;

to produce output like this:

$2 = "fnord"

instead of like this:

$1 = 0x403680 "fnord"

Here's the patch from that thread:

--- gdb/python/py-prettyprint.c#1    2009-11-09 17:58:39.000000000 -0800
+++ gdb/python/py-prettyprint.c     2009-11-09 16:51:16.862840000 -0800
@@ -209,7 +209,12 @@ print_string_repr (PyObject *printer, co
       Py_DECREF (py_str);
     }
   else if (replacement)
-    common_val_print (replacement, stream, recurse, options, language);
+    {
+      struct value_print_options opts = *options;
+
+      opts.addressprint = 0;
+      common_val_print (replacement, stream, recurse, &opts, language);
+    }
   else
     gdbpy_print_stack ();
 }

It seems to me this change is over-broad: all addresses appearing
anywhere in the non-pretty printing of a replacement value get
omitted, even if they're, say, a 'void *' or a pointer to some
structure. For example, this is unhelpful:

$ cat pretty-printers.c
struct B { void *ptr; };
struct A { struct B b; };
int main() {
  struct A a;
  a.b.ptr = 0;
  return 0;
};
$ cat pretty-printers-gdb.py
class ppA(object):
    def __init__(self, value): self.value = value
    def to_string(self): return self.value['b']
def lookup(value):
    if value.type.tag == 'A': return ppA(value)
gdb.pretty_printers[:] = [lookup]
$ gcc -g3 -O0 pretty-printers.c -o pretty-printers
$ gdb pretty-printers
(gdb) break 6
Breakpoint 1 at 0x400538: file pretty-printers.c, line 6.
(gdb) run
Breakpoint 1, main () at pretty-printers.c:6
6      return 0;
(gdb) print a
$1 = {ptr = }
(gdb)

The pretty-printer returns a B as the replacement value, and since B
contains pointers, they don't print.

It's trouble for NULL 'char *' pointers too: we always omit the string
contents of a 'char *' when it's NULL, which makes sense; but if we
omit the address as well, then there's nothing left:

$ cat pp2.c
struct S { char *s; };
int main() {
  struct S s;
  s.s = 0;
  return 0;
};
$ cat pp2-gdb.py
class ppS(object):
    def __init__(self, value): self.value = value
    def to_string(self): return self.value['s']
def lookup(value):
    if value.type.tag == 'S': return ppS(value)
gdb.pretty_printers[:] = [lookup]
$ gcc -g3 -O0 pp2.c -o pp2
$ gdb pp2
(gdb) b 5
Breakpoint 1 at 0x400538: file pp2.c, line 5.
(gdb) run
Breakpoint 1, main () at pp2.c:5
5      return 0;
(gdb) p s
$1 =
(gdb)

That's not good.

Just on first principles, I think it's odd to answer the question "How
can I get GDB to print a string without the address?" with something
like "return it as a replacement value". But that's what the
aforementioned patch does. Whether a pretty-printer hands GDB a value
as a replacement value, or calls Python's 'str', or returns it as a
child, shouldn't affect whether addresses get printed.

I'd like to suggest an alternative: gdb.Value should have a 'format'
method that behaves almost like applying Python's 'str' built-in
function to the value, except that it allows you to specify print
options for that value and its sub-values. Thus, the pretty-printer in
py-prettyprint.exp would become, simply:

class string_print:
   def __init__(self, val):
       self.val = val

   def to_string(self):
       return self.val['whybother']['contents'].format({'address': False})

Here is proposed documentation for gdb.Value.format, and two
accompanying functions, gdb.value_print_options and
gdb.set_value_print_options. I'd be willing to implement something
like this.

@defun Value.format (print_options = None)
Return a string holding the text @value{GDBN} would produce if
printing this @code{gdb.Value}. If this value has a pretty-printer,
call that to produce the string; otherwise, use @value{GDBN}'s
built-in printing rules.

@var{print_options}, if given, is a dictionary of the sort returned by
@code{gdb.value_print_options}, binding names of print options to
values to use while formatting this value. These settings affect only
the formatting of this value and its children: when a call to this
function returns, all print settings remain as they were before the
call occurred.

The result of calling method is very similar to that of applying
Python's @code{str} built-in function to the @code{gdb.Value}
instance, except that one may pass a @var{print_options}
argument to affect the value's formatting.
@end defun


@findex gdb.value_print_options
@defun gdb.value_print_options ()
Return a dictionary providing the current values of @value{GDBN}'s
value printing settings, as controlled by the @code{set print} command
(and a few other @code{set} commands). The dictionary's keys are the
names of the print options; the value stored under each key is that
option's current value. The keys and their corresponding @code{set}
subcommands are as follows:

@table @code
@item 'output-radix'
@code{set output-radix}
@item 'elements'
@code{set print elements}
@item 'null-stop'
@code{set print null-stop}
@item 'repeats'
@code{set print repeats}
@item 'pretty'
@code{set print pretty}
@item 'union'
@code{set print union}
@item 'array'
@code{set print array}
@item 'address'
@code{set print address}
@item 'symbol'
@code{set print symbol}
@item 'array-indexes'
@code{set print array-indexes}
@item 'static-members'
@code{set print static-members}
@item 'vtbl'
@code{set print vtbl}
@item 'object'
@code{set print object}
@item 'pascal_static-members'
@code{set print pascal_static-members}
@item 'demangle'
@code{set print demangle}
@item 'asm-demangle'
@code{set print asm-demangle}
@item 'max-symbolic-offset'
@code{set print max-symbolic-offset}
@item 'symbol-filename'
@code{set print symbol-filename}
@item 'sevenbit-strings'
@code{set print sevenbit-strings}
@end table

The dictionary values are booleans or numbers, as appropriate for each
print setting.
@end defun

@findex gdb.set_value_print_options
@defun gdb.set_value_print_options (options)
Set the value printing options as given in @var{options}, a dictionary
whose items' keys name value printing options, and whose values are
the values to which those options should be set. Permitted keys are as
for @code{gdb.value_print_options}, described above.

Only those options named in the dictionary are affected, so you can
use this method to set individual options:

@smallexample
gdb.set_value_print_options({'demangle': False})
@end smallexample
@end defun

       reply	other threads:[~2012-11-19  7:11 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CAHgb+0=pttEZ2uOcO6xfqJ4yvnzCCTJs0DTAZgLKKKwgZiocQQ@mail.gmail.com>
2012-11-19  7:11 ` Jim Blandy [this message]
2012-11-19 21:56   ` Tom Tromey
2012-11-19 23:03     ` Jim Blandy
2012-11-20 20:58       ` Tom Tromey

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=CAHgb+0mRE449yJwRN9OBuDMhXTdRmuH_pq0CfFd2JoJAWf4XJg@mail.gmail.com \
    --to=jimb@red-bean.com \
    --cc=gdb@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).