diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 9fee709bf75..c51ccc640ff 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -392,6 +392,7 @@ extern BOOL types_deref(const struct dbg_lvalue* value, struct dbg_l extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name, long int* tmpbuf); 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_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(unsigned long linear, const char* name, enum SymTagEnum tag); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index e7792bab867..fca6e3d8da0 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -280,17 +280,16 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) long double val_real; DWORD64 size64; DWORD tag, size, count, bt; - struct dbg_type rtype; + struct dbg_type type = lvalue->type; + struct dbg_type sub_type; - if (lvalue->type.id == dbg_itype_none || - !types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag)) - return; + if (!types_get_real_type(&type, &tag)) return; switch (tag) { case SymTagBaseType: - if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size64) || - !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt)) + if (!types_get_info(&type, TI_GET_LENGTH, &size64) || + !types_get_info(&type, TI_GET_BASETYPE, &bt)) { WINE_ERR("Couldn't get information\n"); RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); @@ -326,16 +325,18 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) case SymTagPointerType: if (!memory_read_value(lvalue, sizeof(void*), &val_ptr)) return; - if (!types_get_info(&lvalue->type, TI_GET_TYPE, &rtype.id) || - rtype.id == dbg_itype_none) + sub_type.module = lvalue->type.module; + if (!types_get_info(&type, TI_GET_TYPE, &sub_type.id) || + sub_type.id == dbg_itype_none) { dbg_printf("Internal symbol error: unable to access memory location %p", val_ptr); break; } - rtype.module = lvalue->type.module; - if (types_get_info(&rtype, TI_GET_SYMTAG, &tag) && tag == SymTagBaseType && - types_get_info(&rtype, TI_GET_BASETYPE, &bt) && bt == btChar && - types_get_info(&rtype, TI_GET_LENGTH, &size64)) + if (!types_get_real_type(&sub_type, &tag)) return; + + if (types_get_info(&sub_type, TI_GET_SYMTAG, &tag) && tag == SymTagBaseType && + types_get_info(&sub_type, TI_GET_BASETYPE, &bt) && bt == btChar && + types_get_info(&sub_type, TI_GET_LENGTH, &size64)) { char buffer[1024]; @@ -366,7 +367,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) */ if (!be_cpu->fetch_integer(lvalue, 4, TRUE, &val_int)) return; - if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count)) + if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count)) { char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)]; TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer; @@ -374,19 +375,18 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) char tmp[256]; VARIANT variant; int i; - struct dbg_type type; fcp->Start = 0; while (count) { fcp->Count = min(count, 256); - if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp)) + if (types_get_info(&type, TI_FINDCHILDREN, fcp)) { - type.module = lvalue->type.module; + sub_type.module = type.module; for (i = 0; i < min(fcp->Count, count); i++) { - type.id = fcp->ChildId[i]; - if (!types_get_info(&type, TI_GET_VALUE, &variant)) + sub_type.id = fcp->ChildId[i]; + if (!types_get_info(&sub_type, TI_GET_VALUE, &variant)) continue; switch (variant.n1.n2.vt) { @@ -396,7 +396,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) if (ok) { ptr = NULL; - types_get_info(&type, TI_GET_SYMNAME, &ptr); + types_get_info(&sub_type, TI_GET_SYMNAME, &ptr); if (!ptr) continue; WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL); HeapFree(GetProcessHeap(), 0, ptr); diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 05e1e89b17d..7ea1aa5fc37 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -29,6 +29,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(winedbg); +/****************************************************************** + * types_get_real_type + * + * Get rid of any potential typedef in the lvalue's type to get + * to the 'real' type (the one we can work upon). + */ +BOOL types_get_real_type(struct dbg_type* type, DWORD* tag) +{ + if (type->id == dbg_itype_none) return FALSE; + do + { + 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)); + return FALSE; +} + /****************************************************************** * types_extract_as_integer * @@ -41,12 +59,12 @@ long int types_extract_as_integer(const struct dbg_lvalue* lvalue) LONGLONG val; DWORD tag, bt; DWORD64 size; + struct dbg_type type = lvalue->type; - if (lvalue->type.id == dbg_itype_none || - !types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag)) + if (!types_get_real_type(&type, &tag)) RaiseException(DEBUG_STATUS_NOT_AN_INTEGER, 0, 0, NULL); - if (lvalue->type.id == dbg_itype_segptr) + if (type.id == dbg_itype_segptr) { return (long int)memory_to_linear_addr(&lvalue->addr); } @@ -54,8 +72,8 @@ long int types_extract_as_integer(const struct dbg_lvalue* lvalue) switch (tag) { case SymTagBaseType: - if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size) || - !types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt)) + if (!types_get_info(&type, TI_GET_LENGTH, &size) || + !types_get_info(&type, TI_GET_BASETYPE, &bt)) { WINE_ERR("Couldn't get information\n"); RaiseException(DEBUG_STATUS_INTERNAL_ERROR, 0, 0, NULL); @@ -133,7 +151,8 @@ void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS* addr) */ BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result) { - DWORD tag; + struct dbg_type type = lvalue->type; + DWORD tag; memset(result, 0, sizeof(*result)); result->type.id = dbg_itype_none; @@ -142,12 +161,11 @@ BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result) /* * Make sure that this really makes sense. */ - if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag) || - tag != SymTagPointerType || + if (!types_get_real_type(&type, &tag) || tag != SymTagPointerType || !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) || - !types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id)) + !types_get_info(&type, TI_GET_TYPE, &result->type.id)) return FALSE; - result->type.module = lvalue->type.module; + result->type.module = type.module; result->cookie = DLV_TARGET; /* FIXME: this is currently buggy. * there is no way to tell were the deref:ed value is... @@ -219,7 +237,6 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, else { if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE; - } return TRUE; } @@ -279,15 +296,15 @@ BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long in BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result) { - DWORD tag, count; - DWORD64 length; + struct dbg_type type = lvalue->type; + DWORD tag, count; + DWORD64 length; - if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag)) - return FALSE; + if (!types_get_real_type(&type, &tag)) return FALSE; switch (tag) { case SymTagArrayType: - types_get_info(&lvalue->type, TI_GET_COUNT, &count); + types_get_info(&type, TI_GET_COUNT, &count); if (index < 0 || index >= count) return FALSE; /* fall through */ case SymTagPointerType: @@ -296,7 +313,7 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, /* * Get the base type, so we know how much to index by. */ - types_get_info(&lvalue->type, TI_GET_TYPE, &result->type.id); + types_get_info(&type, TI_GET_TYPE, &result->type.id); types_get_info(&result->type, TI_GET_LENGTH, &length); memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset); result->addr.Offset += index * (DWORD)length; @@ -399,13 +416,20 @@ struct dbg_type types_find_type(unsigned long linear, const char* name, enum Sym */ void print_value(const struct dbg_lvalue* lvalue, char format, int level) { + struct dbg_type type = lvalue->type; struct dbg_lvalue lvalue_field; int i; DWORD tag; DWORD count; DWORD64 size; - if (lvalue->type.id == dbg_itype_none) + if (!types_get_real_type(&type, &tag)) + { + WINE_FIXME("---error\n"); + return; + } + + if (type.id == dbg_itype_none) { /* No type, just print the addr value */ print_bare_address(&lvalue->addr); @@ -418,47 +442,45 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) format = '\0'; } - if (!types_get_info(&lvalue->type, TI_GET_SYMTAG, &tag)) - { - WINE_FIXME("---error\n"); - return; - } switch (tag) { case SymTagBaseType: case SymTagEnum: case SymTagPointerType: + /* FIXME: this in not 100% optimal (as we're going through the typedef handling + * stuff again + */ print_basic(lvalue, 1, format); break; case SymTagUDT: - if (types_get_info(&lvalue->type, TI_GET_CHILDRENCOUNT, &count)) + if (types_get_info(&type, TI_GET_CHILDRENCOUNT, &count)) { char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)]; TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer; WCHAR* ptr; char tmp[256]; long int tmpbuf; - struct dbg_type type; + struct dbg_type sub_type; dbg_printf("{"); fcp->Start = 0; while (count) { fcp->Count = min(count, 256); - if (types_get_info(&lvalue->type, TI_FINDCHILDREN, fcp)) + if (types_get_info(&type, TI_FINDCHILDREN, fcp)) { for (i = 0; i < min(fcp->Count, count); i++) { ptr = NULL; - type.module = lvalue->type.module; - type.id = fcp->ChildId[i]; - types_get_info(&type, TI_GET_SYMNAME, &ptr); + sub_type.module = type.module; + sub_type.id = fcp->ChildId[i]; + types_get_info(&sub_type, TI_GET_SYMNAME, &ptr); if (!ptr) continue; WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL); dbg_printf("%s=", tmp); HeapFree(GetProcessHeap(), 0, ptr); lvalue_field = *lvalue; - if (types_get_udt_element_lvalue(&lvalue_field, &type, &tmpbuf)) + if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf)) { print_value(&lvalue_field, format, level + 1); } @@ -476,8 +498,8 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) * Loop over all of the entries, printing stuff as we go. */ count = 1; size = 1; - types_get_info(&lvalue->type, TI_GET_COUNT, &count); - types_get_info(&lvalue->type, TI_GET_LENGTH, &size); + types_get_info(&type, TI_GET_COUNT, &count); + types_get_info(&type, TI_GET_LENGTH, &size); if (size == count) { @@ -495,7 +517,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) break; } lvalue_field = *lvalue; - types_get_info(&lvalue->type, TI_GET_TYPE, &lvalue_field.type.id); + types_get_info(&type, TI_GET_TYPE, &lvalue_field.type.id); dbg_printf("{"); for (i = 0; i < count; i++) { @@ -508,7 +530,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) dbg_printf("Function "); print_bare_address(&lvalue->addr); dbg_printf(": "); - types_print_type(&lvalue->type, FALSE); + types_print_type(&type, FALSE); break; case SymTagTypedef: lvalue_field = *lvalue;