1999-07-27 Mark Kettenis <kettenis@gnu.org>

* sysdeps/mach/hurd/i386/init-first.c (init): Move the inline
	assembler code to switch stacks and call init1 outside this
	function.  Inside `init' the code was optimized away by gcc
	2.95 since it was "clearly" unreachable.
	* sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler):
	Do something similar for the trampoline code.
This commit is contained in:
Roland McGrath 1999-07-28 18:22:23 +00:00
parent a3dd87b380
commit 68a743d253
2 changed files with 50 additions and 43 deletions

View File

@ -1,5 +1,5 @@
/* Initialization code run first thing by the ELF startup code. For i386/Hurd. /* Initialization code run first thing by the ELF startup code. For i386/Hurd.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Copyright (C) 1995, 96, 97, 98, 99 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -157,6 +157,8 @@ init (int *data)
void *newsp = (*_cthread_init_routine) (); void *newsp = (*_cthread_init_routine) ();
struct hurd_startup_data *od; struct hurd_startup_data *od;
void switch_stacks (void);
/* Copy per-thread variables from that temporary /* Copy per-thread variables from that temporary
area onto the new cthread stack. */ area onto the new cthread stack. */
memcpy (__hurd_threadvar_location_from_sp (0, newsp), memcpy (__hurd_threadvar_location_from_sp (0, newsp),
@ -181,7 +183,7 @@ init (int *data)
be the return address for `init1'; we will jump there with NEWSP be the return address for `init1'; we will jump there with NEWSP
as the stack pointer. */ as the stack pointer. */
*--(int *) newsp = data[-1]; *--(int *) newsp = data[-1];
((void **) data)[-1] = &&switch_stacks; ((void **) data)[-1] = switch_stacks;
/* Force NEWSP into %ecx and &init1 into %eax, which are not restored /* Force NEWSP into %ecx and &init1 into %eax, which are not restored
by function return. */ by function return. */
asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1)); asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1));
@ -194,6 +196,8 @@ init (int *data)
unsigned int i; unsigned int i;
int usercode; int usercode;
void call_init1 (void);
array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); array = malloc (__hurd_threadvar_max * sizeof (unsigned long int));
if (array == NULL) if (array == NULL)
__libc_fatal ("Can't allocate single-threaded thread variables."); __libc_fatal ("Can't allocate single-threaded thread variables.");
@ -208,34 +212,40 @@ init (int *data)
/* The argument data is just above the stack frame we will unwind by /* The argument data is just above the stack frame we will unwind by
returning. Mutate our own return address to run the code below. */ returning. Mutate our own return address to run the code below. */
usercode = data[-1]; usercode = data[-1];
((void **) data)[-1] = &&call_init1; ((void **) data)[-1] = call_init1;
/* Force USERCODE into %eax and &init1 into %ecx, which are not /* Force USERCODE into %eax and &init1 into %ecx, which are not
restored by function return. */ restored by function return. */
asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1)); asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1));
} }
return;
switch_stacks:
/* Our return address was redirected to here, so at this point our stack
is unwound and callers' registers restored. Only %ecx and %eax are
call-clobbered and thus still have the values we set just above.
Fetch from there the new stack pointer we will run on, and jmp to the
run-time address of `init1'; when it returns, it will run the user
code with the argument data at the top of the stack. */
asm volatile ("movl %eax, %esp; jmp *%ecx");
/* NOTREACHED */
call_init1:
/* As in the stack-switching case, at this point our stack is unwound and
callers' registers restored, and only %ecx and %eax communicate values
from the lines above. In this case we have stashed in %eax the user
code return address. Push it on the top of the stack so it acts as
init1's return address, and then jump there. */
asm volatile ("pushl %eax; jmp *%ecx");
/* NOTREACHED */
} }
/* These bits of inline assembler used to be located inside `init'.
However they were optimized away by gcc 2.95. */
/* The return address of `init' above, was redirected to here, so at
this point our stack is unwound and callers' registers restored.
Only %ecx and %eax are call-clobbered and thus still have the
values we set just above. Fetch from there the new stack pointer
we will run on, and jmp to the run-time address of `init1'; when it
returns, it will run the user code with the argument data at the
top of the stack. */
asm ("
switch_stacks:
movl %eax, %esp
jmp *%ecx
");
/* As in the stack-switching case, at this point our stack is unwound
and callers' registers restored, and only %ecx and %eax communicate
values from the lines above. In this case we have stashed in %eax
the user code return address. Push it on the top of the stack so
it acts as init1's return address, and then jump there. */
asm ("
call_init1:
push %eax
jmp *%ecx
");
#ifdef PIC #ifdef PIC
/* This function is called to initialize the shared C library. /* This function is called to initialize the shared C library.

View File

@ -1,5 +1,5 @@
/* Set thread_state for sighandler, and sigcontext to recover. i386 version. /* Set thread_state for sighandler, and sigcontext to recover. i386 version.
Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Copyright (C) 1994, 95, 96, 97, 98, 99 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -32,7 +32,9 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
volatile int rpc_wait, volatile int rpc_wait,
struct machine_thread_all_state *state) struct machine_thread_all_state *state)
{ {
__label__ trampoline, rpc_wait_trampoline, firewall; void trampoline (void);
void rpc_wait_trampoline (void);
void firewall (void);
extern const void _hurd_intr_rpc_msg_in_trap; extern const void _hurd_intr_rpc_msg_in_trap;
extern const void _hurd_intr_rpc_msg_cx_sp; extern const void _hurd_intr_rpc_msg_cx_sp;
extern const void _hurd_intr_rpc_msg_sp_restored; extern const void _hurd_intr_rpc_msg_sp_restored;
@ -140,7 +142,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
stackframe->sigcode = detail->code; stackframe->sigcode = detail->code;
stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx; stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx;
stackframe->sigreturn_addr = &__sigreturn; stackframe->sigreturn_addr = &__sigreturn;
stackframe->sigreturn_returns_here = &&firewall; /* Crash on return. */ stackframe->sigreturn_returns_here = firewall; /* Crash on return. */
/* Set up the sigcontext from the current state of the thread. */ /* Set up the sigcontext from the current state of the thread. */
@ -196,7 +198,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
_hurdsig_end_catch_fault (); _hurdsig_end_catch_fault ();
state->basic.eip = (int) &&rpc_wait_trampoline; state->basic.eip = (int) rpc_wait_trampoline;
/* The reply-receiving trampoline code runs initially on the original /* The reply-receiving trampoline code runs initially on the original
user stack. We pass it the signal stack pointer in %ebx. */ user stack. We pass it the signal stack pointer in %ebx. */
state->basic.uesp = state->basic.esp; /* Restore mach_msg syscall SP. */ state->basic.uesp = state->basic.esp; /* Restore mach_msg syscall SP. */
@ -209,26 +211,26 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
} }
else else
{ {
state->basic.eip = (int) &&trampoline; state->basic.eip = (int) trampoline;
state->basic.uesp = (int) sigsp; state->basic.uesp = (int) sigsp;
} }
/* We pass the handler function to the trampoline code in %edx. */ /* We pass the handler function to the trampoline code in %edx. */
state->basic.edx = (int) handler; state->basic.edx = (int) handler;
return scp; return scp;
}
/* The trampoline code follows. This is not actually executed as part of /* The trampoline code follows. This used to be located inside
this function, it is just convenient to write it that way. */ _hurd_setup_sighandler, but was optimized away by gcc 2.95. */
rpc_wait_trampoline: asm ("rpc_wait_trampoline:\n");
/* This is the entry point when we have an RPC reply message to receive /* This is the entry point when we have an RPC reply message to receive
before running the handler. The MACH_MSG_SEND bit has already been before running the handler. The MACH_MSG_SEND bit has already been
cleared in the OPTION argument on our stack. The interrupted user cleared in the OPTION argument on our stack. The interrupted user
stack pointer has not been changed, so the system call can find its stack pointer has not been changed, so the system call can find its
arguments; the signal stack pointer is in %ebx. For our convenience, arguments; the signal stack pointer is in %ebx. For our convenience,
%ecx points to the sc_eax member of the sigcontext. */ %ecx points to the sc_eax member of the sigcontext. */
asm volatile asm (/* Retry the interrupted mach_msg system call. */
(/* Retry the interrupted mach_msg system call. */
"movl $-25, %eax\n" /* mach_msg_trap */ "movl $-25, %eax\n" /* mach_msg_trap */
"lcall $7, $0\n" "lcall $7, $0\n"
/* When the sigcontext was saved, %eax was MACH_RCV_INTERRUPTED. But /* When the sigcontext was saved, %eax was MACH_RCV_INTERRUPTED. But
@ -241,7 +243,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
/* Switch to the signal stack. */ /* Switch to the signal stack. */
"movl %ebx, %esp\n"); "movl %ebx, %esp\n");
trampoline: asm ("trampoline:\n");
/* Entry point for running the handler normally. The arguments to the /* Entry point for running the handler normally. The arguments to the
handler function are already on the top of the stack: handler function are already on the top of the stack:
@ -249,8 +251,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
4(%esp) SIGCODE 4(%esp) SIGCODE
8(%esp) SCP 8(%esp) SCP
*/ */
asm volatile asm ("call *%edx\n" /* Call the handler function. */
("call *%edx\n" /* Call the handler function. */
"addl $12, %esp\n" /* Pop its args. */ "addl $12, %esp\n" /* Pop its args. */
/* The word at the top of stack is &__sigreturn; following are a dummy /* The word at the top of stack is &__sigreturn; following are a dummy
word to fill the slot for the address for __sigreturn to return to, word to fill the slot for the address for __sigreturn to return to,
@ -258,9 +259,5 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
__sigreturn (SCP); this call never returns. */ __sigreturn (SCP); this call never returns. */
"ret"); "ret");
firewall: asm ("firewall:\n"
asm volatile ("hlt"); "hlt");
/* NOTREACHED */
return NULL;
}