mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Get address sanitizer mostly working
This commit is contained in:
parent
1f1f3cd477
commit
7327c345f9
149 changed files with 3777 additions and 3457 deletions
8
Makefile
8
Makefile
|
@ -60,9 +60,10 @@
|
|||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = /bin/sh
|
||||
HOSTS ?= freebsd openbsd alpine
|
||||
SANITY := $(shell build/sanitycheck $$PPID)
|
||||
SHELL = /bin/sh
|
||||
HOSTS ?= freebsd openbsd alpine
|
||||
SANITY := $(shell build/sanitycheck $$PPID)
|
||||
GNUMAKEFLAGS += --output-sync
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
|
@ -156,7 +157,6 @@ include tool/build/lib/buildlib.mk
|
|||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include tool/debug/debug.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/hash/hash.mk
|
||||
|
|
|
@ -276,10 +276,5 @@ if "$@"; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TERM" = "dumb" ]; then
|
||||
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
|
||||
printf "$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
|
||||
exit 1
|
||||
|
|
|
@ -17,9 +17,6 @@ CONFIG_CCFLAGS += \
|
|||
$(FTRACE) \
|
||||
-Og
|
||||
|
||||
CONFIG_COPTS += \
|
||||
-ftrapv
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-march=k8-sse3
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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_ */
|
|
@ -7,6 +7,7 @@
|
|||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/inttypes.h"
|
||||
#include "libc/literal.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(&lo, &buf[0], sizeof(lo));
|
||||
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) {
|
||||
|
@ -44,7 +45,7 @@ void dohex(const char *op, long double x, FILE *f) {
|
|||
memcpy(buf, &x, sizeof(x));
|
||||
memcpy(&lo, &buf[0], sizeof(lo));
|
||||
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) \
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
|
|
@ -32,9 +32,10 @@ int main(int argc, char *argv[]) {
|
|||
int pid, wstatus;
|
||||
long double ts1, ts2;
|
||||
struct rusage rusage;
|
||||
char pathbuf[PATH_MAX];
|
||||
memset(&rusage, -1, sizeof(rusage));
|
||||
CHECK_GT(argc, 1);
|
||||
CHECK_NOTNULL((exe = commandv(argv[1])));
|
||||
CHECK_NOTNULL((exe = commandv(argv[1], pathbuf)));
|
||||
ts1 = nowl();
|
||||
CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ)));
|
||||
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));
|
||||
|
|
|
@ -86,7 +86,7 @@ char *realpath(const char *, char *);
|
|||
char *replaceuser(const char *) nodiscard;
|
||||
char *slurp(const char *, size_t *) nodiscard;
|
||||
char *ttyname(int);
|
||||
const char *commandv(const char *);
|
||||
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||
int access(const char *, int) nothrow;
|
||||
int arch_prctl();
|
||||
int chdir(const char *);
|
||||
|
@ -140,12 +140,8 @@ int mknodat(int, const char *, int32_t, uint64_t);
|
|||
int mlock(const void *, size_t);
|
||||
int mlock2(const void *, size_t, int);
|
||||
int mlockall(int);
|
||||
int mprotect(void *, uint64_t, int) privileged;
|
||||
int msync(void *, size_t, int);
|
||||
int munlock(const void *, size_t);
|
||||
int munlockall(void);
|
||||
int munmap(void *, uint64_t);
|
||||
int munmap_s(void *, uint64_t);
|
||||
int nice(int);
|
||||
int open(const char *, int, ...) nodiscard;
|
||||
int openanon(char *, unsigned) nodiscard;
|
||||
|
@ -229,8 +225,6 @@ uint32_t gettid(void) nosideeffect;
|
|||
uint32_t getuid(void) nosideeffect;
|
||||
uint32_t umask(int32_t);
|
||||
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) \
|
||||
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
|
||||
|
|
|
@ -17,28 +17,18 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/bits/progn.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ok.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,
|
||||
const char *ext) {
|
||||
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,
|
||||
size_t namelen) {
|
||||
int rc;
|
||||
char *ep, *path, *pathtok;
|
||||
struct critbit0 deduplicate;
|
||||
char *path, *pathtok, ep[PATH_MAX];
|
||||
rc = -1;
|
||||
pathtok = ep =
|
||||
strdup(firstnonnull(getenv("PATH"), "/bin:/usr/local/bin:/usr/bin"));
|
||||
memset(&deduplicate, 0, sizeof(deduplicate));
|
||||
if (!memccpy(ep,
|
||||
firstnonnull(emptytonull(getenv("PATH")),
|
||||
"/bin:/usr/local/bin:/usr/bin"),
|
||||
'\0', sizeof(ep))) {
|
||||
return enomem();
|
||||
}
|
||||
pathtok = ep;
|
||||
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
|
||||
if (strchr(path, '=')) continue;
|
||||
if (!critbit0_insert(&deduplicate, path)) continue;
|
||||
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
critbit0_clear(&deduplicate);
|
||||
free(ep);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -105,66 +95,29 @@ static char *mkcmdquery(const char *name, size_t namelen,
|
|||
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.
|
||||
*
|
||||
* 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.
|
||||
* Resolves full pathname of executable.
|
||||
*
|
||||
* @return execve()'able path, or NULL w/ errno
|
||||
* @errno ENOENT, EACCES, ENOMEM
|
||||
* @see free(), execvpe()
|
||||
*/
|
||||
const char *commandv(const char *name) {
|
||||
char pathname[PATH_MAX];
|
||||
return findcmdpath(name, pathname);
|
||||
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||
char *p;
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -19,11 +19,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
.init.start 300,_init_g_fds
|
||||
.init.start 302,_init_g_fds
|
||||
push %rdi
|
||||
push %rsi
|
||||
call InitializeFileDescriptors
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
.init.end 300,_init_g_fds
|
||||
.init.end 302,_init_g_fds
|
||||
.source __FILE__
|
||||
|
|
|
@ -25,16 +25,22 @@
|
|||
/**
|
||||
* Returns value of environment variable, or NULL if not found.
|
||||
*/
|
||||
char *getenv(const char *name) {
|
||||
char **ep;
|
||||
size_t i, namelen;
|
||||
char *empty[1] = {0};
|
||||
ep = environ;
|
||||
if (!ep) ep = empty;
|
||||
namelen = strlen(name);
|
||||
for (i = 0; ep[i]; ++i) {
|
||||
if (strncmp(ep[i], name, namelen) == 0 && ep[i][namelen] == '=') {
|
||||
return &ep[i][namelen + 1];
|
||||
char *getenv(const char *s) {
|
||||
char **p;
|
||||
size_t i, j;
|
||||
if ((p = environ)) {
|
||||
for (i = 0; p[i]; ++i) {
|
||||
for (j = 0;; ++j) {
|
||||
if (!s[j]) {
|
||||
if (p[i][j] == '=') {
|
||||
return &p[i][j + 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s[j] != p[i][j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
/**
|
||||
* Executes program, with custom environment.
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/mem/mem.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.
|
||||
|
@ -36,7 +36,8 @@
|
|||
*/
|
||||
int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
||||
char *exe;
|
||||
if ((exe = commandv(prog))) {
|
||||
char pathbuf[PATH_MAX];
|
||||
if ((exe = commandv(prog, pathbuf))) {
|
||||
va_list va;
|
||||
void *argv;
|
||||
va_start(va, arg);
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
|
||||
/**
|
||||
* Executes program, with path environment search.
|
||||
|
@ -33,7 +33,8 @@
|
|||
*/
|
||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||
char *exe;
|
||||
if ((exe = commandv(prog))) {
|
||||
char pathbuf[PATH_MAX];
|
||||
if ((exe = commandv(prog, pathbuf))) {
|
||||
execve(exe, argv, envp);
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -24,17 +24,18 @@
|
|||
#include "libc/nexgen32e/tinystrcmp.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;
|
||||
const char *t;
|
||||
for (i = 1; i < n; ++i) {
|
||||
j = i;
|
||||
t = a[i];
|
||||
while (j > 0 && tinystrcmp(t, a[j - 1]) < 0) {
|
||||
for (t = a[i], j = i; j > 0 && CompareStrings(t, a[j - 1]) < 0; --j) {
|
||||
a[j] = a[j - 1];
|
||||
--j;
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
|
@ -52,17 +53,14 @@ static void slowsort(char **a, int n) {
|
|||
* @return newly allocated sorted copy of envp pointer array
|
||||
*/
|
||||
hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
|
||||
size_t count = 0;
|
||||
while (envp[count]) count++;
|
||||
size_t bytesize = (count + 1) * sizeof(char *);
|
||||
char **copy = malloc(bytesize);
|
||||
if (copy) {
|
||||
memcpy(copy, envp, bytesize);
|
||||
if (IsTiny()) {
|
||||
slowsort(copy, count);
|
||||
} else {
|
||||
qsort(copy, count, sizeof(char *), (void *)sortenvpcb);
|
||||
}
|
||||
char **copy;
|
||||
size_t n, size;
|
||||
n = 0;
|
||||
while (envp[n]) n++;
|
||||
size = (n + 1) * sizeof(char *);
|
||||
if ((copy = malloc(size))) {
|
||||
memcpy(copy, envp, size);
|
||||
SortStrings(copy, n);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,9 @@ nodiscard int spawnlp(unsigned flags, int stdiofds[3], const char *prog,
|
|||
char *exe;
|
||||
va_list va;
|
||||
void *argv;
|
||||
char pathbuf[PATH_MAX];
|
||||
pid = -1;
|
||||
if ((exe = commandv(prog))) {
|
||||
if ((exe = commandv(prog, pathbuf))) {
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
pid = spawnve(flags, stdiofds, exe, argv, environ);
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 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/securityinformation.h"
|
||||
#include "libc/nt/errors.h"
|
||||
|
@ -28,33 +29,33 @@
|
|||
#include "libc/nt/struct/securitydescriptor.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.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.
|
||||
* @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
|
||||
*/
|
||||
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||
int rc;
|
||||
bool32 result;
|
||||
struct NtGenericMapping mapping;
|
||||
struct NtPrivilegeSet privileges;
|
||||
int64_t hToken, hImpersonatedToken;
|
||||
uint32_t secsize, granted, privsize;
|
||||
struct NtPrivilegeSet privileges;
|
||||
struct NtGenericMapping mapping;
|
||||
struct NtSecurityDescriptor security;
|
||||
struct NtSecurityDescriptor *psecurity;
|
||||
const uint32_t request = kNtOwnerSecurityInformation |
|
||||
kNtGroupSecurityInformation |
|
||||
kNtDaclSecurityInformation;
|
||||
union NtSecurityDescriptorLol {
|
||||
struct NtSecurityDescriptor s;
|
||||
char b[1024];
|
||||
} security;
|
||||
granted = 0;
|
||||
result = false;
|
||||
psecurity = &security;
|
||||
secsize = sizeof(security);
|
||||
privsize = sizeof(privileges);
|
||||
memset(&privileges, 0, sizeof(privileges));
|
||||
|
@ -64,23 +65,23 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
|||
mapping.GenericAll = kNtFileAllAccess;
|
||||
MapGenericMask(&flags, &mapping);
|
||||
hImpersonatedToken = hToken = -1;
|
||||
if ((GetFileSecurity(pathname, request, psecurity, 0, &secsize) ||
|
||||
(GetLastError() == kNtErrorInsufficientBuffer &&
|
||||
(psecurity = malloc(secsize)) &&
|
||||
GetFileSecurity(pathname, request, psecurity, secsize, &secsize))) &&
|
||||
if (GetFileSecurity(pathname,
|
||||
kNtOwnerSecurityInformation |
|
||||
kNtGroupSecurityInformation |
|
||||
kNtDaclSecurityInformation,
|
||||
&security.s, 0, &secsize) &&
|
||||
OpenProcessToken(GetCurrentProcess(),
|
||||
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
|
||||
kNtStandardRightsRead,
|
||||
&hToken) &&
|
||||
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
|
||||
AccessCheck(psecurity, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
AccessCheck(&security.s, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
&privsize, &granted, &result) &&
|
||||
(result || flags == F_OK)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = winerr();
|
||||
}
|
||||
free_s(&psecurity);
|
||||
close(hImpersonatedToken);
|
||||
close(hToken);
|
||||
return rc;
|
|
@ -57,10 +57,7 @@ int(vdprintf)(int fd, const char *fmt, va_list va) {
|
|||
struct VdprintfState df;
|
||||
df.n = 0;
|
||||
df.fd = fd;
|
||||
if (palandprintf(vdprintfputchar, &df, fmt, va) != -1 ||
|
||||
vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) != -1) {
|
||||
return df.n;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
if (palandprintf(vdprintfputchar, &df, fmt, va) == -1) return -1;
|
||||
if (vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) == -1) return -1;
|
||||
return df.n;
|
||||
}
|
||||
|
|
|
@ -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_ */
|
|
@ -33,7 +33,7 @@ static void unrijndaelinit$westmere(struct Rijndael *ctx, uint32_t n,
|
|||
x = ctx->rk[i].xmm;
|
||||
asm("aesimc\t%1,%0" : "=x"(x) : "0"(x));
|
||||
ctx->rk[i].xmm = x;
|
||||
} while (i++ < n);
|
||||
} while (++i < n);
|
||||
XMM_DESTROY(x);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ static relegated noinline void unrijndaelinit$pure(struct Rijndael *ctx,
|
|||
x = ctx->rk[i].xmm;
|
||||
x = InvMixColumns(x);
|
||||
ctx->rk[i].xmm = x;
|
||||
} while (i++ < n);
|
||||
} while (++i < n);
|
||||
XMM_DESTROY(x);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,10 +45,11 @@
|
|||
*/
|
||||
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
|
||||
int rc = 0;
|
||||
char stackline[128];
|
||||
char *line = stackline;
|
||||
size_t linecap = sizeof(stackline);
|
||||
while ((getline(&line, &linecap, f)) != -1) {
|
||||
char *line;
|
||||
size_t linesize;
|
||||
line = NULL;
|
||||
linesize = 0;
|
||||
while ((getline(&line, &linesize, f)) != -1) {
|
||||
struct HostsTxtEntry entry;
|
||||
char *addr, *name, *tok, *comment;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/dns/resolvconf.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
@ -44,13 +45,14 @@
|
|||
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
||||
/* TODO(jart): options ndots:5 */
|
||||
int rc = 0;
|
||||
char stackline[32];
|
||||
char *line = stackline;
|
||||
size_t linecap = sizeof(stackline);
|
||||
char *line;
|
||||
size_t linesize;
|
||||
struct sockaddr_in nameserver;
|
||||
line = NULL;
|
||||
linesize = 0;
|
||||
nameserver.sin_family = AF_INET;
|
||||
nameserver.sin_port = htons(DNS_PORT);
|
||||
while (getline(&line, &linecap, f) != -1) {
|
||||
while (getline(&line, &linesize, f) != -1) {
|
||||
char *directive, *value, *tok, *comment;
|
||||
if ((comment = strchr(line, '#'))) *comment = '\0';
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -56,14 +56,7 @@ static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)];
|
|||
* @see bing()
|
||||
*/
|
||||
int unbing(int c) {
|
||||
int i, 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;
|
||||
}
|
||||
int m, l, r;
|
||||
l = 0;
|
||||
r = ARRAYLEN(g_cp437i) - 1;
|
||||
while (l <= r) {
|
||||
|
@ -78,3 +71,12 @@ int unbing(int c) {
|
|||
}
|
||||
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};
|
||||
|
|
|
@ -336,6 +336,7 @@ typedef uint64_t uintmax_t;
|
|||
* 4. unprofilable
|
||||
* 5. unhookable
|
||||
*
|
||||
* @note consider static or writing a macro
|
||||
* @see externinline
|
||||
*/
|
||||
#ifndef forceinline
|
||||
|
|
|
@ -66,8 +66,8 @@
|
|||
#endif
|
||||
|
||||
#define BIGPAGESIZE 0x200000
|
||||
#define STACKSIZE 0x20000
|
||||
#define FRAMESIZE 0x10000 /* 8086 */
|
||||
#define STACKSIZE 0x10000 /* goog */
|
||||
#define PAGESIZE 0x1000 /* i386+ */
|
||||
#define BUFSIZ 0x1000 /* best stdio default */
|
||||
#define CACHELINE 0x40 /* nexgen32e */
|
||||
|
|
|
@ -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_FILES := \
|
||||
$(wildcard libc/intrin/*) \
|
||||
$(wildcard libc/intrin/delegates/*)
|
||||
$(wildcard libc/intrin/*)
|
||||
|
||||
LIBC_INTRIN_A_OBJS = \
|
||||
$(LIBC_INTRIN_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_INTRIN_REPMOVSB_H_
|
||||
#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;
|
||||
const char *si = (const char *)*src;
|
||||
while (cx) *di++ = *si++, cx--;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_INTRIN_REPSTOSB_H_
|
||||
#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;
|
||||
while (cx) *di++ = al, cx--;
|
||||
return di;
|
||||
|
|
370
libc/log/asan.c
Normal file
370
libc/log/asan.c
Normal 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
Normal file
21
libc/log/asan.h
Normal 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_ */
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nexgen32e/vendor.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
|
||||
void backtrace(FILE *f) {
|
||||
showbacktrace(f, __builtin_frame_address(0));
|
||||
|
|
15
libc/log/backtrace.h
Normal file
15
libc/log/backtrace.h
Normal 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_ */
|
|
@ -26,6 +26,7 @@
|
|||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -37,54 +38,7 @@
|
|||
#define kBacktraceMaxFrames 128
|
||||
#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1))
|
||||
|
||||
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
||||
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]) {
|
||||
static int PrintBacktraceUsingAddr2line(FILE *f, const struct StackFrame *bp) {
|
||||
ssize_t got;
|
||||
intptr_t addr;
|
||||
size_t i, j, gi;
|
||||
|
@ -92,6 +46,7 @@ static int PrintBacktraceUsingAddr2line(
|
|||
struct Garbages *garbage;
|
||||
const struct StackFrame *frame;
|
||||
const char *debugbin, *p1, *p2, *p3, *addr2line;
|
||||
char buf[kBacktraceBufSize], *argv[kBacktraceMaxFrames];
|
||||
if (!(debugbin = finddebugbinary()) || !(addr2line = GetAddr2linePath())) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -148,24 +103,20 @@ static int PrintBacktraceUsingAddr2line(
|
|||
return 0;
|
||||
}
|
||||
|
||||
static noinline int PrintBacktrace(FILE *f, const struct StackFrame *bp,
|
||||
char *argv[hasatleast kBacktraceMaxFrames],
|
||||
char buf[hasatleast kBacktraceBufSize]) {
|
||||
static int PrintBacktrace(FILE *f, const struct StackFrame *bp) {
|
||||
if (!IsTiny()) {
|
||||
if (PrintBacktraceUsingAddr2line(f, bp, buf, argv) != -1) {
|
||||
if (PrintBacktraceUsingAddr2line(f, bp) != -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return PrintBacktraceUsingSymbols(f, bp, buf);
|
||||
return PrintBacktraceUsingSymbols(f, bp, getsymboltable());
|
||||
}
|
||||
|
||||
void showbacktrace(FILE *f, const struct StackFrame *bp) {
|
||||
static bool noreentry;
|
||||
char *argv[kBacktraceMaxFrames];
|
||||
char buf[kBacktraceBufSize];
|
||||
if (!noreentry) {
|
||||
noreentry = true;
|
||||
PrintBacktrace(f, bp, argv, buf);
|
||||
PrintBacktrace(f, bp);
|
||||
noreentry = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,83 +17,53 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 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/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
struct SourceLocation {
|
||||
const char *filename;
|
||||
int line;
|
||||
int column;
|
||||
};
|
||||
|
||||
struct AccessInfo {
|
||||
const uint8_t *addr;
|
||||
const uint8_t *first_bad_addr;
|
||||
size_t size;
|
||||
bool iswrite;
|
||||
unsigned long ip;
|
||||
};
|
||||
|
||||
struct Global {
|
||||
const uint8_t *addr;
|
||||
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) {
|
||||
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
||||
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;
|
||||
}
|
||||
|
||||
privileged void __asan_version_mismatch_check_v8(void) {
|
||||
}
|
||||
|
||||
privileged void __asan_register_globals(struct Global globals[], int n) {
|
||||
}
|
||||
|
||||
privileged void __asan_unregister_globals(struct Global globals[], int n) {
|
||||
}
|
||||
|
||||
privileged void __asan_report_load_n(uint8_t *p, int n) {
|
||||
}
|
||||
|
||||
privileged void __asan_report_store_n(uint8_t *p, int n) {
|
||||
__asan_report_load_n(p, n);
|
||||
}
|
||||
|
||||
privileged void __asan_loadN(uintptr_t ptr, size_t size) {
|
||||
}
|
||||
|
||||
privileged void __asan_storeN(uintptr_t ptr, size_t size) {
|
||||
}
|
||||
|
||||
privileged uintptr_t __asan_stack_malloc(size_t size, int classid) {
|
||||
int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
||||
struct SymbolTable *symbols) {
|
||||
size_t gi;
|
||||
char buf[256];
|
||||
intptr_t addr;
|
||||
struct Garbages *garbage;
|
||||
const struct StackFrame *frame;
|
||||
if (!symbols) return -1;
|
||||
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, sizeof(buf), true));
|
||||
}
|
||||
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;
|
||||
}
|
|
@ -28,13 +28,14 @@
|
|||
*/
|
||||
nodiscard char *commandvenv(const char *var, const char *cmd) {
|
||||
const char *exepath;
|
||||
char pathbuf[PATH_MAX];
|
||||
if ((exepath = getenv(var))) {
|
||||
if (!isempty(exepath) && access(exepath, X_OK) != -1) {
|
||||
return exepath;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else if ((exepath = commandv(cmd))) {
|
||||
} else if ((exepath = commandv(cmd, pathbuf))) {
|
||||
return exepath;
|
||||
} else {
|
||||
return NULL;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
struct sigset;
|
||||
struct winsize;
|
||||
struct StackFrame;
|
||||
typedef struct FILE FILE;
|
||||
|
||||
extern FILE *g_logfile;
|
||||
|
@ -51,7 +50,6 @@ void showcrashreports(void);
|
|||
void callexitontermination(struct sigset *);
|
||||
bool32 IsDebuggerPresent(bool);
|
||||
bool isrunningundermake(void);
|
||||
void showbacktrace(FILE *, const struct StackFrame *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § liblog » logging ─╬─│┼
|
||||
|
|
|
@ -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_FILES := \
|
||||
$(wildcard libc/log/thunks/*) \
|
||||
$(wildcard libc/log/elf/*) \
|
||||
$(wildcard libc/log/*)
|
||||
LIBC_LOG_A_HDRS = $(filter %.h,$(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_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_MEM \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
|
@ -60,17 +60,10 @@ $(LIBC_LOG_A).pkg: \
|
|||
$(LIBC_LOG_A_OBJS) \
|
||||
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/log/die.o \
|
||||
o/$(MODE)/libc/log/perror.o \
|
||||
o/$(MODE)/libc/log/ftrace.o \
|
||||
o/$(MODE)/libc/log/ubsan.o \
|
||||
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_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(NO_MAGIC) \
|
||||
-fwrapv
|
||||
|
||||
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
|
||||
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/backtrace.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -163,7 +165,6 @@ relegated static void ShowCrashReport(int err, FILE *f, int sig,
|
|||
}
|
||||
fputc('\n', f);
|
||||
fflush(f);
|
||||
memsummary(fileno(f));
|
||||
ShowMemoryMappings(fileno(f));
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,12 @@
|
|||
.privileged
|
||||
.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:
|
||||
push $1
|
||||
jmp OnLoad
|
||||
|
@ -43,13 +49,11 @@ __asan_load16:
|
|||
.endfn __asan_load16,globl
|
||||
__asan_load32:
|
||||
push $32
|
||||
/ fallthrough
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_load32,globl
|
||||
OnLoad: pop %rsi
|
||||
.globl __asan_loadN
|
||||
.weak __asan_loadN
|
||||
ezlea __asan_loadN,ax
|
||||
jmp OnAsan
|
||||
jmp __asan_report_noreentry
|
||||
.endfn OnStore
|
||||
|
||||
__asan_store1:
|
||||
|
@ -74,13 +78,11 @@ __asan_store16:
|
|||
.endfn __asan_store16,globl
|
||||
__asan_store32:
|
||||
push $32
|
||||
/ fallthrough
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_store32,globl
|
||||
OnStore:pop %rsi
|
||||
.globl __asan_storeN
|
||||
.weak __asan_storeN
|
||||
ezlea __asan_storeN,ax
|
||||
jmp OnAsan
|
||||
jmp __asan_report_noreentry
|
||||
.endfn OnStore
|
||||
|
||||
__asan_report_load1:
|
||||
|
@ -101,14 +103,12 @@ __asan_report_load8:
|
|||
.endfn __asan_report_load8,globl
|
||||
__asan_report_load16:
|
||||
push $16
|
||||
/ fallthrough
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_report_load16,globl
|
||||
OnReportLoad:
|
||||
pop %rsi
|
||||
.globl __asan_report_load_n
|
||||
.weak __asan_report_load_n
|
||||
ezlea __asan_report_load_n,ax
|
||||
jmp OnAsan
|
||||
jmp __asan_report_noreentry
|
||||
.endfn OnReportLoad
|
||||
|
||||
__asan_report_store1:
|
||||
|
@ -133,33 +133,31 @@ __asan_report_store16:
|
|||
.endfn __asan_report_store16,globl
|
||||
__asan_report_store32:
|
||||
push $32
|
||||
/ fallthrough
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_report_store32,globl
|
||||
ReportStore:
|
||||
pop %rsi
|
||||
.globl __asan_report_store_n
|
||||
.weak __asan_report_store_n
|
||||
ezlea __asan_report_store_n,ax
|
||||
/ fallthrough
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn ReportStore
|
||||
|
||||
OnAsan: test %rax,%rax
|
||||
jz 1f
|
||||
jmp *%rax
|
||||
1: ret
|
||||
.endfn OnAsan
|
||||
__asan_report_noreentry:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
cmpb $0,noreentry(%rip)
|
||||
jnz 2f
|
||||
incb noreentry(%rip)
|
||||
call *%rax
|
||||
decb noreentry(%rip)
|
||||
pop %rbp
|
||||
ret
|
||||
2: call abort
|
||||
.endfn __asan_report_noreentry
|
||||
|
||||
__asan_stack_free_0:
|
||||
push $0
|
||||
/ fallthrough
|
||||
jmp OnStackFree
|
||||
.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:
|
||||
push $1
|
||||
jmp OnStackFree
|
||||
|
@ -198,20 +196,17 @@ __asan_stack_free_9:
|
|||
.endfn __asan_stack_free_9,globl
|
||||
__asan_stack_free_10:
|
||||
push $10
|
||||
jmp OnStackFree
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn __asan_stack_free_10,globl
|
||||
OnStackFree:
|
||||
pop %rdx
|
||||
jmp __asan_stack_free
|
||||
.endfn OnStackFree
|
||||
|
||||
__asan_stack_malloc_0:
|
||||
push $0
|
||||
/ fallthrough
|
||||
jmp OnStackMalloc
|
||||
.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:
|
||||
push $1
|
||||
jmp OnStackMalloc
|
||||
|
@ -250,11 +245,54 @@ __asan_stack_malloc_9:
|
|||
.endfn __asan_stack_malloc_9,globl
|
||||
__asan_stack_malloc_10:
|
||||
push $10
|
||||
jmp OnStackMalloc
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.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
|
||||
__asan_option_detect_stack_use_after_return:
|
||||
.long 1
|
||||
.endobj __asan_option_detect_stack_use_after_return,globl
|
||||
.previous
|
||||
|
||||
.bss
|
||||
noreentry:
|
||||
.byte 0
|
||||
.endobj noreentry
|
||||
.previous
|
|
@ -6,9 +6,7 @@ PKGS += LIBC_MATH
|
|||
LIBC_MATH_ARTIFACTS += LIBC_MATH_A
|
||||
LIBC_MATH = $(LIBC_MATH_A_DEPS) $(LIBC_MATH_A)
|
||||
LIBC_MATH_A = o/$(MODE)/libc/math/math.a
|
||||
LIBC_MATH_A_FILES := \
|
||||
$(wildcard libc/math/*) \
|
||||
$(wildcard libc/math/delegates/*)
|
||||
LIBC_MATH_A_FILES := $(wildcard libc/math/*)
|
||||
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_C = $(filter %.c,$(LIBC_MATH_A_FILES))
|
||||
|
|
|
@ -26,34 +26,61 @@
|
|||
/ @param %rsi is ignored
|
||||
/ @param %rdx is ignored
|
||||
_ZdlPvSt11align_val_tRKSt9nothrow_t:
|
||||
/ operator delete(void*, std::align_val_t, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
|
||||
_ZdaPvSt11align_val_tRKSt9nothrow_t:
|
||||
/ operator delete[](void*, std::align_val_t, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
|
||||
_ZdlPvRKSt9nothrow_t:
|
||||
/ operator delete(void*, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdlPvRKSt9nothrow_t,weak
|
||||
_ZdaPvRKSt9nothrow_t:
|
||||
/ operator delete[](void*, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPvRKSt9nothrow_t,weak
|
||||
_ZdlPvmSt11align_val_t:
|
||||
/ operator delete(void*, unsigned long, std::align_val_t)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdlPvmSt11align_val_t,weak
|
||||
_ZdaPvmSt11align_val_t:
|
||||
/ operator delete[](void*, unsigned long, std::align_val_t)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPvmSt11align_val_t,weak
|
||||
_ZdlPvSt11align_val_t:
|
||||
/ operator delete(void*, std::align_val_t)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdlPvSt11align_val_t,weak
|
||||
_ZdaPvSt11align_val_t:
|
||||
/ operator delete[](void*, std::align_val_t)
|
||||
nop
|
||||
_ZdaPvm:nop
|
||||
_ZdlPvm:nop
|
||||
_ZdaPv: nop
|
||||
_ZdlPv: jmp *hook$free(%rip)
|
||||
.endfn _ZdlPv,globl,weak
|
||||
.endfn _ZdaPv,globl,weak
|
||||
.endfn _ZdaPvm,globl,weak
|
||||
.endfn _ZdlPvm,globl,weak
|
||||
.endfn _ZdaPvRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZdlPvRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZdaPvSt11align_val_t,globl,weak
|
||||
.endfn _ZdlPvSt11align_val_t,globl,weak
|
||||
.endfn _ZdaPvmSt11align_val_t,globl,weak
|
||||
.endfn _ZdlPvmSt11align_val_t,globl,weak
|
||||
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,globl,weak
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPvSt11align_val_t,weak
|
||||
_ZdaPvm:
|
||||
/ operator delete[](void*, unsigned long):
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPvm,weak
|
||||
_ZdlPvm:
|
||||
/ operator delete(void*, unsigned long)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdlPvm,weak
|
||||
_ZdaPv:
|
||||
/ operator delete[](void*)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZdaPv,weak
|
||||
_ZdlPv:
|
||||
/ operator delete(void*)
|
||||
jmp *hook$free(%rip)
|
||||
.endfn _ZdlPv,weak
|
|
@ -26,15 +26,24 @@
|
|||
/ @param %rsi is ignored
|
||||
/ @return new memory or NULL on OOM
|
||||
_ZnamRKSt9nothrow_t:
|
||||
/ operator new[](unsigned long, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZnamRKSt9nothrow_t,weak
|
||||
_ZnwmRKSt9nothrow_t:
|
||||
/ operator new(unsigned long, std::nothrow_t const&)
|
||||
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
|
||||
mov $1,%edi
|
||||
1: jmp *hook$malloc(%rip)
|
||||
.endfn _Znwm,globl,weak
|
||||
.endfn _Znam,globl,weak
|
||||
.endfn _ZnwmRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZnamRKSt9nothrow_t,globl,weak
|
||||
.endfn _Znwm,weak
|
|
@ -27,12 +27,22 @@
|
|||
/ @param %rdx is ignored
|
||||
/ @return new memory or NULL on OOM
|
||||
_ZnamSt11align_val_tRKSt9nothrow_t:
|
||||
/ operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
|
||||
_ZnwmSt11align_val_tRKSt9nothrow_t:
|
||||
/ operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
|
||||
_ZnwmSt11align_val_t:
|
||||
/ operator new(unsigned long, std::align_val_t)
|
||||
nop
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn _ZnwmSt11align_val_t,weak
|
||||
_ZnamSt11align_val_t:
|
||||
/ operator new[](unsigned long, std::align_val_t)
|
||||
test %rdi,%rdi
|
||||
jnz 1f
|
||||
mov $1,%eax
|
||||
|
@ -41,7 +51,4 @@ _ZnamSt11align_val_t:
|
|||
cmovb %rax,%rsi
|
||||
xchg %rdi,%rsi
|
||||
jmp *hook$memalign(%rip)
|
||||
.endfn _ZnwmSt11align_val_t,globl,weak
|
||||
.endfn _ZnamSt11align_val_t,globl,weak
|
||||
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,globl,weak
|
||||
.endfn _ZnamSt11align_val_t,weak
|
|
@ -20,15 +20,15 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 800,_init_calloc
|
||||
.initbss 202,_init_calloc
|
||||
hook$calloc:
|
||||
.quad 0
|
||||
.endobj hook$calloc,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 800,_init_calloc
|
||||
.init.start 202,_init_calloc
|
||||
.hidden dlcalloc
|
||||
ezlea dlcalloc,ax
|
||||
stosq
|
||||
yoink free
|
||||
.init.end 800,_init_calloc
|
||||
.init.end 202,_init_calloc
|
|
@ -20,16 +20,16 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 800,_init_free
|
||||
.initbss 202,_init_free
|
||||
hook$free:
|
||||
.quad 0
|
||||
.endobj hook$free,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 800,_init_free
|
||||
.init.start 202,_init_free
|
||||
ezlea dlfree,ax
|
||||
stosq
|
||||
yoink realloc
|
||||
.init.end 800,_init_free
|
||||
.init.end 202,_init_free
|
||||
|
||||
.hidden dlfree
|
18
libc/mem/hook/hook.h
Normal file
18
libc/mem/hook/hook.h
Normal 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_ */
|
|
@ -20,16 +20,15 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 800,_init_malloc
|
||||
.initbss 202,_init_malloc
|
||||
hook$malloc:
|
||||
.quad 0
|
||||
.endobj hook$malloc,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 800,_init_malloc
|
||||
.init.start 202,_init_malloc
|
||||
.hidden dlmalloc
|
||||
ezlea dlmalloc,ax
|
||||
stosq
|
||||
yoink free
|
||||
.init.end 800,_init_malloc
|
||||
|
||||
.hidden dlmalloc
|
||||
.init.end 202,_init_malloc
|
33
libc/mem/hook/malloc_usable_size.S
Normal file
33
libc/mem/hook/malloc_usable_size.S
Normal 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
|
|
@ -20,16 +20,15 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 800,_init_memalign
|
||||
.initbss 202,_init_memalign
|
||||
hook$memalign:
|
||||
.quad 0
|
||||
.endobj hook$memalign,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 800,_init_memalign
|
||||
.init.start 202,_init_memalign
|
||||
.hidden dlmemalign
|
||||
ezlea dlmemalign,ax
|
||||
stosq
|
||||
yoink free
|
||||
.init.end 800,_init_memalign
|
||||
|
||||
.hidden dlmemalign
|
||||
.init.end 202,_init_memalign
|
34
libc/mem/hook/posix_memalign.S
Normal file
34
libc/mem/hook/posix_memalign.S
Normal 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
|
34
libc/mem/hook/pvalloc.S
Normal file
34
libc/mem/hook/pvalloc.S
Normal 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
|
|
@ -20,15 +20,15 @@
|
|||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
.initbss 800,_init_realloc
|
||||
.initbss 202,_init_realloc
|
||||
hook$realloc:
|
||||
.quad 0
|
||||
.endobj hook$realloc,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 800,_init_realloc
|
||||
.init.start 202,_init_realloc
|
||||
.hidden dlrealloc
|
||||
ezlea dlrealloc,ax
|
||||
stosq
|
||||
yoink free
|
||||
.init.end 800,_init_realloc
|
||||
.init.end 202,_init_realloc
|
34
libc/mem/hook/realloc_in_place.S
Normal file
34
libc/mem/hook/realloc_in_place.S
Normal 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
|
34
libc/mem/hook/valloc.S
Normal file
34
libc/mem/hook/valloc.S
Normal 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
|
|
@ -39,4 +39,3 @@
|
|||
/ @see dlmalloc()
|
||||
malloc: jmp *hook$malloc(%rip)
|
||||
.endfn malloc,globl
|
||||
|
||||
|
|
|
@ -40,14 +40,3 @@
|
|||
malloc_usable_size:
|
||||
jmp *hook$malloc_usable_size(%rip)
|
||||
.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
|
||||
|
|
|
@ -6,11 +6,15 @@ PKGS += LIBC_MEM
|
|||
LIBC_MEM_ARTIFACTS += LIBC_MEM_A
|
||||
LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
|
||||
LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
|
||||
LIBC_MEM_A_FILES := $(wildcard libc/mem/*)
|
||||
LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
|
||||
LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
|
||||
LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
|
||||
|
||||
LIBC_MEM_A_FILES := \
|
||||
$(wildcard libc/mem/*) \
|
||||
$(wildcard libc/mem/cxx/*) \
|
||||
$(wildcard libc/mem/hook/*)
|
||||
|
||||
LIBC_MEM_A_SRCS = \
|
||||
$(LIBC_MEM_A_SRCS_S) \
|
||||
$(LIBC_MEM_A_SRCS_C)
|
||||
|
|
|
@ -35,17 +35,3 @@
|
|||
posix_memalign:
|
||||
jmp *hook$posix_memalign(%rip)
|
||||
.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
|
||||
|
|
|
@ -22,24 +22,10 @@
|
|||
.source __FILE__
|
||||
|
||||
/ 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
|
||||
/ @return rax is memory address, or NULL w/ errno
|
||||
/ @see dlpvalloc()
|
||||
pvalloc:jmp *hook$pvalloc(%rip)
|
||||
.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
|
||||
|
|
|
@ -55,5 +55,6 @@
|
|||
/ @note realloc(p=0, n=0) → malloc(32)
|
||||
/ @note realloc(p≠0, n=0) → free(p)
|
||||
/ @see dlrealloc()
|
||||
realloc:jmp *hook$realloc(%rip)
|
||||
realloc:
|
||||
jmp *hook$realloc(%rip)
|
||||
.endfn realloc,globl
|
||||
|
|
|
@ -23,12 +23,12 @@
|
|||
|
||||
/ Resizes the space allocated for p to size n, only if this can be
|
||||
/ done without moving p (i.e., only if there is adjacent space
|
||||
/ available if n is greater than p's current allocated size, or n is
|
||||
/ less than or equal to p's size). This may be used instead of plain
|
||||
/ realloc if an alternative allocation strategy is needed upon failure
|
||||
/ to expand space, for example, reallocation of a buffer that must be
|
||||
/ memory-aligned or cleared. You can use realloc_in_place to trigger
|
||||
/ these alternatives only when needed.
|
||||
/ available if n is greater than p's current allocated size, or n
|
||||
/ is less than or equal to p's size). This may be used instead of
|
||||
/ plain realloc if an alternative allocation strategy is needed
|
||||
/ upon failure to expand space, for example, reallocation of a
|
||||
/ buffer that must be memory-aligned or cleared. You can use
|
||||
/ realloc_in_place to trigger these alternatives only when needed.
|
||||
/
|
||||
/ @param rdi (p) is address of current allocation
|
||||
/ @param rsi (newsize) is number of bytes needed
|
||||
|
@ -37,17 +37,3 @@
|
|||
realloc_in_place:
|
||||
jmp *hook$realloc_in_place(%rip)
|
||||
.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
|
||||
|
|
|
@ -21,24 +21,10 @@
|
|||
#include "libc/notice.inc"
|
||||
.source __FILE__
|
||||
|
||||
/ Equivalent to memalign(PAGESIZE, n).
|
||||
/ Equivalent to memalign(4096, n).
|
||||
/
|
||||
/ @param rdi is number of bytes needed
|
||||
/ @return rax is memory address, or NULL w/ errno
|
||||
/ @see dlvalloc()
|
||||
valloc: jmp *hook$valloc(%rip)
|
||||
.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
|
@ -1,10 +1,9 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
||||
#define COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct StackFrame;
|
||||
|
||||
struct Garbages {
|
||||
size_t i, n;
|
||||
struct Garbage {
|
||||
|
|
|
@ -25,9 +25,8 @@
|
|||
world's most popular function──one all programmers love.
|
||||
|
||||
This implementation is the fastest and nearly the tiniest too.
|
||||
It doesn't clobber general registers. It won't break down on old
|
||||
computers or misaligned data. It's so easy that even a child
|
||||
could use it──and they do.
|
||||
It doesn't break when copying backwards or on misaligned data.
|
||||
It's so easy that even a child could use it, and they do.
|
||||
*/
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/macros.h"
|
||||
|
@ -53,11 +52,10 @@ memcpy: mov %rdi,%rax
|
|||
/ @param rdi is dest
|
||||
/ @param rsi is src
|
||||
/ @param rdx is number of bytes
|
||||
/ @clob flags,xmm3,xmm4
|
||||
/ @clob flags,rcx,xmm3,xmm4
|
||||
/ @mode long
|
||||
.align 16
|
||||
MemCpy: .leafprologue
|
||||
push %rcx
|
||||
mov $.Lmemcpytab.ro.size,%ecx
|
||||
cmp %rcx,%rdx
|
||||
cmovb %rdx,%rcx
|
||||
|
@ -95,8 +93,7 @@ MemCpy: .leafprologue
|
|||
mov %rcx,(%rdi)
|
||||
mov %rbx,-8(%rdi,%rdx)
|
||||
1: pop %rbx
|
||||
.L0: pop %rcx
|
||||
.leafepilogue
|
||||
.L0: .leafepilogue
|
||||
.L4: push %rbx
|
||||
mov (%rsi),%ecx
|
||||
mov -4(%rsi,%rdx),%ebx
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/ @param rsi is src
|
||||
/ @param rdx is number of bytes
|
||||
/ @return original rdi copied to rax
|
||||
/ @clob flags,rcx
|
||||
/ @asyncsignalsafe
|
||||
memmove:
|
||||
mov %rdi,%rax
|
||||
|
@ -36,7 +37,6 @@ memmove:
|
|||
MemMove:
|
||||
.leafprologue
|
||||
.profilable
|
||||
push %rcx
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov %rdx,%rcx
|
||||
|
@ -49,7 +49,6 @@ MemMove:
|
|||
cld
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %rcx
|
||||
.leafepilogue
|
||||
.endfn memmove,globl
|
||||
.source __FILE__
|
||||
|
|
|
@ -43,12 +43,11 @@ memset: mov %rdi,%rax
|
|||
/ @param rdi is dest
|
||||
/ @param esi is the byte to set
|
||||
/ @param edx is the number of bytes to set
|
||||
/ @clob flags,xmm3
|
||||
/ @clob flags,rcx,xmm3
|
||||
/ @mode long
|
||||
MemSet: .leafprologue
|
||||
.profilable
|
||||
push %rbx
|
||||
push %rcx
|
||||
movd %esi,%xmm3
|
||||
mov $.Lmemsettab.ro.size,%ecx
|
||||
cmp %rcx,%rdx
|
||||
|
@ -77,8 +76,7 @@ MemSet: .leafprologue
|
|||
ja 1b
|
||||
movdqu %xmm3,-16(%rdi,%rdx)
|
||||
pxor %xmm3,%xmm3
|
||||
.L0: pop %rcx
|
||||
pop %rbx
|
||||
.L0: pop %rbx
|
||||
.leafepilogue
|
||||
.L8: movzbq %sil,%rbx
|
||||
mov $0x0101010101010101,%rcx
|
||||
|
|
13
libc/nexgen32e/stackframe.h
Normal file
13
libc/nexgen32e/stackframe.h
Normal 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_ */
|
|
@ -40,6 +40,10 @@ _construct:
|
|||
je 2f
|
||||
push %rax
|
||||
push %rcx
|
||||
mov %r12,%rdi
|
||||
mov %r13,%rsi
|
||||
mov %r14,%rdx
|
||||
mov %r15,%rcx
|
||||
call *(%rax)
|
||||
pop %rcx
|
||||
pop %rax
|
||||
|
|
|
@ -17,59 +17,39 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/mpeg/ycbcrio.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.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"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/directmap.h"
|
||||
|
||||
#define USAGE \
|
||||
" [FLAGS] [PATH...]\n\
|
||||
\n\
|
||||
Flags:\n\
|
||||
-h shows this information\n\
|
||||
\n"
|
||||
|
||||
static char *inpath_;
|
||||
|
||||
static void PrintUsage(int rc, FILE *f) {
|
||||
fputs("Usage: ", f);
|
||||
fputs(program_invocation_name, f);
|
||||
fputs(USAGE, f);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
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);
|
||||
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
|
||||
unsigned prot, unsigned flags,
|
||||
int fd, int64_t off) {
|
||||
struct DirectMap res;
|
||||
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 = (void *)(intptr_t)winerr();
|
||||
}
|
||||
} else {
|
||||
res.maphandle = kNtInvalidHandleValue;
|
||||
res.addr = (void *)(intptr_t)winerr();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void ProcessFile(struct Ycbcrio *m) {
|
||||
/* m->frame-> */
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
size_t i;
|
||||
struct Ycbcrio *m;
|
||||
GetOpts(&argc, argv);
|
||||
for (i = optind; i < argc; ++i) {
|
||||
inpath_ = argv[i];
|
||||
m = YcbcrioOpen(inpath_, NULL);
|
||||
ProcessFile(m);
|
||||
YcbcrioClose(&m);
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
}
|
15
libc/runtime/directmap.h
Normal file
15
libc/runtime/directmap.h
Normal 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_ */
|
|
@ -17,7 +17,6 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/limits.h"
|
||||
|
@ -51,8 +50,14 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
|
|||
int unmapfile(struct MappedFile *mf) {
|
||||
int rc;
|
||||
rc = 0;
|
||||
rc |= munmap_s(&mf->addr, mf->size);
|
||||
rc |= close_s(&mf->fd);
|
||||
pushmov(&mf->size, 0);
|
||||
if (mf->addr != MAP_FAILED) {
|
||||
rc |= munmap(mf->addr, mf->size);
|
||||
mf->addr = MAP_FAILED;
|
||||
}
|
||||
if (mf->fd != -1) {
|
||||
rc |= close(mf->fd);
|
||||
mf->fd = -1;
|
||||
}
|
||||
mf->size = 0;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -13,8 +14,6 @@ COSMOPOLITAN_C_START_
|
|||
* using very few lines of code.
|
||||
*/
|
||||
|
||||
struct StackFrame;
|
||||
|
||||
/**
|
||||
* Releases resource when function returns.
|
||||
*
|
||||
|
|
|
@ -19,10 +19,8 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/conv/sizemultiply.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.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;
|
||||
p2 = NULL;
|
||||
n1 = *capacity;
|
||||
n2 = (*p ? n1 + (n1 >> 1) : max(4, INITIAL_CAPACITY / itemsize)) + extra;
|
||||
if (sizemultiply(&t1, n1, itemsize) && sizemultiply(&t2, n2, itemsize)) {
|
||||
n2 = (*p ? n1 + (n1 >> 1) : MAX(4, INITIAL_CAPACITY / itemsize)) + extra;
|
||||
if (!__builtin_mul_overflow(n1, itemsize, &t1) &&
|
||||
!__builtin_mul_overflow(n2, itemsize, &t2)) {
|
||||
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
|
||||
if (!p1 && *p) memcpy(p2, *p, t1);
|
||||
memset((char *)p2 + t1, 0, t2 - t1);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
hidden extern bool _mmap_asan_mode;
|
||||
hidden extern char **g_freebsdhint;
|
||||
hidden extern unsigned g_runstate;
|
||||
hidden extern void *g_stacktop;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||
#include "libc/nexgen32e/vendor.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define kMappingsSize 0x0000100000000000 /* 16TB */
|
||||
#define kMappingsStart (IsGenuineCosmo() ? 0x300000000000 : 0x200000000000)
|
||||
#define kFixedMappingsStart 0x0000100000000000
|
||||
#define kFixedMappingsSize kMappingsSize
|
||||
#define kAutomapStart 0x0000100000000000
|
||||
#define kAutomapSize 0x0000100000000000
|
||||
#define kFixedmapStart 0x0000200000000000
|
||||
|
||||
struct MemoryIntervals {
|
||||
int i;
|
||||
|
@ -27,6 +25,7 @@ int TrackMemoryInterval(struct MemoryIntervals *, int, int, long);
|
|||
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
|
||||
void (*)(struct MemoryIntervals *, int, int));
|
||||
void ReleaseMemoryNt(struct MemoryIntervals *, int, int);
|
||||
int UntrackMemoryIntervals(void *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -18,13 +18,14 @@
|
|||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/asan.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/directmap.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -32,79 +33,14 @@
|
|||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define IP(X) (intptr_t)(X)
|
||||
#define VIP(X) (void *)IP(X)
|
||||
#define COORD(a) (int)(IP(a) >> 16)
|
||||
#define ADDR(c) (void *)(IP(c) << 16)
|
||||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||
#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;
|
||||
};
|
||||
#define IP(X) (intptr_t)(X)
|
||||
#define VIP(X) (void *)IP(X)
|
||||
#define ADDR(c) (void *)(IP(c) << 16)
|
||||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
|
||||
|
||||
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.
|
||||
*
|
||||
|
@ -120,8 +56,7 @@ int munmap(void *addr, size_t size) {
|
|||
* @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) {
|
||||
int i;
|
||||
long gap;
|
||||
int i, x, n, a, b;
|
||||
struct DirectMap dm;
|
||||
if (!size) 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) {
|
||||
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 {
|
||||
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) ||
|
||||
(!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) {
|
||||
return MAP_FAILED;
|
||||
}
|
||||
if (TrackMemoryInterval(&_mmi, COORD(dm.addr), LAST_COORD(dm.addr, size),
|
||||
dm.maphandle) == -1) {
|
||||
_Exit(1);
|
||||
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||
if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle) == -1) {
|
||||
abort();
|
||||
}
|
||||
if (weaken(__asan_map_shadow)) {
|
||||
weaken(__asan_map_shadow)(dm.addr, size);
|
||||
}
|
||||
return dm.addr;
|
||||
}
|
||||
|
|
|
@ -17,21 +17,34 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/memtrack.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.
|
||||
*
|
||||
* The caller's address holder is set to MAP_FAILED (-1) which is a
|
||||
* no-op for subsequent invocations.
|
||||
* 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_s(void *addrp, uint64_t size) {
|
||||
void **addrpp = (void **)addrp;
|
||||
void *addr = (void *)pushpop(-1L);
|
||||
return munmap(lockxchg(addrpp, &addr), size);
|
||||
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);
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/limits.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/ring.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/ring.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Frees ring buffer.
|
||||
|
|
|
@ -6,13 +6,6 @@ COSMOPOLITAN_C_START_
|
|||
│ cosmopolitan § runtime ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
struct SymbolTable;
|
||||
|
||||
struct StackFrame {
|
||||
struct StackFrame *next;
|
||||
intptr_t addr;
|
||||
};
|
||||
|
||||
typedef long jmp_buf[8] aligned(CACHELINE);
|
||||
|
||||
extern int g_argc; /* CRT */
|
||||
|
@ -71,8 +64,12 @@ void loadxmm(void *);
|
|||
void peekall(void);
|
||||
int issetugid(void);
|
||||
void weakfree(void *) libcesque;
|
||||
void __hook(void (*)(void), struct SymbolTable *);
|
||||
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 ─╬─│┼
|
||||
|
|
|
@ -60,13 +60,8 @@ $(LIBC_RUNTIME_A).pkg: \
|
|||
$(LIBC_RUNTIME_A_OBJS) \
|
||||
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/runtime/asan.greg.o \
|
||||
o/$(MODE)/libc/runtime/shadowargs.o \
|
||||
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 += \
|
||||
$(LIBC_RUNTIME_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(NO_MAGIC)
|
||||
|
||||
# @see ape/ape.s for tuning parameters that make this safe
|
||||
|
|
|
@ -53,6 +53,7 @@ struct SymbolTable *opensymboltable(const char *) nodiscard;
|
|||
int closesymboltable(struct SymbolTable **);
|
||||
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
|
||||
const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
|
||||
void __hook(void (*)(void), struct SymbolTable *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/tinymath/tinymath.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
|
||||
double(powi)(double a, int b) {
|
||||
return tinymath_powl(a, b);
|
||||
int UntrackMemoryIntervals(void *addr, size_t size) {
|
||||
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);
|
||||
}
|
|
@ -53,9 +53,9 @@ $(LIBC_STDIO_A).pkg: \
|
|||
$(LIBC_STDIO_A_OBJS) \
|
||||
$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
#o/$(MODE)/libc/stdio/fputc.o: \
|
||||
o/$(MODE)/libc/stdio/fputc.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(NO_MAGIC)
|
||||
-O3
|
||||
|
||||
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
|
||||
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
|
||||
|
|
|
@ -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 mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
size_t SIze = (SIZE); \
|
||||
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
||||
})
|
||||
|
||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
|
@ -448,16 +454,10 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
|||
asm("call\t" FN \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
|
||||
: __STR_XMM_CLOBBER "cc"); \
|
||||
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
#define mempcpy(DEST, SRC, SIZE) \
|
||||
({ \
|
||||
size_t SIze = (SIZE); \
|
||||
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
||||
})
|
||||
|
||||
#define __memset(DEST, BYTE, SIZE) \
|
||||
({ \
|
||||
void *DeSt = (DEST); \
|
||||
|
@ -465,7 +465,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
|||
asm("call\tMemSet" \
|
||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
||||
: __STR_XMM_CLOBBER "cc"); \
|
||||
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||
DeSt; \
|
||||
})
|
||||
|
||||
|
@ -506,7 +506,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
|||
size_t Rcx; \
|
||||
asm("rep stosb" \
|
||||
: "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
||||
: "0"(Dest), "1"(SiZe), "S"(BYTE) \
|
||||
: "0"(Dest), "1"(SiZe), "a"(BYTE) \
|
||||
: "cc"); \
|
||||
Dest; \
|
||||
})
|
||||
|
|
|
@ -42,6 +42,10 @@ $(LIBC_STR_A).pkg: \
|
|||
$(LIBC_STR_A_OBJS) \
|
||||
$(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_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
|
||||
|
|
279
libc/stubs/asan.S
Normal file
279
libc/stubs/asan.S
Normal 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
|
|
@ -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
|
|
@ -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
Loading…
Reference in a new issue