Get address sanitizer mostly working

main
Justine Tunney 2020-09-03 05:44:37 -07:00
parent 1f1f3cd477
commit 7327c345f9
149 changed files with 3777 additions and 3457 deletions

View File

@ -60,9 +60,10 @@
# #
# build/config.mk # build/config.mk
SHELL = /bin/sh SHELL = /bin/sh
HOSTS ?= freebsd openbsd alpine HOSTS ?= freebsd openbsd alpine
SANITY := $(shell build/sanitycheck $$PPID) SANITY := $(shell build/sanitycheck $$PPID)
GNUMAKEFLAGS += --output-sync
.SUFFIXES: .SUFFIXES:
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -156,7 +157,6 @@ include tool/build/lib/buildlib.mk
include tool/build/emucrt/emucrt.mk include tool/build/emucrt/emucrt.mk
include tool/build/emubin/emubin.mk include tool/build/emubin/emubin.mk
include tool/build/build.mk include tool/build/build.mk
include tool/debug/debug.mk
include tool/decode/lib/decodelib.mk include tool/decode/lib/decodelib.mk
include tool/decode/decode.mk include tool/decode/decode.mk
include tool/hash/hash.mk include tool/hash/hash.mk

View File

@ -276,10 +276,5 @@ if "$@"; then
exit 0 exit 0
fi fi
if [ "$TERM" = "dumb" ]; then printf "$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
f='%s %s\r\n\r\n'
else
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
fi
printf "$f" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
exit 1 exit 1

View File

@ -17,9 +17,6 @@ CONFIG_CCFLAGS += \
$(FTRACE) \ $(FTRACE) \
-Og -Og
CONFIG_COPTS += \
-ftrapv
TARGET_ARCH ?= \ TARGET_ARCH ?= \
-march=k8-sse3 -march=k8-sse3

View File

@ -1,139 +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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "dsp/mpeg/mpeg.h"
#include "dsp/mpeg/ycbcrio.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
static void CheckPlmFrame(const struct plm_frame_t *frame) {
CHECK_NE(0, frame->width);
CHECK_NE(0, frame->height);
CHECK_GE(frame->y.width, frame->width);
CHECK_GE(frame->y.height, frame->height);
CHECK_EQ(frame->cr.width, frame->cb.width);
CHECK_EQ(frame->cr.height, frame->cb.height);
CHECK_EQ(frame->y.width, frame->cr.width * 2);
CHECK_EQ(frame->y.height, frame->cr.height * 2);
CHECK_NOTNULL(frame->y.data);
CHECK_NOTNULL(frame->cr.data);
CHECK_NOTNULL(frame->cb.data);
}
static size_t GetHeaderBytes(const struct plm_frame_t *frame) {
return MAX(sizeof(struct Ycbcrio), ROUNDUP(frame->y.width, 16));
}
static size_t GetPlaneBytes(const struct plm_plane_t *plane) {
/*
* planes must be 16-byte aligned, but due to their hugeness, and the
* recommendation of intel's 6,000 page manual, it makes sense to have
* planes on isolated 64kb frames for multiprocessing.
*/
return ROUNDUP(ROUNDUP(plane->height, 16) * ROUNDUP(plane->width, 16),
FRAMESIZE);
}
static size_t CalcMapBytes(const struct plm_frame_t *frame) {
return ROUNDUP(GetHeaderBytes(frame) + GetPlaneBytes(&frame->y) +
GetPlaneBytes(&frame->cb) + GetPlaneBytes(&frame->cb),
FRAMESIZE);
}
static void FixupPointers(struct Ycbcrio *map) {
map->frame.y.data = (unsigned char *)map + GetHeaderBytes(&map->frame);
map->frame.cr.data = map->frame.y.data + GetPlaneBytes(&map->frame.y);
map->frame.cb.data = map->frame.cr.data + GetPlaneBytes(&map->frame.cr);
}
static struct Ycbcrio *YcbcrioOpenNew(const char *path,
const struct plm_frame_t *frame) {
int fd;
size_t size;
struct stat st;
struct Ycbcrio *map;
CheckPlmFrame(frame);
size = CalcMapBytes(frame);
CHECK_NE(-1, (fd = open(path, O_CREAT | O_RDWR, 0644)));
CHECK_NE(-1, fstat(fd, &st));
if (st.st_size < size) {
CHECK_NE(-1, ftruncate(fd, size));
}
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)));
map->magic = YCBCRIO_MAGIC;
map->fd = fd;
map->size = size;
memcpy(&map->frame, frame, sizeof(map->frame));
FixupPointers(map);
memcpy(&map->frame.y.data, frame->y.data, GetPlaneBytes(&frame->y));
memcpy(&map->frame.cb.data, frame->cb.data, GetPlaneBytes(&frame->cb));
memcpy(&map->frame.cr.data, frame->cr.data, GetPlaneBytes(&frame->cr));
return map;
}
static struct Ycbcrio *YcbcrioOpenExisting(const char *path) {
int fd;
struct stat st;
struct Ycbcrio *map;
CHECK_NE(-1, (fd = open(path, O_RDWR)));
CHECK_NE(-1, fstat(fd, &st));
CHECK_NE(MAP_FAILED, (map = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)));
CHECK_EQ(YCBCRIO_MAGIC, map->magic);
CHECK_GE(st.st_size, CalcMapBytes(&map->frame));
FixupPointers(map);
map->fd = fd;
map->size = st.st_size;
return map;
}
/**
* Opens shareable persistable MPEG video frame memory.
*
* @param path is a file name
* @param frame if NULL means open existing file, otherwise copies new
* @param points to pointer returned by YcbcrioOpen() which is cleared
* @return memory mapping needing YcbcrioClose()
*/
struct Ycbcrio *YcbcrioOpen(const char *path, const struct plm_frame_t *frame) {
if (frame) {
return YcbcrioOpenNew(path, frame);
} else {
return YcbcrioOpenExisting(path);
}
}
/**
* Closes mapped video frame file.
*
* @param points to pointer returned by YcbcrioOpen() which is cleared
*/
void YcbcrioClose(struct Ycbcrio **map) {
CHECK_NE(-1, close_s(&(*map)->fd));
CHECK_NE(-1, munmap_s(map, (*map)->size));
}

View File

@ -1,27 +0,0 @@
#ifndef COSMOPOLITAN_DSP_MPEG_YCBCRIO_H_
#define COSMOPOLITAN_DSP_MPEG_YCBCRIO_H_
#include "dsp/mpeg/mpeg.h"
#include "libc/bits/bswap.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define YCBCRIO_MAGIC bswap_32(0xBCCBCCBCu)
/**
* Mappable persistable MPEG-2 video frame in Y-Cr-Cb colorspace.
*/
struct Ycbcrio {
uint32_t magic;
int32_t fd;
uint64_t size;
plm_frame_t frame;
};
struct Ycbcrio *YcbcrioOpen(const char *, const struct plm_frame_t *)
paramsnonnull((1)) vallocesque returnsnonnull;
void YcbcrioClose(struct Ycbcrio **) paramsnonnull();
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_DSP_MPEG_YCBCRIO_H_ */

View File

@ -7,6 +7,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ │ http://creativecommons.org/publicdomain/zero/1.0/ │
*/ */
#endif #endif
#include "libc/bits/bits.h"
#include "libc/inttypes.h" #include "libc/inttypes.h"
#include "libc/literal.h" #include "libc/literal.h"
#include "libc/math.h" #include "libc/math.h"
@ -34,7 +35,7 @@ void dobin(const char *op, long double x, FILE *f) {
memcpy(buf, &x, sizeof(x)); memcpy(buf, &x, sizeof(x));
memcpy(&lo, &buf[0], sizeof(lo)); memcpy(&lo, &buf[0], sizeof(lo));
memcpy(&hi, &buf[8], sizeof(hi)); memcpy(&hi, &buf[8], sizeof(hi));
fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s %19.19Lf\n", hi, lo, op, x); fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s % 19.19Lf\n", hi, lo, op, x);
} }
void dohex(const char *op, long double x, FILE *f) { void dohex(const char *op, long double x, FILE *f) {
@ -44,7 +45,7 @@ void dohex(const char *op, long double x, FILE *f) {
memcpy(buf, &x, sizeof(x)); memcpy(buf, &x, sizeof(x));
memcpy(&lo, &buf[0], sizeof(lo)); memcpy(&lo, &buf[0], sizeof(lo));
memcpy(&hi, &buf[8], sizeof(hi)); memcpy(&hi, &buf[8], sizeof(hi));
fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s %19.19Lf\n", hi, lo, op, x); fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s % 19.19Lf\n", hi, lo, op, x);
} }
#define DOBIN(OP) \ #define DOBIN(OP) \

View File

@ -10,6 +10,7 @@
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"

View File

@ -32,9 +32,10 @@ int main(int argc, char *argv[]) {
int pid, wstatus; int pid, wstatus;
long double ts1, ts2; long double ts1, ts2;
struct rusage rusage; struct rusage rusage;
char pathbuf[PATH_MAX];
memset(&rusage, -1, sizeof(rusage)); memset(&rusage, -1, sizeof(rusage));
CHECK_GT(argc, 1); CHECK_GT(argc, 1);
CHECK_NOTNULL((exe = commandv(argv[1]))); CHECK_NOTNULL((exe = commandv(argv[1], pathbuf)));
ts1 = nowl(); ts1 = nowl();
CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ))); CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ)));
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage)); CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));

View File

@ -86,7 +86,7 @@ char *realpath(const char *, char *);
char *replaceuser(const char *) nodiscard; char *replaceuser(const char *) nodiscard;
char *slurp(const char *, size_t *) nodiscard; char *slurp(const char *, size_t *) nodiscard;
char *ttyname(int); char *ttyname(int);
const char *commandv(const char *); char *commandv(const char *, char[hasatleast PATH_MAX]);
int access(const char *, int) nothrow; int access(const char *, int) nothrow;
int arch_prctl(); int arch_prctl();
int chdir(const char *); int chdir(const char *);
@ -140,12 +140,8 @@ int mknodat(int, const char *, int32_t, uint64_t);
int mlock(const void *, size_t); int mlock(const void *, size_t);
int mlock2(const void *, size_t, int); int mlock2(const void *, size_t, int);
int mlockall(int); int mlockall(int);
int mprotect(void *, uint64_t, int) privileged;
int msync(void *, size_t, int);
int munlock(const void *, size_t); int munlock(const void *, size_t);
int munlockall(void); int munlockall(void);
int munmap(void *, uint64_t);
int munmap_s(void *, uint64_t);
int nice(int); int nice(int);
int open(const char *, int, ...) nodiscard; int open(const char *, int, ...) nodiscard;
int openanon(char *, unsigned) nodiscard; int openanon(char *, unsigned) nodiscard;
@ -229,8 +225,6 @@ uint32_t gettid(void) nosideeffect;
uint32_t getuid(void) nosideeffect; uint32_t getuid(void) nosideeffect;
uint32_t umask(int32_t); uint32_t umask(int32_t);
void *getprocaddressmodule(const char *, const char *); void *getprocaddressmodule(const char *, const char *);
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
#define getcwd(BUF, SIZE) \ #define getcwd(BUF, SIZE) \
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \ (isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \

View File

@ -17,28 +17,18 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/alg/alg.h"
#include "libc/bits/progn.h" #include "libc/bits/progn.h"
#include "libc/bits/safemacros.h" #include "libc/bits/safemacros.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/conv/conv.h" #include "libc/conv/conv.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/mem/mem.h"
#include "libc/nt/ntdll.h" #include "libc/nt/ntdll.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/ok.h" #include "libc/sysv/consts/ok.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
static struct critbit0 g_commandv;
textstartup static void g_commandv_init(void) {
__cxa_atexit(critbit0_clear, &g_commandv, NULL);
}
const void *const g_commandv_ctor[] initarray = {g_commandv_init};
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len, static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
const char *ext) { const char *ext) {
len = stpcpy(&pathname[len], ext) - &pathname[0]; len = stpcpy(&pathname[len], ext) - &pathname[0];
@ -76,21 +66,21 @@ static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name, static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name,
size_t namelen) { size_t namelen) {
int rc; int rc;
char *ep, *path, *pathtok; char *path, *pathtok, ep[PATH_MAX];
struct critbit0 deduplicate;
rc = -1; rc = -1;
pathtok = ep = if (!memccpy(ep,
strdup(firstnonnull(getenv("PATH"), "/bin:/usr/local/bin:/usr/bin")); firstnonnull(emptytonull(getenv("PATH")),
memset(&deduplicate, 0, sizeof(deduplicate)); "/bin:/usr/local/bin:/usr/bin"),
'\0', sizeof(ep))) {
return enomem();
}
pathtok = ep;
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) { while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
if (strchr(path, '=')) continue; if (strchr(path, '=')) continue;
if (!critbit0_insert(&deduplicate, path)) continue;
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) { if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
break; break;
} }
} }
critbit0_clear(&deduplicate);
free(ep);
return rc; return rc;
} }
@ -105,66 +95,29 @@ static char *mkcmdquery(const char *name, size_t namelen,
return &scratch[0]; return &scratch[0];
} }
static const char *cachecmd(const char *name, size_t namelen,
const char *pathname, size_t pathnamelen) {
size_t entrylen;
char *res, *entry;
if ((entry = malloc((entrylen = namelen + 1 + pathnamelen) + 1))) {
mkcmdquery(name, namelen, entry);
res = memcpy(&entry[namelen + 1], pathname, pathnamelen + 1);
critbit0_emplace(&g_commandv, entry, entrylen);
} else {
res = NULL;
}
return res;
}
static const char *getcmdcache(const char *name, size_t namelen,
char scratch[hasatleast PATH_MAX]) {
const char *entry;
if ((entry = critbit0_get(&g_commandv, mkcmdquery(name, namelen, scratch)))) {
return &entry[namelen + 1];
}
return NULL;
}
noinline static const char *findcmdpath(const char *name,
char pathname[hasatleast PATH_MAX]) {
char *p;
int rc, olderr;
size_t len;
olderr = errno;
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
if ((p = getcmdcache(name, len, pathname)) ||
(((IsWindows() &&
((rc = accesscmd(pathname, kNtSystemDirectory, name, len)) != -1 ||
(rc = accesscmd(pathname, kNtWindowsDirectory, name, len)) != -1)) ||
(rc = accesscmd(pathname, "", name, len)) != -1 ||
(!strpbrk(name, "/\\") &&
(rc = searchcmdpath(pathname, name, len)) != -1)) &&
(p = cachecmd(name, len, pathname, rc)))) {
errno = olderr;
return p;
} else {
return NULL;
}
}
/** /**
* Resolves pathname of executable. * Resolves full pathname of executable.
*
* This does the same thing as `command -v` in bourne shell. Path
* lookups are cached for the lifetime of the process. Paths with
* multiple components will skip the resolution process. Undotted
* basenames get automatic .com and .exe suffix resolution on all
* platforms. Windows' system directories will always trump PATH.
* *
* @return execve()'able path, or NULL w/ errno * @return execve()'able path, or NULL w/ errno
* @errno ENOENT, EACCES, ENOMEM * @errno ENOENT, EACCES, ENOMEM
* @see free(), execvpe() * @see free(), execvpe()
*/ */
const char *commandv(const char *name) { char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
char pathname[PATH_MAX]; char *p;
return findcmdpath(name, pathname); size_t len;
int rc, olderr;
olderr = errno;
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
if ((IsWindows() &&
((rc = accesscmd(pathbuf, kNtSystemDirectory, name, len)) != -1 ||
(rc = accesscmd(pathbuf, kNtWindowsDirectory, name, len)) != -1)) ||
(rc = accesscmd(pathbuf, "", name, len)) != -1 ||
(!strpbrk(name, "/\\") &&
(rc = searchcmdpath(pathbuf, name, len)) != -1)) {
errno = olderr;
return pathbuf;
} else {
return NULL;
}
} }

