ReactOS 0.4.16-dev-178-g8ba6102
kdb.c File Reference
#include <ntoskrnl.h>
#include "kdb.h"
Include dependency graph for kdb.c:

Go to the source code of this file.

Macros

#define KDB_STACK_SIZE   (4096*3)
 
#define KDB_STACK_ALIGN   4
 
#define KDB_STACK_RESERVE   sizeof(ULONG) /* Return address */
 
#define KDB_MAXIMUM_BREAKPOINT_COUNT   256
 
#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT   4
 
#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT   256
 
#define __STRING(x)   #x
 
#define _STRING(x)   __STRING(x)
 
#define CONST_STR_LEN(x)   (sizeof(x)/sizeof(x[0]) - 1)
 

Functions

static DECLSPEC_ALIGN (KDB_STACK_ALIGN)
 
static VOID KdbpKdbTrapFrameFromKernelStack (PVOID KernelStack, PKDB_KTRAP_FRAME KdbTrapFrame)
 
static NTSTATUS KdbpOverwriteInstruction (IN PEPROCESS Process, IN ULONG_PTR Address, IN UCHAR NewInst, OUT PUCHAR OldInst OPTIONAL)
 Overwrites the instruction at Address with NewInst and stores the old instruction in *OldInst.
 
BOOLEAN KdbpShouldStepOverInstruction (ULONG_PTR Eip)
 Checks whether the given instruction can be single stepped or has to be stepped over using a temporary breakpoint.
 
BOOLEAN KdbpStepOverInstruction (ULONG_PTR Eip)
 Steps over an instruction.
 
BOOLEAN KdbpStepIntoInstruction (ULONG_PTR Eip)
 Steps into an instruction (interrupts)
 
LONG KdbpGetNextBreakPointNr (IN ULONG Start OPTIONAL)
 Gets the number of the next breakpoint >= Start.
 
BOOLEAN KdbpGetBreakPointInfo (IN ULONG BreakPointNr, OUT ULONG_PTR *Address OPTIONAL, OUT KDB_BREAKPOINT_TYPE *Type OPTIONAL, OUT UCHAR *Size OPTIONAL, OUT KDB_ACCESS_TYPE *AccessType OPTIONAL, OUT UCHAR *DebugReg OPTIONAL, OUT BOOLEAN *Enabled OPTIONAL, OUT BOOLEAN *Global OPTIONAL, OUT PEPROCESS *Process OPTIONAL, OUT PCHAR *ConditionExpression OPTIONAL)
 Returns information of the specified breakpoint.
 
NTSTATUS KdbpInsertBreakPoint (IN ULONG_PTR Address, IN KDB_BREAKPOINT_TYPE Type, IN UCHAR Size OPTIONAL, IN KDB_ACCESS_TYPE AccessType OPTIONAL, IN PCHAR ConditionExpression OPTIONAL, IN BOOLEAN Global, OUT PLONG BreakPointNr OPTIONAL)
 Inserts a breakpoint into the breakpoint array.
 
