From 711283b6f4c872945e49ffba3ff3641ed5a64860 Mon Sep 17 00:00:00 2001 From: guzhihao4 Date: Sun, 13 Aug 2023 18:25:24 +0800 Subject: [PATCH] Fix dlclose error about weak symbol dependency Do unmap_library after all dependent libraries are closed. Test: local test pass & libctest pass Issue: #I7SRPDw Signed-off-by: guzhihao4 Change-Id: Ie27666dfb07e85d7123150ba26797626bbc46c79 --- libc-test/src/functional/BUILD.gn | 7 +++++++ libc-test/src/functional/dlopen.c | 18 ++++++++++++++++++ libc-test/src/functional/dlopen_weak.c | 11 +++++++++++ libc-test/src/functional/dlopen_weak_deps.c | 9 +++++++++ libc-test/src/functional/dlopen_weak_deps.h | 2 ++ porting/linux/user/ldso/dynlink.c | 19 +++++++++++++++---- 6 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 libc-test/src/functional/dlopen_weak.c create mode 100644 libc-test/src/functional/dlopen_weak_deps.c create mode 100644 libc-test/src/functional/dlopen_weak_deps.h diff --git a/libc-test/src/functional/BUILD.gn b/libc-test/src/functional/BUILD.gn index f6935c3b..9a491b20 100644 --- a/libc-test/src/functional/BUILD.gn +++ b/libc-test/src/functional/BUILD.gn @@ -39,6 +39,11 @@ test_sharedlib("tls_align_dso") { } test_sharedlib("atexit_dlclose_dso") { } +test_sharedlib("dlopen_weak_deps") { +} +test_sharedlib("dlopen_weak") { + deps = [ ":dlopen_weak_deps" ] +} group("dso_shared") { testonly = true @@ -51,6 +56,8 @@ group("dso_shared") { ":dlopen_for_load_by_local_dso", ":dlopen_ns_dso", ":dlopen_so_dep_dlopen_ns_dso", + ":dlopen_weak", + ":dlopen_weak_deps", ":tls_align_dso", ":tls_init_dso", ] diff --git a/libc-test/src/functional/dlopen.c b/libc-test/src/functional/dlopen.c index cff78a6d..85e0fa40 100644 --- a/libc-test/src/functional/dlopen.c +++ b/libc-test/src/functional/dlopen.c @@ -121,6 +121,23 @@ void dlopen_dlclose() } } +#define DLOPEN_WEAK "libdlopen_weak.so" +typedef int (*FuncPtr_TestNumber)(int input); + +void dlopen_dlclose_weak() +{ + void* handle = dlopen(DLOPEN_WEAK, RTLD_LAZY | RTLD_GLOBAL); + if (!handle) + t_error("dlopen(name=%s, mode=%d) failed: %s\n", DLOPEN_WEAK, RTLD_LAZY | RTLD_GLOBAL, dlerror()); + FuncPtr_TestNumber fn = (FuncPtr_TestNumber)dlsym(handle, "TestNumber"); + if (fn) { + int ret = fn(12); + if (ret != 0) + t_error("weak symbol relocation error: so_name: %s, symbol: TestNumber\n", DLOPEN_WEAK); + } + dlclose(handle); +} + int main(int argc, char *argv[]) { void *h, *g; @@ -179,6 +196,7 @@ int main(int argc, char *argv[]) dlopen_so_used_by_dlsym(); dlopen_nodelete_and_noload(); dlopen_dlclose(); + dlopen_dlclose_weak(); return t_status; } diff --git a/libc-test/src/functional/dlopen_weak.c b/libc-test/src/functional/dlopen_weak.c new file mode 100644 index 00000000..790dd511 --- /dev/null +++ b/libc-test/src/functional/dlopen_weak.c @@ -0,0 +1,11 @@ +#include "dlopen_weak_deps.h" + +__attribute__((weak)) int TestFunction(int input) +{ + return input % 2; +} + +int TestNumber(int input) +{ + return TestNumber2(input); +} diff --git a/libc-test/src/functional/dlopen_weak_deps.c b/libc-test/src/functional/dlopen_weak_deps.c new file mode 100644 index 00000000..f6b3883c --- /dev/null +++ b/libc-test/src/functional/dlopen_weak_deps.c @@ -0,0 +1,9 @@ +__attribute__((weak)) int TestFunction(int input) +{ + return input % 5; +} + +int TestNumber2(int input) +{ + return TestFunction(input) == 2; +} diff --git a/libc-test/src/functional/dlopen_weak_deps.h b/libc-test/src/functional/dlopen_weak_deps.h new file mode 100644 index 00000000..3f033cf2 --- /dev/null +++ b/libc-test/src/functional/dlopen_weak_deps.h @@ -0,0 +1,2 @@ +int TestNumber2(int input); +__attribute__((weak)) int TestFunction(int input); diff --git a/porting/linux/user/ldso/dynlink.c b/porting/linux/user/ldso/dynlink.c index c8832f63..9acb83a3 100644 --- a/porting/linux/user/ldso/dynlink.c +++ b/porting/linux/user/ldso/dynlink.c @@ -3754,7 +3754,7 @@ static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra) extern int invalidate_exit_funcs(struct dso *p); -static int dlclose_impl(struct dso *p) +static int dlclose_impl(struct dso *p, struct dso **dso_close_list, int *dso_close_list_size) { size_t n; struct dso *d; @@ -3864,7 +3864,9 @@ static int dlclose_impl(struct dso *p) if (p->deps != no_deps) free(p->deps); LD_LOGD("dlclose unloading %{public}s @%{public}p", p->name, p); - unmap_library(p); + + dso_close_list[*dso_close_list_size] = p; + *dso_close_list_size += 1; if (p->parents) { free(p->parents); @@ -3906,16 +3908,25 @@ static int do_dlclose(struct dso *p) memcpy(deps_bak, p->deps, deps_num*sizeof(struct dso*)); } + struct dso **dso_close_list = malloc((deps_num + 1) * sizeof(struct dso*)); + memset(dso_close_list, 0, deps_num + 1); + int dso_close_list_size = 0; + LD_LOGI("do_dlclose name=%{public}s count=%{public}d by_dlopen=%{public}d", p->name, p->nr_dlopen, p->by_dlopen); - dlclose_impl(p); + dlclose_impl(p, dso_close_list, &dso_close_list_size); if (ldclose_deps) { for (size_t i = 0; i < deps_num; i++) { LD_LOGI("do_dlclose name=%{public}s count=%{public}d by_dlopen=%{public}d", deps_bak[i]->name, deps_bak[i]->nr_dlopen, deps_bak[i]->by_dlopen); - dlclose_impl(deps_bak[i]); + dlclose_impl(deps_bak[i], dso_close_list, &dso_close_list_size); } } + for (size_t i = 0; i < dso_close_list_size; i++) { + unmap_library(dso_close_list[i]); + } + + free(dso_close_list); free(deps_bak); return 0; -- GitLab