about summary refs log tree commit homepage
path: root/mwrap_core.h
diff options
context:
space:
mode:
Diffstat (limited to 'mwrap_core.h')
-rw-r--r--mwrap_core.h43
1 files changed, 20 insertions, 23 deletions
diff --git a/mwrap_core.h b/mwrap_core.h
index b2d0511..6d498c1 100644
--- a/mwrap_core.h
+++ b/mwrap_core.h
@@ -134,7 +134,7 @@ static void *my_mempcpy(void *dest, const void *src, size_t n)
   (uintptr_t)(__builtin_extract_return_addr(__builtin_return_address(nr)))
 
 /*
- * only for interpreted sources (Perl/Ruby/etc), not backtrace_symbols files
+ * only for interpreted sources (Perl/Ruby/etc), not backtrace_symbols* files
  */
 struct src_file {
         struct cds_lfht_node nd; /* <=> files table */
@@ -160,7 +160,7 @@ struct src_loc {
         struct src_file *f;
         /* .lineno only needs `unsigned', but is size_t for alignment */
         size_t lineno;
-        uintptr_t bt[];
+        void *bt[];
 };
 
 /*
@@ -400,7 +400,7 @@ update_stats_rcu_lock(size_t *generation, size_t size, uintptr_t caller)
                 k->total = size;
                 k->f = NULL;
                 k->lineno = 0;
-                k->bt[0] = caller;
+                k->bt[0] = (void *)caller;
                 k->bt_len = 1;
                 hash_src_loc(k);
                 ret = totals_add_rcu(k);
@@ -681,6 +681,18 @@ struct dump_arg {
         size_t min;
 };
 
+char **bt_syms(void * const *addrlist, uint32_t size)
+{
+        mwrap_assert(size < INT_MAX);
+#if defined(__GLIBC__)
+        char **s = backtrace_symbols(addrlist, size);
+#else /* make FreeBSD look like glibc output: */
+        char **s = backtrace_symbols_fmt(addrlist, size, "%f(%n%D) [%a]");
+#endif
+        if (!s) fprintf(stderr, "backtrace_symbols: %m\n");
+        return s;
+}
+
 static void *dump_to_file(struct dump_arg *a)
 {
         struct cds_lfht_iter iter;
@@ -697,15 +709,12 @@ static void *dump_to_file(struct dump_arg *a)
                 if (l->total <= a->min) continue;
 
                 if (loc_is_addr(l)) {
-                        char **s = backtrace_symbols((void **)l->bt, 1);
+                        char **s = bt_syms(l->bt, 1);
 
                         if (s) {
                                 fprintf(a->fp, "%16zu %12zu %s\n",
                                         l->total, l->allocations, s[0]);
                                 free(s);
-                        } else {
-                                fprintf(stderr, "backtrace_symbols: %s\n",
-                                        strerror(errno));
                         }
                 } else {
                         fprintf(a->fp, "%16zu %12zu %s:%zu\n",
@@ -718,14 +727,14 @@ out_unlock:
         return 0;
 }
 
-/* extract from backtrace_symbols(3) output */
+/* str = "/path/to/foo.so(+0x123) [0xdeadbeefcafe]" (see bt_syms()) */
 static int extract_addr(const char *str, size_t len, void **p)
 {
         unsigned long x;
         char *e;
-#if defined(__GLIBC__) /* str = "/path/to/foo.so(+0x123) [0xdeadbeefcafe]" */
         const char *end = str + len;
         const char *c = memrchr(str, '[', len);
+
         if (c && (c + 2) < end && c[1] == '0' && c[2] == 'x') {
                 errno = 0;
                 x = strtoul(c + 3, &e, 16);
@@ -734,18 +743,6 @@ static int extract_addr(const char *str, size_t len, void **p)
                         return 1;
                 }
         }
-#elif defined(__FreeBSD__) /* str = "0xdeadbeefcafe <%n%D> at %f" */
-        const char *c = memchr(str, ' ', len);
-        errno = 0;
-        if (len > 4 && c && str[0] == '0' && str[1] == 'x') {
-                errno = 0;
-                x = strtoul(str + 2, &e, 16);
-                if (!errno && *e == ' ') {
-                        *p = (void *)x;
-                        return 1;
-                }
-        }
-#endif
         return 0;
 }
 
@@ -890,11 +887,11 @@ static void mwrap_reset(void)
 static struct src_loc *mwrap_get(const char *str, size_t len)
 {
         struct src_loc *l = NULL;
-        uintptr_t p;
+        void *p;
 
         if (len >= PATH_MAX)
                 return l;
-        if (extract_addr(str, len, (void **)&p)) {
+        if (extract_addr(str, len, &p)) {
                 struct cds_lfht *t = CMM_LOAD_SHARED(totals);
                 struct src_loc *k;