Eric Pouech : winedbg: Synthetize pointer to type when not available.

Alexandre Julliard julliard at winehq.org
Fri Jul 29 15:01:30 CDT 2022


Module: wine
Branch: master
Commit: 16bcc3bc29dfdb435fee48061d7dd8304ae21d11
URL:    https://gitlab.winehq.org/wine/wine/-/commit/16bcc3bc29dfdb435fee48061d7dd8304ae21d11

Author: Eric Pouech <eric.pouech at gmail.com>
Date:   Fri Jul 29 10:28:54 2022 +0200

winedbg: Synthetize pointer to type when not available.

This ensures that we always have a type as pointer to a known <type>
(either because it exists in <type>'s module, or it's synthetized inside
debugger).

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

---

 programs/winedbg/debugger.h   |  5 +++
 programs/winedbg/tgt_active.c |  1 +
 programs/winedbg/types.c      | 83 +++++++++++++++++++++++++++++++++++++++----
 programs/winedbg/winedbg.c    |  3 ++
 4 files changed, 86 insertions(+), 6 deletions(-)

diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index c3eac423a13..1cfdfb9386b 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -67,6 +67,8 @@ enum dbg_line_status
 
 enum dbg_internal_types
 {
+    /* types that we synthetize inside the debugger */
+    dbg_itype_synthetized       = 0xf0000000,
     /* order here must match types.c:basic_types_details table */
     dbg_itype_first             = 0xffffff00,
     dbg_itype_void              = dbg_itype_first,
@@ -282,6 +284,8 @@ struct dbg_process
     int                         source_start_line;
     int                         source_end_line;
     const struct data_model*    data_model;
+    struct dbg_type*            synthetized_types;
+    unsigned                    num_synthetized_types;
 };
 
 /* describes the way the debugger interacts with a given process */
@@ -499,6 +503,7 @@ extern BOOL             types_is_integral_type(const struct dbg_lvalue*);
 extern BOOL             types_is_float_type(const struct dbg_lvalue*);
 extern BOOL             types_is_pointer_type(const struct dbg_lvalue*);
 extern BOOL             types_find_basic(const WCHAR*, const char*, struct dbg_type* type);
+extern BOOL             types_unload_module(DWORD_PTR linear);
 
   /* winedbg.c */
 #ifdef __GNUC__
diff --git a/programs/winedbg/tgt_active.c b/programs/winedbg/tgt_active.c
index b3b385ee2b4..943ac7a5891 100644
--- a/programs/winedbg/tgt_active.c
+++ b/programs/winedbg/tgt_active.c
@@ -500,6 +500,7 @@ static unsigned dbg_handle_debug_event(DEBUG_EVENT* de)
                    de->dwProcessId, de->dwThreadId,
                    de->u.UnloadDll.lpBaseOfDll);
         break_delete_xpoints_from_module((DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
+        types_unload_module((DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
         SymUnloadModule64(dbg_curr_process->handle, (DWORD_PTR)de->u.UnloadDll.lpBaseOfDll);
         break;
 
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c
index 48c72122688..dd162eb8987 100644
--- a/programs/winedbg/types.c
+++ b/programs/winedbg/types.c
@@ -371,19 +371,56 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user)
 /******************************************************************
  *		types_find_pointer
  *
- * Should look up in module based at linear whether (typeid*) exists
- * Otherwise, we could create it locally
+ * There's no simple API in dbghelp for looking up the pointer type of a given type
+ * - SymEnumTypes would do, but it'll enumerate all types, which could be long
+ * - and more impacting, there's no guarantee such a type exists
+ * Hence, we synthetize inside Winedbg all needed pointer types.
+ * That's cumbersome as we end up with dbg_type in different modules between pointer
+ * and pointee types.
  */
 BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* outtype)
 {
     struct type_find_t  f;
+    unsigned i;
+    struct dbg_type* new;
 
+    if (!dbg_curr_process) return FALSE;
+
+    /* first lookup if pointer to type exists in module */
     f.type.id = dbg_itype_none;
     f.tag = SymTagPointerType;
     f.ptr_typeid = type->id;
-    if (!SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f) || f.type.id == dbg_itype_none)
+    SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f);
+    if (f.type.id != dbg_itype_none)
+    {
+        *outtype = f.type;
+        return TRUE;
+    }
+
+    /* then look up in synthetized types */
+    for (i = 0; i < dbg_curr_process->num_synthetized_types; i++)
+        if (!memcmp(type, &dbg_curr_process->synthetized_types[i], sizeof(*type)))
+        {
+            outtype->module = 0;
+            outtype->id = dbg_itype_synthetized + i;
+            return TRUE;
+        }
+    if (dbg_itype_synthetized + dbg_curr_process->num_synthetized_types >= dbg_itype_first)
+    {
+        /* for now, we don't reuse old slots... */
+        FIXME("overflow in pointer types\n");
         return FALSE;
-    *outtype = f.type;
+    }
+    /* otherwise, synthetize it */
+    new = realloc(dbg_curr_process->synthetized_types,
+                  (dbg_curr_process->num_synthetized_types + 1) * sizeof(*new));
+    if (!new) return FALSE;
+    dbg_curr_process->synthetized_types = new;
+    dbg_curr_process->synthetized_types[dbg_curr_process->num_synthetized_types] = *type;
+    outtype->module = 0;
+    outtype->id = dbg_itype_synthetized + dbg_curr_process->num_synthetized_types;
+    dbg_curr_process->num_synthetized_types++;
+
     return TRUE;
 }
 
