17
17
#define NOMINMAX
18
18
#include < Windows.h>
19
19
#include < DbgHelp.h>
20
+ #include < psapi.h>
20
21
#elif SWIFT_STDLIB_HAS_DLADDR
21
22
#include < dlfcn.h>
22
23
#endif
@@ -29,7 +30,7 @@ using namespace swift;
29
30
30
31
const char *SymbolInfo::getFilename () const {
31
32
#if defined(_WIN32) && !defined(__CYGWIN__)
32
- return nullptr ;
33
+ return _moduleFileName ;
33
34
#elif SWIFT_STDLIB_HAS_DLADDR
34
35
return _info.dli_fname ;
35
36
#else
@@ -39,7 +40,7 @@ const char *SymbolInfo::getFilename() const {
39
40
40
41
const void *SymbolInfo::getBaseAddress () const {
41
42
#if defined(_WIN32) && !defined(__CYGWIN__)
42
- return reinterpret_cast < const void *>(_package. si . ModBase ) ;
43
+ return _moduleBaseAddress ;
43
44
#elif SWIFT_STDLIB_HAS_DLADDR
44
45
return _info.dli_fbase ;
45
46
#else
@@ -49,7 +50,7 @@ const void *SymbolInfo::getBaseAddress() const {
49
50
50
51
const char *SymbolInfo::getSymbolName () const {
51
52
#if defined(_WIN32) && !defined(__CYGWIN__)
52
- return _package. si . Name ;
53
+ return _symbolName ;
53
54
#elif SWIFT_STDLIB_HAS_DLADDR
54
55
return _info.dli_sname ;
55
56
#else
@@ -59,42 +60,119 @@ const char *SymbolInfo::getSymbolName() const {
59
60
60
61
const void *SymbolInfo::getSymbolAddress () const {
61
62
#if defined(_WIN32) && !defined(__CYGWIN__)
62
- return reinterpret_cast < const void *>(_package. si . Address ) ;
63
+ return _symbolAddress ;
63
64
#elif SWIFT_STDLIB_HAS_DLADDR
64
65
return _info.dli_saddr ;
65
66
#else
66
67
return nullptr ;
67
68
#endif
68
69
}
69
70
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);
72
119
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) {
73
136
#if defined(__wasm__)
74
137
// Currently, Wasm doesn't have a standard stable ABI for exporting address <->
75
138
// symbol table, it's work in progress. Also, there is no API to access such
76
139
// information from Wasm binary side. It's accessible only from host VM.
77
140
// See https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
78
141
#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
+
79
149
_swift_win32_withDbgHelpLibrary ([&] (HANDLE hProcess) {
80
150
if (!hProcess) {
81
- return ;
151
+ bRet = false ;
152
+ return ;
82
153
}
83
154
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 );
91
157
});
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
+ }
92
170
#elif SWIFT_STDLIB_HAS_DLADDR
93
171
SymbolInfo info;
94
172
if (dladdr (address, &info._info )) {
95
- result = info;
173
+ return info;
96
174
}
97
175
#endif
98
176
99
- return result ;
177
+ return {} ;
100
178
}
0 commit comments