From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/undname.c | 73 +++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 47 deletions(-)
diff --git a/dlls/msvcrt/undname.c b/dlls/msvcrt/undname.c index 21a4924b6a4..85ee181fc2c 100644 --- a/dlls/msvcrt/undname.c +++ b/dlls/msvcrt/undname.c @@ -301,7 +301,7 @@ enum datatype_flags
/* forward declaration */ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, - struct array* pmt, enum datatype_flags flags); + enum datatype_flags flags);
static const char* get_number(struct parsed_symbol* sym) { @@ -354,7 +354,7 @@ static const char* get_number(struct parsed_symbol* sym) * Parses a list of function/method arguments, creates a string corresponding * to the arguments' list. */ -static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_term, +static char* get_args(struct parsed_symbol* sym, BOOL z_term, char open_char, char close_char)
{ @@ -378,7 +378,7 @@ static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_t sym->current++; break; } - if (!demangle_datatype(sym, &ct, pmt_ref, IN_ARGS)) + if (!demangle_datatype(sym, &ct, IN_ARGS)) return NULL; /* 'void' terminates an argument list in a function */ if (z_term && !strcmp(ct.left, "void")) break; @@ -504,7 +504,7 @@ static BOOL get_function_qualifier(struct parsed_symbol *sym, const char** quali }
static BOOL get_qualified_type(struct datatype_t *ct, struct parsed_symbol* sym, - struct array *pmt_ref, char qualif, enum datatype_flags flags) + char qualif, enum datatype_flags flags) { struct datatype_t xdt1; struct datatype_t xdt2; @@ -589,7 +589,7 @@ static BOOL get_qualified_type(struct datatype_t *ct, struct parsed_symbol* sym, }
/* Recurse to get the referred-to type */ - if (!demangle_datatype(sym, &sub_ct, pmt_ref, 0)) + if (!demangle_datatype(sym, &sub_ct, 0)) return FALSE; if (sub_ct.flags & DT_NO_LEADING_WS) ct->left++; @@ -653,15 +653,13 @@ static char* get_template_name(struct parsed_symbol* sym) unsigned start_mark = sym->names.start; unsigned stack_mark = sym->stack.num; unsigned args_mark = sym->args.num; - struct array array_pmt;
sym->names.start = sym->names.num; if (!(name = get_literal_string(sym))) { sym->names.start = start_mark; return FALSE; } - str_array_init(&array_pmt); - args = get_args(sym, &array_pmt, FALSE, '<', '>'); + args = get_args(sym, FALSE, '<', '>'); if (args != NULL) name = str_printf(sym, "%s%s", name, args); sym->names.num = num_mark; @@ -899,18 +897,17 @@ struct function_signature const char* arguments; };
-static BOOL get_function_signature(struct parsed_symbol* sym, struct array* pmt_ref, - struct function_signature* fs) +static BOOL get_function_signature(struct parsed_symbol* sym, struct function_signature* fs) { unsigned mark = sym->stack.num;
if (!get_calling_convention(*sym->current++, &fs->call_conv, &fs->exported, sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) || - !demangle_datatype(sym, &fs->return_ct, pmt_ref, FALSE)) + !demangle_datatype(sym, &fs->return_ct, FALSE)) return FALSE;
- if (!(fs->arguments = get_args(sym, pmt_ref, TRUE, '(', ')'))) + if (!(fs->arguments = get_args(sym, TRUE, '(', ')'))) return FALSE; sym->stack.num = mark;
@@ -925,10 +922,9 @@ static BOOL get_function_signature(struct parsed_symbol* sym, struct array* pmt_ * char** = (pointer to (pointer to (char))) */ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, - struct array* pmt_ref, enum datatype_flags flags) + enum datatype_flags flags) { char dt; - BOOL add_pmt = TRUE;
assert(ct); ct->left = ct->right = NULL; @@ -945,7 +941,6 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, case 'N': case 'O': case 'X': case 'Z': /* Simple data types */ ct->left = get_simple_type(dt); - add_pmt = FALSE; break; case 'T': /* union */ case 'U': /* struct */ @@ -981,17 +976,17 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, } else { - if (!get_qualified_type(ct, sym, pmt_ref, '?', flags)) goto done; + if (!get_qualified_type(ct, sym, '?', flags)) goto done; } break; case 'A': /* reference */ case 'B': /* volatile reference */ - if (!get_qualified_type(ct, sym, pmt_ref, dt, flags)) goto done; + if (!get_qualified_type(ct, sym, dt, flags)) goto done; break; case 'Q': /* const pointer */ case 'R': /* volatile pointer */ case 'S': /* const volatile pointer */ - if (!get_qualified_type(ct, sym, pmt_ref, (flags & IN_ARGS) ? dt : 'P', flags)) goto done; + if (!get_qualified_type(ct, sym, (flags & IN_ARGS) ? dt : 'P', flags)) goto done; break; case 'P': /* Pointer */ if (isdigit(*sym->current)) @@ -1012,7 +1007,7 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, goto done; if (!get_function_qualifier(sym, &function_qualifier)) goto done; - if (!get_function_signature(sym, pmt_ref, &fs)) + if (!get_function_signature(sym, &fs)) goto done;
ct->left = str_printf(sym, "%s%s (%s %s::*", @@ -1025,7 +1020,7 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
sym->current++;
- if (!get_function_signature(sym, pmt_ref, &fs)) + if (!get_function_signature(sym, &fs)) goto done;
ct->left = str_printf(sym, "%s%s (%s*", @@ -1035,7 +1030,7 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, } else goto done; } - else if (!get_qualified_type(ct, sym, pmt_ref, 'P', flags)) goto done; + else if (!get_qualified_type(ct, sym, 'P', flags)) goto done; break; case 'W': if (*sym->current == '4') @@ -1058,7 +1053,6 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, ct->left = str_array_get_ref(&sym->args, (dt - '0') * 2); ct->right = str_array_get_ref(&sym->args, (dt - '0') * 2 + 1); if (!ct->left) goto done; - add_pmt = FALSE; break; case '$': switch (*sym->current++) @@ -1110,7 +1104,7 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
sym->current++;
- if (!get_function_signature(sym, pmt_ref, &fs)) + if (!get_function_signature(sym, &fs)) goto done; ct->left = str_printf(sym, "%s%s %s%s", fs.return_ct.left, fs.return_ct.right, fs.call_conv, fs.arguments); @@ -1137,7 +1131,7 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, arr = str_printf(sym, "%s[%s]", arr, get_number(sym)); }
- if (!demangle_datatype(sym, &sub_ct, pmt_ref, 0)) goto done; + if (!demangle_datatype(sym, &sub_ct, 0)) goto done;
if (arr) ct->left = str_printf(sym, "%s %s", sub_ct.left, arr); @@ -1152,13 +1146,13 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
sym->current++; if (!get_qualifier(sym, &xdt, NULL)) goto done; - if (!demangle_datatype(sym, ct, pmt_ref, flags)) goto done; + if (!demangle_datatype(sym, ct, flags)) goto done; ct->left = str_printf(sym, "%s %s", ct->left, xdt.left); } else if (*sym->current == 'Q') { sym->current++; - if (!get_qualified_type(ct, sym, pmt_ref, '$', flags)) goto done; + if (!get_qualified_type(ct, sym, '$', flags)) goto done; } break; } @@ -1167,13 +1161,6 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, ERR("Unknown type %c\n", dt); break; } - if (add_pmt && pmt_ref && (flags & IN_ARGS)) - { - /* left and right are pushed as two separate strings */ - if (!str_array_push(sym, ct->left ? ct->left : "", -1, pmt_ref) || - !str_array_push(sym, ct->right ? ct->right : "", -1, pmt_ref)) - return FALSE; - } done:
return ct->left != NULL; @@ -1228,12 +1215,9 @@ static BOOL handle_data(struct parsed_symbol* sym) case '3': case '4': case '5': { unsigned mark = sym->stack.num; - struct array pmt; const char* class;
- str_array_init(&pmt); - - if (!demangle_datatype(sym, &ct, &pmt, 0)) goto done; + if (!demangle_datatype(sym, &ct, 0)) goto done; if (!get_qualifier(sym, &xdt, &class)) goto done; /* class doesn't seem to be displayed */ if (xdt.left && xdt.right) xdt.left = str_printf(sym, "%s %s", xdt.left, xdt.right); else if (!xdt.left) xdt.left = xdt.right; @@ -1289,7 +1273,6 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) const char* name = NULL; BOOL ret = FALSE, has_args = TRUE, has_ret = TRUE; unsigned mark; - struct array array_pmt;
/* FIXME: why 2 possible letters for each option? * 'A' private: @@ -1419,8 +1402,6 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) sym->flags)) goto done;
- str_array_init(&array_pmt); - /* Return type, or @ if 'void' */ if (has_ret && *sym->current == '@') { @@ -1430,7 +1411,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) } else if (has_ret) { - if (!demangle_datatype(sym, &ct_ret, &array_pmt, cast_op ? WS_AFTER_QUAL_IF : 0)) + if (!demangle_datatype(sym, &ct_ret, cast_op ? WS_AFTER_QUAL_IF : 0)) goto done; } if (!has_ret || sym->flags & UNDNAME_NO_FUNCTION_RETURNS) @@ -1442,7 +1423,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) }
mark = sym->stack.num; - if (has_args && !(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done; + if (has_args && !(args_str = get_args(sym, TRUE, '(', ')'))) goto done; if (sym->flags & UNDNAME_NAME_ONLY) args_str = function_qualifier = NULL; if (sym->flags & UNDNAME_NO_THISTYPE) function_qualifier = NULL; sym->stack.num = mark; @@ -1479,7 +1460,7 @@ static BOOL symbol_demangle(struct parsed_symbol* sym) { struct datatype_t ct;
- if (demangle_datatype(sym, &ct, NULL, 0)) + if (demangle_datatype(sym, &ct, 0)) { sym->result = str_printf(sym, "%s%s", ct.left, ct.right); ret = TRUE; @@ -1582,7 +1563,7 @@ static BOOL symbol_demangle(struct parsed_symbol* sym) struct datatype_t ct;
sym->current++; - if (!demangle_datatype(sym, &ct, NULL, 0)) + if (!demangle_datatype(sym, &ct, 0)) goto done; function_name = str_printf(sym, "%s%s `RTTI Type Descriptor'", ct.left, ct.right); @@ -1649,10 +1630,8 @@ static BOOL symbol_demangle(struct parsed_symbol* sym) { unsigned args_mark = sym->args.num; const char *args; - struct array array_pmt;
- str_array_init(&array_pmt); - args = get_args(sym, &array_pmt, FALSE, '<', '>'); + args = get_args(sym, FALSE, '<', '>'); if (args) function_name = function_name ? str_printf(sym, "%s%s", function_name, args) : args; sym->args.num = args_mark; sym->names.num = 0;
From: Piotr Caban piotr@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53934 --- dlls/msvcrt/tests/cpp.c | 6 ++++++ dlls/msvcrt/undname.c | 29 +++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c index d230659404d..5716455424a 100644 --- a/dlls/msvcrt/tests/cpp.c +++ b/dlls/msvcrt/tests/cpp.c @@ -1324,6 +1324,12 @@ static void test_demangle(void) "void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler ^)"}, /* 151 */ {"?RegisterModuleUninitializer@<CrtImplementationDetails>@@YAXBE$AAVEventHandler@System@@@Z", "void __cdecl <CrtImplementationDetails>::RegisterModuleUninitializer(class System::EventHandler % __ptr64 volatile)"}, +/* 152 */ {"??$forward@AEAUFFIValue@?1??call@FFIFunctionBinder@@CAHPEAUlua_State@@@Z@@std@@YAAEAUFFIValue@?1??call@" + "FFIFunctionBinder@@CAHPEAUxlua_State@@@Z@AEAU1?1??23@CAH0@Z@@Z", + "struct `private: static int __cdecl FFIFunctionBinder::call(struct xlua_State * __ptr64)'::`2'::FFIValue & " + "__ptr64 __cdecl std::forward<struct `private: static int __cdecl FFIFunctionBinder::call(struct lua_State " + "* __ptr64)'::`2'::FFIValue & __ptr64>(struct `private: static int __cdecl FFIFunctionBinder::call(struct " + "xlua_State * __ptr64)'::`2'::FFIValue & __ptr64)"}, }; int i, num_test = ARRAY_SIZE(test); char* name; diff --git a/dlls/msvcrt/undname.c b/dlls/msvcrt/undname.c index 91d4fdbc3eb..21a4924b6a4 100644 --- a/dlls/msvcrt/undname.c +++ b/dlls/msvcrt/undname.c @@ -70,6 +70,7 @@ struct parsed_symbol char* result; /* demangled string */
struct array names; /* array of names for back reference */ + struct array args; /* array of arguments for back reference */ struct array stack; /* stack of parsed strings */
void* alloc_list; /* linked list of allocated blocks */ @@ -362,12 +363,15 @@ static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_t char* args_str = NULL; char* last; unsigned int i; + const char *p;
str_array_init(&arg_collect);
/* Now come the function arguments */ while (*sym->current) { + p = sym->current; + /* Decode each data type and append it to the argument list */ if (*sym->current == '@') { @@ -382,14 +386,20 @@ static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_t &arg_collect)) return NULL; if (!strcmp(ct.left, "...")) break; + if (z_term && sym->current - p > 1 && sym->args.num < 20) + { + if (!str_array_push(sym, ct.left ? ct.left : "", -1, &sym->args) || + !str_array_push(sym, ct.right ? ct.right : "", -1, &sym->args)) + return NULL; + } } /* Functions are always terminated by 'Z'. If we made it this far and * don't find it, we have incorrectly identified a data type. */ if (z_term && *sym->current++ != 'Z') return NULL;
- if (arg_collect.num == 0 || - (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void"))) + if (arg_collect.num == 0 || + (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void"))) return str_printf(sym, "%cvoid%c", open_char, close_char); for (i = 1; i < arg_collect.num; i++) { @@ -398,12 +408,12 @@ static char* get_args(struct parsed_symbol* sym, struct array* pmt_ref, BOOL z_t
last = args_str ? args_str : arg_collect.elts[0]; if (close_char == '>' && last[strlen(last) - 1] == '>') - args_str = str_printf(sym, "%c%s%s %c", + args_str = str_printf(sym, "%c%s%s %c", open_char, arg_collect.elts[0], args_str, close_char); else - args_str = str_printf(sym, "%c%s%s%c", + args_str = str_printf(sym, "%c%s%s%c", open_char, arg_collect.elts[0], args_str, close_char); - + return args_str; }
@@ -642,6 +652,7 @@ static char* get_template_name(struct parsed_symbol* sym) unsigned num_mark = sym->names.num; unsigned start_mark = sym->names.start; unsigned stack_mark = sym->stack.num; + unsigned args_mark = sym->args.num; struct array array_pmt;
sym->names.start = sym->names.num; @@ -656,6 +667,7 @@ static char* get_template_name(struct parsed_symbol* sym) sym->names.num = num_mark; sym->names.start = start_mark; sym->stack.num = stack_mark; + sym->args.num = args_mark; return name; }
@@ -1043,9 +1055,8 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, case '5': case '6': case '7': case '8': case '9': /* Referring back to previously parsed type */ /* left and right are pushed as two separate strings */ - if (!pmt_ref) goto done; - ct->left = str_array_get_ref(pmt_ref, (dt - '0') * 2); - ct->right = str_array_get_ref(pmt_ref, (dt - '0') * 2 + 1); + ct->left = str_array_get_ref(&sym->args, (dt - '0') * 2); + ct->right = str_array_get_ref(&sym->args, (dt - '0') * 2 + 1); if (!ct->left) goto done; add_pmt = FALSE; break; @@ -1636,12 +1647,14 @@ static BOOL symbol_demangle(struct parsed_symbol* sym) sym->current++; if (in_template) { + unsigned args_mark = sym->args.num; const char *args; struct array array_pmt;
str_array_init(&array_pmt); args = get_args(sym, &array_pmt, FALSE, '<', '>'); if (args) function_name = function_name ? str_printf(sym, "%s%s", function_name, args) : args; + sym->args.num = args_mark; sym->names.num = 0; } if (!str_array_push(sym, function_name, -1, &sym->stack))
eric pouech (@epo) commented about dlls/msvcrt/undname.c:
!str_array_push(sym, ct.right ? ct.right : "", -1, &sym->args))
return NULL;
} /* Functions are always terminated by 'Z'. If we made it this far and * don't find it, we have incorrectly identified a data type. */ if (z_term && *sym->current++ != 'Z') return NULL;}
- if (arg_collect.num == 0 ||
(arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void")))
- if (arg_collect.num == 0 ||
for (i = 1; i < arg_collect.num; i++) {(arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void"))) return str_printf(sym, "%cvoid%c", open_char, close_char);
this looks like a gratuitous white-space only change
eric pouech (@epo) commented about dlls/msvcrt/undname.c:
last = args_str ? args_str : arg_collect.elts[0]; if (close_char == '>' && last[strlen(last) - 1] == '>')
args_str = str_printf(sym, "%c%s%s %c",
ditto
eric pouech (@epo) commented about dlls/msvcrt/undname.c:
last = args_str ? args_str : arg_collect.elts[0]; if (close_char == '>' && last[strlen(last) - 1] == '>')
args_str = str_printf(sym, "%c%s%s %c",
elseargs_str = str_printf(sym, "%c%s%s %c", open_char, arg_collect.elts[0], args_str, close_char);
args_str = str_printf(sym, "%c%s%s%c",
args_str = str_printf(sym, "%c%s%s%c", open_char, arg_collect.elts[0], args_str, close_char);
ditto
otherwise, tested against my local mangled names database and looks very good in output - a great bunch of unmangling correctly done with this MR - a couple of white space mismatches in "fixed" output, but likely not directly bound to this change
please also update tools/winedump/msmangle.c
On Mon Jan 29 13:59:03 2024 +0000, eric pouech wrote:
this looks like a gratuitous white-space only change
Yes, it's intentional. I have fixed some white-space errors close to the code that is changed.
On Mon Jan 29 14:56:13 2024 +0000, eric pouech wrote:
otherwise, tested against my local mangled names database and looks very good in output
- a great bunch of unmangling correctly done with this MR
- a couple of white space mismatches in "fixed" output, but likely not
directly bound to this change please also update tools/winedump/msmangle.c
I was planning to update winedump in separate MR after this one is merged.
On Mon Jan 29 14:54:03 2024 +0000, Piotr Caban wrote:
Yes, it's intentional. I have fixed some white-space errors close to the code that is changed.
I had in mind a smaller distance for white-space removal surrounding a change... (note that I don't mind the change at all, just it didn't look like the "usual rule")