Add MODE=optlinux build mode (#141)

This commit is contained in:
Justine Tunney 2021-10-14 19:36:49 -07:00
parent 226aaf3547
commit 67b5200a0b
111 changed files with 934 additions and 854 deletions

Binary file not shown.

View file

@ -9,17 +9,13 @@
# - Reasonably small # - Reasonably small
# - Reasonably optimized # - Reasonably optimized
# - Reasonably debuggable # - Reasonably debuggable
ifeq ($(MODE),) ifeq ($(MODE),)
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
$(BACKTRACES) \ $(BACKTRACES) \
$(FTRACE) \ $(FTRACE) \
-Og -Og
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-msse3 -msse3
endif endif
# Optimized Mode # Optimized Mode
@ -31,22 +27,39 @@ endif
# - No memory corruption detection # - No memory corruption detection
# - assert() / CHECK_xx() may leak code into binary for debuggability # - assert() / CHECK_xx() may leak code into binary for debuggability
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact # - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
ifeq ($(MODE), opt) ifeq ($(MODE), opt)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DNDEBUG \ -DNDEBUG \
-msse2avx \ -msse2avx \
-Wa,-msse2avx -Wa,-msse2avx
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
$(BACKTRACES) \ $(BACKTRACES) \
$(FTRACE) \ $(FTRACE) \
-O3 -O3
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-march=native -march=native
endif
# Optimized Linux Mode
#
# - `make MODE=optlinux`
# - Turns on red zone
# - Turns off backtraces
# - Turns off function tracing
# - Turns off support for older cpu models
# - Turns off support for other operating systems
ifeq ($(MODE), optlinux)
CONFIG_CPPFLAGS += \
-DNDEBUG \
-msse2avx \
-Wa,-msse2avx \
-DSUPPORT_VECTOR=1
CONFIG_CCFLAGS += \
-O3
DEFAULT_COPTS += \
-mred-zone
TARGET_ARCH ?= \
-march=native
endif endif
# Release Mode # Release Mode
@ -62,22 +75,16 @@ endif
# - DCHECK_xx() statements removed # - DCHECK_xx() statements removed
# - No memory corruption detection # - No memory corruption detection
# - CHECK_xx() won't leak strings into binary # - CHECK_xx() won't leak strings into binary
ifeq ($(MODE), rel) ifeq ($(MODE), rel)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DNDEBUG -DNDEBUG
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
$(BACKTRACES) \ $(BACKTRACES) \
-O2 -O2
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-msse3 -msse3
PYFLAGS += \ PYFLAGS += \
-O1 -O1
endif endif
# Asan Mode # Asan Mode
@ -90,19 +97,14 @@ endif
# - Backtraces # - Backtraces
# - Debuggability # - Debuggability
# - Larger binaries # - Larger binaries
ifeq ($(MODE), asan) ifeq ($(MODE), asan)
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
$(BACKTRACES) \ $(BACKTRACES) \
-O2 -O2
CONFIG_COPTS += \ CONFIG_COPTS += \
-fsanitize=address -fsanitize=address
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-msse3 -msse3
endif endif
# Debug Mode # Debug Mode
@ -114,27 +116,20 @@ endif
# - Stack canaries # - Stack canaries
# - No optimization (TODO) # - No optimization (TODO)
# - Enormous binaries # - Enormous binaries
ifeq ($(MODE), dbg) ifeq ($(MODE), dbg)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DMODE_DBG -DMODE_DBG
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
$(BACKTRACES) \ $(BACKTRACES) \
$(FTRACE) \ $(FTRACE) \
-O2 \ -O2 \
-fno-inline -fno-inline
CONFIG_COPTS += \ CONFIG_COPTS += \
-fsanitize=address -fsanitize=address
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-msse3 -msse3
OVERRIDE_CCFLAGS += \ OVERRIDE_CCFLAGS += \
-fno-pie -fno-pie
endif endif
# Tiny Mode # Tiny Mode
@ -148,7 +143,6 @@ endif
# - No backtraces # - No backtraces
# - No algorithmics # - No algorithmics
# - YOLO # - YOLO
ifeq ($(MODE), tiny) ifeq ($(MODE), tiny)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \
@ -161,6 +155,7 @@ CONFIG_CCFLAGS += \
-fno-align-labels \ -fno-align-labels \
-fno-align-loops \ -fno-align-loops \
-fschedule-insns2 \ -fschedule-insns2 \
-fomit-frame-pointer \
-momit-leaf-frame-pointer \ -momit-leaf-frame-pointer \
-foptimize-sibling-calls -foptimize-sibling-calls
TARGET_ARCH ?= \ TARGET_ARCH ?= \
@ -182,13 +177,14 @@ endif
# - No portability # - No portability
# - No algorithmics # - No algorithmics
# - YOLO # - YOLO
ifeq ($(MODE), tinylinux) ifeq ($(MODE), tinylinux)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \
-DNDEBUG \ -DNDEBUG \
-DTRUSTWORTHY \ -DTRUSTWORTHY \
-DSUPPORT_VECTOR=1 -DSUPPORT_VECTOR=1
DEFAULT_COPTS += \
-mred-zone
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
-Os \ -Os \
-fno-align-functions \ -fno-align-functions \
@ -212,13 +208,14 @@ endif
# - No backtraces # - No backtraces
# - No algorithmics # - No algorithmics
# - YOLO # - YOLO
ifeq ($(MODE), tinylinuxbsd) ifeq ($(MODE), tinylinuxbsd)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \
-DNDEBUG \ -DNDEBUG \
-DTRUSTWORTHY \ -DTRUSTWORTHY \
-DSUPPORT_VECTOR=113 -DSUPPORT_VECTOR=113
DEFAULT_COPTS += \
-mred-zone
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
-Os \ -Os \
-fno-align-functions \ -fno-align-functions \
@ -241,13 +238,14 @@ endif
# - No backtraces # - No backtraces
# - No algorithmics # - No algorithmics
# - YOLO # - YOLO
ifeq ($(MODE), tinysysv) ifeq ($(MODE), tinysysv)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \
-DNDEBUG \ -DNDEBUG \
-DTRUSTWORTHY \ -DTRUSTWORTHY \
-DSUPPORT_VECTOR=121 -DSUPPORT_VECTOR=121
DEFAULT_COPTS += \
-mred-zone
CONFIG_CCFLAGS += \ CONFIG_CCFLAGS += \
-Os \ -Os \
-fno-align-functions \ -fno-align-functions \
@ -270,7 +268,6 @@ endif
# - No backtraces # - No backtraces
# - No algorithmics # - No algorithmics
# - YOLO # - YOLO
ifeq ($(MODE), tinynowin) ifeq ($(MODE), tinynowin)
CONFIG_CPPFLAGS += \ CONFIG_CPPFLAGS += \
-DTINY \ -DTINY \

View file

@ -89,6 +89,8 @@ FTRACE = \
-pg -pg
BACKTRACES = \ BACKTRACES = \
-fno-schedule-insns2 \
-fno-omit-frame-pointer \
-fno-optimize-sibling-calls \ -fno-optimize-sibling-calls \
-mno-omit-leaf-frame-pointer -mno-omit-leaf-frame-pointer
@ -129,7 +131,6 @@ DEFAULT_COPTS = \
-fno-gnu-unique \ -fno-gnu-unique \
-fstrict-aliasing \ -fstrict-aliasing \
-fstrict-overflow \ -fstrict-overflow \
-fno-omit-frame-pointer \
-fno-semantic-interposition -fno-semantic-interposition
MATHEMATICAL = \ MATHEMATICAL = \

View file

@ -132,6 +132,14 @@ o/$(MODE)/examples/nesemu1.com.dbg: \
$(APE) $(APE)
@$(APELINK) @$(APELINK)
o/$(MODE)/examples/hello.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hello.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
$(EXAMPLES_OBJS): examples/examples.mk $(EXAMPLES_OBJS): examples/examples.mk

View file

@ -19,9 +19,12 @@
#include "libc/calls/math.h" #include "libc/calls/math.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
/**
* Adds resource usages.
*/
void AddRusage(struct rusage *x, const struct rusage *y) { void AddRusage(struct rusage *x, const struct rusage *y) {
AddTimeval(&x->ru_utime, &y->ru_utime); x->ru_utime = AddTimeval(x->ru_utime, y->ru_utime);
AddTimeval(&x->ru_stime, &y->ru_stime); x->ru_stime = AddTimeval(x->ru_stime, y->ru_stime);
x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss); x->ru_maxrss = MAX(x->ru_maxrss, y->ru_maxrss);
x->ru_ixrss += y->ru_ixrss; x->ru_ixrss += y->ru_ixrss;
x->ru_idrss += y->ru_idrss; x->ru_idrss += y->ru_idrss;

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,21 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/calls/math.h"
// 8-bit strlen that's tiny and near optimal if data's tiny. /**
// * Adds two microsecond timestamps.
// @param RDI is char *s */
// @param EAX is unsigned length struct timespec AddTimespec(struct timespec x, struct timespec y) {
// @see libc/nexgen32e/strsak.S x.tv_sec += y.tv_sec;
tinystrlen: x.tv_nsec += y.tv_nsec;
.leafprologue if (x.tv_nsec >= 10000000000) {
.profilable x.tv_nsec -= 10000000000;
xor %eax,%eax x.tv_sec += 1;
1: cmpb $0,(%rdi,%rax) }
jz 2f return x;
inc %eax }
jmp 1b
2: .leafepilogue
.endfn tinystrlen,globl
.source __FILE__

View file

@ -18,11 +18,15 @@
*/ */
#include "libc/calls/math.h" #include "libc/calls/math.h"
void AddTimeval(struct timeval *x, const struct timeval *y) { /**
x->tv_sec += y->tv_sec; * Adds two microsecond timestamps.
x->tv_usec += y->tv_usec; */
if (x->tv_usec >= 1000000) { struct timeval AddTimeval(struct timeval x, struct timeval y) {
x->tv_usec -= 1000000; x.tv_sec += y.tv_sec;
x->tv_sec += 1; x.tv_usec += y.tv_usec;
if (x.tv_usec >= 1000000) {
x.tv_usec -= 1000000;
x.tv_sec += 1;
} }
return x;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
@ -39,9 +40,16 @@
* @see fchmod() * @see fchmod()
*/ */
int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) { int fchmodat(int dirfd, const char *path, uint32_t mode, int flags) {
int rc;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) { if (weaken(__zipos_notat) && weaken(__zipos_notat)(dirfd, path) == -1) {
return -1; /* TODO(jart): implement me */ rc = -1; /* TODO(jart): implement me */
} else if (!IsWindows()) {
rc = sys_fchmodat(dirfd, path, mode, flags);
} else {
rc = sys_fchmodat_nt(dirfd, path, mode, flags);
} }
return sys_fchmodat(dirfd, path, mode, flags); SYSDEBUG("fchmodat(%d, %s, %o, %d) -> %d %s", (long)dirfd, path, mode, flags,
rc != -1 ? "" : strerror(errno));
return rc;
} }

View file

@ -44,30 +44,35 @@
*/ */
bool fileexists(const char *path) { bool fileexists(const char *path) {
int e; int e;
bool res;
union metastat st; union metastat st;
struct ZiposUri zipname; struct ZiposUri zipname;
uint16_t path16[PATH_MAX]; uint16_t path16[PATH_MAX];
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return true; res = true;
} else { } else {
errno = e; res = false;
return false;
} }
} else if (IsMetal()) { } else if (IsMetal()) {
return false; res = false;
} else if (!IsWindows()) { } else if (!IsWindows()) {
e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) { if (__sys_fstatat(AT_FDCWD, path, &st, 0) != -1) {
return true; res = true;
} else { } else {
res = false;
}
} else if (__mkntpath(path, path16) != -1) {
res = GetFileAttributes(path16) != -1u;
} else {
res = false;
}
SYSDEBUG("fileexists(%s) -> %s %s", path, res ? "true" : "false",
res ? "" : strerror(errno));
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e; errno = e;
return false;
}
} else {
if (__mkntpath(path, path16) == -1) return -1;
return GetFileAttributes(path16) != -1u;
} }
return res;
} }

View file

@ -21,6 +21,9 @@
#include "libc/calls/weirdtypes.h" #include "libc/calls/weirdtypes.h"
#include "libc/str/str.h" #include "libc/str/str.h"
/**
* Convert pathname and a project ID to System V IPC key.
*/
int ftok(const char *path, int id) { int ftok(const char *path, int id) {
struct stat st; struct stat st;
if (stat(path, &st) == -1) return -1; if (stat(path, &st) == -1) return -1;

View file

@ -16,8 +16,12 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/dce.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#define ToUpper(c) \
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
/** /**
* Returns value of environment variable, or NULL if not found. * Returns value of environment variable, or NULL if not found.
* *
@ -35,11 +39,11 @@ char *getenv(const char *s) {
} }
break; break;
} }
if (s[j] != p[i][j]) { if (ToUpper(s[j]) != ToUpper(p[i][j])) {
break; break;
} }
} }
} }
} }
return NULL; return 0;
} }

View file

@ -21,6 +21,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/struct/metastat.internal.h" #include "libc/calls/struct/metastat.internal.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
@ -43,29 +44,34 @@
* @see isregularfile(), issymlink(), ischardev() * @see isregularfile(), issymlink(), ischardev()
*/ */
bool isdirectory(const char *path) { bool isdirectory(const char *path) {
int rc, e; int e;
bool res;
union metastat st; union metastat st;
struct ZiposUri zipname; struct ZiposUri zipname;
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) return efault(); if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) { if (weaken(__zipos_open) && weaken(__zipos_parseuri)(path, &zipname) != -1) {
e = errno;
if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) { if (weaken(__zipos_stat)(&zipname, &st.cosmo) != -1) {
return S_ISDIR(st.cosmo.st_mode); res = S_ISDIR(st.cosmo.st_mode);
} else { } else {
errno = e; res = false;
return false;
} }
} else if (IsMetal()) { } else if (IsMetal()) {
return false; res = false;
} else if (!IsWindows()) { } else if (!IsWindows()) {
e = errno; e = errno;
if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) { if (__sys_fstatat(AT_FDCWD, path, &st, AT_SYMLINK_NOFOLLOW) != -1) {
return S_ISDIR(METASTAT(st, st_mode)); res = S_ISDIR(METASTAT(st, st_mode));
} else { } else {
res = false;
}
} else {
res = isdirectory_nt(path);
}
SYSDEBUG("isdirectory(%s) -> %s %s", path, res ? "true" : "false",
res ? "" : strerror(errno));
if (!res && (errno == ENOENT || errno == ENOTDIR)) {
errno = e; errno = e;
return false;
}
} else {
return isdirectory_nt(path);
} }
return res;
} }

View file