BOOLEAN KdbpDeleteBreakPoint (IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
 Deletes a breakpoint.
 
static LONG KdbpIsBreakPointOurs (IN NTSTATUS ExceptionCode, IN PCONTEXT Context)
 Checks if the breakpoint was set by the debugger.
 
BOOLEAN KdbpEnableBreakPoint (IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
 Enables a breakpoint.
 
BOOLEAN KdbpDisableBreakPoint (IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
 Disables a breakpoint.
 
BOOLEAN KdbpGetEnterCondition (IN LONG ExceptionNr, IN BOOLEAN FirstChance, OUT KDB_ENTER_CONDITION *Condition)
 Gets the first or last chance enter-condition for exception nr. ExceptionNr.
 
BOOLEAN KdbpSetEnterCondition (IN LONG ExceptionNr, IN BOOLEAN FirstChance, IN KDB_ENTER_CONDITION Condition)
 Sets the first or last chance enter-condition for exception nr. ExceptionNr.
 
BOOLEAN KdbpAttachToThread (PVOID ThreadId)
 Switches to another thread context.
 
BOOLEAN KdbpAttachToProcess (PVOID ProcessId)
 Switches to another process/thread context.
 
static VOID KdbpCallMainLoop (VOID)
 Calls the main interactive debugger loop.
 
static VOID KdbpInternalEnter (_In_ VOID(*Procedure)(VOID))
 Internal function to enter KDBG and run the specified procedure.
 
static ULONG KdbpGetExceptionNumberFromStatus (IN NTSTATUS ExceptionCode)
 
KD_CONTINUE_TYPE KdbEnterDebuggerException (IN PEXCEPTION_RECORD64 ExceptionRecord, IN KPROCESSOR_MODE PreviousMode, IN PCONTEXT Context, IN BOOLEAN FirstChance)
 KDB Exception filter.
 
VOID KdbpGetCommandLineSettings (_In_ PCSTR p1)
 
NTSTATUS KdbpSafeReadMemory (OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
 
NTSTATUS KdbpSafeWriteMemory (OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
 

Variables

static LONG KdbEntryCount = 0
 
static ULONG KdbSwBreakPointCount = 0
 
static ULONG KdbHwBreakPointCount = 0
 
static PKDB_BREAKPOINT KdbSwBreakPoints [KDB_MAXIMUM_SW_BREAKPOINT_COUNT]
 
static PKDB_BREAKPOINT KdbHwBreakPoints [KDB_MAXIMUM_HW_BREAKPOINT_COUNT]
 
static PKDB_BREAKPOINT KdbBreakPointToReenable = NULL
 
static BOOLEAN KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep
 
LONG KdbLastBreakPointNr = -1
 
ULONG KdbNumSingleSteps = 0
 
BOOLEAN KdbSingleStepOver = FALSE
 
static BOOLEAN KdbEnteredOnSingleStep = FALSE
 
PEPROCESS KdbCurrentProcess = NULL
 
PEPROCESS KdbOriginalProcess = NULL
 
PETHREAD KdbCurrentThread = NULL
 
PETHREAD KdbOriginalThread = NULL
 
PKDB_KTRAP_FRAME KdbCurrentTrapFrame = NULL
 
static KDB_KTRAP_FRAME KdbTrapFrame = { 0 }
 
static KDB_KTRAP_FRAME KdbThreadTrapFrame = { 0 }
 
static KAPC_STATE KdbApcState
 
BOOLEAN KdbpBugCheckRequested
 
static KDB_ENTER_CONDITION KdbEnterConditions [][2]
 
static const CHARExceptionNrToString []
 

Macro Definition Documentation

◆ __STRING

#define __STRING (   x)    #x

Definition at line 31 of file kdb.c.

◆ _STRING

#define _STRING (   x)    __STRING(x)

Definition at line 32 of file kdb.c.

◆ CONST_STR_LEN

#define CONST_STR_LEN (   x)    (sizeof(x)/sizeof(x[0]) - 1)

◆ KDB_MAXIMUM_BREAKPOINT_COUNT

#define KDB_MAXIMUM_BREAKPOINT_COUNT   256

Definition at line 27 of file kdb.c.

◆ KDB_MAXIMUM_HW_BREAKPOINT_COUNT

#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT   4

Definition at line 28 of file kdb.c.

◆ KDB_MAXIMUM_SW_BREAKPOINT_COUNT

#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT   256

Definition at line 29 of file kdb.c.

◆ KDB_STACK_ALIGN

#define KDB_STACK_ALIGN   4

Definition at line 24 of file kdb.c.

◆ KDB_STACK_RESERVE

#define KDB_STACK_RESERVE   sizeof(ULONG) /* Return address */

Definition at line 25 of file kdb.c.

◆ KDB_STACK_SIZE

#define KDB_STACK_SIZE   (4096*3)

Definition at line 19 of file kdb.c.

Function Documentation

◆ DECLSPEC_ALIGN()

static DECLSPEC_ALIGN ( KDB_STACK_ALIGN  )
static

Definition at line 37 of file kdb.c.

40 {{0}}; /* Breakpoint array */

◆ KdbEnterDebuggerException()

KD_CONTINUE_TYPE KdbEnterDebuggerException ( IN PEXCEPTION_RECORD64  ExceptionRecord,
IN KPROCESSOR_MODE  PreviousMode,
IN PCONTEXT  Context,
IN BOOLEAN  FirstChance 
)

KDB Exception filter.

Called by the exception dispatcher.

Parameters
ExceptionRecordUnused.
PreviousModeUserMode if the exception was raised from umode, otherwise KernelMode.
ContextContext, IN/OUT parameter.
TrapFrameException TrapFrame.
FirstChanceTRUE when called before exception frames were serached, FALSE for the second call.
Returns
KD_CONTINUE_TYPE

Definition at line 1272 of file kdb.c.

1277{
1278 KDB_ENTER_CONDITION EnterCondition;
1279 KD_CONTINUE_TYPE ContinueType = kdHandleException;
1280 PKDB_BREAKPOINT BreakPoint;
1281 ULONG ExpNr;
1282 ULONGLONG ull;
1283 BOOLEAN Resume = FALSE;
1284 BOOLEAN EnterConditionMet = TRUE;
1285 ULONG OldEflags;
1286 KIRQL OldIrql;
1288 VOID (*EntryPoint)(VOID) = KdbpCallMainLoop;
1289
1290 ExceptionCode = (ExceptionRecord ? ExceptionRecord->ExceptionCode : STATUS_BREAKPOINT);
1291
1293
1294 /* Set continue type to kdContinue for single steps and breakpoints */
1298 {
1299 ContinueType = kdContinue;
1300 }
1301
1302 /* Check if we should handle the exception. */
1303 /* FIXME - won't get all exceptions here :( */
1305 EnterCondition = KdbEnterConditions[ExpNr][FirstChance ? 0 : 1];
1306 if (EnterCondition == KdbDoNotEnter ||
1307 (EnterCondition == KdbEnterFromUmode && PreviousMode == KernelMode) ||
1308 (EnterCondition == KdbEnterFromKmode && PreviousMode != KernelMode))
1309 {
1310 EnterConditionMet = FALSE;
1311 }
1312
1313 /* If we stopped on one of our breakpoints then let the user know */
1316
1317 if (FirstChance && (ExceptionCode == STATUS_SINGLE_STEP || ExceptionCode == STATUS_BREAKPOINT) &&
1319 {
1320 BreakPoint = KdbBreakPoints + KdbLastBreakPointNr;
1321
1323 {
1324 /* ... and restore the original instruction */
1326 BreakPoint->Data.SavedInstruction, NULL)))
1327 {
1328 KdbPuts("Couldn't restore original instruction after INT3! Cannot continue execution.\n");
1329 KeBugCheck(0); // FIXME: Proper bugcode!
1330 }
1331
1332 /* Also since we are past the int3 now, decrement EIP in the
1333 TrapFrame. This is only needed because KDBG insists on working
1334 with the TrapFrame instead of with the Context, as it is supposed
1335 to do. The context has already EIP point to the int3, since
1336 KiDispatchException accounts for that. Whatever we do here with
1337 the TrapFrame does not matter anyway, since KiDispatchException
1338 will overwrite it with the values from the Context! */
1340 }
1341
1342 if ((BreakPoint->Type == KdbBreakPointHardware) &&
1343 (BreakPoint->Data.Hw.AccessType == KdbAccessExec))
1344 {
1345 Resume = TRUE; /* Set the resume flag when continuing execution */
1346 }
1347 /*
1348 * When a temporary breakpoint is hit we have to make sure that we are
1349 * in the same context in which it was set, otherwise it could happen
1350 * that another process/thread hits it before and it gets deleted.
1351 */
1352 else if (BreakPoint->Type == KdbBreakPointTemporary &&
1353 BreakPoint->Process == KdbCurrentProcess)
1354 {
1355 ASSERT((Context->EFlags & EFLAGS_TF) == 0);
1356
1357 /* Delete the temporary breakpoint which was used to step over or into the instruction */
1358 KdbpDeleteBreakPoint(-1, BreakPoint);
1359
1360 if (--KdbNumSingleSteps > 0)
1361 {
1364 {
1365 Context->EFlags |= EFLAGS_TF;
1366 }
1367
1368 goto continue_execution; /* return */
1369 }
1370
1372 }
1373 /*
1374 * If we hit a breakpoint set by the debugger we set the single step flag,
1375 * ignore the next single step and reenable the breakpoint.
1376 */
1377 else if (BreakPoint->Type == KdbBreakPointSoftware ||
1378 BreakPoint->Type == KdbBreakPointTemporary)
1379 {
1381 Context->EFlags |= EFLAGS_TF;
1382 KdbBreakPointToReenable = BreakPoint;
1383 }
1384
1385 /* Make sure that the breakpoint should be triggered in this context */
1386 if (!BreakPoint->Global && BreakPoint->Process != KdbCurrentProcess)
1387 {
1388 goto continue_execution; /* return */
1389 }
1390
1391 /* Check if the condition for the breakpoint is met. */
1392 if (BreakPoint->Condition)
1393 {
1394 /* Setup the KDB trap frame */
1396
1397 ull = 0;
1399 {
1400 /* FIXME: Print warning? */
1401 }
1402 else if (ull == 0) /* condition is not met */
1403 {
1404 goto continue_execution; /* return */
1405 }
1406 }
1407
1408 if (BreakPoint->Type == KdbBreakPointSoftware)
1409 {
1410 KdbPrintf("\nEntered debugger on breakpoint #%d: EXEC 0x%04x:0x%p\n",
1412 }
1413 else if (BreakPoint->Type == KdbBreakPointHardware)
1414 {
1415 KdbPrintf("\nEntered debugger on breakpoint #%d: %s 0x%08x\n",
1417 (BreakPoint->Data.Hw.AccessType == KdbAccessRead) ? "READ" :
1418 ((BreakPoint->Data.Hw.AccessType == KdbAccessWrite) ? "WRITE" :
1419 ((BreakPoint->Data.Hw.AccessType == KdbAccessReadWrite) ? "RDWR" : "EXEC")),
1420 BreakPoint->Address);
1421 }
1422 }
1424 {
1425 /* Silently ignore a debugger initiated single step. */
1426 if ((Context->Dr6 & 0xf) == 0 && KdbBreakPointToReenable)
1427 {
1428 /* FIXME: Make sure that the breakpoint was really hit (check bp->Address vs. tf->Eip) */
1429 BreakPoint = KdbBreakPointToReenable;
1431 ASSERT(BreakPoint->Type == KdbBreakPointSoftware ||
1432 BreakPoint->Type == KdbBreakPointTemporary);
1433
1434 /*
1435 * Reenable the breakpoint we disabled to execute the breakpointed
1436 * instruction.
1437 */
1439 &BreakPoint->Data.SavedInstruction)))
1440 {
1441 KdbPrintf("Warning: Couldn't reenable breakpoint %d\n",
1442 BreakPoint - KdbBreakPoints);
1443 }
1444
1445 /* Unset TF if we are no longer single stepping. */
1446 if (KdbNumSingleSteps == 0)
1447 Context->EFlags &= ~EFLAGS_TF;
1448
1450 {
1451 goto continue_execution; /* return */
1452 }
1453 }
1454
1455 /* Quoth the raven, 'Nevermore!' */
1457
1458 /* Check if we expect a single step */
1459 if ((Context->Dr6 & 0xf) == 0 && KdbNumSingleSteps > 0)
1460 {
1461 /*ASSERT((Context->Eflags & EFLAGS_TF) != 0);*/
1462 if (--KdbNumSingleSteps > 0)
1463 {
1466 {
1467 Context->EFlags &= ~EFLAGS_TF;
1468 }
1469 else
1470 {
1471 Context->EFlags |= EFLAGS_TF;
1472 }
1473
1474 goto continue_execution; /* return */
1475 }
1476 else
1477 {
1478 Context->EFlags &= ~EFLAGS_TF;
1480 }
1481 }
1482 else
1483 {
1484 if (!EnterConditionMet)
1485 {
1486 return kdHandleException;
1487 }
1488
1489 KdbPuts("\nEntered debugger on unexpected debug trap!\n");
1490 }
1491 }
1492 else if (ExceptionCode == STATUS_BREAKPOINT)
1493 {
1494 /* Do the condition check and banner display only if we enter
1495 * from a true code breakpoint. We skip those when running the
1496 * KDBinit file, because it is done via an artificial breakpoint. */
1498 {
1499 EntryPoint = KdbpCliInterpretInitFile;
1500 goto EnterKdbg;
1501 }
1502
1503 if (!EnterConditionMet)
1504 {
1505 return kdHandleException;
1506 }
1507
1508 KdbPrintf("\nEntered debugger on embedded INT3 at 0x%04x:0x%p.\n",
1509 Context->SegCs & 0xffff, KeGetContextPc(Context));
1510EnterKdbg:;
1511 }
1512 else
1513 {
1514 const CHAR *ExceptionString = (ExpNr < RTL_NUMBER_OF(ExceptionNrToString)) ?
1515 ExceptionNrToString[ExpNr] :
1516 "Unknown/User defined exception";
1517
1518 if (!EnterConditionMet)
1519 {
1520 return ContinueType;
1521 }
1522
1523 KdbPrintf("\nEntered debugger on %s-chance exception (Exception Code: 0x%x) (%s)\n",
1524 FirstChance ? "first" : "last", ExceptionCode, ExceptionString);
1525
1527 ExceptionRecord && ExceptionRecord->NumberParameters != 0)
1528 {
1529 ULONG_PTR TrapCr2 = __readcr2();
1530 KdbPrintf("Memory at 0x%p could not be accessed\n", TrapCr2);
1531 }
1532 }
1533
1534 /* Once we enter the debugger we do not expect any more single steps to happen */
1536
1537 /* Update the current process pointer */
1541
1542 /* Setup the KDB trap frame */
1544
1545 /* Enter critical section */
1546 OldEflags = __readeflags();
1547 _disable();
1548
1549 /* HACK: Save the current IRQL and pretend we are at dispatch level */
1551 if (OldIrql > DISPATCH_LEVEL)
1553
1554 /* Exception inside the debugger? Game over. */
1556 {
1557 __writeeflags(OldEflags);
1558 return kdHandleException;
1559 }
1560
1561 /* Enter KDBG proper and run either the main loop or the KDBinit file */
1562 KdbpInternalEnter(EntryPoint);
1563
1564 /* Check if we should single step */
1565 if (KdbNumSingleSteps > 0)
1566 {
1567 /* Variable explains itself! */
1569
1572 {
1574 /*KdbCurrentTrapFrame->EFlags &= ~EFLAGS_TF;*/
1575 }
1576 else
1577 {
1579 }
1580 }
1581
1582 /* We can't update the current thread's trapframe 'cause it might not have one */
1583
1584 /* Detach from attached process */
1586 {
1588 }
1589
1590 /* Update the exception Context */
1592
1593 /* Decrement the entry count */
1595
1596 /* HACK: Raise back to old IRQL */
1597 if (OldIrql > DISPATCH_LEVEL)
1599
1600 /* Leave critical section */
1601 __writeeflags(OldEflags);
1602
1603 /* Check if user requested a bugcheck */
1605 {
1606 /* Clear the flag and bugcheck the system */
1608 KeBugCheck(MANUALLY_INITIATED_CRASH);
1609 }
1610
1611continue_execution:
1612 /* Clear debug status */
1613 if (ExceptionCode == STATUS_BREAKPOINT) /* FIXME: Why clear DR6 on INT3? */
1614 {
1615 /* Set the RF flag so we don't trigger the same breakpoint again. */
1616 if (Resume)
1617 {
1618 Context->EFlags |= EFLAGS_RF;
1619 }
1620
1621 /* Clear dr6 status flags. */
1622 Context->Dr6 &= ~0x0000e00f;
1623
1625 {
1626 /* Skip the current instruction */
1628 }
1629 }
1630
1631 return ContinueType;
1632}
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define EFLAGS_TF
Definition: SystemCall.c:10
#define VOID
Definition: acefi.h:82
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
DECLSPEC_NORETURN VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1430
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
void __cdecl _disable(void)
Definition: intrin_arm.h:365
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
__INTRIN_INLINE unsigned long __readcr2(void)
Definition: intrin_x86.h:1811
PEPROCESS KdbCurrentProcess
Definition: kdb.c:52
PETHREAD KdbCurrentThread
Definition: kdb.c:54
PETHREAD KdbOriginalThread
Definition: kdb.c:55
static PKDB_BREAKPOINT KdbBreakPointToReenable
Definition: kdb.c:45
PKDB_KTRAP_FRAME KdbCurrentTrapFrame
Definition: kdb.c:56
static LONG KdbpIsBreakPointOurs(IN NTSTATUS ExceptionCode, IN PCONTEXT Context)
Checks if the breakpoint was set by the debugger.
Definition: kdb.c:649
static VOID KdbpInternalEnter(_In_ VOID(*Procedure)(VOID))
Internal function to enter KDBG and run the specified procedure.
Definition: kdb.c:1165
static KDB_KTRAP_FRAME KdbTrapFrame
Definition: kdb.c:57
static BOOLEAN KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep
Definition: kdb.c:47
PEPROCESS KdbOriginalProcess
Definition: kdb.c:53
BOOLEAN KdbpBugCheckRequested
Definition: kdb_cli.c:138
BOOLEAN KdbpStepIntoInstruction(ULONG_PTR Eip)
Steps into an instruction (interrupts)
Definition: kdb.c:300
static NTSTATUS KdbpOverwriteInstruction(IN PEPROCESS Process, IN ULONG_PTR Address, IN UCHAR NewInst, OUT PUCHAR OldInst OPTIONAL)
Overwrites the instruction at Address with NewInst and stores the old instruction in *OldInst.
Definition: kdb.c:155
static KDB_ENTER_CONDITION KdbEnterConditions[][2]
Definition: kdb.c:63
static BOOLEAN KdbEnteredOnSingleStep
Definition: kdb.c:51
LONG KdbLastBreakPointNr
Definition: kdb.c:48
static LONG KdbEntryCount
Definition: kdb.c:36
BOOLEAN KdbSingleStepOver
Definition: kdb.c:50
BOOLEAN KdbpDeleteBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Deletes a breakpoint.
Definition: kdb.c:599
ULONG KdbNumSingleSteps
Definition: kdb.c:49
static const CHAR * ExceptionNrToString[]
Definition: kdb.c:91
BOOLEAN KdbpStepOverInstruction(ULONG_PTR Eip)
Steps over an instruction.
Definition: kdb.c:272
static VOID KdbpCallMainLoop(VOID)
Calls the main interactive debugger loop.
Definition: kdb.c:1148
static ULONG KdbpGetExceptionNumberFromStatus(IN NTSTATUS ExceptionCode)
Definition: kdb.c:1206
static KAPC_STATE KdbApcState
Definition: kdb.c:59
enum _KD_CONTINUE_TYPE KD_CONTINUE_TYPE
enum _KDB_ENTER_CONDITION KDB_ENTER_CONDITION
@ KdbBreakPointSoftware
Definition: kdb.h:12
@ KdbBreakPointTemporary
Definition: kdb.h:14
@ KdbBreakPointHardware
Definition: kdb.h:13
VOID KdbpCliInterpretInitFile(VOID)
Interprets the KDBinit file from the \SystemRoot\System32\drivers\etc directory, that has been loaded...
Definition: kdb_cli.c:3351
BOOLEAN KdbpRpnEvaluateParsedExpression(IN PVOID Expression, IN PKDB_KTRAP_FRAME TrapFrame, OUT PULONGLONG Result, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Evaluates the given expression and returns the result.
Definition: kdb_expr.c:1200
volatile PCHAR KdbInitFileBuffer
Definition: kdb_cli.c:137
@ kdContinue
Definition: kdb.h:56
@ kdHandleException
Definition: kdb.h:58
VOID KdbPuts(_In_ PCSTR String)
Definition: kdb_print.c:152
@ KdbAccessExec
Definition: kdb.h:22
@ KdbAccessRead
Definition: kdb.h:19
@ KdbAccessReadWrite
Definition: kdb.h:21
@ KdbAccessWrite
Definition: kdb.h:20
@ KdbDoNotEnter
Definition: kdb.h:48
@ KdbEnterFromUmode
Definition: kdb.h:51
@ KdbEnterFromKmode
Definition: kdb.h:50
VOID __cdecl KdbPrintf(_In_ PCSTR Format,...)
Definition: kdb_print.c:160
#define ASSERT(a)
Definition: mode.c:44
#define KernelMode
Definition: asm.h:34
#define EFLAGS_RF
Definition: ketypes.h:181
#define KD_BREAKPOINT_SIZE
Definition: ke.h:122
#define KeSetContextPc(Context, ProgramCounter)
Definition: ke.h:34
#define KeGetContextPc(Context)
Definition: ke.h:31
#define STATUS_ASSERTION_FAILURE
Definition: ntstatus.h:960
#define STATUS_SINGLE_STEP
Definition: ntstatus.h:185
#define STATUS_BREAKPOINT
Definition: ntstatus.h:184
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:756
ULONG EFlags
Definition: nt_native.h:1478
PVOID Condition
Definition: kdb.h:33
UCHAR SavedInstruction
Definition: kdb.h:36
union _KDB_BREAKPOINT::@1817 Data
ULONG_PTR Address
Definition: kdb.h:29
PEPROCESS Process
Definition: kdb.h:31
KDB_BREAKPOINT_TYPE Type
Definition: kdb.h:27
BOOLEAN Global
Definition: kdb.h:30
struct _KDB_BREAKPOINT::@1817::@1818 Hw
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778
#define PsGetCurrentProcess
Definition: psfuncs.h:17
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
char CHAR
Definition: xmlstorage.h:175

Referenced by KdSendPacket().

◆ KdbpAttachToProcess()

BOOLEAN KdbpAttachToProcess ( PVOID  ProcessId)

Switches to another process/thread context.

This function switches to the first thread in the specified process.

Parameters
ProcessIdId of the process to switch to.
Return values
TRUESuccess.
FALSEFailure (i.e. invalid process id)

Definition at line 1117 of file kdb.c.

1119{
1123
1124 /* Get a pointer to the process */
1126 {
1127 KdbpPrint("Invalid process id: 0x%08x\n", (ULONG_PTR)ProcessId);
1128 return FALSE;
1129 }
1130
1131 Entry = Process->ThreadListHead.Flink;
1134 {
1135 KdbpPrint("No threads in process 0x%p, cannot attach to process!\n", ProcessId);
1136 return FALSE;
1137 }
1138
1139 Thread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
1140
1142}
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ProcessId
Definition: fatprocs.h:2712
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
BOOLEAN KdbpAttachToThread(PVOID ThreadId)
Switches to another thread context.
Definition: kdb.c:1036
VOID KdbpPrint(_In_ PSTR Format, _In_ ...)
Prints the given string with printf-like formatting.
Definition: kdb_cli.c:3081
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process)
Definition: process.c:919
base of all file and directory entries
Definition: entries.h:83
HANDLE UniqueThread
Definition: compat.h:826
LIST_ENTRY ThreadListHead
Definition: pstypes.h:1330
CLIENT_ID Cid
Definition: pstypes.h:1129
Definition: typedefs.h:120
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by KdbpCmdProc().

