From 3dc755fb814406e634cddba36cf0250fda624b5e Mon Sep 17 00:00:00 2001 From: Fred Fish Date: Fri, 14 Aug 1992 19:14:15 +0000 Subject: [PATCH] * cplus-dem.c (cplus_markers): Add table for gnu style and use throughout, in place of compile time constant CPLUS_MARKER. * cplus-dem.c (ARM_VTABLE_STRING, ARM_VTABLE_STRLEN): Add. * cplus-dem.c (cfront_special): New function, as suggested by pfieland@stratus.com. * cplus-dem.c (forget_types): New function. * cplus-dem.c (cplus_demangle): Call gnu_special, moved from demangle_prefix(). * cplus-dem.c (mop_up): Call forget_types(). * cplus-dem.c (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING): Use throughout, instead of checking current_demangling_style. * cplus-dem.c (demangle_signature): When finding an explicit start of function args, forget all remembered types for lucid/cfront style demangling. * cplus-dem.c (demangle_prefix): In a sequence of two or more underbar characters, use last pair as the delimiter. Hoist gnu_special() call up to cplus_demangle(). Call cfront_special() when appropriate. * cplus-dem.c (cplus_special): Fix virtual table name demangling for inherited classes. * cplus-dem.c (demangle_args): Document quirks of numbered references to previously seen types. * dbxread.c (read_ofile_symtab, process_one_symbol): Use AUTO_DEMANGLING rather than explicitly checking current_demangling_style. * demangle.h: Add some comments. * demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING, CFRONT_DEMANGLING): New macros. * dwarfread.c (LCC_PRODUCER): Remove trailing space, which is not found in the actual producer string produced by lcc. * dwarfread.c (handle_producer): Use AUTO_DEMANGLING rather than explicitly checking current_demangling_style. --- gdb/ChangeLog | 35 ++++++ gdb/cplus-dem.c | 275 ++++++++++++++++++++++++++++++++++++++---------- gdb/demangle.h | 19 +++- gdb/dwarfread.c | 4 +- 4 files changed, 276 insertions(+), 57 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 329996cad04..21195b9c276 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,38 @@ +Fri Aug 14 12:11:25 1992 Fred Fish (fnf@cygnus.com) + + * cplus-dem.c (cplus_markers): Add table for gnu style and + use throughout, in place of compile time constant CPLUS_MARKER. + * cplus-dem.c (ARM_VTABLE_STRING, ARM_VTABLE_STRLEN): Add. + * cplus-dem.c (cfront_special): New function, as suggested + by pfieland@stratus.com. + * cplus-dem.c (forget_types): New function. + * cplus-dem.c (cplus_demangle): Call gnu_special, moved from + demangle_prefix(). + * cplus-dem.c (mop_up): Call forget_types(). + * cplus-dem.c (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING): + Use throughout, instead of checking current_demangling_style. + * cplus-dem.c (demangle_signature): When finding an explicit + start of function args, forget all remembered types for + lucid/cfront style demangling. + * cplus-dem.c (demangle_prefix): In a sequence of two or more + underbar characters, use last pair as the delimiter. Hoist + gnu_special() call up to cplus_demangle(). Call cfront_special() + when appropriate. + * cplus-dem.c (cplus_special): Fix virtual table name demangling + for inherited classes. + * cplus-dem.c (demangle_args): Document quirks of numbered + references to previously seen types. + * dbxread.c (read_ofile_symtab, process_one_symbol): + Use AUTO_DEMANGLING rather than explicitly checking + current_demangling_style. + * demangle.h: Add some comments. + * demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING, LUCID_DEMANGLING, + CFRONT_DEMANGLING): New macros. + * dwarfread.c (LCC_PRODUCER): Remove trailing space, which is + not found in the actual producer string produced by lcc. + * dwarfread.c (handle_producer): Use AUTO_DEMANGLING rather + than explicitly checking current_demangling_style. + Thu Aug 13 11:54:46 1992 John Gilmore (gnu at cygnus.com) * breakpoint.c (enable_longjmp_breakpoint, diff --git a/gdb/cplus-dem.c b/gdb/cplus-dem.c index 525df0b53c9..4bf4b110e2e 100644 --- a/gdb/cplus-dem.c +++ b/gdb/cplus-dem.c @@ -32,14 +32,28 @@ #include #include -/* This is '$' on systems where the assembler can deal with that. - Where the assembler can't, it's '.' (but on many systems '.' is - used for other things). */ +/* In order to allow a single demangler executable to demangle strings + using various common values of CPLUS_MARKER, as well as any specific + one set at compile time, we maintain a string containing all the + commonly used ones, and check to see if the marker we are looking for + is in that string. CPLUS_MARKER is usually '$' on systems where the + assembler can deal with that. Where the assembler can't, it's usually + '.' (but on many systems '.' is used for other things). We put the + current defined CPLUS_MARKER first (which defaults to '$'), followed + by the next most common value, followed by an explicit '$' in case + the value of CPLUS_MARKER is not '$'. + + We could avoid this if we could just get g++ to tell us what the actual + cplus marker character is as part of the debug information, perhaps by + ensuring that it is the character that terminates the gcc_compiled + marker symbol (FIXME). */ #if !defined (CPLUS_MARKER) #define CPLUS_MARKER '$' #endif +static const char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; + #ifndef __STDC__ #define const #endif @@ -160,6 +174,9 @@ typedef struct string /* Beware: these aren't required to be */ #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_append(str, " ");} +#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/cfront virtual table prefix */ +#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ + /* Prototypes for local functions */ static char * @@ -191,6 +208,9 @@ demangle_prefix PARAMS ((string *, const char **, struct work_stuff *)); static int gnu_special PARAMS ((string *, const char **, struct work_stuff *)); +static int +cfront_special PARAMS ((string *, const char **, struct work_stuff *)); + static void string_need PARAMS ((string *, int)); @@ -245,6 +265,9 @@ demangle_function_name PARAMS ((string *, const char **, struct work_stuff*, static void remember_type PARAMS ((const char *, int, struct work_stuff *)); +static void +forget_types PARAMS ((struct work_stuff *)); + #if 0 static void string_prepends PARAMS ((string *, string *)); @@ -337,7 +360,23 @@ cplus_demangle (mangled, options) work -> options = options; string_init (&decl); - success = demangle_prefix (&decl, &mangled, work); + + /* First check to see if gnu style demangling is active and if the + string to be demangled contains a CPLUS_MARKER. If so, attempt to + recognize one of the gnu special forms rather than looking for a + standard prefix. In particular, don't worry about whether there + is a "__" string in the mangled string. Consider "_$_5__foo" for + example. */ + + if ((AUTO_DEMANGLING || GNU_DEMANGLING) + && (strpbrk (mangled, cplus_markers)) != NULL) + { + success = gnu_special (&decl, &mangled, work); + } + else + { + success = demangle_prefix (&decl, &mangled, work); + } if (success && (*mangled != '\0')) { success = demangle_signature (&decl, &mangled, work); @@ -358,13 +397,7 @@ mop_up (declp, work, success) /* Discard the remembered types, if any. */ - for (i = 0; i < work -> ntypes; i++) - { - if (work -> typevec[i] != NULL) - { - free (work -> typevec[i]); - } - } + forget_types (work); if (work -> typevec != NULL) { free ((char *) work -> typevec); @@ -439,8 +472,7 @@ demangle_signature (declp, mangled, work) { case 'Q': success = demangle_qualified (declp, mangled, work); - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { expect_func = 1; } @@ -467,8 +499,7 @@ demangle_signature (declp, mangled, work) remember_type (premangle, *mangled - premangle, work); } #endif - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { expect_func = 1; } @@ -480,8 +511,19 @@ demangle_signature (declp, mangled, work) the class name. For GNU style, it is just implied. So we can safely just consume any 'F' at this point and be compatible with either style. */ + func_done = 1; (*mangled)++; + + /* For lucid/cfront style we have to forget any types we might + have remembered up to this point, since they were not argument + types. GNU style considers all types seen as available for + back references. See comment in demangle_args() */ + + if (LUCID_DEMANGLING || CFRONT_DEMANGLING) + { + forget_types (work); + } success = demangle_args (declp, mangled, work); break; @@ -500,8 +542,7 @@ demangle_signature (declp, mangled, work) break; default: - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* Assume we have stumbled onto the first outermost function argument token, and start processing args. */ @@ -518,8 +559,7 @@ demangle_signature (declp, mangled, work) } break; } - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { if (success && expect_func) { @@ -530,8 +570,7 @@ demangle_signature (declp, mangled, work) } if (success && !func_done) { - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and bar__3fooi is 'foo::bar(int)'. We get here when we find the @@ -894,20 +933,25 @@ demangle_prefix (declp, mangled, work) { int success = 1; const char *scan; + int i; scan = strstr (*mangled, "__"); - if (scan == NULL) + + if (scan != NULL) { - if (current_demangling_style == auto_demangling || - current_demangling_style == gnu_demangling) + /* We found a sequence of two or more '_', ensure that we start at + the last pair in the sequence. */ + i = strspn (scan, "_"); + if (i > 2) { - success = gnu_special (declp, mangled, work); - } - else - { - success = 0; + scan += (i - 2); } } + + if (scan == NULL) + { + success = 0; + } else if (work -> static_type) { if (!isdigit (scan[0]) && (scan[0] != 't')) @@ -926,19 +970,23 @@ demangle_prefix (declp, mangled, work) /* Mangled name starts with "__". Skip over any leading '_' characters, then find the next "__" that separates the prefix from the signature. */ - while (*scan == '_') - { - scan++; - } - if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) - { - /* No separator (I.E. "__not_mangled"), or empty signature - (I.E. "__not_mangled_either__") */ - success = 0; - } - else + if (!(CFRONT_DEMANGLING || LUCID_DEMANGLING) + || (cfront_special (declp, mangled, work) == 0)) { - demangle_function_name (declp, mangled, work, scan); + while (*scan == '_') + { + scan++; + } + if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) + { + /* No separator (I.E. "__not_mangled"), or empty signature + (I.E. "__not_mangled_either__") */ + success = 0; + } + else + { + demangle_function_name (declp, mangled, work, scan); + } } } else if (*(scan + 2) != '\0') @@ -975,7 +1023,8 @@ DESCRIPTION the normal pattern. For example: _$_3foo (destructor for class foo) - _vt$foo (virtual table) + _vt$foo (foo virtual table) + _vt$foo$bar (foo::bar virtual table) _3foo$varname (static data member) */ @@ -990,7 +1039,7 @@ gnu_special (declp, mangled, work) const char *p; if ((*mangled)[0] == '_' - && (*mangled)[1] == CPLUS_MARKER + && strchr (cplus_markers, (*mangled)[1]) != NULL && (*mangled)[2] == '_') { /* Found a GNU style destructor, get past "__" */ @@ -1000,21 +1049,29 @@ gnu_special (declp, mangled, work) else if ((*mangled)[0] == '_' && (*mangled)[1] == 'v' && (*mangled)[2] == 't' - && (*mangled)[3] == CPLUS_MARKER) + && strchr (cplus_markers, (*mangled)[3]) != NULL) { /* Found a GNU style virtual table, get past "_vt" and create the decl. Note that we consume the entire mangled input string, which means that demangle_signature has no work to do. */ (*mangled) += 4; - n = strlen (*mangled); - string_appendn (declp, *mangled, n); + while (**mangled != '\0') + { + n = strcspn (*mangled, cplus_markers); + string_appendn (declp, *mangled, n); + (*mangled) += n; + if (**mangled != '\0') + { + string_append (declp, "::"); + (*mangled)++; + } + } string_append (declp, " virtual table"); - (*mangled) += n; } else if ((*mangled)[0] == '_' && isdigit ((*mangled)[1]) - && (p = strchr (*mangled, CPLUS_MARKER)) != NULL) + && (p = strpbrk (*mangled, cplus_markers)) != NULL) { /* static data member, "_3foo$varname" for example */ (*mangled)++; @@ -1033,6 +1090,67 @@ gnu_special (declp, mangled, work) return (success); } +/* + +LOCAL FUNCTION + + cfront_special -- special handling of cfront/lucid mangled strings + +SYNOPSIS + + static int + cfront_special (string *declp, const char **mangled, + struct work_stuff *work) + + +DESCRIPTION + + Process some special cfront style mangling forms that don't fit + the normal pattern. For example: + + __vtbl__3foo (foo virtual table) + __vtbl__3foo__3bar (bar::foo virtual table) + + */ + +static int +cfront_special (declp, mangled, work) + string *declp; + const char **mangled; + struct work_stuff *work; +{ + int n; + int i; + int success = 1; + const char *p; + + if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) + { + /* Found a cfront style virtual table, get past ARM_VTABLE_STRING + and create the decl. Note that we consume the entire mangled + input string, which means that demangle_signature has no work + to do. */ + (*mangled) += ARM_VTABLE_STRLEN; + while (**mangled != '\0') + { + n = consume_count (mangled); + string_prependn (declp, *mangled, n); + (*mangled) += n; + if ((*mangled)[0] == '_' && (*mangled)[1] == '_') + { + string_prepend (declp, "::"); + (*mangled) += 2; + } + } + string_append (declp, " virtual table"); + } + else + { + success = 0; + } + return (success); +} + /* Do a qualified name, such as "Q25Outer5Inner" for "Outer::Inner" */ static int @@ -1531,6 +1649,25 @@ remember_type (start, len, work) work -> typevec[work -> ntypes++] = tem; } +/* Forget the remembered types, but not the type vector itself. */ + +static void +forget_types (work) + struct work_stuff *work; +{ + int i; + + while (work -> ntypes > 0) + { + i = --(work -> ntypes); + if (work -> typevec[i] != NULL) + { + free (work -> typevec[i]); + work -> typevec[i] = NULL; + } + } +} + /* Process the argument list part of the signature, after any class spec has been consumed, as well as the first 'F' character (if any). For example: @@ -1539,7 +1676,39 @@ remember_type (start, len, work) "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" DECLP must be already initialised, usually non-empty. It won't be freed - on failure */ + on failure. + + Note that g++ differs significantly from cfront and lucid style mangling + with regards to references to previously seen types. For example, given + the source fragment: + + class foo { + public: + foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); + }; + + foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } + void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } + + g++ produces the names: + + __3fooiRT0iT2iT2 + foo__FiR3fooiT1iT1 + + while lcc (and presumably cfront as well) produces: + + foo__FiR3fooT1T2T1T2 + __ct__3fooFiR3fooT1T2T1T2 + + Note that g++ bases it's type numbers starting at zero and counts all + previously seen types, while lucid/cfront bases it's type numbers starting + at one and only considers types after it has seen the 'F' character + indicating the start of the function args. For lucid/cfront style, we + account for this difference by discarding any previously seen types when + we see the 'F' character, and subtracting one from the type number + reference. + + */ static int demangle_args (declp, type, work) @@ -1584,8 +1753,7 @@ demangle_args (declp, type, work) { return (0); } - if (current_demangling_style == lucid_demangling || - current_demangling_style == cfront_demangling) + if (LUCID_DEMANGLING || CFRONT_DEMANGLING) { t--; } @@ -1675,8 +1843,7 @@ demangle_function_name (declp, mangled, work, scan) (*mangled) = scan + 2; - if (current_demangling_style == lucid_demangling || - current_demangling_style == cfront_demangling) + if (LUCID_DEMANGLING || CFRONT_DEMANGLING) { /* See if we have an ARM style constructor or destructor operator. @@ -1701,7 +1868,7 @@ demangle_function_name (declp, mangled, work, scan) if (declp->p - declp->b >= 3 && declp->b[0] == 'o' && declp->b[1] == 'p' - && declp->b[2] == CPLUS_MARKER) + && strchr (cplus_markers, declp->b[2]) != NULL) { /* see if it's an assignment expression */ if (declp->p - declp->b >= 10 /* op$assign_ */ diff --git a/gdb/demangle.h b/gdb/demangle.h index ce50eb79a96..cc3fc60c0f4 100644 --- a/gdb/demangle.h +++ b/gdb/demangle.h @@ -19,6 +19,14 @@ #define DMGL_PARAMS (1 << 0) /* Include function args */ #define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ +/* Enumeration of possible demangling styles. + + Lucid and cfront styles are still kept logically distinct, even though + they now both behave identically. The resulting style is actual the + union of both. I.E. either style recognizes both "__pt__" and "__rf__" + for operator "->", even though the first is lucid style and the second + is cfront/ARM style. (FIXME?) */ + extern enum demangling_styles { unknown_demangling = 0, @@ -28,10 +36,19 @@ extern enum demangling_styles cfront_demangling } current_demangling_style; +/* Define string names for the various demangling styles. */ + +#define AUTO_DEMANGLING_STYLE_STRING "auto" #define GNU_DEMANGLING_STYLE_STRING "gnu" #define LUCID_DEMANGLING_STYLE_STRING "lucid" #define CFRONT_DEMANGLING_STYLE_STRING "cfront" -#define AUTO_DEMANGLING_STYLE_STRING "auto" + +/* Some macros to test what demangling style is active. */ + +#define AUTO_DEMANGLING (current_demangling_style == auto_demangling) +#define GNU_DEMANGLING (current_demangling_style == gnu_demangling) +#define LUCID_DEMANGLING (current_demangling_style == lucid_demangling) +#define CFRONT_DEMANGLING (current_demangling_style == cfront_demangling) extern void set_demangling_style PARAMS ((char *)); diff --git a/gdb/dwarfread.c b/gdb/dwarfread.c index fcca11c72f5..6844813fb04 100644 --- a/gdb/dwarfread.c +++ b/gdb/dwarfread.c @@ -76,7 +76,7 @@ typedef unsigned int DIE_REF; /* Reference to a DIE */ #endif #ifndef LCC_PRODUCER -#define LCC_PRODUCER "NCR C/C++ " +#define LCC_PRODUCER "NCR C/C++" #endif #ifndef CFRONT_PRODUCER @@ -1593,7 +1593,7 @@ handle_producer (producer) gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */ #if 1 /* Works, but is experimental. -fnf */ - if (current_demangling_style == auto_demangling) + if (AUTO_DEMANGLING) { if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))) { -- 2.30.2