aboutsummaryrefslogtreecommitdiffstats
path: root/main/musl/0002-66fcde4a-to-3fa2eb2a.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/musl/0002-66fcde4a-to-3fa2eb2a.patch')
-rw-r--r--main/musl/0002-66fcde4a-to-3fa2eb2a.patch1194
1 files changed, 0 insertions, 1194 deletions
diff --git a/main/musl/0002-66fcde4a-to-3fa2eb2a.patch b/main/musl/0002-66fcde4a-to-3fa2eb2a.patch
deleted file mode 100644
index 5b30442f06..0000000000
--- a/main/musl/0002-66fcde4a-to-3fa2eb2a.patch
+++ /dev/null
@@ -1,1194 +0,0 @@
-diff --git a/Makefile b/Makefile
-index 0ab0bfd..d5a64fc 100644
---- a/Makefile
-+++ b/Makefile
-@@ -125,7 +125,7 @@ $(foreach s,$(wildcard src/*/$(ARCH)*/*.s),$(eval $(call mkasmdep,$(s))))
-
- lib/libc.so: $(LOBJS)
- $(CC) $(CFLAGS_ALL_SHARED) $(LDFLAGS) -nostdlib -shared \
-- -Wl,-e,_start -Wl,-Bsymbolic-functions \
-+ -Wl,-e,_dlstart -Wl,-Bsymbolic-functions \
- -o $@ $(LOBJS) $(LIBCC)
-
- lib/libc.a: $(OBJS)
-diff --git a/arch/arm/reloc.h b/arch/arm/reloc.h
-index 264b7ab..ee39b7f 100644
---- a/arch/arm/reloc.h
-+++ b/arch/arm/reloc.h
-@@ -16,41 +16,29 @@
-
- #define LDSO_ARCH "arm" ENDIAN_SUFFIX FP_SUFFIX
-
--#define IS_COPY(x) ((x)==R_ARM_COPY)
--#define IS_PLT(x) ((x)==R_ARM_JUMP_SLOT)
-+#define NO_LEGACY_INITFINI
-+
-+#define TPOFF_K 8
-
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
- case R_ARM_ABS32:
-- *reloc_addr += sym_val;
-- break;
-+ return REL_SYMBOLIC;
- case R_ARM_GLOB_DAT:
-+ return REL_GOT;
- case R_ARM_JUMP_SLOT:
-- *reloc_addr = sym_val;
-- break;
-+ return REL_PLT;
- case R_ARM_RELATIVE:
-- *reloc_addr += (size_t)base_addr;
-- break;
-+ return REL_RELATIVE;
- case R_ARM_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_ARM_TLS_DTPMOD32:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_ARM_TLS_DTPOFF32:
-- *reloc_addr += def.sym->st_value;
-- break;
-+ return REL_DTPOFF;
- case R_ARM_TLS_TPOFF32:
-- *reloc_addr += def.sym
-- ? def.sym->st_value + def.dso->tls_offset + 8
-- : self->tls_offset + 8;
-- break;
-+ return REL_TPOFF;
- }
-+ return 0;
- }
--
--#define NO_LEGACY_INITFINI
-diff --git a/arch/i386/reloc.h b/arch/i386/reloc.h
-index 3923b54..eaf5aae 100644
---- a/arch/i386/reloc.h
-+++ b/arch/i386/reloc.h
-@@ -3,47 +3,31 @@
-
- #define LDSO_ARCH "i386"
-
--#define IS_COPY(x) ((x)==R_386_COPY)
--#define IS_PLT(x) ((x)==R_386_JMP_SLOT)
--
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
- case R_386_32:
-- *reloc_addr += sym_val;
-- break;
-+ return REL_SYMBOLIC;
- case R_386_PC32:
-- *reloc_addr += sym_val - (size_t)reloc_addr;
-- break;
-+ return REL_OFFSET;
- case R_386_GLOB_DAT:
-+ return REL_GOT;
- case R_386_JMP_SLOT:
-- *reloc_addr = sym_val;
-- break;
-+ return REL_PLT;
- case R_386_RELATIVE:
-- *reloc_addr += (size_t)base_addr;
-- break;
-+ return REL_RELATIVE;
- case R_386_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_386_TLS_DTPMOD32:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_386_TLS_DTPOFF32:
-- *reloc_addr = def.sym->st_value;
-- break;
-+ return REL_DTPOFF;
- case R_386_TLS_TPOFF:
-- *reloc_addr += def.sym
-- ? def.sym->st_value - def.dso->tls_offset
-- : 0 - self->tls_offset;
-- break;
-+ return REL_TPOFF;
- case R_386_TLS_TPOFF32:
-- *reloc_addr += def.sym
-- ? def.dso->tls_offset - def.sym->st_value
-- : self->tls_offset;
-- break;
-+ return REL_TPOFF_NEG;
-+ case R_386_TLS_DESC:
-+ return REL_TLSDESC;
- }
-+ return 0;
- }
-diff --git a/arch/microblaze/reloc.h b/arch/microblaze/reloc.h
-index 7bf3a5b..71a6219 100644
---- a/arch/microblaze/reloc.h
-+++ b/arch/microblaze/reloc.h
-@@ -10,34 +10,27 @@
-
- #define LDSO_ARCH "microblaze" ENDIAN_SUFFIX
-
--#define IS_COPY(x) ((x)==R_MICROBLAZE_COPY)
--#define IS_PLT(x) ((x)==R_MICROBLAZE_JUMP_SLOT)
-+#define TPOFF_K 0
-
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
- case R_MICROBLAZE_32:
-+ return REL_SYMBOLIC;
- case R_MICROBLAZE_GLOB_DAT:
-+ return REL_GOT;
- case R_MICROBLAZE_JUMP_SLOT:
-- *reloc_addr = sym_val + addend;
-- break;
-+ return REL_PLT;
- case R_MICROBLAZE_REL:
-- *reloc_addr = (size_t)base_addr + addend;
-- break;
-+ return REL_RELATIVE;
- case R_MICROBLAZE_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_MICROBLAZE_TLSDTPMOD32:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_MICROBLAZE_TLSDTPREL32:
-- *reloc_addr = def.sym->st_value + addend;
-- break;
-+ return REL_DTPOFF;
- }
-+ return 0;
- }
-
- #include "syscall.h"
-diff --git a/arch/mips/reloc.h b/arch/mips/reloc.h
-index 4ca8125..91fa097 100644
---- a/arch/mips/reloc.h
-+++ b/arch/mips/reloc.h
-@@ -16,38 +16,25 @@
-
- #define LDSO_ARCH "mips" ENDIAN_SUFFIX FP_SUFFIX
-
--#define IS_COPY(x) ((x)==R_MIPS_COPY)
--#define IS_PLT(x) 1
-+#define TPOFF_K (-0x7000)
-
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
-- case R_MIPS_JUMP_SLOT:
-- *reloc_addr = sym_val;
-- break;
- case R_MIPS_REL32:
-- if (sym_val) *reloc_addr += sym_val;
-- else *reloc_addr += (size_t)base_addr;
-- break;
-+ return REL_SYM_OR_REL;
-+ case R_MIPS_JUMP_SLOT:
-+ return REL_PLT;
- case R_MIPS_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_MIPS_TLS_DTPMOD32:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_MIPS_TLS_DTPREL32:
-- *reloc_addr += def.sym->st_value;
-- break;
-+ return REL_DTPOFF;
- case R_MIPS_TLS_TPREL32:
-- *reloc_addr += def.sym
-- ? def.sym->st_value + def.dso->tls_offset - 0x7000
-- : self->tls_offset - 0x7000;
-- break;
-+ return REL_TPOFF;
- }
-+ return 0;
- }
-
- void __reloc_self(int c, size_t *a, size_t *dynv, size_t *got)
-diff --git a/arch/powerpc/reloc.h b/arch/powerpc/reloc.h
-index 38034c5..73c583b 100644
---- a/arch/powerpc/reloc.h
-+++ b/arch/powerpc/reloc.h
-@@ -3,40 +3,29 @@
-
- #define LDSO_ARCH "powerpc"
-
--#define IS_COPY(x) ((x)==R_PPC_COPY)
--#define IS_PLT(x) ((x)==R_PPC_JMP_SLOT)
-+#define TPOFF_K (-0x7000)
-
--// see linux' arch/powerpc/include/asm/elf.h
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
-+ case R_PPC_ADDR32:
-+ return REL_SYMBOLIC;
- case R_PPC_GLOB_DAT:
-+ return REL_GOT;
- case R_PPC_JMP_SLOT:
-- case R_PPC_ADDR32:
-- *reloc_addr = sym_val + addend;
-- break;
-- case R_PPC_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_PLT;
- case R_PPC_RELATIVE:
-- *reloc_addr = (size_t)base_addr + addend;
-- break;
-+ return REL_RELATIVE;
-+ case R_PPC_COPY:
-+ return REL_COPY;
- case R_PPC_DTPMOD32:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_PPC_DTPREL32:
-- *reloc_addr = def.sym->st_value + addend;
-- break;
-+ return REL_DTPOFF;
- case R_PPC_TPREL32:
-- *reloc_addr += def.sym
-- ? def.sym->st_value + def.dso->tls_offset - 0x7000
-- : self->tls_offset - 0x7000;
-- break;
-+ return REL_TPOFF;
- }
-+ return 0;
- }
-
- void __reloc_self(int c, size_t *a, size_t *dynv)
-diff --git a/arch/sh/reloc.h b/arch/sh/reloc.h
-index db3de08..aeb02d0 100644
---- a/arch/sh/reloc.h
-+++ b/arch/sh/reloc.h
-@@ -6,42 +6,29 @@
-
- #define LDSO_ARCH "sh" ENDIAN_SUFFIX
-
--#define IS_COPY(x) ((x) == R_SH_COPY)
--#define IS_PLT(x) ((x) == R_SH_JMP_SLOT)
-+#define TPOFF_K 8
-
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
-+ case R_SH_DIR32:
-+ return REL_SYMBOLIC;
-+ case R_SH_REL32:
-+ return REL_OFFSET;
- case R_SH_GLOB_DAT:
-+ return REL_GOT;
- case R_SH_JMP_SLOT:
-- *reloc_addr = sym_val;
-- break;
-+ return REL_PLT;
- case R_SH_RELATIVE:
-- *reloc_addr = (size_t)base_addr + addend;
-- break;
-- case R_SH_DIR32:
-- *reloc_addr = sym_val + addend;
-- break;
-- case R_SH_REL32:
-- *reloc_addr = sym_val + addend - (size_t)reloc_addr + (size_t)base_addr;
-- break;
-+ return REL_RELATIVE;
- case R_SH_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_SH_TLS_DTPMOD32:
-- *reloc_addr += def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_SH_TLS_DTPOFF32:
-- *reloc_addr += def.sym->st_value;
-- break;
-+ return REL_DTPOFF;
- case R_SH_TLS_TPOFF32:
-- *reloc_addr += def.sym
-- ? def.sym->st_value + def.dso->tls_offset + 8
-- : self->tls_offset + 8;
-- break;
-+ return REL_TPOFF;
- }
-+ return 0;
- }
-diff --git a/arch/x32/reloc.h b/arch/x32/reloc.h
-index f294eec..fcfbf99 100644
---- a/arch/x32/reloc.h
-+++ b/arch/x32/reloc.h
-@@ -4,43 +4,37 @@
-
- #define LDSO_ARCH "x32"
-
--#define IS_COPY(x) ((x)==R_X86_64_COPY)
--#define IS_PLT(x) ((x)==R_X86_64_JUMP_SLOT)
-+/* FIXME: x32 is very strange in its use of 64-bit relocation types in
-+ * a 32-bit environment. As long as the memory at reloc_addr is
-+ * zero-filled prior to relocations, just treating 64-bit relocations
-+ * as operating on 32-bit slots should be fine, but this should be
-+ * checked. In particular, R_X86_64_64, R_X86_64_DTPOFF64, and
-+ * R_X86_64_TPOFF64 may need checking. */
-
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
-- case R_X86_64_GLOB_DAT:
-- case R_X86_64_JUMP_SLOT:
- case R_X86_64_64:
-- *reloc_addr = sym_val + addend;
-- break;
- case R_X86_64_32:
-- *(uint32_t *)reloc_addr = sym_val + addend;
-- break;
-+ return REL_SYMBOLIC;
- case R_X86_64_PC32:
-- *reloc_addr = sym_val + addend - (size_t)reloc_addr + (size_t)base_addr;
-- break;
-+ return REL_OFFSET;
-+ case R_X86_64_GLOB_DAT:
-+ return REL_GOT;
-+ case R_X86_64_JUMP_SLOT:
-+ return REL_PLT;
- case R_X86_64_RELATIVE:
-- *reloc_addr = (size_t)base_addr + addend;
-- break;
-+ return REL_RELATIVE;
- case R_X86_64_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_X86_64_DTPMOD64:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_X86_64_DTPOFF64:
-- *reloc_addr = def.sym->st_value + addend;
-- break;
-+ case R_X86_64_DTPOFF32:
-+ return REL_DTPOFF;
- case R_X86_64_TPOFF64:
-- *reloc_addr = (def.sym
-- ? def.sym->st_value - def.dso->tls_offset
-- : 0 - self->tls_offset) + addend;
-- break;
-+ case R_X86_64_TPOFF32:
-+ return REL_TPOFF;
- }
-+ return 0;
- }
-diff --git a/arch/x86_64/reloc.h b/arch/x86_64/reloc.h
-index 28cf7cc..9bc5849 100644
---- a/arch/x86_64/reloc.h
-+++ b/arch/x86_64/reloc.h
-@@ -4,43 +4,29 @@
-
- #define LDSO_ARCH "x86_64"
-
--#define IS_COPY(x) ((x)==R_X86_64_COPY)
--#define IS_PLT(x) ((x)==R_X86_64_JUMP_SLOT)
--
--static inline void do_single_reloc(
-- struct dso *self, unsigned char *base_addr,
-- size_t *reloc_addr, int type, size_t addend,
-- Sym *sym, size_t sym_size,
-- struct symdef def, size_t sym_val)
-+static int remap_rel(int type)
- {
- switch(type) {
-- case R_X86_64_GLOB_DAT:
-- case R_X86_64_JUMP_SLOT:
- case R_X86_64_64:
-- *reloc_addr = sym_val + addend;
-- break;
-- case R_X86_64_32:
-- *(uint32_t *)reloc_addr = sym_val + addend;
-- break;
-+ return REL_SYMBOLIC;
- case R_X86_64_PC32:
-- *reloc_addr = sym_val + addend - (size_t)reloc_addr + (size_t)base_addr;
-- break;
-+ return REL_OFFSET32;
-+ case R_X86_64_GLOB_DAT:
-+ return REL_GOT;
-+ case R_X86_64_JUMP_SLOT:
-+ return REL_PLT;
- case R_X86_64_RELATIVE:
-- *reloc_addr = (size_t)base_addr + addend;
-- break;
-+ return REL_RELATIVE;
- case R_X86_64_COPY:
-- memcpy(reloc_addr, (void *)sym_val, sym_size);
-- break;
-+ return REL_COPY;
- case R_X86_64_DTPMOD64:
-- *reloc_addr = def.dso ? def.dso->tls_id : self->tls_id;
-- break;
-+ return REL_DTPMOD;
- case R_X86_64_DTPOFF64:
-- *reloc_addr = def.sym->st_value + addend;
-- break;
-+ return REL_DTPOFF;
- case R_X86_64_TPOFF64:
-- *reloc_addr = (def.sym
-- ? def.sym->st_value - def.dso->tls_offset
-- : 0 - self->tls_offset) + addend;
-- break;
-+ return REL_TPOFF;
-+ case R_X86_64_TLSDESC:
-+ return REL_TLSDESC;
- }
-+ return 0;
- }
-diff --git a/include/sys/socket.h b/include/sys/socket.h
-index d752791..b911d6e 100644
---- a/include/sys/socket.h
-+++ b/include/sys/socket.h
-@@ -26,6 +26,17 @@ struct ucred
- uid_t uid;
- gid_t gid;
- };
-+
-+struct mmsghdr
-+{
-+ struct msghdr msg_hdr;
-+ unsigned int msg_len;
-+};
-+
-+struct timespec;
-+
-+int sendmmsg (int, struct mmsghdr *, unsigned int, unsigned int);
-+int recvmmsg (int, struct mmsghdr *, unsigned int, unsigned int, struct timespec *);
- #endif
-
- struct linger
-diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
-index f7eab8d..13cf2ee 100644
---- a/src/env/__init_tls.c
-+++ b/src/env/__init_tls.c
-@@ -53,11 +53,6 @@ void *__copy_tls(unsigned char *mem)
- return td;
- }
-
--void *__tls_get_addr(size_t *v)
--{
-- return (char *)__pthread_self()->dtv[1]+v[1];
--}
--
- #if ULONG_MAX == 0xffffffff
- typedef Elf32_Phdr Phdr;
- #else
-diff --git a/src/ldso/arm/start.s b/src/ldso/arm/start.s
-index dfa3657..5dd93b5 100644
---- a/src/ldso/arm/start.s
-+++ b/src/ldso/arm/start.s
-@@ -1,6 +1,6 @@
- .text
--.global _start
--_start:
-+.global _dlstart
-+_dlstart:
- ldr r0,[sp]
- add r1,sp,#4
- bl __dynlink
-diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c
-index 1cb3fb4..bc4f2f6 100644
---- a/src/ldso/dynlink.c
-+++ b/src/ldso/dynlink.c
-@@ -1,6 +1,8 @@
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
-+#include <stdarg.h>
-+#include <stddef.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdint.h>
-@@ -48,6 +50,11 @@ struct debug {
- void *base;
- };
-
-+struct td_index {
-+ size_t args[2];
-+ struct td_index *next;
-+};
-+
- struct dso {
- unsigned char *base;
- char *name;
-@@ -79,6 +86,7 @@ struct dso {
- void **new_dtv;
- unsigned char *new_tls;
- int new_dtv_idx, new_tls_idx;
-+ struct td_index *td_index;
- struct dso *fini_next;
- char *shortname;
- char buf[];
-@@ -89,6 +97,24 @@ struct symdef {
- struct dso *dso;
- };
-
-+enum {
-+ REL_ERR,
-+ REL_SYMBOLIC,
-+ REL_GOT,
-+ REL_PLT,
-+ REL_RELATIVE,
-+ REL_OFFSET,
-+ REL_OFFSET32,
-+ REL_COPY,
-+ REL_SYM_OR_REL,
-+ REL_TLS, /* everything past here is TLS */
-+ REL_DTPMOD,
-+ REL_DTPOFF,
-+ REL_TPOFF,
-+ REL_TPOFF_NEG,
-+ REL_TLSDESC,
-+};
-+
- #include "reloc.h"
-
- int __init_tp(void *);
-@@ -107,6 +133,7 @@ static jmp_buf *rtld_fail;
- static pthread_rwlock_t lock;
- static struct debug debug;
- static size_t tls_cnt, tls_offset, tls_align = 4*sizeof(size_t);
-+static size_t static_tls_cnt;
- static pthread_mutex_t init_fini_lock = { ._m_type = PTHREAD_MUTEX_RECURSIVE };
- static long long builtin_tls[(sizeof(struct pthread) + 64)/sizeof(long long)];
-
-@@ -132,6 +159,17 @@ static int search_vec(size_t *v, size_t *r, size_t key)
- return 1;
- }
-
-+static void error(const char *fmt, ...)
-+{
-+ va_list ap;
-+ va_start(ap, fmt);
-+ vsnprintf(errbuf, sizeof errbuf, fmt, ap);
-+ va_end(ap);
-+ if (runtime) longjmp(*rtld_fail, 1);
-+ dprintf(2, "%s\n", errbuf);
-+ ldso_fail = 1;
-+}
-+
- static uint32_t sysv_hash(const char *s0)
- {
- const unsigned char *s = (void *)s0;
-@@ -227,6 +265,10 @@ static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
- return def;
- }
-
-+#define NO_INLINE_ADDEND (1<<REL_COPY | 1<<REL_GOT | 1<<REL_PLT)
-+
-+ptrdiff_t __tlsdesc_static(), __tlsdesc_dynamic();
-+
- static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
- {
- unsigned char *base = dso->base;
-@@ -235,36 +277,116 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
- Sym *sym;
- const char *name;
- void *ctx;
-- int type;
-+ int astype, type;
- int sym_index;
- struct symdef def;
-+ size_t *reloc_addr;
-+ size_t sym_val;
-+ size_t tls_val;
-+ size_t addend;
-
- for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
-- type = R_TYPE(rel[1]);
-+ astype = R_TYPE(rel[1]);
-+ if (!astype) continue;
-+ type = remap_rel(astype);
-+ if (!type) {
-+ error(errbuf, sizeof errbuf,
-+ "Error relocating %s: unsupported relocation type %d",
-+ dso->name, astype);
-+ continue;
-+ }
- sym_index = R_SYM(rel[1]);
-+ reloc_addr = (void *)(base + rel[0]);
- if (sym_index) {
- sym = syms + sym_index;
- name = strings + sym->st_name;
-- ctx = IS_COPY(type) ? head->next : head;
-- def = find_sym(ctx, name, IS_PLT(type));
-+ ctx = type==REL_COPY ? head->next : head;
-+ def = find_sym(ctx, name, type==REL_PLT);
- if (!def.sym && (sym->st_shndx != SHN_UNDEF
- || sym->st_info>>4 != STB_WEAK)) {
-- snprintf(errbuf, sizeof errbuf,
-+ error(errbuf, sizeof errbuf,
- "Error relocating %s: %s: symbol not found",
- dso->name, name);
-- if (runtime) longjmp(*rtld_fail, 1);
-- dprintf(2, "%s\n", errbuf);
-- ldso_fail = 1;
- continue;
- }
- } else {
- sym = 0;
- def.sym = 0;
-- def.dso = 0;
-+ def.dso = dso;
-+ }
-+
-+ addend = stride>2 ? rel[2]
-+ : (1<<type & NO_INLINE_ADDEND) ? 0
-+ : *reloc_addr;
-+
-+ sym_val = def.sym ? (size_t)def.dso->base+def.sym->st_value : 0;
-+ tls_val = def.sym ? def.sym->st_value : 0;
-+
-+ switch(type) {
-+ case REL_OFFSET:
-+ addend -= (size_t)reloc_addr;
-+ case REL_SYMBOLIC:
-+ case REL_GOT:
-+ case REL_PLT:
-+ *reloc_addr = sym_val + addend;
-+ break;
-+ case REL_RELATIVE:
-+ *reloc_addr = (size_t)base + addend;
-+ break;
-+ case REL_SYM_OR_REL:
-+ if (sym) *reloc_addr = sym_val + addend;
-+ else *reloc_addr = (size_t)base + addend;
-+ break;
-+ case REL_COPY:
-+ memcpy(reloc_addr, (void *)sym_val, sym->st_size);
-+ break;
-+ case REL_OFFSET32:
-+ *(uint32_t *)reloc_addr = sym_val + addend
-+ - (size_t)reloc_addr;
-+ break;
-+ case REL_DTPMOD:
-+ *reloc_addr = def.dso->tls_id;
-+ break;
-+ case REL_DTPOFF:
-+ *reloc_addr = tls_val + addend;
-+ break;
-+#ifdef TLS_ABOVE_TP
-+ case REL_TPOFF:
-+ *reloc_addr = tls_val + def.dso->tls_offset + TPOFF_K + addend;
-+ break;
-+#else
-+ case REL_TPOFF:
-+ *reloc_addr = tls_val - def.dso->tls_offset + addend;
-+ break;
-+ case REL_TPOFF_NEG:
-+ *reloc_addr = def.dso->tls_offset - tls_val + addend;
-+ break;
-+#endif
-+ case REL_TLSDESC:
-+ if (stride<3) addend = reloc_addr[1];
-+ if (runtime && def.dso->tls_id >= static_tls_cnt) {
-+ struct td_index *new = malloc(sizeof *new);
-+ if (!new) error(errbuf, sizeof errbuf,
-+ "Error relocating %s: cannot allocate TLSDESC for %s",
-+ dso->name, sym ? name : "(local)" );
-+ new->next = dso->td_index;
-+ dso->td_index = new;
-+ new->args[0] = def.dso->tls_id;
-+ new->args[1] = tls_val + addend;
-+ reloc_addr[0] = (size_t)__tlsdesc_dynamic;
-+ reloc_addr[1] = (size_t)new;
-+ } else {
-+ reloc_addr[0] = (size_t)__tlsdesc_static;
-+#ifdef TLS_ABOVE_TP
-+ reloc_addr[1] = tls_val + def.dso->tls_offset
-+ + TPOFF_K + addend;
-+#else
-+ reloc_addr[1] = tls_val - def.dso->tls_offset
-+ + addend;
-+#endif
-+ }
-+ break;
- }
-- do_single_reloc(dso, base, (void *)(base + rel[0]), type,
-- stride>2 ? rel[2] : 0, sym, sym?sym->st_size:0, def,
-- def.sym?(size_t)(def.dso->base+def.sym->st_value):0);
- }
- }
-
-@@ -717,12 +839,9 @@ static void load_deps(struct dso *p)
- if (p->dynv[i] != DT_NEEDED) continue;
- dep = load_library(p->strings + p->dynv[i+1], p);
- if (!dep) {
-- snprintf(errbuf, sizeof errbuf,
-+ error(errbuf, sizeof errbuf,
- "Error loading shared library %s: %m (needed by %s)",
- p->strings + p->dynv[i+1], p->name);
-- if (runtime) longjmp(*rtld_fail, 1);
-- dprintf(2, "%s\n", errbuf);
-- ldso_fail = 1;
- continue;
- }
- if (runtime) {
-@@ -771,12 +890,9 @@ static void reloc_all(struct dso *p)
-
- if (p->relro_start != p->relro_end &&
- mprotect(p->base+p->relro_start, p->relro_end-p->relro_start, PROT_READ) < 0) {
-- snprintf(errbuf, sizeof errbuf,
-+ error(errbuf, sizeof errbuf,
- "Error relocating %s: RELRO protection failed: %m",
- p->name);
-- if (runtime) longjmp(*rtld_fail, 1);
-- dprintf(2, "%s\n", errbuf);
-- ldso_fail = 1;
- }
-
- p->relocated = 1;
-@@ -915,17 +1031,15 @@ void *__copy_tls(unsigned char *mem)
- return td;
- }
-
--void *__tls_get_addr(size_t *v)
-+void *__tls_get_new(size_t *v)
- {
- pthread_t self = __pthread_self();
-- if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]])
-- return (char *)self->dtv[v[0]]+v[1];
-
- /* Block signals to make accessing new TLS async-signal-safe */
- sigset_t set;
-- pthread_sigmask(SIG_BLOCK, SIGALL_SET, &set);
-- if (v[0]<=(size_t)self->dtv[0] && self->dtv[v[0]]) {
-- pthread_sigmask(SIG_SETMASK, &set, 0);
-+ __block_all_sigs(&set);
-+ if (v[0]<=(size_t)self->dtv[0]) {
-+ __restore_sigs(&set);
- return (char *)self->dtv[v[0]]+v[1];
- }
-
-@@ -946,13 +1060,19 @@ void *__tls_get_addr(size_t *v)
- self->dtv = newdtv;
- }
-
-- /* Get new TLS memory from new DSO */
-- unsigned char *mem = p->new_tls +
-- (p->tls_size + p->tls_align) * a_fetch_add(&p->new_tls_idx,1);
-- mem += ((uintptr_t)p->tls_image - (uintptr_t)mem) & (p->tls_align-1);
-- self->dtv[v[0]] = mem;
-- memcpy(mem, p->tls_image, p->tls_len);
-- pthread_sigmask(SIG_SETMASK, &set, 0);
-+ /* Get new TLS memory from all new DSOs up to the requested one */
-+ unsigned char *mem;
-+ for (p=head; ; p=p->next) {
-+ if (!p->tls_id || self->dtv[p->tls_id]) continue;
-+ mem = p->new_tls + (p->tls_size + p->tls_align)
-+ * a_fetch_add(&p->new_tls_idx,1);
-+ mem += ((uintptr_t)p->tls_image - (uintptr_t)mem)
-+ & (p->tls_align-1);
-+ self->dtv[p->tls_id] = mem;
-+ memcpy(mem, p->tls_image, p->tls_len);
-+ if (p->tls_id == v[0]) break;
-+ }
-+ __restore_sigs(&set);
- return mem + v[1];
- }
-
-@@ -1196,6 +1316,7 @@ void *__dynlink(int argc, char **argv)
- dprintf(2, "%s: Thread-local storage not supported by kernel.\n", argv[0]);
- _exit(127);
- }
-+ static_tls_cnt = tls_cnt;
-
- if (ldso_fail) _exit(127);
- if (ldd_mode) _exit(0);
-@@ -1251,6 +1372,11 @@ void *dlopen(const char *file, int mode)
- for (p=orig_tail->next; p; p=next) {
- next = p->next;
- munmap(p->map, p->map_len);
-+ while (p->td_index) {
-+ void *tmp = p->td_index->next;
-+ free(p->td_index);
-+ p->td_index = tmp;
-+ }
- free(p->deps);
- free(p);
- }
-@@ -1314,6 +1440,8 @@ static int invalid_dso_handle(void *h)
- return 1;
- }
-
-+void *__tls_get_addr(size_t *);
-+
- static void *do_dlsym(struct dso *p, const char *s, void *ra)
- {
- size_t i;
-diff --git a/src/ldso/i386/start.s b/src/ldso/i386/start.s
-index b16f8af..c37a1fa 100644
---- a/src/ldso/i386/start.s
-+++ b/src/ldso/i386/start.s
-@@ -1,6 +1,6 @@
- .text
--.global _start
--_start:
-+.global _dlstart
-+_dlstart:
- xor %ebp,%ebp
- pop %edi
- mov %esp,%esi
-diff --git a/src/ldso/i386/tlsdesc.s b/src/ldso/i386/tlsdesc.s
-new file mode 100644
-index 0000000..3ac6129
---- /dev/null
-+++ b/src/ldso/i386/tlsdesc.s
-@@ -0,0 +1,27 @@
-+.text
-+.global __tlsdesc_static
-+.type __tlsdesc_static,@function
-+__tlsdesc_static:
-+ mov 4(%eax),%eax
-+ ret
-+
-+.global __tlsdesc_dynamic
-+.type __tlsdesc_dynamic,@function
-+__tlsdesc_dynamic:
-+ mov 4(%eax),%eax
-+ push %edx
-+ mov %gs:4,%edx
-+ push %ecx
-+ mov (%eax),%ecx
-+ cmp %ecx,(%edx)
-+ jc 1f
-+ mov 4(%eax),%eax
-+ add (%edx,%ecx,4),%eax
-+2: pop %ecx
-+ sub %gs:0,%eax
-+ pop %edx
-+ ret
-+1: push %eax
-+ call __tls_get_addr
-+ pop %ecx
-+ jmp 2b
-diff --git a/src/ldso/microblaze/start.s b/src/ldso/microblaze/start.s
-index 4e0a0e5..067e861 100644
---- a/src/ldso/microblaze/start.s
-+++ b/src/ldso/microblaze/start.s
-@@ -1,6 +1,6 @@
- # FIXME: clearing argv entries
--.global _start
--_start:
-+.global _dlstart
-+_dlstart:
- add r19, r0, r0
-
- lw r5, r0, r1
-diff --git a/src/ldso/mips/start.s b/src/ldso/mips/start.s
-index 2e98529..0cadbf8 100644
---- a/src/ldso/mips/start.s
-+++ b/src/ldso/mips/start.s
-@@ -2,9 +2,9 @@
- .hidden __reloc_self
- .set noreorder
- .set nomacro
--.global _start
--.type _start,@function
--_start:
-+.global _dlstart
-+.type _dlstart,@function
-+_dlstart:
- move $fp, $0
-
- bgezal $0, 1f
-diff --git a/src/ldso/powerpc/start.s b/src/ldso/powerpc/start.s
-index 6c499e8..6548d58 100644
---- a/src/ldso/powerpc/start.s
-+++ b/src/ldso/powerpc/start.s
-@@ -1,6 +1,6 @@
-- .global _start
-- .type _start,@function
--_start:
-+ .global _dlstart
-+ .type _dlstart,@function
-+_dlstart:
- bl 1f
- 2: .long _DYNAMIC-2b
- 1: mflr 5
-diff --git a/src/ldso/sh/start.s b/src/ldso/sh/start.s
-index ca6b7fc..0d2d913 100644
---- a/src/ldso/sh/start.s
-+++ b/src/ldso/sh/start.s
-@@ -1,7 +1,7 @@
- .text
--.global _start
--.type _start, @function
--_start:
-+.global _dlstart
-+.type _dlstart, @function
-+_dlstart:
- mov.l @r15, r4
- mov r15, r5
- mov.l L1, r0
-diff --git a/src/ldso/tlsdesc.c b/src/ldso/tlsdesc.c
-new file mode 100644
-index 0000000..031b5b8
---- /dev/null
-+++ b/src/ldso/tlsdesc.c
-@@ -0,0 +1,13 @@
-+#ifdef SHARED
-+
-+#include <stddef.h>
-+#include "libc.h"
-+
-+ptrdiff_t __tlsdesc_static()
-+{
-+ return 0;
-+}
-+
-+weak_alias(__tlsdesc_static, __tlsdesc_dynamic);
-+
-+#endif
-diff --git a/src/ldso/x32/start.s b/src/ldso/x32/start.s
-index 0fcf46d..3c3800a 100644
---- a/src/ldso/x32/start.s
-+++ b/src/ldso/x32/start.s
-@@ -1,6 +1,6 @@
- .text
--.global _start
--_start:
-+.global _dlstart
-+_dlstart:
- mov (%rsp),%rdi /* move argc into 1st argument slot */
- lea 4(%rsp),%rsi /* move argv into 2nd argument slot */
- call __dynlink
-diff --git a/src/ldso/x86_64/start.s b/src/ldso/x86_64/start.s
-index 80c1d08..1c5598a 100644
---- a/src/ldso/x86_64/start.s
-+++ b/src/ldso/x86_64/start.s
-@@ -1,6 +1,6 @@
- .text
--.global _start
--_start:
-+.global _dlstart
-+_dlstart:
- mov (%rsp),%rdi
- lea 8(%rsp),%rsi
- call __dynlink
-diff --git a/src/ldso/x86_64/tlsdesc.s b/src/ldso/x86_64/tlsdesc.s
-new file mode 100644
-index 0000000..57b78e0
---- /dev/null
-+++ b/src/ldso/x86_64/tlsdesc.s
-@@ -0,0 +1,40 @@
-+.text
-+.global __tlsdesc_static
-+.type __tlsdesc_static,@function
-+__tlsdesc_static:
-+ mov 8(%rax),%rax
-+ ret
-+
-+.global __tlsdesc_dynamic
-+.type __tlsdesc_dynamic,@function
-+__tlsdesc_dynamic:
-+ mov 8(%rax),%rax
-+ push %rdx
-+ mov %fs:8,%rdx
-+ push %rcx
-+ mov (%rax),%rcx
-+ cmp %rcx,(%rdx)
-+ jc 1f
-+ mov 8(%rax),%rax
-+ add (%rdx,%rcx,8),%rax
-+2: pop %rcx
-+ sub %fs:0,%rax
-+ pop %rdx
-+ ret
-+1: push %rdi
-+ push %rdi
-+ push %rsi
-+ push %r8
-+ push %r9
-+ push %r10
-+ push %r11
-+ mov %rax,%rdi
-+ call __tls_get_addr
-+ pop %r11
-+ pop %r10
-+ pop %r9
-+ pop %r8
-+ pop %rsi
-+ pop %rdi
-+ pop %rdi
-+ jmp 2b
-diff --git a/src/linux/fanotify.c b/src/linux/fanotify.c
-index 1f4ef93..c6211af 100644
---- a/src/linux/fanotify.c
-+++ b/src/linux/fanotify.c
-@@ -9,6 +9,6 @@ int fanotify_init(unsigned flags, unsigned event_f_flags)
- int fanotify_mark(int fanotify_fd, unsigned flags, unsigned long long mask,
- int dfd, const char *pathname)
- {
-- return syscall(SYS_fanotify_mark, flags, __SYSCALL_LL_O(mask), dfd, pathname);
-+ return syscall(SYS_fanotify_mark, fanotify_fd, flags, __SYSCALL_LL_E(mask), dfd, pathname);
- }
-
-diff --git a/src/network/recvmmsg.c b/src/network/recvmmsg.c
-new file mode 100644
-index 0000000..58b1b2f
---- /dev/null
-+++ b/src/network/recvmmsg.c
-@@ -0,0 +1,15 @@
-+#define _GNU_SOURCE
-+#include <sys/socket.h>
-+#include <limits.h>
-+#include "syscall.h"
-+
-+int recvmmsg(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags, struct timespec *timeout)
-+{
-+#if LONG_MAX > INT_MAX
-+ struct mmsghdr *mh = msgvec;
-+ unsigned int i;
-+ for (i = vlen; i; i--, mh++)
-+ mh->msg_hdr.__pad1 = mh->msg_hdr.__pad2 = 0;
-+#endif
-+ return syscall_cp(SYS_recvmmsg, fd, msgvec, vlen, flags, timeout);
-+}
-diff --git a/src/network/sendmmsg.c b/src/network/sendmmsg.c
-new file mode 100644
-index 0000000..ff9f861
---- /dev/null
-+++ b/src/network/sendmmsg.c
-@@ -0,0 +1,29 @@
-+#define _GNU_SOURCE
-+#include <sys/socket.h>
-+#include <limits.h>
-+#include <errno.h>
-+#include "syscall.h"
-+
-+int sendmmsg(int fd, struct mmsghdr *msgvec, unsigned int vlen, unsigned int flags)
-+{
-+#if LONG_MAX > INT_MAX
-+ /* Can't use the syscall directly because the kernel has the wrong
-+ * idea for the types of msg_iovlen, msg_controllen, and cmsg_len,
-+ * and the cmsg blocks cannot be modified in-place. */
-+ int i;
-+ if (vlen > IOV_MAX) vlen = IOV_MAX; /* This matches the kernel. */
-+ for (i=0; i<vlen; i++) {
-+ /* As an unfortunate inconsistency, the sendmmsg API uses
-+ * unsigned int for the resulting msg_len, despite sendmsg
-+ * returning ssize_t. However Linux limits the total bytes
-+ * sent by sendmsg to INT_MAX, so the assignment is safe. */
-+ ssize_t r = sendmsg(fd, &msgvec[i].msg_hdr, flags);
-+ if (r < 0) goto error;
-+ msgvec[i].msg_len = r;
-+ }
-+error:
-+ return i ? i : -1;
-+#else
-+ return syscall_cp(SYS_sendmmsg, fd, msgvec, vlen, flags);
-+#endif
-+}
-diff --git a/src/string/memmem.c b/src/string/memmem.c
-index 3b1ae18..d7e1221 100644
---- a/src/string/memmem.c
-+++ b/src/string/memmem.c
-@@ -112,8 +112,8 @@ static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const
- }
-
- /* Compare right half */
-- for (k=MAX(ms+1,mem); n[k] && n[k] == h[k]; k++);
-- if (n[k]) {
-+ for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
-+ if (k < l) {
- h += k-ms;
- mem = 0;
- continue;
-diff --git a/src/thread/__tls_get_addr.c b/src/thread/__tls_get_addr.c
-new file mode 100644
-index 0000000..28ec7f0
---- /dev/null
-+++ b/src/thread/__tls_get_addr.c
-@@ -0,0 +1,17 @@
-+#include <stddef.h>
-+#include "pthread_impl.h"
-+#include "libc.h"
-+
-+void *__tls_get_new(size_t *) ATTR_LIBC_VISIBILITY;
-+
-+void *__tls_get_addr(size_t *v)
-+{
-+ pthread_t self = __pthread_self();
-+#ifdef SHARED
-+ if (v[0]<=(size_t)self->dtv[0])
-+ return (char *)self->dtv[v[0]]+v[1];
-+ return __tls_get_new(v);
-+#else
-+ return (char *)self->dtv[1]+v[1];
-+#endif
-+}
-diff --git a/src/thread/i386/tls.s b/src/thread/i386/tls.s
-index e1f2262..6e01adf 100644
---- a/src/thread/i386/tls.s
-+++ b/src/thread/i386/tls.s
-@@ -2,7 +2,14 @@
- .global ___tls_get_addr
- .type ___tls_get_addr,@function
- ___tls_get_addr:
-- push %eax
-+ mov %gs:4,%edx
-+ mov (%eax),%ecx
-+ cmp %ecx,(%edx)
-+ jc 1f
-+ mov 4(%eax),%eax
-+ add (%edx,%ecx,4),%eax
-+ ret
-+1: push %eax
- call __tls_get_addr
- pop %edx
- ret