[PATCH 16/19] programs/winedbg: move type lookup at parsing time for cast operation

Eric Pouech eric.pouech at gmail.com
Wed Dec 8 07:45:14 CST 2021


Signed-off-by: Eric Pouech <eric.pouech at gmail.com>

---
 programs/winedbg/dbg.y      |   61 +++++++++++++++-------------
 programs/winedbg/debug.l    |    9 ++++
 programs/winedbg/debugger.h |   24 +----------
 programs/winedbg/expr.c     |   71 +++-----------------------------
 programs/winedbg/types.c    |   95 +++++++++++++++++++++++--------------------
 5 files changed, 101 insertions(+), 159 deletions(-)

diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y
index 3e6ef34b836..3fc5a87c0b5 100644
--- a/programs/winedbg/dbg.y
+++ b/programs/winedbg/dbg.y
@@ -42,7 +42,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;
 }
 
@@ -55,6 +55,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
 
@@ -303,32 +304,38 @@ noprocess_state:
     ;
 
 type_expr:
-      tCHAR			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_char; }
-    | tINT			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_int; }
-    | tLONG tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
-    | tLONG     		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; }
-    | tUNSIGNED tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
-    | tUNSIGNED 		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; }
-    | tLONG tUNSIGNED tINT	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
-    | tLONG tUNSIGNED   	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; }
-    | tSHORT tINT		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
-    | tSHORT    		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; }
-    | tSHORT tUNSIGNED tINT	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
-    | tSHORT tUNSIGNED  	{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; }
-    | tSIGNED tCHAR		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_char_int; }
-    | tUNSIGNED tCHAR		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_char_int; }
-    | tLONG tLONG tUNSIGNED tINT{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
-    | tLONG tLONG tUNSIGNED     { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; }
-    | tLONG tLONG tINT          { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
-    | tLONG tLONG               { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; }
-    | tFLOAT			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_short_real; }
-    | tDOUBLE			{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_real; }
-    | tLONG tDOUBLE		{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_long_real; }
-    | 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; }
+      tCHAR                     { $$.module = 0; $$.id = dbg_itype_char; }
+    | tINT                      { $$.module = 0; $$.id = dbg_itype_signed_int; }
+    | tLONG tINT                { $$.module = 0; $$.id = dbg_itype_signed_long_int; }
+    | tLONG                     { $$.module = 0; $$.id = dbg_itype_signed_long_int; }
+    | tUNSIGNED tINT            { $$.module = 0; $$.id = dbg_itype_unsigned_int; }
+    | tUNSIGNED                 { $$.module = 0; $$.id = dbg_itype_unsigned_int; }
+    | tLONG tUNSIGNED tINT      { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; }
+    | tUNSIGNED tLONG tINT      { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; }
+    | tLONG tUNSIGNED           { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; }
+    | tUNSIGNED tLONG           { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; }
+    | tSHORT tINT               { $$.module = 0; $$.id = dbg_itype_signed_short_int; }
+    | tSHORT                    { $$.module = 0; $$.id = dbg_itype_signed_short_int; }
+    | tSHORT tUNSIGNED tINT     { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; }
+    | tUNSIGNED tSHORT tINT     { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; }
+    | tSHORT tUNSIGNED          { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; }
+    | tUNSIGNED tSHORT          { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; }
+    | tSIGNED tCHAR             { $$.module = 0; $$.id = dbg_itype_signed_char_int; }
+    | tUNSIGNED tCHAR           { $$.module = 0; $$.id = dbg_itype_unsigned_char_int; }
+    | tLONG tLONG tUNSIGNED tINT{ $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; }
+    | tLONG tLONG tUNSIGNED     { $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; }
+    | tUNSIGNED tLONG tLONG     { $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; }
+    | tLONG tLONG tINT          { $$.module = 0; $$.id = dbg_itype_signed_longlong_int; }
+    | tLONG tLONG               { $$.module = 0; $$.id = dbg_itype_signed_longlong_int; }
+    | tFLOAT                    { $$.module = 0; $$.id = dbg_itype_short_real; }
+    | tDOUBLE                   { $$.module = 0; $$.id = dbg_itype_real; }
+    | tLONG tDOUBLE             { $$.module = 0; $$.id = dbg_itype_long_real; }
+    | 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:
diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l
index 280013799c9..eea31f30c97 100644
--- a/programs/winedbg/debug.l
+++ b/programs/winedbg/debug.l
@@ -88,6 +88,13 @@ static char* unescape_string(const char* str)
     return ret;
 }
 
+static int resolve_identifier(const char* id, YYSTYPE* 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))
 
@@ -244,7 +251,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; }
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index a29b731017f..6bc6d8a1954 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -297,26 +297,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 */
@@ -372,7 +352,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);
@@ -499,7 +479,7 @@ extern BOOL             types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_T
 extern BOOL             types_get_type(const struct dbg_type*, struct dbg_type* ret);
 extern BOOL             types_get_real_type(struct dbg_type* type, DWORD* tag);
 extern BOOL             types_find_pointer(const struct dbg_type* type, struct dbg_type* pttype);
-extern struct dbg_type  types_find_type(DWORD64 linear, const char* name, enum SymTagEnum tag);
+extern BOOL             types_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* type);
 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*);
diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c
index bd48e3e868f..7a7c2013578 100644
--- a/programs/winedbg/expr.c
+++ b/programs/winedbg/expr.c
@@ -75,7 +75,7 @@ struct expr
 
         struct
         {
-            struct type_expr_t  cast_to;
+            struct dbg_type     cast_to;
             struct expr*        expr;
         } cast;
 
@@ -128,14 +128,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,7 +272,6 @@ 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;
@@ -285,52 +284,11 @@ struct dbg_lvalue expr_eval(struct expr* exp)
     switch (exp->type)
     {
     case EXPR_TYPE_CAST:
-        /* this is really brute force, we simply change the type... without 
+        /* 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);
-            RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
-        }
-        for (i = 0; i < exp->un.cast.cast_to.deref_count; i++)
-        {
-            if (!types_find_pointer(&rtn.type, &rtn.type))
-            {
-                dbg_printf("Cannot find pointer type\n");
-                RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
-            }
-        }
+        rtn.type = exp->un.cast.cast_to;
         break;
     case EXPR_TYPE_STRING:
         init_lvalue_in_debugger(&rtn, dbg_itype_astring, &exp->un.string.str);
@@ -626,30 +584,13 @@ 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(")");
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c
index 5633201d2fe..af0fd8806c6 100644
--- a/programs/winedbg/types.c
+++ b/programs/winedbg/types.c
@@ -324,39 +324,6 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv
     return TRUE;
 }
 
-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;
-};
-
-static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
-{
-    struct type_find_t* user = _user;
-    BOOL                ret = TRUE;
-
-    if (sym->Tag == user->tag)
-    {
-        switch (user->tag)
-        {
-        case SymTagUDT:
-            if (!strcmp(user->u.name, sym->Name))
-            {
-                user->result = sym->TypeIndex;
-                ret = FALSE;
-            }
-            break;
-        default: break;
-        }
-    }
-    return ret;
-}
-
 /******************************************************************
  *		types_find_pointer
  *
@@ -396,25 +363,65 @@ BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* ret)
     return TRUE;
 }
 
+struct type_find_type_t
+{
+    enum SymTagEnum     tag;    /* in: the tag to look for */
+    struct dbg_type     found;  /* out: the found type */
+    unsigned            count;  /* out: incremented at each different type */
+};
+
+static BOOL CALLBACK find_type_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
+{
+    struct type_find_type_t* f = _user;
+    if (sym->Tag == f->tag)
+    {
+        if (f->found.id == dbg_itype_none)
+        {
+            f->found.module = sym->ModBase;
+            f->found.id = sym->TypeIndex;
+        }
+        else
+        {
+            /* potential conflict */
+            struct dbg_type alt;
+            BOOL equal;
+            alt.module = sym->ModBase;
+            alt.id = sym->TypeIndex;
+            if (!types_compare(f->found, alt, &equal) || !equal)
+                f->count++;
+        }
+    }
+    return TRUE;
+}
+
 /******************************************************************
  *		types_find_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* type)
 
 {
-    struct type_find_t  f;
-    struct dbg_type     ret;
+    struct type_find_type_t f;
+    char* ptr;
 
-    f.result = dbg_itype_none;
+    if (!strchr(name, '!'))
+    {
+        ptr = malloc(2 + strlen(name) + 1);
+        if (!ptr) return FALSE;
+        strcpy(ptr, "*!");
+        strcat(ptr, name);
+    }
+    else ptr = NULL;
     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;
+    f.found.id = dbg_itype_none;
+    f.count = 0;
+    SymEnumTypesByName(dbg_curr_process->handle, 0, ptr ? ptr : name, find_type_cb, &f);
+    free(ptr);
+    if (f.found.id == dbg_itype_none) return FALSE;
+    /* FIXME report different types (f.count != 0) */
+    *type = f.found;
+
+    return TRUE;
 }
 
 /***********************************************************************




More information about the wine-devel mailing list