This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Pretty-printers for members can't be influenced by pretty-printers for their containing structure
- From: Jim Blandy <jimb at red-bean dot com>
- To: gdb ml <gdb at sourceware dot org>
- Date: Tue, 27 Nov 2012 13:20:38 -0800
- Subject: Pretty-printers for members can't be influenced by pretty-printers for their containing structure
Here's a difficulty I've run into using GDB's pretty-printer API.
Mozilla's JavaScript engine uses a number of struct types that contain
unions. I'd like to define a pretty-printer such that the dead union
branches simply don't show up. Here's an example, from our string
representation.
struct JSString {
struct Data
{
size_t lengthAndFlags; /* JSString */
union {
const jschar *chars; /* JSLinearString */
JSString *left; /* JSRope */
} u1;
union {
jschar inlineStorage[NUM_INLINE_CHARS]; /*
JS(Inline|Short)String */
struct {
union {
JSLinearString *base; /*
JS(Dependent|Undepended)String */
JSString *right; /* JSRope */
size_t capacity; /*
JSFlatString (extensible) */
const JSStringFinalizer *externalFinalizer;/*
JSExternalString */
} u2;
union {
JSString *parent; /* JSRope (temporary) */
size_t reserved; /* may use for
bug 615290 */
} u3;
} s;
};
} d;
...
Assume I'm looking at the struct itself, not trying to find the text
it represents. (I handle that angle elsewhere just fine.)
Some bits of the lengthAndFlags member serve as a tag indicating which
fields of the unions are live. If what I've actually got is a JSRope,
say, representing the concatenation of two strings, then d.u1.left and
d.s.u2.right are live, and the overlapping union members like
d.u1.chars should be omitted, as they're just garbage.
Certainly, I can write a pretty-printer that just generates a string like this:
{ lengthAndFlags = blah, u1 = { left = blah }, s = { right = blah } ... }
But then I have to re-implement all the relevant 'set print'
parameters myself, like 'set print pretty' or 'set print address'. It
would be much nicer if I could simply have the pretty-printer provide
a 'children' method that skips dead union branches, and leave GDB's
own code responsible for respecting those parameters. That is, if the
pretty-printer could describe the structure at an appropriate level of
abstraction, I wouldn't need to re-implement bits of GDB.
Unfortunately, I can't do that. The pretty-printer for JSString::Data
can report 'u1' as one of its children, but then when I'm asked to
create a pretty-printer for that 'u1' value, I have no way of finding
the JSString::Data instance from which it was extracted. I've lost the
context I need to make a pretty-printer that lists only 'left' (say)
as a child, omitting 'chars'.
One possible fix would be to allow the second element of the 2-tuple
items produced by the iterator returned by the pretty-printer's
'children' method to be a new pretty-printer. The set of Python values
that GDB will convert to gdb.Values doesn't include any object types,
so this is unambiguous.
If GDB worked this way, then the pretty-printer for JSString::Data
could consult 'lengthAndFlags', and then list ('u1', P) as one of its
children, where P is a pretty-printer that knows which of its branches
is live.
How does this sound? Am I looking for a solution in the wrong place?
Is there a better way to get what I want?