summaryrefslogtreecommitdiff
path: root/os/backtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/backtrace.c')
-rw-r--r--os/backtrace.c235
1 files changed, 126 insertions, 109 deletions
diff --git a/os/backtrace.c b/os/backtrace.c
index edaeb17c7..81348f417 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -37,53 +37,61 @@
#include <dlfcn.h>
#include <execinfo.h>
-void xorg_backtrace(void)
+void
+xorg_backtrace(void)
{
void *array[64];
const char *mod;
int size, i;
Dl_info info;
+
ErrorF("\n");
ErrorF("Backtrace:\n");
size = backtrace(array, 64);
for (i = 0; i < size; i++) {
- int rc = dladdr(array[i], &info);
- if (rc == 0) {
- ErrorF("%d: ?? [%p]\n", i, array[i]);
- continue;
- }
- mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)";
- if (info.dli_saddr)
- ErrorF("%d: %s (%s+0x%lx) [%p]\n", i, mod,
- info.dli_sname, (long unsigned int)((char *) array[i] - (char *) info.dli_saddr), array[i]);
- else
- ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod,
- info.dli_fbase, (long unsigned int)((char *) array[i] - (char *) info.dli_fbase), array[i]);
+ int rc = dladdr(array[i], &info);
+
+ if (rc == 0) {
+ ErrorF("%d: ?? [%p]\n", i, array[i]);
+ continue;
+ }
+ mod = (info.dli_fname && *info.dli_fname) ? info.dli_fname : "(vdso)";
+ if (info.dli_saddr)
+ ErrorF("%d: %s (%s+0x%lx) [%p]\n", i, mod,
+ info.dli_sname,
+ (long unsigned int) ((char *) array[i] -
+ (char *) info.dli_saddr), array[i]);
+ else
+ ErrorF("%d: %s (%p+0x%lx) [%p]\n", i, mod,
+ info.dli_fbase,
+ (long unsigned int) ((char *) array[i] -
+ (char *) info.dli_fbase), array[i]);
}
ErrorF("\n");
}
-#else /* not glibc or glibc < 2.1 */
+#else /* not glibc or glibc < 2.1 */
-# if defined(sun) && defined(__SVR4)
-# define HAVE_PSTACK
-# endif
+#if defined(sun) && defined(__SVR4)
+#define HAVE_PSTACK
+#endif
-# if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
+#if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
-# include <ucontext.h>
-# include <signal.h>
-# include <dlfcn.h>
-# include <sys/elf.h>
+#include <ucontext.h>
+#include <signal.h>
+#include <dlfcn.h>
+#include <sys/elf.h>
#ifdef _LP64
-# define ElfSym Elf64_Sym
+#define ElfSym Elf64_Sym
#else
-# define ElfSym Elf32_Sym
+#define ElfSym Elf32_Sym
#endif
/* Called for each frame on the stack to print it's contents */
-static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
+static int
+xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
{
Dl_info dlinfo;
ElfSym *dlsym;
@@ -91,13 +99,13 @@ static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
int depth = *((int *) arg);
if (signo) {
- char signame[SIG2STR_MAX];
+ char signame[SIG2STR_MAX];
- if (sig2str(signo, signame) != 0) {
- strcpy(signame, "unknown");
- }
+ if (sig2str(signo, signame) != 0) {
+ strcpy(signame, "unknown");
+ }
- ErrorF("** Signal %d (%s)\n", signo, signame);
+ ErrorF("** Signal %d (%s)\n", signo, signame);
}
snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
@@ -105,118 +113,127 @@ static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
/* Ask system dynamic loader for info on the address */
if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
- unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
- const char *symname;
-
- if (offset < dlsym->st_size) { /* inside a function */
- symname = dlinfo.dli_sname;
- } else { /* found which file it was in, but not which function */
- symname = "<section start>";
- offset = pc - (uintptr_t)dlinfo.dli_fbase;
- }
- ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname,
- symname, offset);
-
- } else {
- /* Couldn't find symbol info from system dynamic loader, should
- * probably poke elfloader here, but haven't written that code yet,
- * so we just print the pc.
- */
- ErrorF("%s\n", header);
+ unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
+ const char *symname;
+
+ if (offset < dlsym->st_size) { /* inside a function */
+ symname = dlinfo.dli_sname;
+ }
+ else { /* found which file it was in, but not which function */
+ symname = "<section start>";
+ offset = pc - (uintptr_t) dlinfo.dli_fbase;
+ }
+ ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname, symname, offset);
+
+ }
+ else {
+ /* Couldn't find symbol info from system dynamic loader, should
+ * probably poke elfloader here, but haven't written that code yet,
+ * so we just print the pc.
+ */
+ ErrorF("%s\n", header);
}
return 0;
}
-# endif /* HAVE_WALKCONTEXT */
+#endif /* HAVE_WALKCONTEXT */
-# ifdef HAVE_PSTACK
-static int xorg_backtrace_pstack(void) {
+#ifdef HAVE_PSTACK
+static int
+xorg_backtrace_pstack(void)
+{
pid_t kidpid;
int pipefd[2];
if (pipe(pipefd) != 0) {
- return -1;
+ return -1;
}
kidpid = fork1();
if (kidpid == -1) {
- /* ERROR */
- return -1;
- } else if (kidpid == 0) {
- /* CHILD */
- char parent[16];
-
- seteuid(0);
- close(STDIN_FILENO);
- close(STDOUT_FILENO);
- dup2(pipefd[1],STDOUT_FILENO);
- closefrom(STDERR_FILENO);
-
- snprintf(parent, sizeof(parent), "%d", getppid());
- execle("/usr/bin/pstack", "pstack", parent, NULL);
- exit(1);
- } else {
- /* PARENT */
- char btline[256];
- int kidstat;
- int bytesread;
- int done = 0;
-
- close(pipefd[1]);
-
- while (!done) {
- bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
-
- if (bytesread > 0) {
- btline[bytesread] = 0;
- ErrorF("%s", btline);
- }
- else if ((bytesread < 0) ||
- ((errno != EINTR) && (errno != EAGAIN)))
- done = 1;
- }
- close(pipefd[0]);
- waitpid(kidpid, &kidstat, 0);
- if (kidstat != 0)
- return -1;
+ /* ERROR */
+ return -1;
+ }
+ else if (kidpid == 0) {
+ /* CHILD */
+ char parent[16];
+
+ seteuid(0);
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ dup2(pipefd[1], STDOUT_FILENO);
+ closefrom(STDERR_FILENO);
+
+ snprintf(parent, sizeof(parent), "%d", getppid());
+ execle("/usr/bin/pstack", "pstack", parent, NULL);
+ exit(1);
+ }
+ else {
+ /* PARENT */
+ char btline[256];
+ int kidstat;
+ int bytesread;
+ int done = 0;
+
+ close(pipefd[1]);
+
+ while (!done) {
+ bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
+
+ if (bytesread > 0) {
+ btline[bytesread] = 0;
+ ErrorF("%s", btline);
+ }
+ else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN)))
+ done = 1;
+ }
+ close(pipefd[0]);
+ waitpid(kidpid, &kidstat, 0);
+ if (kidstat != 0)
+ return -1;
}
return 0;
}
-# endif /* HAVE_PSTACK */
-
+#endif /* HAVE_PSTACK */
-# if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
+#if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
-void xorg_backtrace(void) {
+void
+xorg_backtrace(void)
+{
ErrorF("\n");
ErrorF("Backtrace:\n");
-# ifdef HAVE_PSTACK
+#ifdef HAVE_PSTACK
/* First try fork/exec of pstack - otherwise fall back to walkcontext
pstack is preferred since it can print names of non-exported functions */
if (xorg_backtrace_pstack() < 0)
-# endif
+#endif
{
-# ifdef HAVE_WALKCONTEXT
- ucontext_t u;
- int depth = 1;
-
- if (getcontext(&u) == 0)
- walkcontext(&u, xorg_backtrace_frame, &depth);
- else
-# endif
- ErrorF("Failed to get backtrace info: %s\n", strerror(errno));
+#ifdef HAVE_WALKCONTEXT
+ ucontext_t u;
+ int depth = 1;
+
+ if (getcontext(&u) == 0)
+ walkcontext(&u, xorg_backtrace_frame, &depth);
+ else
+#endif
+ ErrorF("Failed to get backtrace info: %s\n", strerror(errno));
}
ErrorF("\n");
}
-# else
+#else
/* Default fallback if we can't find any way to get a backtrace */
-void xorg_backtrace(void) { return; }
+void
+xorg_backtrace(void)
+{
+ return;
+}
-# endif
+#endif
#endif