aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-07-23 17:00:30 +0200
committerJustin M. Keyes <justinkz@gmail.com>2017-07-23 17:16:19 +0200
commiteb2473e9ea0a875b79612f84d1fae32b670d9b88 (patch)
tree5816446b2fb1323763a4ce58842b5dcc971631db /src
parent5fc775e2efd1adf4985d9abcb1d970dcaa944555 (diff)
downloadrneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.tar.gz
rneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.tar.bz2
rneovim-eb2473e9ea0a875b79612f84d1fae32b670d9b88.zip
log: log_callstack()
Diffstat (limited to 'src')
-rw-r--r--src/nvim/README.md19
-rw-r--r--src/nvim/log.c47
-rw-r--r--src/nvim/log.h22
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