◆ KdbpAttachToThread()

BOOLEAN KdbpAttachToThread ( PVOID  ThreadId)

Switches to another thread context.

Parameters
ThreadIdId of the thread to switch to.
Return values
TRUESuccess.
FALSEFailure (i.e. invalid thread id)

Definition at line 1036 of file kdb.c.

1038{
1041
1042 /* Get a pointer to the thread */
1043 if (!NT_SUCCESS(PsLookupThreadByThreadId(ThreadId, &Thread)))
1044 {
1045 KdbpPrint("Invalid thread id: 0x%08x\n", (ULONG_PTR)ThreadId);
1046 return FALSE;
1047 }
1048 Process = Thread->ThreadsProcess;
1049
1051 {
1052 KdbpPrint("Cannot attach to thread within another process while executing a DPC.\n");
1054 return FALSE;
1055 }
1056
1057 /* Save the current thread's context (if we previously attached to a thread) */
1059 {
1061 /* Actually, we can't save the context, there's no guarantee that there was a trap frame */
1062 }
1063 else
1064 {
1066 }
1067
1068 /* Switch to the thread's context */
1070 {
1071 /* The thread we're attaching to isn't the thread on which we entered
1072 * kdb and so the thread we're attaching to is not running. There
1073 * is no guarantee that it actually has a trap frame. So we have to
1074 * peek directly at the registers which were saved on the stack when the
1075 * thread was preempted in the scheduler */
1079 }
1080 else /* Switching back to original thread */
1081 {
1083 }
1085
1086 /* Attach to the thread's process */
1089 {
1090 if (KdbCurrentProcess != KdbOriginalProcess) /* detach from previously attached process */
1091 {
1093 }
1094
1096 {
1098 }
1099
1101 }
1102
1104 return TRUE;
1105}
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:965
static KDB_KTRAP_FRAME KdbThreadTrapFrame
Definition: kdb.c:58
static VOID KdbpKdbTrapFrameFromKernelStack(PVOID KernelStack, PKDB_KTRAP_FRAME KdbTrapFrame)
Definition: kdb.c:119
NTSTATUS NTAPI PsLookupThreadByThreadId(IN HANDLE ThreadId, OUT PETHREAD *Thread)
Definition: thread.c:643
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:704
KTHREAD Tcb
Definition: pstypes.h:1104
PVOID KernelStack
Definition: ketypes.h:1675

