From 6454485dd590a590bb6c64149fd0b0ddd9aa5b7a Mon Sep 17 00:00:00 2001 From: Waldemar Kozaczuk Date: Sat, 17 Mar 2018 14:46:56 -0400 Subject: [PATCH] Add vdso fast syscall compatibility library Some application runtimes like Golang need libvdso in order to lookup time. More specifically on startup Golang gets passed in address of libvdso library so that it can lookup addresses of these 3 function symbols - __vdso_time, __vdso_gettimeofday and __vdso_clock_gettime. For details please look at https://github.com/golang/go/blob/master/src/runtime/vdso_linux.go and https://github.com/golang/go/blob/master/src/runtime/vdso_linux_amd64.go. This patch adds implementation of 3 required functions (vdso.c) and modifies Makefile and bootstrap skeleton files to produce libvdso.so and add it the user image. One of the follow up patches will actually add the logic to pass base address of libvdso ELF as part of auxv when initializing Golang shared object. The alternative to having separate libvdso.so would be linking the __vdso_* functions directly to the loader.elf and passing its base address to auxv but unfortunately it would not work for following reasons: 1. For some reason (possibly a bug) the base address of loader.elf (per object::base()) is 0x0000000000000000 instead of expected 0x0000000000200000x and Golang guards against address 0. 2. Even if the above was not an issue there is high probability that Golang would have not been able to find symbols of __vdso_* functions from loader.elf given that it directly reads content of of the ELF to parse and find the symbols at binary level (it does not use standard dlopen() and dlsym()). The content of this patch was authored by Benoit Canet. Signed-off-by: Waldemar Kozaczuk Message-Id: <1521312416-29803-1-git-send-email-jwkozaczuk@gmail.com> --- Makefile | 7 ++++++- bootfs.manifest.skel | 1 + libc/vdso/vdso.c | 18 ++++++++++++++++++ libc/vdso/vdso.version | 3 +++ usr.manifest.skel | 1 + usr_nozfs.manifest.skel | 1 + 6 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 libc/vdso/vdso.c create mode 100644 libc/vdso/vdso.version diff --git a/Makefile b/Makefile index 8dd237150c..7a36ebc449 100644 --- a/Makefile +++ b/Makefile @@ -1873,6 +1873,11 @@ $(out)/libenviron.so: $(environ_sources) $(makedir) $(call quiet, $(CC) $(CFLAGS) -shared -o $(out)/libenviron.so $(environ_sources), CC libenviron.so) +$(out)/libvdso.so: libc/vdso/vdso.c + $(makedir) + $(call quiet, $(CC) -c -fPIC -o $(out)/libvdso.o libc/vdso/vdso.c, CC libvdso.o) + $(call quiet, $(LD) -shared -fPIC -o $(out)/libvdso.so $(out)/libvdso.o --version-script=libc/vdso/vdso.version, LINK libvdso.so) + bootfs_manifest ?= bootfs.manifest.skel # If parameter "bootfs_manifest" has been changed since the last make, @@ -1885,7 +1890,7 @@ $(bootfs_manifest_dep): phony fi $(out)/bootfs.bin: scripts/mkbootfs.py $(bootfs_manifest) $(bootfs_manifest_dep) $(tools:%=$(out)/%) \ - $(out)/zpool.so $(out)/zfs.so $(out)/libenviron.so + $(out)/zpool.so $(out)/zfs.so $(out)/libenviron.so $(out)/libvdso.so $(call quiet, olddir=`pwd`; cd $(out); $$olddir/scripts/mkbootfs.py -o bootfs.bin -d bootfs.bin.d -m $$olddir/$(bootfs_manifest) \ -D jdkbase=$(jdkbase) -D gccbase=$(gccbase) -D \ glibcbase=$(glibcbase) -D miscbase=$(miscbase), MKBOOTFS $@) diff --git a/bootfs.manifest.skel b/bootfs.manifest.skel index 9816e92b11..41d48b48ff 100644 --- a/bootfs.manifest.skel +++ b/bootfs.manifest.skel @@ -1,4 +1,5 @@ [manifest] +/libvdso.so: libvdso.so /libuutil.so: libuutil.so /zpool.so: zpool.so /libzfs.so: libzfs.so diff --git a/libc/vdso/vdso.c b/libc/vdso/vdso.c new file mode 100644 index 0000000000..92123210db --- /dev/null +++ b/libc/vdso/vdso.c @@ -0,0 +1,18 @@ +//#include "libc.h" +#include +#include + +time_t __vdso_time(time_t *tloc) +{ + return time(tloc); +} + +int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + return gettimeofday(tv, tz); +} + +int __vdso_clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + return clock_gettime(clk_id, tp); +} diff --git a/libc/vdso/vdso.version b/libc/vdso/vdso.version new file mode 100644 index 0000000000..a98ad1a8ec --- /dev/null +++ b/libc/vdso/vdso.version @@ -0,0 +1,3 @@ +LINUX_2.6 { +global: *; +}; diff --git a/usr.manifest.skel b/usr.manifest.skel index 583bdfe5eb..159b73d5cb 100644 --- a/usr.manifest.skel +++ b/usr.manifest.skel @@ -1,5 +1,6 @@ [manifest] /libenviron.so: libenviron.so +/libvdso.so: libvdso.so /zpool.so: zpool.so /libzfs.so: libzfs.so /libuutil.so: libuutil.so diff --git a/usr_nozfs.manifest.skel b/usr_nozfs.manifest.skel index 235b957a28..4875faeac3 100644 --- a/usr_nozfs.manifest.skel +++ b/usr_nozfs.manifest.skel @@ -1,5 +1,6 @@ [manifest] /libenviron.so: libenviron.so +/libvdso.so: libvdso.so /tools/mount-nfs.so: tools/mount/mount-nfs.so /tools/umount.so: tools/mount/umount.so /usr/lib/libgcc_s.so.1: %(gccbase)s/lib64/libgcc_s.so.1