From 7a0f2c7ffbcfef6d02184c44353b5692ef3c7ad1 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Fri, 25 Apr 2014 20:01:08 +0000 Subject: [PATCH] [CRT] - Sync get_this_pointer with Wine. Fixes crash in msvcrt_winetest:cpp - Sync undname.c with Wine. Fixes assertion failure in msvcrt_winetest:cpp svn path=/trunk/; revision=62967 --- reactos/lib/sdk/crt/except/cpp.c | 2 +- .../sdk/crt/include/internal/wine/cppexcept.h | 17 +- .../sdk/crt/include/internal/wine/msvcrt.h | 25 ++- reactos/lib/sdk/crt/wine/undname.c | 193 ++++++++++-------- 4 files changed, 144 insertions(+), 93 deletions(-) diff --git a/reactos/lib/sdk/crt/except/cpp.c b/reactos/lib/sdk/crt/except/cpp.c index 402734e7f20..f54e8a78d21 100644 --- a/reactos/lib/sdk/crt/except/cpp.c +++ b/reactos/lib/sdk/crt/except/cpp.c @@ -604,7 +604,7 @@ const char * __stdcall MSVCRT_type_info_name(type_info * _this) * Is this '.' really part of the mangled name, or has it some other meaning ? */ char* name = __unDName(0, _this->mangled + 1, 0, - MSVCRT_malloc, MSVCRT_free, 0x2800); + MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE); if (name) { size_t len = strlen(name); diff --git a/reactos/lib/sdk/crt/include/internal/wine/cppexcept.h b/reactos/lib/sdk/crt/include/internal/wine/cppexcept.h index d1b60c3139b..d4dbbee2f34 100644 --- a/reactos/lib/sdk/crt/include/internal/wine/cppexcept.h +++ b/reactos/lib/sdk/crt/include/internal/wine/cppexcept.h @@ -164,20 +164,21 @@ static inline const char *dbgstr_type_info( const type_info *info ) /* compute the this pointer for a base class of a given type */ static inline void *get_this_pointer( const this_ptr_offsets *off, void *object ) { - void *this_ptr; - int *offset_ptr; - if (!object) return NULL; - this_ptr = (char *)object + off->this_offset; + if (off->vbase_descr >= 0) { + int *offset_ptr; + /* move this ptr to vbase descriptor */ - this_ptr = (char *)this_ptr + off->vbase_descr; + object = (char *)object + off->vbase_descr; /* and fetch additional offset from vbase descriptor */ - offset_ptr = (int *)(*(char **)this_ptr + off->vbase_offset); - this_ptr = (char *)this_ptr + *offset_ptr; + offset_ptr = (int *)(*(char **)object + off->vbase_offset); + object = (char *)object + *offset_ptr; } - return this_ptr; + + object = (char *)object + off->this_offset; + return object; } #endif /* __MSVCRT_CPPEXCEPT_H */ diff --git a/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h b/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h index f4d30aa97bb..319075a597f 100644 --- a/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h +++ b/reactos/lib/sdk/crt/include/internal/wine/msvcrt.h @@ -81,9 +81,6 @@ void __cdecl MSVCRT_operator_delete(void*); typedef void* (__cdecl *malloc_func_t)(size_t); typedef void (__cdecl *free_func_t)(void*); -extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,unsigned short int); -extern char* __cdecl __unDNameEx(char *,const char*,int,malloc_func_t,free_func_t,void *,unsigned short int); - /* Setup and teardown multi threaded locks */ extern void msvcrt_init_mt_locks(void); extern void msvcrt_free_mt_locks(void); @@ -119,6 +116,28 @@ extern unsigned create_io_inherit_block(WORD*, BYTE**); #define MSVCRT__OUT_TO_MSGBOX 2 #define MSVCRT__REPORT_ERRMODE 3 +extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,unsigned short int); + +/* __unDName/__unDNameEx flags */ +#define UNDNAME_COMPLETE (0x0000) +#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) /* Don't show __ in calling convention */ +#define UNDNAME_NO_MS_KEYWORDS (0x0002) /* Don't show calling convention at all */ +#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) /* Don't show function/method return value */ +#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) +#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) +#define UNDNAME_NO_MS_THISTYPE (0x0020) +#define UNDNAME_NO_CV_THISTYPE (0x0040) +#define UNDNAME_NO_THISTYPE (0x0060) +#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) /* Don't show access specifier (public/protected/private) */ +#define UNDNAME_NO_THROW_SIGNATURES (0x0100) +#define UNDNAME_NO_MEMBER_TYPE (0x0200) /* Don't show static/virtual specifier */ +#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) +#define UNDNAME_32_BIT_DECODE (0x0800) +#define UNDNAME_NAME_ONLY (0x1000) /* Only report the variable/method name */ +#define UNDNAME_NO_ARGUMENTS (0x2000) /* Don't show method arguments */ +#define UNDNAME_NO_SPECIAL_SYMS (0x4000) +#define UNDNAME_NO_COMPLEX_TYPE (0x8000) + typedef void (*float_handler)(int, int); void _default_handler(int signal); typedef struct _sig_element diff --git a/reactos/lib/sdk/crt/wine/undname.c b/reactos/lib/sdk/crt/wine/undname.c index 71956f6c4d3..4d64a4a1fd8 100644 --- a/reactos/lib/sdk/crt/wine/undname.c +++ b/reactos/lib/sdk/crt/wine/undname.c @@ -33,25 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); * - back-port this new code into tools/winedump/msmangle.c */ -#define UNDNAME_COMPLETE (0x0000) -#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001) /* Don't show __ in calling convention */ -#define UNDNAME_NO_MS_KEYWORDS (0x0002) /* Don't show calling convention at all */ -#define UNDNAME_NO_FUNCTION_RETURNS (0x0004) /* Don't show function/method return value */ -#define UNDNAME_NO_ALLOCATION_MODEL (0x0008) -#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010) -#define UNDNAME_NO_MS_THISTYPE (0x0020) -#define UNDNAME_NO_CV_THISTYPE (0x0040) -#define UNDNAME_NO_THISTYPE (0x0060) -#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080) /* Don't show access specifier (public/protected/private) */ -#define UNDNAME_NO_THROW_SIGNATURES (0x0100) -#define UNDNAME_NO_MEMBER_TYPE (0x0200) /* Don't show static/virtual specifier */ -#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400) -#define UNDNAME_32_BIT_DECODE (0x0800) -#define UNDNAME_NAME_ONLY (0x1000) /* Only report the variable/method name */ -#define UNDNAME_NO_ARGUMENTS (0x2000) /* Don't show method arguments */ -#define UNDNAME_NO_SPECIAL_SYMS (0x4000) -#define UNDNAME_NO_COMPLEX_TYPE (0x8000) - /* How data types modifiers are stored: * M (in the following definitions) is defined for * 'A', 'B', 'C' and 'D' as follows @@ -267,7 +248,7 @@ static char* str_printf(struct parsed_symbol* sym, const char* format, ...) { case 's': t = va_arg(args, char*); if (t) len += (int)strlen(t); break; case 'c': (void)va_arg(args, int); len++; break; - default: i--; /* fall thru */ + default: i--; /* fall through */ case '%': len++; break; } } @@ -294,7 +275,7 @@ static char* str_printf(struct parsed_symbol* sym, const char* format, ...) case 'c': *p++ = (char)va_arg(args, int); break; - default: i--; /* fall thru */ + default: i--; /* fall through */ case '%': *p++ = '%'; break; } } @@ -348,7 +329,7 @@ static const char* get_number(struct parsed_symbol* sym) if (*sym->current != '@') return NULL; ptr = und_alloc(sym, 17); - sprintf(ptr, "%s%d", sgn ? "-" : "", ret); + sprintf(ptr, "%s%u", sgn ? "-" : "", ret); sym->current++; } else return NULL; @@ -423,7 +404,12 @@ static BOOL get_modifier(struct parsed_symbol *sym, const char **ret, const char *ptr_modif = NULL; if (*sym->current == 'E') { - *ptr_modif = "__ptr64"; + if (!(sym->flags & UNDNAME_NO_MS_KEYWORDS)) + { + *ptr_modif = "__ptr64"; + if (sym->flags & UNDNAME_NO_LEADING_UNDERSCORES) + *ptr_modif = *ptr_modif + 2; + } sym->current++; } switch (*sym->current++) @@ -446,7 +432,13 @@ static BOOL get_modified_type(struct datatype_t *ct, struct parsed_symbol* sym, if (*sym->current == 'E') { - ptr_modif = " __ptr64"; + if (!(sym->flags & UNDNAME_NO_MS_KEYWORDS)) + { + if (sym->flags & UNDNAME_NO_LEADING_UNDERSCORES) + ptr_modif = " ptr64"; + else + ptr_modif = " __ptr64"; + } sym->current++; } @@ -556,8 +548,10 @@ static char* get_template_name(struct parsed_symbol* sym) struct array array_pmt; sym->names.start = sym->names.num; - if (!(name = get_literal_string(sym))) + 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, '<', '>'); if (args != NULL) @@ -1082,6 +1076,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) { char accmem; const char* access = NULL; + int access_id = -1; const char* member_type = NULL; struct datatype_t ct_ret; const char* call_conv; @@ -1089,7 +1084,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) const char* exported; const char* args_str = NULL; const char* name = NULL; - BOOL ret = FALSE; + BOOL ret = FALSE, has_args = TRUE, has_ret = TRUE; unsigned mark; struct array array_pmt; @@ -1120,50 +1115,104 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) * 'X' public: thunk * 'Y' * 'Z' + * "$0" private: thunk vtordisp + * "$1" private: thunk vtordisp + * "$2" protected: thunk vtordisp + * "$3" protected: thunk vtordisp + * "$4" public: thunk vtordisp + * "$5" public: thunk vtordisp + * "$B" vcall thunk + * "$R" thunk vtordispex */ accmem = *sym->current++; - if (accmem < 'A' || accmem > 'Z') goto done; + if (accmem == '$') + { + if (*sym->current >= '0' && *sym->current <= '5') + access_id = (*sym->current - '0') / 2; + else if (*sym->current == 'R') + access_id = (sym->current[1] - '0') / 2; + else if (*sym->current != 'B') + goto done; + } + else if (accmem >= 'A' && accmem <= 'Z') + access_id = (accmem - 'A') / 8; + else + goto done; - if (!(sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS)) + switch (access_id) { - switch ((accmem - 'A') / 8) + case 0: access = "private: "; break; + case 1: access = "protected: "; break; + case 2: access = "public: "; break; + } + if (accmem == '$' || (accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) + access = str_printf(sym, "[thunk]:%s", access ? access : " "); + + if (accmem == '$' && *sym->current != 'B') + member_type = "virtual "; + else if (accmem <= 'X') + { + switch ((accmem - 'A') % 8) { - case 0: access = "private: "; break; - case 1: access = "protected: "; break; - case 2: access = "public: "; break; - } - } - if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE)) - { - if (accmem <= 'X') - { - switch ((accmem - 'A') % 8) - { - case 2: case 3: member_type = "static "; break; - case 4: case 5: member_type = "virtual "; break; - case 6: case 7: - access = str_printf(sym, "[thunk]:%s", access); - member_type = "virtual "; - break; - } + case 2: case 3: member_type = "static "; break; + case 4: case 5: case 6: case 7: member_type = "virtual "; break; } } + if (sym->flags & UNDNAME_NO_ACCESS_SPECIFIERS) + access = NULL; + if (sym->flags & UNDNAME_NO_MEMBER_TYPE) + member_type = NULL; + name = get_class_string(sym, 0); - if ((accmem - 'A') % 8 == 6 || (accmem - '8') % 8 == 7) /* a thunk */ + if (accmem == '$' && *sym->current == 'B') /* vcall thunk */ + { + const char *n; + + sym->current++; + n = get_number(sym); + + if(!n || *sym->current++ != 'A') goto done; + name = str_printf(sym, "%s{%s,{flat}}' }'", name, n); + has_args = FALSE; + has_ret = FALSE; + } + else if (accmem == '$' && *sym->current == 'R') /* vtordispex thunk */ + { + const char *n1, *n2, *n3, *n4; + + sym->current += 2; + n1 = get_number(sym); + n2 = get_number(sym); + n3 = get_number(sym); + n4 = get_number(sym); + + if(!n1 || !n2 || !n3 || !n4) goto done; + name = str_printf(sym, "%s`vtordispex{%s,%s,%s,%s}' ", name, n1, n2, n3, n4); + } + else if (accmem == '$') /* vtordisp thunk */ + { + const char *n1, *n2; + + sym->current++; + n1 = get_number(sym); + n2 = get_number(sym); + + if (!n1 || !n2) goto done; + name = str_printf(sym, "%s`vtordisp{%s,%s}' ", name, n1, n2); + } + else if ((accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) /* a thunk */ name = str_printf(sym, "%s`adjustor{%s}' ", name, get_number(sym)); - if (accmem <= 'X') + if (has_args && (accmem == '$' || + (accmem <= 'X' && (accmem - 'A') % 8 != 2 && (accmem - 'A') % 8 != 3))) { - if (((accmem - 'A') % 8) != 2 && ((accmem - 'A') % 8) != 3) - { - const char *ptr_modif; - /* Implicit 'this' pointer */ - /* If there is an implicit this pointer, const modifier follows */ - if (!get_modifier(sym, &modifier, &ptr_modif)) goto done; - if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif); - } + const char *ptr_modif; + /* Implicit 'this' pointer */ + /* If there is an implicit this pointer, const modifier follows */ + if (!get_modifier(sym, &modifier, &ptr_modif)) goto done; + if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif); } if (!get_calling_convention(*sym->current++, &call_conv, &exported, @@ -1173,18 +1222,18 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) str_array_init(&array_pmt); /* Return type, or @ if 'void' */ - if (*sym->current == '@') + if (has_ret && *sym->current == '@') { ct_ret.left = "void"; ct_ret.right = NULL; sym->current++; } - else + else if (has_ret) { if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE)) goto done; } - if (sym->flags & UNDNAME_NO_FUNCTION_RETURNS) + if (!has_ret || sym->flags & UNDNAME_NO_FUNCTION_RETURNS) ct_ret.left = ct_ret.right = NULL; if (cast_op) { @@ -1193,8 +1242,9 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op) } mark = sym->stack.num; - if (!(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done; + if (has_args && !(args_str = get_args(sym, &array_pmt, TRUE, '(', ')'))) goto done; if (sym->flags & UNDNAME_NAME_ONLY) args_str = modifier = NULL; + if (sym->flags & UNDNAME_NO_THISTYPE) modifier = NULL; sym->stack.num = mark; /* Note: '()' after 'Z' means 'throws', but we don't care here @@ -1210,23 +1260,6 @@ done: return ret; } -/****************************************************************** - * handle_template - * Does the final parsing and handling for a name with templates - */ -static BOOL handle_template(struct parsed_symbol* sym) -{ - const char* name; - const char* args; - - assert(*sym->current == '$'); - sym->current++; - if (!(name = get_literal_string(sym))) return FALSE; - if (!(args = get_args(sym, NULL, FALSE, '<', '>'))) return FALSE; - sym->result = str_printf(sym, "%s%s", name, args); - return TRUE; -} - /******************************************************************* * symbol_demangle * Demangle a C++ linker symbol @@ -1460,10 +1493,8 @@ static BOOL symbol_demangle(struct parsed_symbol* sym) /* Function/Data type and access level */ if (*sym->current >= '0' && *sym->current <= '9') ret = handle_data(sym); - else if (*sym->current >= 'A' && *sym->current <= 'Z') + else if ((*sym->current >= 'A' && *sym->current <= 'Z') || *sym->current == '$') ret = handle_method(sym, do_after == 3); - else if (*sym->current == '$') - ret = handle_template(sym); else ret = FALSE; done: if (ret) assert(sym->result);