log: Add support for backtrace symbole resolving

This commit is contained in:
Marcel Holtmann 2011-10-05 19:41:40 -07:00
parent b285fbb6f9
commit 35ea6a5a05
3 changed files with 112 additions and 17 deletions

125
src/log.c
View File

@ -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;
}
ofono_error("Aborting (signal %d)", signo);
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);
}
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);

View File

@ -226,7 +226,7 @@ int main(int argc, char **argv)
signal = setup_signalfd();
__ofono_log_init(option_debug, option_detach);
__ofono_log_init(argv[0], option_debug, option_detach);
dbus_error_init(&error);

View File

@ -34,7 +34,7 @@ void __ofono_modem_shutdown(void);
#include <ofono/log.h>
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);
void __ofono_log_cleanup(void);
void __ofono_log_enable(struct ofono_debug_desc *start,
struct ofono_debug_desc *stop);