@@ -40,30 +40,25 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) {
40
40
info->symbolAddress = dli_saddr;
41
41
return 1 ;
42
42
#elif defined(_WIN32)
43
- return _swift_withWin32DbgHelpLibrary ([&] (bool isInitialized ) {
43
+ return _swift_win32_withDbgHelpLibrary ([&] (HANDLE hProcess ) {
44
44
static const constexpr size_t kSymbolMaxNameLen = 1024 ;
45
45
46
- if (!isInitialized ) {
46
+ if (!hProcess ) {
47
47
return 0 ;
48
48
}
49
49
50
- char buffer[sizeof (SYMBOL_INFO) + kSymbolMaxNameLen ];
51
- PSYMBOL_INFO pSymbol = reinterpret_cast <PSYMBOL_INFO>(buffer);
52
- pSymbol->SizeOfStruct = sizeof (SYMBOL_INFO);
53
- pSymbol->MaxNameLen = kSymbolMaxNameLen ;
54
-
55
- DWORD64 dwDisplacement = 0 ;
56
-
57
- if (SymFromAddr (GetCurrentProcess (),
58
- reinterpret_cast <const DWORD64>(address),
59
- &dwDisplacement, pSymbol) == FALSE ) {
50
+ SYMBOL_INFO_PACKAGE symbol = {};
51
+ symbol.si .SizeOfStruct = sizeof (SYMBOL_INFO);
52
+ symbol.si .MaxNameLen = MAX_SYM_NAME;
53
+ if (SymFromAddr (hProcess, reinterpret_cast <const DWORD64>(address),
54
+ nullptr , &symbol.si ) == FALSE ) {
60
55
return 0 ;
61
56
}
62
57
63
58
info->fileName = NULL ;
64
- info->baseAddress = reinterpret_cast <void *>(pSymbol-> ModBase );
65
- info->symbolName .reset (_strdup (pSymbol-> Name ));
66
- info->symbolAddress = reinterpret_cast <void *>(pSymbol-> Address );
59
+ info->baseAddress = reinterpret_cast <void *>(symbol. si . ModBase );
60
+ info->symbolName .reset (_strdup (symbol. si . Name ));
61
+ info->symbolAddress = reinterpret_cast <void *>(symbol. si . Address );
67
62
68
63
return 1 ;
69
64
});
@@ -74,16 +69,58 @@ int swift::lookupSymbol(const void *address, SymbolInfo *info) {
74
69
75
70
#if defined(_WIN32)
76
71
static LazyMutex mutex;
77
- static bool isDbgHelpInitialized = false ;
72
+ static HANDLE dbgHelpHandle = nullptr ;
78
73
79
- void swift::_swift_withWin32DbgHelpLibrary (
80
- void (* body)(bool isInitialized , void *context), void *context) {
74
+ void swift::_swift_win32_withDbgHelpLibrary (
75
+ void (* body)(HANDLE hProcess , void *context), void *context) {
81
76
mutex.withLock ([=] () {
82
- if (!isDbgHelpInitialized) {
83
- SymSetOptions (SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS);
84
- isDbgHelpInitialized = SymInitialize (GetCurrentProcess (), nullptr , true );
77
+ // If we have not previously created a handle to use with the library, do so
78
+ // now. This handle belongs to the Swift runtime and should not be closed by
79
+ // `body` (or anybody else.)
80
+ if (!dbgHelpHandle) {
81
+ // Per the documentation for the Debug Help library, we should not use the
82
+ // current process handle because other subsystems might also use it and
83
+ // end up stomping on each other. So we'll try to duplicate that handle to
84
+ // get a unique one that still fulfills the needs of the library. If that
85
+ // fails (presumably because the current process doesn't have the
86
+ // PROCESS_DUP_HANDLE access right) then fall back to using the original
87
+ // process handle and hope nobody else is using it too.
88
+ HANDLE currentProcess = GetCurrentProcess ();
89
+ if (!DuplicateHandle (currentProcess, currentProcess, currentProcess,
90
+ &dbgHelpHandle, 0 , false , DUPLICATE_SAME_ACCESS)) {
91
+ dbgHelpHandle = currentProcess;
92
+ }
93
+ }
94
+
95
+ // If we have not previously initialized the Debug Help library, do so now.
96
+ bool isDbgHelpInitialized = false ;
97
+ if (dbgHelpHandle) {
98
+ isDbgHelpInitialized = SymInitialize (dbgHelpHandle, nullptr , true );
99
+ }
100
+
101
+ if (isDbgHelpInitialized) {
102
+ // Set the library's options to what the Swift runtime generally expects.
103
+ // If the options aren't going to change, we can skip the call and save a
104
+ // few CPU cycles on the library call.
105
+ constexpr const DWORD options = SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS;
106
+ DWORD oldOptions = SymGetOptions ();
107
+ if (oldOptions != options) {
108
+ SymSetOptions (options);
109
+ }
110
+
111
+ body (dbgHelpHandle, context);
112
+
113
+ // Before returning, reset the library's options back to their previous
114
+ // value. No need to call if the options didn't change because LazyMutex
115
+ // is not recursive, so there shouldn't be an outer call expecting the
116
+ // original options, and a subsequent call to this function will set them
117
+ // to the defaults above.
118
+ if (oldOptions != options) {
119
+ SymSetOptions (oldOptions);
120
+ }
121
+ } else {
122
+ body (nullptr , context);
85
123
}
86
- body (isDbgHelpInitialized, context);
87
124
});
88
125
}
89
126
#endif
0 commit comments