Eric Pouech : winedbg: Add helper to compare types and use it to detect wrong assigments.

Alexandre Julliard julliard at winehq.org
Fri Dec 10 15:07:51 CST 2021


Module: wine
Branch: master
Commit: c4548c04eb8e1e7e94b10ad42b59831f6687f4f8
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c4548c04eb8e1e7e94b10ad42b59831f6687f4f8

Author: Eric Pouech <eric.pouech at gmail.com>
Date:   Wed Dec  8 14:44:21 2021 +0100

winedbg: Add helper to compare types and use it to detect wrong assigments.

Signed-off-by: Eric Pouech <eric.pouech at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/winedbg/debugger.h |   2 +
 programs/winedbg/types.c    | 190 ++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 186 insertions(+), 6 deletions(-)

diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index cd7a723f176..1d08c0e1262 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -493,6 +493,8 @@ extern BOOL             types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_T
 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_compare(const struct dbg_type, const struct dbg_type, BOOL* equal);
+extern BOOL             types_is_integral_type(const struct dbg_lvalue*);
 
   /* winedbg.c */
 extern void	        dbg_outputW(const WCHAR* buffer, int len);
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c
index 8f16a535606..1fafaac8c80 100644
--- a/programs/winedbg/types.c
+++ b/programs/winedbg/types.c
@@ -164,16 +164,33 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv
 {
     dbg_lgint_t val;
     DWORD64     size;
+    BOOL        equal;
 
-    if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE;
-    if (sizeof(val) < size)
+    if (!lvalue_to->bitlen && !lvalue_from->bitlen)
     {
-        dbg_printf("Insufficient size\n");
-        return FALSE;
+        if (!types_compare(lvalue_to->type, lvalue_from->type, &equal)) return FALSE;
+        if (equal)
+        {
+            if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE;
+            if (sizeof(val) < size)
+            {
+                return memory_read_value(lvalue_from, size, &val) &&
+                    memory_write_value(lvalue_to, size, &val);
+            }
+            dbg_printf("NIY\n");
+            /* else: should allocate intermediate buffer... */
+            return FALSE;
+        }
+    }
+    if (types_is_integral_type(lvalue_from) && types_is_integral_type(lvalue_to))
+    {
+        /* doing integer conversion (about sign, size) */
+        val = types_extract_as_integer(lvalue_from);
+        return memory_store_integer(lvalue_to, val);
     }
     /* FIXME: should support floats as well */
-    val = types_extract_as_integer(lvalue_from);
-    return memory_store_integer(lvalue_to, val);
+    dbg_printf("Cannot assign (different types)\n"); return FALSE;
+    return FALSE;
 }
 
 /******************************************************************
@@ -910,3 +927,164 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v
 #undef X
     return TRUE;
 }
+
+static BOOL types_compare_name(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
+{
+    LPWSTR name1, name2;
+    BOOL ret;
+
+    if (types_get_info(&type1, TI_GET_SYMNAME, &name1))
+    {
+        if (types_get_info(&type2, TI_GET_SYMNAME, &name2))
+        {
+            *equal = !wcscmp(name1, name2);
+            ret = TRUE;
+            HeapFree(GetProcessHeap(), 0, name2);
+        }
+        else ret = FALSE;
+        HeapFree(GetProcessHeap(), 0, name1);
+    }
+    else ret = FALSE;
+    return ret;
+}
+
+static BOOL types_compare_children(struct dbg_type type1, struct dbg_type type2, BOOL* equal, DWORD tag)
+{
+    DWORD count1, count2, i;
+    DWORD* children;
+    BOOL ret;
+
+    if (!types_get_info(&type1, TI_GET_CHILDRENCOUNT, &count1) ||
+        !types_get_info(&type2, TI_GET_CHILDRENCOUNT, &count2)) return FALSE;
+    if (count1 != count2) {*equal = FALSE; return TRUE;}
+    if (!count1) return *equal = TRUE;
+    if ((children = malloc(sizeof(*children) * 2 * count1)) == NULL) return FALSE;
+    if (types_get_info(&type1, TI_FINDCHILDREN, &children[0]) &&
+        types_get_info(&type2, TI_FINDCHILDREN, &children[count1]))
+    {
+        for (i = 0; i < count1; ++i)
+        {
+            type1.id = children[i];
+            type2.id = children[count1 + i];
+            switch (tag)
+            {
+            case SymTagFunctionType: ret = types_compare(type1, type2, equal); break;
+            case SymTagUDT:
+                /* each child is a SymTagData that describes the member */
+                ret = types_compare_name(type1, type2, equal);
+                if (ret && *equal)
+                {
+                    /* compare type of member */
+                    ret = types_get_info(&type1, TI_GET_TYPE, &type1.id) &&
+                        types_get_info(&type2, TI_GET_TYPE, &type2.id);
+                    if (ret) ret = types_compare(type1, type2, equal);
+                    /* FIXME should compare bitfield info when present */
+                }
+                break;
+            default: ret = FALSE; break;
+            }
+            if (!ret || !*equal) break;
+        }
+        if (i == count1) ret = *equal = TRUE;
+    }
+    else ret = FALSE;
+
+    free(children);
+    return ret;
+}
+
+BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
+{
+    DWORD           tag1, tag2;
+    DWORD64         size1, size2;
+    DWORD           bt1, bt2;
+    DWORD           count1, count2;
+    BOOL            ret;
+
+    do
+    {
+        if (type1.module == type2.module && type1.id == type2.id)
+            return *equal = TRUE;
+
+        if (!types_get_real_type(&type1, &tag1) ||
+            !types_get_real_type(&type2, &tag2)) return FALSE;
+
+        if (type1.module == type2.module && type1.id == type2.id)
+            return *equal = TRUE;
+
+        if (tag1 != tag2) return !(*equal = FALSE);
+
+        switch (tag1)
+        {
+        case SymTagBaseType:
+            if (!types_get_info(&type1, TI_GET_BASETYPE, &bt1) ||
+                !types_get_info(&type2, TI_GET_BASETYPE, &bt2) ||
+                !types_get_info(&type1, TI_GET_LENGTH,   &size1) ||
+                !types_get_info(&type2, TI_GET_LENGTH,   &size2))
+                return FALSE;
+            *equal = bt1 == bt2 && size1 == size2;
+            return TRUE;
+        case SymTagPointerType:
+            /* compare sub types */
+            break;
+        case SymTagUDT:
+        case SymTagEnum:
+            ret = types_compare_name(type1, type2, equal);
+            if (!ret || !*equal) return ret;
+            ret = types_compare_children(type1, type2, equal, tag1);
+            if (!ret || !*equal) return ret;
+            if (tag1 == SymTagUDT) return TRUE;
+            /* compare underlying type for enums */
+            break;
+        case SymTagArrayType:
+            if (!types_get_info(&type1, TI_GET_LENGTH, &size1) ||
+                !types_get_info(&type2, TI_GET_LENGTH, &size2) ||
+                !types_get_info(&type1, TI_GET_COUNT,  &count1) ||
+                !types_get_info(&type2, TI_GET_COUNT,  &count2)) return FALSE;
+            if (size1 == size2 && count1 == count2)
+            {
+                struct dbg_type subtype1 = type1, subtype2 = type2;
+                if (!types_get_info(&type1, TI_GET_ARRAYINDEXTYPEID, &subtype1.id) ||
+                    !types_get_info(&type2, TI_GET_ARRAYINDEXTYPEID, &subtype2.id)) return FALSE;
+                if (!types_compare(subtype1, subtype2, equal)) return FALSE;
+                if (!*equal) return TRUE;
+            }
+            else return !(*equal = FALSE);
+            /* compare subtypes */
+            break;
+        case SymTagFunctionType:
+            if (!types_compare_children(type1, type2, equal, tag1)) return FALSE;
+            if (!*equal) return TRUE;
+            /* compare return:ed type */
+            break;
+        case SymTagFunctionArgType:
+            /* compare argument type */
+            break;
+        default:
+            dbg_printf("Unsupported yet tag %d\n", tag1);
+            return FALSE;
+        }
+    } while (types_get_info(&type1, TI_GET_TYPE, &type1.id) &&
+             types_get_info(&type2, TI_GET_TYPE, &type2.id));
+    return FALSE;
+}
+
+static BOOL is_basetype_char(DWORD bt)
+{
+    return bt == btChar || bt == btWChar || bt == btChar8 || bt == btChar16 || bt == btChar32;
+}
+
+static BOOL is_basetype_integer(DWORD bt)
+{
+    return is_basetype_char(bt) || bt == btInt || bt == btUInt || bt == btLong || bt == btULong;
+}
+
+BOOL types_is_integral_type(const struct dbg_lvalue* lv)
+{
+    struct dbg_type type = lv->type;
+    DWORD tag, bt;
+    if (lv->bitlen) return TRUE;
+    if (!types_get_real_type(&type, &tag) ||
+        !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
+    return is_basetype_integer(bt);
+}




More information about the wine-cvs mailing list