diff --git a/tests/rtld/meson.build b/tests/rtld/meson.build index c8dfe73647..2a8d852d59 100644 --- a/tests/rtld/meson.build +++ b/tests/rtld/meson.build @@ -15,6 +15,7 @@ rtld_test_cases = [ 'scope5', 'tls_align', 'relr', + 'symver', ] host_libc_rtld_nosan_test_cases = [ diff --git a/tests/rtld/symver/libfoo.c b/tests/rtld/symver/libfoo.c new file mode 100644 index 0000000000..35141700f8 --- /dev/null +++ b/tests/rtld/symver/libfoo.c @@ -0,0 +1,15 @@ +int foo_v1(void) { + return 1; +} + +int foo_v2(void) { + return 2; +} + +int foo_v3(void) { + return 3; +} + +asm(".symver foo_v1, foo@FOO_1"); +asm(".symver foo_v2, foo@FOO_2"); +asm(".symver foo_v3, foo@@FOO_3"); // default version (due to @@ vs @) diff --git a/tests/rtld/symver/libfoo.ver b/tests/rtld/symver/libfoo.ver new file mode 100644 index 0000000000..ee16bdc2d3 --- /dev/null +++ b/tests/rtld/symver/libfoo.ver @@ -0,0 +1,14 @@ +FOO_1 { + global: foo; + local: *; +}; + +FOO_2 { + global: foo; + local: *; +}; + +FOO_3 { + global: foo; + local: *; +}; diff --git a/tests/rtld/symver/meson.build b/tests/rtld/symver/meson.build new file mode 100644 index 0000000000..65dde2f1d1 --- /dev/null +++ b/tests/rtld/symver/meson.build @@ -0,0 +1,11 @@ +version_script = meson.current_source_dir() / 'libfoo.ver' + +libfoo = shared_library('foo', 'libfoo.c', + link_args : ['-Wl,--version-script', version_script]) +test_depends = [libfoo] +test_link_with = [libfoo] + +libfoo_native = shared_library('native-foo', 'libfoo.c', native: true, + link_args : ['-Wl,--version-script', version_script]) +test_native_depends = [libfoo_native] +test_native_link_with = [libfoo_native] diff --git a/tests/rtld/symver/test.c b/tests/rtld/symver/test.c new file mode 100644 index 0000000000..3a53a9f650 --- /dev/null +++ b/tests/rtld/symver/test.c @@ -0,0 +1,39 @@ +#include +#include +#include + +#ifdef USE_HOST_LIBC +#define LIBFOO "libnative-foo.so" +#else +#define LIBFOO "libfoo.so" +#endif + +int foo(void); + +int main() { + int ver = foo(); + fprintf(stderr, "called foo version %d\n", ver); + assert(ver == 3); // version 3 is the default for libfoo.so + + void *libfoo_h = dlopen(LIBFOO, RTLD_GLOBAL | RTLD_NOW); + assert(libfoo_h); + + int (*foo1)(void) = dlvsym(libfoo_h, "foo", "FOO_1"); + assert(foo1); + + int (*foo2)(void) = dlvsym(libfoo_h, "foo", "FOO_2"); + assert(foo2); + + int (*foo3)(void) = dlvsym(libfoo_h, "foo", "FOO_3"); + assert(foo3); + + int (*foo_def)(void) = dlsym(libfoo_h, "foo"); + assert(foo_def); + + assert(foo1() == 1); + assert(foo2() == 2); + assert(foo3() == 3); + assert(foo3 == foo_def); + + return 0; +}