6a8b653
From 7a8a31c041b52d87c1522e684cb301b07ea6ad9b Mon Sep 17 00:00:00 2001
6a8b653
From: Adam Jackson <ajax@redhat.com>
6a8b653
Date: Fri, 10 Oct 2008 15:53:48 -0400
6a8b653
Subject: [PATCH] Move xorg_backtrace() up to the OS level so we can call it from DIX.
6a8b653
6a8b653
---
6a8b653
 hw/xfree86/common/xf86Events.c |  173 ----------------------------------
6a8b653
 include/os.h                   |    2 +
6a8b653
 os/Makefile.am                 |    1 +
6a8b653
 os/backtrace.c                 |  202 ++++++++++++++++++++++++++++++++++++++++
6a8b653
 4 files changed, 205 insertions(+), 173 deletions(-)
6a8b653
 create mode 100644 os/backtrace.c
6a8b653
6a8b653
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
6a8b653
index 6ca0ae7..a2c206e 100644
6a8b653
--- a/hw/xfree86/common/xf86Events.c
6a8b653
+++ b/hw/xfree86/common/xf86Events.c
6a8b653
@@ -358,179 +358,6 @@
6a8b653
     xf86SigIllHandler = sigillhandler;
6a8b653
 }
6a8b653
 
6a8b653
-#ifdef HAVE_BACKTRACE
6a8b653
-#include <execinfo.h>
6a8b653
-
6a8b653
-static __inline__ void xorg_backtrace(void)
6a8b653
-{
6a8b653
-    void *array[32]; /* deeper nesting than this means something's wrong */
6a8b653
-    size_t size, i;
6a8b653
-    char **strings;
6a8b653
-    ErrorF("\nBacktrace:\n");
6a8b653
-    size = backtrace(array, 32);
6a8b653
-    strings = backtrace_symbols(array, size);
6a8b653
-    for (i = 0; i < size; i++)
6a8b653
-        ErrorF("%d: %s\n", i, strings[i]);
6a8b653
-    free(strings);
6a8b653
-}
6a8b653
-
6a8b653
-#else /* not glibc or glibc < 2.1 */
6a8b653
-
6a8b653
-# if defined(sun) && defined(__SVR4)
6a8b653
-#  define HAVE_PSTACK
6a8b653
-# endif
6a8b653
-
6a8b653
-# if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
6a8b653
-
6a8b653
-# include <ucontext.h>
6a8b653
-# include <signal.h>
6a8b653
-# include <dlfcn.h>
6a8b653
-# include <sys/elf.h>
6a8b653
-
6a8b653
-#ifdef _LP64
6a8b653
-# define ElfSym Elf64_Sym
6a8b653
-#else
6a8b653
-# define ElfSym Elf32_Sym
6a8b653
-#endif
6a8b653
-
6a8b653
-/* Called for each frame on the stack to print it's contents */
6a8b653
-static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
6a8b653
-{
6a8b653
-    Dl_info dlinfo;
6a8b653
-    ElfSym *dlsym;
6a8b653
-    char header[32];
6a8b653
-    int depth = *((int *) arg);
6a8b653
-
6a8b653
-    if (signo) {
6a8b653
-	char signame[SIG2STR_MAX];
6a8b653
-
6a8b653
-	if (sig2str(signo, signame) != 0) {
6a8b653
-	    strcpy(signame, "unknown");
6a8b653
-	}
6a8b653
-
6a8b653
-	ErrorF("** Signal %d (%s)\n", signo, signame);
6a8b653
-    }
6a8b653
-
6a8b653
-    snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
6a8b653
-    *((int *) arg) = depth + 1;
6a8b653
-
6a8b653
-    /* Ask system dynamic loader for info on the address */
6a8b653
-    if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
6a8b653
-	unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
6a8b653
-	const char *symname;
6a8b653
-	
6a8b653
-	if (offset < dlsym->st_size) { /* inside a function */
6a8b653
-	    symname = dlinfo.dli_sname;
6a8b653
-	} else { /* found which file it was in, but not which function */
6a8b653
-	    symname = "<section start>";
6a8b653
-	    offset = pc - (uintptr_t)dlinfo.dli_fbase;
6a8b653
-	}
6a8b653
-	ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname,
6a8b653
-	       symname, offset);
6a8b653
-
6a8b653
-    } else {
6a8b653
-	/* Couldn't find symbol info from system dynamic loader, should
6a8b653
-	 * probably poke elfloader here, but haven't written that code yet,
6a8b653
-	 * so we just print the pc.
6a8b653
-	 */
6a8b653
-	ErrorF("%s\n", header);
6a8b653
-    }
6a8b653
-
6a8b653
-    return 0;
6a8b653
-}
6a8b653
-# endif /* HAVE_WALKCONTEXT */
6a8b653
-
6a8b653
-# ifdef HAVE_PSTACK
6a8b653
-static int xorg_backtrace_pstack(void) {
6a8b653
-    pid_t kidpid;
6a8b653
-    int pipefd[2];
6a8b653
-
6a8b653
-    if (pipe(pipefd) != 0) {
6a8b653
-	return -1;
6a8b653
-    }
6a8b653
-
6a8b653
-    kidpid = fork1();
6a8b653
-
6a8b653
-    if (kidpid == -1) {
6a8b653
-	/* ERROR */
6a8b653
-	return -1;
6a8b653
-    } else if (kidpid == 0) {
6a8b653
-	/* CHILD */
6a8b653
-	char parent[16];
6a8b653
-	
6a8b653
-	seteuid(0);
6a8b653
-	close(STDIN_FILENO);
6a8b653
-	close(STDOUT_FILENO);
6a8b653
-	dup2(pipefd[1],STDOUT_FILENO);
6a8b653
-	closefrom(STDERR_FILENO);
6a8b653
-
6a8b653
-	snprintf(parent, sizeof(parent), "%d", getppid());
6a8b653
-	execle("/usr/bin/pstack", "pstack", parent, NULL);
6a8b653
-	exit(1);
6a8b653
-    } else {
6a8b653
-	/* PARENT */
6a8b653
-	char btline[256];
6a8b653
-	int kidstat;
6a8b653
-	int bytesread;
6a8b653
-	int done = 0;
6a8b653
-	
6a8b653
-	close(pipefd[1]);
6a8b653
-
6a8b653
-	while (!done) {
6a8b653
-	    bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
6a8b653
-
6a8b653
-	    if (bytesread > 0) {
6a8b653
-		btline[bytesread] = 0;
6a8b653
-		ErrorF("%s", btline);
6a8b653
-	    }
6a8b653
-	    else if ((bytesread < 0) ||
6a8b653
-		     ((errno != EINTR) && (errno != EAGAIN)))
6a8b653
-		done = 1;
6a8b653
-	}
6a8b653
-	close(pipefd[0]);
6a8b653
-	waitpid(kidpid, &kidstat, 0);
6a8b653
-	if (kidstat != 0)
6a8b653
-	    return -1;
6a8b653
-    }
6a8b653
-    return 0;
6a8b653
-}
6a8b653
-# endif /* HAVE_PSTACK */
6a8b653
-
6a8b653
-
6a8b653
-# if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
6a8b653
-
6a8b653
-static __inline__ void xorg_backtrace(void) {
6a8b653
-
6a8b653
-    ErrorF("\nBacktrace:\n");
6a8b653
-
6a8b653
-#  ifdef HAVE_PSTACK
6a8b653
-/* First try fork/exec of pstack - otherwise fall back to walkcontext
6a8b653
-   pstack is preferred since it can print names of non-exported functions */
6a8b653
-
6a8b653
-    if (xorg_backtrace_pstack() < 0)
6a8b653
-#  endif	
6a8b653
-    {
6a8b653
-#  ifdef HAVE_WALKCONTEXT
6a8b653
-	ucontext_t u;
6a8b653
-	int depth = 1;
6a8b653
-	
6a8b653
-	if (getcontext(&u) == 0)
6a8b653
-	    walkcontext(&u, xorg_backtrace_frame, &depth);
6a8b653
-	else
6a8b653
-#  endif
6a8b653
-	    Error("Failed to get backtrace info");
6a8b653
-    }
6a8b653
-    ErrorF("\n");	
6a8b653
-}
6a8b653
-
6a8b653
-# else
6a8b653
-
6a8b653
-/* Default fallback if we can't find any way to get a backtrace */
6a8b653
-static __inline__ void xorg_backtrace(void) { return; }
6a8b653
-
6a8b653
-# endif
6a8b653
-#endif
6a8b653
-
6a8b653
 /*
6a8b653
  * xf86SigHandler --
6a8b653
  *    Catch unexpected signals and exit or continue cleanly.
6a8b653
diff --git a/include/os.h b/include/os.h
6a8b653
--- a/include/os.h
6a8b653
+++ b/include/os.h
6a8b653
@@ -517,4 +517,6 @@
6a8b653
 extern void Error(char *str);
6a8b653
 extern void LogPrintMarkers(void);
6a8b653
 
6a8b653
+extern void xorg_backtrace(void);
6a8b653
+
6a8b653
 #endif /* OS_H */
