diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index d7ea3c968a0..6c7cde377f4 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -395,6 +395,12 @@ extern void symbol_info(const char* str); extern void symbol_print_local(const SYMBOL_INFO* sym, ULONG base, BOOL detailed); extern int symbol_info_locals(void); extern BOOL symbol_is_local(const char* name); +struct sgv_data; +typedef enum sym_get_lval (*symbol_picker_t)(const char* name, const struct sgv_data* sgv, + struct dbg_lvalue* rtn); +extern symbol_picker_t symbol_current_picker; +extern enum sym_get_lval symbol_picker_interactive(const char* name, const struct sgv_data* sgv, + struct dbg_lvalue* rtn); /* tgt_active.c */ extern void dbg_run_debuggee(const char* args); diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index b4b04e62e1a..56f814bf0e2 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -192,6 +192,67 @@ static BOOL CALLBACK sgv_cb(PSYMBOL_INFO sym, ULONG size, PVOID ctx) return TRUE; } +enum sym_get_lval symbol_picker_interactive(const char* name, const struct sgv_data* sgv, + struct dbg_lvalue* rtn) +{ + char buffer[512]; + unsigned i; + + if (!dbg_interactiveP) + { + dbg_printf("More than one symbol named %s, picking the first one\n", name); + *rtn = sgv->syms[0].lvalue; + return sglv_found; + } + + dbg_printf("Many symbols with name '%s', " + "choose the one you want ( to abort):\n", name); + for (i = 0; i < sgv->num; i++) + { + if (sgv->num - sgv->num_thunks > 1 && (sgv->syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) + continue; + dbg_printf("[%d]: ", i + 1); + if (sgv->syms[i].flags & SYMFLAG_LOCAL) + { + dbg_printf("%s %sof %s\n", + sgv->syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", + sgv->syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", + name); + } + else if (sgv->syms[i].flags & SYMFLAG_THUNK) + { + print_address(&sgv->syms[i].lvalue.addr, TRUE); + /* FIXME: should display where the thunks points to */ + dbg_printf(" thunk %s\n", name); + } + else + { + print_address(&sgv->syms[i].lvalue.addr, TRUE); + dbg_printf("\n"); + } + } + do + { + i = 0; + if (input_read_line("=> ", buffer, sizeof(buffer))) + { + if (buffer[0] == '\0') return sglv_aborted; + i = atoi(buffer); + if (i < 1 || i > sgv->num) + dbg_printf("Invalid choice %d\n", i); + } + else return sglv_aborted; + } while (i < 1 || i > sgv->num); + + /* The array is 0-based, but the choices are 1..n, + * so we have to subtract one before returning. + */ + *rtn = sgv->syms[i - 1].lvalue; + return sglv_found; +} + +symbol_picker_t symbol_current_picker = symbol_picker_interactive; + /*********************************************************************** * symbol_get_lvalue * @@ -317,65 +378,17 @@ enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, } } - i = 0; - if (dbg_interactiveP) + if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ + (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ + (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) { - if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */ - (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */ - (sgv.num == sgv.num_thunks && sgv.num_thunks > 1)) - { - dbg_printf("Many symbols with name '%s', " - "choose the one you want ( to abort):\n", name); - for (i = 0; i < sgv.num; i++) - { - if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks)) - continue; - dbg_printf("[%d]: ", i + 1); - if (sgv.syms[i].flags & SYMFLAG_LOCAL) - { - dbg_printf("%s %sof %s\n", - sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable", - sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "", - name); - } - else if (sgv.syms[i].flags & SYMFLAG_THUNK) - { - print_address(&sgv.syms[i].lvalue.addr, TRUE); - /* FIXME: should display where the thunks points to */ - dbg_printf(" thunk %s\n", name); - } - else - { - print_address(&sgv.syms[i].lvalue.addr, TRUE); - dbg_printf("\n"); - } - } - do - { - i = 0; - if (input_read_line("=> ", buffer, sizeof(buffer))) - { - if (buffer[0] == '\0') return sglv_aborted; - i = atoi(buffer); - if (i < 1 || i > sgv.num) - dbg_printf("Invalid choice %d\n", i); - } - else return sglv_aborted; - } while (i < 1 || i > sgv.num); - - /* The array is 0-based, but the choices are 1..n, - * so we have to subtract one before returning. - */ - i--; - } + return symbol_current_picker(name, &sgv, rtn); } - else - { - /* FIXME: could display the list of non-picked up symbols */ - if (sgv.num > 1) - dbg_printf("More than one symbol named %s, picking the first one\n", name); - } - *rtn = sgv.syms[i].lvalue; + /* first symbol is the one we want: + * - only one symbol found, + * - or many symbols but only one non thunk when AlwaysShowThunks is FALSE + */ + *rtn = sgv.syms[0].lvalue; return sglv_found; }