Fix setjmp (didn't save correct ESP, so it crashed after longjmp).

Fix the kernel debugger.

svn path=/trunk/; revision=16002
This commit is contained in:
Gregor Anich 2005-06-17 17:25:02 +00:00
parent 8502799382
commit faeb567e1c
4 changed files with 132 additions and 89 deletions

View file

@ -8,15 +8,17 @@ _KdbEnter:
/* /*
* Set up a trap frame * Set up a trap frame
*/ */
/* Ss - space already reserved by return EIP */
pushl %esp /* Esp */
pushfl /* Eflags */ pushfl /* Eflags */
pushl %cs /* Cs */ pushl %cs /* Cs */
pushl 12(%esp) /* Eip */
movl %ss, 16(%esp) /* Save Ss */
pushl $0 /* ErrorCode */ pushl $0 /* ErrorCode */
pushl %ebp /* Ebp */ pushl %ebp /* Ebp */
pushl %ebx /* Ebx */ pushl %ebx /* Ebx */
movl 20(%esp), %ebp /* Eip */
movl 16(%esp), %ebx /* Eflags */
movl %ebx, 20(%esp)
movl 12(%esp), %ebx /* Cs */
movl %ebx, 16(%esp)
movl %ebp, 12(%esp)
pushl %esi /* Esi */ pushl %esi /* Esi */
pushl %edi /* Edi */ pushl %edi /* Edi */
pushl %fs /* Fs */ pushl %fs /* Fs */
@ -43,8 +45,9 @@ _KdbEnter:
pushl %eax /* Dr1 */ pushl %eax /* Dr1 */
movl %dr0, %eax movl %dr0, %eax
pushl %eax /* Dr0 */ pushl %eax /* Dr0 */
pushl $0 /* TempEip */ leal 0x58(%esp), %eax
pushl $0 /* TempCs */ pushl %eax /* TempEsp */
pushl %ss /* TempSegSs */
pushl $0 /* DebugPointer */ pushl $0 /* DebugPointer */
pushl $3 /* DebugArgMark (Exception number) */ pushl $3 /* DebugArgMark (Exception number) */
pushl 0x60(%esp) /* DebugEip */ pushl 0x60(%esp) /* DebugEip */
@ -67,8 +70,8 @@ _KdbEnter:
* DebugEip * DebugEip
* DebugArgMark * DebugArgMark
* DebugPointer * DebugPointer
* TempCs * TempSegSs
* TempEip * TempEsp
*/ */
addl $(11*4), %esp addl $(11*4), %esp
@ -98,23 +101,13 @@ _KdbEnter:
popl %edx /* Edx */ popl %edx /* Edx */
popl %ecx /* Ecx */ popl %ecx /* Ecx */
popl %eax /* Eax */ popl %eax /* Eax */
addl $4, %esp /* PreviousMode */ addl $8, %esp /* PreviousMode, ExceptionList */
addl $4, %esp /* ExceptionList */
popl %fs /* Fs */ popl %fs /* Fs */
popl %edi /* Edi */ popl %edi /* Edi */
popl %esi /* Esi */ popl %esi /* Esi */
popl %ebx /* Ebx */ popl %ebx /* Ebx */
/* Remove SS:ESP from the stack */
movl 16(%esp), %ebp
movl %ebp, 24(%esp)
movl 12(%esp), %ebp
movl %ebp, 20(%esp)
movl 8(%esp), %ebp
movl %ebp, 16(%esp)
popl %ebp /* Ebp */ popl %ebp /* Ebp */
addl $12, %esp /* ErrorCode and SS:ESP */ addl $4, %esp /* ErrorCode */
/* /*
* Return to the caller. * Return to the caller.

View file

@ -38,7 +38,9 @@
* return PC * return PC
*/ */
.globl _setjmp .globl _setjmp
.globl __setjmp
_setjmp: _setjmp:
__setjmp:
pushl %ebp pushl %ebp
movl %esp,%ebp movl %esp,%ebp
@ -55,5 +57,5 @@ _setjmp:
xorl %eax,%eax /* return 0 the first time */ xorl %eax,%eax /* return 0 the first time */
leave leave
ret $4 ret

View file

@ -6,7 +6,7 @@
* *
* PROGRAMMERS: Gregor Anich * PROGRAMMERS: Gregor Anich
*/ */
/* INCLUDES ******************************************************************/ /* INCLUDES ******************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
@ -106,6 +106,65 @@ STATIC CONST PCHAR ExceptionNrToString[] =
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
STATIC VOID
KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFrame)
{
/* Copy the TrapFrame only up to Eflags and zero the rest*/
RtlCopyMemory(&KdbTrapFrame->Tf, TrapFrame, FIELD_OFFSET(KTRAP_FRAME, Esp));
RtlZeroMemory((PVOID)((ULONG_PTR)&KdbTrapFrame->Tf + FIELD_OFFSET(KTRAP_FRAME, Esp)),
sizeof (KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, Esp));
asm volatile(
"movl %%cr0, %0" "\n\t"
"movl %%cr2, %1" "\n\t"
"movl %%cr3, %2" "\n\t"
"movl %%cr4, %3" "\n\t"
: "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
"=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
if (TrapFrame->PreviousMode == KernelMode)
{
/* If the trapframe is a kmode one use the temp ss:esp */
KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
}
else
{
/* Otherwise use ss:esp pushed by the CPU */
/* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
* can handle umode and kmode the same way */
KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
}
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
}
STATIC VOID
KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFrame)
{
/* Copy the TrapFrame only up to Eflags and zero the rest*/
RtlCopyMemory(TrapFrame, &KdbTrapFrame->Tf, FIELD_OFFSET(KTRAP_FRAME, Esp));
/* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
if (TrapFrame->PreviousMode == KernelMode)
{
/* If the trapframe is a kmode one write to the temp ss:esp */
TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
}
else
{
/* Otherwise write to ss:esp pushed by the CPU */
/* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
* can handle umode and kmode the same way */
TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
}
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
}
/*!\brief Overwrites the instruction at \a Address with \a NewInst and stores /*!\brief Overwrites the instruction at \a Address with \a NewInst and stores
* the old instruction in *OldInst. * the old instruction in *OldInst.
* *
@ -981,7 +1040,7 @@ KdbpAttachToThread(
if (KdbCurrentThread != KdbOriginalThread) if (KdbCurrentThread != KdbOriginalThread)
{ {
ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame); ASSERT(KdbCurrentTrapFrame == &KdbThreadTrapFrame);
RtlCopyMemory(KdbCurrentThread->Tcb.TrapFrame, &KdbCurrentTrapFrame->Tf, sizeof (KTRAP_FRAME)); KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
} }
else else
{ {
@ -991,15 +1050,12 @@ KdbpAttachToThread(
/* Switch to the thread's context */ /* Switch to the thread's context */
if (Thread != KdbOriginalThread) if (Thread != KdbOriginalThread)
{ {
ASSERT(Thread->Tcb.TrapFrame != NULL); if (Thread->Tcb.TrapFrame == NULL)
RtlCopyMemory(&KdbThreadTrapFrame.Tf, Thread->Tcb.TrapFrame, sizeof (KTRAP_FRAME)); {
asm volatile( KdbpPrint("Threads TrapFrame is NULL! Cannot attach.\n");
"movl %%cr0, %0" "\n\t" return FALSE;
"movl %%cr2, %1" "\n\t" }
"movl %%cr3, %2" "\n\t" KdbpTrapFrameToKdbTrapFrame(Thread->Tcb.TrapFrame, &KdbThreadTrapFrame);
"movl %%cr4, %3" "\n\t"
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
KdbCurrentTrapFrame = &KdbThreadTrapFrame; KdbCurrentTrapFrame = &KdbThreadTrapFrame;
} }
else /* Switching back to original thread */ else /* Switching back to original thread */
@ -1243,14 +1299,7 @@ KdbEnterDebuggerException(
if (BreakPoint->Condition != NULL) if (BreakPoint->Condition != NULL)
{ {
/* Setup the KDB trap frame */ /* Setup the KDB trap frame */
RtlCopyMemory(&KdbTrapFrame.Tf, TrapFrame, sizeof (KTRAP_FRAME)); KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
asm volatile(
"movl %%cr0, %0" "\n\t"
"movl %%cr2, %1" "\n\t"
"movl %%cr3, %2" "\n\t"
"movl %%cr4, %3" "\n\t"
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
ull = 0; ull = 0;
if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL)) if (!KdbpRpnEvaluateParsedExpression(BreakPoint->Condition, &KdbTrapFrame, &ull, NULL, NULL))
@ -1395,14 +1444,7 @@ KdbEnterDebuggerException(
KdbCurrentTrapFrame = &KdbTrapFrame; KdbCurrentTrapFrame = &KdbTrapFrame;
/* Setup the KDB trap frame */ /* Setup the KDB trap frame */
RtlCopyMemory(&KdbTrapFrame.Tf, TrapFrame, sizeof(KTRAP_FRAME)); KdbpTrapFrameToKdbTrapFrame(TrapFrame, &KdbTrapFrame);
asm volatile(
"movl %%cr0, %0" "\n\t"
"movl %%cr2, %1" "\n\t"
"movl %%cr3, %2" "\n\t"
"movl %%cr4, %3" "\n\t"
: "=r"(KdbTrapFrame.Cr0), "=r"(KdbTrapFrame.Cr2),
"=r"(KdbTrapFrame.Cr3), "=r"(KdbTrapFrame.Cr4));
/* Enter critical section */ /* Enter critical section */
Ke386SaveFlags(OldEflags); Ke386SaveFlags(OldEflags);
@ -1436,7 +1478,7 @@ KdbEnterDebuggerException(
/* Save the current thread's trapframe */ /* Save the current thread's trapframe */
if (KdbCurrentTrapFrame == &KdbThreadTrapFrame) if (KdbCurrentTrapFrame == &KdbThreadTrapFrame)
{ {
RtlCopyMemory(KdbCurrentThread->Tcb.TrapFrame, KdbCurrentTrapFrame, sizeof (KTRAP_FRAME)); KdbpKdbTrapFrameToTrapFrame(KdbCurrentTrapFrame, KdbCurrentThread->Tcb.TrapFrame);
} }
/* Detach from attached process */ /* Detach from attached process */
@ -1446,16 +1488,7 @@ KdbEnterDebuggerException(
} }
/* Update the exception TrapFrame */ /* Update the exception TrapFrame */
RtlCopyMemory(TrapFrame, &KdbTrapFrame.Tf, sizeof(KTRAP_FRAME)); KdbpKdbTrapFrameToTrapFrame(&KdbTrapFrame, TrapFrame);
#if 0
asm volatile(
"movl %0, %%cr0" "\n\t"
"movl %1, %%cr2" "\n\t"
"movl %2, %%cr3" "\n\t"
"movl %3, %%cr4" "\n\t"
: : "r"(KdbTrapFrame.Cr0), "r"(KdbTrapFrame.Cr2),
"r"(KdbTrapFrame.Cr3), "r"(KdbTrapFrame.Cr4));
#endif
/* Decrement the entry count */ /* Decrement the entry count */
InterlockedDecrement(&KdbEntryCount); InterlockedDecrement(&KdbEntryCount);

View file

@ -116,7 +116,7 @@ BadThread:
.globl @KiSwapContextInternal@0 .globl @KiSwapContextInternal@0
@KiSwapContextInternal@0: @KiSwapContextInternal@0:
#ifdef KDBG #ifdef KDBG
//jmp SaveTrapFrameForKDB jmp SaveTrapFrameForKDB
SaveTrapFrameForKDB_Return: SaveTrapFrameForKDB_Return:
#endif #endif
@ -298,32 +298,55 @@ SameProcess:
SaveTrapFrameForKDB: SaveTrapFrameForKDB:
/* Set up a trap frame */ /* Set up a trap frame */
/* Fake Interrupt Stack */
push esp // 0x74
pushf // 0x70 pushf // 0x70
push cs // 0x6C push cs // 0x6C
push [esp+12] /* EIP */ // 0x68 push 0 /* Error Code */ // 0x64
mov [esp+16], ss // 0x78
/* Trap Frame */
push 0 /* Error Code */ // 0x64
push ebp // 0x60 push ebp // 0x60
push ebx push ebx
/* Fake Interrupt Stack */
mov ebp, [esp+20] /* Eip */
mov ebx, [esp+16] /* Eflags */
mov [esp+20], ebx
mov ebx, [esp+12] /* Cs */
mov [esp+16], ebx
mov [esp+12], ebp
push esi push esi
push edi push edi
push fs push fs
push -1 /* Exception List */ // 0x4C push -1 /* Exception List */ // 0x4C
push 0 /* Previous Mode */ // 0x48 push 0 /* Previous Mode */ // 0x48
push eax push eax
push ecx push ecx
push edx push edx
push ds push ds
push es push es
push gs // 0x30 push gs // 0x30
sub esp, 0x28 /* Debug Registers */ // 0x8
push [esp+60] /* Debug EIP */ // 0x4 mov eax, dr7
push ebp /* Debug EBP */ // 0x0 push eax /* Dr7 */
/* Clear breakpoint enables in dr7. */
and eax, 0xffff0000
mov dr7, eax
mov eax, dr6
push eax /* Dr6 */
mov eax, dr3
push eax /* Dr3 */
mov eax, dr2
push eax /* Dr2 */
mov eax, dr1
push eax /* Dr1 */
mov eax, dr0
push eax /* Dr0 */
lea eax, [esp+0x58]
push eax /* TempEsp */
push ss /* TempSegSs */
push 0 /* DebugPointer */
push -1 /* DebugArgMark */
push [esp+60] /* Debug EIP */ // 0x4
push ebp /* Debug EBP */ // 0x0
/* Set Stack */ /* Set Stack */
mov ebp, esp mov ebp, esp
@ -334,19 +357,21 @@ SaveTrapFrameForKDB:
/* Save new one */ /* Save new one */
mov [edi+KTHREAD_TRAP_FRAME], ebp mov [edi+KTHREAD_TRAP_FRAME], ebp
/* Restore EBP, EBX and EAX */
mov ebp, [ebp+KTRAP_FRAME_EBP]
mov ebx, [ebp+KTRAP_FRAME_EBX]
mov eax, [ebp+KTRAP_FRAME_EAX]
/* Return EIP */ /* Return EIP */
push offset RestoreTrapFrameForKDB push offset RestoreTrapFrameForKDB
/* Restore EBP */
mov ebp, [ebp+KTRAP_FRAME_EBP]
/* Jump to normal code */ /* Jump to normal code */
jmp SaveTrapFrameForKDB_Return jmp SaveTrapFrameForKDB_Return
RestoreTrapFrameForKDB: RestoreTrapFrameForKDB:
/* Restore the old trapframe */ /* Restore the old trapframe */
pop [edi+KTHREAD_TRAP_FRAME] pop [esi+KTHREAD_TRAP_FRAME]
/* Pop unused portions of the trap frame */ /* Pop unused portions of the trap frame */
add esp, 0x30 add esp, 0x30
@ -358,23 +383,13 @@ RestoreTrapFrameForKDB:
pop edx pop edx
pop ecx pop ecx
pop eax pop eax
add esp, 8 add esp, 8 /* ExceptionList and PreviousMode */
pop fs pop fs
pop edi pop edi
pop esi pop esi
pop ebx pop ebx
/* Remove SS:ESP from the stack */
mov ebp, [esp+16]
mov [esp+24], ebp
mov ebp, [esp+12]
mov [esp+20], ebp
mov ebp, [esp+8]
mov [esp+16], ebp
/* Restore Fake INT Stack */
pop ebp pop ebp
add esp, 12 add esp, 4 /* ErrorCode */
/* Return to the caller. */ /* Return to the caller. */
iret iret