this doesn't require searching debuggee's type when taking address of an expression not to mention, this search could also fail
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 6 ++ programs/winedbg/expr.c | 17 ++--- programs/winedbg/types.c | 135 +++++++++++++++++++++++++++---------------- programs/winedbg/winedbg.c | 3 + 4 files changed, 99 insertions(+), 62 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index f74ddfc210f..a29b731017f 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -67,6 +67,7 @@ enum dbg_line_status
enum dbg_internal_types { + dbg_itype_pointers = 0xf0000000, dbg_itype_first = 0xffffff00, dbg_itype_unsigned_int, dbg_itype_signed_int, @@ -265,6 +266,8 @@ struct dbg_process char source_current_file[MAX_PATH]; int source_start_line; int source_end_line; + struct dbg_type* pointers_type; + unsigned num_pointers_type; };
/* describes the way the debugger interacts with a given process */ @@ -493,8 +496,9 @@ extern BOOL types_store_value(struct dbg_lvalue* lvalue_to, const st extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name); extern BOOL types_array_index(const struct dbg_lvalue* value, int index, struct dbg_lvalue* result); extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_TYPE_INFO, void*); +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 struct dbg_type types_find_pointer(const struct dbg_type* type); +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_compare(const struct dbg_type, const struct dbg_type, BOOL* equal); extern BOOL types_is_integral_type(const struct dbg_lvalue*); diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c index 5d9ef30ad13..bd48e3e868f 100644 --- a/programs/winedbg/expr.c +++ b/programs/winedbg/expr.c @@ -325,8 +325,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) } for (i = 0; i < exp->un.cast.cast_to.deref_count; i++) { - rtn.type = types_find_pointer(&rtn.type); - if (rtn.type.id == dbg_itype_none) + if (!types_find_pointer(&rtn.type, &rtn.type)) { dbg_printf("Cannot find pointer type\n"); RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); @@ -442,8 +441,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) #endif init_lvalue_in_debugger(&rtn, dbg_itype_none, &exp->un.call.result); /* get return type from function signature type */ - /* FIXME rtn.type.module should be set to function's module... */ - types_get_info(&rtn.type, TI_GET_TYPE, &rtn.type.id); + types_get_type(&rtn.type, &rtn.type); break; case EXPR_TYPE_INTVAR: if (!(div = dbg_get_internal_var(exp->un.intvar.name))) @@ -463,11 +461,11 @@ struct dbg_lvalue expr_eval(struct expr* exp) case EXP_OP_ADD: if (!types_get_info(&exp1.type, TI_GET_SYMTAG, &tag) || tag != SymTagPointerType || - !types_get_info(&exp1.type, TI_GET_TYPE, &type1.id)) + !types_get_type(&exp1.type, &type1)) type1.id = dbg_itype_none; if (!types_get_info(&exp2.type, TI_GET_SYMTAG, &tag) || tag != SymTagPointerType || - !types_get_info(&exp2.type, TI_GET_TYPE, &type2.id)) + !types_get_type(&exp2.type, &type2)) type2.id = dbg_itype_none; scale1 = 1; scale2 = 1; @@ -489,11 +487,11 @@ struct dbg_lvalue expr_eval(struct expr* exp) case EXP_OP_SUB: if (!types_get_info(&exp1.type, TI_GET_SYMTAG, &tag) || tag != SymTagPointerType || - !types_get_info(&exp1.type, TI_GET_TYPE, &type1.id)) + !types_get_type(&exp1.type, &type1)) type1.id = dbg_itype_none; if (!types_get_info(&exp2.type, TI_GET_SYMTAG, &tag) || tag != SymTagPointerType || - !types_get_info(&exp2.type, TI_GET_TYPE, &type2.id)) + !types_get_type(&exp2.type, &type2)) type2.id = dbg_itype_none; scale1 = 1; scale2 = 1; @@ -610,8 +608,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) if (exp1.addr.Mode != AddrModeFlat) RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL); exp->un.unop.result = (ULONG_PTR)memory_to_linear_addr(&exp1.addr); - rtn.type = types_find_pointer(&exp1.type); - if (rtn.type.id == dbg_itype_none) + if (!types_find_pointer(&exp1.type, &rtn.type)) RaiseException(DEBUG_STATUS_CANT_DEREF, 0, 0, NULL); break; default: RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 3aefbe03058..5633201d2fe 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -42,7 +42,7 @@ BOOL types_get_real_type(struct dbg_type* type, DWORD* tag) if (!types_get_info(type, TI_GET_SYMTAG, tag)) return FALSE; if (*tag != SymTagTypedef) return TRUE; - } while (types_get_info(type, TI_GET_TYPE, &type->id)); + } while (types_get_type(type, type)); return FALSE; }
@@ -195,9 +195,8 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, const struct DWORD offset, bitoffset; DWORD64 length;
- types_get_info(type, TI_GET_TYPE, &lvalue->type.id); - lvalue->type.module = type->module; - if (!types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE; + if (!types_get_type(type, &lvalue->type) || + !types_get_info(type, TI_GET_OFFSET, &offset)) return FALSE; lvalue->addr.Offset += offset;
if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset)) @@ -301,8 +300,7 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv /* * Get the base type, so we know how much to index by. */ - if (!types_get_info(&type, TI_GET_TYPE, &result->type.id)) return FALSE; - result->type.module = type.module; + if (!types_get_type(&type, &result->type)) return FALSE; if (index) { DWORD64 length; @@ -341,8 +339,6 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user) { struct type_find_t* user = _user; BOOL ret = TRUE; - struct dbg_type type; - DWORD type_id;
if (sym->Tag == user->tag) { @@ -355,15 +351,6 @@ static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user) ret = FALSE; } break; - case SymTagPointerType: - type.module = sym->ModBase; - type.id = sym->TypeIndex; - if (types_get_info(&type, TI_GET_TYPE, &type_id) && type_id == user->u.typeid) - { - user->result = sym->TypeIndex; - ret = FALSE; - } - break; default: break; } } @@ -373,21 +360,40 @@ 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 way 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 + * - but more impacting, there's no guarantee such a type exists + * Hence, we create a cache of all needed pointer types. + * That's cumbersome as we end up with dbg_type in different modules (types_get_type() + * must be used for querying TI_GET_TYPE instead of types_get_info). */ -struct dbg_type types_find_pointer(const struct dbg_type* type) +BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* ret) { - struct type_find_t f; - struct dbg_type ret; + unsigned i; + struct dbg_type* new;
- f.result = dbg_itype_none; - f.tag = SymTagPointerType; - f.u.typeid = type->id; - SymEnumTypes(dbg_curr_process->handle, type->module, types_cb, &f); - ret.module = type->module; - ret.id = f.result; - return ret; + if (!dbg_curr_process) return FALSE; + for (i = 0; i < dbg_curr_process->num_pointers_type; i++) + if (!memcmp(type, &dbg_curr_process->pointers_type[i], sizeof(*type))) + { + ret->module = 0; + ret->id = dbg_itype_pointers + i; + return TRUE; + } + if (dbg_itype_pointers + dbg_curr_process->num_pointers_type >= dbg_itype_first) + { + FIXME("overflow in pointer types\n"); + return FALSE; + } + new = dbg_heap_realloc(dbg_curr_process->pointers_type, (dbg_curr_process->num_pointers_type + 1) * sizeof(*new)); + if (!new) return FALSE; + dbg_curr_process->pointers_type = new; + dbg_curr_process->pointers_type[dbg_curr_process->num_pointers_type] = *type; + ret->module = 0; + ret->id = dbg_itype_pointers + dbg_curr_process->num_pointers_type; + dbg_curr_process->num_pointers_type++; + + return TRUE; }
/****************************************************************** @@ -498,7 +504,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) types_get_info(&type, TI_GET_COUNT, &count); types_get_info(&type, TI_GET_LENGTH, &size); lvalue_field = *lvalue; - types_get_info(&lvalue_field.type, TI_GET_TYPE, &lvalue_field.type.id); + types_get_type(&lvalue_field.type, &lvalue_field.type); types_get_real_type(&lvalue_field.type, &tag);
if (size == count && tag == SymTagBaseType) @@ -536,7 +542,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) break; case SymTagTypedef: lvalue_field = *lvalue; - types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id); + types_get_type(&lvalue->type, &lvalue_field.type); print_value(&lvalue_field, format, level); break; default: @@ -598,8 +604,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) if (details) dbg_printf("Basic<%ls>", name); else dbg_printf("%ls", name); break; case SymTagPointerType: - types_get_info(type, TI_GET_TYPE, &subtype.id); - subtype.module = type->module; + types_get_type(type, &subtype); types_print_type(&subtype, FALSE); dbg_printf("*"); break; @@ -635,7 +640,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) if (!types_get_info(&type_elt, TI_GET_SYMNAME, &ptr) || !ptr) continue; dbg_printf("%ls", ptr); HeapFree(GetProcessHeap(), 0, ptr); - if (types_get_info(&type_elt, TI_GET_TYPE, &type_elt.id)) + if (types_get_type(&type_elt, &type_elt)) { dbg_printf(":"); types_print_type(&type_elt, details); @@ -650,8 +655,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) } break; case SymTagArrayType: - types_get_info(type, TI_GET_TYPE, &subtype.id); - subtype.module = type->module; + types_get_type(type, &subtype); types_print_type(&subtype, details); if (types_get_info(type, TI_GET_COUNT, &count)) dbg_printf(" %ls[%d]", name, count); @@ -662,17 +666,12 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) dbg_printf("enum %ls", name); break; case SymTagFunctionType: - types_get_info(type, TI_GET_TYPE, &subtype.id); - /* is the returned type the same object as function sig itself ? */ - if (subtype.id != type->id) + if (types_get_type(type, &subtype)) { - subtype.module = type->module; - types_print_type(&subtype, FALSE); - } - else - { - subtype.module = 0; - dbg_printf("<ret_type=self>"); + if (memcmp(type, &subtype, sizeof(subtype))) + types_print_type(&subtype, FALSE); + else + dbg_printf("<ret_type=self>"); } dbg_printf(" (*%ls)(", name); if (types_get_info(type, TI_GET_CHILDRENCOUNT, &count)) @@ -691,7 +690,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) for (i = 0; i < min(fcp->Count, count); i++) { subtype.id = fcp->ChildId[i]; - types_get_info(&subtype, TI_GET_TYPE, &subtype.id); + types_get_type(&subtype, &subtype); types_print_type(&subtype, FALSE); if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", "); } @@ -717,6 +716,9 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) /* helper to typecast pInfo to its expected type (_t) */ #define X(_t) (*((_t*)pInfo))
+/* wrapper to SymGetInfo, including also: support for internal types + * use types_get_type() rather than this function for TI_GET_TYPE request + */ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, void* pInfo) { if (type->id == dbg_itype_none) return FALSE; @@ -756,6 +758,20 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v return ret; }
+ if (type->id >= dbg_itype_pointers && type->id < dbg_itype_first) + { + unsigned i = type->id - dbg_itype_pointers; + if (i >= dbg_curr_process->num_pointers_type) return FALSE; + switch (ti) + { + case TI_GET_SYMTAG: X(DWORD) = SymTagPointerType; break; + case TI_GET_LENGTH: X(DWORD64) = ADDRSIZE; break; + case TI_GET_TYPE: WINE_FIXME("Should use types_get_type() instead\n"); break; + default: WINE_FIXME("unsupported %u for pointer type %d\n", ti, i); return FALSE; + } + return TRUE; + } + assert(type->id >= dbg_itype_first);
switch (type->id) @@ -920,6 +936,24 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v return TRUE; }
+/* one shouldn't call TI_GET_TYPE in symt_get_info() as cached pointer info won't be properly supported + * this function should be used instead + * (type and ret could point to the same structure) + */ +BOOL types_get_type(const struct dbg_type* type, struct dbg_type* ret) +{ + if (type->module == 0 && type->id >= dbg_itype_pointers && type->id < dbg_itype_first) + { + unsigned i = type->id - dbg_itype_pointers; + if (i >= dbg_curr_process->num_pointers_type) return FALSE; + *ret = dbg_curr_process->pointers_type[i]; + return TRUE; + } + if (!types_get_info(type, TI_GET_TYPE, &ret->id)) return FALSE; + ret->module = type->module; + return TRUE; +} + BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal);
static BOOL types_compare_name(struct dbg_type type1, struct dbg_type type2, BOOL* equal) @@ -969,8 +1003,7 @@ static BOOL types_compare_children(struct dbg_type type1, struct dbg_type type2, 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); + ret = types_get_type(&type1, &type1) && types_get_type(&type2, &type2); if (ret) ret = types_compare(type1, type2, equal); /* FIXME should compare bitfield info when present */ } @@ -1058,8 +1091,8 @@ BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal) 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)); + } while (types_get_type(&type1, &type1) && + types_get_type(&type2, &type2)); return FALSE; }
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index dab5fbd85a3..a152ea8a2c8 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -313,6 +313,8 @@ struct dbg_process* dbg_add_process(const struct be_process_io* pio, DWORD pid, p->source_current_file[0] = '\0'; p->source_start_line = -1; p->source_end_line = -1; + p->pointers_type = NULL; + p->num_pointers_type = 0;
list_add_head(&dbg_process_list, &p->entry);
@@ -362,6 +364,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); HeapFree(GetProcessHeap(), 0, (char*)p->imageName); + HeapFree(GetProcessHeap(), 0, p->pointers_type); HeapFree(GetProcessHeap(), 0, p); }