summaryrefslogtreecommitdiff
path: root/main/astmm.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-06-08 22:09:07 +0000
committerMatthew Jordan <mjordan@digium.com>2013-06-08 22:09:07 +0000
commitc43f380d036783ae10c426f23e8863ec1efdaa68 (patch)
treef4487b920b741d1e6a0d3195168a234935906ea1 /main/astmm.c
parent2fe6b6a5331e41b351774da0b66de40aa2f77ae7 (diff)
Add backtrace generation to MALLOC_DEBUG memory corruption reports
This patch allows astmm to access the backtrace generation code in Asterisk. When memory is allocated, a backtrace is created and stored with the memory region that tracks the allocation. If a memory corruption is detected, the backtrace is printed to the astmm log. The backtrace will make use of the BETTER_BACKTRACES build option if available. As a result, this patch moves the backtrace generation code into its own file and uses the non-wrapped versions of the C library memory allocation routines. This allows the memory allocation code to safely use the backtrace generation routines without infinitely recursing. Review: https://reviewboard.asterisk.org/r/2567 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@391012 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/astmm.c')
-rw-r--r--main/astmm.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/main/astmm.c b/main/astmm.c
index 9396d0987..d01b745b0 100644
--- a/main/astmm.c
+++ b/main/astmm.c
@@ -42,6 +42,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/strings.h"
#include "asterisk/unaligned.h"
+#include "asterisk/backtrace.h"
/*!
* The larger the number the faster memory can be freed.
@@ -78,13 +79,13 @@ static FILE *mmlog;
struct ast_region {
AST_LIST_ENTRY(ast_region) node;
+ struct ast_bt *bt;
size_t len;
unsigned int cache; /* region was allocated as part of a cache pool */
unsigned int lineno;
enum func_type which;
char file[64];
char func[40];
-
/*!
* \brief Lower guard fence.
*
@@ -157,6 +158,25 @@ AST_MUTEX_DEFINE_STATIC_NOTRACKING(reglock);
} \
} while (0)
+static void print_backtrace(struct ast_bt *bt)
+{
+ int i = 0;
+ char **strings;
+
+ if (!bt) {
+ return;
+ }
+
+ if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
+ astmm_log("Memory allocation backtrace:\n");
+ for (i = 3; i < bt->num_frames - 2; i++) {
+ astmm_log("#%d: [%p] %s\n", i - 3, bt->addresses[i], strings[i]);
+ }
+ free(strings);
+ }
+}
+
+
/*!
* \internal
*
@@ -191,6 +211,7 @@ static void *__ast_alloc_region(size_t size, const enum func_type which, const c
reg->cache = cache;
reg->lineno = lineno;
reg->which = which;
+ reg->bt = ast_bt_create();
ast_copy_string(reg->file, file, sizeof(reg->file));
ast_copy_string(reg->func, func, sizeof(reg->func));
@@ -262,6 +283,7 @@ static void region_data_check(struct ast_region *reg)
if (*pos != FREED_MAGIC) {
astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
reg->data, reg->file, reg->func, reg->lineno);
+ print_backtrace(reg->bt);
my_do_crash();
break;
}
@@ -321,6 +343,9 @@ static void region_free(struct ast_freed_regions *freed, struct ast_region *reg)
if (old) {
region_data_check(old);
+ if (old->bt) {
+ old->bt = ast_bt_destroy(old->bt);
+ }
free(old);
}
}
@@ -380,12 +405,14 @@ static void region_check_fences(struct ast_region *reg)
if (*fence != FENCE_MAGIC) {
astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
reg->data, reg->file, reg->func, reg->lineno);
+ print_backtrace(reg->bt);
my_do_crash();
}
fence = (unsigned int *) (reg->data + reg->len);
if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n",
reg->data, reg->file, reg->func, reg->lineno);
+ print_backtrace(reg->bt);
my_do_crash();
}
}