svn commit: samba r15047 - branches/SAMBA_3_0/source branches/SAMBA_3_0/source/include branches/SAMBA_3_0/source/lib trunk/source trunk/source/include trunk/source/lib

jpeach at samba.org jpeach at samba.org
Wed Apr 12 00:07:52 GMT 2006


Author: jpeach
Date: 2006-04-12 00:07:40 +0000 (Wed, 12 Apr 2006)
New Revision: 15047

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=15047

Log:
Add support for using libunwind to generate a backtrace. This is
primarily intended for ia64 systems where libunwind knows more about
the different ways of walking the stack that just about anything else.

Modified:
   branches/SAMBA_3_0/source/configure.in
   branches/SAMBA_3_0/source/include/includes.h
   branches/SAMBA_3_0/source/lib/util.c
   trunk/source/configure.in
   trunk/source/include/includes.h
   trunk/source/lib/util.c


Changeset:
Modified: branches/SAMBA_3_0/source/configure.in
===================================================================
--- branches/SAMBA_3_0/source/configure.in	2006-04-11 23:32:04 UTC (rev 15046)
+++ branches/SAMBA_3_0/source/configure.in	2006-04-12 00:07:40 UTC (rev 15047)
@@ -827,7 +827,7 @@
 AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
 AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
 AC_CHECK_HEADERS(sys/sysmacros.h security/_pam_macros.h dlfcn.h)
-AC_CHECK_HEADERS(sys/syslog.h syslog.h execinfo.h)
+AC_CHECK_HEADERS(sys/syslog.h syslog.h)
 AC_CHECK_HEADERS(langinfo.h locale.h)
 AC_CHECK_HEADERS(sys/dmi.h xfs/dmapi.h sys/jfsdmapi.h sys/dmapi.h)
 
@@ -1243,10 +1243,48 @@
 AC_CHECK_FUNCS(setlocale nl_langinfo)
 AC_CHECK_FUNCS(nanosleep)
 # setbuffer, shmget, shm_open are needed for smbtorture
-AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols)
-AC_CHECK_HEADERS(libexc.h)
+AC_CHECK_FUNCS(setbuffer shmget shm_open)
+
+# Find a method of generating a stack trace
+AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
+AC_CHECK_FUNCS(backtrace_symbols)
 AC_CHECK_LIB(exc, trace_back_stack)
 
+# Note that all the libunwind symbols in the API are defined to internal
+# platform-specific version, so we must include libunwind.h before checking
+# any of them.
+AC_MSG_CHECKING([for libunwind])
+save_LIBS=$LIBS
+if test x"$UNAME_P" != xunknown ; then
+    # This probably won't link without the platform-specific libunwind.
+    LIBS="$LIBS -lunwind"
+else
+    # Add the platform-specific libunwind module. uname -p seems the most
+    # plausible option and works for ia64, where libunwind is most useful.
+    LIBS="$LIBS -lunwind -lunwind-$UNAME_P"
+fi
+
+AC_TRY_LINK(
+    [
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+    ],
+    [
+	unw_context_t ctx; unw_cursor_t cur;
+	char buf[256]; unw_word_t off; 
+	unw_getcontext(&ctx); unw_init_local(&cur, &ctx);
+	unw_get_proc_name(&cur, buf, sizeof(buf), &off);
+    ],
+    [
+	AC_MSG_RESULT(yes)
+	AC_DEFINE(HAVE_LIBUNWIND, 1, [Whether libunwind is available])
+    ],
+    [
+	AC_MSG_RESULT(no)
+	LIBS=$save_LIBS
+    ])
+
 # syscall() is needed for smbwrapper.
 AC_CHECK_FUNCS(syscall)
 