View File

@ -19,11 +19,11 @@
*/ */
#include "libc/macros.h" #include "libc/macros.h"
.init.start 300,_init_g_fds .init.start 302,_init_g_fds
push %rdi push %rdi
push %rsi push %rsi
call InitializeFileDescriptors call InitializeFileDescriptors
pop %rsi pop %rsi
pop %rdi pop %rdi
.init.end 300,_init_g_fds .init.end 302,_init_g_fds
.source __FILE__ .source __FILE__

View File

@ -25,16 +25,22 @@
/** /**
* Returns value of environment variable, or NULL if not found. * Returns value of environment variable, or NULL if not found.
*/ */
char *getenv(const char *name) { char *getenv(const char *s) {
char **ep; char **p;
size_t i, namelen; size_t i, j;
char *empty[1] = {0}; if ((p = environ)) {
ep = environ; for (i = 0; p[i]; ++i) {
if (!ep) ep = empty; for (j = 0;; ++j) {
namelen = strlen(name); if (!s[j]) {
for (i = 0; ep[i]; ++i) { if (p[i][j] == '=') {
if (strncmp(ep[i], name, namelen) == 0 && ep[i][namelen] == '=') { return &p[i][j + 1];
return &ep[i][namelen + 1]; }
break;
}
if (s[j] != p[i][j]) {
break;
}
}
} }
} }
return NULL; return NULL;

View File

@ -17,9 +17,9 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/mem/mem.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/mem/mem.h"
/** /**
* Executes program, with custom environment. * Executes program, with custom environment.

View File

@ -17,10 +17,10 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/calls/calls.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/calls.h"
/** /**
* Executes program, with PATH search and current environment. * Executes program, with PATH search and current environment.
@ -36,7 +36,8 @@
*/ */
int execlp(const char *prog, const char *arg, ... /*, NULL*/) { int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
char *exe; char *exe;
if ((exe = commandv(prog))) { char pathbuf[PATH_MAX];
if ((exe = commandv(prog, pathbuf))) {
va_list va; va_list va;
void *argv; void *argv;
va_start(va, arg); va_start(va, arg);

View File

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/mem/mem.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/mem/mem.h"
/** /**
* Executes program, with path environment search. * Executes program, with path environment search.
@ -33,7 +33,8 @@
*/ */
int execvpe(const char *prog, char *const argv[], char *const *envp) { int execvpe(const char *prog, char *const argv[], char *const *envp) {
char *exe; char *exe;
if ((exe = commandv(prog))) { char pathbuf[PATH_MAX];
if ((exe = commandv(prog, pathbuf))) {
execve(exe, argv, envp); execve(exe, argv, envp);
} }
return -1; return -1;

View File

@ -24,17 +24,18 @@
#include "libc/nexgen32e/tinystrcmp.h" #include "libc/nexgen32e/tinystrcmp.h"
#include "libc/str/str.h" #include "libc/str/str.h"
static int sortenvpcb(const char **a, const char **b) { return strcmp(*a, *b); } static int CompareStrings(const char *l, const char *r) {
size_t i = 0;
while (l[i] == r[i] && r[i]) ++i;
return (l[i] & 0xff) - (r[i] & 0xff);
}
static void slowsort(char **a, int n) { static void SortStrings(char **a, size_t n) {
char *t;
size_t i, j; size_t i, j;
const char *t;
for (i = 1; i < n; ++i) { for (i = 1; i < n; ++i) {
j = i; for (t = a[i], j = i; j > 0 && CompareStrings(t, a[j - 1]) < 0; --j) {
t = a[i];
while (j > 0 && tinystrcmp(t, a[j - 1]) < 0) {
a[j] = a[j - 1]; a[j] = a[j - 1];
--j;
} }
a[j] = t; a[j] = t;
} }
@ -52,17 +53,14 @@ static void slowsort(char **a, int n) {
* @return newly allocated sorted copy of envp pointer array * @return newly allocated sorted copy of envp pointer array
*/ */
hidden textwindows nodiscard char **sortenvp(char *const envp[]) { hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
size_t count = 0; char **copy;
while (envp[count]) count++; size_t n, size;
size_t bytesize = (count + 1) * sizeof(char *); n = 0;
char **copy = malloc(bytesize); while (envp[n]) n++;
if (copy) { size = (n + 1) * sizeof(char *);
memcpy(copy, envp, bytesize); if ((copy = malloc(size))) {
if (IsTiny()) { memcpy(copy, envp, size);
slowsort(copy, count); SortStrings(copy, n);
} else {
qsort(copy, count, sizeof(char *), (void *)sortenvpcb);
}
} }
return copy; return copy;
} }

View File

@ -40,8 +40,9 @@ nodiscard int spawnlp(unsigned flags, int stdiofds[3], const char *prog,
char *exe; char *exe;
va_list va; va_list va;
void *argv; void *argv;
char pathbuf[PATH_MAX];
pid = -1; pid = -1;
if ((exe = commandv(prog))) { if ((exe = commandv(prog, pathbuf))) {
va_start(va, arg); va_start(va, arg);
if ((argv = mkvarargv(arg, va))) { if ((argv = mkvarargv(arg, va))) {
pid = spawnve(flags, stdiofds, exe, argv, environ); pid = spawnve(flags, stdiofds, exe, argv, environ);

View File

@ -17,7 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/mem/mem.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/enum/accessmask.h" #include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/securityinformation.h" #include "libc/nt/enum/securityinformation.h"
#include "libc/nt/errors.h" #include "libc/nt/errors.h"
@ -28,33 +29,33 @@
#include "libc/nt/struct/securitydescriptor.h" #include "libc/nt/struct/securitydescriptor.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/calls/internal.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/ok.h" #include "libc/sysv/consts/ok.h"
/** /**
* Checks if current process has access to folder or file. * Asks Microsoft if we're authorized to use a folder or file.
*
* Implementation Details: MSDN documentation imposes no limit on the
* internal size of SECURITY_DESCRIPTOR, which we are responsible for
* allocating. We've selected 1024 which shall hopefully be adequate.
* *
* @param flags can have R_OK, W_OK, X_OK, etc. * @param flags can have R_OK, W_OK, X_OK, etc.
* @return 0 if authorized, or -1 w/ errno * @return 0 if authorized, or -1 w/ errno
* @kudos Aaron Ballman for teaching how to do this * @kudos Aaron Ballman for teaching this
* @see libc/sysv/consts.sh * @see libc/sysv/consts.sh
*/ */
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) { textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
int rc; int rc;
bool32 result; bool32 result;
struct NtGenericMapping mapping;
struct NtPrivilegeSet privileges;
int64_t hToken, hImpersonatedToken; int64_t hToken, hImpersonatedToken;
uint32_t secsize, granted, privsize; uint32_t secsize, granted, privsize;
struct NtPrivilegeSet privileges; union NtSecurityDescriptorLol {
struct NtGenericMapping mapping; struct NtSecurityDescriptor s;
struct NtSecurityDescriptor security; char b[1024];
struct NtSecurityDescriptor *psecurity; } security;
const uint32_t request = kNtOwnerSecurityInformation |
kNtGroupSecurityInformation |
kNtDaclSecurityInformation;
granted = 0; granted = 0;
result = false; result = false;
psecurity = &security;
secsize = sizeof(security); secsize = sizeof(security);
privsize = sizeof(privileges); privsize = sizeof(privileges);
memset(&privileges, 0, sizeof(privileges)); memset(&privileges, 0, sizeof(privileges));
@ -64,23 +65,23 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
mapping.GenericAll = kNtFileAllAccess; mapping.GenericAll = kNtFileAllAccess;
MapGenericMask(&flags, &mapping); MapGenericMask(&flags, &mapping);
hImpersonatedToken = hToken = -1; hImpersonatedToken = hToken = -1;
if ((GetFileSecurity(pathname, request, psecurity, 0, &secsize) || if (GetFileSecurity(pathname,
(GetLastError() == kNtErrorInsufficientBuffer && kNtOwnerSecurityInformation |
(psecurity = malloc(secsize)) && kNtGroupSecurityInformation |
GetFileSecurity(pathname, request, psecurity, secsize, &secsize))) && kNtDaclSecurityInformation,
&security.s, 0, &secsize) &&
OpenProcessToken(GetCurrentProcess(), OpenProcessToken(GetCurrentProcess(),
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate | kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
kNtStandardRightsRead, kNtStandardRightsRead,
&hToken) && &hToken) &&
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) && DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
AccessCheck(psecurity, hImpersonatedToken, flags, &mapping, &privileges, AccessCheck(&security.s, hImpersonatedToken, flags, &mapping, &privileges,
&privsize, &granted, &result) && &privsize, &granted, &result) &&
(result || flags == F_OK)) { (result || flags == F_OK)) {
rc = 0; rc = 0;
} else { } else {
rc = winerr(); rc = winerr();
} }
free_s(&psecurity);
close(hImpersonatedToken); close(hImpersonatedToken);
close(hToken); close(hToken);
return rc; return rc;

View File

@ -57,10 +57,7 @@ int(vdprintf)(int fd, const char *fmt, va_list va) {
struct VdprintfState df; struct VdprintfState df;
df.n = 0; df.n = 0;
df.fd = fd; df.fd = fd;
if (palandprintf(vdprintfputchar, &df, fmt, va) != -1 || if (palandprintf(vdprintfputchar, &df, fmt, va) == -1) return -1;
vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) != -1) { if (vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) == -1) return -1;
return df.n; return df.n;
} else {
return -1;
}
} }

View File

@ -1,28 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_CONV_SIZEMULTIPLY_H_
#define COSMOPOLITAN_LIBC_CONV_SIZEMULTIPLY_H_
#include "libc/limits.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
* Multiplies memory sizes.
*
* @param count may be 0 to for realloc() free() behavior
* @param opt_out set to count*itemsize or SIZE_MAX on overflow
* @return true on success or false on overflow
*/
forceinline bool sizemultiply(size_t *opt_out, size_t count, size_t itemsize) {
size_t res = 0;
bool overflowed = false;
if (count != 0) {
res = count * itemsize;
if (((count | itemsize) & ~0xfffful) && (res / count != itemsize)) {
overflowed = true;
res = SIZE_MAX;
}
}
if (opt_out) *opt_out = res;
return !overflowed;
}
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CONV_SIZEMULTIPLY_H_ */

View File

@ -33,7 +33,7 @@ static void unrijndaelinit$westmere(struct Rijndael *ctx, uint32_t n,
x = ctx->rk[i].xmm; x = ctx->rk[i].xmm;
asm("aesimc\t%1,%0" : "=x"(x) : "0"(x)); asm("aesimc\t%1,%0" : "=x"(x) : "0"(x));
ctx->rk[i].xmm = x; ctx->rk[i].xmm = x;
} while (i++ < n); } while (++i < n);
XMM_DESTROY(x); XMM_DESTROY(x);
} }
@ -49,7 +49,7 @@ static relegated noinline void unrijndaelinit$pure(struct Rijndael *ctx,
x = ctx->rk[i].xmm; x = ctx->rk[i].xmm;
x = InvMixColumns(x); x = InvMixColumns(x);
ctx->rk[i].xmm = x; ctx->rk[i].xmm = x;
} while (i++ < n); } while (++i < n);
XMM_DESTROY(x); XMM_DESTROY(x);
} }

View File

@ -45,10 +45,11 @@
*/ */
int parsehoststxt(struct HostsTxt *ht, FILE *f) { int parsehoststxt(struct HostsTxt *ht, FILE *f) {
int rc = 0; int rc = 0;
char stackline[128]; char *line;
char *line = stackline; size_t linesize;
size_t linecap = sizeof(stackline); line = NULL;
while ((getline(&line, &linecap, f)) != -1) { linesize = 0;
while ((getline(&line, &linesize, f)) != -1) {
struct HostsTxtEntry entry; struct HostsTxtEntry entry;
char *addr, *name, *tok, *comment; char *addr, *name, *tok, *comment;
if ((comment = strchr(line, '#'))) *comment = '\0'; if ((comment = strchr(line, '#'))) *comment = '\0';
@ -64,6 +65,6 @@ int parsehoststxt(struct HostsTxt *ht, FILE *f) {
} }
} }
} }
free_s(&line); free(line);
return rc | ferror(f); return rc | ferror(f);
} }

View File

@ -20,6 +20,7 @@
#include "libc/alg/arraylist.h" #include "libc/alg/arraylist.h"
#include "libc/dns/dns.h" #include "libc/dns/dns.h"
#include "libc/dns/resolvconf.h" #include "libc/dns/resolvconf.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
@ -44,13 +45,14 @@
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) { int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
/* TODO(jart): options ndots:5 */ /* TODO(jart): options ndots:5 */
int rc = 0; int rc = 0;
char stackline[32]; char *line;
char *line = stackline; size_t linesize;
size_t linecap = sizeof(stackline);
struct sockaddr_in nameserver; struct sockaddr_in nameserver;
line = NULL;
linesize = 0;
nameserver.sin_family = AF_INET; nameserver.sin_family = AF_INET;
nameserver.sin_port = htons(DNS_PORT); nameserver.sin_port = htons(DNS_PORT);
while (getline(&line, &linecap, f) != -1) { while (getline(&line, &linesize, f) != -1) {
char *directive, *value, *tok, *comment; char *directive, *value, *tok, *comment;
if ((comment = strchr(line, '#'))) *comment = '\0'; if ((comment = strchr(line, '#'))) *comment = '\0';
if ((directive = strtok_r(line, " \t\r\n\v", &tok)) && if ((directive = strtok_r(line, " \t\r\n\v", &tok)) &&
@ -61,6 +63,6 @@ int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
} }
} }
} }
free_s(&line); free(line);
return rc | ferror(f); return rc | ferror(f);
} }

