[PATCH 4/6] [WineDbg]: merge pointer deref and array index functions into a single one
Eric Pouech
eric.pouech at orange.fr
Mon Apr 12 14:18:25 CDT 2010
- fix incidentally target/host bug for array index (wasn't forcing target address space)
- fix also the number of bytes read by these two operations (now aligned on machine ptr size)
A+
---
programs/winedbg/debugger.h | 1 -
programs/winedbg/expr.c | 4 +-
programs/winedbg/memory.c | 2 +
programs/winedbg/types.c | 86 +++++++++++++++++++------------------------
programs/winedbg/winedbg.c | 2 -
5 files changed, 40 insertions(+), 55 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h
index 385a412..7efbaea 100644
--- a/programs/winedbg/debugger.h
+++ b/programs/winedbg/debugger.h
@@ -434,7 +434,6 @@ extern int print_types(void);
extern long int types_extract_as_integer(const struct dbg_lvalue*);
extern LONGLONG types_extract_as_longlong(const struct dbg_lvalue*, unsigned* psize);
extern void types_extract_as_address(const struct dbg_lvalue*, ADDRESS64*);
-extern BOOL types_deref(const struct dbg_lvalue* value, struct dbg_lvalue* result);
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*);
diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c
index 6b8c46f..66cd701 100644
--- a/programs/winedbg/expr.c
+++ b/programs/winedbg/expr.c
@@ -375,7 +375,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
break;
case EXPR_TYPE_PSTRUCT:
exp1 = expr_eval(exp->un.structure.exp1);
- if (exp1.type.id == dbg_itype_none || !types_deref(&exp1, &rtn) ||
+ 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,
@@ -626,7 +626,7 @@ struct dbg_lvalue expr_eval(struct expr* exp)
exp->un.unop.result = ~types_extract_as_integer(&exp1);
break;
case EXP_OP_DEREF:
- if (!types_deref(&exp1, &rtn))
+ if (!types_array_index(&exp1, 0, &rtn))
RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL);
break;
case EXP_OP_FORCE_DEREF:
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c
index 86aa881..7aad239 100644
--- a/programs/winedbg/memory.c
+++ b/programs/winedbg/memory.c
@@ -402,7 +402,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue)
}
break;
case SymTagPointerType:
- if (!types_deref(lvalue, &sub_lvalue))
+ if (!types_array_index(lvalue, 0, &sub_lvalue))
{
dbg_printf("Internal symbol error: unable to access memory location %p",
memory_to_linear_addr(&lvalue->addr));
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c
index 414bb9f..6d50c81 100644
--- a/programs/winedbg/types.c
+++ b/programs/winedbg/types.c
@@ -155,45 +155,6 @@ void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS64* addr)
}
/******************************************************************
- * types_deref
- *
- */
-BOOL types_deref(const struct dbg_lvalue* lvalue, struct dbg_lvalue* result)
-{
- struct dbg_type type = lvalue->type;
- DWORD tag;
-
- memset(result, 0, sizeof(*result));
- result->type.id = dbg_itype_none;
- result->type.module = 0;
-
- /*
- * Make sure that this really makes sense.
- */
- if (!types_get_real_type(&type, &tag) || tag != SymTagPointerType ||
- !memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset) ||
- !types_get_info(&type, TI_GET_TYPE, &result->type.id))
- return FALSE;
- 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...
- * for example:
- * x is a pointer to struct s, x being on the stack
- * => lvalue is in debuggee, result is in debugger
- * x is a pointer to struct s, x being optimized into a reg
- * => lvalue is debugger, result is debuggee
- * x is a pointer to internal variable x
- * => lvalue is debugger, result is debuggee
- * so we force debuggee address space, because dereferencing pointers to
- * internal variables is very unlikely. A correct fix would be
- * rather large.
- */
- result->addr.Mode = AddrModeFlat;
- return TRUE;
-}
-
-/******************************************************************
* types_get_udt_element_lvalue
*
* Implement a structure derefencement
@@ -301,24 +262,32 @@ BOOL types_udt_find_element(struct dbg_lvalue* lvalue, const char* name, long in
*
* Grab an element from an array
*/
-BOOL types_array_index(const struct dbg_lvalue* lvalue, int index,
- struct dbg_lvalue* result)
+BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lvalue* result)
{
struct dbg_type type = lvalue->type;
DWORD tag, count;
- DWORD64 length;
+
+ memset(result, 0, sizeof(*result));
+ result->type.id = dbg_itype_none;
+ result->type.module = 0;
if (!types_get_real_type(&type, &tag)) return FALSE;
- /* Contents of array share same data (addr mode, module...) */
- *result = *lvalue;
switch (tag)
{
case SymTagArrayType:
- types_get_info(&type, TI_GET_COUNT, &count);
+ if (!types_get_info(&type, TI_GET_COUNT, &count)) return FALSE;
if (index < 0 || index >= count) return FALSE;
+ result->addr = lvalue->addr;
break;
case SymTagPointerType:
- memory_read_value(lvalue, sizeof(result->addr.Offset), &result->addr.Offset);
+ if (!memory_read_value(lvalue, be_cpu->pointer_size, &result->addr.Offset)) return FALSE;
+ result->addr.Mode = AddrModeFlat;
+ switch (be_cpu->pointer_size)
+ {
+ case 4: result->addr.Offset = (DWORD)result->addr.Offset; break;
+ case 8: break;
+ default: assert(0);
+ }
break;
default:
assert(FALSE);
@@ -326,9 +295,28 @@ 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(&type, TI_GET_TYPE, &result->type.id);
- types_get_info(&result->type, TI_GET_LENGTH, &length);
- result->addr.Offset += index * (DWORD)length;
+ if (!types_get_info(&type, TI_GET_TYPE, &result->type.id)) return FALSE;
+ result->type.module = type.module;
+ if (index)
+ {
+ DWORD64 length;
+ if (!types_get_info(&result->type, TI_GET_LENGTH, &length)) return FALSE;
+ result->addr.Offset += index * (DWORD)length;
+ }
+ /* FIXME: the following statement is not always true (and can lead to buggy behavior).
+ * There is no way to tell were the deref:ed value is...
+ * For example:
+ * x is a pointer to struct s, x being on the stack
+ * => lvalue is in debuggee, result is in debugger
+ * x is a pointer to struct s, x being optimized into a reg
+ * => lvalue is debugger, result is debuggee
+ * x is a pointer to internal variable x
+ * => lvalue is debugger, result is debuggee
+ * So we always force debuggee address space, because dereferencing pointers to
+ * internal variables is very unlikely. A correct fix would be
+ * rather large.
+ */
+ result->cookie = DLV_TARGET;
return TRUE;
}
diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c
index 6ce6db4..7a37805 100644
--- a/programs/winedbg/winedbg.c
+++ b/programs/winedbg/winedbg.c
@@ -55,8 +55,6 @@
* + all computations should be made on long long
* o expr computations are in int:s
* o bitfield size is on a 4-bytes
- * + array_index and deref should be the same function (or should share the same
- * core)
* - execution:
* + set a better fix for gdb (proxy mode) than the step-mode hack
* + implement function call in debuggee
More information about the wine-patches
mailing list