@@ -1041,6 +1078,7 @@ static BOOL lookup_base_type_in_data_model(DWORD64 module, unsigned bt, unsigned
  * - module & type id on input are in dbg_type structure
  * - for TI_GET_TYPE a pointer to a dbg_type is expected for pInfo
  *   (instead of DWORD* for SymGetTypeInfo)
+ * - handles also internal types, and synthetized types.
  */
 BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo)
 {
@@ -1074,6 +1112,24 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v
         return SymGetTypeInfo(dbg_curr_process->handle, type->module, type->id, ti, pInfo);
     }
 
+    if (type->id >= dbg_itype_synthetized && type->id < dbg_itype_first)
+    {
+        unsigned i = type->id - dbg_itype_synthetized;
+        if (i >= dbg_curr_process->num_synthetized_types) return FALSE;
+        switch (ti)
+        {
+        case TI_GET_SYMTAG:  X(DWORD)   = SymTagPointerType; break;
+        case TI_GET_LENGTH:  X(DWORD64) = ADDRSIZE; break;
+        case TI_GET_TYPE:    if (dbg_curr_process->synthetized_types[i].module == 0 &&
+                                 dbg_curr_process->synthetized_types[i].id == dbg_itype_none) return FALSE;
+
+                             X(struct dbg_type) = dbg_curr_process->synthetized_types[i];
+                             break;
+        default: WINE_FIXME("unsupported %u for pointer type %d\n", ti, i); return FALSE;
+        }
+        return TRUE;
+    }
+
     assert(type->id >= dbg_itype_first);
 
     if (type->id >= dbg_itype_first && type->id < dbg_itype_last)
@@ -1143,6 +1199,21 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v
     return TRUE;
 }
 
+BOOL types_unload_module(DWORD_PTR linear)
+{
+    unsigned i;
+    if (!dbg_curr_process) return FALSE;
+    for (i = 0; i < dbg_curr_process->num_synthetized_types; i++)
+    {
+        if (dbg_curr_process->synthetized_types[i].module == linear)
+        {
+            dbg_curr_process->synthetized_types[i].module = 0;
+            dbg_curr_process->synthetized_types[i].id = dbg_itype_none;
+        }
+    }
+    return TRUE;
+}
+
 static BOOL types_compare_name(struct dbg_type type1, struct dbg_type type2, BOOL* equal)
 {
     LPWSTR name1, name2;
@@ -1299,7 +1370,7 @@ 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) ||
+    if (!types_get_real_type(&type, &tag) || tag != SymTagBaseType ||
         !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
     return is_basetype_integer(bt);
 }
@@ -1309,7 +1380,7 @@ BOOL types_is_float_type(const struct dbg_lvalue* lv)
     struct dbg_type type = lv->type;
     DWORD tag, bt;
     if (lv->bitlen) return FALSE;
-    if (!types_get_real_type(&type, &tag) ||
+    if (!types_get_real_type(&type, &tag) || tag != SymTagBaseType ||
         !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE;
     return bt == btFloat;
 }
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index 1bf627fd53c..84ec7802396 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -285,6 +285,8 @@ struct dbg_process*	dbg_add_process(const struct be_process_io* pio, DWORD pid,
     p->source_start_line = -1;
     p->source_end_line = -1;
     p->data_model = NULL;
+    p->synthetized_types = NULL;
+    p->num_synthetized_types = 0;
 
     list_add_head(&dbg_process_list, &p->entry);
 
@@ -330,6 +332,7 @@ void dbg_del_process(struct dbg_process* p)
     if (p == dbg_curr_process) dbg_curr_process = NULL;
     if (p->event_on_first_exception) CloseHandle(p->event_on_first_exception);
     free((char*)p->imageName);
+    free(p->synthetized_types);
     free(p);
 }
 




More information about the wine-cvs mailing list