Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkdinit.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/kd64/kdinit.c 00005 * PURPOSE: KD64 Initialization Code 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* FUNCTIONS *****************************************************************/ 00017 00018 VOID 00019 NTAPI 00020 KdUpdateDataBlock(VOID) 00021 { 00022 /* Update the KeUserCallbackDispatcher pointer */ 00023 KdDebuggerDataBlock.KeUserCallbackDispatcher = 00024 (ULONG_PTR)KeUserCallbackDispatcher; 00025 } 00026 00027 BOOLEAN 00028 NTAPI 00029 KdRegisterDebuggerDataBlock(IN ULONG Tag, 00030 IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader, 00031 IN ULONG Size) 00032 { 00033 KIRQL OldIrql; 00034 PLIST_ENTRY NextEntry; 00035 PDBGKD_DEBUG_DATA_HEADER64 CurrentHeader; 00036 00037 /* Acquire the Data Lock */ 00038 KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql); 00039 00040 /* Loop the debugger data list */ 00041 NextEntry = KdpDebuggerDataListHead.Flink; 00042 while (NextEntry != &KdpDebuggerDataListHead) 00043 { 00044 /* Get the header for this entry */ 00045 CurrentHeader = CONTAINING_RECORD(NextEntry, 00046 DBGKD_DEBUG_DATA_HEADER64, 00047 List); 00048 00049 /* Move to the next one */ 00050 NextEntry = NextEntry->Flink; 00051 00052 /* Check if we already have this data block */ 00053 if ((CurrentHeader == DataHeader) || (CurrentHeader->OwnerTag == Tag)) 00054 { 00055 /* Release the lock and fail */ 00056 KeReleaseSpinLock(&KdpDataSpinLock, OldIrql); 00057 return FALSE; 00058 } 00059 } 00060 00061 /* Setup the header */ 00062 DataHeader->OwnerTag = Tag; 00063 DataHeader->Size = Size; 00064 00065 /* Insert it into the list and release the lock */ 00066 InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)&DataHeader->List); 00067 KeReleaseSpinLock(&KdpDataSpinLock, OldIrql); 00068 return TRUE; 00069 } 00070 00071 BOOLEAN 00072 NTAPI 00073 KdInitSystem(IN ULONG BootPhase, 00074 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00075 { 00076 BOOLEAN EnableKd, DisableKdAfterInit = FALSE, BlockEnable; 00077 LPSTR CommandLine, DebugLine, DebugOptionStart, DebugOptionEnd; 00078 STRING ImageName; 00079 PLDR_DATA_TABLE_ENTRY LdrEntry; 00080 PLIST_ENTRY NextEntry; 00081 ULONG i, j, Length; 00082 SIZE_T DebugOptionLength; 00083 CHAR NameBuffer[256]; 00084 PWCHAR Name; 00085 00086 #if defined(__GNUC__) 00087 /* Make gcc happy */ 00088 BlockEnable = FALSE; 00089 #endif 00090 00091 /* Check if this is Phase 1 */ 00092 if (BootPhase) 00093 { 00094 /* Just query the performance counter */ 00095 KeQueryPerformanceCounter(&KdPerformanceCounterRate); 00096 return TRUE; 00097 } 00098 00099 /* Check if we already initialized once */ 00100 if (KdDebuggerEnabled) return TRUE; 00101 00102 /* Set the Debug Routine as the Stub for now */ 00103 KiDebugRoutine = KdpStub; 00104 00105 /* Disable break after symbol load for now */ 00106 KdBreakAfterSymbolLoad = FALSE; 00107 00108 /* Check if the Debugger Data Block was already initialized */ 00109 if (!KdpDebuggerDataListHead.Flink) 00110 { 00111 /* It wasn't...Initialize the KD Data Listhead */ 00112 InitializeListHead(&KdpDebuggerDataListHead); 00113 00114 /* Register the Debugger Data Block */ 00115 KdRegisterDebuggerDataBlock(KDBG_TAG, 00116 &KdDebuggerDataBlock.Header, 00117 sizeof(KdDebuggerDataBlock)); 00118 00119 /* Fill out the KD Version Block */ 00120 KdVersionBlock.MajorVersion = (USHORT)((DBGKD_MAJOR_NT << 8) | (NtBuildNumber >> 28)); 00121 KdVersionBlock.MinorVersion = (USHORT)(NtBuildNumber & 0xFFFF); 00122 00123 #ifdef CONFIG_SMP 00124 /* This is an MP Build */ 00125 KdVersionBlock.Flags |= DBGKD_VERS_FLAG_MP; 00126 #endif 00127 00128 /* Save Pointers to Loaded Module List and Debugger Data */ 00129 KdVersionBlock.PsLoadedModuleList = (ULONG64)(LONG_PTR)&PsLoadedModuleList; 00130 KdVersionBlock.DebuggerDataList = (ULONG64)(LONG_PTR)&KdpDebuggerDataListHead; 00131 00132 /* Set protocol limits */ 00133 KdVersionBlock.MaxStateChange = DbgKdMaximumStateChange - 00134 DbgKdMinimumStateChange; 00135 KdVersionBlock.MaxManipulate = DbgKdMaximumManipulate - 00136 DbgKdMinimumManipulate; 00137 KdVersionBlock.Unused[0] = 0; 00138 00139 /* Link us in the KPCR */ 00140 KeGetPcr()->KdVersionBlock = &KdVersionBlock; 00141 } 00142 00143 /* Check if we have a loader block */ 00144 if (LoaderBlock) 00145 { 00146 /* Get the image entry */ 00147 LdrEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink, 00148 LDR_DATA_TABLE_ENTRY, 00149 InLoadOrderLinks); 00150 00151 /* Save the Kernel Base */ 00152 PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase; 00153 KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)LdrEntry->DllBase; 00154 00155 /* Check if we have a command line */ 00156 CommandLine = LoaderBlock->LoadOptions; 00157 if (CommandLine) 00158 { 00159 /* Upcase it */ 00160 _strupr(CommandLine); 00161 00162 /* Assume we'll disable KD */ 00163 EnableKd = FALSE; 00164 00165 /* Check for CRASHDEBUG, NODEBUG and just DEBUG */ 00166 if (strstr(CommandLine, "CRASHDEBUG")) 00167 { 00168 /* Don't enable KD now, but allow it to be enabled later */ 00169 KdPitchDebugger = FALSE; 00170 } 00171 else if (strstr(CommandLine, "NODEBUG")) 00172 { 00173 /* Don't enable KD and don't let it be enabled later */ 00174 KdPitchDebugger = TRUE; 00175 } 00176 else if ((DebugLine = strstr(CommandLine, "DEBUG")) != NULL) 00177 { 00178 /* Enable KD */ 00179 EnableKd = TRUE; 00180 00181 /* Check if there are any options */ 00182 if (DebugLine[5] == '=') 00183 { 00184 /* Save pointers */ 00185 DebugOptionStart = DebugOptionEnd = &DebugLine[6]; 00186 00187 /* Scan the string for debug options */ 00188 for (;;) 00189 { 00190 /* Loop until we reach the end of the string */ 00191 while (*DebugOptionEnd != ANSI_NULL) 00192 { 00193 /* Check if this is a comma, a space or a tab */ 00194 if ((*DebugOptionEnd == ',') || 00195 (*DebugOptionEnd == ' ') || 00196 (*DebugOptionEnd == ' ')) 00197 { 00198 /* 00199 * We reached the end of the option or 00200 * the end of the string, break out 00201 */ 00202 break; 00203 } 00204 else 00205 { 00206 /* Move on to the next character */ 00207 DebugOptionEnd++; 00208 } 00209 } 00210 00211 /* Calculate the length of the current option */ 00212 DebugOptionLength = (DebugOptionEnd - DebugOptionStart); 00213 00214 /* 00215 * Break out if we reached the last option 00216 * or if there were no options at all 00217 */ 00218 if (!DebugOptionLength) break; 00219 00220 /* Now check which option this is */ 00221 if ((DebugOptionLength == 10) && 00222 !(strncmp(DebugOptionStart, "AUTOENABLE", 10))) 00223 { 00224 /* 00225 * Disable the debugger, but 00226 * allow it to be reenabled 00227 */ 00228 DisableKdAfterInit = TRUE; 00229 BlockEnable = FALSE; 00230 KdAutoEnableOnEvent = TRUE; 00231 } 00232 else if ((DebugOptionLength == 7) && 00233 !(strncmp(DebugOptionStart, "DISABLE", 7))) 00234 { 00235 /* Disable the debugger */ 00236 DisableKdAfterInit = TRUE; 00237 BlockEnable = TRUE; 00238 KdAutoEnableOnEvent = FALSE; 00239 } 00240 else if ((DebugOptionLength == 6) && 00241 !(strncmp(DebugOptionStart, "NOUMEX", 6))) 00242 { 00243 /* Ignore user mode exceptions */ 00244 KdIgnoreUmExceptions = TRUE; 00245 } 00246 00247 /* 00248 * If there are more options then 00249 * the next character should be a comma 00250 */ 00251 if (*DebugOptionEnd != ',') 00252 { 00253 /* It isn't, break out */ 00254 break; 00255 } 00256 00257 /* Move on to the next option */ 00258 DebugOptionEnd++; 00259 DebugOptionStart = DebugOptionEnd; 00260 } 00261 } 00262 } 00263 } 00264 else 00265 { 00266 /* No command line options? Disable debugger by default */ 00267 KdPitchDebugger = TRUE; 00268 EnableKd = FALSE; 00269 } 00270 } 00271 else 00272 { 00273 /* Called from a bugcheck or a re-enable. Save the Kernel Base */ 00274 KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)PsNtosImageBase; 00275 00276 /* Unconditionally enable KD */ 00277 EnableKd = TRUE; 00278 } 00279 00280 /* Set the Kernel Base in the Data Block */ 00281 KdDebuggerDataBlock.KernBase = (ULONG_PTR)KdVersionBlock.KernBase; 00282 00283 /* Initialize the debugger if requested */ 00284 if ((EnableKd) && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock)))) 00285 { 00286 /* Now set our real KD routine */ 00287 KiDebugRoutine = KdpTrap; 00288 00289 /* Check if we've already initialized our structures */ 00290 if (!KdpDebuggerStructuresInitialized) 00291 { 00292 /* Set the Debug Switch Routine and Retries*/ 00293 KdpContext.KdpDefaultRetries = 20; 00294 KiDebugSwitchRoutine = KdpSwitchProcessor; 00295 00296 /* Initialize the Time Slip DPC */ 00297 KeInitializeDpc(&KdpTimeSlipDpc, KdpTimeSlipDpcRoutine, NULL); 00298 KeInitializeTimer(&KdpTimeSlipTimer); 00299 ExInitializeWorkItem(&KdpTimeSlipWorkItem, KdpTimeSlipWork, NULL); 00300 00301 /* First-time initialization done! */ 00302 KdpDebuggerStructuresInitialized = TRUE; 00303 } 00304 00305 /* Initialize the timer */ 00306 KdTimerStart.QuadPart = 0; 00307 00308 /* Officially enable KD */ 00309 KdPitchDebugger = FALSE; 00310 KdDebuggerEnabled = TRUE; 00311 00312 /* Let user-mode know that it's enabled as well */ 00313 #undef KdDebuggerEnabled 00314 SharedUserData->KdDebuggerEnabled = TRUE; 00315 #define KdDebuggerEnabled _KdDebuggerEnabled 00316 00317 /* Check if the debugger should be disabled initially */ 00318 if (DisableKdAfterInit) 00319 { 00320 /* Disable it */ 00321 KdDisableDebuggerWithLock(FALSE); 00322 00323 /* 00324 * Save the enable block state and return initialized 00325 * (the debugger is active but disabled). 00326 */ 00327 KdBlockEnable = BlockEnable; 00328 return TRUE; 00329 } 00330 00331 /* Check if we have a loader block */ 00332 if (LoaderBlock) 00333 { 00334 /* Loop boot images */ 00335 NextEntry = LoaderBlock->LoadOrderListHead.Flink; 00336 i = 0; 00337 while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (i < 2)) 00338 { 00339 /* Get the image entry */ 00340 LdrEntry = CONTAINING_RECORD(NextEntry, 00341 LDR_DATA_TABLE_ENTRY, 00342 InLoadOrderLinks); 00343 00344 /* Generate the image name */ 00345 Name = LdrEntry->FullDllName.Buffer; 00346 Length = LdrEntry->FullDllName.Length / sizeof(WCHAR); 00347 j = 0; 00348 do 00349 { 00350 /* Do cheap Unicode to ANSI conversion */ 00351 NameBuffer[j++] = (CHAR)*Name++; 00352 } while (j < Length); 00353 00354 /* Null-terminate */ 00355 NameBuffer[j] = ANSI_NULL; 00356 00357 /* Load symbols for image */ 00358 RtlInitString(&ImageName, NameBuffer); 00359 DbgLoadImageSymbols(&ImageName, 00360 LdrEntry->DllBase, 00361 (ULONG_PTR)ZwCurrentProcess()); 00362 00363 /* Go to the next entry */ 00364 NextEntry = NextEntry->Flink; 00365 i++; 00366 } 00367 } 00368 00369 /* Check for incoming breakin and break on symbol load if we have it*/ 00370 KdBreakAfterSymbolLoad = KdPollBreakIn(); 00371 } 00372 else 00373 { 00374 /* Disable debugger */ 00375 KdDebuggerNotPresent = TRUE; 00376 } 00377 00378 /* Return initialized */ 00379 return TRUE; 00380 } Generated on Sun May 27 2012 04:37:19 for ReactOS by
1.7.6.1
|