linux-user/i386: Add vdso
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1267 Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
2fa536d107
commit
a1367443ba
@ -305,12 +305,27 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
|
||||
(*regs)[15] = tswapreg(env->regs[R_ESP]);
|
||||
(*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* i386 is the only target which supplies AT_SYSINFO for the vdso.
|
||||
* All others only supply AT_SYSINFO_EHDR.
|
||||
*/
|
||||
#define DLINFO_ARCH_ITEMS (vdso_info != NULL)
|
||||
#define ARCH_DLINFO \
|
||||
do { \
|
||||
if (vdso_info) { \
|
||||
NEW_AUX_ENT(AT_SYSINFO, vdso_info->entry); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VDSO_HEADER "vdso.c.inc"
|
||||
|
||||
#endif /* TARGET_X86_64 */
|
||||
|
||||
#define USE_ELF_CORE_DUMP
|
||||
#define ELF_EXEC_PAGESIZE 4096
|
||||
|
||||
#endif
|
||||
#endif /* TARGET_I386 */
|
||||
|
||||
#ifdef TARGET_ARM
|
||||
|
||||
|
11
linux-user/i386/Makefile.vdso
Normal file
11
linux-user/i386/Makefile.vdso
Normal file
@ -0,0 +1,11 @@
|
||||
include $(BUILD_DIR)/tests/tcg/i386-linux-user/config-target.mak
|
||||
|
||||
SUBDIR = $(SRC_PATH)/linux-user/i386
|
||||
VPATH += $(SUBDIR)
|
||||
|
||||
all: $(SUBDIR)/vdso.so
|
||||
|
||||
$(SUBDIR)/vdso.so: vdso.S vdso.ld vdso-asmoffset.h
|
||||
$(CC) -o $@ -m32 -nostdlib -shared -Wl,-h,linux-gate.so.1 \
|
||||
-Wl,--build-id=sha1 -Wl,--hash-style=both \
|
||||
-Wl,-T,$(SUBDIR)/vdso.ld $<
|
@ -3,3 +3,10 @@ syscall_nr_generators += {
|
||||
arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
|
||||
output: '@BASENAME@_nr.h')
|
||||
}
|
||||
|
||||
vdso_inc = gen_vdso.process('vdso.so', extra_args: [
|
||||
'-s', '__kernel_sigreturn',
|
||||
'-r', '__kernel_rt_sigreturn'
|
||||
])
|
||||
|
||||
linux_user_ss.add(when: 'TARGET_I386', if_true: vdso_inc)
|
||||
|
@ -214,6 +214,17 @@ struct rt_sigframe {
|
||||
};
|
||||
#define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( \
|
||||
offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET)
|
||||
|
||||
/*
|
||||
* Verify that vdso-asmoffset.h constants match.
|
||||
*/
|
||||
#include "i386/vdso-asmoffset.h"
|
||||
|
||||
QEMU_BUILD_BUG_ON(offsetof(struct sigframe, sc.eip)
|
||||
!= SIGFRAME_SIGCONTEXT_eip);
|
||||
QEMU_BUILD_BUG_ON(offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
|
||||
!= RT_SIGFRAME_SIGCONTEXT_eip);
|
||||
|
||||
#else
|
||||
|
||||
struct rt_sigframe {
|
||||
|
6
linux-user/i386/vdso-asmoffset.h
Normal file
6
linux-user/i386/vdso-asmoffset.h
Normal file
@ -0,0 +1,6 @@
|
||||
/*
|
||||
* offsetof(struct sigframe, sc.eip)
|
||||
* offsetof(struct rt_sigframe, uc.tuc_mcontext.eip)
|
||||
*/
|
||||
#define SIGFRAME_SIGCONTEXT_eip 64
|
||||
#define RT_SIGFRAME_SIGCONTEXT_eip 220
|
143
linux-user/i386/vdso.S
Normal file
143
linux-user/i386/vdso.S
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* i386 linux replacement vdso.
|
||||
*
|
||||
* Copyright 2023 Linaro, Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include "vdso-asmoffset.h"
|
||||
|
||||
.macro endf name
|
||||
.globl \name
|
||||
.type \name, @function
|
||||
.size \name, . - \name
|
||||
.endm
|
||||
|
||||
.macro vdso_syscall1 name, nr
|
||||
\name:
|
||||
.cfi_startproc
|
||||
mov %ebx, %edx
|
||||
.cfi_register %ebx, %edx
|
||||
mov 4(%esp), %ebx
|
||||
mov $\nr, %eax
|
||||
int $0x80
|
||||
mov %edx, %ebx
|
||||
ret
|
||||
.cfi_endproc
|
||||
endf \name
|
||||
.endm
|
||||
|
||||
.macro vdso_syscall2 name, nr
|
||||
\name:
|
||||
.cfi_startproc
|
||||
mov %ebx, %edx
|
||||
.cfi_register %ebx, %edx
|
||||
mov 4(%esp), %ebx
|
||||
mov 8(%esp), %ecx
|
||||
mov $\nr, %eax
|
||||
int $0x80
|
||||
mov %edx, %ebx
|
||||
ret
|
||||
.cfi_endproc
|
||||
endf \name
|
||||
.endm
|
||||
|
||||
.macro vdso_syscall3 name, nr
|
||||
\name:
|
||||
.cfi_startproc
|
||||
push %ebx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset %ebx, 0
|
||||
mov 8(%esp), %ebx
|
||||
mov 12(%esp), %ecx
|
||||
mov 16(%esp), %edx
|
||||
mov $\nr, %eax
|
||||
int $0x80
|
||||
pop %ebx
|
||||
.cfi_adjust_cfa_offset -4
|
||||
.cfi_restore %ebx
|
||||
ret
|
||||
.cfi_endproc
|
||||
endf \name
|
||||
.endm
|
||||
|
||||
__kernel_vsyscall:
|
||||
.cfi_startproc
|
||||
int $0x80
|
||||
ret
|
||||
.cfi_endproc
|
||||
endf __kernel_vsyscall
|
||||
|
||||
vdso_syscall2 __vdso_clock_gettime, __NR_clock_gettime
|
||||
vdso_syscall2 __vdso_clock_gettime64, __NR_clock_gettime64
|
||||
vdso_syscall2 __vdso_clock_getres, __NR_clock_getres
|
||||
vdso_syscall2 __vdso_gettimeofday, __NR_gettimeofday
|
||||
vdso_syscall1 __vdso_time, __NR_time
|
||||
vdso_syscall3 __vdso_getcpu, __NR_gettimeofday
|
||||
|
||||
/*
|
||||
* Signal return handlers.
|
||||
*/
|
||||
|
||||
.cfi_startproc simple
|
||||
.cfi_signal_frame
|
||||
|
||||
/*
|
||||
* For convenience, put the cfa just above eip in sigcontext, and count
|
||||
* offsets backward from there. Re-compute the cfa in the two contexts
|
||||
* we have for signal unwinding. This is far simpler than the
|
||||
* DW_CFA_expression form that the kernel uses, and is equally correct.
|
||||
*/
|
||||
|
||||
.cfi_def_cfa %esp, SIGFRAME_SIGCONTEXT_eip + 4
|
||||
|
||||
.cfi_offset %eip, -4
|
||||
/* err, -8 */
|
||||
/* trapno, -12 */
|
||||
.cfi_offset %eax, -16
|
||||
.cfi_offset %ecx, -20
|
||||
.cfi_offset %edx, -24
|
||||
.cfi_offset %ebx, -28
|
||||
.cfi_offset %esp, -32
|
||||
.cfi_offset %ebp, -36
|
||||
.cfi_offset %esi, -40
|
||||
.cfi_offset %edi, -44
|
||||
|
||||
/*
|
||||
* While this frame is marked as a signal frame, that only applies to how
|
||||
* the return address is handled for the outer frame. The return address
|
||||
* that arrived here, from the inner frame, is not marked as a signal frame
|
||||
* and so the unwinder still tries to subtract 1 to examine the presumed
|
||||
* call insn. Thus we must extend the unwind info to a nop before the start.
|
||||
*/
|
||||
nop
|
||||
|
||||
__kernel_sigreturn:
|
||||
popl %eax /* pop sig */
|
||||
.cfi_adjust_cfa_offset -4
|
||||
movl $__NR_sigreturn, %eax
|
||||
int $0x80
|
||||
endf __kernel_sigreturn
|
||||
|
||||
.cfi_def_cfa_offset RT_SIGFRAME_SIGCONTEXT_eip + 4
|
||||
nop
|
||||
|
||||
__kernel_rt_sigreturn:
|
||||
movl $__NR_rt_sigreturn, %eax
|
||||
int $0x80
|
||||
endf __kernel_rt_sigreturn
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
/*
|
||||
* TODO: Add elf notes. E.g.
|
||||
*
|
||||
* #include <linux/elfnote.h>
|
||||
* ELFNOTE_START(Linux, 0, "a")
|
||||
* .long LINUX_VERSION_CODE
|
||||
* ELFNOTE_END
|
||||
*
|
||||
* but what version number would we set for QEMU?
|
||||
*/
|
76
linux-user/i386/vdso.ld
Normal file
76
linux-user/i386/vdso.ld
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Linker script for linux i386 replacement vdso.
|
||||
*
|
||||
* Copyright 2023 Linaro, Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
ENTRY(__kernel_vsyscall)
|
||||
|
||||
VERSION {
|
||||
LINUX_2.6 {
|
||||
global:
|
||||
__vdso_clock_gettime;
|
||||
__vdso_gettimeofday;
|
||||
__vdso_time;
|
||||
__vdso_clock_getres;
|
||||
__vdso_clock_gettime64;
|
||||
__vdso_getcpu;
|
||||
};
|
||||
|
||||
LINUX_2.5 {
|
||||
global:
|
||||
__kernel_vsyscall;
|
||||
__kernel_sigreturn;
|
||||
__kernel_rt_sigreturn;
|
||||
local: *;
|
||||
};
|
||||
}
|
||||
|
||||
PHDRS {
|
||||
phdr PT_PHDR FLAGS(4) PHDRS;
|
||||
load PT_LOAD FLAGS(7) FILEHDR PHDRS; /* FLAGS=RWX */
|
||||
dynamic PT_DYNAMIC FLAGS(4);
|
||||
eh_frame_hdr PT_GNU_EH_FRAME;
|
||||
note PT_NOTE FLAGS(4);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
. = SIZEOF_HEADERS;
|
||||
|
||||
/*
|
||||
* The following, including the FILEHDRS and PHDRS, are modified
|
||||
* when we relocate the binary. We want them to be initially
|
||||
* writable for the relocation; we'll force them read-only after.
|
||||
*/
|
||||
.note : { *(.note*) } :load :note
|
||||
.dynamic : { *(.dynamic) } :load :dynamic
|
||||
.dynsym : { *(.dynsym) } :load
|
||||
.data : {
|
||||
/*
|
||||
* There ought not be any real read-write data.
|
||||
* But since we manipulated the segment layout,
|
||||
* we have to put these sections somewhere.
|
||||
*/
|
||||
*(.data*)
|
||||
*(.sdata*)
|
||||
*(.got.plt) *(.got)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.bss*)
|
||||
*(.dynbss*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
}
|
||||
|
||||
.rodata : { *(.rodata*) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) } :load :eh_frame_hdr
|
||||
.eh_frame : { *(.eh_frame) } :load
|
||||
|
||||
.text : { *(.text*) } :load =0x90909090
|
||||
}
|
BIN
linux-user/i386/vdso.so
Executable file
BIN
linux-user/i386/vdso.so
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user