1919# include < cstring>
2020# include < mutex>
2121
22- # if defined(_MSC_VER) && !defined(__MINGW32__)
23- # pragma comment(lib, "dbghelp")
24- # pragma comment(lib, "psapi")
25- # endif
26-
2722_LIBCPP_BEGIN_NAMESPACE_STD
2823namespace __stacktrace {
2924
3025namespace {
3126
27+ namespace __dll {
28+
29+ template <typename F>
30+ bool get_func (HMODULE module , F** func, char const * name) {
31+ return ((*func = reinterpret_cast <F*>(reinterpret_cast <void *>(GetProcAddress (module , name)))) != nullptr );
32+ }
33+
34+ IMAGE_NT_HEADERS* (*ImageNtHeader)(void *);
35+ bool (WINAPI* SymCleanup)(HANDLE);
36+ DWORD (WINAPI* SymGetOptions)();
37+ bool (WINAPI* SymGetSearchPath)(HANDLE, char const *, DWORD);
38+ bool (WINAPI* SymInitialize)(HANDLE, char const *, bool );
39+ DWORD (WINAPI* SymSetOptions)(DWORD);
40+ bool (WINAPI* SymSetSearchPath)(HANDLE, char const *);
41+ bool (WINAPI* EnumProcessModules)(HANDLE, HMODULE*, DWORD, DWORD*);
42+ bool (WINAPI* GetModuleInformation)(HANDLE, HMODULE, MODULEINFO*, DWORD);
43+ DWORD (WINAPI* GetModuleBaseName)(HANDLE, HMODULE, char **, DWORD);
44+ # ifdef _WIN64
45+ void *(WINAPI* SymFunctionTableAccess)(HANDLE, DWORD64);
46+ bool (WINAPI* SymGetLineFromAddr)(HANDLE, DWORD64, DWORD*, IMAGEHLP_LINE64*);
47+ DWORD64 (WINAPI* SymGetModuleBase)(HANDLE, DWORD64);
48+ bool (WINAPI* SymGetModuleInfo)(HANDLE, DWORD64, IMAGEHLP_MODULE64*);
49+ bool (WINAPI* SymGetSymFromAddr)(HANDLE, DWORD64, DWORD64*, IMAGEHLP_SYMBOL64*);
50+ DWORD64 (WINAPI* SymLoadModule)(HANDLE, HANDLE, char const *, char const *, void *, DWORD);
51+ bool (WINAPI* StackWalk)(
52+ DWORD,
53+ HANDLE,
54+ HANDLE,
55+ STACKFRAME64*,
56+ void *,
57+ void *,
58+ decltype (SymFunctionTableAccess),
59+ decltype(SymGetModuleBase),
60+ void*);
61+ # else
62+ void *(WINAPI* SymFunctionTableAccess)(HANDLE, DWORD);
63+ bool (WINAPI* SymGetLineFromAddr)(HANDLE, DWORD, DWORD*, IMAGEHLP_LINE*);
64+ DWORD (WINAPI* SymGetModuleBase)(HANDLE, DWORD);
65+ bool (WINAPI* SymGetModuleInfo)(HANDLE, DWORD, IMAGEHLP_MODULE*);
66+ bool (WINAPI* SymGetSymFromAddr)(HANDLE, DWORD, DWORD*, IMAGEHLP_SYMBOL*);
67+ DWORD (WINAPI* SymLoadModule)(HANDLE, HANDLE, char const *, char const *, void *, DWORD);
68+ bool (WINAPI* StackWalk)(
69+ DWORD,
70+ HANDLE,
71+ HANDLE,
72+ STACKFRAME*,
73+ void *,
74+ void *,
75+ decltype (SymFunctionTableAccess),
76+ decltype(SymGetModuleBase),
77+ void*);
78+ # endif
79+
80+ bool loadFuncs () {
81+ static bool attempted{false };
82+ static bool succeeded{false };
83+ static std::mutex mutex;
84+
85+ std::lock_guard<std::mutex> g (mutex);
86+
87+ if (succeeded) {
88+ return true ;
89+ }
90+ if (attempted) {
91+ return false ;
92+ }
93+
94+ attempted = true ;
95+
96+ HMODULE dbghelp = LoadLibrary (" dbghelp.dll" );
97+ HMODULE psapi = LoadLibrary (" psapi.dll" );
98+
99+ // clang-format off
100+ succeeded = true
101+ && (dbghelp != nullptr )
102+ && (psapi != nullptr )
103+ && get_func (dbghelp, &ImageNtHeader, " ImageNtHeader" )
104+ && get_func (dbghelp, &SymCleanup, " SymCleanup" )
105+ && get_func (dbghelp, &SymGetOptions, " SymGetOptions" )
106+ && get_func (dbghelp, &SymGetSearchPath, " SymGetSearchPath" )
107+ && get_func (dbghelp, &SymInitialize, " SymInitialize" )
108+ && get_func (dbghelp, &SymSetOptions, " SymSetOptions" )
109+ && get_func (dbghelp, &SymSetSearchPath, " SymSetSearchPath" )
110+ && get_func (psapi, &EnumProcessModules, " EnumProcessModules" )
111+ && get_func (psapi, &GetModuleInformation, " GetModuleInformation" )
112+ && get_func (psapi, &GetModuleBaseName, " GetModuleBaseNameA" )
113+ #ifdef _WIN64
114+ && get_func (dbghelp, &StackWalk, " StackWalk64" )
115+ && get_func (dbghelp, &SymFunctionTableAccess, " SymFunctionTableAccess64" )
116+ && get_func (dbghelp, &SymGetLineFromAddr, " SymGetLineFromAddr64" )
117+ && get_func (dbghelp, &SymGetModuleBase, " SymGetModuleBase64" )
118+ && get_func (dbghelp, &SymGetModuleInfo, " SymGetModuleInfo64" )
119+ && get_func (dbghelp, &SymGetSymFromAddr, " SymGetSymFromAddr64" )
120+ && get_func (dbghelp, &SymLoadModule, " SymLoadModule64" )
121+ #else
122+ && get_func (dbghelp, &StackWalk, " StackWalk" )
123+ && get_func (dbghelp, &SymFunctionTableAccess, " SymFunctionTableAccess" )
124+ && get_func (dbghelp, &SymGetLineFromAddr, " SymGetLineFromAddr" )
125+ && get_func (dbghelp, &SymGetModuleBase, " SymGetModuleBase" )
126+ && get_func (dbghelp, &SymGetModuleInfo, " SymGetModuleInfo" )
127+ && get_func (dbghelp, &SymGetSymFromAddr, " SymGetSymFromAddr" )
128+ && get_func (dbghelp, &SymLoadModule, " SymLoadModule" )
129+ #endif
130+ ;
131+ // clang-format on
132+
133+ FreeLibrary (psapi);
134+ FreeLibrary (dbghelp);
135+ return succeeded;
136+ }
137+
138+ } // namespace __dll
139+
140+ using namespace __dll ;
141+
32142struct _Sym_Init_Scope {
33143 HANDLE proc_;
34144
@@ -39,6 +149,11 @@ struct _Sym_Init_Scope {
39149} // namespace
40150
41151_LIBCPP_EXPORTED_FROM_ABI void _Trace::windows_impl (size_t skip, size_t max_depth) {
152+ static bool loadedDLLFuncs = loadFuncs ();
153+ if (!loadedDLLFuncs) {
154+ return ;
155+ }
156+
42157 if (!max_depth) {
43158 return ;
44159 }
@@ -171,11 +286,11 @@ _LIBCPP_EXPORTED_FROM_ABI void _Trace::windows_impl(size_t skip, size_t max_dept
171286 sym->SizeOfStruct = sizeof (IMAGEHLP_SYMBOL);
172287 sym->MaxNameLength = __max_sym_len;
173288# if defined(_WIN64)
174- DWORD64 symdisp;
289+ DWORD64 symdisp{} ;
175290# else
176- DWORD32 symdisp;
291+ DWORD symdisp{} ;
177292# endif
178- DWORD linedisp{0 };
293+ DWORD linedisp{};
179294 IMAGEHLP_LINE line;
180295 if (SymGetSymFromAddr (proc, entry.__addr_ , &symdisp, sym)) {
181296 entry.__desc_ .assign (sym->Name );
0 commit comments