diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2017-07-23 17:00:30 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2017-07-23 17:16:19 +0200 |
commit | eb2473e9ea0a875b79612f84d1fae32b670d9b88 (patch) | |
tree | 5816446b2fb1323763a4ce58842b5dcc971631db /src/nvim/log.c | |
parent | 5fc775e2efd1adf4985d9abcb1d970dcaa944555 (diff) | |
download | rneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.tar.gz rneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.tar.bz2 rneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.zip |
log: log_callstack()
Diffstat (limited to 'src/nvim/log.c')
-rw-r--r-- | src/nvim/log.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/src/nvim/log.c b/src/nvim/log.c index f1dbe61dda..252fe5438d 100644 --- a/src/nvim/log.c +++ b/src/nvim/log.c @@ -173,6 +173,53 @@ FILE *open_log_file(void) return stderr; } +#if defined(__linux__) +# include <execinfo.h> +void log_callstack(const char *const func_name, const int line_num) +{ + void *trace[100]; + int trace_size = backtrace(trace, ARRAY_SIZE(trace)); + + char exepath[MAXPATHL] = { 0 }; + size_t exepathlen = MAXPATHL; + if (os_exepath(exepath, &exepathlen) != 0) { + abort(); + } + assert(24 + exepathlen < IOSIZE); // Must fit in `cmdbuf` below. + + do_log(DEBUG_LOG_LEVEL, func_name, line_num, true, "trace:"); + + char cmdbuf[IOSIZE + (20 * ARRAY_SIZE(trace))]; + snprintf(cmdbuf, sizeof(cmdbuf), "addr2line -e %s -f -p", exepath); + for (int i = 1; i < trace_size; i++) { + char buf[20]; // 64-bit pointer 0xNNNNNNNNNNNNNNNN with leading space. + snprintf(buf, sizeof(buf), " %p", trace[i]); + xstrlcat(cmdbuf, buf, sizeof(cmdbuf)); + } + // Now we have a command string like: + // addr2line -e /path/to/exe -f -p 0x123 0x456 ... + + log_lock(); + FILE *log_file = open_log_file(); + if (log_file == NULL) { + goto end; + } + + FILE *fp = popen(cmdbuf, "r"); + char linebuf[IOSIZE]; + while (fgets(linebuf, sizeof(linebuf) - 1, fp) != NULL) { + fprintf(log_file, " %s", linebuf); + } + pclose(fp); + + if (log_file != stderr && log_file != stdout) { + fclose(log_file); + } +end: + log_unlock(); +} +#endif + static bool do_log_to_file(FILE *log_file, int log_level, const char *func_name, int line_num, bool eol, const char* fmt, ...) |