Modified: branches/SAMBA_3_0/source/include/includes.h
===================================================================
--- branches/SAMBA_3_0/source/include/includes.h	2006-04-11 23:32:04 UTC (rev 15046)
+++ branches/SAMBA_3_0/source/include/includes.h	2006-04-12 00:07:40 UTC (rev 15047)
@@ -358,10 +358,6 @@
 #include <poll.h>
 #endif
 
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
 #if defined(HAVE_RPC_RPC_H)
 /*
  * Check for AUTH_ERROR define conflict with rpc/rpc.h in prot.h.

Modified: branches/SAMBA_3_0/source/lib/util.c
===================================================================
--- branches/SAMBA_3_0/source/lib/util.c	2006-04-11 23:32:04 UTC (rev 15046)
+++ branches/SAMBA_3_0/source/lib/util.c	2006-04-12 00:07:40 UTC (rev 15047)
@@ -5,7 +5,8 @@
    Copyright (C) Jeremy Allison 2001-2002
    Copyright (C) Simo Sorce 2001
    Copyright (C) Jim McDonough <jmcd at us.ibm.com> 2003
-   
+   Copyright (C) James Peach 2006
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -1616,13 +1617,76 @@
  exit shortly after calling it.
 ********************************************************************/
 
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
 #ifdef HAVE_LIBEXC_H
 #include <libexc.h>
 #endif
 
 void log_stack_trace(void)
 {
-#ifdef HAVE_BACKTRACE_SYMBOLS
+#ifdef HAVE_LIBUNWIND
+	/* Try to use libunwind before any other technique since on ia64
+	 * libunwind correctly walks the stack in more circumstances than
+	 * backtrace.
+	 */ 
+	unw_cursor_t cursor;
+	unw_context_t uc;
+	unsigned i = 0;
+
+	char procname[256];
+	unw_word_t ip, sp, off;
+
+	procname[sizeof(procname) - 1] = '\0';
+
+	if (unw_getcontext(&uc) != 0) {
+		goto libunwind_failed;
+	}
+
+	if (unw_init_local(&cursor, &uc) != 0) {
+		goto libunwind_failed;
+	}
+
+	DEBUG(0, ("BACKTRACE:\n"));
+
+	do {
+	    ip = sp = 0;
+	    unw_get_reg(&cursor, UNW_REG_IP, &ip);
+	    unw_get_reg(&cursor, UNW_REG_SP, &sp);
+
+	    switch (unw_get_proc_name(&cursor,
+			procname, sizeof(procname) - 1, &off) ) {
+	    case 0:
+		    /* Name found. */
+	    case -UNW_ENOMEM:
+		    /* Name truncated. */
+		    DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
+			    i, procname, (long long)off,
+			    (long long)ip, (long long) sp));
+		    break;
+	    default:
+	    /* case -UNW_ENOINFO: */
+	    /* case -UNW_EUNSPEC: */
+		    /* No symbol name found. */
+		    DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
+			    i, "<unknown symbol>",
+			    (long long)ip, (long long) sp));
+	    }
+	    ++i;
+	} while (unw_step(&cursor) > 0);
+
+	return;
+
+libunwind_failed:
+	DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
+
+#elif HAVE_BACKTRACE_SYMBOLS
 	void *backtrace_stack[BACKTRACE_STACK_SIZE];
 	size_t backtrace_size;
 	char **backtrace_strings;
@@ -1649,39 +1713,38 @@
 	 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
 	 * since we are about to abort anyway, it hardly matters.
 	 */
-	{
 
 #define NAMESIZE 32 /* Arbitrary */
 
-		__uint64_t	addrs[BACKTRACE_STACK_SIZE];
-		char *      	names[BACKTRACE_STACK_SIZE];
-		char		namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
+	__uint64_t	addrs[BACKTRACE_STACK_SIZE];
+	char *      	names[BACKTRACE_STACK_SIZE];
+	char		namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
 
-		int		i;
-		int		levels;
+	int		i;
+	int		levels;
 
-		ZERO_ARRAY(addrs);
-		ZERO_ARRAY(names);
-		ZERO_ARRAY(namebuf);
+	ZERO_ARRAY(addrs);
+	ZERO_ARRAY(names);
+	ZERO_ARRAY(namebuf);
 
-		/* We need to be root so we can open our /proc entry to walk
-		 * our stack. It also helps when we want to dump core.
-		 */
-		become_root();
+	/* We need to be root so we can open our /proc entry to walk
+	 * our stack. It also helps when we want to dump core.
+	 */
+	become_root();
 
-		for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
-			names[i] = namebuf + (i * NAMESIZE);
-		}
+	for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
+		names[i] = namebuf + (i * NAMESIZE);
+	}
 
-		levels = trace_back_stack(0, addrs, names,
-				BACKTRACE_STACK_SIZE, NAMESIZE - 1);
+	levels = trace_back_stack(0, addrs, names,
+			BACKTRACE_STACK_SIZE, NAMESIZE - 1);
 
