diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 672c44e35c5..cd7a723f176 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -487,7 +487,7 @@ extern dbg_lgint_t types_extract_as_integer(const struct dbg_lvalue*); extern dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue*, unsigned* psize, BOOL *pissigned); extern void types_extract_as_address(const struct dbg_lvalue*, ADDRESS64*); extern BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from); -extern BOOL types_udt_find_element(struct dbg_lvalue* value, const char* name, ULONG *tmpbuf); +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_real_type(struct dbg_type* type, DWORD* tag); diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c index e7c41094544..5d9ef30ad13 100644 --- a/programs/winedbg/expr.c +++ b/programs/winedbg/expr.c @@ -83,7 +83,6 @@ struct expr { struct expr* exp1; const char* element_name; - ULONG /* FIXME */ result; } structure; struct @@ -361,8 +360,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) if (exp1.type.id == dbg_itype_none || !types_array_index(&exp1, 0, &rtn) || rtn.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - if (!types_udt_find_element(&rtn, exp->un.structure.element_name, - &exp->un.structure.result)) + if (!types_udt_find_element(&rtn, exp->un.structure.element_name)) { dbg_printf("%s\n", exp->un.structure.element_name); RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL); @@ -372,8 +370,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) exp1 = expr_eval(exp->un.structure.exp1); if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); rtn = exp1; - if (!types_udt_find_element(&rtn, exp->un.structure.element_name, - &exp->un.structure.result)) + if (!types_udt_find_element(&rtn, exp->un.structure.element_name)) { dbg_printf("%s\n", exp->un.structure.element_name); RaiseException(DEBUG_STATUS_NO_FIELD, 0, 0, NULL); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 2fed92c38f8..a5f169c5db4 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -237,15 +237,47 @@ BOOL memory_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size, /* size must fit in ret and be a power of two */ if (size > sizeof(*ret) || (size & (size - 1))) return FALSE; - /* we are on little endian CPU */ - memset(ret, 0, sizeof(*ret)); /* clear unread bytes */ - if (!memory_read_value(lvalue, size, ret)) return FALSE; - - /* propagate sign information */ - if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0) + if (lvalue->bitlen) { - dbg_lguint_t neg = -1; - *ret |= neg << (size * 8); + struct dbg_lvalue alt_lvalue = *lvalue; + dbg_lguint_t mask; + DWORD bt; + /* FIXME: this test isn't sufficient, depending on start of bitfield + * (ie a 64 bit field can spread across 9 bytes) + */ + if (lvalue->bitlen > 8 * sizeof(dbg_lgint_t)) return FALSE; + alt_lvalue.addr.Offset += lvalue->bitstart >> 3; + /* + * Bitfield operation. We have to extract the field. + */ + if (!memory_read_value(&alt_lvalue, sizeof(*ret), ret)) return FALSE; + mask = ~(dbg_lguint_t)0 << lvalue->bitlen; + *ret >>= lvalue->bitstart & 7; + *ret &= ~mask; + + /* + * OK, now we have the correct part of the number. + * Check to see whether the basic type is signed or not, and if so, + * we need to sign extend the number. + */ + if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && + (bt == btInt || bt == btLong) && (*ret & (1 << (lvalue->bitlen - 1)))) + { + *ret |= mask; + } + } + else + { + /* we are on little endian CPU */ + memset(ret, 0, sizeof(*ret)); /* clear unread bytes */ + if (!memory_read_value(lvalue, size, ret)) return FALSE; + + /* propagate sign information */ + if (is_signed && size < 8 && (*ret >> (size * 8 - 1)) != 0) + { + dbg_lguint_t neg = -1; + *ret |= neg << (size * 8); + } } return TRUE; } diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index de1fee9f84b..8f16a535606 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -68,6 +68,7 @@ dbg_lgint_t types_extract_as_lgint(const struct dbg_lvalue* lvalue, { return (LONG_PTR)memory_to_linear_addr(&lvalue->addr); } + if (tag != SymTagBaseType && lvalue->bitlen) dbg_printf("Unexpected bitfield on tag %d\n", tag); if (psize) *psize = 0; if (issigned) *issigned = FALSE; @@ -180,15 +181,11 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv * * Implement a structure derefencement */ -static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, - const struct dbg_type* type, ULONG *tmpbuf) +static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, const struct dbg_type* type) { DWORD offset, bitoffset; - DWORD bt; DWORD64 length; - unsigned mask; - 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; @@ -197,38 +194,17 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, if (types_get_info(type, TI_GET_BITPOSITION, &bitoffset)) { types_get_info(type, TI_GET_LENGTH, &length); - /* FIXME: this test isn't sufficient, depending on start of bitfield - * (ie a 32 bit field can spread across 5 bytes) - */ - if (length > 8 * sizeof(*tmpbuf)) return FALSE; - lvalue->addr.Offset += bitoffset >> 3; - /* - * Bitfield operation. We have to extract the field and store - * it in a temporary buffer so that we get it all right. - */ - if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE; - mask = 0xffffffff << (DWORD)length; - *tmpbuf >>= bitoffset & 7; - *tmpbuf &= ~mask; - - lvalue->in_debuggee = 0; - lvalue->addr.Offset = (ULONG_PTR)tmpbuf; - - /* - * OK, now we have the correct part of the number. - * Check to see whether the basic type is signed or not, and if so, - * we need to sign extend the number. - */ - if (types_get_info(&lvalue->type, TI_GET_BASETYPE, &bt) && - bt == btInt && (*tmpbuf & (1 << ((DWORD)length - 1)))) + lvalue->bitlen = length; + lvalue->bitstart = bitoffset; + if (lvalue->bitlen != length || lvalue->bitstart != bitoffset) { - *tmpbuf |= mask; + dbg_printf("too wide bitfields\n"); /* shouldn't happen */ + return FALSE; } } else - { - if (!memory_read_value(lvalue, sizeof(*tmpbuf), tmpbuf)) return FALSE; - } + lvalue->bitlen = lvalue->bitstart = 0; + return TRUE; } @@ -236,7 +212,7 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, * types_udt_find_element * */ -BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, ULONG *tmpbuf) +BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name) { DWORD tag, count; char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)]; @@ -266,7 +242,7 @@ BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, ULONG * WideCharToMultiByte(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp), NULL, NULL); HeapFree(GetProcessHeap(), 0, ptr); if (!strcmp(tmp, name)) - return types_get_udt_element_lvalue(lvalue, &type, tmpbuf); + return types_get_udt_element_lvalue(lvalue, &type); } } } @@ -475,7 +451,6 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) char buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)]; TI_FINDCHILDREN_PARAMS* fcp = (TI_FINDCHILDREN_PARAMS*)buffer; WCHAR* ptr; - ULONG tmpbuf; struct dbg_type sub_type; dbg_printf("{"); @@ -493,7 +468,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) dbg_printf("%ls=", ptr); HeapFree(GetProcessHeap(), 0, ptr); lvalue_field = *lvalue; - if (types_get_udt_element_lvalue(&lvalue_field, &sub_type, &tmpbuf)) + if (types_get_udt_element_lvalue(&lvalue_field, &sub_type)) { print_value(&lvalue_field, format, level + 1); } diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index 283b126ba84..dab5fbd85a3 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -44,9 +44,9 @@ * - type management: * + some bits of internal types are missing (like type casts and the address * operator) - * + all computations should be made on long long - * o expr computations are in int:s - * o bitfield size is on a 4-bytes + * + all computations should be made on 64bit + * o bitfield spreading on more bytes than dbg_lgint_t isn't supported + * (can happen on 128bit integers, of an ELF build...) * - execution: * + set a better fix for gdb (proxy mode) than the step-mode hack * + implement function call in debuggee