ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kdmain.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS Kernel
00004  * FILE:            ntoskrnl/kd/kdinit.c
00005  * PURPOSE:         Kernel Debugger Initialization
00006  *
00007  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00008  */
00009 
00010 #include <ntoskrnl.h>
00011 #define NDEBUG
00012 #include <debug.h>
00013 
00014 /* VARIABLES ***************************************************************/
00015 
00016 BOOLEAN KdDebuggerEnabled = FALSE;
00017 BOOLEAN KdEnteredDebugger = FALSE;
00018 BOOLEAN KdDebuggerNotPresent = TRUE;
00019 BOOLEAN KdBreakAfterSymbolLoad = FALSE;
00020 BOOLEAN KdpBreakPending = FALSE;
00021 BOOLEAN KdPitchDebugger = TRUE;
00022 BOOLEAN KdIgnoreUmExceptions = FALSE;
00023 KD_CONTEXT KdpContext;
00024 ULONG Kd_WIN2000_Mask;
00025 VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads);
00026 
00027 typedef struct
00028 {
00029     ULONG ComponentId;
00030     ULONG Level;
00031 } KD_COMPONENT_DATA;
00032 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
00033 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
00034 ULONG KdComponentTableEntries = 0;
00035 
00036 ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL;
00037 
00038 /* PRIVATE FUNCTIONS *********************************************************/
00039 
00040 ULONG
00041 NTAPI
00042 KdpServiceDispatcher(ULONG Service,
00043                      PVOID Buffer1,
00044                      ULONG Buffer1Length)
00045 {
00046     ULONG Result = 0;
00047 
00048     switch (Service)
00049     {
00050         case BREAKPOINT_PRINT: /* DbgPrint */
00051             Result = KdpPrintString(Buffer1, Buffer1Length);
00052             break;
00053 
00054 #if DBG
00055         case ' soR': /* ROS-INTERNAL */
00056         {
00057             switch ((ULONG_PTR)Buffer1)
00058             {
00059                 case DumpAllThreads:
00060                     PspDumpThreads(TRUE);
00061                     break;
00062 
00063                 case DumpUserThreads:
00064                     PspDumpThreads(FALSE);
00065                     break;
00066 
00067                 case KdSpare3:
00068                     MmDumpArmPfnDatabase(FALSE);
00069                     break;
00070 
00071                 default:
00072                     break;
00073             }
00074             break;
00075         }
00076 
00077         /* Register a debug callback */
00078         case 'CsoR':
00079         {
00080             switch (Buffer1Length)
00081             {
00082                 case ID_Win32PreServiceHook:
00083                     KeWin32PreServiceHook = Buffer1;
00084                     break;
00085 
00086                 case ID_Win32PostServiceHook:
00087                     KeWin32PostServiceHook = Buffer1;
00088                     break;
00089 
00090             }
00091             break;
00092         }
00093 
00094         /* Special  case for stack frame dumps */
00095         case 'DsoR':
00096         {
00097             KeRosDumpStackFrames((PULONG)Buffer1, Buffer1Length);
00098             break;
00099         }
00100 #endif
00101         default:
00102             HalDisplayString ("Invalid debug service call!\n");
00103             break;
00104     }
00105 
00106     return Result;
00107 }
00108 
00109 BOOLEAN
00110 NTAPI
00111 KdpEnterDebuggerException(IN PKTRAP_FRAME TrapFrame,
00112                           IN PKEXCEPTION_FRAME ExceptionFrame,
00113                           IN PEXCEPTION_RECORD ExceptionRecord,
00114                           IN PCONTEXT Context,
00115                           IN KPROCESSOR_MODE PreviousMode,
00116                           IN BOOLEAN SecondChance)
00117 {
00118     KD_CONTINUE_TYPE Return = kdHandleException;
00119     ULONG ExceptionCommand = ExceptionRecord->ExceptionInformation[0];
00120 
00121     /* Check if this was a breakpoint due to DbgPrint or Load/UnloadSymbols */
00122     if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
00123         (ExceptionRecord->NumberParameters > 0) &&
00124         ((ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS) ||
00125          (ExceptionCommand == BREAKPOINT_UNLOAD_SYMBOLS) ||
00126          (ExceptionCommand == BREAKPOINT_COMMAND_STRING) ||
00127          (ExceptionCommand == BREAKPOINT_PRINT) ||
00128          (ExceptionCommand == BREAKPOINT_PROMPT)))
00129     {
00130         /* Check if this is a debug print */
00131         if (ExceptionCommand == BREAKPOINT_PRINT)
00132         {
00133             /* Print the string */
00134             KdpServiceDispatcher(BREAKPOINT_PRINT,
00135                                  (PVOID)ExceptionRecord->ExceptionInformation[1],
00136                                  ExceptionRecord->ExceptionInformation[2]);
00137 
00138             /* Return success */
00139             KeSetContextReturnRegister(Context, STATUS_SUCCESS);
00140         }
00141 #ifdef KDBG
00142         else if (ExceptionCommand == BREAKPOINT_LOAD_SYMBOLS)
00143         {
00144             PLDR_DATA_TABLE_ENTRY LdrEntry;
00145 
00146             /* Load symbols. Currently implemented only for KDBG! */
00147             if(KdbpSymFindModule(((PKD_SYMBOLS_INFO)ExceptionRecord->ExceptionInformation[2])->BaseOfDll, NULL, -1, &LdrEntry))
00148                 KdbSymProcessSymbols(LdrEntry);
00149         }
00150         else if (ExceptionCommand == BREAKPOINT_PROMPT)
00151         {
00152             ULONG ReturnValue;
00153             LPSTR OutString;
00154             USHORT OutStringLength;
00155 
00156             /* Get the response string  and length */
00157             OutString = (LPSTR)Context->Ebx;
00158             OutStringLength = (USHORT)Context->Edi;
00159 
00160             /* Call KDBG */
00161             ReturnValue = KdpPrompt((LPSTR)ExceptionRecord->
00162                                     ExceptionInformation[1],
00163                                     (USHORT)ExceptionRecord->
00164                                     ExceptionInformation[2],
00165                                     OutString,
00166                                     OutStringLength);
00167 
00168             /* Return the number of characters that we received */
00169             Context->Eax = ReturnValue;
00170         }
00171 #endif
00172 
00173         /* This we can handle: simply bump the Program Counter */
00174         KeSetContextPc(Context, KeGetContextPc(Context) + KD_BREAKPOINT_SIZE);
00175         return TRUE;
00176     }
00177 
00178 #ifdef KDBG
00179     /* Check if this is an assertion failure */
00180     if (ExceptionRecord->ExceptionCode == STATUS_ASSERTION_FAILURE)
00181     {
00182         /* Warn about it */
00183         DbgPrint("\n!!! Assertion Failure at Address 0x%p !!!\n\n",
00184                  (PVOID)Context->Eip);
00185 
00186         /* Bump EIP to the instruction following the int 2C and return */
00187         Context->Eip += 2;
00188         return TRUE;
00189     }
00190 #endif
00191 
00192     /* Get out of here if the Debugger isn't connected */
00193     if (KdDebuggerNotPresent) return FALSE;
00194 
00195 #ifdef KDBG
00196     /* Call KDBG if available */
00197     Return = KdbEnterDebuggerException(ExceptionRecord,
00198                                        PreviousMode,
00199                                        Context,
00200                                        TrapFrame,
00201                                        !SecondChance);
00202 #else /* not KDBG */
00203     if (WrapperInitRoutine)
00204     {
00205         /* Call GDB */
00206         Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
00207                                                   Context,
00208                                                   TrapFrame);
00209     }
00210 #endif /* not KDBG */
00211 
00212     /* Debugger didn't handle it, please handle! */
00213     if (Return == kdHandleException) return FALSE;
00214 
00215     /* Debugger handled it */
00216     return TRUE;
00217 }
00218 
00219 BOOLEAN
00220 NTAPI
00221 KdpCallGdb(IN PKTRAP_FRAME TrapFrame,
00222            IN PEXCEPTION_RECORD ExceptionRecord,
00223            IN PCONTEXT Context)
00224 {
00225     KD_CONTINUE_TYPE Return = kdDoNotHandleException;
00226 
00227     /* Get out of here if the Debugger isn't connected */
00228     if (KdDebuggerNotPresent) return FALSE;
00229 
00230     /* FIXME:
00231      * Right now, the GDB wrapper seems to handle exceptions differntly
00232      * from KDGB and both are called at different times, while the GDB
00233      * one is only called once and that's it. I don't really have the knowledge
00234      * to fix the GDB stub, so until then, we'll be using this hack
00235      */
00236     if (WrapperInitRoutine)
00237     {
00238         Return = WrapperTable.KdpExceptionRoutine(ExceptionRecord,
00239                                                   Context,
00240                                                   TrapFrame);
00241     }
00242 
00243     /* Debugger didn't handle it, please handle! */
00244     if (Return == kdHandleException) return FALSE;
00245 
00246     /* Debugger handled it */
00247     return TRUE;
00248 }
00249 
00250 BOOLEAN
00251 NTAPI
00252 KdIsThisAKdTrap(IN PEXCEPTION_RECORD ExceptionRecord,
00253                 IN PCONTEXT Context,
00254                 IN KPROCESSOR_MODE PreviousMode)
00255 {
00256     /* KDBG has its own mechanism for ignoring user mode exceptions */
00257     return FALSE;
00258 }
00259 
00260 /* PUBLIC FUNCTIONS *********************************************************/
00261 
00262 /*
00263  * @implemented
00264  */
00265 BOOLEAN
00266 NTAPI
00267 KdRefreshDebuggerNotPresent(VOID)
00268 {
00269     UNIMPLEMENTED;
00270 
00271     /* Just return whatever was set previously -- FIXME! */
00272     return KdDebuggerNotPresent;
00273 }
00274 
00275 /*
00276  * @implemented
00277  */
00278 NTSTATUS
00279 NTAPI
00280 KdDisableDebugger(VOID)
00281 {
00282     KIRQL OldIrql;
00283 
00284     /* Raise IRQL */
00285     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00286 
00287     /* TODO: Disable any breakpoints */
00288 
00289     /* Disable the Debugger */
00290     KdDebuggerEnabled = FALSE;
00291 
00292     /* Lower the IRQL */
00293     KeLowerIrql(OldIrql);
00294 
00295     /* Return success */
00296     return STATUS_SUCCESS;
00297 }
00298 
00299 /*
00300  * @implemented
00301  */
00302 NTSTATUS
00303 NTAPI
00304 KdEnableDebugger(VOID)
00305 {
00306     KIRQL OldIrql;
00307 
00308     /* Raise IRQL */
00309     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00310 
00311     /* TODO: Re-enable any breakpoints */
00312 
00313     /* Enable the Debugger */
00314     KdDebuggerEnabled = TRUE;
00315 
00316     /* Lower the IRQL */
00317     KeLowerIrql(OldIrql);
00318 
00319     /* Return success */
00320     return STATUS_SUCCESS;
00321 }
00322 
00323 /*
00324  * @implemented
00325  */
00326 BOOLEAN
00327 NTAPI
00328 KdPollBreakIn(VOID)
00329 {
00330     return KdpBreakPending;
00331 }
00332 
00333 /*
00334  * @unimplemented
00335  */
00336 NTSTATUS
00337 NTAPI
00338 KdPowerTransition(ULONG PowerState)
00339 {
00340     UNIMPLEMENTED;
00341     return STATUS_NOT_IMPLEMENTED;
00342 }
00343 
00344 /*
00345  * @unimplemented
00346  */
00347 NTSTATUS
00348 NTAPI
00349 KdChangeOption(IN KD_OPTION Option,
00350                IN ULONG InBufferLength OPTIONAL,
00351                IN PVOID InBuffer,
00352                IN ULONG OutBufferLength OPTIONAL,
00353                OUT PVOID OutBuffer,
00354                OUT PULONG OutBufferRequiredLength OPTIONAL)
00355 {
00356     UNIMPLEMENTED;
00357     return STATUS_NOT_IMPLEMENTED;
00358 }
00359 
00360 
00361 NTSTATUS
00362 NTAPI
00363 NtQueryDebugFilterState(IN ULONG ComponentId,
00364                         IN ULONG Level)
00365 {
00366     ULONG i;
00367 
00368     /* Convert Level to mask if it isn't already one */
00369     if (Level < 32)
00370         Level = 1 << Level;
00371 
00372     /* Check if it is not the default component */
00373     if (ComponentId != DPFLTR_DEFAULT_ID)
00374     {
00375         /* No, search for an existing entry in the table */
00376         for (i = 0; i < KdComponentTableEntries; i++)
00377         {
00378             /* Check if it is the right component */
00379             if (ComponentId == KdComponentTable[i].ComponentId)
00380             {
00381                 /* Check if mask are matching */
00382                 return (Level & KdComponentTable[i].Level) ? TRUE : FALSE;
00383             }
00384         }
00385     }
00386 
00387     /* Entry not found in the table, use default mask */
00388     return (Level & Kd_DEFAULT_MASK) ? TRUE : FALSE;
00389 }
00390 
00391 NTSTATUS
00392 NTAPI
00393 NtSetDebugFilterState(IN ULONG ComponentId,
00394                       IN ULONG Level,
00395                       IN BOOLEAN State)
00396 {
00397     ULONG i;
00398 
00399     /* Convert Level to mask if it isn't already one */
00400     if (Level < 32)
00401         Level = 1 << Level;
00402     Level &= ~DPFLTR_MASK;
00403 
00404     /* Check if it is the default component */
00405     if (ComponentId == DPFLTR_DEFAULT_ID)
00406     {
00407         /* Yes, modify the default mask */
00408         if (State)
00409             Kd_DEFAULT_MASK |= Level;
00410         else
00411             Kd_DEFAULT_MASK &= ~Level;
00412 
00413         return STATUS_SUCCESS;
00414     }
00415 
00416     /* Search for an existing entry */
00417     for (i = 0; i < KdComponentTableEntries; i++ )
00418     {
00419         if (ComponentId == KdComponentTable[i].ComponentId)
00420             break;
00421     }
00422 
00423     /* Check if we have found an existing entry */
00424     if (i == KdComponentTableEntries)
00425     {
00426         /* Check if we have enough space in the table */
00427         if (i == MAX_KD_COMPONENT_TABLE_ENTRIES)
00428             return STATUS_INVALID_PARAMETER_1;
00429 
00430         /* Add a new entry */
00431         ++KdComponentTableEntries;
00432         KdComponentTable[i].ComponentId = ComponentId;
00433         KdComponentTable[i].Level = Kd_DEFAULT_MASK;
00434     }
00435 
00436     /* Update entry table */
00437     if (State)
00438         KdComponentTable[i].Level |= Level;
00439     else
00440         KdComponentTable[i].Level &= ~Level;
00441 
00442     return STATUS_SUCCESS;
00443 }
00444 
00445 /*
00446  * @unimplemented
00447  */
00448 NTSTATUS
00449 NTAPI
00450 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
00451                      IN PVOID InputBuffer,
00452                      IN ULONG InputBufferLength,
00453                      OUT PVOID OutputBuffer,
00454                      IN ULONG OutputBufferLength,
00455                      IN OUT PULONG ReturnLength,
00456                      IN KPROCESSOR_MODE PreviousMode)
00457 {
00458     /* HACK */
00459     return KdpServiceDispatcher(Command, InputBuffer, InputBufferLength);
00460 }
00461 
00462 PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException;
00463 
00464  /* EOF */

Generated on Sat May 26 2012 04:36:14 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.