util: Lookup symbol names from addresses.
[mesa.git] / src / gallium / auxiliary / util / u_debug_symbol.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Symbol lookup.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 */
34
35 #include "pipe/p_compiler.h"
36
37 #include "u_debug.h"
38 #include "u_debug_symbol.h"
39
40 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86)
41
42 #include <windows.h>
43 #include <stddef.h>
44 #include <imagehlp.h>
45
46 /*
47 * TODO: Cleanup code.
48 * TODO: Support x86_64
49 */
50
51 static BOOL bSymInitialized = FALSE;
52
53 static HMODULE hModule_Imagehlp = NULL;
54
55 typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL);
56 static PFNSYMINITIALIZE pfnSymInitialize = NULL;
57
58 static
59 BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess)
60 {
61 if(
62 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
63 (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) GetProcAddress(hModule_Imagehlp, "SymInitialize")))
64 )
65 return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess);
66 else
67 return FALSE;
68 }
69
70 typedef BOOL (WINAPI *PFNSYMCLEANUP)(HANDLE);
71 static PFNSYMCLEANUP pfnSymCleanup = NULL;
72
73 static
74 BOOL WINAPI j_SymCleanup(HANDLE hProcess)
75 {
76 if(
77 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
78 (pfnSymCleanup || (pfnSymCleanup = (PFNSYMCLEANUP) GetProcAddress(hModule_Imagehlp, "SymCleanup")))
79 )
80 return pfnSymCleanup(hProcess);
81 else
82 return FALSE;
83 }
84
85 typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD);
86 static PFNSYMSETOPTIONS pfnSymSetOptions = NULL;
87
88 static
89 DWORD WINAPI j_SymSetOptions(DWORD SymOptions)
90 {
91 if(
92 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
93 (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) GetProcAddress(hModule_Imagehlp, "SymSetOptions")))
94 )
95 return pfnSymSetOptions(SymOptions);
96 else
97 return FALSE;
98 }
99
100 typedef BOOL (WINAPI *PFNSYMUNDNAME)(PIMAGEHLP_SYMBOL, PSTR, DWORD);
101 static PFNSYMUNDNAME pfnSymUnDName = NULL;
102
103 static
104 BOOL WINAPI j_SymUnDName(PIMAGEHLP_SYMBOL Symbol, PSTR UnDecName, DWORD UnDecNameLength)
105 {
106 if(
107 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
108 (pfnSymUnDName || (pfnSymUnDName = (PFNSYMUNDNAME) GetProcAddress(hModule_Imagehlp, "SymUnDName")))
109 )
110 return pfnSymUnDName(Symbol, UnDecName, UnDecNameLength);
111 else
112 return FALSE;
113 }
114
115 typedef PFUNCTION_TABLE_ACCESS_ROUTINE PFNSYMFUNCTIONTABLEACCESS;
116 static PFNSYMFUNCTIONTABLEACCESS pfnSymFunctionTableAccess = NULL;
117
118 static
119 PVOID WINAPI j_SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
120 {
121 if(
122 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
123 (pfnSymFunctionTableAccess || (pfnSymFunctionTableAccess = (PFNSYMFUNCTIONTABLEACCESS) GetProcAddress(hModule_Imagehlp, "SymFunctionTableAccess")))
124 )
125 return pfnSymFunctionTableAccess(hProcess, AddrBase);
126 else
127 return NULL;
128 }
129
130 typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE;
131 static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL;
132
133 static
134 DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
135 {
136 if(
137 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
138 (pfnSymGetModuleBase || (pfnSymGetModuleBase = (PFNSYMGETMODULEBASE) GetProcAddress(hModule_Imagehlp, "SymGetModuleBase")))
139 )
140 return pfnSymGetModuleBase(hProcess, dwAddr);
141 else
142 return 0;
143 }
144
145 typedef BOOL (WINAPI *PFNSTACKWALK)(DWORD, HANDLE, HANDLE, LPSTACKFRAME, LPVOID, PREAD_PROCESS_MEMORY_ROUTINE, PFUNCTION_TABLE_ACCESS_ROUTINE, PGET_MODULE_BASE_ROUTINE, PTRANSLATE_ADDRESS_ROUTINE);
146 static PFNSTACKWALK pfnStackWalk = NULL;
147
148 static
149 BOOL WINAPI j_StackWalk(
150 DWORD MachineType,
151 HANDLE hProcess,
152 HANDLE hThread,
153 LPSTACKFRAME StackFrame,
154 PVOID ContextRecord,
155 PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,
156 PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
157 PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
158 PTRANSLATE_ADDRESS_ROUTINE TranslateAddress
159 )
160 {
161 if(
162 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
163 (pfnStackWalk || (pfnStackWalk = (PFNSTACKWALK) GetProcAddress(hModule_Imagehlp, "StackWalk")))
164 )
165 return pfnStackWalk(
166 MachineType,
167 hProcess,
168 hThread,
169 StackFrame,
170 ContextRecord,
171 ReadMemoryRoutine,
172 FunctionTableAccessRoutine,
173 GetModuleBaseRoutine,
174 TranslateAddress
175 );
176 else
177 return FALSE;
178 }
179
180 typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL);
181 static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL;
182
183 static
184 BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol)
185 {
186 if(
187 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
188 (pfnSymGetSymFromAddr || (pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetSymFromAddr")))
189 )
190 return pfnSymGetSymFromAddr(hProcess, Address, Displacement, Symbol);
191 else
192 return FALSE;
193 }
194
195 typedef BOOL (WINAPI *PFNSYMGETLINEFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_LINE);
196 static PFNSYMGETLINEFROMADDR pfnSymGetLineFromAddr = NULL;
197
198 static
199 BOOL WINAPI j_SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
200 {
201 if(
202 (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) &&
203 (pfnSymGetLineFromAddr || (pfnSymGetLineFromAddr = (PFNSYMGETLINEFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetLineFromAddr")))
204 )
205 return pfnSymGetLineFromAddr(hProcess, dwAddr, pdwDisplacement, Line);
206 else
207 return FALSE;
208 }
209
210
211 static INLINE boolean
212 debug_symbol_print_imagehlp(const void *addr)
213 {
214 HANDLE hProcess;
215 BYTE symbolBuffer[1024];
216 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer;
217 DWORD dwDisplacement = 0; // Displacement of the input address, relative to the start of the symbol
218
219 hProcess = GetCurrentProcess();
220
221 pSymbol->SizeOfStruct = sizeof(symbolBuffer);
222 pSymbol->MaxNameLength = sizeof(symbolBuffer) - offsetof(IMAGEHLP_SYMBOL, Name);
223
224 if(!bSymInitialized) {
225 j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
226 if(j_SymInitialize(hProcess, NULL, TRUE))
227 bSymInitialized = TRUE;
228 }
229
230 if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol))
231 return FALSE;
232
233 debug_printf("\t%s\n", pSymbol->Name);
234
235 return TRUE;
236
237 }
238 #endif
239
240
241 void
242 debug_symbol_print(const void *addr)
243 {
244 #if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
245 if(debug_symbol_print_imagehlp(addr))
246 return;
247 #endif
248
249 debug_printf("\t%p\n", addr);
250 }