View File

@ -56,14 +56,7 @@ static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)];
* @see bing() * @see bing()
*/ */
int unbing(int c) { int unbing(int c) {
int i, m, l, r; int m, l, r;
static bool once;
if (!once) {
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
insertionsort(ARRAYLEN(g_cp437i), g_cp437i);
once = true;
}
l = 0; l = 0;
r = ARRAYLEN(g_cp437i) - 1; r = ARRAYLEN(g_cp437i) - 1;
while (l <= r) { while (l <= r) {
@ -78,3 +71,12 @@ int unbing(int c) {
} }
return -1; return -1;
} }
static textstartup void g_cp437i_init() {
unsigned i;
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
djbsort(ARRAYLEN(g_cp437i), g_cp437i);
}
const void *const g_cp437i_ctor[] initarray = {g_cp437i_init};

View File

@ -336,6 +336,7 @@ typedef uint64_t uintmax_t;
* 4. unprofilable * 4. unprofilable
* 5. unhookable * 5. unhookable
* *
* @note consider static or writing a macro
* @see externinline * @see externinline
*/ */
#ifndef forceinline #ifndef forceinline

View File

@ -66,8 +66,8 @@
#endif #endif
#define BIGPAGESIZE 0x200000 #define BIGPAGESIZE 0x200000
#define STACKSIZE 0x20000
#define FRAMESIZE 0x10000 /* 8086 */ #define FRAMESIZE 0x10000 /* 8086 */
#define STACKSIZE 0x10000 /* goog */
#define PAGESIZE 0x1000 /* i386+ */ #define PAGESIZE 0x1000 /* i386+ */
#define BUFSIZ 0x1000 /* best stdio default */ #define BUFSIZ 0x1000 /* best stdio default */
#define CACHELINE 0x40 /* nexgen32e */ #define CACHELINE 0x40 /* nexgen32e */

View File

@ -13,8 +13,7 @@ LIBC_INTRIN_A_SRCS = $(LIBC_INTRIN_A_SRCS_S) $(LIBC_INTRIN_A_SRCS_C)
LIBC_INTRIN_A_CHECKS = $(LIBC_INTRIN_A).pkg LIBC_INTRIN_A_CHECKS = $(LIBC_INTRIN_A).pkg
LIBC_INTRIN_A_FILES := \ LIBC_INTRIN_A_FILES := \
$(wildcard libc/intrin/*) \ $(wildcard libc/intrin/*)
$(wildcard libc/intrin/delegates/*)
LIBC_INTRIN_A_OBJS = \ LIBC_INTRIN_A_OBJS = \
$(LIBC_INTRIN_A_SRCS:%=o/$(MODE)/%.zip.o) \ $(LIBC_INTRIN_A_SRCS:%=o/$(MODE)/%.zip.o) \

View File

@ -2,7 +2,7 @@
#define COSMOPOLITAN_LIBC_INTRIN_REPMOVSB_H_ #define COSMOPOLITAN_LIBC_INTRIN_REPMOVSB_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
static void repmovsb(void **dest, const void **src, size_t cx) { forceinline void repmovsb(void **dest, const void **src, size_t cx) {
char *di = (char *)*dest; char *di = (char *)*dest;
const char *si = (const char *)*src; const char *si = (const char *)*src;
while (cx) *di++ = *si++, cx--; while (cx) *di++ = *si++, cx--;

View File

@ -2,7 +2,7 @@
#define COSMOPOLITAN_LIBC_INTRIN_REPSTOSB_H_ #define COSMOPOLITAN_LIBC_INTRIN_REPSTOSB_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
static void *repstosb(void *dest, unsigned char al, size_t cx) { forceinline void *repstosb(void *dest, unsigned char al, size_t cx) {
unsigned char *di = (unsigned char *)dest; unsigned char *di = (unsigned char *)dest;
while (cx) *di++ = al, cx--; while (cx) *di++ = al, cx--;
return di; return di;

370
libc/log/asan.c 100644
View File

@ -0,0 +1,370 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/conv/conv.h"
#include "libc/conv/itoa.h"
#include "libc/log/asan.h"
#include "libc/log/backtrace.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/mem/hook/hook.h"
#include "libc/runtime/directmap.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "third_party/dlmalloc/dlmalloc.h"
/**
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
*
* Someone brilliant at Google figured out a way to improve upon memory
* protection. Rather than invent another Java or Rust they changed GCC
* so it can emit fast code, that checks the validity of each memory op
* with byte granularity, by probing shadow memory.
*
* AddressSanitizer dedicates one-eighth of the virtual address space
* to its shadow memory and uses a direct mapping with a scale and
* offset to translate an application address to its corresponding
* shadow address. Given the application memory address Addr, the
* address of the shadow byte is computed as (Addr>>3)+Offset."
*
* We use the following encoding for each shadow byte: 0 means that
* all 8 bytes of the corresponding application memory region are
* addressable; k (1 k 7) means that the first k bytes are
* addressible; any negative value indicates that the entire 8-byte
* word is unaddressable. We use different negative values to
* distinguish between different kinds of unaddressable memory (heap
* redzones, stack redzones, global redzones, freed memory).
*
* Here's what the generated code looks like for 64-bit reads:
*
* movq %addr,%tmp
* shrq $3,%tmp
* cmpb $0,0x7fff8000(%tmp)
* jnz abort
* movq (%addr),%dst
*/
#define HOOK(HOOK, IMPL) \
if (weaken(HOOK)) { \
*weaken(HOOK) = IMPL; \
}
struct AsanSourceLocation {
const char *filename;
int line;
int column;
};
struct AsanAccessInfo {
const char *addr;
const char *first_bad_addr;
size_t size;
bool iswrite;
unsigned long ip;
};
struct AsanGlobal {
const char *addr;
size_t size;
size_t size_with_redzone;
const void *name;
const void *module_name;
unsigned long has_cxx_init;
struct AsanSourceLocation *location;
char *odr_indicator;
};
static bool __asan_is_mapped(void *p) {
int x, i;
x = (intptr_t)p >> 16;
i = FindMemoryInterval(&_mmi, x);
return i < _mmi.i && x >= _mmi.p[i].x && x <= _mmi.p[i].y;
}
void __asan_map_shadow(void *addr, size_t size) {
int i, n, x;
char *a, *b;
struct DirectMap sm;
a = (char *)ROUNDDOWN(SHADOW((intptr_t)addr), FRAMESIZE);
b = (char *)ROUNDDOWN(SHADOW((intptr_t)addr + size - 1), FRAMESIZE);
for (; a <= b; a += FRAMESIZE) {
if (!__asan_is_mapped(a)) {
sm = DirectMap(a, FRAMESIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (sm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, (intptr_t)a >> 16, (intptr_t)a >> 16,
sm.maphandle) == -1) {
abort();
}
}
}
}
size_t __asan_malloc_usable_size(const void *vp) {
char *s;
size_t n;
for (n = 0, s = (char *)SHADOW((intptr_t)vp);; ++s) {
if (!*s) {
n += 8;
} else if (*s > 0) {
n += *s & 7;
} else {
break;
}
}
return n;
}
void *__asan_allocate(size_t align, size_t size, int underrun, int overrun) {
char *p, *s;
size_t q, r, i;
if (!(p = dlmemalign(align, ROUNDUP(size, 8) + 16))) return NULL;
s = (char *)SHADOW((intptr_t)p - 16);
q = size / 8;
r = size % 8;
*s++ = underrun;
*s++ = underrun;
memset(s, 0, q);
s += q;
if (r) *s++ = r;
*s++ = overrun;
*s++ = overrun;
return p;
}
void __asan_deallocate(char *p, int kind) {
char *s;
size_t n;
s = (char *)SHADOW((intptr_t)p);
n = dlmalloc_usable_size(p);
n /= 8;
memset(s, kind, n);
dlfree(p);
}
void __asan_free(void *vp) {
__asan_deallocate(vp, kAsanHeapFree);
}
void *__asan_memalign(size_t align, size_t size) {
return __asan_allocate(align, size, kAsanHeapUnderrun, kAsanHeapOverrun);
}
void *__asan_malloc(size_t size) {
return __asan_memalign(16, size);
}
void *__asan_calloc(size_t n, size_t m) {
char *p;
size_t size;
if (__builtin_mul_overflow(n, m, &size)) size = -1;
if ((p = __asan_malloc(size))) memset(p, 0, size);
return p;
}
void *__asan_realloc(void *p, size_t n) {
char *p2;
if (p) {
if (n) {
if ((p2 = __asan_malloc(n))) {
memcpy(p2, p, min(n, dlmalloc_usable_size(p)));
__asan_deallocate(p, kAsanRelocated);
}
} else {
__asan_free(p);
p2 = NULL;
}
} else {
p2 = __asan_malloc(n);
}
return p2;
}
void *__asan_valloc(size_t n) {
return __asan_memalign(PAGESIZE, n);
}
void *__asan_pvalloc(size_t n) {
return __asan_valloc(ROUNDUP(n, PAGESIZE));
}
void __asan_poison(intptr_t addr, size_t size, size_t redsize, int kind) {
char *s;
intptr_t p;
size_t a, b, w;
w = (intptr_t)addr & 7;
p = (intptr_t)addr - w;
a = w + size;
b = w + redsize;
s = (char *)SHADOW(p + a);
if (a & 7) *s++ = a & 7;
memset(s, kind, (b - ROUNDUP(a, 8)) >> 3);
}
void __asan_register_globals(struct AsanGlobal g[], int n) {
size_t i;
for (i = 0; i < n; ++i) {
__asan_poison((intptr_t)g[i].addr, g[i].size, g[i].size_with_redzone,
kAsanGlobalOverrun);
}
}
void __asan_report_memory_fault(uint8_t *addr, int size, const char *kind) {
char *p, *s, ibuf[21], buf[256];
switch (*(char *)SHADOW((intptr_t)addr)) {
case kAsanStackFree:
s = "stack use after release";
break;
case kAsanHeapFree:
s = "heap use after free";
break;
case kAsanRelocated:
s = "heap use after relocate";
break;
case kAsanHeapUnderrun:
s = "heap underrun";
break;
case kAsanHeapOverrun:
s = "heap overrun";
break;
case kAsanStackUnderrun:
s = "stack underflow";
break;
case kAsanStackOverrun:
s = "stack overflow";
break;
case kAsanAllocaOverrun:
s = "alloca overflow";
break;
case kAsanUnscoped:
s = "unscoped";
break;
default:
s = "poisoned";
break;
}
p = buf;
p = stpcpy(p, "error: ");
p = stpcpy(p, s);
p = stpcpy(p, " ");
uint64toarray_radix10(size, ibuf);
p = stpcpy(p, ibuf);
p = stpcpy(p, "-byte ");
p = stpcpy(p, kind);
p = stpcpy(p, " at 0x");
uint64toarray_fixed16((intptr_t)addr, ibuf, 48);
p = stpcpy(p, ibuf);
p = stpcpy(p, "\n");
__print(buf, p - buf);
PrintBacktraceUsingSymbols(stderr, __builtin_frame_address(0),
getsymboltable());
DebugBreak();
_Exit(66);
}
void *__asan_stack_malloc(size_t size, int classid) {
return __asan_allocate(32, size, kAsanStackUnderrun, kAsanStackOverrun);
}
void __asan_stack_free(char *p, size_t size, int classid) {
return __asan_deallocate(p, kAsanStackFree);
}
void __asan_report_load_n(uint8_t *addr, int size) {
__asan_report_memory_fault(addr, size, "load");
}
void __asan_report_store_n(uint8_t *addr, int size) {
__asan_report_memory_fault(addr, size, "store");
}
void __asan_poison_stack_memory(uintptr_t p, size_t n) {
memset((char *)SHADOW(p), kAsanUnscoped, n >> 3);
if (n & 7) *(char *)SHADOW(p + n) = 8 - (n & 7);
}
void __asan_unpoison_stack_memory(uintptr_t p, size_t n) {
memset((char *)SHADOW(p), 0, n >> 3);
if (n & 7) *(char *)SHADOW(p + n) = n & 7;
}
void __asan_loadN(intptr_t ptr, size_t size) {
DebugBreak();
}
void __asan_storeN(intptr_t ptr, size_t size) {
DebugBreak();
}
void __asan_alloca_poison(intptr_t addr, size_t size) {
__asan_poison(addr, size, size + 32, kAsanAllocaOverrun);
}
void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
memset((char *)SHADOW(top), 0, (bottom - top) >> 3);
}
void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr, void **beg,
void **end) {
return NULL;
}
void *__asan_get_current_fake_stack(void) {
return NULL;
}
void __asan_install_malloc_hooks(void) {
HOOK(hook$free, __asan_free);
HOOK(hook$malloc, __asan_malloc);
HOOK(hook$calloc, __asan_calloc);
HOOK(hook$valloc, __asan_valloc);
HOOK(hook$pvalloc, __asan_pvalloc);
HOOK(hook$realloc, __asan_realloc);
HOOK(hook$memalign, __asan_memalign);
HOOK(hook$malloc_usable_size, __asan_malloc_usable_size);
}
void __asan_init(int argc, char *argv[], char **envp, intptr_t *auxv) {
int i;
static bool once;
register intptr_t rsp asm("rsp");
if (!once) {
__asan_map_shadow(_base, _end - _base);
__asan_map_shadow((void *)ROUNDDOWN(rsp, STACKSIZE), STACKSIZE);
for (i = 0; i < argc; ++i) __asan_map_shadow(argv[i], strlen(argv[i]));
for (; *envp; ++envp) __asan_map_shadow(*envp, strlen(*envp));
__asan_map_shadow(auxv, sizeof(intptr_t) * 2);
__asan_install_malloc_hooks();
once = true;
}
}
const void *const g_asan_ctor[] initarray = {getsymboltable};

