Skip to content

Commit fde9c59

Browse files
compnerdpalmer-dabbelt
authored andcommitted
riscv: explicitly use symbol offsets for VDSO
The current implementation of the `__rt_sigaction` reference computed an absolute offset relative to the mapped base of the VDSO. While this can be handled in the medlow model, the medany model cannot handle this as it is meant to be position independent. The current implementation relied on the BFD linker relaxing the PC-relative relocation into an absolute relocation as it was a near-zero address allowing it to be referenced relative to `zero`. We now extract the offsets and create a generated header allowing the build with LLVM and lld to succeed as we no longer depend on the linker rewriting address references near zero. This change was largely modelled after the ARM64 target which does something similar. Signed-off-by: Saleem Abdulrasool <[email protected]> Tested-by: Nathan Chancellor <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 8341dcf commit fde9c59

File tree

5 files changed

+22
-32
lines changed

5 files changed

+22
-32
lines changed

arch/riscv/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ PHONY += vdso_install
108108
vdso_install:
109109
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso $@
110110

111+
prepare: vdso_prepare
112+
vdso_prepare: prepare0
113+
$(Q)$(MAKE) $(build)=arch/riscv/kernel/vdso include/generated/vdso-offsets.h
114+
111115
ifneq ($(CONFIG_XIP_KERNEL),y)
112116
ifeq ($(CONFIG_RISCV_M_MODE)$(CONFIG_SOC_CANAAN),yy)
113117
KBUILD_IMAGE := $(boot)/loader.bin

arch/riscv/include/asm/vdso.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,15 @@
99
#define _ASM_RISCV_VDSO_H
1010

1111
#include <linux/types.h>
12+
#include <generated/vdso-offsets.h>
1213

1314
#ifndef CONFIG_GENERIC_TIME_VSYSCALL
1415
struct vdso_data {
1516
};
1617
#endif
1718

18-
/*
19-
* The VDSO symbols are mapped into Linux so we can just use regular symbol
20-
* addressing to get their offsets in userspace. The symbols are mapped at an
21-
* offset of 0, but since the linker must support setting weak undefined
22-
* symbols to the absolute address 0 it also happens to support other low
23-
* addresses even when the code model suggests those low addresses would not
24-
* otherwise be availiable.
25-
*/
2619
#define VDSO_SYMBOL(base, name) \
27-
({ \
28-
extern const char __vdso_##name[]; \
29-
(void __user *)((unsigned long)(base) + __vdso_##name); \
30-
})
20+
(void __user *)((unsigned long)(base) + __vdso_##name##_offset)
3121

3222
asmlinkage long sys_riscv_flush_icache(uintptr_t, uintptr_t, uintptr_t);
3323

arch/riscv/kernel/vdso/Makefile

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ ifneq ($(c-gettimeofday-y),)
2323
endif
2424

2525
# Build rules
26-
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds vdso-syms.S
26+
targets := $(obj-vdso) vdso.so vdso.so.dbg vdso.lds
2727
obj-vdso := $(addprefix $(obj)/, $(obj-vdso))
2828

29-
obj-y += vdso.o vdso-syms.o
29+
obj-y += vdso.o
3030
CPPFLAGS_vdso.lds += -P -C -U$(ARCH)
3131

3232
# Disable -pg to prevent insert call site
@@ -44,20 +44,22 @@ $(obj)/vdso.o: $(obj)/vdso.so
4444
# link rule for the .so file, .lds has to be first
4545
$(obj)/vdso.so.dbg: $(obj)/vdso.lds $(obj-vdso) FORCE
4646
$(call if_changed,vdsold)
47-
LDFLAGS_vdso.so.dbg = -shared -s -soname=linux-vdso.so.1 \
47+
LDFLAGS_vdso.so.dbg = -shared -S -soname=linux-vdso.so.1 \
4848
--build-id=sha1 --hash-style=both --eh-frame-hdr
4949

50-
# We also create a special relocatable object that should mirror the symbol
51-
# table and layout of the linked DSO. With ld --just-symbols we can then
52-
# refer to these symbols in the kernel code rather than hand-coded addresses.
53-
$(obj)/vdso-syms.S: $(obj)/vdso.so FORCE
54-
$(call if_changed,so2s)
55-
5650
# strip rule for the .so file
5751
$(obj)/%.so: OBJCOPYFLAGS := -S
5852
$(obj)/%.so: $(obj)/%.so.dbg FORCE
5953
$(call if_changed,objcopy)
6054

55+
# Generate VDSO offsets using helper script
56+
gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh
57+
quiet_cmd_vdsosym = VDSOSYM $@
58+
cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@
59+
60+
include/generated/vdso-offsets.h: $(obj)/vdso.so.dbg FORCE
61+
$(call if_changed,vdsosym)
62+
6163
# actual build commands
6264
# The DSO images are built using a special linker script
6365
# Make sure only to export the intended __vdso_xxx symbol offsets.
@@ -66,11 +68,6 @@ quiet_cmd_vdsold = VDSOLD $@
6668
$(OBJCOPY) $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
6769
rm $@.tmp
6870

69-
# Extracts symbol offsets from the VDSO, converting them into an assembly file
70-
# that contains the same symbols at the same offsets.
71-
quiet_cmd_so2s = SO2S $@
72-
cmd_so2s = $(NM) -D $< | $(srctree)/$(src)/so2s.sh > $@
73-
7471
# install commands for the unstripped file
7572
quiet_cmd_vdso_install = INSTALL $@
7673
cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/$@
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: GPL-2.0
3+
4+
LC_ALL=C
5+
sed -n -e 's/^[0]\+\(0[0-9a-fA-F]*\) . \(__vdso_[a-zA-Z0-9_]*\)$/\#define \2_offset\t0x\1/p'

arch/riscv/kernel/vdso/so2s.sh

Lines changed: 0 additions & 6 deletions
This file was deleted.

0 commit comments

Comments
 (0)