Use `long int' for sigcode values.
Use _hurdsig_catch_fault. Pass address of __sigreturn in $27, SCP value in $25. In trampoline code, use those regs.
This commit is contained in:
parent
94cd6ef1f8
commit
edae2ab8af
@ -20,7 +20,8 @@ Cambridge, MA 02139, USA. */
|
|||||||
#include <hurd/signal.h>
|
#include <hurd/signal.h>
|
||||||
#include "thread_state.h"
|
#include "thread_state.h"
|
||||||
#include <mach/machine/alpha_instruction.h>
|
#include <mach/machine/alpha_instruction.h>
|
||||||
|
#include "hurdfault.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
struct mach_msg_trap_args
|
struct mach_msg_trap_args
|
||||||
{
|
{
|
||||||
@ -37,7 +38,7 @@ struct mach_msg_trap_args
|
|||||||
|
|
||||||
struct sigcontext *
|
struct sigcontext *
|
||||||
_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
||||||
int signo, int sigcode,
|
int signo, long int sigcode,
|
||||||
int rpc_wait,
|
int rpc_wait,
|
||||||
struct machine_thread_all_state *state)
|
struct machine_thread_all_state *state)
|
||||||
{
|
{
|
||||||
@ -50,7 +51,10 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
/* We have a previous sigcontext that sigreturn was about
|
/* We have a previous sigcontext that sigreturn was about
|
||||||
to restore when another signal arrived. We will just base
|
to restore when another signal arrived. We will just base
|
||||||
our setup on that. */
|
our setup on that. */
|
||||||
if (! setjmp (_hurd_sigthread_fault_env))
|
if (_hurdsig_catch_fault (SIGSEGV))
|
||||||
|
assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
|
||||||
|
_hurdsig_fault_sigcode < (long int) (ss->context + 1));
|
||||||
|
else
|
||||||
{
|
{
|
||||||
memcpy (&state->basic, &ss->context->sc_alpha_thread_state,
|
memcpy (&state->basic, &ss->context->sc_alpha_thread_state,
|
||||||
sizeof (state->basic));
|
sizeof (state->basic));
|
||||||
@ -97,7 +101,16 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
sigsp -= sizeof (*scp);
|
sigsp -= sizeof (*scp);
|
||||||
scp = sigsp;
|
scp = sigsp;
|
||||||
|
|
||||||
if (! setjmp (_hurd_sigthread_fault_env))
|
if (_hurdsig_catch_fault (SIGSEGV))
|
||||||
|
{
|
||||||
|
assert (_hurdsig_fault_sigcode >= (long int) scp &&
|
||||||
|
_hurdsig_fault_sigcode < (long int) (scp + 1));
|
||||||
|
/* We got a fault trying to write the stack frame.
|
||||||
|
We cannot set up the signal handler.
|
||||||
|
Returning NULL tells our caller, who will nuke us with a SIGILL. */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* Set up the sigcontext from the current state of the thread. */
|
/* Set up the sigcontext from the current state of the thread. */
|
||||||
|
|
||||||
@ -125,11 +138,6 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
sizeof (state->fpu)))
|
sizeof (state->fpu)))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
/* We got a fault trying to write the stack frame.
|
|
||||||
We cannot set up the signal handler.
|
|
||||||
Returning NULL tells our caller, who will nuke us with a SIGILL. */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* Modify the thread state to call the trampoline code on the new stack. */
|
/* Modify the thread state to call the trampoline code on the new stack. */
|
||||||
if (rpc_wait)
|
if (rpc_wait)
|
||||||
@ -177,9 +185,12 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
|
|
||||||
/* We pass the handler function to the trampoline code in ra ($26). */
|
/* We pass the handler function to the trampoline code in ra ($26). */
|
||||||
state->basic.r26 = (long int) handler;
|
state->basic.r26 = (long int) handler;
|
||||||
/* In the callee-saved register t12 ($27), we save the SCP value to pass
|
/* In the callee-saved register t12/pv ($27), we store the
|
||||||
|
address of __sigreturn itself, for the trampoline code to use. */
|
||||||
|
state->basic.r27 = (long int) &__sigreturn;
|
||||||
|
/* In the callee-saved register t11/ai ($25), we save the SCP value to pass
|
||||||
to __sigreturn after the handler returns. */
|
to __sigreturn after the handler returns. */
|
||||||
state->basic.r27 = (long int) scp;
|
state->basic.r25 = (long int) scp;
|
||||||
|
|
||||||
return scp;
|
return scp;
|
||||||
|
|
||||||
@ -223,15 +234,14 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
|
|||||||
clobbered by running the handler). We use this saved value to pass to
|
clobbered by running the handler). We use this saved value to pass to
|
||||||
__sigreturn, so the handler can clobber the argument registers if it
|
__sigreturn, so the handler can clobber the argument registers if it
|
||||||
likes. */
|
likes. */
|
||||||
asm volatile
|
#define A(line) asm volatile (#line)
|
||||||
(/* Call the handler function, saving return address in ra ($26). */
|
/* Call the handler function, saving return address in ra ($26). */
|
||||||
"jsr $26, $26\n"
|
A (jsr $26, $26);
|
||||||
/* Reset gp ($29) from the return address (here) in ra ($26).
|
/* Reset gp ($29) from the return address (here) in ra ($26). */
|
||||||
This may be required to locate __sigreturn. */
|
A (ldgp $29, 0($26));
|
||||||
"ldgp $29, 0($26)\n"
|
A (mov $25, $16); /* Move saved SCP to argument register. */
|
||||||
/* Call __sigreturn (SCP); this cannot return. */
|
/* Call __sigreturn (SCP); this cannot return. */
|
||||||
"mov $27, $16\n" /* Move saved SCP to argument register. */
|
A (jmp $31, $27);
|
||||||
"jmp $31, %0" : : "i" (&__sigreturn));
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -246,21 +256,30 @@ int
|
|||||||
_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
|
_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
|
||||||
mach_port_t *port)
|
mach_port_t *port)
|
||||||
{
|
{
|
||||||
if (! setjmp (_hurd_sigthread_fault_env))
|
if (state->basic.r0 == MACH_RCV_INTERRUPTED)
|
||||||
{
|
{
|
||||||
const unsigned int *pc = (void *) state->basic.pc;
|
const unsigned int *pc = (void *) state->basic.pc;
|
||||||
if (state->basic.r0 == MACH_RCV_INTERRUPTED &&
|
struct mach_msg_trap_args *args = (void *) &state->basic.r16;
|
||||||
pc[-1] == ((alpha_instruction) { pal_format:
|
|
||||||
{ opcode: op_pal,
|
|
||||||
function: op_chmk } }).bits)
|
|
||||||
{
|
|
||||||
/* We did just return from a mach_msg_trap system call
|
|
||||||
doing a message receive that was interrupted.
|
|
||||||
Examine the parameters to find the receive right. */
|
|
||||||
struct mach_msg_trap_args *args = (void *) &state->basic.r16;
|
|
||||||
|
|
||||||
*port = args->rcv_name;
|
if (_hurdsig_catch_fault (SIGSEGV))
|
||||||
return 1;
|
{
|
||||||
|
assert (_hurdsig_fault_sigcode == (long int) (pc - 1) ||
|
||||||
|
_hurdsig_fault_sigcode == (long int) &args->rcv_name);
|
||||||
|
/* We got a fault trying to read the PC or stack. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (pc[-1] == ((alpha_instruction) { pal_format:
|
||||||
|
{ opcode: op_pal,
|
||||||
|
function: op_chmk } }).bits)
|
||||||
|
{
|
||||||
|
/* We did just return from a mach_msg_trap system call
|
||||||
|
doing a message receive that was interrupted.
|
||||||
|
Examine the parameters to find the receive right. */
|
||||||
|
*port = args->rcv_name;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user