@ -1,11 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_MATH_H_ #ifndef COSMOPOLITAN_LIBC_CALLS_MATH_H_
#define COSMOPOLITAN_LIBC_CALLS_MATH_H_ #define COSMOPOLITAN_LIBC_CALLS_MATH_H_
#include "libc/calls/struct/rusage.h" #include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h" #include "libc/calls/struct/timeval.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
void AddTimeval(struct timeval *, const struct timeval *); struct timeval AddTimeval(struct timeval, struct timeval);
struct timespec AddTimespec(struct timespec, struct timespec);
void AddRusage(struct rusage *, const struct rusage *); void AddRusage(struct rusage *, const struct rusage *);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_

View file

@ -29,10 +29,13 @@
#include "libc/str/utf16.h" #include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
static noasan int CompareStrings(const char *l, const char *r) { static noasan int CompareStrings(const char *l, const char *r) {
int a, b;
size_t i = 0; size_t i = 0;
while (l[i] == r[i] && r[i]) ++i; while ((a = ToUpper(l[i] & 255)) == (b = ToUpper(r[i] & 255)) && r[i]) ++i;
return (l[i] & 0xff) - (r[i] & 0xff); return a - b;
} }
static noasan void InsertString(char **a, size_t i, char *s) { static noasan void InsertString(char **a, size_t i, char *s) {
@ -56,6 +59,7 @@ static noasan void InsertString(char **a, size_t i, char *s) {
*/ */
textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX], textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
char *const envp[], const char *extravar) { char *const envp[], const char *extravar) {
bool v;
char *t; char *t;
axdx_t rc; axdx_t rc;
uint64_t w; uint64_t w;
@ -68,6 +72,7 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
if (extravar) InsertString(vars, n++, extravar); if (extravar) InsertString(vars, n++, extravar);
for (k = i = 0; i < n; ++i) { for (k = i = 0; i < n; ++i) {
j = 0; j = 0;
v = false;
do { do {
x = vars[i][j++] & 0xff; x = vars[i][j++] & 0xff;
if (x >= 0200) { if (x >= 0200) {
@ -83,6 +88,13 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
} }
} }
} }
if (!v) {
if (x != '=') {
x = ToUpper(x);
} else {
v = true;
}
}
w = EncodeUtf16(x); w = EncodeUtf16(x);
do { do {
envvars[k++] = w & 0xffff; envvars[k++] = w & 0xffff;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -59,12 +58,5 @@ int sys_openat(int dirfd, const char *file, int flags, unsigned mode) {
d = sys_openat(dirfd, file, flags, mode); d = sys_openat(dirfd, file, flags, mode);
} }
} }
if (d != -1) {
SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %d", (long)dirfd, file, flags,
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, d);
} else {
SYSDEBUG("sys_openat(%d, %s, %d, %d) -> %s", (long)dirfd, file, flags,
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, strerror(errno));
}
return d; return d;
} }

View file

@ -19,6 +19,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
@ -43,24 +44,37 @@
* @vforksafe * @vforksafe
*/ */
int openat(int dirfd, const char *file, int flags, ...) { int openat(int dirfd, const char *file, int flags, ...) {
int rc;
va_list va; va_list va;
unsigned mode; unsigned mode;
struct ZiposUri zipname; struct ZiposUri zipname;
va_start(va, flags); va_start(va, flags);
mode = va_arg(va, unsigned); mode = va_arg(va, unsigned);
va_end(va); va_end(va);
if (!file) return efault(); if (file && (!IsAsan() || __asan_is_valid(file, 1))) {
if (IsAsan() && !__asan_is_valid(file, 1)) return efault(); if (!__isfdkind(dirfd, kFdZip)) {
if (__isfdkind(dirfd, kFdZip)) return einval(); /* TODO(jart): implement me */ if (weaken(__zipos_open) &&
if (weaken(__zipos_open) && weaken(__zipos_parseuri)(file, &zipname) != -1) { weaken(__zipos_parseuri)(file, &zipname) != -1) {
if (__vforked) return eopnotsupp(); if (!__vforked && dirfd == AT_FDCWD) {
if (dirfd != AT_FDCWD) return eopnotsupp(); rc = weaken(__zipos_open)(&zipname, flags, mode);
return weaken(__zipos_open)(&zipname, flags, mode);
} else if (!IsWindows() && !IsMetal()) {
return sys_openat(dirfd, file, flags, mode);
} else if (IsMetal()) {
return sys_openat_metal(dirfd, file, flags, mode);
} else { } else {
return sys_open_nt(dirfd, file, flags, mode); rc = eopnotsupp(); /* TODO */
} }
} else if (!IsWindows() && !IsMetal()) {
rc = sys_openat(dirfd, file, flags, mode);
} else if (IsMetal()) {
rc = sys_openat_metal(dirfd, file, flags, mode);
} else {
rc = sys_open_nt(dirfd, file, flags, mode);
}
} else {
rc = eopnotsupp(); /* TODO */
}
} else {
rc = efault();
}
SYSDEBUG("openat(%d, %s, %d, %d) -> %d %s", (long)dirfd, file, flags,
(flags & (O_CREAT | O_TMPFILE)) ? mode : 0, (long)rc,
rc == -1 ? strerror(errno) : "");
return rc;
} }

View file

@ -16,9 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sock/internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Reads data from file descriptor. * Reads data from file descriptor.
@ -32,5 +39,22 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
ssize_t read(int fd, void *buf, size_t size) { ssize_t read(int fd, void *buf, size_t size) {
return readv(fd, &(struct iovec){buf, size}, 1); if (fd >= 0) {
if (IsAsan() && !__asan_is_valid(buf, size)) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_read)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
&(struct iovec){buf, size}, 1, -1);
} else if (!IsWindows() && !IsMetal()) {
return sys_read(fd, buf, size);
} else if (fd >= g_fds.n) {
return ebadf();
} else if (IsMetal()) {
return sys_readv_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
} else {
return sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
}
} else {
return einval();
}
} }

View file

@ -96,7 +96,7 @@ noasan int sigaltstack(const struct sigaltstack *neu, struct sigaltstack *old) {
return enosys(); return enosys();
} }
if ((rc = sys_sigaltstack(a, b)) != -1) { if ((rc = sys_sigaltstack(a, b)) != -1) {
if (old) { if (IsBsd() && old) {
sigaltstack2linux(old, &bsd); sigaltstack2linux(old, &bsd);
} }
return 0; return 0;

View file

@ -17,9 +17,13 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/dce.h"
#include "libc/mem/internal.h" #include "libc/mem/internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#define ToUpper(c) \
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
/** /**
* Removes environment variable. * Removes environment variable.
*/ */
@ -42,7 +46,7 @@ int unsetenv(const char *s) {
} }
break; break;
} }
if (s[j] != p[i][j]) { if (ToUpper(s[j]) != ToUpper(p[i][j])) {
break; break;
} }
} }

View file

@ -16,8 +16,14 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/dce.h"
#include "libc/intrin/asan.internal.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/sysv/errfuns.h"
#include "libc/zipos/zipos.internal.h"
/** /**
* Writes data to file descriptor. * Writes data to file descriptor.
@ -31,5 +37,22 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
ssize_t write(int fd, const void *buf, size_t size) { ssize_t write(int fd, const void *buf, size_t size) {
return writev(fd, &(struct iovec){buf, size}, 1); if (fd >= 0) {
if (IsAsan() && !__asan_is_valid(buf, size)) return efault();
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
return weaken(__zipos_write)(
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
&(struct iovec){buf, size}, 1, -1);
} else if (!IsWindows() && !IsMetal()) {
return sys_write(fd, buf, size);
} else if (fd >= g_fds.n) {
return ebadf();
} else if (IsMetal()) {
return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
} else {
return sys_writev_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
}
} else {
return einval();
}
} }

View file

@ -37,6 +37,7 @@ _start:
0: mov (%rsp),%ebx # argc 0: mov (%rsp),%ebx # argc
lea 8(%rsp),%rsi # argv lea 8(%rsp),%rsi # argv
lea 16(%rsp,%rbx,8),%rdx # envp lea 16(%rsp,%rbx,8),%rdx # envp
mov %rsp,__oldstack(%rip)
.frame0 .frame0
// bofram 9f // bofram 9f
.weak ape_idata_iat .weak ape_idata_iat

View file

@ -16,13 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/assert.h"
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h" #include "libc/bits/safemacros.internal.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/fmt/fmts.h" #include "libc/fmt/fmts.h"
#include "libc/fmt/internal.h" #include "libc/fmt/internal.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/tinystrlen.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/thompike.h" #include "libc/str/thompike.h"
#include "libc/str/tpenc.h" #include "libc/str/tpenc.h"
@ -131,9 +131,9 @@ int __fmt_stoa(int out(const char *, void *, size_t), void *arg, void *data,
if (!(flags & FLAGS_PRECISION)) precision = -1; if (!(flags & FLAGS_PRECISION)) precision = -1;
if (!(flags & FLAGS_PRECISION) || !ignorenul) { if (!(flags & FLAGS_PRECISION) || !ignorenul) {
if (signbit == 63) { if (signbit == 63) {
precision = tinywcsnlen((const wchar_t *)p, precision); precision = wcsnlen((const wchar_t *)p, precision);
} else if (signbit == 15) { } else if (signbit == 15) {
precision = tinystrnlen16((const char16_t *)p, precision); precision = strnlen16((const char16_t *)p, precision);
} else { } else {
precision = strnlen(p, precision); precision = strnlen(p, precision);
} }

View file

@ -431,7 +431,7 @@ struct AsanFault __asan_check(const void *p, long n) {
s = (signed char *)a; s = (signed char *)a;
if (OverlapsShadowSpace(p, n)) { if (OverlapsShadowSpace(p, n)) {
return (struct AsanFault){kAsanProtected, s}; return (struct AsanFault){kAsanProtected, s};
} else if (!(0 <= a && a <= 0x7fffffffffff) && !__asan_is_mapped(a >> 16)) { } else if (IsLegalPointer(a) && !__asan_is_mapped(a >> 16)) {
return (struct AsanFault){kAsanUnmapped, s}; return (struct AsanFault){kAsanUnmapped, s};
} }
if (UNLIKELY(k)) { if (UNLIKELY(k)) {

View file

@ -13,7 +13,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias;
#define INTRIN_SSEVEX_X_X_X_(PURE, ISA, OP, FLAGS, A, B, C) \ #define INTRIN_SSEVEX_X_X_X_(PURE, ISA, OP, FLAGS, A, B, C) \
do { \ do { \
if (!IsModeDbg() && X86_HAVE(ISA)) { \ if (X86_HAVE(ISA)) { \
__intrin_xmm_t *Xmm0 = (void *)(A); \ __intrin_xmm_t *Xmm0 = (void *)(A); \
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(C); \ const __intrin_xmm_t *Xmm2 = (const __intrin_xmm_t *)(C); \
@ -29,7 +29,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias;
#define INTRIN_SSEVEX_X_X_I_(PURE, ISA, OP, A, B, I) \ #define INTRIN_SSEVEX_X_X_I_(PURE, ISA, OP, A, B, I) \
do { \ do { \
if (!IsModeDbg() && X86_HAVE(ISA)) { \ if (X86_HAVE(ISA)) { \
__intrin_xmm_t *Xmm0 = (void *)(A); \ __intrin_xmm_t *Xmm0 = (void *)(A); \
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
if (!X86_NEED(AVX)) { \ if (!X86_NEED(AVX)) { \
@ -44,7 +44,7 @@ typedef char __intrin_xmm_t _Vector_size(16) forcealign(16) mayalias;
#define INTRIN_SSEVEX_X_X_(PURE, ISA, OP, A, B) \ #define INTRIN_SSEVEX_X_X_(PURE, ISA, OP, A, B) \
do { \ do { \
if (!IsModeDbg() && X86_HAVE(ISA)) { \ if (X86_HAVE(ISA)) { \
__intrin_xmm_t *Xmm0 = (void *)(A); \ __intrin_xmm_t *Xmm0 = (void *)(A); \
const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \ const __intrin_xmm_t *Xmm1 = (const __intrin_xmm_t *)(B); \
if (!X86_NEED(AVX)) { \ if (!X86_NEED(AVX)) { \

View file

@ -22,7 +22,7 @@
/** /**
* Returns New Technology version, e.g. * Returns New Technology version, e.g.
* *
* if (IsWindows() && NtGetVersion() >= kNtVersionWindows10) {...} * if (IsWindows() && NtGetVersion() >=k NtVersionWindows10) {...}
* *
* This can only be called on Windows. * This can only be called on Windows.
*/ */

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,21 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/runtime/runtime.h"
// 16-bit strlen that's tiny and near optimal if data's tiny. intptr_t __oldstack;
//
// @param RDI is char16_t *s
// @param EAX is unsigned length
// @see libc/nexgen32e/strsak16.S
tinystrlen16:
.leafprologue
.profilable
xor %eax,%eax
1: cmpw $0,(%rdi,%rax,2)
jz 2f
inc %eax
jmp 1b
2: .leafepilogue
.endfn tinystrlen16,globl
.source __FILE__

View file

@ -25,17 +25,14 @@
#include "libc/sysv/consts/nr.h" #include "libc/sysv/consts/nr.h"
/** /**
* Privileged printf. * Privileged vprintf.
* *
* This will work without any cosmopolitan runtime support once the * This will work without any cosmopolitan runtime support once the
* executable has been loaded into memory. * executable has been loaded into memory.
*/ */
privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) { privileged noasan noubsan noinstrument void __vprintf(const char *fmt,
/* system call support runtime depends on this function */ va_list va) {
/* function tracing runtime depends on this function */
/* asan runtime depends on this function */
short w[2]; short w[2];
va_list va;
uint16_t dx; uint16_t dx;
const void *s; const void *s;
uint32_t wrote; uint32_t wrote;
@ -46,7 +43,6 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) {
char c, *p, *e, pad, bits, base, sign, thou, z[28], b[2048]; char c, *p, *e, pad, bits, base, sign, thou, z[28], b[2048];
p = b; p = b;
e = p + sizeof(b); e = p + sizeof(b);
va_start(va, fmt);
do { do {
switch ((c = *fmt++)) { switch ((c = *fmt++)) {
default: default:
@ -200,7 +196,6 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) {
break; break;
} }
} while (c); } while (c);
va_end(va);
if (p == e) { if (p == e) {
e[-4] = '.'; e[-4] = '.';
e[-3] = '.'; e[-3] = '.';
@ -229,3 +224,19 @@ privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) {
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc"); : "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
} }
} }
/**
* Privileged printf.
*
* This will work without any cosmopolitan runtime support once the
* executable has been loaded into memory.
*/
privileged noasan noubsan noinstrument void __printf(const char *fmt, ...) {
/* system call support runtime depends on this function */
/* function tracing runtime depends on this function */
/* asan runtime depends on this function */
va_list va;
va_start(va, fmt);
__vprintf(fmt, va);
va_end(va);
}

View file