21
libc/log/asan.h 100644
View File

@ -0,0 +1,21 @@
#ifndef COSMOPOLITAN_LIBC_LOG_ASAN_H_
#define COSMOPOLITAN_LIBC_LOG_ASAN_H_
#define kAsanScale 3
#define kAsanMagic 0x7fff8000
#define kAsanHeapFree -1
#define kAsanStackFree -2
#define kAsanRelocated -3
#define kAsanHeapUnderrun -4
#define kAsanHeapOverrun -5
#define kAsanGlobalOverrun -6
#define kAsanStackUnderrun -7
#define kAsanStackOverrun -8
#define kAsanAllocaOverrun -9
#define kAsanUnscoped -10
#define SHADOW(x) (((x) >> kAsanScale) + kAsanMagic)
void __asan_map_shadow(void *, size_t);
#endif /* COSMOPOLITAN_LIBC_LOG_ASAN_H_ */

View File

@ -23,6 +23,7 @@
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/log/gdb.h" #include "libc/log/gdb.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nexgen32e/vendor.h" #include "libc/nexgen32e/vendor.h"
#include "libc/paths.h" #include "libc/paths.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"

View File

@ -17,8 +17,7 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/dce.h" #include "libc/log/backtrace.h"
#include "libc/log/log.h"
void backtrace(FILE *f) { void backtrace(FILE *f) {
showbacktrace(f, __builtin_frame_address(0)); showbacktrace(f, __builtin_frame_address(0));

View File

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_
#define COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/symbols.h"
#include "libc/stdio/stdio.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
void showbacktrace(FILE *, const struct StackFrame *);
int PrintBacktraceUsingSymbols(FILE *, const struct StackFrame *,
struct SymbolTable *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_LOG_BACKTRACE_H_ */

View File

@ -26,6 +26,7 @@
#include "libc/conv/conv.h" #include "libc/conv/conv.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/log/backtrace.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/nexgen32e/gc.h" #include "libc/nexgen32e/gc.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -37,54 +38,7 @@
#define kBacktraceMaxFrames 128 #define kBacktraceMaxFrames 128
#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1)) #define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1))
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr, static int PrintBacktraceUsingAddr2line(FILE *f, const struct StackFrame *bp) {
char *out, unsigned size, bool symbolic) {
int64_t addend;
const char *name;
const struct Symbol *symbol;
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
(intptr_t)addr <= (intptr_t)&_end && symbolic)) {
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
st->count, addr - st->addr_base - 1)];
addend = addr - st->addr_base - symbol->addr_rva;
name = &st->name_base[symbol->name_rva];
snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', abs(addend));
} else {
snprintf(out, size, "%p", addr);
}
return out;
}
static int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
char buf[hasatleast kBacktraceBufSize]) {
size_t gi;
intptr_t addr;
struct Garbages *garbage;
struct SymbolTable *symbols;
const struct StackFrame *frame;
if ((symbols = getsymboltable())) {
garbage = weaken(g_garbage);
gi = garbage ? garbage->i : 0;
for (frame = bp; frame; frame = frame->next) {
addr = frame->addr;
if (addr == weakaddr("CollectGarbage")) {
do {
--gi;
} while ((addr = garbage->p[gi].ret) == weakaddr("CollectGarbage"));
}
fprintf(f, "%p %p %s\n", frame, addr,
FormatAddress(f, symbols, addr, buf, kBacktraceBufSize, true));
}
return 0;
} else {
return -1;
}
}
static int PrintBacktraceUsingAddr2line(
FILE *f, const struct StackFrame *bp,
char buf[hasatleast kBacktraceBufSize],
char *argv[hasatleast kBacktraceMaxFrames]) {
ssize_t got; ssize_t got;
intptr_t addr; intptr_t addr;
size_t i, j, gi; size_t i, j, gi;
@ -92,6 +46,7 @@ static int PrintBacktraceUsingAddr2line(
struct Garbages *garbage; struct Garbages *garbage;
const struct StackFrame *frame; const struct StackFrame *frame;
const char *debugbin, *p1, *p2, *p3, *addr2line; const char *debugbin, *p1, *p2, *p3, *addr2line;
char buf[kBacktraceBufSize], *argv[kBacktraceMaxFrames];
if (!(debugbin = finddebugbinary()) || !(addr2line = GetAddr2linePath())) { if (!(debugbin = finddebugbinary()) || !(addr2line = GetAddr2linePath())) {
return -1; return -1;
} }
@ -148,24 +103,20 @@ static int PrintBacktraceUsingAddr2line(
return 0; return 0;
} }
static noinline int PrintBacktrace(FILE *f, const struct StackFrame *bp, static int PrintBacktrace(FILE *f, const struct StackFrame *bp) {
char *argv[hasatleast kBacktraceMaxFrames],
char buf[hasatleast kBacktraceBufSize]) {
if (!IsTiny()) { if (!IsTiny()) {
if (PrintBacktraceUsingAddr2line(f, bp, buf, argv) != -1) { if (PrintBacktraceUsingAddr2line(f, bp) != -1) {
return 0; return 0;
} }
} }
return PrintBacktraceUsingSymbols(f, bp, buf); return PrintBacktraceUsingSymbols(f, bp, getsymboltable());
} }
void showbacktrace(FILE *f, const struct StackFrame *bp) { void showbacktrace(FILE *f, const struct StackFrame *bp) {
static bool noreentry; static bool noreentry;
char *argv[kBacktraceMaxFrames];
char buf[kBacktraceBufSize];
if (!noreentry) { if (!noreentry) {
noreentry = true; noreentry = true;
PrintBacktrace(f, bp, argv, buf); PrintBacktrace(f, bp);
noreentry = 0; noreentry = 0;
} }
} }

View File

@ -17,83 +17,53 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/calls/calls.h" #include "libc/alg/bisectcarleft.h"
#include "libc/bits/weaken.h"
#include "libc/fmt/fmt.h"
#include "libc/log/backtrace.h"
#include "libc/macros.h"
#include "libc/nexgen32e/gc.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/symbols.h"
#include "libc/stdio/stdio.h" #include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
struct SourceLocation { static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
const char *filename; char *out, unsigned size, bool symbolic) {
int line; int64_t addend;
int column; const char *name;
}; const struct Symbol *symbol;
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
struct AccessInfo { (intptr_t)addr <= (intptr_t)&_end && symbolic)) {
const uint8_t *addr; symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
const uint8_t *first_bad_addr; st->count, addr - st->addr_base - 1)];
size_t size; addend = addr - st->addr_base - symbol->addr_rva;
bool iswrite; name = &st->name_base[symbol->name_rva];
unsigned long ip; snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', ABS(addend));
}; } else {
snprintf(out, size, "%p", addr);
struct Global { }
const uint8_t *addr; return out;
size_t size;
size_t size_with_redzone;
const void *name;
const void *module_name;
unsigned long has_cxx_init;
struct kasan_source_location *location;
char *odr_indicator;
};
privileged void __asan_init(void) {
} }
privileged void __asan_version_mismatch_check_v8(void) { int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
} struct SymbolTable *symbols) {
size_t gi;
privileged void __asan_register_globals(struct Global globals[], int n) { char buf[256];
} intptr_t addr;
struct Garbages *garbage;
privileged void __asan_unregister_globals(struct Global globals[], int n) { const struct StackFrame *frame;
} if (!symbols) return -1;
garbage = weaken(g_garbage);
privileged void __asan_report_load_n(uint8_t *p, int n) { gi = garbage ? garbage->i : 0;
} for (frame = bp; frame; frame = frame->next) {
addr = frame->addr;
privileged void __asan_report_store_n(uint8_t *p, int n) { if (addr == weakaddr("CollectGarbage")) {
__asan_report_load_n(p, n); do {
} --gi;
} while ((addr = garbage->p[gi].ret) == weakaddr("CollectGarbage"));
privileged void __asan_loadN(uintptr_t ptr, size_t size) { }
} fprintf(f, "%p %p %s\n", frame, addr,
FormatAddress(f, symbols, addr, buf, sizeof(buf), true));
privileged void __asan_storeN(uintptr_t ptr, size_t size) { }
}
privileged uintptr_t __asan_stack_malloc(size_t size, int classid) {
return 0; return 0;
} }
privileged void __asan_stack_free(uintptr_t ptr, size_t size, int classid) {
}
privileged void __asan_handle_no_return(void) {
DebugBreak();
}
privileged void __asan_alloca_poison(uintptr_t addr, uintptr_t size) {
}
privileged void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
}
privileged void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr,
void **beg, void **end) {
return NULL;
}
privileged void *__asan_get_current_fake_stack(void) {
return NULL;
}

View File