-		DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
-		for (i = 0; i < levels; i++) {
-			DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
-		}
-     }
+	DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
+	for (i = 0; i < levels; i++) {
+		DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
+	}
 #undef NAMESIZE
+
 #else
 	DEBUG(0, ("unable to produce a stack trace on this platform\n"));
 #endif

Modified: trunk/source/configure.in
===================================================================
--- trunk/source/configure.in	2006-04-11 23:32:04 UTC (rev 15046)
+++ trunk/source/configure.in	2006-04-12 00:07:40 UTC (rev 15047)
@@ -827,7 +827,7 @@
 AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
 AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
 AC_CHECK_HEADERS(sys/sysmacros.h security/_pam_macros.h dlfcn.h)
-AC_CHECK_HEADERS(sys/syslog.h syslog.h execinfo.h)
+AC_CHECK_HEADERS(sys/syslog.h syslog.h)
 AC_CHECK_HEADERS(langinfo.h locale.h)
 AC_CHECK_HEADERS(sys/dmi.h xfs/dmapi.h sys/jfsdmapi.h sys/dmapi.h)
 
@@ -1243,10 +1243,48 @@
 AC_CHECK_FUNCS(setlocale nl_langinfo)
 AC_CHECK_FUNCS(nanosleep)
 # setbuffer, shmget, shm_open are needed for smbtorture
-AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols)
-AC_CHECK_HEADERS(libexc.h)
+AC_CHECK_FUNCS(setbuffer shmget shm_open)
+
+# Find a method of generating a stack trace
+AC_CHECK_HEADERS(execinfo.h libexc.h libunwind.h)
+AC_CHECK_FUNCS(backtrace_symbols)
 AC_CHECK_LIB(exc, trace_back_stack)
 
+# Note that all the libunwind symbols in the API are defined to internal
+# platform-specific version, so we must include libunwind.h before checking
+# any of them.
+AC_MSG_CHECKING([for libunwind])
+save_LIBS=$LIBS
+if test x"$UNAME_P" != xunknown ; then
+    # This probably won't link without the platform-specific libunwind.
+    LIBS="$LIBS -lunwind"
+else
+    # Add the platform-specific libunwind module. uname -p seems the most
+    # plausible option and works for ia64, where libunwind is most useful.
+    LIBS="$LIBS -lunwind -lunwind-$UNAME_P"
+fi
+
+AC_TRY_LINK(
+    [
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+    ],
+    [
+	unw_context_t ctx; unw_cursor_t cur;
+	char buf[256]; unw_word_t off; 
+	unw_getcontext(&ctx); unw_init_local(&cur, &ctx);
+	unw_get_proc_name(&cur, buf, sizeof(buf), &off);
+    ],
+    [
+	AC_MSG_RESULT(yes)
+	AC_DEFINE(HAVE_LIBUNWIND, 1, [Whether libunwind is available])
+    ],
+    [
+	AC_MSG_RESULT(no)
+	LIBS=$save_LIBS
+    ])
+
 # syscall() is needed for smbwrapper.
 AC_CHECK_FUNCS(syscall)
 

Modified: trunk/source/include/includes.h
===================================================================
--- trunk/source/include/includes.h	2006-04-11 23:32:04 UTC (rev 15046)
+++ trunk/source/include/includes.h	2006-04-12 00:07:40 UTC (rev 15047)
@@ -358,10 +358,6 @@
 #include <poll.h>
 #endif
 
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
 #if defined(HAVE_RPC_RPC_H)
 /*
  * Check for AUTH_ERROR define conflict with rpc/rpc.h in prot.h.

Modified: trunk/source/lib/util.c
===================================================================
--- trunk/source/lib/util.c	2006-04-11 23:32:04 UTC (rev 15046)
+++ trunk/source/lib/util.c	2006-04-12 00:07:40 UTC (rev 15047)
@@ -5,7 +5,8 @@
    Copyright (C) Jeremy Allison 2001-2002
    Copyright (C) Simo Sorce 2001
    Copyright (C) Jim McDonough <jmcd at us.ibm.com> 2003
-   
+   Copyright (C) James Peach 2006
+
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
@@ -1616,13 +1617,76 @@
  exit shortly after calling it.
 ********************************************************************/
 
