Module: wine Branch: master Commit: d6d8682d711d5f1500832f5c5095f4df85a06c2f URL: http://source.winehq.org/git/wine.git/?a=commit;h=d6d8682d711d5f1500832f5c50... Author: Eric Pouech <eric.pouech(a)wanadoo.fr> Date: Sat Dec 2 17:43:08 2006 +0100 winedbg: Added some black magic to still handle register values on non current frame for some of the registers we know of (frame pointer, stack pointer). --- programs/winedbg/be_alpha.c | 7 +++++++ programs/winedbg/be_cpu.h | 4 ++++ programs/winedbg/be_i386.c | 12 ++++++++++++ programs/winedbg/be_ppc.c | 7 +++++++ programs/winedbg/be_x86_64.c | 13 +++++++++++++ programs/winedbg/debugger.h | 5 +++++ programs/winedbg/memory.c | 18 ++++++++++++------ programs/winedbg/stack.c | 35 +++++++++++++++++++++++++++++++---- 8 files changed, 91 insertions(+), 10 deletions(-) diff --git a/programs/winedbg/be_alpha.c b/programs/winedbg/be_alpha.c index 6bc9cd8..e3072ae 100644 --- a/programs/winedbg/be_alpha.c +++ b/programs/winedbg/be_alpha.c @@ -29,6 +29,12 @@ static unsigned be_alpha_get_addr(HANDLE return FALSE; } +static unsigned be_alpha_get_register_info(int regno, enum be_cpu_addr* kind) +{ + dbg_printf("not done\n"); + return FALSE; +} + static void be_alpha_single_step(CONTEXT* ctx, unsigned enable) { dbg_printf("not done\n"); @@ -148,6 +154,7 @@ struct backend_cpu be_alpha = be_cpu_linearize, be_cpu_build_addr, be_alpha_get_addr, + be_alpha_get_register_info, be_alpha_single_step, be_alpha_print_context, be_alpha_print_segment_info, diff --git a/programs/winedbg/be_cpu.h b/programs/winedbg/be_cpu.h index 4111dff..db3e0cd 100644 --- a/programs/winedbg/be_cpu.h +++ b/programs/winedbg/be_cpu.h @@ -43,6 +43,10 @@ struct backend_cpu */ unsigned (*get_addr)(HANDLE hThread, const CONTEXT* ctx, enum be_cpu_addr, ADDRESS64* addr); + + /* returns which kind of information a given register number refers to */ + unsigned (*get_register_info)(int regno, enum be_cpu_addr* kind); + /* ------------------------------------------------------------------------------- * context manipulation * ------------------------------------------------------------------------------- */ diff --git a/programs/winedbg/be_i386.c b/programs/winedbg/be_i386.c index dc8f824..f15121d 100644 --- a/programs/winedbg/be_i386.c +++ b/programs/winedbg/be_i386.c @@ -111,6 +111,17 @@ static unsigned be_i386_get_addr(HANDLE return FALSE; } +static unsigned be_i386_get_register_info(int regno, enum be_cpu_addr* kind) +{ + switch (regno) + { + case CV_REG_EIP: *kind = be_cpu_addr_pc; return TRUE; + case CV_REG_EBP: *kind = be_cpu_addr_frame; return TRUE; + case CV_REG_ESP: *kind = be_cpu_addr_stack; return TRUE; + } + return FALSE; +} + static void be_i386_single_step(CONTEXT* ctx, unsigned enable) { if (enable) ctx->EFlags |= STEP_FLAG; @@ -739,6 +750,7 @@ struct backend_cpu be_i386 = be_i386_linearize, be_i386_build_addr, be_i386_get_addr, + be_i386_get_register_info, be_i386_single_step, be_i386_print_context, be_i386_print_segment_info, diff --git a/programs/winedbg/be_ppc.c b/programs/winedbg/be_ppc.c index 24e75e5..2e8826e 100644 --- a/programs/winedbg/be_ppc.c +++ b/programs/winedbg/be_ppc.c @@ -38,6 +38,12 @@ static unsigned be_ppc_get_addr(HANDLE h return FALSE; } +static unsigned be_ppc_get_register_info(int regno, enum be_cpu_addr* kind) +{ + dbg_printf("not done\n"); + return FALSE; +} + static void be_ppc_single_step(CONTEXT* ctx, unsigned enable) { #ifndef MSR_SE @@ -172,6 +178,7 @@ struct backend_cpu be_ppc = be_cpu_linearize, be_cpu_build_addr, be_ppc_get_addr, + be_ppc_get_register_info, be_ppc_single_step, be_ppc_print_context, be_ppc_print_segment_info, diff --git a/programs/winedbg/be_x86_64.c b/programs/winedbg/be_x86_64.c index 9a40a8c..3400f72 100644 --- a/programs/winedbg/be_x86_64.c +++ b/programs/winedbg/be_x86_64.c @@ -46,6 +46,18 @@ static unsigned be_x86_64_get_addr(HANDL } } +static unsigned be_x86_64_get_register_info(int regno, enum be_cpu_addr* kind) +{ + /* this is true when running in 32bit mode... and wrong in 64 :-/ */ + switch (regno) + { + case CV_AMD64_EIP: *kind = be_cpu_addr_pc; return TRUE; + case CV_AMD64_EBP: *kind = be_cpu_addr_frame; return TRUE; + case CV_AMD64_ESP: *kind = be_cpu_addr_stack; return TRUE; + } + return FALSE; +} + static void be_x86_64_single_step(CONTEXT* ctx, unsigned enable) { dbg_printf("not done single_step\n"); @@ -210,6 +222,7 @@ struct backend_cpu be_x86_64 = be_cpu_linearize, be_cpu_build_addr, be_x86_64_get_addr, + be_x86_64_get_register_info, be_x86_64_single_step, be_x86_64_print_context, be_x86_64_print_segment_info, diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 67b84ba..43abb60 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -176,6 +176,10 @@ struct dbg_thread { ADDRESS64 addr_pc; ADDRESS64 addr_frame; + ADDRESS64 addr_stack; + DWORD linear_pc; + DWORD linear_frame; + DWORD linear_stack; }* frames; int num_frames; int curr_frame; @@ -361,6 +365,7 @@ extern void stack_info(void) extern void stack_backtrace(DWORD threadID); extern BOOL stack_set_frame(int newframe); extern BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf); +extern BOOL stack_get_register_current_frame(unsigned regno, DWORD** pval); extern unsigned stack_fetch_frames(void); extern BOOL stack_get_current_symbol(SYMBOL_INFO* sym); diff --git a/programs/winedbg/memory.c b/programs/winedbg/memory.c index d4fb7c3..01d3da0 100644 --- a/programs/winedbg/memory.c +++ b/programs/winedbg/memory.c @@ -636,16 +636,22 @@ BOOL memory_get_register(DWORD regno, DW if (buffer) snprintf(buffer, len, "<couldn't read memory>"); return FALSE; } - if (dbg_curr_thread->curr_frame != 0) - { - if (buffer) snprintf(buffer, len, "<register not in topmost frame>"); - return FALSE; - } + for (div = dbg_context_vars; div->name; div++) { if (div->val == regno) { - *value = div->pval; + if (dbg_curr_thread->curr_frame != 0) + { + if (!stack_get_register_current_frame(regno, value)) + { + if (buffer) snprintf(buffer, len, "<register %s not in topmost frame>", div->name); + return FALSE; + } + } + else + *value = div->pval; + snprintf(buffer, len, div->name); return TRUE; } diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index 527ed03..c279014 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -82,8 +82,8 @@ static BOOL stack_set_frame_internal(int static BOOL stack_get_frame(int nf, IMAGEHLP_STACK_FRAME* ihsf) { memset(ihsf, 0, sizeof(*ihsf)); - ihsf->InstructionOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[nf].addr_pc); - ihsf->FrameOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[nf].addr_frame); + ihsf->InstructionOffset = dbg_curr_thread->frames[nf].linear_pc; + ihsf->FrameOffset = dbg_curr_thread->frames[nf].linear_frame; return TRUE; } @@ -96,6 +96,29 @@ BOOL stack_get_current_frame(IMAGEHLP_ST return stack_get_frame(dbg_curr_thread->curr_frame, ihsf); } +BOOL stack_get_register_current_frame(unsigned regno, DWORD** pval) +{ + enum be_cpu_addr kind; + + if (dbg_curr_thread->frames == NULL) return FALSE; + + if (!be_cpu->get_register_info(regno, &kind)) return FALSE; + + switch (kind) + { + case be_cpu_addr_pc: + *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_pc; + break; + case be_cpu_addr_stack: + *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_stack; + break; + case be_cpu_addr_frame: + *pval = &dbg_curr_thread->frames[dbg_curr_thread->curr_frame].linear_frame; + break; + } + return TRUE; +} + BOOL stack_set_frame(int newframe) { ADDRESS64 addr; @@ -170,8 +193,12 @@ unsigned stack_fetch_frames(void) dbg_curr_thread->frames = dbg_heap_realloc(dbg_curr_thread->frames, (nf + 1) * sizeof(dbg_curr_thread->frames[0])); - dbg_curr_thread->frames[nf].addr_pc = sf.AddrPC; - dbg_curr_thread->frames[nf].addr_frame = sf.AddrFrame; + dbg_curr_thread->frames[nf].addr_pc = sf.AddrPC; + dbg_curr_thread->frames[nf].linear_pc = (DWORD)memory_to_linear_addr(&sf.AddrPC); + dbg_curr_thread->frames[nf].addr_frame = sf.AddrFrame; + dbg_curr_thread->frames[nf].linear_frame = (DWORD)memory_to_linear_addr(&sf.AddrFrame); + dbg_curr_thread->frames[nf].addr_stack = sf.AddrStack; + dbg_curr_thread->frames[nf].linear_stack = (DWORD)memory_to_linear_addr(&sf.AddrStack); nf++; /* we've probably gotten ourselves into an infinite loop so bail */ if (nf > 200) break;