Referenced by KdbpAttachToProcess(), and KdbpCmdThread().

◆ KdbpCallMainLoop()

static VOID KdbpCallMainLoop ( VOID  )
static

Calls the main interactive debugger loop.

Definition at line 1148 of file kdb.c.

1149{
1151}
VOID KdbpCliMainLoop(IN BOOLEAN EnteredOnSingleStep)
KDB Main Loop.
Definition: kdb_cli.c:3274

Referenced by KdbEnterDebuggerException().

◆ KdbpDeleteBreakPoint()

BOOLEAN KdbpDeleteBreakPoint ( IN LONG BreakPointNr  OPTIONAL,
IN OUT PKDB_BREAKPOINT BreakPoint  OPTIONAL 
)

Deletes a breakpoint.

Parameters
BreakPointNrNumber of the breakpoint to delete. Can be -1
BreakPointBreakpoint to delete. Can be NULL.
Return values
TRUESuccess.
FALSEFailure (invalid breakpoint number)

Definition at line 599 of file kdb.c.

602{
603 if (BreakPointNr < 0)
604 {
605 ASSERT(BreakPoint);
606 BreakPointNr = BreakPoint - KdbBreakPoints;
607 }
608
609 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
610 {
611 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
612 return FALSE;
613 }
614
615 if (!BreakPoint)
616 {
617 BreakPoint = KdbBreakPoints + BreakPointNr;
618 }
619
620 if (BreakPoint->Type == KdbBreakPointNone)
621 {
622 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
623 return FALSE;
624 }
625
626 if (BreakPoint->Enabled && !KdbpDisableBreakPoint(-1, BreakPoint))
627 return FALSE;
628
629 if (BreakPoint->Type != KdbBreakPointTemporary)
630 KdbPrintf("Breakpoint %d deleted.\n", BreakPointNr);
631
632 BreakPoint->Type = KdbBreakPointNone;
633 KdbBreakPointCount--;
634
635 return TRUE;
636}
BOOLEAN KdbpDisableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Disables a breakpoint.
Definition: kdb.c:868
#define KDB_MAXIMUM_BREAKPOINT_COUNT
Definition: kdb.c:27
@ KdbBreakPointNone
Definition: kdb.h:11

Referenced by KdbEnterDebuggerException(), and KdbpCmdEnableDisableClearBreakPoint().

◆ KdbpDisableBreakPoint()

BOOLEAN KdbpDisableBreakPoint ( IN LONG BreakPointNr  OPTIONAL,
IN OUT PKDB_BREAKPOINT BreakPoint  OPTIONAL 
)

Disables a breakpoint.

Parameters
BreakPointNrNumber of the breakpoint to disable. Can be -1
BreakPointBreakpoint to disable. Can be NULL.
Return values
TRUESuccess.
FALSEFailure.
See also
KdbpEnableBreakPoint

Definition at line 868 of file kdb.c.

871{
872 ULONG i;
874
875 if (BreakPointNr < 0)
876 {
877 ASSERT(BreakPoint);
878 BreakPointNr = BreakPoint - KdbBreakPoints;
879 }
880
881 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
882 {
883 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
884 return FALSE;
885 }
886
887 if (!BreakPoint)
888 {
889 BreakPoint = KdbBreakPoints + BreakPointNr;
890 }
891
892 if (BreakPoint->Type == KdbBreakPointNone)
893 {
894 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
895 return FALSE;
896 }
897
898 if (BreakPoint->Enabled == FALSE)
899 {
900 KdbPrintf("Breakpoint %d is not enabled.\n", BreakPointNr);
901 return TRUE;
902 }
903
904 if (BreakPoint->Type == KdbBreakPointSoftware ||
905 BreakPoint->Type == KdbBreakPointTemporary)
906 {
908 Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
909 BreakPoint->Data.SavedInstruction, NULL);
910
911 if (!NT_SUCCESS(Status))
912 {
913 KdbPuts("Couldn't restore original instruction.\n");
914 return FALSE;
915 }
916
917 for (i = 0; i < KdbSwBreakPointCount; i++)
918 {
919 if (KdbSwBreakPoints[i] == BreakPoint)
920 {
922 i = -1; /* if the last breakpoint is disabled dont break with i >= KdbSwBreakPointCount */
923 break;
924 }
925 }
926
927 if (i != MAXULONG) /* not found */
928 ASSERT(0);
929 }
930 else
931 {
932 ASSERT(BreakPoint->Type == KdbBreakPointHardware);
933
934 /* Clear the breakpoint. */
935 KdbTrapFrame.Dr7 &= ~(0x3 << (BreakPoint->Data.Hw.DebugReg * 2));
936 if ((KdbTrapFrame.Dr7 & 0xFF) == 0)
937 {
938 /* If no breakpoints are enabled then clear the exact match flags. */
939 KdbTrapFrame.Dr7 &= 0xFFFFFCFF;
940 }
941
942 for (i = 0; i < KdbHwBreakPointCount; i++)
943 {
944 if (KdbHwBreakPoints[i] == BreakPoint)
945 {
947 i = -1; /* if the last breakpoint is disabled dont break with i >= KdbHwBreakPointCount */
948 break;
949 }
950 }
951
952 if (i != MAXULONG) /* not found */
953 ASSERT(0);
954 }
955
956 BreakPoint->Enabled = FALSE;
957 if (BreakPoint->Type != KdbBreakPointTemporary)
958 KdbPrintf("Breakpoint %d disabled.\n", BreakPointNr);
959
960 return TRUE;
961}
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static PKDB_BREAKPOINT KdbHwBreakPoints[KDB_MAXIMUM_HW_BREAKPOINT_COUNT]
Definition: kdb.c:44
static PKDB_BREAKPOINT KdbSwBreakPoints[KDB_MAXIMUM_SW_BREAKPOINT_COUNT]
Definition: kdb.c:43
static ULONG KdbSwBreakPointCount
Definition: kdb.c:41
static ULONG KdbHwBreakPointCount
Definition: kdb.c:42
ULONG Dr7
Definition: nt_native.h:1439
#define MAXULONG
Definition: typedefs.h:251

Referenced by KdbpCmdEnableDisableClearBreakPoint(), and KdbpDeleteBreakPoint().

◆ KdbpEnableBreakPoint()

BOOLEAN KdbpEnableBreakPoint ( IN LONG BreakPointNr  OPTIONAL,
IN OUT PKDB_BREAKPOINT BreakPoint  OPTIONAL 
)

Enables a breakpoint.

Parameters
BreakPointNrNumber of the breakpoint to enable Can be -1.
BreakPointBreakpoint to enable. Can be NULL.
Return values
TRUESuccess.
FALSEFailure.
See also
KdbpDisableBreakPoint

Definition at line 702 of file kdb.c.