@ -28,13 +28,14 @@
*/ */
nodiscard char *commandvenv(const char *var, const char *cmd) { nodiscard char *commandvenv(const char *var, const char *cmd) {
const char *exepath; const char *exepath;
char pathbuf[PATH_MAX];
if ((exepath = getenv(var))) { if ((exepath = getenv(var))) {
if (!isempty(exepath) && access(exepath, X_OK) != -1) { if (!isempty(exepath) && access(exepath, X_OK) != -1) {
return exepath; return exepath;
} else { } else {
return NULL; return NULL;
} }
} else if ((exepath = commandv(cmd))) { } else if ((exepath = commandv(cmd, pathbuf))) {
return exepath; return exepath;
} else { } else {
return NULL; return NULL;

View File

@ -23,6 +23,7 @@
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/log/gdb.h" #include "libc/log/gdb.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.h" #include "libc/runtime/symbols.h"

View File

@ -29,7 +29,6 @@ COSMOPOLITAN_C_START_
struct sigset; struct sigset;
struct winsize; struct winsize;
struct StackFrame;
typedef struct FILE FILE; typedef struct FILE FILE;
extern FILE *g_logfile; extern FILE *g_logfile;
@ -51,7 +50,6 @@ void showcrashreports(void);
void callexitontermination(struct sigset *); void callexitontermination(struct sigset *);
bool32 IsDebuggerPresent(bool); bool32 IsDebuggerPresent(bool);
bool isrunningundermake(void); bool isrunningundermake(void);
void showbacktrace(FILE *, const struct StackFrame *);
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § liblog » logging cosmopolitan § liblog » logging

View File

@ -8,7 +8,6 @@ LIBC_LOG = $(LIBC_LOG_A_DEPS) $(LIBC_LOG_A)
LIBC_LOG_A = o/$(MODE)/libc/log/log.a LIBC_LOG_A = o/$(MODE)/libc/log/log.a
LIBC_LOG_A_FILES := \ LIBC_LOG_A_FILES := \
$(wildcard libc/log/thunks/*) \ $(wildcard libc/log/thunks/*) \
$(wildcard libc/log/elf/*) \
$(wildcard libc/log/*) $(wildcard libc/log/*)
LIBC_LOG_A_HDRS = $(filter %.h,$(LIBC_LOG_A_FILES)) LIBC_LOG_A_HDRS = $(filter %.h,$(LIBC_LOG_A_FILES))
LIBC_LOG_A_SRCS_C = $(filter %.c,$(LIBC_LOG_A_FILES)) LIBC_LOG_A_SRCS_C = $(filter %.c,$(LIBC_LOG_A_FILES))
@ -38,6 +37,7 @@ LIBC_LOG_A_DIRECTDEPS = \
LIBC_TINYMATH \ LIBC_TINYMATH \
LIBC_NEXGEN32E \ LIBC_NEXGEN32E \
LIBC_NT_KERNELBASE \ LIBC_NT_KERNELBASE \
LIBC_MEM \
LIBC_RAND \ LIBC_RAND \
LIBC_RUNTIME \ LIBC_RUNTIME \
LIBC_STDIO \ LIBC_STDIO \
@ -60,17 +60,10 @@ $(LIBC_LOG_A).pkg: \
$(LIBC_LOG_A_OBJS) \ $(LIBC_LOG_A_OBJS) \
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/log/die.o \ $(LIBC_LOG_A_OBJS): \
o/$(MODE)/libc/log/perror.o \ OVERRIDE_CFLAGS += \
o/$(MODE)/libc/log/ftrace.o \ $(NO_MAGIC) \
o/$(MODE)/libc/log/ubsan.o \ -fwrapv
o/$(MODE)/libc/log/symbols.o \
o/$(MODE)/libc/log/backtrace.o \
o/$(MODE)/libc/log/oncrash.o \
o/$(MODE)/libc/log/shadowargs.o \
o/$(MODE)/libc/log/thunks/__check_fail_ndebug.o: \
OVERRIDE_COPTS += \
$(NO_MAGIC)
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x))) LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS)) LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))

View File

@ -23,10 +23,12 @@
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/fmt/fmt.h" #include "libc/fmt/fmt.h"
#include "libc/log/backtrace.h"
#include "libc/log/gdb.h" #include "libc/log/gdb.h"
#include "libc/log/internal.h" #include "libc/log/internal.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/internal.h" #include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.h" #include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -163,7 +165,6 @@ relegated static void ShowCrashReport(int err, FILE *f, int sig,
} }
fputc('\n', f); fputc('\n', f);
fflush(f); fflush(f);
memsummary(fileno(f));
ShowMemoryMappings(fileno(f)); ShowMemoryMappings(fileno(f));
} }

View File

@ -21,6 +21,12 @@
.privileged .privileged
.source __FILE__ .source __FILE__
/ @fileoverview Address Sanitizer Thunks
/
/ This has tiny code size and reduces API surface area
/ since ASAN has the same stylistic hugeness as UBSAN.
/ We also guard all the functions, against reentrancy.
__asan_load1: __asan_load1:
push $1 push $1
jmp OnLoad jmp OnLoad
@ -43,13 +49,11 @@ __asan_load16:
.endfn __asan_load16,globl .endfn __asan_load16,globl
__asan_load32: __asan_load32:
push $32 push $32
/ fallthrough / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_load32,globl .endfn __asan_load32,globl
OnLoad: pop %rsi OnLoad: pop %rsi
.globl __asan_loadN
.weak __asan_loadN
ezlea __asan_loadN,ax ezlea __asan_loadN,ax
jmp OnAsan jmp __asan_report_noreentry
.endfn OnStore .endfn OnStore
__asan_store1: __asan_store1:
@ -74,13 +78,11 @@ __asan_store16:
.endfn __asan_store16,globl .endfn __asan_store16,globl
__asan_store32: __asan_store32:
push $32 push $32
/ fallthrough / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_store32,globl .endfn __asan_store32,globl
OnStore:pop %rsi OnStore:pop %rsi
.globl __asan_storeN
.weak __asan_storeN
ezlea __asan_storeN,ax ezlea __asan_storeN,ax
jmp OnAsan jmp __asan_report_noreentry
.endfn OnStore .endfn OnStore
__asan_report_load1: __asan_report_load1:
@ -101,14 +103,12 @@ __asan_report_load8:
.endfn __asan_report_load8,globl .endfn __asan_report_load8,globl
__asan_report_load16: __asan_report_load16:
push $16 push $16
/ fallthrough / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_load16,globl .endfn __asan_report_load16,globl
OnReportLoad: OnReportLoad:
pop %rsi pop %rsi
.globl __asan_report_load_n
.weak __asan_report_load_n
ezlea __asan_report_load_n,ax ezlea __asan_report_load_n,ax
jmp OnAsan jmp __asan_report_noreentry
.endfn OnReportLoad .endfn OnReportLoad
__asan_report_store1: __asan_report_store1:
@ -133,33 +133,31 @@ __asan_report_store16:
.endfn __asan_report_store16,globl .endfn __asan_report_store16,globl
__asan_report_store32: __asan_report_store32:
push $32 push $32
/ fallthrough / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_report_store32,globl .endfn __asan_report_store32,globl
ReportStore: ReportStore:
pop %rsi pop %rsi
.globl __asan_report_store_n
.weak __asan_report_store_n
ezlea __asan_report_store_n,ax ezlea __asan_report_store_n,ax
/ fallthrough / 𝑠𝑙𝑖𝑑𝑒
.endfn ReportStore .endfn ReportStore
OnAsan: test %rax,%rax __asan_report_noreentry:
jz 1f push %rbp
jmp *%rax mov %rsp,%rbp
1: ret cmpb $0,noreentry(%rip)
.endfn OnAsan jnz 2f
incb noreentry(%rip)
call *%rax
decb noreentry(%rip)
pop %rbp
ret
2: call abort
.endfn __asan_report_noreentry
__asan_stack_free_0: __asan_stack_free_0:
push $0 push $0
/ fallthrough jmp OnStackFree
.endfn __asan_stack_free_0,globl .endfn __asan_stack_free_0,globl
OnStackFree:
pop %rdx
.globl __asan_stack_free
.weak __asan_stack_free
ezlea __asan_stack_free,ax
jmp OnAsan
.endfn OnStackFree
__asan_stack_free_1: __asan_stack_free_1:
push $1 push $1
jmp OnStackFree jmp OnStackFree
@ -198,20 +196,17 @@ __asan_stack_free_9:
.endfn __asan_stack_free_9,globl .endfn __asan_stack_free_9,globl
__asan_stack_free_10: __asan_stack_free_10:
push $10 push $10
jmp OnStackFree / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_free_10,globl .endfn __asan_stack_free_10,globl
OnStackFree:
pop %rdx
jmp __asan_stack_free
.endfn OnStackFree
__asan_stack_malloc_0: __asan_stack_malloc_0:
push $0 push $0
/ fallthrough jmp OnStackMalloc
.endfn __asan_stack_malloc_0,globl .endfn __asan_stack_malloc_0,globl
OnStackMalloc:
pop %rsi
.globl __asan_stack_malloc
.weak __asan_stack_malloc
ezlea __asan_stack_malloc,ax
jmp OnAsan
.endfn OnStackMalloc
__asan_stack_malloc_1: __asan_stack_malloc_1:
push $1 push $1
jmp OnStackMalloc jmp OnStackMalloc
@ -250,11 +245,54 @@ __asan_stack_malloc_9:
.endfn __asan_stack_malloc_9,globl .endfn __asan_stack_malloc_9,globl
__asan_stack_malloc_10: __asan_stack_malloc_10:
push $10 push $10
jmp OnStackMalloc / 𝑠𝑙𝑖𝑑𝑒
.endfn __asan_stack_malloc_10,globl .endfn __asan_stack_malloc_10,globl
OnStackMalloc:
pop %rsi
jmp __asan_stack_malloc
.endfn OnStackMalloc
__asan_handle_no_return:
ret
.endfn __asan_handle_no_return,globl
__asan_before_dynamic_init:
ret
.endfn __asan_before_dynamic_init,globl
__asan_after_dynamic_init:
ret
.endfn __asan_after_dynamic_init,globl
__asan_unregister_globals:
ret
.endfn __asan_unregister_globals,globl
__asan_version_mismatch_check_v8:
ret
.endfn __asan_version_mismatch_check_v8,globl
/ Initializes Address Sanitizer runtime earlier if linked.
.init.start 301,_init_asan
push %rdi
push %rsi
mov %r12,%rdi
mov %r13,%rsi
mov %r14,%rdx
mov %r15,%rcx
call __asan_init
pop %rsi
pop %rdi
.init.end 301,_init_asan
.rodata.cst4 .rodata.cst4
__asan_option_detect_stack_use_after_return: __asan_option_detect_stack_use_after_return:
.long 1 .long 1
.endobj __asan_option_detect_stack_use_after_return,globl .endobj __asan_option_detect_stack_use_after_return,globl
.previous .previous
.bss
noreentry:
.byte 0
.endobj noreentry
.previous

View File

@ -6,9 +6,7 @@ PKGS += LIBC_MATH
LIBC_MATH_ARTIFACTS += LIBC_MATH_A LIBC_MATH_ARTIFACTS += LIBC_MATH_A
LIBC_MATH = $(LIBC_MATH_A_DEPS) $(LIBC_MATH_A) LIBC_MATH = $(LIBC_MATH_A_DEPS) $(LIBC_MATH_A)
LIBC_MATH_A = o/$(MODE)/libc/math/math.a LIBC_MATH_A = o/$(MODE)/libc/math/math.a
LIBC_MATH_A_FILES := \ LIBC_MATH_A_FILES := $(wildcard libc/math/*)
$(wildcard libc/math/*) \
$(wildcard libc/math/delegates/*)
LIBC_MATH_A_SRCS_A = $(filter %.s,$(LIBC_MATH_A_FILES)) LIBC_MATH_A_SRCS_A = $(filter %.s,$(LIBC_MATH_A_FILES))
LIBC_MATH_A_SRCS_S = $(filter %.S,$(LIBC_MATH_A_FILES)) LIBC_MATH_A_SRCS_S = $(filter %.S,$(LIBC_MATH_A_FILES))
LIBC_MATH_A_SRCS_C = $(filter %.c,$(LIBC_MATH_A_FILES)) LIBC_MATH_A_SRCS_C = $(filter %.c,$(LIBC_MATH_A_FILES))

View File

@ -26,34 +26,61 @@
/ @param %rsi is ignored / @param %rsi is ignored
/ @param %rdx is ignored / @param %rdx is ignored
_ZdlPvSt11align_val_tRKSt9nothrow_t: _ZdlPvSt11align_val_tRKSt9nothrow_t:
/ operator delete(void*, std::align_val_t, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
_ZdaPvSt11align_val_tRKSt9nothrow_t: _ZdaPvSt11align_val_tRKSt9nothrow_t:
/ operator delete[](void*, std::align_val_t, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
_ZdlPvRKSt9nothrow_t: _ZdlPvRKSt9nothrow_t:
/ operator delete(void*, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvRKSt9nothrow_t,weak
_ZdaPvRKSt9nothrow_t: _ZdaPvRKSt9nothrow_t:
/ operator delete[](void*, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvRKSt9nothrow_t,weak
_ZdlPvmSt11align_val_t: _ZdlPvmSt11align_val_t:
/ operator delete(void*, unsigned long, std::align_val_t)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvmSt11align_val_t,weak
_ZdaPvmSt11align_val_t: _ZdaPvmSt11align_val_t:
/ operator delete[](void*, unsigned long, std::align_val_t)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvmSt11align_val_t,weak
_ZdlPvSt11align_val_t: _ZdlPvSt11align_val_t:
/ operator delete(void*, std::align_val_t)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_t,weak
_ZdaPvSt11align_val_t: _ZdaPvSt11align_val_t:
/ operator delete[](void*, std::align_val_t)
nop nop
_ZdaPvm:nop / 𝑠𝑙𝑖𝑑𝑒
_ZdlPvm:nop .endfn _ZdaPvSt11align_val_t,weak
_ZdaPv: nop _ZdaPvm:
_ZdlPv: jmp *hook$free(%rip) / operator delete[](void*, unsigned long):
.endfn _ZdlPv,globl,weak nop
.endfn _ZdaPv,globl,weak / 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPvm,globl,weak .endfn _ZdaPvm,weak
.endfn _ZdlPvm,globl,weak _ZdlPvm:
.endfn _ZdaPvRKSt9nothrow_t,globl,weak / operator delete(void*, unsigned long)
.endfn _ZdlPvRKSt9nothrow_t,globl,weak nop
.endfn _ZdaPvSt11align_val_t,globl,weak / 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdlPvSt11align_val_t,globl,weak .endfn _ZdlPvm,weak
.endfn _ZdaPvmSt11align_val_t,globl,weak _ZdaPv:
.endfn _ZdlPvmSt11align_val_t,globl,weak / operator delete[](void*)
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,globl,weak nop
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,globl,weak / 𝑠𝑙𝑖𝑑𝑒
.endfn _ZdaPv,weak
_ZdlPv:
/ operator delete(void*)
jmp *hook$free(%rip)
.endfn _ZdlPv,weak

View File

@ -26,15 +26,24 @@
/ @param %rsi is ignored / @param %rsi is ignored
/ @return new memory or NULL on OOM / @return new memory or NULL on OOM
_ZnamRKSt9nothrow_t: _ZnamRKSt9nothrow_t:
/ operator new[](unsigned long, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamRKSt9nothrow_t,weak
_ZnwmRKSt9nothrow_t: _ZnwmRKSt9nothrow_t:
/ operator new(unsigned long, std::nothrow_t const&)
nop nop
_Znam: nop / 𝑠𝑙𝑖𝑑𝑒
_Znwm: test %rdi,%rdi .endfn _ZnwmRKSt9nothrow_t,weak
_Znam:
/ operator new[](unsigned long)
nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _Znam,weak
_Znwm:
/ operator new(unsigned long)
test %rdi,%rdi
jne 1f jne 1f
mov $1,%edi mov $1,%edi
1: jmp *hook$malloc(%rip) 1: jmp *hook$malloc(%rip)
.endfn _Znwm,globl,weak .endfn _Znwm,weak
.endfn _Znam,globl,weak
.endfn _ZnwmRKSt9nothrow_t,globl,weak
.endfn _ZnamRKSt9nothrow_t,globl,weak

View File

@ -27,12 +27,22 @@
/ @param %rdx is ignored / @param %rdx is ignored
/ @return new memory or NULL on OOM / @return new memory or NULL on OOM
_ZnamSt11align_val_tRKSt9nothrow_t: _ZnamSt11align_val_tRKSt9nothrow_t:
/ operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
_ZnwmSt11align_val_tRKSt9nothrow_t: _ZnwmSt11align_val_tRKSt9nothrow_t:
/ operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
_ZnwmSt11align_val_t: _ZnwmSt11align_val_t:
/ operator new(unsigned long, std::align_val_t)
nop nop
/ 𝑠𝑙𝑖𝑑𝑒
.endfn _ZnwmSt11align_val_t,weak
_ZnamSt11align_val_t: _ZnamSt11align_val_t:
/ operator new[](unsigned long, std::align_val_t)
test %rdi,%rdi test %rdi,%rdi
jnz 1f jnz 1f
mov $1,%eax mov $1,%eax
@ -41,7 +51,4 @@ _ZnamSt11align_val_t:
cmovb %rax,%rsi cmovb %rax,%rsi
xchg %rdi,%rsi xchg %rdi,%rsi
jmp *hook$memalign(%rip) jmp *hook$memalign(%rip)
.endfn _ZnwmSt11align_val_t,globl,weak .endfn _ZnamSt11align_val_t,weak
.endfn _ZnamSt11align_val_t,globl,weak
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,globl,weak
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,globl,weak

View File

@ -20,15 +20,15 @@
#include "libc/macros.h" #include "libc/macros.h"
.source __FILE__ .source __FILE__
.initbss 800,_init_calloc .initbss 202,_init_calloc
hook$calloc: hook$calloc:
.quad 0 .quad 0
.endobj hook$calloc,globl,hidden .endobj hook$calloc,globl,hidden
.previous .previous
.init.start 800,_init_calloc .init.start 202,_init_calloc
.hidden dlcalloc .hidden dlcalloc
ezlea dlcalloc,ax ezlea dlcalloc,ax
stosq stosq
yoink free yoink free
.init.end 800,_init_calloc .init.end 202,_init_calloc

View File

@ -20,16 +20,16 @@
#include "libc/macros.h" #include "libc/macros.h"
.source __FILE__ .source __FILE__
.initbss 800,_init_free .initbss 202,_init_free
hook$free: hook$free:
.quad 0 .quad 0
.endobj hook$free,globl,hidden .endobj hook$free,globl,hidden
.previous .previous
.init.start 800,_init_free .init.start 202,_init_free
ezlea dlfree,ax ezlea dlfree,ax
stosq stosq
yoink realloc yoink realloc
.init.end 800,_init_free .init.end 202,_init_free
.hidden dlfree .hidden dlfree

View File

@ -0,0 +1,18 @@
#ifndef COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
#define COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern void (*hook$free)(void *);
extern void *(*hook$malloc)(size_t);
extern void *(*hook$calloc)(size_t, size_t);
extern void *(*hook$memalign)(size_t, size_t);
extern void *(*hook$realloc)(void *, size_t);
extern void *(*hook$realloc_in_place)(void *, size_t);
extern void *(*hook$valloc)(size_t);
extern void *(*hook$pvalloc)(size_t);
extern size_t (*hook$malloc_usable_size)(const void *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_HOOK_HOOK_H_ */

View File

@ -20,16 +20,15 @@
#include "libc/macros.h" #include "libc/macros.h"
.source __FILE__ .source __FILE__
.initbss 800,_init_malloc .initbss 202,_init_malloc
hook$malloc: hook$malloc:
.quad 0 .quad 0
.endobj hook$malloc,globl,hidden .endobj hook$malloc,globl,hidden
.previous .previous
.init.start 800,_init_malloc .init.start 202,_init_malloc
.hidden dlmalloc
ezlea dlmalloc,ax ezlea dlmalloc,ax
stosq stosq
yoink free yoink free
.init.end 800,_init_malloc .init.end 202,_init_malloc
.hidden dlmalloc

View File

@ -0,0 +1,33 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_malloc_usable_size
hook$malloc_usable_size:
.quad 0
.endobj hook$malloc_usable_size,globl,hidden
.previous
.init.start 202,_init_malloc_usable_size
.hidden dlmalloc_usable_size
ezlea dlmalloc_usable_size,ax
stosq
.init.end 202,_init_malloc_usable_size

View File

@ -20,16 +20,15 @@
#include "libc/macros.h" #include "libc/macros.h"
.source __FILE__ .source __FILE__
.initbss 800,_init_memalign .initbss 202,_init_memalign
hook$memalign: hook$memalign:
.quad 0 .quad 0
.endobj hook$memalign,globl,hidden .endobj hook$memalign,globl,hidden
.previous .previous
.init.start 800,_init_memalign .init.start 202,_init_memalign
.hidden dlmemalign
ezlea dlmemalign,ax ezlea dlmemalign,ax
stosq stosq
yoink free yoink free
.init.end 800,_init_memalign .init.end 202,_init_memalign
.hidden dlmemalign

View File

@ -0,0 +1,34 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_posix_memalign
hook$posix_memalign:
.quad 0
.endobj hook$posix_memalign,globl,hidden
.previous
.init.start 202,_init_posix_memalign
.hidden dlposix_memalign
ezlea dlposix_memalign,ax
stosq
yoink free
.init.end 202,_init_posix_memalign

View File

@ -0,0 +1,34 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_pvalloc
hook$pvalloc:
.quad 0
.endobj hook$pvalloc,globl,hidden
.previous
.init.start 202,_init_pvalloc
.hidden dlpvalloc
ezlea dlpvalloc,ax
stosq
yoink free
.init.end 202,_init_pvalloc

View File

@ -20,15 +20,15 @@
#include "libc/macros.h" #include "libc/macros.h"
.source __FILE__ .source __FILE__
.initbss 800,_init_realloc .initbss 202,_init_realloc
hook$realloc: hook$realloc:
.quad 0 .quad 0
.endobj hook$realloc,globl,hidden .endobj hook$realloc,globl,hidden
.previous .previous
.init.start 800,_init_realloc .init.start 202,_init_realloc
.hidden dlrealloc .hidden dlrealloc
ezlea dlrealloc,ax ezlea dlrealloc,ax
stosq stosq
yoink free yoink free
.init.end 800,_init_realloc .init.end 202,_init_realloc

View File

@ -0,0 +1,34 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_realloc_in_place
hook$realloc_in_place:
.quad 0
.endobj hook$realloc_in_place,globl,hidden
.previous
.init.start 202,_init_realloc_in_place
.hidden dlrealloc_in_place
ezlea dlrealloc_in_place,ax
stosq
yoink free
.init.end 202,_init_realloc_in_place

View File

@ -0,0 +1,34 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_valloc
hook$valloc:
.quad 0
.endobj hook$valloc,globl,hidden
.previous
.init.start 202,_init_valloc
.hidden dlvalloc
ezlea dlvalloc,ax
stosq
yoink free
.init.end 202,_init_valloc

View File

@ -39,4 +39,3 @@
/ @see dlmalloc() / @see dlmalloc()
malloc: jmp *hook$malloc(%rip) malloc: jmp *hook$malloc(%rip)
.endfn malloc,globl .endfn malloc,globl

View File

@ -40,14 +40,3 @@
malloc_usable_size: malloc_usable_size:
jmp *hook$malloc_usable_size(%rip) jmp *hook$malloc_usable_size(%rip)
.endfn malloc_usable_size,globl .endfn malloc_usable_size,globl
.initbss 800,_init_malloc_usable_size
hook$malloc_usable_size:
.quad 0
.endobj hook$malloc_usable_size,globl,hidden
.previous
.init.start 800,_init_malloc_usable_size
ezlea dlmalloc_usable_size,ax
stosq
.init.end 800,_init_malloc_usable_size

View File

@ -6,11 +6,15 @@ PKGS += LIBC_MEM
LIBC_MEM_ARTIFACTS += LIBC_MEM_A LIBC_MEM_ARTIFACTS += LIBC_MEM_A
LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A) LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
LIBC_MEM_A_FILES := $(wildcard libc/mem/*)
LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES)) LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES)) LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES)) LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
LIBC_MEM_A_FILES := \
$(wildcard libc/mem/*) \
$(wildcard libc/mem/cxx/*) \
$(wildcard libc/mem/hook/*)
LIBC_MEM_A_SRCS = \ LIBC_MEM_A_SRCS = \
$(LIBC_MEM_A_SRCS_S) \ $(LIBC_MEM_A_SRCS_S) \
$(LIBC_MEM_A_SRCS_C) $(LIBC_MEM_A_SRCS_C)

View File

@ -35,17 +35,3 @@
posix_memalign: posix_memalign:
jmp *hook$posix_memalign(%rip) jmp *hook$posix_memalign(%rip)
.endfn posix_memalign,globl .endfn posix_memalign,globl
.initbss 800,_init_posix_memalign
hook$posix_memalign:
.quad 0
.endobj hook$posix_memalign,globl,hidden
.previous
.init.start 800,_init_posix_memalign
.hidden dlposix_memalign
ezlea dlposix_memalign,ax
stosq
.init.end 800,_init_posix_memalign
yoink free

View File

@ -22,24 +22,10 @@
.source __FILE__ .source __FILE__
/ Equivalent to valloc(minimum-page-that-holds(n)), that is, / Equivalent to valloc(minimum-page-that-holds(n)), that is,
/ round up n to nearest PAGESIZE. / round up n to nearest pagesize.
/ /
/ @param rdi is number of bytes needed / @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno / @return rax is memory address, or NULL w/ errno
/ @see dlpvalloc() / @see dlpvalloc()
pvalloc:jmp *hook$pvalloc(%rip) pvalloc:jmp *hook$pvalloc(%rip)
.endfn pvalloc,globl .endfn pvalloc,globl
.initbss 800,_init_pvalloc
hook$pvalloc:
.quad 0
.endobj hook$pvalloc,globl,hidden
.previous
.init.start 800,_init_pvalloc
.hidden dlpvalloc
ezlea dlpvalloc,ax
stosq
.init.end 800,_init_pvalloc
yoink free

View File

@ -55,5 +55,6 @@
/ @note realloc(p=0, n=0) → malloc(32) / @note realloc(p=0, n=0) → malloc(32)
/ @note realloc(p≠0, n=0) → free(p) / @note realloc(p≠0, n=0) → free(p)
/ @see dlrealloc() / @see dlrealloc()
realloc:jmp *hook$realloc(%rip) realloc:
jmp *hook$realloc(%rip)
.endfn realloc,globl .endfn realloc,globl

View File

@ -23,12 +23,12 @@
/ Resizes the space allocated for p to size n, only if this can be / Resizes the space allocated for p to size n, only if this can be
/ done without moving p (i.e., only if there is adjacent space / done without moving p (i.e., only if there is adjacent space
/ available if n is greater than p's current allocated size, or n is / available if n is greater than p's current allocated size, or n
/ less than or equal to p's size). This may be used instead of plain / is less than or equal to p's size). This may be used instead of
/ realloc if an alternative allocation strategy is needed upon failure / plain realloc if an alternative allocation strategy is needed
/ to expand space, for example, reallocation of a buffer that must be / upon failure to expand space, for example, reallocation of a
/ memory-aligned or cleared. You can use realloc_in_place to trigger / buffer that must be memory-aligned or cleared. You can use
/ these alternatives only when needed. / realloc_in_place to trigger these alternatives only when needed.
/ /
/ @param rdi (p) is address of current allocation / @param rdi (p) is address of current allocation
/ @param rsi (newsize) is number of bytes needed / @param rsi (newsize) is number of bytes needed
@ -37,17 +37,3 @@
realloc_in_place: realloc_in_place:
jmp *hook$realloc_in_place(%rip) jmp *hook$realloc_in_place(%rip)
.endfn realloc_in_place,globl .endfn realloc_in_place,globl
.initbss 800,_init_realloc_in_place
hook$realloc_in_place:
.quad 0
.endobj hook$realloc_in_place,globl,hidden
.previous
.init.start 800,_init_realloc_in_place
.hidden dlrealloc_in_place
ezlea dlrealloc_in_place,ax
stosq
.init.end 800,_init_realloc_in_place
yoink free

View File

@ -21,24 +21,10 @@
#include "libc/notice.inc" #include "libc/notice.inc"
.source __FILE__ .source __FILE__
/ Equivalent to memalign(PAGESIZE, n). / Equivalent to memalign(4096, n).
/ /
/ @param rdi is number of bytes needed / @param rdi is number of bytes needed
/ @return rax is memory address, or NULL w/ errno / @return rax is memory address, or NULL w/ errno
/ @see dlvalloc() / @see dlvalloc()
valloc: jmp *hook$valloc(%rip) valloc: jmp *hook$valloc(%rip)
.endfn valloc,globl .endfn valloc,globl
.initbss 800,_init_valloc
hook$valloc:
.quad 0
.endobj hook$valloc,globl,hidden
.previous
.init.start 800,_init_valloc
.hidden dlvalloc
ezlea dlvalloc,ax
stosq
.init.end 800,_init_valloc
yoink free

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_ #ifndef COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_ #define COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
#include "libc/nexgen32e/stackframe.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
struct StackFrame;
struct Garbages { struct Garbages {
size_t i, n; size_t i, n;
struct Garbage { struct Garbage {

View File

@ -25,9 +25,8 @@
world's most popular functionone all programmers love. world's most popular functionone all programmers love.
This implementation is the fastest and nearly the tiniest too. This implementation is the fastest and nearly the tiniest too.
It doesn't clobber general registers. It won't break down on old It doesn't break when copying backwards or on misaligned data.
computers or misaligned data. It's so easy that even a child It's so easy that even a child could use it, and they do.
could use itand they do.
*/ */
#include "libc/nexgen32e/x86feature.h" #include "libc/nexgen32e/x86feature.h"
#include "libc/macros.h" #include "libc/macros.h"
@ -53,11 +52,10 @@ memcpy: mov %rdi,%rax
/ @param rdi is dest / @param rdi is dest
/ @param rsi is src / @param rsi is src
/ @param rdx is number of bytes / @param rdx is number of bytes
/ @clob flags,xmm3,xmm4 / @clob flags,rcx,xmm3,xmm4
/ @mode long / @mode long
.align 16 .align 16
MemCpy: .leafprologue MemCpy: .leafprologue
push %rcx
mov $.Lmemcpytab.ro.size,%ecx mov $.Lmemcpytab.ro.size,%ecx
cmp %rcx,%rdx cmp %rcx,%rdx
cmovb %rdx,%rcx cmovb %rdx,%rcx
@ -95,8 +93,7 @@ MemCpy: .leafprologue
mov %rcx,(%rdi) mov %rcx,(%rdi)
mov %rbx,-8(%rdi,%rdx) mov %rbx,-8(%rdi,%rdx)
1: pop %rbx 1: pop %rbx
.L0: pop %rcx .L0: .leafepilogue
.leafepilogue
.L4: push %rbx .L4: push %rbx
mov (%rsi),%ecx mov (%rsi),%ecx
mov -4(%rsi,%rdx),%ebx mov -4(%rsi,%rdx),%ebx

View File

@ -27,6 +27,7 @@
/ @param rsi is src / @param rsi is src
/ @param rdx is number of bytes / @param rdx is number of bytes
/ @return original rdi copied to rax / @return original rdi copied to rax
/ @clob flags,rcx
/ @asyncsignalsafe / @asyncsignalsafe
memmove: memmove:
mov %rdi,%rax mov %rdi,%rax
@ -36,7 +37,6 @@ memmove:
MemMove: MemMove:
.leafprologue .leafprologue
.profilable .profilable
push %rcx
push %rdi push %rdi
push %rsi push %rsi
mov %rdx,%rcx mov %rdx,%rcx
@ -49,7 +49,6 @@ MemMove:
cld cld
pop %rsi pop %rsi
pop %rdi pop %rdi
pop %rcx
.leafepilogue .leafepilogue
.endfn memmove,globl .endfn memmove,globl
.source __FILE__ .source __FILE__

View File

@ -43,12 +43,11 @@ memset: mov %rdi,%rax
/ @param rdi is dest / @param rdi is dest
/ @param esi is the byte to set / @param esi is the byte to set
/ @param edx is the number of bytes to set / @param edx is the number of bytes to set
/ @clob flags,xmm3 / @clob flags,rcx,xmm3
/ @mode long / @mode long
MemSet: .leafprologue MemSet: .leafprologue
.profilable .profilable
push %rbx push %rbx
push %rcx
movd %esi,%xmm3 movd %esi,%xmm3
mov $.Lmemsettab.ro.size,%ecx mov $.Lmemsettab.ro.size,%ecx
cmp %rcx,%rdx cmp %rcx,%rdx
@ -77,8 +76,7 @@ MemSet: .leafprologue
ja 1b ja 1b
movdqu %xmm3,-16(%rdi,%rdx) movdqu %xmm3,-16(%rdi,%rdx)
pxor %xmm3,%xmm3 pxor %xmm3,%xmm3
.L0: pop %rcx .L0: pop %rbx
pop %rbx
.leafepilogue .leafepilogue
.L8: movzbq %sil,%rbx .L8: movzbq %sil,%rbx
mov $0x0101010101010101,%rcx mov $0x0101010101010101,%rcx

View File

@ -0,0 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_STACKFRAME_H_
#define COSMOPOLITAN_LIBC_NEXGEN32E_STACKFRAME_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct StackFrame {
struct StackFrame *next;
intptr_t addr;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NEXGEN32E_STACKFRAME_H_ */

View File

@ -40,6 +40,10 @@ _construct:
je 2f je 2f
push %rax push %rax
push %rcx push %rcx
mov %r12,%rdi
mov %r13,%rsi
mov %r14,%rdx
mov %r15,%rcx
call *(%rax) call *(%rax)
pop %rcx pop %rcx
pop %rax pop %rax

View File

@ -17,59 +17,39 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "dsp/mpeg/ycbcrio.h" #include "libc/calls/internal.h"
#include "libc/fmt/fmt.h" #include "libc/nt/memory.h"
#include "libc/log/check.h" #include "libc/nt/runtime.h"
#include "libc/mem/mem.h" #include "libc/runtime/directmap.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.h"
#define USAGE \ static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
" [FLAGS] [PATH...]\n\ unsigned prot, unsigned flags,
\n\ int fd, int64_t off) {
Flags:\n\ struct DirectMap res;
-h shows this information\n\ if ((res.maphandle = CreateFileMappingNuma(
\n" fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
static char *inpath_; kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
static void PrintUsage(int rc, FILE *f) { off >> 32, off, size, addr,
fputs("Usage: ", f); kNtNumaNoPreferredNode))) {
fputs(program_invocation_name, f); CloseHandle(res.maphandle);
fputs(USAGE, f); res.maphandle = kNtInvalidHandleValue;
exit(rc); res.addr = (void *)(intptr_t)winerr();
}
static void GetOpts(int *argc, char *argv[]) {
int opt;
while ((opt = getopt(*argc, argv, "?h")) != -1) {
switch (opt) {
case '?':
case 'h':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
} }
} else {
res.maphandle = kNtInvalidHandleValue;
res.addr = (void *)(intptr_t)winerr();
} }
return res;
} }
static void ProcessFile(struct Ycbcrio *m) { struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
/* m->frame-> */ unsigned flags, int fd, int64_t off) {
} if (!IsWindows()) {
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
int main(int argc, char *argv[]) { kNtInvalidHandleValue};
size_t i; } else {
struct Ycbcrio *m; return DirectMapNt(addr, size, prot, flags, fd, off);
GetOpts(&argc, argv);
for (i = optind; i < argc; ++i) {
inpath_ = argv[i];
m = YcbcrioOpen(inpath_, NULL);
ProcessFile(m);
YcbcrioClose(&m);
} }
return 0;
} }

View File

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_
#define COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct DirectMap {
void *addr;
int64_t maphandle;
};
struct DirectMap DirectMap(void *, size_t, unsigned, unsigned, int, int64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_DIRECTMAP_H_ */

View File

@ -17,7 +17,6 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/bits/pushpop.h"
#include "libc/bits/safemacros.h" #include "libc/bits/safemacros.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/limits.h" #include "libc/limits.h"
@ -51,8 +50,14 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
int unmapfile(struct MappedFile *mf) { int unmapfile(struct MappedFile *mf) {
int rc; int rc;
rc = 0; rc = 0;
rc |= munmap_s(&mf->addr, mf->size); if (mf->addr != MAP_FAILED) {
rc |= close_s(&mf->fd); rc |= munmap(mf->addr, mf->size);
pushmov(&mf->size, 0); mf->addr = MAP_FAILED;
}
if (mf->fd != -1) {
rc |= close(mf->fd);
mf->fd = -1;
}
mf->size = 0;
return rc; return rc;
} }

View File

@ -25,6 +25,7 @@
#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h" #include "libc/nt/thunk/msabi.h"

View File

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_ #ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_ #define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/nexgen32e/stackframe.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
@ -13,8 +14,6 @@ COSMOPOLITAN_C_START_
* using very few lines of code. * using very few lines of code.
*/ */
struct StackFrame;
/** /**
* Releases resource when function returns. * Releases resource when function returns.
* *

View File

@ -19,10 +19,8 @@
*/ */
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/bits.h" #include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h" #include "libc/bits/weaken.h"
#include "libc/conv/conv.h" #include "libc/conv/conv.h"
#include "libc/conv/sizemultiply.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
@ -70,8 +68,9 @@ bool grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
p1 = isheap(*p) ? *p : NULL; p1 = isheap(*p) ? *p : NULL;
p2 = NULL; p2 = NULL;
n1 = *capacity; n1 = *capacity;
n2 = (*p ? n1 + (n1 >> 1) : max(4, INITIAL_CAPACITY / itemsize)) + extra; n2 = (*p ? n1 + (n1 >> 1) : MAX(4, INITIAL_CAPACITY / itemsize)) + extra;
if (sizemultiply(&t1, n1, itemsize) && sizemultiply(&t2, n2, itemsize)) { if (!__builtin_mul_overflow(n1, itemsize, &t1) &&
!__builtin_mul_overflow(n2, itemsize, &t2)) {
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) { if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
if (!p1 && *p) memcpy(p2, *p, t1); if (!p1 && *p) memcpy(p2, *p, t1);
memset((char *)p2 + t1, 0, t2 - t1); memset((char *)p2 + t1, 0, t2 - t1);

View File

@ -14,6 +14,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
hidden extern bool _mmap_asan_mode;
hidden extern char **g_freebsdhint; hidden extern char **g_freebsdhint;
hidden extern unsigned g_runstate; hidden extern unsigned g_runstate;
hidden extern void *g_stacktop; hidden extern void *g_stacktop;

View File

@ -1,13 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ #ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_ #define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
#include "libc/nexgen32e/vendor.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
#define kMappingsSize 0x0000100000000000 /* 16TB */ #define kAutomapStart 0x0000100000000000
#define kMappingsStart (IsGenuineCosmo() ? 0x300000000000 : 0x200000000000) #define kAutomapSize 0x0000100000000000
#define kFixedMappingsStart 0x0000100000000000 #define kFixedmapStart 0x0000200000000000
#define kFixedMappingsSize kMappingsSize
struct MemoryIntervals { struct MemoryIntervals {
int i; int i;
@ -27,6 +25,7 @@ int TrackMemoryInterval(struct MemoryIntervals *, int, int, long);
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int, int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void (*)(struct MemoryIntervals *, int, int)); void (*)(struct MemoryIntervals *, int, int));
void ReleaseMemoryNt(struct MemoryIntervals *, int, int); void ReleaseMemoryNt(struct MemoryIntervals *, int, int);
int UntrackMemoryIntervals(void *, size_t);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -18,13 +18,14 @@
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/assert.h" #include "libc/assert.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/dce.h" #include "libc/dce.h"
#include "libc/log/asan.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/rand/rand.h" #include "libc/rand/rand.h"
#include "libc/runtime/directmap.h"
#include "libc/runtime/memtrack.h" #include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
@ -32,79 +33,14 @@
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"
#define IP(X) (intptr_t)(X) #define IP(X) (intptr_t)(X)
#define VIP(X) (void *)IP(X) #define VIP(X) (void *)IP(X)
#define COORD(a) (int)(IP(a) >> 16) #define ADDR(c) (void *)(IP(c) << 16)
#define ADDR(c) (void *)(IP(c) << 16) #define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1))) #define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
#define LAST_COORD(a, n) (COORD(a) + (ROUNDUP(n, FRAMESIZE) >> 16) - 1)
struct DirectMap {
void *addr;
int64_t maphandle;
};
struct MemoryIntervals _mmi; struct MemoryIntervals _mmi;
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
unsigned prot, unsigned flags,
int fd, int64_t off) {
struct DirectMap res; /* NT IS TORTURE */
if ((res.maphandle = CreateFileMappingNuma(
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
off >> 32, off, size, addr,
kNtNumaNoPreferredNode))) {
CloseHandle(res.maphandle);
res.maphandle = kNtInvalidHandleValue;
res.addr = VIP(winerr());
}
} else {
res.maphandle = kNtInvalidHandleValue;
res.addr = VIP(winerr());
}
return res;
}
static struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
if (!IsWindows()) {
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
kNtInvalidHandleValue};
} else {
return DirectMapNt(addr, size, prot, flags, fd, off);
}
}
static int UntrackMemoryIntervals(void *addr, size_t size) {
return ReleaseMemoryIntervals(&_mmi, COORD(addr), LAST_COORD(addr, size),
ReleaseMemoryNt);
}
/**
* Releases memory pages.
*
* @param addr is a pointer within any memory mapped region the process
* has permission to control, such as address ranges returned by
* mmap(), the program image itself, etc.
* @param size is the amount of memory to unmap, which needn't be a
* multiple of FRAMESIZE, and may be a subset of that which was
* mapped previously, and may punch holes in existing mappings,
* but your mileage may vary on windows
* @return 0 on success, or -1 w/ errno
*/
int munmap(void *addr, size_t size) {
int rc;
if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
size = ROUNDUP(size, FRAMESIZE);
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
if (IsWindows()) return 0;
return munmap$sysv(addr, size);
}
/** /**
* Beseeches system for page-table entries. * Beseeches system for page-table entries.
* *
@ -120,8 +56,7 @@ int munmap(void *addr, size_t size) {
* @return virtual base address of new mapping, or MAP_FAILED w/ errno * @return virtual base address of new mapping, or MAP_FAILED w/ errno
*/ */
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
int i; int i, x, n, a, b;
long gap;
struct DirectMap dm; struct DirectMap dm;
if (!size) return VIP(einval()); if (!size) return VIP(einval());
if (!ALIGNED(off)) return VIP(einval()); if (!ALIGNED(off)) return VIP(einval());
@ -134,24 +69,18 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
if (UntrackMemoryIntervals(addr, size) == -1) { if (UntrackMemoryIntervals(addr, size) == -1) {
return MAP_FAILED; return MAP_FAILED;
} }
} else if (_mmi.i) {
if (0 && IsModeDbg()) {
addr = VIP(rand64() & 0x00007ffffffff000);
} else {
for (i = _mmi.i - 1; i > 0; --i) {
gap = _mmi.p[i].x - _mmi.p[i - 1].y - 1;
assert(gap > 0);
if (gap >= (ROUNDUP(size, FRAMESIZE) >> 16)) {
addr = ADDR(_mmi.p[i - 1].y + 1);
break;
}
}
if (!addr) {
addr = ADDR(_mmi.p[_mmi.i - 1].y + 1);
}
}
} else { } else {
addr = VIP(kMappingsStart); x = kAutomapStart >> 16;
n = ROUNDUP(size, FRAMESIZE) >> 16;
for (i = 0; i < _mmi.i; ++i) {
if (_mmi.p[i].y < x) continue;
if (_mmi.p[i].x > x + n - 1) break;
x = _mmi.p[i].y + 1;
}
if (x + n - 1 >= ((kAutomapStart + kAutomapSize) >> 16)) {
return (void *)(intptr_t)enomem();
}
addr = (void *)(intptr_t)((int64_t)x << 16);
} }
assert((flags & MAP_FIXED) || assert((flags & MAP_FIXED) ||
(!isheap(addr) && !isheap((char *)addr + size - 1))); (!isheap(addr) && !isheap((char *)addr + size - 1)));
@ -159,9 +88,13 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
if (dm.addr == MAP_FAILED || dm.addr != addr) { if (dm.addr == MAP_FAILED || dm.addr != addr) {
return MAP_FAILED; return MAP_FAILED;
} }
if (TrackMemoryInterval(&_mmi, COORD(dm.addr), LAST_COORD(dm.addr, size), a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
dm.maphandle) == -1) { b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
_Exit(1); if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle) == -1) {
abort();
}
if (weaken(__asan_map_shadow)) {
weaken(__asan_map_shadow)(dm.addr, size);
} }
return dm.addr; return dm.addr;
} }