@ -1,10 +1,18 @@
#ifndef COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_ #ifndef COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_
#define COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_ #define COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_
#include "libc/nexgen32e/stackframe.h" #include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/symbols.internal.h" #include "libc/runtime/symbols.internal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
forceinline pureconst bool IsValidStackFramePointer(struct StackFrame *x) {
return IsLegalPointer(x) && !((uintptr_t)x & 15) &&
(IsStaticStackFrame((uintptr_t)x >> 16) ||
IsSigAltStackFrame((uintptr_t)x >> 16) ||
IsOldStackFrame((uintptr_t)x >> 16));
}
void ShowBacktrace(int, const struct StackFrame *); void ShowBacktrace(int, const struct StackFrame *);
int PrintBacktraceUsingSymbols(int, const struct StackFrame *, int PrintBacktraceUsingSymbols(int, const struct StackFrame *,
struct SymbolTable *); struct SymbolTable *);

View file

@ -70,6 +70,9 @@ static noasan int PrintBacktraceUsingAddr2line(int fd,
garbage = weaken(__garbage); garbage = weaken(__garbage);
gi = garbage ? garbage->i : 0; gi = garbage ? garbage->i : 0;
for (frame = bp; frame && i < kBacktraceMaxFrames - 1; frame = frame->next) { for (frame = bp; frame && i < kBacktraceMaxFrames - 1; frame = frame->next) {
if (!IsValidStackFramePointer(frame)) {
return -1;
}
addr = frame->addr; addr = frame->addr;
if (addr == weakaddr("__gc")) { if (addr == weakaddr("__gc")) {
do { do {
@ -172,6 +175,7 @@ static noasan int PrintBacktrace(int fd, const struct StackFrame *bp) {
} }
noasan void ShowBacktrace(int fd, const struct StackFrame *bp) { noasan void ShowBacktrace(int fd, const struct StackFrame *bp) {
#ifdef __FNO_OMIT_FRAME_POINTER__
/* asan runtime depends on this function */ /* asan runtime depends on this function */
static bool noreentry; static bool noreentry;
++g_ftrace; ++g_ftrace;
@ -182,4 +186,9 @@ noasan void ShowBacktrace(int fd, const struct StackFrame *bp) {
noreentry = false; noreentry = false;
} }
--g_ftrace; --g_ftrace;
#else
__printf("ShowBacktrace() needs these flags to show C backtrace:\n"
"\t-D__FNO_OMIT_FRAME_POINTER__\n"
"\t-fno-omit-frame-pointer\n");
#endif
} }

View file

@ -56,6 +56,10 @@ noinstrument noasan int PrintBacktraceUsingSymbols(int fd,
garbage = weaken(__garbage); garbage = weaken(__garbage);
gi = garbage ? garbage->i : 0; gi = garbage ? garbage->i : 0;
for (i = 0, frame = bp; frame; frame = frame->next) { for (i = 0, frame = bp; frame; frame = frame->next) {
if (!IsValidStackFramePointer(frame)) {
__printf("%p corrupt frame pointer\n", frame);
break;
}
if (++i == LIMIT) { if (++i == LIMIT) {
__printf("<truncated backtrace>\n"); __printf("<truncated backtrace>\n");
break; break;

View file

@ -17,10 +17,10 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/log/internal.h" #include "libc/log/internal.h"
#include "libc/log/log.h" #include "libc/log/libfatal.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h"
/** /**
* Handles failure of CHECK_xx() macros in -DNDEBUG mode. * Handles failure of CHECK_xx() macros in -DNDEBUG mode.
@ -34,17 +34,9 @@
*/ */
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got, relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
const char *opchar) { const char *opchar) {
char bx[21]; __restore_tty(1);
int lasterr; __printf("\n%serror: %s: check failed: 0x%x %s 0x%x (%s)\n",
lasterr = errno; !g_isterminalinarticulate ? "\e[J" : "", program_invocation_name,
__start_fatal_ndebug(); want, opchar, got, strerror(errno));
__print_string("check failed: 0x"); exit(1);
__print(bx, uint64toarray_radix16(want, bx));
__print_string(" ");
__print_string(opchar);
__print_string(" 0x");
__print(bx, uint64toarray_radix16(got, bx));
__print_string(" (");
__print(bx, int64toarray_radix10(lasterr, bx));
__print_string(")\n");
} }

View file

@ -22,6 +22,7 @@
#include "libc/log/internal.h" #include "libc/log/internal.h"
#include "libc/log/libfatal.internal.h" #include "libc/log/libfatal.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/runtime/runtime.h"
/** /**
* Aborts process after printing a backtrace. * Aborts process after printing a backtrace.
@ -33,11 +34,12 @@ relegated wontreturn void __die(void) {
static bool once; static bool once;
if (cmpxchg(&once, false, true)) { if (cmpxchg(&once, false, true)) {
__restore_tty(1); __restore_tty(1);
if (IsDebuggerPresent(false)) DebugBreak(); if (IsDebuggerPresent(false)) {
ShowBacktrace(2, NULL); DebugBreak();
exit(77);
} else {
__write_str("PANIC: __DIE() DIED\r\n");
_exit(78);
} }
ShowBacktrace(2, NULL);
quick_exit(77);
}
__write_str("PANIC: __DIE() DIED\r\n");
_Exit(78);
} }

View file

@ -14,7 +14,6 @@ extern hidden struct termios g_oldtermios;
extern hidden struct sigaction g_oldcrashacts[8]; extern hidden struct sigaction g_oldcrashacts[8];
void __start_fatal(const char *, int) hidden; void __start_fatal(const char *, int) hidden;
void __start_fatal_ndebug(void) hidden;
void __oncrash(int, struct siginfo *, struct ucontext *) relegated; void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
void __restore_tty(int); void __restore_tty(int);

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_ #ifndef COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_
#define COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_ #define COSMOPOLITAN_LIBC_LOG_LIBFATAL_INTERNAL_H_
#include "libc/calls/calls.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"
@ -13,65 +14,96 @@ COSMOPOLITAN_C_START_
extern char __fatalbuf[]; extern char __fatalbuf[];
void __printf(const char *, ...); void __printf(const char *, ...);
void __vprintf(const char *, va_list);
forceinline void __sysv_exit(long rc) { forceinline long __sysv_exit(long rc) {
long ax;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: /* no outputs */ : "=a"(ax)
: "a"(__NR_exit_group), "D"(rc) : "0"(__NR_exit_group), "D"(rc)
: "memory", "cc"); : "memory", "cc");
#else
ax = syscall(__NR_exit_group, rc);
#endif
return ax;
} }
forceinline int __sysv_close(long fd) { forceinline int __sysv_close(long fd) {
long ax; long ax;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax) : "=a"(ax)
: "0"(__NR_close), "D"(fd) : "0"(__NR_close), "D"(fd)
: "rdx", "memory", "cc"); : "rdx", "memory", "cc");
#else
ax = syscall(__NR_close, fd);
#endif
return ax; return ax;
} }
forceinline int __sysv_open(const char *path, long flags, long mode) { forceinline int __sysv_open(const char *path, long flags, long mode) {
long ax, dx; long ax, dx;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax), "=d"(dx) : "=a"(ax), "=d"(dx)
: "0"(__NR_open), "D"(path), "S"(flags), "1"(mode) : "0"(__NR_open), "D"(path), "S"(flags), "1"(mode)
: "memory", "cc"); : "memory", "cc");
#else
ax = syscall(__NR_open, path, flags, mode);
#endif
return ax; return ax;
} }
forceinline long __sysv_read(long fd, void *data, unsigned long size) { forceinline long __sysv_read(long fd, void *data, unsigned long size) {
long ax, dx; long ax, dx;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax), "=d"(dx) : "=a"(ax), "=d"(dx)
: "0"(__NR_read), "D"(fd), "S"(data), "1"(size) : "0"(__NR_read), "D"(fd), "S"(data), "1"(size)
: "memory", "cc"); : "memory", "cc");
#else
ax = syscall(__NR_read, fd, data, size);
#endif
return ax; return ax;
} }
forceinline long __sysv_write(long fd, const void *data, unsigned long size) { forceinline long __sysv_write(long fd, const void *data, unsigned long size) {
long ax, dx; long ax, dx;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax), "=d"(dx) : "=a"(ax), "=d"(dx)
: "0"(__NR_write), "D"(fd), "S"(data), "1"(size) : "0"(__NR_write), "D"(fd), "S"(data), "1"(size)
: "memory", "cc"); : "memory", "cc");
#else
ax = syscall(__NR_write, fd, data, size);
#endif
return ax; return ax;
} }
forceinline long __sysv_mprotect(void *addr, size_t size, long prot) { forceinline long __sysv_mprotect(void *addr, size_t size, long prot) {
long ax, dx; long ax, dx;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax), "=d"(dx) : "=a"(ax), "=d"(dx)
: "0"(__NR_mprotect), "D"(addr), "S"(size), "1"(prot) : "0"(__NR_mprotect), "D"(addr), "S"(size), "1"(prot)
: "memory", "cc"); : "memory", "cc");
#else
ax = syscall(__NR_mprotect, addr, size, prot);
#endif
return ax; return ax;
} }
forceinline int __sysv_getpid(void) { forceinline int __sysv_getpid(void) {
long ax; long ax;
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm volatile("call\t__syscall__" asm volatile("call\t__syscall__"
: "=a"(ax) : "=a"(ax)
: "0"(__NR_getpid) : "0"(__NR_getpid)
: "rdx", "memory", "cc"); : "rdx", "memory", "cc");
#else
ax = syscall(__NR_getpid);
#endif
return ax; return ax;
} }
@ -122,17 +154,32 @@ forceinline char *__stpcpy(char *d, const char *s) {
} }
forceinline void *__repstosb(void *di, char al, size_t cx) { forceinline void *__repstosb(void *di, char al, size_t cx) {
#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm("rep stosb" asm("rep stosb"
: "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di) : "=D"(di), "=c"(cx), "=m"(*(char(*)[cx])di)
: "0"(di), "1"(cx), "a"(al)); : "0"(di), "1"(cx), "a"(al));
return di; return di;
#else
size_t i;
volatile char *volatile d = di;
while (cx--) *d++ = al;
return d;
#endif
} }
forceinline void *__repmovsb(void *di, void *si, size_t cx) { forceinline void *__repmovsb(void *di, void *si, size_t cx) {
#if defined(__x86__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
asm("rep movsb" asm("rep movsb"
: "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di) : "=D"(di), "=S"(si), "=c"(cx), "=m"(*(char(*)[cx])di)
: "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si)); : "0"(di), "1"(si), "2"(cx), "m"(*(char(*)[cx])si));
return di; return di;
#else
size_t i;
volatile char *volatile d = di;
volatile char *volatile s = si;
while (cx--) *d++ = *s++;
return d;
#endif
} }
forceinline void *__mempcpy(void *d, const void *s, size_t n) { forceinline void *__mempcpy(void *d, const void *s, size_t n) {

View file

@ -99,7 +99,11 @@ relegated static const char *TinyStrSignal(int sig) {
relegated static void ShowFunctionCalls(ucontext_t *ctx) { relegated static void ShowFunctionCalls(ucontext_t *ctx) {
struct StackFrame *bp; struct StackFrame *bp;
struct StackFrame goodframe; struct StackFrame goodframe;
if (ctx->uc_mcontext.rip && ctx->uc_mcontext.rbp) { if (!ctx->uc_mcontext.rip) {
__printf("%s is NULL can't show backtrace\n", "RIP");
} else if (!ctx->uc_mcontext.rbp) {
__printf("%s is NULL can't show backtrace\n", "RBP");
} else {
goodframe.next = (struct StackFrame *)ctx->uc_mcontext.rbp; goodframe.next = (struct StackFrame *)ctx->uc_mcontext.rbp;
goodframe.addr = ctx->uc_mcontext.rip; goodframe.addr = ctx->uc_mcontext.rip;
bp = &goodframe; bp = &goodframe;

View file

@ -25,7 +25,6 @@
* Prints initial part of fatal message. * Prints initial part of fatal message.
* *
* @note this is support code for __check_fail(), __assert_fail(), etc. * @note this is support code for __check_fail(), __assert_fail(), etc.
* @see __start_fatal_ndebug()
*/ */
relegated void __start_fatal(const char *file, int line) { relegated void __start_fatal(const char *file, int line) {
bool colorful; bool colorful;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/alg/alg.h" #include "libc/alg/alg.h"
#include "libc/dce.h"
#include "libc/mem/internal.h" #include "libc/mem/internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -25,6 +26,8 @@
#define MAX_VARS 512 #define MAX_VARS 512
#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
static bool once; static bool once;
static void PutEnvDestroy(void) { static void PutEnvDestroy(void) {
@ -56,8 +59,12 @@ int PutEnvImpl(char *s, bool overwrite) {
PutEnvInit(); PutEnvInit();
once = true; once = true;
} }
p = strchr(s, '='); for (p = s; *p && *p != '='; ++p) {
if (!p) goto fail; if (IsWindows()) {
*p = ToUpper(*p);
}
}
if (*p != '=') goto fail;
namelen = p + 1 - s; namelen = p + 1 - s;
for (i = 0; environ[i]; ++i) { for (i = 0; environ[i]; ++i) {
if (!strncmp(environ[i], s, namelen)) { if (!strncmp(environ[i], s, namelen)) {

View file

@ -42,11 +42,6 @@ $(LIBC_NEXGEN32E_A).pkg: \
$(LIBC_NEXGEN32E_A_OBJS) \ $(LIBC_NEXGEN32E_A_OBJS) \
$(foreach x,$(LIBC_NEXGEN32E_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_NEXGEN32E_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/nexgen32e/tinystrlen.ncabi.o \
o/$(MODE)/libc/nexgen32e/tinystrncmp.ncabi.o: \
OVERRIDE_CFLAGS += \
-Os
o/$(MODE)/libc/nexgen32e/errno.o: \ o/$(MODE)/libc/nexgen32e/errno.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
$(NO_MAGIC) \ $(NO_MAGIC) \

View file

@ -95,32 +95,6 @@ strnlen16_s:
.leafepilogue .leafepilogue
.endfn strnlen16_s,globl .endfn strnlen16_s,globl
// Returns length of NUL-terminated char16_t string.
//
// @param rdi is non-null NUL-terminated char16_t string pointer
// @return rax is the number of shorts, excluding the NUL
// @asyncsignalsafe
strlen16:
or $-1,%rsi
// fallthrough
.endfn strlen16,globl
// Returns length of NUL-terminated memory, with limit.
//
// @param rdi is non-null memory
// @param rsi is the maximum number of shorts to consider
// @return rax is the number of shorts, excluding the NUL
// @asyncsignalsafe
strnlen16:
.leafprologue
.profilable
or $-1,%r10
0: xor %edx,%edx
xor %r11d,%r11d
mov %rdi,%r8
// fallthrough
.endfn strnlen16,globl
// Swiss Army Knife of string char16_t scanning. // Swiss Army Knife of string char16_t scanning.
// Sixteen fast functions in one. // Sixteen fast functions in one.
// //

View file

@ -79,7 +79,8 @@ wcslen: or $-1,%rsi
// @param rsi is the maximum number of chars to consider // @param rsi is the maximum number of chars to consider
// @return rax is the number of chars, excluding the NUL // @return rax is the number of chars, excluding the NUL
// @asyncsignalsafe // @asyncsignalsafe
wcsnlen:.leafprologue wcsnlen:
.leafprologue
.profilable .profilable
or $-1,%r10 or $-1,%r10
0: xor %edx,%edx 0: xor %edx,%edx

View file

@ -1,55 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#if !defined(__GNUC__) || defined(__STRICT_ANSI__)
int tinystrlen(const char *);
int tinystrnlen(const char *, size_t);
int tinystrlen16(const char16_t *);
int tinystrnlen16(const char16_t *, size_t);
int tinywcslen(const wchar_t *);
int tinywcsnlen(const wchar_t *, size_t);
#else
forceinline int tinystrlen(const char *s) {
unsigned ax;
asm("call\ttinystrlen" : "=a"(ax) : "D"(s), "m"(*(char(*)[PAGESIZE])s));
return ax;
}
forceinline int tinystrnlen(const char *s, size_t n) {
unsigned ax;
asm("call\ttinystrnlen" : "=a"(ax) : "D"(s), "S"(n), "m"(*(char(*)[n])s));
return ax;
}
forceinline int tinystrlen16(const char16_t *s) {
unsigned ax;
asm("call\ttinystrlen16" : "=a"(ax) : "D"(s), "m"(*(char16_t(*)[PAGESIZE])s));
return ax;
}
forceinline int tinystrnlen16(const char16_t *s, size_t n) {
unsigned ax;
asm("call\ttinystrnlen16"
: "=a"(ax)
: "D"(s), "S"(n), "m"(*(char16_t(*)[n])s));
return ax;
}
forceinline int tinywcslen(const wchar_t *s) {
unsigned ax;
asm("call\ttinywcslen" : "=a"(ax) : "D"(s), "m"(*(wchar_t(*)[PAGESIZE])s));
return ax;
}
forceinline int tinywcsnlen(const wchar_t *s, size_t n) {
unsigned ax;
asm("call\ttinywcsnlen" : "=a"(ax) : "D"(s), "S"(n), "m"(*(wchar_t(*)[n])s));
return ax;
}
#endif
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_TINYSTRLEN_H_ */

View file

@ -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/macros.internal.h"
// 8-bit strnlen that's tiny and near optimal if data's tiny.
//
// @param RDI is char *s
// @param RSI is size_t n
// @param EAX is unsigned length
// @see libc/nexgen32e/strsak.S
tinystrnlen:
.leafprologue
.profilable
xor %eax,%eax
1: cmp %esi,%eax
jae 2f
cmpb $0,(%rdi,%rax)
jz 2f
inc %eax
jmp 1b
2: .leafepilogue
.endfn tinystrnlen,globl
.source __FILE__

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/sysdebug.internal.h"
#include "libc/runtime/memtrack.internal.h" #include "libc/runtime/memtrack.internal.h"
noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) { noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
@ -23,6 +24,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
int i; int i;
for (i = 0; i < mm->i; ++i) { for (i = 0; i < mm->i; ++i) {
if (mm->p[i].y < mm->p[i].x) { if (mm->p[i].y < mm->p[i].x) {
SYSDEBUG("AreMemoryIntervalsOk() y should be >= x!");
return false; return false;
} }
if (i) { if (i) {
@ -32,6 +34,7 @@ noasan bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
} }
} else { } else {
if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) { if (!(mm->p[i - 1].y + 1 <= mm->p[i].x)) {
SYSDEBUG("AreMemoryIntervalsOk() out of order or overlap!");
return false; return false;
} }
} }

View file

@ -21,6 +21,7 @@
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/log/libfatal.internal.h" #include "libc/log/libfatal.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/runtime/runtime.h"
/** /**
* Handles failure of assert() macro. * Handles failure of assert() macro.
@ -28,14 +29,14 @@
relegated wontreturn void __assert_fail(const char *expr, const char *file, relegated wontreturn void __assert_fail(const char *expr, const char *file,
int line) { int line) {
static bool noreentry; static bool noreentry;
__printf("\r\n%s:%d: assert(%s) failed\r\n", file, line, expr); __printf("%s:%d: assert(%s) failed\r\n", file, line, expr);
if (cmpxchg(&noreentry, false, true)) { if (cmpxchg(&noreentry, false, true)) {
if (weaken(__die)) { if (weaken(__die)) {
weaken(__die)(); weaken(__die)();
} else { } else {
__printf("can't backtrace b/c `__die` not linked\r\n"); __printf("can't backtrace b/c `__die` not linked\r\n");
} }
exit(23); quick_exit(23);
} }
_exit(24); _Exit(24);
} }

View file

@ -41,7 +41,7 @@ noasan const char *DescribeFrame(int x) {
return " fixed "; return " fixed ";
} else if (IsArenaFrame(x)) { } else if (IsArenaFrame(x)) {
return " arena "; return " arena ";
} else if (IsStackFrame(x)) { } else if (IsStaticStackFrame(x)) {
return " stack "; return " stack ";
} else { } else {
return ""; return "";

View file

@ -91,7 +91,7 @@ textwindows noasan struct DirectMap sys_mmap_nt(void *addr, size_t size,
SYSDEBUG( SYSDEBUG(
"MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> " "MapViewOfFileExNuma(prot:%s, off:0x%x, size:0x%x, addr:0x%x) -> "
"addr:0x%x", "addr:0x%x",
(prot & PROT_WRITE) ? "WX" : "RX", off, size, addr); (prot & PROT_WRITE) ? "WX" : "RX", off, size, addr, dm.addr);
if (dm.addr) { if (dm.addr) {
return dm; return dm;
} else { } else {

View file

@ -19,6 +19,7 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h" #include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"

View file

@ -21,19 +21,29 @@
#include "libc/str/tpenc.h" #include "libc/str/tpenc.h"
#include "libc/str/utf16.h" #include "libc/str/utf16.h"
#define ToUpper(c) ((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
static textwindows noasan noinstrument axdx_t Recode16to8(char *dst, static textwindows noasan noinstrument axdx_t Recode16to8(char *dst,
size_t dstsize, size_t dstsize,
const char16_t *src) { const char16_t *src) {
bool v;
axdx_t r; axdx_t r;
uint64_t w; uint64_t w;
wint_t x, y; wint_t x, y;
for (r.ax = 0, r.dx = 0;;) { for (v = r.ax = 0, r.dx = 0;;) {
if (!(x = src[r.dx++])) break; if (!(x = src[r.dx++])) break;
if (IsUtf16Cont(x)) continue; if (IsUtf16Cont(x)) continue;
if (!IsUcs2(x)) { if (!IsUcs2(x)) {
y = src[r.dx++]; y = src[r.dx++];
x = MergeUtf16(x, y); x = MergeUtf16(x, y);
} }
if (!v) {
if (x == '=') {
v = true;
} else {
x = ToUpper(x);
}
}
w = tpenc(x); w = tpenc(x);
do { do {
if (r.ax + 1 >= dstsize) break; if (r.ax + 1 >= dstsize) break;

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/likely.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/sysdebug.internal.h" #include "libc/calls/sysdebug.internal.h"
@ -61,71 +62,52 @@ static noasan void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i,
mm->i -= n; mm->i -= n;
} }
static noasan void MapNewMappingArray(struct MemoryIntervals *mm) { static noasan bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
/* asan runtime depends on this function */
void *a;
int i, x, y, g;
size_t n, m, f;
int prot, flags; int prot, flags;
char *base, *shad;
size_t gran, size;
struct DirectMap dm; struct DirectMap dm;
struct MemoryInterval *p, *q; gran = kMemtrackGran;
assert(mm->i); base = (char *)kMemtrackStart;
assert(AreMemoryIntervalsOk(mm));
n = mm->n;
n = n * sizeof(*mm->p);
n = ROUNDUP(n, FRAMESIZE);
if (mm->p == mm->s) {
m = n;
q = 0;
} else {
q = mm->p;
m = n + (n >> 1);
m = ROUNDUP(m, FRAMESIZE);
}
/*
* find a hole in the automap range
* we pad the sides for easier insertion logic
* only time this fails is MODE=tiny which makes no stack
*/
i = 0;
f = m >> 16;
for (;;) {
if (++i == mm->i || mm->p[i].x - mm->p[i - 1].y >= 1 + f + 1) {
x = mm->p[i - 1].y + 1;
y = x + f - 1;
a = (void *)((intptr_t)((uint64_t)x << 32) >> 16);
if (i == mm->i || (kAutomapStart <= (intptr_t)a &&
(intptr_t)a + m < kAutomapStart + kAutomapSize)) {
break;
}
}
}
flags = MAP_ANONYMOUS | MAP_PRIVATE;
prot = PROT_READ | PROT_WRITE; prot = PROT_READ | PROT_WRITE;
SYSDEBUG("MapNewMappingArray(0x%x, 0x%x) %d/%d/%d", a, m, i, mm->i, mm->n); flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;
dm = sys_mmap(a, m, prot, flags | MAP_FIXED, -1, 0); if (mm->p == mm->s) {
if ((p = dm.addr) != MAP_FAILED) {
MoveMemoryIntervals(p, mm->p, i);
MoveMemoryIntervals(p + i + 1, mm->p + i, mm->i - i);
mm->i += 1;
mm->n = m / sizeof(*mm->p);
mm->p = p;
mm->p[i].x = x;
mm->p[i].y = y;
mm->p[i].h = dm.maphandle;
mm->p[i].prot = prot;
mm->p[i].flags = flags;
if (q) {
munmap(q, n);
}
if (IsAsan()) { if (IsAsan()) {
__asan_map_shadow((uintptr_t)a, m); shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #1");
return false;
} }
SYSDEBUG("MapNewMappingArray() succeeded"); }
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #2");
return false;
}
MoveMemoryIntervals(dm.addr, mm->p, mm->i);
mm->p = dm.addr;
mm->n = gran / sizeof(*mm->p);
} else { } else {
SYSDEBUG("MapNewMappingArray() failed: %s", strerror(errno)); size = ROUNDUP(mm->n * sizeof(*mm->p), gran);
base += size;
if (IsAsan()) {
shad = (char *)(((intptr_t)base >> 3) + 0x7fff8000);
dm = sys_mmap(shad, gran >> 3, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #3");
return false;
}
}
dm = sys_mmap(base, gran, prot, flags, -1, 0);
if (!dm.addr) {
SYSDEBUG("ExtendMemoryIntervals() fail #4");
return false;
}
mm->n = (size + gran) / sizeof(*mm->p);
} }
assert(AreMemoryIntervalsOk(mm)); assert(AreMemoryIntervalsOk(mm));
return true;
} }
noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) { noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
@ -135,16 +117,12 @@ noasan int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
assert(i >= 0); assert(i >= 0);
assert(i <= mm->i); assert(i <= mm->i);
assert(mm->n >= 0); assert(mm->n >= 0);
if (mm->i == mm->n) { if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
SYSDEBUG("CreateMemoryInterval() failed");
return enomem();
}
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i); MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
return 0; return 0;
} }
static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) { static noasan int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
if (mm->i == mm->n) return enomem();
if (CreateMemoryInterval(mm, i) == -1) return -1; if (CreateMemoryInterval(mm, i) == -1) return -1;
mm->p[i].y = x - 1; mm->p[i].y = x - 1;
mm->p[i + 1].x = y + 1; mm->p[i + 1].x = y + 1;
@ -210,16 +188,12 @@ noasan int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
prot == mm->p[i].prot && flags == mm->p[i].flags) { prot == mm->p[i].prot && flags == mm->p[i].flags) {
mm->p[i].x = x; mm->p[i].x = x;
} else { } else {
if (mm->i == mm->n) return enomem();
if (CreateMemoryInterval(mm, i) == -1) return -1; if (CreateMemoryInterval(mm, i) == -1) return -1;
mm->p[i].x = x; mm->p[i].x = x;
mm->p[i].y = y; mm->p[i].y = y;
mm->p[i].h = h; mm->p[i].h = h;
mm->p[i].prot = prot; mm->p[i].prot = prot;
mm->p[i].flags = flags; mm->p[i].flags = flags;
if (mm->i >= mm->n / 2) {
MapNewMappingArray(mm);
}
} }
return 0; return 0;
} }

View file

@ -5,24 +5,26 @@
#include "libc/nt/enum/version.h" #include "libc/nt/enum/version.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h" #include "libc/runtime/stack.h"
#include "libc/sysv/consts/ss.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#define _kAutomapStart 0x0000100080000000 #define kAutomapStart _kMem(0x100080000000, 0x000010000000)
#define _kAutomapSize 0x00000fff80000000 #define kAutomapSize \
#define _kFixedmapStart 0x0000300000000000 _kMem(0x200000000000 - 0x100080000000 - _kMmi(0x800000000000), \
#define _kFixedmapSize 0x00000fff80000000 0x000040000000 - 0x000010000000 - _kMmi(0x000080000000))
#define kMemtrackStart \
/* _kMem(0x200000000000 - _kMmi(0x800000000000), \
* TODO: Why can't we allocate addresses above 4GB on Windows 7 x64? 0x000040000000 - _kMmi(0x000080000000))
* https://github.com/jart/cosmopolitan/issues/19 #define kMemtrackSize _kMem(_kMmi(0x800000000000), _kMmi(0x000080000000))
*/ #define kMemtrackGran (!IsAsan() ? FRAMESIZE : FRAMESIZE * 8)
#define MEMTRACK_ADDRESS(NORMAL, WIN7) \ #define kFixedmapStart _kMem(0x300000000000, 0x000040000000)
#define kFixedmapSize \
_kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000)
#define _kMmi(VSPACE) \
ROUNDUP(VSPACE / FRAMESIZE * sizeof(struct MemoryInterval), FRAMESIZE)
#define _kMem(NORMAL, WIN7) \
(!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7) (!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7)
#define kAutomapStart MEMTRACK_ADDRESS(_kAutomapStart, 0x10000000)
#define kAutomapSize MEMTRACK_ADDRESS(_kAutomapSize, 0x30000000)
#define kFixedmapStart MEMTRACK_ADDRESS(_kFixedmapStart, 0x40000000)
#define kFixedmapSize MEMTRACK_ADDRESS(_kFixedmapSize, 0x30000000)
struct MemoryInterval { struct MemoryInterval {
int x; int x;
@ -52,11 +54,19 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden; void ReleaseMemoryNt(struct MemoryIntervals *, int, int) hidden;
int UntrackMemoryIntervals(void *, size_t) hidden; int UntrackMemoryIntervals(void *, size_t) hidden;
#define IsLegalPointer(p) \
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
forceinline pureconst bool IsAutoFrame(int x) { forceinline pureconst bool IsAutoFrame(int x) {
return (kAutomapStart >> 16) <= x && return (kAutomapStart >> 16) <= x &&
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16); x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
} }
forceinline pureconst bool IsMemtrackFrame(int x) {
return (kAutomapStart >> 16) <= x &&
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
}
forceinline pureconst bool IsArenaFrame(int x) { forceinline pureconst bool IsArenaFrame(int x) {
return 0x5000 <= x && x < 0x7ffe; return 0x5000 <= x && x < 0x7ffe;
} }
@ -65,11 +75,21 @@ forceinline pureconst bool IsShadowFrame(int x) {
return 0x7fff <= x && x < 0x10008000; return 0x7fff <= x && x < 0x10008000;
} }
forceinline pureconst bool IsStackFrame(int x) { forceinline pureconst bool IsStaticStackFrame(int x) {
return (GetStaticStackAddr(0) >> 16) <= x && return (GetStaticStackAddr(0) >> 16) <= x &&
x <= ((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16); x <= ((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16);
} }
forceinline pureconst bool IsSigAltStackFrame(int x) {
return (GetStackAddr(0) >> 16) <= x &&
x <= ((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16);
}
forceinline pureconst bool IsOldStackFrame(int x) {
intptr_t old = ROUNDDOWN(__oldstack, STACKSIZE);
return (old >> 16) <= x && x <= ((old + (STACKSIZE - FRAMESIZE)) >> 16);
}
forceinline pureconst bool IsFixedFrame(int x) { forceinline pureconst bool IsFixedFrame(int x) {
return (kFixedmapStart >> 16) <= x && return (kFixedmapStart >> 16) <= x &&
x <= ((kFixedmapStart + (kFixedmapSize - 1)) >> 16); x <= ((kFixedmapStart + (kFixedmapSize - 1)) >> 16);

View file

@ -23,8 +23,10 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h" #include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/backtrace.internal.h" #include "libc/log/backtrace.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/rand/rand.h" #include "libc/rand/rand.h"
@ -40,7 +42,6 @@
#define VIP(X) (void *)IP(X) #define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff) #define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) #define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16)) #define FRAME(x) ((int)((intptr_t)(x) >> 16))
@ -104,6 +105,87 @@ noasan static bool Automap(int n, int *res) {
} }
} }
static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
int fd, int64_t off, int f, int x, int n) {
struct DirectMap dm;
dm = sys_mmap(addr, size, prot, f, fd, off);
if (UNLIKELY(dm.addr == MAP_FAILED)) {
if (IsWindows() && (flags & MAP_FIXED)) {
SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", addr, size, strerror(errno),
"can't recover from MAP_FIXED errors on Windows");
assert(!"MapMemory() failed");
Die();
}
return MAP_FAILED;
}
if (UNLIKELY(dm.addr != addr)) {
SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED");
assert(!"MapMemory() failed");
Die();
}
if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(addr, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
}
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(addr, n) == -1) {
SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno));
assert(!"MapMemory() failed");
Die();
}
return MAP_FAILED;
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) {
weaken(__asan_map_shadow)((intptr_t)addr, size);
}
return addr;
}
/**
* Maps memory from system, one frame at a time.
*
* This is useful on Windows since it allows us to partially unmap or
* punch holes into existing mappings.
*/
static textwindows noinline noasan void *MapMemories(char *addr, size_t size,
int prot, int flags,
int fd, int64_t off, int f,
int x, size_t n) {
struct DirectMap dm;
size_t i, m = (n - 1) * FRAMESIZE;
assert(m < size && m + FRAMESIZE >= size);
dm = sys_mmap(addr + m, size - m, prot, f, fd, fd == -1 ? 0 : off + m);
if (dm.addr == MAP_FAILED) {
SYSDEBUG("MapMemories(%p+%x/%x) %s", addr, m, size, strerror(errno));
return MAP_FAILED;
}
if (TrackMemoryInterval(&_mmi, x + (n - 1), x + (n - 1), dm.maphandle, prot,
flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #1 %s", addr, m, size,
strerror(errno));
assert(!"MapMemories() failed");
Die();
}
for (i = 0; i < m; i += FRAMESIZE) {
dm = sys_mmap(addr + i, FRAMESIZE, prot, f, fd, fd == -1 ? 0 : off + i);
if (dm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, x + i / FRAMESIZE, x + i / FRAMESIZE,
dm.maphandle, prot, flags) == -1) {
SYSDEBUG("MapMemories(%p+%x/%x) unrecoverable failure #2 %s", addr, i,
size, strerror(errno));
assert(!"MapMemories() failed");
Die();
}
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(addr, size)) {
weaken(__asan_map_shadow)((intptr_t)addr, size);
}
return addr;
}
/** /**
* Beseeches system for page-table entries, e.g. * Beseeches system for page-table entries, e.g.
* *
@ -146,7 +228,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size); SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (size isn't 48-bit)", p, size);
return VIP(einval()); return VIP(einval());
} }
if (UNLIKELY(!LEGAL(p))) { if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size); SYSDEBUG("mmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, size);
return VIP(einval()); return VIP(einval());
} }
@ -202,6 +284,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
if (IsWindows()) { if (IsWindows()) {
if (UntrackMemoryIntervals(p, size)) { if (UntrackMemoryIntervals(p, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno)); SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
assert(!"mmap() failed");
Die(); Die();
} }
} }
@ -215,34 +298,9 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off); dm = sys_mmap(p, size, prot, f & ~MAP_GROWSDOWN, fd, off);
if (dm.addr == MAP_FAILED) return MAP_FAILED; if (dm.addr == MAP_FAILED) return MAP_FAILED;
} }
dm = sys_mmap(p, size, prot, f, fd, off); if (!IsWindows()) {
if (UNLIKELY(dm.addr == MAP_FAILED)) { return MapMemory(p, size, prot, flags, fd, off, f, x, n);
if (IsWindows() && (flags & MAP_FIXED)) { } else {
SYSDEBUG("mmap(0x%p, 0x%x) -> %s (%s)", p, size, strerror(errno), return MapMemories(p, size, prot, flags, fd, off, f, x, n);
"can't recover from MAP_FIXED errors on Windows");
Die();
} }
return MAP_FAILED;
}
if (UNLIKELY(dm.addr != p)) {
SYSDEBUG("KERNEL DIDN'T RESPECT MAP_FIXED");
Die();
}
if (!IsWindows() && (flags & MAP_FIXED)) {
if (UntrackMemoryIntervals(p, size)) {
SYSDEBUG("FIXED UNTRACK FAILED %s", strerror(errno));
Die();
}
}
if (TrackMemoryInterval(&_mmi, x, x + (n - 1), dm.maphandle, prot, flags)) {
if (sys_munmap(p, n) == -1) {
SYSDEBUG("TRACK MUNMAP FAILED %s", strerror(errno));
Die();
}
return MAP_FAILED;
}
if (weaken(__asan_map_shadow) && !OverlapsShadowSpace(p, size)) {
weaken(__asan_map_shadow)((intptr_t)p, size);
}
return p;
} }

View file

@ -38,7 +38,6 @@
#define VIP(X) (void *)IP(X) #define VIP(X) (void *)IP(X)
#define SMALL(n) ((n) <= 0xffffffffffff) #define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) #define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16)) #define FRAME(x) ((int)((intptr_t)(x) >> 16))

View file

@ -20,6 +20,7 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/sysdebug.internal.h" #include "libc/calls/sysdebug.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/libfatal.internal.h" #include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
@ -32,7 +33,6 @@
#define IP(X) (intptr_t)(X) #define IP(X) (intptr_t)(X)
#define SMALL(n) ((n) <= 0xffffffffffff) #define SMALL(n) ((n) <= 0xffffffffffff)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define LEGAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16) #define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000) #define SHADE(x) (((intptr_t)(x) >> 3) + 0x7fff8000)
#define FRAME(x) ((int)((intptr_t)(x) >> 16)) #define FRAME(x) ((int)((intptr_t)(x) >> 16))
@ -64,11 +64,11 @@ noasan int munmap(void *v, size_t n) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n); SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (n isn't 48-bit)", p, n);
return einval(); return einval();
} }
if (UNLIKELY(!LEGAL(p))) { if (UNLIKELY(!IsLegalPointer(p))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n); SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p isn't 48-bit)", p, n);
return einval(); return einval();
} }
if (UNLIKELY(!LEGAL(p + (n - 1)))) { if (UNLIKELY(!IsLegalPointer(p + (n - 1)))) {
SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n); SYSDEBUG("munmap(0x%p, 0x%x) EINVAL (p+(n-1) isn't 48-bit)", p, n);
return einval(); return einval();
} }
@ -80,7 +80,6 @@ noasan int munmap(void *v, size_t n) {
SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n); SYSDEBUG("munmap(0x%p, 0x%x) EFAULT (interval not tracked)", p, n);
return efault(); return efault();
} }
SYSDEBUG("munmap(0x%p, 0x%x)", p, n);
if (UntrackMemoryIntervals(p, n) != -1) { if (UntrackMemoryIntervals(p, n) != -1) {
if (!IsWindows()) { if (!IsWindows()) {
rc = sys_munmap(p, n); rc = sys_munmap(p, n);
@ -105,11 +104,13 @@ noasan int munmap(void *v, size_t n) {
} }
} }
} }
} else {
rc = 0; /* UntrackMemoryIntervals does it for NT */
}
} else {
rc = -1;
}
SYSDEBUG("munmap(0x%p, 0x%x) -> %d %s", p, n, (long)rc,
rc == -1 ? strerror(errno) : "");
return rc; return rc;
} else {
return 0; /* UntrackMemoryIntervals does it for NT */
}
} else {
return -1;
}
} }

