vdso for ia32 on amd64

Reviewed by:	emaste
Discussed with:	jrtc27
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 month
Differential revision:	https://reviews.freebsd.org/D32960
This commit is contained in:
Konstantin Belousov 2021-11-14 02:26:55 +02:00
parent 290e05dde0
commit 98c8b62524
9 changed files with 211 additions and 47 deletions

View File

@ -81,6 +81,12 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/trap.h>
#include "vdso_ia32_offsets.h"
extern const char _binary_elf_vdso32_so_1_start[];
extern const char _binary_elf_vdso32_so_1_end[];
extern char _binary_elf_vdso32_so_1_size;
#ifdef COMPAT_FREEBSD4
static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
#endif
@ -416,7 +422,9 @@ ia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
}
regs->tf_rsp = (uintptr_t)fp;
regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode;
regs->tf_rip = p->p_sysent->sv_psstrings -
(_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
VDSO_IA32_OSIGCODE_OFFSET;
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ds = _udatasel;
@ -527,8 +535,8 @@ freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
}
regs->tf_rsp = (uintptr_t)sfp;
regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode -
sz_freebsd4_ia32_sigcode;
regs->tf_rip = p->p_sysent->sv_sigcode_base +
VDSO_FREEBSD4_IA32_SIGCODE_OFFSET - VDSO_IA32_SIGCODE_OFFSET;
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;

View File

@ -32,14 +32,13 @@
#include "ia32_assym.h"
.text
.code32
/*
* Signal trampoline, copied to top of user stack
* XXX may need to be MD to match backend sendsig handoff protocol
* Signal trampoline, mapped as vdso into shared page, or copied to
* top of user stack for old binaries.
*/
ALIGN_TEXT
.globl ia32_sigcode
ia32_sigcode:
.globl __vdso_ia32_sigcode
__vdso_ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
pushl %eax
@ -52,7 +51,8 @@ ia32_sigcode:
#ifdef COMPAT_FREEBSD4
ALIGN_TEXT
freebsd4_ia32_sigcode:
.globl __vdso_freebsd4_ia32_sigcode
__vdso_freebsd4_ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC4(%esp),%eax/* get ucontext */
pushl %eax
@ -66,7 +66,8 @@ freebsd4_ia32_sigcode:
#ifdef COMPAT_43
ALIGN_TEXT
ia32_osigcode:
.globl __vdso_ia32_osigcode
__vdso_ia32_osigcode:
calll *IA32_SIGF_HANDLER(%esp)/* call signal handler */
leal IA32_SIGF_SC(%esp),%eax /* get sigcontext */
pushl %eax
@ -90,28 +91,9 @@ ia32_osigcode:
* vfork() and harder for other syscalls.
*/
ALIGN_TEXT
lcall_tramp:
.globl __vdso_lcall_tramp
__vdso_lcall_tramp:
int $0x80
1: jmp 1b
#endif
ALIGN_TEXT
esigcode:
.data
.globl sz_ia32_sigcode
sz_ia32_sigcode:
.long esigcode-ia32_sigcode
#ifdef COMPAT_FREEBSD4
.globl sz_freebsd4_ia32_sigcode
sz_freebsd4_ia32_sigcode:
.long esigcode-freebsd4_ia32_sigcode
#endif
#ifdef COMPAT_43
.globl sz_ia32_osigcode
sz_ia32_osigcode:
.long esigcode-ia32_osigcode
.globl sz_lcall_tramp
sz_lcall_tramp:
.long esigcode-lcall_tramp
#endif
.p2align 1

View File

