Module: wine Branch: master Commit: 16bcc3bc29dfdb435fee48061d7dd8304ae21d11 URL: https://gitlab.winehq.org/wine/wine/-/commit/16bcc3bc29dfdb435fee48061d7dd83...
Author: Eric Pouech eric.pouech@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@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); }