View file

@ -23,9 +23,17 @@
_peekall: _peekall:
.leafprologue .leafprologue
ezlea _base,si ezlea _base,si
ezlea _etext,cx
add $0x1000,%rsi
0: xor (%rsi),%eax
add $PAGESIZE,%rsi
cmp %rcx,%rsi
jb 0b
ezlea _etext,si
ezlea _end,cx ezlea _end,cx
add $0x1000,%rsi add $0x1000,%rsi
0: mov (%rsi),%eax 0: incq (%rsi)
decq (%rsi)
add $PAGESIZE,%rsi add $PAGESIZE,%rsi
cmp %rcx,%rsi cmp %rcx,%rsi
jb 0b jb 0b

View file

@ -1,76 +0,0 @@
/*-*- 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.
*/
#define ShouldUseMsabiAttribute() 1
#include "libc/dce.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/nr.h"
/* TODO(jart): DELETE */
#define WasImported(SLOT) \
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)
static void __sys_print_nt(const void *data, size_t len) {
int64_t hand;
char xmm[256];
uint32_t wrote;
_savexmm(xmm + 128);
hand = __imp_GetStdHandle(kNtStdErrorHandle);
__imp_WriteFile(hand, data, len, &wrote, NULL);
_loadxmm(xmm + 128);
}
/**
* Prints string, by any means necessary.
*
* This function offers a subset of write(STDERR_FILENO) functionality.
* It's designed to work even when the runtime hasn't initialized, e.g.
* before _init() gets called.
*
* @param len can be computed w/ tinystrlen()
* @clob nothing except flags
*/
privileged noinline void __print(const void *data, size_t len) {
int64_t ax, ordinal;
if (WasImported(__imp_WriteFile)) {
__sys_print_nt(data, len);
} else {
ordinal = __NR_write > 0 ? __NR_write : IsXnu() ? 0x2000004 : 4;
asm volatile("syscall"
: "=a"(ax)
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
: "rcx", "r11", "memory", "cc");
if (ax == -1 && !__hostos && !__NR_write) {
asm volatile("syscall"
: "=a"(ax)
: "0"(ordinal), "D"(STDERR_FILENO), "S"(data), "d"(len)
: "rcx", "r11", "memory", "cc");
}
}
}
void __print_string(const char *s) {
size_t n = 0;
while (s[n]) ++n;
__print(s, n);
}

