From 73c8f83a08161273aeb4c71917a0e8cf6ba59db8 Mon Sep 17 00:00:00 2001 From: sanana Date: Sat, 1 Feb 2025 17:36:40 +0300 Subject: [PATCH] tests/rtld: Add test for breadth-first search order --- tests/rtld/meson.build | 1 + tests/rtld/search-order/libbar.c | 19 +++++++++++++++ tests/rtld/search-order/libfoo.c | 3 +++ tests/rtld/search-order/meson.build | 37 +++++++++++++++++++++++++++++ tests/rtld/search-order/test.c | 21 ++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 tests/rtld/search-order/libbar.c create mode 100644 tests/rtld/search-order/libfoo.c create mode 100644 tests/rtld/search-order/meson.build create mode 100644 tests/rtld/search-order/test.c diff --git a/tests/rtld/meson.build b/tests/rtld/meson.build index 638e50b32..d32939dad 100644 --- a/tests/rtld/meson.build +++ b/tests/rtld/meson.build @@ -13,6 +13,7 @@ rtld_test_cases = [ 'scope3', 'scope4', 'scope5', + 'search-order', 'tls_align', 'relr', 'symver', diff --git a/tests/rtld/search-order/libbar.c b/tests/rtld/search-order/libbar.c new file mode 100644 index 000000000..22f09b0fb --- /dev/null +++ b/tests/rtld/search-order/libbar.c @@ -0,0 +1,19 @@ +#include +#include + +#ifdef USE_HOST_LIBC +#define LIBFOO "libnative-foo.so" +#else +#define LIBFOO "libfoo.so" +#endif + +int foo(void); + +int bar(void) { + return foo() + 0xBABE; +} + +[[constructor]] void init(void) { + void *libfoo = dlopen(LIBFOO, RTLD_LOCAL | RTLD_NOW); + assert(libfoo); +} diff --git a/tests/rtld/search-order/libfoo.c b/tests/rtld/search-order/libfoo.c new file mode 100644 index 000000000..d62656d0e --- /dev/null +++ b/tests/rtld/search-order/libfoo.c @@ -0,0 +1,3 @@ +int foo(void) { + return 0xCAFE0000; +} diff --git a/tests/rtld/search-order/meson.build b/tests/rtld/search-order/meson.build new file mode 100644 index 000000000..dcb5d5847 --- /dev/null +++ b/tests/rtld/search-order/meson.build @@ -0,0 +1,37 @@ +patchelf = find_program('patchelf', required: false) + +if patchelf.found() + # Overwrite LD_LIBRARY_PATH to make meson not fix our shenanigans + # Otherwise, meson's LD_LIBRARY_PATH makes this test useless because libfoo + # will be found through it instead of failing when libfoo is not found + test_env += ['LD_LIBRARY_PATH='] + test_native_env += ['LD_LIBRARY_PATH='] + + libfoo = shared_library('foo', 'libfoo.c') + libbar_unpatched = shared_library('bar-unpatched', 'libbar.c', + dependencies: libc_dep, link_with: libfoo) + libbar = custom_target('patch-libbar', + command: [patchelf, + '--remove-rpath', + '--set-soname', 'libbar.so', + libbar_unpatched, + '--output', '@OUTPUT0@'], + output: ['libbar.so'], + ) + test_link_with = [libbar, libfoo] + + libfoo_native = shared_library('native-foo', 'libfoo.c', native: true) + libbar_native_unpatched = shared_library('native-bar-unpatched', 'libbar.c', + dependencies: rtlib_deps, link_with: libfoo_native, native: true) + libbar_native = custom_target('patch-libnative-bar', + command: [patchelf, + '--remove-rpath', + '--set-soname', 'libnative-bar.so', + libbar_native_unpatched, + '--output', '@OUTPUT0@'], + output: ['libnative-bar.so'], + ) + test_native_link_with = [libbar_native, libfoo_native] +else + test_skipped = true +endif diff --git a/tests/rtld/search-order/test.c b/tests/rtld/search-order/test.c new file mode 100644 index 000000000..986311e0c --- /dev/null +++ b/tests/rtld/search-order/test.c @@ -0,0 +1,21 @@ +#include +#include + +#ifdef USE_HOST_LIBC +#define LIBBAR "libnative-bar.so" +#else +#define LIBBAR "libbar.so" +#endif + +int foo(); +int bar(); + +int main() { + void *libbar = dlopen(LIBBAR, RTLD_LOCAL | RTLD_NOW); + assert(libbar); + + assert(foo() == (int) 0xCAFE0000); + assert(bar() == (int) 0xCAFEBABE); + + return 0; +}