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);
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);
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) {
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);
602 if ((ptr = __ast_alloc_region(
len, FUNC_STRDUP,
file, lineno, func, 0))) {
615 if ((ptr = __ast_alloc_region(
len + 1, FUNC_STRNDUP,
file, lineno, func, 0))) {
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);
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;
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);
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);
1587 va_start(ap, format);
1654 char *newstr =
NULL;
1668 char *newstr =
NULL;
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);
Prototypes for public functions only of internal interest,.
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.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#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)
int vasprintf(char **strp, const char *fmt, va_list ap)
char * strndup(const char *, size_t)
size_t strnlen(const char *, size_t)
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
struct stasis_forward * sub
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::@212 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.