View file

@ -26,9 +26,10 @@
static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) { static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) {
// gaps between shadow frames aren't interesting // gaps between shadow frames aren't interesting
// the chasm from heap to stack ruins statistics // the chasm from heap to stack ruins statistics
return !((IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) || return !(
(IsArenaFrame(mm->p[i].y) && !IsArenaFrame(mm->p[i + 1].x)) ||
(IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) || (IsShadowFrame(mm->p[i].y) || IsShadowFrame(mm->p[i + 1].x)) ||
(!IsStackFrame(mm->p[i].y) && IsStackFrame(mm->p[i + 1].x))); (!IsStaticStackFrame(mm->p[i].y) && IsStaticStackFrame(mm->p[i + 1].x)));
} }
void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) { void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
@ -40,8 +41,7 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
for (i = 0; i < mm->i; ++i) { for (i = 0; i < mm->i; ++i) {
frames = mm->p[i].y + 1 - mm->p[i].x; frames = mm->p[i].y + 1 - mm->p[i].x;
maptally += frames; maptally += frames;
__printf("%0*x-%0*x %s %,*dx%s", 12, ADDR(mm->p[i].x), 12, __printf("%012x-%012x %s %,*dx%s", ADDR(mm->p[i].x), ADDR(mm->p[i].y + 1),
ADDR(mm->p[i].y + 1),
DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames, DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames,
DescribeFrame(mm->p[i].x)); DescribeFrame(mm->p[i].x));
if (i + 1 < _mmi.i) { if (i + 1 < _mmi.i) {

View file

@ -33,6 +33,7 @@
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
#include "libc/sysv/consts/auxv.h" #include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/consts/prot.h"
#define SIZE 1024 #define SIZE 1024
#define CTL_KERN 1 #define CTL_KERN 1

View file

@ -13,6 +13,7 @@ extern const int __argc; /* CRT */
extern char **const __argv; /* CRT */ extern char **const __argv; /* CRT */
extern char **const __envp; /* CRT */ extern char **const __envp; /* CRT */
extern unsigned long *const __auxv; /* CRT */ extern unsigned long *const __auxv; /* CRT */
extern intptr_t __oldstack; /* CRT */
extern char program_executable_name[]; /* RII */ extern char program_executable_name[]; /* RII */
extern char *program_invocation_name; /* RII */ extern char *program_invocation_name; /* RII */
extern char *program_invocation_short_name; /* RII */ extern char *program_invocation_short_name; /* RII */
@ -86,8 +87,6 @@ bool _isheap(void *);
int NtGetVersion(void) pureconst; int NtGetVersion(void) pureconst;
long missingno(); long missingno();
void __oom_hook(size_t); void __oom_hook(size_t);
void __print(const void *, size_t);
void __print_string(const char *);
void _loadxmm(void *); void _loadxmm(void *);
void _peekall(void); void _peekall(void);
void _savexmm(void *); void _savexmm(void *);

View file

@ -2,6 +2,7 @@
#define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_ #define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_
#include "ape/config.h" #include "ape/config.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/runtime/runtime.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
/** /**
@ -65,11 +66,15 @@ extern char ape_stack_memsz[] __attribute__((__weak__));
*/ */
#define GetStaticStackAddr(ADDEND) \ #define GetStaticStackAddr(ADDEND) \
({ \ ({ \
intptr_t vAddr = 0; \ intptr_t vAddr; \
if (!IsWindows() || NtGetVersion() >= kNtVersionWindows10) { \
asm(".weak\tape_stack_vaddr\n\t" \ asm(".weak\tape_stack_vaddr\n\t" \
"movabs\t%1+ape_stack_vaddr,%0" \ "movabs\t%1+ape_stack_vaddr,%0" \
: "=r"(vAddr) \ : "=r"(vAddr) \
: "i"(ADDEND)); \ : "i"(ADDEND)); \
} else { \
vAddr = 0x10000000; \
} \
vAddr; \ vAddr; \
}) })

View file

@ -98,6 +98,7 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
extern char os asm("__hostos"); extern char os asm("__hostos");
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */ os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
version = NtGetPeb()->OSMajorVersion; version = NtGetPeb()->OSMajorVersion;
__oldstack = (intptr_t)__builtin_frame_address(0);
if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) { if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) {
SetConsoleCP(kNtCpUtf8); SetConsoleCP(kNtCpUtf8);
SetConsoleOutputCP(kNtCpUtf8); SetConsoleOutputCP(kNtCpUtf8);
@ -114,9 +115,9 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
kNtEnableVirtualTerminalProcessing); kNtEnableVirtualTerminalProcessing);
} }
_mmi.p = _mmi.s; _mmi.p = _mmi.s;
_mmi.n = OPEN_MAX; _mmi.n = ARRAYLEN(_mmi.s);
argsize = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE); argsize = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE);
stackaddr = version < 10 ? 0x10000000 : GetStaticStackAddr(0); stackaddr = GetStaticStackAddr(0);
stacksize = GetStackSize(); stacksize = GetStackSize();
allocsize = argsize + stacksize; allocsize = argsize + stacksize;
allocaddr = stackaddr - argsize; allocaddr = stackaddr - argsize;

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,40 +16,35 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/bits/bits.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/str/str.h"
// Compares strings w/ limit & no-clobber greg abi. #define TRIES 8
//
// @param %rdi is first string /**
// @param %rsi is second string * Returns offset of binary embedded inside binary.
// @param %rdx is max length *
// @return <0, 0, or >0 depending on comparison * This can be used to load zip assets from an executable that hasn't
// @clob flags only * gone through the `objcopy -S -O binary` step. We make the assumption
// @asyncsignalsafe * that an x86_64-pc-linux-gnu toolchain is being used. This routine
tinystrncmp: * would need to be changed to accommodate binaries built locally on
.leafprologue * Apple, FreeBSD, etc.
push %rbx *
push %rcx * @param p needs to be page aligned
xor %eax,%eax * @param n is byte length of p
xor %ebx,%ebx * @return base address of image or NULL if not found
xor %ecx,%ecx */
test %edx,%edx uint8_t *FindEmbeddedApe(const uint8_t *p, size_t n) {
jz 2f size_t i;
cmp %rdi,%rsi uint64_t w;
je 2f n = MIN(n, TRIES * PAGESIZE);
0: cmp %edx,%ecx for (i = 0; i + 8 <= n; i += PAGESIZE) {
jae 1f w = READ64LE(p + i);
movzbl (%rdi,%rcx,1),%eax if (w == READ64LE("MZqFpD='") || w == READ64LE("\177ELF\2\1\1\11")) {
movzbl (%rsi,%rcx,1),%ebx return (/*unconst*/ uint8_t *)(p + i);
test %al,%al }
jz 1f }
cmp %bl,%al return 0;
jne 1f }
inc %ecx
jmp 0b
1: sub %ebx,%eax
2: pop %rcx
pop %rbx
.leafepilogue
.endfn tinystrncmp,globl
.source __FILE__

