msvcrt: Add support for vcall thunks demangling.

oldstable
Piotr Caban 2013-10-07 13:01:10 +02:00 committed by Alexandre Julliard
parent d13436e048
commit 501d60b020
2 changed files with 56 additions and 44 deletions

View File

@ -1312,6 +1312,9 @@ static void test_demangle(void)
/* 123 */ {"?vtordisp_thunk@std@@$4PPPPPPPM@3EAA_NXZ", /* 123 */ {"?vtordisp_thunk@std@@$4PPPPPPPM@3EAA_NXZ",
"[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{4294967292,4}' (void) __ptr64", "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{4294967292,4}' (void) __ptr64",
"[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{-4,4}' (void) __ptr64"}, "[thunk]:public: virtual bool __cdecl std::vtordisp_thunk`vtordisp{-4,4}' (void) __ptr64"},
/* 124 */ {"??_9CView@@$BBII@AE",
"[thunk]: __thiscall CView::`vcall'{392,{flat}}' }'",
"[thunk]: __thiscall CView::`vcall'{392,{flat}}' "},
}; };
int i, num_test = (sizeof(test)/sizeof(test[0])); int i, num_test = (sizeof(test)/sizeof(test[0]));
char* name; char* name;

View File

@ -1067,6 +1067,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
{ {
char accmem; char accmem;
const char* access = NULL; const char* access = NULL;
int access_id = -1;
const char* member_type = NULL; const char* member_type = NULL;
struct datatype_t ct_ret; struct datatype_t ct_ret;
const char* call_conv; const char* call_conv;
@ -1074,7 +1075,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
const char* exported; const char* exported;
const char* args_str = NULL; const char* args_str = NULL;
const char* name = NULL; const char* name = NULL;
BOOL ret = FALSE; BOOL ret = FALSE, has_args = TRUE, has_ret = TRUE;
unsigned mark; unsigned mark;
struct array array_pmt; struct array array_pmt;
@ -1111,48 +1112,58 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
* "$3" protected: thunk vtordisp * "$3" protected: thunk vtordisp
* "$4" public: thunk vtordisp * "$4" public: thunk vtordisp
* "$5" public: thunk vtordisp * "$5" public: thunk vtordisp
* "$B" vcall thunk
*/ */
accmem = *sym->current++; accmem = *sym->current++;
if (accmem == '$') if (accmem == '$')
{ {
accmem = *sym->current++; if (*sym->current >= '0' && *sym->current <= '5')
if (accmem < '0' || accmem > '5') goto done; access_id = (*sym->current - '0') / 2;
else if (*sym->current != 'B')
goto done;
} }
else if (accmem < 'A' || accmem > 'Z') 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 >= '0' && accmem <= '5' ? (accmem - '0') / 2 : (accmem - 'A') / 8)
{ {
case 0: access = "private: "; break; case 0: access = "private: "; break;
case 1: access = "protected: "; break; case 1: access = "protected: "; break;
case 2: access = "public: "; break; case 2: access = "public: "; break;
} }
} if (accmem == '$' || (accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7)
if (!(sym->flags & UNDNAME_NO_MEMBER_TYPE)) access = str_printf(sym, "[thunk]:%s", access ? access : " ");
{
if (accmem >= '0' && accmem <= '5') if (accmem == '$' && *sym->current >= '0' && *sym->current <= '5')
{
access = str_printf(sym, "[thunk]:%s", access);
member_type = "virtual "; member_type = "virtual ";
}
else if (accmem <= 'X') else if (accmem <= 'X')
{ {
switch ((accmem - 'A') % 8) switch ((accmem - 'A') % 8)
{ {
case 2: case 3: member_type = "static "; break; case 2: case 3: member_type = "static "; break;
case 4: case 5: member_type = "virtual "; break; case 4: case 5: case 6: case 7: member_type = "virtual "; break;
case 6: case 7:
access = str_printf(sym, "[thunk]:%s", access);
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); name = get_class_string(sym, 0);
if (accmem >= '0' && accmem <='5') /* vtordisp thunk */ if (accmem == '$' && *sym->current++ == 'B') /* vcall thunk */
{
const char *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 == '$') /* vtordisp thunk */
{ {
const char *n1 = get_number(sym); const char *n1 = get_number(sym);
const char *n2 = get_number(sym); const char *n2 = get_number(sym);
@ -1163,9 +1174,8 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
else if ((accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) /* a thunk */ else if ((accmem - 'A') % 8 == 6 || (accmem - 'A') % 8 == 7) /* a thunk */
name = str_printf(sym, "%s`adjustor{%s}' ", name, get_number(sym)); 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; const char *ptr_modif;
/* Implicit 'this' pointer */ /* Implicit 'this' pointer */
@ -1173,7 +1183,6 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
if (!get_modifier(sym, &modifier, &ptr_modif)) goto done; if (!get_modifier(sym, &modifier, &ptr_modif)) goto done;
if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif); if (modifier || ptr_modif) modifier = str_printf(sym, "%s %s", modifier, ptr_modif);
} }
}
if (!get_calling_convention(*sym->current++, &call_conv, &exported, if (!get_calling_convention(*sym->current++, &call_conv, &exported,
sym->flags)) sym->flags))
@ -1182,18 +1191,18 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
str_array_init(&array_pmt); str_array_init(&array_pmt);
/* Return type, or @ if 'void' */ /* Return type, or @ if 'void' */
if (*sym->current == '@') if (has_ret && *sym->current == '@')
{ {
ct_ret.left = "void"; ct_ret.left = "void";
ct_ret.right = NULL; ct_ret.right = NULL;
sym->current++; sym->current++;
} }
else else if (has_ret)
{ {
if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE)) if (!demangle_datatype(sym, &ct_ret, &array_pmt, FALSE))
goto done; 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; ct_ret.left = ct_ret.right = NULL;
if (cast_op) if (cast_op)
{ {
@ -1202,7 +1211,7 @@ static BOOL handle_method(struct parsed_symbol* sym, BOOL cast_op)
} }
mark = sym->stack.num; 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_NAME_ONLY) args_str = modifier = NULL;
sym->stack.num = mark; sym->stack.num = mark;