From 02e76e727b95dc21dc07d1fe8424b68e37e91a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= Date: Sat, 6 Jan 2024 22:53:54 +0100 Subject: [PATCH 3/3] libbacktrace: Add loaded dlls after initialize libbacktrace/Changelog: * pecoff.c [HAVE_WINDOWS_H]: (dll_notification_data): Added (dll_notification_context): Added (dll_notification): Added (backtrace_initialize): Use LdrRegisterDllNotification to load debug information of later loaded dlls. --- libbacktrace/pecoff.c | 102 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c index 647baa39640..bfe12cc2a0a 100644 --- a/libbacktrace/pecoff.c +++ b/libbacktrace/pecoff.c @@ -62,6 +62,32 @@ POSSIBILITY OF SUCH DAMAGE. */ #undef Module32Next #endif #endif + +#if defined(_ARM_) +#define NTAPI +#else +#define NTAPI __stdcall +#endif + +/* This is a simplified (but binary compatible) version of what Microsoft + defines in their documentation. */ +struct dll_notifcation_data +{ + ULONG reserved; + /* The name as UNICODE_STRING struct. */ + PVOID full_dll_name; + PVOID base_dll_name; + PVOID dll_base; + ULONG size_of_image; +}; + +typedef LONG NTSTATUS; +typedef VOID CALLBACK (*LDR_DLL_NOTIFICATION)(ULONG, + struct dll_notifcation_data*, + PVOID); +typedef NTSTATUS NTAPI (*LDR_REGISTER_FUNCTION)(ULONG, + LDR_DLL_NOTIFICATION, PVOID, + PVOID*); #endif /* Coff file header. */ @@ -912,7 +938,8 @@ coff_add (struct backtrace_state *state, int descriptor, return 0; } -#if defined(HAVE_WINDOWS_H) && !defined(HAVE_TLHELP32_H) +#ifdef HAVE_WINDOWS_H +#ifndef HAVE_TLHELP32_H static void free_modules (struct backtrace_state *state, backtrace_error_callback error_callback, void *data, @@ -958,6 +985,51 @@ get_all_modules (struct backtrace_state *state, } } #endif +struct dll_notification_context +{ + struct backtrace_state *state; + backtrace_error_callback error_callback; + void *data; +}; + +VOID CALLBACK +dll_notification (ULONG reason, +struct dll_notifcation_data *notification_data, +PVOID context) +{ + char module_name[MAX_PATH]; + int descriptor; + struct dll_notification_context* dll_context = + (struct dll_notification_context*) context; + struct backtrace_state *state = dll_context->state; + void *data = dll_context->data; + backtrace_error_callback error_callback = dll_context->data; + fileline fileline; + int found_sym; + int found_dwarf; + HMODULE module_handle; + + if (reason != /*LDR_DLL_NOTIFICATION_REASON_LOADED*/1) + return; + + if (!GetModuleHandleEx (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (TCHAR*) notification_data->dll_base, + &module_handle)) + return; + + if (!GetModuleFileNameA ((HMODULE) module_handle, module_name, MAX_PATH - 1)) + return; + + descriptor = backtrace_open (module_name, error_callback, data, NULL); + + if (descriptor < 0) + return; + + coff_add (state, descriptor, error_callback, data, &fileline, &found_sym, + &found_dwarf, (uintptr_t) module_handle); +} +#endif /* Initialize the backtrace data we need from an ELF executable. At the ELF level, all we need to do is find the debug info @@ -978,6 +1050,7 @@ backtrace_initialize (struct backtrace_state *state, #ifdef HAVE_WINDOWS_H fileline module_fileline_fn; int module_found_sym; + HMODULE nt_dll_handle; #ifdef HAVE_TLHELP32_H HANDLE snapshot; @@ -1065,6 +1138,33 @@ backtrace_initialize (struct backtrace_state *state, if (modules) free_modules (state, error_callback, data, &modules, bytes_allocated_for_modules); #endif + + nt_dll_handle = GetModuleHandle (TEXT ("ntdll.dll")); + if (nt_dll_handle) + { + LDR_REGISTER_FUNCTION register_func; + const char register_name[] = "LdrRegisterDllNotification"; + register_func = (LDR_REGISTER_FUNCTION) GetProcAddress (nt_dll_handle, + register_name); + + if (register_func) + { + PVOID cookie; + struct dll_notification_context *context + = backtrace_alloc (state, + sizeof(struct dll_notification_context), + error_callback, data); + + if (context) + { + context->state = state; + context->data = data; + context->error_callback = error_callback; + + register_func (0, &dll_notification, context, &cookie); + } + } + } #endif if (!state->threaded) -- 2.42.1