Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

debug.c

Go to the documentation of this file.
00001 // TITLE("Debug Support Functions") 00002 //++ 00003 // 00004 // Copyright (c) 1990 Microsoft Corporation 00005 // 00006 // Module Name: 00007 // 00008 // debug.c 00009 // 00010 // Abstract: 00011 // 00012 // This module implements functions to support debugging NT. They call 00013 // architecture specific routines to do the actual work. 00014 // 00015 // Author: 00016 // 00017 // Steven R. Wood (stevewo) 8-Nov-1994 00018 // 00019 // Environment: 00020 // 00021 // Any mode. 00022 // 00023 // Revision History: 00024 // 00025 //-- 00026 00027 #include "stdarg.h" 00028 #include "stdio.h" 00029 #include "ntrtlp.h" 00030 #define NOEXTAPI 00031 #include "wdbgexts.h" 00032 #include <ntdbg.h> 00033 00034 00035 ULONG 00036 DbgPrint( 00037 PCHAR Format, 00038 ... 00039 ) 00040 00041 //++ 00042 // 00043 // Routine Description: 00044 // 00045 // This routine provides a "printf" style capability for the kernel 00046 // debugger. 00047 // 00048 // Note: control-C is consumed by the debugger and returned to 00049 // this routine as status. If status indicates control-C was 00050 // pressed, this routine breakpoints. 00051 // 00052 // Arguments: 00053 // 00054 // Format - printf style format string 00055 // ... - additional arguments consumed according to the 00056 // format string. 00057 // 00058 // Return Value: 00059 // 00060 // Defined as returning a ULONG, actually returns status. 00061 // 00062 //-- 00063 00064 { 00065 va_list arglist; 00066 UCHAR Buffer[512]; 00067 int cb; 00068 STRING Output; 00069 NTSTATUS Status = STATUS_SUCCESS; 00070 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00071 00072 if (NtCurrentTeb()->InDbgPrint) { 00073 return STATUS_SUCCESS; 00074 } 00075 NtCurrentTeb()->InDbgPrint = TRUE; 00076 #endif 00077 00078 // 00079 // Format the output into a buffer and then print it. 00080 // 00081 00082 va_start(arglist, Format); 00083 00084 #if !defined(BLDR_KERNEL_RUNTIME) 00085 __try { 00086 cb = _vsnprintf(Buffer, sizeof(Buffer), Format, arglist); 00087 } __except (EXCEPTION_EXECUTE_HANDLER) { 00088 Status = GetExceptionCode(); 00089 } 00090 #else 00091 cb = _vsnprintf(Buffer, sizeof(Buffer), Format, arglist); 00092 #endif 00093 00094 va_end(arglist); 00095 00096 if (!NT_SUCCESS(Status)) { 00097 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00098 NtCurrentTeb()->InDbgPrint = FALSE; 00099 #endif 00100 return Status; 00101 } 00102 00103 if (cb == -1) { // detect buffer overflow 00104 cb = sizeof(Buffer); 00105 Buffer[sizeof(Buffer) - 1] = '\n'; 00106 } 00107 Output.Buffer = Buffer; 00108 Output.Length = (USHORT) cb; 00109 00110 // 00111 // If APP is being debugged, raise an exception and the debugger 00112 // will catch and handle this. Otherwise, kernel debugger service 00113 // is called. 00114 // 00115 00116 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00117 #if !i386 00118 // 00119 // For non-Intel architectures, can't raise exceptions until the PebLock 00120 // is initialized, since the Function Table lookup code uses the PebLock 00121 // to serialize access to the loaded module database. What a crock 00122 // 00123 if (NtCurrentPeb()->FastPebLockRoutine != NULL) 00124 #endif 00125 if (NtCurrentPeb()->BeingDebugged) { 00126 EXCEPTION_RECORD ExceptionRecord; 00127 00128 // 00129 // Construct an exception record. 00130 // 00131 00132 ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C; 00133 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL; 00134 ExceptionRecord.NumberParameters = 2; 00135 ExceptionRecord.ExceptionFlags = 0; 00136 ExceptionRecord.ExceptionInformation[ 0 ] = Output.Length + 1; 00137 ExceptionRecord.ExceptionInformation[ 1 ] = (ULONG_PTR)(Output.Buffer); 00138 RtlRaiseException( &ExceptionRecord ); 00139 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00140 NtCurrentTeb()->InDbgPrint = FALSE; 00141 #endif 00142 return STATUS_SUCCESS; 00143 } 00144 #endif 00145 Status = DebugPrint( &Output ); 00146 if (Status == STATUS_BREAKPOINT) { 00147 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 00148 Status = STATUS_SUCCESS; 00149 } 00150 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00151 NtCurrentTeb()->InDbgPrint = FALSE; 00152 #endif 00153 return Status; 00154 } 00155 00156 ULONG 00157 DbgPrintReturnControlC( 00158 PCHAR Format, 00159 ... 00160 ) 00161 00162 //++ 00163 // 00164 // Routine Description: 00165 // 00166 // This routine provides a "printf" style capability for the kernel 00167 // debugger. 00168 // 00169 // This routine is exactly the same as DbgPrint except that control-C 00170 // is NOT handled here. Instead, status indicating control-C is 00171 // returned to the caller to do with as they will. 00172 // 00173 // Arguments: 00174 // 00175 // Format - printf style format string 00176 // ... - additional arguments consumed according to the 00177 // format string. 00178 // 00179 // Return Value: 00180 // 00181 // Defined as returning a ULONG, actually returns status. 00182 // 00183 //-- 00184 00185 { 00186 va_list arglist; 00187 UCHAR Buffer[512]; 00188 int cb; 00189 STRING Output; 00190 00191 // 00192 // Format the output into a buffer and then print it. 00193 // 00194 00195 va_start(arglist, Format); 00196 00197 cb = _vsnprintf(Buffer, sizeof(Buffer), Format, arglist); 00198 if (cb == -1) { // detect buffer overflow 00199 cb = sizeof(Buffer); 00200 Buffer[sizeof(Buffer) - 1] = '\n'; 00201 } 00202 Output.Buffer = Buffer; 00203 Output.Length = (USHORT) cb; 00204 00205 // 00206 // If APP is being debugged, raise an exception and the debugger 00207 // will catch and handle this. Otherwise, kernel debugger service 00208 // is called. 00209 // 00210 00211 #if !defined(BLDR_KERNEL_RUNTIME) && !defined(NTOS_KERNEL_RUNTIME) 00212 #if !i386 00213 // 00214 // For non-Intel architectures, can't raise exceptions until the PebLock 00215 // is initialized, since the Function Table lookup code uses the PebLock 00216 // to serialize access to the loaded module database. What a crock 00217 // 00218 if (NtCurrentPeb()->FastPebLockRoutine != NULL) 00219 #endif 00220 if (NtCurrentPeb()->BeingDebugged) { 00221 EXCEPTION_RECORD ExceptionRecord; 00222 00223 // 00224 // Construct an exception record. 00225 // 00226 00227 ExceptionRecord.ExceptionCode = DBG_PRINTEXCEPTION_C; 00228 ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL; 00229 ExceptionRecord.NumberParameters = 2; 00230 ExceptionRecord.ExceptionFlags = 0; 00231 ExceptionRecord.ExceptionInformation[ 0 ] = Output.Length + 1; 00232 ExceptionRecord.ExceptionInformation[ 1 ] = (ULONG_PTR)(Output.Buffer); 00233 RtlRaiseException( &ExceptionRecord ); 00234 return STATUS_SUCCESS; 00235 } 00236 #endif 00237 return DebugPrint( &Output ); 00238 } 00239 00240 ULONG 00241 DbgPrompt( 00242 IN PCHAR Prompt, 00243 OUT PCHAR Response, 00244 IN ULONG MaximumResponseLength 00245 ) 00246 00247 //++ 00248 // 00249 // Routine Description: 00250 // 00251 // This function displays the prompt string on the debugging console and 00252 // then reads a line of text from the debugging console. The line read 00253 // is returned in the memory pointed to by the second parameter. The 00254 // third parameter specifies the maximum number of characters that can 00255 // be stored in the response area. 00256 // 00257 // Arguments: 00258 // 00259 // Prompt - specifies the text to display as the prompt. 00260 // 00261 // Response - specifies where to store the response read from the 00262 // debugging console. 00263 // 00264 // Prompt - specifies the maximum number of characters that can be 00265 // stored in the Response buffer. 00266 // 00267 // Return Value: 00268 // 00269 // Number of characters stored in the Response buffer. Includes the 00270 // terminating newline character, but not the null character after 00271 // that. 00272 // 00273 //-- 00274 00275 { 00276 00277 STRING Input; 00278 STRING Output; 00279 00280 // 00281 // Output the prompt string and read input. 00282 // 00283 00284 Input.MaximumLength = (USHORT)MaximumResponseLength; 00285 Input.Buffer = Response; 00286 Output.Length = (USHORT)strlen( Prompt ); 00287 Output.Buffer = Prompt; 00288 return DebugPrompt( &Output, &Input ); 00289 } 00290 00291 #if defined(NTOS_KERNEL_RUNTIME) || defined(BLDR_KERNEL_RUNTIME) 00292 00293 00294 VOID 00295 DbgLoadImageSymbols( 00296 IN PSTRING FileName, 00297 IN PVOID ImageBase, 00298 IN ULONG_PTR ProcessId 00299 ) 00300 00301 //++ 00302 // 00303 // Routine Description: 00304 // 00305 // Tells the debugger about newly loaded symbols. 00306 // 00307 // Arguments: 00308 // 00309 // Return Value: 00310 // 00311 //-- 00312 00313 { 00314 00315 PIMAGE_NT_HEADERS NtHeaders; 00316 KD_SYMBOLS_INFO SymbolInfo; 00317 00318 SymbolInfo.BaseOfDll = ImageBase; 00319 SymbolInfo.ProcessId = ProcessId; 00320 NtHeaders = RtlImageNtHeader( ImageBase ); 00321 if (NtHeaders != NULL) { 00322 SymbolInfo.CheckSum = (ULONG)NtHeaders->OptionalHeader.CheckSum; 00323 SymbolInfo.SizeOfImage = (ULONG)NtHeaders->OptionalHeader.SizeOfImage; 00324 00325 } else { 00326 00327 #if defined(BLDR_KERNEL_RUNTIME) 00328 00329 // 00330 // There is only one image loaded in the loader environment that 00331 // does not have an NT image header. The image is the OS loader 00332 // and it is loaded by the firmware which strips the file header 00333 // and the optional ROM header. All the debugger requires is a 00334 // good guest at the size of the image. 00335 // 00336 00337 SymbolInfo.SizeOfImage = 0x100000; 00338 00339 #else 00340 00341 SymbolInfo.SizeOfImage = 0; 00342 00343 #endif 00344 00345 SymbolInfo.CheckSum = 0; 00346 } 00347 00348 DebugLoadImageSymbols( FileName, &SymbolInfo); 00349 00350 return; 00351 } 00352 00353 00354 VOID 00355 DbgUnLoadImageSymbols ( 00356 IN PSTRING FileName, 00357 IN PVOID ImageBase, 00358 IN ULONG_PTR ProcessId 00359 ) 00360 00361 //++ 00362 // 00363 // Routine Description: 00364 // 00365 // Tells the debugger about newly unloaded symbols. 00366 // 00367 // Arguments: 00368 // 00369 // Return Value: 00370 // 00371 //-- 00372 00373 { 00374 KD_SYMBOLS_INFO SymbolInfo; 00375 00376 SymbolInfo.BaseOfDll = ImageBase; 00377 SymbolInfo.ProcessId = ProcessId; 00378 SymbolInfo.CheckSum = 0; 00379 SymbolInfo.SizeOfImage = 0; 00380 00381 DebugUnLoadImageSymbols( FileName, &SymbolInfo ); 00382 00383 return; 00384 } 00385 00386 #endif // defined(NTOS_KERNEL_RUNTIME)

Generated on Sat May 15 19:39:39 2004 for test by doxygen 1.3.7