Make more functions friendly to Address Sanitizer

This commit is contained in:
Justine Tunney 2021-02-02 03:45:31 -08:00
parent 3ab76b2312
commit cbfd4ccd1e
70 changed files with 1267 additions and 291 deletions

View file

@ -199,6 +199,7 @@ include test/test.mk
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
SRCS = $(foreach x,$(PKGS),$($(x)_SRCS))
HDRS = $(foreach x,$(PKGS),$($(x)_HDRS))
INCS = $(foreach x,$(PKGS),$($(x)_INCS))
BINS = $(foreach x,$(PKGS),$($(x)_BINS))
TESTS = $(foreach x,$(PKGS),$($(x)_TESTS))
CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
@ -215,10 +216,10 @@ o/$(MODE)/.x:
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS),$(dir $(x))))
$(file >$@) $(foreach x,$(HDRS),$(file >>$@,$(x)))
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS)
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt $(SRCS) $(HDRS) $(INCS)
@build/mkdeps -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt
TAGS: o/$(MODE)/srcs.txt $(SRCS)
@ -351,6 +352,7 @@ o/cosmopolitan.html: \
~/.cosmo.mk:
$(SRCS):
$(HDRS):
$(INCS):
.DEFAULT:
@echo >&2
@echo NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2

View file

@ -33,6 +33,7 @@ APELINK = \
APE_FILES := $(wildcard ape/*.*)
APE_HDRS = $(filter %.h,$(APE_FILES))
APE_INCS = $(filter %.inc,$(APE_FILES))
APE_SRCS = $(filter %.S,$(APE_FILES))
APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
APE_DEPS = $(APE_LIB)

View file

@ -37,6 +37,8 @@ export LC_ALL=C
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
GZME=
ASAN=
UBSAN=
PLAT="${1%% *}"
FDIAGNOSTIC_COLOR=
CCNAME=${CCNAME:-gcc}
@ -87,11 +89,21 @@ for x; do
set -- "$@" "$x" -Wa,-msse2avx -D__MNO_VZEROUPPER__
;;
-fsanitize=address)
set -- "$@" "$x" -D__FSANITIZE_ADDRESS__
ASAN="$x -D__FSANITIZE_ADDRESS__"
;;
-fsanitize=undefined)
set -- "$@" "$x" -D__FSANITIZE_UNDEFINED__
COUNTERMAND="$COUNTERMAND -fno-data-sections" # sqlite.o
# UBSAN w/ -fdata-sections exceeds ELF's 65,280 section limit
UBSAN="$x -fno-data-sections"
;;
-fno-sanitize=address)
ASAN=
;;
-fno-sanitize=ubsan)
UBSAN=
;;
-fno-sanitize=all)
ASAN=
UBSAN=
;;
-mnop-mcount)
if [ "$CCNAME" = "gcc" ] && [ "$CCVERSION" -ge 6 ]; then
@ -256,7 +268,7 @@ else
done
fi
set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $COUNTERMAND
set -- "$@" -no-canonical-prefixes $FDIAGNOSTIC_COLOR $ASAN $UBSAN $COUNTERMAND
if [ "$SILENT" = "0" ]; then
printf "%s\n" "$*" >&2

View file

@ -2,16 +2,16 @@
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
#if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then
# set -- "o/$MODE/tool/build/mkdeps.com" "$@"
#else
if [ -x "o/$MODE/tool/build/mkdeps.com" ]; then
set -- "o/$MODE/tool/build/mkdeps.com" "$@"
else
if [ ! -x o/build/bootstrap/mkdeps.com ]; then
mkdir -p o/build/bootstrap &&
cp -a build/bootstrap/mkdeps.com \
o/build/bootstrap/mkdeps.com || exit
fi
set -- o/build/bootstrap/mkdeps.com "$@"
#fi
fi
if [ "$SILENT" = "0" ]; then
printf "%s\n" "$*" >&2

View file

@ -24,9 +24,10 @@ DSP_CORE_A_CHECKS = \
$(DSP_CORE_A_HDRS:%=o/$(MODE)/%.ok)
DSP_CORE_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_MEM \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_STR \
LIBC_TINYMATH \
LIBC_STUBS

View file

@ -30,6 +30,7 @@ DSP_SCALE_A_DIRECTDEPS = \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \
LIBC_STUBS \
LIBC_TIME \

View file

@ -8,6 +8,7 @@ LIBC_ALG = $(LIBC_ALG_A_DEPS) $(LIBC_ALG_A)
LIBC_ALG_A = o/$(MODE)/libc/alg/alg.a
LIBC_ALG_A_FILES := $(wildcard libc/alg/*)
LIBC_ALG_A_HDRS = $(filter %.h,$(LIBC_ALG_A_FILES))
LIBC_ALG_A_INCS = $(filter %.inc,$(LIBC_ALG_A_FILES))
LIBC_ALG_A_SRCS_S = $(filter %.S,$(LIBC_ALG_A_FILES))
LIBC_ALG_A_SRCS_C = $(filter %.c,$(LIBC_ALG_A_FILES))
@ -51,6 +52,7 @@ o/$(MODE)/libc/alg/critbit0.o: \
LIBC_ALG_LIBS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)))
LIBC_ALG_SRCS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_SRCS))
LIBC_ALG_HDRS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_HDRS))
LIBC_ALG_INCS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_INCS))
LIBC_ALG_CHECKS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_CHECKS))
LIBC_ALG_OBJS = $(foreach x,$(LIBC_ALG_ARTIFACTS),$($(x)_OBJS))
$(LIBC_ALG_OBJS): $(BUILD_FILES) libc/alg/alg.mk

View file

@ -21,6 +21,7 @@ LIBC_CALLS_A_FILES := \
$(wildcard libc/calls/struct/*) \
$(wildcard libc/calls/*)
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_INCS = $(filter %.inc,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))
@ -86,6 +87,7 @@ o/$(MODE)/libc/calls/mkntenvblock.o: \
LIBC_CALLS_LIBS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)))
LIBC_CALLS_SRCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_SRCS))
LIBC_CALLS_HDRS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_HDRS))
LIBC_CALLS_INCS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_INCS))
LIBC_CALLS_BINS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_BINS))
LIBC_CALLS_CHECKS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_CHECKS))
LIBC_CALLS_OBJS = $(foreach x,$(LIBC_CALLS_ARTIFACTS),$($(x)_OBJS))

View file

@ -25,13 +25,14 @@ int32_t dup3$sysv(int32_t oldfd, int32_t newfd, int flags) {
static bool once, demodernize;
int olderr, fd;
if (!once) {
once = true;
olderr = errno;
fd = __dup3$sysv(oldfd, newfd, flags);
if ((fd == -1 && errno == ENOSYS) || fd == __NR_dup3_linux) {
demodernize = true;
once = true;
errno = olderr;
} else {
once = true;
return fd;
}
} else if (!demodernize) {

View file

@ -29,9 +29,9 @@ forceinline typeof(PrefetchVirtualMemory) *GetPrefetchVirtualMemory(void) {
static bool once;
static typeof(PrefetchVirtualMemory) *PrefetchVirtualMemory_;
if (!once) {
once = true;
PrefetchVirtualMemory_ = /* win8.1+ */
GetProcAddressModule("Kernel32.dll", "PrefetchVirtualMemory");
once = true;
}
return PrefetchVirtualMemory_;
}
@ -40,9 +40,9 @@ forceinline typeof(OfferVirtualMemory) *GetOfferVirtualMemory(void) {
static bool once;
static typeof(OfferVirtualMemory) *OfferVirtualMemory_;
if (!once) {
once = true;
OfferVirtualMemory_ = /* win8.1+ */
GetProcAddressModule("Kernel32.dll", "OfferVirtualMemory");
once = true;
}
return OfferVirtualMemory_;
}

View file

