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