Commit 3e07e047 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

- now storing frames information in thread structure

- frames are cached after each thread stops execution - reimplemented backtrace on top of this
parent ba2cb7c9
......@@ -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 {} /* <CR> 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); }
;
......
......@@ -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);
......
......@@ -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);
}
}
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment