winedump: Sync demangling code with msvcrt.
This commit is contained in:
parent
a128ad5c5b
commit
268f3adce9
1 changed files with 42 additions and 50 deletions
|
@ -45,6 +45,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 */
|
||||
|
@ -195,7 +196,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)
|
||||
{
|
||||
|
@ -248,7 +249,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)
|
||||
|
||||
{
|
||||
|
@ -257,19 +258,22 @@ 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 == '@')
|
||||
{
|
||||
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;
|
||||
|
@ -277,6 +281,12 @@ 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.
|
||||
|
@ -385,7 +395,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;
|
||||
|
@ -470,7 +480,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++;
|
||||
|
@ -532,20 +542,20 @@ 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;
|
||||
struct array array_pmt;
|
||||
unsigned args_mark = sym->args.num;
|
||||
|
||||
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;
|
||||
sym->names.start = start_mark;
|
||||
sym->stack.num = stack_mark;
|
||||
sym->args.num = args_mark;
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -777,18 +787,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;
|
||||
|
||||
|
@ -803,10 +812,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;
|
||||
|
@ -823,7 +831,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 */
|
||||
|
@ -859,17 +866,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))
|
||||
|
@ -890,7 +897,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::*",
|
||||
|
@ -903,7 +910,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*",
|
||||
|
@ -913,7 +920,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')
|
||||
|
@ -933,11 +940,9 @@ 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;
|
||||
case '$':
|
||||
switch (*sym->current++)
|
||||
|
@ -989,7 +994,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);
|
||||
|
@ -1016,7 +1021,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);
|
||||
|
@ -1031,13 +1036,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;
|
||||
}
|
||||
|
@ -1045,13 +1050,6 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct,
|
|||
default :
|
||||
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;
|
||||
|
@ -1106,12 +1104,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;
|
||||
|
@ -1167,7 +1162,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:
|
||||
|
@ -1297,8 +1291,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 == '@')
|
||||
{
|
||||
|
@ -1308,7 +1300,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)
|
||||
|
@ -1320,7 +1312,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;
|
||||
|
@ -1357,7 +1349,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;
|
||||
|
@ -1460,7 +1452,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);
|
||||
|
@ -1521,12 +1513,12 @@ 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, '<', '>');
|
||||
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;
|
||||
}
|
||||
if (!str_array_push(sym, function_name, -1, &sym->stack))
|
||||
|
|
Loading…
Add table
Reference in a new issue