diff options
-rw-r--r-- | binutils/ChangeLog | 7 | ||||
-rw-r--r-- | binutils/stabs.c | 304 |
2 files changed, 310 insertions, 1 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 0601728..708682f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2004-01-12 Ian Lance Taylor <ian@wasabisystems.com> + + * stabs.c (parse_stab_argtypes): Handle g++ ABI version 3 names. + (stab_demangle_argtypes): Likewise. + (stab_demangle_v3_argtypes): New static function. + (stab_demangle_v3_arg): New static function. + 2004-01-12 Nick Clifton <nickc@redhat.com> * objcopy.c (copy_object): Make the function boolean, returning diff --git a/binutils/stabs.c b/binutils/stabs.c index 558fe0e..5844f09 100644 --- a/binutils/stabs.c +++ b/binutils/stabs.c @@ -201,6 +201,11 @@ static debug_type stab_find_tagged_type (void *, struct stab_handle *, const char *, int, enum debug_type_kind); static debug_type *stab_demangle_argtypes (void *, struct stab_handle *, const char *, bfd_boolean *, unsigned int); +static debug_type *stab_demangle_v3_argtypes + (void *, struct stab_handle *, const char *, bfd_boolean *); +static debug_type stab_demangle_v3_arg + (void *, struct stab_handle *, struct demangle_component *, debug_type, + bfd_boolean *); /* Save a string in memory. */ @@ -2814,6 +2819,7 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info, bfd_boolean is_full_physname_constructor; bfd_boolean is_constructor; bfd_boolean is_destructor; + bfd_boolean is_v3; debug_type *args; bfd_boolean varargs; unsigned int physname_len = 0; @@ -2833,8 +2839,9 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info, && (argtypes[1] == '$' || argtypes[1] == '.') && argtypes[2] == '_') || strncmp (argtypes, "__dt", 4) == 0); + is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z'; - if (is_destructor || is_full_physname_constructor) + if (is_destructor || is_full_physname_constructor || is_v3) *pphysname = argtypes; else { @@ -3697,6 +3704,10 @@ stab_demangle_argtypes (void *dhandle, struct stab_handle *info, { struct stab_demangle_info minfo; + /* Check for the g++ V3 ABI. */ + if (physname[0] == '_' && physname[1] == 'Z') + return stab_demangle_v3_argtypes (dhandle, info, physname, pvarargs); + minfo.dhandle = dhandle; minfo.info = info; minfo.args = NULL; @@ -5045,3 +5056,294 @@ stab_demangle_remember_type (struct stab_demangle_info *minfo, return TRUE; } + +/* Demangle names encoded using the g++ V3 ABI. The newer versions of + g++ which use this ABI do not encode ordinary method argument types + in a mangled name; they simply output the argument types. However, + for a static method, g++ simply outputs the return type and the + physical name. So in that case we need to demangle the name here. + Here PHYSNAME is the physical name of the function, and we set the + variable pointed at by PVARARGS to indicate whether this function + is varargs. This returns NULL, or a NULL terminated array of + argument types. */ + +static debug_type * +stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info, + const char *physname, bfd_boolean *pvarargs) +{ + struct demangle_component *dc; + void *mem; + unsigned int alloc, count; + debug_type *pargs; + + dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem); + if (dc == NULL) + { + stab_bad_demangle (physname); + return NULL; + } + + /* We expect to see TYPED_NAME, and the right subtree describes the + function type. */ + if (dc->type != DEMANGLE_COMPONENT_TYPED_NAME + || dc->u.s_binary.right->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) + { + fprintf (stderr, _("Demangled name is not a function\n")); + free (mem); + return NULL; + } + + alloc = 10; + pargs = (debug_type *) xmalloc (alloc * sizeof *pargs); + *pvarargs = FALSE; + + count = 0; + + for (dc = dc->u.s_binary.right->u.s_binary.right; + dc != NULL; + dc = dc->u.s_binary.right) + { + debug_type arg; + bfd_boolean varargs; + + if (dc->type != DEMANGLE_COMPONENT_ARGLIST) + { + fprintf (stderr, _("Unexpected type in demangle tree\n")); + free (mem); + return NULL; + } + + arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, + NULL, &varargs); + if (arg == NULL) + { + if (varargs) + { + *pvarargs = TRUE; + continue; + } + free (mem); + return NULL; + } + + if (count + 1 >= alloc) + { + alloc += 10; + pargs = (debug_type *) xrealloc (pargs, alloc * sizeof *pargs); + } + + pargs[count] = arg; + ++count; + } + + pargs[count] = DEBUG_TYPE_NULL; + + free (mem); + + return pargs; +} + +/* Convert a struct demangle_component tree describing an argument + type into a debug_type. */ + +static debug_type +stab_demangle_v3_arg (void *dhandle, struct stab_handle *info, + struct demangle_component *dc, debug_type context, + bfd_boolean *pvarargs) +{ + debug_type dt; + + if (pvarargs != NULL) + *pvarargs = FALSE; + + switch (dc->type) + { + /* FIXME: These are demangle component types which we probably + need to handle one way or another. */ + case DEMANGLE_COMPONENT_LOCAL_NAME: + case DEMANGLE_COMPONENT_TYPED_NAME: + case DEMANGLE_COMPONENT_TEMPLATE_PARAM: + case DEMANGLE_COMPONENT_CTOR: + case DEMANGLE_COMPONENT_DTOR: + case DEMANGLE_COMPONENT_JAVA_CLASS: + case DEMANGLE_COMPONENT_RESTRICT_THIS: + case DEMANGLE_COMPONENT_VOLATILE_THIS: + case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: + case DEMANGLE_COMPONENT_COMPLEX: + case DEMANGLE_COMPONENT_IMAGINARY: + case DEMANGLE_COMPONENT_VENDOR_TYPE: + case DEMANGLE_COMPONENT_FUNCTION_TYPE: + case DEMANGLE_COMPONENT_ARRAY_TYPE: + case DEMANGLE_COMPONENT_PTRMEM_TYPE: + case DEMANGLE_COMPONENT_ARGLIST: + default: + fprintf (stderr, _("Unrecognized demangle component\n")); + return NULL; + + case DEMANGLE_COMPONENT_NAME: + if (context != NULL) + { + const debug_field *fields; + + fields = debug_get_fields (dhandle, context); + if (fields != NULL) + { + /* Try to find this type by looking through the context + class. */ + for (; *fields != DEBUG_FIELD_NULL; fields++) + { + debug_type ft; + const char *dn; + + ft = debug_get_field_type (dhandle, *fields); + if (ft == NULL) + return NULL; + dn = debug_get_type_name (dhandle, ft); + if (dn != NULL + && (int) strlen (dn) == dc->u.s_name.len + && strncmp (dn, dc->u.s_name.s, dc->u.s_name.len) == 0) + return ft; + } + } + } + return stab_find_tagged_type (dhandle, info, dc->u.s_name.s, + dc->u.s_name.len, DEBUG_KIND_ILLEGAL); + + case DEMANGLE_COMPONENT_QUAL_NAME: + context = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, + context, NULL); + if (context == NULL) + return NULL; + return stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.right, + context, NULL); + + case DEMANGLE_COMPONENT_TEMPLATE: + { + char *p; + size_t alc; + + /* We print this component to get a class name which we can + use. FIXME: This probably won't work if the template uses + template parameters which refer to an outer template. */ + p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc); + if (p == NULL) + { + fprintf (stderr, _("Failed to print demangled template\n")); + return NULL; + } + dt = stab_find_tagged_type (dhandle, info, p, strlen (p), + DEBUG_KIND_CLASS); + free (p); + return dt; + } + + case DEMANGLE_COMPONENT_SUB_STD: + return stab_find_tagged_type (dhandle, info, dc->u.s_string.string, + dc->u.s_string.len, DEBUG_KIND_ILLEGAL); + + case DEMANGLE_COMPONENT_RESTRICT: + case DEMANGLE_COMPONENT_VOLATILE: + case DEMANGLE_COMPONENT_CONST: + case DEMANGLE_COMPONENT_POINTER: + case DEMANGLE_COMPONENT_REFERENCE: + dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL, + NULL); + if (dt == NULL) + return NULL; + + switch (dc->type) + { + default: + abort (); + case DEMANGLE_COMPONENT_RESTRICT: + /* FIXME: We have no way to represent restrict. */ + return dt; + case DEMANGLE_COMPONENT_VOLATILE: + return debug_make_volatile_type (dhandle, dt); + case DEMANGLE_COMPONENT_CONST: + return debug_make_const_type (dhandle, dt); + case DEMANGLE_COMPONENT_POINTER: + return debug_make_pointer_type (dhandle, dt); + case DEMANGLE_COMPONENT_REFERENCE: + return debug_make_reference_type (dhandle, dt); + } + + case DEMANGLE_COMPONENT_BUILTIN_TYPE: + { + char *p; + size_t alc; + debug_type ret; + + /* We print this component in order to find out the type name. + FIXME: Should we instead expose the + demangle_builtin_type_info structure? */ + p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc); + if (p == NULL) + { + fprintf (stderr, _("Couldn't get demangled builtin type\n")); + return NULL; + } + + /* The mangling is based on the type, but does not itself + indicate what the sizes are. So we have to guess. */ + if (strcmp (p, "signed char") == 0) + ret = debug_make_int_type (dhandle, 1, FALSE); + else if (strcmp (p, "bool") == 0) + ret = debug_make_bool_type (dhandle, 1); + else if (strcmp (p, "char") == 0) + ret = debug_make_int_type (dhandle, 1, FALSE); + else if (strcmp (p, "double") == 0) + ret = debug_make_float_type (dhandle, 8); + else if (strcmp (p, "long double") == 0) + ret = debug_make_float_type (dhandle, 8); + else if (strcmp (p, "float") == 0) + ret = debug_make_float_type (dhandle, 4); + else if (strcmp (p, "__float128") == 0) + ret = debug_make_float_type (dhandle, 16); + else if (strcmp (p, "unsigned char") == 0) + ret = debug_make_int_type (dhandle, 1, TRUE); + else if (strcmp (p, "int") == 0) + ret = debug_make_int_type (dhandle, 4, FALSE); + else if (strcmp (p, "unsigned int") == 0) + ret = debug_make_int_type (dhandle, 4, TRUE); + else if (strcmp (p, "long") == 0) + ret = debug_make_int_type (dhandle, 4, FALSE); + else if (strcmp (p, "unsigned long") == 0) + ret = debug_make_int_type (dhandle, 4, TRUE); + else if (strcmp (p, "__int128") == 0) + ret = debug_make_int_type (dhandle, 16, FALSE); + else if (strcmp (p, "unsigned __int128") == 0) + ret = debug_make_int_type (dhandle, 16, TRUE); + else if (strcmp (p, "short") == 0) + ret = debug_make_int_type (dhandle, 2, FALSE); + else if (strcmp (p, "unsigned short") == 0) + ret = debug_make_int_type (dhandle, 2, TRUE); + else if (strcmp (p, "void") == 0) + ret = debug_make_void_type (dhandle); + else if (strcmp (p, "wchar_t") == 0) + ret = debug_make_int_type (dhandle, 4, TRUE); + else if (strcmp (p, "long long") == 0) + ret = debug_make_int_type (dhandle, 8, FALSE); + else if (strcmp (p, "unsigned long long") == 0) + ret = debug_make_int_type (dhandle, 8, TRUE); + else if (strcmp (p, "...") == 0) + { + if (pvarargs == NULL) + fprintf (stderr, _("Unexpected demangled varargs\n")); + else + *pvarargs = TRUE; + ret = NULL; + } + else + { + fprintf (stderr, _("Unrecognized demangled builtin type\n")); + ret = NULL; + } + + free (p); + + return ret; + } + } +} |