From 98799477a6418d5af555b2d3104b1526af246c7d Mon Sep 17 00:00:00 2001 From: yinchuang Date: Sun, 4 Dec 2022 13:09:30 +0800 Subject: [PATCH] Optimize dlopen performance by reducing search so range Signed-off-by: yinchuang --- porting/linux/user/ldso/dynlink.c | 49 +++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/porting/linux/user/ldso/dynlink.c b/porting/linux/user/ldso/dynlink.c index c72da6e2..705591a0 100644 --- a/porting/linux/user/ldso/dynlink.c +++ b/porting/linux/user/ldso/dynlink.c @@ -162,6 +162,8 @@ struct dso { struct dso **parents; size_t parents_count; size_t parents_capacity; + bool is_global; + bool is_reloc_head_so_dep; struct dso **reloc_can_search_dso_list; size_t reloc_can_search_dso_count; size_t reloc_can_search_dso_capacity; @@ -762,14 +764,20 @@ static void free_reloc_can_search_dso(struct dso *p) } } -static void add_can_search_so_list_in_dso(struct dso *dso, struct dso *start_check_dso) { - struct dso *check_dso = start_check_dso; - while (check_dso) { - if (dso->namespace && check_sym_accessible(check_dso, dso->namespace)) { - add_reloc_can_search_dso(dso, check_dso); +static void add_can_search_so_list_in_dso(struct dso *dso_relocating, struct dso *start_check_dso) { + struct dso *p = start_check_dso; + for (; p; p = p->syms_next) { + if (p->is_global) { /* main exe, ld prelaod so, ldso. */ + add_reloc_can_search_dso(dso_relocating, p); + continue; + } + if (p->is_reloc_head_so_dep) { + if (dso_relocating->namespace && check_sym_accessible(p, dso_relocating->namespace)) { + add_reloc_can_search_dso(dso_relocating, p); + } } - check_dso = check_dso->syms_next; } + return; } @@ -2212,7 +2220,9 @@ static void reloc_all(struct dso *p, const dl_extinfo *extinfo) size_t dyn[DYN_CNT]; for (; p; p=p->next) { if (p->relocated) continue; - add_can_search_so_list_in_dso(p, head); + if (p != &ldso) { + add_can_search_so_list_in_dso(p, head); + } decode_vec(p->dynv, dyn, DYN_CNT); if (NEED_MIPS_GOT_RELOCS) do_mips_relocs(p, laddr(p, dyn[DT_PLTGOT])); @@ -2519,6 +2529,7 @@ hidden void __dls2(unsigned char *base, size_t *sp) ldso.phnum = ehdr->e_phnum; ldso.phdr = laddr(&ldso, ehdr->e_phoff); ldso.phentsize = ehdr->e_phentsize; + ldso.is_global = true; kernel_mapped_dso(&ldso); decode_dyn(&ldso); @@ -2735,6 +2746,7 @@ void __dls3(size_t *sp, size_t *auxv) } argv[-3] = (void *)app.loadmap; } + app.is_global = true; /* Initial dso chain consists only of the app. */ head = tail = syms_tail = &app; @@ -2764,6 +2776,9 @@ void __dls3(size_t *sp, size_t *auxv) if (env_preload) { load_preload(env_preload, get_default_ns(), tasks); } + for (struct dso *q=head; q; q=q->next) { + q->is_global = true; + } preload_deps(&app, tasks); unmap_preloaded_sections(tasks); shuffle_loadtasks(tasks); @@ -2772,11 +2787,16 @@ void __dls3(size_t *sp, size_t *auxv) assign_tls(app.next); #else if (env_preload) load_preload(env_preload, get_default_ns()); + for (struct dso *q=head; q; q=q->next) { + q->is_global = true; + } load_deps(&app, NULL); #endif - for (struct dso *p=head; p; p=p->next) + for (struct dso *p=head; p; p=p->next) { + p->is_reloc_head_so_dep = true; add_syms(p); + } /* Attach to vdso, if provided by the kernel, last so that it does * not become part of the global namespace. */ @@ -2838,6 +2858,9 @@ void __dls3(size_t *sp, size_t *auxv) * copy relocations which depend on libraries' relocations. */ reloc_all(app.next, NULL); reloc_all(&app, NULL); + for (struct dso *q=head; q; q=q->next) { + q->is_reloc_head_so_dep = false; + } /* Actual copying to new TLS needs to happen after relocations, * since the TLS images might have contained relocated addresses. */ @@ -3128,12 +3151,20 @@ static void *dlopen_impl( /* Make new symbols global, at least temporarily, so we can do * relocations. If not RTLD_GLOBAL, this is reverted below. */ add_syms(p); - for (i=0; p->deps[i]; i++) + p->is_reloc_head_so_dep = true; + for (i=0; p->deps[i]; i++) { + p->deps[i]->is_reloc_head_so_dep = true; add_syms(p->deps[i]); + } } + struct dso *reloc_head_so = p; if (!p->relocated) { reloc_all(p, extinfo); } + reloc_head_so->is_reloc_head_so_dep = false; + for (size_t i=0; reloc_head_so->deps[i]; i++) { + reloc_head_so->deps[i]->is_reloc_head_so_dep = false; + } /* If RTLD_GLOBAL was not specified, undo any new additions * to the global symbol table. This is a nop if the library was -- GitLab