winedbg: Do type / id discrimination when parsing.

- Get rid of struct type_expr_t
- Enable back typecasts (and rewrite the typecast to fit the type parsing scheme)

Signed-off-by: Eric Pouech <eric.pouech@gmail.com>
This commit is contained in:
Eric Pouech 2022-05-20 17:03:27 +02:00 committed by Alexandre Julliard
parent af0c59bcc8
commit 73770ce573
6 changed files with 133 additions and 148 deletions

View file

@ -44,7 +44,7 @@ static void parser(const char*);
dbg_lgint_t integer;
IMAGEHLP_LINE64 listing;
struct expr* expression;
struct type_expr_t type;
struct dbg_type type;
struct list_string* strings;
}
@ -57,6 +57,7 @@ static void parser(const char*);
%token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE
%token <string> tPATH tIDENTIFIER tSTRING tINTVAR
%token <integer> tNUM tFORMAT
%token <type> tTYPEDEF
%token tSYMBOLFILE tRUN tATTACH tDETACH tKILL tMAINTENANCE tTYPE tMINIDUMP
%token tNOPROCESS
@ -346,11 +347,12 @@ type_expr:
| tFLOAT { if (!types_find_basic(L"float", $1, &$$)) YYERROR; }
| tDOUBLE { if (!types_find_basic(L"double", $1, &$$)) YYERROR; }
| tLONG tDOUBLE { if (!types_find_basic(L"long double", $1, &$$)) YYERROR; }
| type_expr '*' { $$ = $1; $$.deref_count++; }
| tCLASS identifier { $$.type = type_expr_udt_class; $$.deref_count = 0; $$.u.name = $2; }
| tSTRUCT identifier { $$.type = type_expr_udt_struct; $$.deref_count = 0; $$.u.name = $2; }
| tUNION identifier { $$.type = type_expr_udt_union; $$.deref_count = 0; $$.u.name = $2; }
| tENUM identifier { $$.type = type_expr_enumeration; $$.deref_count = 0; $$.u.name = $2; }
| tTYPEDEF { $$ = $1; }
| type_expr '*' { if (!types_find_pointer(&$1, &$$)) {yyerror("Cannot find pointer type\n"); YYERROR; } }
| tCLASS identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } }
| tSTRUCT identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } }
| tUNION identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } }
| tENUM identifier { if (!types_find_type($2, SymTagEnum, &$$)) {yyerror("Unknown type\n"); YYERROR; } }
;
expr_lvalue:

View file

@ -100,6 +100,13 @@ static char* unescape_string(const char* str)
return ret;
}
static int resolve_identifier(const char* id, DBG_STYPE* lval)
{
if (types_find_type(id, SymTagTypedef, &lval->type)) return tTYPEDEF;
lval->string = lexeme_alloc(id);
return tIDENTIFIER;
}
#define YY_INPUT(buf,result,max_size) \
(result = input_lex_read_buffer(buf, max_size))
@ -258,7 +265,7 @@ union { return tUNION; }
enum { return tENUM; }
all { return tALL; }
{MODULE_IDENTIFIER}?{SCOPED_IDENTIFIER}*{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; }
{MODULE_IDENTIFIER}?{SCOPED_IDENTIFIER}*{IDENTIFIER} { return resolve_identifier(yytext, &dbg_lval); }
"$"{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext+1); return tINTVAR; }
<PATH_EXPECTED,PATH_ACCEPTED>{PATHNAME} { dbg_lval.string = lexeme_alloc(yytext); return tPATH; }

View file

