Re: adding namespace support to GDB

Daniel Jacobowitz
2002-08-23T21:26:08Z

On Fri, Aug 23, 2002 at 02:06:35PM -0400, Daniel Jacobowitz wrote:
> On Fri, Aug 23, 2002 at 08:42:40AM -0700, David Carlton wrote:
> > I recently asked Daniel Jacobwitz for suggestions as to what I could
> > do to help GDB, and he suggested that I might try adding proper
> > namespace support. I've skimmed a thread on the issue from early
> > April with lots of interesting ideas; at some point, it sounded like
> > Jim Blandy was about to start writing up some concrete possible
> > interfaces, and I was wondering if anything more came of that.
> >
> > For the time being, I'm going to reread that thread more closely, look
> > at Petr Sorfa's module patch, look at the DWARF-3 standard, look at
> > existing GDB code, and think about this for a while. (Or at least I
> > hope that's what I'm going to do: maybe I'll instead spend all of my
> > time arguing with Stanford's benefits office. Anybody know of any
> > interesting free software jobs in countries with nationalized health
> > insurance?) But I don't want to duplicate effort if somebody else has
> > already started working on this.
>
> Meanwhile, I'm working on ugly namespace support - without all the
> symbol table and scoping work that we'll need to make things quite
> "correct", I'm trying to make the debug readers provide scope
> information (mostly done) and the rest of GDB cope with it
> (investigating). I have patches for both stabs and DWARF-2 to generate
> class and types names properly qualified, but because the rest of GDB
> doesn't expect this they never get unqualified; we get things like
>
> std::bar std::bar::function(std::bar&)
>
> because it doesn't know that the std:: can be elided. Etc.
>
> Hope to have more time to work on this next week.

Well, for the amusement of our audience, here's code to do this for
stabs. This isn't an RFA, since GDB isn't ready for this data. It's
also not quite right; it handles TYPE_NAME but not TYPE_TAG_NAME, since
I'm still not 100% sure what TYPE_TAG_NAME ought to be. I suspect I
should just set it at the same time as setting TYPE_NAME in
read_member_functions.

With this, the return type from methods in
class C {
class D {
};
};

is written as C::D instead of D. The symbol's name is still wrong, so
GDB thinks the type is D instead of C::D, still. And there's a missing
optimization (only call class_name_from_physname once per class). But
you get the picture...

With this technique to get the information, the next step will be to
remove it in the appropriate places, like in printing; that requires
passing around the current name prefix all the time. When we know what
it is.

--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer

Index: gdbtypes.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.c,v
retrieving revision 1.55
diff -u -p -r1.55 gdbtypes.c
--- gdbtypes.c 10 Aug 2002 05:12:40 -0000 1.55
+++ gdbtypes.c 23 Aug 2002 21:16:23 -0000
@@ -3431,6 +3431,41 @@ build_gdbtypes (void)
"__bfd_vma", (struct objfile *) NULL);
}

+char *
+class_name_from_physname (const char *physname)
+{
+ char *p, *end;
+ int depth = 0;
+ char *demangled_name = cplus_demangle (physname, DMGL_ANSI);
+
+ if (demangled_name == NULL)
+ return;
+
+ p = end = demangled_name;
+ while (*p && *p != ' ' && *p != '(')
+ {
+ if (depth == 0 && *p == ':' && *(p+1) == ':')
+ end = p;
+ else if (depth == '<' || depth == '(')
+ depth++;
+ else if (depth == '>' || depth == ')')
+ depth--;
+ p++;
+ }
+
+ if (end != demangled_name)
+ {
+ char *ret;
+ ret = xmalloc (end - demangled_name + 1);
+ memcpy (ret, demangled_name, end - demangled_name);
+ ret[end - demangled_name] = '\0';
+ xfree (demangled_name);
+ return ret;
+ }
+
+ xfree (demangled_name);
+ return NULL;
+}

extern void _initialize_gdbtypes (void);
void
Index: gdbtypes.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbtypes.h,v
retrieving revision 1.35
diff -u -p -r1.35 gdbtypes.h
--- gdbtypes.h 10 Aug 2002 05:12:40 -0000 1.35
+++ gdbtypes.h 23 Aug 2002 21:16:24 -0000
@@ -1130,6 +1130,8 @@ extern struct type *lookup_primitive_typ

extern char *gdb_mangle_name (struct type *, int, int);

+extern char *class_name_from_physname (const char *physname);
+
extern struct type *builtin_type (char **);

extern struct type *lookup_typename (char *, struct block *, int);
Index: stabsread.c
===================================================================
RCS file: /cvs/src/src/gdb/stabsread.c,v
retrieving revision 1.38
diff -u -p -r1.38 stabsread.c
--- stabsread.c 1 Aug 2002 17:18:32 -0000 1.38
+++ stabsread.c 23 Aug 2002 21:16:28 -0000
@@ -44,6 +44,7 @@
#include "demangle.h"
#include "language.h"
#include "doublest.h"
+#include "cp-abi.h"

#include <ctype.h>

@@ -136,8 +137,7 @@ static int
attach_fields_to_type (struct field_info *, struct type *, struct objfile *);

static struct type *read_struct_type (char **, struct type *,
- enum type_code,
- struct objfile *);
+ enum type_code, struct objfile *);

static struct type *read_array_type (char **, struct type *,
struct objfile *);
@@ -3093,6 +3093,9 @@ rs6000_builtin_type (int typenum)
$ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
name (such as `+=') and `.' marks the end of the operator name.

+ If we read at least one method with a complete physname, set
+ TYPE_NAME (TYPE) appropriately.
+
Returns 1 for success, 0 for failure. */

static int
@@ -3225,6 +3228,25 @@ read_member_functions (struct field_info
}
new_sublist->fn_field.physname = savestring (*pp, p - *pp);
*pp = p + 1;
+
+ /* This is needed because GCC doesn't output the complete name of
+ the class, for e.g. nested classes. For v3 there are no
+ abbreviated physnames, so we can find the real class name
+ from a synthetic or real constructor; for v2 in nested classes
+ the synthetic constructor [or a real one] is generally (always?)
+ present, and because its physname is mangled starting with two
+ underscores instead of starting with the method name, the
+ physname is included unabbreviated. */
+ if (is_constructor_name (new_sublist->fn_field.physname))
+ {
+ char *class_name
+ = class_name_from_physname (new_sublist->fn_field.physname);
+
+ /* G++ anonymous structures have names starting with '.'. */
+ if (class_name[0] != '.')
+ TYPE_NAME (type) = obconcat (&objfile->type_obstack, "",
+ "", class_name);
+ }

/* Set this member function's visibility fields. */
switch (*(*pp)++)