31 #define ASTMM_LIBC ASTMM_IGNORE
45 #ifndef DEBUG_CHAOS_ALLOC_CHANCE
46 #define DEBUG_CHAOS_ALLOC_CHANCE 100000
49 #ifndef DEBUG_CHAOS_ENABLE
50 #define DEBUG_CHAOS_ENABLE 1
52 #define DEBUG_CHAOS_RETURN(CHANCE, FAILURE) \
54 if ((DEBUG_CHAOS_ENABLE) && (ast_random() % CHANCE == 0)) { \
59 #define DEBUG_CHAOS_RETURN(c,f)
62 #if defined(STANDALONE) || defined(STANDALONE2)
63 #define ast_log_safe ast_log
66 #if defined(MALLOC_DEBUG) && !defined(STANDALONE) && !defined(STANDALONE2)
67 #define __AST_DEBUG_MALLOC
70 #define MALLOC_FAILURE_MSG \
71 ast_log_safe(LOG_ERROR, "Memory Allocation Failure in function %s at line %d of %s\n", func, lineno, file)
73 #if defined(__AST_DEBUG_MALLOC)
90 #define SOME_PRIME 1567
102 #define FENCE_MAGIC 0xfeedbabe
103 #define FREED_MAGIC 0xdeaddead
104 #define MALLOC_FILLER 0x55
114 enum func_type which;
134 unsigned char data[0] __attribute__((aligned));
138 static struct ast_region *regions[SOME_PRIME];
141 #define FREED_MAX_COUNT 1500
144 #define MINNOWS_MAX_SIZE 50
146 struct ast_freed_regions {
148 struct ast_region *regions[FREED_MAX_COUNT];
154 static struct ast_freed_regions whales;
156 static struct ast_freed_regions minnows;
162 SUMMARY_BY_LINE = (1 << 0),
164 SUMMARY_BY_FUNC = (1 << 1),
166 SUMMARY_BY_FILE = (1 << 2),
170 static enum summary_opts atexit_summary;
172 static int atexit_list;
174 static int backtrace_enabled;
176 #define HASH(a) (((unsigned long)(a)) % ARRAY_LEN(regions))
180 AST_MUTEX_DEFINE_STATIC_NOTRACKING(reglock);
182 #define astmm_log(...) \
184 fprintf(stderr, __VA_ARGS__); \
186 fprintf(mmlog, __VA_ARGS__); \
202 ast_cli(a->fd,
"Memory allocation backtrace:\n");
204 astmm_log(
"Memory allocation backtrace:\n");
213 ast_bt_free_symbols(strings);
222 static void my_do_crash(
void)
233 static void *__ast_alloc_region(
size_t size,
const enum func_type which,
const char *file,
int lineno,
const char *func,
unsigned int cache)
235 struct ast_region *reg;
241 if (!(reg = malloc(size +
sizeof(*reg) +
sizeof(*fence)))) {
242 astmm_log(
"Memory Allocation Failure - '%d' bytes at %s %s() line %d\n",
243 (
int) size, file, func, lineno);
249 reg->lineno = lineno;
251 reg->bt = backtrace_enabled ? ast_bt_create() : NULL;
262 fence = (
unsigned int *) (reg->data -
sizeof(*fence));
263 *fence = FENCE_MAGIC;
266 fence = (
unsigned int *) (reg->data + reg->len);
267 put_unaligned_uint32(fence, FENCE_MAGIC);
269 hash = HASH(reg->data);
270 ast_mutex_lock(®lock);
273 ast_mutex_unlock(®lock);
284 static void region_data_wipe(
struct ast_region *reg)
293 end = reg->data + reg->len;
294 for (pos = ®->fence; (
void *) pos <= end; ++pos) {
305 static void region_data_check(
struct ast_region *reg)
314 end = reg->data + reg->len;
315 for (pos = ®->fence; (
void *) pos <= end; ++pos) {
316 if (*pos != FREED_MAGIC) {
317 astmm_log(
"WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
318 reg->data, reg->file, reg->func, reg->lineno);
319 print_backtrace(reg->bt, NULL);
332 static void freed_regions_flush(
struct ast_freed_regions *freed)
335 struct ast_region *old;
337 ast_mutex_lock(®lock);
338 for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
339 old = freed->regions[idx];
340 freed->regions[idx] = NULL;
342 region_data_check(old);
347 ast_mutex_unlock(®lock);
357 static void region_free(
struct ast_freed_regions *freed,
struct ast_region *reg)
359 struct ast_region *old;
361 region_data_wipe(reg);
363 ast_mutex_lock(®lock);
364 old = freed->regions[freed->index];
365 freed->regions[freed->index] = reg;
368 if (ARRAY_LEN(freed->regions) <= freed->index) {
371 ast_mutex_unlock(®lock);
374 region_data_check(old);
375 old->bt = ast_bt_destroy(old->bt);
389 static struct ast_region *region_remove(
void *ptr)
392 struct ast_region *reg;
393 struct ast_region *prev = NULL;
397 ast_mutex_lock(®lock);
398 for (reg = regions[hash]; reg; reg =
AST_LIST_NEXT(reg, node)) {
399 if (reg->data == ptr) {
409 ast_mutex_unlock(®lock);
420 static void region_check_fences(
struct ast_region *reg)
429 fence = (
unsigned int *) (reg->data -
sizeof(*fence));
430 if (*fence != FENCE_MAGIC) {
431 astmm_log(
"WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
432 reg->data, reg->file, reg->func, reg->lineno);
433 print_backtrace(reg->bt, NULL);
436 fence = (
unsigned int *) (reg->data + reg->len);
437 if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
438 astmm_log(
"WARNING: High fence violation of %p allocated at %s %s() line %d\n",
439 reg->data, reg->file, reg->func, reg->lineno);
440 print_backtrace(reg->bt, NULL);
449 static void regions_check_all_fences(
void)
452 struct ast_region *reg;
454 ast_mutex_lock(®lock);
455 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
456 for (reg = regions[idx]; reg; reg =
AST_LIST_NEXT(reg, node)) {
457 region_check_fences(reg);
460 ast_mutex_unlock(®lock);
463 void __ast_free(
void *ptr,
const char *file,
int lineno,
const char *func)
465 struct ast_region *reg;
471 reg = region_remove(ptr);
473 region_check_fences(reg);
475 if (reg->len <= MINNOWS_MAX_SIZE) {
476 region_free(&minnows, reg);
478 region_free(&whales, reg);
486 astmm_log(
"WARNING: Freeing unregistered memory %p by %s %s() line %d\n",
487 ptr, file, func, lineno);
492 void *__ast_repl_calloc(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
496 ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 0);
498 memset(ptr, 0, size * nmemb);
504 static void *__ast_repl_calloc_cache(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
508 ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1);
510 memset(ptr, 0, size * nmemb);
516 void *__ast_repl_malloc(
size_t size,
const char *file,
int lineno,
const char *func)
520 ptr = __ast_alloc_region(size, FUNC_MALLOC, file, lineno, func, 0);
523 memset(ptr, MALLOC_FILLER, size);
532 static struct ast_region *region_find(
void *ptr)
535 struct ast_region *reg;
538 for (reg = regions[hash]; reg; reg =
AST_LIST_NEXT(reg, node)) {
539 if (reg->data == ptr) {
547 void *__ast_repl_realloc(
void *ptr,
size_t size,
const char *file,
int lineno,
const char *func)
550 struct ast_region *found;
554 ast_mutex_lock(®lock);
555 found = region_find(ptr);
557 ast_mutex_unlock(®lock);
558 astmm_log(
"WARNING: Realloc of unregistered memory %p by %s %s() line %d\n",
559 ptr, file, func, lineno);
564 ast_mutex_unlock(®lock);
571 __ast_free(ptr, file, lineno, func);
575 new_mem = __ast_alloc_region(size, FUNC_REALLOC, file, lineno, func, 0);
580 memcpy(new_mem, ptr, size);
582 memcpy(new_mem, ptr, len);
584 memset(new_mem + len, MALLOC_FILLER, size - len);
586 __ast_free(ptr, file, lineno, func);
589 memset(new_mem, MALLOC_FILLER, size);
596 char *__ast_repl_strdup(
const char *s,
const char *file,
int lineno,
const char *func)
602 if ((ptr = __ast_alloc_region(len, FUNC_STRDUP, file, lineno, func, 0))) {
609 char *__ast_repl_strndup(
const char *s,
size_t n,
const char *file,
int lineno,
const char *func)
615 if ((ptr = __ast_alloc_region(len + 1, FUNC_STRNDUP, file, lineno, func, 0))) {
623 int __ast_repl_asprintf(
const char *file,
int lineno,
const char *func,
char **strp,
const char *fmt, ...)
632 size = vsnprintf(&s, 1, fmt, ap2);
634 ptr = __ast_alloc_region(size + 1, FUNC_ASPRINTF, file, lineno, func, 0);
640 vsnprintf(ptr, size + 1, fmt, ap);
647 int __ast_repl_vasprintf(
char **strp,
const char *fmt, va_list ap,
const char *file,
int lineno,
const char *func)
655 size = vsnprintf(&s, 1, fmt, ap2);
657 ptr = __ast_alloc_region(size + 1, FUNC_VASPRINTF, file, lineno, func, 0);
662 vsnprintf(ptr, size + 1, fmt, ap);
678 static size_t freed_regions_size(
struct ast_freed_regions *freed)
680 size_t total_len = 0;
682 struct ast_region *old;
684 for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) {
685 old = freed->regions[idx];
687 total_len += old->len;
698 e->
command =
"memory atexit list {on|off}";
700 "Usage: memory atexit list {on|off}\n"
701 " Enable dumping a list of still allocated memory segments at exit.\n";
708 return CLI_SHOWUSAGE;
716 return CLI_SHOWUSAGE;
719 ast_cli(a->fd,
"The atexit list is: %s\n", atexit_list ?
"On" :
"Off");
730 e->
command =
"memory atexit summary {off|byline|byfunc|byfile}";
732 "Usage: memory atexit summary {off|byline|byfunc|byfile}\n"
733 " Summary of still allocated memory segments at exit options.\n"
734 " off - Disable at exit summary.\n"
735 " byline - Enable at exit summary by file line number.\n"
736 " byfunc - Enable at exit summary by function name.\n"
737 " byfile - Enable at exit summary by file.\n"
739 " Note: byline, byfunc, and byfile are cumulative enables.\n";
746 return CLI_SHOWUSAGE;
750 atexit_summary = SUMMARY_OFF;
751 }
else if (!strcasecmp(a->argv[3],
"byline")) {
752 atexit_summary |= SUMMARY_BY_LINE;
753 }
else if (!strcasecmp(a->argv[3],
"byfunc")) {
754 atexit_summary |= SUMMARY_BY_FUNC;
755 }
else if (!strcasecmp(a->argv[3],
"byfile")) {
756 atexit_summary |= SUMMARY_BY_FILE;
758 return CLI_SHOWUSAGE;
761 if (atexit_summary) {
763 if (atexit_summary & SUMMARY_BY_LINE) {
764 strcat(buf,
"byline");
766 if (atexit_summary & SUMMARY_BY_FUNC) {
770 strcat(buf,
"byfunc");
772 if (atexit_summary & SUMMARY_BY_FILE) {
776 strcat(buf,
"byfile");
781 ast_cli(a->fd,
"The atexit summary is: %s\n", buf);
798 static void print_memory_show_common_stats(
int fd,
799 unsigned int whales_len,
800 unsigned int minnows_len,
801 unsigned int total_len,
802 unsigned int selected_len,
803 unsigned int cache_len,
807 ast_cli(fd,
"%10u bytes allocated (%u in caches) in %u selected allocations\n\n",
808 selected_len, cache_len, count);
810 ast_cli(fd,
"%10u bytes allocated in %u selected allocations\n\n",
811 selected_len, count);
814 ast_cli(fd,
"%10u bytes in all allocations\n", total_len);
815 ast_cli(fd,
"%10u bytes in deferred free large allocations\n", whales_len);
816 ast_cli(fd,
"%10u bytes in deferred free small allocations\n", minnows_len);
817 ast_cli(fd,
"%10u bytes in deferred free allocations\n",
818 whales_len + minnows_len);
819 ast_cli(fd,
"%10u bytes in all allocations and deferred free allocations\n",
820 total_len + whales_len + minnows_len);
825 const char *fn = NULL;
826 struct ast_region *reg;
828 unsigned int whales_len;
829 unsigned int minnows_len;
830 unsigned int total_len = 0;
831 unsigned int selected_len = 0;
832 unsigned int cache_len = 0;
833 unsigned int count = 0;
837 e->
command =
"memory show allocations";
839 "Usage: memory show allocations [<file>|anomalies]\n"
840 " Dumps a list of segments of allocated memory.\n"
841 " Defaults to listing all memory allocations.\n"
842 " <file> - Restricts output to memory allocated by the file.\n"
843 " anomalies - Only check for fence violations.\n";
851 }
else if (a->argc != 3) {
852 return CLI_SHOWUSAGE;
856 if (fn && (!strcasecmp(fn,
"anomalies") || !strcasecmp(fn,
"anomolies"))) {
857 regions_check_all_fences();
858 ast_cli(a->fd,
"Anomaly check complete.\n");
862 ast_mutex_lock(®lock);
863 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
864 for (reg = regions[idx]; reg; reg =
AST_LIST_NEXT(reg, node)) {
865 total_len += reg->len;
866 if (fn && strcasecmp(fn, reg->file)) {
870 region_check_fences(reg);
872 ast_cli(a->fd,
"%10u bytes allocated%s by %20s() line %5u of %s\n",
873 (
unsigned int) reg->len, reg->cache ?
" (cache)" :
"",
874 reg->func, reg->lineno, reg->file);
875 if (reg->bt && !ast_strlen_zero(fn)) {
876 print_backtrace(reg->bt, a);
879 selected_len += reg->len;
881 cache_len += reg->len;
887 whales_len = freed_regions_size(&whales);
888 minnows_len = freed_regions_size(&minnows);
889 ast_mutex_unlock(®lock);
891 print_memory_show_common_stats(a->fd,
892 whales_len, minnows_len, total_len,
893 selected_len, cache_len, count);
900 #define my_max(a, b) ((a) >= (b) ? (a) : (b))
902 const char *fn = NULL;
905 struct ast_region *reg;
906 unsigned int whales_len;
907 unsigned int minnows_len;
908 unsigned int total_len = 0;
909 unsigned int selected_len = 0;
910 unsigned int cache_len = 0;
911 unsigned int count = 0;
912 struct file_summary {
913 struct file_summary *next;
915 unsigned int cache_len;
918 char name[my_max(
sizeof(reg->file),
sizeof(reg->func))];
919 } *list = NULL, *cur, **prev;
923 e->
command =
"memory show summary";
925 "Usage: memory show summary [<file>]\n"
926 " Summarizes heap memory allocations by file, or optionally\n"
927 " by line if a file is specified.\n";
935 }
else if (a->argc != 3) {
936 return CLI_SHOWUSAGE;
939 ast_mutex_lock(®lock);
940 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
941 for (reg = regions[idx]; reg; reg =
AST_LIST_NEXT(reg, node)) {
942 total_len += reg->len;
944 if (strcasecmp(fn, reg->file)) {
949 for (prev = &list; (cur = *prev); prev = &cur->next) {
950 cmp = strcmp(cur->name, reg->func);
959 cmp = cur->lineno - reg->lineno;
971 for (prev = &list; (cur = *prev); prev = &cur->next) {
972 cmp = strcmp(cur->name, reg->file);
986 memset(cur, 0,
sizeof(*cur));
987 cur->lineno = reg->lineno;
988 ast_copy_string(cur->name, fn ? reg->func : reg->file,
sizeof(cur->name));
994 cur->len += reg->len;
996 cur->cache_len += reg->len;
1002 whales_len = freed_regions_size(&whales);
1003 minnows_len = freed_regions_size(&minnows);
1004 ast_mutex_unlock(®lock);
1007 for (cur = list; cur; cur = cur->next) {
1008 selected_len += cur->len;
1009 cache_len += cur->cache_len;
1010 count += cur->count;
1011 if (cur->cache_len) {
1013 ast_cli(a->fd,
"%10u bytes (%10u cache) in %10u allocations by %20s() line %5u of %s\n",
1014 cur->len, cur->cache_len, cur->count, cur->name, cur->lineno, fn);
1016 ast_cli(a->fd,
"%10u bytes (%10u cache) in %10u allocations in file %s\n",
1017 cur->len, cur->cache_len, cur->count, cur->name);
1021 ast_cli(a->fd,
"%10u bytes in %10u allocations by %20s() line %5u of %s\n",
1022 cur->len, cur->count, cur->name, cur->lineno, fn);
1024 ast_cli(a->fd,
"%10u bytes in %10u allocations in file %s\n",
1025 cur->len, cur->count, cur->name);
1030 print_memory_show_common_stats(a->fd,
1031 whales_len, minnows_len, total_len,
1032 selected_len, cache_len, count);
1041 e->
command =
"memory backtrace {on|off}";
1043 "Usage: memory backtrace {on|off}\n"
1044 " Enable dumping an allocation backtrace with memory diagnostics.\n"
1045 " Note that saving the backtrace data for each allocation\n"
1046 " can be CPU intensive.\n";
1053 return CLI_SHOWUSAGE;
1057 backtrace_enabled = 1;
1059 backtrace_enabled = 0;
1061 return CLI_SHOWUSAGE;
1064 ast_cli(a->fd,
"The memory backtrace is: %s\n", backtrace_enabled ?
"On" :
"Off");
1070 AST_CLI_DEFINE(handle_memory_atexit_list,
"Enable memory allocations not freed at exit list."),
1071 AST_CLI_DEFINE(handle_memory_atexit_summary,
"Enable memory allocations not freed at exit summary."),
1072 AST_CLI_DEFINE(handle_memory_show_allocations,
"Display outstanding memory allocations"),
1073 AST_CLI_DEFINE(handle_memory_show_summary,
"Summarize outstanding memory allocations"),
1074 AST_CLI_DEFINE(handle_memory_backtrace,
"Enable dumping an allocation backtrace with memory diagnostics."),
1095 static size_t mm_atexit_hash_list(
struct region_list *
list)
1097 struct ast_region *reg;
1098 size_t total_length;
1102 for (idx = 0; idx < ARRAY_LEN(regions); ++idx) {
1103 while ((reg = regions[idx])) {
1110 return total_length;
1121 static void mm_atexit_hash_restore(
struct region_list *list)
1123 struct ast_region *reg;
1127 hash = HASH(reg->data);
1129 regions[hash] = reg;
1144 static int mm_atexit_cmp(
struct ast_region *left,
struct ast_region *right)
1151 cmp = strcmp(left->file, right->file);
1157 cmp = left->lineno - right->lineno;
1163 cmp_size = left->len - right->len;
1172 cmp_ptr = left->data - right->data;
1191 static void mm_atexit_list_merge(
struct region_list *list,
struct region_list *sub1,
struct region_list *sub2)
1193 struct ast_region *reg;
1226 static void mm_atexit_list_split(
struct region_list *list,
struct region_list sub[],
size_t num_lists,
size_t size,
size_t *remaining)
1230 for (idx = 0; idx < num_lists; ++idx) {
1233 if (*remaining < size) {
1242 for (count = size; count--;) {
1243 struct ast_region *reg;
1258 static void mm_atexit_list_sort(
struct region_list *list,
size_t length)
1263 struct region_list sub[2] = {
1279 mm_atexit_list_split(list, sub, ARRAY_LEN(sub), size, &remaining);
1280 mm_atexit_list_merge(&merged, &sub[0], &sub[1]);
1300 static void mm_atexit_regions_list(
struct region_list *alloced)
1302 struct ast_region *reg;
1305 astmm_log(
"%s %s() line %u: %u bytes%s at %p\n",
1306 reg->file, reg->func, reg->lineno,
1307 (
unsigned int) reg->len, reg->cache ?
" (cache)" :
"", reg->data);
1317 static void mm_atexit_regions_summary(
struct region_list *alloced)
1319 struct ast_region *reg;
1320 struct ast_region *next;
1324 unsigned int cache_len;
1325 } by_line, by_func, by_file, total;
1329 by_line.cache_len = 0;
1333 by_func.cache_len = 0;
1337 by_file.cache_len = 0;
1341 total.cache_len = 0;
1347 by_line.len += reg->len;
1349 by_line.cache_len += reg->len;
1351 if (next && !strcmp(reg->file, next->file) && reg->lineno == next->lineno) {
1354 if (atexit_summary & SUMMARY_BY_LINE) {
1355 if (by_line.cache_len) {
1356 astmm_log(
"%10u bytes (%u in caches) in %u allocations. %s %s() line %u\n",
1357 by_line.len, by_line.cache_len, by_line.count, reg->file, reg->func, reg->lineno);
1359 astmm_log(
"%10u bytes in %5u allocations. %s %s() line %u\n",
1360 by_line.len, by_line.count, reg->file, reg->func, reg->lineno);
1364 by_func.count += by_line.count;
1365 by_func.len += by_line.len;
1366 by_func.cache_len += by_line.cache_len;
1369 by_line.cache_len = 0;
1370 if (next && !strcmp(reg->file, next->file) && !strcmp(reg->func, next->func)) {
1373 if (atexit_summary & SUMMARY_BY_FUNC) {
1374 if (by_func.cache_len) {
1375 astmm_log(
"%10u bytes (%u in caches) in %u allocations. %s %s()\n",
1376 by_func.len, by_func.cache_len, by_func.count, reg->file, reg->func);
1378 astmm_log(
"%10u bytes in %5u allocations. %s %s()\n",
1379 by_func.len, by_func.count, reg->file, reg->func);
1383 by_file.count += by_func.count;
1384 by_file.len += by_func.len;
1385 by_file.cache_len += by_func.cache_len;
1388 by_func.cache_len = 0;
1389 if (next && !strcmp(reg->file, next->file)) {
1392 if (atexit_summary & SUMMARY_BY_FILE) {
1393 if (by_file.cache_len) {
1394 astmm_log(
"%10u bytes (%u in caches) in %u allocations. %s\n",
1395 by_file.len, by_file.cache_len, by_file.count, reg->file);
1397 astmm_log(
"%10u bytes in %5u allocations. %s\n",
1398 by_file.len, by_file.count, reg->file);
1402 total.count += by_file.count;
1403 total.len += by_file.len;
1404 total.cache_len += by_file.cache_len;
1407 by_file.cache_len = 0;
1410 if (total.cache_len) {
1411 astmm_log(
"%u bytes (%u in caches) in %u allocations.\n",
1412 total.len, total.cache_len, total.count);
1414 astmm_log(
"%u bytes in %u allocations.\n", total.len, total.count);
1424 static void mm_atexit_dump(
void)
1429 length = mm_atexit_hash_list(&alloced_atexit);
1432 astmm_log(
"Exiting with all memory freed.\n");
1436 mm_atexit_list_sort(&alloced_atexit, length);
1438 astmm_log(
"Exiting with the following memory not freed:\n");
1440 mm_atexit_regions_list(&alloced_atexit);
1442 if (atexit_summary) {
1443 mm_atexit_regions_summary(&alloced_atexit);
1452 mm_atexit_hash_restore(&alloced_atexit);
1458 static void mm_atexit_final(
void)
1463 if (atexit_list || atexit_summary) {
1464 fprintf(stderr,
"Waiting 10 seconds to let other threads die.\n");
1468 regions_check_all_fences();
1471 freed_regions_flush(&whales);
1472 freed_regions_flush(&minnows);
1475 if (atexit_list || atexit_summary) {
1476 ast_mutex_lock(®lock);
1478 ast_mutex_unlock(®lock);
1491 atexit(mm_atexit_final);
1497 static void mm_atexit_ast(
void)
1504 char filename[PATH_MAX];
1508 snprintf(filename,
sizeof(filename),
"%s/mmlog", ast_config_AST_LOG_DIR);
1510 ast_verb(1,
"Asterisk Malloc Debugger Started (see %s))\n", filename);
1512 mmlog = fopen(filename,
"a+");
1514 fprintf(mmlog,
"%ld - New session\n", (
long) time(NULL));
1517 ast_log(LOG_ERROR,
"Could not open malloc debug log file: %s\n", filename);
1533 void *__ast_repl_calloc(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
1537 return calloc(nmemb, size);
1540 static void *__ast_repl_calloc_cache(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
1544 return calloc(nmemb, size);
1547 void *__ast_repl_malloc(
size_t size,
const char *file,
int lineno,
const char *func)
1551 return malloc(size);
1554 void __ast_free(
void *ptr,
const char *file,
int lineno,
const char *func)
1559 void *__ast_repl_realloc(
void *ptr,
size_t size,
const char *file,
int lineno,
const char *func)
1563 return realloc(ptr, size);
1566 char *__ast_repl_strdup(
const char *s,
const char *file,
int lineno,
const char *func)
1573 char *__ast_repl_strndup(
const char *s,
size_t n,
const char *file,
int lineno,
const char *func)
1577 return strndup(s, n);
1580 int __ast_repl_asprintf(
const char *file,
int lineno,
const char *func,
char **strp,
const char *format, ...)
1587 va_start(ap, format);
1588 res = vasprintf(strp, format, ap);
1594 int __ast_repl_vasprintf(
char **strp,
const char *format, va_list ap,
const char *file,
int lineno,
const char *func)
1598 return vasprintf(strp, format, ap);
1603 void *__ast_calloc(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
1607 p = __ast_repl_calloc(nmemb, size, file, lineno, func);
1615 void *__ast_calloc_cache(
size_t nmemb,
size_t size,
const char *file,
int lineno,
const char *func)
1619 p = __ast_repl_calloc_cache(nmemb, size, file, lineno, func);
1628 void *__ast_malloc(
size_t size,
const char *file,
int lineno,
const char *func)
1632 p = __ast_repl_malloc(size, file, lineno, func);
1640 void *__ast_realloc(
void *ptr,
size_t size,
const char *file,
int lineno,
const char *func)
1644 newp = __ast_repl_realloc(ptr, size, file, lineno, func);
1652 char *__ast_strdup(
const char *s,
const char *file,
int lineno,
const char *func)
1654 char *newstr = NULL;
1657 newstr = __ast_repl_strdup(s, file, lineno, func);
1666 char *__ast_strndup(
const char *s,
size_t n,
const char *file,
int lineno,
const char *func)
1668 char *newstr = NULL;
1671 newstr = __ast_repl_strndup(s, n, file, lineno, func);
1680 int __ast_asprintf(
const char *file,
int lineno,
const char *func,
char **strp,
const char *format, ...)
1685 va_start(ap, format);
1686 res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
1701 int __ast_vasprintf(
char **strp,
const char *format, va_list ap,
const char *file,
int lineno,
const char *func)
1705 res = __ast_repl_vasprintf(strp, format, ap, file, lineno, func);
1719 void *ast_std_malloc(
size_t size)
1721 return malloc(size);
1724 void *ast_std_calloc(
size_t nmemb,
size_t size)
1726 return calloc(nmemb, size);
1729 void *ast_std_realloc(
void *ptr,
size_t size)
1731 return realloc(ptr, size);
1734 void ast_std_free(
void *ptr)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
void load_astmm_phase_2(void)
Initialize malloc debug phase 2.
Asterisk backtrace generation.
String manipulation functions.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Time-related functions and macros.
descriptor for a cli entry.
struct ast_cli_entry::@210 list
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
void ast_free_ptr(void *ptr)
free() wrapper
Handle unaligned data access.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Asterisk file paths, configured in asterisk.conf.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
void load_astmm_phase_1(void)
Initialize malloc debug phase 1.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Prototypes for public functions only of internal interest,.
void * addresses[AST_MAX_BT_FRAMES]
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
static struct sorcery_test_caching cache
Global scope caching structure for testing.
String vector definitions.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_LIST_APPEND_LIST(head, list, field)
Appends a whole list to the tail of a list.
#define DEBUG_CHAOS_RETURN(c, f)
DEBUG_CHAOS returns failure randomly.