View File

@ -17,21 +17,34 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/bits/bits.h" #include "libc/calls/internal.h"
#include "libc/bits/pushpop.h" #include "libc/dce.h"
#include "libc/calls/calls.h" #include "libc/macros.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sysv/errfuns.h"
#define IP(X) (intptr_t)(X)
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
/** /**
* Closes memory mapping. * Releases memory pages.
*
* The caller's address holder is set to MAP_FAILED (-1) which is a
* no-op for subsequent invocations.
* *
* @param addr is a pointer within any memory mapped region the process
* has permission to control, such as address ranges returned by
* mmap(), the program image itself, etc.
* @param size is the amount of memory to unmap, which needn't be a
* multiple of FRAMESIZE, and may be a subset of that which was
* mapped previously, and may punch holes in existing mappings,
* but your mileage may vary on windows
* @return 0 on success, or -1 w/ errno * @return 0 on success, or -1 w/ errno
*/ */
int munmap_s(void *addrp, uint64_t size) { int munmap(void *addr, size_t size) {
void **addrpp = (void **)addrp; int rc;
void *addr = (void *)pushpop(-1L); if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
return munmap(lockxchg(addrpp, &addr), size); size = ROUNDUP(size, FRAMESIZE);
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
if (IsWindows()) return 0;
return munmap$sysv(addr, size);
} }

