mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 13:13:40 +00:00
[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
This commit is contained in:
parent
0373d3643b
commit
7a0f2c7ffb
4 changed files with 144 additions and 93 deletions
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue