Am 07.01.2024 um 18:03 schrieb Eli Zaretskii:
Date: Sun, 7 Jan 2024 17:07:06 +0100
Cc: i...@google.com, gcc-patc...@gcc.gnu.org, gcc@gcc.gnu.org
From: Björn Schäpers <g...@hazardy.de>

That was about GetModuleHandle, not about GetModuleHandleEx.  For the
latter, all Windows versions that support it also support "wide" APIs.
So my suggestion is to use GetModuleHandleExW here.  However, you will
need to make sure that notification_data->dll_base is declared as
'wchar_t *', not 'char *'.  If dll_base is declared as 'char *', then
only GetModuleHandleExA will work, and you will lose the ability to
support file names with non-ASCII characters outside of the current
system codepage.

The dll_base is a PVOID. With the GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS flag
GetModuleHandleEx does not look for a name, but uses an adress in the module to
get the HMODULE, so you cast it to char* or wchar_t* depending on which function
you call. Actually one could just cast the dll_base to HMODULE, at least in
win32 on x86 the HMODULE of a dll is always its base adress. But to make it
safer and future proof I went the way through GetModuleHandeEx.

In that case, you an call either GetModuleHandeExA or
GetModuleHandeExW, the difference is minor.

Here an updated version without relying on TEXT or TCHAR, directly calling GetModuleHandleExW.

Kind regards,
Björn.
From a8e1e64ccb56158ec8a7e5de0d5228f3f6f7e5c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Sch=C3=A4pers?= <bjo...@hazardy.de>
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 | 104 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 103 insertions(+), 1 deletion(-)

diff --git a/libbacktrace/pecoff.c b/libbacktrace/pecoff.c
index 647baa39640..d973a26f05a 100644
--- a/libbacktrace/pecoff.c
+++ b/libbacktrace/pecoff.c
@@ -62,6 +62,34 @@ 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;
+};
+
+#define LDR_DLL_NOTIFICATION_REASON_LOADED 1
+
+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 +940,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 +987,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)
+    return;
+
+  if (!GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
+                          | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+                          (wchar_t*) 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 +1052,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 +1140,33 @@ backtrace_initialize (struct backtrace_state *state,
   if (modules)
     free_modules (state, error_callback, data, &modules, 
bytes_allocated_for_modules);
 #endif
+
+  nt_dll_handle = GetModuleHandleW (L"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

Reply via email to