705{
707 INT i;
708 ULONG ul;
709
710 if (BreakPointNr < 0)
711 {
712 ASSERT(BreakPoint);
713 BreakPointNr = BreakPoint - KdbBreakPoints;
714 }
715
716 if (BreakPointNr < 0 || BreakPointNr >= KDB_MAXIMUM_BREAKPOINT_COUNT)
717 {
718 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
719 return FALSE;
720 }
721
722 if (!BreakPoint)
723 {
724 BreakPoint = KdbBreakPoints + BreakPointNr;
725 }
726
727 if (BreakPoint->Type == KdbBreakPointNone)
728 {
729 KdbPrintf("Invalid breakpoint: %d\n", BreakPointNr);
730 return FALSE;
731 }
732
733 if (BreakPoint->Enabled)
734 {
735 KdbPrintf("Breakpoint %d is already enabled.\n", BreakPointNr);
736 return TRUE;
737 }
738
739 if (BreakPoint->Type == KdbBreakPointSoftware ||
740 BreakPoint->Type == KdbBreakPointTemporary)
741 {
743 {
744 KdbPrintf("Maximum number of SW breakpoints (%d) used. "
745 "Disable another breakpoint in order to enable this one.\n",
747 return FALSE;
748 }
749
750 Status = KdbpOverwriteInstruction(BreakPoint->Process, BreakPoint->Address,
751 0xCC, &BreakPoint->Data.SavedInstruction);
752 if (!NT_SUCCESS(Status))
753 {
754 KdbPrintf("Couldn't access memory at 0x%p\n", BreakPoint->Address);
755 return FALSE;
756 }
757
759 }
760 else
761 {
762 if (BreakPoint->Data.Hw.AccessType == KdbAccessExec)
763 ASSERT(BreakPoint->Data.Hw.Size == 1);
764
765 ASSERT((BreakPoint->Address % BreakPoint->Data.Hw.Size) == 0);
766
768 {
769 KdbPrintf("Maximum number of HW breakpoints (%d) already used. "
770 "Disable another breakpoint in order to enable this one.\n",
772 return FALSE;
773 }
774
775 /* Find unused hw breakpoint */
777 for (i = 0; i < KDB_MAXIMUM_HW_BREAKPOINT_COUNT; i++)
778 {
779 if ((KdbTrapFrame.Dr7 & (0x3 << (i * 2))) == 0)
780 break;
781 }
782
784
785 /* Set the breakpoint address. */
786 switch (i)
787 {
788 case 0:
789 KdbTrapFrame.Dr0 = BreakPoint->Address;
790 break;
791 case 1:
792 KdbTrapFrame.Dr1 = BreakPoint->Address;
793 break;
794 case 2:
795 KdbTrapFrame.Dr2 = BreakPoint->Address;
796 break;
797 case 3:
798 KdbTrapFrame.Dr3 = BreakPoint->Address;
799 break;
800 }
801
802 /* Enable the global breakpoint */
803 KdbTrapFrame.Dr7 |= (0x2 << (i * 2));
804
805 /* Enable the exact match bits. */
806 KdbTrapFrame.Dr7 |= 0x00000300;
807
808 /* Clear existing state. */
809 KdbTrapFrame.Dr7 &= ~(0xF << (16 + (i * 4)));
810
811 /* Set the breakpoint type. */
812 switch (BreakPoint->Data.Hw.AccessType)
813 {
814 case KdbAccessExec:
815 ul = 0;
816 break;
817 case KdbAccessWrite:
818 ul = 1;
819 break;
820 case KdbAccessRead:
822 ul = 3;
823 break;
824 default:
825 ASSERT(0);
826 return TRUE;
827 break;
828 }
829
830 KdbTrapFrame.Dr7 |= (ul << (16 + (i * 4)));
831
832 /* Set the breakpoint length. */
833 KdbTrapFrame.Dr7 |= ((BreakPoint->Data.Hw.Size - 1) << (18 + (i * 4)));
834
835 /* Update KdbCurrentTrapFrame - values are taken from there by the CLI */
837 {
844 }
845
846 BreakPoint->Data.Hw.DebugReg = i;
848 }
849
850 BreakPoint->Enabled = TRUE;
851 if (BreakPoint->Type != KdbBreakPointTemporary)
852 KdbPrintf("Breakpoint %d enabled.\n", BreakPointNr);
853
854 return TRUE;
855}
#define KDB_MAXIMUM_HW_BREAKPOINT_COUNT
Definition: kdb.c:28
#define KDB_MAXIMUM_SW_BREAKPOINT_COUNT
Definition: kdb.c:29
ULONG Dr3
Definition: nt_native.h:1437
ULONG Dr1
Definition: nt_native.h:1435
ULONG Dr6
Definition: nt_native.h:1438
ULONG Dr0
Definition: nt_native.h:1434
ULONG Dr2
Definition: nt_native.h:1436
BOOLEAN Enabled
Definition: kdb.h:28
int32_t INT
Definition: typedefs.h:58

Referenced by KdbpCmdEnableDisableClearBreakPoint(), and KdbpInsertBreakPoint().

◆ KdbpGetBreakPointInfo()

BOOLEAN KdbpGetBreakPointInfo ( IN ULONG  BreakPointNr,
OUT ULONG_PTR *Address  OPTIONAL,
OUT KDB_BREAKPOINT_TYPE *Type  OPTIONAL,
OUT UCHAR *Size  OPTIONAL,
OUT KDB_ACCESS_TYPE *AccessType  OPTIONAL,
OUT UCHAR *DebugReg  OPTIONAL,
OUT BOOLEAN *Enabled  OPTIONAL,
OUT BOOLEAN *Global  OPTIONAL,
OUT PEPROCESS *Process  OPTIONAL,
OUT PCHAR *ConditionExpression  OPTIONAL 
)

Returns information of the specified breakpoint.

Parameters
BreakPointNrNumber of the breakpoint to return information of.
AddressReceives the address of the breakpoint.
TypeReceives the type of the breakpoint (hardware or software)
SizeSize - for memory breakpoints.
AccessTypeAccess type - for hardware breakpoints.
DebugRegDebug register - for enabled hardware breakpoints.
EnabledWhether the breakpoint is enabled or not.
ProcessThe owning process of the breakpoint.
ConditionExpressionThe expression which was given as condition for the bp.
Returns
NULL on failure, pointer to a KDB_BREAKPOINT struct on success.

Definition at line 409 of file kdb.c.

420{
422
423 if (BreakPointNr >= RTL_NUMBER_OF(KdbBreakPoints) ||
424 KdbBreakPoints[BreakPointNr].Type == KdbBreakPointNone)
425 {
426 return FALSE;
427 }
428
429 bp = KdbBreakPoints + BreakPointNr;
430 if (Address)
431 *Address = bp->Address;
432
433 if (Type)
434 *Type = bp->Type;
435
436 if (bp->Type == KdbBreakPointHardware)
437 {
438 if (Size)
439 *Size = bp->Data.Hw.Size;
440
441 if (AccessType)
442 *AccessType = bp->Data.Hw.AccessType;
443
444 if (DebugReg && bp->Enabled)
445 *DebugReg = bp->Data.Hw.DebugReg;
446 }
447
448 if (Enabled)
449 *Enabled = bp->Enabled;
450
451 if (Global)
452 *Global = bp->Global;
453
454 if (Process)
455 *Process = bp->Process;
456
457 if (ConditionExpression)
458 *ConditionExpression = bp->ConditionExpression;
459
460 return TRUE;
461}
Type
Definition: Type.h:7
UNICODE_STRING Global
Definition: symlink.c:46
@ Enabled
Definition: mountmgr.h:179
static WCHAR Address[46]
Definition: ping.c:68
PCHAR ConditionExpression
Definition: kdb.h:32
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by KdbpCmdBreakPointList().

◆ KdbpGetCommandLineSettings()

VOID KdbpGetCommandLineSettings ( _In_ PCSTR  p1)

Definition at line 1635 of file kdb.c.

1637{
1638#define CONST_STR_LEN(x) (sizeof(x)/sizeof(x[0]) - 1)
1639
1640 while (p1 && *p1)
1641 {
1642 /* Skip leading whitespace */
1643 while (*p1 == ' ') ++p1;
1644
1645 if (!_strnicmp(p1, "FIRSTCHANCE", CONST_STR_LEN("FIRSTCHANCE")))
1646 {
1647 p1 += CONST_STR_LEN("FIRSTCHANCE");
1649 }
1650
1651 /* Move on to the next option */
1652 p1 = strchr(p1, ' ');
1653 }
1654}
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
BOOLEAN KdbpSetEnterCondition(IN LONG ExceptionNr, IN BOOLEAN FirstChance, IN KDB_ENTER_CONDITION Condition)
Sets the first or last chance enter-condition for exception nr. ExceptionNr.
Definition: kdb.c:995
#define CONST_STR_LEN(x)
@ KdbEnterAlways
Definition: kdb.h:49

Referenced by KdbInitialize().

◆ KdbpGetEnterCondition()

BOOLEAN KdbpGetEnterCondition ( IN LONG  ExceptionNr,
IN BOOLEAN  FirstChance,
OUT KDB_ENTER_CONDITION Condition 
)

Gets the first or last chance enter-condition for exception nr. ExceptionNr.

Parameters
ExceptionNrNumber of the exception to get condition of.
FirstChanceWhether to get first or last chance condition.
ConditionReceives the condition setting.
Return values
TRUESuccess.
FALSEFailure (invalid exception nr)

Definition at line 973 of file kdb.c.

977{
978 if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions))
979 return FALSE;
980
981 *Condition = KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1];
982 return TRUE;
983}
IN ULONG IN UCHAR Condition
long LONG
Definition: pedump.c:60

Referenced by KdbpCmdSet().

◆ KdbpGetExceptionNumberFromStatus()

static ULONG KdbpGetExceptionNumberFromStatus ( IN NTSTATUS  ExceptionCode)
static

Definition at line 1206 of file kdb.c.

1208{
1209 ULONG Ret;
1210
1211 switch (ExceptionCode)
1212 {
1214 Ret = 0;
1215 break;
1216 case STATUS_SINGLE_STEP:
1217 Ret = 1;
1218 break;
1219 case STATUS_BREAKPOINT:
1220 Ret = 3;
1221 break;
1223 Ret = 4;
1224 break;
1226 Ret = 5;
1227 break;
1229 Ret = 6;
1230 break;
1232 Ret = 7;
1233 break;
1235 Ret = 12;
1236 break;
1238 Ret = 14;
1239 break;
1241 Ret = 17;
1242 break;
1244 Ret = 18;
1245 break;
1247 Ret = 20;
1248 break;
1249
1250 default:
1252 break;
1253 }
1254
1255 return Ret;
1256}
#define STATUS_ILLEGAL_INSTRUCTION
Definition: d3dkmdt.h:41
#define STATUS_ARRAY_BOUNDS_EXCEEDED
Definition: ntstatus.h:376
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
#define STATUS_FLOAT_MULTIPLE_TRAPS
Definition: ntstatus.h:808
#define STATUS_FLOAT_INVALID_OPERATION
Definition: ntstatus.h:380
#define STATUS_DATATYPE_MISALIGNMENT
Definition: ntstatus.h:183
#define STATUS_INTEGER_OVERFLOW
Definition: ntstatus.h:385
#define STATUS_INTEGER_DIVIDE_BY_ZERO
Definition: ntstatus.h:384

