mirror of git://git.sysmocom.de/ofono
log: Add support for backtrace symbole resolving
This commit is contained in:
parent
b285fbb6f9
commit
35ea6a5a05
125
src/log.c
125
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue