VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/init-win.cpp@ 69434

Last change on this file since 69434 was 69434, checked in by vboxsync, 7 years ago

Runtime: scm updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.3 KB
Line 
1/* $Id: init-win.cpp 69434 2017-10-27 15:48:25Z vboxsync $ */
2/** @file
3 * IPRT - Init Ring-3, Windows Specific Code.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DEFAULT
32#include <iprt/nt/nt-and-windows.h>
33#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
34# define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x200
35# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
36#endif
37
38#include "internal-r3-win.h"
39#include <iprt/initterm.h>
40#include <iprt/assert.h>
41#include <iprt/err.h>
42#include <iprt/log.h>
43#include <iprt/param.h>
44#include <iprt/string.h>
45#include <iprt/thread.h>
46#include "../init.h"
47
48
49/*********************************************************************************************************************************
50* Structures and Typedefs *
51*********************************************************************************************************************************/
52typedef VOID (WINAPI *PFNGETCURRENTTHREADSTACKLIMITS)(PULONG_PTR puLow, PULONG_PTR puHigh);
53typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI * PFNSETUNHANDLEDEXCEPTIONFILTER)(LPTOP_LEVEL_EXCEPTION_FILTER);
54
55
56/*********************************************************************************************************************************
57* Global Variables *
58*********************************************************************************************************************************/
59/** Windows DLL loader protection level. */
60DECLHIDDEN(RTR3WINLDRPROT) g_enmWinLdrProt = RTR3WINLDRPROT_NONE;
61/** Our simplified windows version. */
62DECLHIDDEN(RTWINOSTYPE) g_enmWinVer = kRTWinOSType_UNKNOWN;
63/** Extended windows version information. */
64DECLHIDDEN(OSVERSIONINFOEXW) g_WinOsInfoEx;
65/** The native kernel32.dll handle. */
66DECLHIDDEN(HMODULE) g_hModKernel32 = NULL;
67/** The native ntdll.dll handle. */
68DECLHIDDEN(HMODULE) g_hModNtDll = NULL;
69/** GetSystemWindowsDirectoryW or GetWindowsDirectoryW (NT4). */
70DECLHIDDEN(PFNGETWINSYSDIR) g_pfnGetSystemWindowsDirectoryW = NULL;
71/** The GetCurrentThreadStackLimits API. */
72static PFNGETCURRENTTHREADSTACKLIMITS g_pfnGetCurrentThreadStackLimits = NULL;
73/** SetUnhandledExceptionFilter. */
74static PFNSETUNHANDLEDEXCEPTIONFILTER g_pfnSetUnhandledExceptionFilter = NULL;
75/** The previous unhandled exception filter. */
76static LPTOP_LEVEL_EXCEPTION_FILTER g_pfnUnhandledXcptFilter = NULL;
77
78
79/*********************************************************************************************************************************
80* Internal Functions *
81*********************************************************************************************************************************/
82static LONG CALLBACK rtR3WinUnhandledXcptFilter(PEXCEPTION_POINTERS);
83
84
85/**
86 * Translates OSVERSIONINOFEX into a Windows OS type.
87 *
88 * @returns The Windows OS type.
89 * @param pOSInfoEx The OS info returned by Windows.
90 *
91 * @remarks This table has been assembled from Usenet postings, personal
92 * observations, and reading other people's code. Please feel
93 * free to add to it or correct it.
94 * <pre>
95 dwPlatFormID dwMajorVersion dwMinorVersion dwBuildNumber
9695 1 4 0 950
9795 SP1 1 4 0 >950 && <=1080
9895 OSR2 1 4 <10 >1080
9998 1 4 10 1998
10098 SP1 1 4 10 >1998 && <2183
10198 SE 1 4 10 >=2183
102ME 1 4 90 3000
103
104NT 3.51 2 3 51 1057
105NT 4 2 4 0 1381
1062000 2 5 0 2195
107XP 2 5 1 2600
1082003 2 5 2 3790
109Vista 2 6 0
110
111CE 1.0 3 1 0
112CE 2.0 3 2 0
113CE 2.1 3 2 1
114CE 3.0 3 3 0
115</pre>
116 */
117static RTWINOSTYPE rtR3InitWinSimplifiedVersion(OSVERSIONINFOEXW const *pOSInfoEx)
118{
119 RTWINOSTYPE enmVer = kRTWinOSType_UNKNOWN;
120 BYTE const bProductType = pOSInfoEx->wProductType;
121 DWORD const dwPlatformId = pOSInfoEx->dwPlatformId;
122 DWORD const dwMinorVersion = pOSInfoEx->dwMinorVersion;
123 DWORD const dwMajorVersion = pOSInfoEx->dwMajorVersion;
124 DWORD const dwBuildNumber = pOSInfoEx->dwBuildNumber & 0xFFFF; /* Win 9x needs this. */
125
126 if ( dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
127 && dwMajorVersion == 4)
128 {
129 if ( dwMinorVersion < 10
130 && dwBuildNumber == 950)
131 enmVer = kRTWinOSType_95;
132 else if ( dwMinorVersion < 10
133 && dwBuildNumber > 950
134 && dwBuildNumber <= 1080)
135 enmVer = kRTWinOSType_95SP1;
136 else if ( dwMinorVersion < 10
137 && dwBuildNumber > 1080)
138 enmVer = kRTWinOSType_95OSR2;
139 else if ( dwMinorVersion == 10
140 && dwBuildNumber == 1998)
141 enmVer = kRTWinOSType_98;
142 else if ( dwMinorVersion == 10
143 && dwBuildNumber > 1998
144 && dwBuildNumber < 2183)
145 enmVer = kRTWinOSType_98SP1;
146 else if ( dwMinorVersion == 10
147 && dwBuildNumber >= 2183)
148 enmVer = kRTWinOSType_98SE;
149 else if (dwMinorVersion == 90)
150 enmVer = kRTWinOSType_ME;
151 }
152 else if (dwPlatformId == VER_PLATFORM_WIN32_NT)
153 {
154 if ( dwMajorVersion == 3
155 && dwMinorVersion == 51)
156 enmVer = kRTWinOSType_NT351;
157 else if ( dwMajorVersion == 4
158 && dwMinorVersion == 0)
159 enmVer = kRTWinOSType_NT4;
160 else if ( dwMajorVersion == 5
161 && dwMinorVersion == 0)
162 enmVer = kRTWinOSType_2K;
163 else if ( dwMajorVersion == 5
164 && dwMinorVersion == 1)
165 enmVer = kRTWinOSType_XP;
166 else if ( dwMajorVersion == 5
167 && dwMinorVersion == 2)
168 enmVer = kRTWinOSType_2003;
169 else if ( dwMajorVersion == 6
170 && dwMinorVersion == 0)
171 {
172 if (bProductType != VER_NT_WORKSTATION)
173 enmVer = kRTWinOSType_2008;
174 else
175 enmVer = kRTWinOSType_VISTA;
176 }
177 else if ( dwMajorVersion == 6
178 && dwMinorVersion == 1)
179 {
180 if (bProductType != VER_NT_WORKSTATION)
181 enmVer = kRTWinOSType_2008R2;
182 else
183 enmVer = kRTWinOSType_7;
184 }
185 else if ( dwMajorVersion == 6
186 && dwMinorVersion == 2)
187 {
188 if (bProductType != VER_NT_WORKSTATION)
189 enmVer = kRTWinOSType_2012;
190 else
191 enmVer = kRTWinOSType_8;
192 }
193 else if ( dwMajorVersion == 6
194 && dwMinorVersion == 3)
195 {
196 if (bProductType != VER_NT_WORKSTATION)
197 enmVer = kRTWinOSType_2012R2;
198 else
199 enmVer = kRTWinOSType_81;
200 }
201 else if ( ( dwMajorVersion == 6
202 && dwMinorVersion == 4)
203 || ( dwMajorVersion == 10
204 && dwMinorVersion == 0))
205 {
206 if (bProductType != VER_NT_WORKSTATION)
207 enmVer = kRTWinOSType_2016;
208 else
209 enmVer = kRTWinOSType_10;
210 }
211 else
212 enmVer = kRTWinOSType_NT_UNKNOWN;
213 }
214
215 return enmVer;
216}
217
218
219/**
220 * Initializes the global variables related to windows version.
221 */
222static void rtR3InitWindowsVersion(void)
223{
224 Assert(g_hModNtDll != NULL);
225
226 /*
227 * ASSUMES OSVERSIONINFOEX starts with the exact same layout as OSVERSIONINFO (safe).
228 */
229 AssertCompileMembersSameSizeAndOffset(OSVERSIONINFOEX, szCSDVersion, OSVERSIONINFO, szCSDVersion);
230 AssertCompileMemberOffset(OSVERSIONINFOEX, wServicePackMajor, sizeof(OSVERSIONINFO));
231
232 /*
233 * Use the NT version of GetVersionExW so we don't get fooled by
234 * compatability shims.
235 */
236 RT_ZERO(g_WinOsInfoEx);
237 g_WinOsInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
238
239 LONG (__stdcall *pfnRtlGetVersion)(OSVERSIONINFOEXW *);
240 *(FARPROC *)&pfnRtlGetVersion = GetProcAddress(g_hModNtDll, "RtlGetVersion");
241 LONG rcNt = -1;
242 if (pfnRtlGetVersion)
243 rcNt = pfnRtlGetVersion(&g_WinOsInfoEx);
244 if (rcNt != 0)
245 {
246 /*
247 * Couldn't find it or it failed, try the windows version of the API.
248 */
249 RT_ZERO(g_WinOsInfoEx);
250 g_WinOsInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
251 if (!GetVersionExW((POSVERSIONINFOW)&g_WinOsInfoEx))
252 {
253 /*
254 * If that didn't work either, just get the basic version bits.
255 */
256 RT_ZERO(g_WinOsInfoEx);
257 g_WinOsInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
258 if (GetVersionExW((POSVERSIONINFOW)&g_WinOsInfoEx))
259 Assert(g_WinOsInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT || g_WinOsInfoEx.dwMajorVersion < 5);
260 else
261 {
262 AssertBreakpoint();
263 RT_ZERO(g_WinOsInfoEx);
264 }
265 }
266 }
267
268 if (g_WinOsInfoEx.dwOSVersionInfoSize)
269 g_enmWinVer = rtR3InitWinSimplifiedVersion(&g_WinOsInfoEx);
270}
271
272
273static int rtR3InitNativeObtrusiveWorker(uint32_t fFlags)
274{
275 /*
276 * Disable error popups.
277 */
278 UINT fOldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
279 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX | fOldErrMode);
280
281 /*
282 * Restrict DLL searching for the process on windows versions which allow
283 * us to do so.
284 * - The first trick works on XP SP1+ and disables the searching of the
285 * current directory.
286 * - The second trick is W7 w/ KB2533623 and W8+, it restrict the DLL
287 * searching to the application directory (except when
288 * RTR3INIT_FLAGS_STANDALONE_APP is given) and the System32 directory.
289 */
290 int rc = VINF_SUCCESS;
291
292 typedef BOOL (WINAPI *PFNSETDLLDIRECTORY)(LPCWSTR);
293 PFNSETDLLDIRECTORY pfnSetDllDir = (PFNSETDLLDIRECTORY)GetProcAddress(g_hModKernel32, "SetDllDirectoryW");
294 if (pfnSetDllDir)
295 {
296 if (pfnSetDllDir(L""))
297 g_enmWinLdrProt = RTR3WINLDRPROT_NO_CWD;
298 else
299 rc = VERR_INTERNAL_ERROR_3;
300 }
301
302 /** @bugref{6861} Observed GUI issues on Vista (32-bit and 64-bit) when using
303 * SetDefaultDllDirectories.
304 * @bugref{8194} Try use SetDefaultDllDirectories on Vista for standalone apps
305 * despite potential GUI issues. */
306 if ( g_enmWinVer > kRTWinOSType_VISTA
307 || (fFlags & RTR3INIT_FLAGS_STANDALONE_APP))
308 {
309 typedef BOOL(WINAPI *PFNSETDEFAULTDLLDIRECTORIES)(DWORD);
310 PFNSETDEFAULTDLLDIRECTORIES pfnSetDefDllDirs;
311 pfnSetDefDllDirs = (PFNSETDEFAULTDLLDIRECTORIES)GetProcAddress(g_hModKernel32, "SetDefaultDllDirectories");
312 if (pfnSetDefDllDirs)
313 {
314 DWORD fDllDirs = LOAD_LIBRARY_SEARCH_SYSTEM32;
315 if (!(fFlags & RTR3INIT_FLAGS_STANDALONE_APP))
316 fDllDirs |= LOAD_LIBRARY_SEARCH_APPLICATION_DIR;
317 if (pfnSetDefDllDirs(fDllDirs))
318 g_enmWinLdrProt = fDllDirs & LOAD_LIBRARY_SEARCH_APPLICATION_DIR ? RTR3WINLDRPROT_SAFE : RTR3WINLDRPROT_SAFER;
319 else if (RT_SUCCESS(rc))
320 rc = VERR_INTERNAL_ERROR_4;
321 }
322 }
323
324 /*
325 * Register an unhandled exception callback if we can.
326 */
327 g_pfnGetCurrentThreadStackLimits = (PFNGETCURRENTTHREADSTACKLIMITS)GetProcAddress(g_hModKernel32, "GetCurrentThreadStackLimits");
328 g_pfnSetUnhandledExceptionFilter = (PFNSETUNHANDLEDEXCEPTIONFILTER)GetProcAddress(g_hModKernel32, "SetUnhandledExceptionFilter");
329 if (g_pfnSetUnhandledExceptionFilter && !g_pfnUnhandledXcptFilter)
330 {
331 g_pfnUnhandledXcptFilter = g_pfnSetUnhandledExceptionFilter(rtR3WinUnhandledXcptFilter);
332 AssertStmt(g_pfnUnhandledXcptFilter != rtR3WinUnhandledXcptFilter, g_pfnUnhandledXcptFilter = NULL);
333 }
334
335 return rc;
336}
337
338
339DECLHIDDEN(int) rtR3InitNativeFirst(uint32_t fFlags)
340{
341 /*
342 * Make sure we've got the handles of the two main Windows NT dlls.
343 */
344 g_hModKernel32 = GetModuleHandleW(L"kernel32.dll");
345 if (g_hModKernel32 == NULL)
346 return VERR_INTERNAL_ERROR_2;
347 g_hModNtDll = GetModuleHandleW(L"ntdll.dll");
348 if (g_hModNtDll == NULL)
349 return VERR_INTERNAL_ERROR_2;
350
351 rtR3InitWindowsVersion();
352
353 int rc = VINF_SUCCESS;
354 if (!(fFlags & RTR3INIT_FLAGS_UNOBTRUSIVE))
355 rc = rtR3InitNativeObtrusiveWorker(fFlags);
356
357 /*
358 * Resolve some kernel32.dll APIs we may need but aren't necessarily
359 * present in older windows versions.
360 */
361 g_pfnGetSystemWindowsDirectoryW = (PFNGETWINSYSDIR)GetProcAddress(g_hModKernel32, "GetSystemWindowsDirectoryW");
362 if (g_pfnGetSystemWindowsDirectoryW)
363 g_pfnGetSystemWindowsDirectoryW = (PFNGETWINSYSDIR)GetProcAddress(g_hModKernel32, "GetWindowsDirectoryW");
364
365 return rc;
366}
367
368
369DECLHIDDEN(void) rtR3InitNativeObtrusive(uint32_t fFlags)
370{
371 rtR3InitNativeObtrusiveWorker(fFlags);
372}
373
374
375DECLHIDDEN(int) rtR3InitNativeFinal(uint32_t fFlags)
376{
377 /* Nothing to do here. */
378 RT_NOREF_PV(fFlags);
379 return VINF_SUCCESS;
380}
381
382
383/**
384 * Unhandled exception filter callback.
385 *
386 * Will try log stuff.
387 */
388static LONG CALLBACK rtR3WinUnhandledXcptFilter(PEXCEPTION_POINTERS pPtrs)
389{
390 /*
391 * Try get the logger and log exception details.
392 *
393 * Note! We'll be using RTLogLogger for now, though we should probably add
394 * a less deadlock prone API here and gives up pretty fast if it
395 * cannot get the lock...
396 */
397 PRTLOGGER pLogger = RTLogRelGetDefaultInstance();
398 if (!pLogger)
399 pLogger = RTLogGetDefaultInstance();
400 if (pLogger)
401 {
402 RTLogLogger(pLogger, NULL, "\n!!! rtR3WinUnhandledXcptFilter caught an exception on thread %p!!!\n", RTThreadNativeSelf());
403
404 /*
405 * Dump the exception record.
406 */
407 uintptr_t uXcptPC = 0;
408 PEXCEPTION_RECORD pXcptRec = RT_VALID_PTR(pPtrs) && RT_VALID_PTR(pPtrs->ExceptionRecord) ? pPtrs->ExceptionRecord : NULL;
409 if (pXcptRec)
410 {
411 RTLogLogger(pLogger, NULL, "\nExceptionCode=%#010x ExceptionFlags=%#010x ExceptionAddress=%p\n",
412 pXcptRec->ExceptionCode, pXcptRec->ExceptionFlags, pXcptRec->ExceptionAddress);
413 for (uint32_t i = 0; i < RT_MIN(pXcptRec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); i++)
414 RTLogLogger(pLogger, NULL, "ExceptionInformation[%d]=%p\n", i, pXcptRec->ExceptionInformation[i]);
415 uXcptPC = (uintptr_t)pXcptRec->ExceptionAddress;
416
417 /* Nested? Display one level only. */
418 PEXCEPTION_RECORD pNestedRec = pXcptRec->ExceptionRecord;
419 if (RT_VALID_PTR(pNestedRec))
420 {
421 RTLogLogger(pLogger, NULL, "Nested: ExceptionCode=%#010x ExceptionFlags=%#010x ExceptionAddress=%p (nested %p)\n",
422 pNestedRec->ExceptionCode, pNestedRec->ExceptionFlags, pNestedRec->ExceptionAddress,
423 pNestedRec->ExceptionRecord);
424 for (uint32_t i = 0; i < RT_MIN(pNestedRec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); i++)
425 RTLogLogger(pLogger, NULL, "Nested: ExceptionInformation[%d]=%p\n", i, pNestedRec->ExceptionInformation[i]);
426 uXcptPC = (uintptr_t)pNestedRec->ExceptionAddress;
427 }
428 }
429
430 /*
431 * Dump the context record.
432 */
433 volatile char szMarker[] = "stackmarker";
434 uintptr_t uXcptSP = (uintptr_t)&szMarker[0];
435 PCONTEXT pXcptCtx = RT_VALID_PTR(pPtrs) && RT_VALID_PTR(pPtrs->ContextRecord) ? pPtrs->ContextRecord : NULL;
436 if (pXcptCtx)
437 {
438#ifdef RT_ARCH_AMD64
439 RTLogLogger(pLogger, NULL, "\ncs:rip=%04x:%016RX64\n", pXcptCtx->SegCs, pXcptCtx->Rip);
440 RTLogLogger(pLogger, NULL, "ss:rsp=%04x:%016RX64 rbp=%016RX64\n", pXcptCtx->SegSs, pXcptCtx->Rsp, pXcptCtx->Rbp);
441 RTLogLogger(pLogger, NULL, "rax=%016RX64 rcx=%016RX64 rdx=%016RX64 rbx=%016RX64\n",
442 pXcptCtx->Rax, pXcptCtx->Rcx, pXcptCtx->Rdx, pXcptCtx->Rbx);
443 RTLogLogger(pLogger, NULL, "rsi=%016RX64 rdi=%016RX64 rsp=%016RX64 rbp=%016RX64\n",
444 pXcptCtx->Rsi, pXcptCtx->Rdi, pXcptCtx->Rsp, pXcptCtx->Rbp);
445 RTLogLogger(pLogger, NULL, "r8 =%016RX64 r9 =%016RX64 r10=%016RX64 r11=%016RX64\n",
446 pXcptCtx->R8, pXcptCtx->R9, pXcptCtx->R10, pXcptCtx->R11);
447 RTLogLogger(pLogger, NULL, "r12=%016RX64 r13=%016RX64 r14=%016RX64 r15=%016RX64\n",
448 pXcptCtx->R12, pXcptCtx->R13, pXcptCtx->R14, pXcptCtx->R15);
449 RTLogLogger(pLogger, NULL, "ds=%04x es=%04x fs=%04x gs=%04x eflags=%08x\n",
450 pXcptCtx->SegDs, pXcptCtx->SegEs, pXcptCtx->SegFs, pXcptCtx->SegGs, pXcptCtx->EFlags);
451 RTLogLogger(pLogger, NULL, "p1home=%016RX64 p2home=%016RX64 pe3home=%016RX64\n",
452 pXcptCtx->P1Home, pXcptCtx->P2Home, pXcptCtx->P3Home);
453 RTLogLogger(pLogger, NULL, "p4home=%016RX64 p5home=%016RX64 pe6home=%016RX64\n",
454 pXcptCtx->P4Home, pXcptCtx->P5Home, pXcptCtx->P6Home);
455 RTLogLogger(pLogger, NULL, " LastBranchToRip=%016RX64 LastBranchFromRip=%016RX64\n",
456 pXcptCtx->LastBranchToRip, pXcptCtx->LastBranchFromRip);
457 RTLogLogger(pLogger, NULL, "LastExceptionToRip=%016RX64 LastExceptionFromRip=%016RX64\n",
458 pXcptCtx->LastExceptionToRip, pXcptCtx->LastExceptionFromRip);
459 uXcptSP = pXcptCtx->Rsp;
460 uXcptPC = pXcptCtx->Rip;
461
462#elif defined(RT_ARCH_X86)
463 RTLogLogger(pLogger, NULL, "\ncs:eip=%04x:%08RX32\n", pXcptCtx->SegCs, pXcptCtx->Eip);
464 RTLogLogger(pLogger, NULL, "ss:esp=%04x:%08RX32 ebp=%08RX32\n", pXcptCtx->SegSs, pXcptCtx->Esp, pXcptCtx->Ebp);
465 RTLogLogger(pLogger, NULL, "eax=%08RX32 ecx=%08RX32 edx=%08RX32 ebx=%08RX32\n",
466 pXcptCtx->Eax, pXcptCtx->Ecx, pXcptCtx->Edx, pXcptCtx->Ebx);
467 RTLogLogger(pLogger, NULL, "esi=%08RX32 edi=%08RX32 esp=%08RX32 ebp=%08RX32\n",
468 pXcptCtx->Esi, pXcptCtx->Edi, pXcptCtx->Esp, pXcptCtx->Ebp);
469 RTLogLogger(pLogger, NULL, "ds=%04x es=%04x fs=%04x gs=%04x eflags=%08x\n",
470 pXcptCtx->SegDs, pXcptCtx->SegEs, pXcptCtx->SegFs, pXcptCtx->SegGs, pXcptCtx->EFlags);
471 uXcptSP = pXcptCtx->Esp;
472 uXcptPC = pXcptCtx->Eip;
473#endif
474 }
475
476 /*
477 * Dump stack.
478 */
479 uintptr_t uStack = (uintptr_t)(void *)&szMarker[0];
480 uStack -= uStack & 15;
481
482 size_t cbToDump = PAGE_SIZE - (uStack & PAGE_OFFSET_MASK);
483 if (cbToDump < 512)
484 cbToDump += PAGE_SIZE;
485 size_t cbToXcpt = uXcptSP - uStack;
486 while (cbToXcpt > cbToDump && cbToXcpt <= _16K)
487 cbToDump += PAGE_SIZE;
488 ULONG_PTR uLow = (uintptr_t)&szMarker[0];
489 ULONG_PTR uHigh = (uintptr_t)&szMarker[0];
490 if (g_pfnGetCurrentThreadStackLimits)
491 {
492 g_pfnGetCurrentThreadStackLimits(&uLow, &uHigh);
493 size_t cbToTop = RT_MAX(uLow, uHigh) - uStack;
494 if (cbToTop < _1M)
495 cbToDump = cbToTop;
496 }
497
498 RTLogLogger(pLogger, NULL, "\nStack %p, dumping %#x bytes (low=%p, high=%p)\n", uStack, cbToDump, uLow, uHigh);
499 RTLogLogger(pLogger, NULL, "%.*RhxD\n", cbToDump, uStack);
500
501 /*
502 * Try figure the thread name.
503 *
504 * Note! This involves the thread db lock, so it may deadlock, which
505 * is why it's at the end.
506 */
507 RTLogLogger(pLogger, NULL, "Thread ID: %p\n", RTThreadNativeSelf());
508 RTLogLogger(pLogger, NULL, "Thread name: %s\n", RTThreadSelfName());
509 RTLogLogger(pLogger, NULL, "Thread IPRT: %p\n", RTThreadSelf());
510
511 /*
512 * Try dump the load information.
513 */
514 PPEB pPeb = RTNtCurrentPeb();
515 if (RT_VALID_PTR(pPeb))
516 {
517 PPEB_LDR_DATA pLdrData = pPeb->Ldr;
518 if (RT_VALID_PTR(pLdrData))
519 {
520 PLDR_DATA_TABLE_ENTRY pFound = NULL;
521 LIST_ENTRY * const pList = &pLdrData->InMemoryOrderModuleList;
522 LIST_ENTRY *pListEntry = pList->Flink;
523 uint32_t cLoops = 0;
524 RTLogLogger(pLogger, NULL,
525 "\nLoaded Modules:\n"
526 "%-*s[*] Timestamp Path\n", sizeof(void *) * 4 + 2 - 1, "Address range"
527 );
528 while (pListEntry != pList && RT_VALID_PTR(pListEntry) && cLoops < 1024)
529 {
530 PLDR_DATA_TABLE_ENTRY pLdrEntry = RT_FROM_MEMBER(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
531 uint32_t const cbLength = (uint32_t)(uintptr_t)pLdrEntry->Reserved3[1];
532 char chInd = ' ';
533 if (uXcptPC - (uintptr_t)pLdrEntry->DllBase < cbLength)
534 {
535 chInd = '*';
536 pFound = pLdrEntry;
537 }
538
539 if ( RT_VALID_PTR(pLdrEntry->FullDllName.Buffer)
540 && pLdrEntry->FullDllName.Length > 0
541 && pLdrEntry->FullDllName.Length < _8K
542 && (pLdrEntry->FullDllName.Length & 1) == 0
543 && pLdrEntry->FullDllName.Length <= pLdrEntry->FullDllName.MaximumLength)
544 RTLogLogger(pLogger, NULL, "%p..%p%c %08RX32 %.*ls\n",
545 pLdrEntry->DllBase, (uintptr_t)pLdrEntry->DllBase + cbLength - 1, chInd,
546 pLdrEntry->TimeDateStamp, pLdrEntry->FullDllName.Length / sizeof(RTUTF16),
547 pLdrEntry->FullDllName.Buffer);
548 else
549 RTLogLogger(pLogger, NULL, "%p..%p%c %08RX32 <bad or missing: %p LB %#x max %#x\n",
550 pLdrEntry->DllBase, (uintptr_t)pLdrEntry->DllBase + cbLength - 1, chInd,
551 pLdrEntry->TimeDateStamp, pLdrEntry->FullDllName.Buffer, pLdrEntry->FullDllName.Length,
552 pLdrEntry->FullDllName.MaximumLength);
553
554 /* advance */
555 pListEntry = pListEntry->Flink;
556 cLoops++;
557 }
558
559 /*
560 * Use the above to pick out code addresses on the stack.
561 */
562 if ( cLoops < 1024
563 && uXcptSP - uStack < cbToDump)
564 {
565 RTLogLogger(pLogger, NULL, "\nPotential code addresses on the stack:\n");
566 if (pFound)
567 {
568 if ( RT_VALID_PTR(pFound->FullDllName.Buffer)
569 && pFound->FullDllName.Length > 0
570 && pFound->FullDllName.Length < _8K
571 && (pFound->FullDllName.Length & 1) == 0
572 && pFound->FullDllName.Length <= pFound->FullDllName.MaximumLength)
573 RTLogLogger(pLogger, NULL, "%-*s: %p - %#010RX32 bytes into %.*ls\n",
574 sizeof(void *) * 2, "Xcpt PC", uXcptPC, (uint32_t)(uXcptPC - (uintptr_t)pFound->DllBase),
575 pFound->FullDllName.Length / sizeof(RTUTF16), pFound->FullDllName.Buffer);
576 else
577 RTLogLogger(pLogger, NULL, "%-*s: %p - %08RX32 into module at %p\n",
578 sizeof(void *) * 2, "Xcpt PC", uXcptPC, (uint32_t)(uXcptPC - (uintptr_t)pFound->DllBase),
579 pFound->DllBase);
580 }
581
582 uintptr_t const *puStack = (uintptr_t const *)uXcptSP;
583 uintptr_t cLeft = (cbToDump - (uXcptSP - uStack)) / sizeof(uintptr_t);
584 while (cLeft-- > 0)
585 {
586 uintptr_t uPtr = *puStack;
587 if (RT_VALID_PTR(uPtr))
588 {
589 /* Search the module table. */
590 pFound = NULL;
591 cLoops = 0;
592 pListEntry = pList->Flink;
593 while (pListEntry != pList && RT_VALID_PTR(pListEntry) && cLoops < 1024)
594 {
595 PLDR_DATA_TABLE_ENTRY pLdrEntry = RT_FROM_MEMBER(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
596 uint32_t const cbLength = (uint32_t)(uintptr_t)pLdrEntry->Reserved3[1];
597 if (uPtr - (uintptr_t)pLdrEntry->DllBase < cbLength)
598 {
599 pFound = pLdrEntry;
600 break;
601 }
602
603 /* advance */
604 pListEntry = pListEntry->Flink;
605 cLoops++;
606 }
607
608 if (pFound)
609 {
610 if ( RT_VALID_PTR(pFound->FullDllName.Buffer)
611 && pFound->FullDllName.Length > 0
612 && pFound->FullDllName.Length < _8K
613 && (pFound->FullDllName.Length & 1) == 0
614 && pFound->FullDllName.Length <= pFound->FullDllName.MaximumLength)
615 RTLogLogger(pLogger, NULL, "%p: %p - %#010RX32 bytes into %.*ls\n",
616 puStack, uPtr, (uint32_t)(uPtr - (uintptr_t)pFound->DllBase),
617 pFound->FullDllName.Length / sizeof(RTUTF16), pFound->FullDllName.Buffer);
618 else
619 RTLogLogger(pLogger, NULL, "%p: %p - %08RX32 into module at %p\n",
620 puStack, uPtr, (uint32_t)(uPtr - (uintptr_t)pFound->DllBase), pFound->DllBase);
621 }
622 }
623
624 puStack++;
625 }
626 }
627 }
628 }
629 }
630
631 /*
632 * Do the default stuff, never mind us.
633 */
634 if (g_pfnUnhandledXcptFilter)
635 return g_pfnUnhandledXcptFilter(pPtrs);
636 return EXCEPTION_CONTINUE_SEARCH;
637}
638
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette