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));
 
  138static struct ast_region *regions[SOME_PRIME];
 
  141#define FREED_MAX_COUNT     1500 
  144#define MINNOWS_MAX_SIZE    50 
  146struct ast_freed_regions {
 
  148    struct ast_region *regions[FREED_MAX_COUNT];
 
  154static struct ast_freed_regions whales;
 
  156static struct ast_freed_regions minnows;
 
  162    SUMMARY_BY_LINE = (1 << 0),
 
  164    SUMMARY_BY_FUNC = (1 << 1),
 
  166    SUMMARY_BY_FILE = (1 << 2),
 
  170static enum summary_opts atexit_summary;
 
  172static int atexit_list;
 
  174static int backtrace_enabled;
 
  176#define HASH(a)     (((unsigned long)(a)) % ARRAY_LEN(regions)) 
  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");
 
  222static void my_do_crash(
void)
 
  233static 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;
 
  262    fence = (
unsigned int *) (reg->data - 
sizeof(*fence));
 
  263    *fence = FENCE_MAGIC;
 
  266    fence = (
unsigned int *) (reg->data + reg->len);
 
  269    hash = HASH(reg->data);
 
  284static void region_data_wipe(
struct ast_region *reg)
 
  293    end = reg->data + reg->len;
 
  294    for (pos = ®->fence; (
void *) pos <= 
end; ++pos) {
 
  305static 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);
 
  332static void freed_regions_flush(
struct ast_freed_regions *freed)
 
  335    struct ast_region *old;
 
  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);
 
  357static void region_free(
struct ast_freed_regions *freed, 
struct ast_region *reg)
 
  359    struct ast_region *old;
 
  361    region_data_wipe(reg);
 
  364    old = freed->regions[freed->index];
 
  365    freed->regions[freed->index] = reg;
 
  368    if (
ARRAY_LEN(freed->regions) <= freed->index) {
 
  374        region_data_check(old);
 
  389static struct ast_region *region_remove(
void *ptr)
 
  392    struct ast_region *reg;
 
  393    struct ast_region *prev = 
NULL;
 
  399        if (reg->data == ptr) {
 
  420static 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);
 
  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);
 
  449static void regions_check_all_fences(
void)
 
  452    struct ast_region *reg;
 
  455    for (idx = 0; idx < 
ARRAY_LEN(regions); ++idx) {
 
  457            region_check_fences(reg);
 
  463void __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);
 
  492void *
__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);
 
  508    ptr = __ast_alloc_region(size * nmemb, FUNC_CALLOC, file, lineno, func, 1);
 
  510        memset(ptr, 0, size * nmemb);
 
  516void *
__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);
 
  532static struct ast_region *region_find(
void *ptr)
 
  535    struct ast_region *reg;
 
  539        if (reg->data == ptr) {
 
  547void *
__ast_repl_realloc(
void *ptr, 
size_t size, 
const char *file, 
int lineno, 
const char *func)
 
  550    struct ast_region *found;
 
  555        found = region_find(ptr);
 
  558            astmm_log(
"WARNING: Realloc of unregistered memory %p by %s %s() line %d\n",
 
  559                ptr, file, func, lineno);
 
  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);
 
  589            memset(new_mem, MALLOC_FILLER, size);
 
  596char *
__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))) {
 
  609char *
__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))) {
 
  623int __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);
 
  647int __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);
 
  678static 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";
 
  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";
 
  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;
 
  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);
 
  798static 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) {
 
  856    if (fn && (!strcasecmp(fn, 
"anomalies") || !strcasecmp(fn, 
"anomolies"))) {
 
  857        regions_check_all_fences();
 
  858        ast_cli(
a->fd, 
"Anomaly check complete.\n");
 
  863    for (idx = 0; idx < 
ARRAY_LEN(regions); ++idx) {
 
  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);
 
  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);
 
  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) {
 
  940    for (idx = 0; idx < 
ARRAY_LEN(regions); ++idx) {
 
  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;
 
  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);
 
 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";
 
 1057        backtrace_enabled = 1;
 
 1059        backtrace_enabled = 0;
 
 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."),
 
 1095static 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;
 
 1121static void mm_atexit_hash_restore(
struct region_list *list)
 
 1123    struct ast_region *reg;
 
 1127        hash = HASH(reg->data);
 
 1129        regions[hash] = reg;
 
 1144static 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;
 
 1191static void mm_atexit_list_merge(
struct region_list *list, 
struct region_list *sub1, 
struct region_list *sub2)
 
 1193    struct ast_region *reg;
 
 1226static 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;
 
 1258static void mm_atexit_list_sort(
struct region_list *list, 
size_t length)
 
 1263    struct region_list 
sub[2] = {
 
 1280            mm_atexit_list_merge(&merged, &
sub[0], &
sub[1]);
 
 1300static 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);
 
 1317static 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",
 
 1414        astmm_log(
"%u bytes in %u allocations.\n", 
total.len, 
total.count);
 
 1424static 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);
 
 1458static 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) {
 
 1491    atexit(mm_atexit_final);
 
 1497static void mm_atexit_ast(
void)
 
 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);
 
 1537    return calloc(nmemb, size);
 
 
 1544    return calloc(nmemb, size);
 
 
 1554void __ast_free(
void *ptr, 
const char *file, 
int lineno, 
const char *func)
 
 
 1563    return realloc(ptr, size);
 
 
 1587    va_start(ap, format);
 
 
 1594int __ast_repl_vasprintf(
char **strp, 
const char *format, va_list ap, 
const char *file, 
int lineno, 
const char *func)
 
 
 1603void *
