pkgs/musl/0002-scudo-add-necessary-plumbing.patch

591 lines
18 KiB
Diff

From 7861991a3c003faf60ac185caf4f08e01077b0aa Mon Sep 17 00:00:00 2001
From: Daryl Ronningen <relms@relms.dev>
Date: Fri, 8 Dec 2023 12:31:42 -0800
Subject: [PATCH 2/6] scudo: add necessary plumbing
---
Makefile | 31 ++++++++++++++--
configure | 72 ++++++++++++++++++++++++++++++++++---
src/env/__init_tls.c | 1 +
src/include/errno.h | 8 +++++
src/include/features.h | 2 ++
src/include/pthread.h | 4 +++
src/include/sys/stat.h | 2 ++
src/include/time.h | 4 +++
src/internal/atomic.h | 4 +++
src/internal/linux/futex.h | 31 ++++++++++++++++
src/internal/pthread_impl.h | 3 ++
src/internal/syscall.h | 4 +++
src/malloc/calloc.c | 4 +++
src/malloc/libc_calloc.c | 4 +++
src/thread/pthread_create.c | 6 ++++
15 files changed, 174 insertions(+), 6 deletions(-)
create mode 100644 src/internal/linux/futex.h
diff --git a/Makefile b/Makefile
index e8cc4436..17158106 100644
--- a/Makefile
+++ b/Makefile
@@ -17,16 +17,19 @@ includedir = $(prefix)/include
libdir = $(prefix)/lib
syslibdir = /lib
-MALLOC_DIR = mallocng
+MALLOC_DIR = scudo
SRC_DIRS = $(addprefix $(srcdir)/,src/* src/malloc/$(MALLOC_DIR) crt ldso $(COMPAT_SRC_DIRS))
BASE_GLOBS = $(addsuffix /*.c,$(SRC_DIRS))
+CPP_GLOBS = $(addsuffix /*.cpp,$(SRC_DIRS))
ARCH_GLOBS = $(addsuffix /$(ARCH)/*.[csS],$(SRC_DIRS))
BASE_SRCS = $(sort $(wildcard $(BASE_GLOBS)))
+CPP_SRCS = $(sort $(wildcard $(CPP_GLOBS)))
ARCH_SRCS = $(sort $(wildcard $(ARCH_GLOBS)))
BASE_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(BASE_SRCS)))
+CPP_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(CPP_SRCS)))
ARCH_OBJS = $(patsubst $(srcdir)/%,%.o,$(basename $(ARCH_SRCS)))
REPLACED_OBJS = $(sort $(subst /$(ARCH)/,/,$(ARCH_OBJS)))
-ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(ARCH_OBJS))))
+ALL_OBJS = $(addprefix obj/, $(filter-out $(REPLACED_OBJS), $(sort $(BASE_OBJS) $(CPP_OBJS) $(ARCH_OBJS))))
LIBC_OBJS = $(filter obj/src/%,$(ALL_OBJS)) $(filter obj/compat/%,$(ALL_OBJS))
LDSO_OBJS = $(filter obj/ldso/%,$(ALL_OBJS:%.o=%.lo))
@@ -45,10 +48,18 @@ CPPFLAGS =
CFLAGS =
CFLAGS_AUTO = -Os -pipe
CFLAGS_C99FSE = -std=c99 -ffreestanding -nostdinc
+CXXFLAGS =
+CXXFLAGS_AUTO = -Os -pipe
+CXXFLAGS_FSE = -std=c++17 -ffreestanding -nostdinc -nostdinc++ -fno-exceptions -fno-rtti -fvisibility=hidden
CFLAGS_ALL = $(CFLAGS_C99FSE)
CFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
+
+CXXFLAGS_ALL = $(CXXFLAGS_FSE)
+CXXFLAGS_ALL += -D_XOPEN_SOURCE=700 -I$(srcdir)/arch/$(ARCH) -I$(srcdir)/arch/generic -Iobj/src/internal -I$(srcdir)/src/include -I$(srcdir)/src/internal -Iobj/include -I$(srcdir)/include
+
CFLAGS_ALL += $(CPPFLAGS) $(CFLAGS_AUTO) $(CFLAGS)
+CXXFLAGS_ALL += $(CPPFLAGS) $(CXXFLAGS_AUTO) $(CXXFLAGS)
LDFLAGS_ALL = $(LDFLAGS_AUTO) $(LDFLAGS)
@@ -117,6 +128,7 @@ obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
$(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
+$(OPTIMIZE_SRCS:$(srcdir)/%.cpp=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.cpp=obj/%.lo): CXXFLAGS += -O3
MEMOPS_OBJS = $(filter %/memcpy.o %/memmove.o %/memcmp.o %/memset.o, $(LIBC_OBJS))
$(MEMOPS_OBJS) $(MEMOPS_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_MEMOPS)
@@ -130,8 +142,17 @@ $(NOSSP_OBJS) $(NOSSP_OBJS:%.o=%.lo): CFLAGS_ALL += $(CFLAGS_NOSSP)
$(CRT_OBJS): CFLAGS_ALL += -DCRT
$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC
+$(LOBJS) $(LDSO_OBJS): CXXFLAGS_ALL += -fPIC
+
+obj/src/malloc/scudo/crc32_hw.lo: CXXFLAGS_ALL += $(CXXFLAGS_CRC)
+
+ifeq (scudo,$(MALLOC_DIR))
+obj/src/malloc/calloc.lo: CFLAGS_ALL += -DLIBC_CALLOC_EXTERNAL
+obj/src/malloc/libc_calloc.lo: CFLAGS_ALL += -DLIBC_CALLOC_EXTERNAL
+endif
CC_CMD = $(CC) $(CFLAGS_ALL) -c -o $@ $<
+CXX_CMD = $(CXX) $(CXXFLAGS_ALL) -c -o $@ $<
# Choose invocation of assembler to be used
ifeq ($(ADD_CFI),yes)
@@ -149,6 +170,9 @@ obj/%.o: $(srcdir)/%.S
obj/%.o: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
+obj/%.o: $(srcdir)/%.cpp $(GENH) $(IMPH)
+ $(CXX_CMD)
+
obj/%.lo: $(srcdir)/%.s
$(AS_CMD)
@@ -158,6 +182,9 @@ obj/%.lo: $(srcdir)/%.S
obj/%.lo: $(srcdir)/%.c $(GENH) $(IMPH)
$(CC_CMD)
+obj/%.lo: $(srcdir)/%.cpp $(GENH) $(IMPH)
+ $(CXX_CMD)
+
lib/libc.so: $(LOBJS) $(LDSO_OBJS)
$(CC) $(CFLAGS_ALL) $(LDFLAGS_ALL) -nostdlib -shared \
-Wl,-e,_dlstart -o $@ $(LOBJS) $(LDSO_OBJS) $(LIBCC)
diff --git a/configure b/configure
index 853bf05e..2a0632fa 100755
--- a/configure
+++ b/configure
@@ -63,6 +63,7 @@ fail () { echo "$*" ; exit 1 ; }
fnmatch () { eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" ; }
cmdexists () { type "$1" >/dev/null 2>&1 ; }
trycc () { test -z "$CC" && cmdexists "$1" && CC=$1 ; }
+trycxx () { test -z "$CXX" && cmdexists "$1" && CXX=$1 ; }
stripdir () {
while eval "fnmatch '*/' \"\${$1}\"" ; do eval "$1=\${$1%/}" ; done
@@ -97,6 +98,20 @@ return 1
fi
}
+tryxflag () {
+printf "checking whether C++ compiler accepts %s... " "$2"
+echo "typedef int x;" > "$tmpc"
+if $CXX $CXXFLAGS_TRY $2 -c -o /dev/null "$tmpc" >/dev/null 2>&1 ; then
+printf "yes\n"
+eval "$1=\"\${$1} \$2\""
+eval "$1=\${$1# }"
+return 0
+else
+printf "no\n"
+return 1
+fi
+}
+
tryldflag () {
printf "checking whether linker accepts %s... " "$2"
echo "typedef int x;" > "$tmpc"
@@ -120,6 +135,10 @@ CFLAGS_AUTO=
CFLAGS_MEMOPS=
CFLAGS_NOSSP=
CFLAGS_TRY=
+CXXFLAGS_FSE=
+CXXFLAGS_AUTO=
+CXXFLAGS_CRC=
+CXXFLAGS_TRY=
LDFLAGS_AUTO=
LDFLAGS_TRY=
OPTIMIZE_GLOBS=
@@ -142,7 +161,7 @@ static=yes
wrapper=auto
gcc_wrapper=no
clang_wrapper=no
-malloc_dir=mallocng
+malloc_dir=scudo
for arg ; do
case "$arg" in
@@ -180,7 +199,9 @@ case "$arg" in
AR=*) AR=${arg#*=} ;;
RANLIB=*) RANLIB=${arg#*=} ;;
CC=*) CC=${arg#*=} ;;
+CXX=*) CXX=${arg#*=} ;;
CFLAGS=*) CFLAGS=${arg#*=} ;;
+CXXFLAGS=*) CXXFLAGS=${arg#*=} ;;
CPPFLAGS=*) CPPFLAGS=${arg#*=} ;;
LDFLAGS=*) LDFLAGS=${arg#*=} ;;
CROSS_COMPILE=*) CROSS_COMPILE=${arg#*=} ;;
@@ -253,6 +274,21 @@ printf "no; compiler output follows:\n%s\n" "$output"
exit 1
fi
+printf "checking for C++ compiler... "
+trycxx ${CROSS_COMPILE}g++
+trycxx ${CROSS_COMPILE}c++
+printf "%s\n" "$CXX"
+test -n "$CXX" || { echo "$0: cannot find a C++ compiler" ; exit 1 ; }
+
+printf "checking whether C++ compiler works... "
+echo "typedef int x;" > "$tmpc"
+if output=$($CXX $CPPFLAGS $CXXFLAGS -c -o /dev/null "$tmpc" 2>&1) ; then
+printf "yes\n"
+else
+printf "no; compiler output follows:\n%s\n" "$output"
+exit 1
+fi
+
#
# Figure out options to force errors on unknown flags.
#
@@ -353,6 +389,14 @@ tryflag CFLAGS_C99FSE -fexcess-precision=standard \
|| { test "$ARCH" = i386 && tryflag CFLAGS_C99FSE -ffloat-store ; }
tryflag CFLAGS_C99FSE -frounding-math
+tryxflag CXXFLAGS_FSE -std=c++17
+tryxflag CXXFLAGS_FSE -nostdinc
+tryxflag CXXFLAGS_FSE -nostdinc++
+tryxflag CXXFLAGS_FSE -fno-exceptions
+tryxflag CXXFLAGS_FSE -fno-rtti
+tryxflag CXXFLAGS_FSE -ffreestanding || tryxflag CXXFLAGS_FSE -fno-builtin
+tryxflag CXXFLAGS_FSE -fvisibility=internal || tryxflag CXXFLAGS_FSE -fvisibility=hidden
+
#
# Semantically we want to insist that our sources follow the
# C rules for type-based aliasing, but most if not all real-world
@@ -388,6 +432,7 @@ fi
# linked with such object files. Fix this.
#
tryflag CFLAGS_C99FSE -Wa,--noexecstack
+tryxflag CXXFLAGS_FSE -Wa,--noexecstack
#
# Check for options to disable stack protector, which needs to be
@@ -405,10 +450,16 @@ tryflag CFLAGS_NOSSP -fno-stack-protector
#
tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns
+# enable the necessary instruction set for hardware crc32
+if test "$ARCH" = "x86_64"; then
+ tryxflag CXXFLAGS_CRC -mcrc32 || tryxflag CXXFLAGS_CRC -msse4.2
+fi
+test "$ARCH" = "aarch64" && tryflag CXXFLAGS_CRC -mcrc
+
#
# Enable debugging if requessted.
#
-test "$debug" = yes && CFLAGS_AUTO=-g
+test "$debug" = yes && CFLAGS_AUTO=-g && CXXFLAGS_AUTO=-g
#
# Preprocess asm files to add extra debugging information if debug is
@@ -445,7 +496,8 @@ xno|x) printf "disabled\n" ; optimize=no ;;
esac
test "$optimize" = no || tryflag CFLAGS_AUTO -Os || tryflag CFLAGS_AUTO -O2
-test "$optimize" = yes && optimize="internal,malloc,string"
+test "$optimize" = no || tryflag CXXFLAGS_AUTO -Os || tryflag CXXFLAGS_AUTO -O2
+test "$optimize" = yes && optimize="internal,malloc,malloc/scudo,string"
if fnmatch 'no|size' "$optimize" ; then :
else
@@ -457,6 +509,7 @@ case "$optimize" in
esac
printf " $this"
case "$this" in
+malloc/scudo) this=$this/*.cpp ;;
*/*.c) ;;
*/*) this=$this*.c ;;
*) this=$this/*.c ;;
@@ -469,6 +522,7 @@ fi
# Always try -pipe
tryflag CFLAGS_AUTO -pipe
+tryxflag CXXFLAGS_AUTO -pipe
#
# If debugging is disabled, omit frame pointer. Modern GCC does this
@@ -478,6 +532,7 @@ tryflag CFLAGS_AUTO -pipe
if fnmatch '-g*|*\ -g*' "$CFLAGS_AUTO $CFLAGS" ; then :
else
tryflag CFLAGS_AUTO -fomit-frame-pointer
+tryxflag CXXFLAGS_AUTO -fomit-frame-pointer
fi
#
@@ -488,6 +543,8 @@ fi
#
tryflag CFLAGS_AUTO -fno-unwind-tables
tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
+tryxflag CXXFLAGS_AUTO -fno-unwind-tables
+tryxflag CXXFLAGS_AUTO -fno-asynchronous-unwind-tables
#
# Attempt to put each function and each data object in its own
@@ -499,6 +556,8 @@ tryflag CFLAGS_AUTO -fno-asynchronous-unwind-tables
#
tryflag CFLAGS_AUTO -ffunction-sections
tryflag CFLAGS_AUTO -fdata-sections
+tryxflag CXXFLAGS_AUTO -ffunction-sections
+tryxflag CXXFLAGS_AUTO -fdata-sections
#
# On x86, make sure we don't have incompatible instruction set
@@ -519,7 +578,7 @@ fi
# to start from a clean slate. So use -w if building with clang. Also
# turn off a common on-by-default cast warning regardless of compiler.
#
-test "$cc_family" = clang && tryflag CFLAGS_AUTO -w
+test "$cc_family" = clang && tryflag CFLAGS_AUTO -w && tryxflag CXXFLAGS_AUTO -w
tryflag CFLAGS_AUTO -Wno-pointer-to-int-cast
@@ -787,11 +846,16 @@ libdir = $libdir
includedir = $includedir
syslibdir = $syslibdir
CC = $CC
+CXX = $CXX
CFLAGS = $CFLAGS
CFLAGS_AUTO = $CFLAGS_AUTO
CFLAGS_C99FSE = $CFLAGS_C99FSE
CFLAGS_MEMOPS = $CFLAGS_MEMOPS
CFLAGS_NOSSP = $CFLAGS_NOSSP
+CXXFLAGS = $CXXFLAGS
+CXXFLAGS_AUTO = $CXXFLAGS_AUTO
+CXXFLAGS_FSE = $CXXFLAGS_FSE
+CXXFLAGS_CRC = $CXXFLAGS_CRC
CPPFLAGS = $CPPFLAGS
LDFLAGS = $LDFLAGS
LDFLAGS_AUTO = $LDFLAGS_AUTO
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index a93141ed..6347577c 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -21,6 +21,7 @@ int __init_tp(void *p)
td->detach_state = DT_JOINABLE;
td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock);
td->locale = &libc.global_locale;
+ td->scudo_tsd = NULL;
td->robust_list.head = &td->robust_list.head;
td->sysinfo = __sysinfo;
td->next = td->prev = td;
diff --git a/src/include/errno.h b/src/include/errno.h
index 8ec49377..547e2af0 100644
--- a/src/include/errno.h
+++ b/src/include/errno.h
@@ -3,6 +3,10 @@
#include "../../include/errno.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#ifdef __GNUC__
__attribute__((const))
#endif
@@ -11,4 +15,8 @@ hidden int *___errno_location(void);
#undef errno
#define errno (*___errno_location())
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/src/include/features.h b/src/include/features.h
index f17bd151..157f2def 100644
--- a/src/include/features.h
+++ b/src/include/features.h
@@ -3,7 +3,9 @@
#include "../../include/features.h"
+#ifndef __cplusplus
#define weak __attribute__((__weak__))
+#endif
#define hidden __attribute__((__visibility__("hidden")))
#define weak_alias(old, new) \
extern __typeof(old) new __attribute__((__weak__, __alias__(#old)))
diff --git a/src/include/pthread.h b/src/include/pthread.h
index 7167d3e1..0107a704 100644
--- a/src/include/pthread.h
+++ b/src/include/pthread.h
@@ -3,6 +3,8 @@
#include "../../include/pthread.h"
+#ifndef __cplusplus
+
hidden int __pthread_once(pthread_once_t *, void (*)(void));
hidden void __pthread_testcancel(void);
hidden int __pthread_setcancelstate(int, int *);
@@ -26,4 +28,6 @@ hidden int __pthread_rwlock_trywrlock(pthread_rwlock_t *);
hidden int __pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
hidden int __pthread_rwlock_unlock(pthread_rwlock_t *);
+#endif /* __cplusplus */
+
#endif
diff --git a/src/include/sys/stat.h b/src/include/sys/stat.h
index 59339bee..cc3af59d 100644
--- a/src/include/sys/stat.h
+++ b/src/include/sys/stat.h
@@ -3,7 +3,9 @@
#include "../../../include/sys/stat.h"
+#ifndef __cplusplus
hidden int __fstat(int, struct stat *);
hidden int __fstatat(int, const char *restrict, struct stat *restrict, int);
+#endif
#endif
diff --git a/src/include/time.h b/src/include/time.h
index cbabde47..8eefd311 100644
--- a/src/include/time.h
+++ b/src/include/time.h
@@ -3,6 +3,8 @@
#include "../../include/time.h"
+#ifndef __cplusplus
+
hidden int __clock_gettime(clockid_t, struct timespec *);
hidden int __clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
@@ -12,4 +14,6 @@ hidden struct tm *__localtime_r(const time_t *restrict, struct tm *restrict);
hidden size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
+#endif /* __cplusplus */
+
#endif
diff --git a/src/internal/atomic.h b/src/internal/atomic.h
index 96c1552d..9c4e720c 100644
--- a/src/internal/atomic.h
+++ b/src/internal/atomic.h
@@ -3,6 +3,8 @@
#include <stdint.h>
+#ifndef __cplusplus
+
#include "atomic_arch.h"
#ifdef a_ll
@@ -330,4 +332,6 @@ static inline int a_clz_32(uint32_t x)
}
#endif
+#endif /* __cplusplus */
+
#endif
diff --git a/src/internal/linux/futex.h b/src/internal/linux/futex.h
new file mode 100644
index 00000000..0e216dcc
--- /dev/null
+++ b/src/internal/linux/futex.h
@@ -0,0 +1,31 @@
+#ifndef _INTERNAL_LINUX_FUTEX_H
+#define _INTERNAL_LINUX_FUTEX_H
+
+extern "C" {
+/* while at it, use the prefixed versions for mmap and so on */
+#include <sys/mman.h>
+/* must be first, otherwise the below include here would result in the syscall
+ * function in unistd being replaced by a macro into what would be invalid code
+ */
+#include <unistd.h>
+/* we include this here, so that linux.cpp in scudo does not use the unistd
+ * syscall definition but instead uses the macro that expands to raw calls
+ */
+#include "syscall.h"
+}
+
+#define mmap __mmap
+#define munmap __munmap
+#define mremap __mremap
+#define madvise __madvise
+#define mprotect __mprotect
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#define FUTEX_PRIVATE_FLAG 128
+
+#define FUTEX_WAIT_PRIVATE (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
+#define FUTEX_WAKE_PRIVATE (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
+
+#endif
diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h
index de2b9d8b..22b39232 100644
--- a/src/internal/pthread_impl.h
+++ b/src/internal/pthread_impl.h
@@ -56,6 +56,7 @@ struct pthread {
volatile int timer_id;
locale_t locale;
volatile int killlock[1];
+ void *scudo_tsd;
char *dlerror_buf;
void *stdio_locks;
@@ -187,6 +188,8 @@ hidden void __tl_lock(void);
hidden void __tl_unlock(void);
hidden void __tl_sync(pthread_t);
+hidden void __malloc_tsd_teardown(void *p);
+
extern hidden volatile int __thread_list_lock;
extern hidden volatile int __abort_lock[1];
diff --git a/src/internal/syscall.h b/src/internal/syscall.h
index 4a446157..a4ae20b5 100644
--- a/src/internal/syscall.h
+++ b/src/internal/syscall.h
@@ -58,6 +58,7 @@ hidden long __syscall_ret(unsigned long),
#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__)
#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))
+#ifndef __cplusplus
static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, syscall_arg_t b, syscall_arg_t c, syscall_arg_t d, syscall_arg_t e, syscall_arg_t f)
{
long r;
@@ -74,6 +75,7 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a,
__scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \
__scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
+#endif /* __cplusplus */
/* fixup legacy 16-bit junk */
@@ -391,8 +393,10 @@ static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a,
#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__)
#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__))
+#ifndef __cplusplus
hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
hidden void *__vdsosym(const char *, const char *);
+#endif
#endif
diff --git a/src/malloc/calloc.c b/src/malloc/calloc.c
index bf6bddca..6aa482c6 100644
--- a/src/malloc/calloc.c
+++ b/src/malloc/calloc.c
@@ -32,6 +32,10 @@ weak_alias(allzerop, __malloc_allzerop);
void *calloc(size_t m, size_t n)
{
+#ifdef LIBC_CALLOC_EXTERNAL
+ if (!__malloc_replaced)
+ return __libc_calloc(m, n);
+#endif
if (n && m > (size_t)-1/n) {
errno = ENOMEM;
return 0;
diff --git a/src/malloc/libc_calloc.c b/src/malloc/libc_calloc.c
index d25eabea..3895c8cf 100644
--- a/src/malloc/libc_calloc.c
+++ b/src/malloc/libc_calloc.c
@@ -1,4 +1,8 @@
+#ifndef LIBC_CALLOC_EXTERNAL
+
#define calloc __libc_calloc
#define malloc __libc_malloc
#include "calloc.c"
+
+#endif
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index 087f6206..b1345b34 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -68,6 +68,7 @@ _Noreturn void __pthread_exit(void *result)
}
__pthread_tsd_run_dtors();
+ __malloc_tsd_teardown(&self->scudo_tsd);
__block_app_sigs(&set);
@@ -319,6 +320,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
new->self = new;
new->tsd = (void *)tsd;
new->locale = &libc.global_locale;
+ new->scudo_tsd = NULL;
if (attr._a_detach) {
new->detach_state = DT_DETACHED;
} else {
@@ -395,3 +397,7 @@ fail:
weak_alias(__pthread_exit, pthread_exit);
weak_alias(__pthread_create, pthread_create);
+
+static void malloc_tsd_teardown(void *p) {}
+
+weak_alias(malloc_tsd_teardown, __malloc_tsd_teardown);
--
2.43.0