+static volatile int print_backtrace_len = DEFAULT_PRINT_BACKTRACE_LEN;
+
+/*
+ * Allocates a string, or NULL.
+ */
+static
+char *get_symbol(const void *caller)
+{
+ Dl_info info;
+ char *caller_symbol;
+
+ if (caller && dladdr(caller, &info) && info.dli_sname) {
+ caller_symbol = strdup(info.dli_sname);
+ } else {
+ caller_symbol = NULL;
+ }
+ return caller_symbol;
+}
+
+static inline __attribute__((always_inline))
+void save_backtrace(struct backtrace *bt)
+{
+ memset(bt, 0, sizeof(*bt));
+ (void) backtrace(bt->ptrs, BACKTRACE_LEN);
+ bt->symbols = backtrace_symbols(bt->ptrs, BACKTRACE_LEN);
+}
+
+static
+void free_backtrace(struct backtrace *bt)
+{
+ free(bt->symbols);
+}
+
+static
+void print_bt(struct backtrace *bt)
+{
+ int j;
+ unsigned int empty = 1;
+
+ for (j = 0; j < BACKTRACE_LEN; j++) {
+ if (bt->ptrs[j]) {
+ empty = 0;
+ break;
+ }
+ }
+ if (empty)
+ return;
+
+ err_printf("[backtrace]\n");
+ for (j = 0; j < BACKTRACE_LEN && j < print_backtrace_len; j++) {
+ if (!bt->ptrs[j])
+ continue;
+ if (bt->symbols)
+ err_printf(" %p <%s>\n", bt->ptrs[j], bt->symbols[j]);
+ else
+ err_printf(" %p\n", bt->ptrs[j]);
+ }
+}
+