From d1f588ab0b670f677eaa844e68b7e790d6f03c51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=81lvaro=20Herrera?= <alvherre@kurilemu.de>
Date: Mon, 9 Feb 2026 17:51:51 +0100
Subject: [PATCH v7 2/2] fixups

---
 src/backend/meson.build        | 10 +++---
 src/backend/utils/error/elog.c | 57 ++++++++++++++++++----------------
 2 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/src/backend/meson.build b/src/backend/meson.build
index 2e7f2be2c78..1ee2c079390 100644
--- a/src/backend/meson.build
+++ b/src/backend/meson.build
@@ -2,10 +2,6 @@
 
 backend_build_deps = [backend_code]
 
-if host_system == 'windows' and cc.get_id() == 'msvc'
-  backend_build_deps += cc.find_library('dbghelp')
-endif
-
 backend_sources = []
 backend_link_with = [pgport_srv, common_srv]
 
@@ -46,6 +42,12 @@ backend_link_args = []
 backend_link_depends = []
 
 
+# On Windows also make the backend depend on dbghelp, for backtrace support
+if host_system == 'windows' and cc.get_id() == 'msvc'
+  backend_build_deps += cc.find_library('dbghelp')
+endif
+
+
 # On windows when compiling with msvc we need to make postgres export all its
 # symbols so that extension libraries can use them. For that we need to scan
 # the constituting objects and generate a file specifying all the functions as
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 60f95a58f7a..6b80e44fb5d 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -74,6 +74,7 @@
 #include "common/ip.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
+#include "mb/pg_wchar.h"
 #include "miscadmin.h"
 #include "nodes/miscnodes.h"
 #include "pgstat.h"
@@ -188,6 +189,7 @@ static void set_stack_entry_location(ErrorData *edata,
 									 const char *funcname);
 static bool matches_backtrace_functions(const char *funcname);
 static pg_noinline void set_backtrace(ErrorData *edata, int num_skip);
+static void backtrace_cleanup(int code, Datum arg);
 static void set_errdata_field(MemoryContextData *cxt, char **ptr, const char *str);
 static void FreeErrorDataContents(ErrorData *edata);
 static int	log_min_messages_cmp(const ListCell *a, const ListCell *b);
@@ -1125,30 +1127,17 @@ errbacktrace(void)
 	return 0;
 }
 
-#ifdef _MSC_VER
-/*
- * Cleanup function for DbgHelp resources.
- * Called via on_proc_exit() to release resources allocated by SymInitialize().
- */
-static void
-backtrace_cleanup(int code, Datum arg)
-{
-	SymCleanup(backtrace_process);
-}
-#endif
-
 /*
  * Compute backtrace data and add it to the supplied ErrorData.  num_skip
  * specifies how many inner frames to skip.  Use this to avoid showing the
  * internal backtrace support functions in the backtrace.  This requires that
  * this and related functions are not inlined.
  *
- * Platform-specific implementations:
- * - Unix/Linux: Uses backtrace() and backtrace_symbols()
+ * The implementation is, unsurprisingly, platform-specific:
+ * - Linux, Unix: Uses backtrace() and backtrace_symbols()
  * - Windows: Uses CaptureStackBackTrace() with DbgHelp for symbol resolution
  * 	 (requires PDB files; falls back to exported functions/raw addresses if
  * 	 unavailable)
- * - Other: Returns unsupported message
  */
 static void
 set_backtrace(ErrorData *edata, int num_skip)
@@ -1159,12 +1148,12 @@ set_backtrace(ErrorData *edata, int num_skip)
 
 #ifdef HAVE_BACKTRACE_SYMBOLS
 	{
-		void	   *buf[100];
+		void	   *frames[100];
 		int			nframes;
 		char	  **strfrms;
 
-		nframes = backtrace(buf, lengthof(buf));
-		strfrms = backtrace_symbols(buf, nframes);
+		nframes = backtrace(frames, lengthof(frames));
+		strfrms = backtrace_symbols(frames, nframes);
 		if (strfrms != NULL)
 		{
 			for (int i = num_skip; i < nframes; i++)
@@ -1177,7 +1166,7 @@ set_backtrace(ErrorData *edata, int num_skip)
 	}
 #elif defined(_MSC_VER)
 	{
-		void	   *buf[100];
+		void	   *frames[100];
 		int			nframes;
 		char		buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME * sizeof(wchar_t)];
 		PSYMBOL_INFOW psymbol;
@@ -1198,18 +1187,19 @@ set_backtrace(ErrorData *edata, int num_skip)
 			}
 			else
 			{
-				elog(WARNING, "could not initialize the symbol handler: error code %lu",
-					 GetLastError());
+				appendStringInfo(&errtrace,
+								 "could not initialize symbol handler: error code %lu",
+								 GetLastError());
 				edata->backtrace = errtrace.data;
 				return;
 			}
 		}
 
-		nframes = CaptureStackBackTrace(num_skip, lengthof(buf), buf, NULL);
+		nframes = CaptureStackBackTrace(num_skip, lengthof(frames), frames, NULL);
 
 		if (nframes == 0)
 		{
-			appendStringInfoString(&errtrace, "\nNo stack frames captured");
+			appendStringInfoString(&errtrace, "zero stack frames captured");
 			edata->backtrace = errtrace.data;
 			return;
 		}
@@ -1220,7 +1210,7 @@ set_backtrace(ErrorData *edata, int num_skip)
 
 		for (int i = 0; i < nframes; i++)
 		{
-			DWORD64		address = (DWORD64) buf[i];
+			DWORD64		address = (DWORD64) frames[i];
 			DWORD64		displacement = 0;
 			BOOL		sym_result;
 
@@ -1284,8 +1274,10 @@ set_backtrace(ErrorData *edata, int num_skip)
 			}
 			else
 			{
-				elog(WARNING, "symbol lookup failed: error code %lu",
-					 GetLastError());
+				appendStringInfo(&errtrace,
+								 "\n[0x%llx] (symbol lookup failed: error code %lu)",
+								 (unsigned long long) address,
+								 GetLastError());
 			}
 		}
 	}
@@ -1297,6 +1289,19 @@ set_backtrace(ErrorData *edata, int num_skip)
 	edata->backtrace = errtrace.data;
 }
 
+/*
+ * Cleanup function for DbgHelp resources.
+ * Called via on_proc_exit() to release resources allocated by SymInitialize().
+ */
+pg_attribute_unused()
+static void
+backtrace_cleanup(int code, Datum arg)
+{
+#ifdef _MSC_VER
+	SymCleanup(backtrace_process);
+#endif
+}
+
 /*
  * errmsg_internal --- add a primary error message text to the current error
  *
-- 
2.47.3

