129 lines
2.3 KiB
C
129 lines
2.3 KiB
C
|
/*
|
||
|
Trap handling
|
||
|
*/
|
||
|
|
||
|
/* $Header$ */
|
||
|
|
||
|
#include <setjmp.h>
|
||
|
|
||
|
#include <em_abs.h>
|
||
|
#include "logging.h"
|
||
|
#include "global.h"
|
||
|
#include "log.h"
|
||
|
#include "trap.h"
|
||
|
#include "warn.h"
|
||
|
#include "mem.h"
|
||
|
#include "shadow.h"
|
||
|
#include "linfil.h"
|
||
|
#include "rsb.h"
|
||
|
#include "fra.h"
|
||
|
|
||
|
extern char *sprintf();
|
||
|
|
||
|
extern jmp_buf trapbuf; /* from main.c */
|
||
|
|
||
|
int must_test; /* TEST-bit on in EM header word 2 */
|
||
|
int signalled;
|
||
|
|
||
|
PRIVATE int nonreturnable();
|
||
|
|
||
|
PRIVATE char *trap_msg[] = {
|
||
|
#include "trap_msg" /* generated from $(EM)/etc/traps */
|
||
|
""
|
||
|
};
|
||
|
|
||
|
char *trap2text(nr) /* transient */
|
||
|
int nr;
|
||
|
{
|
||
|
if ( /* trap number in predefined range */
|
||
|
nr < sizeof (trap_msg) / sizeof (trap_msg[0])
|
||
|
&& /* trap message not the empty string */
|
||
|
trap_msg[nr][0]
|
||
|
) {
|
||
|
return trap_msg[nr];
|
||
|
}
|
||
|
else {
|
||
|
static char buf[50];
|
||
|
|
||
|
sprintf(buf, "TRAP %d", nr);
|
||
|
return buf;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*ARGSUSED*/
|
||
|
do_trap(nr, L, F)
|
||
|
int nr;
|
||
|
int L;
|
||
|
char *F;
|
||
|
{
|
||
|
/*
|
||
|
1. The trap has not been masked.
|
||
|
2. This routine does not return; it either ends in a call of
|
||
|
fatal() or in a longjmp().
|
||
|
*/
|
||
|
static int rec_nr; /* Recursive trap number */
|
||
|
static int rec_trap = 0; /* To detect traps inside do_trap() */
|
||
|
|
||
|
register long tpi; /* Trap Procedure Identifier */
|
||
|
|
||
|
LOG(("@t1 trap(%d) [%s: %d]", nr, F, L));
|
||
|
warning(WMSG + nr);
|
||
|
|
||
|
switch (OnTrap) {
|
||
|
case TR_ABORT:
|
||
|
fatal("trap \"%s\" before program started", trap2text(nr));
|
||
|
/*NOTREACHED*/
|
||
|
|
||
|
case TR_HALT:
|
||
|
fatal("trap \"%s\" not caught at %s",
|
||
|
trap2text(nr), position());
|
||
|
/*NOTREACHED*/
|
||
|
|
||
|
case TR_TRAP:
|
||
|
/* execute the trap */
|
||
|
if (rec_trap) {
|
||
|
fatal("recursive trap; first trap number was \"%s\"",
|
||
|
trap2text(rec_nr));
|
||
|
}
|
||
|
rec_trap = 1;
|
||
|
rec_nr = nr;
|
||
|
|
||
|
/* save the Function Return Area */
|
||
|
pushFRA(FRASize);
|
||
|
npush((long)FRASize, wsize);
|
||
|
npush((long)FRA_def, wsize);
|
||
|
|
||
|
/* set up the trap number as the only parameter */
|
||
|
npush((long) nr, wsize);
|
||
|
|
||
|
tpi = TrapPI; /* allowed since OnTrap == TR_TRAP */
|
||
|
TrapPI = 0;
|
||
|
OnTrap = TR_HALT;
|
||
|
call(tpi, (nonreturnable(nr) ? RSB_NRT : RSB_RTT));
|
||
|
rec_trap = 0;
|
||
|
longjmp(trapbuf, 1);
|
||
|
/*NOTREACHED*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PRIVATE int nonreturnable(nr)
|
||
|
int nr;
|
||
|
{
|
||
|
switch (nr) {
|
||
|
case ESTACK:
|
||
|
case EILLINS:
|
||
|
case EODDZ:
|
||
|
case ECASE:
|
||
|
case EMEMFLT:
|
||
|
case EBADPTR:
|
||
|
case EBADPC:
|
||
|
case EBADLAE:
|
||
|
case EBADGTO:
|
||
|
return 1;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
/*NOTREACHED*/
|
||
|
}
|
||
|
|