@ -150,14 +150,15 @@ static inline void init_lvalue(struct dbg_lvalue* lv, BOOL in_debuggee, void* ad
lv->type.id = dbg_itype_none;
}
static inline void init_lvalue_in_debugger(struct dbg_lvalue* lv, enum dbg_internal_types it, void* addr)
static inline void init_lvalue_in_debugger(struct dbg_lvalue* lv, DWORD_PTR module,
enum dbg_internal_types it, void* addr)
{
lv->in_debuggee = 0;
lv->bitstart = 0;
lv->bitlen = 0;
lv->addr.Mode = AddrModeFlat;
lv->addr.Offset = (DWORD_PTR)addr;
lv->type.module = 0;
lv->type.module = module;
lv->type.id = it;
}
@ -310,26 +311,6 @@ struct dbg_internal_var
enum sym_get_lval {sglv_found, sglv_unknown, sglv_aborted};
enum type_expr_e
{
type_expr_type_id,
type_expr_udt_class,
type_expr_udt_struct,
type_expr_udt_union,
type_expr_enumeration
};
struct type_expr_t
{
enum type_expr_e type;
unsigned deref_count;
union
{
struct dbg_type type;
const char* name;
} u;
};
enum dbg_start {start_ok, start_error_parse, start_error_init};
/* break.c */
@ -385,7 +366,7 @@ extern struct expr* expr_alloc_unary_op(int oper, struct expr*);
extern struct expr* expr_alloc_pstruct(struct expr*, const char* element);
extern struct expr* expr_alloc_struct(struct expr*, const char* element);
extern struct expr* WINAPIV expr_alloc_func_call(const char*, int nargs, ...);
extern struct expr* expr_alloc_typecast(struct type_expr_t*, struct expr*);
extern struct expr* expr_alloc_typecast(struct dbg_type*, struct expr*);
extern struct dbg_lvalue expr_eval(struct expr*);
extern struct expr* expr_clone(const struct expr* exp, BOOL *local_binding);
extern BOOL expr_free(struct expr* exp);
@ -510,12 +491,13 @@ extern BOOL types_udt_find_element(struct dbg_lvalue* value, const c
extern BOOL types_array_index(const struct dbg_lvalue* value, int index, struct dbg_lvalue* result);
extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_TYPE_INFO, void*);
extern BOOL types_get_real_type(struct dbg_type* type, DWORD* tag);
extern struct dbg_type types_find_pointer(const struct dbg_type* type);
extern struct dbg_type types_find_type(DWORD64 linear, const char* name, enum SymTagEnum tag);
extern BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* outtype);
extern BOOL types_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* outtype);
extern BOOL types_compare(const struct dbg_type, const struct dbg_type, BOOL* equal);
extern BOOL types_is_integral_type(const struct dbg_lvalue*);
extern BOOL types_is_float_type(const struct dbg_lvalue*);
extern BOOL types_find_basic(const WCHAR*, const char*, struct type_expr_t* type);
extern BOOL types_is_pointer_type(const struct dbg_lvalue*);
extern BOOL types_find_basic(const WCHAR*, const char*, struct dbg_type* type);
/* winedbg.c */
#ifdef __GNUC__

View file

