From 3726b992ed3631c3571df056da70839c35a05582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Tue, 27 Apr 2021 10:23:37 +0200 Subject: [PATCH] [NTOS:KDBG] Begin port for amd64. Not really functional, but it prints debug output. Take this as an opportunity to add consistancy between some i386 & amd64 intrinsics --- ntoskrnl/include/internal/amd64/ke.h | 85 +++++++-- ntoskrnl/include/internal/i386/intrin_i.h | 64 ++++--- ntoskrnl/include/internal/i386/ke.h | 81 +++++++-- ntoskrnl/kd/kdio.c | 2 +- ntoskrnl/kdbg/amd64/amd64-dis.c | 0 ntoskrnl/kdbg/amd64/kdb_help.S | 22 +++ ntoskrnl/kdbg/kdb.c | 33 ++-- ntoskrnl/kdbg/kdb_cli.c | 209 ++++++++++++++++------ ntoskrnl/kdbg/kdb_expr.c | 18 +- ntoskrnl/ke/i386/cpu.c | 2 +- ntoskrnl/ntos.cmake | 4 + 11 files changed, 396 insertions(+), 124 deletions(-) create mode 100644 ntoskrnl/kdbg/amd64/amd64-dis.c create mode 100644 ntoskrnl/kdbg/amd64/kdb_help.S diff --git a/ntoskrnl/include/internal/amd64/ke.h b/ntoskrnl/include/internal/amd64/ke.h index d4e1354290d..9917b9334cd 100644 --- a/ntoskrnl/include/internal/amd64/ke.h +++ b/ntoskrnl/include/internal/amd64/ke.h @@ -119,25 +119,84 @@ extern ULONG KeI386CpuStep; #define KD_BREAKPOINT_VALUE 0xCC // -// Macros for getting and setting special purpose registers in portable code +// One-liners for getting and setting special purpose registers in portable code // -#define KeGetContextPc(Context) \ - ((Context)->Rip) +FORCEINLINE +ULONG_PTR +KeGetContextPc(PCONTEXT Context) +{ + return Context->Rip; +} -#define KeSetContextPc(Context, ProgramCounter) \ - ((Context)->Rip = (ProgramCounter)) +FORCEINLINE +VOID +KeSetContextPc(PCONTEXT Context, ULONG_PTR ProgramCounter) +{ + Context->Rip = ProgramCounter; +} -#define KeGetTrapFramePc(TrapFrame) \ - ((TrapFrame)->Rip) +FORCEINLINE +ULONG_PTR +KeGetContextReturnRegister(PCONTEXT Context) +{ + return Context->Rax; +} -#define KiGetLinkedTrapFrame(x) \ - (PKTRAP_FRAME)((x)->TrapFrame) +FORCEINLINE +VOID +KeSetContextReturnRegister(PCONTEXT Context, ULONG_PTR ReturnValue) +{ + Context->Rax = ReturnValue; +} -#define KeGetContextReturnRegister(Context) \ - ((Context)->Rax) +FORCEINLINE +ULONG_PTR +KeGetContextStackRegister(PCONTEXT Context) +{ + return Context->Rsp; +} -#define KeSetContextReturnRegister(Context, ReturnValue) \ - ((Context)->Rax = (ReturnValue)) +FORCEINLINE +ULONG_PTR +KeGetContextFrameRegister(PCONTEXT Context) +{ + return Context->Rbp; +} + +FORCEINLINE +VOID +KeSetContextFrameRegister(PCONTEXT Context, ULONG_PTR Frame) +{ + Context->Rbp = Frame; +} + +FORCEINLINE +ULONG_PTR +KeGetTrapFramePc(PKTRAP_FRAME TrapFrame) +{ + return TrapFrame->Rip; +} + +FORCEINLINE +PKTRAP_FRAME +KiGetLinkedTrapFrame(PKTRAP_FRAME TrapFrame) +{ + return (PKTRAP_FRAME)TrapFrame->TrapFrame; +} + +FORCEINLINE +ULONG_PTR +KeGetTrapFrameStackRegister(PKTRAP_FRAME TrapFrame) +{ + return TrapFrame->Rsp; +} + +FORCEINLINE +ULONG_PTR +KeGetTrapFrameFrameRegister(PKTRAP_FRAME TrapFrame) +{ + return TrapFrame->Rbp; +} // // Macro to get trap and exception frame from a thread stack diff --git a/ntoskrnl/include/internal/i386/intrin_i.h b/ntoskrnl/include/internal/i386/intrin_i.h index 76e391e10ba..a458be957fb 100644 --- a/ntoskrnl/include/internal/i386/intrin_i.h +++ b/ntoskrnl/include/internal/i386/intrin_i.h @@ -2,16 +2,29 @@ #if defined(__GNUC__) -#define Ke386SetGlobalDescriptorTable(X) \ - __asm__("lgdt %0\n\t" \ - : /* no outputs */ \ - : "m" (*X)); +FORCEINLINE +VOID +__lgdt(_Out_ PVOID Descriptor) +{ + PVOID* desc = Descriptor; + __asm__ __volatile__( + "lgdt %0" + : "=m" (*desc) + : /* no input */ + : "memory"); +} -#define Ke386GetGlobalDescriptorTable(X) \ - __asm__("sgdt %0\n\t" \ - : "=m" (*X) \ - : /* no input */ \ - : "memory"); +FORCEINLINE +VOID +__sgdt(_Out_ PVOID Descriptor) +{ + PVOID* desc = Descriptor; + __asm__ __volatile__( + "sgdt %0" + : "=m" (*desc) + : /* no input */ + : "memory"); +} FORCEINLINE VOID @@ -51,15 +64,14 @@ Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea) } FORCEINLINE -USHORT -Ke386GetLocalDescriptorTable(VOID) +VOID +__sldt(PVOID Descriptor) { - USHORT Ldt; - __asm__("sldt %0\n\t" - : "=m" (Ldt) - : /* no input */ - : "memory"); - return Ldt; + __asm__ __volatile__( + "sldt %0" + : "=m" (*((short*)Descriptor)) + : /* no input */ + : "memory"); } #define Ke386SetLocalDescriptorTable(X) \ @@ -155,8 +167,6 @@ __fnsave(OUT PFLOATING_SAVE_AREA SaveArea) __asm wait; } -#define Ke386GetGlobalDescriptorTable __sgdt - FORCEINLINE VOID __lgdt(IN PVOID Descriptor) @@ -167,13 +177,17 @@ __lgdt(IN PVOID Descriptor) lgdt [eax] } } -#define Ke386SetGlobalDescriptorTable __lgdt FORCEINLINE -USHORT -Ke386GetLocalDescriptorTable(VOID) +VOID +__sldt(PVOID Descriptor) { - __asm sldt ax; + __asm + { + sldt ax + mov ecx, Descriptor + mov [ecx], ax + } } FORCEINLINE @@ -305,4 +319,8 @@ Ke386SaveFpuState(IN PVOID SaveArea) #error Unknown compiler for inline assembler #endif +#define Ke386GetGlobalDescriptorTable __sgdt +#define Ke386SetGlobalDescriptorTable __lgdt +#define Ke386GetLocalDescriptorTable __sldt + /* EOF */ diff --git a/ntoskrnl/include/internal/i386/ke.h b/ntoskrnl/include/internal/i386/ke.h index e91b8d6ad16..58adbf52906 100644 --- a/ntoskrnl/include/internal/i386/ke.h +++ b/ntoskrnl/include/internal/i386/ke.h @@ -18,25 +18,80 @@ #define KD_BREAKPOINT_VALUE 0xCC // -// Macros for getting and setting special purpose registers in portable code +// One-liners for getting and setting special purpose registers in portable code // -#define KeGetContextPc(Context) \ - ((Context)->Eip) +FORCEINLINE +ULONG_PTR +KeGetContextPc(PCONTEXT Context) +{ + return Context->Eip; +} -#define KeSetContextPc(Context, ProgramCounter) \ - ((Context)->Eip = (ProgramCounter)) +FORCEINLINE +VOID +KeSetContextPc(PCONTEXT Context, ULONG_PTR ProgramCounter) +{ + Context->Eip = ProgramCounter; +} -#define KeGetTrapFramePc(TrapFrame) \ - ((TrapFrame)->Eip) +FORCEINLINE +ULONG_PTR +KeGetContextReturnRegister(PCONTEXT Context) +{ + return Context->Eax; +} -#define KiGetLinkedTrapFrame(x) \ - (PKTRAP_FRAME)((x)->Edx) +FORCEINLINE +VOID +KeSetContextReturnRegister(PCONTEXT Context, ULONG_PTR ReturnValue) +{ + Context->Eax = ReturnValue; +} -#define KeGetContextReturnRegister(Context) \ - ((Context)->Eax) +FORCEINLINE +ULONG_PTR +KeGetContextFrameRegister(PCONTEXT Context) +{ + return Context->Ebp; +} -#define KeSetContextReturnRegister(Context, ReturnValue) \ - ((Context)->Eax = (ReturnValue)) +FORCEINLINE +VOID +KeSetContextFrameRegister(PCONTEXT Context, ULONG_PTR Frame) +{ + Context->Ebp = Frame; +} + +FORCEINLINE +ULONG_PTR +KeGetTrapFramePc(PKTRAP_FRAME TrapFrame) +{ + return TrapFrame->Eip; +} + +FORCEINLINE +PKTRAP_FRAME +KiGetLinkedTrapFrame(PKTRAP_FRAME TrapFrame) +{ + return (PKTRAP_FRAME)TrapFrame->Edx; +} + + +FORCEINLINE +ULONG_PTR +KeGetTrapFrameStackRegister(PKTRAP_FRAME TrapFrame) +{ + if (TrapFrame->PreviousPreviousMode == KernelMode) + return TrapFrame->TempEsp; + return TrapFrame->HardwareEsp; +} + +FORCEINLINE +ULONG_PTR +KeGetTrapFrameFrameRegister(PKTRAP_FRAME TrapFrame) +{ + return TrapFrame->Ebp; +} // // Macro to get trap and exception frame from a thread stack diff --git a/ntoskrnl/kd/kdio.c b/ntoskrnl/kd/kdio.c index af7accb3afc..9c35c9586e9 100644 --- a/ntoskrnl/kd/kdio.c +++ b/ntoskrnl/kd/kdio.c @@ -611,7 +611,7 @@ KdSendPacket( if (KdbgExceptionRecord.ExceptionCode == STATUS_ASSERTION_FAILURE) { /* Bump EIP to the instruction following the int 2C */ - KdbgContext.Eip += 2; + KeSetContextPc(&KdbgContext, KeGetContextPc(&KdbgContext) + 2); } Result = KdbEnterDebuggerException(&KdbgExceptionRecord, diff --git a/ntoskrnl/kdbg/amd64/amd64-dis.c b/ntoskrnl/kdbg/amd64/amd64-dis.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ntoskrnl/kdbg/amd64/kdb_help.S b/ntoskrnl/kdbg/amd64/kdb_help.S new file mode 100644 index 00000000000..39ae8721f8e --- /dev/null +++ b/ntoskrnl/kdbg/amd64/kdb_help.S @@ -0,0 +1,22 @@ + +#include + +.code64 + +PUBLIC KdbpStackSwitchAndCall +KdbpStackSwitchAndCall: + push rbp + mov rbp, rsp /* Old stack - frame */ + + /* Switch stack */ + mov rsp, rcx + + /* Call function */ + call rdx + + /* Switch back to old stack */ + pop rsp + + ret 8 + +END diff --git a/ntoskrnl/kdbg/kdb.c b/ntoskrnl/kdbg/kdb.c index f9a3b8792bb..8ec2e3bef1d 100644 --- a/ntoskrnl/kdbg/kdb.c +++ b/ntoskrnl/kdbg/kdb.c @@ -650,14 +650,14 @@ KdbpIsBreakPointOurs( if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */ { - ULONG_PTR BpEip = (ULONG_PTR)Context->Eip - 1; /* Get EIP of INT3 instruction */ + ULONG_PTR BpPc = KeGetContextPc(Context) - 1; /* Get EIP of INT3 instruction */ for (i = 0; i < KdbSwBreakPointCount; i++) { ASSERT((KdbSwBreakPoints[i]->Type == KdbBreakPointSoftware || KdbSwBreakPoints[i]->Type == KdbBreakPointTemporary)); ASSERT(KdbSwBreakPoints[i]->Enabled); - if (KdbSwBreakPoints[i]->Address == BpEip) + if (KdbSwBreakPoints[i]->Address == BpPc) { return KdbSwBreakPoints[i] - KdbBreakPoints; } @@ -1321,7 +1321,7 @@ KdbEnterDebuggerException( KiDispatchException accounts for that. Whatever we do here with the TrapFrame does not matter anyway, since KiDispatchException will overwrite it with the values from the Context! */ - Context->Eip--; + KeSetContextPc(Context, KeGetContextPc(Context) - 1); } if ((BreakPoint->Type == KdbBreakPointHardware) && @@ -1345,8 +1345,8 @@ KdbEnterDebuggerException( if (--KdbNumSingleSteps > 0) { - if ((KdbSingleStepOver && !KdbpStepOverInstruction(Context->Eip)) || - (!KdbSingleStepOver && !KdbpStepIntoInstruction(Context->Eip))) + if ((KdbSingleStepOver && !KdbpStepOverInstruction(KeGetContextPc(Context))) || + (!KdbSingleStepOver && !KdbpStepIntoInstruction(KeGetContextPc(Context)))) { Context->EFlags |= EFLAGS_TF; } @@ -1394,8 +1394,8 @@ KdbEnterDebuggerException( if (BreakPoint->Type == KdbBreakPointSoftware) { - KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%08x\n", - KdbLastBreakPointNr, Context->SegCs & 0xffff, Context->Eip); + KdbpPrint("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%p\n", + KdbLastBreakPointNr, Context->SegCs & 0xffff, KeGetContextPc(Context)); } else if (BreakPoint->Type == KdbBreakPointHardware) { @@ -1448,8 +1448,8 @@ KdbEnterDebuggerException( /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/ if (--KdbNumSingleSteps > 0) { - if ((KdbSingleStepOver && KdbpStepOverInstruction(Context->Eip)) || - (!KdbSingleStepOver && KdbpStepIntoInstruction(Context->Eip))) + if ((KdbSingleStepOver && KdbpStepOverInstruction(KeGetContextPc(Context))) || + (!KdbSingleStepOver && KdbpStepIntoInstruction(KeGetContextPc(Context)))) { Context->EFlags &= ~EFLAGS_TF; } @@ -1488,8 +1488,8 @@ KdbEnterDebuggerException( return kdHandleException; } - KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%08x.\n", - Context->SegCs & 0xffff, Context->Eip - 1); + KdbpPrint("\nEntered debugger on embedded INT3 at 0x%04x:0x%p.\n", + Context->SegCs & 0xffff, KeGetContextPc(Context) - 1); } else { @@ -1552,8 +1552,8 @@ KdbEnterDebuggerException( /* Variable explains itself! */ KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep = TRUE; - if ((KdbSingleStepOver && KdbpStepOverInstruction(KdbCurrentTrapFrame->Eip)) || - (!KdbSingleStepOver && KdbpStepIntoInstruction(KdbCurrentTrapFrame->Eip))) + if ((KdbSingleStepOver && KdbpStepOverInstruction(KeGetContextPc(KdbCurrentTrapFrame))) || + (!KdbSingleStepOver && KdbpStepIntoInstruction(KeGetContextPc(KdbCurrentTrapFrame)))) { ASSERT((KdbCurrentTrapFrame->EFlags & EFLAGS_TF) == 0); /*KdbCurrentTrapFrame->EFlags &= ~EFLAGS_TF;*/ @@ -1608,7 +1608,7 @@ continue_execution: if (!(KdbEnteredOnSingleStep && KdbSingleStepOver)) { /* Skip the current instruction */ - Context->Eip++; + KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE); } } @@ -1625,7 +1625,10 @@ KdbEnterDebuggerFirstChanceException( /* Copy TrapFrame to Context */ RtlZeroMemory(&Context, sizeof(CONTEXT)); - Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_EXTENDED_REGISTERS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; + Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS; +#ifdef CONTEXT_EXTENDED_REGISTERS + Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS; +#endif KeTrapFrameToContext(TrapFrame, NULL, &Context); /* Create ExceptionRecord (assume breakpoint) */ diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index 50805fe9f66..01473e99b0d 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -82,7 +82,9 @@ static BOOLEAN KdbpCmdProc(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdMod(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdGdtLdtIdt(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdPcr(ULONG Argc, PCHAR Argv[]); +#ifdef _M_IX86 static BOOLEAN KdbpCmdTss(ULONG Argc, PCHAR Argv[]); +#endif static BOOLEAN KdbpCmdBugCheck(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdReboot(ULONG Argc, PCHAR Argv[]); @@ -103,6 +105,26 @@ BOOLEAN ExpKdbgExtHandle(ULONG Argc, PCHAR Argv[]); static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]); #endif +/* Be more descriptive than intrinsics */ +#ifndef Ke386GetGlobalDescriptorTable +# define Ke386GetGlobalDescriptorTable __sgdt +#endif +#ifndef Ke386GetLocalDescriptorTable +# define Ke386GetLocalDescriptorTable __sldt +#endif + +/* Portability */ +FORCEINLINE +ULONG_PTR +strtoulptr(const char* nptr, char** endptr, int base) +{ +#ifdef _M_IX86 + return strtoul(nptr, endptr, base); +#else + return strtoull(nptr, endptr, base); +#endif +} + /* GLOBALS *******************************************************************/ typedef @@ -376,7 +398,9 @@ static const struct { "ldt", "ldt", "Display the local descriptor table.", KdbpCmdGdtLdtIdt }, { "idt", "idt", "Display the interrupt descriptor table.", KdbpCmdGdtLdtIdt }, { "pcr", "pcr", "Display the processor control region.", KdbpCmdPcr }, +#ifdef _M_IX86 { "tss", "tss [selector|*descaddr]", "Display the current task state segment, or the one specified by its selector number or descriptor address.", KdbpCmdTss }, +#endif /* Others */ { NULL, NULL, "Others", NULL }, @@ -793,7 +817,7 @@ KdbpCmdDisassembleX( ULONG ul; INT i; ULONGLONG Result = 0; - ULONG_PTR Address = KdbCurrentTrapFrame->Eip; + ULONG_PTR Address = KeGetContextPc(KdbCurrentTrapFrame); LONG InstLen; if (Argv[0][0] == 'x') /* display memory */ @@ -922,6 +946,7 @@ KdbpCmdRegs( if (Argv[0][0] == 'r') /* regs */ { +#ifdef _M_IX86 KdbpPrint("CS:EIP 0x%04x:0x%08x\n" "SS:ESP 0x%04x:0x%08x\n" " EAX 0x%08x EBX 0x%08x\n" @@ -934,7 +959,20 @@ KdbpCmdRegs( Context->Ecx, Context->Edx, Context->Esi, Context->Edi, Context->Ebp); - +#else + KdbpPrint("CS:RIP 0x%04x:0x%p\n" + "SS:RSP 0x%04x:0x%p\n" + " RAX 0x%p RBX 0x%p\n" + " RCX 0x%p RDX 0x%p\n" + " RSI 0x%p RDI 0x%p\n" + " RBP 0x%p\n", + Context->SegCs & 0xFFFF, Context->Rip, + Context->SegSs, Context->Rsp, + Context->Rax, Context->Rbx, + Context->Rcx, Context->Rdx, + Context->Rsi, Context->Rdi, + Context->Rbp); +#endif /* Display the EFlags */ KdbpPrint("EFLAGS 0x%08x ", Context->EFlags); for (i = 0; i < 32; i++) @@ -990,6 +1028,7 @@ KdbpCmdRegs( return TRUE; } +#ifdef _M_IX86 static PKTSS KdbpRetrieveTss( IN USHORT TssSelector, @@ -1102,6 +1141,7 @@ KdbpContextFromPrevTss( Context->Ebp = Ebp; return TRUE; } +#endif /*!\brief Displays a backtrace. */ @@ -1113,11 +1153,8 @@ KdbpCmdBackTrace( ULONG ul; ULONGLONG Result = 0; CONTEXT Context = *KdbCurrentTrapFrame; - ULONG_PTR Frame = Context.Ebp; + ULONG_PTR Frame = KeGetContextFrameRegister(&Context); ULONG_PTR Address; - KDESCRIPTOR Gdtr; - USHORT TssSelector; - PKTSS Tss; if (Argc >= 2) { @@ -1172,6 +1209,11 @@ KdbpCmdBackTrace( } } +#ifdef _M_IX86 + KDESCRIPTOR Gdtr; + USHORT TssSelector; + PKTSS Tss; + /* Retrieve the Global Descriptor Table */ Ke386GetGlobalDescriptorTable(&Gdtr.Limit); @@ -1183,13 +1225,14 @@ KdbpCmdBackTrace( /* Display the active TSS if it is nested */ KdbpPrint("[Active TSS 0x%04x @ 0x%p]\n", TssSelector, Tss); } +#endif /* If no Frame Address or Thread ID was given, try printing the function at EIP */ if (Argc <= 1) { KdbpPrint("Eip:\n"); - if (!KdbSymPrintAddress((PVOID)Context.Eip, &Context)) - KdbpPrint("<%08x>\n", Context.Eip); + if (!KdbSymPrintAddress((PVOID)KeGetContextPc(&Context), &Context)) + KdbpPrint("<%p>\n", KeGetContextPc(&Context)); else KdbpPrint("\n"); } @@ -1215,7 +1258,9 @@ KdbpCmdBackTrace( GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof(ULONG_PTR))); if (GotNextFrame) - Context.Ebp = Frame; + { + KeSetContextFrameRegister(&Context, Frame); + } // else // Frame = 0; @@ -1237,6 +1282,9 @@ KdbpCmdBackTrace( continue; CheckForParentTSS: +#ifndef _M_IX86 + break; +#else /* * We have ended the stack walking for the current (active) TSS. * Check whether this TSS was nested, and if so switch to its parent @@ -1251,6 +1299,8 @@ CheckForParentTSS: KdbpPrint("Couldn't access parent TSS 0x%04x\n", Tss->Backlink); break; // Cannot retrieve the parent TSS, we stop there. } + + Address = Context.Eip; Frame = Context.Ebp; @@ -1260,6 +1310,7 @@ CheckForParentTSS: KdbpPrint("<%08x>\n", Address); else KdbpPrint("\n"); +#endif } return TRUE; @@ -1359,8 +1410,8 @@ KdbpCmdBreakPointList( else { GlobalOrLocal = Buffer; - sprintf(Buffer, " PID 0x%08lx", - (ULONG)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE)); + sprintf(Buffer, " PID 0x%lx", + (ULONG_PTR)(Process ? Process->UniqueProcessId : INVALID_HANDLE_VALUE)); } if (Type == KdbBreakPointSoftware || Type == KdbBreakPointTemporary) @@ -1579,10 +1630,10 @@ KdbpCmdThread( PETHREAD Thread = NULL; PEPROCESS Process = NULL; BOOLEAN ReferencedThread = FALSE, ReferencedProcess = FALSE; - PULONG Esp; - PULONG Ebp; - ULONG Eip; - ULONG ul = 0; + PULONG_PTR Stack; + PULONG_PTR Frame; + ULONG_PTR Pc; + ULONG_PTR ul = 0; PCHAR State, pend, str1, str2; static const PCHAR ThreadStateToString[DeferredReady+1] = { @@ -1599,7 +1650,7 @@ KdbpCmdThread( if (Argc >= 3) { - ul = strtoul(Argv[2], &pend, 0); + ul = strtoulptr(Argv[2], &pend, 0); if (Argv[2] == pend) { KdbpPrint("thread: '%s' is not a valid process id!\n", Argv[2]); @@ -1620,7 +1671,7 @@ KdbpCmdThread( if (Entry == &Process->ThreadListHead) { if (Argc >= 3) - KdbpPrint("No threads in process 0x%08x!\n", ul); + KdbpPrint("No threads in process 0x%px!\n", (PVOID)ul); else KdbpPrint("No threads in current process!\n"); @@ -1649,27 +1700,23 @@ KdbpCmdThread( if (!Thread->Tcb.InitialStack) { /* Thread has no kernel stack (probably terminated) */ - Esp = Ebp = NULL; - Eip = 0; + Stack = Frame = NULL; + Pc = 0; } else if (Thread->Tcb.TrapFrame) { - if (Thread->Tcb.TrapFrame->PreviousPreviousMode == KernelMode) - Esp = (PULONG)Thread->Tcb.TrapFrame->TempEsp; - else - Esp = (PULONG)Thread->Tcb.TrapFrame->HardwareEsp; - - Ebp = (PULONG)Thread->Tcb.TrapFrame->Ebp; - Eip = Thread->Tcb.TrapFrame->Eip; + Stack = (PULONG_PTR)KeGetTrapFrameStackRegister(Thread->Tcb.TrapFrame); + Frame = (PULONG_PTR)KeGetTrapFrameFrameRegister(Thread->Tcb.TrapFrame); + Pc = KeGetTrapFramePc(Thread->Tcb.TrapFrame); } else { - Esp = (PULONG)Thread->Tcb.KernelStack; - Ebp = (PULONG)Esp[4]; - Eip = 0; + Stack = (PULONG_PTR)Thread->Tcb.KernelStack; + Frame = (PULONG_PTR)Stack[4]; + Pc = 0; - if (Ebp) /* FIXME: Should we attach to the process to read Ebp[1]? */ - KdbpSafeReadMemory(&Eip, Ebp + 1, sizeof(Eip)); + if (Frame) /* FIXME: Should we attach to the process to read Ebp[1]? */ + KdbpSafeReadMemory(&Pc, Frame + 1, sizeof(Pc)); } if (Thread->Tcb.State < (DeferredReady + 1)) @@ -1683,8 +1730,8 @@ KdbpCmdThread( State, Thread->Tcb.Priority, Thread->Tcb.Affinity, - Ebp, - Eip, + Frame, + Pc, str2); Entry = Entry->Flink; @@ -1703,7 +1750,7 @@ KdbpCmdThread( return TRUE; } - ul = strtoul(Argv[2], &pend, 0); + ul = strtoulptr(Argv[2], &pend, 0); if (Argv[2] == pend) { KdbpPrint("thread attach: '%s' is not a valid thread id!\n", Argv[2]); @@ -1723,7 +1770,7 @@ KdbpCmdThread( if (Argc >= 2) { - ul = strtoul(Argv[1], &pend, 0); + ul = strtoulptr(Argv[1], &pend, 0); if (Argv[1] == pend) { KdbpPrint("thread: '%s' is not a valid thread id!\n", Argv[1]); @@ -1765,8 +1812,11 @@ KdbpCmdThread( Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Thread->Tcb.KernelStack, - Thread->Tcb.TrapFrame, - NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState); + Thread->Tcb.TrapFrame +#ifndef _M_AMD64 + , NPX_STATE_TO_STRING(Thread->Tcb.NpxState), Thread->Tcb.NpxState +#endif +); /* Release our reference if we had one */ if (ReferencedThread) @@ -1787,7 +1837,7 @@ KdbpCmdProc( PEPROCESS Process; BOOLEAN ReferencedProcess = FALSE; PCHAR State, pend, str1, str2; - ULONG ul; + ULONG_PTR ul; extern LIST_ENTRY PsActiveProcessHead; if (Argc >= 2 && _stricmp(Argv[1], "list") == 0) @@ -1837,7 +1887,7 @@ KdbpCmdProc( return TRUE; } - ul = strtoul(Argv[2], &pend, 0); + ul = strtoulptr(Argv[2], &pend, 0); if (Argv[2] == pend) { KdbpPrint("process attach: '%s' is not a valid process id!\n", Argv[2]); @@ -1849,8 +1899,8 @@ KdbpCmdProc( return TRUE; } - KdbpPrint("Attached to process 0x%08x, thread 0x%08x.\n", (ULONG)ul, - (ULONG)KdbCurrentThread->Cid.UniqueThread); + KdbpPrint("Attached to process 0x%p, thread 0x%p.\n", (PVOID)ul, + KdbCurrentThread->Cid.UniqueThread); } else { @@ -1858,7 +1908,7 @@ KdbpCmdProc( if (Argc >= 2) { - ul = strtoul(Argv[1], &pend, 0); + ul = strtoulptr(Argv[1], &pend, 0); if (Argv[1] == pend) { KdbpPrint("proc: '%s' is not a valid process id!\n", Argv[1]); @@ -1991,9 +2041,9 @@ KdbpCmdGdtLdtIdt( for (i = 0; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8) { - if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc)))) + if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc)))) { - KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i); + KdbpPrint("Couldn't access memory at 0x%p!\n", (PVOID)((ULONG_PTR)Reg.Base + i)); return TRUE; } @@ -2046,7 +2096,7 @@ KdbpCmdGdtLdtIdt( ASSERT(Argv[0][0] == 'l'); /* Read LDTR */ - Reg.Limit = Ke386GetLocalDescriptorTable(); + Ke386GetLocalDescriptorTable(&Reg.Limit); Reg.Base = 0; i = 0; ul = 1 << 2; @@ -2065,9 +2115,9 @@ KdbpCmdGdtLdtIdt( for (; (i + sizeof(SegDesc) - 1) <= Reg.Limit; i += 8) { - if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)(Reg.Base + i), sizeof(SegDesc)))) + if (!NT_SUCCESS(KdbpSafeReadMemory(SegDesc, (PVOID)((ULONG_PTR)Reg.Base + i), sizeof(SegDesc)))) { - KdbpPrint("Couldn't access memory at 0x%08x!\n", Reg.Base + i); + KdbpPrint("Couldn't access memory at 0x%p!\n", (ULONG_PTR)Reg.Base + i); return TRUE; } @@ -2194,36 +2244,80 @@ KdbpCmdPcr( " Tib.FiberData/Version: 0x%08x\n" " Tib.ArbitraryUserPointer: 0x%08x\n" " Tib.Self: 0x%08x\n" +#ifdef _M_IX86 " SelfPcr: 0x%08x\n" +#else + " Self: 0x%p\n" +#endif " PCRCB: 0x%08x\n" " Irql: 0x%02x\n" +#ifdef _M_IX86 " IRR: 0x%08x\n" " IrrActive: 0x%08x\n" " IDR: 0x%08x\n" +#endif " KdVersionBlock: 0x%08x\n" +#ifdef _M_IX86 " IDT: 0x%08x\n" " GDT: 0x%08x\n" " TSS: 0x%08x\n" +#endif " MajorVersion: 0x%04x\n" " MinorVersion: 0x%04x\n" +#ifdef _M_IX86 " SetMember: 0x%08x\n" +#endif " StallScaleFactor: 0x%08x\n" +#ifdef _M_IX86 " Number: 0x%02x\n" +#endif " L2CacheAssociativity: 0x%02x\n" +#ifdef _M_IX86 " VdmAlert: 0x%08x\n" +#endif " L2CacheSize: 0x%08x\n" - " InterruptMode: 0x%08x\n", - Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit, +#ifdef _M_IX86 + " InterruptMode: 0x%08x\n" +#endif + , Pcr->NtTib.ExceptionList, Pcr->NtTib.StackBase, Pcr->NtTib.StackLimit, Pcr->NtTib.SubSystemTib, Pcr->NtTib.FiberData, Pcr->NtTib.ArbitraryUserPointer, - Pcr->NtTib.Self, Pcr->SelfPcr, Pcr->Prcb, Pcr->Irql, Pcr->IRR, Pcr->IrrActive, - Pcr->IDR, Pcr->KdVersionBlock, Pcr->IDT, Pcr->GDT, Pcr->TSS, - Pcr->MajorVersion, Pcr->MinorVersion, Pcr->SetMember, Pcr->StallScaleFactor, - Pcr->Number, Pcr->SecondLevelCacheAssociativity, - Pcr->VdmAlert, Pcr->SecondLevelCacheSize, Pcr->InterruptMode); + Pcr->NtTib.Self +#ifdef _M_IX86 + , Pcr->SelfPcr +#else + , Pcr->Self +#endif + , Pcr->Prcb, Pcr->Irql +#ifdef _M_IX86 + , Pcr->IRR, Pcr->IrrActive , Pcr->IDR +#endif + , Pcr->KdVersionBlock +#ifdef _M_IX86 + , Pcr->IDT, Pcr->GDT, Pcr->TSS +#endif + , Pcr->MajorVersion, Pcr->MinorVersion +#ifdef _M_IX86 + , Pcr->SetMember +#endif + , Pcr->StallScaleFactor +#ifdef _M_IX86 + , Pcr->Number +#endif + , Pcr->SecondLevelCacheAssociativity +#ifdef _M_IX86 + , Pcr->VdmAlert +#endif + , Pcr->SecondLevelCacheSize +#ifdef _M_IX86 + , Pcr->InterruptMode +#endif + ); + return TRUE; } +#ifdef _M_IX86 /*!\brief Displays the TSS */ static BOOLEAN @@ -2321,6 +2415,7 @@ KdbpCmdTss( return TRUE; } +#endif /*!\brief Bugchecks the system. */ @@ -3613,13 +3708,13 @@ KdbpCliMainLoop( if (EnteredOnSingleStep) { - if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Eip, KdbCurrentTrapFrame)) + if (!KdbSymPrintAddress((PVOID)KeGetContextPc(KdbCurrentTrapFrame), KdbCurrentTrapFrame)) { - KdbpPrint("<%08x>", KdbCurrentTrapFrame->Eip); + KdbpPrint("<%p>", KeGetContextPc(KdbCurrentTrapFrame)); } KdbpPrint(": "); - if (KdbpDisassemble(KdbCurrentTrapFrame->Eip, KdbUseIntelSyntax) < 0) + if (KdbpDisassemble(KeGetContextPc(KdbCurrentTrapFrame), KdbUseIntelSyntax) < 0) { KdbpPrint(""); } diff --git a/ntoskrnl/kdbg/kdb_expr.c b/ntoskrnl/kdbg/kdb_expr.c index 9a1924852b6..69a57d8e8ae 100644 --- a/ntoskrnl/kdbg/kdb_expr.c +++ b/ntoskrnl/kdbg/kdb_expr.c @@ -111,8 +111,14 @@ static const struct } RegisterToTrapFrame[] = { + /* FIXME: X86 only */ +#ifdef _M_IX86 {"eip", FIELD_OFFSET(KDB_KTRAP_FRAME, Eip), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Eip)}, +#else + {"rip", FIELD_OFFSET(KDB_KTRAP_FRAME, Rip), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rip)}, +#endif {"eflags", FIELD_OFFSET(KDB_KTRAP_FRAME, EFlags), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, EFlags)}, +#ifdef _M_IX86 {"eax", FIELD_OFFSET(KDB_KTRAP_FRAME, Eax), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Eax)}, {"ebx", FIELD_OFFSET(KDB_KTRAP_FRAME, Ebx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ebx)}, {"ecx", FIELD_OFFSET(KDB_KTRAP_FRAME, Ecx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ecx)}, @@ -121,6 +127,16 @@ RegisterToTrapFrame[] = {"edi", FIELD_OFFSET(KDB_KTRAP_FRAME, Edi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Edi)}, {"esp", FIELD_OFFSET(KDB_KTRAP_FRAME, Esp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Esp)}, {"ebp", FIELD_OFFSET(KDB_KTRAP_FRAME, Ebp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Ebp)}, +#else + {"rax", FIELD_OFFSET(KDB_KTRAP_FRAME, Rax), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rax)}, + {"rbx", FIELD_OFFSET(KDB_KTRAP_FRAME, Rbx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rbx)}, + {"rcx", FIELD_OFFSET(KDB_KTRAP_FRAME, Rcx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rcx)}, + {"rdx", FIELD_OFFSET(KDB_KTRAP_FRAME, Rdx), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rdx)}, + {"rsi", FIELD_OFFSET(KDB_KTRAP_FRAME, Rsi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rsi)}, + {"rdi", FIELD_OFFSET(KDB_KTRAP_FRAME, Rdi), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rdi)}, + {"rsp", FIELD_OFFSET(KDB_KTRAP_FRAME, Rsp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rsp)}, + {"rbp", FIELD_OFFSET(KDB_KTRAP_FRAME, Rbp), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, Rbp)}, +#endif {"cs", FIELD_OFFSET(KDB_KTRAP_FRAME, SegCs), 2 }, /* Use only the lower 2 bytes */ {"ds", FIELD_OFFSET(KDB_KTRAP_FRAME, SegDs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegDs)}, {"es", FIELD_OFFSET(KDB_KTRAP_FRAME, SegEs), RTL_FIELD_SIZE(KDB_KTRAP_FRAME, SegEs)}, @@ -1009,7 +1025,7 @@ RpnpEvaluateStack( if (!Ok) { - _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%lx", (ULONG)p); + _snprintf(ErrMsg, 128, "Couldn't access memory at 0x%p", p); if (ErrOffset) *ErrOffset = Op->CharacterOffset; diff --git a/ntoskrnl/ke/i386/cpu.c b/ntoskrnl/ke/i386/cpu.c index 043ab2b62d2..3b07453af53 100644 --- a/ntoskrnl/ke/i386/cpu.c +++ b/ntoskrnl/ke/i386/cpu.c @@ -979,7 +979,7 @@ KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState) Ke386GetGlobalDescriptorTable(&ProcessorState->SpecialRegisters.Gdtr.Limit); __sidt(&ProcessorState->SpecialRegisters.Idtr.Limit); ProcessorState->SpecialRegisters.Tr = Ke386GetTr(); - ProcessorState->SpecialRegisters.Ldtr = Ke386GetLocalDescriptorTable(); + Ke386GetLocalDescriptorTable(&ProcessorState->SpecialRegisters.Ldtr); } CODE_SEG("INIT") diff --git a/ntoskrnl/ntos.cmake b/ntoskrnl/ntos.cmake index c392bcd95ec..dbb9f911016 100644 --- a/ntoskrnl/ntos.cmake +++ b/ntoskrnl/ntos.cmake @@ -395,6 +395,10 @@ if(NOT _WINKD_) elseif(ARCH STREQUAL "amd64") list(APPEND SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/i386/kdbg.c) + if(KDBG) + list(APPEND ASM_SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/amd64/kdb_help.S) + list(APPEND SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kdbg/i386/i386-dis.c) + endif() elseif(ARCH STREQUAL "arm") list(APPEND SOURCE ${REACTOS_SOURCE_DIR}/ntoskrnl/kd/arm/kdbg.c) endif()