1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
#ifdef NEED_TRAP
#include <stdio.h>
#include "lutil.h"
#include "trap.h"
#ifdef TESTING
#define logerr printf
#else
#include "lutil.h"
#endif
#if defined(linux)
# ifndef __GLIBC__
# define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S))
# include <linux/version.h>
# if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
# define sigcontext sigcontext_struct
# endif
# define __KERNEL__
# include <linux/signal.h>
# undef __KERNEL__
# endif /* __GLIBC__ */
# ifdef __i386__
# define iBCS2
# else
# define SUNSTYLE
# endif /* __i386__ */
#elif defined(sun)
#define SUNSTYLE
#elif defined(SVR4)
#define SVR4STYLE
#endif
#include <signal.h>
#ifdef HAS_SYSLOG
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
#endif
static char *nm="";
static struct _signames {
int sig;
char *name;
} signames[] =
{
#ifdef SIGSEGV
{SIGSEGV,"SIGSEGV"},
#endif
#ifdef SIGBUS
{SIGBUS,"SIGBUS"},
#endif
#ifdef SIGFPE
{SIGFPE,"SIGFPE"},
#endif
#ifdef SIGSTKFLT
{SIGSTKFLT,"SIGSTKFLT"},
#endif
{0,NULL}
};
static char *signame(sig)
int sig;
{
int i;
static char buf[8];
for (i=0;signames[i].name;i++)
if (signames[i].sig == sig) break;
if (signames[i].name) return signames[i].name;
sprintf(buf,"%d",sig);
return buf;
}
#if defined(iBCS2)
static void trap(sig,context)
int sig;
struct sigcontext context;
#elif defined(SVR4STYLE)
static void trap(sig,context)
int sig;
siginfo_t *si;
#elif defined(SUNSTYLE)
static void trap(sig,code,context,addr)
int sig;
int code;
struct sigcontext *context;
char *addr;
#else
static void trap(sig)
int sig;
#endif
{
#if defined(iBCS2)
long *stack;
#ifdef TESTING
int i;
printf("conext.gs=%04hx,%04hx\n",context.__gsh,context.gs);
printf("conext.fs=%04hx,%04hx\n",context.__fsh,context.fs);
printf("conext.es=%04hx,%04hx\n",context.__esh,context.es);
printf("conext.ds=%04hx,%04hx\n",context.__dsh,context.ds);
printf("conext.edi=%08lx\n",context.edi);
printf("conext.esi=%08lx\n",context.esi);
printf("conext.ebp=%08lx\n",context.ebp);
printf("conext.esp=%08lx\n",context.esp);
printf("conext.ebx=%08lx\n",context.ebx);
printf("conext.edx=%08lx\n",context.edx);
printf("conext.ecx=%08lx\n",context.ecx);
printf("conext.eax=%08lx\n",context.eax);
printf("conext.trapno=%08lx\n",context.trapno);
printf("conext.err=%08lx\n",context.err);
printf("conext.eip=%08lx\n",context.eip);
printf("conext.cs=%04hx,%04hx\n",context.__csh,context.cs);
printf("conext.eflags=%08lx\n",context.eflags);
printf("conext.esp_at_signal=%08lx\n",context.esp_at_signal);
printf("conext.ss=%04hx,%04hx\n",context.__ssh,context.ss);
printf("conext.i387=%08lx\n",context.i387);
printf("conext.oldmask=%08lx\n",context.oldmask);
printf("conext.cr2=%08lx\n",context.cr2);
stack=(long *)context.esp_at_signal;
for (i=-2;i<10;i++)
printf("stack %2d: 0x%08lx: 0x%08lx\n",i,(long)&(stack[i]),stack[i]);
#endif
signal(sig,SIG_DFL); /* for BSD compatibility, won't harm SysV */
logerr("caught %s at offset 0x%08lx",signame(sig),context.eip);
/*
Follows an awful, nasty kludge. The problem is that when
interrupt occurs in a function compiled with
-fomit-frame-pointer, there is no way (or at least I don't know
one) to catch the beginning of the stack frame chain. So, the
only thing I could think of is to scan the stack in search of a
value the _looks_like_ a frame chain pointer. Generally, this
approach may cause all kind of problems: from false backtrace
information to segfault inside the handler. If you know a
better way, _please_ make me know!
*/
for (stack=(long *)context.esp_at_signal;
stack && ((unsigned)((long *)stack[0]-stack) > 20);
stack++);
for (;stack && stack[1];stack=(long*)stack[0])
{
#ifdef TESTING
printf("\n[0x%08lx] next 0x%08lx, ret 0x%08lx ",(long)stack,
stack[0],stack[1]);
#endif
logerr("called from 0x%08lx",stack[1]);
}
#elif defined(SVR4STYLE)
if (context) psiginfo(si,nm);
else psignal(sig,nm);
#elif defined(SUNSTYLE)
logerr("caught %s at offset 0x%08lx",signame(sig),addr);
#else
#warning Cannot provide detailed info on this architecture
logerr("caught %s",signame(sig));
psignal(sig,nm);
#endif
#ifdef HAS_SYSLOG
debug(2,"closing syslog");
closelog();
#endif
#ifdef TESTING
printf("\n");
#else
abort(); /* stupid, but BSD will cycle otherwise */
#endif
return;
}
void catch(name)
char *name;
{
int i=0;
nm=name;
for (i=0;signames[i].name;i++)
debug(2,"catch: signal(%d) return %d",
signames[i].sig,signal(signames[i].sig,trap));
return;
}
#ifdef TESTING
void faulty(s)
int *s;
{
int w=1234;
memcpy(s,&w,sizeof(int));
*s=1234;
return;
}
int good(s)
int *s;
{
faulty(s);
return 0;
}
int main()
{
int *s=NULL;
int i;
catch("trap test");
printf("\nbefore fault\n");
i=good(s);
printf("\nafter fault\n");
return 0;
}
#endif /* TESTING */
#endif /* NEED_TRAP */
|