1717#define NOMINMAX
1818#include < Windows.h>
1919#include < DbgHelp.h>
20+ #include < psapi.h>
2021#elif SWIFT_STDLIB_HAS_DLADDR
2122#include < dlfcn.h>
2223#endif
@@ -29,7 +30,7 @@ using namespace swift;
2930
3031const char *SymbolInfo::getFilename () const {
3132#if defined(_WIN32) && !defined(__CYGWIN__)
32- return nullptr ;
33+ return _moduleFileName ;
3334#elif SWIFT_STDLIB_HAS_DLADDR
3435 return _info.dli_fname ;
3536#else
@@ -39,7 +40,7 @@ const char *SymbolInfo::getFilename() const {
3940
4041const void *SymbolInfo::getBaseAddress () const {
4142#if defined(_WIN32) && !defined(__CYGWIN__)
42- return reinterpret_cast < const void *>(_package. si . ModBase ) ;
43+ return _moduleBaseAddress ;
4344#elif SWIFT_STDLIB_HAS_DLADDR
4445 return _info.dli_fbase ;
4546#else
@@ -49,7 +50,7 @@ const void *SymbolInfo::getBaseAddress() const {
4950
5051const char *SymbolInfo::getSymbolName () const {
5152#if defined(_WIN32) && !defined(__CYGWIN__)
52- return _package. si . Name ;
53+ return _symbolName ;
5354#elif SWIFT_STDLIB_HAS_DLADDR
5455 return _info.dli_sname ;
5556#else
@@ -59,42 +60,119 @@ const char *SymbolInfo::getSymbolName() const {
5960
6061const void *SymbolInfo::getSymbolAddress () const {
6162#if defined(_WIN32) && !defined(__CYGWIN__)
62- return reinterpret_cast < const void *>(_package. si . Address ) ;
63+ return _symbolAddress ;
6364#elif SWIFT_STDLIB_HAS_DLADDR
6465 return _info.dli_saddr ;
6566#else
6667 return nullptr ;
6768#endif
6869}
6970
70- std::optional<SymbolInfo> SymbolInfo::lookup (const void *address) {
71- std::optional<SymbolInfo> result;
71+ #if defined(_WIN32) && !defined(__CYGWIN__)
72+ struct Win32ModuleInfo {
73+ const char *name;
74+ const void *base;
75+
76+ Win32ModuleInfo (const char *n, const void *b) : name(n), base(b) {}
77+ };
78+
79+ // Get the filename and base of the module that contains the specified
80+ // address. N.B. This returns a malloc()ed copy of the filename in the
81+ // Win32ModuleInfo struct; you are responsible for freeing that.
82+ static Win32ModuleInfo moduleInfoFromAddress (const void *address) {
83+ HMODULE hModule;
84+ if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
85+ | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
86+ (LPCTSTR)address,
87+ &hModule)) {
88+ MODULEINFO mi;
89+
90+ if (!GetModuleInformation (GetCurrentProcess (), hModule,
91+ &mi, sizeof (mi))) {
92+ ::memset (&mi, 0 , sizeof (mi));
93+ }
94+
95+ WCHAR wszBuffer[256 ];
96+ LPWSTR pwszFileName = wszBuffer;
97+ DWORD dwCapacity = sizeof (wszBuffer) / sizeof (WCHAR);
98+ DWORD dwRet = GetModuleFileNameW (hModule, pwszFileName, dwCapacity);
99+
100+ if (dwRet == dwCapacity) {
101+ dwCapacity = 512 ;
102+
103+ pwszFileName = (LPWSTR)::malloc (sizeof (WCHAR) * dwCapacity);
104+ while (true ) {
105+ dwRet = GetModuleFileNameW (hModule, pwszFileName, dwCapacity);
106+ if (dwRet != dwCapacity)
107+ break ;
108+
109+ dwCapacity *= 2 ;
110+
111+ pwszFileName = (LPWSTR)::realloc (pwszFileName,
112+ sizeof (WCHAR) * dwCapacity);
113+ }
114+ }
115+
116+ if (dwRet == 0 ) {
117+ if (pwszFileName != wszBuffer)
118+ ::free (pwszFileName);
72119
120+ return Win32ModuleInfo (::strdup (" <unknown>" ), mi.lpBaseOfDll );
121+ }
122+
123+ const char *result = _swift_win32_copyUTF8FromWide (pwszFileName);
124+
125+ if (pwszFileName != wszBuffer)
126+ ::free ((void *)pwszFileName);
127+
128+ return Win32ModuleInfo (result, mi.lpBaseOfDll );
129+ } else {
130+ return Win32ModuleInfo (::strdup (" <unknown>" ), nullptr );
131+ }
132+ }
133+ #endif
134+
135+ std::optional<SymbolInfo> SymbolInfo::lookup (const void *address) {
73136#if defined(__wasm__)
74137 // Currently, Wasm doesn't have a standard stable ABI for exporting address <->
75138 // symbol table, it's work in progress. Also, there is no API to access such
76139 // information from Wasm binary side. It's accessible only from host VM.
77140 // See https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
78141#elif defined(_WIN32) && !defined(__CYGWIN__)
142+ Win32ModuleInfo moduleInfo = moduleInfoFromAddress (address);
143+ SYMBOL_INFO_PACKAGE package;
144+ BOOL bRet;
145+
146+ package.si .SizeOfStruct = sizeof (SYMBOL_INFO);
147+ package.si .MaxNameLen = MAX_SYM_NAME;
148+
79149 _swift_win32_withDbgHelpLibrary ([&] (HANDLE hProcess) {
80150 if (!hProcess) {
81- return ;
151+ bRet = false ;
152+ return ;
82153 }
83154
84- SymbolInfo info;
85- info._package .si .SizeOfStruct = sizeof (SYMBOL_INFO);
86- info._package .si .MaxNameLen = MAX_SYM_NAME;
87- if (SymFromAddr (hProcess, reinterpret_cast <const DWORD64>(address),
88- nullptr , &info._package .si )) {
89- result = info;
90- }
155+ bRet = SymFromAddr (hProcess, reinterpret_cast <const DWORD64>(address),
156+ nullptr , &package.si );
91157 });
158+
159+ if (bRet) {
160+ return SymbolInfo ((const void *)package.si .Address ,
161+ ::strdup (package.si.Name),
162+ moduleInfo.name,
163+ moduleInfo.base);
164+ } else {
165+ return SymbolInfo (address,
166+ nullptr ,
167+ moduleInfo.name ,
168+ moduleInfo.base );
169+ }
92170#elif SWIFT_STDLIB_HAS_DLADDR
93171 SymbolInfo info;
94172 if (dladdr (address, &info._info )) {
95- result = info;
173+ return info;
96174 }
97175#endif
98176
99- return result ;
177+ return {} ;
100178}
0 commit comments