[RFC] Empty result of "info types inner": Is this a bug?

Doug Evans
2015-01-04T08:54:37Z

Hi.

Consider this example (source appended at the end).

bash$ gdb info-types
(gdb) info types inner
All types matching regular expression "inner":
(gdb) start
...
(gdb) step
...
(gdb) info types inner
All types matching regular expression "inner":

File info-types-2.cc:
c::inner;
(gdb)

Technically, it's a bug that the first "info types inner" didn't
print anything, but is this a bug we're willing to accept for
performance reasons? I want to make the case that the answer is "No."

"info types" shouldn't have a different answer depending on what
symtabs have been expanded. However, it currently does because
of the shortcut we take building the partial symtab:
When reading classes we don't traverse into inner classes
(as well as taking other shortcuts).
[That and the fact that we don't make up for these shortcuts
in search_symbols() - kinda hard without expanding every symtab
or adding more specialized debug info reading code.]

We take shortcuts when building partial syms in order to speed up startup.
However, it would be nice to collect some new data on what we're saving
relative to what we're spending. If it's not much, it'd be worth it IMO
to spend it given the simplification it would allow. I'm not suggesting
we couldn't build psymtabs even faster, e.g., being even lazier than
what we are now. But (depending on what we're being lazy with) this
increases the complexity of symbol lookup, and we have .gdb_index now:
if we slow down building psymtabs by 10% (I just picked that number out
of the air, as I say I need to collect some data) we don't slow down
startup with .gdb_index at all. We have an index we generate to make
gdb faster, here's another way it can help:
put every symbol from GLOBAL/STATIC_BLOCKs in it.
[We still have to support older indices, but we can phase them out,
we've done it before.]

As part of my cleaning up of symbol handling, I've been wanting to
simplify things (as well as speed things up), and one thing that
will help is if *every* symbol that appears in GLOBAL/STATIC_BLOCK of
expanded symtabs already appears in partial symtabs/.gdb_index.
I think this would result in a massive simplfication: The subtleties
that we currently have could disappear. Plus it would simplify the
last step I want to take for now in symbol lookup: search
psymtabs/index first (not last) and only search psymtabs/index
(and never loop over GLOBAL/STATIC_BLOCK). I have a version of this
patch that works with psymtabs/index as they exist today, and I'm mostly
happy with it, but if I can I'd like to simplify it, and I'm using
the above example as motivation for thinking about the problem some
more: It doesn't fix the above bug, and we don't want IMO to fix it
by expanding every symtab ...

If you think about it, it's odd that we loop over GLOBAL/STATIC_BLOCK.
I kinda wonder how that ever got started. If I'm missing something
please let me know!
Setting aside the fact that we always expand the symtab with main()
at startup, there are no expanded symtabs at startup.
So if we want gdb to work as well at startup as it does later during the
debugging session, symbol lookup has to work with no expanded symtabs!
There's kinda no point in looping over something that isn't there. :-)
So why can't we just search psymtab/index and leave it at that?
The answer, or at least part of the answer, is that psymtabs/index
doesn't contain everything that exists in GLOBAL/STATIC_BLOCK, and
we rely on progressive lookup to expand symtabs as we go along so that
when we get to looking up "c" in "a::b::c" its symtab as already been
expanded (because we're not going to find it in psymtabs/index).
Still, why do we have to loop over all GLOBAL/STATIC_BLOCKs
to find "c"? I don't actually know, I think it's just convervatism,
but if there is a real reason it'd be great to add some clarity here.
If we know where we found "b", I think(!) we could just look there, and
if that fails look in psymtabs/index (e.g., static members can get put
in psymtabs even though their containing class isn't in psymtabs).

Would gcc emit a c++ class with two typedefs, with one typedef in one
compilation unit and the other typedef in another compilation unit?
Maybe we can't assume it won't happen, sigh, in which case all the
more reason to have psymtabs/index include every static/global symbol.
Plus if gcc could do that, "ptype foo::second_typedef" cannot otherwise
work, unless the (potentially only) compilation unit with that typedef
happens to get expanded via other means. Or we change lookup to loop
over all compilation units that define foo until we find second_typedef,
except that psymtabs/index only contain one entry for foo, so we'd have
to change that too.

[There is still one reason to support looping over all expanded symtabs:
if there's a bug psymtabs/index. GDB is just a tool and users would
rather it still work, even with its bugs. But that doesn't have to be
the default behaviour.]

---snip--- info-types.cc
extern void foo ();

int
main ()
{
foo ();
return 0;
}
---snip--- info-types-2.cc
class foo_class
{
public:
foo_class () { }

typedef int foo_typedef;

class inner
{
public:
static foo_typedef y;
};
};

foo_class::foo_typedef foo_class::inner::y = 23;

int xyz;

void
foo ()
{
xyz = foo_class::inner::y;
}
---snip---

bash$ g++ -g info-types.c info-types-2.cc -o info-types