Referenced by KdbEnterDebuggerException().

◆ KdbpGetNextBreakPointNr()

LONG KdbpGetNextBreakPointNr ( IN ULONG Start  OPTIONAL)

Gets the number of the next breakpoint >= Start.

Parameters
StartBreakpoint number to start searching at. -1 if no more breakpoints are found.
Returns
Breakpoint number (-1 if no more breakpoints are found)

Definition at line 382 of file kdb.c.

384{
385 for (; Start < RTL_NUMBER_OF(KdbBreakPoints); Start++)
386 {
387 if (KdbBreakPoints[Start].Type != KdbBreakPointNone)
388 return Start;
389 }
390
391 return -1;
392}
return pTarget Start()

Referenced by KdbpCmdBreakPointList().

◆ KdbpInsertBreakPoint()

NTSTATUS KdbpInsertBreakPoint ( IN ULONG_PTR  Address,
IN KDB_BREAKPOINT_TYPE  Type,
IN UCHAR Size  OPTIONAL,
IN KDB_ACCESS_TYPE AccessType  OPTIONAL,
IN PCHAR ConditionExpression  OPTIONAL,
IN BOOLEAN  Global,
OUT PLONG BreakPointNr  OPTIONAL 
)

Inserts a breakpoint into the breakpoint array.

The Process of the breakpoint is set to KdbCurrentProcess

Parameters
AddressAddress at which to set the breakpoint.
TypeType of breakpoint (hardware or software)
SizeSize of breakpoint (for hardware/memory breakpoints)
AccessTypeAccess type (for hardware breakpoins)
ConditionExpressionExpression which must evaluate to true for conditional breakpoints.
GlobalWether the breakpoint is global or local to a process.
BreakPointNumberReceives the breakpoint number on success
Returns
NTSTATUS

Definition at line 478 of file kdb.c.

486{
487 LONG_PTR i;
489 PCHAR ConditionExpressionDup;
490 LONG ErrOffset;
491 CHAR ErrMsg[128];
492
494
496 {
497 if ((Address % Size) != 0)
498 {
499 KdbPrintf("Address (0x%p) must be aligned to a multiple of the size (%d)\n", Address, Size);
500 return STATUS_UNSUCCESSFUL;
501 }
502
503 if (AccessType == KdbAccessExec && Size != 1)
504 {
505 KdbPuts("Size must be 1 for execution breakpoints.\n");
506 return STATUS_UNSUCCESSFUL;
507 }
508 }
509
510 if (KdbBreakPointCount == KDB_MAXIMUM_BREAKPOINT_COUNT)
511 {
512 return STATUS_UNSUCCESSFUL;
513 }
514
515 /* Parse condition expression string and duplicate it */
516 if (ConditionExpression)
517 {
518 Condition = KdbpRpnParseExpression(ConditionExpression, &ErrOffset, ErrMsg);
519 if (!Condition)
520 {
521 if (ErrOffset >= 0)
522 KdbPrintf("Couldn't parse expression: %s at character %d\n", ErrMsg, ErrOffset);
523 else
524 KdbPrintf("Couldn't parse expression: %s", ErrMsg);
525
526 return STATUS_UNSUCCESSFUL;
527 }
528
529 i = strlen(ConditionExpression) + 1;
530 ConditionExpressionDup = ExAllocatePoolWithTag(NonPagedPool, i, TAG_KDBG);
531 RtlCopyMemory(ConditionExpressionDup, ConditionExpression, i);
532 }
533 else
534 {
535 Condition = NULL;
536 ConditionExpressionDup = NULL;
537 }
538
539 /* Find unused breakpoint */
541 {
542 for (i = RTL_NUMBER_OF(KdbBreakPoints) - 1; i >= 0; i--)
543 {
544 if (KdbBreakPoints[i].Type == KdbBreakPointNone)
545 break;
546 }
547 }
548 else
549 {
550 for (i = 0; i < (LONG)RTL_NUMBER_OF(KdbBreakPoints); i++)
551 {
552 if (KdbBreakPoints[i].Type == KdbBreakPointNone)
553 break;
554 }
555 }
556
557 ASSERT(i < (LONG)RTL_NUMBER_OF(KdbBreakPoints));
558
559 /* Set the breakpoint */
561 KdbBreakPoints[i].Type = Type;
562 KdbBreakPoints[i].Address = Address;
563 KdbBreakPoints[i].Enabled = FALSE;
564 KdbBreakPoints[i].Global = Global;
565 KdbBreakPoints[i].Process = KdbCurrentProcess;
566 KdbBreakPoints[i].ConditionExpression = ConditionExpressionDup;
567 KdbBreakPoints[i].Condition = Condition;
568
570 {
571 KdbBreakPoints[i].Data.Hw.Size = Size;
572 KdbBreakPoints[i].Data.Hw.AccessType = AccessType;
573 }
574
575 KdbBreakPointCount++;
576
578 KdbPrintf("Breakpoint %d inserted.\n", i);
579
580 /* Try to enable the breakpoint */
582
583 /* Return the breakpoint number */
584 if (BreakPointNr)
585 *BreakPointNr = i;
586
587 return STATUS_SUCCESS;
588}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
BOOLEAN KdbpEnableBreakPoint(IN LONG BreakPointNr OPTIONAL, IN OUT PKDB_BREAKPOINT BreakPoint OPTIONAL)
Enables a breakpoint.
Definition: kdb.c:702
PVOID KdbpRpnParseExpression(IN PCHAR Expression, OUT PLONG ErrOffset OPTIONAL, OUT PCHAR ErrMsg OPTIONAL)
Parses the given expression and returns a "handle" to it.
Definition: kdb_expr.c:1146
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define STATUS_SUCCESS
Definition: shellext.h:65
static int ErrMsg(int Error)
Definition: shlextdbg.cpp:71
#define TAG_KDBG
Definition: tag.h:38
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
char * PCHAR
Definition: typedefs.h:51
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by KdbpCmdBreakPoint(), KdbpStepIntoInstruction(), and KdbpStepOverInstruction().

◆ KdbpInternalEnter()

static VOID KdbpInternalEnter ( _In_ VOID(*)(VOID Procedure)
static

Internal function to enter KDBG and run the specified procedure.

Disables interrupts, releases display ownership, ...

Parameters
[in]ProcedureThe procedure to execute under the KDBG environment. Either execute the main interactive debugger loop (KdbpCallMainLoop) or run the KDBinit file (KdbpCliInterpretInitFile).

Definition at line 1165 of file kdb.c.

1167{
1169 PVOID SavedInitialStack, SavedStackBase, SavedKernelStack;
1170 ULONG SavedStackLimit;
1171
1173
1174 /* Take control of the display */
1175 if (KdpDebugMode.Screen)
1177
1178 /* Call the specified debugger procedure on a different stack */
1180 SavedInitialStack = Thread->Tcb.InitialStack;
1181 SavedStackBase = Thread->Tcb.StackBase;
1182 SavedStackLimit = Thread->Tcb.StackLimit;
1183 SavedKernelStack = Thread->Tcb.KernelStack;
1184 Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)KdbStack + KDB_STACK_SIZE;
1185 Thread->Tcb.StackLimit = (ULONG_PTR)KdbStack;
1186 Thread->Tcb.KernelStack = (char*)KdbStack + KDB_STACK_SIZE;
1187
1188 // KdbPrintf("Switching to KDB stack 0x%08x-0x%08x (Current Stack is 0x%08x)\n",
1189 // Thread->Tcb.StackLimit, Thread->Tcb.StackBase, Esp);
1190
1192
1193 Thread->Tcb.InitialStack = SavedInitialStack;
1194 Thread->Tcb.StackBase = SavedStackBase;
1195 Thread->Tcb.StackLimit = SavedStackLimit;
1196 Thread->Tcb.KernelStack = SavedKernelStack;
1197
1198 /* Release the display */
1199 if (KdpDebugMode.Screen)
1201
1203}
#define ULONG_PTR
Definition: config.h:101
KDP_DEBUG_MODE KdpDebugMode
Definition: kdio.c:46
VOID KdpScreenRelease(VOID)
Definition: kdio.c:450
VOID KdpScreenAcquire(VOID)
Definition: kdio.c:431
#define KDB_STACK_RESERVE
Definition: kdb.c:25
#define KDB_STACK_SIZE
Definition: kdb.c:19
VOID NTAPI KdbpStackSwitchAndCall(IN PVOID NewStack, IN VOID(*Function)(VOID))
VOID KbdDisableMouse(VOID)
Definition: kdps2kbd.c:98
VOID KbdEnableMouse(VOID)
Definition: kdps2kbd.c:93
UCHAR Screen
Definition: kd.h:100
PVOID InitialStack
Definition: ketypes.h:1664
PVOID StackBase
Definition: ketypes.h:1666
volatile VOID * StackLimit
Definition: ketypes.h:1665

Referenced by KdbEnterDebuggerException().

◆ KdbpIsBreakPointOurs()

static LONG KdbpIsBreakPointOurs ( IN NTSTATUS  ExceptionCode,
IN PCONTEXT  Context 
)
static

Checks if the breakpoint was set by the debugger.

Tries to find a breakpoint in the breakpoint array which caused the debug exception to happen.

