diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index 48ce0721dd0c..86f6049c0f2e 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -84,6 +84,7 @@ #include #include #include +#include #include #include @@ -942,7 +943,7 @@ static void sig_handler(int signo) { struct sigaction action; - libspl_dump_backtrace(); + libspl_backtrace(); dump_debug_buffer(); /* diff --git a/cmd/ztest.c b/cmd/ztest.c index b4d53a59e1dd..651a9b838044 100644 --- a/cmd/ztest.c +++ b/cmd/ztest.c @@ -136,6 +136,7 @@ #include #include #include +#include static int ztest_fd_data = -1; static int ztest_fd_rand = -1; @@ -598,7 +599,7 @@ static void sig_handler(int signo) { struct sigaction action; - libspl_dump_backtrace(); + libspl_backtrace(); dump_debug_buffer(); /* diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am index 94be416d46aa..f8943572bf29 100644 --- a/lib/libspl/Makefile.am +++ b/lib/libspl/Makefile.am @@ -7,7 +7,8 @@ noinst_LTLIBRARIES += libspl_assert.la libspl.la CPPCHECKTARGETS += libspl_assert.la libspl.la libspl_assert_la_SOURCES = \ - %D%/assert.c + %D%/assert.c \ + %D%/backtrace.c libspl_la_SOURCES = \ %D%/libspl_impl.h \ diff --git a/lib/libspl/assert.c b/lib/libspl/assert.c index 79b640d89521..ff0d17ba2a5e 100644 --- a/lib/libspl/assert.c +++ b/lib/libspl/assert.c @@ -28,6 +28,7 @@ #include #include +#include #if defined(__linux__) #include @@ -51,58 +52,6 @@ pthread_getname_np(pthread_self(), buf, len); #endif -#if defined(HAVE_LIBUNWIND) -#define UNW_LOCAL_ONLY -#include - -void -libspl_dump_backtrace(void) -{ - unw_context_t uc; - unw_cursor_t cp; - unw_word_t ip, off; - char funcname[128]; -#ifdef HAVE_LIBUNWIND_ELF - char objname[128]; - unw_word_t objoff; -#endif - - fprintf(stderr, "Call trace:\n"); - unw_getcontext(&uc); - unw_init_local(&cp, &uc); - while (unw_step(&cp) > 0) { - unw_get_reg(&cp, UNW_REG_IP, &ip); - unw_get_proc_name(&cp, funcname, sizeof (funcname), &off); -#ifdef HAVE_LIBUNWIND_ELF - unw_get_elf_filename(&cp, objname, sizeof (objname), &objoff); - fprintf(stderr, " [0x%08lx] %s+0x%2lx (in %s +0x%2lx)\n", - ip, funcname, off, objname, objoff); -#else - fprintf(stderr, " [0x%08lx] %s+0x%2lx\n", ip, funcname, off); -#endif - } -} -#elif defined(HAVE_BACKTRACE) -#include - -void -libspl_dump_backtrace(void) -{ - void *btptrs[100]; - size_t nptrs = backtrace(btptrs, 100); - char **bt = backtrace_symbols(btptrs, nptrs); - fprintf(stderr, "Call trace:\n"); - for (size_t i = 0; i < nptrs; i++) - fprintf(stderr, " %s\n", bt[i]); - free(bt); -} -#else -void -libspl_dump_backtrace(void) -{ -} -#endif - #if defined(__APPLE__) static inline uint64_t libspl_gettid(void) @@ -154,7 +103,7 @@ libspl_assertf(const char *file, const char *func, int line, getpid(), libspl_getprogname(), libspl_gettid(), tname); - libspl_dump_backtrace(); + libspl_backtrace(); #if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__) if (libspl_assert_ok) { diff --git a/lib/libspl/backtrace.c b/lib/libspl/backtrace.c new file mode 100644 index 000000000000..0e653cd96434 --- /dev/null +++ b/lib/libspl/backtrace.c @@ -0,0 +1,80 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2024, Rob Norris + * Copyright (c) 2024, Klara Inc. + */ + +#include +#include + +#if defined(HAVE_LIBUNWIND) +#define UNW_LOCAL_ONLY +#include + +void +libspl_backtrace(void) +{ + unw_context_t uc; + unw_cursor_t cp; + unw_word_t ip, off; + char funcname[128]; +#ifdef HAVE_LIBUNWIND_ELF + char objname[128]; + unw_word_t objoff; +#endif + + fprintf(stderr, "Call trace:\n"); + unw_getcontext(&uc); + unw_init_local(&cp, &uc); + while (unw_step(&cp) > 0) { + unw_get_reg(&cp, UNW_REG_IP, &ip); + unw_get_proc_name(&cp, funcname, sizeof (funcname), &off); +#ifdef HAVE_LIBUNWIND_ELF + unw_get_elf_filename(&cp, objname, sizeof (objname), &objoff); + fprintf(stderr, " [0x%08lx] %s+0x%2lx (in %s +0x%2lx)\n", + ip, funcname, off, objname, objoff); +#else + fprintf(stderr, " [0x%08lx] %s+0x%2lx\n", ip, funcname, off); +#endif + } +} +#elif defined(HAVE_BACKTRACE) +#include + +void +libspl_backtrace(void) +{ + void *btptrs[100]; + size_t nptrs = backtrace(btptrs, 100); + char **bt = backtrace_symbols(btptrs, nptrs); + fprintf(stderr, "Call trace:\n"); + for (size_t i = 0; i < nptrs; i++) + fprintf(stderr, " %s\n", bt[i]); + free(bt); +} +#else +void +libspl_backtrace(void) +{ +} +#endif + diff --git a/lib/libspl/include/Makefile.am b/lib/libspl/include/Makefile.am index 2c1d21edf19d..4ad3b854cbee 100644 --- a/lib/libspl/include/Makefile.am +++ b/lib/libspl/include/Makefile.am @@ -27,6 +27,7 @@ libspl_sys_HEADERS = \ %D%/sys/acl.h \ %D%/sys/acl_impl.h \ %D%/sys/asm_linkage.h \ + %D%/sys/backtrace.h \ %D%/sys/callb.h \ %D%/sys/cmn_err.h \ %D%/sys/cred.h \ diff --git a/lib/libspl/include/assert.h b/lib/libspl/include/assert.h index 343ef853b1f3..57f5719c1ac1 100644 --- a/lib/libspl/include/assert.h +++ b/lib/libspl/include/assert.h @@ -60,8 +60,6 @@ libspl_assert(const char *buf, const char *file, const char *func, int line) return (0); } -extern void libspl_dump_backtrace(void); - #ifdef verify #undef verify #endif diff --git a/lib/libspl/include/sys/backtrace.h b/lib/libspl/include/sys/backtrace.h new file mode 100644 index 000000000000..97ee7740ce6f --- /dev/null +++ b/lib/libspl/include/sys/backtrace.h @@ -0,0 +1,32 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or https://opensource.org/licenses/CDDL-1.0. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2024, Rob Norris + * Copyright (c) 2024, Klara Inc. + */ + +#ifndef _LIBSPL_SYS_BACKTRACE_H +#define _LIBSPL_SYS_BACKTRACE_H + +void libspl_backtrace(void); + +#endif