@ -92,6 +92,12 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/cpufunc.h>
#include "vdso_ia32_offsets.h"
extern const char _binary_elf_vdso32_so_1_start[];
extern const char _binary_elf_vdso32_so_1_end[];
extern char _binary_elf_vdso32_so_1_size;
#define IDTVEC(name) __CONCAT(X,name)
extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(int0x80_syscall_pti),
@ -264,7 +270,9 @@ setup_lcall_gate(void)
bzero(&uap, sizeof(uap));
uap.start = 0;
uap.num = 1;
lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp;
lcall_addr = curproc->p_sysent->sv_psstrings -
(_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
VDSO_LCALL_TRAMP_OFFSET;
bzero(&desc, sizeof(desc));
desc.sd_type = SDT_MEMERA;
desc.sd_dpl = SEL_UPL;

View File

@ -195,14 +195,6 @@ struct ia32_sigframe3 {
struct ksiginfo;
struct image_params;
extern char ia32_sigcode[];
extern char freebsd4_ia32_sigcode[];
extern char ia32_osigcode[];
extern char lcall_tramp;
extern int sz_ia32_sigcode;
extern int sz_freebsd4_ia32_sigcode;
extern int sz_ia32_osigcode;
extern int sz_lcall_tramp;
void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
void ia32_setregs(struct thread *td, struct image_params *imgp,
uintptr_t stack);

View File

@ -83,6 +83,12 @@ CTASSERT(sizeof(struct ia32_ucontext4) == 324);
CTASSERT(sizeof(struct ia32_sigframe4) == 408);
#endif
#include "vdso_ia32_offsets.h"
extern const char _binary_elf_vdso32_so_1_start[];
extern const char _binary_elf_vdso32_so_1_end[];
extern char _binary_elf_vdso32_so_1_size;
extern const char *freebsd32_syscallnames[];
static SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
@ -101,8 +107,9 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_transtrap = NULL,
.sv_fixup = elf32_freebsd_fixup,
.sv_sendsig = ia32_sendsig,
.sv_sigcode = ia32_sigcode,
.sv_szsigcode = &sz_ia32_sigcode,
.sv_sigcode = _binary_elf_vdso32_so_1_start,
.sv_szsigcode = (int *)&_binary_elf_vdso32_so_1_size,
.sv_sigcodeoff = VDSO_IA32_SIGCODE_OFFSET,
.sv_name = "FreeBSD ELF32",
.sv_coredump = elf32_coredump,
.sv_elf_core_osabi = ELFOSABI_FREEBSD,
@ -121,7 +128,7 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER,
SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,

View File

@ -18,6 +18,12 @@ elf-vdso.so.o standard \
no-implicit-rule before-depend \
clean "elf-vdso.so.o elf-vdso.so.1 vdso_offsets.h sigtramp.pico"
#
elf-vdso32.so.o optional compat_freebsd32 \
dependency "$S/amd64/ia32/ia32_sigtramp.S ia32_assym.h $S/tools/amd64_ia32_vdso.sh" \
compile-with "env AWK='${AWK}' NM='${NM}' LD='${LD}' CC='${CC}' OBJCOPY='${OBJCOPY}' S='${S}' sh $S/tools/amd64_ia32_vdso.sh" \
no-implicit-rule before-depend \
clean "elf-vdso32.so.o elf-vdso32.so.1 vdso_ia32_offsets.h ia32_sigtramp.pico"
#
ia32_genassym.o standard \
dependency "$S/compat/ia32/ia32_genassym.c offset.inc" \
compile-with "${CC} ${CFLAGS:N-flto:N-fno-common} -fcommon -c ${.IMPSRC}" \
@ -368,7 +374,6 @@ kern/link_elf_obj.c standard
#amd64/ia32/ia32_exception.S optional compat_freebsd32
amd64/ia32/ia32_reg.c optional compat_freebsd32
amd64/ia32/ia32_signal.c optional compat_freebsd32
amd64/ia32/ia32_sigtramp.S optional compat_freebsd32
amd64/ia32/ia32_syscall.c optional compat_freebsd32
amd64/ia32/ia32_misc.c optional compat_freebsd32
compat/ia32/ia32_sysvec.c optional compat_freebsd32

View File

@ -0,0 +1,94 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2021 The FreeBSD Foundation
*
* This software was developed by Konstantin Belousov <kib@FreeBSD.org>
* under sponsorship from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Linker script for ia32 (32bit) vdso on amd64.
*/
OUTPUT_ARCH(i386)
PHDRS
{
text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
dynamic PT_DYNAMIC FLAGS(5);
eh_frame_hdr PT_GNU_EH_FRAME FLAGS(5);
}
SECTIONS
{
. = . + SIZEOF_HEADERS;
.hash : { *(.hash) } :text
.gnu.hash : { *(.gnu.hash) } :text
.dynsym : { *(.dynsym) } :text
.dynstr : { *(.dynstr) } :text
.gnu.version : { *(.gnu.version) } :text
.gnu.version_d : { *(.gnu.version_d) } :text
.gnu.version_r : { *(.gnu.version_r) } :text
.eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
.eh_frame : { KEEP (*(.eh_frame)) } :text
.dynamic : { *(.dynamic) } :text :dynamic
.rodata : { *(.rodata*) } :text
.data : {
*(.got.plt) *(.got)
} :text
/DISCARD/ /* .data */: {
*(.data*)
*(.sdata*)
*(.gnu.linkonce.d.*)
*(.bss*)
*(.dynbss*)
*(.gnu.linkonce.b.*)
*(.ctors)
*(.dtors)
*(.jcr)
*(.init_array)
*(.init)
*(.fini)
*(.debug*)
*(.comment)
}
. = ALIGN(0x10);
.text : { *(.text .text*) } :text =0x90909090
}
VERSION
{
FBSD_1.7 {
global:
__vdso_ia32_sigcode;
__vdso_freebsd4_ia32_sigcode;
__vdso_ia32_osigcode;
__vdso_lcall_tramp;
local:
*;
};
}

View File

@ -108,6 +108,12 @@ struct sysentvec aout_sysvec = {
#elif defined(__amd64__)
#include "vdso_ia32_offsets.h"
extern const char _binary_elf_vdso32_so_1_start[];
extern const char _binary_elf_vdso32_so_1_end[];
extern char _binary_elf_vdso32_so_1_size;
#define AOUT32_PS_STRINGS \
(AOUT32_USRSTACK - sizeof(struct freebsd32_ps_strings))
#define AOUT32_MINUSER FREEBSD32_MINUSER
@ -115,14 +121,16 @@ struct sysentvec aout_sysvec = {
extern const char *freebsd32_syscallnames[];
extern u_long ia32_maxssiz;
static int aout_szsigcode;
struct sysentvec aout_sysvec = {
.sv_size = FREEBSD32_SYS_MAXSYSCALL,
.sv_table = freebsd32_sysent,
.sv_transtrap = NULL,
.sv_fixup = aout_fixup,
.sv_sendsig = ia32_sendsig,
.sv_sigcode = ia32_sigcode,
.sv_szsigcode = &sz_ia32_sigcode,
.sv_sigcode = _binary_elf_vdso32_so_1_start,
.sv_szsigcode = &aout_szsigcode,
.sv_name = "FreeBSD a.out",
.sv_coredump = NULL,
.sv_imgact_try = NULL,
@ -144,6 +152,13 @@ struct sysentvec aout_sysvec = {
.sv_onexit = exit_onexit,
.sv_set_fork_retval = x86_set_fork_retval,
};
static void
aout_sysent(void *arg __unused)
{
aout_szsigcode = (int)(uintptr_t)&_binary_elf_vdso32_so_1_size;
}
SYSINIT(aout_sysent, SI_SUB_EXEC, SI_ORDER_ANY, aout_sysent, NULL);
#else
#error "Only ia32 arch is supported"
#endif

View File

@ -0,0 +1,53 @@
#!/bin/sh
# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
#
# Copyright (c) 2021 The FreeBSD Foundation
# All rights reserved.
#
# This software was developed by Konstantin Belousov <kib@FreeBSD.org>
# under sponsorship from the FreeBSD Foundation.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
set -e
${CC} -x assembler-with-cpp -DLOCORE -fPIC -nostdinc -c -m32 \
-o ia32_sigtramp.pico -I. -I"${S}" -include opt_global.h \
"${S}"/amd64/ia32/ia32_sigtramp.S
${LD} --shared -Bsymbolic -soname="elf-vdso32.so.1" \
-T "${S}"/conf/vdso_amd64_ia32.ldscript \
--eh-frame-hdr --no-undefined -z rodynamic -z norelro -nmagic \
--hash-style=sysv --fatal-warnings --strip-all \
-o elf-vdso32.so.1 ia32_sigtramp.pico
${CC} -x assembler-with-cpp -DLOCORE -fPIC -nostdinc -c \
-o elf-vdso32.so.o -I. -I"${S}" -include opt_global.h \
-DVDSO_NAME=elf_vdso32_so_1 -DVDSO_FILE=elf-vdso32.so.1 \
"${S}"/tools/vdso_wrap.S
${NM} -D elf-vdso32.so.1 | ${AWK} \
'/__vdso_ia32_sigcode/{printf "#define VDSO_IA32_SIGCODE_OFFSET 0x%s\n",$1}
/__vdso_freebsd4_ia32_sigcode/{printf "#define VDSO_FREEBSD4_IA32_SIGCODE_OFFSET 0x%s\n",$1}
/__vdso_ia32_osigcode/{printf "#define VDSO_IA32_OSIGCODE_OFFSET 0x%s\n",$1}
/__vdso_lcall_tramp/{printf "#define VDSO_LCALL_TRAMP_OFFSET 0x%s\n",$1}' \
>vdso_ia32_offsets.h