Parameters
ExpNrException Number (1 or 3)
TrapFrameException trapframe
Returns
Breakpoint number, -1 on error.

Definition at line 649 of file kdb.c.

652{
653 ULONG i;
655
656 if (ExceptionCode == STATUS_BREAKPOINT) /* Software interrupt */
657 {
658 ULONG_PTR BpPc = KeGetContextPc(Context) - 1; /* Get EIP of INT3 instruction */
659 for (i = 0; i < KdbSwBreakPointCount; i++)
660 {
664
665 if (KdbSwBreakPoints[i]->Address == BpPc)
666 {
667 return KdbSwBreakPoints[i] - KdbBreakPoints;
668 }
669 }
670 }
671 else if (ExceptionCode == STATUS_SINGLE_STEP) /* Hardware interrupt */
672 {
673 UCHAR DebugReg;
674
675 for (i = 0; i < KdbHwBreakPointCount; i++)
676 {
679 DebugReg = KdbHwBreakPoints[i]->Data.Hw.DebugReg;
680
681 if ((Context->Dr6 & ((ULONG_PTR)1 << DebugReg)) != 0)
682 {
683 return KdbHwBreakPoints[i] - KdbBreakPoints;
684 }
685 }
686 }
687
688 return -1;
689}
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by KdbEnterDebuggerException().

◆ KdbpKdbTrapFrameFromKernelStack()

static VOID KdbpKdbTrapFrameFromKernelStack ( PVOID  KernelStack,
PKDB_KTRAP_FRAME  KdbTrapFrame 
)
static

Definition at line 119 of file kdb.c.

122{
123 ULONG_PTR *StackPtr;
124
126 StackPtr = (ULONG_PTR *) KernelStack;
127#ifdef _M_IX86
128 KdbTrapFrame->Ebp = StackPtr[3];
129 KdbTrapFrame->Edi = StackPtr[4];
130 KdbTrapFrame->Esi = StackPtr[5];
131 KdbTrapFrame->Ebx = StackPtr[6];
132 KdbTrapFrame->Eip = StackPtr[7];
133 KdbTrapFrame->Esp = (ULONG) (StackPtr + 8);
139#endif
140
141 /* FIXME: what about the other registers??? */
142}
#define KGDT_R0_CODE
Definition: ketypes.h:123
#define KGDT_R0_DATA
Definition: ketypes.h:124
ULONG Esp
Definition: nt_native.h:1479
ULONG Esi
Definition: nt_native.h:1464
ULONG Ebp
Definition: nt_native.h:1475
ULONG SegSs
Definition: nt_native.h:1480
ULONG Eip
Definition: nt_native.h:1476
ULONG SegCs
Definition: nt_native.h:1477
ULONG SegDs
Definition: nt_native.h:1456
ULONG SegGs
Definition: nt_native.h:1453
ULONG SegEs
Definition: nt_native.h:1455
ULONG Ebx
Definition: nt_native.h:1465
ULONG Edi
Definition: nt_native.h:1463
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262

Referenced by KdbpAttachToThread().

◆ KdbpOverwriteInstruction()

static NTSTATUS KdbpOverwriteInstruction ( IN PEPROCESS  Process,
IN ULONG_PTR  Address,
IN UCHAR  NewInst,
OUT PUCHAR OldInst  OPTIONAL 
)
static

Overwrites the instruction at Address with NewInst and stores the old instruction in *OldInst.

Parameters
ProcessProcess in which's context to overwrite the instruction.
AddressAddress at which to overwrite the instruction.
NewInstNew instruction (written to Address)
OldInstOld instruction (read from Address)
Returns
NTSTATUS

Definition at line 155 of file kdb.c.

160{
163 PEPROCESS CurrentProcess = PsGetCurrentProcess();
165
166 /* Get the protection for the address. */
168
169 /* Return if that page isn't present. */
171 {
173 }
174
175 /* Attach to the process */
176 if (CurrentProcess != Process)
177 {
179 }
180
181 /* Make the page writeable if it is read only. */
183 {
186 }
187
188 /* Copy the old instruction back to the caller. */
189 if (OldInst)
190 {
191 Status = KdbpSafeReadMemory(OldInst, (PUCHAR)Address, 1);
192 if (!NT_SUCCESS(Status))
193 {
195 {
197 }
198
199 /* Detach from process */
200 if (CurrentProcess != Process)
201 {
203 }
204
205 return Status;
206 }
207 }
208
209 /* Copy the new instruction in its place. */
210 Status = KdbpSafeWriteMemory((PUCHAR)Address, &NewInst, 1);
211
212 /* Restore the page protection. */
214 {
216 }
217
218 /* Detach from process */
219 if (CurrentProcess != Process)
220 {
222 }
223
224 return Status;
225}
#define PAGE_READONLY
Definition: compat.h:138
NTSTATUS KdbpSafeWriteMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1671
NTSTATUS KdbpSafeReadMemory(OUT PVOID Dest, IN PVOID Src, IN ULONG Bytes)
Definition: kdb.c:1657
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define PAGE_EXECUTE_READ
Definition: nt_native.h:1307
#define PAGE_EXECUTE
Definition: nt_native.h:1306
#define PAGE_NOACCESS
Definition: nt_native.h:1302
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
ULONG NTAPI MmGetPageProtect(struct _EPROCESS *Process, PVOID Address)
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1765
#define STATUS_MEMORY_NOT_ALLOCATED
Definition: ntstatus.h:396
unsigned char * PUCHAR
Definition: typedefs.h:53
KAPC_STATE
Definition: ketypes.h:1409
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221

Referenced by KdbEnterDebuggerException(), KdbpDisableBreakPoint(), and KdbpEnableBreakPoint().

◆ KdbpSafeReadMemory()

NTSTATUS KdbpSafeReadMemory ( OUT PVOID  Dest,
IN PVOID  Src,
IN ULONG  Bytes 
)

Definition at line 1657 of file kdb.c.

1661{
1663 Dest,
1664 Bytes,
1665 0,
1667 NULL);
1668}
NTSTATUS NTAPI KdpCopyMemoryChunks(_In_ ULONG64 Address, _In_ PVOID Buffer, _In_ ULONG TotalSize, _In_ ULONG ChunkSize, _In_ ULONG Flags, _Out_opt_ PULONG ActualSize)
Definition: kdapi.c:55
_In_ UINT Bytes
Definition: mmcopy.h:9
unsigned __int64 ULONG64
Definition: imports.h:198
#define MMDBG_COPY_UNSAFE
Definition: mm.h:77

Referenced by KdbpCmdBackTrace(), KdbpCmdDisassembleX(), KdbpCmdGdtLdtIdt(), KdbpCmdThread(), KdbpOverwriteInstruction(), KdbpReadMemory(), KdbpShouldStepOverInstruction(), KdbpStepIntoInstruction(), and RpnpEvaluateStack().

◆ KdbpSafeWriteMemory()

NTSTATUS KdbpSafeWriteMemory ( OUT PVOID  Dest,
IN PVOID  Src,
IN ULONG  Bytes 
)

Definition at line 1671 of file kdb.c.

1675{
1677 Src,
1678 Bytes,
1679 0,
1681 NULL);
1682}
#define MMDBG_COPY_WRITE
Definition: mm.h:75

Referenced by KdbpOverwriteInstruction().

◆ KdbpSetEnterCondition()

BOOLEAN KdbpSetEnterCondition ( IN LONG  ExceptionNr,
IN BOOLEAN  FirstChance,
IN KDB_ENTER_CONDITION  Condition 
)

Sets the first or last chance enter-condition for exception nr. ExceptionNr.

Parameters
ExceptionNrNumber of the exception to set condition of (-1 for all)
FirstChanceWhether to set first or last chance condition.
ConditionThe new condition setting.
Return values
TRUESuccess.
FALSEFailure (invalid exception nr)

Definition at line 995 of file kdb.c.

999{
1000 if (ExceptionNr < 0)
1001 {
1002 for (ExceptionNr = 0; ExceptionNr < (LONG)RTL_NUMBER_OF(KdbEnterConditions); ExceptionNr++)
1003 {
1004 if (ExceptionNr == 1 || ExceptionNr == 8 ||
1005 ExceptionNr == 9 || ExceptionNr == 15) /* Reserved exceptions */
1006 {
1007 continue;
1008 }
1009
1010 KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1011 }
1012 }
1013 else
1014 {
1015 if (ExceptionNr >= (LONG)RTL_NUMBER_OF(KdbEnterConditions) ||
1016 ExceptionNr == 1 || ExceptionNr == 8 || /* Do not allow changing of the debug */
1017 ExceptionNr == 9 || ExceptionNr == 15) /* trap or reserved exceptions */
1018 {
1019 return FALSE;
1020 }
1021
1022 KdbEnterConditions[ExceptionNr][FirstChance ? 0 : 1] = Condition;
1023 }
1024
1025 return TRUE;
1026}

Referenced by KdbpCmdSet(), and KdbpGetCommandLineSettings().

◆ KdbpShouldStepOverInstruction()

BOOLEAN KdbpShouldStepOverInstruction ( ULONG_PTR  Eip)

Checks whether the given instruction can be single stepped or has to be stepped over using a temporary breakpoint.

Return values
TRUEInstruction is a call.
FALSEInstruction is not a call.

Definition at line 234 of file kdb.c.

