From d04430f4efbe6253521ce66f295add7ede33d1c4 Mon Sep 17 00:00:00 2001
From: Justine Tunney <jtunney@gmail.com>
Date: Tue, 9 May 2023 08:08:56 -0700
Subject: [PATCH] Get LIBC_MEM and LIBC_STDIO building with aarch64

---
 dsp/tty/ident.c                               |  3 +-
 dsp/tty/identclear.c                          |  2 +-
 libc/calls/interrupts-nt.c                    |  1 -
 libc/dns/freehoststxt.c                       |  8 +-
 libc/dns/freeresolvconf.c                     |  6 +-
 libc/intrin/asan.c                            |  7 +-
 libc/intrin/cmpxchg16b.internal.h             | 46 ----------
 libc/intrin/futex.S                           | 10 +-
 libc/intrin/intrin.mk                         |  2 +
 libc/intrin/lockcmpxchg.h                     | 24 -----
 libc/intrin/lockcmpxchg16b.h                  | 46 ----------
 libc/intrin/lockcmpxchgp.h                    | 24 -----
 libc/intrin/lockxchg.h                        | 31 -------
 libc/intrin/xchg.internal.h                   |  1 -
 libc/log/memlog.c                             |  2 +-
 libc/log/oncrash.c                            |  2 +-
 libc/mem/arena.c                              |  2 +-
 libc/mem/{bulk_free.S => bulk_free.c}         | 34 ++++---
 libc/mem/{calloc.S => calloc.c}               | 36 +++++---
 libc/mem/{free.S => free.c}                   | 41 +++++----
 libc/mem/gc.c                                 |  4 +
 libc/mem/{hook => }/hook.internal.h           |  8 +-
 libc/mem/hook/bulk_free.S                     | 31 -------
 libc/mem/hook/calloc.S                        | 32 -------
 libc/mem/hook/free.S                          | 33 -------
 libc/mem/hook/malloc.S                        | 32 -------
 libc/mem/hook/malloc_trim.S                   | 32 -------
 libc/mem/hook/malloc_usable_size.S            | 31 -------
 libc/mem/hook/memalign.S                      | 32 -------
 libc/mem/hook/realloc.S                       | 32 -------
 libc/mem/hook/realloc_in_place.S              | 32 -------
 ...loc_in_place.S => hook_realloc_in_place.c} | 49 +++++-----
 libc/mem/{malloc.S => malloc.c}               | 51 ++++++-----
 libc/mem/malloc_trim.S                        | 27 ------
 libc/{runtime/free_s.c => mem/malloc_trim.c}  | 22 +++--
 ...loc_usable_size.S => malloc_usable_size.c} | 55 ++++++-----
 libc/mem/mem.mk                               | 15 +--
 libc/mem/{memalign.S => memalign.c}           | 45 +++++----
 libc/mem/{realloc.S => realloc.c}             | 91 ++++++++++---------
 libc/nexgen32e/bench.h                        |  6 +-
 libc/nexgen32e/kcrc32ctab.S                   | 40 --------
 libc/runtime/runtime.h                        |  1 -
 libc/sock/epoll.c                             |  4 +
 libc/sock/nointernet.c                        |  4 +
 libc/stdio/fflushimpl.c                       |  4 +-
 libc/stdio/g_rando.S                          | 30 ------
 libc/stdio/{fclose_s.c => g_rando.c}          | 10 +-
 libc/stdio/stderr-init.S                      | 39 --------
 libc/stdio/stderr.c                           | 19 ++--
 libc/stdio/stdin-init.S                       | 35 -------
 libc/stdio/stdin.c                            | 18 ++--
 libc/stdio/stdio.h                            |  1 -
 libc/stdio/stdout-init.S                      | 37 --------
 libc/stdio/stdout.c                           | 28 +++---
 libc/str/crc32c.c                             | 58 ++----------
 libc/str/crc32z.c                             |  2 -
 libc/testlib/clearxmmregisters.c              |  2 +
 libc/testlib/getcore.c                        |  4 +
 libc/testlib/showerror.c                      |  9 +-
 libc/thread/pthread_cancel.c                  |  4 +
 net/https/sslcache.c                          |  8 +-
 test/libc/mem/arraylist_test.c                | 14 ++-
 test/libc/runtime/grow_test.c                 | 12 +--
 third_party/dlmalloc/dlmalloc.c               |  4 +-
 third_party/dlmalloc/dlmalloc.h               |  2 +-
 third_party/dlmalloc/dlmalloc.mk              | 12 +--
 third_party/dlmalloc/init.S                   | 27 ------
 third_party/dlmalloc/init.inc                 |  4 +-
 third_party/ggml/ggml.mk                      |  7 +-
 third_party/zlib/adler32simd.c                |  4 +
 third_party/zlib/zlib.mk                      |  4 +-
 tool/build/lib/interner.c                     |  4 +-
 tool/build/rle.c                              | 17 ++--
 tool/decode/lib/bitabuilder.c                 |  7 +-
 tool/viz/comma.c                              |  6 +-
 tool/viz/invertblocks.c                       |  6 +-
 tool/viz/lib/formatstringtable.c              |  5 +-
 tool/viz/od16.c                               |  6 +-
 tool/viz/rgbtoxterm.c                         |  6 +-
 tool/viz/tabalign.c                           |  6 +-
 tool/viz/xterm256effective2.c                 |  6 +-
 81 files changed, 440 insertions(+), 1064 deletions(-)
 delete mode 100644 libc/intrin/cmpxchg16b.internal.h
 delete mode 100644 libc/intrin/lockcmpxchg.h
 delete mode 100644 libc/intrin/lockcmpxchg16b.h
 delete mode 100644 libc/intrin/lockcmpxchgp.h
 delete mode 100644 libc/intrin/lockxchg.h
 rename libc/mem/{bulk_free.S => bulk_free.c} (66%)
 rename libc/mem/{calloc.S => calloc.c} (69%)
 rename libc/mem/{free.S => free.c} (67%)
 rename libc/mem/{hook => }/hook.internal.h (71%)
 delete mode 100644 libc/mem/hook/bulk_free.S
 delete mode 100644 libc/mem/hook/calloc.S
 delete mode 100644 libc/mem/hook/free.S
 delete mode 100644 libc/mem/hook/malloc.S
 delete mode 100644 libc/mem/hook/malloc_trim.S
 delete mode 100644 libc/mem/hook/malloc_usable_size.S
 delete mode 100644 libc/mem/hook/memalign.S
 delete mode 100644 libc/mem/hook/realloc.S
 delete mode 100644 libc/mem/hook/realloc_in_place.S
 rename libc/mem/{realloc_in_place.S => hook_realloc_in_place.c} (58%)
 rename libc/mem/{malloc.S => malloc.c} (60%)
 delete mode 100644 libc/mem/malloc_trim.S
 rename libc/{runtime/free_s.c => mem/malloc_trim.c} (81%)
 rename libc/mem/{malloc_usable_size.S => malloc_usable_size.c} (60%)
 rename libc/mem/{memalign.S => memalign.c} (62%)
 rename libc/mem/{realloc.S => realloc.c} (50%)
 delete mode 100644 libc/nexgen32e/kcrc32ctab.S
 delete mode 100644 libc/stdio/g_rando.S
 rename libc/stdio/{fclose_s.c => g_rando.c} (89%)
 delete mode 100644 libc/stdio/stderr-init.S
 delete mode 100644 libc/stdio/stdin-init.S
 delete mode 100644 libc/stdio/stdout-init.S
 delete mode 100644 third_party/dlmalloc/init.S

diff --git a/dsp/tty/ident.c b/dsp/tty/ident.c
index 45f7e83e3..602a5212f 100644
--- a/dsp/tty/ident.c
+++ b/dsp/tty/ident.c
@@ -90,7 +90,8 @@ int ttyident(struct TtyIdent *ti, int ttyinfd, int ttyoutfd) {
                            : _weaken(malloc)(sizeof(struct TtyIdent))))) {
           memcpy(ti->next, &outer, sizeof(outer));
         } else {
-          free_s(&ti->next);
+          free(ti->next);
+          ti->next = 0;
         }
       }
       ttyrestore(ttyinfd, &old);
diff --git a/dsp/tty/identclear.c b/dsp/tty/identclear.c
index 825ec3d60..752fb6707 100644
--- a/dsp/tty/identclear.c
+++ b/dsp/tty/identclear.c
@@ -26,7 +26,7 @@ static void ttyidentfree(struct TtyIdent *ti) {
   if (ti) {
     assert(ti != ti->next);
     ttyidentfree(ti->next);
-    free_s(&ti);
+    free(ti);
   }
 }
 
diff --git a/libc/calls/interrupts-nt.c b/libc/calls/interrupts-nt.c
index b30c2fcb1..e1a276168 100644
--- a/libc/calls/interrupts-nt.c
+++ b/libc/calls/interrupts-nt.c
@@ -26,7 +26,6 @@
 #include "libc/calls/syscall_support-nt.internal.h"
 #include "libc/dce.h"
 #include "libc/errno.h"
-#include "libc/intrin/lockcmpxchgp.h"
 #include "libc/intrin/strace.internal.h"
 #include "libc/intrin/weaken.h"
 #include "libc/sysv/errfuns.h"
diff --git a/libc/dns/freehoststxt.c b/libc/dns/freehoststxt.c
index d586adc10..2998f6ae7 100644
--- a/libc/dns/freehoststxt.c
+++ b/libc/dns/freehoststxt.c
@@ -17,6 +17,7 @@
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/dns/hoststxt.h"
+#include "libc/mem/mem.h"
 #include "libc/runtime/runtime.h"
 
 /**
@@ -24,8 +25,9 @@
  */
 void FreeHostsTxt(struct HostsTxt **ht) {
   if (*ht) {
-    free_s(&(*ht)->entries.p);
-    free_s(&(*ht)->strings.p);
-    free_s(ht);
+    free((*ht)->entries.p);
+    free((*ht)->strings.p);
+    free(*ht);
+    *ht = 0;
   }
 }
diff --git a/libc/dns/freeresolvconf.c b/libc/dns/freeresolvconf.c
index f11e3e619..84b0db655 100644
--- a/libc/dns/freeresolvconf.c
+++ b/libc/dns/freeresolvconf.c
@@ -17,6 +17,7 @@
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/dns/resolvconf.h"
+#include "libc/mem/mem.h"
 #include "libc/runtime/runtime.h"
 
 /**
@@ -24,7 +25,8 @@
  */
 void FreeResolvConf(struct ResolvConf **rvp) {
   if (*rvp) {
-    free_s(&(*rvp)->nameservers.p);
-    free_s(rvp);
+    free((*rvp)->nameservers.p);
+    free(*rvp);
+    *rvp = 0;
   }
 }
diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c
index 6e795b960..c07855ab3 100644
--- a/libc/intrin/asan.c
+++ b/libc/intrin/asan.c
@@ -16,7 +16,6 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#ifdef __x86_64__
 #include "libc/calls/state.internal.h"
 #include "libc/dce.h"
 #include "libc/intrin/asan.internal.h"
@@ -33,7 +32,7 @@
 #include "libc/log/libfatal.internal.h"
 #include "libc/log/log.h"
 #include "libc/macros.internal.h"
-#include "libc/mem/hook/hook.internal.h"
+#include "libc/mem/hook.internal.h"
 #include "libc/mem/mem.h"
 #include "libc/nexgen32e/gc.internal.h"
 #include "libc/nexgen32e/stackframe.h"
@@ -1087,7 +1086,7 @@ size_t __asan_get_heap_size(const void *p) {
   return 0;
 }
 