@ -75,8 +75,9 @@ struct expr
struct
{
struct type_expr_t cast_to;
struct dbg_type cast_to;
struct expr* expr;
dbg_lgint_t result;
} cast;
struct
@ -128,14 +129,14 @@ void expr_free_all(void)
next_expr_free = 0;
}
struct expr* expr_alloc_typecast(struct type_expr_t* tet, struct expr* exp)
struct expr* expr_alloc_typecast(struct dbg_type* type, struct expr* exp)
{
struct expr* ex;
ex = expr_alloc();
ex->type = EXPR_TYPE_CAST;
ex->un.cast.cast_to = *tet;
ex->un.cast.cast_to = *type;
ex->un.cast.expr = exp;
return ex;
}
@ -272,75 +273,74 @@ struct expr* WINAPIV expr_alloc_func_call(const char* funcname, int nargs, ...)
struct dbg_lvalue expr_eval(struct expr* exp)
{
struct dbg_lvalue rtn;
int i;
struct dbg_lvalue exp1;
struct dbg_lvalue exp2;
DWORD64 scale1, scale2, scale3;
struct dbg_type type1, type2;
DWORD tag;
const struct dbg_internal_var* div;
BOOL ret;
init_lvalue_in_debugger(&rtn, dbg_itype_none, NULL);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_none, NULL);
switch (exp->type)
{
case EXPR_TYPE_CAST:
/* this is really brute force, we simply change the type... without
* checking if this is right or not
*/
rtn = expr_eval(exp->un.cast.expr);
switch (exp->un.cast.cast_to.type)
{
case type_expr_type_id:
if (exp->un.cast.cast_to.u.type.id == dbg_itype_none)
{
dbg_printf("Can't cast to unknown type\n");
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
}
rtn.type = exp->un.cast.cast_to.u.type;
break;
case type_expr_udt_class:
case type_expr_udt_struct:
case type_expr_udt_union:
rtn.type = types_find_type(rtn.type.module, exp->un.cast.cast_to.u.name,
SymTagUDT);
if (rtn.type.id == dbg_itype_none)
{
dbg_printf("Can't cast to UDT %s\n", exp->un.cast.cast_to.u.name);
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
}
break;
case type_expr_enumeration:
rtn.type = types_find_type(rtn.type.module, exp->un.cast.cast_to.u.name,
SymTagEnum);
if (rtn.type.id == dbg_itype_none)
{
dbg_printf("Can't cast to enumeration %s\n", exp->un.cast.cast_to.u.name);
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
}
break;
default:
dbg_printf("Unsupported cast type %u\n", exp->un.cast.cast_to.type);
exp1 = expr_eval(exp->un.cast.expr);
if (exp1.type.id == dbg_itype_none)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
}
for (i = 0; i < exp->un.cast.cast_to.deref_count; i++)
rtn = exp1;
rtn.type = exp->un.cast.cast_to;
init_lvalue_in_debugger(&rtn, exp->un.cast.cast_to.module, exp->un.cast.cast_to.id, &exp->un.cast.result);
if (types_is_float_type(&exp1))
{
rtn.type = types_find_pointer(&rtn.type);
if (rtn.type.id == dbg_itype_none)
double dbl;
ret = memory_fetch_float(&exp1, &dbl);
if (ret)
{
dbg_printf("Cannot find pointer type\n");
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
if (types_is_float_type(&rtn))
ret = memory_store_float(&rtn, &dbl);
else if (types_is_integral_type(&rtn))
ret = memory_store_integer(&rtn, (dbg_lgint_t)dbl);
else
ret = FALSE;
}
}
else if (types_is_integral_type(&exp1))
{
dbg_lgint_t val = types_extract_as_integer(&exp1);
if (types_is_float_type(&rtn))
{
double dbl = val;
ret = memory_store_float(&rtn, &dbl);
}
else if (types_is_integral_type(&rtn) || types_is_pointer_type(&rtn))
ret = memory_store_integer(&rtn, val);
else
ret = FALSE;
}
else if (types_is_pointer_type(&exp1))
{
dbg_lgint_t val = types_extract_as_integer(&exp1);
if (types_is_integral_type(&rtn) || types_is_pointer_type(&rtn))
ret = memory_store_integer(&rtn, val);
else
ret = FALSE;
}
else
ret = FALSE;
if (!ret)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
break;
case EXPR_TYPE_STRING:
init_lvalue_in_debugger(&rtn, dbg_itype_astring, &exp->un.string.str);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_astring, &exp->un.string.str);
break;
case EXPR_TYPE_U_CONST:
init_lvalue_in_debugger(&rtn, dbg_itype_lguint, &exp->un.u_const.value);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_lguint, &exp->un.u_const.value);
break;
case EXPR_TYPE_S_CONST:
init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.s_const.value);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_lgint, &exp->un.s_const.value);
break;
case EXPR_TYPE_SYMBOL:
switch (symbol_get_lvalue(exp->un.symbol.name, -1, &rtn, FALSE))
@ -440,7 +440,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
*/
exp->un.call.result = 0;
#endif
init_lvalue_in_debugger(&rtn, dbg_itype_none, &exp->un.call.result);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_none, &exp->un.call.result);
/* get return type from function signature type */
/* FIXME rtn.type.module should be set to function's module... */
types_get_info(&rtn.type, TI_GET_TYPE, &rtn.type.id);
@ -448,14 +448,14 @@ struct dbg_lvalue expr_eval(struct expr* exp)
case EXPR_TYPE_INTVAR:
if (!(div = dbg_get_internal_var(exp->un.intvar.name)))
RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL);
init_lvalue_in_debugger(&rtn, div->typeid, div->pval);
init_lvalue_in_debugger(&rtn, 0, div->typeid, div->pval);
break;
case EXPR_TYPE_BINOP:
exp1 = expr_eval(exp->un.binop.exp1);
exp2 = expr_eval(exp->un.binop.exp2);
if (exp1.type.id == dbg_itype_none || exp2.type.id == dbg_itype_none)
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.binop.result);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_lgint, &exp->un.binop.result);
type1 = exp1.type;
type2 = exp2.type;
switch (exp->un.binop.binop_type)
@ -584,7 +584,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
case EXPR_TYPE_UNOP:
exp1 = expr_eval(exp->un.unop.exp1);
if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.unop.result);
init_lvalue_in_debugger(&rtn, 0, dbg_itype_lgint, &exp->un.unop.result);
switch (exp->un.unop.unop_type)
{
case EXP_OP_NEG:
@ -610,8 +610,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
if (exp1.addr.Mode != AddrModeFlat)
RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL);
exp->un.unop.result = (ULONG_PTR)memory_to_linear_addr(&exp1.addr);
rtn.type = types_find_pointer(&exp1.type);
if (rtn.type.id == dbg_itype_none)
if (!types_find_pointer(&exp1.type, &rtn.type))
RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL);
break;
default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL);
@ -629,30 +628,12 @@ struct dbg_lvalue expr_eval(struct expr* exp)
BOOL expr_print(const struct expr* exp)
{
int i;
struct dbg_type type;
switch (exp->type)
{
case EXPR_TYPE_CAST:
WINE_FIXME("No longer supported (missing module base)\n");
dbg_printf("((");
switch (exp->un.cast.cast_to.type)
{
case type_expr_type_id:
type.module = 0;
type.id = exp->un.cast.cast_to.type;
types_print_type(&type, FALSE); break;
case type_expr_udt_class:
dbg_printf("class %s", exp->un.cast.cast_to.u.name); break;
case type_expr_udt_struct:
dbg_printf("struct %s", exp->un.cast.cast_to.u.name); break;
case type_expr_udt_union:
dbg_printf("union %s", exp->un.cast.cast_to.u.name); break;
case type_expr_enumeration:
dbg_printf("enum %s", exp->un.cast.cast_to.u.name); break;
}
for (i = 0; i < exp->un.cast.cast_to.deref_count; i++)
dbg_printf("*");
types_print_type(&exp->un.cast.cast_to, FALSE);
dbg_printf(")");
expr_print(exp->un.cast.expr);
dbg_printf(")");

View file

@ -103,7 +103,7 @@ BOOL stack_get_register_frame(const struct dbg_internal_var* div, struct dbg_lva
struct dbg_frame* currfrm = stack_get_curr_frame();
if (currfrm == NULL) return FALSE;
if (currfrm->is_ctx_valid)
init_lvalue_in_debugger(lvalue, div->typeid,
init_lvalue_in_debugger(lvalue, 0, div->typeid,
(char*)&currfrm->context + (DWORD_PTR)div->pval);
else
{
@ -116,13 +116,13 @@ BOOL stack_get_register_frame(const struct dbg_internal_var* div, struct dbg_lva
switch (kind)
{
case be_cpu_addr_pc:
init_lvalue_in_debugger(lvalue, itype, &currfrm->linear_pc);
init_lvalue_in_debugger(lvalue, 0, itype, &currfrm->linear_pc);
break;
case be_cpu_addr_stack:
init_lvalue_in_debugger(lvalue, itype, &currfrm->linear_stack);
init_lvalue_in_debugger(lvalue, 0, itype, &currfrm->linear_stack);
break;
case be_cpu_addr_frame:
init_lvalue_in_debugger(lvalue, itype, &currfrm->linear_frame);
init_lvalue_in_debugger(lvalue, 0, itype, &currfrm->linear_frame);
break;
}
}

View file

@ -300,7 +300,8 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv
}
break;
default:
assert(FALSE);
FIXME("unexpected tag %lx\n", tag);
return FALSE;
}
/*
* Get the base type, so we know how much to index by.
@ -332,13 +333,9 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv
struct type_find_t
{
ULONG result; /* out: the found type */
enum SymTagEnum tag; /* in: the tag to look for */
union
{
ULONG typeid; /* when tag is SymTagUDT */
const char* name; /* when tag is SymTagPointerType */
} u;
struct dbg_type type; /* out: the type found */
ULONG ptr_typeid; /* in: when tag is SymTagPointerType */
};
static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
@ -353,18 +350,18 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
switch (user->tag)
{
case SymTagUDT:
if (!strcmp(user->u.name, sym->Name))
{
user->result = sym->TypeIndex;
ret = FALSE;
}
case SymTagEnum:
case SymTagTypedef:
user->type.module = sym->ModBase;
user->type.id = sym->TypeIndex;
ret = FALSE;
break;
case SymTagPointerType:
type.module = sym->ModBase;
type.id = sym->TypeIndex;
if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid)
if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->ptr_typeid)
{
user->result = sym->TypeIndex;
user->type = type;
ret = FALSE;
}
break;
@ -380,18 +377,17 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
* Should look up in module based at linear whether (typeid*) exists
* Otherwise, we could create it locally
*/
struct dbg_type types_find_pointer(const struct dbg_type* type)
BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* outtype)
{
struct type_find_t f;
struct dbg_type ret;
f.result = dbg_itype_none;
f.type.id = dbg_itype_none;
f.tag = SymTagPointerType;
f.u.typeid = type->id;
SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
ret.module = type->module;
ret.id = f.result;
return ret;
f.ptr_typeid = type->id;
if (!SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f) || f.type.id == dbg_itype_none)
return FALSE;
*outtype = f.type;
return TRUE;
}
/******************************************************************
@ -400,19 +396,29 @@ struct dbg_type types_find_pointer(const struct dbg_type* type)
* Should look up in the module based at linear address whether a type
* named 'name' and with the correct tag exists
*/
struct dbg_type types_find_type(DWORD64 linear, const char* name, enum SymTagEnum tag)
BOOL types_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* outtype)
{
struct type_find_t f;
struct dbg_type ret;
char* str = NULL;
BOOL ret;
f.result = dbg_itype_none;
if (!strchr(name, '!')) /* no module, lookup across all modules */
{
str = malloc(strlen(name) + 3);
if (!str) return FALSE;
str[0] = '*';
str[1] = '!';
strcpy(str + 2, name);
name = str;
}
f.type.id = dbg_itype_none;
f.tag = tag;
f.u.name = name;
SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f);
ret.module = linear;
ret.id = f.result;
return ret;
ret = SymEnumTypesByName(dbg_curr_process->handle, 0, name, types_cb, &f);
free(str);
if (!ret || f.type.id == dbg_itype_none)
return FALSE;
*outtype = f.type;
return TRUE;
}
/***********************************************************************
@ -916,7 +922,7 @@ static BOOL CALLBACK enum_mod_cb(const char* module, DWORD64 base, void* user)
return TRUE;
}
BOOL types_find_basic(const WCHAR* name, const char* mod, struct type_expr_t* type)
BOOL types_find_basic(const WCHAR* name, const char* mod, struct dbg_type* type)
{
const struct data_model* model;
struct mod_by_name mbn = {mod, 0};
@ -928,15 +934,13 @@ BOOL types_find_basic(const WCHAR* name, const char* mod, struct typ
SymSetExtendedOption(SYMOPT_EX_WINE_NATIVE_MODULES, opt);
if (!ret || mbn.base == 0)
return FALSE;
type->type = type_expr_type_id;
type->deref_count = 0;
model = get_data_model(mbn.base);
for (; model->name; model++)
{
if (!wcscmp(name, model->name))
{
type->u.type.module = 0;
type->u.type.id = model->itype;
type->module = 0;
type->id = model->itype;
return TRUE;
}
}
@ -1238,3 +1242,12 @@ BOOL types_is_float_type(const struct dbg_lvalue* lv)
!types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
return bt == btFloat;
}
BOOL types_is_pointer_type(const struct dbg_lvalue* lv)
{
struct dbg_type type = lv->type;
DWORD tag;
if (lv->bitlen) return FALSE;
return types_get_real_type(&type, &tag) &&
(tag == SymTagPointerType || tag == SymTagArrayType || tag == SymTagFunctionType);
}