Extended bt command to display backtrace of another thread.
Enhanced process & thread display with process name.
diff --git a/debugger/stack.c b/debugger/stack.c
index 157d144..b892a0e 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -106,7 +106,7 @@
}
}
-static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
+static BOOL DEBUG_Frame16(DBG_THREAD* thread, DBG_ADDR *addr, unsigned int *cs, int frameno, int noisy)
{
unsigned int possible_cs = 0;
FRAME16 frame;
@@ -128,7 +128,7 @@
if (((frame.cs&7)==7) && (frame.cs != *cs)) {
LDT_ENTRY le;
- if (GetThreadSelectorEntry( DEBUG_CurrThread->handle, frame.cs, &le) &&
+ if (GetThreadSelectorEntry( thread->handle, frame.cs, &le) &&
(le.HighWord.Bits.Type & 0x08)) { /* code segment */
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases */
@@ -174,25 +174,64 @@
*
* Display a stack back-trace.
*/
-void DEBUG_BackTrace(BOOL noisy)
+void DEBUG_BackTrace(DWORD tid, BOOL noisy)
{
#ifdef __i386
DBG_ADDR addr, sw_addr, code, tmp;
- unsigned int ss = DEBUG_context.SegSs;
- unsigned int cs = DEBUG_context.SegCs;
+ unsigned int ss, cs;
int frameno = 0, is16, ok;
DWORD next_switch, cur_switch, p;
STACK16FRAME frame16;
STACK32FRAME frame32;
char ch;
+ CONTEXT ctx;
+ DBG_THREAD* thread;
+ int copy_nframe = 0;
+ int copy_curr_frame = 0;
+ struct bt_info* copy_frames = NULL;
+
if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Backtrace:\n" );
+ if (tid == DEBUG_CurrTid)
+ {
+ ctx = DEBUG_context;
+ thread = DEBUG_CurrThread;
+
+ if (frames) DBG_free( frames );
+ /* frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); */
+ }
+ else
+ {
+ thread = DEBUG_GetThread(DEBUG_CurrProcess, tid);
+
+ if (!thread)
+ {
+ DEBUG_Printf( DBG_CHN_MESG, "Unknown thread id (0x%08lx) in current process\n", tid);
+ return;
+ }
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+
+ if ( SuspendThread( thread->handle ) == -1 ||
+ !GetThreadContext( thread->handle, &ctx ))
+ {
+ DEBUG_Printf( DBG_CHN_MESG, "Can't get context for thread id (0x%08lx) in current process\n", tid);
+ return;
+ }
+ /* need to avoid trashing stack frame for current thread */
+ copy_nframe = nframe;
+ copy_frames = frames;
+ copy_curr_frame = curr_frame;
+ curr_frame = 0;
+ }
+
nframe = 0;
- if (frames) DBG_free( frames );
- /* frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); */
frames = NULL;
+ cs = ctx.SegCs;
+ ss = ctx.SegSs;
+
if (DEBUG_IsSelectorSystem(ss)) ss = 0;
if (DEBUG_IsSelectorSystem(cs)) cs = 0;
@@ -201,16 +240,16 @@
{
case MODE_32:
code.seg = cs;
- code.off = DEBUG_context.Eip;
+ code.off = ctx.Eip;
addr.seg = ss;
- addr.off = DEBUG_context.Ebp;
+ addr.off = ctx.Ebp;
DEBUG_ForceFrame( &addr, &code, frameno, MODE_32, noisy, NULL );
if (!(code.seg || code.off)) {
/* trying to execute a null pointer... yuck...
* if it was a call to null, the return EIP should be
* available at SS:ESP, so let's try to retrieve it */
tmp.seg = ss;
- tmp.off = DEBUG_context.Esp;
+ tmp.off = ctx.Esp;
if (DEBUG_READ_MEM((void *)DEBUG_ToLinear(&tmp), &code.off, sizeof(code.off))) {
DEBUG_ForceFrame( &addr, &code, ++frameno, MODE_32, noisy, ", null call assumed" );
}
@@ -220,9 +259,9 @@
case MODE_16:
case MODE_VM86:
code.seg = cs;
- code.off = LOWORD(DEBUG_context.Eip);
+ code.off = LOWORD(ctx.Eip);
addr.seg = ss;
- addr.off = LOWORD(DEBUG_context.Ebp);
+ addr.off = LOWORD(ctx.Ebp);
DEBUG_ForceFrame( &addr, &code, frameno, MODE_16, noisy, NULL );
is16 = TRUE;
break;
@@ -234,7 +273,7 @@
/* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space
*/
- cur_switch = (DWORD)DEBUG_CurrThread->teb + OFFSET_OF(TEB, cur_stack);
+ cur_switch = (DWORD)thread->teb + OFFSET_OF(TEB, cur_stack);
if (!DEBUG_READ_MEM((void*)cur_switch, &next_switch, sizeof(next_switch))) {
if (noisy) DEBUG_Printf( DBG_CHN_MESG, "Can't read TEB:cur_stack\n");
return;
@@ -342,11 +381,21 @@
}
} else {
/* ordinary stack frame */
- ok = is16 ? DEBUG_Frame16( &addr, &cs, ++frameno, noisy)
+ ok = is16 ? DEBUG_Frame16( thread, &addr, &cs, ++frameno, noisy)
: DEBUG_Frame32( &addr, &cs, ++frameno, noisy);
}
}
if (noisy) DEBUG_Printf( DBG_CHN_MESG, "\n" );
+
+ if (tid != DEBUG_CurrTid)
+ {
+ ResumeThread( thread->handle );
+ /* restore stack frame for current thread */
+ if (frames) DBG_free( frames );
+ frames = copy_frames;
+ nframe = copy_nframe;
+ curr_frame = copy_curr_frame;
+ }
#endif
}