From 83ddec31c69ac3dd3a6c83db8155ac1c63b13178 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 28 Jul 1999 18:19:47 +0000 Subject: 1999-07-27 Mark Kettenis * 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. --- sysdeps/mach/hurd/i386/init-first.c | 56 ++++++++++++++++++++++--------------- sysdeps/mach/hurd/i386/trampoline.c | 35 +++++++++++------------ 2 files changed, 49 insertions(+), 42 deletions(-) diff --git a/sysdeps/mach/hurd/i386/init-first.c b/sysdeps/mach/hurd/i386/init-first.c index c18b6a8..ee7b902 100644 --- a/sysdeps/mach/hurd/i386/init-first.c +++ b/sysdeps/mach/hurd/i386/init-first.c @@ -1,5 +1,5 @@ /* 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. 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) (); struct hurd_startup_data *od; + void switch_stacks (void); + /* Copy per-thread variables from that temporary area onto the new cthread stack. */ 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 as the stack pointer. */ *--(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 by function return. */ asm volatile ("# a %0 c %1" : : "a" (newsp), "c" (&init1)); @@ -194,6 +196,8 @@ init (int *data) unsigned int i; int usercode; + void call_init1 (void); + array = malloc (__hurd_threadvar_max * sizeof (unsigned long int)); if (array == NULL) __libc_fatal ("Can't allocate single-threaded thread variables."); @@ -208,33 +212,39 @@ init (int *data) /* The argument data is just above the stack frame we will unwind by returning. Mutate our own return address to run the code below. */ usercode = data[-1]; - ((void **) data)[-1] = &&call_init1; + ((void **) data)[-1] = call_init1; /* Force USERCODE into %eax and &init1 into %ecx, which are not restored by function return. */ asm volatile ("# a %0 c %1" : : "a" (usercode), "c" (&init1)); } +} - return; - +/* 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: - /* 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 */ -} + 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 diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c index 4c1fa60..448b15f 100644 --- a/sysdeps/mach/hurd/i386/trampoline.c +++ b/sysdeps/mach/hurd/i386/trampoline.c @@ -1,5 +1,5 @@ /* 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. 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, 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_cx_sp; 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->scp = stackframe->return_scp = scp = &stackframe->ctx; 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. */ @@ -196,7 +198,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, _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 user stack. We pass it the signal stack pointer in %ebx. */ 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 { - state->basic.eip = (int) &&trampoline; + state->basic.eip = (int) trampoline; state->basic.uesp = (int) sigsp; } /* We pass the handler function to the trampoline code in %edx. */ state->basic.edx = (int) handler; return scp; +} - /* The trampoline code follows. This is not actually executed as part of - this function, it is just convenient to write it that way. */ +/* The trampoline code follows. This used to be located inside + _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 before running the handler. The MACH_MSG_SEND bit has already been cleared in the OPTION argument on our stack. The interrupted user stack pointer has not been changed, so the system call can find its arguments; the signal stack pointer is in %ebx. For our convenience, %ecx points to the sc_eax member of the sigcontext. */ - asm volatile - (/* Retry the interrupted mach_msg system call. */ +asm (/* Retry the interrupted mach_msg system call. */ "movl $-25, %eax\n" /* mach_msg_trap */ "lcall $7, $0\n" /* 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. */ "movl %ebx, %esp\n"); - trampoline: + asm ("trampoline:\n"); /* Entry point for running the handler normally. The arguments to the 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 8(%esp) SCP */ - asm volatile - ("call *%edx\n" /* Call the handler function. */ +asm ("call *%edx\n" /* Call the handler function. */ "addl $12, %esp\n" /* Pop its args. */ /* 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, @@ -258,9 +259,5 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, __sigreturn (SCP); this call never returns. */ "ret"); - firewall: - asm volatile ("hlt"); - - /* NOTREACHED */ - return NULL; -} +asm ("firewall:\n" + "hlt"); -- cgit v1.1