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,117 @@ 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
+
77
+ // Get the filename and base of the module that contains the specified
78
+ // address. N.B. This returns a `malloc`-ed copy of the filename in the
79
+ // Win32ModuleInfo struct; you are responsible for freeing that.
80
+ static Win32ModuleInfo moduleInfoFromAddress (const void *address) {
81
+ HMODULE hModule;
82
+ if (GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
83
+ | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
84
+ (LPCTSTR)address,
85
+ &hModule)) {
86
+ MODULEINFO mi;
87
+
88
+ if (!GetModuleInformation (GetCurrentProcess (), hModule,
89
+ &mi, sizeof (mi))) {
90
+ ZeroMemory (&mi, sizeof (mi));
91
+ }
92
+
93
+ WCHAR wszBuffer[256 ];
94
+ LPWSTR pwszFileName = wszBuffer;
95
+ DWORD dwCapacity = sizeof (wszBuffer) / sizeof (*wszBuffer);
96
+ DWORD dwRet = GetModuleFileNameW (hModule, pwszFileName, dwCapacity);
72
97
98
+ if (dwRet == dwCapacity) {
99
+ dwCapacity = 512 ;
100
+
101
+ pwszFileName = (LPWSTR)::malloc (sizeof (WCHAR) * dwCapacity);
102
+ while (true ) {
103
+ dwRet = GetModuleFileNameW (hModule, pwszFileName, dwCapacity);
104
+ if (dwRet != dwCapacity)
105
+ break ;
106
+
107
+ dwCapacity *= 2 ;
108
+
109
+ pwszFileName = (LPWSTR)::realloc (pwszFileName,
110
+ sizeof (WCHAR) * dwCapacity);
111
+ }
112
+ }
113
+
114
+ if (dwRet == 0 ) {
115
+ if (pwszFileName != wszBuffer)
116
+ ::free (pwszFileName);
117
+
118
+ return { ::strdup (" <unknown>" ), mi.lpBaseOfDll };
119
+ }
120
+
121
+ const char *result = _swift_win32_copyUTF8FromWide (pwszFileName);
122
+
123
+ if (pwszFileName != wszBuffer)
124
+ ::free ((void *)pwszFileName);
125
+
126
+ return { result, mi.lpBaseOfDll };
127
+ } else {
128
+ return { ::strdup (" <unknown>" ), nullptr };
129
+ }
130
+ }
131
+ #endif
132
+
133
+ std::optional<SymbolInfo> SymbolInfo::lookup (const void *address) {
73
134
#if defined(__wasm__)
74
135
// Currently, Wasm doesn't have a standard stable ABI for exporting address <->
75
136
// symbol table, it's work in progress. Also, there is no API to access such
76
137
// information from Wasm binary side. It's accessible only from host VM.
77
138
// See https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md
78
139
#elif defined(_WIN32) && !defined(__CYGWIN__)
140
+ Win32ModuleInfo moduleInfo = moduleInfoFromAddress (address);
141
+ SYMBOL_INFO_PACKAGE package;
142
+ BOOL bRet;
143
+
144
+ package.si .SizeOfStruct = sizeof (SYMBOL_INFO);
145
+ package.si .MaxNameLen = MAX_SYM_NAME;
146
+
79
147
_swift_win32_withDbgHelpLibrary ([&] (HANDLE hProcess) {
80
148
if (!hProcess) {
81
- return ;
149
+ bRet = false ;
150
+ return ;
82
151
}
83
152
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
- }
153
+ bRet = SymFromAddr (hProcess, reinterpret_cast <const DWORD64>(address),
154
+ nullptr , &package.si );
91
155
});
156
+
157
+ if (bRet) {
158
+ return SymbolInfo ((const void *)package.si .Address ,
159
+ ::strdup (package.si.Name),
160
+ moduleInfo.name,
161
+ moduleInfo.base);
162
+ } else {
163
+ return SymbolInfo (address,
164
+ nullptr ,
165
+ moduleInfo.name ,
166
+ moduleInfo.base );
167
+ }
92
168
#elif SWIFT_STDLIB_HAS_DLADDR
93
169
SymbolInfo info;
94
170
if (dladdr (address, &info._info )) {
95
- result = info;
171
+ return info;
96
172
}
97
173
#endif
98
174
99
- return result ;
175
+ return {} ;
100
176
}
0 commit comments