View File

@ -23,6 +23,7 @@
#include "libc/limits.h" #include "libc/limits.h"
#include "libc/macros.h" #include "libc/macros.h"
#include "libc/runtime/ring.h" #include "libc/runtime/ring.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/sysv/consts/map.h" #include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h" #include "libc/sysv/consts/prot.h"

View File

@ -17,8 +17,8 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/calls/calls.h"
#include "libc/runtime/ring.h" #include "libc/runtime/ring.h"
#include "libc/runtime/runtime.h"
/** /**
* Frees ring buffer. * Frees ring buffer.

View File

@ -6,13 +6,6 @@ COSMOPOLITAN_C_START_
cosmopolitan § runtime cosmopolitan § runtime
*/ */
struct SymbolTable;
struct StackFrame {
struct StackFrame *next;
intptr_t addr;
};
typedef long jmp_buf[8] aligned(CACHELINE); typedef long jmp_buf[8] aligned(CACHELINE);
extern int g_argc; /* CRT */ extern int g_argc; /* CRT */
@ -71,8 +64,12 @@ void loadxmm(void *);
void peekall(void); void peekall(void);
int issetugid(void); int issetugid(void);
void weakfree(void *) libcesque; void weakfree(void *) libcesque;
void __hook(void (*)(void), struct SymbolTable *);
bool isheap(void *); bool isheap(void *);
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
int munmap(void *, uint64_t);
int mprotect(void *, uint64_t, int) privileged;
int msync(void *, size_t, int);
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § runtime » optimizations cosmopolitan § runtime » optimizations

