aboutsummaryrefslogtreecommitdiffstats
path: root/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2017-03-21 15:17:26 +0200
committerTimo Teräs <timo.teras@iki.fi>2017-03-21 15:27:08 +0200
commitdd232808d24fb6cba3f06117f5e974effd3051c7 (patch)
treed956a5df2228b1710bd64648e8f05bda2d3d9d8f /main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
parentebada60098b1cfc0d1f7a21bdd3e7ed27af2f873 (diff)
downloadaports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.bz2
aports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.xz
main/musl: cherry-pick ldso improvements and lazy relocation emulation
Diffstat (limited to 'main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch')
-rw-r--r--main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch255
1 files changed, 255 insertions, 0 deletions
diff --git a/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch b/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
new file mode 100644
index 0000000000..03e1da813b
--- /dev/null
+++ b/main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
@@ -0,0 +1,255 @@
+From 4ff234f6cba96403b5de6d29d48a59fd73252040 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Sun, 12 Mar 2017 21:03:05 -0400
+Subject: [PATCH] rework ldso handling of global symbol table for consistency
+
+when loading libraries with dlopen, the caller can request that the
+library's symbols become part of the global symbol table, or that they
+only be used for resolving relocations in the loaded library and its
+dependencies. in the latter case, a subsequent dlopen of the same
+library can upgrade it to global status.
+
+previously, if a library was upgraded from local to global mode, its
+symbols entered the symbol lookup search order at the point where the
+library was originally loaded. this means that a new call to dlopen
+could change the value of a symbol that already had a visible
+definition, an inconsistency which applications could observe.
+
+POSIX is unclear whether this should happen or whether it's permitted
+to happen, but the resolution of Austin Group issue #982 made it
+formally unspecified.
+
+with this patch, a library whose mode is upgraded from local to global
+enters the symbol lookup order at the point where it was made global,
+so that symbol resolution before and after the upgrade are consistent.
+
+in order to implement this change, the per-dso global flag is replaced
+with a separate set of linked-list pointers for participation in the
+global symbol table. this permits the order of dso objects for symbol
+resolution to differ from the order used for iteration of all loaded
+libraries. it also improves performance of find_sym, by avoiding a
+branch per iteration and skipping, and especially in the case where
+many non-global libraries have been loaded, by allowing the loop to
+skip over them entirely. logic for temporarily adding non-global
+libraries to the symbol table for relocation purposes is also mildly
+simplified.
+---
+ ldso/dynlink.c | 97 ++++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 53 insertions(+), 44 deletions(-)
+
+diff --git a/ldso/dynlink.c b/ldso/dynlink.c
+index d00827a3..0e394e0d 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -58,11 +58,11 @@ struct dso {
+ uint32_t *ghashtab;
+ int16_t *versym;
+ char *strings;
++ struct dso *syms_next;
+ unsigned char *map;
+ size_t map_len;
+ dev_t dev;
+ ino_t ino;
+- signed char global;
+ char relocated;
+ char constructed;
+ char kernel_mapped;
+@@ -113,7 +113,7 @@ static struct builtin_tls {
+ static size_t *saved_addends, *apply_addends_to;
+
+ static struct dso ldso;
+-static struct dso *head, *tail, *fini_head;
++static struct dso *head, *tail, *fini_head, *syms_tail;
+ static char *env_path, *sys_path;
+ static unsigned long long gencnt;
+ static int runtime;
+@@ -261,9 +261,8 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
+ uint32_t h = 0, gh, gho, *ght;
+ size_t ghm = 0;
+ struct symdef def = {0};
+- for (; dso; dso=dso->next) {
++ for (; dso; dso=dso->syms_next) {
+ Sym *sym;
+- if (!dso->global) continue;
+ if ((ght = dso->ghashtab)) {
+ if (!ghm) {
+ gh = gnu_hash(s);
+@@ -329,7 +328,7 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ if (sym_index) {
+ sym = syms + sym_index;
+ name = strings + sym->st_name;
+- ctx = type==REL_COPY ? head->next : head;
++ ctx = type==REL_COPY ? head->syms_next : head;
+ def = (sym->st_info&0xf) == STT_SECTION
+ ? (struct symdef){ .dso = dso, .sym = sym }
+ : find_sym(ctx, name, type==REL_PLT);
+@@ -932,7 +931,7 @@ static struct dso *load_library(const char *name, struct dso *needed_by)
+ if (!ldso.prev) {
+ tail->next = &ldso;
+ ldso.prev = tail;
+- tail = ldso.next ? ldso.next : &ldso;
++ tail = &ldso;
+ }
+ return &ldso;
+ }
+@@ -1113,9 +1112,24 @@ static void load_preload(char *s)
+ }
+ }
+
+-static void make_global(struct dso *p)
++static void add_syms(struct dso *p)
+ {
+- for (; p; p=p->next) p->global = 1;
++ if (!p->syms_next && syms_tail != p) {
++ syms_tail->syms_next = p;
++ syms_tail = p;
++ }
++}
++
++static void revert_syms(struct dso *old_tail)
++{
++ struct dso *p, *next;
++ /* Chop off the tail of the list of dsos that participate in
++ * the global symbol table, reverting them to RTLD_LOCAL. */
++ for (p=old_tail; p; p=next) {
++ next = p->syms_next;
++ p->syms_next = 0;
++ }
++ syms_tail = old_tail;
+ }
+
+ static void do_mips_relocs(struct dso *p, size_t *got)
+@@ -1344,7 +1358,6 @@ void __dls2(unsigned char *base, size_t *sp)
+ }
+ Ehdr *ehdr = (void *)ldso.base;
+ ldso.name = ldso.shortname = "libc.so";
+- ldso.global = 1;
+ ldso.phnum = ehdr->e_phnum;
+ ldso.phdr = laddr(&ldso, ehdr->e_phoff);
+ ldso.phentsize = ehdr->e_phentsize;
+@@ -1532,7 +1545,6 @@ _Noreturn void __dls3(size_t *sp)
+ #endif
+ tls_align = MAXP2(tls_align, app.tls.align);
+ }
+- app.global = 1;
+ decode_dyn(&app);
+ if (DL_FDPIC) {
+ makefuncdescs(&app);
+@@ -1547,7 +1559,21 @@ _Noreturn void __dls3(size_t *sp)
+ argv[-3] = (void *)app.loadmap;
+ }
+
+- /* Attach to vdso, if provided by the kernel */
++ /* Initial dso chain consists only of the app. */
++ head = tail = syms_tail = &app;
++
++ /* Donate unused parts of app and library mapping to malloc */
++ reclaim_gaps(&app);
++ reclaim_gaps(&ldso);
++
++ /* Load preload/needed libraries, add symbols to global namespace. */
++ if (env_preload) load_preload(env_preload);
++ load_deps(&app);
++ for (struct dso *p=head; p; p=p->next)
++ add_syms(p);
++
++ /* Attach to vdso, if provided by the kernel, last so that it does
++ * not become part of the global namespace. */
+ if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR) && vdso_base) {
+ Ehdr *ehdr = (void *)vdso_base;
+ Phdr *phdr = vdso.phdr = (void *)(vdso_base + ehdr->e_phoff);
+@@ -1561,26 +1587,13 @@ _Noreturn void __dls3(size_t *sp)
+ }
+ vdso.name = "";
+ vdso.shortname = "linux-gate.so.1";
+- vdso.global = 1;
+ vdso.relocated = 1;
+ decode_dyn(&vdso);
+- vdso.prev = &ldso;
+- ldso.next = &vdso;
++ vdso.prev = tail;
++ tail->next = &vdso;
++ tail = &vdso;
+ }
+
+- /* Initial dso chain consists only of the app. */
+- head = tail = &app;
+-
+- /* Donate unused parts of app and library mapping to malloc */
+- reclaim_gaps(&app);
+- reclaim_gaps(&ldso);
+-
+- /* Load preload/needed libraries, add their symbols to the global
+- * namespace, and perform all remaining relocations. */
+- if (env_preload) load_preload(env_preload);
+- load_deps(&app);
+- make_global(&app);
+-
+ for (i=0; app.dynv[i]; i+=2) {
+ if (!DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG)
+ app.dynv[i+1] = (size_t)&debug;
+@@ -1641,7 +1654,7 @@ _Noreturn void __dls3(size_t *sp)
+
+ void *dlopen(const char *file, int mode)
+ {
+- struct dso *volatile p, *orig_tail, *next;
++ struct dso *volatile p, *orig_tail, *orig_syms_tail, *next;
+ struct tls_module *orig_tls_tail;
+ size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
+ size_t i;
+@@ -1659,15 +1672,14 @@ void *dlopen(const char *file, int mode)
+ orig_tls_cnt = tls_cnt;
+ orig_tls_offset = tls_offset;
+ orig_tls_align = tls_align;
++ orig_syms_tail = syms_tail;
+ orig_tail = tail;
+ noload = mode & RTLD_NOLOAD;
+
+ rtld_fail = &jb;
+ if (setjmp(*rtld_fail)) {
+ /* Clean up anything new that was (partially) loaded */
+- if (p && p->deps) for (i=0; p->deps[i]; i++)
+- if (p->deps[i]->global < 0)
+- p->deps[i]->global = 0;
++ revert_syms(orig_syms_tail);
+ for (p=orig_tail->next; p; p=next) {
+ next = p->next;
+ while (p->td_index) {
+@@ -1703,24 +1715,21 @@ void *dlopen(const char *file, int mode)
+ }
+
+ /* First load handling */
+- if (!p->deps) {
++ if (!p->relocated) {
+ load_deps(p);
++ /* Make new symbols global, at least temporarily, so we can do
++ * relocations. If not RTLD_GLOBAL, this is reverted below. */
++ add_syms(p);
+ if (p->deps) for (i=0; p->deps[i]; i++)
+- if (!p->deps[i]->global)
+- p->deps[i]->global = -1;
+- if (!p->global) p->global = -1;
++ add_syms(p->deps[i]);
+ reloc_all(p);
+- if (p->deps) for (i=0; p->deps[i]; i++)
+- if (p->deps[i]->global < 0)
+- p->deps[i]->global = 0;
+- if (p->global < 0) p->global = 0;
+ }
+
+- if (mode & RTLD_GLOBAL) {
+- if (p->deps) for (i=0; p->deps[i]; i++)
+- p->deps[i]->global = 1;
+- p->global = 1;
+- }
++ /* If RTLD_GLOBAL was not specified, undo any new additions
++ * to the global symbol table. This is a nop if the library was
++ * previously loaded and already global. */
++ if (!(mode & RTLD_GLOBAL))
++ revert_syms(orig_syms_tail);
+
+ update_tls_size();
+ _dl_debug_state();
+--
+2.12.1
+