99 // Note: We loaded the DLL successfully. From here on we count
100 // initialization as success. We still may fail to load all of the
101 // desired function pointers successfully, but DLL may still be usable
102 // enough for our purposes.
103 g_state = state_ready;
104
105 #define DO_RESOLVE(functionname) \
106 g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);
107
108 FOR_ALL_FUNCTIONS(DO_RESOLVE)
109
110 // Retrieve version information.
111 if (g_pfn_ImagehlpApiVersion) {
112 const API_VERSION* p = g_pfn_ImagehlpApiVersion();
113 memcpy(&g_version, p, sizeof(API_VERSION));
114 }
115 }
116
117 }
118
119 ///////////////////// External functions //////////////////////////
120
121 // All outside facing functions are synchronized. Also, we run
122 // initialization on first touch.
123
124
125 // Call InitializeCriticalSection as early as possible.
126 class CritSect {
127 CRITICAL_SECTION cs;
128 public:
129 CritSect() { ::InitializeCriticalSection(&cs); }
130 void enter() { ::EnterCriticalSection(&cs); }
131 void leave() { ::LeaveCriticalSection(&cs); }
132 };
133
134 static CritSect g_cs;
135
136 class EntryGuard {
137 public:
138 EntryGuard() {
139 g_cs.enter();
140 if (g_state == state_uninitialized) {
141 initialize();
142 }
143 }
144 ~EntryGuard() {
145 g_cs.leave();
146 }
147 };
148
149 DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {
150 EntryGuard entry_guard;
151 if (g_pfn_SymSetOptions != NULL) {
152 return g_pfn_SymSetOptions(arg);
153 }
154 return 0;
155 }
156
157 DWORD WindowsDbgHelp::symGetOptions(void) {
158 EntryGuard entry_guard;
159 if (g_pfn_SymGetOptions != NULL) {
160 return g_pfn_SymGetOptions();
161 }
162 return 0;
163 }
164
165 BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {
166 EntryGuard entry_guard;
167 if (g_pfn_SymInitialize != NULL) {
168 return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
169 }
170 return FALSE;
171 }
172
173 BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,
174 PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {
175 EntryGuard entry_guard;
176 if (g_pfn_SymGetSymFromAddr64 != NULL) {
177 return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);
178 }
179 return FALSE;
180 }
181
182 DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,
183 DWORD UndecoratedLength, DWORD Flags) {
184 EntryGuard entry_guard;
185 if (g_pfn_UnDecorateSymbolName != NULL) {
186 return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);
187 }
188 if (UnDecoratedName != NULL && UndecoratedLength > 0) {
189 UnDecoratedName[0] = '\0';
190 }
191 return 0;
192 }
193
194 BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {
195 EntryGuard entry_guard;
196 if (g_pfn_SymSetSearchPath != NULL) {
197 return g_pfn_SymSetSearchPath(hProcess, SearchPath);
198 }
199 return FALSE;
200 }
201
202 BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {
203 EntryGuard entry_guard;
204 if (g_pfn_SymGetSearchPath != NULL) {
205 return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
206 }
207 return FALSE;
208 }
209
210 BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,
211 HANDLE hProcess,
212 HANDLE hThread,
213 LPSTACKFRAME64 StackFrame,
214 PVOID ContextRecord) {
215 EntryGuard entry_guard;
216 if (g_pfn_StackWalk64 != NULL) {
217 return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,
218 ContextRecord,
219 NULL, // ReadMemoryRoutine
220 g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,
221 g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine
222 NULL // TranslateAddressRoutine
223 );
224 }
225 return FALSE;
226 }
227
228 PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
229 EntryGuard entry_guard;
230 if (g_pfn_SymFunctionTableAccess64 != NULL) {
231 return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);
232 }
233 return NULL;
234 }
235
236 DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {
237 EntryGuard entry_guard;
238 if (g_pfn_SymGetModuleBase64 != NULL) {
239 return g_pfn_SymGetModuleBase64(hProcess, dwAddr);
240 }
241 return 0;
242 }
243
244 BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
245 MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
246 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
247 PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
248 EntryGuard entry_guard;
249 if (g_pfn_MiniDumpWriteDump != NULL) {
250 return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,
251 ExceptionParam, UserStreamParam, CallbackParam);
252 }
253 return FALSE;
254 }
255
256 BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
257 PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {
258 EntryGuard entry_guard;
259 if (g_pfn_SymGetLineFromAddr64 != NULL) {
260 return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);
261 }
262 return FALSE;
263 }
264
265 // Print one liner describing state (if library loaded, which functions are
266 // missing - if any, and the dbhelp API version)
267 void WindowsDbgHelp::print_state_on(outputStream* st) {
268 // Note: We should not lock while printing, but this should be
269 // safe to do without lock anyway.
270 st->print("dbghelp: ");
271
272 if (g_state == state_uninitialized) {
273 st->print("uninitialized.");
274 } else if (g_state == state_error) {
275 st->print("loading error: %u", g_dll_load_error);
276 } else {
277 st->print("loaded successfully ");
278
|
99 // Note: We loaded the DLL successfully. From here on we count
100 // initialization as success. We still may fail to load all of the
101 // desired function pointers successfully, but DLL may still be usable
102 // enough for our purposes.
103 g_state = state_ready;
104
105 #define DO_RESOLVE(functionname) \
106 g_pfn_##functionname = (pfn_##functionname) ::GetProcAddress(g_dll_handle, #functionname);
107
108 FOR_ALL_FUNCTIONS(DO_RESOLVE)
109
110 // Retrieve version information.
111 if (g_pfn_ImagehlpApiVersion) {
112 const API_VERSION* p = g_pfn_ImagehlpApiVersion();
113 memcpy(&g_version, p, sizeof(API_VERSION));
114 }
115 }
116
117 }
118
119
120 ///////////////////// External functions //////////////////////////
121
122 // All outside facing functions are synchronized. Also, we run
123 // initialization on first touch.
124
125 static CRITICAL_SECTION g_cs;
126
127 namespace { // Do not export.
128 class WindowsDbgHelpEntry {
129 public:
130 WindowsDbgHelpEntry() {
131 ::EnterCriticalSection(&g_cs);
132 if (g_state == state_uninitialized) {
133 initialize();
134 }
135 }
136 ~WindowsDbgHelpEntry() {
137 ::LeaveCriticalSection(&g_cs);
138 }
139 };
140 }
141
142 // Called at DLL_PROCESS_ATTACH.
143 void WindowsDbgHelp::pre_initialize() {
144 ::InitializeCriticalSection(&g_cs);
145 }
146
147 DWORD WindowsDbgHelp::symSetOptions(DWORD arg) {
148 WindowsDbgHelpEntry entry_guard;
149 if (g_pfn_SymSetOptions != NULL) {
150 return g_pfn_SymSetOptions(arg);
151 }
152 return 0;
153 }
154
155 DWORD WindowsDbgHelp::symGetOptions(void) {
156 WindowsDbgHelpEntry entry_guard;
157 if (g_pfn_SymGetOptions != NULL) {
158 return g_pfn_SymGetOptions();
159 }
160 return 0;
161 }
162
163 BOOL WindowsDbgHelp::symInitialize(HANDLE hProcess, PCTSTR UserSearchPath, BOOL fInvadeProcess) {
164 WindowsDbgHelpEntry entry_guard;
165 if (g_pfn_SymInitialize != NULL) {
166 return g_pfn_SymInitialize(hProcess, UserSearchPath, fInvadeProcess);
167 }
168 return FALSE;
169 }
170
171 BOOL WindowsDbgHelp::symGetSymFromAddr64(HANDLE hProcess, DWORD64 the_address,
172 PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) {
173 WindowsDbgHelpEntry entry_guard;
174 if (g_pfn_SymGetSymFromAddr64 != NULL) {
175 return g_pfn_SymGetSymFromAddr64(hProcess, the_address, Displacement, Symbol);
176 }
177 return FALSE;
178 }
179
180 DWORD WindowsDbgHelp::unDecorateSymbolName(const char* DecoratedName, char* UnDecoratedName,
181 DWORD UndecoratedLength, DWORD Flags) {
182 WindowsDbgHelpEntry entry_guard;
183 if (g_pfn_UnDecorateSymbolName != NULL) {
184 return g_pfn_UnDecorateSymbolName(DecoratedName, UnDecoratedName, UndecoratedLength, Flags);
185 }
186 if (UnDecoratedName != NULL && UndecoratedLength > 0) {
187 UnDecoratedName[0] = '\0';
188 }
189 return 0;
190 }
191
192 BOOL WindowsDbgHelp::symSetSearchPath(HANDLE hProcess, PCTSTR SearchPath) {
193 WindowsDbgHelpEntry entry_guard;
194 if (g_pfn_SymSetSearchPath != NULL) {
195 return g_pfn_SymSetSearchPath(hProcess, SearchPath);
196 }
197 return FALSE;
198 }
199
200 BOOL WindowsDbgHelp::symGetSearchPath(HANDLE hProcess, PTSTR SearchPath, int SearchPathLength) {
201 WindowsDbgHelpEntry entry_guard;
202 if (g_pfn_SymGetSearchPath != NULL) {
203 return g_pfn_SymGetSearchPath(hProcess, SearchPath, SearchPathLength);
204 }
205 return FALSE;
206 }
207
208 BOOL WindowsDbgHelp::stackWalk64(DWORD MachineType,
209 HANDLE hProcess,
210 HANDLE hThread,
211 LPSTACKFRAME64 StackFrame,
212 PVOID ContextRecord) {
213 WindowsDbgHelpEntry entry_guard;
214 if (g_pfn_StackWalk64 != NULL) {
215 return g_pfn_StackWalk64(MachineType, hProcess, hThread, StackFrame,
216 ContextRecord,
217 NULL, // ReadMemoryRoutine
218 g_pfn_SymFunctionTableAccess64, // FunctionTableAccessRoutine,
219 g_pfn_SymGetModuleBase64, // GetModuleBaseRoutine
220 NULL // TranslateAddressRoutine
221 );
222 }
223 return FALSE;
224 }
225
226 PVOID WindowsDbgHelp::symFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) {
227 WindowsDbgHelpEntry entry_guard;
228 if (g_pfn_SymFunctionTableAccess64 != NULL) {
229 return g_pfn_SymFunctionTableAccess64(hProcess, AddrBase);
230 }
231 return NULL;
232 }
233
234 DWORD64 WindowsDbgHelp::symGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) {
235 WindowsDbgHelpEntry entry_guard;
236 if (g_pfn_SymGetModuleBase64 != NULL) {
237 return g_pfn_SymGetModuleBase64(hProcess, dwAddr);
238 }
239 return 0;
240 }
241
242 BOOL WindowsDbgHelp::miniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
243 MINIDUMP_TYPE DumpType, PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
244 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
245 PMINIDUMP_CALLBACK_INFORMATION CallbackParam) {
246 WindowsDbgHelpEntry entry_guard;
247 if (g_pfn_MiniDumpWriteDump != NULL) {
248 return g_pfn_MiniDumpWriteDump(hProcess, ProcessId, hFile, DumpType,
249 ExceptionParam, UserStreamParam, CallbackParam);
250 }
251 return FALSE;
252 }
253
254 BOOL WindowsDbgHelp::symGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr,
255 PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) {
256 WindowsDbgHelpEntry entry_guard;
257 if (g_pfn_SymGetLineFromAddr64 != NULL) {
258 return g_pfn_SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, Line);
259 }
260 return FALSE;
261 }
262
263 // Print one liner describing state (if library loaded, which functions are
264 // missing - if any, and the dbhelp API version)
265 void WindowsDbgHelp::print_state_on(outputStream* st) {
266 // Note: We should not lock while printing, but this should be
267 // safe to do without lock anyway.
268 st->print("dbghelp: ");
269
270 if (g_state == state_uninitialized) {
271 st->print("uninitialized.");
272 } else if (g_state == state_error) {
273 st->print("loading error: %u", g_dll_load_error);
274 } else {
275 st->print("loaded successfully ");
276
|