summaryrefslogtreecommitdiff
path: root/lib/mlibc/tests/rtdl/dl_iterate_phdr
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mlibc/tests/rtdl/dl_iterate_phdr')
-rw-r--r--lib/mlibc/tests/rtdl/dl_iterate_phdr/libbar.c3
-rw-r--r--lib/mlibc/tests/rtdl/dl_iterate_phdr/libfoo.c1
-rw-r--r--lib/mlibc/tests/rtdl/dl_iterate_phdr/meson.build7
-rw-r--r--lib/mlibc/tests/rtdl/dl_iterate_phdr/test.c91
4 files changed, 102 insertions, 0 deletions
diff --git a/lib/mlibc/tests/rtdl/dl_iterate_phdr/libbar.c b/lib/mlibc/tests/rtdl/dl_iterate_phdr/libbar.c
new file mode 100644
index 0000000..41ccc56
--- /dev/null
+++ b/lib/mlibc/tests/rtdl/dl_iterate_phdr/libbar.c
@@ -0,0 +1,3 @@
+// Bar needs to have a relocation against foo in order to set DT_NEEDED.
+int foo(void);
+int bar() { return foo(); }
diff --git a/lib/mlibc/tests/rtdl/dl_iterate_phdr/libfoo.c b/lib/mlibc/tests/rtdl/dl_iterate_phdr/libfoo.c
new file mode 100644
index 0000000..9fe07f8
--- /dev/null
+++ b/lib/mlibc/tests/rtdl/dl_iterate_phdr/libfoo.c
@@ -0,0 +1 @@
+int foo() { return 0; }
diff --git a/lib/mlibc/tests/rtdl/dl_iterate_phdr/meson.build b/lib/mlibc/tests/rtdl/dl_iterate_phdr/meson.build
new file mode 100644
index 0000000..acb679e
--- /dev/null
+++ b/lib/mlibc/tests/rtdl/dl_iterate_phdr/meson.build
@@ -0,0 +1,7 @@
+libfoo = shared_library('foo', 'libfoo.c')
+libbar = shared_library('bar', 'libbar.c', build_rpath: test_rpath, link_with: libfoo)
+test_depends = [libfoo, libbar]
+
+libfoo_native = shared_library('native-foo', 'libfoo.c', native: true)
+libbar_native = shared_library('native-bar', 'libbar.c', build_rpath: test_rpath, link_with: libfoo_native, native: true)
+test_native_depends = [libfoo_native, libbar_native]
diff --git a/lib/mlibc/tests/rtdl/dl_iterate_phdr/test.c b/lib/mlibc/tests/rtdl/dl_iterate_phdr/test.c
new file mode 100644
index 0000000..5d48a41
--- /dev/null
+++ b/lib/mlibc/tests/rtdl/dl_iterate_phdr/test.c
@@ -0,0 +1,91 @@
+#include <assert.h>
+#include <link.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <stdio.h>
+
+#ifdef USE_HOST_LIBC
+#define LDSO_PATTERN "ld-linux-"
+#define LIBFOO "libnative-foo.so"
+#define LIBBAR "libnative-bar.so"
+#else
+#define LDSO_PATTERN "ld.so"
+#define LIBFOO "libfoo.so"
+#define LIBBAR "libbar.so"
+#endif
+
+struct result {
+ int found_ldso;
+ int found_self;
+ int found_foo;
+ int found_bar;
+};
+
+static int ends_with(const char *suffix, const char *s) {
+ size_t suffix_len = strlen(suffix);
+ size_t s_len = strlen(s);
+ if (s_len < suffix_len)
+ return 0;
+ else {
+ return !strcmp(suffix, s + s_len - suffix_len);
+ }
+}
+
+static int contains(const char *pattern, const char *s) {
+ return !!strstr(s, pattern);
+}
+
+static int callback(struct dl_phdr_info *info, size_t size, void *data) {
+ assert(size == sizeof(struct dl_phdr_info));
+ struct result *found = (struct result *) data;
+
+ printf("%s\n", info->dlpi_name);
+ fflush(stdout);
+
+ if (ends_with("foo.so", info->dlpi_name))
+ found->found_foo++;
+ if (ends_with("bar.so", info->dlpi_name))
+ found->found_bar++;
+ if (contains(LDSO_PATTERN, info->dlpi_name))
+ found->found_ldso++;
+
+ if (!strcmp("", info->dlpi_name))
+ found->found_self++;
+
+ assert(info->dlpi_phdr);
+ return 0;
+}
+
+int main() {
+ struct result found = { 0 };
+ assert(!dl_iterate_phdr(callback, &found));
+ assert(found.found_ldso == 1);
+ assert(found.found_self == 1);
+ assert(found.found_foo == 0);
+ assert(found.found_bar == 0);
+ printf("---\n");
+
+ memset(&found, 0, sizeof(found));
+ void *bar = dlopen(LIBBAR, RTLD_LOCAL | RTLD_NOW);
+ assert(bar);
+ assert(!dl_iterate_phdr(callback, &found));
+ assert(found.found_ldso == 1);
+ assert(found.found_self == 1);
+ assert(found.found_bar == 1);
+ assert(found.found_foo == 1); // Since bar depends on foo.
+ printf("---\n");
+
+ memset(&found, 0, sizeof(found));
+ void *foo = dlopen(LIBFOO, RTLD_GLOBAL | RTLD_NOW);
+ assert(foo);
+ assert(!dl_iterate_phdr(callback, &found));
+ assert(found.found_ldso == 1);
+ assert(found.found_self == 1);
+ assert(found.found_foo == 1);
+ assert(found.found_bar == 1);
+ printf("---\n");
+
+ dlclose(bar);
+ dlclose(foo);
+ return 0;
+}