@ -23,6 +23,7 @@
#include "libc/dce.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
@ -55,19 +56,21 @@ static long double MeasureNanosPerCycle(void) {
}
static void InitTime(void) {
g_now.cpn = MeasureNanosPerCycle();
g_now.r0 = dtime(CLOCK_REALTIME);
g_now.k0 = rdtsc();
g_now.once = true;
struct Now now;
now.cpn = MeasureNanosPerCycle();
now.r0 = dtime(CLOCK_REALTIME);
now.k0 = rdtsc();
now.once = true;
memcpy(&g_now, &now, sizeof(now));
}
long double converttickstonanos(uint64_t ticks) {
long double ConvertTicksToNanos(uint64_t ticks) {
if (!g_now.once) InitTime();
return ticks * g_now.cpn; /* pico scale */
}
long double converttickstoseconds(uint64_t ticks) {
return 1 / 1e9 * converttickstonanos(ticks);
static long double ConvertTicksToSeconds(uint64_t ticks) {
return 1 / 1e9 * ConvertTicksToNanos(ticks);
}
long double nowl$sys(void) {
@ -78,5 +81,5 @@ long double nowl$art(void) {
uint64_t ticks;
if (!g_now.once) InitTime();
ticks = unsignedsubtract(rdtsc(), g_now.k0);
return g_now.r0 + converttickstoseconds(ticks);
return g_now.r0 + ConvertTicksToSeconds(ticks);
}

View file

@ -17,6 +17,7 @@ LIBC_FMT = $(LIBC_FMT_A_DEPS) $(LIBC_FMT_A)
LIBC_FMT_A = o/$(MODE)/libc/fmt/fmt.a
LIBC_FMT_A_FILES := $(wildcard libc/fmt/*)
LIBC_FMT_A_HDRS = $(filter %.h,$(LIBC_FMT_A_FILES))
LIBC_FMT_A_INCS = $(filter %.inc,$(LIBC_FMT_A_FILES))
LIBC_FMT_A_SRCS_S = $(filter %.S,$(LIBC_FMT_A_FILES))
LIBC_FMT_A_SRCS_C = $(filter %.c,$(LIBC_FMT_A_FILES))
@ -75,6 +76,7 @@ o/$(MODE)/libc/fmt/itoa128radix10.greg.o: \
LIBC_FMT_LIBS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)))
LIBC_FMT_SRCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_SRCS))
LIBC_FMT_HDRS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_HDRS))
LIBC_FMT_INCS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_INCS))
LIBC_FMT_CHECKS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_CHECKS))
LIBC_FMT_OBJS = $(foreach x,$(LIBC_FMT_ARTIFACTS),$($(x)_OBJS))
$(LIBC_FMT_OBJS): $(BUILD_FILES) libc/fmt/fmt.mk

View file

@ -331,7 +331,7 @@ typedef uint64_t uintmax_t;
#ifndef nullterminated
#if !defined(__STRICT_ANSI__) && \
(__has_attribute(__sentinel__) || __GNUC__ >= 4)
(__has_attribute(__sentinel__) || __GNUC__ + 0 >= 4)
#define nullterminated(x) __attribute__((__sentinel__ x))
#else
#define nullterminated(x)

View file

@ -154,6 +154,13 @@ static void *__asan_repstosb(void *di, int al, size_t cx) {
return di;
}
static void *__asan_repmovsb(void *di, void *si, size_t cx) {
asm("rep movsb"
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
return di;
}
static void *__asan_memset(void *p, int c, size_t n) {
char *b;
size_t i;
@ -264,14 +271,18 @@ static void *__asan_mempcpy(void *dst, const void *src, size_t n) {
__builtin_memcpy(d + n - 8, &b, 8);
return d + n;
default:
i = 0;
do {
__builtin_memcpy(&a, s + i, 8);
asm volatile("" ::: "memory");
__builtin_memcpy(d + i, &a, 8);
} while ((i += 8) + 8 <= n);
for (; i < n; ++i) d[i] = s[i];
return d + i;
if (n <= 64) {
i = 0;
do {
__builtin_memcpy(&a, s + i, 8);
asm volatile("" ::: "memory");
__builtin_memcpy(d + i, &a, 8);
} while ((i += 8) + 8 <= n);
for (; i < n; ++i) d[i] = s[i];
return d + i;
} else {
return __asan_repmovsb(d, s, n);
}
}
}
@ -280,16 +291,6 @@ static void *__asan_memcpy(void *dst, const void *src, size_t n) {
return dst;
}
static void *__asan_memrchr(void *p, int c, size_t n) {
uint8_t *b;
for (c &= 0xff, b = p; n--;) {
if (b[n] == c) {
return b + n;
}
}
return NULL;
}
static size_t __asan_int2hex(uint64_t x, char b[17], uint8_t k) {
int i;
char *p;
@ -455,8 +456,6 @@ static wontreturn void __asan_report_heap_fault(void *addr, long c) {
char *p, ibuf[21], buf[256];
p = __asan_report_start(buf);
p = __asan_stpcpy(p, __asan_dscribe_heap_poison(c));
p = __asan_stpcpy(p, " ");
p = __asan_mempcpy(p, ibuf, __asan_int2str(c, ibuf));
p = __asan_stpcpy(p, " at 0x");
p = __asan_mempcpy(p, ibuf, __asan_int2hex((intptr_t)addr, ibuf, 48));
p = __asan_stpcpy(p, " shadow 0x");
@ -709,7 +708,9 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
int i, x, a, b;
struct DirectMap sm;
struct MemoryIntervals *m;
if (0x7fff8000 <= p && p < 0x100080000000) {
if ((0x7fff8000 <= p && p < 0x100080000000) ||
(0x7fff8000 <= p + n && p + n < 0x100080000000) ||
(p < 0x7fff8000 && 0x100080000000 <= p + n)) {
__asan_die("asan error: mmap can't shadow a shadow\r\n");
}
m = weaken(_mmi);

View file

@ -46,7 +46,8 @@ $(LIBC_INTRIN_A_OBJS): \
o/$(MODE)/libc/intrin/asan.o: \
OVERRIDE_CFLAGS += \
-mgeneral-regs-only
-mgeneral-regs-only \
-O2
LIBC_INTRIN_LIBS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)))
LIBC_INTRIN_HDRS = $(foreach x,$(LIBC_INTRIN_ARTIFACTS),$($(x)_HDRS))

View file

@ -29,6 +29,6 @@
void(psrldq)(uint8_t b[16], const uint8_t a[16], unsigned long n) {
unsigned i;
if (n > 16) n = 16;
memcpy(b, a + n, 16 - n);
memset(b + (16 - n), 0, n);
__builtin_memcpy(b, a + n, 16 - n);
__builtin_memset(b + (16 - n), 0, n);
}

View file

@ -4,6 +4,7 @@
PKGS += LIBC
LIBC_HDRS = $(filter %.h,$(LIBC_FILES))
LIBC_INCS = $(filter %.inc,$(LIBC_FILES))
LIBC_FILES := $(wildcard libc/*)
LIBC_CHECKS = $(LIBC_HDRS:%=o/$(MODE)/%.ok)

View file

@ -18,8 +18,8 @@
*/
#include "libc/macros.h"
/ Half size of level 3 cache in bytes.
.initbss 202,_init_kHalfCache3
/ Half size of level 3 cache in bytes.
kHalfCache3:
.quad 0
.endobj kHalfCache3,globl

View file

@ -3,6 +3,8 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern long kHalfCache3;
void imapxlatab(void *);
void insertionsort(int32_t *, size_t);

View file

@ -8,6 +8,7 @@ LIBC_NEXGEN32E = $(LIBC_NEXGEN32E_A_DEPS) $(LIBC_NEXGEN32E_A)
LIBC_NEXGEN32E_A = o/$(MODE)/libc/nexgen32e/nexgen32e.a
LIBC_NEXGEN32E_A_FILES := $(wildcard libc/nexgen32e/*)
LIBC_NEXGEN32E_A_HDRS = $(filter %.h,$(LIBC_NEXGEN32E_A_FILES))
LIBC_NEXGEN32E_A_INCS = $(filter %.inc,$(LIBC_NEXGEN32E_A_FILES))
LIBC_NEXGEN32E_A_SRCS_A = $(filter %.s,$(LIBC_NEXGEN32E_A_FILES))
LIBC_NEXGEN32E_A_SRCS_S = $(filter %.S,$(LIBC_NEXGEN32E_A_FILES))
LIBC_NEXGEN32E_A_SRCS_C = $(filter %.c,$(LIBC_NEXGEN32E_A_FILES))
@ -49,6 +50,7 @@ o/$(MODE)/libc/nexgen32e/tinystrncmp.ncabi.o: \
LIBC_NEXGEN32E_LIBS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)))
LIBC_NEXGEN32E_SRCS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_SRCS))
LIBC_NEXGEN32E_HDRS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_HDRS))
LIBC_NEXGEN32E_INCS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_INCS))
LIBC_NEXGEN32E_CHECKS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_CHECKS))
LIBC_NEXGEN32E_OBJS = $(foreach x,$(LIBC_NEXGEN32E_ARTIFACTS),$($(x)_OBJS))
$(LIBC_NEXGEN32E_OBJS): $(BUILD_FILES) libc/nexgen32e/nexgen32e.mk

View file

@ -21,71 +21,6 @@
#include "libc/macros.h"
.source __FILE__
/ Returns pointer to first instance of character.
/
/ @param rdi is a non-null NUL-terminated string pointer
/ @param esi is the search byte
/ @return rax points to character, or to NUL byte if not found
/ @note this won't return NULL if search character is NUL
strchrnul:
.leafprologue
.profilable
or $-1,%r9
jmp 0f
.endfn strchrnul,globl
/ Returns pointer to first instance of character, the BSD way.
/
/ @param rdi is a non-null NUL-terminated string pointer
/ @param esi is the search byte
/ @return rax points to first result, or NULL if not found
/ @note this won't return NULL if search character is NUL
index: nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn index,globl
/ Returns pointer to first instance of character.
/
/ @param rdi is a non-null NUL-terminated string pointer
/ @param esi is the search byte
/ @return rax points to first result, or NULL if not found
/ @note this won't return NULL if search character is NUL
/ @asyncsignalsafe
strchr: .leafprologue
.profilable
xor %r9d,%r9d
0: movzbl %sil,%edx
or $-1,%rsi
xor %r8,%r8
jmp strsak
.endfn strchr,globl
/ Returns pointer to first instance of character in range.
/
/ @param rdi is a non-null pointer to memory
/ @param esi is the search byte
/ @return rax points to byte if found, or else undefined behavior
rawmemchr:
or $-1,%rdx
/ 𝑠𝑙𝑖𝑑𝑒
.endfn rawmemchr,globl
/ Returns pointer to first instance of character in range.
/
/ @param rdi is a non-null pointer to memory
/ @param esi is the search byte
/ @param rdx is length of memory in bytes
/ @return rax points to byte if found or NULL
/ @asyncsignalsafe
memchr: .leafprologue
.profilable
xchg %rsi,%rdx
mov %dl,%dh
xor %r8,%r8
xor %r10,%r10
jmp strsak
.endfn memchr,globl
/ Returns length of NUL-terminated string w/ security blankets.
/
/ This is like strnlen() except it'll return 0 if (1) RDI is NULL
@ -102,24 +37,13 @@ strnlen_s:
test %rdi,%rdi
jnz 0f
.leafepilogue
.endfn strnlen_s,globl
/ Returns length of NUL-terminated memory, with limit.
/
/ @param rdi is non-null memory
/ @param rsi is the maximum number of bytes to consider
/ @return rax is the number of bytes, excluding the NUL
/ @asyncsignalsafe
strnlen:.leafprologue
.profilable
or $-1,%r10
0: xor %edx,%edx
mov %rdi,%r8
/ 𝑠𝑙𝑖𝑑𝑒
.endfn strnlen,globl
.endfn strnlen_s,globl
/ Swiss army knife of string character scanning.
/ Fourteen fast functions in one.
/ Used to be fourteen fast functions in one.
/
/ @param rdi is non-null string memory
/ @param rsi is max number of bytes to consider

View file

@ -5,6 +5,7 @@ PKGS += LIBC_NT
LIBC_NT_LIBS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)))
LIBC_NT_HDRS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_HDRS))
LIBC_NT_INCS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_INCS))
LIBC_NT_SRCS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_SRCS))
LIBC_NT_OBJS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_OBJS))
LIBC_NT_CHECKS = $(foreach x,$(LIBC_NT_ARTIFACTS),$($(x)_CHECKS))
@ -22,9 +23,8 @@ LIBC_NT_A_FILES := \
$(wildcard libc/nt/nt/*.*) \
$(wildcard libc/nt/*)
LIBC_NT_A_HDRS = \
$(filter %.h,$(LIBC_NT_A_FILES))
LIBC_NT_A_HDRS = $(filter %.h,$(LIBC_NT_A_FILES))
LIBC_NT_A_INCS = $(filter %.inc,$(LIBC_NT_A_FILES))
LIBC_NT_A_CHECKS = $(patsubst %,o/$(MODE)/%.ok,$(filter %.h,$(LIBC_NT_A_HDRS)))
#───────────────────────────────────────────────────────────────────────────────

View file

@ -8,6 +8,7 @@ LIBC_SOCK = $(LIBC_SOCK_A_DEPS) $(LIBC_SOCK_A)
LIBC_SOCK_A = o/$(MODE)/libc/sock/sock.a
LIBC_SOCK_A_FILES := $(wildcard libc/sock/*)
LIBC_SOCK_A_HDRS = $(filter %.h,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_INCS = $(filter %.inc,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_SRCS = $(filter %.c,$(LIBC_SOCK_A_FILES))
LIBC_SOCK_A_OBJS = \
@ -31,6 +32,7 @@ LIBC_SOCK_A_DIRECTDEPS = \
LIBC_NT_WS2_32 \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV_CALLS \
LIBC_SYSV
@ -49,6 +51,7 @@ $(LIBC_SOCK_A).pkg: \
LIBC_SOCK_LIBS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)))
LIBC_SOCK_SRCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_SRCS))
LIBC_SOCK_HDRS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_HDRS))
LIBC_SOCK_INCS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_INCS))
LIBC_SOCK_CHECKS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_CHECKS))
LIBC_SOCK_OBJS = $(foreach x,$(LIBC_SOCK_ARTIFACTS),$($(x)_OBJS))
$(LIBC_SOCK_OBJS): $(BUILD_FILES) libc/sock/sock.mk

View file

@ -27,7 +27,7 @@ STATIC_YOINK("_init_g_stderr");
FILE *stderr;
hidden FILE g_stderr;
hidden unsigned char g_stderr_buf[BUFSIZ] forcealign(PAGESIZE);
hidden unsigned char g_stderr_buf[BUFSIZ];
static textstartup void _init_g_stderr2() {
_fflushregister(stderr);

View file

@ -27,7 +27,7 @@ STATIC_YOINK("_init_g_stdin");
FILE *stdin;
hidden FILE g_stdin;
hidden unsigned char g_stdin_buf[BUFSIZ] forcealign(PAGESIZE);
hidden unsigned char g_stdin_buf[BUFSIZ];
static textstartup void g_stdin_init() {
_fflushregister(stdin);

View file

@ -30,7 +30,7 @@ STATIC_YOINK("_init_g_stdout");
FILE *stdout;
hidden FILE g_stdout;
hidden unsigned char g_stdout_buf[BUFSIZ] forcealign(PAGESIZE);
hidden unsigned char g_stdout_buf[BUFSIZ];
static textstartup void _init_g_stdout2() {
struct FILE *sf;

View file

@ -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 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
@ -18,12 +18,14 @@
*/
#include "libc/str/str.h"
void *tinymemccpy(void *dst, const void *src, int termchar, size_t limit) {
size_t i;
unsigned char *d;
const unsigned char *s;
for (termchar &= 0xff, d = dst, s = src, i = 0; i < limit; ++i) {
if ((d[i] = s[i]) == termchar) return d + i + 1;
}
return NULL;
/**
* Returns pointer to first instance of character, the BSD way.
*
* @param s is a NUL-terminated string
* @param is masked with 255 as byte to search for
* @return is pointer to first instance of c or NULL if not found,
* noting that c being NUL will return a pointer to terminator
*/
char *index(const char *s, int c) {
return strchr(s, c);
}

View file

@ -18,8 +18,14 @@
*/
#include "libc/str/str.h"
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
}
/**
* Copies at most 𝑛 bytes from 𝑠 to 𝑑 until 𝑐 is encountered.
* Copies at most N bytes from SRC to DST until 𝑐 is encountered.
*
* This is little-known C Standard Library approach, dating back to the
* Fourth Edition of System Five, for copying a C strings to fixed-width
@ -39,17 +45,46 @@
* char cstrbuf[16];
* snprintf(cstrbuf, sizeof(cstrbuf), "%s", CSTR);
*
* @return 𝑑 + idx(𝑐) + 1, or NULL if 𝑐 𝑠
* @note 𝑑 and 𝑠 can't overlap
* @param c is search character and is masked with 255
* @return DST + idx(c) + 1, or NULL if 𝑐 𝑠
* @note DST and SRC can't overlap
* @asyncsignalsafe
*/
void *memccpy(void *d, const void *s, int c, size_t n) {
const char *p, *pe;
p = s;
if ((pe = memchr(p, c, n))) {
return mempcpy(d, s, pe - p + 1);
} else {
memcpy(d, s, n);
return NULL;
void *memccpy(void *dst, const void *src, int c, size_t n) {
size_t i;
uint64_t v, w;
unsigned char *d;
unsigned char *pd;
const unsigned char *s;
i = 0;
d = dst;
s = src;
c &= 255;
v = 0x0101010101010101 * c;
for (; (uintptr_t)(s + i) & 7; ++i) {
if (i == n) return NULL;
if ((d[i] = s[i]) == c) return d + i + 1;
}
for (; i + 8 <= n; i += 8) {
w = UncheckedAlignedRead64(s + i);
if (~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080) {
break;
} else {
pd = d + i;
pd[0] = (w >> 000) & 255;
pd[1] = (w >> 010) & 255;
pd[2] = (w >> 020) & 255;
pd[3] = (w >> 030) & 255;
pd[4] = (w >> 040) & 255;
pd[5] = (w >> 050) & 255;
pd[6] = (w >> 060) & 255;
pd[7] = (w >> 070) & 255;
}
}
for (; i < n; ++i) {
if ((d[i] = s[i]) == c) {
return d + i + 1;
}
}
return NULL;
}

47
libc/str/memchr.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- 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 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/str/str.h"
/**
* Returns pointer to first instance of character.
*
* @param m is memory to search
* @param c is search byte which is masked with 255
* @param n is byte length of p
* @return is pointer to first instance of c or NULL if not found
* @asyncsignalsafe
*/
void *memchr(const void *m, int c, size_t n) {
uint64_t v, w;
const unsigned char *p, *pe;
c &= 255;
v = 0x0101010101010101 * c;
for (p = (const unsigned char *)m, pe = p + n; p + 8 <= pe; p += 8) {
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
return p + ((unsigned)__builtin_ctzll(w) >> 3);
}
}
for (; p < pe; ++p) {
if (*p == c) return p;
}
return NULL;
}

160
libc/str/memmove-pure.c Normal file
View file

@ -0,0 +1,160 @@
/*-*- 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 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/str/str.h"
typedef long long xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
/**
* Copies memory.
*
* DST and SRC may overlap.
*
* @param dst is destination
* @param src is memory to copy
* @param n is number of bytes to copy
* @return dst
* @asyncsignalsafe
*/
void *memmove$pure(void *dst, const void *src, size_t n) {
size_t i;
xmm_t v, w;
char *d, *r;
const char *s;
uint64_t a, b;
d = dst;
s = src;
switch (n) {
case 9 ... 15:
__builtin_memcpy(&a, s, 8);
__builtin_memcpy(&b, s + n - 8, 8);
__builtin_memcpy(d, &a, 8);
__builtin_memcpy(d + n - 8, &b, 8);
return d;
case 5 ... 7:
__builtin_memcpy(&a, s, 4);
__builtin_memcpy(&b, s + n - 4, 4);
__builtin_memcpy(d, &a, 4);
__builtin_memcpy(d + n - 4, &b, 4);
return d;
case 17 ... 32:
__builtin_memcpy(&v, s, 16);
__builtin_memcpy(&w, s + n - 16, 16);
__builtin_memcpy(d, &v, 16);
__builtin_memcpy(d + n - 16, &w, 16);
return d;
case 16:
__builtin_memcpy(&v, s, 16);
__builtin_memcpy(d, &v, 16);
return d;
case 0:
return d;
case 1:
*d = *s;
return d;
case 8:
__builtin_memcpy(&a, s, 8);
__builtin_memcpy(d, &a, 8);
return d;
case 4:
__builtin_memcpy(&a, s, 4);
__builtin_memcpy(d, &a, 4);
return d;
case 2:
__builtin_memcpy(&a, s, 2);
__builtin_memcpy(d, &a, 2);
return d;
case 3:
__builtin_memcpy(&a, s, 2);
__builtin_memcpy(&b, s + 1, 2);
__builtin_memcpy(d, &a, 2);
__builtin_memcpy(d + 1, &b, 2);
return d;
default:
r = d;
if (d > s) {
do {
n -= 32;
__builtin_memcpy(&v, s + n, 16);
__builtin_memcpy(&w, s + n + 16, 16);
__builtin_memcpy(d + n, &v, 16);
__builtin_memcpy(d + n + 16, &w, 16);
} while (n >= 32);
} else {
i = 0;
do {
__builtin_memcpy(&v, s + i, 16);
__builtin_memcpy(&w, s + i + 16, 16);
__builtin_memcpy(d + i, &v, 16);
__builtin_memcpy(d + i + 16, &w, 16);
} while ((i += 32) + 32 <= n);
d += i;
s += i;
n -= i;
}
switch (n) {
case 0:
return r;
case 17 ... 31:
__builtin_memcpy(&v, s, 16);
__builtin_memcpy(&w, s + n - 16, 16);
__builtin_memcpy(d, &v, 16);
__builtin_memcpy(d + n - 16, &w, 16);
return r;
case 9 ... 15:
__builtin_memcpy(&a, s, 8);
__builtin_memcpy(&b, s + n - 8, 8);
__builtin_memcpy(d, &a, 8);
__builtin_memcpy(d + n - 8, &b, 8);
return r;
case 5 ... 7:
__builtin_memcpy(&a, s, 4);
__builtin_memcpy(&b, s + n - 4, 4);
__builtin_memcpy(d, &a, 4);
__builtin_memcpy(d + n - 4, &b, 4);
return r;
case 16:
__builtin_memcpy(&v, s, 16);
__builtin_memcpy(d, &v, 16);
return r;
case 8:
__builtin_memcpy(&a, s, 8);
__builtin_memcpy(d, &a, 8);
return r;
case 4:
__builtin_memcpy(&a, s, 4);
__builtin_memcpy(d, &a, 4);
return r;
case 1:
*d = *s;
return r;
case 2:
__builtin_memcpy(&a, s, 2);
__builtin_memcpy(d, &a, 2);
return r;
case 3:
__builtin_memcpy(&a, s, 2);
__builtin_memcpy(&b, s + 1, 2);
__builtin_memcpy(d, &a, 2);
__builtin_memcpy(d + 1, &b, 2);
return r;
default:
unreachable;
}
}
}

100
libc/str/memset-pure.c Normal file
View file

@ -0,0 +1,100 @@
/*-*- 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 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/str/str.h"
/**
* Sets memory.
*
* @param p is memory address
* @param c is masked with 255 and used as repeated byte
* @param n is byte length
* @return p
* @asyncsignalsafe
*/
void *memset$pure(void *p, int c, size_t n) {
char *b;
uint64_t x;
b = p;
x = 0x0101010101010101 * (c & 0xff);
switch (n) {
case 0:
return p;
case 1:
__builtin_memcpy(b, &x, 1);
return p;
case 2:
__builtin_memcpy(b, &x, 2);
return p;
case 3:
__builtin_memcpy(b, &x, 2);
__builtin_memcpy(b + 1, &x, 2);
return p;
case 4:
__builtin_memcpy(b, &x, 4);
return p;
case 5 ... 7:
__builtin_memcpy(b, &x, 4);
__builtin_memcpy(b + n - 4, &x, 4);
return p;
case 8:
__builtin_memcpy(b, &x, 8);
return p;
case 9 ... 16:
__builtin_memcpy(b, &x, 8);
__builtin_memcpy(b + n - 8, &x, 8);
return p;
default:
do {
n -= 16;
__builtin_memcpy(b + n, &x, 8);
asm volatile("" ::: "memory");
__builtin_memcpy(b + n + 8, &x, 8);
} while (n >= 16);
switch (n) {
case 0:
return p;
case 1:
__builtin_memcpy(b, &x, 1);
return p;
case 2:
__builtin_memcpy(b, &x, 2);
return p;
case 3:
__builtin_memcpy(b, &x, 2);
__builtin_memcpy(b + 1, &x, 2);
return p;
case 4:
__builtin_memcpy(b, &x, 4);
return p;
case 5 ... 7:
__builtin_memcpy(b, &x, 4);
__builtin_memcpy(b + n - 4, &x, 4);
return p;
case 8:
__builtin_memcpy(b, &x, 8);
return p;
case 9 ... 15:
__builtin_memcpy(b, &x, 8);
__builtin_memcpy(b + n - 8, &x, 8);
return p;
default:
unreachable;
}
}
}

53
libc/str/rawmemchr.c Normal file
View file

@ -0,0 +1,53 @@
/*-*- 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 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/assert.h"
#include "libc/str/str.h"
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
}
/**
* Returns pointer to first instance of character.
*
* @param m is memory to search
* @param c is search byte which is masked with 255
* @return is pointer to first instance of c
*/
void *rawmemchr(const void *m, int c) {
uint64_t v, w;
const unsigned char *s;
s = m;
c &= 255;
v = 0x0101010101010101 * c;
for (; (uintptr_t)s & 7; ++s) {
if (*s == c) return s;
}
for (;; s += 8) {
w = UncheckedAlignedRead64(s);
if ((w = ~(w ^ v) & ((w ^ v) - 0x0101010101010101) & 0x8080808080808080)) {
s += (unsigned)__builtin_ctzll(w) >> 3;
break;
}
}
assert(*s == c);
return s;
}

View file

@ -90,7 +90,6 @@ void *memeqmask(void *, const void *, const void *, size_t) memcpyesque;
size_t strlen(const char *) strlenesque;
size_t strnlen(const char *, size_t) strlenesque;
size_t strnlen_s(const char *, size_t);
size_t strlen$pure(const char *) strlenesque;
char *strchr(const char *, int) strlenesque;
char *index(const char *, int) strlenesque;
void *memchr(const void *, int, size_t) strlenesque;
@ -246,8 +245,8 @@ char *strsignal(int) returnsnonnull libcesque;
cosmopolitan § strings » optimizations
*/
#define __memcpy_isgoodsize(SIZE) \
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ * 2 && \
#define __memcpy_isgoodsize(SIZE) \
(__builtin_constant_p(SIZE) && ((SIZE) <= __BIGGEST_ALIGNMENT__ && \
__builtin_popcountl((unsigned)(SIZE)) == 1))
#define __memset_isgoodsize(SIZE) \
@ -361,15 +360,44 @@ char *strsignal(int) returnsnonnull libcesque;
})
#endif /* hosted/sse2/unbloat */
#ifdef __FSANITIZE_ADDRESS__
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § strings » address sanitizer
*/
void *memset$pure(void *, int, size_t) memcpyesque;
void *memmove$pure(void *, const void *, size_t) memcpyesque;
size_t strlen$pure(const char *) strlenesque;
size_t strcspn$pure(const char *, const char *) strlenesque;
#if defined(__FSANITIZE_ADDRESS__)
#define strcspn(STR, REJECT) strcspn$pure(STR, REJECT)
#ifdef strlen
#undef strlen
#endif
#define strlen(s) strlen$pure(s)
#define strlen(STR) \
(__builtin_constant_p(STR) ? __builtin_strlen(STR) : strlen$pure(STR))
#undef memset
#define memset(DST, CHAR, SIZE) \
(__memcpy_isgoodsize(SIZE) ? __builtin_memset(DST, CHAR, SIZE) \
: memset$pure(DST, CHAR, SIZE))
#undef memmove
#define memmove(DST, SRC, SIZE) \
(__memcpy_isgoodsize(SIZE) ? __builtin_memmove(DST, SRC, SIZE) \
: memmove$pure(DST, SRC, SIZE))
#undef memcpy
#define memcpy(DST, SRC, SIZE) \
(__memcpy_isgoodsize(SIZE) ? __builtin_memcpy(DST, SRC, SIZE) \
: memmove$pure(DST, SRC, SIZE))
#undef mempcpy
#define mempcpy(DST, SRC, SIZE) \
(__memcpy_isgoodsize(SIZE) ? __builtin_mempcpy(DST, SRC, SIZE) : ({ \
void *DsT = (DST); \
size_t SiZe = (SIZE); \
memmove$pure(DsT, SRC, SiZe); \
(void *)((char *)DsT + SiZe); \
}))
#endif /* __FSANITIZE_ADDRESS__ */
#endif /* __GNUC__ && !__STRICT_ANSI__ */

View file

@ -8,6 +8,7 @@ LIBC_STR = $(LIBC_STR_A_DEPS) $(LIBC_STR_A)
LIBC_STR_A = o/$(MODE)/libc/str/str.a
LIBC_STR_A_FILES := $(wildcard libc/str/*)
LIBC_STR_A_HDRS = $(filter %.h,$(LIBC_STR_A_FILES))
LIBC_STR_A_INCS = $(filter %.inc,$(LIBC_STR_A_FILES))
LIBC_STR_A_SRCS_A = $(filter %.s,$(LIBC_STR_A_FILES))
LIBC_STR_A_SRCS_S = $(filter %.S,$(LIBC_STR_A_FILES))
LIBC_STR_A_SRCS_C = $(filter %.c,$(LIBC_STR_A_FILES))
@ -49,6 +50,7 @@ o/$(MODE)/libc/str/memmem.o: \
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
LIBC_STR_INCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_INCS))
LIBC_STR_BINS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_BINS))
LIBC_STR_CHECKS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_CHECKS))
LIBC_STR_OBJS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_OBJS))

69
libc/str/strchr.c Normal file
View file

@ -0,0 +1,69 @@
/*-*- 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 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/assert.h"
#include "libc/str/str.h"
noasan static const unsigned char *strchr$x64(const unsigned char *p,
uint64_t c) {
unsigned a, b;
uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) {
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
if (x) {
a = __builtin_ctzll(x);
if (y) {
b = __builtin_ctzll(y);
if (a <= b) {
return p + (a >> 3);
} else {
return NULL;
}
} else {
return p + (a >> 3);
}
} else {
return NULL;
}
}
}
}
/**
* Returns pointer to first instance of character.
*
* @param s is a NUL-terminated string
* @param c is masked with 255 as byte to search for
* @return pointer to first instance of c or NULL if not found
* noting that if c is NUL we return pointer to terminator
* @asyncsignalsafe
*/
char *strchr(const char *s, int c) {
char *r;
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
if ((*s & 0xff) == c) return s;
if (!*s) return NULL;
}
r = (char *)strchr$x64((const unsigned char *)s, c);
assert(!r || *r || !c);
return r;
}

69
libc/str/strchrnul.c Normal file
View file

@ -0,0 +1,69 @@
/*-*- 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 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/assert.h"
#include "libc/str/str.h"
noasan static const unsigned char *strchrnul$x64(const unsigned char *p,
uint64_t c) {
unsigned a, b;
uint64_t w, x, y;
for (c *= 0x0101010101010101;; p += 8) {
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
if ((x = ~(w ^ c) & ((w ^ c) - 0x0101010101010101) & 0x8080808080808080) |
(y = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
if (x) {
a = __builtin_ctzll(x);
if (y) {
b = __builtin_ctzll(y);
if (a <= b) {
return p + (a >> 3);
} else {
return p + (b >> 3);
}
} else {
return p + (a >> 3);
}
} else {
b = __builtin_ctzll(y);
return p + (b >> 3);
}
}
}
}
/**
* Returns pointer to first instance of character.
*
* @param s is a NUL-terminated string
* @param c is masked with 255 as byte to search for
* @return pointer to first instance of c, or pointer to
* NUL terminator if c is not found
*/
char *strchrnul(const char *s, int c) {
char *r;
for (c &= 0xff; (uintptr_t)s & 7; ++s) {
if ((*s & 0xff) == c) return s;
if (!*s) return s;
}
r = (char *)strchrnul$x64((const unsigned char *)s, c);
assert((*r & 0xff) == c || !*r);
return r;
}

View file

@ -18,6 +18,12 @@
*/
#include "libc/str/str.h"
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
}
/**
* Compares NUL-terminated strings.
*
@ -28,7 +34,25 @@
*/
int strcmp(const char *a, const char *b) {
size_t i = 0;
uint64_t v, w, d;
if (a == b) return 0;
while (a[i] == b[i] && b[i]) ++i;
return (a[i] & 0xff) - (b[i] & 0xff);
if (((uintptr_t)a & 7) == ((uintptr_t)b & 7)) {
for (; (uintptr_t)a & 7; ++i) {
if (a[i] != b[i] || !b[i]) {
return (a[i] & 0xff) - (b[i] & 0xff);
}
}
for (;; i += 8) {
v = UncheckedAlignedRead64(a + i);
w = UncheckedAlignedRead64(b + i);
w = (v ^ w) | (~v & (v - 0x0101010101010101) & 0x8080808080808080);
if (w) {
i += (unsigned)__builtin_ctzll(w) >> 3;
return (a[i] & 0xff) - (b[i] & 0xff);
}
}
} else {
while (a[i] == b[i] && b[i]) ++i;
return (a[i] & 0xff) - (b[i] & 0xff);
}
}

62
libc/str/strcspn-pure.c Normal file
View file

@ -0,0 +1,62 @@
/*-*- 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
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/intrin/pcmpeqb.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/intrin/pshufd.h"
#include "libc/intrin/punpcklbw.h"
#include "libc/intrin/punpcklwd.h"
#include "libc/nexgen32e/hascharacter.internal.h"
#include "libc/str/str.h"
#define V(p) (void *)(p)
/**
* Returns prefix length, consisting of chars not in reject.
* a.k.a. Return index of first byte that's in charset.
*
* @param reject is nul-terminated character set
* @see strspn(), strtok_r()
* @asyncsignalsafe
*/
size_t strcspn$pure(const char *s, const char *reject) {
size_t i, n;
unsigned m;
char cv[16], sv[16];
if ((n = strlen(reject)) < 16) {
memset(sv, 0, 16);
memcpy(sv, reject, n);
for (i = 0;; ++i) {
cv[0] = s[i];
punpcklbw(V(cv), V(cv), V(cv));
punpcklwd(V(cv), V(cv), V(cv));
pshufd(V(cv), V(cv), 0);
pcmpeqb(V(cv), V(cv), V(sv));
if ((m = pmovmskb(V(cv)))) {
break;
}
}
return i;
}
for (i = 0; s[i]; ++i) {
if (HasCharacter(s[i], reject)) {
break;
}
}
return i;
}

View file

@ -16,35 +16,35 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/str/str.h"
noasan static const char *strlen$pure$x64(const char *p) {
static noasan size_t strlen$pure$x64(const char *s, size_t i) {
uint64_t w;
const unsigned char *p;
for (;;) {
w = *(uint64_t *)p;
if (~w & (w - 0x0101010101010101) & 0x8080808080808080) {
break;
p = (const unsigned char *)s + i;
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
return i + ((unsigned)__builtin_ctzll(w) >> 3);
} else {
p += 8;
i += 8;
}
}
return p;
}
/**
* Returns length of NUL-terminated string.
*/
size_t strlen$pure(const char *s) {
const char *p;
p = s;
while ((uintptr_t)p & 7) {
if (*p) {
++p;
} else {
return p - s;
}
size_t i;
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
if (!s[i]) return i;
}
p = strlen$pure$x64(p);
while (*p) ++p;
return p - s;
i = strlen$pure$x64(s, i);
assert(!i || s[0]);
assert(!s[i]);
return i;
}

57
libc/str/strnlen.c Normal file
View file

@ -0,0 +1,57 @@
/*-*- 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 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/assert.h"
#include "libc/str/str.h"
static noasan size_t strnlen$x64(const char *s, size_t n, size_t i) {
uint64_t w;
const unsigned char *p;
for (; i + 8 < n; i += 8) {
p = (const unsigned char *)s + i;
w = (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
if ((w = ~w & (w - 0x0101010101010101) & 0x8080808080808080)) {
i += (unsigned)__builtin_ctzll(w) >> 3;
break;
}
}
return i;
}
/**
* Returns length of NUL-terminated string w/ limit.
*
* @param s is string
* @param n is max length
* @return byte length
* @asyncsignalsafe
*/
size_t strnlen(const char *s, size_t n) {
size_t i;
for (i = 0; (uintptr_t)(s + i) & 7; ++i) {
if (i == n || !s[i]) return i;
}
i = strnlen$x64(s, n, i);
for (;; ++i) {
if (i == n || !s[i]) break;
}
assert(i == n || (i < n && !s[i]));
return i;
}

View file

@ -5,6 +5,7 @@ PKGS += LIBC_SYSV
LIBC_SYSV_LIBS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_A))
LIBC_SYSV_ARCHIVES = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_A))
LIBC_SYSV_HDRS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_HDRS))
LIBC_SYSV_INCS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_INCS))
LIBC_SYSV_BINS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_BINS))
LIBC_SYSV_CHECKS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_CHECKS))
LIBC_SYSV_OBJS = $(foreach x,$(LIBC_SYSV_ARTIFACTS),$($(x)_OBJS))
@ -20,6 +21,7 @@ LIBC_SYSV = \
LIBC_SYSV_ARTIFACTS += LIBC_SYSV_A
LIBC_SYSV_A = o/$(MODE)/libc/sysv/sysv.a
LIBC_SYSV_A_HDRS = $(filter %.h,$(LIBC_SYSV_A_FILES))
LIBC_SYSV_A_INCS = $(filter %.inc,$(LIBC_SYSV_A_FILES))
LIBC_SYSV_A_SRCS_A = $(filter %.s,$(LIBC_SYSV_A_FILES))
LIBC_SYSV_A_SRCS_S = $(filter %.S,$(LIBC_SYSV_A_FILES))
LIBC_SYSV_A_CHECKS = $(LIBC_SYSV_A).pkg