236{
237 UCHAR Mem[3];
238 ULONG i = 0;
239
240 if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
241 {
242 KdbPrintf("Couldn't access memory at 0x%p\n", Eip);
243 return FALSE;
244 }
245
246 /* Check if the current instruction is a call. */
247 while ((i < sizeof (Mem)) && (Mem[i] == 0x66 || Mem[i] == 0x67))
248 i++;
249
250 if (i == sizeof (Mem))
251 return FALSE;
252
253 if (Mem[i] == 0xE8 || Mem[i] == 0x9A || Mem[i] == 0xF2 || Mem[i] == 0xF3 ||
254 (((i + 1) < sizeof (Mem)) && Mem[i] == 0xFF && (Mem[i+1] & 0x38) == 0x10))
255 {
256 return TRUE;
257 }
258
259 return FALSE;
260}

Referenced by KdbpStepOverInstruction().

◆ KdbpStepIntoInstruction()

BOOLEAN KdbpStepIntoInstruction ( ULONG_PTR  Eip)

Steps into an instruction (interrupts)

If the given instruction should be stepped into, this function inserts a temporary breakpoint at the target instruction and returns TRUE, otherwise it returns FALSE.

Return values
TRUETemporary breakpoint set at target instruction.
FALSENo breakpoint was set.

Definition at line 300 of file kdb.c.

302{
303 KDESCRIPTOR Idtr = {0};
304 UCHAR Mem[2];
305 INT IntVect;
306 ULONG IntDesc[2];
307 ULONG_PTR TargetEip;
308
309 /* Read memory */
310 if (!NT_SUCCESS(KdbpSafeReadMemory(Mem, (PVOID)Eip, sizeof (Mem))))
311 {
312 // KdbPrintf("Couldn't access memory at 0x%p\n", Eip);
313 return FALSE;
314 }
315
316 /* Check for INT instruction */
317 /* FIXME: Check for iret */
318 if (Mem[0] == 0xcc)
319 IntVect = 3;
320 else if (Mem[0] == 0xcd)
321 IntVect = Mem[1];
322 else if (Mem[0] == 0xce && KdbCurrentTrapFrame->EFlags & (1<<11)) /* 1 << 11 is the overflow flag */
323 IntVect = 4;
324 else
325 return FALSE;
326
327 if (IntVect < 32) /* We should be informed about interrupts < 32 by the kernel, no need to breakpoint them */
328 {
329 return FALSE;
330 }
331
332 /* Read the interrupt descriptor table register */
333 __sidt(&Idtr.Limit);
334 if (IntVect >= (Idtr.Limit + 1) / 8)
335 {
336 // KdbPrintf("IDT does not contain interrupt vector %d.\n", IntVect);
337 return TRUE;
338 }
339
340 /* Get the interrupt descriptor */
341 if (!NT_SUCCESS(KdbpSafeReadMemory(IntDesc, (PVOID)((ULONG_PTR)Idtr.Base + (IntVect * 8)), sizeof(IntDesc))))
342 {
343 // KdbPrintf("Couldn't access memory at 0x%p\n", (ULONG_PTR)Idtr.Base + (IntVect * 8));
344 return FALSE;
345 }
346
347 /* Check descriptor and get target eip (16 bit interrupt/trap gates not supported) */
348 if ((IntDesc[1] & (1 << 15)) == 0) /* not present */
349 {
350 return FALSE;
351 }
352 if ((IntDesc[1] & 0x1f00) == 0x0500) /* Task gate */
353 {
354 /* FIXME: Task gates not supported */
355 return FALSE;
356 }
357 else if (((IntDesc[1] & 0x1fe0) == 0x0e00) || /* 32 bit Interrupt gate */
358 ((IntDesc[1] & 0x1fe0) == 0x0f00)) /* 32 bit Trap gate */
359 {
360 /* FIXME: Should the segment selector of the interrupt gate be checked? */
361 TargetEip = (IntDesc[1] & 0xffff0000) | (IntDesc[0] & 0x0000ffff);
362 }
363 else
364 {
365 return FALSE;
366 }
367
368 /* Insert breakpoint */
370 return FALSE;
371
372 return TRUE;
373}
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2023
NTSTATUS KdbpInsertBreakPoint(IN ULONG_PTR Address, IN KDB_BREAKPOINT_TYPE Type, IN UCHAR Size OPTIONAL, IN KDB_ACCESS_TYPE AccessType OPTIONAL, IN PCHAR ConditionExpression OPTIONAL, IN BOOLEAN Global, OUT PLONG BreakPointNr OPTIONAL)
Inserts a breakpoint into the breakpoint array.
Definition: kdb.c:478
PVOID Base
Definition: ketypes.h:560
USHORT Limit
Definition: ketypes.h:559

Referenced by KdbEnterDebuggerException().

◆ KdbpStepOverInstruction()

BOOLEAN KdbpStepOverInstruction ( ULONG_PTR  Eip)

Steps over an instruction.

If the given instruction should be stepped over, this function inserts a temporary breakpoint after the instruction and returns TRUE, otherwise it returns FALSE.

Return values
TRUETemporary breakpoint set after instruction.
FALSENo breakpoint was set.

Definition at line 272 of file kdb.c.

274{
275 LONG InstLen;
276
278 return FALSE;
279
280 InstLen = KdbpGetInstLength(Eip);
281 if (InstLen < 1)
282 return FALSE;
283
285 return FALSE;
286
287 return TRUE;
288}
LONG KdbpGetInstLength(IN ULONG_PTR Address)
Definition: i386-dis.c:94
BOOLEAN KdbpShouldStepOverInstruction(ULONG_PTR Eip)
Checks whether the given instruction can be single stepped or has to be stepped over using a temporar...
Definition: kdb.c:234

Referenced by KdbEnterDebuggerException().

Variable Documentation

◆ ExceptionNrToString

const CHAR* ExceptionNrToString[]
static
Initial value:
=
{
"Divide Error",
"Debug Trap",
"NMI",
"Breakpoint",
"Overflow",
"BOUND range exceeded",
"Invalid Opcode",
"No Math Coprocessor",
"Double Fault",
"Unknown(9)",
"Invalid TSS",
"Segment Not Present",
"Stack Segment Fault",
"General Protection",
"Page Fault",
"Reserved(15)",
"Math Fault",
"Alignment Check",
"Machine Check",
"SIMD Fault",
"Assertion Failure"
}

Definition at line 91 of file kdb.c.

Referenced by KdbEnterDebuggerException().

◆ KdbApcState

KAPC_STATE KdbApcState
static

Definition at line 59 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpAttachToThread().

◆ KdbBreakPointToReenable

PKDB_BREAKPOINT KdbBreakPointToReenable = NULL
static

Definition at line 45 of file kdb.c.

Referenced by KdbEnterDebuggerException().

◆ KdbCurrentProcess

◆ KdbCurrentThread

PETHREAD KdbCurrentThread = NULL

Definition at line 54 of file kdb.c.

Referenced by KdbEnterDebuggerException(), KdbpAttachToThread(), KdbpCmdProc(), and KdbpCmdThread().

◆ KdbCurrentTrapFrame

◆ KdbEnterConditions

◆ KdbEnteredOnSingleStep

BOOLEAN KdbEnteredOnSingleStep = FALSE
static

Definition at line 51 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpCallMainLoop().

◆ KdbEntryCount

LONG KdbEntryCount = 0
static

Definition at line 36 of file kdb.c.

Referenced by KdbEnterDebuggerException().

◆ KdbHwBreakPointCount

ULONG KdbHwBreakPointCount = 0
static

Definition at line 42 of file kdb.c.

Referenced by KdbpDisableBreakPoint(), KdbpEnableBreakPoint(), and KdbpIsBreakPointOurs().

◆ KdbHwBreakPoints

Definition at line 44 of file kdb.c.

Referenced by KdbpDisableBreakPoint(), KdbpEnableBreakPoint(), and KdbpIsBreakPointOurs().

◆ KdbLastBreakPointNr

LONG KdbLastBreakPointNr = -1

Definition at line 48 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpCmdBreakPointList().

◆ KdbNumSingleSteps

ULONG KdbNumSingleSteps = 0

Definition at line 49 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpCmdStep().

◆ KdbOriginalProcess

PEPROCESS KdbOriginalProcess = NULL

Definition at line 53 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpAttachToThread().

◆ KdbOriginalThread

PETHREAD KdbOriginalThread = NULL

Definition at line 55 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpAttachToThread().

◆ KdbpBugCheckRequested

BOOLEAN KdbpBugCheckRequested
extern

Definition at line 138 of file kdb_cli.c.

Referenced by KdbEnterDebuggerException(), and KdbpCmdBugCheck().

◆ KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep

BOOLEAN KdbpEvenThoughWeHaveABreakPointToReenableWeAlsoHaveARealSingleStep
static

Definition at line 47 of file kdb.c.

Referenced by KdbEnterDebuggerException().

◆ KdbSingleStepOver

BOOLEAN KdbSingleStepOver = FALSE

Definition at line 50 of file kdb.c.

Referenced by KdbEnterDebuggerException(), and KdbpCmdStep().

◆ KdbSwBreakPointCount

ULONG KdbSwBreakPointCount = 0
static

Definition at line 41 of file kdb.c.

Referenced by KdbpDisableBreakPoint(), KdbpEnableBreakPoint(), and KdbpIsBreakPointOurs().

◆ KdbSwBreakPoints

Definition at line 43 of file kdb.c.

Referenced by KdbpDisableBreakPoint(), KdbpEnableBreakPoint(), and KdbpIsBreakPointOurs().

◆ KdbThreadTrapFrame

KDB_KTRAP_FRAME KdbThreadTrapFrame = { 0 }
static

Definition at line 58 of file kdb.c.

Referenced by KdbpAttachToThread().

◆ KdbTrapFrame