View File

@ -60,13 +60,8 @@ $(LIBC_RUNTIME_A).pkg: \
$(LIBC_RUNTIME_A_OBJS) \ $(LIBC_RUNTIME_A_OBJS) \
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/runtime/asan.greg.o \ $(LIBC_RUNTIME_A_OBJS): \
o/$(MODE)/libc/runtime/shadowargs.o \ OVERRIDE_CFLAGS += \
o/$(MODE)/libc/runtime/hook.greg.o \
o/$(MODE)/libc/runtime/ftrace.greg.o \
o/$(MODE)/libc/runtime/__stack_chk_fail.o \
o/$(MODE)/libc/runtime/__stack_chk_guard.o: \
OVERRIDE_COPTS += \
$(NO_MAGIC) $(NO_MAGIC)
# @see ape/ape.s for tuning parameters that make this safe # @see ape/ape.s for tuning parameters that make this safe

View File

@ -53,6 +53,7 @@ struct SymbolTable *opensymboltable(const char *) nodiscard;
int closesymboltable(struct SymbolTable **); int closesymboltable(struct SymbolTable **);
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *); const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
const char *getsymbolname(struct SymbolTable *, const struct Symbol *); const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
void __hook(void (*)(void), struct SymbolTable *);
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -17,8 +17,12 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/tinymath/tinymath.h" #include "libc/macros.h"
#include "libc/runtime/memtrack.h"
double(powi)(double a, int b) { int UntrackMemoryIntervals(void *addr, size_t size) {
return tinymath_powl(a, b); int a, b;
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
return ReleaseMemoryIntervals(&_mmi, a, b, ReleaseMemoryNt);
} }

View File

@ -53,9 +53,9 @@ $(LIBC_STDIO_A).pkg: \
$(LIBC_STDIO_A_OBJS) \ $(LIBC_STDIO_A_OBJS) \
$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg)
#o/$(MODE)/libc/stdio/fputc.o: \ o/$(MODE)/libc/stdio/fputc.o: \
OVERRIDE_CFLAGS += \ OVERRIDE_CFLAGS += \
$(NO_MAGIC) -O3
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x))) LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS)) LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))

View File

@ -440,6 +440,12 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
#define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE)) #define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE))
#define mempcpy(DEST, SRC, SIZE) \
({ \
size_t SIze = (SIZE); \
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
})
#define __memcpy(FN, DEST, SRC, SIZE) \ #define __memcpy(FN, DEST, SRC, SIZE) \
({ \ ({ \
void *DeSt = (DEST); \ void *DeSt = (DEST); \
@ -448,16 +454,10 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
asm("call\t" FN \ asm("call\t" FN \
: "=m"(*(char(*)[SiZe])(DeSt)) \ : "=m"(*(char(*)[SiZe])(DeSt)) \
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \ : "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
: __STR_XMM_CLOBBER "cc"); \ : __STR_XMM_CLOBBER "rcx", "cc"); \
DeSt; \ DeSt; \
}) })
#define mempcpy(DEST, SRC, SIZE) \
({ \
size_t SIze = (SIZE); \
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
})
#define __memset(DEST, BYTE, SIZE) \ #define __memset(DEST, BYTE, SIZE) \
({ \ ({ \
void *DeSt = (DEST); \ void *DeSt = (DEST); \
@ -465,7 +465,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
asm("call\tMemSet" \ asm("call\tMemSet" \
: "=m"(*(char(*)[SiZe])(DeSt)) \ : "=m"(*(char(*)[SiZe])(DeSt)) \
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \ : "D"(DeSt), "S"(BYTE), "d"(SiZe) \
: __STR_XMM_CLOBBER "cc"); \ : __STR_XMM_CLOBBER "rcx", "cc"); \
DeSt; \ DeSt; \
}) })
@ -506,7 +506,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
size_t Rcx; \ size_t Rcx; \
asm("rep stosb" \ asm("rep stosb" \
: "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \ : "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
: "0"(Dest), "1"(SiZe), "S"(BYTE) \ : "0"(Dest), "1"(SiZe), "a"(BYTE) \
: "cc"); \ : "cc"); \
Dest; \ Dest; \
}) })

View File

@ -42,6 +42,10 @@ $(LIBC_STR_A).pkg: \
$(LIBC_STR_A_OBJS) \ $(LIBC_STR_A_OBJS) \
$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg) $(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/str/lz4cpy.o: \
OVERRIDE_CFLAGS += \
$(NO_MAGIC)
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x))) LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS)) LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS)) LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))

279
libc/stubs/asan.S 100644
View File

@ -0,0 +1,279 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
/ @fileoverview Address Sanitizer Linker Poison
__asan_addr_is_in_fake_stack:
ud2
.endfn __asan_addr_is_in_fake_stack,weak
__asan_after_dynamic_init:
ud2
.endfn __asan_after_dynamic_init,weak
__asan_alloca_poison:
ud2
.endfn __asan_alloca_poison,weak
__asan_allocas_unpoison:
ud2
.endfn __asan_allocas_unpoison,weak
__asan_before_dynamic_init:
ud2
.endfn __asan_before_dynamic_init,weak
__asan_get_current_fake_stack:
ud2
.endfn __asan_get_current_fake_stack,weak
__asan_handle_no_return:
ud2
.endfn __asan_handle_no_return,weak
__asan_init:
ud2
.endfn __asan_init,weak
__asan_load1:
ud2
.endfn __asan_load1,weak
__asan_load2:
ud2
.endfn __asan_load2,weak
__asan_load4:
ud2
.endfn __asan_load4,weak
__asan_load8:
ud2
.endfn __asan_load8,weak
__asan_load16:
ud2
.endfn __asan_load16,weak
__asan_load32:
ud2
.endfn __asan_load32,weak
__asan_noreentry:
ud2
.endfn __asan_noreentry,weak
__asan_option_detect_stack_use_after_return:
ud2
.endfn __asan_option_detect_stack_use_after_return,weak
__asan_poison_stack_memory:
ud2
.endfn __asan_poison_stack_memory,weak
__asan_register_globals:
ud2
.endfn __asan_register_globals,weak
__asan_report_load1:
ud2
.endfn __asan_report_load1,weak
__asan_report_load2:
ud2
.endfn __asan_report_load2,weak
__asan_report_load4:
ud2
.endfn __asan_report_load4,weak
__asan_report_load8:
ud2
.endfn __asan_report_load8,weak
__asan_report_load16:
ud2
.endfn __asan_report_load16,weak
__asan_report_load_n:
ud2
.endfn __asan_report_load_n,weak
__asan_report_store1:
ud2
.endfn __asan_report_store1,weak
__asan_report_store2:
ud2
.endfn __asan_report_store2,weak
__asan_report_store4:
ud2
.endfn __asan_report_store4,weak
__asan_report_store8:
ud2
.endfn __asan_report_store8,weak
__asan_report_store16:
ud2
.endfn __asan_report_store16,weak
__asan_report_store32:
ud2
.endfn __asan_report_store32,weak
__asan_report_store_n:
ud2
.endfn __asan_report_store_n,weak
__asan_stack_free:
ud2
.endfn __asan_stack_free,weak
__asan_stack_free_0:
ud2
.endfn __asan_stack_free_0,weak
__asan_stack_free_1:
ud2
.endfn __asan_stack_free_1,weak
__asan_stack_free_10:
ud2
.endfn __asan_stack_free_10,weak
__asan_stack_free_2:
ud2
.endfn __asan_stack_free_2,weak
__asan_stack_free_3:
ud2
.endfn __asan_stack_free_3,weak
__asan_stack_free_4:
ud2
.endfn __asan_stack_free_4,weak
__asan_stack_free_5:
ud2
.endfn __asan_stack_free_5,weak
__asan_stack_free_6:
ud2
.endfn __asan_stack_free_6,weak
__asan_stack_free_7:
ud2
.endfn __asan_stack_free_7,weak
__asan_stack_free_8:
ud2
.endfn __asan_stack_free_8,weak
__asan_stack_free_9:
ud2
.endfn __asan_stack_free_9,weak
__asan_stack_malloc:
ud2
.endfn __asan_stack_malloc,weak
__asan_stack_malloc_0:
ud2
.endfn __asan_stack_malloc_0,weak
__asan_stack_malloc_1:
ud2
.endfn __asan_stack_malloc_1,weak
__asan_stack_malloc_2:
ud2
.endfn __asan_stack_malloc_2,weak
__asan_stack_malloc_3:
ud2
.endfn __asan_stack_malloc_3,weak
__asan_stack_malloc_4:
ud2
.endfn __asan_stack_malloc_4,weak
__asan_stack_malloc_5:
ud2
.endfn __asan_stack_malloc_5,weak
__asan_stack_malloc_6:
ud2
.endfn __asan_stack_malloc_6,weak
__asan_stack_malloc_7:
ud2
.endfn __asan_stack_malloc_7,weak
__asan_stack_malloc_8:
ud2
.endfn __asan_stack_malloc_8,weak
__asan_stack_malloc_9:
ud2
.endfn __asan_stack_malloc_9,weak
__asan_stack_malloc_10:
ud2
.endfn __asan_stack_malloc_10,weak
__asan_store1:
ud2
.endfn __asan_store1,weak
__asan_store2:
ud2
.endfn __asan_store2,weak
__asan_store4:
ud2
.endfn __asan_store4,weak
__asan_store8:
ud2
.endfn __asan_store8,weak
__asan_store16:
ud2
.endfn __asan_store16,weak
__asan_store32:
ud2
.endfn __asan_store32,weak
__asan_unpoison_stack_memory:
ud2
.endfn __asan_unpoison_stack_memory,weak
__asan_unregister_globals:
ud2
.endfn __asan_unregister_globals,weak
__asan_version_mismatch_check_v8:
ud2
.endfn __asan_version_mismatch_check_v8,weak

View File

@ -1,54 +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
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
__asan_addr_is_in_fake_stack:
__asan_alloca_poison:
__asan_allocas_unpoison:
__asan_get_current_fake_stack:
__asan_handle_no_return:
__asan_init:
__asan_loadN:
__asan_register_globals:
__asan_report_load_n:
__asan_report_store_n:
__asan_stack_free:
__asan_stack_malloc:
__asan_storeN:
__asan_unregister_globals:
__asan_version_mismatch_check_v8:
xor %eax,%eax
ret
.endfn __asan_addr_is_in_fake_stack,globl,weak
.endfn __asan_alloca_poison,globl,weak
.endfn __asan_allocas_unpoison,globl,weak
.endfn __asan_get_current_fake_stack,globl,weak
.endfn __asan_handle_no_return,globl,weak
.endfn __asan_init,globl,weak
.endfn __asan_loadN,globl,weak
.endfn __asan_register_globals,globl,weak
.endfn __asan_report_load_n,globl,weak
.endfn __asan_report_store_n,globl,weak
.endfn __asan_stack_free,globl,weak
.endfn __asan_stack_malloc,globl,weak
.endfn __asan_storeN,globl,weak
.endfn __asan_unregister_globals,globl,weak
.endfn __asan_version_mismatch_check_v8,globl,weak

View File

@ -1,24 +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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/tinymath/tinymath.h"
float powif(float a, int b) {
return tinymath_powl(a, b);
}

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