+#ifdef HAVE_LIBUNWIND_H
+#include <libunwind.h>
+#endif
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
 #ifdef HAVE_LIBEXC_H
 #include <libexc.h>
 #endif
 
 void log_stack_trace(void)
 {
-#ifdef HAVE_BACKTRACE_SYMBOLS
+#ifdef HAVE_LIBUNWIND
+	/* Try to use libunwind before any other technique since on ia64
+	 * libunwind correctly walks the stack in more circumstances than
+	 * backtrace.
+	 */ 
+	unw_cursor_t cursor;
+	unw_context_t uc;
+	unsigned i = 0;
+
+	char procname[256];
+	unw_word_t ip, sp, off;
+
+	procname[sizeof(procname) - 1] = '\0';
+
+	if (unw_getcontext(&uc) != 0) {
+		goto libunwind_failed;
+	}
+
+	if (unw_init_local(&cursor, &uc) != 0) {
+		goto libunwind_failed;
+	}
+
+	DEBUG(0, ("BACKTRACE:\n"));
+
+	do {
+	    ip = sp = 0;
+	    unw_get_reg(&cursor, UNW_REG_IP, &ip);
+	    unw_get_reg(&cursor, UNW_REG_SP, &sp);
+
+	    switch (unw_get_proc_name(&cursor,
+			procname, sizeof(procname) - 1, &off) ) {
+	    case 0:
+		    /* Name found. */
+	    case -UNW_ENOMEM:
+		    /* Name truncated. */
+		    DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
+			    i, procname, (long long)off,
+			    (long long)ip, (long long) sp));
+		    break;
+	    default:
+	    /* case -UNW_ENOINFO: */
+	    /* case -UNW_EUNSPEC: */
+		    /* No symbol name found. */
+		    DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
+			    i, "<unknown symbol>",
+			    (long long)ip, (long long) sp));
+	    }
+	    ++i;
+	} while (unw_step(&cursor) > 0);
+
+	return;
+
+libunwind_failed:
+	DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
+
+#elif HAVE_BACKTRACE_SYMBOLS
 	void *backtrace_stack[BACKTRACE_STACK_SIZE];
 	size_t backtrace_size;
 	char **backtrace_strings;
@@ -1649,39 +1713,38 @@
 	 * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
 	 * since we are about to abort anyway, it hardly matters.
 	 */
-	{
 
 #define NAMESIZE 32 /* Arbitrary */
 
-		__uint64_t	addrs[BACKTRACE_STACK_SIZE];
-		char *      	names[BACKTRACE_STACK_SIZE];
-		char		namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
+	__uint64_t	addrs[BACKTRACE_STACK_SIZE];
+	char *      	names[BACKTRACE_STACK_SIZE];
+	char		namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
 
-		int		i;
-		int		levels;
+	int		i;
+	int		levels;
 
-		ZERO_ARRAY(addrs);
-		ZERO_ARRAY(names);
-		ZERO_ARRAY(namebuf);
+	ZERO_ARRAY(addrs);
+	ZERO_ARRAY(names);
+	ZERO_ARRAY(namebuf);
 
-		/* We need to be root so we can open our /proc entry to walk
-		 * our stack. It also helps when we want to dump core.
-		 */
-		become_root();
+	/* We need to be root so we can open our /proc entry to walk
+	 * our stack. It also helps when we want to dump core.
+	 */
+	become_root();
 
-		for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
-			names[i] = namebuf + (i * NAMESIZE);
-		}
+	for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
+		names[i] = namebuf + (i * NAMESIZE);
+	}
 
-		levels = trace_back_stack(0, addrs, names,
-				BACKTRACE_STACK_SIZE, NAMESIZE - 1);
+	levels = trace_back_stack(0, addrs, names,
+			BACKTRACE_STACK_SIZE, NAMESIZE - 1);
 
-		DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
-		for (i = 0; i < levels; i++) {
-			DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
-		}
-     }
+	DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
+	for (i = 0; i < levels; i++) {
+		DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
+	}
 #undef NAMESIZE
+
 #else
 	DEBUG(0, ("unable to produce a stack trace on this platform\n"));
 #endif



More information about the samba-cvs mailing list