aboutsummaryrefslogtreecommitdiffstats
path: root/main
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
parentebada60098b1cfc0d1f7a21bdd3e7ed27af2f873 (diff)
downloadaports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.bz2
aports-dd232808d24fb6cba3f06117f5e974effd3051c7.tar.xz
main/musl: cherry-pick ldso improvements and lazy relocation emulation
Diffstat (limited to 'main')
-rw-r--r--main/musl/0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch255
-rw-r--r--main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch68
-rw-r--r--main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch172
-rw-r--r--main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch51
-rw-r--r--main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch44
-rw-r--r--main/musl/APKBUILD12
6 files changed, 601 insertions, 1 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
+
diff --git a/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch b/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch
new file mode 100644
index 0000000000..970c2e99ad
--- /dev/null
+++ b/main/musl/0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch
@@ -0,0 +1,68 @@
+From 4823b13a75b40c4408c1101b363ab00fd118fb27 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Mon, 13 Mar 2017 00:30:26 -0400
+Subject: [PATCH] reorder addend handling before symbol lookup in relocation
+ code
+
+these two tasks are independent now, but in order to support lazy
+relocations, the failure path for symbol lookup may want the addend to
+be available.
+---
+ ldso/dynlink.c | 33 +++++++++++++++++----------------
+ 1 file changed, 17 insertions(+), 16 deletions(-)
+
+diff --git a/ldso/dynlink.c b/ldso/dynlink.c
+index 0e394e0d..0bd9d50c 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -323,8 +323,24 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue;
+ type = R_TYPE(rel[1]);
+ if (type == REL_NONE) continue;
+- sym_index = R_SYM(rel[1]);
+ reloc_addr = laddr(dso, rel[0]);
++
++ if (stride > 2) {
++ addend = rel[2];
++ } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) {
++ addend = 0;
++ } else if (reuse_addends) {
++ /* Save original addend in stage 2 where the dso
++ * chain consists of just ldso; otherwise read back
++ * saved addend since the inline one was clobbered. */
++ if (head==&ldso)
++ saved_addends[save_slot] = *reloc_addr;
++ addend = saved_addends[save_slot++];
++ } else {
++ addend = *reloc_addr;
++ }
++
++ sym_index = R_SYM(rel[1]);
+ if (sym_index) {
+ sym = syms + sym_index;
+ name = strings + sym->st_name;
+@@ -345,21 +361,6 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ def.dso = dso;
+ }
+
+- if (stride > 2) {
+- addend = rel[2];
+- } else if (type==REL_GOT || type==REL_PLT|| type==REL_COPY) {
+- addend = 0;
+- } else if (reuse_addends) {
+- /* Save original addend in stage 2 where the dso
+- * chain consists of just ldso; otherwise read back
+- * saved addend since the inline one was clobbered. */
+- if (head==&ldso)
+- saved_addends[save_slot] = *reloc_addr;
+- addend = saved_addends[save_slot++];
+- } else {
+- addend = *reloc_addr;
+- }
+-
+ sym_val = def.sym ? (size_t)laddr(def.dso, def.sym->st_value) : 0;
+ tls_val = def.sym ? def.sym->st_value : 0;
+
+--
+2.12.1
+
diff --git a/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch b/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch
new file mode 100644
index 0000000000..19e3764e68
--- /dev/null
+++ b/main/musl/0018-emulate-lazy-relocation-as-deferrable-relocation.patch
@@ -0,0 +1,172 @@
+From 6476b8135760659b25c93ff9308425ca98a9e777 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Mon, 13 Mar 2017 08:52:41 -0400
+Subject: [PATCH] emulate lazy relocation as deferrable relocation
+
+traditional lazy relocation with call-time plt resolver is
+intentionally not implemented, as it is a huge bug surface and demands
+significant amounts of arch-specific code and requires ongoing
+maintenance to ensure compatibility with applications which make use
+of new additions to the arch's register file in passing function
+arguments.
+
+some applications, however, depend on the ability to dlopen modules
+which have unsatisfied symbol references at the time they are loaded,
+either avoiding use of the affected interfaces or manually loading
+another module to provide the missing definition via their own module
+dependency tracking outside the ELF data structures. while such usage
+is non-conforming, failure to support it has been a significant
+obstacle for users/distributions trying to support affected software,
+particularly the X.org server.
+
+instead of resolving lazy relocations at call time, this patch saves
+unresolved GOT/PLT relocations for deferral and retries them after
+each subsequent dlopen until they are resolved. since dlopen is the
+only time at which the effective global symbol table can change, this
+behavior is not observably different from traditional lazy binding,
+and the required code is minimal.
+---
+ ldso/dynlink.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 66 insertions(+), 3 deletions(-)
+
+diff --git a/ldso/dynlink.c b/ldso/dynlink.c
+index 0bd9d50c..f8db1f82 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -58,7 +58,8 @@ struct dso {
+ uint32_t *ghashtab;
+ int16_t *versym;
+ char *strings;
+- struct dso *syms_next;
++ struct dso *syms_next, *lazy_next;
++ size_t *lazy, lazy_cnt;
+ unsigned char *map;
+ size_t map_len;
+ dev_t dev;
+@@ -113,7 +114,7 @@ static struct builtin_tls {
+ static size_t *saved_addends, *apply_addends_to;
+
+ static struct dso ldso;
+-static struct dso *head, *tail, *fini_head, *syms_tail;
++static struct dso *head, *tail, *fini_head, *syms_tail, *lazy_head;
+ static char *env_path, *sys_path;
+ static unsigned long long gencnt;
+ static int runtime;
+@@ -350,6 +351,13 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ : find_sym(ctx, name, type==REL_PLT);
+ if (!def.sym && (sym->st_shndx != SHN_UNDEF
+ || sym->st_info>>4 != STB_WEAK)) {
++ if (dso->lazy && (type==REL_PLT || type==REL_GOT)) {
++ dso->lazy[3*dso->lazy_cnt+0] = rel[0];
++ dso->lazy[3*dso->lazy_cnt+1] = rel[1];
++ dso->lazy[3*dso->lazy_cnt+2] = addend;
++ dso->lazy_cnt++;
++ continue;
++ }
+ error("Error relocating %s: %s: symbol not found",
+ dso->name, name);
+ if (runtime) longjmp(*rtld_fail, 1);
+@@ -451,6 +459,26 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
+ }
+ }
+
++static void redo_lazy_relocs()
++{
++ struct dso *p = lazy_head, *next;
++ lazy_head = 0;
++ for (; p; p=next) {
++ next = p->lazy_next;
++ size_t size = p->lazy_cnt*3*sizeof(size_t);
++ p->lazy_cnt = 0;
++ do_relocs(p, p->lazy, size, 3);
++ if (p->lazy_cnt) {
++ p->lazy_next = lazy_head;
++ lazy_head = p;
++ } else {
++ free(p->lazy);
++ p->lazy = 0;
++ p->lazy_next = 0;
++ }
++ }
++}
++
+ /* A huge hack: to make up for the wastefulness of shared libraries
+ * needing at least a page of dirty memory even if they have no global
+ * data, we reclaim the gaps at the beginning and end of writable maps
+@@ -1653,9 +1681,31 @@ _Noreturn void __dls3(size_t *sp)
+ for(;;);
+ }
+
++static void prepare_lazy(struct dso *p)
++{
++ size_t dyn[DYN_CNT], n, flags1=0;
++ decode_vec(p->dynv, dyn, DYN_CNT);
++ search_vec(p->dynv, &flags1, DT_FLAGS_1);
++ if (dyn[DT_BIND_NOW] || (dyn[DT_FLAGS] & DF_BIND_NOW) || (flags1 & DF_1_NOW))
++ return;
++ n = dyn[DT_RELSZ]/2 + dyn[DT_RELASZ]/3 + dyn[DT_PLTRELSZ]/2 + 1;
++ if (NEED_MIPS_GOT_RELOCS) {
++ size_t j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM);
++ size_t i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO);
++ n += i-j;
++ }
++ p->lazy = calloc(n, 3*sizeof(size_t));
++ if (!p->lazy) {
++ error("Error preparing lazy relocation for %s: %m", p->name);
++ longjmp(*rtld_fail, 1);
++ }
++ p->lazy_next = lazy_head;
++ lazy_head = p;
++}
++
+ void *dlopen(const char *file, int mode)
+ {
+- struct dso *volatile p, *orig_tail, *orig_syms_tail, *next;
++ struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next;
+ struct tls_module *orig_tls_tail;
+ size_t orig_tls_cnt, orig_tls_offset, orig_tls_align;
+ size_t i;
+@@ -1673,6 +1723,7 @@ void *dlopen(const char *file, int mode)
+ orig_tls_cnt = tls_cnt;
+ orig_tls_offset = tls_offset;
+ orig_tls_align = tls_align;
++ orig_lazy_head = lazy_head;
+ orig_syms_tail = syms_tail;
+ orig_tail = tail;
+ noload = mode & RTLD_NOLOAD;
+@@ -1701,6 +1752,7 @@ void *dlopen(const char *file, int mode)
+ tls_cnt = orig_tls_cnt;
+ tls_offset = orig_tls_offset;
+ tls_align = orig_tls_align;
++ lazy_head = orig_lazy_head;
+ tail = orig_tail;
+ tail->next = 0;
+ p = 0;
+@@ -1718,6 +1770,12 @@ void *dlopen(const char *file, int mode)
+ /* First load handling */
+ if (!p->relocated) {
+ load_deps(p);
++ if ((mode & RTLD_LAZY)) {
++ prepare_lazy(p);
++ if (p->deps) for (i=0; p->deps[i]; i++)
++ if (!p->deps[i]->relocated)
++ prepare_lazy(p->deps[i]);
++ }
+ /* Make new symbols global, at least temporarily, so we can do
+ * relocations. If not RTLD_GLOBAL, this is reverted below. */
+ add_syms(p);
+@@ -1732,6 +1790,11 @@ void *dlopen(const char *file, int mode)
+ if (!(mode & RTLD_GLOBAL))
+ revert_syms(orig_syms_tail);
+
++ /* Processing of deferred lazy relocations must not happen until
++ * the new libraries are committed; otherwise we could end up with
++ * relocations resolved to symbol definitions that get removed. */
++ redo_lazy_relocs();
++
+ update_tls_size();
+ _dl_debug_state();
+ orig_tail = tail;
+--
+2.12.1
+
diff --git a/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch b/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch
new file mode 100644
index 0000000000..4ad7149fc8
--- /dev/null
+++ b/main/musl/0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch
@@ -0,0 +1,51 @@
+From a393d5cc8d22b628fcc1da1b3a2cdae42ca643a9 Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Wed, 15 Mar 2017 16:50:19 -0400
+Subject: [PATCH] precalculate gnu hash rather than doing it lazily in find_sym
+ inner loop
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+this change was suggested based on testing done by Timo Teräs almost
+two years ago; the branch (and probably call prep overhead) in the
+inner loop was found to contribute noticably to total symbol lookup
+time. this change will make lookup slightly slower if libraries were
+built with only the traditional "sysv" ELF hash table, but based on
+how much slower lookup tends to be without the gnu hash table, it
+seems reasonable to assume that (1) users building without gnu hash
+don't care about dynamic linking performance, and (2) the extra time
+spent computing the gnu hash is likely to be dominated by the slowness
+of the sysv hash table lookup anyway.
+---
+ ldso/dynlink.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/ldso/dynlink.c b/ldso/dynlink.c
+index 178fe27e..5361b844 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -258,18 +258,12 @@ static Sym *gnu_lookup_filtered(uint32_t h1, uint32_t *hashtab, struct dso *dso,
+
+ 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;
++ uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght;
++ size_t ghm = 1ul << gh % (8*sizeof(size_t));
+ struct symdef def = {0};
+ for (; dso; dso=dso->syms_next) {
+ Sym *sym;
+ if ((ght = dso->ghashtab)) {
+- if (!ghm) {
+- gh = gnu_hash(s);
+- int maskbits = 8 * sizeof ghm;
+- gho = gh / maskbits;
+- ghm = 1ul << gh % maskbits;
+- }
+ sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
+ } else {
+ if (!h) h = sysv_hash(s);
+--
+2.12.1
+
diff --git a/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch b/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch
new file mode 100644
index 0000000000..81fd2d7145
--- /dev/null
+++ b/main/musl/0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch
@@ -0,0 +1,44 @@
+From 0c53178ec09478ca5f6ca6b5ad09d50a10c8f19d Mon Sep 17 00:00:00 2001
+From: Rich Felker <dalias@aerifal.cx>
+Date: Tue, 21 Mar 2017 08:35:59 -0400
+Subject: [PATCH] fix dlopen/dlsym regression opening libs already loaded at
+ startup
+
+commit 4ff234f6cba96403b5de6d29d48a59fd73252040 erroneously changed
+the condition for running certain code at dlopen time to check whether
+the library was already relocated rather than whether it already had
+its deps[] table filled. this was out of concern over whether the code
+under the conditional would be idempotent/safe to call on an
+already-loaded libraries. however, I missed a consideration in the
+opposite direction: if a library was loaded at program startup rather
+than dlopen, its deps[] table was not yet allocated/filled, and
+load_deps needs to be called at dlopen time in order for dlsym to be
+able to perform dependency-order symbol lookups.
+
+in order to avoid wasteful allocation of lazy-binding relocation
+tables for libraries which were already loaded and relocated at
+startup, the check for !p->relocated is not deleted entirely, but
+moved to apply only to allocation of these dables.
+---
+ ldso/dynlink.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ldso/dynlink.c b/ldso/dynlink.c
+index 5361b844..d20dbd87 100644
+--- a/ldso/dynlink.c
++++ b/ldso/dynlink.c
+@@ -1768,9 +1768,9 @@ void *dlopen(const char *file, int mode)
+ }
+
+ /* First load handling */
+- if (!p->relocated) {
++ if (!p->deps) {
+ load_deps(p);
+- if ((mode & RTLD_LAZY)) {
++ if (!p->relocated && (mode & RTLD_LAZY)) {
+ prepare_lazy(p);
+ if (p->deps) for (i=0; p->deps[i]; i++)
+ if (!p->deps[i]->relocated)
+--
+2.12.1
+
diff --git a/main/musl/APKBUILD b/main/musl/APKBUILD
index 3425bba77b..6987757653 100644
--- a/main/musl/APKBUILD
+++ b/main/musl/APKBUILD
@@ -2,7 +2,7 @@
# Maintainer: Timo Teräs <timo.teras@iki.fi>
pkgname=musl
pkgver=1.1.16
-pkgrel=5
+pkgrel=6
pkgdesc="the musl c library (libc) implementation"
url="http://www.musl-libc.org/"
arch="all"
@@ -32,6 +32,9 @@ source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz
0013-fix-lsearch-and-lfind-to-pass-key-as-first-arg-to-th.patch
0014-fix-ld-behavior-dependent-crash-in-ppc64-ldso-startu.patch
0015-treat-STB_WEAK-and-STB_GNU_UNIQUE-like-STB_GLOBAL-in.patch
+ 0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
+ 0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch
+ 0018-emulate-lazy-relocation-as-deferrable-relocation.patch
0019-fix-free-of-uninitialized-buffer-pointer-on-error-in.patch
0020-in-static-dl_iterate_phdr-fix-use-of-possibly-uninit.patch
0021-fix-possible-fd-leak-unrestored-cancellation-state-o.patch
@@ -40,8 +43,10 @@ source="http://www.musl-libc.org/releases/musl-$pkgver.tar.gz
0024-avoid-loading-of-multiple-libc-versions-via-explicit.patch
0025-remove-unused-refcnt-field-for-shared-libraries.patch
0026-fix-threshold-constants-in-j0f-y0f-j1f-y1f.patch
+ 0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch
0028-s390x-fix-fpreg_t-and-remove-unused-per_struct.patch
0029-fix-POSIX-format-TZ-dst-transition-times-for-souther.patch
+ 0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch
ldconfig
__stack_chk_fail_local.c
@@ -177,6 +182,9 @@ d73358b5377db7b708dd8fecda8f6bdae007423e853cde86b33ce5078e31761eab3f2169541aca5b
e3fe35bf310c9d5813553e6762c66764b384a9c2f405e3ba3cea887ff55f6bcd947e55012c5f3e06e16a66d5f289b694ac898fc9b1d4bb0cfb50cf92135e36a3 0013-fix-lsearch-and-lfind-to-pass-key-as-first-arg-to-th.patch
7a6cd67a5ca246eaedb992f9267bb94b0baccbbd5bb9a6a10a503f623ef052480fc4832da4330b5d3531f239580fdb9e36072f456fe4dd2e9ca6ae6050c55aab 0014-fix-ld-behavior-dependent-crash-in-ppc64-ldso-startu.patch
48d4fd3510404b2fe934dffb2fc725c6a31e30e33421dc81073673d680d00866890f9c826bf48874845c863db52ebbb015c9e94b45c7a20b6949236f76f81709 0015-treat-STB_WEAK-and-STB_GNU_UNIQUE-like-STB_GLOBAL-in.patch
+41b8ba87082e586393b6c9570b7fc32455832a4a294ca1bb344f9eb72cd971be92cd03e590508cc1cd44fea532ab860690f38daaae665c68864302a20f11a01d 0016-rework-ldso-handling-of-global-symbol-table-for-cons.patch
+cad53ef772bc3ceae7695304df2a202d01a72cd4a707cffa9a7489947c9151ddd72bd2e2672e6508f56ec188973c886a0a99f85d4a4c54306284fe1b241c52db 0017-reorder-addend-handling-before-symbol-lookup-in-relo.patch
+e4935a23787e5eb5df4f1d487c10d63d4d2f34509ba5871c40037229f09057caad0679d12c444d7e7c5c719c2106e1b130921275d2ed3b1b8ffc6c97c9dde67a 0018-emulate-lazy-relocation-as-deferrable-relocation.patch
0754297d5e2cc9d2244835badb39325b0907604e377ddbabbb865a12429741c71b461ee9f19ebdebc6bd9b6e878919b2bc292b113e1477591171627623dbf557 0019-fix-free-of-uninitialized-buffer-pointer-on-error-in.patch
0fb792b688bea5024a59645eda680c57c509ad5f6923c8816647644ce5b438f18ef2036b4252ae2993c003e0e192d3a0cfd1f909d5a8c3cd8c21ef1130fca929 0020-in-static-dl_iterate_phdr-fix-use-of-possibly-uninit.patch
5cb2e43b01d30b9552668508bc4e855c7e90b323c811bf34989eae97b8cfbdccbe50e13bf95cac727314c0077af823eb4666318e53cb2d4584052b2870c36a3b 0021-fix-possible-fd-leak-unrestored-cancellation-state-o.patch
@@ -185,8 +193,10 @@ efabb66abd01dbf73d89933328beffb738d71b227f7d7dd48b02ca0c9b04b554475bde70a814317b
b1141d2b5c28d16848dcd8b40182938d634023a4aa0e7f0be567fa7e6c40c03431574e9214949e723a031f90a6c20153ca1a6c21eda3b8ea05de5cebf6b1fe38 0024-avoid-loading-of-multiple-libc-versions-via-explicit.patch
955882a1a2a3e7211e20527858ca5dc0944b5d44fdacb547e0d4b4bd27fdf63672b95e16faa4b37e9ee4b384e7f33ce394ee556a201be6011630c84ebf64b312 0025-remove-unused-refcnt-field-for-shared-libraries.patch
dad1ed979898ddaa0a49c601160a948ba229b251307210a14240e4ebf6230b16ffc0138f396fc226942c487e196211964449e7314f83d208ac219a071a4e11b3 0026-fix-threshold-constants-in-j0f-y0f-j1f-y1f.patch
+9b91076729245d4192c01b82700898e8baca0d3db11fdb5f257f88a40d3d59442c30d13434a81e4a067553e28477ceea9edd0960c49da9bba684147dd645a85d 0027-precalculate-gnu-hash-rather-than-doing-it-lazily-in.patch
0472694cdd5a95b8df9b0e585afc7171ae9138133832ad7c0fadae4ea0a742eaa09a4d4449197ccaaefeae99c3cb7ec784068243a3a2d434429a0455c396e6bb 0028-s390x-fix-fpreg_t-and-remove-unused-per_struct.patch
33c24b895bcf1b84d90a522328b39d5b0a4aff822d0701f2f9db07a6c44c49bb3a8b16a19150c550b4fe04fad40e9af43fdf5e1fda0201e9779a471088fe9f23 0029-fix-POSIX-format-TZ-dst-transition-times-for-souther.patch
+adcb5b213ebd9fc5d50cc46d4444ed64a4f928a6b4767428d7d720c6a563ba1d4a3173d6546b41379356b155a26eaad652d7b831776cc3f31e942f155db9239d 0030-fix-dlopen-dlsym-regression-opening-libs-already-loa.patch
8d3a2d5315fc56fee7da9abb8b89bb38c6046c33d154c10d168fb35bfde6b0cf9f13042a3bceee34daf091bc409d699223735dcf19f382eeee1f6be34154f26f ldconfig
062bb49fa54839010acd4af113e20f7263dde1c8a2ca359b5fb2661ef9ed9d84a0f7c3bc10c25dcfa10bb3c5a4874588dff636ac43d5dbb3d748d75400756d0b __stack_chk_fail_local.c
0d80f37b34a35e3d14b012257c50862dfeb9d2c81139ea2dfa101d981d093b009b9fa450ba27a708ac59377a48626971dfc58e20a3799084a65777a0c32cbc7d getconf.c