-static size_t __asan_malloc_usable_size(const void *p) {
+static size_t __asan_malloc_usable_size(void *p) {
   size_t n, c;
   struct AsanExtra *e;
   if ((e = __asan_get_extra(p, &c)) && __asan_read48(e->size, &n)) {
@@ -1498,5 +1497,3 @@ __attribute__((__constructor__)) void __asan_init(int argc, char **argv,
   STRACE("/_/   \\_\\____/_/   \\_\\_| \\_|");
   STRACE("cosmopolitan memory safety module initialized");
 }
-
-#endif /* __x86_64__ */
diff --git a/libc/intrin/cmpxchg16b.internal.h b/libc/intrin/cmpxchg16b.internal.h
deleted file mode 100644
index 897566adc..000000000
--- a/libc/intrin/cmpxchg16b.internal.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_
-#define COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_
-#include "libc/intrin/asmflag.h"
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-/**
- * Compares and exchanges 128-bit value, i.e.
- *
- *     if (*IfThing == *IsEqualToMe) {
- *       *IfThing = ReplaceItWithMe;
- *       return true;
- *     } else {
- *       *IsEqualToMe = *IfThing;
- *       return false;
- *     }
- *
- * Please note that Intel Architecture doesn't guarantee 16-byte memory
- * accesses to be atomic on their own. Therefore _lockcmpxchg16b should
- * be considered instead for both thread and asynchronous signal safety
- *
- * @param IfThing should point to aligned memory
- * @param IsEqualToMe should point to in/out local variable
- * @param ReplaceItWithMe might become the new memory value
- * @return true if *IfThing was changed
- */
-static inline bool _cmpxchg16b(uint128_t *IfThing, uint128_t *IsEqualToMe,
-                               uint128_t ReplaceItWithMe) {
-  bool DidIt;
-  uint64_t ax, bx, cx, dx;
-  ax = *IsEqualToMe;
-  dx = *IsEqualToMe >> 64;
-  bx = ReplaceItWithMe;
-  cx = ReplaceItWithMe >> 64;
-  asm volatile(ZFLAG_ASM("cmpxchg16b\t%1")
-               : ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(ax), "+d"(dx)
-               : "b"(bx), "c"(cx));
-  if (!DidIt) {
-    *IsEqualToMe = ax | (uint128_t)dx << 64;
-  }
-  return DidIt;
-}
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_BITS_CMPXCHG16B_INTERNAL_H_ */
diff --git a/libc/intrin/futex.S b/libc/intrin/futex.S
index 1ff350b72..c2948ef24 100644
--- a/libc/intrin/futex.S
+++ b/libc/intrin/futex.S
@@ -20,7 +20,9 @@
 #include "libc/macros.internal.h"
 .privileged
 
-_futex:	push	%rbp
+_futex:
+#ifdef __x86_64__
+	push	%rbp
 	mov	%rsp,%rbp
 	mov	%rcx,%r10
 	mov	__NR_futex,%eax
@@ -29,5 +31,11 @@ _futex:	push	%rbp
 	jnc	1f
 	neg	%eax
 1:	pop	%rbp
+#elif defined(__aarch64__)
+	mov	x8,#0x062
+	svc	#0
+#else
+#error "unsupported architecture"
+#endif /* __x86_64__ */
 	ret
 	.endfn	_futex,globl,hidden
diff --git a/libc/intrin/intrin.mk b/libc/intrin/intrin.mk
index c3b4f933d..b46291faa 100644
--- a/libc/intrin/intrin.mk
+++ b/libc/intrin/intrin.mk
@@ -189,6 +189,8 @@ o/$(MODE)/libc/intrin/memmove.o: private		\
 # these assembly files are safe to build on aarch64
 o/$(MODE)/libc/intrin/fenv.o: libc/intrin/fenv.S
 	@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
+o/$(MODE)/libc/intrin/futex.o: libc/intrin/futex.S
+	@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
 o/$(MODE)/libc/intrin/kclocknames.o: libc/intrin/kclocknames.S
 	@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
 o/$(MODE)/libc/intrin/kdos2errno.o: libc/intrin/kdos2errno.S
diff --git a/libc/intrin/lockcmpxchg.h b/libc/intrin/lockcmpxchg.h
deleted file mode 100644
index d025e8d58..000000000
--- a/libc/intrin/lockcmpxchg.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHG_H_
-#define COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHG_H_
-#include "libc/intrin/asmflag.h"
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
-#define _lockcmpxchg(IFTHING, ISEQUALTOME, REPLACEITWITHME)                   \
-  ({                                                                          \
-    bool DidIt;                                                               \
-    autotype(IFTHING) IfThing = (IFTHING);                                    \
-    typeof(*IfThing) IsEqualToMe = (ISEQUALTOME);                             \
-    typeof(*IfThing) ReplaceItWithMe = (REPLACEITWITHME);                     \
-    asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1")                             \
-                 : ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(IsEqualToMe) \
-                 : "r"(ReplaceItWithMe)                                       \
-                 : "cc");                                                     \
-    DidIt;                                                                    \
-  })
-#endif /* GNUC && !ANSI && x86 */
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHG_H_ */
diff --git a/libc/intrin/lockcmpxchg16b.h b/libc/intrin/lockcmpxchg16b.h
deleted file mode 100644
index 7e3158f41..000000000
--- a/libc/intrin/lockcmpxchg16b.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_H_
-#define COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_H_
-#include "libc/intrin/asmflag.h"
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
-/**
- * Compares and exchanges 128-bit value, i.e.
- *
- *     if (*IfThing == *IsEqualToMe) {
- *       *IfThing = ReplaceItWithMe;
- *       return true;
- *     } else {
- *       *IsEqualToMe = *IfThing;
- *       return false;
- *     }
- *
- * @param IfThing should point to aligned memory
- * @param IsEqualToMe should point to in/out local variable
- * @param ReplaceItWithMe might become the new memory value
- * @return true if *IfThing was changed
- * @asyncsignalsafe
- * @threadsafe
- */
-static inline bool _lockcmpxchg16b(uint128_t *IfThing, uint128_t *IsEqualToMe,
-                                   uint128_t ReplaceItWithMe) {
-  bool DidIt;
-  uint64_t ax, bx, cx, dx;
-  ax = *IsEqualToMe;
-  dx = *IsEqualToMe >> 64;
-  bx = ReplaceItWithMe;
-  cx = ReplaceItWithMe >> 64;
-  asm volatile(ZFLAG_ASM("lock cmpxchg16b\t%1")
-               : ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(ax), "+d"(dx)
-               : "b"(bx), "c"(cx));
-  if (!DidIt) {
-    *IsEqualToMe = ax | (uint128_t)dx << 64;
-  }
-  return DidIt;
-}
-#endif /* __GNUC__ && !__STRICT_ANSI__ */
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_BITS_LOCKCMPXCHG16B_H_ */
diff --git a/libc/intrin/lockcmpxchgp.h b/libc/intrin/lockcmpxchgp.h
deleted file mode 100644
index 3b4c010c7..000000000
--- a/libc/intrin/lockcmpxchgp.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_
-#define COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_
-#include "libc/intrin/asmflag.h"
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86__)
-#define _lockcmpxchgp(IN_OUT_IFTHING, IN_OUT_ISEQUALTOME, IN_REPLACEITWITHME)  \
-  ({                                                                           \
-    bool DidIt;                                                                \
-    autotype(IN_OUT_IFTHING) IfThing = (IN_OUT_IFTHING);                       \
-    typeof(IfThing) IsEqualToMe = (IN_OUT_ISEQUALTOME);                        \
-    typeof(*IfThing) ReplaceItWithMe = (IN_REPLACEITWITHME);                   \
-    asm volatile(ZFLAG_ASM("lock cmpxchg\t%3,%1")                              \
-                 : ZFLAG_CONSTRAINT(DidIt), "+m"(*IfThing), "+a"(*IsEqualToMe) \
-                 : "r"(ReplaceItWithMe)                                        \
-                 : "cc");                                                      \
-    DidIt;                                                                     \
-  })
-#endif /* GNUC && !ANSI && x86 */
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_INTRIN_LOCKCMPXCHGP_H_ */
diff --git a/libc/intrin/lockxchg.h b/libc/intrin/lockxchg.h
deleted file mode 100644
index 6385cca02..000000000
--- a/libc/intrin/lockxchg.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef COSMOPOLITAN_LIBC_INTRIN_LOCKXCHG_H_
-#define COSMOPOLITAN_LIBC_INTRIN_LOCKXCHG_H_
-#if !(__ASSEMBLER__ + __LINKER__ + 0)
-COSMOPOLITAN_C_START_
-
-/* TODO(jart): DELETE */
-
-intptr_t lockxchg(void *, void *, size_t);
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(__x86_64__)
-/**
- * Exchanges *MEMORY into *LOCALVAR w/ one operation.
- *
- * @param MEMORY is uint𝑘_t[hasatleast 1] where 𝑘 ∈ {8,16,32,64}
- * @param LOCALVAR is uint𝑘_t[hasatleast 1]
- * @return LOCALVAR[0]
- * @see xchg()
- */
-#define lockxchg(MEMORY, LOCALVAR)                            \
-  ({                                                          \
-    asm("xchg\t%0,%1" : "+%m"(*(MEMORY)), "+r"(*(LOCALVAR))); \
-    *(LOCALVAR);                                              \
-  })
-#else
-#define lockxchg(MEM, VAR) \
-  lockxchg(MEM, VAR, sizeof(*(MEM)) / (sizeof(*(MEM)) == sizeof(*(VAR))))
-#endif /* __GNUC__ && !__STRICT_ANSI__ */
-
-COSMOPOLITAN_C_END_
-#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_INTRIN_LOCKXCHG_H_ */
diff --git a/libc/intrin/xchg.internal.h b/libc/intrin/xchg.internal.h
index b912306e5..333f81398 100644
--- a/libc/intrin/xchg.internal.h
+++ b/libc/intrin/xchg.internal.h
@@ -7,7 +7,6 @@
  * Exchanges *MEMORY into *LOCALVAR.
  *
  * @return *MEMORY
- * @see lockcmpxchg()
  * todo(jart): what's the point of this?
  */
 #define xchg(MEMORY, LOCALVAR)              \
diff --git a/libc/log/memlog.c b/libc/log/memlog.c
index be4240430..ba64a92a8 100644
--- a/libc/log/memlog.c
+++ b/libc/log/memlog.c
@@ -22,7 +22,7 @@
 #include "libc/log/backtrace.internal.h"
 #include "libc/log/log.h"
 #include "libc/macros.internal.h"
-#include "libc/mem/hook/hook.internal.h"
+#include "libc/mem/hook.internal.h"
 #include "libc/mem/mem.h"
 #include "libc/runtime/symbols.internal.h"
 #include "libc/sysv/consts/o.h"
diff --git a/libc/log/oncrash.c b/libc/log/oncrash.c
index fa5afe231..168649a51 100644
--- a/libc/log/oncrash.c
+++ b/libc/log/oncrash.c
@@ -348,7 +348,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
     } else {
       // somehow __minicrash() crashed not possible
       for (;;) {
-        asm("ud2");
+        __builtin_trap();
       }
     }
   } else {
diff --git a/libc/mem/arena.c b/libc/mem/arena.c
index 44b8fd308..f1fb05f63 100644
--- a/libc/mem/arena.c
+++ b/libc/mem/arena.c
@@ -27,7 +27,7 @@
 #include "libc/limits.h"
 #include "libc/log/log.h"
 #include "libc/macros.internal.h"
-#include "libc/mem/hook/hook.internal.h"
+#include "libc/mem/hook.internal.h"
 #include "libc/runtime/memtrack.internal.h"
 #include "libc/runtime/runtime.h"
 #include "libc/str/str.h"
diff --git a/libc/mem/bulk_free.S b/libc/mem/bulk_free.c
similarity index 66%
rename from libc/mem/bulk_free.S
rename to libc/mem/bulk_free.c
index 2516b1380..6a1f700d5 100644
--- a/libc/mem/bulk_free.S
+++ b/libc/mem/bulk_free.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,15 +16,21 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Frees and clears (sets to NULL) each non-null pointer in given array.
-//
-//	This is twice as fast as freeing them one-by-one. If footers are
-//	used, pointers that have been allocated in different mspaces are
-//	not freed or cleared, and the count of all such pointers is returned.
-//	For large arrays of pointers with poor locality, it may be worthwhile
-//	to sort this array before calling bulk_free.
-bulk_free:
-	jmp	*hook_bulk_free(%rip)
-	.endfn	bulk_free,globl
+size_t (*hook_bulk_free)(void *[], size_t) = dlbulk_free;
+
+/**
+ * Frees and clears (sets to NULL) each non-null pointer in given array.
+ *
+ * This is twice as fast as freeing them one-by-one. If footers are
+ * used, pointers that have been allocated in different mspaces are
+ * not freed or cleared, and the count of all such pointers is returned.
+ * For large arrays of pointers with poor locality, it may be worthwhile
+ * to sort this array before calling bulk_free.
+ */
+size_t bulk_free(void **p, size_t n) {
+  return hook_bulk_free(p, n);
+}
diff --git a/libc/mem/calloc.S b/libc/mem/calloc.c
similarity index 69%
rename from libc/mem/calloc.S
rename to libc/mem/calloc.c
index 0486dfac1..c207741b9 100644
--- a/libc/mem/calloc.S
+++ b/libc/mem/calloc.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,16 +16,22 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-#include "libc/notice.inc"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Allocates n * itemsize bytes, initialized to zero.
-//
-//	@param	rdi is number of items (n)
-//	@param	rsi is size of each item (itemsize)
-//	@return	rax is memory address, or NULL w/ errno
-//	@note	overreliance on memalign is a sure way to fragment space
-//	@see	dlcalloc()
-//	@threadsafe
-calloc:	jmp	*hook_calloc(%rip)
-	.endfn	calloc,globl
+void *(*hook_calloc)(size_t, size_t) = dlcalloc;
+
+/**
+ * Allocates n * itemsize bytes, initialized to zero.
+ *
+ * @param n is number of items
+ * @param itemsize is size of each item
+ * @return rax is memory address, or NULL w/ errno
+ * @note overreliance on memalign is a sure way to fragment space
+ * @see dlcalloc()
+ * @threadsafe
+ */
+void *calloc(size_t n, size_t itemsize) {
+  return hook_calloc(n, itemsize);
+}
diff --git a/libc/mem/free.S b/libc/mem/free.c
similarity index 67%
rename from libc/mem/free.S
rename to libc/mem/free.c
index d5eef70c4..c88786a4d 100644
--- a/libc/mem/free.S
+++ b/libc/mem/free.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,18 +16,25 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Free memory returned by malloc() & co.
-//
-//	Releases the chunk of memory pointed to by p, that had been
-//	previously allocated using malloc or a related routine such as
-//	realloc. It has no effect if p is null. If p was not malloced or
-//	already freed, free(p) will by default cause the current program to
-//	abort.
-//
-//	@param	rdi is allocation address, which may be NULL
-//	@see	dlfree()
-//	@threadsafe
-free:	jmp	*hook_free(%rip)
-	.endfn	free,globl
+void (*hook_free)(void *) = dlfree;
+
+/**
+ * Free memory returned by malloc() & co.
+ *
+ * Releases the chunk of memory pointed to by p, that had been
+ * previously allocated using malloc or a related routine such as
+ * realloc. It has no effect if p is null. If p was not malloced or
+ * already freed, free(p) will by default cause the current program to
+ * abort.
+ *
+ * @param p is allocation address, which may be NULL
+ * @see dlfree()
+ * @threadsafe
+ */
+void free(void *p) {
+  hook_free(p);
+}
diff --git a/libc/mem/gc.c b/libc/mem/gc.c
index ab0c2697b..8962fbcfb 100644
--- a/libc/mem/gc.c
+++ b/libc/mem/gc.c
@@ -25,6 +25,8 @@
 #include "libc/str/str.h"
 #include "libc/thread/tls.h"
 
+#ifdef __x86_64__
+
 forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
                                                    struct StackFrame *parent,
                                                    void *ptr) {
@@ -144,3 +146,5 @@ void *(_defer)(void *fn, void *arg) {
   DeferFunction(frame->next, fn, arg);
   return arg;
 }
+
+#endif /* __x86_64__ */
diff --git a/libc/mem/hook/hook.internal.h b/libc/mem/hook.internal.h
similarity index 71%
rename from libc/mem/hook/hook.internal.h
rename to libc/mem/hook.internal.h
index 6e92ee960..b4b3b4471 100644
--- a/libc/mem/hook/hook.internal.h
+++ b/libc/mem/hook.internal.h
@@ -1,5 +1,5 @@
-#ifndef COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
-#define COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
+#ifndef COSMOPOLITAN_LIBC_MEM_HOOK_H_
+#define COSMOPOLITAN_LIBC_MEM_HOOK_H_
 #if !(__ASSEMBLER__ + __LINKER__ + 0)
 COSMOPOLITAN_C_START_
 
@@ -10,9 +10,9 @@ extern void *(*hook_memalign)(size_t, size_t);
 extern void *(*hook_realloc)(void *, size_t);
 extern void *(*hook_realloc_in_place)(void *, size_t);
 extern int (*hook_malloc_trim)(size_t);
-extern size_t (*hook_malloc_usable_size)(const void *);
+extern size_t (*hook_malloc_usable_size)(void *);
 extern size_t (*hook_bulk_free)(void *[], size_t);
 
 COSMOPOLITAN_C_END_
 #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
-#endif /* COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_ */
+#endif /* COSMOPOLITAN_LIBC_MEM_HOOK_H_ */
diff --git a/libc/mem/hook/bulk_free.S b/libc/mem/hook/bulk_free.S
deleted file mode 100644
index b42e6149f..000000000
--- a/libc/mem/hook/bulk_free.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_bulk_free
-hook_bulk_free:
-	.quad	0
-	.endobj	hook_bulk_free,globl,hidden
-	.previous
-
-	.init.start 202,_init_bulk_free
-	.hidden	dlbulk_free
-	ezlea	dlbulk_free,ax
-	stosq
-	.init.end 202,_init_bulk_free
diff --git a/libc/mem/hook/calloc.S b/libc/mem/hook/calloc.S
deleted file mode 100644
index 904e30269..000000000
--- a/libc/mem/hook/calloc.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_calloc
-hook_calloc:
-	.quad	0
-	.endobj	hook_calloc,globl,hidden
-	.previous
-
-	.init.start 202,_init_calloc
-	.hidden	dlcalloc
-	ezlea	dlcalloc,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_calloc
diff --git a/libc/mem/hook/free.S b/libc/mem/hook/free.S
deleted file mode 100644
index dc12a20ba..000000000
--- a/libc/mem/hook/free.S
+++ /dev/null
@@ -1,33 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_free
-hook_free:
-	.quad	0
-	.endobj	hook_free,globl,hidden
-	.previous
-
-	.init.start 202,_init_free
-	ezlea	dlfree,ax
-	stosq
-	.yoink	realloc
-	.init.end 202,_init_free
-
-	.hidden	dlfree
diff --git a/libc/mem/hook/malloc.S b/libc/mem/hook/malloc.S
deleted file mode 100644
index 081b0a9e3..000000000
--- a/libc/mem/hook/malloc.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_malloc
-hook_malloc:
-	.quad	0
-	.endobj	hook_malloc,globl,hidden
-	.previous
-
-	.init.start 202,_init_malloc
-	.hidden	dlmalloc
-	ezlea	dlmalloc,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_malloc
diff --git a/libc/mem/hook/malloc_trim.S b/libc/mem/hook/malloc_trim.S
deleted file mode 100644
index 616217ed0..000000000
--- a/libc/mem/hook/malloc_trim.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_malloc_trim
-hook_malloc_trim:
-	.quad	0
-	.endobj	hook_malloc_trim,globl,hidden
-	.previous
-
-	.init.start 202,_init_malloc_trim
-	.hidden	dlmalloc_trim
-	ezlea	dlmalloc_trim,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_malloc_trim
diff --git a/libc/mem/hook/malloc_usable_size.S b/libc/mem/hook/malloc_usable_size.S
deleted file mode 100644
index 1dabdbdc8..000000000
--- a/libc/mem/hook/malloc_usable_size.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_malloc_usable_size
-hook_malloc_usable_size:
-	.quad	0
-	.endobj	hook_malloc_usable_size,globl,hidden
-	.previous
-
-	.init.start 202,_init_malloc_usable_size
-	.hidden	dlmalloc_usable_size
-	ezlea	dlmalloc_usable_size,ax
-	stosq
-	.init.end 202,_init_malloc_usable_size
diff --git a/libc/mem/hook/memalign.S b/libc/mem/hook/memalign.S
deleted file mode 100644
index 0f051cfe7..000000000
--- a/libc/mem/hook/memalign.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_memalign
-hook_memalign:
-	.quad	0
-	.endobj	hook_memalign,globl,hidden
-	.previous
-
-	.init.start 202,_init_memalign
-	.hidden	dlmemalign
-	ezlea	dlmemalign,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_memalign
diff --git a/libc/mem/hook/realloc.S b/libc/mem/hook/realloc.S
deleted file mode 100644
index ad7daa56e..000000000
--- a/libc/mem/hook/realloc.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_realloc
-hook_realloc:
-	.quad	0
-	.endobj	hook_realloc,globl,hidden
-	.previous
-
-	.init.start 202,_init_realloc
-	.hidden	dlrealloc
-	ezlea	dlrealloc,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_realloc
diff --git a/libc/mem/hook/realloc_in_place.S b/libc/mem/hook/realloc_in_place.S
deleted file mode 100644
index 0f2649608..000000000
--- a/libc/mem/hook/realloc_in_place.S
+++ /dev/null
@@ -1,32 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.initbss 202,_init_realloc_in_place
-hook_realloc_in_place:
-	.quad	0
-	.endobj	hook_realloc_in_place,globl,hidden
-	.previous
-
-	.init.start 202,_init_realloc_in_place
-	.hidden	dlrealloc_in_place
-	ezlea	dlrealloc_in_place,ax
-	stosq
-	.yoink	free
-	.init.end 202,_init_realloc_in_place
diff --git a/libc/mem/realloc_in_place.S b/libc/mem/hook_realloc_in_place.c
similarity index 58%
rename from libc/mem/realloc_in_place.S
rename to libc/mem/hook_realloc_in_place.c
index 674393545..191cfcfc3 100644
--- a/libc/mem/realloc_in_place.S
+++ b/libc/mem/hook_realloc_in_place.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,23 +16,28 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-#include "libc/notice.inc"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Resizes the space allocated for p to size n, only if this can be
-//	done without moving p (i.e., only if there is adjacent space
-//	available if n is greater than p's current allocated size, or n
-//	is less than or equal to p's size). This may be used instead of
-//	plain realloc if an alternative allocation strategy is needed
-//	upon failure to expand space, for example, reallocation of a
-//	buffer that must be memory-aligned or cleared. You can use
-//	realloc_in_place to trigger these alternatives only when needed.
-//
-//	@param	rdi (p) is address of current allocation
-//	@param	rsi (newsize) is number of bytes needed
-//	@return	rax is result, or NULL w/ errno
-//	@see	dlrealloc_in_place()
-//	@threadsafe
-realloc_in_place:
-	jmp	*hook_realloc_in_place(%rip)
-	.endfn	realloc_in_place,globl
+void *(*hook_realloc_in_place)(void *, size_t) = dlrealloc_in_place;
+
+/**
+ * Resizes the space allocated for p to size n, only if this can be
+ * done without moving p (i.e., only if there is adjacent space
+ * available if n is greater than p's current allocated size, or n
+ * is less than or equal to p's size). This may be used instead of
+ * plain realloc if an alternative allocation strategy is needed
+ * upon failure to expand space, for example, reallocation of a
+ * buffer that must be memory-aligned or cleared. You can use
+ * realloc_in_place to trigger these alternatives only when needed.
+ *
+ * @param p is address of current allocation
+ * @param n is number of bytes needed
+ * @return rax is result, or NULL w/ errno
+ * @see dlrealloc_in_place()
+ * @threadsafe
+ */
+void *realloc_in_place(void *p, size_t n) {
+  return hook_realloc_in_place(p, n);
+}
diff --git a/libc/mem/malloc.S b/libc/mem/malloc.c
similarity index 60%
rename from libc/mem/malloc.S
rename to libc/mem/malloc.c
index 1afda752c..635473c01 100644
--- a/libc/mem/malloc.S
+++ b/libc/mem/malloc.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,23 +16,30 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Allocates uninitialized memory.
-//
-//	Returns a pointer to a newly allocated chunk of at least n bytes, or
-//	null if no space is available, in which case errno is set to ENOMEM
-//	on ANSI C systems.
-//
-//	If n is zero, malloc returns a minimum-sized chunk. (The minimum size
-//	is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
-//	so calls with arguments that would be negative if signed are
-//	interpreted as requests for huge amounts of space, which will often
-//	fail. The maximum supported value of n differs across systems, but is
-//	in all cases less than the maximum representable value of a size_t.
-//
-//	@param	rdi is number of bytes needed, coerced to 1+
-//	@return	new memory, or NULL w/ errno
-//	@threadsafe
-malloc:	jmp	*hook_malloc(%rip)
-	.endfn	malloc,globl
+void *(*hook_malloc)(size_t) = dlmalloc;
+
+/**
+ * Allocates uninitialized memory.
+ *
+ * Returns a pointer to a newly allocated chunk of at least n bytes, or
+ * null if no space is available, in which case errno is set to ENOMEM
+ * on ANSI C systems.
+ *
+ * If n is zero, malloc returns a minimum-sized chunk. (The minimum size
+ * is 32 bytes on 64bit systems.) Note that size_t is an unsigned type,
+ * so calls with arguments that would be negative if signed are
+ * interpreted as requests for huge amounts of space, which will often
+ * fail. The maximum supported value of n differs across systems, but is
+ * in all cases less than the maximum representable value of a size_t.
+ *
+ * @param rdi is number of bytes needed, coerced to 1+
+ * @return new memory, or NULL w/ errno
+ * @threadsafe
+ */
+void *malloc(size_t n) {
+  return hook_malloc(n);
+}
diff --git a/libc/mem/malloc_trim.S b/libc/mem/malloc_trim.S
deleted file mode 100644
index 873f27553..000000000
--- a/libc/mem/malloc_trim.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2021 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-//	Releases freed memory back to system.
-//
-//	@param	rdi specifies bytes of memory to leave available
-//	@return	1 if it actually released any memory, else 0
-malloc_trim:
-	jmp	*hook_malloc_trim(%rip)
-	.endfn	malloc_trim,globl
diff --git a/libc/runtime/free_s.c b/libc/mem/malloc_trim.c
similarity index 81%
rename from libc/runtime/free_s.c
rename to libc/mem/malloc_trim.c
index 7d6c57c9c..2f967e2f3 100644
--- a/libc/runtime/free_s.c
+++ b/libc/mem/malloc_trim.c
@@ -1,7 +1,7 @@
 /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,16 +16,18 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/mem/hook.internal.h"
 #include "libc/mem/mem.h"
-#include "libc/runtime/runtime.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-/* TODO(jart): DELETE */
+int (*hook_malloc_trim)(size_t) = dlmalloc_trim;
 
-void free_s(void *v) {
-  void **pp = (void **)v;
-  void *p = *pp;
-  *pp = 0;
-  if (_isheap(p)) {
-    _weakfree(p);
-  }
+/**
+ * Releases freed memory back to system.
+ *
+ * @param n specifies bytes of memory to leave available
+ * @return 1 if it actually released any memory, else 0
+ */
+int malloc_trim(size_t n) {
+  return hook_malloc_trim(n);
 }
diff --git a/libc/mem/malloc_usable_size.S b/libc/mem/malloc_usable_size.c
similarity index 60%
rename from libc/mem/malloc_usable_size.S
rename to libc/mem/malloc_usable_size.c
index 161f050fd..2dcda5fe6 100644
--- a/libc/mem/malloc_usable_size.S
+++ b/libc/mem/malloc_usable_size.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,26 +16,31 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-#include "libc/notice.inc"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Returns the number of bytes you can actually use in
-//	an allocated chunk, which may be more than you requested
-//	(although often not) due to alignment and minimum size
-//	constraints.
-//
-//	You can use this many bytes without worrying about overwriting
-//	other allocated objects. This is not a particularly great
-//	programming practice. malloc_usable_size can be more useful in
-//	debugging and assertions, for example:
-//
-//	    p = malloc(n)
-//	    assert(malloc_usable_size(p) >= 256)
-//
-//	@param	rdi is address of allocation
-//	@return	rax is total number of bytes
-//	@see	dlmalloc_usable_size()
-//	@threadsafe
-malloc_usable_size:
-	jmp	*hook_malloc_usable_size(%rip)
-	.endfn	malloc_usable_size,globl
+size_t (*hook_malloc_usable_size)(void *) = dlmalloc_usable_size;
+
+/**
+ * Returns the number of bytes you can actually use in
+ * an allocated chunk, which may be more than you requested
+ * (although often not) due to alignment and minimum size
+ * constraints.
+ *
+ * You can use this many bytes without worrying about overwriting
+ * other allocated objects. This is not a particularly great
+ * programming practice. malloc_usable_size can be more useful in
+ * debugging and assertions, for example:
+ *
+ *     p = malloc(n)
+ *     assert(malloc_usable_size(p) >= 256)
+ *
+ * @param p is address of allocation
+ * @return total number of bytes
+ * @see dlmalloc_usable_size()
+ * @threadsafe
+ */
+size_t malloc_usable_size(void *p) {
+  return hook_malloc_usable_size(p);
+}
diff --git a/libc/mem/mem.mk b/libc/mem/mem.mk
index 39dc4327b..ba82e2210 100644
--- a/libc/mem/mem.mk
+++ b/libc/mem/mem.mk
@@ -7,21 +7,12 @@ LIBC_MEM_ARTIFACTS += LIBC_MEM_A
 LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
 LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
 LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
-LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
-LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
+LIBC_MEM_A_SRCS = $(filter %.c,$(LIBC_MEM_A_FILES))
+LIBC_MEM_A_OBJS = $(LIBC_MEM_A_SRCS:%.c=o/$(MODE)/%.o)
 
 LIBC_MEM_A_FILES :=				\
 	$(wildcard libc/mem/*)			\
-	$(wildcard libc/mem/cxx/*)		\
-	$(wildcard libc/mem/hook/*)
-
-LIBC_MEM_A_SRCS =				\
-	$(LIBC_MEM_A_SRCS_S)			\
-	$(LIBC_MEM_A_SRCS_C)
-
-LIBC_MEM_A_OBJS =				\
-	$(LIBC_MEM_A_SRCS_S:%.S=o/$(MODE)/%.o)	\
-	$(LIBC_MEM_A_SRCS_C:%.c=o/$(MODE)/%.o)
+	$(wildcard libc/mem/cxx/*)
 
 LIBC_MEM_A_CHECKS =				\
 	$(LIBC_MEM_A).pkg			\
diff --git a/libc/mem/memalign.S b/libc/mem/memalign.c
similarity index 62%
rename from libc/mem/memalign.S
rename to libc/mem/memalign.c
index 9a8e762ee..6d5579f42 100644
--- a/libc/mem/memalign.S
+++ b/libc/mem/memalign.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,21 +16,26 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-#include "libc/notice.inc"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Allocates aligned memory.
-//
-//	Returns a pointer to a newly allocated chunk of n bytes, aligned in
-//	accord with the alignment argument. The alignment argument shall be
-//	rounded up to the nearest two power and higher 2 powers may be used
-//	if the allocator imposes a minimum alignment requirement.
-//
-//	@param	rdi is alignment in bytes, coerced to 1+ w/ 2-power roundup
-//	@param	rsi is number of bytes needed, coerced to 1+
-//	@return	rax is memory address, or NULL w/ errno
-//	@see	valloc(), pvalloc()
-//	@threadsafe
-memalign:
-	jmp	*hook_memalign(%rip)
-	.endfn	memalign,globl
+void *(*hook_memalign)(size_t, size_t) = dlmemalign;
+
+/**
+ * Allocates aligned memory.
+ *
+ * Returns a pointer to a newly allocated chunk of n bytes, aligned in
+ * accord with the alignment argument. The alignment argument shall be
+ * rounded up to the nearest two power and higher 2 powers may be used
+ * if the allocator imposes a minimum alignment requirement.
+ *
+ * @param align is alignment in bytes, coerced to 1+ w/ 2-power roundup
+ * @param bytes is number of bytes needed, coerced to 1+
+ * @return rax is memory address, or NULL w/ errno
+ * @see valloc(), pvalloc()
+ * @threadsafe
+ */
+void *memalign(size_t align, size_t bytes) {
+  return hook_memalign(align, bytes);
+}
diff --git a/libc/mem/realloc.S b/libc/mem/realloc.c
similarity index 50%
rename from libc/mem/realloc.S
rename to libc/mem/realloc.c
index b89010ff8..e00b1b4aa 100644
--- a/libc/mem/realloc.S
+++ b/libc/mem/realloc.c
@@ -1,7 +1,7 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
+/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
+│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,44 +16,49 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-#include "libc/notice.inc"
+#include "libc/mem/hook.internal.h"
+#include "libc/mem/mem.h"
+#include "third_party/dlmalloc/dlmalloc.h"
 
-//	Allocates / resizes / frees memory, e.g.
-//
-//	Returns a pointer to a chunk of size n that contains the same data as
-//	does chunk p up to the minimum of (n, p's size) bytes, or null if no
-//	space is available.
-//
-//	If p is NULL, realloc is equivalent to malloc.
-//	If p is not NULL and n is 0, realloc is equivalent to free.
-//
-//	The returned pointer may or may not be the same as p. The algorithm
-//	prefers extending p in most cases when possible, otherwise it employs
-//	the equivalent of a malloc-copy-free sequence.
-//
-//	Please note that p is NOT free()'d should realloc() fail, thus:
-//
-//	    if ((p2 = realloc(p, n2))) {
-//	      p = p2;
-//	      ...
-//	    } else {
-//	      ...
-//	    }
-//
-//	if n is for fewer bytes than already held by p, the newly unused
-//	space is lopped off and freed if possible.
-//
-//	The old unix realloc convention of allowing the last-free'd chunk to
-//	be used as an argument to realloc is not supported.
-//
-//	@param	rdi (p) is address of current allocation or NULL
-//	@param	rsi (n) is number of bytes needed
-//	@return	rax is result, or NULL w/ errno w/o free(p)
-//	@note	realloc(p=0, n=0) → malloc(32)
-//	@note	realloc(p≠0, n=0) → free(p)
-//	@see	dlrealloc()
-//	@threadsafe
-realloc:
-	jmp	*hook_realloc(%rip)
-	.endfn	realloc,globl
+void *(*hook_realloc)(void *, size_t) = dlrealloc;
+
+/**
+ * Allocates / resizes / frees memory, e.g.
+ *
+ * Returns a pointer to a chunk of size n that contains the same data as
+ * does chunk p up to the minimum of (n, p's size) bytes, or null if no
+ * space is available.
+ *
+ * If p is NULL, realloc is equivalent to malloc.
+ * If p is not NULL and n is 0, realloc is equivalent to free.
+ *
+ * The returned pointer may or may not be the same as p. The algorithm
+ * prefers extending p in most cases when possible, otherwise it employs
+ * the equivalent of a malloc-copy-free sequence.
+ *
+ * Please note that p is NOT free()'d should realloc() fail, thus:
+ *
+ *     if ((p2 = realloc(p, n2))) {
+ *       p = p2;
+ *       ...
+ *     } else {
+ *       ...
+ *     }
+ *
+ * if n is for fewer bytes than already held by p, the newly unused
+ * space is lopped off and freed if possible.
+ *
+ * The old unix realloc convention of allowing the last-free'd chunk to
+ * be used as an argument to realloc is not supported.
+ *
+ * @param p is address of current allocation or NULL
+ * @param n is number of bytes needed
+ * @return rax is result, or NULL w/ errno w/o free(p)
+ * @note realloc(p=0, n=0) → malloc(32)
+ * @note realloc(p≠0, n=0) → free(p)
+ * @see dlrealloc()
+ * @threadsafe
+ */
+void *realloc(void *p, size_t n) {
+  return hook_realloc(p, n);
+}
diff --git a/libc/nexgen32e/bench.h b/libc/nexgen32e/bench.h
index 0b20290a7..681779d1f 100644
--- a/libc/nexgen32e/bench.h
+++ b/libc/nexgen32e/bench.h
@@ -10,6 +10,7 @@
  * @see libc/testlib/bench.h
  */
 
+#ifdef __x86__
 #define __startbench()                            \
   ({                                              \
     uint64_t Ticks;                               \
@@ -25,7 +26,6 @@
                  : "rcx", "rdx", "memory", "cc"); \
     Ticks;                                        \
   })
-
 #define __endbench()                                     \
   ({                                                     \
     uint64_t Ticks;                                      \
@@ -42,6 +42,10 @@
                  : "rax", "rcx", "rdx", "memory", "cc"); \
     Ticks;                                               \
   })
+#else
+#define __startbench() rdtsc()
+#define __endbench()   rdtsc()
+#endif
 
 #define __startbench_m() mfence_lfence_rdtsc_lfence()
 #define __endbench_m()   __startbench_m()
diff --git a/libc/nexgen32e/kcrc32ctab.S b/libc/nexgen32e/kcrc32ctab.S
deleted file mode 100644
index b86c4d02f..000000000
--- a/libc/nexgen32e/kcrc32ctab.S
+++ /dev/null
@@ -1,40 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-//	Castagnoli CRC32 ISCSI Polynomial
-//	x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
-//	0b00011110110111000110111101000001
-//	_bitreverse32(0x1edc6f41)
-#define ISCSI_POLYNOMIAL 0x82f63b78
-
-	.initbss 300,_init_kCrc32cTab
-kCrc32cTab:
-	.rept	256
-	.long	0
-	.endr
-	.endobj	kCrc32cTab,globl,hidden
-	.previous
-
-	.init.start 300,_init_kCrc32cTab
-	push	%rsi
-	mov	$ISCSI_POLYNOMIAL,%esi
-	call	crc32init
-	pop	%rsi
-	.init.end 300,_init_kCrc32cTab
diff --git a/libc/runtime/runtime.h b/libc/runtime/runtime.h
index 7081685ee..fecb3f2a6 100644
--- a/libc/runtime/runtime.h
+++ b/libc/runtime/runtime.h
@@ -106,7 +106,6 @@ void _loadxmm(void *);
 void _peekall(void);
 void _savexmm(void *);
 void _weakfree(void *);
-void free_s(void *) paramsnonnull() libcesque;
 int _OpenExecutable(void);
 int ftrace_install(void);
 int ftrace_enabled(int);
diff --git a/libc/sock/epoll.c b/libc/sock/epoll.c
index e476bdc57..01223db8b 100644
--- a/libc/sock/epoll.c
+++ b/libc/sock/epoll.c
@@ -73,6 +73,8 @@
 #include "libc/sysv/consts/epoll.h"
 #include "libc/sysv/errfuns.h"
 
+#ifdef __x86_64__
+
 /**
  * @fileoverview epoll
  *
@@ -1530,3 +1532,5 @@ int epoll_wait(int epfd, struct epoll_event *events, int maxevents,
          timeoutms, rc);
   return rc;
 }
+
+#endif /* __x86_64__ */
diff --git a/libc/sock/nointernet.c b/libc/sock/nointernet.c
index 40f320b52..503cc5872 100644
--- a/libc/sock/nointernet.c
+++ b/libc/sock/nointernet.c
@@ -45,6 +45,8 @@
 #include "libc/sysv/errfuns.h"
 #include "net/http/ip.h"
 
+#ifdef __x86_64__
+
 #define ORIG_RAX 120
 #define RAX      80
 #define RDI      112
@@ -337,3 +339,5 @@ int nointernet(void) {
     HandleSeccompTrace(act);
   }
 }
+
+#endif /* __x86_64__ */
diff --git a/libc/stdio/fflushimpl.c b/libc/stdio/fflushimpl.c
index a3a75cbf4..8fea0bf58 100644
--- a/libc/stdio/fflushimpl.c
+++ b/libc/stdio/fflushimpl.c
@@ -18,6 +18,7 @@
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/calls/calls.h"
 #include "libc/errno.h"
+#include "libc/mem/mem.h"
 #include "libc/runtime/runtime.h"
 #include "libc/stdio/internal.h"
 #include "libc/stdio/stdio.h"
@@ -26,7 +27,8 @@
 int __fflush_impl(FILE *f) {
   size_t i;
   ssize_t rc;
-  free_s(&f->getln);
+  free(f->getln);
+  f->getln = 0;
   if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
     for (i = 0; i < f->beg; i += rc) {
       if ((rc = write(f->fd, f->buf + i, f->beg - i)) == -1) {
diff --git a/libc/stdio/g_rando.S b/libc/stdio/g_rando.S
deleted file mode 100644
index 23985e4e1..000000000
--- a/libc/stdio/g_rando.S
+++ /dev/null
@@ -1,30 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.bss
-	.balign	8
-g_rando:
-	.quad	0
-	.endobj	g_rando,globl
-	.previous
-
-	.init.start 100,_init_g_rando
-	movb	$1,g_rando(%rip)
-	.init.end 100,_init_g_rando
diff --git a/libc/stdio/fclose_s.c b/libc/stdio/g_rando.c
similarity index 89%
rename from libc/stdio/fclose_s.c
rename to libc/stdio/g_rando.c
index 3b0a887ab..ab96287be 100644
--- a/libc/stdio/fclose_s.c
+++ b/libc/stdio/g_rando.c
@@ -1,7 +1,7 @@
 /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
 │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8                                :vi│
 ╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
+│ Copyright 2023 Justine Alexandra Roberts Tunney                              │
 │                                                                              │
 │ Permission to use, copy, modify, and/or distribute this software for         │
 │ any purpose with or without fee is hereby granted, provided that the         │
@@ -16,12 +16,6 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/intrin/lockxchg.h"
 #include "libc/stdio/stdio.h"
 
-// TODO(jart): delete
-
-int fclose_s(FILE **fp) {
-  FILE *f = NULL;
-  return fclose(lockxchg(fp, &f));
-}
+uint64_t g_rando = 1;
diff --git a/libc/stdio/stderr-init.S b/libc/stdio/stderr-init.S
deleted file mode 100644
index ebbfcfd9a..000000000
--- a/libc/stdio/stderr-init.S
+++ /dev/null
@@ -1,39 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/sysv/consts/o.h"
-#include "libc/dce.h"
-#include "libc/calls/calls.h"
-#include "libc/sysv/consts/fileno.h"
-#include "libc/thread/thread.h"
-#include "libc/macros.internal.h"
-
-	.init.start 400,_init_stderr
-	ezlea	__stderr,ax
-	push	$_IOLBF
-	pop	(%rax)					#→ f.fd
-	push	STDERR_FILENO
-	pop	12(%rax)
-	mov	O_WRONLY,%edx
-	mov	%edx,4(%rax)				#→ f.iomode
-	lea	0x50(%rax),%rcx				#← f.mem
-	mov	%rcx,0x18(%rax)				#→ f.buf
-	movl	$BUFSIZ,0x20(%rax)			#→ f.size
-	movb	$PTHREAD_MUTEX_RECURSIVE,0x38+4(%rax)	#→ f.lock._type
-	mov	%rax,stderr(%rip)
-	.init.end 400,_init_stderr,globl,hidden
diff --git a/libc/stdio/stderr.c b/libc/stdio/stderr.c
index f2d1f61f4..298a06693 100644
--- a/libc/stdio/stderr.c
+++ b/libc/stdio/stderr.c
@@ -16,20 +16,27 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
 #include "libc/stdio/internal.h"
 #include "libc/stdio/stdio.h"
-
-STATIC_YOINK("_init_stderr");
+#include "libc/sysv/consts/fileno.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/thread/thread.h"
 
 /**
  * Pointer to standard error stream.
  */
 FILE *stderr;
 
-_Hide FILE __stderr;
+static FILE __stderr;
 
-static textstartup void __stderr_init() {
+__attribute__((__constructor__)) static void __stderr_init(void) {
+  stderr = &__stderr;
+  stderr->fd = STDERR_FILENO;
+  stderr->bufmode = _IOLBF;
+  stderr->iomode = O_WRONLY;
+  stderr->buf = stderr->mem;
+  stderr->size = sizeof(stderr->mem);
+  ((pthread_mutex_t *)stderr->lock)->_type = PTHREAD_MUTEX_RECURSIVE;
   __fflush_register(stderr);
 }
-
-const void *const __stderr_ctor[] initarray = {__stderr_init};
diff --git a/libc/stdio/stdin-init.S b/libc/stdio/stdin-init.S
deleted file mode 100644
index caf7af75b..000000000
--- a/libc/stdio/stdin-init.S
+++ /dev/null
@@ -1,35 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/sysv/consts/o.h"
-#include "libc/dce.h"
-#include "libc/calls/calls.h"
-#include "libc/sysv/consts/fileno.h"
-#include "libc/thread/thread.h"
-#include "libc/macros.internal.h"
-
-	.init.start 400,_init_stdin
-	ezlea	__stdin,ax
-	mov	O_RDONLY,%edx
-	mov	%edx,4(%rax)				#→ f.iomode
-	lea	0x50(%rax),%rcx				#← f.mem
-	mov	%rcx,0x18(%rax)				#→ f.buf
-	movl	$BUFSIZ,0x20(%rax)			#→ f.size
-	movb	$PTHREAD_MUTEX_RECURSIVE,0x38+4(%rax)	#→ f.lock._type
-	mov	%rax,stdin(%rip)
-	.init.end 400,_init_stdin,globl,hidden
diff --git a/libc/stdio/stdin.c b/libc/stdio/stdin.c
index 83c25e9cf..ba56e117e 100644
--- a/libc/stdio/stdin.c
+++ b/libc/stdio/stdin.c
@@ -16,20 +16,26 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/calls/calls.h"
 #include "libc/stdio/internal.h"
 #include "libc/stdio/stdio.h"
-
-STATIC_YOINK("_init_stdin");
+#include "libc/sysv/consts/fileno.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/thread/thread.h"
 
 /**
  * Pointer to standard input stream.
  */
 FILE *stdin;
 
-_Hide FILE __stdin;
+static FILE __stdin;
 
-static textstartup void __stdin_init() {
+__attribute__((__constructor__)) static void __stdin_init(void) {
+  stdin = &__stdin;
+  stdin->fd = STDIN_FILENO;
+  stdin->iomode = O_RDONLY;
+  stdin->buf = stdin->mem;
+  stdin->size = sizeof(stdin->mem);
+  ((pthread_mutex_t *)stdin->lock)->_type = PTHREAD_MUTEX_RECURSIVE;
   __fflush_register(stdin);
 }
-
-const void *const __stdin_ctor[] initarray = {__stdin_init};
diff --git a/libc/stdio/stdio.h b/libc/stdio/stdio.h
index b5729bac9..e924694fa 100644
--- a/libc/stdio/stdio.h
+++ b/libc/stdio/stdio.h
@@ -74,7 +74,6 @@ FILE *freopen(const char *, const char *, FILE *) paramsnonnull((2, 3));
 size_t fread(void *, size_t, size_t, FILE *) paramsnonnull((4));
 size_t fwrite(const void *, size_t, size_t, FILE *) paramsnonnull((4));
 int fclose(FILE *);
-int fclose_s(FILE **) paramsnonnull();
 int fseek(FILE *, long, int) paramsnonnull();
 long ftell(FILE *) paramsnonnull();
 int fseeko(FILE *, int64_t, int) paramsnonnull();
diff --git a/libc/stdio/stdout-init.S b/libc/stdio/stdout-init.S
deleted file mode 100644
index db218be67..000000000
--- a/libc/stdio/stdout-init.S
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2020 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/sysv/consts/o.h"
-#include "libc/dce.h"
-#include "libc/calls/calls.h"
-#include "libc/sysv/consts/fileno.h"
-#include "libc/thread/thread.h"
-#include "libc/macros.internal.h"
-
-	.init.start 400,_init_stdout
-	ezlea	__stdout,ax
-	push	STDOUT_FILENO
-	pop	0x0c(%rax)				#→ f.fd
-	mov	O_WRONLY,%edx
-	mov	%edx,4(%rax)				#→ f.iomode
-	lea	0x50(%rax),%rcx				#← f.mem
-	mov	%rcx,0x18(%rax)				#→ f.buf
-	movl	$BUFSIZ,0x20(%rax)			#→ f.size
-	movb	$PTHREAD_MUTEX_RECURSIVE,0x38+4(%rax)	#→ f.lock._type
-	mov	%rax,stdout(%rip)
-	.init.end 400,_init_stdout,globl,hidden
diff --git a/libc/stdio/stdout.c b/libc/stdio/stdout.c
index fb83bc299..0b4ec5f24 100644
--- a/libc/stdio/stdout.c
+++ b/libc/stdio/stdout.c
@@ -18,23 +18,28 @@
 ╚─────────────────────────────────────────────────────────────────────────────*/
 #include "libc/calls/calls.h"
 #include "libc/dce.h"
-#include "libc/intrin/pushpop.h"
 #include "libc/stdio/internal.h"
 #include "libc/stdio/stdio.h"
-
-STATIC_YOINK("_init_stdout");
+#include "libc/sysv/consts/fileno.h"
+#include "libc/sysv/consts/o.h"
+#include "libc/thread/thread.h"
 
 /**
  * Pointer to standard output stream.
  */
 FILE *stdout;
 
-_Hide FILE __stdout;
+static FILE __stdout;
+
+__attribute__((__constructor__)) static void __stdout_init(void) {
+  stdout = &__stdout;
+
+  stdout->fd = STDOUT_FILENO;
+  stdout->iomode = O_WRONLY;
+  stdout->buf = stdout->mem;
+  stdout->size = sizeof(stdout->mem);
+  ((pthread_mutex_t *)stdout->lock)->_type = PTHREAD_MUTEX_RECURSIVE;
 
-static textstartup void __stdout_init() {
-  struct FILE *sf;
-  sf = stdout;
-  asm("" : "+r"(sf));
   /*
    * Unlike other C libraries we don't bother calling fstat() to check
    * if stdio is a character device and we instead choose to always line
@@ -43,8 +48,7 @@ static textstartup void __stdout_init() {
    * value latency more than throughput, and stdio isn't the best api
    * when the goal is throughput.
    */
-  sf->bufmode = _IOLBF;
-  __fflush_register(sf);
-}
+  stdout->bufmode = _IOLBF;
 
-const void *const __stdout_ctor[] initarray = {__stdout_init};
+  __fflush_register(stdout);
+}
diff --git a/libc/str/crc32c.c b/libc/str/crc32c.c
index c484e5f51..69099d1ba 100644
--- a/libc/str/crc32c.c
+++ b/libc/str/crc32c.c
@@ -19,57 +19,13 @@
 #include "libc/nexgen32e/crc32.h"
 #include "libc/nexgen32e/x86feature.h"
 
-#ifndef __x86_64__
-const uint32_t kCrc32cTab[256] = {
-    0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c,
-    0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
-    0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c,
-    0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
-    0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54, 0x5d1d08bf, 0xaf768bbc,
-    0xbc267848, 0x4e4dfb4b, 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
-    0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35, 0xaa64d611, 0x580f5512,
-    0x4b5fa6e6, 0xb93425e5, 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
-    0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45, 0xf779deae, 0x05125dad,
-    0x1642ae59, 0xe4292d5a, 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
-    0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595, 0x417b1dbc, 0xb3109ebf,
-    0xa0406d4b, 0x522bee48, 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
-    0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687, 0x0c38d26c, 0xfe53516f,
-    0xed03a29b, 0x1f682198, 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
-    0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38, 0xdbfc821c, 0x2997011f,
-    0x3ac7f2eb, 0xc8ac71e8, 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
-    0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096, 0xa65c047d, 0x5437877e,
-    0x4767748a, 0xb50cf789, 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
-    0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46, 0x7198540d, 0x83f3d70e,
-    0x90a324fa, 0x62c8a7f9, 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
-    0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36, 0x3cdb9bdd, 0xceb018de,
-    0xdde0eb2a, 0x2f8b6829, 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
-    0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93, 0x082f63b7, 0xfa44e0b4,
-    0xe9141340, 0x1b7f9043, 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
-    0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3, 0x55326b08, 0xa759e80b,
-    0xb4091bff, 0x466298fc, 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
-    0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033, 0xa24bb5a6, 0x502036a5,
-    0x4370c551, 0xb11b4652, 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
-    0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d, 0xef087a76, 0x1d63f975,
-    0x0e330a81, 0xfc588982, 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
-    0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622, 0x38cc2a06, 0xcaa7a905,
-    0xd9f75af1, 0x2b9cd9f2, 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
-    0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530, 0x0417b1db, 0xf67c32d8,
-    0xe52cc12c, 0x1747422f, 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
-    0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0, 0xd3d3e1ab, 0x21b862a8,
-    0x32e8915c, 0xc083125f, 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
-    0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90, 0x9e902e7b, 0x6cfbad78,
-    0x7fab5e8c, 0x8dc0dd8f, 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
-    0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1, 0x69e9f0d5, 0x9b8273d6,
-    0x88d28022, 0x7ab90321, 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
-    0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81, 0x34f4f86a, 0xc69f7b69,
-    0xd5cf889d, 0x27a40b9e, 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
-    0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351,
-};
-#endif
-
 /**
  * Computes 32-bit Castagnoli Cyclic Redundancy Check.
  *
+ *     x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
+ *     0b00011110110111000110111101000001
+ *     _bitreverse32(0x1edc6f41)
+ *
  * @param init is the initial hash value
  * @param data points to the data
  * @param size is the byte size of data
@@ -78,7 +34,13 @@ const uint32_t kCrc32cTab[256] = {
  */
 uint32_t crc32c(uint32_t init, const void *data, size_t size) {
   uint64_t h;
+  static bool once;
   const unsigned char *p, *pe;
+  static uint32_t kCrc32cTab[256];
+  if (!once) {
+    crc32init(kCrc32cTab, 0x82f63b78);
+    once = 0;
+  }
   p = data;
   pe = p + size;
   h = init ^ 0xffffffff;
diff --git a/libc/str/crc32z.c b/libc/str/crc32z.c
index ff332e2ac..468891981 100644
--- a/libc/str/crc32z.c
+++ b/libc/str/crc32z.c
@@ -16,10 +16,8 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/assert.h"
 #include "libc/dce.h"
 #include "libc/intrin/asan.internal.h"
-#include "libc/intrin/safemacros.internal.h"
 #include "libc/macros.internal.h"
 #include "libc/nexgen32e/crc32.h"
 #include "libc/nexgen32e/x86feature.h"
diff --git a/libc/testlib/clearxmmregisters.c b/libc/testlib/clearxmmregisters.c
index 104d38eaa..f3c05d906 100644
--- a/libc/testlib/clearxmmregisters.c
+++ b/libc/testlib/clearxmmregisters.c
@@ -19,6 +19,7 @@
 #include "libc/testlib/testlib.h"
 
 void testlib_clearxmmregisters(void) {
+#ifdef __x86_64__
   asm("pxor\t%xmm0,%xmm0\n\t"
       "pxor\t%xmm1,%xmm1\n\t"
       "pxor\t%xmm2,%xmm2\n\t"
@@ -27,4 +28,5 @@ void testlib_clearxmmregisters(void) {
       "pxor\t%xmm5,%xmm5\n\t"
       "pxor\t%xmm6,%xmm6\n\t"
       "pxor\t%xmm7,%xmm7");
+#endif
 }
diff --git a/libc/testlib/getcore.c b/libc/testlib/getcore.c
index 6cace6cca..44a08cd2e 100644
--- a/libc/testlib/getcore.c
+++ b/libc/testlib/getcore.c
@@ -20,7 +20,11 @@
 #include "libc/testlib/ezbench.h"
 
 int __testlib_getcore(void) {
+#ifdef __x86__
   long tscaux;
   tscaux = rdpid();
   return TSC_AUX_CORE(tscaux);
+#else
+  return 0;
+#endif
 }
diff --git a/libc/testlib/showerror.c b/libc/testlib/showerror.c
index 546665e25..60cc7345a 100644
--- a/libc/testlib/showerror.c
+++ b/libc/testlib/showerror.c
@@ -25,6 +25,7 @@
 #include "libc/log/color.internal.h"
 #include "libc/log/internal.h"
 #include "libc/log/libfatal.internal.h"
+#include "libc/mem/mem.h"
 #include "libc/str/str.h"
 #include "libc/testlib/testlib.h"
 
@@ -51,8 +52,8 @@ void testlib_showerror(const char *file, int line, const char *func,
           RED2, UNBOLD, BLUE1, file, (long)line, RESET, method, func,
           g_fixturename, hostname, getpid(), gettid(), code, v1, symbol, v2,
           SUBTLE, strerror(errno), GetProgramExecutableName(), RESET);
-  free_s(&v1);
-  free_s(&v2);
+  free(v1);
+  free(v2);
 }
 
 /* TODO(jart): Pay off tech debt re duplication */
@@ -89,8 +90,8 @@ void testlib_showerror_(int line, const char *wantcode, const char *gotcode,
           "\t%s%s @ %s%s\n",
           SUBTLE, strerror(e), RESET, SUBTLE,
           firstnonnull(program_invocation_name, "unknown"), hostname, RESET);
-  free_s(&FREED_want);
-  free_s(&FREED_got);
+  free(FREED_want);
+  free(FREED_got);
   ++g_testlib_failed;
   if (testlib_showerror_isfatal) {
     testlib_abort();
diff --git a/libc/thread/pthread_cancel.c b/libc/thread/pthread_cancel.c
index 5a451aed5..81876935d 100644
--- a/libc/thread/pthread_cancel.c
+++ b/libc/thread/pthread_cancel.c
@@ -36,6 +36,8 @@
 #include "libc/thread/thread.h"
 #include "libc/thread/tls.h"
 
+#ifdef __x86_64__
+
 int systemfive_cancel(void);
 
 extern const char systemfive_cancellable[];
@@ -293,6 +295,8 @@ errno_t pthread_cancel(pthread_t thread) {
   return rc;
 }
 
+#endif /* __x86_64__ */
+
 /**
  * Creates cancellation point in calling thread.
  *
diff --git a/net/https/sslcache.c b/net/https/sslcache.c
index 79c4ceaa5..fb602a810 100644
--- a/net/https/sslcache.c
+++ b/net/https/sslcache.c
@@ -16,11 +16,12 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "net/https/sslcache.h"
 #include "libc/calls/calls.h"
 #include "libc/calls/struct/stat.h"
 #include "libc/errno.h"
 #include "libc/intrin/bits.h"
-#include "libc/intrin/lockcmpxchg.h"
+#include "libc/intrin/cmpxchg.h"
 #include "libc/intrin/safemacros.internal.h"
 #include "libc/log/check.h"
 #include "libc/log/log.h"
@@ -32,7 +33,6 @@
 #include "libc/sysv/consts/o.h"
 #include "libc/sysv/consts/prot.h"
 #include "libc/time/time.h"
-#include "net/https/sslcache.h"
 #include "third_party/mbedtls/ssl.h"
 #include "third_party/mbedtls/x509_crt.h"
 
@@ -131,7 +131,7 @@ int UncacheSslSession(void *data, mbedtls_ssl_session *session) {
   ts = time(0);
   if (!(e->time <= ts && ts <= e->time + cache->lifetime)) {
     DEBUGF("%u sslcache expired", i);
-    _lockcmpxchg(&e->tick, tick, 0);
+    _cmpxchg(&e->tick, tick, 0);
     return 1;
   }
   cert = 0;
@@ -201,7 +201,7 @@ int CacheSslSession(void *data, const mbedtls_ssl_session *session) {
   e->time = time(0);
   tick = rdtsc();
   asm volatile("" ::: "memory");
-  if (tick && _lockcmpxchg(&e->pid, pid, 0)) {
+  if (tick && _cmpxchg(&e->pid, pid, 0)) {
     DEBUGF("%u saved %s%s %`#.*s", i,
            mbedtls_ssl_get_ciphersuite_name(session->ciphersuite),
            session->compression ? " DEFLATE" : "", session->id_len,
diff --git a/test/libc/mem/arraylist_test.c b/test/libc/mem/arraylist_test.c
index ef007404b..2cb7f226e 100644
--- a/test/libc/mem/arraylist_test.c
+++ b/test/libc/mem/arraylist_test.c
@@ -16,9 +16,9 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "libc/log/libfatal.internal.h"
 #include "libc/mem/alg.h"
 #include "libc/mem/arraylist.internal.h"
-#include "libc/log/libfatal.internal.h"
 #include "libc/mem/mem.h"
 #include "libc/runtime/runtime.h"
 #include "libc/str/str.h"
@@ -48,7 +48,8 @@ TEST(append, worksGreatForScalars) {
   }
   ASSERT_EQ(1024, s.i);
   for (size_t i = 0; i < s.i; ++i) ASSERT_EQ('a', s.p[i]);
-  free_s(&s.p);
+  free(s.p);
+  s.p = 0;
 }
 
 TEST(append, isGenericallyTyped) {
@@ -63,7 +64,8 @@ TEST(append, isGenericallyTyped) {
   for (size_t i = 0; i < s.i; ++i) {
     ASSERT_EQ(0x31337, s.p[i]);
   }
-  free_s(&s.p);
+  free(s.p);
+  s.p = 0;
 }
 
 TEST(concat, worksGreatForStrings) {
@@ -79,7 +81,8 @@ TEST(concat, worksGreatForStrings) {
                "Wir werden wieder auferstehen\n",
                s.p);
   ASSERT_EQ(strlen(ks) * 2 + 1, s.i);
-  free_s(&s.p);
+  free(s.p);
+  s.p = 0;
 }
 
 TEST(concat, isGenericallyTyped) {
@@ -95,5 +98,6 @@ TEST(concat, isGenericallyTyped) {
                u"Unsere schwarzen Seelen bekommt ihr nicht.\n",
                s.p);
   ASSERT_EQ(strlen16(ks) * 2 + 1, s.i);
-  free_s(&s.p);
+  free(s.p);
+  s.p = 0;
 }
diff --git a/test/libc/runtime/grow_test.c b/test/libc/runtime/grow_test.c
index 08e541056..fc154d122 100644
--- a/test/libc/runtime/grow_test.c
+++ b/test/libc/runtime/grow_test.c
@@ -32,7 +32,7 @@ TEST(grow, testNull_hasAllocatingBehavior) {
   EXPECT_TRUE(__grow(&p, &capacity, 1, 0));
   EXPECT_NE(NULL, p);
   EXPECT_EQ(32, capacity);
-  free_s(&p);
+  free(p);
 }
 
 TEST(grow, testCapacity_isInUnits_withTerminatorGuarantee) {
@@ -41,7 +41,7 @@ TEST(grow, testCapacity_isInUnits_withTerminatorGuarantee) {
   EXPECT_TRUE(__grow(&p, &capacity, 8, 0));
   EXPECT_NE(NULL, p);
   EXPECT_EQ(32 / 8 + 1, capacity);
-  free_s(&p);
+  free(p);
 }
 
 TEST(grow, testStackMemory_convertsToDynamic) {
@@ -69,7 +69,7 @@ TEST(grow, testGrowth_clearsNewMemory) {
   EXPECT_GT(capacity, 123);
   for (i = 0; i < 123; ++i) ASSERT_EQ('a', p[i]);
   for (i = 123; i < capacity; ++i) ASSERT_EQ(0, p[i]);
-  free_s(&p);
+  free(p);
 }
 
 TEST(grow, testBonusParam_willGoAboveAndBeyond) {
@@ -77,11 +77,11 @@ TEST(grow, testBonusParam_willGoAboveAndBeyond) {
   char *p = malloc(capacity);
   EXPECT_TRUE(__grow(&p, &capacity, 1, 0));
   EXPECT_LT(capacity, 1024);
-  free_s(&p);
+  free(p);
   p = malloc((capacity = 32));
   EXPECT_TRUE(__grow(&p, &capacity, 1, 1024));
   EXPECT_GT(capacity, 1024);
-  free_s(&p);
+  free(p);
 }
 
 TEST(grow, testOverflow_returnsFalseAndDoesNotFree) {
@@ -95,6 +95,6 @@ TEST(grow, testOverflow_returnsFalseAndDoesNotFree) {
     EXPECT_EQ(1, p[0]);
     EXPECT_EQ(2, p[1]);
     EXPECT_EQ(3, p[2]);
-    free_s(&p);
+    free(p);
   }
 }
diff --git a/third_party/dlmalloc/dlmalloc.c b/third_party/dlmalloc/dlmalloc.c
index 250eee7b0..95b107ca0 100644
--- a/third_party/dlmalloc/dlmalloc.c
+++ b/third_party/dlmalloc/dlmalloc.c
@@ -1,3 +1,4 @@
+#include "third_party/dlmalloc/dlmalloc.h"
 #include "libc/assert.h"
 #include "libc/calls/calls.h"
 #include "libc/dce.h"
@@ -16,7 +17,6 @@
 #include "libc/sysv/consts/map.h"
 #include "libc/sysv/consts/prot.h"
 #include "libc/thread/thread.h"
-#include "third_party/dlmalloc/dlmalloc.h"
 #include "third_party/dlmalloc/vespene.internal.h"
 // clang-format off
 
@@ -1418,7 +1418,7 @@ int dlmallopt(int param_number, int value) {
   return change_mparam(param_number, value);
 }
 
-size_t dlmalloc_usable_size(const void* mem) {
+size_t dlmalloc_usable_size(void* mem) {
   mchunkptr p;
   size_t bytes;
   if (mem) {
diff --git a/third_party/dlmalloc/dlmalloc.h b/third_party/dlmalloc/dlmalloc.h
index ab095f8c5..03162b1af 100644
--- a/third_party/dlmalloc/dlmalloc.h
+++ b/third_party/dlmalloc/dlmalloc.h
@@ -415,7 +415,7 @@ void dlmalloc_stats(void);
   p = malloc(n);
   assert(malloc_usable_size(p) >= 256);
 */
-size_t dlmalloc_usable_size(const void*);
+size_t dlmalloc_usable_size(void*);
 
 /*
   mspace is an opaque type representing an independent
diff --git a/third_party/dlmalloc/dlmalloc.mk b/third_party/dlmalloc/dlmalloc.mk
index 8119ec2b6..a0da1c366 100644
--- a/third_party/dlmalloc/dlmalloc.mk
+++ b/third_party/dlmalloc/dlmalloc.mk
@@ -9,16 +9,8 @@ THIRD_PARTY_DLMALLOC_A = o/$(MODE)/third_party/dlmalloc/dlmalloc.a
 THIRD_PARTY_DLMALLOC_A_FILES := $(wildcard third_party/dlmalloc/*)
 THIRD_PARTY_DLMALLOC_A_HDRS = $(filter %.h,$(THIRD_PARTY_DLMALLOC_A_FILES))
 THIRD_PARTY_DLMALLOC_A_INCS = $(filter %.inc,$(THIRD_PARTY_DLMALLOC_A_FILES))
-THIRD_PARTY_DLMALLOC_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_DLMALLOC_A_FILES))
-THIRD_PARTY_DLMALLOC_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_DLMALLOC_A_FILES))
-
-THIRD_PARTY_DLMALLOC_A_SRCS =					\
-	$(THIRD_PARTY_DLMALLOC_A_SRCS_S)			\
-	$(THIRD_PARTY_DLMALLOC_A_SRCS_C)
-
-THIRD_PARTY_DLMALLOC_A_OBJS =					\
-	$(THIRD_PARTY_DLMALLOC_A_SRCS_S:%.S=o/$(MODE)/%.o)	\
-	$(THIRD_PARTY_DLMALLOC_A_SRCS_C:%.c=o/$(MODE)/%.o)
+THIRD_PARTY_DLMALLOC_A_SRCS = $(filter %.c,$(THIRD_PARTY_DLMALLOC_A_FILES))
+THIRD_PARTY_DLMALLOC_A_OBJS = $(THIRD_PARTY_DLMALLOC_A_SRCS:%.c=o/$(MODE)/%.o)
 
 THIRD_PARTY_DLMALLOC_A_CHECKS =					\
 	$(THIRD_PARTY_DLMALLOC_A).pkg				\
diff --git a/third_party/dlmalloc/init.S b/third_party/dlmalloc/init.S
deleted file mode 100644
index cd51aa0e3..000000000
--- a/third_party/dlmalloc/init.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8     -*-│
-│vi: set et ft=asm ts=8 tw=8 fenc=utf-8                                     :vi│
-╞══════════════════════════════════════════════════════════════════════════════╡
-│ Copyright 2022 Justine Alexandra Roberts Tunney                              │
-│                                                                              │
-│ Permission to use, copy, modify, and/or distribute this software for         │
-│ any purpose with or without fee is hereby granted, provided that the         │
-│ above copyright notice and this permission notice appear in all copies.      │
-│                                                                              │
-│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL                │
-│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED                │
-│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE             │
-│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL         │
-│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR        │
-│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER               │
-│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
-│ PERFORMANCE OF THIS SOFTWARE.                                                │
-╚─────────────────────────────────────────────────────────────────────────────*/
-#include "libc/macros.internal.h"
-
-	.init.start 600,_init_dlmalloc
-	push	%rdi
-	push	%rsi
-	call	init_mparams
-	pop	%rsi
-	pop	%rdi
-	.init.end 600,_init_dlmalloc
diff --git a/third_party/dlmalloc/init.inc b/third_party/dlmalloc/init.inc
index c93477238..810412d13 100644
--- a/third_party/dlmalloc/init.inc
+++ b/third_party/dlmalloc/init.inc
@@ -1,7 +1,5 @@
 // clang-format off
 
-STATIC_YOINK("_init_dlmalloc");
-
 /* ---------------------------- setting mparams -------------------------- */
 
 #if LOCK_AT_FORK
@@ -11,7 +9,7 @@ static void dlmalloc_post_fork_child(void)  { INITIAL_LOCK(&(gm)->mutex); }
 #endif /* LOCK_AT_FORK */
 
 /* Initialize mparams */
-int init_mparams(void) {
+__attribute__((__constructor__)) int init_mparams(void) {
 #ifdef NEED_GLOBAL_LOCK_INIT
   if (malloc_global_mutex_status <= 0)
     init_malloc_global_mutex();
diff --git a/third_party/ggml/ggml.mk b/third_party/ggml/ggml.mk
index 2d2118829..fd5c8ad13 100644
--- a/third_party/ggml/ggml.mk
+++ b/third_party/ggml/ggml.mk
@@ -45,12 +45,17 @@ $(THIRD_PARTY_GGML_A_OBJS): private					\
 		OVERRIDE_CFLAGS +=					\
 			-O3						\
 			-ffunction-sections				\
-			-fdata-sections					\
+			-fdata-sections
+
+ifeq ($(ARCH), x86_64)
+$(THIRD_PARTY_GGML_A_OBJS): private					\
+		OVERRIDE_CFLAGS +=					\
 			-msse3						\
 			-mavx						\
 			-mavx2						\
 			-mf16c						\
 			-mfma
+endif
 
 ################################################################################
 # command for running inference on large language models
diff --git a/third_party/zlib/adler32simd.c b/third_party/zlib/adler32simd.c
index ee5568bc8..0fe0be144 100644
--- a/third_party/zlib/adler32simd.c
+++ b/third_party/zlib/adler32simd.c
@@ -58,6 +58,8 @@ asm(".include \"libc/disclaimer.inc\"");
 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
 #define NMAX 5552
 
+#ifdef ADLER32_SIMD_SSSE3
+
 uint32_t adler32_simd_(uint32_t adler, const unsigned char *buf, size_t len) {
   /*
    * Split Adler-32 into component sums.
@@ -192,3 +194,5 @@ uint32_t adler32_simd_(uint32_t adler, const unsigned char *buf, size_t len) {
    */
   return s1 | (s2 << 16);
 }
+
+#endif /* ADLER32_SIMD_SSSE3 */
diff --git a/third_party/zlib/zlib.mk b/third_party/zlib/zlib.mk
index af06671c8..ed0b7eaad 100644
--- a/third_party/zlib/zlib.mk
+++ b/third_party/zlib/zlib.mk
@@ -41,17 +41,17 @@ $(THIRD_PARTY_ZLIB_A).pkg:				\
 		$(THIRD_PARTY_ZLIB_A_OBJS)		\
 		$(foreach x,$(THIRD_PARTY_ZLIB_A_DIRECTDEPS),$($(x)_A).pkg)
 
+ifeq ($(ARCH), x86_64)
 o/$(MODE)/third_party/zlib/adler32simd.o: private	\
 		OVERRIDE_CFLAGS +=			\
 			-mssse3
-
 o/$(MODE)/third_party/zlib/adler32.o: private		\
 		OVERRIDE_CPPFLAGS +=			\
 			-DADLER32_SIMD_SSSE3
-
 o/$(MODE)/third_party/zlib/deflate.o: private		\
 		OVERRIDE_CPPFLAGS +=			\
 			-DCRC32_SIMD_SSE42_PCLMUL
+endif
 
 $(THIRD_PARTY_ZLIB_A_OBJS): private			\
 		OVERRIDE_CFLAGS +=			\
diff --git a/tool/build/lib/interner.c b/tool/build/lib/interner.c
index 1ac897d0f..b1c89d658 100644
--- a/tool/build/lib/interner.c
+++ b/tool/build/lib/interner.c
@@ -16,13 +16,13 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "tool/build/lib/interner.h"
 #include "libc/intrin/safemacros.internal.h"
 #include "libc/mem/mem.h"
 #include "libc/nexgen32e/crc32.h"
 #include "libc/runtime/runtime.h"
 #include "libc/str/str.h"
 #include "libc/x/x.h"
-#include "tool/build/lib/interner.h"
 
 #define kInitialItems 16
 
@@ -50,7 +50,7 @@ static void rehash(struct InternerObject *it) {
     } while (it->p[j].hash);
     memcpy(&it->p[j], &p[i], sizeof(p[i]));
   }
-  free_s(&p);
+  free(p);
 }
 
 /**
diff --git a/tool/build/rle.c b/tool/build/rle.c
index 5ca186e8b..16b3c3696 100644
--- a/tool/build/rle.c
+++ b/tool/build/rle.c
@@ -114,7 +114,7 @@ void GetOpts(int argc, char *argv[]) {
         test_ = true;
         break;
       case 'o':
-        fclose_s(&fout_);
+        fclose(fout_);
         if (!(fout_ = fopen((hint_ = optarg), "w"))) {
           PrintIoErrorMessage();
           exit(1);
@@ -191,9 +191,11 @@ int Run(char **paths, size_t count) {
     hint_ = "/dev/stdin";
     if (!fout_) fout_ = stdout;
     rc = RunLengthCode();
-    rc |= fclose_s(&fin_);
+    rc |= fclose(fin_);
+    fin_ = 0;
   } else {
-    rc = fclose_s(&fin_);
+    rc = fclose(fin_);
+    fin_ = 0;
     for (i = 0; i < count && rc != -1; ++i) {
       rc = -1;
       if ((fin_ = fopen((hint_ = paths[i]), "r"))) {
@@ -219,18 +221,21 @@ int Run(char **paths, size_t count) {
             if (rc != -1 && !decompress_) {
               rc = RunLengthEncode2();
             }
-            if ((rc |= fclose_s(&fout_)) != -1) {
+            if ((rc |= fclose(fout_)) != -1) {
               unlink(paths[i]);
             }
+            fout_ = 0;
           }
         }
-        rc |= fclose_s(&fin_);
+        rc |= fclose(fin_);
+        fin_ = 0;
       }
     }
   }
   if (rc != -1 && fout_) {
     rc = RunLengthEncode2();
-    rc |= fclose_s(&fout_);
+    rc |= fclose(fout_);
+    fout_ = 0;
   }
   return rc;
 }
diff --git a/tool/decode/lib/bitabuilder.c b/tool/decode/lib/bitabuilder.c
index 9652b36b6..d4d4fee4d 100644
--- a/tool/decode/lib/bitabuilder.c
+++ b/tool/decode/lib/bitabuilder.c
@@ -16,6 +16,7 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "tool/decode/lib/bitabuilder.h"
 #include "libc/assert.h"
 #include "libc/intrin/bits.h"
 #include "libc/log/check.h"
@@ -24,7 +25,6 @@
 #include "libc/runtime/runtime.h"
 #include "libc/stdio/stdio.h"
 #include "libc/str/str.h"
-#include "tool/decode/lib/bitabuilder.h"
 
 /**
  * @fileoverview Sparse bit array builder.
@@ -41,8 +41,9 @@ struct BitaBuilder *bitabuilder_new(void) {
 
 void bitabuilder_free(struct BitaBuilder **bbpp) {
   if (*bbpp) {
-    free_s(&(*bbpp)->p);
-    free_s(bbpp);
+    free((*bbpp)->p);
+    free(*bbpp);
+    *bbpp = 0;
   }
 }
 
diff --git a/tool/viz/comma.c b/tool/viz/comma.c
index 70118c23d..95e049531 100644
--- a/tool/viz/comma.c
+++ b/tool/viz/comma.c
@@ -95,9 +95,11 @@ int main(int argc, char *argv[]) {
   for (i = optind; i < argc; ++i) {
     CHECK_NOTNULL((in_ = fopen((inpath_ = argv[i]), "r")));
     ProcessFile();
-    CHECK_NE(-1, fclose_s(&in_));
+    CHECK_NE(-1, fclose(in_));
+    in_ = 0;
   }
-  CHECK_NE(-1, fclose_s(&out_));
+  CHECK_NE(-1, fclose(out_));
+  out_ = 0;
   free(line_);
   return 0;
 }
diff --git a/tool/viz/invertblocks.c b/tool/viz/invertblocks.c
index b7b6849a4..dc430b37c 100644
--- a/tool/viz/invertblocks.c
+++ b/tool/viz/invertblocks.c
@@ -107,8 +107,10 @@ int main(int argc, char *argv[]) {
   for (i = optind; i < argc; ++i) {
     CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r")));
     processfile();
-    CHECK_NE(-1, fclose_s(&fi_));
+    CHECK_NE(-1, fclose(fi_));
+    fi_ = 0;
   }
-  CHECK_NE(-1, fclose_s(&fo_));
+  CHECK_NE(-1, fclose(fo_));
+  fo_ = 0;
   return 0;
 }
diff --git a/tool/viz/lib/formatstringtable.c b/tool/viz/lib/formatstringtable.c
index 0dfe56549..605373804 100644
--- a/tool/viz/lib/formatstringtable.c
+++ b/tool/viz/lib/formatstringtable.c
@@ -16,15 +16,16 @@
 │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR             │
 │ PERFORMANCE OF THIS SOFTWARE.                                                │
 ╚─────────────────────────────────────────────────────────────────────────────*/
+#include "tool/viz/lib/formatstringtable.h"
 #include "libc/intrin/safemacros.internal.h"
 #include "libc/str/strwidth.h"
-#include "tool/viz/lib/formatstringtable.h"
 
 void *FreeStringTableCells(long yn, long xn, char *T[yn][xn]) {
   long y, x;
   for (y = 0; y < yn; ++y) {
     for (x = 0; x < xn; ++x) {
-      free_s(&T[y][x]);
+      free(T[y][x]);
+      T[y][x] = 0;
     }
   }
   return T;
diff --git a/tool/viz/od16.c b/tool/viz/od16.c
index 75c09a98e..97663bf90 100644
--- a/tool/viz/od16.c
+++ b/tool/viz/od16.c
@@ -102,8 +102,10 @@ int main(int argc, char *argv[]) {
   for (i = optind; i < argc; ++i) {
     CHECK_NOTNULL((in_ = fopen((inpath_ = argv[i]), "r")));
     ProcessFile();
-    CHECK_NE(-1, fclose_s(&in_));
+    CHECK_NE(-1, fclose(in_));
+    in_ = 0;
   }
-  CHECK_NE(-1, fclose_s(&out_));
+  CHECK_NE(-1, fclose(out_));
+  out_ = 0;
   return 0;
 }
diff --git a/tool/viz/rgbtoxterm.c b/tool/viz/rgbtoxterm.c
index cb9b405bb..44262aa1d 100644
--- a/tool/viz/rgbtoxterm.c
+++ b/tool/viz/rgbtoxterm.c
@@ -122,11 +122,13 @@ int main(int argc, char *argv[]) {
     while ((getline(&line_, &linecap_, stdin)) != -1) {
       processarg(_chomp(line_));
     }
-    free_s(&line_);
+    free(line_);
+    line_ = 0;
   }
   if (cleanup_) {
     fprintf(fout_, "%s[0m\n", rawmode_ ? "\e" : "\\e");
   }
-  CHECK_NE(-1, fclose_s(&fout_));
+  CHECK_NE(-1, fclose(fout_));
+  fout_ = 0;
   return 0;
 }
diff --git a/tool/viz/tabalign.c b/tool/viz/tabalign.c
index c0579267e..069a5d4a9 100644
--- a/tool/viz/tabalign.c
+++ b/tool/viz/tabalign.c
@@ -164,10 +164,12 @@ int main(int argc, char *argv[]) {
   for (i = optind; i < argc; ++i) {
     CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r")));
     processfile();
-    CHECK_NE(-1, fclose_s(&fi_));
+    CHECK_NE(-1, fclose(fi_));
+    fi_ = 0;
   }
   flush();
-  CHECK_NE(-1, fclose_s(&fo_));
+  CHECK_NE(-1, fclose(fo_));
+  fo_ = 0;
   free(lines_.p);
   free(pool_.p);
   free(line_);
diff --git a/tool/viz/xterm256effective2.c b/tool/viz/xterm256effective2.c
index 0ba3216a2..e5e4e9c03 100644
--- a/tool/viz/xterm256effective2.c
+++ b/tool/viz/xterm256effective2.c
@@ -176,9 +176,11 @@ int main(int argc, char *argv[]) {
   for (i = optind; i < argc; ++i) {
     CHECK_NOTNULL((in_ = fopen((inpath_ = argv[i]), "r")));
     ProcessFile();
-    CHECK_NE(-1, fclose_s(&in_));
+    CHECK_NE(-1, fclose(in_));
+    in_ = 0;
   }
-  CHECK_NE(-1, fclose_s(&out_));
+  CHECK_NE(-1, fclose(out_));
+  out_ = 0;
   free(line_);
   return 0;
 }