From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jerry Gamache To: "'binutils@sourceware.cygnus.com'" Subject: Demangling long function argument lists Date: Wed, 02 Aug 2000 17:03:00 -0000 Message-id: X-SW-Source: 2000-08/msg00019.html Title: Demangling long function argument lists I found a bug in libiberty/cplus-dem.c where the repeat count for long function prototypes was not extracted correctly when demangling (still there in binutils snapshot 000801). When mangling the following name: class bar { ... }; int foo(int, int, int, int, int, int, int, int, int, int, bar, bar, bar, bar); I get foo__FiiiiiiiiiiG3barN310_ which fails when demangling using c++filt (or, most important in my case, when resctricting the export of C++ symbols in a version-script) The problem lies in the get_count function, which gets called twice in demangle_args. The function will always decode everything up to the underscore, giving a repeat count of 310 of the "unknown" arg. When called the first time to get the repeat count, the get_count function must make sure something is left after the underscore for the typevec index. I looked in gcc/cp/method.c and g++ will emit underscores if the repeat count is greater than 10, which means N12_12_ would be the way to signify 12 repeats of the 12th arg. Probably fixable by adding a boolean parameter to get_count indicating the need for some numbers after the underscore, which means the last test in get_count would look like           if (*p == '_' && !(leave_number && !isdigit(*(p+1)))) In fact, here is a patch against snapshot 000801 that worked in my case. Another option would be to create a specialized get_repeat_count function instead.         Jerry Gamache         SDE Core & Linux port         Avid/SoftImage Montreal =================================================================== *** cplus-dem.c Wed Aug  2 19:41:36 2000 --- cplus-dem.c.orig    Wed Aug  2 18:57:46 2000 *************** *** 413,419 ****   string_append_template_idx PARAMS ((string *, int));     static int ! get_count PARAMS ((const char **, int, int *));     static int   consume_count PARAMS ((const char **)); --- 413,419 ----   string_append_template_idx PARAMS ((string *, int));     static int ! get_count PARAMS ((const char **, int *));     static int   consume_count PARAMS ((const char **)); *************** *** 1499,1505 ****       string_append (tname, "template <");     /* get size of template parameter list */ !   if (get_count (mangled, 0, &r))       {         for (i = 0; i < r; i++)         { --- 1499,1505 ----       string_append (tname, "template <");     /* get size of template parameter list */ !   if (get_count (mangled, &r))       {         for (i = 0; i < r; i++)         { *************** *** 1921,1927 ****     if (!is_java_array)       string_append (tname, "<");     /* get size of template parameter list */ !   if (!get_count (mangled, 0, &r))       {         return (0);       } --- 1921,1927 ----     if (!is_java_array)       string_append (tname, "<");     /* get size of template parameter list */ !   if (!get_count (mangled, &r))       {         return (0);       } *************** *** 3214,3220 ****   SYNOPSIS           static int !       get_count (const char **type, int leave_numbers, int *count)     DESCRIPTION   --- 3214,3220 ----   SYNOPSIS           static int !       get_count (const char **type, int *count)     DESCRIPTION   *************** *** 3226,3235 ****           If *type points at a string of digits followed by an         underscore, set *count to their value as an integer, advance !       *type to point *after the underscore, but if the leave_number !       variable is true, then make sure there is a number left to !       crunch after the underscore. !                 If *type points at a string of digits not followed by an         underscore, consume only the first digit.  Set *count to its --- 3226,3232 ----           If *type points at a string of digits followed by an         underscore, set *count to their value as an integer, advance !       *type to point *after the underscore, and return 1.           If *type points at a string of digits not followed by an         underscore, consume only the first digit.  Set *count to its *************** *** 3252,3268 ****           pointer to an integer (`Pi'), and then the next five arguments           are the same (`N5'), and the first repeat is the function's           second argument (`1'). - -       Also of note, the g++ compiler will emit underscore everytime -       a number is greater than 10, giving N10_1 for ten repeats of -       argument 1, N10_10_ for ten repeats of argument 10, and the -       non-trivial N510_ for five repeats of argument 10.   */     static int ! get_count (type, leave_number, count)        const char **type; -      int leave_number;        int *count;   {     const char *p; --- 3249,3259 ----           pointer to an integer (`Pi'), and then the next five arguments           are the same (`N5'), and the first repeat is the function's           second argument (`1').   */     static int ! get_count (type, count)        const char **type;        int *count;   {     const char *p; *************** *** 3285,3291 ****               p++;             }           while (isdigit ((unsigned char)*p)); !         if (*p == '_' && !(leave_number && !isdigit(*(p+1))))             {               *type = p + 1;               *count = n; --- 3276,3282 ----               p++;             }           while (isdigit ((unsigned char)*p)); !         if (*p == '_')             {               *type = p + 1;               *count = n; *************** *** 3366,3372 ****         /* A back reference to a previously seen type */         case 'T':           (*mangled)++; !         if (!get_count (mangled, 0, &n) || n >= work -> ntypes)             {               success = 0;             } --- 3357,3363 ----         /* A back reference to a previously seen type */         case 'T':           (*mangled)++; !         if (!get_count (mangled, &n) || n >= work -> ntypes)             {               success = 0;             } *************** *** 3540,3546 ****       /* A back reference to a previously seen squangled type */       case 'B':         (*mangled)++; !       if (!get_count (mangled, 0, &n) || n >= work -> numb)         success = 0;         else         string_append (result, work->btypevec[n]); --- 3531,3537 ----       /* A back reference to a previously seen squangled type */       case 'B':         (*mangled)++; !       if (!get_count (mangled, &n) || n >= work -> numb)         success = 0;         else         string_append (result, work->btypevec[n]); *************** *** 4247,4253 ****             if (temptype == 'N')             { !             if (!get_count (mangled, 1, &r))                 {                   return (0);                 } --- 4238,4244 ----             if (temptype == 'N')             { !             if (!get_count (mangled, &r))                 {                   return (0);                 } *************** *** 4271,4277 ****               }             else             { !             if (!get_count (mangled, 0, &t))                 {                   return (0);                 } --- 4262,4268 ----               }             else             { !             if (!get_count (mangled, &t))                 {                   return (0);                 } ===================================================================