View file

@ -6,6 +6,8 @@ COSMOPOLITAN_C_START_
unsigned getutf16(const char16_t *, wint_t *); unsigned getutf16(const char16_t *, wint_t *);
int pututf16(char16_t *, size_t, wint_t, bool); int pututf16(char16_t *, size_t, wint_t, bool);
#if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define pututf16(BUF, SIZE, CH, AWESOME) __pututf16(BUF, SIZE, CH, AWESOME) #define pututf16(BUF, SIZE, CH, AWESOME) __pututf16(BUF, SIZE, CH, AWESOME)
#define getutf16(BUF, CHPTR) __getutf16(BUF, CHPTR) #define getutf16(BUF, CHPTR) __getutf16(BUF, CHPTR)
@ -42,6 +44,8 @@ forceinline unsigned __getutf16(const char16_t *s, wint_t *wc) {
return ax; return ax;
} }
#endif
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_STR_OLDUTF16_H_ */ #endif /* COSMOPOLITAN_LIBC_STR_OLDUTF16_H_ */

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,29 +16,28 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/dce.h"
#include "libc/log/color.internal.h" #include "libc/intrin/asan.internal.h"
#include "libc/log/internal.h" #include "libc/str/str.h"
#include "libc/stdio/stdio.h"
asm(".section .privileged,\"ax\",@progbits\n__syscall:\n\t" typedef char16_t xmm_t __attribute__((__vector_size__(16), __aligned__(16)));
"syscall\n\t"
"ret\n\t"
".previous");
/** /**
* Prints initial part of fatal message. * Returns length of NUL-terminated utf-16 string.
* *
* @note this is support code for __check_fail(), __assert_fail(), etc. * @param s is non-null NUL-terminated string pointer
* @see __start_fatal() * @return number of shorts (excluding NUL)
* @asyncsignalsafe
*/ */
relegated void __start_fatal_ndebug(void) { noasan size_t strlen16(const char16_t *s) {
char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s; size_t n;
__restore_tty(1); xmm_t v, z = {0};
*p++ = '\r'; unsigned m, k = (uintptr_t)s & 15;
if (cancolor()) p = stpcpy(p, "\e[J"); const xmm_t *p = (const xmm_t *)((uintptr_t)s & -16);
p = stpcpy(p, "error:"); if (IsAsan()) __asan_verify(s, 2);
p = stpcpy(p, program_invocation_name); m = __builtin_ia32_pmovmskb128(*p == z) >> k << k;
p = stpcpy(p, ": "); while (!m) m = __builtin_ia32_pmovmskb128(*++p == z);
write(2, s, p - s); n = (const char16_t *)p + (__builtin_ctzl(m) >> 1) - s;
if (IsAsan()) __asan_verify(s, n * 2);
return n;
} }

View file

@ -1,7 +1,7 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,24 +16,22 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/assert.h"
#include "libc/str/str.h"
// 16-bit strnlen that's tiny and near optimal if data's tiny. /**
// * Returns length of NUL-terminated 16-bit string w/ limit.
// @param RDI is char16_t *s *
// @param RSI is size_t n * @param s is utf16 string pointer
// @param EAX is unsigned length * @param n is max length in shorts
// @see libc/nexgen32e/strsak16.S * @return number of shorts
tinystrnlen16: * @asyncsignalsafe
.leafprologue */
.profilable noasan size_t strnlen16(const char16_t *s, size_t n) {
xor %eax,%eax size_t i;
1: cmp %esi,%eax for (i = 0;; ++i) {
jae 2f if (i == n || !s[i]) break;
cmpw $0,(%rdi,%rax,2) }
jz 2f assert(i == n || (i < n && !s[i]));
inc %eax return i;
jmp 1b }
2: .leafepilogue
.endfn tinystrnlen16,globl
.source __FILE__

View file