__ast_calloc(
size_t nmemb, 
size_t size, 
const char *file, 
int lineno, 
const char *func)
 
 
 1628void *
__ast_malloc(
size_t size, 
const char *file, 
int lineno, 
const char *func)
 
 
 1640void *
__ast_realloc(
void *ptr, 
size_t size, 
const char *file, 
int lineno, 
const char *func)
 
 
 1652char *
__ast_strdup(
const char *s, 
const char *file, 
int lineno, 
const char *func)
 
 1654    char *newstr = 
NULL;
 
 
 1666char *
__ast_strndup(
const char *s, 
size_t n, 
const char *file, 
int lineno, 
const char *func)
 
 1668    char *newstr = 
NULL;
 
 
 1680int __ast_asprintf(
const char *file, 
int lineno, 
const char *func, 
char **strp, 
const char *format, ...)
 
 1685    va_start(ap, format);
 
 
 1701int __ast_vasprintf(
char **strp, 
const char *format, va_list ap, 
const char *file, 
int lineno, 
const char *func)
 
 
 1726    return calloc(nmemb, size);
 
 
 1731    return realloc(ptr, size);
 
 
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
int vasprintf(char **strp, const char *fmt, va_list ap)
char * strndup(const char *, size_t)
size_t strnlen(const char *, size_t)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
void * __ast_repl_malloc(size_t size, const char *file, int lineno, const char *func)
void * ast_std_malloc(size_t size)
void * ast_std_calloc(size_t nmemb, size_t size)
void ast_std_free(void *ptr)
int __ast_repl_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
#define DEBUG_CHAOS_RETURN(c, f)
DEBUG_CHAOS returns failure randomly.
void * ast_std_realloc(void *ptr, size_t size)
void load_astmm_phase_2(void)
Initialize malloc debug phase 2.
char * __ast_repl_strdup(const char *s, const char *file, int lineno, const char *func)
void * __ast_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
static void * __ast_repl_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
int __ast_vasprintf(char **strp, const char *format, va_list ap, const char *file, int lineno, const char *func)
void * __ast_repl_realloc(void *ptr, size_t size, const char *file, int lineno, const char *func)
void load_astmm_phase_1(void)
Initialize malloc debug phase 1.
char * __ast_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
#define MALLOC_FAILURE_MSG
void * __ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
int __ast_repl_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format,...)
void * __ast_malloc(size_t size, const char *file, int lineno, const char *func)
void ast_free_ptr(void *ptr)
free() wrapper
char * __ast_repl_strndup(const char *s, size_t n, const char *file, int lineno, const char *func)
void __ast_free(void *ptr, const char *file, int lineno, const char *func)
int __ast_asprintf(const char *file, int lineno, const char *func, char **strp, const char *format,...)
void * __ast_repl_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
char * __ast_strdup(const char *s, const char *file, int lineno, const char *func)
void * __ast_calloc_cache(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Asterisk backtrace generation.
#define ast_bt_free_symbols(string_vector)
#define ast_bt_get_symbols(addresses, num_frames)
#define ast_bt_destroy(bt)
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_verb(level,...)
#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_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
#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.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_APPEND_LIST(head, list, field)
Appends a whole list to the tail of a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Asterisk locking-related definitions:
#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)
#define ast_mutex_unlock(a)
#define ast_mutex_lock(a)
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_LOG_DIR
struct ao2_container * cache
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
String manipulation functions.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
void * addresses[AST_MAX_BT_FRAMES]
descriptor for a cli entry.
struct ast_cli_entry::@225 list
String vector definitions.
Time-related functions and macros.
Handle unaligned data access.
static unsigned int get_unaligned_uint32(const void *p)
static void put_unaligned_uint32(void *p, unsigned int datum)
void DO_CRASH_NORETURN ast_do_crash(void)
Force a crash if DO_CRASH is defined.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.