diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/README.md | 19 | ||||
-rw-r--r-- | src/nvim/log.c | 47 | ||||
-rw-r--r-- | src/nvim/log.h | 22 |
3 files changed, 61 insertions, 27 deletions
diff --git a/src/nvim/README.md b/src/nvim/README.md index 660e3d1010..1c1c3c364e 100644 --- a/src/nvim/README.md +++ b/src/nvim/README.md @@ -1,13 +1,20 @@ +Nvim core source +================ -Module-specific details are documented at the top of each module (e.g. -terminal.c, screen.c). +Module-specific details are documented at the top of each module (`terminal.c`, +`screen.c`, ...). -See also `:help development`. +See `:help development` for more guidelines. -UI Debugging ------------- +Logs +---- -At `DEBUG_LOG_LEVEL`, all UI events are logged. +Low-level log messages sink to `$NVIM_LOG_FILE`. + +You can use `LOG_CALLSTACK()` anywhere in the source to log the current +stacktrace. (Currently Linux-only.) + +UI events are logged at level 0 (`DEBUG_LOG_LEVEL`). rm -rf build/ make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0" 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, ...) diff --git a/src/nvim/log.h b/src/nvim/log.h index 48be7606e7..2bd18f5776 100644 --- a/src/nvim/log.h +++ b/src/nvim/log.h @@ -62,27 +62,7 @@ #endif #if defined(__linux__) -# include <execinfo.h> -# define LOG_CALLSTACK(prefix) \ - do { \ - void *trace[100]; \ - int trace_size = backtrace(trace, 100); \ - \ - char exe[1024]; \ - ssize_t elen = readlink("/proc/self/exe", exe, sizeof(exe) - 1); \ - exe[elen] = 0; \ - \ - for (int i = 1; i < trace_size; i++) { \ - char buf[256]; \ - snprintf(buf, sizeof(buf), "addr2line -e %s -f -p %p", exe, trace[i]); \ - FILE *fp = popen(buf, "r"); \ - while (fgets(buf, sizeof(buf) - 1, fp) != NULL) { \ - buf[strlen(buf)-1] = 0; \ - do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, prefix "%s", buf); \ - } \ - fclose(fp); \ - } \ - } while (0) +# define LOG_CALLSTACK() log_callstack(__func__, __LINE__) #endif #ifdef INCLUDE_GENERATED_DECLARATIONS |