The following series supercedes previous (v3) which has been partially applied (contains non applied patches of (v3), plus a couple of improvements)
This serie: - improves WineDbg parsing (no more bison warnings) - module scoping (in the form module!name) now allows wildcards in module part - get/set on integers is fully supported (even on bitfields, including integral conversions) - get/set on floats is fully supported (including float/double conversions) - WineDbg now can access types from debuggee in its own expressions, as well as pointer types to debuggee's type, even if the debuggee doesn't provide them - type definition can be explored (extending print command with type eg. 'p HANDLE' gives 'typedef HANDLE => void*') - implements DbgHelp.SymEnumTypeFromName(W) - fixes a couple of bugs
A+ ---
Eric Pouech (19): programs/winedbg: let type_print_hex use dbg_lgint_t as its parameter type programs/winedbg: rename print_longlong into print_sdecimal (to mimic print_hex) programs/winedbg: revamp dbg_lvalue structure and add helpers for init programs/winedbg: add bitfield capability to dbg_lvalue programs/winedbg: move bitfield extraction to extract_lgint dbghelp: in SymGetTypeInfo(), return the correct basetype for enums programs/winedbg: add helper to compare types and use it to detect wrong assigments programs/winedbg: add helper to transfer memory between lvalues programs/winedbg: correctly store integers into a bitfield programs/winedbg: remove fetch_float() method from CPU backends programs/winedbg: implement proper assignements of floating point numbers programs/winedbg: move C++ identifier detection in the lexer programs/winedbg: move module scoping inside lexer dbghelp: implement SymEnumTypesByName(W) programs/winedbg: cache pointer type:s programs/winedbg: move type lookup at parsing time for cast operation programs/winedbg: added 'print type <TYPE>' command programs/winedbg: only call HeapFree on rightfully obtained buffers programs/winedbg: remove FORCE_DEREF expressions
dlls/dbghelp/dbghelp.spec | 4 +- dlls/dbghelp/type.c | 119 ++++++++- include/dbghelp.h | 2 + programs/winedbg/be_arm.c | 18 -- programs/winedbg/be_arm64.c | 18 -- programs/winedbg/be_cpu.h | 3 - programs/winedbg/be_i386.c | 18 -- programs/winedbg/be_x86_64.c | 18 -- programs/winedbg/break.c | 4 +- programs/winedbg/dbg.y | 78 +++--- programs/winedbg/debug.l | 12 +- programs/winedbg/debugger.h | 69 ++--- programs/winedbg/expr.c | 139 ++-------- programs/winedbg/expr.h | 1 - programs/winedbg/memory.c | 161 +++++++++-- programs/winedbg/stack.c | 4 +- programs/winedbg/symbol.c | 21 +- programs/winedbg/types.c | 499 +++++++++++++++++++++++++---------- programs/winedbg/winedbg.c | 9 +- 19 files changed, 734 insertions(+), 463 deletions(-)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index db4060d816a..d919922c058 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -360,13 +360,13 @@ static void dbg_print_longlong(LONGLONG sv, BOOL is_signed) dbg_printf("%s", ptr); }
-static void dbg_print_hex(DWORD size, ULONGLONG sv) +static void dbg_print_hex(DWORD size, dbg_lgint_t sv) { if (!sv) dbg_printf("0"); else /* clear unneeded high bits, esp. sign extension */ - dbg_printf("%#I64x", sv & (~0LLU >> (64 - 8 * size))); + dbg_printf("%#I64x", sv & (~(dbg_lguint_t)0 >> (8 * (sizeof(dbg_lgint_t) - size)))); }
static void print_typed_basic(const struct dbg_lvalue* lvalue) @@ -543,7 +543,7 @@ void print_basic(const struct dbg_lvalue* lvalue, char format) switch (format) { case 'x': - dbg_print_hex(size, (ULONGLONG)res); + dbg_print_hex(size, res); return;
case 'd':
dropping unsigned support as it's not used
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/memory.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-)
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index d919922c058..13bbc80c2fe 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -346,18 +346,9 @@ char* memory_offset_to_string(char *str, DWORD64 offset, unsigned mode) return str; }
-static void dbg_print_longlong(LONGLONG sv, BOOL is_signed) +static void dbg_print_sdecimal(dbg_lgint_t sv) { - char tmp[24], *ptr = tmp + sizeof(tmp) - 1; - ULONGLONG uv, div; - *ptr = '\0'; - if (is_signed && sv < 0) uv = -sv; - else { uv = sv; is_signed = FALSE; } - for (div = 10; uv; div *= 10, uv /= 10) - *--ptr = '0' + (uv % 10); - if (ptr == tmp + sizeof(tmp) - 1) *--ptr = '0'; - if (is_signed) *--ptr = '-'; - dbg_printf("%s", ptr); + dbg_printf("%I64d", sv); }
static void dbg_print_hex(DWORD size, dbg_lgint_t sv) @@ -512,7 +503,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) fcp->Start += 256; } } - if (!ok) dbg_print_longlong(val_int, TRUE); + if (!ok) dbg_print_sdecimal(val_int); } break; default: @@ -547,7 +538,7 @@ void print_basic(const struct dbg_lvalue* lvalue, char format) return;
case 'd': - dbg_print_longlong(res, TRUE); + dbg_print_sdecimal(res); return;
case 'c': @@ -570,7 +561,7 @@ void print_basic(const struct dbg_lvalue* lvalue, char format) } if (lvalue->type.id == dbg_itype_segptr) { - dbg_print_longlong(types_extract_as_lgint(lvalue, NULL, NULL), TRUE); + dbg_print_sdecimal(types_extract_as_lgint(lvalue, NULL, NULL)); } else print_typed_basic(lvalue); }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/break.c | 4 ++-- programs/winedbg/debugger.h | 25 ++++++++++++++++++------ programs/winedbg/expr.c | 45 +++++++++++-------------------------------- programs/winedbg/memory.c | 6 +++--- programs/winedbg/stack.c | 4 +--- programs/winedbg/symbol.c | 21 +++++++------------- programs/winedbg/types.c | 6 +++--- 7 files changed, 46 insertions(+), 65 deletions(-)
diff --git a/programs/winedbg/break.c b/programs/winedbg/break.c index d22dd7ac074..27a11a00d33 100644 --- a/programs/winedbg/break.c +++ b/programs/winedbg/break.c @@ -357,7 +357,7 @@ void break_check_delayed_bp(void) if (symbol_get_lvalue(dbp[i].u.symbol.name, dbp[i].u.symbol.lineno, &lvalue, TRUE) != sglv_found) continue; - if (lvalue.cookie != DLV_TARGET) continue; + if (!lvalue.in_debuggee) continue; } else lvalue.addr = dbp[i].u.addr; @@ -385,7 +385,7 @@ static void break_add_watch(const struct dbg_lvalue* lvalue, BOOL is_write) int num; DWORD64 l = 4;
- if (lvalue->cookie == DLV_HOST) + if (!lvalue->in_debuggee) { dbg_printf("Cannot set a watch point on register or register-based variable\n"); return; diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 5da569574f7..d3073c15f39 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -117,16 +117,29 @@ struct dbg_type
struct dbg_lvalue /* structure to hold left-values... */ { - int cookie; /* DLV_??? */ -/* DLV_TARGET references an address in debuggee's address space, whereas DLV_HOST - * references the winedbg's address space - */ -# define DLV_TARGET 0xF00D -# define DLV_HOST 0x50DA + unsigned in_debuggee : 1; /* 1 = debuggee address space, 0 = debugger address space) */ ADDRESS64 addr; struct dbg_type type; };
+static inline void init_lvalue(struct dbg_lvalue* lv, BOOL in_debuggee, void* addr) +{ + lv->in_debuggee = !!in_debuggee; + lv->addr.Mode = AddrModeFlat; + lv->addr.Offset = (DWORD_PTR)addr; + lv->type.module = 0; + lv->type.id = dbg_itype_none; +} + +static inline void init_lvalue_in_debugger(struct dbg_lvalue* lv, enum dbg_internal_types it, void* addr) +{ + lv->in_debuggee = 0; + lv->addr.Mode = AddrModeFlat; + lv->addr.Offset = (DWORD_PTR)addr; + lv->type.module = 0; + lv->type.id = it; +} + enum dbg_exec_mode { dbg_exec_cont, /* Continue execution */ diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c index 70bf6316785..e7c41094544 100644 --- a/programs/winedbg/expr.c +++ b/programs/winedbg/expr.c @@ -281,12 +281,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) DWORD tag; const struct dbg_internal_var* div;
- rtn.cookie = 0; - rtn.type.id = dbg_itype_none; - rtn.type.module = 0; - rtn.addr.Mode = AddrModeFlat; - rtn.addr.Offset = 0; - rtn.addr.Segment = 0; + init_lvalue_in_debugger(&rtn, dbg_itype_none, NULL);
switch (exp->type) { @@ -340,22 +335,13 @@ struct dbg_lvalue expr_eval(struct expr* exp) } break; case EXPR_TYPE_STRING: - rtn.cookie = DLV_HOST; - rtn.type.id = dbg_itype_astring; - rtn.type.module = 0; - rtn.addr.Offset = (ULONG_PTR)&exp->un.string.str; + init_lvalue_in_debugger(&rtn, dbg_itype_astring, &exp->un.string.str); break; case EXPR_TYPE_U_CONST: - rtn.cookie = DLV_HOST; - rtn.type.id = dbg_itype_lguint; - rtn.type.module = 0; - rtn.addr.Offset = (ULONG_PTR)&exp->un.u_const.value; + init_lvalue_in_debugger(&rtn, dbg_itype_lguint, &exp->un.u_const.value); break; case EXPR_TYPE_S_CONST: - rtn.cookie = DLV_HOST; - rtn.type.id = dbg_itype_lgint; - rtn.type.module = 0; - rtn.addr.Offset = (ULONG_PTR)&exp->un.s_const.value; + init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.s_const.value); break; case EXPR_TYPE_SYMBOL: switch (symbol_get_lvalue(exp->un.symbol.name, -1, &rtn, FALSE)) @@ -457,28 +443,22 @@ struct dbg_lvalue expr_eval(struct expr* exp) */ exp->un.call.result = 0; #endif - rtn.cookie = DLV_HOST; - /* get return type from function signature tupe */ + 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); - rtn.addr.Offset = (ULONG_PTR)&exp->un.call.result; break; case EXPR_TYPE_INTVAR: - rtn.cookie = DLV_HOST; if (!(div = dbg_get_internal_var(exp->un.intvar.name))) RaiseException(DEBUG_STATUS_NO_SYMBOL, 0, 0, NULL); - rtn.type.id = div->typeid; - rtn.type.module = 0; - rtn.addr.Offset = (ULONG_PTR)div->pval; + init_lvalue_in_debugger(&rtn, div->typeid, div->pval); break; case EXPR_TYPE_BINOP: - rtn.cookie = DLV_HOST; exp1 = expr_eval(exp->un.binop.exp1); exp2 = expr_eval(exp->un.binop.exp2); if (exp1.type.id == dbg_itype_none || exp2.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - rtn.type.id = dbg_itype_lgint; - rtn.type.module = 0; - rtn.addr.Offset = (ULONG_PTR)&exp->un.binop.result; + init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.binop.result); type1 = exp1.type; type2 = exp2.type; switch (exp->un.binop.binop_type) @@ -605,12 +585,9 @@ struct dbg_lvalue expr_eval(struct expr* exp) } break; case EXPR_TYPE_UNOP: - rtn.cookie = DLV_HOST; exp1 = expr_eval(exp->un.unop.exp1); if (exp1.type.id == dbg_itype_none) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - rtn.addr.Offset = (ULONG_PTR)&exp->un.unop.result; - rtn.type.id = dbg_itype_lgint; - rtn.type.module = 0; + init_lvalue_in_debugger(&rtn, dbg_itype_lgint, &exp->un.unop.result); switch (exp->un.unop.unop_type) { case EXP_OP_NEG: @@ -628,7 +605,7 @@ struct dbg_lvalue expr_eval(struct expr* exp) break; case EXP_OP_FORCE_DEREF: rtn = exp1; - if (exp1.cookie == DLV_TARGET) + if (exp1.in_debuggee) dbg_read_memory(memory_to_linear_addr(&exp1.addr), &rtn.addr.Offset, sizeof(rtn.addr.Offset)); break; case EXP_OP_ADDR: diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 13bbc80c2fe..2fed92c38f8 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -84,7 +84,7 @@ BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result { BOOL ret = FALSE;
- if (lvalue->cookie == DLV_TARGET) + if (lvalue->in_debuggee) { void* linear = memory_to_linear_addr(&lvalue->addr); if (!(ret = dbg_read_memory(linear, result, size))) @@ -120,7 +120,7 @@ BOOL memory_write_value(const struct dbg_lvalue* lvalue, DWORD size, void* value }
/* FIXME: only works on little endian systems */ - if (lvalue->cookie == DLV_TARGET) + if (lvalue->in_debuggee) { void* linear = memory_to_linear_addr(&lvalue->addr); if (!(ret = dbg_write_memory(linear, value, size))) @@ -440,7 +440,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) if (!val_ptr) dbg_printf("0x0"); else if (((bt == btChar || bt == btInt) && size64 == 1) || (bt == btUInt && size64 == 2)) { - if (memory_get_string(dbg_curr_process, val_ptr, sub_lvalue.cookie == DLV_TARGET, + if (memory_get_string(dbg_curr_process, val_ptr, sub_lvalue.in_debuggee, size64 == 2, buffer, sizeof(buffer))) dbg_printf(""%s"", buffer); else diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index 34089bcde04..c8352d8a994 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -39,10 +39,8 @@ void stack_info(int len)
if(len <= 0) len = 24; - - lvalue.cookie = 0; + init_lvalue(&lvalue, TRUE, 0); lvalue.type.id = dbg_itype_segptr; - lvalue.type.module = 0;
/* FIXME: we assume stack grows the same way as on i386 */ if (!memory_get_current_stack(&lvalue.addr)) diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index 896690c9eaf..08e0317154e 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -71,8 +71,7 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base,
if (!memory_get_register(sym->Register, &pval, buffer, sz)) return FALSE; - lvalue->cookie = DLV_HOST; - lvalue->addr.Offset = (DWORD_PTR)pval; + init_lvalue(lvalue, FALSE, pval); } else if (sym->Flags & SYMFLAG_REGREL) { @@ -85,8 +84,7 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base, l = strlen(buffer); sz -= l; buffer += l; - lvalue->cookie = DLV_TARGET; - lvalue->addr.Offset = (ULONG64)*pval + sym->Address; + init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(*pval + sym->Address)); if ((LONG64)sym->Address >= 0) snprintf(buffer, sz, "+%I64d]", sym->Address); else @@ -119,21 +117,18 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base, /* this is likely Wine's dbghelp which passes const values by reference * (object is managed by dbghelp, hence in debugger address space) */ - lvalue->cookie = DLV_HOST; - lvalue->addr.Offset = (DWORD_PTR)sym->Value; + init_lvalue(lvalue, FALSE, (void*)(DWORD_PTR)sym->Value); } else { DWORD* pdw = (DWORD*)lexeme_alloc_size(sizeof(*pdw)); - lvalue->cookie = DLV_HOST; - lvalue->addr.Offset = (DWORD_PTR)pdw; + init_lvalue(lvalue, FALSE, pdw); *pdw = sym->Value; } } else if (sym->Flags & SYMFLAG_LOCAL) { - lvalue->cookie = DLV_TARGET; - lvalue->addr.Offset = base + sym->Address; + init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(base + sym->Address)); } else if (sym->Flags & SYMFLAG_TLSREL) { @@ -176,13 +171,11 @@ static BOOL fill_sym_lvalue(const SYMBOL_INFO* sym, ULONG_PTR base,
addr += tlsindex * sizeof(DWORD_PTR); if (!dbg_read_memory((void*)addr, &addr, sizeof(addr))) goto tls_error; - lvalue->cookie = DLV_TARGET; - lvalue->addr.Offset = addr + sym->Address; + init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)(addr + sym->Address)); } else { - lvalue->cookie = DLV_TARGET; - lvalue->addr.Offset = sym->Address; + init_lvalue(lvalue, TRUE, (void*)(DWORD_PTR)sym->Address); } lvalue->addr.Mode = AddrModeFlat; lvalue->type.module = sym->ModBase; diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 74ba06cc31c..de1fee9f84b 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -211,7 +211,7 @@ static BOOL types_get_udt_element_lvalue(struct dbg_lvalue* lvalue, *tmpbuf >>= bitoffset & 7; *tmpbuf &= ~mask;
- lvalue->cookie = DLV_HOST; + lvalue->in_debuggee = 0; lvalue->addr.Offset = (ULONG_PTR)tmpbuf;
/* @@ -337,7 +337,7 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv * internal variables is very unlikely. A correct fix would be * rather large. */ - result->cookie = DLV_TARGET; + result->in_debuggee = 1; return TRUE; }
@@ -531,7 +531,7 @@ void print_value(const struct dbg_lvalue* lvalue, char format, int level) unsigned len = min(count, sizeof(buffer)); memory_get_string(dbg_curr_process, memory_to_linear_addr(&lvalue->addr), - lvalue->cookie == DLV_TARGET, TRUE, buffer, len); + lvalue->in_debuggee, TRUE, buffer, len); dbg_printf(""%s%s"", buffer, (len < count) ? "..." : ""); break; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index d3073c15f39..8a8921cb685 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -117,7 +117,9 @@ struct dbg_type
struct dbg_lvalue /* structure to hold left-values... */ { - unsigned in_debuggee : 1; /* 1 = debuggee address space, 0 = debugger address space) */ + unsigned in_debuggee : 1, /* 1 = debuggee address space, 0 = debugger address space) */ + bitstart : 8, /* in fact, 7 should be sufficient for underlying 128bit integers */ + bitlen; ADDRESS64 addr; struct dbg_type type; }; @@ -125,6 +127,8 @@ struct dbg_lvalue /* structure to hold left-values... */ static inline void init_lvalue(struct dbg_lvalue* lv, BOOL in_debuggee, void* addr) { lv->in_debuggee = !!in_debuggee; + lv->bitstart = 0; + lv->bitlen = 0; lv->addr.Mode = AddrModeFlat; lv->addr.Offset = (DWORD_PTR)addr; lv->type.module = 0; @@ -134,6 +138,8 @@ static inline void init_lvalue(struct dbg_lvalue* lv, BOOL in_debuggee, void* ad static inline void init_lvalue_in_debugger(struct dbg_lvalue* lv, enum dbg_internal_types it, void* addr) { lv->in_debuggee = 0; + lv->bitstart = 0; + lv->bitlen = 0; lv->addr.Mode = AddrModeFlat; lv->addr.Offset = (DWORD_PTR)addr; lv->type.module = 0;
(extraction is made on bitfield of width up to dbg_lgint_t size instead of LONG)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 2 +- programs/winedbg/expr.c | 7 ++---- programs/winedbg/memory.c | 48 +++++++++++++++++++++++++++++++++++------- programs/winedbg/types.c | 49 +++++++++++-------------------------------- programs/winedbg/winedbg.c | 6 +++-- 5 files changed, 58 insertions(+), 54 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 8a8921cb685..2e316548511 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
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/type.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index b7eb49116e2..3140d30e0bc 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -613,8 +613,7 @@ BOOL symt_get_info(struct module* module, const struct symt* type, X(DWORD) = ((const struct symt_basic*)type)->bt; break; case SymTagEnum: - X(DWORD) = btInt; - break; + return symt_get_info(module, ((const struct symt_enum*)type)->base_type, req, pInfo); default: return FALSE; }
DbgHelp exposes in SymGetTypeInfo() requests for testing type equivalence, but native implementation is more than broken. So don't rely on DbgHelp (in sake of portability) and keep implementation inside debugger instead.
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 2 programs/winedbg/types.c | 192 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 188 insertions(+), 6 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 2e316548511..35829e83f96 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -493,6 +493,8 @@ extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_T 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(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*);
/* winedbg.c */ extern void dbg_outputW(const WCHAR* buffer, int len); diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 8f16a535606..6b3fb0c9572 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -164,16 +164,33 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv { dbg_lgint_t val; DWORD64 size; + BOOL equal;
- if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE; - if (sizeof(val) < size) + if (!lvalue_to->bitlen && !lvalue_from->bitlen) { - dbg_printf("Insufficient size\n"); - return FALSE; + if (!types_compare(lvalue_to->type, lvalue_from->type, &equal)) return FALSE; + if (equal) + { + if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE; + if (sizeof(val) < size) + { + return memory_read_value(lvalue_from, size, &val) && + memory_write_value(lvalue_to, size, &val); + } + dbg_printf("NIY\n"); + /* else: should allocate intermediate buffer... */ + return FALSE; + } + } + if (types_is_integral_type(lvalue_from) && types_is_integral_type(lvalue_to)) + { + /* doing integer conversion (about sign, size) */ + val = types_extract_as_integer(lvalue_from); + return memory_store_integer(lvalue_to, val); } /* FIXME: should support floats as well */ - val = types_extract_as_integer(lvalue_from); - return memory_store_integer(lvalue_to, val); + dbg_printf("Cannot assign (different types)\n"); return FALSE; + return FALSE; }
/****************************************************************** @@ -910,3 +927,166 @@ BOOL types_get_info(const struct dbg_type* type, IMAGEHLP_SYMBOL_TYPE_INFO ti, v #undef X 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) +{ + LPWSTR name1, name2; + BOOL ret; + + if (types_get_info(&type1, TI_GET_SYMNAME, &name1)) + { + if (types_get_info(&type2, TI_GET_SYMNAME, &name2)) + { + *equal = !wcscmp(name1, name2); + ret = TRUE; + HeapFree(GetProcessHeap(), 0, name2); + } + else ret = FALSE; + HeapFree(GetProcessHeap(), 0, name1); + } + else ret = FALSE; + return ret; +} + +static BOOL types_compare_children(struct dbg_type type1, struct dbg_type type2, BOOL* equal, DWORD tag) +{ + DWORD count1, count2, i; + DWORD* children; + BOOL ret; + + if (!types_get_info(&type1, TI_GET_CHILDRENCOUNT, &count1) || + !types_get_info(&type2, TI_GET_CHILDRENCOUNT, &count2)) return FALSE; + if (count1 != count2) {*equal = FALSE; return TRUE;} + if (!count1) return *equal = TRUE; + if ((children = malloc(sizeof(*children) * 2 * count1)) == NULL) return FALSE; + if (types_get_info(&type1, TI_FINDCHILDREN, &children[0]) && + types_get_info(&type2, TI_FINDCHILDREN, &children[count1])) + { + for (i = 0; i < count1; ++i) + { + type1.id = children[i]; + type2.id = children[count1 + i]; + switch (tag) + { + case SymTagFunctionType: ret = types_compare(type1, type2, equal); break; + case SymTagUDT: + /* each child is a SymTagData that describes the member */ + ret = types_compare_name(type1, type2, equal); + 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); + if (ret) ret = types_compare(type1, type2, equal); + /* FIXME should compare bitfield info when present */ + } + break; + default: ret = FALSE; break; + } + if (!ret || !*equal) break; + } + if (i == count1) ret = *equal = TRUE; + } + else ret = FALSE; + + free(children); + return ret; +} + +BOOL types_compare(struct dbg_type type1, struct dbg_type type2, BOOL* equal) +{ + DWORD tag1, tag2; + DWORD64 size1, size2; + DWORD bt1, bt2; + DWORD count1, count2; + BOOL ret; + + do + { + if (type1.module == type2.module && type1.id == type2.id) + return *equal = TRUE; + + if (!types_get_real_type(&type1, &tag1) || + !types_get_real_type(&type2, &tag2)) return FALSE; + + if (type1.module == type2.module && type1.id == type2.id) + return *equal = TRUE; + + if (tag1 != tag2) return !(*equal = FALSE); + + switch (tag1) + { + case SymTagBaseType: + if (!types_get_info(&type1, TI_GET_BASETYPE, &bt1) || + !types_get_info(&type2, TI_GET_BASETYPE, &bt2) || + !types_get_info(&type1, TI_GET_LENGTH, &size1) || + !types_get_info(&type2, TI_GET_LENGTH, &size2)) + return FALSE; + *equal = bt1 == bt2 && size1 == size2; + return TRUE; + case SymTagPointerType: + /* compare sub types */ + break; + case SymTagUDT: + case SymTagEnum: + ret = types_compare_name(type1, type2, equal); + if (!ret || !*equal) return ret; + ret = types_compare_children(type1, type2, equal, tag1); + if (!ret || !*equal) return ret; + if (tag1 == SymTagUDT) return TRUE; + /* compare underlying type for enums */ + break; + case SymTagArrayType: + if (!types_get_info(&type1, TI_GET_LENGTH, &size1) || + !types_get_info(&type2, TI_GET_LENGTH, &size2) || + !types_get_info(&type1, TI_GET_COUNT, &count1) || + !types_get_info(&type2, TI_GET_COUNT, &count2)) return FALSE; + if (size1 == size2 && count1 == count2) + { + struct dbg_type subtype1 = type1, subtype2 = type2; + if (!types_get_info(&type1, TI_GET_ARRAYINDEXTYPEID, &subtype1.id) || + !types_get_info(&type2, TI_GET_ARRAYINDEXTYPEID, &subtype2.id)) return FALSE; + if (!types_compare(subtype1, subtype2, equal)) return FALSE; + if (!*equal) return TRUE; + } + else return !(*equal = FALSE); + /* compare subtypes */ + break; + case SymTagFunctionType: + if (!types_compare_children(type1, type2, equal, tag1)) return FALSE; + if (!*equal) return TRUE; + /* compare return:ed type */ + break; + case SymTagFunctionArgType: + /* compare argument type */ + break; + default: + 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)); + return FALSE; +} + +static BOOL is_basetype_char(DWORD bt) +{ + return bt == btChar || bt == btWChar || bt == btChar8 || bt == btChar16 || bt == btChar32; +} + +static BOOL is_basetype_integer(DWORD bt) +{ + return is_basetype_char(bt) || bt == btInt || bt == btUInt || bt == btLong || bt == btULong; +} + +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) || + !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE; + return is_basetype_integer(bt); +}
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 1 + programs/winedbg/memory.c | 31 +++++++++++++++++++++++++++++++ programs/winedbg/types.c | 19 +++---------------- 3 files changed, 35 insertions(+), 16 deletions(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 35829e83f96..97f79a1883c 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -392,6 +392,7 @@ extern void info_wine_dbg_channel(BOOL add, const char* chnl, const /* memory.c */ extern BOOL memory_read_value(const struct dbg_lvalue* lvalue, DWORD size, void* result); extern BOOL memory_write_value(const struct dbg_lvalue* val, DWORD size, void* value); +extern BOOL memory_transfer_value(const struct dbg_lvalue* to, const struct dbg_lvalue* from); extern BOOL memory_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size, BOOL is_signed, dbg_lgint_t* ret); extern BOOL memory_store_integer(const struct dbg_lvalue* lvalue, dbg_lgint_t val); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index a5f169c5db4..1cf8726f467 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -133,6 +133,37 @@ BOOL memory_write_value(const struct dbg_lvalue* lvalue, DWORD size, void* value return ret; }
+/* transfer a block of memory + * the two lvalue:s are expected to be of same size + */ +BOOL memory_transfer_value(const struct dbg_lvalue* to, const struct dbg_lvalue* from) +{ + DWORD64 size_to, size_from; + BYTE tmp[256]; + BYTE* ptr = tmp; + BOOL ret; + + if (to->bitlen || from->bitlen) return FALSE; + if (!types_get_info(&to->type, TI_GET_LENGTH, &size_to) || + !types_get_info(&from->type, TI_GET_LENGTH, &size_from) || + size_from != size_to) return FALSE; + /* optimize debugger to debugger transfer */ + if (!to->in_debuggee && !from->in_debuggee) + { + memcpy(memory_to_linear_addr(&to->addr), memory_to_linear_addr(&from->addr), size_from); + return TRUE; + } + if (size_to > sizeof(tmp)) + { + ptr = malloc(size_from); + if (!ptr) return FALSE; + } + ret = memory_read_value(from, size_from, ptr) && + memory_write_value(to, size_from, ptr); + if (size_to > sizeof(tmp)) free(ptr); + return ret; +} + /*********************************************************************** * memory_examine * diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 6b3fb0c9572..f8d242fb64d 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -162,30 +162,17 @@ void types_extract_as_address(const struct dbg_lvalue* lvalue, ADDRESS64* addr)
BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lvalue_from) { - dbg_lgint_t val; - DWORD64 size; - BOOL equal; - if (!lvalue_to->bitlen && !lvalue_from->bitlen) { + BOOL equal; if (!types_compare(lvalue_to->type, lvalue_from->type, &equal)) return FALSE; if (equal) - { - if (!types_get_info(&lvalue_to->type, TI_GET_LENGTH, &size)) return FALSE; - if (sizeof(val) < size) - { - return memory_read_value(lvalue_from, size, &val) && - memory_write_value(lvalue_to, size, &val); - } - dbg_printf("NIY\n"); - /* else: should allocate intermediate buffer... */ - return FALSE; - } + return memory_transfer_value(lvalue_to, lvalue_from); } if (types_is_integral_type(lvalue_from) && types_is_integral_type(lvalue_to)) { /* doing integer conversion (about sign, size) */ - val = types_extract_as_integer(lvalue_from); + dbg_lgint_t val = types_extract_as_integer(lvalue_from); return memory_store_integer(lvalue_to, val); } /* FIXME: should support floats as well */
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/memory.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 1cf8726f467..6dffcc9db45 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -317,6 +317,23 @@ BOOL memory_store_integer(const struct dbg_lvalue* lvalue, dbg_lgint_t val) { DWORD64 size; if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size)) return FALSE; + if (lvalue->bitlen) + { + struct dbg_lvalue alt_lvalue = *lvalue; + dbg_lguint_t mask, dst; + + /* 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; + /* mask is 1 where bitfield is present, 0 outside */ + mask = (~(dbg_lguint_t)0 >> (sizeof(val) * 8 - lvalue->bitlen)) << (lvalue->bitstart & 7); + alt_lvalue.addr.Offset += lvalue->bitstart >> 3; + val <<= lvalue->bitstart & 7; + if (!memory_read_value(&alt_lvalue, (unsigned)size, &dst)) return FALSE; + val = (dst & ~mask) | (val & mask); + return memory_write_value(&alt_lvalue, (unsigned)size, &val); + } /* this is simple if we're on a little endian CPU */ return memory_write_value(lvalue, (unsigned)size, &val); }
As they're all the same
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/be_arm.c | 18 ------------------ programs/winedbg/be_arm64.c | 18 ------------------ programs/winedbg/be_cpu.h | 3 --- programs/winedbg/be_i386.c | 18 ------------------ programs/winedbg/be_x86_64.c | 18 ------------------ programs/winedbg/debugger.h | 1 + programs/winedbg/memory.c | 17 ++++++++++++++++- 7 files changed, 17 insertions(+), 76 deletions(-)
diff --git a/programs/winedbg/be_arm.c b/programs/winedbg/be_arm.c index 02f72e9c789..a9551a40337 100644 --- a/programs/winedbg/be_arm.c +++ b/programs/winedbg/be_arm.c @@ -1831,23 +1831,6 @@ static int be_arm_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way) return step; }
-static BOOL be_arm_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, double *ret) -{ - char tmp[sizeof(double)]; - - /* FIXME: this assumes that debuggee and debugger use the same - * representation for reals - */ - if (size > sizeof(tmp)) return FALSE; - if (!memory_read_value(lvalue, size, tmp)) return FALSE; - - if (size == sizeof(float)) *ret = *(float*)tmp; - else if (size == sizeof(double)) *ret = *(double*)tmp; - else return FALSE; - - return TRUE; -} - static BOOL be_arm_get_context(HANDLE thread, dbg_ctx_t *ctx) { ctx->ctx.ContextFlags = CONTEXT_ALL; @@ -1904,7 +1887,6 @@ struct backend_cpu be_arm = be_arm_is_watchpoint_set, be_arm_clear_watchpoint, be_arm_adjust_pc_for_break, - be_arm_fetch_float, be_arm_get_context, be_arm_set_context, be_arm_gdb_register_map, diff --git a/programs/winedbg/be_arm64.c b/programs/winedbg/be_arm64.c index 8ca54e6c461..ab64801e6db 100644 --- a/programs/winedbg/be_arm64.c +++ b/programs/winedbg/be_arm64.c @@ -228,23 +228,6 @@ static int be_arm64_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way) return 4; }
-static BOOL be_arm64_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, double *ret) -{ - char tmp[sizeof(double)]; - - /* FIXME: this assumes that debuggee and debugger use the same - * representation for reals - */ - if (size > sizeof(tmp)) return FALSE; - if (!memory_read_value(lvalue, size, tmp)) return FALSE; - - if (size == sizeof(float)) *ret = *(float*)tmp; - else if (size == sizeof(double)) *ret = *(double*)tmp; - else return FALSE; - - return TRUE; -} - void be_arm64_disasm_one_insn(ADDRESS64 *addr, int display) { dbg_printf("be_arm64_disasm_one_insn: not done\n"); @@ -323,7 +306,6 @@ struct backend_cpu be_arm64 = be_arm64_is_watchpoint_set, be_arm64_clear_watchpoint, be_arm64_adjust_pc_for_break, - be_arm64_fetch_float, be_arm64_get_context, be_arm64_set_context, be_arm64_gdb_register_map, diff --git a/programs/winedbg/be_cpu.h b/programs/winedbg/be_cpu.h index 69e3e148f75..0c4f9b8f056 100644 --- a/programs/winedbg/be_cpu.h +++ b/programs/winedbg/be_cpu.h @@ -118,9 +118,6 @@ struct backend_cpu /* ------------------------------------------------------------------------------- * basic type read/write * -------------------------------------------------------------------------------*/ - /* Reads a real from memory and stores it inside a long double */ - BOOL (*fetch_float)(const struct dbg_lvalue* lvalue, unsigned size, double*); - BOOL (*get_context)(HANDLE thread, dbg_ctx_t *ctx); BOOL (*set_context)(HANDLE thread, const dbg_ctx_t *ctx);
diff --git a/programs/winedbg/be_i386.c b/programs/winedbg/be_i386.c index 9b3c615092c..262e68894d5 100644 --- a/programs/winedbg/be_i386.c +++ b/programs/winedbg/be_i386.c @@ -777,23 +777,6 @@ static int be_i386_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way) return 1; }
-static BOOL be_i386_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, double *ret) -{ - char tmp[sizeof(double)]; - - /* FIXME: this assumes that debuggee and debugger use the same - * representation for reals - */ - if (size > sizeof(tmp)) return FALSE; - if (!memory_read_value(lvalue, size, tmp)) return FALSE; - - if (size == sizeof(float)) *ret = *(float*)tmp; - else if (size == sizeof(double)) *ret = *(double*)tmp; - else return FALSE; - - return TRUE; -} - static BOOL be_i386_get_context(HANDLE thread, dbg_ctx_t *ctx) { ctx->x86.ContextFlags = WOW64_CONTEXT_ALL; @@ -875,7 +858,6 @@ struct backend_cpu be_i386 = be_i386_is_watchpoint_set, be_i386_clear_watchpoint, be_i386_adjust_pc_for_break, - be_i386_fetch_float, be_i386_get_context, be_i386_set_context, be_i386_gdb_register_map, diff --git a/programs/winedbg/be_x86_64.c b/programs/winedbg/be_x86_64.c index 169a31a584d..44079c2fe76 100644 --- a/programs/winedbg/be_x86_64.c +++ b/programs/winedbg/be_x86_64.c @@ -699,23 +699,6 @@ static int be_x86_64_adjust_pc_for_break(dbg_ctx_t *ctx, BOOL way) return 1; }
-static BOOL be_x86_64_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, double *ret) -{ - char tmp[sizeof(double)]; - - /* FIXME: this assumes that debuggee and debugger use the same - * representation for reals - */ - if (size > sizeof(tmp)) return FALSE; - if (!memory_read_value(lvalue, size, tmp)) return FALSE; - - if (size == sizeof(float)) *ret = *(float*)tmp; - else if (size == sizeof(double)) *ret = *(double*)tmp; - else return FALSE; - - return TRUE; -} - static BOOL be_x86_64_get_context(HANDLE thread, dbg_ctx_t *ctx) { ctx->ctx.ContextFlags = CONTEXT_ALL; @@ -813,7 +796,6 @@ struct backend_cpu be_x86_64 = be_x86_64_is_watchpoint_set, be_x86_64_clear_watchpoint, be_x86_64_adjust_pc_for_break, - be_x86_64_fetch_float, be_x86_64_get_context, be_x86_64_set_context, be_x86_64_gdb_register_map, diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 97f79a1883c..9b6efccb69e 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -396,6 +396,7 @@ extern BOOL memory_transfer_value(const struct dbg_lvalue* to, const extern BOOL memory_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size, BOOL is_signed, dbg_lgint_t* ret); extern BOOL memory_store_integer(const struct dbg_lvalue* lvalue, dbg_lgint_t val); +extern BOOL memory_fetch_float(const struct dbg_lvalue* lvalue, double *ret); extern void memory_examine(const struct dbg_lvalue *lvalue, int count, char format); extern void* memory_to_linear_addr(const ADDRESS64* address); extern BOOL memory_get_current_pc(ADDRESS64* address); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index 6dffcc9db45..eed9bf6c049 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -338,6 +338,21 @@ BOOL memory_store_integer(const struct dbg_lvalue* lvalue, dbg_lgint_t val) return memory_write_value(lvalue, (unsigned)size, &val); }
+BOOL memory_fetch_float(const struct dbg_lvalue* lvalue, double *ret) +{ + DWORD64 size; + if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size)) return FALSE; + /* FIXME: this assumes that debuggee and debugger use the same + * representation for reals + */ + if (size > sizeof(*ret)) return FALSE; + if (!memory_read_value(lvalue, size, ret)) return FALSE; + + if (size == sizeof(float)) *ret = *(float*)ret; + else if (size != sizeof(double)) return FALSE; + + return TRUE; +}
BOOL memory_get_string(struct dbg_process* pcs, void* addr, BOOL in_debuggee, BOOL unicode, char* buffer, int size) @@ -478,7 +493,7 @@ static void print_typed_basic(const struct dbg_lvalue* lvalue) dbg_print_hex(size, val_int); break; case btFloat: - if (!dbg_curr_process->be_cpu->fetch_float(lvalue, size, &val_real)) return; + if (!memory_fetch_float(lvalue, &val_real)) return; dbg_printf("%f", val_real); break; case btChar:
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/debugger.h | 2 ++ programs/winedbg/memory.c | 17 +++++++++++++++++ programs/winedbg/types.c | 17 ++++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 9b6efccb69e..f74ddfc210f 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -397,6 +397,7 @@ extern BOOL memory_fetch_integer(const struct dbg_lvalue* lvalue, un BOOL is_signed, dbg_lgint_t* ret); extern BOOL memory_store_integer(const struct dbg_lvalue* lvalue, dbg_lgint_t val); extern BOOL memory_fetch_float(const struct dbg_lvalue* lvalue, double *ret); +extern BOOL memory_store_float(const struct dbg_lvalue* lvalue, double *ret); extern void memory_examine(const struct dbg_lvalue *lvalue, int count, char format); extern void* memory_to_linear_addr(const ADDRESS64* address); extern BOOL memory_get_current_pc(ADDRESS64* address); @@ -497,6 +498,7 @@ extern struct dbg_type types_find_pointer(const struct dbg_type* type); 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*); +extern BOOL types_is_float_type(const struct dbg_lvalue*);
/* winedbg.c */ extern void dbg_outputW(const WCHAR* buffer, int len); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index eed9bf6c049..5e01bef5607 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -354,6 +354,23 @@ BOOL memory_fetch_float(const struct dbg_lvalue* lvalue, double *ret) return TRUE; }
+BOOL memory_store_float(const struct dbg_lvalue* lvalue, double *ret) +{ + DWORD64 size; + if (!types_get_info(&lvalue->type, TI_GET_LENGTH, &size)) return FALSE; + /* FIXME: this assumes that debuggee and debugger use the same + * representation for reals + */ + if (size > sizeof(*ret)) return FALSE; + if (size == sizeof(float)) + { + float f = *ret; + return memory_write_value(lvalue, size, &f); + } + if (size != sizeof(double)) return FALSE; + return memory_write_value(lvalue, size, ret); +} + BOOL memory_get_string(struct dbg_process* pcs, void* addr, BOOL in_debuggee, BOOL unicode, char* buffer, int size) { diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index f8d242fb64d..3aefbe03058 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -168,6 +168,12 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv if (!types_compare(lvalue_to->type, lvalue_from->type, &equal)) return FALSE; if (equal) return memory_transfer_value(lvalue_to, lvalue_from); + if (types_is_float_type(lvalue_from) && types_is_float_type(lvalue_to)) + { + double d; + return memory_fetch_float(lvalue_from, &d) && + memory_store_float(lvalue_to, &d); + } } if (types_is_integral_type(lvalue_from) && types_is_integral_type(lvalue_to)) { @@ -175,7 +181,6 @@ BOOL types_store_value(struct dbg_lvalue* lvalue_to, const struct dbg_lvalue* lv dbg_lgint_t val = types_extract_as_integer(lvalue_from); return memory_store_integer(lvalue_to, val); } - /* FIXME: should support floats as well */ dbg_printf("Cannot assign (different types)\n"); return FALSE; return FALSE; } @@ -1077,3 +1082,13 @@ BOOL types_is_integral_type(const struct dbg_lvalue* lv) !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE; return is_basetype_integer(bt); } + +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) || + !types_get_info(&type, TI_GET_BASETYPE, &bt)) return FALSE; + return bt == btFloat; +}
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/dbg.y | 14 ++++---------- programs/winedbg/debug.l | 4 ++-- 2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 46a643bfb47..79877b2c644 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -77,13 +77,13 @@ static void parser(const char*); %left '+' '-' %left '*' '/' '%' %left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */ -%left '.' '[' OP_DRF OP_SCOPE +%left '.' '[' OP_DRF %nonassoc ':'
%type <expression> expr lvalue %type <lvalue> expr_lvalue lvalue_addr %type <integer> expr_rvalue -%type <string> pathname identifier cpp_identifier +%type <string> pathname identifier %type <listing> list_arg %type <type> type_expr %type <strings> list_of_words @@ -162,15 +162,9 @@ pathname: | tPATH { $$ = $1; } ;
-cpp_identifier: - tIDENTIFIER { $$ = $1; } - | identifier OP_SCOPE tIDENTIFIER { $$ = lexeme_alloc_size(strlen($1) + 2 + strlen($3) + 1); - sprintf($$, "%s::%s", $1, $3); } - ; - identifier: - cpp_identifier { $$ = $1; } - | tIDENTIFIER '!' cpp_identifier { $$ = lexeme_alloc_size(strlen($1) + 1 + strlen($3) + 1); + tIDENTIFIER { $$ = $1; } + | tIDENTIFIER '!' tIDENTIFIER { $$ = lexeme_alloc_size(strlen($1) + 1 + strlen($3) + 1); sprintf($$, "%s!%s", $1, $3); } ;
diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l index 5c87f05abe5..a587a13fb70 100644 --- a/programs/winedbg/debug.l +++ b/programs/winedbg/debug.l @@ -99,6 +99,7 @@ DIGIT [0-9] HEXDIGIT [0-9a-fA-F] FORMAT [ubcdgiswxa] IDENTIFIER [_a-zA-Z~?][_a-zA-Z0-9~?@]* +SCOPED_IDENTIFIER [_a-zA-Z~?][_a-zA-Z0-9~?@]*"::" PATHNAME [\/_a-zA-Z0-9.~@][\/-_a-zA-Z0-9.~@]* STRING "(\[^\n]|[^\"\n])*"
@@ -135,7 +136,6 @@ STRING "(\[^\n]|[^\"\n])*" "<<" { return OP_SHL; } ">>" { return OP_SHR; } "->" { return OP_DRF; } -"::" { return OP_SCOPE; } "[" { return *yytext; } "]" { return *yytext; }
@@ -243,7 +243,7 @@ union { return tUNION; } enum { return tENUM; } all { return tALL; }
-{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; } +{SCOPED_IDENTIFIER}*{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; } "$"{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext+1); return tINTVAR; }
<PATH_EXPECTED,PATH_ACCEPTED>{PATHNAME} { dbg_lval.string = lexeme_alloc(yytext); return tPATH; }
this allows to express module scoping with wild characters (eg kernel*!CreateFileA)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/dbg.y | 2 -- programs/winedbg/debug.l | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 79877b2c644..3e6ef34b836 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -164,8 +164,6 @@ pathname:
identifier: tIDENTIFIER { $$ = $1; } - | tIDENTIFIER '!' tIDENTIFIER { $$ = lexeme_alloc_size(strlen($1) + 1 + strlen($3) + 1); - sprintf($$, "%s!%s", $1, $3); } ;
list_arg: diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l index a587a13fb70..280013799c9 100644 --- a/programs/winedbg/debug.l +++ b/programs/winedbg/debug.l @@ -100,6 +100,7 @@ HEXDIGIT [0-9a-fA-F] FORMAT [ubcdgiswxa] IDENTIFIER [_a-zA-Z~?][_a-zA-Z0-9~?@]* SCOPED_IDENTIFIER [_a-zA-Z~?][_a-zA-Z0-9~?@]*"::" +MODULE_IDENTIFIER [_a-zA-Z~?*][_a-zA-Z0-9~?*@]*"!" PATHNAME [\/_a-zA-Z0-9.~@][\/-_a-zA-Z0-9.~@]* STRING "(\[^\n]|[^\"\n])*"
@@ -243,7 +244,7 @@ union { return tUNION; } enum { return tENUM; } all { return tALL; }
-{SCOPED_IDENTIFIER}*{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; } +{MODULE_IDENTIFIER}?{SCOPED_IDENTIFIER}*{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; } "$"{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext+1); return tINTVAR; }
<PATH_EXPECTED,PATH_ACCEPTED>{PATHNAME} { dbg_lval.string = lexeme_alloc(yytext); return tPATH; }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- dlls/dbghelp/dbghelp.spec | 4 +- dlls/dbghelp/type.c | 116 +++++++++++++++++++++++++++++++++++++++++++++ include/dbghelp.h | 2 + 3 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/dlls/dbghelp/dbghelp.spec b/dlls/dbghelp/dbghelp.spec index 471d9b6141c..87861cd87ce 100644 --- a/dlls/dbghelp/dbghelp.spec +++ b/dlls/dbghelp/dbghelp.spec @@ -57,8 +57,8 @@ @ stub SymEnumSymbolsForAddrW @ stdcall SymEnumSymbolsW(ptr int64 wstr ptr ptr) @ stdcall SymEnumTypes(ptr int64 ptr ptr) -@ stub SymEnumTypesByName -@ stub SymEnumTypesByNameW +@ stdcall SymEnumTypesByName(ptr int64 str ptr ptr) +@ stdcall SymEnumTypesByNameW(ptr int64 wstr ptr ptr) @ stdcall SymEnumTypesW(ptr int64 ptr ptr) @ stdcall SymEnumerateModules(long ptr ptr) @ stdcall SymEnumerateModules64(long ptr ptr) diff --git a/dlls/dbghelp/type.c b/dlls/dbghelp/type.c index 3140d30e0bc..2412994830c 100644 --- a/dlls/dbghelp/type.c +++ b/dlls/dbghelp/type.c @@ -544,6 +544,122 @@ BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll, return SymEnumTypes(hProcess, BaseOfDll, enum_types_AtoW, &et); }
+static void enum_types_of_module(struct module_pair* pair, const char* name, PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user) +{ + char buffer[sizeof(SYMBOL_INFO) + 256]; + SYMBOL_INFO* sym_info = (SYMBOL_INFO*)buffer; + struct symt* type; + DWORD64 size; + unsigned i; + const char* tname; + + sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); + sym_info->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO); + + for (i = 0; i < vector_length(&pair->effective->vtypes); i++) + { + type = *(struct symt**)vector_at(&pair->effective->vtypes, i); + tname = symt_get_name(type); + if (tname && SymMatchStringA(tname, name, TRUE)) + { + sym_info->TypeIndex = symt_ptr2index(pair->effective, type); + sym_info->Index = 0; /* FIXME */ + symt_get_info(pair->effective, type, TI_GET_LENGTH, &size); + sym_info->Size = size; + sym_info->ModBase = pair->requested->module.BaseOfImage; + sym_info->Flags = 0; /* FIXME */ + sym_info->Value = 0; /* FIXME */ + sym_info->Address = 0; /* FIXME */ + sym_info->Register = 0; /* FIXME */ + sym_info->Scope = 0; /* FIXME */ + sym_info->Tag = type->tag; + symbol_setname(sym_info, tname); + if (!cb(sym_info, sym_info->Size, user)) break; + } + } +} + +BOOL walk_modules(struct module_pair* pair) +{ + /* first walk PE only modules */ + if (!pair->requested || pair->requested->type == DMT_PE) + { + while ((pair->requested = pair->requested ? pair->requested->next : pair->pcs->lmodules) != NULL) + { + if (pair->requested->type == DMT_PE && module_get_debug(pair)) return TRUE; + } + } + /* then walk ELF or Mach-O modules, not containing PE modules */ + while ((pair->requested = pair->requested ? pair->requested->next : pair->pcs->lmodules) != NULL) + { + if ((pair->requested->type == DMT_ELF || pair->requested->type == DMT_MACHO) && + !module_get_containee(pair->pcs, pair->requested) && + module_get_debug(pair)) + return TRUE; + } + return FALSE; +} + +BOOL WINAPI SymEnumTypesByName(HANDLE proc, ULONG64 base, PCSTR name, PSYM_ENUMERATESYMBOLS_CALLBACK cb, PVOID user) +{ + struct module_pair pair; + const char* bang; + + TRACE("(%p %I64x %s %p %p)\n", proc, base, wine_dbgstr_a(name), cb, user); + + if (!name) return SymEnumTypes(proc, base, cb, user); + bang = strchr(name, '!'); + if (bang) + { + DWORD sz; + WCHAR* modW; + pair.pcs = process_find_by_handle(proc); + if (bang == name) return FALSE; + if (!pair.pcs) return FALSE; + sz = MultiByteToWideChar(CP_ACP, 0, name, bang - name, NULL, 0) + 1; + if ((modW = malloc(sz * sizeof(WCHAR))) == NULL) return FALSE; + MultiByteToWideChar(CP_ACP, 0, name, bang - name, modW, sz); + modW[sz - 1] = L'\0'; + pair.requested = NULL; + while (walk_modules(&pair)) + { + if (SymMatchStringW(pair.requested->modulename, modW, FALSE)) + enum_types_of_module(&pair, bang + 1, cb, user); + } + free(modW); + } + else + { + if (!module_init_pair(&pair, proc, base) || !module_get_debug(&pair)) return FALSE; + enum_types_of_module(&pair, name, cb, user); + } + return TRUE; +} + +BOOL WINAPI SymEnumTypesByNameW(HANDLE proc, ULONG64 base, PCWSTR nameW, PSYM_ENUMERATESYMBOLS_CALLBACKW cb, PVOID user) +{ + struct enum_types_AtoW et; + DWORD len = nameW ? WideCharToMultiByte(CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL) : 0; + char* name; + BOOL ret; + + TRACE("(%p %I64x %s %p %p)\n", proc, base, wine_dbgstr_w(nameW), cb, user); + + if (len) + { + if (!(name = malloc(len))) return FALSE; + WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, len, NULL, NULL); + } + else name = NULL; + + et.callback = cb; + et.user = user; + + ret = SymEnumTypesByName(proc, base, name, enum_types_AtoW, &et); + free(name); + return ret; +} + /****************************************************************** * symt_get_info * diff --git a/include/dbghelp.h b/include/dbghelp.h index 248b3ab418d..07fa429809a 100644 --- a/include/dbghelp.h +++ b/include/dbghelp.h @@ -1081,6 +1081,8 @@ typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO, ULONG, PVO typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACKW)(PSYMBOL_INFOW, ULONG, PVOID); BOOL WINAPI SymEnumTypes(HANDLE, ULONG64, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID); BOOL WINAPI SymEnumTypesW(HANDLE, ULONG64, PSYM_ENUMERATESYMBOLS_CALLBACKW, PVOID); +BOOL WINAPI SymEnumTypesByName(HANDLE, ULONG64, PCSTR, PSYM_ENUMERATESYMBOLS_CALLBACK, PVOID); +BOOL WINAPI SymEnumTypesByNameW(HANDLE, ULONG64, PCWSTR, PSYM_ENUMERATESYMBOLS_CALLBACKW, PVOID); BOOL WINAPI SymFromAddr(HANDLE, DWORD64, DWORD64*, SYMBOL_INFO*); BOOL WINAPI SymFromAddrW(HANDLE, DWORD64, DWORD64*, SYMBOL_INFOW*); BOOL WINAPI SymFromInlineContext(HANDLE, DWORD64, ULONG, PDWORD64, PSYMBOL_INFO);
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); }
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/dbg.y | 61 +++++++++++++++------------- programs/winedbg/debug.l | 9 ++++ programs/winedbg/debugger.h | 24 +---------- programs/winedbg/expr.c | 71 +++----------------------------- programs/winedbg/types.c | 95 +++++++++++++++++++++++-------------------- 5 files changed, 101 insertions(+), 159 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 3e6ef34b836..3fc5a87c0b5 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -42,7 +42,7 @@ static void parser(const char*); dbg_lgint_t integer; IMAGEHLP_LINE64 listing; struct expr* expression; - struct type_expr_t type; + struct dbg_type type; struct list_string* strings; }
@@ -55,6 +55,7 @@ static void parser(const char*); %token tSTEPI tNEXTI tFINISH tSHOW tDIR tWHATIS tSOURCE %token <string> tPATH tIDENTIFIER tSTRING tINTVAR %token <integer> tNUM tFORMAT +%token <type> tTYPEDEF %token tSYMBOLFILE tRUN tATTACH tDETACH tKILL tMAINTENANCE tTYPE tMINIDUMP %token tNOPROCESS
@@ -303,32 +304,38 @@ noprocess_state: ;
type_expr: - tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_char; } - | tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_int; } - | tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; } - | tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_long_int; } - | tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; } - | tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_int; } - | tLONG tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; } - | tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_long_int; } - | tSHORT tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; } - | tSHORT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_short_int; } - | tSHORT tUNSIGNED tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; } - | tSHORT tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_short_int; } - | tSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_char_int; } - | tUNSIGNED tCHAR { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_char_int; } - | tLONG tLONG tUNSIGNED tINT{ $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; } - | tLONG tLONG tUNSIGNED { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_unsigned_longlong_int; } - | tLONG tLONG tINT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; } - | tLONG tLONG { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_signed_longlong_int; } - | tFLOAT { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_short_real; } - | tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_real; } - | tLONG tDOUBLE { $$.type = type_expr_type_id; $$.deref_count = 0; $$.u.type.module = 0; $$.u.type.id = dbg_itype_long_real; } - | type_expr '*' { $$ = $1; $$.deref_count++; } - | tCLASS identifier { $$.type = type_expr_udt_class; $$.deref_count = 0; $$.u.name = $2; } - | tSTRUCT identifier { $$.type = type_expr_udt_struct; $$.deref_count = 0; $$.u.name = $2; } - | tUNION identifier { $$.type = type_expr_udt_union; $$.deref_count = 0; $$.u.name = $2; } - | tENUM identifier { $$.type = type_expr_enumeration; $$.deref_count = 0; $$.u.name = $2; } + tCHAR { $$.module = 0; $$.id = dbg_itype_char; } + | tINT { $$.module = 0; $$.id = dbg_itype_signed_int; } + | tLONG tINT { $$.module = 0; $$.id = dbg_itype_signed_long_int; } + | tLONG { $$.module = 0; $$.id = dbg_itype_signed_long_int; } + | tUNSIGNED tINT { $$.module = 0; $$.id = dbg_itype_unsigned_int; } + | tUNSIGNED { $$.module = 0; $$.id = dbg_itype_unsigned_int; } + | tLONG tUNSIGNED tINT { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; } + | tUNSIGNED tLONG tINT { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; } + | tLONG tUNSIGNED { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; } + | tUNSIGNED tLONG { $$.module = 0; $$.id = dbg_itype_unsigned_long_int; } + | tSHORT tINT { $$.module = 0; $$.id = dbg_itype_signed_short_int; } + | tSHORT { $$.module = 0; $$.id = dbg_itype_signed_short_int; } + | tSHORT tUNSIGNED tINT { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; } + | tUNSIGNED tSHORT tINT { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; } + | tSHORT tUNSIGNED { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; } + | tUNSIGNED tSHORT { $$.module = 0; $$.id = dbg_itype_unsigned_short_int; } + | tSIGNED tCHAR { $$.module = 0; $$.id = dbg_itype_signed_char_int; } + | tUNSIGNED tCHAR { $$.module = 0; $$.id = dbg_itype_unsigned_char_int; } + | tLONG tLONG tUNSIGNED tINT{ $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; } + | tLONG tLONG tUNSIGNED { $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; } + | tUNSIGNED tLONG tLONG { $$.module = 0; $$.id = dbg_itype_unsigned_longlong_int; } + | tLONG tLONG tINT { $$.module = 0; $$.id = dbg_itype_signed_longlong_int; } + | tLONG tLONG { $$.module = 0; $$.id = dbg_itype_signed_longlong_int; } + | tFLOAT { $$.module = 0; $$.id = dbg_itype_short_real; } + | tDOUBLE { $$.module = 0; $$.id = dbg_itype_real; } + | tLONG tDOUBLE { $$.module = 0; $$.id = dbg_itype_long_real; } + | tTYPEDEF { $$ = $1; } + | type_expr '*' { if (!types_find_pointer(&$1, &$$)) {yyerror("Cannot find pointer type\n"); YYERROR; } } + | tCLASS identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } } + | tSTRUCT identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } } + | tUNION identifier { if (!types_find_type($2, SymTagUDT, &$$)) {yyerror("Unknown type\n"); YYERROR; } } + | tENUM identifier { if (!types_find_type($2, SymTagEnum, &$$)) {yyerror("Unknown type\n"); YYERROR; } } ;
expr_lvalue: diff --git a/programs/winedbg/debug.l b/programs/winedbg/debug.l index 280013799c9..eea31f30c97 100644 --- a/programs/winedbg/debug.l +++ b/programs/winedbg/debug.l @@ -88,6 +88,13 @@ static char* unescape_string(const char* str) return ret; }
+static int resolve_identifier(const char* id, YYSTYPE* lval) +{ + if (types_find_type(id, SymTagTypedef, &lval->type)) return tTYPEDEF; + lval->string = lexeme_alloc(id); + return tIDENTIFIER; +} + #define YY_INPUT(buf,result,max_size) \ (result = input_lex_read_buffer(buf, max_size))
@@ -244,7 +251,7 @@ union { return tUNION; } enum { return tENUM; } all { return tALL; }
-{MODULE_IDENTIFIER}?{SCOPED_IDENTIFIER}*{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext); return tIDENTIFIER; } +{MODULE_IDENTIFIER}?{SCOPED_IDENTIFIER}*{IDENTIFIER} { return resolve_identifier(yytext, &dbg_lval); } "$"{IDENTIFIER} { dbg_lval.string = lexeme_alloc(yytext+1); return tINTVAR; }
<PATH_EXPECTED,PATH_ACCEPTED>{PATHNAME} { dbg_lval.string = lexeme_alloc(yytext); return tPATH; } diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index a29b731017f..6bc6d8a1954 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -297,26 +297,6 @@ struct dbg_internal_var
enum sym_get_lval {sglv_found, sglv_unknown, sglv_aborted};
-enum type_expr_e -{ - type_expr_type_id, - type_expr_udt_class, - type_expr_udt_struct, - type_expr_udt_union, - type_expr_enumeration -}; - -struct type_expr_t -{ - enum type_expr_e type; - unsigned deref_count; - union - { - struct dbg_type type; - const char* name; - } u; -}; - enum dbg_start {start_ok, start_error_parse, start_error_init};
/* break.c */ @@ -372,7 +352,7 @@ extern struct expr* expr_alloc_unary_op(int oper, struct expr*); extern struct expr* expr_alloc_pstruct(struct expr*, const char* element); extern struct expr* expr_alloc_struct(struct expr*, const char* element); extern struct expr* WINAPIV expr_alloc_func_call(const char*, int nargs, ...); -extern struct expr* expr_alloc_typecast(struct type_expr_t*, struct expr*); +extern struct expr* expr_alloc_typecast(struct dbg_type*, struct expr*); extern struct dbg_lvalue expr_eval(struct expr*); extern struct expr* expr_clone(const struct expr* exp, BOOL *local_binding); extern BOOL expr_free(struct expr* exp); @@ -499,7 +479,7 @@ extern BOOL types_get_info(const struct dbg_type*, IMAGEHLP_SYMBOL_T 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 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_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* type); extern BOOL types_compare(const struct dbg_type, const struct dbg_type, BOOL* equal); extern BOOL types_is_integral_type(const struct dbg_lvalue*); extern BOOL types_is_float_type(const struct dbg_lvalue*); diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c index bd48e3e868f..7a7c2013578 100644 --- a/programs/winedbg/expr.c +++ b/programs/winedbg/expr.c @@ -75,7 +75,7 @@ struct expr
struct { - struct type_expr_t cast_to; + struct dbg_type cast_to; struct expr* expr; } cast;
@@ -128,14 +128,14 @@ void expr_free_all(void) next_expr_free = 0; }
-struct expr* expr_alloc_typecast(struct type_expr_t* tet, struct expr* exp) +struct expr* expr_alloc_typecast(struct dbg_type* type, struct expr* exp) { struct expr* ex;
ex = expr_alloc();
ex->type = EXPR_TYPE_CAST; - ex->un.cast.cast_to = *tet; + ex->un.cast.cast_to = *type; ex->un.cast.expr = exp; return ex; } @@ -272,7 +272,6 @@ struct expr* WINAPIV expr_alloc_func_call(const char* funcname, int nargs, ...) struct dbg_lvalue expr_eval(struct expr* exp) { struct dbg_lvalue rtn; - int i; struct dbg_lvalue exp1; struct dbg_lvalue exp2; DWORD64 scale1, scale2, scale3; @@ -285,52 +284,11 @@ struct dbg_lvalue expr_eval(struct expr* exp) switch (exp->type) { case EXPR_TYPE_CAST: - /* this is really brute force, we simply change the type... without + /* this is really brute force, we simply change the type... without * checking if this is right or not */ rtn = expr_eval(exp->un.cast.expr); - switch (exp->un.cast.cast_to.type) - { - case type_expr_type_id: - if (exp->un.cast.cast_to.u.type.id == dbg_itype_none) - { - dbg_printf("Can't cast to unknown type\n"); - RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - } - rtn.type = exp->un.cast.cast_to.u.type; - break; - case type_expr_udt_class: - case type_expr_udt_struct: - case type_expr_udt_union: - rtn.type = types_find_type(rtn.type.module, exp->un.cast.cast_to.u.name, - SymTagUDT); - if (rtn.type.id == dbg_itype_none) - { - dbg_printf("Can't cast to UDT %s\n", exp->un.cast.cast_to.u.name); - RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - } - break; - case type_expr_enumeration: - rtn.type = types_find_type(rtn.type.module, exp->un.cast.cast_to.u.name, - SymTagEnum); - if (rtn.type.id == dbg_itype_none) - { - dbg_printf("Can't cast to enumeration %s\n", exp->un.cast.cast_to.u.name); - RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - } - break; - default: - dbg_printf("Unsupported cast type %u\n", exp->un.cast.cast_to.type); - RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - } - for (i = 0; i < exp->un.cast.cast_to.deref_count; i++) - { - if (!types_find_pointer(&rtn.type, &rtn.type)) - { - dbg_printf("Cannot find pointer type\n"); - RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); - } - } + rtn.type = exp->un.cast.cast_to; break; case EXPR_TYPE_STRING: init_lvalue_in_debugger(&rtn, dbg_itype_astring, &exp->un.string.str); @@ -626,30 +584,13 @@ struct dbg_lvalue expr_eval(struct expr* exp) BOOL expr_print(const struct expr* exp) { int i; - struct dbg_type type;
switch (exp->type) { case EXPR_TYPE_CAST: WINE_FIXME("No longer supported (missing module base)\n"); dbg_printf("(("); - switch (exp->un.cast.cast_to.type) - { - case type_expr_type_id: - type.module = 0; - type.id = exp->un.cast.cast_to.type; - types_print_type(&type, FALSE); break; - case type_expr_udt_class: - dbg_printf("class %s", exp->un.cast.cast_to.u.name); break; - case type_expr_udt_struct: - dbg_printf("struct %s", exp->un.cast.cast_to.u.name); break; - case type_expr_udt_union: - dbg_printf("union %s", exp->un.cast.cast_to.u.name); break; - case type_expr_enumeration: - dbg_printf("enum %s", exp->un.cast.cast_to.u.name); break; - } - for (i = 0; i < exp->un.cast.cast_to.deref_count; i++) - dbg_printf("*"); + types_print_type(&exp->un.cast.cast_to, FALSE); dbg_printf(")"); expr_print(exp->un.cast.expr); dbg_printf(")"); diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 5633201d2fe..af0fd8806c6 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -324,39 +324,6 @@ BOOL types_array_index(const struct dbg_lvalue* lvalue, int index, struct dbg_lv return TRUE; }
-struct type_find_t -{ - ULONG result; /* out: the found type */ - enum SymTagEnum tag; /* in: the tag to look for */ - union - { - ULONG typeid; /* when tag is SymTagUDT */ - const char* name; /* when tag is SymTagPointerType */ - } u; -}; - -static BOOL CALLBACK types_cb(PSYMBOL_INFO sym, ULONG size, void* _user) -{ - struct type_find_t* user = _user; - BOOL ret = TRUE; - - if (sym->Tag == user->tag) - { - switch (user->tag) - { - case SymTagUDT: - if (!strcmp(user->u.name, sym->Name)) - { - user->result = sym->TypeIndex; - ret = FALSE; - } - break; - default: break; - } - } - return ret; -} - /****************************************************************** * types_find_pointer * @@ -396,25 +363,65 @@ BOOL types_find_pointer(const struct dbg_type* type, struct dbg_type* ret) return TRUE; }
+struct type_find_type_t +{ + enum SymTagEnum tag; /* in: the tag to look for */ + struct dbg_type found; /* out: the found type */ + unsigned count; /* out: incremented at each different type */ +}; + +static BOOL CALLBACK find_type_cb(PSYMBOL_INFO sym, ULONG size, void* _user) +{ + struct type_find_type_t* f = _user; + if (sym->Tag == f->tag) + { + if (f->found.id == dbg_itype_none) + { + f->found.module = sym->ModBase; + f->found.id = sym->TypeIndex; + } + else + { + /* potential conflict */ + struct dbg_type alt; + BOOL equal; + alt.module = sym->ModBase; + alt.id = sym->TypeIndex; + if (!types_compare(f->found, alt, &equal) || !equal) + f->count++; + } + } + return TRUE; +} + /****************************************************************** * types_find_type * - * Should look up in the module based at linear address whether a type - * named 'name' and with the correct tag exists */ -struct dbg_type types_find_type(DWORD64 linear, const char* name, enum SymTagEnum tag) +BOOL types_find_type(const char* name, enum SymTagEnum tag, struct dbg_type* type)
{ - struct type_find_t f; - struct dbg_type ret; + struct type_find_type_t f; + char* ptr;
- f.result = dbg_itype_none; + if (!strchr(name, '!')) + { + ptr = malloc(2 + strlen(name) + 1); + if (!ptr) return FALSE; + strcpy(ptr, "*!"); + strcat(ptr, name); + } + else ptr = NULL; f.tag = tag; - f.u.name = name; - SymEnumTypes(dbg_curr_process->handle, linear, types_cb, &f); - ret.module = linear; - ret.id = f.result; - return ret; + f.found.id = dbg_itype_none; + f.count = 0; + SymEnumTypesByName(dbg_curr_process->handle, 0, ptr ? ptr : name, find_type_cb, &f); + free(ptr); + if (f.found.id == dbg_itype_none) return FALSE; + /* FIXME report different types (f.count != 0) */ + *type = f.found; + + return TRUE; }
/***********************************************************************
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/dbg.y | 1 + programs/winedbg/types.c | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 3fc5a87c0b5..b10f50a3d6a 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -222,6 +222,7 @@ x_command: print_command: tPRINT expr_lvalue { print_value(&$2, 0, 0); } | tPRINT tFORMAT expr_lvalue { if (($2 >> 8) == 1) print_value(&$3, $2 & 0xff, 0); else dbg_printf("Count is meaningless in print command\n"); } + | tPRINT type_expr { types_print_type(&$2, TRUE); dbg_printf("\n"); } ;
break_command: diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index af0fd8806c6..70fcada494e 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -594,7 +594,8 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) { WCHAR* ptr; const WCHAR* name; - DWORD tag, udt, count; + DWORD tag, udt, count, bitoffset; + DWORD64 bitlen; struct dbg_type subtype;
if (type->id == dbg_itype_none || !types_get_info(type, TI_GET_SYMTAG, &tag)) @@ -608,7 +609,7 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) switch (tag) { case SymTagBaseType: - if (details) dbg_printf("Basic<%ls>", name); else dbg_printf("%ls", name); + dbg_printf("%ls", name); break; case SymTagPointerType: types_get_type(type, &subtype); @@ -645,14 +646,19 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) type_elt.module = type->module; type_elt.id = fcp->ChildId[i]; 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_BITPOSITION, &bitoffset) || + !types_get_info(&type_elt, TI_GET_LENGTH, &bitlen)) + bitlen = ~(DWORD64)0; if (types_get_type(&type_elt, &type_elt)) { - dbg_printf(":"); types_print_type(&type_elt, details); } - if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(", "); + dbg_printf(" %ls", ptr); + HeapFree(GetProcessHeap(), 0, ptr); + if (bitlen != ~(DWORD64)0) + dbg_printf(" : %I64u", bitlen); + dbg_printf(";"); + if (i < min(fcp->Count, count) - 1 || count > 256) dbg_printf(" "); } } count -= min(count, 256); @@ -709,7 +715,12 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) dbg_printf(")"); break; case SymTagTypedef: - dbg_printf("%ls", name); + if (details && types_get_type(type, &subtype)) + { + dbg_printf("typedef %ls => ", name); + types_print_type(&subtype, FALSE); + } + else dbg_printf("%ls", name); break; default: WINE_ERR("Unknown type %u for %ls\n", tag, name);
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/types.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/programs/winedbg/types.c b/programs/winedbg/types.c index 87380487ea2..a5e77c1d5bc 100644 --- a/programs/winedbg/types.c +++ b/programs/winedbg/types.c @@ -604,7 +604,8 @@ BOOL types_print_type(const struct dbg_type* type, BOOL details) return FALSE; }
- name = (types_get_info(type, TI_GET_SYMNAME, &ptr) && ptr) ? ptr : L"--none--"; + if (!types_get_info(type, TI_GET_SYMNAME, &ptr)) ptr = NULL; + name = ptr ? ptr : L"--none--";
switch (tag) {
(simply use DEREF unary op)
Signed-off-by: Eric Pouech eric.pouech@gmail.com
--- programs/winedbg/dbg.y | 2 +- programs/winedbg/expr.c | 5 ----- programs/winedbg/expr.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-)
diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index b10f50a3d6a..d14ae1c399a 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -411,7 +411,7 @@ lvalue: | lvalue OP_DRF tIDENTIFIER { $$ = expr_alloc_pstruct($1, $3); } | lvalue '.' tIDENTIFIER { $$ = expr_alloc_struct($1, $3); } | lvalue '[' expr ']' { $$ = expr_alloc_binary_op(EXP_OP_ARR, $1, $3); } - | '*' expr { $$ = expr_alloc_unary_op(EXP_OP_FORCE_DEREF, $2); } + | '*' expr { $$ = expr_alloc_unary_op(EXP_OP_DEREF, $2); } ;
%% diff --git a/programs/winedbg/expr.c b/programs/winedbg/expr.c index 7a7c2013578..0b5b1c544f3 100644 --- a/programs/winedbg/expr.c +++ b/programs/winedbg/expr.c @@ -556,11 +556,6 @@ struct dbg_lvalue expr_eval(struct expr* exp) if (!types_array_index(&exp1, 0, &rtn)) RaiseException(DEBUG_STATUS_BAD_TYPE, 0, 0, NULL); break; - case EXP_OP_FORCE_DEREF: - rtn = exp1; - if (exp1.in_debuggee) - dbg_read_memory(memory_to_linear_addr(&exp1.addr), &rtn.addr.Offset, sizeof(rtn.addr.Offset)); - break; case EXP_OP_ADDR: /* only do it on linear addresses */ if (exp1.addr.Mode != AddrModeFlat) diff --git a/programs/winedbg/expr.h b/programs/winedbg/expr.h index 295543ec292..24303a4a562 100644 --- a/programs/winedbg/expr.h +++ b/programs/winedbg/expr.h @@ -41,4 +41,3 @@ #define EXP_OP_ADDR 0x27 #define EXP_OP_ARR 0x28 #define EXP_OP_SEG 0x29 -#define EXP_OP_FORCE_DEREF 0x2a