View file

@ -27,8 +27,8 @@ STATIC_YOINK("strnwidth");
void __testlib_ezbenchreport(const char *form, uint64_t c1, uint64_t c2) {
uint64_t ns1, ns2;
ns1 = rintl(converttickstonanos(c1));
ns2 = rintl(converttickstonanos(c2));
ns1 = rintl(ConvertTicksToNanos(c1));
ns2 = rintl(ConvertTicksToNanos(c2));
(fprintf)(stderr,
VEIL("r", "%-30s l: %,10lu𝑐 %,10lu𝑛𝑠 m: %,10lu𝑐 %,10lu𝑛𝑠\n"),
form, c1, ns1, c2, ns2);

View file

@ -60,8 +60,7 @@ int futimesat(int, const char *, const struct timeval[2]);
long double dtime(int);
long double dsleep(long double);
extern long double (*nowl)(void);
long double converttickstonanos(uint64_t);
long double converttickstoseconds(uint64_t);
long double ConvertTicksToNanos(uint64_t);
double difftime(int64_t, int64_t) nothrow pureconst;

View file

@ -80,11 +80,12 @@ prpppppppppppppoooooooonnnnnnnnnnnnnnnooooooooppppppppppppptp\
pppppppppppppppppppoooooooooooooooooooooooppppppppppppppppppp";
TEST(gyarados, testIdentityDifference) {
static unsigned char A[1][32][62];
static unsigned char B[1][32][62];
static unsigned char A[1][32][61];
static unsigned char B[1][32][61];
ASSERT_EQ(sizeof(A), strlen(kDieWelle));
memcpy(A, kDieWelle, sizeof(A));
EzGyarados(1, 32, 61, B, 1, 32, 61, A, 0, 1, 32, 61, 32, 61, 1, 1, 0, 0);
AbsoluteDifference(32, 62, B[0], 32, 62, B[0], 32, 62, A[0]);
AbsoluteDifference(32, 61, B[0], 32, 61, B[0], 32, 61, A[0]);
EXPECT_STREQ(u"\n\
                                                             \n\
                                                             \n\

View file

@ -26,6 +26,7 @@ TEST_LIBC_CRYPTO_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \
LIBC_TESTLIB

View file

@ -30,6 +30,7 @@ TEST_LIBC_MEM_DIRECTDEPS = \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_TESTLIB

View file

@ -17,77 +17,117 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#define N 256
#define S 7
#define N 65
#define S 1
long i, j, n;
char *b1, *b2;
char *b0, *b1, *b2;
noinline char *PosixMemmove(char *dst, const char *src, size_t n) {
char *tmp;
tmp = malloc(n);
memcpy(tmp, src, n);
memcpy(dst, tmp, n);
free(tmp);
return dst;
}
TEST(memmove, overlapping) {
for (i = 0; i < N; i += S) {
for (j = 10; j < N; j += S) {
b1 = malloc(N);
b2 = malloc(N);
n = min(N - i, N - j);
memcpy(b2, b1 + i, n);
ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n));
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
free(b2);
free(b1);
for (j = 0; j < N; j += S) {
for (n = MIN(N - i, N - j) + 1; n--;) {
b0 = rngset(malloc(N), N, rand64, -1);
b1 = memcpy(malloc(N), b0, N);
b2 = memcpy(malloc(N), b0, N);
ASSERT_EQ(b1 + j, memmove(b1 + j, b1 + i, n));
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
ASSERT_EQ(0, memcmp(b1, b2, N),
"j=%ld i=%ld n=%ld\n"
"\t%#.*s data\n"
"\t%#.*s memmove\n"
"\t%#.*s posix",
j, i, n, n, b0, n, b1, n, b2);
free(b2);
free(b1);
free(b0);
}
}
}
}
TEST(memmove$pure, overlapping) {
for (i = 0; i < N; i += S) {
for (j = 0; j < N; j += S) {
for (n = MIN(N - i, N - j) + 1; n--;) {
b0 = rngset(malloc(N), N, rand64, -1);
b1 = memcpy(malloc(N), b0, N);
b2 = memcpy(malloc(N), b0, N);
ASSERT_EQ(b1 + j, memmove$pure(b1 + j, b1 + i, n));
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
ASSERT_EQ(0, memcmp(b1, b2, N),
"j=%ld i=%ld n=%ld\n"
"\t%#.*s data\n"
"\t%#.*s memmove\n"
"\t%#.*s posix",
j, i, n, n, b0, n, b1, n, b2);
free(b2);
free(b1);
free(b0);
}
}
}
}
TEST(memcpy, overlapping) {
for (i = 0; i < N; i += S) {
for (j = 0; j < N; j += S) {
for (n = MIN(N - i, N - j) + 1; n--;) {
if (j <= i) {
b0 = rngset(malloc(N), N, rand64, -1);
b1 = memcpy(malloc(N), b0, N);
b2 = memcpy(malloc(N), b0, N);
ASSERT_EQ(b1 + j, memcpy(b1 + j, b1 + i, n));
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
ASSERT_EQ(0, memcmp(b1, b2, N),
"j=%ld i=%ld n=%ld\n"
"\t%#.*s data\n"
"\t%#.*s memmove\n"
"\t%#.*s posix",
j, i, n, n, b0, n, b1, n, b2);
free(b2);
free(b1);
free(b0);
}
}
}
}
}
TEST(memmove, overlappingDirect) {
for (i = 0; i < N; i += S) {
for (j = 10; j < N; j += S) {
b1 = malloc(N);
b2 = malloc(N);
n = min(N - i, N - j);
memcpy(b2, b1 + i, n);
ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n));
ASSERT_EQ(0, memcmp(b1 + j, b2, n));
free(b2);
free(b1);
for (j = 0; j < N; j += S) {
for (n = MIN(N - i, N - j) + 1; n--;) {
b0 = rngset(malloc(N), N, rand64, -1);
b1 = memcpy(malloc(N), b0, N);
b2 = memcpy(malloc(N), b0, N);
ASSERT_EQ(b1 + j, (memmove)(b1 + j, b1 + i, n));
ASSERT_EQ(b2 + j, PosixMemmove(b2 + j, b2 + i, n));
ASSERT_EQ(0, memcmp(b1, b2, N),
"j=%ld i=%ld n=%ld\n"
"\t%#.*s data\n"
"\t%#.*s memmove\n"
"\t%#.*s posix",
j, i, n, n, b0, n, b1, n, b2);
free(b2);
free(b1);
free(b0);
}
}
}
}
char *MoveMemory(char *dst, const char *src, size_t n) {
size_t i;
for (i = 0; i < n; ++i) {
dst[i] = src[i];
}
return dst;
}
TEST(memmove, overlappingBackwards_isGenerallySafe) {
char buf[32];
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", MoveMemory(buf, buf + 2, 24));
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", memmove(buf, buf + 2, 24));
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
ASSERT_STREQ("cdefghijklmnopqrstuvwxyzyz", memcpy(buf, buf + 2, 24));
}
TEST(memmove, overlappingForwards_avoidsRunLengthDecodeBehavior) {
volatile char buf[32];
strcpy(buf, "abc");
MoveMemory(buf + 1, buf, 2);
ASSERT_STREQ("aaa", buf);
strcpy(buf, "abc");
(memmove)(buf + 1, buf, 2);
ASSERT_STREQ("aab", buf);
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
MoveMemory(buf + 2, buf, 24);
ASSERT_STREQ("ababababababababababababab", buf);
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");
memmove(buf + 2, buf, 24);
ASSERT_STREQ("ababcdefghijklmnopqrstuvwx", buf);
}

View file

@ -31,6 +31,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_STUBS \
LIBC_SYSV \
LIBC_TESTLIB \

View file

@ -23,7 +23,15 @@
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
void *memccpy2(void *, const void *, int, size_t);
void *memccpy$pure(void *d, const void *s, int c, size_t n) {
size_t i;
unsigned char *x;
const unsigned char *y;
for (c &= 0xff, x = d, y = s, i = 0; i < n; ++i) {
if ((x[i] = y[i]) == c) return x + i + 1;
}
return NULL;
}
TEST(memccpy, testStringCopy) {
char buf[16];
@ -49,7 +57,7 @@ TEST(memccpy, memcpy) {
b2 = calloc(1, n);
b3 = calloc(1, n);
rngset(b1, n, rand64, -1);
e1 = tinymemccpy(b2, b1, 31337, n);
e1 = memccpy$pure(b2, b1, 31337, n);
e2 = memccpy(b3, b1, 31337, n);
n1 = e1 ? e1 - b2 : n;
n2 = e2 ? e2 - b3 : n;

View file

@ -18,38 +18,54 @@
*/
#include "libc/bits/bits.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/rand/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
TEST(memcpy, memcpy) {
TEST(memcpy, test) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1, memcpy(b1, b2, n));
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1, memcpy(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n, b2);
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1, memcpy(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n, b2);
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
}
TEST(memcpy, memcpyDirect) {
TEST(mempcpy, test) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = malloc(n);
b2 = malloc(n);
ASSERT_EQ(b1, (memcpy)(b1, b2, n));
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
}
TEST(memcpy, mempcpy) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1 + n, mempcpy(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
@ -57,11 +73,49 @@ TEST(memcpy, mempcpy) {
}
}
TEST(memcpy, mempcpyDirect) {
TEST(memcpy, direct) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1, (memcpy)(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n,
b2);
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1, (memcpy)(b1, b2, n), "%ld\n\t%#.*s\n\t%#.*s", n, n, b1, n,
b2);
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
}
TEST(mempcpy, direct) {
char *b1, *b2;
for (unsigned n = 0; n < 1026; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
free(b1);
}
for (unsigned n = kHalfCache3 - 1; n < kHalfCache3 + 2; ++n) {
b1 = malloc(n);
b2 = malloc(n);
rngset(b1, n, rand64, -1);
rngset(b2, n, rand64, -1);
ASSERT_EQ(b1 + n, (mempcpy)(b1, b2, n));
ASSERT_EQ(0, memcmp(b1, b2, n));
free(b2);
@ -105,3 +159,44 @@ TEST(memcpy, testBackwardsOverlap3) {
EXPECT_EQ('C', c[1]);
free(c);
}
void *MemCpy(void *, const void *, size_t);
#define B(F, N) \
do { \
char *d = rngset(malloc(N), N, rand64, -1); \
char *s = rngset(malloc(N), N, rand64, -1); \
EZBENCH2(#F " " #N, donothing, \
EXPROPRIATE(F(VEIL("r", d), VEIL("r", s), N))); \
free(d); \
free(s); \
} while (0)
#define BB(N) \
do { \
B(memmove$pure, N); \
B(memcpy, N); \
B(MemCpy, N); \
fprintf(stderr, "\n"); \
} while (0)
BENCH(memcpy, bench) {
BB(0);
BB(1);
BB(2);
BB(3);
BB(7);
BB(8);
BB(15);
BB(16);
BB(31);
BB(32);
BB(63);
BB(64);
BB(255);
BB(256);
BB(1023);
BB(1024);
BB(PAGESIZE);
BB(FRAMESIZE);
}

View file

@ -17,7 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/bits/bits.h"
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
TEST(strchr, blank) {
@ -66,3 +69,99 @@ TEST(strchrnul, notFound_returnsPointerToNulByte) {
EXPECT_STREQ("", strchrnul(buf, 'z'));
EXPECT_EQ(&buf[2], strchrnul(buf, 'z'));
}
char *strchr$pure(const char *s, int c) {
char *r;
for (c &= 0xff;; ++s) {
if ((*s & 0xff) == c) return (char *)s;
if (!*s) return NULL;
}
}
TEST(strchr, fuzz) {
char *p;
int i, j;
p = calloc(1, 64);
for (i = -2; i < 257; ++i) {
for (j = 0; j < 17; ++j) {
rngset(p, 63, rand64, -1);
ASSERT_EQ(strchr(p + j, i), strchr$pure(p + j, i));
}
}
free(p);
}
BENCH(strchr, bench) {
EZBENCH2("strchr 0", donothing, EXPROPRIATE(strchr(VEIL("r", ""), 0)));
EZBENCH2("strchr 5", donothing, EXPROPRIATE(strchr(VEIL("r", "hello"), 'o')));
EZBENCH2("strchr 8", donothing,
EXPROPRIATE(strchr(VEIL("r", "hellzzzo"), 'o')));
EZBENCH2("strchr 17", donothing,
EXPROPRIATE(strchr(VEIL("r", "hellzzzhellzzzeeo"), 'o')));
EZBENCH2("strchr 34", donothing,
EXPROPRIATE(
strchr(VEIL("r", "hellzzzhellzzzeeAhellzzzhellzzzeeo"), 'o')));
}
char *memchr$pure(const char *m, int c, size_t n) {
const unsigned char *p, *pe;
for (c &= 0xff, p = (const unsigned char *)m, pe = p + n; p < pe; ++p) {
if (*p == c) return p;
}
return NULL;
}
TEST(memchr, fuzz) {
char *p;
int i, j;
p = malloc(64);
for (i = -2; i < 257; ++i) {
for (j = 0; j < 17; ++j) {
rngset(p, 64, rand64, -1);
ASSERT_EQ(memchr(p + j, i, 64 - j), memchr$pure(p + j, i, 64 - j));
}
}
free(p);
}
char *strchrnul$pure(const char *s, int c) {
char *r;
for (c &= 0xff;; ++s) {
if ((*s & 0xff) == c) return (char *)s;
if (!*s) return s;
}
}
TEST(strchrnul, fuzz) {
char *p;
int i, j;
p = calloc(1, 64);
for (i = -2; i < 257; ++i) {
for (j = 0; j < 17; ++j) {
rngset(p, 63, rand64, -1);
ASSERT_EQ(strchrnul(p + j, i), strchrnul$pure(p + j, i));
}
}
free(p);
}
void *rawmemchr$pure(const void *m, int c) {
const unsigned char *s;
for (c &= 255, s = m;; ++s) {
if (*s == c) return s;
}
}
TEST(rawmemchr, fuzz) {
char *p;
int i, j;
p = malloc(64);
for (i = -2; i < 257; ++i) {
for (j = 0; j < 17; ++j) {
rngset(p, 63, rand64, -1);
p[63] = i;
ASSERT_EQ(rawmemchr(p + j, i), rawmemchr$pure(p + j, i));
}
}
free(p);
}

View file

@ -19,8 +19,10 @@
#include "libc/bits/bits.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/tinystrlen.internal.h"
#include "libc/rand/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
@ -30,6 +32,8 @@ char16_t u16[] = u"utf16 ☻";
wchar_t u32[] = L"utf32 ☻";
TEST(strlen, usageExample_c11) {
_Alignas(16) char ugh[] = "eeeeeeeeeeeeeee\017";
EXPECT_EQ(1, strlen$pure(ugh + 15));
EXPECT_EQ(6 + 3, strlen(u8));
EXPECT_EQ(7, strlen16(u16));
EXPECT_EQ(7, wcslen(u32));
@ -143,7 +147,7 @@ TEST(strlen, fuzz) {
b = rngset(calloc(1, n), n - 1, rand64, -1);
n1 = strlen(b);
n2 = strlen$pure(b);
ASSERT_EQ(n1, n2);
ASSERT_EQ(n1, n2, "%#.*s", n, b);
n1 = strlen(b + 1);
n2 = strlen$pure(b + 1);
ASSERT_EQ(n1, n2);
@ -166,8 +170,14 @@ BENCH(strlen, bench) {
EZBENCH2("strlen$pure 8", donothing, strlen$pure_("1234567"));
EZBENCH2("strlen 9", donothing, strlen_("12345678"));
EZBENCH2("strlen$pure 9", donothing, strlen$pure_("12345678"));
EZBENCH2("strlen 11", donothing, strlen_("12345678aa"));
EZBENCH2("strlen$pure 11", donothing, strlen$pure_("12345678aa"));
EZBENCH2("strlen 13", donothing, strlen_("12345678aabb"));
EZBENCH2("strlen$pure 13", donothing, strlen$pure_("12345678aabb"));
EZBENCH2("strlen 16", donothing, strlen_("123456781234567"));
EZBENCH2("strlen$pure 16", donothing, strlen$pure_("123456781234567"));
EZBENCH2("strlen 17", donothing, strlen_("123456781234567e"));
EZBENCH2("strlen$pure 17", donothing, strlen$pure_("123456781234567e"));
EZBENCH2("strlen 1023", donothing, strlen_(b));
EZBENCH2("strlen$pure 1023", donothing, strlen$pure_(b));
}

View file

@ -28,6 +28,7 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RUNTIME \
LIBC_STR \
LIBC_STUBS \
LIBC_TESTLIB \
LIBC_TINYMATH \

View file

@ -10,6 +10,7 @@ THIRD_PARTY_COMPILER_RT_A_FILES := \
$(wildcard third_party/compiler_rt/*) \
$(wildcard third_party/compiler_rt/nexgen32e/*)
THIRD_PARTY_COMPILER_RT_A_HDRS = $(filter %.h,$(THIRD_PARTY_COMPILER_RT_A_FILES))
THIRD_PARTY_COMPILER_RT_A_INCS = $(filter %.inc,$(THIRD_PARTY_COMPILER_RT_A_FILES))
THIRD_PARTY_COMPILER_RT_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_COMPILER_RT_A_FILES))
THIRD_PARTY_COMPILER_RT_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_COMPILER_RT_A_FILES))
@ -51,6 +52,7 @@ $(THIRD_PARTY_COMPILER_RT_A_OBJS): \
THIRD_PARTY_COMPILER_RT_LIBS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)))
THIRD_PARTY_COMPILER_RT_SRCS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_SRCS))
THIRD_PARTY_COMPILER_RT_HDRS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_HDRS))
THIRD_PARTY_COMPILER_RT_INCS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_INCS))
THIRD_PARTY_COMPILER_RT_CHECKS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_CHECKS))
THIRD_PARTY_COMPILER_RT_OBJS = $(foreach x,$(THIRD_PARTY_COMPILER_RT_ARTIFACTS),$($(x)_OBJS))

View file

@ -8,6 +8,7 @@ THIRD_PARTY_DUKTAPE = $(THIRD_PARTY_DUKTAPE_A_DEPS) $(THIRD_PARTY_DUKTAPE_A)
THIRD_PARTY_DUKTAPE_A = o/$(MODE)/third_party/duktape/duktape.a
THIRD_PARTY_DUKTAPE_A_FILES := $(wildcard third_party/duktape/*)
THIRD_PARTY_DUKTAPE_A_HDRS = $(filter %.h,$(THIRD_PARTY_DUKTAPE_A_FILES))
THIRD_PARTY_DUKTAPE_A_INCS = $(filter %.inc,$(THIRD_PARTY_DUKTAPE_A_FILES))
THIRD_PARTY_DUKTAPE_A_SRCS_A = $(filter %.s,$(THIRD_PARTY_DUKTAPE_A_FILES))
THIRD_PARTY_DUKTAPE_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_DUKTAPE_A_FILES))
THIRD_PARTY_DUKTAPE_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_DUKTAPE_A_FILES))
@ -60,6 +61,7 @@ o/dbg/third_party/duktape/duk_js_executor.o: \
THIRD_PARTY_DUKTAPE_LIBS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)))
THIRD_PARTY_DUKTAPE_SRCS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_SRCS))
THIRD_PARTY_DUKTAPE_HDRS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_HDRS))
THIRD_PARTY_DUKTAPE_INCS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_INCS))
THIRD_PARTY_DUKTAPE_BINS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_BINS))
THIRD_PARTY_DUKTAPE_CHECKS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_CHECKS))
THIRD_PARTY_DUKTAPE_OBJS = $(foreach x,$(THIRD_PARTY_DUKTAPE_ARTIFACTS),$($(x)_OBJS))

View file

@ -8,6 +8,7 @@ THIRD_PARTY_GDTOA = $(THIRD_PARTY_GDTOA_A_DEPS) $(THIRD_PARTY_GDTOA_A)
THIRD_PARTY_GDTOA_A = o/$(MODE)/third_party/gdtoa/gdtoa.a
THIRD_PARTY_GDTOA_A_FILES := $(wildcard third_party/gdtoa/*)
THIRD_PARTY_GDTOA_A_HDRS = $(filter %.h,$(THIRD_PARTY_GDTOA_A_FILES))
THIRD_PARTY_GDTOA_A_INCS = $(filter %.inc,$(THIRD_PARTY_GDTOA_A_FILES))
THIRD_PARTY_GDTOA_A_SRCS_S = $(filter %.S,$(THIRD_PARTY_GDTOA_A_FILES))
THIRD_PARTY_GDTOA_A_SRCS_C = $(filter %.c,$(THIRD_PARTY_GDTOA_A_FILES))
@ -54,6 +55,7 @@ $(THIRD_PARTY_GDTOA_A_OBJS): \
THIRD_PARTY_GDTOA_LIBS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)))
THIRD_PARTY_GDTOA_SRCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_SRCS))
THIRD_PARTY_GDTOA_HDRS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_HDRS))
THIRD_PARTY_GDTOA_INCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_INCS))
THIRD_PARTY_GDTOA_CHECKS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_CHECKS))
THIRD_PARTY_GDTOA_OBJS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_OBJS))
$(THIRD_PARTY_GDTOA_OBJS): $(BUILD_FILES) third_party/gdtoa/gdtoa.mk

View file

@ -1,6 +1,12 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += THIRD_PARTY_LEMON
THIRD_PARTY_LEMON_FILES := $(wildcard third_party/lemon/*)
THIRD_PARTY_LEMON_HDRS = $(filter %.h,$(THIRD_PARTY_LEMON_FILES))
THIRD_PARTY_LEMON_INCS = $(filter %.inc,$(THIRD_PARTY_LEMON_FILES))
THIRD_PARTY_LEMON_SRCS = $(filter %.c,$(THIRD_PARTY_LEMON_FILES))
LEMON = $(MKDIR) $(@D) && ACTION="LEMON $@" build/do $(THIRD_PARTY_LEMON)
THIRD_PARTY_LEMON = o/$(MODE)/third_party/lemon/lemon.com.dbg

View file

@ -36,8 +36,8 @@
/* *************************************
* Includes
***************************************/
#include "platform.h" /* Compiler options */
#include "util.h" /* UTIL_GetFileSize, UTIL_sleep */
#include "third_party/lz4cli/platform.h" /* Compiler options */
#include "third_party/lz4cli/util.h" /* UTIL_GetFileSize, UTIL_sleep */
#include "libc/mem/mem.h" /* malloc, free */
#include "libc/str/str.h" /* memset */
#include "libc/stdio/stdio.h" /* fprintf, fopen, ftello */
@ -46,17 +46,17 @@
#include "libc/bits/initializer.internal.h"
#include "libc/runtime/runtime.h" /* assert */
#include "datagen.h" /* RDG_genBuffer */
#include "xxhash.h"
#include "third_party/lz4cli/datagen.h" /* RDG_genBuffer */
#include "third_party/lz4cli/xxhash.h"
#include "lz4.h"
#include "third_party/lz4cli/lz4.h"
#define COMPRESSOR0 LZ4_compress_local
static int LZ4_compress_local(const char* src, char* dst, int srcSize, int dstSize, int clevel) {
int const acceleration = (clevel < 0) ? -clevel + 1 : 1;
return LZ4_compress_fast(src, dst, srcSize, dstSize, acceleration);
}
#include "lz4hc.h"
#include "third_party/lz4cli/lz4hc.h"
#define COMPRESSOR1 LZ4_compress_HC
#define DEFAULTCOMPRESSOR COMPRESSOR0
#define LZ4_isError(errcode) (errcode==0)

View file

@ -27,8 +27,8 @@
/**************************************
* Includes
**************************************/
#include "platform.h" /* Compiler options, SET_BINARY_MODE */
#include "util.h" /* U32 */
#include "third_party/lz4cli/platform.h" /* Compiler options, SET_BINARY_MODE */
#include "third_party/lz4cli/util.h" /* U32 */
#include "libc/mem/mem.h" /* malloc */
#include "libc/stdio/stdio.h" /* FILE, fwrite */
#include "libc/str/str.h" /* memcpy */

View file

@ -94,7 +94,7 @@
**************************************/
#define LZ4_STATIC_LINKING_ONLY
#define LZ4_DISABLE_DEPRECATE_WARNINGS /* due to LZ4_decompress_safe_withPrefix64k */
#include "lz4.h"
#include "third_party/lz4cli/lz4.h"
/* see also "memory routines" below */

View file

@ -36,17 +36,17 @@ asm(".include \"third_party/lz4cli/COPYING\"");
/****************************
* Includes
*****************************/
#include "platform.h" /* Compiler options, IS_CONSOLE */
#include "util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
#include "third_party/lz4cli/platform.h" /* Compiler options, IS_CONSOLE */
#include "third_party/lz4cli/util.h" /* UTIL_HAS_CREATEFILELIST, UTIL_createFileList */
#include "libc/stdio/stdio.h" /* fprintf, getchar */
#include "libc/mem/mem.h" /* exit, calloc, free */
#include "libc/str/str.h" /* strcmp, strlen */
#include "bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
#include "lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
#include "lz4hc.h" /* LZ4HC_CLEVEL_MAX */
#include "third_party/lz4cli/bench.h" /* BMK_benchFile, BMK_SetNbIterations, BMK_SetBlocksize, BMK_SetPause */
#include "third_party/lz4cli/lz4io.h" /* LZ4IO_compressFilename, LZ4IO_decompressFilename, LZ4IO_compressMultipleFilenames */
#include "third_party/lz4cli/lz4hc.h" /* LZ4HC_CLEVEL_MAX */
#include "libc/runtime/runtime.h"
#include "libc/log/log.h"
#include "lz4.h" /* LZ4_VERSION_STRING */
#include "third_party/lz4cli/lz4.h" /* LZ4_VERSION_STRING */
/*****************************

View file

@ -13,6 +13,10 @@
PKGS += THIRD_PARTY_LZ4CLI
THIRD_PARTY_LZ4CLI_FILES := $(wildcard third_party/lz4cli/*)
THIRD_PARTY_LZ4CLI_SRCS = $(filter %.c,$(THIRD_PARTY_LZ4CLI_FILES))
THIRD_PARTY_LZ4CLI_HDRS = $(filter %.h,$(THIRD_PARTY_LZ4CLI_FILES))
THIRD_PARTY_LZ4CLI = \
o/$(MODE)/third_party/lz4cli/lz4cli.com

View file

@ -51,7 +51,7 @@
/*=== Dependency ===*/
#define LZ4_HC_STATIC_LINKING_ONLY
#include "lz4hc.h"
#include "third_party/lz4cli/lz4hc.h"
/*=== Common LZ4 definitions ===*/
@ -63,7 +63,7 @@
#endif
#define LZ4_COMMONDEFS_ONLY
#include "lz4.c" /* LZ4_count, constants, mem */
#include "third_party/lz4cli/lz4.c" /* LZ4_count, constants, mem */
/*=== Constants ===*/

View file

@ -41,7 +41,7 @@ extern "C" {
/* --- Dependency --- */
/* note : lz4hc requires lz4.h/lz4.c for compilation */
#include "lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
#include "third_party/lz4cli/lz4.h" /* stddef, LZ4LIB_API, LZ4_DEPRECATED */
/* --- Useful constants --- */

View file

@ -106,7 +106,7 @@ static void XXH_free (void* p) { free(p); }
static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
#define XXH_STATIC_LINKING_ONLY
#include "xxhash.h"
#include "third_party/lz4cli/xxhash.h"
/* *************************************

View file

@ -280,7 +280,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src
#endif
# ifdef XXH_PRIVATE_API
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
# include "third_party/lz4cli/xxhash.c" /* include xxhash function bodies as `static`, for inlining */
# endif
#endif /* XXH_STATIC_LINKING_ONLY */

View file

@ -8,6 +8,7 @@ THIRD_PARTY_REGEX = $(THIRD_PARTY_REGEX_A_DEPS) $(THIRD_PARTY_REGEX_A)
THIRD_PARTY_REGEX_A = o/$(MODE)/third_party/regex/regex.a
THIRD_PARTY_REGEX_A_FILES := $(wildcard third_party/regex/*)
THIRD_PARTY_REGEX_A_HDRS = $(filter %.h,$(THIRD_PARTY_REGEX_A_FILES))
THIRD_PARTY_REGEX_A_INCS = $(filter %.inc,$(THIRD_PARTY_REGEX_A_FILES))
THIRD_PARTY_REGEX_A_SRCS = $(filter %.c,$(THIRD_PARTY_REGEX_A_FILES))
THIRD_PARTY_REGEX_A_OBJS = \

View file

@ -245,6 +245,10 @@ static long rombase;
static long codesize;
static int64_t opstart;
static int64_t mapsstart;
static uint64_t readaddr;
static uint64_t readsize;
static uint64_t writeaddr;
static uint64_t writesize;
static int64_t framesstart;
static int64_t breakpointsstart;
static uint64_t last_opcount;
@ -424,6 +428,10 @@ static void OnSigBusted(void) {
longjmp(onbusted, 1);
}
static bool IsShadow(int64_t v) {
return 0x7fff8000 <= v && v < 0x100080000000;
}
static int VirtualBing(int64_t v) {
int rc;
uint8_t *p;
@ -446,7 +454,7 @@ static int VirtualShadow(int64_t v) {
int rc;
char *p;
jmp_buf busted;
if (0x7fff8000 <= v && v < 0x100080000000) return -2;
if (IsShadow(v)) return -2;
onbusted = busted;
if ((p = FindReal(m, (v >> 3) + 0x7fff8000))) {
if (!setjmp(busted)) {
@ -1171,11 +1179,12 @@ static void DrawSse(struct Panel *p) {
}
static void ScrollMemoryView(struct Panel *p, struct MemoryView *v, int64_t a) {
long i, n;
long i, n, w;
w = DUMPWIDTH * (1ull << v->zoom);
n = p->bottom - p->top;
i = a / (DUMPWIDTH * (1ull << v->zoom));
i = a / w;
if (!(v->start <= i && i < v->start + n)) {
v->start = i;
v->start = i - n / 4;
}
}
@ -1194,8 +1203,8 @@ static void ZoomMemoryView(struct MemoryView *v, long y, long x, int dy) {
static void ScrollMemoryViews(void) {
ScrollMemoryView(&pan.code, &codeview, GetIp());
ScrollMemoryView(&pan.readdata, &readview, m->readaddr);
ScrollMemoryView(&pan.writedata, &writeview, m->writeaddr);
ScrollMemoryView(&pan.readdata, &readview, readaddr);
ScrollMemoryView(&pan.writedata, &writeview, writeaddr);
ScrollMemoryView(&pan.stack, &stackview, GetSp());
}
@ -1299,9 +1308,9 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view,
if (sc > 7) {
x = 129; /* PURPLE: shadow corruption */
} else if (sc == kAsanHeapFree) {
x = 17; /* NAVYBLUE: heap freed */
x = 20; /* BLUE: heap freed */
} else if (sc == kAsanRelocated) {
x = 18; /* DARKBLUE: heap relocated */
x = 16; /* BLACK: heap relocated */
} else if (sc == kAsanHeapUnderrun || sc == kAsanAllocaUnderrun) {
x = 53; /* RED+PURPLETINGE: heap underrun */
} else if (sc == kAsanHeapOverrun || sc == kAsanAllocaOverrun) {
@ -1309,7 +1318,7 @@ static void DrawMemoryUnzoomed(struct Panel *p, struct MemoryView *view,
} else if (sc < 0) {
x = 52; /* RED: uncategorized invalid */
} else if (sc > 0 && (k & 7) >= sc) {
x = 54; /* REDPURP: invalid address (skew) */
x = 88; /* BRIGHTRED: invalid address (skew) */
} else if (!sc || (sc > 0 && (k & 7) < sc)) {
x = 22; /* GREEN: valid address */
} else {
@ -1529,6 +1538,14 @@ static void PreventBufferbloat(void) {
static void Redraw(void) {
int i, j;
if (!IsShadow(m->readaddr) && !IsShadow(m->readaddr + m->readsize)) {
readaddr = m->readaddr;
readsize = m->readsize;
}
if (!IsShadow(m->writeaddr) && !IsShadow(m->writeaddr + m->writesize)) {
writeaddr = m->writeaddr;
writesize = m->writesize;
}
ScrollOp(&pan.disassembly, GetDisIndex());
if (last_opcount) {
ips = unsignedsubtract(opcount, last_opcount) / (nowl() - last_seconds);
@ -1555,9 +1572,8 @@ static void Redraw(void) {
DrawFrames(&pan.frames);
DrawBreakpoints(&pan.breakpoints);
DrawMemory(&pan.code, &codeview, GetIp(), GetIp() + m->xedd->length);
DrawMemory(&pan.readdata, &readview, m->readaddr, m->readaddr + m->readsize);
DrawMemory(&pan.writedata, &writeview, m->writeaddr,
m->writeaddr + m->writesize);
DrawMemory(&pan.readdata, &readview, readaddr, readaddr + readsize);
DrawMemory(&pan.writedata, &writeview, writeaddr, writeaddr + writesize);
DrawMemory(&pan.stack, &stackview, GetSp(), GetSp() + GetPointerWidth());
DrawStatus(&pan.status);
PreventBufferbloat();

View file

@ -1011,6 +1011,10 @@ static int OpMkdir(struct Machine *m, int64_t path, int mode) {
return mkdir(LoadStr(m, path), mode);
}
static int OpMkdirat(struct Machine *m, int dirfd, int64_t path, int mode) {
return mkdirat(XlatAfd(m, dirfd), LoadStr(m, path), mode);
}
static int OpMknod(struct Machine *m, int64_t path, uint32_t mode,
uint64_t dev) {
return mknod(LoadStr(m, path), mode, dev);
@ -1024,10 +1028,20 @@ static int OpUnlink(struct Machine *m, int64_t path) {
return unlink(LoadStr(m, path));
}
static int OpUnlinkat(struct Machine *m, int dirfd, int64_t path, int flags) {
return unlinkat(XlatAfd(m, dirfd), LoadStr(m, path), XlatAtf(flags));
}
static int OpRename(struct Machine *m, int64_t src, int64_t dst) {
return rename(LoadStr(m, src), LoadStr(m, dst));
}
static int OpRenameat(struct Machine *m, int srcdirfd, int64_t src,
int dstdirfd, int64_t dst) {
return renameat(XlatAfd(m, srcdirfd), LoadStr(m, src), XlatAfd(m, dstdirfd),
LoadStr(m, dst));
}
static int OpTruncate(struct Machine *m, int64_t path, uint64_t length) {
return truncate(LoadStr(m, path), length);
}
@ -1384,12 +1398,12 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
SYSCALL(0x0DD, OpFadvise(m, di, si, dx, r0));
SYSCALL(0x0E4, OpClockGettime(m, di, si));
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
SYSCALL(0x102, mkdirat(XlatAfd(m, di), P(si), dx));
SYSCALL(0x102, OpMkdirat(m, di, si, dx));
SYSCALL(0x104, fchownat(XlatAfd(m, di), P(si), dx, r0, XlatAtf(r8)));
SYSCALL(0x105, futimesat(XlatAfd(m, di), P(si), P(dx)));
SYSCALL(0x106, OpFstatat(m, di, si, dx, r0));
SYSCALL(0x107, unlinkat(XlatAfd(m, di), P(si), XlatAtf(dx)));
SYSCALL(0x108, renameat(XlatAfd(m, di), P(si), XlatAfd(m, dx), P(r0)));
SYSCALL(0x107, OpUnlinkat(m, di, si, dx));
SYSCALL(0x108, OpRenameat(m, di, si, dx, r0));
SYSCALL(0x10D, OpFaccessat(m, di, si, dx, r0));
SYSCALL(0x113, splice(di, P(si), dx, P(r0), r8, XlatAtf(r9)));
SYSCALL(0x115, sync_file_range(di, si, dx, XlatAtf(r0)));

View file

@ -259,6 +259,8 @@
"__builtin_lrintf"
"__builtin_lrintl"
"__builtin_memcpy"
"__builtin_mempcpy"
"__builtin_memmove"
"__builtin_memcmp"
"__builtin_memset"
"__builtin_strlen"))