Add backtrace to memory leak output
authorRichard Levitte <levitte@openssl.org>
Wed, 2 Dec 2015 12:19:45 +0000 (13:19 +0100)
committerRichard Levitte <levitte@openssl.org>
Wed, 2 Dec 2015 15:49:08 +0000 (16:49 +0100)
This is an option for builds with gcc and --strict-warnings.

Reviewed-by: Rich Salz <rsalz@openssl.org>
Configure
crypto/mem_dbg.c

index cd4f37f..6de3757 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -97,7 +97,7 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [experimenta
 # Minimum warning options... any contributions to OpenSSL should at least get
 # past these.
 
-my $gcc_devteam_warn = "-Wall -pedantic -DPEDANTIC -Wno-long-long -Wsign-compare -Wmissing-prototypes -Wshadow -Wformat -Wtype-limits -Werror -DCRYPTO_MDEBUG_ALL -DCRYPTO_MDEBUG_ABORT -DREF_CHECK -DDEBUG_UNUSED";
+my $gcc_devteam_warn = "-Wall -pedantic -DPEDANTIC -Wno-long-long -Wsign-compare -Wmissing-prototypes -Wshadow -Wformat -Wtype-limits -Werror -rdynamic -DCRYPTO_MDEBUG_ALL -DCRYPTO_MDEBUG_ABORT -DCRYPTO_MDEBUG_BACKTRACE -DREF_CHECK -DDEBUG_UNUSED";
 
 # These are used in addition to $gcc_devteam_warn when the compiler is clang.
 # TODO(openssl-team): fix problems and investigate if (at least) the
index c19847e..c2fe8af 100644 (file)
 #include <openssl/buffer.h>
 #include <openssl/bio.h>
 #include <openssl/lhash.h>
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+# include <execinfo.h>
+#endif
 
 static int mh_mode = CRYPTO_MEM_CHECK_OFF;
 /*
@@ -175,6 +178,10 @@ typedef struct mem_st
     unsigned long order;
     time_t time;
     APP_INFO *app_info;
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+    void *array[30];
+    size_t array_siz;
+#endif
 } MEM;
 
 static long options =           /* extra information to be recorded */
@@ -515,6 +522,9 @@ void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
                 m->time = time(NULL);
             else
                 m->time = 0;
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+            m->array_siz = backtrace(m->array, OSSL_NELEM(m->array));
+#endif
 
             CRYPTO_THREADID_current(&tmp.threadid);
             m->app_info = NULL;
@@ -608,6 +618,9 @@ void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
 #endif
                 mp->addr = addr2;
                 mp->num = num;
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+                mp->array_siz = backtrace(mp->array, OSSL_NELEM(mp->array));
+#endif
                 (void)lh_MEM_insert(mh, mp);
             }
 
@@ -672,36 +685,36 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
 
     amip = m->app_info;
     ami_cnt = 0;
-    if (!amip)
-        return;
-    CRYPTO_THREADID_cpy(&ti, &amip->threadid);
-
-    do {
-        int buf_len;
-        int info_len;
-
-        ami_cnt++;
-        memset(buf, '>', ami_cnt);
-        BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
-                     " thread=%lu, file=%s, line=%d, info=\"",
-                     CRYPTO_THREADID_hash(&amip->threadid), amip->file,
-                     amip->line);
-        buf_len = strlen(buf);
-        info_len = strlen(amip->info);
-        if (128 - buf_len - 3 < info_len) {
-            memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
-            buf_len = 128 - 3;
-        } else {
-            BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
+    if (amip) {
+        CRYPTO_THREADID_cpy(&ti, &amip->threadid);
+
+        do {
+            int buf_len;
+            int info_len;
+
+            ami_cnt++;
+            memset(buf, '>', ami_cnt);
+            BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
+                         " thread=%lu, file=%s, line=%d, info=\"",
+                         CRYPTO_THREADID_hash(&amip->threadid), amip->file,
+                         amip->line);
             buf_len = strlen(buf);
-        }
-        BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
+            info_len = strlen(amip->info);
+            if (128 - buf_len - 3 < info_len) {
+                memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
+                buf_len = 128 - 3;
+            } else {
+                BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
+                buf_len = strlen(buf);
+            }
+            BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
 
-        BIO_puts(l->bio, buf);
+            BIO_puts(l->bio, buf);
 
-        amip = amip->next;
+            amip = amip->next;
+        }
+        while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
     }
-    while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
 
 #ifdef LEVITTE_DEBUG_MEM
     if (amip) {
@@ -709,6 +722,16 @@ static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
         abort();
     }
 #endif
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+    {
+        size_t i;
+        char **strings = backtrace_symbols(m->array, m->array_siz);
+        for (i = 0; i < m->array_siz; i++)
+            fprintf(stderr, "##> %s\n", strings[i]);
+
+        free(strings);
+    }
+#endif
 }
 
 static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)