X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fauxiliary%2Futil%2Fu_debug_symbol.c;h=334803d008ee67fa2e6dd59db8cafd0325a75098;hb=c0f7f833eb9c968e9f1491117d3ddc072eefddb7;hp=332952af88b85c4036a0f7866e3c93cb70775138;hpb=222d2f2ac2c7d93cbc0643082c78278ad2c8cfce;p=mesa.git diff --git a/src/gallium/auxiliary/util/u_debug_symbol.c b/src/gallium/auxiliary/util/u_debug_symbol.c index 332952af88b..334803d008e 100644 --- a/src/gallium/auxiliary/util/u_debug_symbol.c +++ b/src/gallium/auxiliary/util/u_debug_symbol.c @@ -34,150 +34,231 @@ #include "pipe/p_compiler.h" #include "os/os_thread.h" -#include "u_string.h" +#include "util/u_string.h" -#include "u_debug.h" +#include "util/u_debug.h" #include "u_debug_symbol.h" #include "u_hash_table.h" -#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86) + +#if defined(PIPE_OS_WINDOWS) #include #include -#include -/* - * TODO: Cleanup code. - * TODO: Support x86_64 - */ +#include "dbghelp.h" -static BOOL bSymInitialized = FALSE; -static HMODULE hModule_Imagehlp = NULL; +/** + * SymInitialize() must be called once for each process (in this case, the + * current process), before any of the other functions can be called. + */ +static BOOL g_bSymInitialized = FALSE; -typedef BOOL (WINAPI *PFNSYMINITIALIZE)(HANDLE, LPSTR, BOOL); -static PFNSYMINITIALIZE pfnSymInitialize = NULL; -static -BOOL WINAPI j_SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess) +/** + * Lookup the address of a DbgHelp function. + */ +static FARPROC WINAPI +getDbgHelpProcAddress(LPCSTR lpProcName) { - if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymInitialize || (pfnSymInitialize = (PFNSYMINITIALIZE) GetProcAddress(hModule_Imagehlp, "SymInitialize"))) - ) - return pfnSymInitialize(hProcess, UserSearchPath, fInvadeProcess); - else - return FALSE; -} + static HMODULE hModule = NULL; + + if (!hModule) { + static boolean bail = FALSE; + + if (bail) { + return NULL; + } + +#ifdef PIPE_CC_GCC + /* + * DbgHelp does not understand the debug information generated by MinGW toolchain. + * + * mgwhelp.dll is a dbghelp.dll look-alike replacement, which is able to + * understand MinGW symbols, including on 64-bit builds. + */ + if (!hModule) { + hModule = LoadLibraryA("mgwhelp.dll"); + if (!hModule) { + _debug_printf("warning: mgwhelp.dll not found: symbol names will not be resolved\n" + "warning: download it from https://github.com/jrfonseca/drmingw/#mgwhelp\n"); + } + } +#endif -typedef DWORD (WINAPI *PFNSYMSETOPTIONS)(DWORD); -static PFNSYMSETOPTIONS pfnSymSetOptions = NULL; + /* + * Fallback to the real DbgHelp. + */ + if (!hModule) { + hModule = LoadLibraryA("dbghelp.dll"); + } + + if (!hModule) { + bail = TRUE; + return NULL; + } + } -static -DWORD WINAPI j_SymSetOptions(DWORD SymOptions) -{ - if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymSetOptions || (pfnSymSetOptions = (PFNSYMSETOPTIONS) GetProcAddress(hModule_Imagehlp, "SymSetOptions"))) - ) - return pfnSymSetOptions(SymOptions); - else - return FALSE; + return GetProcAddress(hModule, lpProcName); } -typedef PGET_MODULE_BASE_ROUTINE PFNSYMGETMODULEBASE; -static PFNSYMGETMODULEBASE pfnSymGetModuleBase = NULL; -static -DWORD WINAPI j_SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) -{ - if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymGetModuleBase || (pfnSymGetModuleBase = (PFNSYMGETMODULEBASE) GetProcAddress(hModule_Imagehlp, "SymGetModuleBase"))) - ) - return pfnSymGetModuleBase(hProcess, dwAddr); - else - return 0; -} +/** + * Generic macro to dispatch a DbgHelp functions. + */ +#define DBGHELP_DISPATCH(_name, _ret_type, _ret_default, _arg_types, _arg_names) \ + static _ret_type WINAPI \ + j_##_name _arg_types \ + { \ + typedef BOOL (WINAPI *PFN) _arg_types; \ + static PFN pfn = NULL; \ + if (!pfn) { \ + pfn = (PFN) getDbgHelpProcAddress(#_name); \ + if (!pfn) { \ + return _ret_default; \ + } \ + } \ + return pfn _arg_names; \ + } -typedef BOOL (WINAPI *PFNSYMGETSYMFROMADDR)(HANDLE, DWORD, LPDWORD, PIMAGEHLP_SYMBOL); -static PFNSYMGETSYMFROMADDR pfnSymGetSymFromAddr = NULL; +DBGHELP_DISPATCH(SymInitialize, + BOOL, 0, + (HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess), + (hProcess, UserSearchPath, fInvadeProcess)) -static -BOOL WINAPI j_SymGetSymFromAddr(HANDLE hProcess, DWORD Address, PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol) -{ - if( - (hModule_Imagehlp || (hModule_Imagehlp = LoadLibraryA("IMAGEHLP.DLL"))) && - (pfnSymGetSymFromAddr || (pfnSymGetSymFromAddr = (PFNSYMGETSYMFROMADDR) GetProcAddress(hModule_Imagehlp, "SymGetSymFromAddr"))) - ) - return pfnSymGetSymFromAddr(hProcess, Address, Displacement, Symbol); - else - return FALSE; -} +DBGHELP_DISPATCH(SymSetOptions, + DWORD, FALSE, + (DWORD SymOptions), + (SymOptions)) + +DBGHELP_DISPATCH(SymFromAddr, + BOOL, FALSE, + (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol), + (hProcess, Address, Displacement, Symbol)) +DBGHELP_DISPATCH(SymGetLineFromAddr64, + BOOL, FALSE, + (HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line), + (hProcess, dwAddr, pdwDisplacement, Line)) -static INLINE void -debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size) + +#undef DBGHELP_DISPATCH + + +static inline boolean +debug_symbol_name_dbghelp(const void *addr, char* buf, unsigned size) { - HANDLE hProcess; - BYTE symbolBuffer[1024]; - PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL) symbolBuffer; - DWORD dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */ + DWORD64 dwAddr = (DWORD64)(uintptr_t)addr; + HANDLE hProcess = GetCurrentProcess(); - hProcess = GetCurrentProcess(); + /* General purpose buffer, to back pSymbol and other temporary stuff. + * Must not be too memory hungry here to avoid stack overflows. + */ + CHAR buffer[512]; - pSymbol->SizeOfStruct = sizeof(symbolBuffer); - pSymbol->MaxNameLength = sizeof(symbolBuffer) - offsetof(IMAGEHLP_SYMBOL, Name); + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer; + DWORD64 dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */ + DWORD dwLineDisplacement = 0; + IMAGEHLP_LINE64 Line; - if(!bSymInitialized) { + memset(pSymbol, 0, sizeof *pSymbol); + pSymbol->SizeOfStruct = sizeof buffer; + pSymbol->MaxNameLen = sizeof buffer - offsetof(SYMBOL_INFO, Name); + + if (!g_bSymInitialized) { j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES); - if(j_SymInitialize(hProcess, NULL, TRUE)) - bSymInitialized = TRUE; + if (j_SymInitialize(hProcess, NULL, TRUE)) { + g_bSymInitialized = TRUE; + } } - if(!j_SymGetSymFromAddr(hProcess, (DWORD)addr, &dwDisplacement, pSymbol)) - buf[0] = 0; - else - { - strncpy(buf, pSymbol->Name, size); - buf[size - 1] = 0; + /* Lookup symbol name */ + if (!g_bSymInitialized || + !j_SymFromAddr(hProcess, dwAddr, &dwDisplacement, pSymbol)) { + /* + * We couldn't obtain symbol information. At least tell which module the address belongs. + */ + + HMODULE hModule = NULL; + + if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)addr, + &hModule)) { + return FALSE; + } + + if (GetModuleFileNameA(hModule, buffer, sizeof buffer) == sizeof buffer) { + return FALSE; + } + snprintf(buf, size, "%p at %s+0x%lx", + addr, buffer, + (unsigned long)((uintptr_t)addr - (uintptr_t)hModule)); + + return TRUE; + } + + /* + * Try to get filename and line number. + */ + memset(&Line, 0, sizeof Line); + Line.SizeOfStruct = sizeof Line; + if (!j_SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &Line)) { + Line.FileName = NULL; + } + + if (Line.FileName) { + snprintf(buf, size, "%s at %s:%lu", pSymbol->Name, Line.FileName, Line.LineNumber); + } else { + snprintf(buf, size, "%s", pSymbol->Name); } + + return TRUE; } -#endif -#ifdef __GLIBC__ +#endif /* PIPE_OS_WINDOWS */ + + +#if defined(HAVE_EXECINFO_H) + #include /* This can only provide dynamic symbols, or binary offsets into a file. * * To fix this, post-process the output with tools/addr2line.sh */ -static INLINE void +static inline boolean debug_symbol_name_glibc(const void *addr, char* buf, unsigned size) { char** syms = backtrace_symbols((void**)&addr, 1); - strncpy(buf, syms[0], size); + if (!syms) { + return FALSE; + } + strncpy(buf, syms[0], size - 1); buf[size - 1] = 0; free(syms); + return TRUE; } -#endif + +#endif /* defined(HAVE_EXECINFO_H) */ + void debug_symbol_name(const void *addr, char* buf, unsigned size) { -#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) && defined(PIPE_ARCH_X86) - debug_symbol_name_imagehlp(addr, buf, size); - if(buf[0]) +#if defined(PIPE_OS_WINDOWS) + if (debug_symbol_name_dbghelp(addr, buf, size)) { return; + } #endif -#ifdef __GLIBC__ - debug_symbol_name_glibc(addr, buf, size); - if(buf[0]) - return; -#endif +#if defined(HAVE_EXECINFO_H) + if (debug_symbol_name_glibc(addr, buf, size)) { + return; + } +#endif /* defined(HAVE_EXECINFO_H) */ - util_snprintf(buf, size, "%p", addr); + snprintf(buf, size, "%p", addr); buf[size - 1] = 0; } @@ -189,31 +270,25 @@ debug_symbol_print(const void *addr) debug_printf("\t%s\n", buf); } -struct util_hash_table* symbols_hash; -pipe_mutex symbols_mutex; - -static unsigned hash_ptr(void* p) -{ - return (unsigned)(uintptr_t)p; -} - -static int compare_ptr(void* a, void* b) -{ - if(a == b) - return 0; - else if(a < b) - return -1; - else - return 1; -} +struct hash_table* symbols_hash; +static mtx_t symbols_mutex = _MTX_INITIALIZER_NP; const char* debug_symbol_name_cached(const void *addr) { const char* name; - pipe_mutex_lock(symbols_mutex); +#ifdef PIPE_OS_WINDOWS + static boolean first = TRUE; + + if (first) { + (void) mtx_init(&symbols_mutex, mtx_plain); + first = FALSE; + } +#endif + + mtx_lock(&symbols_mutex); if(!symbols_hash) - symbols_hash = util_hash_table_create(hash_ptr, compare_ptr); + symbols_hash = util_hash_table_create_ptr_keys(); name = util_hash_table_get(symbols_hash, (void*)addr); if(!name) { @@ -221,8 +296,8 @@ debug_symbol_name_cached(const void *addr) debug_symbol_name(addr, buf, sizeof(buf)); name = strdup(buf); - util_hash_table_set(symbols_hash, (void*)addr, (void*)name); + _mesa_hash_table_insert(symbols_hash, (void*)addr, (void*)name); } - pipe_mutex_unlock(symbols_mutex); + mtx_unlock(&symbols_mutex); return name; }