home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet MPEG Audio Archive
/
IMAA.mdf
/
util
/
dos
/
l3v100n
/
rsx
/
source
/
signals.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-19
|
7KB
|
287 lines
/* This file is SIGNALS.C
**
** contains :
**
** - signal handling
** - exception handling
**
** Copyright (c) Rainer Schnitker '92 '93
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "DPMI.H"
#include "PROCESS.H"
#include "SIGNALS.H"
#include "START32.H"
#include "CDOSX32.H"
#include "EXCEP32.H"
#include "ADOSX32.H"
#include "COPY32.H"
#include "RSX.H"
/* local functions */
static int exception2signal(WORD);
static int signal_handler_returned(WORD);
static int do_signal(WORD);
static void print_exception_exit(void);
static void print_regs_exception(void);
/* regs after exceptions */
REG386 regf;
extern char *sigtext[];
/*
** give back a signal no from a hardware exception fault no
*/
static int exception2signal(WORD faultno)
{
int signal;
switch (faultno) {
case 0:
case 2:
case 4:
case 5:
case 6:
case 8:
case 10:
case 15:
signal = SIGILL;
break;
case 1:
case 3:
signal = SIGTRAP;
break;
case 7:
case 16:
signal = SIGFPE;
break;
case 9:
case 11:
case 12:
case 13:
case 14:
case 17:
signal = SIGSEGV;
break;
default:
signal = SIGSEGV;
break;
}
return signal;
}
/*
** signal handlers have a return address 0xffffffff
** if signal handler returned: caused a gp-fault no_13
** restore all registers, check raise() , back to user
*/
static int signal_handler_returned(WORD faultno)
{
WORD sig;
/* returned signal caused only a GP-fault 0xD */
if (faultno != 13)
return 0;
/* test [eip]==ret instruction*/
if (verify_illegal(npz, EIP, sizeof(DWORD)))
return 0;
if ((BYTE) read32(npz->data32sel, EIP) != (BYTE) 0xC3)
return 0;
/* test [esp]==0xffffffff */
if (verify_illegal(npz, ESP, 2 * sizeof(DWORD)))
return 0;
if (read32(npz->data32sel, ESP) != 0xffffffff)
return 0;
sig = (WORD) read32(npz->data32sel, ESP + 4);
/* get saved values from stack (stackpos+=ret address + sig no) */
cpy32_16(npz->data32sel, ESP + 2 * sizeof(DWORD), &(npz->regs), sizeof(REG386));
if (AX == 0x7f0E) { /* back from raise() */
EAX = ECX = 0; /* put return values */
}
/*
** if we had a hardware exception, we zero the user handler, to
** prevent a exception loop to handler (may be changed in future)
*/
else if (sig == SIGSEGV || sig == SIGILL || sig == SIGFPE || sig == SIGTRAP) {
npz->sigs[sig] = 0;
npz->sig_ack &= ~(1L << sig);
}
return 1;
}
/*
** called before return to user process
*/
int check_signals(void)
{
int i;
DWORD sigs;
sigs = ~npz->sig_ack & npz->sig_raised;
if (!sigs)
return 0;
for (i = 0; i < MAX_SIGNALS; i++) {
if (sigs & 1)
if (do_signal(i))
return 1;
sigs >>= 1;
}
return 0;
}
/*
** check signals settings , change eip to signal handler
*/
static int do_signal(WORD signal)
{
DWORD address;
DWORD mask;
if (opt_printall)
printf("do_signal %d\n", signal);
if ((npz->p_flags & PF_DEBUG) && signal != SIGKILL) {
npz->p_status = PS_STOP;
npz->wait_return = (signal << 8) | 127;
npz->p_flags |= PF_WAIT_WAIT;
switch_to_process(npz->pptr);
EAX = ECX = 0;
npz->p_status = PS_RUN;
return 1;
}
address = npz->sigs[signal];/* handler address */
if (address == 1L) /* ignore sig */
return 0;
if (address == 0L) {
if (signal == SIGCLD) {
npz->sig_raised &= ~(1L << SIGCLD); /* clear SIGCLD signal */
return 0; /* sigcld,not terminate */
}
do_exit4c(signal);
return 1;
}
mask = 1L << signal;
/* ok, do user handler */
npz->sig_raised &= ~mask; /* clear sig_raised */
npz->sig_ack |= mask; /* set blocked */
if (ESP == ESPORG) /* build stack-frame,if not */
ESP -= 12;
/* save regs for handler return, put reg values on user stack */
cpy16_32(npz->data32sel, ESP - sizeof(REG386),
&(npz->regs), sizeof(REG386));
ESP -= sizeof(REG386); /* sub register-frame */
EIP = address; /* sighandler address */
ESP -= sizeof(long); /* put signalno on user stack */
store32(npz->data32sel, ESP, signal);
ESP -= sizeof(long); /* put bad return address on user stack */
store32(npz->data32sel, ESP, 0xFFFFFFFF);
ESP -= 12; /* sub iret frame */
return 1;
}
char *exceptext[] =
{
"division by zero",
"debug",
"NMI",
"breakpoint",
"overflow",
"bound check",
"invalid opcode",
"copro not availble",
"double fault",
"copro exception",
"invalid TSS",
"segment not present",
"stack fault",
"general protection",
"page fault",
"reserved",
"copro error",
"alignment error"
};
/*
** this function is called after hardware exceptions
*/
void myexcep13(void)
{ /* C exception handler */
int signal;
if (opt_printall)
printf("Exception %d\n", (WORD) regf.faultno);
/* test if we have a error in kernel, abort rsx */
/* future versions will just terminate the running process */
if ((WORD) regf.cs == code16sel || (WORD) regf.ds == data16sel) {
printf("Kernel fault at %X %lX\n", (WORD) regf.cs, regf.eip);
printf("EAX=%08lX EBX=%08lX ECX=%08lX EDX=%08lX\n"
"EBP=%08lX ESP=%08lX ESI=%08lX EDI=%08lX\n"
"CS=%04X DS=%04X ES=%04X SS=%04X\n",
regf.eax, regf.ebx, regf.ecx, regf.edx,
regf.ebp, regf.esp, regf.esi, regf.edi,
(WORD) regf.cs, (WORD) regf.ds, (WORD) regf.es, (WORD) regf.ss);
printf("User Registers:\n");
npz->regs.faultno = regf.faultno;
print_exception_exit();
}
/* user fault, copy saved regs to process table */
memcpy(&(npz->regs), ®f, sizeof(REG386));
/* if signal-handler returns (caused gp-fault), back to program */
if (signal_handler_returned(FAULTNO))
return;
/* ok, we have a normal fault, get convert to signal */
signal = exception2signal(FAULTNO);
if (signal != SIGTRAP) {
printf("process %d get hardware fault %d (%s) at %lX\n",
npz->pid, FAULTNO, exceptext[FAULTNO], EIP);
if (opt_printall)
print_regs_exception();
}
send_signal(npz, signal);
/* then, check_signal() is called (see excep32.asm) */
}
static void print_regs_exception(void)
{
printf("selector=%lX errbits: %X\n"
"cs:eip=%04X:%08lX eflags=%08lX\n"
"eax=%08lX ebx=%08lX ecx=%08lX edx=%08lX\n"
"ebp=%08lX esp=%08lX esi=%08lX edi=%08lX\n"
"cs=%04X ds=%04X es=%04X ss=%04X fs=%04X gs=%04X\n",
ERR & ~7L, (WORD) ERR & 7,
CS, EIP, EFLAGS,
EAX, EBX, ECX, EDX,
EBP, ESP, ESI, EDI,
CS, DS, ES, SS, FS, GS);
}
static void print_exception_exit()
{
printf("PROTECTION FAULT %d :\n", FAULTNO);
print_regs_exception();
shut_down(3);
}