mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-07 13:28:05 +08:00
hurd: Avoid asm statements which return
They are not supposed to change flow control. This fixes miscompilation with gcc 14.2.0 which then drops code, see https://lists.gnu.org/archive/html/bug-hurd/2024-11/msg00145.html
This commit is contained in:
parent
757ac24f8f
commit
7fa9e786b6
@ -231,6 +231,8 @@ _dl_sysdep_start (void **start_argptr,
|
|||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RETURN_TO_TRAMPOLINE();
|
||||||
|
|
||||||
void
|
void
|
||||||
_dl_sysdep_start_cleanup (void)
|
_dl_sysdep_start_cleanup (void)
|
||||||
{
|
{
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
License along with the GNU C Library; if not, see
|
License along with the GNU C Library; if not, see
|
||||||
<https://www.gnu.org/licenses/>. */
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
register int *sp asm ("%esp");
|
|
||||||
|
|
||||||
#include <hurd.h>
|
#include <hurd.h>
|
||||||
#include <hurd/signal.h>
|
#include <hurd/signal.h>
|
||||||
#include <hurd/msg.h>
|
#include <hurd/msg.h>
|
||||||
@ -54,29 +52,36 @@ __sigreturn2 (int *usp, struct sigcontext *scp)
|
|||||||
MACH_PORT_RIGHT_RECEIVE, -1);
|
MACH_PORT_RIGHT_RECEIVE, -1);
|
||||||
THREAD_SETMEM (THREAD_SELF, reply_port, scp->sc_reply_port);
|
THREAD_SETMEM (THREAD_SELF, reply_port, scp->sc_reply_port);
|
||||||
|
|
||||||
sp = usp;
|
void sigreturn2_trampoline (int *usp) __attribute__ ((__noreturn__));
|
||||||
#define A(line) asm volatile (#line)
|
sigreturn2_trampoline (usp);
|
||||||
/* The members in the sigcontext are arranged in this order
|
|
||||||
so we can pop them easily. */
|
|
||||||
|
|
||||||
/* Pop the segment registers (except %cs and %ss, done last). */
|
|
||||||
A (popl %gs);
|
|
||||||
A (popl %fs);
|
|
||||||
A (popl %es);
|
|
||||||
A (popl %ds);
|
|
||||||
/* Pop the general registers. */
|
|
||||||
A (popa);
|
|
||||||
/* Pop the processor flags. */
|
|
||||||
A (popf);
|
|
||||||
/* Return to the saved PC. */
|
|
||||||
A (ret);
|
|
||||||
|
|
||||||
/* Firewall. */
|
|
||||||
A (hlt);
|
|
||||||
#undef A
|
|
||||||
__builtin_unreachable ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asm("sigreturn2_trampoline:\n"
|
||||||
|
|
||||||
|
/* Restore thread stack */
|
||||||
|
"movl 4(%esp),%esp\n"
|
||||||
|
|
||||||
|
/* The members in the sigcontext are arranged in this order
|
||||||
|
so we can pop them easily. */
|
||||||
|
|
||||||
|
/* Pop the segment registers (except %cs and %ss, done last). */
|
||||||
|
"popl %gs\n"
|
||||||
|
"popl %fs\n"
|
||||||
|
"popl %es\n"
|
||||||
|
"popl %ds\n"
|
||||||
|
|
||||||
|
/* Pop the general registers. */
|
||||||
|
"popa\n"
|
||||||
|
|
||||||
|
/* Pop the processor flags. */
|
||||||
|
"popf\n"
|
||||||
|
|
||||||
|
/* Return to the saved PC. */
|
||||||
|
"ret\n"
|
||||||
|
|
||||||
|
/* Firewall. */
|
||||||
|
"hlt\n");
|
||||||
|
|
||||||
int
|
int
|
||||||
__sigreturn (struct sigcontext *scp)
|
__sigreturn (struct sigcontext *scp)
|
||||||
{
|
{
|
||||||
@ -142,16 +147,21 @@ __sigreturn (struct sigcontext *scp)
|
|||||||
*--usp = 0;
|
*--usp = 0;
|
||||||
*--usp = (int) __sigreturn2;
|
*--usp = (int) __sigreturn2;
|
||||||
|
|
||||||
/* Restore thread stack */
|
|
||||||
sp = usp;
|
|
||||||
/* Return into __sigreturn2. */
|
|
||||||
asm volatile ("ret");
|
|
||||||
/* Firewall. */
|
|
||||||
asm volatile ("hlt");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTREACHED */
|
void sigreturn_trampoline (int *usp) __attribute__ ((__noreturn__));
|
||||||
return -1;
|
sigreturn_trampoline (usp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asm("sigreturn_trampoline:\n"
|
||||||
|
|
||||||
|
/* Restore thread stack */
|
||||||
|
"movl 4(%esp),%esp\n"
|
||||||
|
|
||||||
|
/* Return into __sigreturn2. */
|
||||||
|
"ret\n"
|
||||||
|
|
||||||
|
/* Firewall. */
|
||||||
|
"hlt\n");
|
||||||
|
|
||||||
weak_alias (__sigreturn, sigreturn)
|
weak_alias (__sigreturn, sigreturn)
|
||||||
|
@ -249,6 +249,8 @@ _hurd_stack_setup (void **argptr)
|
|||||||
_hurd_startup (argptr, &doinit);
|
_hurd_startup (argptr, &doinit);
|
||||||
__builtin_unreachable ();
|
__builtin_unreachable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RETURN_TO_TRAMPOLINE();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,31 +46,32 @@ __sigreturn2 (struct hurd_sigstate *ss, uintptr_t *usp,
|
|||||||
MACH_PORT_RIGHT_RECEIVE, -1);
|
MACH_PORT_RIGHT_RECEIVE, -1);
|
||||||
THREAD_SETMEM (THREAD_SELF, reply_port, sc_reply_port);
|
THREAD_SETMEM (THREAD_SELF, reply_port, sc_reply_port);
|
||||||
|
|
||||||
asm volatile (
|
void sigreturn2_trampoline (uintptr_t *usp) __attribute__ ((__noreturn__));
|
||||||
|
sigreturn2_trampoline (usp);
|
||||||
|
}
|
||||||
|
|
||||||
|
asm("sigreturn2_trampoline:\n"
|
||||||
/* Point the stack to the register dump. */
|
/* Point the stack to the register dump. */
|
||||||
"movq %0, %%rsp\n"
|
"movq %rdi, %rsp\n"
|
||||||
/* Pop off the registers. */
|
/* Pop off the registers. */
|
||||||
"popq %%r8\n"
|
"popq %r8\n"
|
||||||
"popq %%r9\n"
|
"popq %r9\n"
|
||||||
"popq %%r10\n"
|
"popq %r10\n"
|
||||||
"popq %%r11\n"
|
"popq %r11\n"
|
||||||
"popq %%r12\n"
|
"popq %r12\n"
|
||||||
"popq %%r13\n"
|
"popq %r13\n"
|
||||||
"popq %%r14\n"
|
"popq %r14\n"
|
||||||
"popq %%r15\n"
|
"popq %r15\n"
|
||||||
"popq %%rdi\n"
|
"popq %rdi\n"
|
||||||
"popq %%rsi\n"
|
"popq %rsi\n"
|
||||||
"popq %%rbp\n"
|
"popq %rbp\n"
|
||||||
"popq %%rbx\n"
|
"popq %rbx\n"
|
||||||
"popq %%rdx\n"
|
"popq %rdx\n"
|
||||||
"popq %%rcx\n"
|
"popq %rcx\n"
|
||||||
"popq %%rax\n"
|
"popq %rax\n"
|
||||||
"popfq\n"
|
"popfq\n"
|
||||||
/* Restore %rip and %rsp with a single instruction. */
|
/* Restore %rip and %rsp with a single instruction. */
|
||||||
"retq $128" :
|
"retq $128" );
|
||||||
: "rm" (usp));
|
|
||||||
__builtin_unreachable ();
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
__sigreturn (struct sigcontext *scp)
|
__sigreturn (struct sigcontext *scp)
|
||||||
@ -152,16 +153,18 @@ __sigreturn (struct sigcontext *scp)
|
|||||||
*--usp = scp->sc_r9;
|
*--usp = scp->sc_r9;
|
||||||
*--usp = scp->sc_r8;
|
*--usp = scp->sc_r8;
|
||||||
|
|
||||||
/* Switch to the user's stack that we have just prepared, and call
|
void sigreturn_trampoline (struct hurd_sigstate *ss, uintptr_t *usp,
|
||||||
__sigreturn2. Clobber "memory" to make sure GCC flushes the stack
|
mach_port_t sc_reply_port)
|
||||||
setup to actual memory. We align the stack as per the ABI, but pass
|
__attribute__ ((__noreturn__));
|
||||||
the original usp to __sigreturn2 as an argument. */
|
sigreturn_trampoline (ss, usp, sc_reply_port);
|
||||||
asm volatile ("movq %1, %%rsp\n"
|
|
||||||
"andq $-16, %%rsp\n"
|
|
||||||
"call __sigreturn2" :
|
|
||||||
: "D" (ss), "S" (usp), "d" (sc_reply_port)
|
|
||||||
: "memory");
|
|
||||||
__builtin_unreachable ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
asm("sigreturn_trampoline:\n"
|
||||||
|
/* Switch to the user's stack that we have just prepared, and call
|
||||||
|
__sigreturn2. We align the stack as per the ABI, but pass
|
||||||
|
the original usp to __sigreturn2 as an argument. */
|
||||||
|
"movq %rsi, %rsp\n"
|
||||||
|
"andq $-16, %rsp\n"
|
||||||
|
"call __sigreturn2");
|
||||||
|
|
||||||
weak_alias (__sigreturn, sigreturn)
|
weak_alias (__sigreturn, sigreturn)
|
||||||
|
@ -33,17 +33,29 @@
|
|||||||
#undef ENTRY
|
#undef ENTRY
|
||||||
#undef ALIGN
|
#undef ALIGN
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLER__
|
||||||
|
void return_to_trampoline(intptr_t *sp, void *pc, intptr_t retval)
|
||||||
|
__attribute__((__noreturn__));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define RETURN_TO return_to_trampoline
|
||||||
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
#define RETURN_TO(sp, pc, retval) \
|
#define RETURN_TO_TRAMPOLINE() \
|
||||||
asm volatile ("movq %0, %%rsp; jmp %*%1 # %2" \
|
asm ("return_to_trampoline:\n" \
|
||||||
: : "g" (sp), "r" (pc), "a" (retval))
|
"movq %rdx, %rax\n" \
|
||||||
|
"movq %rdi, %rsp\n" \
|
||||||
|
"jmp *%rsi\n");
|
||||||
/* This should be rearranged, but at the moment this file provides
|
/* This should be rearranged, but at the moment this file provides
|
||||||
the most useful definitions for assembler syntax details. */
|
the most useful definitions for assembler syntax details. */
|
||||||
#include <sysdeps/unix/x86_64/sysdep.h>
|
#include <sysdeps/unix/x86_64/sysdep.h>
|
||||||
#else
|
#else
|
||||||
#define RETURN_TO(sp, pc, retval) \
|
#define RETURN_TO_TRAMPOLINE() \
|
||||||
asm volatile ("movl %0, %%esp; jmp %*%1 # %2" \
|
asm ("return_to_trampoline:\n" \
|
||||||
: : "g" (sp), "r" (pc), "a" (retval))
|
"movl 12(%esp), %eax\n" \
|
||||||
|
"movl 8(%esp), %edx\n" \
|
||||||
|
"movl 4(%esp), %esp\n" \
|
||||||
|
"jmp *%edx\n");
|
||||||
#include <sysdeps/unix/i386/sysdep.h>
|
#include <sysdeps/unix/i386/sysdep.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user