summaryrefslogtreecommitdiffstats
path: root/src/log.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2011-10-05 19:41:40 -0700
committerMarcel Holtmann <marcel@holtmann.org>2011-10-05 19:41:40 -0700
commit35ea6a5a054d61cbcd1db680439f03d152e5a5b4 (patch)
treefd0affc62039a611a5c2d73c50dcd2a8d2699b1a /src/log.c
parentb285fbb6f92fbf6c1f239bb48e49881b64346bbb (diff)
downloadofono-35ea6a5a054d61cbcd1db680439f03d152e5a5b4.tar.bz2
log: Add support for backtrace symbole resolving
Diffstat (limited to 'src/log.c')
-rw-r--r--src/log.c125
1 files changed, 110 insertions, 15 deletions
diff --git a/src/log.c b/src/log.c
index c31a76cc..84710f00 100644
--- a/src/log.c
+++ b/src/log.c
@@ -24,14 +24,20 @@
#endif
#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
#include <stdarg.h>
-#include <syslog.h>
#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
#include <execinfo.h>
#include <dlfcn.h>
#include "ofono.h"
+static const char *program_exec;
+static const char *program_path;
+
/**
* ofono_info:
* @format: format string
@@ -107,30 +113,115 @@ void ofono_debug(const char *format, ...)
va_end(ap);
}
-static void signal_handler(int signo)
+static void print_backtrace(unsigned int offset)
{
- void *frames[64];
- char **symbols;
+ void *frames[99];
size_t n_ptrs;
unsigned int i;
+ int outfd[2], infd[2];
+ int pathlen;
+ pid_t pid;
+
+ if (program_exec == NULL)
+ return;
+
+ pathlen = strlen(program_path);
n_ptrs = backtrace(frames, G_N_ELEMENTS(frames));
- symbols = backtrace_symbols(frames, n_ptrs);
- if (symbols == NULL) {
- ofono_error("No backtrace symbols");
- exit(1);
+ if (n_ptrs < offset)
+ return;
+
+ if (pipe(outfd) < 0)
+ return;
+
+ if (pipe(infd) < 0) {
+ close(outfd[0]);
+ close(outfd[1]);
+ return;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ close(outfd[0]);
+ close(outfd[1]);
+ close(infd[0]);
+ close(infd[1]);
+ return;
+ }
+
+ if (pid == 0) {
+ close(outfd[1]);
+ close(infd[0]);
+
+ dup2(outfd[0], STDIN_FILENO);
+ dup2(infd[1], STDOUT_FILENO);
+
+ execlp("addr2line", "-C", "-f", "-e", program_exec, NULL);
+
+ exit(EXIT_FAILURE);
}
- ofono_error("Aborting (signal %d)", signo);
+ close(outfd[0]);
+ close(infd[1]);
+
ofono_error("++++++++ backtrace ++++++++");
- for (i = 1; i < n_ptrs; i++)
- ofono_error("[%d]: %s", i - 1, symbols[i]);
+ for (i = offset; i < n_ptrs - 1; i++) {
+ Dl_info info;
+ char addr[20], buf[PATH_MAX * 2];
+ int len, written;
+ char *ptr, *pos;
+
+ dladdr(frames[i], &info);
+
+ len = snprintf(addr, sizeof(addr), "%p\n", frames[i]);
+ if (len < 0)
+ break;
+
+ written = write(outfd[1], addr, len);
+ if (written < 0)
+ break;
+
+ len = read(infd[0], buf, sizeof(buf));
+ if (len < 0)
+ break;
+
+ buf[len] = '\0';
+
+ pos = strchr(buf, '\n');
+ *pos++ = '\0';
+
+ if (strcmp(buf, "??") == 0) {
+ ofono_error("#%-2u %p in %s", i - offset,
+ frames[i], info.dli_fname);
+ continue;
+ }
+
+ ptr = strchr(pos, '\n');
+ *ptr++ = '\0';
+
+ if (strncmp(pos, program_path, pathlen) == 0)
+ pos += pathlen + 1;
+
+ ofono_error("#%-2u %p in %s() at %s", i - offset,
+ frames[i], buf, pos);
+ }
ofono_error("+++++++++++++++++++++++++++");
- g_free(symbols);
- exit(1);
+ kill(pid, SIGTERM);
+
+ close(outfd[1]);
+ close(infd[0]);
+}
+
+static void signal_handler(int signo)
+{
+ ofono_error("Aborting (signal %d) [%s]", signo, program_exec);
+
+ print_backtrace(2);
+
+ exit(EXIT_FAILURE);
}
static void signal_setup(sighandler_t handler)
@@ -197,10 +288,14 @@ void __ofono_log_enable(struct ofono_debug_desc *start,
}
}
-int __ofono_log_init(const char *debug, ofono_bool_t detach)
+int __ofono_log_init(const char *exe, const char *debug, ofono_bool_t detach)
{
+ static char path[PATH_MAX];
int option = LOG_NDELAY | LOG_PID;
+ program_exec = exe;
+ program_path = getcwd(path, sizeof(path));
+
if (debug != NULL)
enabled = g_strsplit_set(debug, ":, ", 0);
@@ -211,7 +306,7 @@ int __ofono_log_init(const char *debug, ofono_bool_t detach)
signal_setup(signal_handler);
- openlog("ofonod", option, LOG_DAEMON);
+ openlog(basename(exe), option, LOG_DAEMON);
syslog(LOG_INFO, "oFono version %s", VERSION);