1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/dbgk/dbgkutil.c 5 * PURPOSE: User-Mode Debugging Support, Internal Debug Functions. 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS *****************************************************************/ 16 17 HANDLE 18 NTAPI 19 DbgkpSectionToFileHandle(IN PVOID Section) 20 { 21 NTSTATUS Status; 22 POBJECT_NAME_INFORMATION FileName; 23 OBJECT_ATTRIBUTES ObjectAttributes; 24 IO_STATUS_BLOCK IoStatusBlock; 25 HANDLE Handle; 26 PAGED_CODE(); 27 28 /* Get the filename of the section */ 29 Status = MmGetFileNameForSection(Section, &FileName); 30 if (!NT_SUCCESS(Status)) return NULL; 31 32 /* Initialize object attributes */ 33 InitializeObjectAttributes(&ObjectAttributes, 34 &FileName->Name, 35 OBJ_CASE_INSENSITIVE | 36 OBJ_FORCE_ACCESS_CHECK | 37 OBJ_KERNEL_HANDLE, 38 NULL, 39 NULL); 40 41 /* Open the file */ 42 Status = ZwOpenFile(&Handle, 43 GENERIC_READ | SYNCHRONIZE, 44 &ObjectAttributes, 45 &IoStatusBlock, 46 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 47 FILE_SYNCHRONOUS_IO_NONALERT); 48 49 /* Free the name and return the handle if we succeeded */ 50 ExFreePool(FileName); 51 if (!NT_SUCCESS(Status)) return NULL; 52 return Handle; 53 } 54 55 BOOLEAN 56 NTAPI 57 DbgkpSuspendProcess(VOID) 58 { 59 PAGED_CODE(); 60 61 /* Make sure this isn't a deleted process */ 62 if (!PsGetCurrentProcess()->ProcessDelete) 63 { 64 /* Freeze all the threads */ 65 KeFreezeAllThreads(); 66 return TRUE; 67 } 68 else 69 { 70 /* No suspend was done */ 71 return FALSE; 72 } 73 } 74 75 VOID 76 NTAPI 77 DbgkpResumeProcess(VOID) 78 { 79 PAGED_CODE(); 80 81 /* Thaw all the threads */ 82 KeThawAllThreads(); 83 } 84 85 VOID 86 NTAPI 87 DbgkCreateThread(IN PETHREAD Thread, 88 IN PVOID StartAddress) 89 { 90 PEPROCESS Process = PsGetCurrentProcess(); 91 ULONG ProcessFlags; 92 IMAGE_INFO ImageInfo; 93 PIMAGE_NT_HEADERS NtHeader; 94 POBJECT_NAME_INFORMATION ModuleName; 95 UNICODE_STRING NtDllName; 96 NTSTATUS Status; 97 PVOID DebugPort; 98 DBGKM_MSG ApiMessage; 99 PDBGKM_CREATE_THREAD CreateThread = &ApiMessage.CreateThread; 100 PDBGKM_CREATE_PROCESS CreateProcess = &ApiMessage.CreateProcess; 101 PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll; 102 OBJECT_ATTRIBUTES ObjectAttributes; 103 IO_STATUS_BLOCK IoStatusBlock; 104 PTEB Teb; 105 PAGED_CODE(); 106 107 /* Sanity check */ 108 ASSERT(Thread == PsGetCurrentThread()); 109 110 /* Try ORing in the create reported and image notify flags */ 111 ProcessFlags = PspSetProcessFlag(Process, 112 PSF_CREATE_REPORTED_BIT | 113 PSF_IMAGE_NOTIFY_DONE_BIT); 114 115 /* Check if we were the first to set them or if another thread raced us */ 116 if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled)) 117 { 118 /* It hasn't.. set up the image info for the process */ 119 ImageInfo.Properties = 0; 120 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT; 121 ImageInfo.ImageBase = Process->SectionBaseAddress; 122 ImageInfo.ImageSize = 0; 123 ImageInfo.ImageSelector = 0; 124 ImageInfo.ImageSectionNumber = 0; 125 126 /* Get the NT Headers */ 127 NtHeader = RtlImageNtHeader(Process->SectionBaseAddress); 128 if (NtHeader) 129 { 130 /* Set image size */ 131 ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage; 132 } 133 134 /* Get the image name */ 135 Status = MmGetFileNameForSection(Process->SectionObject, &ModuleName); 136 if (NT_SUCCESS(Status)) 137 { 138 /* Call the notify routines and free the name */ 139 PspRunLoadImageNotifyRoutines(&ModuleName->Name, 140 Process->UniqueProcessId, 141 &ImageInfo); 142 ExFreePool(ModuleName); 143 } 144 else 145 { 146 /* Call the notify routines */ 147 PspRunLoadImageNotifyRoutines(NULL, 148 Process->UniqueProcessId, 149 &ImageInfo); 150 } 151 152 /* Setup the info for ntdll.dll */ 153 ImageInfo.Properties = 0; 154 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT; 155 ImageInfo.ImageBase = PspSystemDllBase; 156 ImageInfo.ImageSize = 0; 157 ImageInfo.ImageSelector = 0; 158 ImageInfo.ImageSectionNumber = 0; 159 160 /* Get the NT Headers */ 161 NtHeader = RtlImageNtHeader(PspSystemDllBase); 162 if (NtHeader) 163 { 164 /* Set image size */ 165 ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage; 166 } 167 168 /* Call the notify routines */ 169 RtlInitUnicodeString(&NtDllName, 170 L"\\SystemRoot\\System32\\ntdll.dll"); 171 PspRunLoadImageNotifyRoutines(&NtDllName, 172 Process->UniqueProcessId, 173 &ImageInfo); 174 } 175 176 /* Fail if we have no port */ 177 DebugPort = Process->DebugPort; 178 if (!DebugPort) return; 179 180 /* Check if create was not already reported */ 181 if (!(ProcessFlags & PSF_CREATE_REPORTED_BIT)) 182 { 183 /* Setup the information structure for the new thread */ 184 CreateProcess->InitialThread.SubSystemKey = 0; 185 CreateProcess->InitialThread.StartAddress = NULL; 186 187 /* And for the new process */ 188 CreateProcess->SubSystemKey = 0; 189 CreateProcess->FileHandle = DbgkpSectionToFileHandle(Process-> 190 SectionObject); 191 CreateProcess->BaseOfImage = Process->SectionBaseAddress; 192 CreateProcess->DebugInfoFileOffset = 0; 193 CreateProcess->DebugInfoSize = 0; 194 195 /* Get the NT Header */ 196 NtHeader = RtlImageNtHeader(Process->SectionBaseAddress); 197 if (NtHeader) 198 { 199 /* Fill out data from the header */ 200 CreateProcess->InitialThread.StartAddress = 201 (PVOID)((ULONG_PTR)NtHeader->OptionalHeader.ImageBase + 202 NtHeader->OptionalHeader.AddressOfEntryPoint); 203 CreateProcess->DebugInfoFileOffset = NtHeader->FileHeader. 204 PointerToSymbolTable; 205 CreateProcess->DebugInfoSize = NtHeader->FileHeader. 206 NumberOfSymbols; 207 } 208 209 /* Setup the API Message */ 210 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 211 (8 + sizeof(DBGKM_CREATE_PROCESS)); 212 ApiMessage.h.u2.ZeroInit = 0; 213 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 214 ApiMessage.ApiNumber = DbgKmCreateProcessApi; 215 216 /* Send the message */ 217 DbgkpSendApiMessage(&ApiMessage, FALSE); 218 219 /* Close the handle */ 220 ObCloseHandle(CreateProcess->FileHandle, KernelMode); 221 222 /* Setup the parameters */ 223 LoadDll->BaseOfDll = PspSystemDllBase; 224 LoadDll->DebugInfoFileOffset = 0; 225 LoadDll->DebugInfoSize = 0; 226 LoadDll->NamePointer = NULL; 227 228 /* Get the NT Headers */ 229 NtHeader = RtlImageNtHeader(PspSystemDllBase); 230 if (NtHeader) 231 { 232 /* Fill out debug information */ 233 LoadDll->DebugInfoFileOffset = NtHeader-> 234 FileHeader.PointerToSymbolTable; 235 LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols; 236 } 237 238 /* Get the TEB */ 239 Teb = Thread->Tcb.Teb; 240 if (Teb) 241 { 242 /* Copy the system library name and link to it */ 243 wcsncpy(Teb->StaticUnicodeBuffer, 244 L"ntdll.dll", 245 sizeof(Teb->StaticUnicodeBuffer) / sizeof(WCHAR)); 246 Teb->NtTib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer; 247 248 /* Return it in the debug event as well */ 249 LoadDll->NamePointer = &Teb->NtTib.ArbitraryUserPointer; 250 } 251 252 /* Get a handle */ 253 InitializeObjectAttributes(&ObjectAttributes, 254 &PsNtDllPathName, 255 OBJ_CASE_INSENSITIVE | 256 OBJ_KERNEL_HANDLE | 257 OBJ_FORCE_ACCESS_CHECK, 258 NULL, 259 NULL); 260 Status = ZwOpenFile(&LoadDll->FileHandle, 261 GENERIC_READ | SYNCHRONIZE, 262 &ObjectAttributes, 263 &IoStatusBlock, 264 FILE_SHARE_DELETE | 265 FILE_SHARE_READ | 266 FILE_SHARE_WRITE, 267 FILE_SYNCHRONOUS_IO_NONALERT); 268 if (NT_SUCCESS(Status)) 269 { 270 /* Setup the API Message */ 271 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 272 (8 + sizeof(DBGKM_LOAD_DLL)); 273 ApiMessage.h.u2.ZeroInit = 0; 274 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 275 ApiMessage.ApiNumber = DbgKmLoadDllApi; 276 277 /* Send the message */ 278 DbgkpSendApiMessage(&ApiMessage, TRUE); 279 280 /* Close the handle */ 281 ObCloseHandle(LoadDll->FileHandle, KernelMode); 282 } 283 } 284 else 285 { 286 /* Otherwise, do it just for the thread */ 287 CreateThread->SubSystemKey = 0; 288 CreateThread->StartAddress = StartAddress; 289 290 /* Setup the API Message */ 291 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 292 (8 + sizeof(DBGKM_CREATE_THREAD)); 293 ApiMessage.h.u2.ZeroInit = 0; 294 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 295 ApiMessage.ApiNumber = DbgKmCreateThreadApi; 296 297 /* Send the message */ 298 DbgkpSendApiMessage(&ApiMessage, TRUE); 299 } 300 } 301 302 VOID 303 NTAPI 304 DbgkExitProcess(IN NTSTATUS ExitStatus) 305 { 306 DBGKM_MSG ApiMessage; 307 PDBGKM_EXIT_PROCESS ExitProcess = &ApiMessage.ExitProcess; 308 PEPROCESS Process = PsGetCurrentProcess(); 309 PETHREAD Thread = PsGetCurrentThread(); 310 PAGED_CODE(); 311 312 /* Check if this thread is hidden, doesn't have a debug port, or died */ 313 if ((Thread->HideFromDebugger) || 314 !(Process->DebugPort) || 315 (Thread->DeadThread)) 316 { 317 /* Don't notify the debugger */ 318 return; 319 } 320 321 /* Set the exit status */ 322 ExitProcess->ExitStatus = ExitStatus; 323 324 /* Setup the API Message */ 325 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 326 (8 + sizeof(DBGKM_EXIT_PROCESS)); 327 ApiMessage.h.u2.ZeroInit = 0; 328 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 329 ApiMessage.ApiNumber = DbgKmExitProcessApi; 330 331 /* Set the current exit time */ 332 KeQuerySystemTime(&Process->ExitTime); 333 334 /* Send the message */ 335 DbgkpSendApiMessage(&ApiMessage, FALSE); 336 } 337 338 VOID 339 NTAPI 340 DbgkExitThread(IN NTSTATUS ExitStatus) 341 { 342 DBGKM_MSG ApiMessage; 343 PDBGKM_EXIT_THREAD ExitThread = &ApiMessage.ExitThread; 344 PEPROCESS Process = PsGetCurrentProcess(); 345 PETHREAD Thread = PsGetCurrentThread(); 346 BOOLEAN Suspended; 347 PAGED_CODE(); 348 349 /* Check if this thread is hidden, doesn't have a debug port, or died */ 350 if ((Thread->HideFromDebugger) || 351 !(Process->DebugPort) || 352 (Thread->DeadThread)) 353 { 354 /* Don't notify the debugger */ 355 return; 356 } 357 358 /* Set the exit status */ 359 ExitThread->ExitStatus = ExitStatus; 360 361 /* Setup the API Message */ 362 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 363 (8 + sizeof(DBGKM_EXIT_THREAD)); 364 ApiMessage.h.u2.ZeroInit = 0; 365 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 366 ApiMessage.ApiNumber = DbgKmExitThreadApi; 367 368 /* Suspend the process */ 369 Suspended = DbgkpSuspendProcess(); 370 371 /* Send the message */ 372 DbgkpSendApiMessage(&ApiMessage, FALSE); 373 374 /* Resume the process if needed */ 375 if (Suspended) DbgkpResumeProcess(); 376 } 377 378 VOID 379 NTAPI 380 DbgkMapViewOfSection(IN PVOID Section, 381 IN PVOID BaseAddress, 382 IN ULONG SectionOffset, 383 IN ULONG_PTR ViewSize) 384 { 385 DBGKM_MSG ApiMessage; 386 PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll; 387 PEPROCESS Process = PsGetCurrentProcess(); 388 PETHREAD Thread = PsGetCurrentThread(); 389 PIMAGE_NT_HEADERS NtHeader; 390 PAGED_CODE(); 391 DBGKTRACE(DBGK_PROCESS_DEBUG, 392 "Section: %p. Base: %p\n", Section, BaseAddress); 393 394 /* Check if this thread is kernel, hidden or doesn't have a debug port */ 395 if ((ExGetPreviousMode() == KernelMode) || 396 (Thread->HideFromDebugger) || 397 !(Process->DebugPort)) 398 { 399 /* Don't notify the debugger */ 400 return; 401 } 402 403 /* Setup the parameters */ 404 LoadDll->FileHandle = DbgkpSectionToFileHandle(Section); 405 LoadDll->BaseOfDll = BaseAddress; 406 LoadDll->DebugInfoFileOffset = 0; 407 LoadDll->DebugInfoSize = 0; 408 LoadDll->NamePointer = &NtCurrentTeb()->NtTib.ArbitraryUserPointer; 409 410 /* Get the NT Headers */ 411 NtHeader = RtlImageNtHeader(BaseAddress); 412 if (NtHeader) 413 { 414 /* Fill out debug information */ 415 LoadDll->DebugInfoFileOffset = NtHeader->FileHeader. 416 PointerToSymbolTable; 417 LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols; 418 } 419 420 /* Setup the API Message */ 421 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 422 (8 + sizeof(DBGKM_LOAD_DLL)); 423 ApiMessage.h.u2.ZeroInit = 0; 424 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 425 ApiMessage.ApiNumber = DbgKmLoadDllApi; 426 427 /* Send the message */ 428 DbgkpSendApiMessage(&ApiMessage, TRUE); 429 430 /* Close the handle */ 431 ObCloseHandle(LoadDll->FileHandle, KernelMode); 432 } 433 434 VOID 435 NTAPI 436 DbgkUnMapViewOfSection(IN PVOID BaseAddress) 437 { 438 DBGKM_MSG ApiMessage; 439 PDBGKM_UNLOAD_DLL UnloadDll = &ApiMessage.UnloadDll; 440 PEPROCESS Process = PsGetCurrentProcess(); 441 PETHREAD Thread = PsGetCurrentThread(); 442 PAGED_CODE(); 443 444 /* Check if this thread is kernel, hidden or doesn't have a debug port */ 445 if ((ExGetPreviousMode() == KernelMode) || 446 (Thread->HideFromDebugger) || 447 !(Process->DebugPort)) 448 { 449 /* Don't notify the debugger */ 450 return; 451 } 452 453 /* Set the DLL Base */ 454 UnloadDll->BaseAddress = BaseAddress; 455 456 /* Setup the API Message */ 457 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 | 458 (8 + sizeof(DBGKM_UNLOAD_DLL)); 459 ApiMessage.h.u2.ZeroInit = 0; 460 ApiMessage.h.u2.s2.Type = LPC_DEBUG_EVENT; 461 ApiMessage.ApiNumber = DbgKmUnloadDllApi; 462 463 /* Send the message */ 464 DbgkpSendApiMessage(&ApiMessage, TRUE); 465 } 466