~ubuntu-branches/ubuntu/trusty/a2jmidid/trusty

« back to all changes in this revision

Viewing changes to .pc/armel-sig-reg-fix.diff/sigsegv.c

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Bennett
  • Date: 2010-04-06 02:53:14 UTC
  • Revision ID: james.westby@ubuntu.com-20100406025314-q9x4evj6rhep6jh6
Tags: 6-0ubuntu2
sigsegv.c: don't try to get register information on anything but x86 and IA64. (LP: #556351)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * This source file is used to print out a stack-trace when your program
 
3
 * segfaults.  It is relatively reliable and spot-on accurate.
 
4
 *
 
5
 * This code is in the public domain.  Use it as you see fit, some credit
 
6
 * would be appreciated, but is not a prerequisite for usage.  Feedback
 
7
 * on it's use would encourage further development and maintenance.
 
8
 *
 
9
 * Author:  Jaco Kroon <jaco@kroon.co.za>
 
10
 *
 
11
 * Copyright (C) 2005 - 2008 Jaco Kroon
 
12
 */
 
13
 
 
14
#if defined(HAVE_CONFIG_H)
 
15
#include "config.h"
 
16
#endif
 
17
 
 
18
#define NO_CPP_DEMANGLE
 
19
#define SIGSEGV_NO_AUTO_INIT
 
20
 
 
21
#ifndef _GNU_SOURCE
 
22
# define _GNU_SOURCE
 
23
#endif
 
24
 
 
25
#include <memory.h>
 
26
#include <stdlib.h>
 
27
#include <stdio.h>
 
28
#include <signal.h>
 
29
#include <ucontext.h>
 
30
#include <dlfcn.h>
 
31
#include <execinfo.h>
 
32
#include <errno.h>
 
33
#ifndef NO_CPP_DEMANGLE
 
34
//#include <cxxabi.h>
 
35
char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status);
 
36
#endif
 
37
 
 
38
#include <stdbool.h>
 
39
#include "log.h"
 
40
 
 
41
#if defined(REG_RIP)
 
42
# define SIGSEGV_STACK_IA64
 
43
# define REGFORMAT "%016lx"
 
44
#elif defined(REG_EIP)
 
45
# define SIGSEGV_STACK_X86
 
46
# define REGFORMAT "%08x"
 
47
#else
 
48
# define SIGSEGV_STACK_GENERIC
 
49
# define REGFORMAT "%x"
 
50
#endif
 
51
 
 
52
static void signal_segv(int signum, siginfo_t* info, void*ptr) {
 
53
    static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};
 
54
 
 
55
    size_t i;
 
56
    ucontext_t *ucontext = (ucontext_t*)ptr;
 
57
 
 
58
#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
 
59
    int f = 0;
 
60
    Dl_info dlinfo;
 
61
    void **bp = 0;
 
62
    void *ip = 0;
 
63
#else
 
64
    void *bt[20];
 
65
    char **strings;
 
66
    size_t sz;
 
67
#endif
 
68
 
 
69
    if (signum == SIGSEGV)
 
70
    {
 
71
        a2j_error("Segmentation Fault!");
 
72
    }
 
73
    else if (signum == SIGABRT)
 
74
    {
 
75
        a2j_error("Abort!");
 
76
    }
 
77
    else if (signum == SIGILL)
 
78
    {
 
79
        a2j_error("Illegal instruction!");
 
80
    }
 
81
    else if (signum == SIGFPE)
 
82
    {
 
83
        a2j_error("Floating point exception!");
 
84
    }
 
85
    else
 
86
    {
 
87
        a2j_error("Unknown bad signal catched!");
 
88
    }
 
89
 
 
90
    a2j_error("info.si_signo = %d", signum);
 
91
    a2j_error("info.si_errno = %d", info->si_errno);
 
92
    a2j_error("info.si_code  = %d (%s)", info->si_code, si_codes[info->si_code]);
 
93
    a2j_error("info.si_addr  = %p", info->si_addr);
 
94
    for(i = 0; i < NGREG; i++)
 
95
        a2j_error("reg[%02d]       = 0x" REGFORMAT, i, ucontext->uc_mcontext.gregs[i]);
 
96
 
 
97
#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64)
 
98
# if defined(SIGSEGV_STACK_IA64)
 
99
    ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP];
 
100
    bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP];
 
101
# elif defined(SIGSEGV_STACK_X86)
 
102
    ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP];
 
103
    bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP];
 
104
# endif
 
105
 
 
106
    a2j_error("Stack trace:");
 
107
    while(bp && ip) {
 
108
        if(!dladdr(ip, &dlinfo))
 
109
            break;
 
110
 
 
111
        const char *symname = dlinfo.dli_sname;
 
112
#ifndef NO_CPP_DEMANGLE
 
113
        int status;
 
114
        char *tmp = __cxa_demangle(symname, NULL, 0, &status);
 
115
 
 
116
        if(status == 0 && tmp)
 
117
            symname = tmp;
 
118
#endif
 
119
 
 
120
        a2j_error("% 2d: %p <%s+%u> (%s)",
 
121
                ++f,
 
122
                ip,
 
123
                symname,
 
124
                (unsigned)(ip - dlinfo.dli_saddr),
 
125
                dlinfo.dli_fname);
 
126
 
 
127
#ifndef NO_CPP_DEMANGLE
 
128
        if(tmp)
 
129
            free(tmp);
 
130
#endif
 
131
 
 
132
        if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main"))
 
133
            break;
 
134
 
 
135
        ip = bp[1];
 
136
        bp = (void**)bp[0];
 
137
    }
 
138
#else
 
139
    a2j_error("Stack trace (non-dedicated):");
 
140
    sz = backtrace(bt, 20);
 
141
    strings = backtrace_symbols(bt, sz);
 
142
 
 
143
    for(i = 0; i < sz; ++i)
 
144
        a2j_error("%s", strings[i]);
 
145
#endif
 
146
    a2j_error("End of stack trace");
 
147
    exit (-1);
 
148
}
 
149
 
 
150
int setup_sigsegv() {
 
151
    struct sigaction action;
 
152
 
 
153
    memset(&action, 0, sizeof(action));
 
154
    action.sa_sigaction = signal_segv;
 
155
    action.sa_flags = SA_SIGINFO;
 
156
    if(sigaction(SIGSEGV, &action, NULL) < 0) {
 
157
        a2j_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
 
158
        return 0;
 
159
    }
 
160
 
 
161
    if(sigaction(SIGILL, &action, NULL) < 0) {
 
162
        a2j_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
 
163
        return 0;
 
164
    }
 
165
 
 
166
    if(sigaction(SIGABRT, &action, NULL) < 0) {
 
167
        a2j_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
 
168
        return 0;
 
169
    }
 
170
 
 
171
    if(sigaction(SIGFPE, &action, NULL) < 0) {
 
172
        a2j_error("sigaction failed. errno is %d (%s)", errno, strerror(errno));
 
173
        return 0;
 
174
    }
 
175
 
 
176
    return 1;
 
177
}
 
178
 
 
179
#ifndef SIGSEGV_NO_AUTO_INIT
 
180
static void __attribute((constructor)) init(void) {
 
181
    setup_sigsegv();
 
182
}
 
183
#endif