diff options
author | Matthew Jordan <mjordan@digium.com> | 2013-06-08 22:09:07 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2013-06-08 22:09:07 +0000 |
commit | c43f380d036783ae10c426f23e8863ec1efdaa68 (patch) | |
tree | f4487b920b741d1e6a0d3195168a234935906ea1 /main/astmm.c | |
parent | 2fe6b6a5331e41b351774da0b66de40aa2f77ae7 (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.c | 29 |
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(); } } |