From 220ce9c3fdcc8d85a87936c2a6696044064ecbed Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Tue, 15 Sep 2020 21:07:27 +0900 Subject: [PATCH] info: Load DbgHelp.dll using g_module_open() ... and update meson file so that enable it only using required headers. "dependency(...)" is unlikely successful for Windows SDK libraries since it doesn't ship pkg-config file. So it needs to be changed to "find_library()" to link corresponding .lib file. That would result to most MSVC build system will link dbghelp.dll. However, one drawback of the change is that gstreamer-1.0.dll will mandate dbghelp.dll although it should be optional. So g_module_open() way can be the most safe way in this case. Part-of: --- gst/gstinfo.c | 109 +++++++++++++++++++++++++++++++++++++++++++------- meson.build | 7 ++-- 2 files changed, 98 insertions(+), 18 deletions(-) diff --git a/gst/gstinfo.c b/gst/gstinfo.c index 37987d367f..f38c18d9f3 100644 --- a/gst/gstinfo.c +++ b/gst/gstinfo.c @@ -156,9 +156,10 @@ static char *gst_info_printf_pointer_extension_func (const char *format, #endif /* HAVE_BACKTRACE */ #ifdef HAVE_DBGHELP -#include +#include #include #include +#include #endif /* HAVE_DBGHELP */ #ifdef G_OS_WIN32 @@ -2958,19 +2959,91 @@ generate_backtrace_trace (void) #endif /* HAVE_BACKTRACE */ #ifdef HAVE_DBGHELP -static void +/* *INDENT-OFF* */ +static struct +{ + DWORD (WINAPI * pSymSetOptions) (DWORD SymOptions); + BOOL (WINAPI * pSymInitialize) (HANDLE hProcess, + PCSTR UserSearchPath, + BOOL fInvadeProcess); + BOOL (WINAPI * pStackWalk64) (DWORD MachineType, + HANDLE hProcess, + HANDLE hThread, + LPSTACKFRAME64 StackFrame, + PVOID ContextRecord, + PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + PVOID (WINAPI * pSymFunctionTableAccess64) (HANDLE hProcess, + DWORD64 AddrBase); + DWORD64 (WINAPI * pSymGetModuleBase64) (HANDLE hProcess, + DWORD64 qwAddr); + BOOL (WINAPI * pSymFromAddr) (HANDLE hProcess, + DWORD64 Address, + PDWORD64 Displacement, + PSYMBOL_INFO Symbol); + BOOL (WINAPI * pSymGetModuleInfo64) (HANDLE hProcess, + DWORD64 qwAddr, + PIMAGEHLP_MODULE64 ModuleInfo); + BOOL (WINAPI * pSymGetLineFromAddr64) (HANDLE hProcess, + DWORD64 qwAddr, + PDWORD pdwDisplacement, + PIMAGEHLP_LINE64 Line64); +} dbg_help_vtable = { NULL,}; +/* *INDENT-ON* */ + +static GModule *dbg_help_module = NULL; + +static gboolean +dbghelp_load_symbol (const gchar * symbol_name, gpointer * symbol) +{ + if (dbg_help_module && + !g_module_symbol (dbg_help_module, symbol_name, symbol)) { + GST_WARNING ("Cannot load %s symbol", symbol_name); + g_module_close (dbg_help_module); + dbg_help_module = NULL; + } + + return ! !dbg_help_module; +} + +static gboolean dbghelp_initialize_symbols (HANDLE process) { static gsize initialization_value = 0; if (g_once_init_enter (&initialization_value)) { GST_INFO ("Initializing Windows symbol handler"); - SymSetOptions (SYMOPT_LOAD_LINES); - SymInitialize (process, NULL, TRUE); - GST_INFO ("Initialized Windows symbol handler"); + + dbg_help_module = g_module_open ("dbghelp.dll", G_MODULE_BIND_LAZY); + dbghelp_load_symbol ("SymSetOptions", + (gpointer *) & dbg_help_vtable.pSymSetOptions); + dbghelp_load_symbol ("SymInitialize", + (gpointer *) & dbg_help_vtable.pSymInitialize); + dbghelp_load_symbol ("StackWalk64", + (gpointer *) & dbg_help_vtable.pStackWalk64); + dbghelp_load_symbol ("SymFunctionTableAccess64", + (gpointer *) & dbg_help_vtable.pSymFunctionTableAccess64); + dbghelp_load_symbol ("SymGetModuleBase64", + (gpointer *) & dbg_help_vtable.pSymGetModuleBase64); + dbghelp_load_symbol ("SymFromAddr", + (gpointer *) & dbg_help_vtable.pSymFromAddr); + dbghelp_load_symbol ("SymGetModuleInfo64", + (gpointer *) & dbg_help_vtable.pSymGetModuleInfo64); + dbghelp_load_symbol ("SymGetLineFromAddr64", + (gpointer *) & dbg_help_vtable.pSymGetLineFromAddr64); + + if (dbg_help_module) { + dbg_help_vtable.pSymSetOptions (SYMOPT_LOAD_LINES); + dbg_help_vtable.pSymInitialize (process, NULL, TRUE); + GST_INFO ("Initialized Windows symbol handler"); + } g_once_init_leave (&initialization_value, 1); } + + return ! !dbg_help_module; } static gchar * @@ -2983,9 +3056,12 @@ generate_dbghelp_trace (void) CONTEXT context; STACKFRAME64 frame = { 0 }; PVOID save_context; - GString *trace = g_string_new (NULL); + GString *trace = NULL; - dbghelp_initialize_symbols (process); + if (!dbghelp_initialize_symbols (process)) + return NULL; + + trace = g_string_new (NULL); memset (&context, 0, sizeof (CONTEXT)); context.ContextFlags = CONTEXT_FULL; @@ -3024,19 +3100,23 @@ generate_dbghelp_trace (void) line.SizeOfStruct = sizeof (line); - if (!StackWalk64 (machine, process, thread, &frame, save_context, 0, - SymFunctionTableAccess64, SymGetModuleBase64, 0)) + if (!dbg_help_vtable.pStackWalk64 (machine, process, thread, &frame, + save_context, 0, dbg_help_vtable.pSymFunctionTableAccess64, + dbg_help_vtable.pSymGetModuleBase64, 0)) { break; + } - if (SymFromAddr (process, frame.AddrPC.Offset, 0, symbol)) + if (dbg_help_vtable.pSymFromAddr (process, frame.AddrPC.Offset, 0, symbol)) g_string_append_printf (trace, "%s ", symbol->Name); else g_string_append (trace, "?? "); - if (SymGetLineFromAddr64 (process, frame.AddrPC.Offset, &displacement, - &line)) - g_string_append_printf (trace, "(%s:%u)", line.FileName, line.LineNumber); - else if (SymGetModuleInfo64 (process, frame.AddrPC.Offset, &module_info)) + if (dbg_help_vtable.pSymGetLineFromAddr64 (process, frame.AddrPC.Offset, + &displacement, &line)) + g_string_append_printf (trace, "(%s:%lu)", line.FileName, + line.LineNumber); + else if (dbg_help_vtable.pSymGetModuleInfo64 (process, frame.AddrPC.Offset, + &module_info)) g_string_append_printf (trace, "(%s)", module_info.ImageName); else g_string_append_printf (trace, "(%s)", "??"); @@ -3044,7 +3124,6 @@ generate_dbghelp_trace (void) g_string_append (trace, "\n"); } -done: return g_string_free (trace, FALSE); } #endif /* HAVE_DBGHELP */ diff --git a/meson.build b/meson.build index 6493b78407..492373fe7a 100644 --- a/meson.build +++ b/meson.build @@ -370,12 +370,13 @@ endif backtrace_deps = [] unwind_dep = dependency('libunwind', required : get_option('libunwind')) dw_dep = dependency('libdw', required: get_option('libdw')) -dbghelp_dep = dependency('DbgHelp', required : get_option('dbghelp')) -backtrace_deps = [unwind_dep, dw_dep, dbghelp_dep] +dbghelp_option = get_option('dbghelp') +have_dbghelp = cc.has_header('dbghelp.h', required: dbghelp_option) and cc.has_header('tlhelp32.h', required: dbghelp_option) +backtrace_deps = [unwind_dep, dw_dep] backtrace_source_info = false backtrace_minimal = false # MSVC debug stack trace support -if host_system == 'windows' and dbghelp_dep.found() +if host_system == 'windows' and have_dbghelp cdata.set('HAVE_DBGHELP', 1) backtrace_source_info = true # DWARF stack trace support with libunwind and elf-utils