6a8b653
diff --git a/os/Makefile.am b/os/Makefile.am
6a8b653
--- a/os/Makefile.am
6a8b653
+++ b/os/Makefile.am
6a8b653
@@ -11,6 +11,7 @@
6a8b653
 	WaitFor.c	\
6a8b653
 	access.c	\
6a8b653
 	auth.c		\
6a8b653
+	backtrace.c	\
6a8b653
 	connection.c	\
6a8b653
 	io.c		\
6a8b653
 	mitauth.c	\
6a8b653
diff --git a/os/backtrace.c b/os/backtrace.c
6a8b653
new file mode 100644
6a8b653
--- /dev/null
6a8b653
+++ b/os/backtrace.c
6a8b653
@@ -0,0 +1,201 @@
6a8b653
+/*
6a8b653
+ * Copyright 2008 Red Hat, Inc.
6a8b653
+ *
6a8b653
+ * Permission is hereby granted, free of charge, to any person obtaining a
6a8b653
+ * copy of this software and associated documentation files (the "Software")
6a8b653
+ * to deal in the software without restriction, including without limitation
6a8b653
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
6a8b653
+ * license, and/or sell copies of the Software, and to permit persons to whom
6a8b653
+ * them Software is furnished to do so, subject to the following conditions:
6a8b653
+ *
6a8b653
+ * The above copyright notice and this permission notice (including the next
6a8b653
+ * paragraph) shall be included in all copies or substantial portions of the
6a8b653
+ * Software.
6a8b653
+ *
6a8b653
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6a8b653
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY,
6a8b653
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
6a8b653
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER
6a8b653
+ * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN
6a8b653
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6a8b653
+ */
6a8b653
+
6a8b653
+#ifdef HAVE_DIX_CONFIG_H
6a8b653
+#include <dix-config.h>
6a8b653
+#endif
6a8b653
+
6a8b653
+#include "os.h"
6a8b653
+#include "misc.h"
6a8b653
+
6a8b653
+#ifdef HAVE_BACKTRACE
6a8b653
+#include <execinfo.h>
6a8b653
+
6a8b653
+void xorg_backtrace(void)
6a8b653
+{
6a8b653
+    void *array[32]; /* deeper nesting than this means something's wrong */
6a8b653
+    size_t size, i;
6a8b653
+    char **strings;
6a8b653
+    ErrorF("\nBacktrace:\n");
6a8b653
+    size = backtrace(array, 32);
6a8b653
+    strings = backtrace_symbols(array, size);
6a8b653
+    for (i = 0; i < size; i++)
6a8b653
+        ErrorF("%d: %s\n", i, strings[i]);
6a8b653
+    free(strings);
6a8b653
+}
6a8b653
+
6a8b653
+#else /* not glibc or glibc < 2.1 */
6a8b653
+
6a8b653
+# if defined(sun) && defined(__SVR4)
6a8b653
+#  define HAVE_PSTACK
6a8b653
+# endif
6a8b653
+
6a8b653
+# if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
6a8b653
+
6a8b653
+# include <ucontext.h>
6a8b653
+# include <signal.h>
6a8b653
+# include <dlfcn.h>
6a8b653
+# include <sys/elf.h>
6a8b653
+
6a8b653
+#ifdef _LP64
6a8b653
+# define ElfSym Elf64_Sym
6a8b653
+#else
6a8b653
+# define ElfSym Elf32_Sym
6a8b653
+#endif
6a8b653
+
6a8b653
+/* Called for each frame on the stack to print it's contents */
6a8b653
+static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
6a8b653
+{
6a8b653
+    Dl_info dlinfo;
6a8b653
+    ElfSym *dlsym;
6a8b653
+    char header[32];
6a8b653
+    int depth = *((int *) arg);
6a8b653
+
6a8b653
+    if (signo) {
6a8b653
+	char signame[SIG2STR_MAX];
6a8b653
+
6a8b653
+	if (sig2str(signo, signame) != 0) {
6a8b653
+	    strcpy(signame, "unknown");
6a8b653
+	}
6a8b653
+
6a8b653
+	ErrorF("** Signal %d (%s)\n", signo, signame);
6a8b653
+    }
6a8b653
+
6a8b653
+    snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
6a8b653
+    *((int *) arg) = depth + 1;
6a8b653
+
6a8b653
+    /* Ask system dynamic loader for info on the address */
6a8b653
+    if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
6a8b653
+	unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
6a8b653
+	const char *symname;
6a8b653
+	
6a8b653
+	if (offset < dlsym->st_size) { /* inside a function */
6a8b653
+	    symname = dlinfo.dli_sname;
6a8b653
+	} else { /* found which file it was in, but not which function */
6a8b653
+	    symname = "<section start>";
6a8b653
+	    offset = pc - (uintptr_t)dlinfo.dli_fbase;
6a8b653
+	}
6a8b653
+	ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname,
6a8b653
+	       symname, offset);
6a8b653
+
6a8b653
+    } else {
6a8b653
+	/* Couldn't find symbol info from system dynamic loader, should
6a8b653
+	 * probably poke elfloader here, but haven't written that code yet,
6a8b653
+	 * so we just print the pc.
6a8b653
+	 */
6a8b653
+	ErrorF("%s\n", header);
6a8b653
+    }
6a8b653
+
6a8b653
+    return 0;
6a8b653
+}
6a8b653
+# endif /* HAVE_WALKCONTEXT */
6a8b653
+
6a8b653
+# ifdef HAVE_PSTACK
6a8b653
+static int xorg_backtrace_pstack(void) {
6a8b653
+    pid_t kidpid;
6a8b653
+    int pipefd[2];
6a8b653
+
6a8b653
+    if (pipe(pipefd) != 0) {
6a8b653
+	return -1;
6a8b653
+    }
6a8b653
+
6a8b653
+    kidpid = fork1();
6a8b653
+
6a8b653
+    if (kidpid == -1) {
6a8b653
+	/* ERROR */
6a8b653
+	return -1;
6a8b653
+    } else if (kidpid == 0) {
6a8b653
+	/* CHILD */
6a8b653
+	char parent[16];
6a8b653
+	
6a8b653
+	seteuid(0);
6a8b653
+	close(STDIN_FILENO);
6a8b653
+	close(STDOUT_FILENO);
6a8b653
+	dup2(pipefd[1],STDOUT_FILENO);
6a8b653
+	closefrom(STDERR_FILENO);
6a8b653
+
6a8b653
+	snprintf(parent, sizeof(parent), "%d", getppid());
6a8b653
+	execle("/usr/bin/pstack", "pstack", parent, NULL);
6a8b653
+	exit(1);
6a8b653
+    } else {
6a8b653
+	/* PARENT */
6a8b653
+	char btline[256];
6a8b653
+	int kidstat;
6a8b653
+	int bytesread;
6a8b653
+	int done = 0;
6a8b653
+	
6a8b653
+	close(pipefd[1]);
6a8b653
+
6a8b653
+	while (!done) {
6a8b653
+	    bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
6a8b653
+
6a8b653
+	    if (bytesread > 0) {
6a8b653
+		btline[bytesread] = 0;
6a8b653
+		ErrorF("%s", btline);
6a8b653
+	    }
6a8b653
+	    else if ((bytesread < 0) ||
6a8b653
+		     ((errno != EINTR) && (errno != EAGAIN)))
6a8b653
+		done = 1;
6a8b653
+	}
6a8b653
+	close(pipefd[0]);
6a8b653
+	waitpid(kidpid, &kidstat, 0);
6a8b653
+	if (kidstat != 0)
6a8b653
+	    return -1;
6a8b653
+    }
6a8b653
+    return 0;
6a8b653
+}
6a8b653
+# endif /* HAVE_PSTACK */
6a8b653
+
6a8b653
+
6a8b653
+# if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
6a8b653
+
6a8b653
+void xorg_backtrace(void) {
6a8b653
+
6a8b653
+    ErrorF("\nBacktrace:\n");
6a8b653
+
6a8b653
+#  ifdef HAVE_PSTACK
6a8b653
+/* First try fork/exec of pstack - otherwise fall back to walkcontext
6a8b653
+   pstack is preferred since it can print names of non-exported functions */
6a8b653
+
6a8b653
+    if (xorg_backtrace_pstack() < 0)
6a8b653
+#  endif	
6a8b653
+    {
6a8b653
+#  ifdef HAVE_WALKCONTEXT
6a8b653
+	ucontext_t u;
6a8b653
+	int depth = 1;
6a8b653
+	
6a8b653
+	if (getcontext(&u) == 0)
6a8b653
+	    walkcontext(&u, xorg_backtrace_frame, &depth);
6a8b653
+	else
6a8b653
+#  endif
6a8b653
+	    Error("Failed to get backtrace info");
6a8b653
+    }
6a8b653
+    ErrorF("\n");	
6a8b653
+}
6a8b653
+
6a8b653
+# else
6a8b653
+
6a8b653
+/* Default fallback if we can't find any way to get a backtrace */
6a8b653
+void xorg_backtrace(void) { return; }
6a8b653
+
6a8b653
+# endif
6a8b653
+#endif
6a8b653
-- 
6a8b653
1.6.0.1
6a8b653