@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_
int tpdecode(const char *, wint_t *) paramsnonnull((1)) libcesque; int tpdecode(const char *, wint_t *) paramsnonnull((1)) libcesque;
#ifndef __STRICT_ANSI__ #if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define tpdecode(S, OUT) __tpdecode(S, OUT) #define tpdecode(S, OUT) __tpdecode(S, OUT)
forceinline int __tpdecode(const char *s, wint_t *out) { forceinline int __tpdecode(const char *s, wint_t *out) {
int ax; int ax;

View file

@ -5,7 +5,7 @@ COSMOPOLITAN_C_START_
uint64_t tpenc(int32_t) pureconst; uint64_t tpenc(int32_t) pureconst;
#ifndef __STRICT_ANSI__ #if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define tpenc(CODE) \ #define tpenc(CODE) \
({ \ ({ \
long Edi, Buf; \ long Edi, Buf; \

View file

@ -153,7 +153,7 @@ intptr_t enotrecoverable(void) relegated;
intptr_t erfkill(void) relegated; intptr_t erfkill(void) relegated;
intptr_t ehwpoison(void) relegated; intptr_t ehwpoison(void) relegated;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) #if defined(__MNO_RED_ZONE__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
#define __ERRFUN(FUNC) \ #define __ERRFUN(FUNC) \
({ \ ({ \
intptr_t NegOne; \ intptr_t NegOne; \

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
.source __FILE__ .privileged
// Performs raw System Five system call. // Performs raw System Five system call.
// //

View file

@ -18,6 +18,7 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/kntprioritycombos.internal.h" #include "libc/calls/kntprioritycombos.internal.h"
#include "libc/errno.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/nexgen32e/x86feature.h" #include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -51,9 +52,12 @@ void testlib_benchwarmup(void) {
* @see BENCH() * @see BENCH()
*/ */
void testlib_runallbenchmarks(void) { void testlib_runallbenchmarks(void) {
int e;
e = errno;
_peekall(); _peekall();
mlockall(MCL_CURRENT); mlockall(MCL_CURRENT);
nice(-1); nice(-1);
errno = e;
__log_level = kLogWarn; __log_level = kLogWarn;
testlib_runtestcases(__bench_start, __bench_end, testlib_benchwarmup); testlib_runtestcases(__bench_start, __bench_end, testlib_benchwarmup);
} }

View file

@ -71,7 +71,7 @@ noasan void testlib_checkformemoryleaks(void) {
struct mallinfo mi; struct mallinfo mi;
if (!cmpxchg(&once, false, true)) { if (!cmpxchg(&once, false, true)) {
__printf("testlib_checkformemoryleaks() may only be called once\n"); __printf("testlib_checkformemoryleaks() may only be called once\n");
_Exit(1); exit(1);
} }
__cxa_finalize(0); __cxa_finalize(0);
if (!IsAsan()) { if (!IsAsan()) {

View file

@ -47,7 +47,7 @@ static relegated void DieBecauseOfQuota(int rc, const char *message) {
gethostname(hostname, sizeof(hostname)); gethostname(hostname, sizeof(hostname));
__printf("%s on %s pid %d\n", message, hostname, (long)__getpid()); __printf("%s on %s pid %d\n", message, hostname, (long)__getpid());
PrintBacktraceUsingSymbols(2, 0, GetSymbolTable()); PrintBacktraceUsingSymbols(2, 0, GetSymbolTable());
_Exit(rc); exit(rc);
} }
static relegated void OnXcpu(int sig) { static relegated void OnXcpu(int sig) {
@ -89,7 +89,7 @@ relegated void __oom_hook(size_t request) {
__printf("\nTHE STRAW THAT BROKE THE CAMEL'S BACK\n"); __printf("\nTHE STRAW THAT BROKE THE CAMEL'S BACK\n");
PrintBacktraceUsingSymbols(2, 0, GetSymbolTable()); PrintBacktraceUsingSymbols(2, 0, GetSymbolTable());
PrintSystemMappings(2); PrintSystemMappings(2);
_Exit(42); exit(42);
} }
static textstartup void InstallQuotaHandlers(void) { static textstartup void InstallQuotaHandlers(void) {

View file

@ -37,18 +37,15 @@ testonly void testlib_showerror(const char *file, int line, const char *func,
/* TODO(jart): Pay off tech debt re duplication */ /* TODO(jart): Pay off tech debt re duplication */
__getpid(); /* make strace easier to read */ __getpid(); /* make strace easier to read */
__getpid(); __getpid();
__printf("%serror%s:%s:%d%s: %s() in %s(%s)\n" __printf("%serror%s%s:%s:%d%s: %s() in %s(%s)\n"
"\t%s\n" "\t%s\n"
"\t\tneed %s %s\n" "\t\tneed %s %s\n"
"\t\t got %s\n" "\t\t got %s\n"
"\t%s%s\n" "\t%s%s\n"
"\t%s%s\n", "\t%s%s\n",
!g_isterminalinarticulate ? "\e[91;1m" : "", RED2, UNBOLD, BLUE1, file, (long)line, RESET, method, func,
!g_isterminalinarticulate ? "\e[22;94;49m" : "", file, (long)line, g_fixturename, code, v1, symbol, v2, SUBTLE, strerror(errno),
!g_isterminalinarticulate ? "\e[0m" : "", method, func, program_executable_name, RESET);
g_fixturename, code, v1, symbol, v2,
!g_isterminalinarticulate ? "\e[35m" : "", strerror(errno),
program_executable_name, !g_isterminalinarticulate ? "\e[0m" : "");
free_s(&v1); free_s(&v1);
free_s(&v2); free_s(&v2);
} }
@ -58,67 +55,36 @@ testonly void testlib_showerror_(int line, const char *wantcode,
const char *gotcode, char *FREED_want, const char *gotcode, char *FREED_want,
char *FREED_got, const char *fmt, ...) { char *FREED_got, const char *fmt, ...) {
int e; int e;
char *p;
va_list va; va_list va;
char hostname[32]; char hostname[32];
__getpid();
__getpid();
p = __fatalbuf;
e = errno; e = errno;
p = __stpcpy(p, RED2); __getpid();
p = __stpcpy(p, "error"); __getpid();
p = __stpcpy(p, UNBOLD); __printf("%serror%s:%s%s:%d%s: %s(%s)\n"
p = __stpcpy(p, ":"); "\t%s(%s, %s)\n",
p = __stpcpy(p, BLUE1); RED2, UNBOLD, BLUE1, testlib_showerror_file, line, RESET,
p = __stpcpy(p, testlib_showerror_file); testlib_showerror_func, g_fixturename, testlib_showerror_macro,
p = __stpcpy(p, ":"); wantcode, gotcode);
p = __intcpy(p, line);
p = __stpcpy(p, RESET);
p = __stpcpy(p, ": ");
p = __stpcpy(p, testlib_showerror_func);
p = __stpcpy(p, "(");
p = __stpcpy(p, g_fixturename);
p = __stpcpy(p, ")\n\t");
p = __stpcpy(p, testlib_showerror_macro);
p = __stpcpy(p, "(");
p = __stpcpy(p, wantcode);
p = __stpcpy(p, ", ");
p = __stpcpy(p, gotcode);
if (wantcode) { if (wantcode) {
p = __stpcpy(p, ")\n\t\tneed "); __printf("\t\tneed %s %s\n"
p = __stpcpy(p, FREED_want); "\t\t got %s\n",
p = __stpcpy(p, " "); FREED_want, testlib_showerror_symbol, FREED_got);
p = __stpcpy(p, testlib_showerror_symbol);
p = __stpcpy(p, "\n\t\t got ");
p = __stpcpy(p, FREED_got);
p = __stpcpy(p, "\n");
} else { } else {
p = __stpcpy(p, ")\n\t\t"); __printf("\t\t→ %s%s\n", testlib_showerror_symbol, FREED_want);
p = __stpcpy(p, testlib_showerror_symbol);
p = __stpcpy(p, FREED_want);
p = __stpcpy(p, "\n");
} }
if (!isempty(fmt)) { if (!isempty(fmt)) {
*p++ = '\t'; __printf("\t");
va_start(va, fmt); va_start(va, fmt);
p += vsprintf(p, fmt, va); __vprintf(fmt, va);
va_end(va); va_end(va);
*p++ = '\n'; __printf("\n");
} }
__stpcpy(hostname, "unknown"); __stpcpy(hostname, "unknown");
gethostname(hostname, sizeof(hostname)); gethostname(hostname, sizeof(hostname));
p = __stpcpy(p, "\t"); __printf("\t%s%s%s\n"
p = __stpcpy(p, SUBTLE); "\t%s%s @ %s%s\n",
p = __stpcpy(p, strerror(e)); SUBTLE, strerror(e), RESET, SUBTLE, program_invocation_name,
p = __stpcpy(p, RESET); hostname, RESET);
p = __stpcpy(p, "\n\t");
p = __stpcpy(p, SUBTLE);
p = __stpcpy(p, program_invocation_name);
p = __stpcpy(p, " @ ");
p = __stpcpy(p, hostname);
p = __stpcpy(p, RESET);
p = __stpcpy(p, "\n");
__write(__fatalbuf, p - __fatalbuf);
free_s(&FREED_want); free_s(&FREED_want);
free_s(&FREED_got); free_s(&FREED_got);
++g_testlib_failed; ++g_testlib_failed;

View file

@ -103,5 +103,5 @@ noasan int main(int argc, char *argv[]) {
} else if (!g_testlib_failed) { } else if (!g_testlib_failed) {
testlib_checkformemoryleaks(); testlib_checkformemoryleaks();
} }
_Exit(min(255, g_testlib_failed)); exit(min(255, g_testlib_failed));
} }

View file

@ -31,8 +31,9 @@
* @see mkdir() * @see mkdir()
*/ */
int makedirs(const char *path, unsigned mode) { int makedirs(const char *path, unsigned mode) {
int rc; int e, rc;
char *dir; char *dir;
e = errno;
if (mkdir(path, mode) != -1) return 0; if (mkdir(path, mode) != -1) return 0;
if (errno != ENOENT) return -1; if (errno != ENOENT) return -1;
dir = xdirname(path); dir = xdirname(path);
@ -43,5 +44,6 @@ int makedirs(const char *path, unsigned mode) {
} }
free(dir); free(dir);
if (rc == -1) return -1; if (rc == -1) return -1;
errno = e;
return mkdir(path, mode); return mkdir(path, mode);
} }

View file

@ -16,10 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/intrin/pcmpgtb.h"
#include "libc/intrin/pmovmskb.h"
#include "libc/intrin/punpckhbw.h"
#include "libc/intrin/punpcklbw.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/thompike.h" #include "libc/str/thompike.h"
@ -38,25 +34,30 @@ char16_t *utf8toutf16(const char *p, size_t n, size_t *z) {
wint_t x, a, b; wint_t x, a, b;
char16_t *r, *q; char16_t *r, *q;
unsigned m, j, w; unsigned m, j, w;
uint8_t v1[16], v2[16], vz[16];
if (z) *z = 0; if (z) *z = 0;
if (n == -1) n = p ? strlen(p) : 0; if (n == -1) n = p ? strlen(p) : 0;
if ((q = r = malloc(n * sizeof(char16_t) * 2 + sizeof(char16_t)))) { if ((q = r = malloc((n + 16) * sizeof(char16_t) * 2 + sizeof(char16_t)))) {
for (i = 0; i < n;) { for (i = 0; i < n;) {
if (i + 16 < n) { /* 34x ascii */ #if defined(__SSE2__) && defined(__GNUC__) && !defined(__STRICT_ANSI__)
bzero(vz, 16); if (i + 16 < n) {
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
xmm_t vi, vz = {0};
do { do {
memcpy(v1, p + i, 16); vi = *(const xmm_t *)(p + i);
pcmpgtb((int8_t *)v2, (int8_t *)v1, (int8_t *)vz); *(xmm_t *)(q + 0) = __builtin_ia32_punpcklbw128(vi, vz);
if (pmovmskb(v2) != 0xFFFF) break; *(xmm_t *)(q + 8) = __builtin_ia32_punpckhbw128(vi, vz);
punpcklbw(v2, v1, vz); if (!(m = __builtin_ia32_pmovmskb128(vi > vz) ^ 0xffff)) {
punpckhbw(v1, v1, vz);
memcpy(q + 0, v2, 16);
memcpy(q + 8, v1, 16);
i += 16; i += 16;
q += 16; q += 16;
} else {
m = __builtin_ctzl(m);
i += m;
q += m;
break;
}
} while (i + 16 < n); } while (i + 16 < n);
} }
#endif
x = p[i++] & 0xff; x = p[i++] & 0xff;
if (x >= 0300) { if (x >= 0300) {
a = ThomPikeByte(x); a = ThomPikeByte(x);

View file

@ -186,6 +186,7 @@
#define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize) #define ZIP_EXTRA_SIZE(P) (ZIP_EXTRA_CONTENTSIZE(P) + kZipExtraHdrSize)
void *GetZipCdir(const uint8_t *, size_t); void *GetZipCdir(const uint8_t *, size_t);
uint8_t *FindEmbeddedApe(const uint8_t *, size_t);
bool IsZipCdir32(const uint8_t *, size_t, size_t); bool IsZipCdir32(const uint8_t *, size_t, size_t);
bool IsZipCdir64(const uint8_t *, size_t, size_t); bool IsZipCdir64(const uint8_t *, size_t, size_t);
int GetZipCfileMode(const uint8_t *); int GetZipCfileMode(const uint8_t *);

View file

@ -22,6 +22,7 @@
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/alloca.h" #include "libc/mem/alloca.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -72,15 +73,11 @@ struct Zipos *__zipos_get(void) {
if ((fd = open(program_executable_name, O_RDONLY)) != -1) { if ((fd = open(program_executable_name, O_RDONLY)) != -1) {
if ((size = getfiledescriptorsize(fd)) != SIZE_MAX && if ((size = getfiledescriptorsize(fd)) != SIZE_MAX &&
(map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { (map = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) {
if (endswith(program_executable_name, ".com.dbg")) { if ((base = FindEmbeddedApe(map, size))) {
if ((base = memmem(map, size, "MZqFpD", 6))) {
size -= base - map; size -= base - map;
} else { } else {
base = map; base = map;
} }
} else {
base = map;
}
if ((cdir = GetZipCdir(base, size))) { if ((cdir = GetZipCdir(base, size))) {
__zipos_munmap_unneeded(base, cdir, map); __zipos_munmap_unneeded(base, cdir, map);
zipos.map = base; zipos.map = base;

View file

@ -21,8 +21,8 @@
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
TEST(getenv, test) { TEST(getenv, test) {
putenv("x=y"); putenv("X=y");
EXPECT_STREQ("y", getenv("x")); EXPECT_STREQ("y", getenv("X"));
unsetenv("x"); unsetenv("X");
EXPECT_EQ(NULL, getenv("x")); EXPECT_EQ(NULL, getenv("X"));
} }

View file

@ -31,10 +31,10 @@ TEST(mkntenvblock, emptyList_onlyOutputsDoubleNulStringTerminator) {
TEST(mkntenvblock, envp_becomesSortedDoubleNulTerminatedUtf16String) { TEST(mkntenvblock, envp_becomesSortedDoubleNulTerminatedUtf16String) {
char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL}; char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL};
ASSERT_NE(-1, mkntenvblock(envvars, envp, NULL)); ASSERT_NE(-1, mkntenvblock(envvars, envp, NULL));
ASSERT_BINEQ(u"c = d   " ASSERT_BINEQ(u"C = d   "
u"h d u c = d   " u"H D U C = d   "
u"u = b   " u"U = b   "
u"u h = d   " u"U H = d   "
u"Θù= ^ù  " u"Θù= ^ù  "
u"  ", u"  ",
envvars); envvars);
@ -43,11 +43,11 @@ TEST(mkntenvblock, envp_becomesSortedDoubleNulTerminatedUtf16String) {
TEST(mkntenvblock, extraVar_getsAdded) { TEST(mkntenvblock, extraVar_getsAdded) {
char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL}; char *envp[] = {"u=b", "c=d", "韩=非", "uh=d", "hduc=d", NULL};
ASSERT_NE(-1, mkntenvblock(envvars, envp, "a=a")); ASSERT_NE(-1, mkntenvblock(envvars, envp, "a=a"));
ASSERT_BINEQ(u"a = a   " ASSERT_BINEQ(u"A = a   "
u"c = d   " u"C = d   "
u"h d u c = d   " u"H D U C = d   "
u"u = b   " u"U = b   "
u"u h = d   " u"U H = d   "
u"Θù= ^ù  " u"Θù= ^ù  "
u"  ", u"  ",
envvars); envvars);

View file

@ -18,14 +18,19 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/runtime/gc.internal.h" #include "libc/runtime/gc.internal.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/nr.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
#include "libc/x/x.h" #include "libc/x/x.h"
STATIC_YOINK("zip_uri_support");
char testlib_enable_tmp_setup_teardown; char testlib_enable_tmp_setup_teardown;
TEST(stat_010, testEmptyFile_sizeIsZero) { TEST(stat_010, testEmptyFile_sizeIsZero) {
@ -44,3 +49,43 @@ TEST(stat, enotdir) {
ASSERT_SYS(0, 0, close(creat("yo", 0644))); ASSERT_SYS(0, 0, close(creat("yo", 0644)));
ASSERT_SYS(ENOTDIR, -1, stat("yo/there", 0)); ASSERT_SYS(ENOTDIR, -1, stat("yo/there", 0));
} }
TEST(stat, zipos) {
struct stat st;
EXPECT_SYS(0, 0,
stat("/zip/.python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
&st));
}
static long Stat(const char *path, struct stat *st) {
long ax, di, si, dx;
asm volatile("syscall"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"(__NR_stat), "1"(path), "2"(st)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
BENCH(stat, bench) {
struct stat st;
EXPECT_SYS(0, 0, makedirs(".python/test", 0755));
EXPECT_SYS(0, 0,
touch(".python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
0644));
if (!IsWindows()) {
EZBENCH2("stat syscall", donothing,
Stat(".python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
&st));
}
EZBENCH2("stat() fs", donothing,
stat(".python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
&st));
EZBENCH2("stat() zipos", donothing,
stat("/zip/.python/test/"
"tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt",
&st));
}

View file

@ -44,6 +44,7 @@ TEST_LIBC_CALLS_DIRECTDEPS = \
LIBC_TESTLIB \ LIBC_TESTLIB \
LIBC_UNICODE \ LIBC_UNICODE \
LIBC_X \ LIBC_X \
LIBC_ZIPOS \
THIRD_PARTY_XED THIRD_PARTY_XED
TEST_LIBC_CALLS_DEPS := \ TEST_LIBC_CALLS_DEPS := \
@ -56,6 +57,7 @@ o/$(MODE)/test/libc/calls/calls.pkg: \
o/$(MODE)/test/libc/calls/%.com.dbg: \ o/$(MODE)/test/libc/calls/%.com.dbg: \
$(TEST_LIBC_CALLS_DEPS) \ $(TEST_LIBC_CALLS_DEPS) \
o/$(MODE)/test/libc/calls/%.o \ o/$(MODE)/test/libc/calls/%.o \
o/$(MODE)/third_party/python/Lib/test/tokenize_tests-latin1-coding-cookie-and-utf8-bom-sig.txt.zip.o \
o/$(MODE)/test/libc/calls/calls.pkg \ o/$(MODE)/test/libc/calls/calls.pkg \
$(LIBC_TESTMAIN) \ $(LIBC_TESTMAIN) \
$(CRT) \ $(CRT) \

View file

@ -0,0 +1,46 @@
/*-*- 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/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/iovec.h"
#include "libc/sock/internal.h"
#include "libc/sysv/consts/nr.h"
#include "libc/sysv/consts/o.h"
#include "libc/testlib/ezbench.h"
#include "libc/testlib/testlib.h"
static long Write(long fd, const void *data, unsigned long size) {
long ax, di, si, dx;
asm volatile("syscall"
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
: "0"(__NR_write), "1"(fd), "2"(data), "3"(size)
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
return ax;
}
BENCH(write, bench) {
ASSERT_SYS(0, 3, open("/dev/null", O_WRONLY));
EZBENCH2("write", donothing, write(3, "hello", 5));
EZBENCH2("sys_write", donothing, sys_write(3, "hello", 5));
EZBENCH2("sys_writev", donothing,
sys_writev(3, &(struct iovec){"hello", 5}, 1));
EZBENCH2("Write", donothing, Write(3, "hello", 5));
EZBENCH2("Write", donothing, Write(3, "hello", 5));
ASSERT_SYS(0, 0, close(3));
}

View file

@ -373,11 +373,13 @@ TEST(ShowCrashReports, testDivideByZero) {
EXPECT_TRUE(WIFEXITED(ws)); EXPECT_TRUE(WIFEXITED(ws));
EXPECT_EQ(128 + SIGFPE, WEXITSTATUS(ws)); EXPECT_EQ(128 + SIGFPE, WEXITSTATUS(ws));
/* NULL is stopgap until we can copy symbol tablces into binary */ /* NULL is stopgap until we can copy symbol tablces into binary */
#ifdef __FNO_OMIT_FRAME_POINTER__
if (!OutputHasSymbol(output, "FpuCrash")) { if (!OutputHasSymbol(output, "FpuCrash")) {
fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
__die(); __die();
} }
#endif
if (!strstr(output, gc(xasprintf("%d", pid)))) { if (!strstr(output, gc(xasprintf("%d", pid)))) {
fprintf(stderr, "ERROR: crash report didn't have pid\n%s\n", fprintf(stderr, "ERROR: crash report didn't have pid\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
@ -472,11 +474,13 @@ TEST(ShowCrashReports, testBssOverrunCrash) {
EXPECT_TRUE(WIFEXITED(ws)); EXPECT_TRUE(WIFEXITED(ws));
EXPECT_EQ(77, WEXITSTATUS(ws)); EXPECT_EQ(77, WEXITSTATUS(ws));
/* NULL is stopgap until we can copy symbol tablces into binary */ /* NULL is stopgap until we can copy symbol tablces into binary */
#ifdef __FNO_OMIT_FRAME_POINTER__
if (!OutputHasSymbol(output, "BssOverrunCrash")) { if (!OutputHasSymbol(output, "BssOverrunCrash")) {
fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
__die(); __die();
} }
#endif
if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) { if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) {
fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n", fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
@ -552,11 +556,13 @@ TEST(ShowCrashReports, testNpeCrash) {
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
__die(); __die();
} }
#ifdef __FNO_OMIT_FRAME_POINTER__
if (!OutputHasSymbol(output, "NpeCrash")) { if (!OutputHasSymbol(output, "NpeCrash")) {
fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
__die(); __die();
} }
#endif
if (!strstr(output, "∅∅∅∅")) { if (!strstr(output, "∅∅∅∅")) {
fprintf(stderr, "ERROR: crash report didn't have shadow diagram\n%s\n", fprintf(stderr, "ERROR: crash report didn't have shadow diagram\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
@ -599,11 +605,13 @@ TEST(ShowCrashReports, testDataOverrunCrash) {
EXPECT_TRUE(WIFEXITED(ws)); EXPECT_TRUE(WIFEXITED(ws));
EXPECT_EQ(77, WEXITSTATUS(ws)); EXPECT_EQ(77, WEXITSTATUS(ws));
/* NULL is stopgap until we can copy symbol tablces into binary */ /* NULL is stopgap until we can copy symbol tablces into binary */
#ifdef __FNO_OMIT_FRAME_POINTER__
if (!OutputHasSymbol(output, "DataOverrunCrash")) { if (!OutputHasSymbol(output, "DataOverrunCrash")) {
fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n", fprintf(stderr, "ERROR: crash report didn't have backtrace\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));
__die(); __die();
} }
#endif
if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) { if (!strstr(output, "☺☻♥♦♣♠•◘○") || !strstr(output, "global redzone")) {
fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n", fprintf(stderr, "ERROR: crash report didn't have memory diagram\n%s\n",
gc(IndentLines(output, -1, 0, 4))); gc(IndentLines(output, -1, 0, 4)));

View file

@ -4,7 +4,7 @@ if [ "$MODE" = dbg ]; then
exit # TODO exit # TODO
fi fi
if [ "$MODE" = opt ]; then if [ "$MODE" = opt ] || [ "$MODE" = optlinux ]; then
exit exit
fi fi

View file

@ -6,8 +6,7 @@ exit
if [ "$MODE" = dbg ]; then if [ "$MODE" = dbg ]; then
exit # TODO exit # TODO
fi fi
if [ "$MODE" = opt ] || [ "$MODE" = optlinux ]; then
if [ "$MODE" = opt ]; then
exit exit
fi fi

View file

@ -22,7 +22,7 @@
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
TEST(GetDosEnviron, testOneVariable) { TEST(GetDosEnviron, testOneVariable) {
#define kEnv u"A=Und wird die Welt auch in Flammen stehen\0" #define kEnv u"a=Und wird die Welt auch in Flammen stehen\0"
size_t max = 2; size_t max = 2;
size_t size = sizeof(kEnv) >> 1; size_t size = sizeof(kEnv) >> 1;
char *block = calloc(1, size); char *block = calloc(1, size);

View file

@ -96,6 +96,7 @@ TEST(TrackMemoryInterval, TestEmpty) {
} }
TEST(TrackMemoryInterval, TestFull) { TEST(TrackMemoryInterval, TestFull) {
#if 0 // TODO(jart): Find way to re-enable
int i; int i;
struct MemoryIntervals *mm; struct MemoryIntervals *mm;
mm = calloc(1, sizeof(struct MemoryIntervals)); mm = calloc(1, sizeof(struct MemoryIntervals));
@ -108,6 +109,7 @@ TEST(TrackMemoryInterval, TestFull) {
CHECK_EQ(ENOMEM, errno); CHECK_EQ(ENOMEM, errno);
CheckMemoryIntervalsAreOk(mm); CheckMemoryIntervalsAreOk(mm);
free(mm); free(mm);
#endif
} }
TEST(TrackMemoryInterval, TestAppend) { TEST(TrackMemoryInterval, TestAppend) {

View file

@ -20,7 +20,6 @@
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h" #include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/tinystrlen.internal.h"
#include "libc/rand/rand.h" #include "libc/rand/rand.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -112,40 +111,6 @@ TEST(strnlen_s, nulNotFound_ReturnsZero) {
ASSERT_EQ(0, strnlen_s(buf, 3)); ASSERT_EQ(0, strnlen_s(buf, 3));
} }
TEST(tinystrlen, test) {
ASSERT_EQ(0, tinystrlen(""));
ASSERT_EQ(1, tinystrlen("a"));
ASSERT_EQ(3, tinystrlen("123"));
}
TEST(tinywcslen, test) {
ASSERT_EQ(0, tinywcslen(L""));
ASSERT_EQ(1, tinywcslen(L"a"));
ASSERT_EQ(3, tinywcslen(L"123"));
}
TEST(tinywcsnlen, test) {
EXPECT_EQ(0, tinywcsnlen(L"", 3));
EXPECT_EQ(0, tinywcsnlen(L"a", 0));
EXPECT_EQ(3, tinywcsnlen(L"123", 3));
EXPECT_EQ(2, tinywcsnlen(L"123", 2));
EXPECT_EQ(3, tinywcsnlen(L"123", 4));
}
TEST(tinystrlen16, test) {
ASSERT_EQ(0, tinystrlen16(u""));
ASSERT_EQ(1, tinystrlen16(u"a"));
ASSERT_EQ(3, tinystrlen16(u"123"));
}
TEST(tinystrnlen16, test) {
EXPECT_EQ(0, tinystrnlen16(u"", 3));
EXPECT_EQ(0, tinystrnlen16(u"a", 0));
EXPECT_EQ(3, tinystrnlen16(u"123", 3));
EXPECT_EQ(2, tinystrnlen16(u"123", 2));
EXPECT_EQ(3, tinystrnlen16(u"123", 4));
}
TEST(strlen, fuzz) { TEST(strlen, fuzz) {
char *b; char *b;
size_t n, n1, n2; size_t n, n1, n2;

View file

@ -26,6 +26,7 @@ TEST_LIBC_XED_TESTLIB_A_OBJS = \
TEST_LIBC_XED_TESTLIB_A_DIRECTDEPS = \ TEST_LIBC_XED_TESTLIB_A_DIRECTDEPS = \
LIBC_INTRIN \ LIBC_INTRIN \
LIBC_STR \
LIBC_MEM \ LIBC_MEM \
LIBC_NEXGEN32E \ LIBC_NEXGEN32E \
LIBC_RUNTIME \ LIBC_RUNTIME \

View file

@ -36,6 +36,7 @@
# endif # endif
#endif #endif
#include "libc/str/str.h"
#include "third_party/infozip/zip/unix/osdep.h" #include "third_party/infozip/zip/unix/osdep.h"
@ -133,8 +134,8 @@
* to_up is used to force upper case even on Unix (for dosify option). * to_up is used to force upper case even on Unix (for dosify option).
*/ */
#ifdef USE_CASE_MAP #ifdef USE_CASE_MAP
# define case_map(c) upper[(c) & 0xff] # define case_map(c) kToUpper[(c) & 0xff]
# define to_up(c) upper[(c) & 0xff] # define to_up(c) kToLower[(c) & 0xff]
#else #else
# define case_map(c) (c) # define case_map(c) (c)
# define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c)) # define to_up(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))

View file

@ -597,71 +597,6 @@ int (*cmp) OF((ZCONST zvoid *, ZCONST zvoid far *)); /* comparison function */
#endif /* !UTIL */ #endif /* !UTIL */
#ifdef MSDOS16
local unsigned ident(unsigned chr)
{
return chr; /* in al */
}
void init_upper()
{
static struct country {
uch ignore[18];
int (far *casemap)(int);
uch filler[16];
} country_info;
struct country far *info = &country_info;
union REGS regs;
struct SREGS sregs;
unsigned int c;
regs.x.ax = 0x3800; /* get country info */
regs.x.dx = FP_OFF(info);
sregs.ds = FP_SEG(info);
intdosx(&regs, &regs, &sregs);
for (c = 0; c < 128; c++) {
upper[c] = (uch) toupper(c);
lower[c] = (uch) c;
}
for (; c < sizeof(upper); c++) {
upper[c] = (uch) (*country_info.casemap)(ident(c));
/* ident() required because casemap takes its parameter in al */
lower[c] = (uch) c;
}
for (c = 0; c < sizeof(upper); c++ ) {
unsigned int u = upper[c];
if (u != c && lower[u] == (uch) u) {
lower[u] = (uch)c;
}
}
for (c = 'A'; c <= 'Z'; c++) {
lower[c] = (uch) (c - 'A' + 'a');
}
}
#else /* !MSDOS16 */
# ifndef OS2
void init_upper()
{
unsigned int c;
#if defined(ATARI) || defined(CMS_MVS)
/* this should be valid for all other platforms too. (HD 11/11/95) */
for (c = 0; c< sizeof(upper); c++) {
upper[c] = islower(c) ? toupper(c) : c;
lower[c] = isupper(c) ? tolower(c) : c;
}
#else
for (c = 0; c < sizeof(upper); c++) upper[c] = lower[c] = (uch)c;
for (c = 'a'; c <= 'z'; c++) upper[c] = (uch)(c - 'a' + 'A');
for (c = 'A'; c <= 'Z'; c++) lower[c] = (uch)(c - 'A' + 'a');
#endif
}
# endif /* !OS2 */
#endif /* ?MSDOS16 */
int namecmp(string1, string2) int namecmp(string1, string2)
ZCONST char *string1, *string2; ZCONST char *string1, *string2;
/* Compare the two strings ignoring case, and correctly taking into /* Compare the two strings ignoring case, and correctly taking into

View file

@ -2489,8 +2489,6 @@ char **argv; /* command line tokens */
mesg = (FILE *) stdout; /* cannot be made at link time for VMS */ mesg = (FILE *) stdout; /* cannot be made at link time for VMS */
comment_stream = (FILE *)stdin; comment_stream = (FILE *)stdin;
init_upper(); /* build case map table */
#ifdef LARGE_FILE_SUPPORT #ifdef LARGE_FILE_SUPPORT
/* test if we can support large files - 9/29/04 */ /* test if we can support large files - 9/29/04 */
if (sizeof(zoff_t) < 8) { if (sizeof(zoff_t) < 8) {

View file

@ -388,8 +388,6 @@ int main(argc, argv)
/* Informational messages are written to stdout. */ /* Informational messages are written to stdout. */
mesg = stdout; mesg = stdout;
init_upper(); /* build case map table */
#ifndef USE_ZLIB #ifndef USE_ZLIB
crc_32_tab = get_crc_table(); crc_32_tab = get_crc_table();
/* initialize crc table for crypt */ /* initialize crc table for crypt */

View file

@ -454,8 +454,6 @@ char **argv; /* command line tokens */
/* Direct info messages to stderr; stdout is used for data output. */ /* Direct info messages to stderr; stdout is used for data output. */
mesg = stderr; mesg = stderr;
init_upper(); /* build case map table */
/* Go through args */ /* Go through args */
zipfile = tempzip = NULL; zipfile = tempzip = NULL;
tempzf = NULL; tempzf = NULL;

View file

@ -586,8 +586,6 @@ char **argv; /* command line tokens */
/* Informational messages are written to stdout. */ /* Informational messages are written to stdout. */
mesg = stdout; mesg = stdout;
init_upper(); /* build case map table */
/* Go through args */ /* Go through args */
signal(SIGINT, handler); signal(SIGINT, handler);
#ifdef SIGTERM /* Amiga has no SIGTERM */ #ifdef SIGTERM /* Amiga has no SIGTERM */

View file

@ -1655,7 +1655,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
return( 0 ); return( 0 );
} }
/* If we got here, we no longer need our cached extension */ /* If we goth here, we no longer need our cached extension */
mbedtls_free( ssl->handshake->ecjpake_cache ); mbedtls_free( ssl->handshake->ecjpake_cache );
ssl->handshake->ecjpake_cache = NULL; ssl->handshake->ecjpake_cache = NULL;
ssl->handshake->ecjpake_cache_len = 0; ssl->handshake->ecjpake_cache_len = 0;

View file

@ -839,7 +839,7 @@ class ConfigChanges(dict):
if idleConf.defaultCfg[config_type].Get(section, item) == value: if idleConf.defaultCfg[config_type].Get(section, item) == value:
# The setting equals a default setting, remove it from user cfg. # The setting equals a default setting, remove it from user cfg.
return idleConf.userCfg[config_type].RemoveOption(section, item) return idleConf.userCfg[config_type].RemoveOption(section, item)
# If we got here, set the option. # If we goth here, set the option.
return idleConf.userCfg[config_type].SetOption(section, item, value) return idleConf.userCfg[config_type].SetOption(section, item, value)
def save_all(self): def save_all(self):

View file

@ -797,7 +797,7 @@ class _BaseNetwork(_IPAddressBase):
yield s1 yield s1
s1, s2 = s2.subnets() s1, s2 = s2.subnets()
else: else:
# If we got here, there's a bug somewhere. # If we goth here, there's a bug somewhere.
raise AssertionError('Error performing exclusion: ' raise AssertionError('Error performing exclusion: '
's1: %s s2: %s other: %s' % 's1: %s s2: %s other: %s' %
(s1, s2, other)) (s1, s2, other))
@ -806,7 +806,7 @@ class _BaseNetwork(_IPAddressBase):
elif s2 == other: elif s2 == other:
yield s1 yield s1
else: else:
# If we got here, there's a bug somewhere. # If we goth here, there's a bug somewhere.
raise AssertionError('Error performing exclusion: ' raise AssertionError('Error performing exclusion: '
's1: %s s2: %s other: %s' % 's1: %s s2: %s other: %s' %
(s1, s2, other)) (s1, s2, other))

View file

@ -886,7 +886,7 @@ class SMTP:
else: else:
self._rset() self._rset()
raise SMTPDataError(code, resp) raise SMTPDataError(code, resp)
#if we got here then somebody got our mail #if we goth here then somebody got our mail
return senderrs return senderrs
def send_message(self, msg, from_addr=None, to_addrs=None, def send_message(self, msg, from_addr=None, to_addrs=None,

BIN
third_party/python/Lib/test/hello.com vendored Executable file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more