From 3e07e047648e061dfa3ff4665d5b31a6c8a7c051 Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Fri, 18 Nov 2005 12:33:03 +0000 Subject: [PATCH] - now storing frames information in thread structure - frames are cached after each thread stops execution - reimplemented backtrace on top of this --- programs/winedbg/dbg.y | 16 ++--- programs/winedbg/debugger.h | 14 ++++- programs/winedbg/stack.c | 118 +++++++++++++++++++++++------------- programs/winedbg/symbol.c | 4 +- programs/winedbg/winedbg.c | 11 ++-- 5 files changed, 104 insertions(+), 59 deletions(-) diff --git a/programs/winedbg/dbg.y b/programs/winedbg/dbg.y index 523855ad46..58162029a8 100644 --- a/programs/winedbg/dbg.y +++ b/programs/winedbg/dbg.y @@ -120,13 +120,13 @@ command: | tNEXTI tNUM { dbg_wait_next_exception(DBG_CONTINUE, $2, dbg_exec_step_over_insn); } | tFINISH { dbg_wait_next_exception(DBG_CONTINUE, 0, dbg_exec_finish); } | tABORT { abort(); } - | tBACKTRACE { stack_backtrace(dbg_curr_tid, TRUE); } - | tBACKTRACE tNUM { stack_backtrace($2, TRUE); } - | tBACKTRACE tALL { stack_backtrace(-1, TRUE); } - | tUP { stack_set_frame(dbg_curr_frame + 1); } - | tUP tNUM { stack_set_frame(dbg_curr_frame + $2); } - | tDOWN { stack_set_frame(dbg_curr_frame - 1); } - | tDOWN tNUM { stack_set_frame(dbg_curr_frame - $2); } + | tBACKTRACE { stack_backtrace(dbg_curr_tid); } + | tBACKTRACE tNUM { stack_backtrace($2); } + | tBACKTRACE tALL { stack_backtrace(-1); } + | tUP { stack_set_frame(dbg_curr_thread->curr_frame + 1); } + | tUP tNUM { stack_set_frame(dbg_curr_thread->curr_frame + $2); } + | tDOWN { stack_set_frame(dbg_curr_thread->curr_frame - 1); } + | tDOWN tNUM { stack_set_frame(dbg_curr_thread->curr_frame - $2); } | tFRAME tNUM { stack_set_frame($2); } | tSHOW tDIR { source_show_path(); } | tDIR pathname { source_add_path($2); } @@ -276,7 +276,7 @@ maintenance_command: noprocess_state: tNOPROCESS {} /* shall not barf anything */ - | tNOPROCESS tBACKTRACE tALL { stack_backtrace(-1, TRUE); } /* can backtrace all threads with no attached process */ + | tNOPROCESS tBACKTRACE tALL { stack_backtrace(-1); } /* can backtrace all threads with no attached process */ | tNOPROCESS tSTRING { dbg_printf("No process loaded, cannot execute '%s'\n", $2); } ; diff --git a/programs/winedbg/debugger.h b/programs/winedbg/debugger.h index 76d0fb34bd..262549360c 100644 --- a/programs/winedbg/debugger.h +++ b/programs/winedbg/debugger.h @@ -168,6 +168,13 @@ struct dbg_thread struct dbg_thread* prev; BOOL in_exception; /* TRUE if thread stopped with an exception */ EXCEPTION_RECORD excpt_record; /* only valid when in_exception is TRUE */ + struct + { + ADDRESS addr_pc; + ADDRESS addr_frame; + }* frames; + int num_frames; + int curr_frame; }; struct dbg_delayed_bp @@ -214,7 +221,6 @@ extern struct dbg_thread* dbg_curr_thread; extern DWORD dbg_curr_tid; extern CONTEXT dbg_context; extern BOOL dbg_interactiveP; -extern int dbg_curr_frame; struct dbg_internal_var { @@ -339,9 +345,11 @@ extern void source_nuke_path(void); /* stack.c */ extern void stack_info(void); -extern void stack_backtrace(DWORD threadID, BOOL noisy); -extern int stack_set_frame(int newframe); +extern void stack_backtrace(DWORD threadID); +extern BOOL stack_set_frame(int newframe); extern BOOL stack_get_frame(SYMBOL_INFO* sym, IMAGEHLP_STACK_FRAME* ihsf); +extern BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf); +extern unsigned stack_fetch_frames(void); /* symbol.c */ extern enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno, struct dbg_lvalue* addr, BOOL bp_disp); diff --git a/programs/winedbg/stack.c b/programs/winedbg/stack.c index b080f0ba0d..6f3b93f7cd 100644 --- a/programs/winedbg/stack.c +++ b/programs/winedbg/stack.c @@ -33,9 +33,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(winedbg); -static int nframe; -static IMAGEHLP_STACK_FRAME* frames = NULL; - /*********************************************************************** * stack_info * @@ -67,16 +64,41 @@ void stack_info(void) } } -int stack_set_frame(int newframe) +static BOOL stack_set_frame_internal(int newframe) { - ADDRESS addr; + if (newframe >= dbg_curr_thread->num_frames) + newframe = dbg_curr_thread->num_frames - 1; + if (newframe < 0) + newframe = 0; - dbg_curr_frame = newframe; - if (dbg_curr_frame >= nframe) dbg_curr_frame = nframe - 1; - if (dbg_curr_frame < 0) dbg_curr_frame = 0; + if (dbg_curr_thread->curr_frame != newframe) + { + IMAGEHLP_STACK_FRAME ihsf; + dbg_curr_thread->curr_frame = newframe; + stack_get_current_frame(&ihsf); + SymSetContext(dbg_curr_process->handle, &ihsf, NULL); + } + return TRUE; +} + +BOOL stack_get_current_frame(IMAGEHLP_STACK_FRAME* ihsf) +{ + /* + * If we don't have a valid backtrace, then just return. + */ + if (dbg_curr_thread->frames == NULL) return FALSE; + ihsf->InstructionOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_pc); + ihsf->FrameOffset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_frame); + return TRUE; +} + +BOOL stack_set_frame(int newframe) +{ + ADDRESS addr; + if (!stack_set_frame_internal(newframe)) return FALSE; addr.Mode = AddrModeFlat; - addr.Offset = frames[dbg_curr_frame].InstructionOffset; + addr.Offset = (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_pc); source_list_from_addr(&addr, 0); return TRUE; } @@ -87,30 +109,36 @@ BOOL stack_get_frame(SYMBOL_INFO* symbol, IMAGEHLP_STACK_FRAME* ihsf) /* * If we don't have a valid backtrace, then just return. */ - if (frames == NULL) return FALSE; + if (dbg_curr_thread->frames == NULL) return FALSE; /* * If we don't know what the current function is, then we also have * nothing to report here. */ - if (!SymFromAddr(dbg_curr_process->handle, frames[dbg_curr_frame].InstructionOffset, + if (!SymFromAddr(dbg_curr_process->handle, + (unsigned long)memory_to_linear_addr(&dbg_curr_thread->frames[dbg_curr_thread->curr_frame].addr_pc), &disp, symbol)) return FALSE; - if (ihsf) *ihsf = frames[dbg_curr_frame]; + if (ihsf && !stack_get_current_frame(ihsf)) return FALSE; return TRUE; } /****************************************************************** - * backtrace + * stack_fetch_frames * * Do a backtrace on the the current thread */ -static unsigned backtrace(BOOL with_frames, BOOL noisy) +unsigned stack_fetch_frames(void) { STACKFRAME sf; unsigned nf = 0; + HeapFree(GetProcessHeap(), 0, dbg_curr_thread->frames); + dbg_curr_thread->frames = NULL; + dbg_curr_thread->num_frames = 0; + dbg_curr_thread->curr_frame = 0; + memset(&sf, 0, sizeof(sf)); memory_get_current_frame(&sf.AddrFrame); memory_get_current_pc(&sf.AddrPC); @@ -122,33 +150,41 @@ static unsigned backtrace(BOOL with_frames, BOOL noisy) sf.AddrFrame.Mode = AddrModeFlat; } - if (noisy) dbg_printf("Backtrace:\n"); while (StackWalk(IMAGE_FILE_MACHINE_I386, dbg_curr_process->handle, dbg_curr_thread->handle, &sf, &dbg_context, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) { - if (with_frames) - { - frames = dbg_heap_realloc(frames, - (nf + 1) * sizeof(IMAGEHLP_STACK_FRAME)); + dbg_curr_thread->frames = dbg_heap_realloc(dbg_curr_thread->frames, + (nf + 1) * sizeof(dbg_curr_thread->frames[0])); - frames[nf].InstructionOffset = (unsigned long)memory_to_linear_addr(&sf.AddrPC); - frames[nf].FrameOffset = (unsigned long)memory_to_linear_addr(&sf.AddrFrame); - } - if (noisy) - { - dbg_printf("%s%d ", - (with_frames && nf == dbg_curr_frame ? "=>" : " "), - nf + 1); - print_addr_and_args(&sf.AddrPC, &sf.AddrFrame); - dbg_printf(" ("); - print_bare_address(&sf.AddrFrame); - dbg_printf(")\n"); - } + dbg_curr_thread->frames[nf].addr_pc = sf.AddrPC; + dbg_curr_thread->frames[nf].addr_frame = sf.AddrFrame; nf++; /* we've probably gotten ourselves into an infinite loop so bail */ - if (nf > 200) - break; + if (nf > 200) break; + } + return dbg_curr_thread->num_frames = nf; +} + +/****************************************************************** + * backtrace + * + * Do a backtrace on the the current thread + */ +static unsigned backtrace(void) +{ + unsigned nf = 0; + + dbg_printf("Backtrace:\n"); + for (nf = 0; nf < dbg_curr_thread->num_frames; nf++) + { + dbg_printf("%s%d ", + (nf == dbg_curr_thread->curr_frame ? "=>" : " "), nf + 1); + print_addr_and_args(&dbg_curr_thread->frames[nf].addr_pc, + &dbg_curr_thread->frames[nf].addr_frame); + dbg_printf(" ("); + print_bare_address(&dbg_curr_thread->frames[nf].addr_pc); + dbg_printf(")\n"); } return nf; } @@ -159,7 +195,7 @@ static unsigned backtrace(BOOL with_frames, BOOL noisy) * Do a backtrace on a thread from its process and its identifier * (preserves current thread and context information) */ -static void backtrace_tid(struct dbg_process* pcs, DWORD tid, BOOL noisy) +static void backtrace_tid(struct dbg_process* pcs, DWORD tid) { struct dbg_thread* thread = dbg_curr_thread; @@ -179,7 +215,7 @@ static void backtrace_tid(struct dbg_process* pcs, DWORD tid, BOOL noisy) dbg_printf("Can't get context for thread 0x%lx in current process\n", tid); } - else backtrace(FALSE, noisy); + else backtrace(); ResumeThread(dbg_curr_thread->handle); } else dbg_printf("Can't suspend thread 0x%lx in current process\n", tid); @@ -228,7 +264,7 @@ static void backtrace_all(void) dbg_printf("\nBacktracing for thread 0x%lx in process 0x%lx (%s):\n", entry.th32ThreadID, dbg_curr_pid, dbg_curr_process->imageName); - backtrace_tid(dbg_curr_process, entry.th32ThreadID, TRUE); + backtrace_tid(dbg_curr_process, entry.th32ThreadID); } while (Thread32Next(snapshot, &entry)); @@ -238,7 +274,7 @@ static void backtrace_all(void) CloseHandle(snapshot); } -void stack_backtrace(DWORD tid, BOOL noisy) +void stack_backtrace(DWORD tid) { /* backtrace every thread in every process except the debugger itself, * invoking via "bt all" @@ -253,12 +289,10 @@ void stack_backtrace(DWORD tid, BOOL noisy) if (tid == dbg_curr_tid) { - HeapFree(GetProcessHeap(), 0, frames); - frames = NULL; - nframe = backtrace(TRUE, noisy); + backtrace(); } else { - backtrace_tid(dbg_curr_process, tid, noisy); + backtrace_tid(dbg_curr_process, tid); } } diff --git a/programs/winedbg/symbol.c b/programs/winedbg/symbol.c index dce6052016..73f11471c8 100644 --- a/programs/winedbg/symbol.c +++ b/programs/winedbg/symbol.c @@ -94,7 +94,7 @@ static BOOL CALLBACK sgv_cb(SYMBOL_INFO* sym, ULONG size, void* ctx) { const struct dbg_internal_var* div; - if (dbg_curr_frame != 0) + if (dbg_curr_thread->curr_frame != 0) { dbg_printf(" %s (register): << cannot display, not in correct frame\n", sym->Name); @@ -570,7 +570,7 @@ static BOOL CALLBACK info_locals_cb(SYMBOL_INFO* sym, ULONG size, void* ctx) { const struct dbg_internal_var* div; - if (dbg_curr_frame != 0) + if (dbg_curr_thread->curr_frame != 0) { dbg_printf(" %s (register): << cannot display, not in correct frame\n", sym->Name); diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index c878a0b5ca..24f7429fd9 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -94,7 +94,6 @@ struct dbg_thread* dbg_curr_thread = NULL; DWORD dbg_curr_tid; DWORD dbg_curr_pid; CONTEXT dbg_context; -int dbg_curr_frame = 0; BOOL dbg_interactiveP = FALSE; static char* dbg_last_cmd_line = NULL; @@ -396,6 +395,9 @@ struct dbg_thread* dbg_add_thread(struct dbg_process* p, DWORD tid, t->step_over_bp.enabled = FALSE; t->step_over_bp.refcount = 0; t->in_exception = FALSE; + t->frames = NULL; + t->num_frames = 0; + t->curr_frame = -1; snprintf(t->name, sizeof(t->name), "0x%08lx", tid); @@ -428,6 +430,7 @@ static void dbg_init_current_thread(void* start) void dbg_del_thread(struct dbg_thread* t) { + HeapFree(GetProcessHeap(), 0, t->frames); if (t->prev) t->prev->next = t->next; if (t->next) t->next->prev = t->prev; if (t == t->process->threads) t->process->threads = t->next; @@ -538,7 +541,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec) * Do a quiet backtrace so that we have an idea of what the situation * is WRT the source files. */ - stack_backtrace(dbg_curr_tid, FALSE); + stack_fetch_frames(); if (is_debug && break_should_continue(&addr, rec->ExceptionCode, &dbg_curr_thread->exec_count, &is_break)) return FALSE; @@ -566,7 +569,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec) be_cpu->print_context(dbg_curr_thread->handle, &dbg_context); stack_info(); be_cpu->print_segment_info(dbg_curr_thread->handle, &dbg_context); - stack_backtrace(dbg_curr_tid, TRUE); + stack_backtrace(dbg_curr_tid); } else { @@ -603,7 +606,7 @@ static unsigned dbg_exception_prolog(BOOL is_debug, const EXCEPTION_RECORD* rec) { ADDRESS tmp = addr; /* Show where we crashed */ - dbg_curr_frame = 0; + stack_set_frame(0); memory_disasm_one_insn(&tmp); } source_list_from_addr(&addr, 0); -- 2.32.0.93.g670b81a890