mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-18 18:58:22 +00:00
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
This commit is contained in:
29
main/astmm.c
29
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();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user