mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +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
|
# build/config.mk
|
||||||
|
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
HOSTS ?= freebsd openbsd alpine
|
HOSTS ?= freebsd openbsd alpine
|
||||||
SANITY := $(shell build/sanitycheck $$PPID)
|
SANITY := $(shell build/sanitycheck $$PPID)
|
||||||
|
GNUMAKEFLAGS += --output-sync
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.DELETE_ON_ERROR:
|
.DELETE_ON_ERROR:
|
||||||
|
@ -156,7 +157,6 @@ include tool/build/lib/buildlib.mk
|
||||||
include tool/build/emucrt/emucrt.mk
|
include tool/build/emucrt/emucrt.mk
|
||||||
include tool/build/emubin/emubin.mk
|
include tool/build/emubin/emubin.mk
|
||||||
include tool/build/build.mk
|
include tool/build/build.mk
|
||||||
include tool/debug/debug.mk
|
|
||||||
include tool/decode/lib/decodelib.mk
|
include tool/decode/lib/decodelib.mk
|
||||||
include tool/decode/decode.mk
|
include tool/decode/decode.mk
|
||||||
include tool/hash/hash.mk
|
include tool/hash/hash.mk
|
||||||
|
|
|
@ -276,10 +276,5 @@ if "$@"; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$TERM" = "dumb" ]; then
|
printf "$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
|
||||||
f='%s %s\r\n\r\n'
|
|
||||||
else
|
|
||||||
f='\033[91m%s\033[39m \033[94m%s\033[39m\r\n\r\n'
|
|
||||||
fi
|
|
||||||
printf "$f" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
|
|
||||||
exit 1
|
exit 1
|
||||||
|
|
|
@ -17,9 +17,6 @@ CONFIG_CCFLAGS += \
|
||||||
$(FTRACE) \
|
$(FTRACE) \
|
||||||
-Og
|
-Og
|
||||||
|
|
||||||
CONFIG_COPTS += \
|
|
||||||
-ftrapv
|
|
||||||
|
|
||||||
TARGET_ARCH ?= \
|
TARGET_ARCH ?= \
|
||||||
-march=k8-sse3
|
-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/ │
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||||
╚─────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────*/
|
||||||
#endif
|
#endif
|
||||||
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/inttypes.h"
|
#include "libc/inttypes.h"
|
||||||
#include "libc/literal.h"
|
#include "libc/literal.h"
|
||||||
#include "libc/math.h"
|
#include "libc/math.h"
|
||||||
|
@ -34,7 +35,7 @@ void dobin(const char *op, long double x, FILE *f) {
|
||||||
memcpy(buf, &x, sizeof(x));
|
memcpy(buf, &x, sizeof(x));
|
||||||
memcpy(&lo, &buf[0], sizeof(lo));
|
memcpy(&lo, &buf[0], sizeof(lo));
|
||||||
memcpy(&hi, &buf[8], sizeof(hi));
|
memcpy(&hi, &buf[8], sizeof(hi));
|
||||||
fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s %19.19Lf\n", hi, lo, op, x);
|
fprintf(f, "/\t%016" PRIb16 "%064" PRIb64 " %-8s % 19.19Lf\n", hi, lo, op, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dohex(const char *op, long double x, FILE *f) {
|
void dohex(const char *op, long double x, FILE *f) {
|
||||||
|
@ -44,7 +45,7 @@ void dohex(const char *op, long double x, FILE *f) {
|
||||||
memcpy(buf, &x, sizeof(x));
|
memcpy(buf, &x, sizeof(x));
|
||||||
memcpy(&lo, &buf[0], sizeof(lo));
|
memcpy(&lo, &buf[0], sizeof(lo));
|
||||||
memcpy(&hi, &buf[8], sizeof(hi));
|
memcpy(&hi, &buf[8], sizeof(hi));
|
||||||
fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s %19.19Lf\n", hi, lo, op, x);
|
fprintf(f, "/\t%04" PRIx16 "%016" PRIx64 " %-8s % 19.19Lf\n", hi, lo, op, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DOBIN(OP) \
|
#define DOBIN(OP) \
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
|
@ -32,9 +32,10 @@ int main(int argc, char *argv[]) {
|
||||||
int pid, wstatus;
|
int pid, wstatus;
|
||||||
long double ts1, ts2;
|
long double ts1, ts2;
|
||||||
struct rusage rusage;
|
struct rusage rusage;
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
memset(&rusage, -1, sizeof(rusage));
|
memset(&rusage, -1, sizeof(rusage));
|
||||||
CHECK_GT(argc, 1);
|
CHECK_GT(argc, 1);
|
||||||
CHECK_NOTNULL((exe = commandv(argv[1])));
|
CHECK_NOTNULL((exe = commandv(argv[1], pathbuf)));
|
||||||
ts1 = nowl();
|
ts1 = nowl();
|
||||||
CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ)));
|
CHECK_NE(-1, (pid = spawnve(0, NULL, exe, &argv[1], environ)));
|
||||||
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));
|
CHECK_NE(-1, wait4(pid, &wstatus, 0, &rusage));
|
||||||
|
|
|
@ -86,7 +86,7 @@ char *realpath(const char *, char *);
|
||||||
char *replaceuser(const char *) nodiscard;
|
char *replaceuser(const char *) nodiscard;
|
||||||
char *slurp(const char *, size_t *) nodiscard;
|
char *slurp(const char *, size_t *) nodiscard;
|
||||||
char *ttyname(int);
|
char *ttyname(int);
|
||||||
const char *commandv(const char *);
|
char *commandv(const char *, char[hasatleast PATH_MAX]);
|
||||||
int access(const char *, int) nothrow;
|
int access(const char *, int) nothrow;
|
||||||
int arch_prctl();
|
int arch_prctl();
|
||||||
int chdir(const char *);
|
int chdir(const char *);
|
||||||
|
@ -140,12 +140,8 @@ int mknodat(int, const char *, int32_t, uint64_t);
|
||||||
int mlock(const void *, size_t);
|
int mlock(const void *, size_t);
|
||||||
int mlock2(const void *, size_t, int);
|
int mlock2(const void *, size_t, int);
|
||||||
int mlockall(int);
|
int mlockall(int);
|
||||||
int mprotect(void *, uint64_t, int) privileged;
|
|
||||||
int msync(void *, size_t, int);
|
|
||||||
int munlock(const void *, size_t);
|
int munlock(const void *, size_t);
|
||||||
int munlockall(void);
|
int munlockall(void);
|
||||||
int munmap(void *, uint64_t);
|
|
||||||
int munmap_s(void *, uint64_t);
|
|
||||||
int nice(int);
|
int nice(int);
|
||||||
int open(const char *, int, ...) nodiscard;
|
int open(const char *, int, ...) nodiscard;
|
||||||
int openanon(char *, unsigned) nodiscard;
|
int openanon(char *, unsigned) nodiscard;
|
||||||
|
@ -229,8 +225,6 @@ uint32_t gettid(void) nosideeffect;
|
||||||
uint32_t getuid(void) nosideeffect;
|
uint32_t getuid(void) nosideeffect;
|
||||||
uint32_t umask(int32_t);
|
uint32_t umask(int32_t);
|
||||||
void *getprocaddressmodule(const char *, const char *);
|
void *getprocaddressmodule(const char *, const char *);
|
||||||
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
|
|
||||||
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
|
|
||||||
|
|
||||||
#define getcwd(BUF, SIZE) \
|
#define getcwd(BUF, SIZE) \
|
||||||
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
|
(isconstant(BUF) && (&(BUF)[0] == NULL) ? get_current_dir_name() \
|
||||||
|
|
|
@ -17,28 +17,18 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/alg/alg.h"
|
|
||||||
#include "libc/bits/progn.h"
|
#include "libc/bits/progn.h"
|
||||||
#include "libc/bits/safemacros.h"
|
#include "libc/bits/safemacros.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/conv/conv.h"
|
#include "libc/conv/conv.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/nt/ntdll.h"
|
#include "libc/nt/ntdll.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/ok.h"
|
#include "libc/sysv/consts/ok.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
static struct critbit0 g_commandv;
|
|
||||||
|
|
||||||
textstartup static void g_commandv_init(void) {
|
|
||||||
__cxa_atexit(critbit0_clear, &g_commandv, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
const void *const g_commandv_ctor[] initarray = {g_commandv_init};
|
|
||||||
|
|
||||||
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
|
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
|
||||||
const char *ext) {
|
const char *ext) {
|
||||||
len = stpcpy(&pathname[len], ext) - &pathname[0];
|
len = stpcpy(&pathname[len], ext) - &pathname[0];
|
||||||
|
@ -76,21 +66,21 @@ static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
|
||||||
static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name,
|
static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name,
|
||||||
size_t namelen) {
|
size_t namelen) {
|
||||||
int rc;
|
int rc;
|
||||||
char *ep, *path, *pathtok;
|
char *path, *pathtok, ep[PATH_MAX];
|
||||||
struct critbit0 deduplicate;
|
|
||||||
rc = -1;
|
rc = -1;
|
||||||
pathtok = ep =
|
if (!memccpy(ep,
|
||||||
strdup(firstnonnull(getenv("PATH"), "/bin:/usr/local/bin:/usr/bin"));
|
firstnonnull(emptytonull(getenv("PATH")),
|
||||||
memset(&deduplicate, 0, sizeof(deduplicate));
|
"/bin:/usr/local/bin:/usr/bin"),
|
||||||
|
'\0', sizeof(ep))) {
|
||||||
|
return enomem();
|
||||||
|
}
|
||||||
|
pathtok = ep;
|
||||||
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
|
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
|
||||||
if (strchr(path, '=')) continue;
|
if (strchr(path, '=')) continue;
|
||||||
if (!critbit0_insert(&deduplicate, path)) continue;
|
|
||||||
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
|
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
critbit0_clear(&deduplicate);
|
|
||||||
free(ep);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,66 +95,29 @@ static char *mkcmdquery(const char *name, size_t namelen,
|
||||||
return &scratch[0];
|
return &scratch[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *cachecmd(const char *name, size_t namelen,
|
|
||||||
const char *pathname, size_t pathnamelen) {
|
|
||||||
size_t entrylen;
|
|
||||||
char *res, *entry;
|
|
||||||
if ((entry = malloc((entrylen = namelen + 1 + pathnamelen) + 1))) {
|
|
||||||
mkcmdquery(name, namelen, entry);
|
|
||||||
res = memcpy(&entry[namelen + 1], pathname, pathnamelen + 1);
|
|
||||||
critbit0_emplace(&g_commandv, entry, entrylen);
|
|
||||||
} else {
|
|
||||||
res = NULL;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *getcmdcache(const char *name, size_t namelen,
|
|
||||||
char scratch[hasatleast PATH_MAX]) {
|
|
||||||
const char *entry;
|
|
||||||
if ((entry = critbit0_get(&g_commandv, mkcmdquery(name, namelen, scratch)))) {
|
|
||||||
return &entry[namelen + 1];
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
noinline static const char *findcmdpath(const char *name,
|
|
||||||
char pathname[hasatleast PATH_MAX]) {
|
|
||||||
char *p;
|
|
||||||
int rc, olderr;
|
|
||||||
size_t len;
|
|
||||||
olderr = errno;
|
|
||||||
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
|
|
||||||
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
|
|
||||||
if ((p = getcmdcache(name, len, pathname)) ||
|
|
||||||
(((IsWindows() &&
|
|
||||||
((rc = accesscmd(pathname, kNtSystemDirectory, name, len)) != -1 ||
|
|
||||||
(rc = accesscmd(pathname, kNtWindowsDirectory, name, len)) != -1)) ||
|
|
||||||
(rc = accesscmd(pathname, "", name, len)) != -1 ||
|
|
||||||
(!strpbrk(name, "/\\") &&
|
|
||||||
(rc = searchcmdpath(pathname, name, len)) != -1)) &&
|
|
||||||
(p = cachecmd(name, len, pathname, rc)))) {
|
|
||||||
errno = olderr;
|
|
||||||
return p;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves pathname of executable.
|
* Resolves full pathname of executable.
|
||||||
*
|
|
||||||
* This does the same thing as `command -v` in bourne shell. Path
|
|
||||||
* lookups are cached for the lifetime of the process. Paths with
|
|
||||||
* multiple components will skip the resolution process. Undotted
|
|
||||||
* basenames get automatic .com and .exe suffix resolution on all
|
|
||||||
* platforms. Windows' system directories will always trump PATH.
|
|
||||||
*
|
*
|
||||||
* @return execve()'able path, or NULL w/ errno
|
* @return execve()'able path, or NULL w/ errno
|
||||||
* @errno ENOENT, EACCES, ENOMEM
|
* @errno ENOENT, EACCES, ENOMEM
|
||||||
* @see free(), execvpe()
|
* @see free(), execvpe()
|
||||||
*/
|
*/
|
||||||
const char *commandv(const char *name) {
|
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
|
||||||
char pathname[PATH_MAX];
|
char *p;
|
||||||
return findcmdpath(name, pathname);
|
size_t len;
|
||||||
|
int rc, olderr;
|
||||||
|
olderr = errno;
|
||||||
|
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
|
||||||
|
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
|
||||||
|
if ((IsWindows() &&
|
||||||
|
((rc = accesscmd(pathbuf, kNtSystemDirectory, name, len)) != -1 ||
|
||||||
|
(rc = accesscmd(pathbuf, kNtWindowsDirectory, name, len)) != -1)) ||
|
||||||
|
(rc = accesscmd(pathbuf, "", name, len)) != -1 ||
|
||||||
|
(!strpbrk(name, "/\\") &&
|
||||||
|
(rc = searchcmdpath(pathbuf, name, len)) != -1)) {
|
||||||
|
errno = olderr;
|
||||||
|
return pathbuf;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -19,11 +19,11 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
|
||||||
.init.start 300,_init_g_fds
|
.init.start 302,_init_g_fds
|
||||||
push %rdi
|
push %rdi
|
||||||
push %rsi
|
push %rsi
|
||||||
call InitializeFileDescriptors
|
call InitializeFileDescriptors
|
||||||
pop %rsi
|
pop %rsi
|
||||||
pop %rdi
|
pop %rdi
|
||||||
.init.end 300,_init_g_fds
|
.init.end 302,_init_g_fds
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
|
@ -25,16 +25,22 @@
|
||||||
/**
|
/**
|
||||||
* Returns value of environment variable, or NULL if not found.
|
* Returns value of environment variable, or NULL if not found.
|
||||||
*/
|
*/
|
||||||
char *getenv(const char *name) {
|
char *getenv(const char *s) {
|
||||||
char **ep;
|
char **p;
|
||||||
size_t i, namelen;
|
size_t i, j;
|
||||||
char *empty[1] = {0};
|
if ((p = environ)) {
|
||||||
ep = environ;
|
for (i = 0; p[i]; ++i) {
|
||||||
if (!ep) ep = empty;
|
for (j = 0;; ++j) {
|
||||||
namelen = strlen(name);
|
if (!s[j]) {
|
||||||
for (i = 0; ep[i]; ++i) {
|
if (p[i][j] == '=') {
|
||||||
if (strncmp(ep[i], name, namelen) == 0 && ep[i][namelen] == '=') {
|
return &p[i][j + 1];
|
||||||
return &ep[i][namelen + 1];
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (s[j] != p[i][j]) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/calls/hefty/mkvarargv.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/hefty/mkvarargv.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes program, with custom environment.
|
* Executes program, with custom environment.
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/hefty/mkvarargv.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/calls/hefty/mkvarargv.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes program, with PATH search and current environment.
|
* Executes program, with PATH search and current environment.
|
||||||
|
@ -36,7 +36,8 @@
|
||||||
*/
|
*/
|
||||||
int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
||||||
char *exe;
|
char *exe;
|
||||||
if ((exe = commandv(prog))) {
|
char pathbuf[PATH_MAX];
|
||||||
|
if ((exe = commandv(prog, pathbuf))) {
|
||||||
va_list va;
|
va_list va;
|
||||||
void *argv;
|
void *argv;
|
||||||
va_start(va, arg);
|
va_start(va, arg);
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/mem/mem.h"
|
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes program, with path environment search.
|
* Executes program, with path environment search.
|
||||||
|
@ -33,7 +33,8 @@
|
||||||
*/
|
*/
|
||||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||||
char *exe;
|
char *exe;
|
||||||
if ((exe = commandv(prog))) {
|
char pathbuf[PATH_MAX];
|
||||||
|
if ((exe = commandv(prog, pathbuf))) {
|
||||||
execve(exe, argv, envp);
|
execve(exe, argv, envp);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -24,17 +24,18 @@
|
||||||
#include "libc/nexgen32e/tinystrcmp.h"
|
#include "libc/nexgen32e/tinystrcmp.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static int sortenvpcb(const char **a, const char **b) { return strcmp(*a, *b); }
|
static int CompareStrings(const char *l, const char *r) {
|
||||||
|
size_t i = 0;
|
||||||
|
while (l[i] == r[i] && r[i]) ++i;
|
||||||
|
return (l[i] & 0xff) - (r[i] & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
static void slowsort(char **a, int n) {
|
static void SortStrings(char **a, size_t n) {
|
||||||
|
char *t;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
const char *t;
|
|
||||||
for (i = 1; i < n; ++i) {
|
for (i = 1; i < n; ++i) {
|
||||||
j = i;
|
for (t = a[i], j = i; j > 0 && CompareStrings(t, a[j - 1]) < 0; --j) {
|
||||||
t = a[i];
|
|
||||||
while (j > 0 && tinystrcmp(t, a[j - 1]) < 0) {
|
|
||||||
a[j] = a[j - 1];
|
a[j] = a[j - 1];
|
||||||
--j;
|
|
||||||
}
|
}
|
||||||
a[j] = t;
|
a[j] = t;
|
||||||
}
|
}
|
||||||
|
@ -52,17 +53,14 @@ static void slowsort(char **a, int n) {
|
||||||
* @return newly allocated sorted copy of envp pointer array
|
* @return newly allocated sorted copy of envp pointer array
|
||||||
*/
|
*/
|
||||||
hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
|
hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
|
||||||
size_t count = 0;
|
char **copy;
|
||||||
while (envp[count]) count++;
|
size_t n, size;
|
||||||
size_t bytesize = (count + 1) * sizeof(char *);
|
n = 0;
|
||||||
char **copy = malloc(bytesize);
|
while (envp[n]) n++;
|
||||||
if (copy) {
|
size = (n + 1) * sizeof(char *);
|
||||||
memcpy(copy, envp, bytesize);
|
if ((copy = malloc(size))) {
|
||||||
if (IsTiny()) {
|
memcpy(copy, envp, size);
|
||||||
slowsort(copy, count);
|
SortStrings(copy, n);
|
||||||
} else {
|
|
||||||
qsort(copy, count, sizeof(char *), (void *)sortenvpcb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,9 @@ nodiscard int spawnlp(unsigned flags, int stdiofds[3], const char *prog,
|
||||||
char *exe;
|
char *exe;
|
||||||
va_list va;
|
va_list va;
|
||||||
void *argv;
|
void *argv;
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
pid = -1;
|
pid = -1;
|
||||||
if ((exe = commandv(prog))) {
|
if ((exe = commandv(prog, pathbuf))) {
|
||||||
va_start(va, arg);
|
va_start(va, arg);
|
||||||
if ((argv = mkvarargv(arg, va))) {
|
if ((argv = mkvarargv(arg, va))) {
|
||||||
pid = spawnve(flags, stdiofds, exe, argv, environ);
|
pid = spawnve(flags, stdiofds, exe, argv, environ);
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/nt/enum/accessmask.h"
|
#include "libc/nt/enum/accessmask.h"
|
||||||
#include "libc/nt/enum/securityinformation.h"
|
#include "libc/nt/enum/securityinformation.h"
|
||||||
#include "libc/nt/errors.h"
|
#include "libc/nt/errors.h"
|
||||||
|
@ -28,33 +29,33 @@
|
||||||
#include "libc/nt/struct/securitydescriptor.h"
|
#include "libc/nt/struct/securitydescriptor.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/calls/internal.h"
|
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/sysv/consts/ok.h"
|
#include "libc/sysv/consts/ok.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current process has access to folder or file.
|
* Asks Microsoft if we're authorized to use a folder or file.
|
||||||
|
*
|
||||||
|
* Implementation Details: MSDN documentation imposes no limit on the
|
||||||
|
* internal size of SECURITY_DESCRIPTOR, which we are responsible for
|
||||||
|
* allocating. We've selected 1024 which shall hopefully be adequate.
|
||||||
*
|
*
|
||||||
* @param flags can have R_OK, W_OK, X_OK, etc.
|
* @param flags can have R_OK, W_OK, X_OK, etc.
|
||||||
* @return 0 if authorized, or -1 w/ errno
|
* @return 0 if authorized, or -1 w/ errno
|
||||||
* @kudos Aaron Ballman for teaching how to do this
|
* @kudos Aaron Ballman for teaching this
|
||||||
* @see libc/sysv/consts.sh
|
* @see libc/sysv/consts.sh
|
||||||
*/
|
*/
|
||||||
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||||
int rc;
|
int rc;
|
||||||
bool32 result;
|
bool32 result;
|
||||||
|
struct NtGenericMapping mapping;
|
||||||
|
struct NtPrivilegeSet privileges;
|
||||||
int64_t hToken, hImpersonatedToken;
|
int64_t hToken, hImpersonatedToken;
|
||||||
uint32_t secsize, granted, privsize;
|
uint32_t secsize, granted, privsize;
|
||||||
struct NtPrivilegeSet privileges;
|
union NtSecurityDescriptorLol {
|
||||||
struct NtGenericMapping mapping;
|
struct NtSecurityDescriptor s;
|
||||||
struct NtSecurityDescriptor security;
|
char b[1024];
|
||||||
struct NtSecurityDescriptor *psecurity;
|
} security;
|
||||||
const uint32_t request = kNtOwnerSecurityInformation |
|
|
||||||
kNtGroupSecurityInformation |
|
|
||||||
kNtDaclSecurityInformation;
|
|
||||||
granted = 0;
|
granted = 0;
|
||||||
result = false;
|
result = false;
|
||||||
psecurity = &security;
|
|
||||||
secsize = sizeof(security);
|
secsize = sizeof(security);
|
||||||
privsize = sizeof(privileges);
|
privsize = sizeof(privileges);
|
||||||
memset(&privileges, 0, sizeof(privileges));
|
memset(&privileges, 0, sizeof(privileges));
|
||||||
|
@ -64,23 +65,23 @@ textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||||
mapping.GenericAll = kNtFileAllAccess;
|
mapping.GenericAll = kNtFileAllAccess;
|
||||||
MapGenericMask(&flags, &mapping);
|
MapGenericMask(&flags, &mapping);
|
||||||
hImpersonatedToken = hToken = -1;
|
hImpersonatedToken = hToken = -1;
|
||||||
if ((GetFileSecurity(pathname, request, psecurity, 0, &secsize) ||
|
if (GetFileSecurity(pathname,
|
||||||
(GetLastError() == kNtErrorInsufficientBuffer &&
|
kNtOwnerSecurityInformation |
|
||||||
(psecurity = malloc(secsize)) &&
|
kNtGroupSecurityInformation |
|
||||||
GetFileSecurity(pathname, request, psecurity, secsize, &secsize))) &&
|
kNtDaclSecurityInformation,
|
||||||
|
&security.s, 0, &secsize) &&
|
||||||
OpenProcessToken(GetCurrentProcess(),
|
OpenProcessToken(GetCurrentProcess(),
|
||||||
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
|
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
|
||||||
kNtStandardRightsRead,
|
kNtStandardRightsRead,
|
||||||
&hToken) &&
|
&hToken) &&
|
||||||
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
|
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
|
||||||
AccessCheck(psecurity, hImpersonatedToken, flags, &mapping, &privileges,
|
AccessCheck(&security.s, hImpersonatedToken, flags, &mapping, &privileges,
|
||||||
&privsize, &granted, &result) &&
|
&privsize, &granted, &result) &&
|
||||||
(result || flags == F_OK)) {
|
(result || flags == F_OK)) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} else {
|
||||||
rc = winerr();
|
rc = winerr();
|
||||||
}
|
}
|
||||||
free_s(&psecurity);
|
|
||||||
close(hImpersonatedToken);
|
close(hImpersonatedToken);
|
||||||
close(hToken);
|
close(hToken);
|
||||||
return rc;
|
return rc;
|
|
@ -57,10 +57,7 @@ int(vdprintf)(int fd, const char *fmt, va_list va) {
|
||||||
struct VdprintfState df;
|
struct VdprintfState df;
|
||||||
df.n = 0;
|
df.n = 0;
|
||||||
df.fd = fd;
|
df.fd = fd;
|
||||||
if (palandprintf(vdprintfputchar, &df, fmt, va) != -1 ||
|
if (palandprintf(vdprintfputchar, &df, fmt, va) == -1) return -1;
|
||||||
vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) != -1) {
|
if (vdprintf_flush(&df, df.n & (ARRAYLEN(df.buf) - 1)) == -1) return -1;
|
||||||
return df.n;
|
return df.n;
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
x = ctx->rk[i].xmm;
|
||||||
asm("aesimc\t%1,%0" : "=x"(x) : "0"(x));
|
asm("aesimc\t%1,%0" : "=x"(x) : "0"(x));
|
||||||
ctx->rk[i].xmm = x;
|
ctx->rk[i].xmm = x;
|
||||||
} while (i++ < n);
|
} while (++i < n);
|
||||||
XMM_DESTROY(x);
|
XMM_DESTROY(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ static relegated noinline void unrijndaelinit$pure(struct Rijndael *ctx,
|
||||||
x = ctx->rk[i].xmm;
|
x = ctx->rk[i].xmm;
|
||||||
x = InvMixColumns(x);
|
x = InvMixColumns(x);
|
||||||
ctx->rk[i].xmm = x;
|
ctx->rk[i].xmm = x;
|
||||||
} while (i++ < n);
|
} while (++i < n);
|
||||||
XMM_DESTROY(x);
|
XMM_DESTROY(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,10 +45,11 @@
|
||||||
*/
|
*/
|
||||||
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
|
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char stackline[128];
|
char *line;
|
||||||
char *line = stackline;
|
size_t linesize;
|
||||||
size_t linecap = sizeof(stackline);
|
line = NULL;
|
||||||
while ((getline(&line, &linecap, f)) != -1) {
|
linesize = 0;
|
||||||
|
while ((getline(&line, &linesize, f)) != -1) {
|
||||||
struct HostsTxtEntry entry;
|
struct HostsTxtEntry entry;
|
||||||
char *addr, *name, *tok, *comment;
|
char *addr, *name, *tok, *comment;
|
||||||
if ((comment = strchr(line, '#'))) *comment = '\0';
|
if ((comment = strchr(line, '#'))) *comment = '\0';
|
||||||
|
@ -64,6 +65,6 @@ int parsehoststxt(struct HostsTxt *ht, FILE *f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_s(&line);
|
free(line);
|
||||||
return rc | ferror(f);
|
return rc | ferror(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/alg/arraylist.h"
|
#include "libc/alg/arraylist.h"
|
||||||
#include "libc/dns/dns.h"
|
#include "libc/dns/dns.h"
|
||||||
#include "libc/dns/resolvconf.h"
|
#include "libc/dns/resolvconf.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/sock/sock.h"
|
#include "libc/sock/sock.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
@ -44,13 +45,14 @@
|
||||||
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
||||||
/* TODO(jart): options ndots:5 */
|
/* TODO(jart): options ndots:5 */
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
char stackline[32];
|
char *line;
|
||||||
char *line = stackline;
|
size_t linesize;
|
||||||
size_t linecap = sizeof(stackline);
|
|
||||||
struct sockaddr_in nameserver;
|
struct sockaddr_in nameserver;
|
||||||
|
line = NULL;
|
||||||
|
linesize = 0;
|
||||||
nameserver.sin_family = AF_INET;
|
nameserver.sin_family = AF_INET;
|
||||||
nameserver.sin_port = htons(DNS_PORT);
|
nameserver.sin_port = htons(DNS_PORT);
|
||||||
while (getline(&line, &linecap, f) != -1) {
|
while (getline(&line, &linesize, f) != -1) {
|
||||||
char *directive, *value, *tok, *comment;
|
char *directive, *value, *tok, *comment;
|
||||||
if ((comment = strchr(line, '#'))) *comment = '\0';
|
if ((comment = strchr(line, '#'))) *comment = '\0';
|
||||||
if ((directive = strtok_r(line, " \t\r\n\v", &tok)) &&
|
if ((directive = strtok_r(line, " \t\r\n\v", &tok)) &&
|
||||||
|
@ -61,6 +63,6 @@ int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_s(&line);
|
free(line);
|
||||||
return rc | ferror(f);
|
return rc | ferror(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,14 +56,7 @@ static int g_cp437i[256 + ARRAYLEN(kCp437iMultimappings)];
|
||||||
* @see bing()
|
* @see bing()
|
||||||
*/
|
*/
|
||||||
int unbing(int c) {
|
int unbing(int c) {
|
||||||
int i, m, l, r;
|
int m, l, r;
|
||||||
static bool once;
|
|
||||||
if (!once) {
|
|
||||||
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
|
|
||||||
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
|
|
||||||
insertionsort(ARRAYLEN(g_cp437i), g_cp437i);
|
|
||||||
once = true;
|
|
||||||
}
|
|
||||||
l = 0;
|
l = 0;
|
||||||
r = ARRAYLEN(g_cp437i) - 1;
|
r = ARRAYLEN(g_cp437i) - 1;
|
||||||
while (l <= r) {
|
while (l <= r) {
|
||||||
|
@ -78,3 +71,12 @@ int unbing(int c) {
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static textstartup void g_cp437i_init() {
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
|
||||||
|
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
|
||||||
|
djbsort(ARRAYLEN(g_cp437i), g_cp437i);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *const g_cp437i_ctor[] initarray = {g_cp437i_init};
|
||||||
|
|
|
@ -336,6 +336,7 @@ typedef uint64_t uintmax_t;
|
||||||
* 4. unprofilable
|
* 4. unprofilable
|
||||||
* 5. unhookable
|
* 5. unhookable
|
||||||
*
|
*
|
||||||
|
* @note consider static or writing a macro
|
||||||
* @see externinline
|
* @see externinline
|
||||||
*/
|
*/
|
||||||
#ifndef forceinline
|
#ifndef forceinline
|
||||||
|
|
|
@ -66,8 +66,8 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BIGPAGESIZE 0x200000
|
#define BIGPAGESIZE 0x200000
|
||||||
|
#define STACKSIZE 0x20000
|
||||||
#define FRAMESIZE 0x10000 /* 8086 */
|
#define FRAMESIZE 0x10000 /* 8086 */
|
||||||
#define STACKSIZE 0x10000 /* goog */
|
|
||||||
#define PAGESIZE 0x1000 /* i386+ */
|
#define PAGESIZE 0x1000 /* i386+ */
|
||||||
#define BUFSIZ 0x1000 /* best stdio default */
|
#define BUFSIZ 0x1000 /* best stdio default */
|
||||||
#define CACHELINE 0x40 /* nexgen32e */
|
#define CACHELINE 0x40 /* nexgen32e */
|
||||||
|
|
|
@ -13,8 +13,7 @@ LIBC_INTRIN_A_SRCS = $(LIBC_INTRIN_A_SRCS_S) $(LIBC_INTRIN_A_SRCS_C)
|
||||||
LIBC_INTRIN_A_CHECKS = $(LIBC_INTRIN_A).pkg
|
LIBC_INTRIN_A_CHECKS = $(LIBC_INTRIN_A).pkg
|
||||||
|
|
||||||
LIBC_INTRIN_A_FILES := \
|
LIBC_INTRIN_A_FILES := \
|
||||||
$(wildcard libc/intrin/*) \
|
$(wildcard libc/intrin/*)
|
||||||
$(wildcard libc/intrin/delegates/*)
|
|
||||||
|
|
||||||
LIBC_INTRIN_A_OBJS = \
|
LIBC_INTRIN_A_OBJS = \
|
||||||
$(LIBC_INTRIN_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
$(LIBC_INTRIN_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_INTRIN_REPMOVSB_H_
|
#define COSMOPOLITAN_LIBC_INTRIN_REPMOVSB_H_
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
static void repmovsb(void **dest, const void **src, size_t cx) {
|
forceinline void repmovsb(void **dest, const void **src, size_t cx) {
|
||||||
char *di = (char *)*dest;
|
char *di = (char *)*dest;
|
||||||
const char *si = (const char *)*src;
|
const char *si = (const char *)*src;
|
||||||
while (cx) *di++ = *si++, cx--;
|
while (cx) *di++ = *si++, cx--;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_INTRIN_REPSTOSB_H_
|
#define COSMOPOLITAN_LIBC_INTRIN_REPSTOSB_H_
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
|
|
||||||
static void *repstosb(void *dest, unsigned char al, size_t cx) {
|
forceinline void *repstosb(void *dest, unsigned char al, size_t cx) {
|
||||||
unsigned char *di = (unsigned char *)dest;
|
unsigned char *di = (unsigned char *)dest;
|
||||||
while (cx) *di++ = al, cx--;
|
while (cx) *di++ = al, cx--;
|
||||||
return di;
|
return di;
|
||||||
|
|
370
libc/log/asan.c
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/fmt/fmt.h"
|
||||||
#include "libc/log/gdb.h"
|
#include "libc/log/gdb.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#include "libc/nexgen32e/vendor.h"
|
#include "libc/nexgen32e/vendor.h"
|
||||||
#include "libc/paths.h"
|
#include "libc/paths.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/log/backtrace.h"
|
||||||
#include "libc/log/log.h"
|
|
||||||
|
|
||||||
void backtrace(FILE *f) {
|
void backtrace(FILE *f) {
|
||||||
showbacktrace(f, __builtin_frame_address(0));
|
showbacktrace(f, __builtin_frame_address(0));
|
||||||
|
|
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/conv/conv.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/log/backtrace.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/nexgen32e/gc.h"
|
#include "libc/nexgen32e/gc.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -37,54 +38,7 @@
|
||||||
#define kBacktraceMaxFrames 128
|
#define kBacktraceMaxFrames 128
|
||||||
#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1))
|
#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1))
|
||||||
|
|
||||||
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
static int PrintBacktraceUsingAddr2line(FILE *f, const struct StackFrame *bp) {
|
||||||
char *out, unsigned size, bool symbolic) {
|
|
||||||
int64_t addend;
|
|
||||||
const char *name;
|
|
||||||
const struct Symbol *symbol;
|
|
||||||
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
|
||||||
(intptr_t)addr <= (intptr_t)&_end && symbolic)) {
|
|
||||||
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
|
||||||
st->count, addr - st->addr_base - 1)];
|
|
||||||
addend = addr - st->addr_base - symbol->addr_rva;
|
|
||||||
name = &st->name_base[symbol->name_rva];
|
|
||||||
snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', abs(addend));
|
|
||||||
} else {
|
|
||||||
snprintf(out, size, "%p", addr);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
|
||||||
char buf[hasatleast kBacktraceBufSize]) {
|
|
||||||
size_t gi;
|
|
||||||
intptr_t addr;
|
|
||||||
struct Garbages *garbage;
|
|
||||||
struct SymbolTable *symbols;
|
|
||||||
const struct StackFrame *frame;
|
|
||||||
if ((symbols = getsymboltable())) {
|
|
||||||
garbage = weaken(g_garbage);
|
|
||||||
gi = garbage ? garbage->i : 0;
|
|
||||||
for (frame = bp; frame; frame = frame->next) {
|
|
||||||
addr = frame->addr;
|
|
||||||
if (addr == weakaddr("CollectGarbage")) {
|
|
||||||
do {
|
|
||||||
--gi;
|
|
||||||
} while ((addr = garbage->p[gi].ret) == weakaddr("CollectGarbage"));
|
|
||||||
}
|
|
||||||
fprintf(f, "%p %p %s\n", frame, addr,
|
|
||||||
FormatAddress(f, symbols, addr, buf, kBacktraceBufSize, true));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int PrintBacktraceUsingAddr2line(
|
|
||||||
FILE *f, const struct StackFrame *bp,
|
|
||||||
char buf[hasatleast kBacktraceBufSize],
|
|
||||||
char *argv[hasatleast kBacktraceMaxFrames]) {
|
|
||||||
ssize_t got;
|
ssize_t got;
|
||||||
intptr_t addr;
|
intptr_t addr;
|
||||||
size_t i, j, gi;
|
size_t i, j, gi;
|
||||||
|
@ -92,6 +46,7 @@ static int PrintBacktraceUsingAddr2line(
|
||||||
struct Garbages *garbage;
|
struct Garbages *garbage;
|
||||||
const struct StackFrame *frame;
|
const struct StackFrame *frame;
|
||||||
const char *debugbin, *p1, *p2, *p3, *addr2line;
|
const char *debugbin, *p1, *p2, *p3, *addr2line;
|
||||||
|
char buf[kBacktraceBufSize], *argv[kBacktraceMaxFrames];
|
||||||
if (!(debugbin = finddebugbinary()) || !(addr2line = GetAddr2linePath())) {
|
if (!(debugbin = finddebugbinary()) || !(addr2line = GetAddr2linePath())) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -148,24 +103,20 @@ static int PrintBacktraceUsingAddr2line(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline int PrintBacktrace(FILE *f, const struct StackFrame *bp,
|
static int PrintBacktrace(FILE *f, const struct StackFrame *bp) {
|
||||||
char *argv[hasatleast kBacktraceMaxFrames],
|
|
||||||
char buf[hasatleast kBacktraceBufSize]) {
|
|
||||||
if (!IsTiny()) {
|
if (!IsTiny()) {
|
||||||
if (PrintBacktraceUsingAddr2line(f, bp, buf, argv) != -1) {
|
if (PrintBacktraceUsingAddr2line(f, bp) != -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PrintBacktraceUsingSymbols(f, bp, buf);
|
return PrintBacktraceUsingSymbols(f, bp, getsymboltable());
|
||||||
}
|
}
|
||||||
|
|
||||||
void showbacktrace(FILE *f, const struct StackFrame *bp) {
|
void showbacktrace(FILE *f, const struct StackFrame *bp) {
|
||||||
static bool noreentry;
|
static bool noreentry;
|
||||||
char *argv[kBacktraceMaxFrames];
|
|
||||||
char buf[kBacktraceBufSize];
|
|
||||||
if (!noreentry) {
|
if (!noreentry) {
|
||||||
noreentry = true;
|
noreentry = true;
|
||||||
PrintBacktrace(f, bp, argv, buf);
|
PrintBacktrace(f, bp);
|
||||||
noreentry = 0;
|
noreentry = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,83 +17,53 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/alg/bisectcarleft.h"
|
||||||
|
#include "libc/bits/weaken.h"
|
||||||
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/log/backtrace.h"
|
||||||
|
#include "libc/macros.h"
|
||||||
|
#include "libc/nexgen32e/gc.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
|
#include "libc/runtime/symbols.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
|
||||||
#include "libc/sysv/consts/fileno.h"
|
|
||||||
|
|
||||||
struct SourceLocation {
|
static char *FormatAddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
||||||
const char *filename;
|
char *out, unsigned size, bool symbolic) {
|
||||||
int line;
|
int64_t addend;
|
||||||
int column;
|
const char *name;
|
||||||
};
|
const struct Symbol *symbol;
|
||||||
|
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
||||||
struct AccessInfo {
|
(intptr_t)addr <= (intptr_t)&_end && symbolic)) {
|
||||||
const uint8_t *addr;
|
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||||
const uint8_t *first_bad_addr;
|
st->count, addr - st->addr_base - 1)];
|
||||||
size_t size;
|
addend = addr - st->addr_base - symbol->addr_rva;
|
||||||
bool iswrite;
|
name = &st->name_base[symbol->name_rva];
|
||||||
unsigned long ip;
|
snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', ABS(addend));
|
||||||
};
|
} else {
|
||||||
|
snprintf(out, size, "%p", addr);
|
||||||
struct Global {
|
}
|
||||||
const uint8_t *addr;
|
return out;
|
||||||
size_t size;
|
|
||||||
size_t size_with_redzone;
|
|
||||||
const void *name;
|
|
||||||
const void *module_name;
|
|
||||||
unsigned long has_cxx_init;
|
|
||||||
struct kasan_source_location *location;
|
|
||||||
char *odr_indicator;
|
|
||||||
};
|
|
||||||
|
|
||||||
privileged void __asan_init(void) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged void __asan_version_mismatch_check_v8(void) {
|
int PrintBacktraceUsingSymbols(FILE *f, const struct StackFrame *bp,
|
||||||
}
|
struct SymbolTable *symbols) {
|
||||||
|
size_t gi;
|
||||||
privileged void __asan_register_globals(struct Global globals[], int n) {
|
char buf[256];
|
||||||
}
|
intptr_t addr;
|
||||||
|
struct Garbages *garbage;
|
||||||
privileged void __asan_unregister_globals(struct Global globals[], int n) {
|
const struct StackFrame *frame;
|
||||||
}
|
if (!symbols) return -1;
|
||||||
|
garbage = weaken(g_garbage);
|
||||||
privileged void __asan_report_load_n(uint8_t *p, int n) {
|
gi = garbage ? garbage->i : 0;
|
||||||
}
|
for (frame = bp; frame; frame = frame->next) {
|
||||||
|
addr = frame->addr;
|
||||||
privileged void __asan_report_store_n(uint8_t *p, int n) {
|
if (addr == weakaddr("CollectGarbage")) {
|
||||||
__asan_report_load_n(p, n);
|
do {
|
||||||
}
|
--gi;
|
||||||
|
} while ((addr = garbage->p[gi].ret) == weakaddr("CollectGarbage"));
|
||||||
privileged void __asan_loadN(uintptr_t ptr, size_t size) {
|
}
|
||||||
}
|
fprintf(f, "%p %p %s\n", frame, addr,
|
||||||
|
FormatAddress(f, symbols, addr, buf, sizeof(buf), true));
|
||||||
privileged void __asan_storeN(uintptr_t ptr, size_t size) {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
privileged uintptr_t __asan_stack_malloc(size_t size, int classid) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
privileged void __asan_stack_free(uintptr_t ptr, size_t size, int classid) {
|
|
||||||
}
|
|
||||||
|
|
||||||
privileged void __asan_handle_no_return(void) {
|
|
||||||
DebugBreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
privileged void __asan_alloca_poison(uintptr_t addr, uintptr_t size) {
|
|
||||||
}
|
|
||||||
|
|
||||||
privileged void __asan_allocas_unpoison(uintptr_t top, uintptr_t bottom) {
|
|
||||||
}
|
|
||||||
|
|
||||||
privileged void *__asan_addr_is_in_fake_stack(void *fakestack, void *addr,
|
|
||||||
void **beg, void **end) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
privileged void *__asan_get_current_fake_stack(void) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
|
@ -28,13 +28,14 @@
|
||||||
*/
|
*/
|
||||||
nodiscard char *commandvenv(const char *var, const char *cmd) {
|
nodiscard char *commandvenv(const char *var, const char *cmd) {
|
||||||
const char *exepath;
|
const char *exepath;
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
if ((exepath = getenv(var))) {
|
if ((exepath = getenv(var))) {
|
||||||
if (!isempty(exepath) && access(exepath, X_OK) != -1) {
|
if (!isempty(exepath) && access(exepath, X_OK) != -1) {
|
||||||
return exepath;
|
return exepath;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
} else if ((exepath = commandv(cmd))) {
|
} else if ((exepath = commandv(cmd, pathbuf))) {
|
||||||
return exepath;
|
return exepath;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
#include "libc/log/gdb.h"
|
#include "libc/log/gdb.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/runtime/symbols.h"
|
#include "libc/runtime/symbols.h"
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,6 @@ COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
struct sigset;
|
struct sigset;
|
||||||
struct winsize;
|
struct winsize;
|
||||||
struct StackFrame;
|
|
||||||
typedef struct FILE FILE;
|
typedef struct FILE FILE;
|
||||||
|
|
||||||
extern FILE *g_logfile;
|
extern FILE *g_logfile;
|
||||||
|
@ -51,7 +50,6 @@ void showcrashreports(void);
|
||||||
void callexitontermination(struct sigset *);
|
void callexitontermination(struct sigset *);
|
||||||
bool32 IsDebuggerPresent(bool);
|
bool32 IsDebuggerPresent(bool);
|
||||||
bool isrunningundermake(void);
|
bool isrunningundermake(void);
|
||||||
void showbacktrace(FILE *, const struct StackFrame *);
|
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § liblog » logging ─╬─│┼
|
│ cosmopolitan § liblog » logging ─╬─│┼
|
||||||
|
|
|
@ -8,7 +8,6 @@ LIBC_LOG = $(LIBC_LOG_A_DEPS) $(LIBC_LOG_A)
|
||||||
LIBC_LOG_A = o/$(MODE)/libc/log/log.a
|
LIBC_LOG_A = o/$(MODE)/libc/log/log.a
|
||||||
LIBC_LOG_A_FILES := \
|
LIBC_LOG_A_FILES := \
|
||||||
$(wildcard libc/log/thunks/*) \
|
$(wildcard libc/log/thunks/*) \
|
||||||
$(wildcard libc/log/elf/*) \
|
|
||||||
$(wildcard libc/log/*)
|
$(wildcard libc/log/*)
|
||||||
LIBC_LOG_A_HDRS = $(filter %.h,$(LIBC_LOG_A_FILES))
|
LIBC_LOG_A_HDRS = $(filter %.h,$(LIBC_LOG_A_FILES))
|
||||||
LIBC_LOG_A_SRCS_C = $(filter %.c,$(LIBC_LOG_A_FILES))
|
LIBC_LOG_A_SRCS_C = $(filter %.c,$(LIBC_LOG_A_FILES))
|
||||||
|
@ -38,6 +37,7 @@ LIBC_LOG_A_DIRECTDEPS = \
|
||||||
LIBC_TINYMATH \
|
LIBC_TINYMATH \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
LIBC_NT_KERNELBASE \
|
LIBC_NT_KERNELBASE \
|
||||||
|
LIBC_MEM \
|
||||||
LIBC_RAND \
|
LIBC_RAND \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
LIBC_STDIO \
|
LIBC_STDIO \
|
||||||
|
@ -60,17 +60,10 @@ $(LIBC_LOG_A).pkg: \
|
||||||
$(LIBC_LOG_A_OBJS) \
|
$(LIBC_LOG_A_OBJS) \
|
||||||
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
|
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
o/$(MODE)/libc/log/die.o \
|
$(LIBC_LOG_A_OBJS): \
|
||||||
o/$(MODE)/libc/log/perror.o \
|
OVERRIDE_CFLAGS += \
|
||||||
o/$(MODE)/libc/log/ftrace.o \
|
$(NO_MAGIC) \
|
||||||
o/$(MODE)/libc/log/ubsan.o \
|
-fwrapv
|
||||||
o/$(MODE)/libc/log/symbols.o \
|
|
||||||
o/$(MODE)/libc/log/backtrace.o \
|
|
||||||
o/$(MODE)/libc/log/oncrash.o \
|
|
||||||
o/$(MODE)/libc/log/shadowargs.o \
|
|
||||||
o/$(MODE)/libc/log/thunks/__check_fail_ndebug.o: \
|
|
||||||
OVERRIDE_COPTS += \
|
|
||||||
$(NO_MAGIC)
|
|
||||||
|
|
||||||
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
|
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
|
||||||
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))
|
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
|
|
@ -23,10 +23,12 @@
|
||||||
#include "libc/calls/ucontext.h"
|
#include "libc/calls/ucontext.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/log/backtrace.h"
|
||||||
#include "libc/log/gdb.h"
|
#include "libc/log/gdb.h"
|
||||||
#include "libc/log/internal.h"
|
#include "libc/log/internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#include "libc/runtime/internal.h"
|
#include "libc/runtime/internal.h"
|
||||||
#include "libc/runtime/memtrack.h"
|
#include "libc/runtime/memtrack.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -163,7 +165,6 @@ relegated static void ShowCrashReport(int err, FILE *f, int sig,
|
||||||
}
|
}
|
||||||
fputc('\n', f);
|
fputc('\n', f);
|
||||||
fflush(f);
|
fflush(f);
|
||||||
memsummary(fileno(f));
|
|
||||||
ShowMemoryMappings(fileno(f));
|
ShowMemoryMappings(fileno(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
.privileged
|
.privileged
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
|
/ @fileoverview Address Sanitizer Thunks
|
||||||
|
/
|
||||||
|
/ This has tiny code size and reduces API surface area
|
||||||
|
/ since ASAN has the same stylistic hugeness as UBSAN.
|
||||||
|
/ We also guard all the functions, against reentrancy.
|
||||||
|
|
||||||
__asan_load1:
|
__asan_load1:
|
||||||
push $1
|
push $1
|
||||||
jmp OnLoad
|
jmp OnLoad
|
||||||
|
@ -43,13 +49,11 @@ __asan_load16:
|
||||||
.endfn __asan_load16,globl
|
.endfn __asan_load16,globl
|
||||||
__asan_load32:
|
__asan_load32:
|
||||||
push $32
|
push $32
|
||||||
/ fallthrough
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_load32,globl
|
.endfn __asan_load32,globl
|
||||||
OnLoad: pop %rsi
|
OnLoad: pop %rsi
|
||||||
.globl __asan_loadN
|
|
||||||
.weak __asan_loadN
|
|
||||||
ezlea __asan_loadN,ax
|
ezlea __asan_loadN,ax
|
||||||
jmp OnAsan
|
jmp __asan_report_noreentry
|
||||||
.endfn OnStore
|
.endfn OnStore
|
||||||
|
|
||||||
__asan_store1:
|
__asan_store1:
|
||||||
|
@ -74,13 +78,11 @@ __asan_store16:
|
||||||
.endfn __asan_store16,globl
|
.endfn __asan_store16,globl
|
||||||
__asan_store32:
|
__asan_store32:
|
||||||
push $32
|
push $32
|
||||||
/ fallthrough
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_store32,globl
|
.endfn __asan_store32,globl
|
||||||
OnStore:pop %rsi
|
OnStore:pop %rsi
|
||||||
.globl __asan_storeN
|
|
||||||
.weak __asan_storeN
|
|
||||||
ezlea __asan_storeN,ax
|
ezlea __asan_storeN,ax
|
||||||
jmp OnAsan
|
jmp __asan_report_noreentry
|
||||||
.endfn OnStore
|
.endfn OnStore
|
||||||
|
|
||||||
__asan_report_load1:
|
__asan_report_load1:
|
||||||
|
@ -101,14 +103,12 @@ __asan_report_load8:
|
||||||
.endfn __asan_report_load8,globl
|
.endfn __asan_report_load8,globl
|
||||||
__asan_report_load16:
|
__asan_report_load16:
|
||||||
push $16
|
push $16
|
||||||
/ fallthrough
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_report_load16,globl
|
.endfn __asan_report_load16,globl
|
||||||
OnReportLoad:
|
OnReportLoad:
|
||||||
pop %rsi
|
pop %rsi
|
||||||
.globl __asan_report_load_n
|
|
||||||
.weak __asan_report_load_n
|
|
||||||
ezlea __asan_report_load_n,ax
|
ezlea __asan_report_load_n,ax
|
||||||
jmp OnAsan
|
jmp __asan_report_noreentry
|
||||||
.endfn OnReportLoad
|
.endfn OnReportLoad
|
||||||
|
|
||||||
__asan_report_store1:
|
__asan_report_store1:
|
||||||
|
@ -133,33 +133,31 @@ __asan_report_store16:
|
||||||
.endfn __asan_report_store16,globl
|
.endfn __asan_report_store16,globl
|
||||||
__asan_report_store32:
|
__asan_report_store32:
|
||||||
push $32
|
push $32
|
||||||
/ fallthrough
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_report_store32,globl
|
.endfn __asan_report_store32,globl
|
||||||
ReportStore:
|
ReportStore:
|
||||||
pop %rsi
|
pop %rsi
|
||||||
.globl __asan_report_store_n
|
|
||||||
.weak __asan_report_store_n
|
|
||||||
ezlea __asan_report_store_n,ax
|
ezlea __asan_report_store_n,ax
|
||||||
/ fallthrough
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn ReportStore
|
.endfn ReportStore
|
||||||
|
|
||||||
OnAsan: test %rax,%rax
|
__asan_report_noreentry:
|
||||||
jz 1f
|
push %rbp
|
||||||
jmp *%rax
|
mov %rsp,%rbp
|
||||||
1: ret
|
cmpb $0,noreentry(%rip)
|
||||||
.endfn OnAsan
|
jnz 2f
|
||||||
|
incb noreentry(%rip)
|
||||||
|
call *%rax
|
||||||
|
decb noreentry(%rip)
|
||||||
|
pop %rbp
|
||||||
|
ret
|
||||||
|
2: call abort
|
||||||
|
.endfn __asan_report_noreentry
|
||||||
|
|
||||||
__asan_stack_free_0:
|
__asan_stack_free_0:
|
||||||
push $0
|
push $0
|
||||||
/ fallthrough
|
jmp OnStackFree
|
||||||
.endfn __asan_stack_free_0,globl
|
.endfn __asan_stack_free_0,globl
|
||||||
OnStackFree:
|
|
||||||
pop %rdx
|
|
||||||
.globl __asan_stack_free
|
|
||||||
.weak __asan_stack_free
|
|
||||||
ezlea __asan_stack_free,ax
|
|
||||||
jmp OnAsan
|
|
||||||
.endfn OnStackFree
|
|
||||||
__asan_stack_free_1:
|
__asan_stack_free_1:
|
||||||
push $1
|
push $1
|
||||||
jmp OnStackFree
|
jmp OnStackFree
|
||||||
|
@ -198,20 +196,17 @@ __asan_stack_free_9:
|
||||||
.endfn __asan_stack_free_9,globl
|
.endfn __asan_stack_free_9,globl
|
||||||
__asan_stack_free_10:
|
__asan_stack_free_10:
|
||||||
push $10
|
push $10
|
||||||
jmp OnStackFree
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_stack_free_10,globl
|
.endfn __asan_stack_free_10,globl
|
||||||
|
OnStackFree:
|
||||||
|
pop %rdx
|
||||||
|
jmp __asan_stack_free
|
||||||
|
.endfn OnStackFree
|
||||||
|
|
||||||
__asan_stack_malloc_0:
|
__asan_stack_malloc_0:
|
||||||
push $0
|
push $0
|
||||||
/ fallthrough
|
jmp OnStackMalloc
|
||||||
.endfn __asan_stack_malloc_0,globl
|
.endfn __asan_stack_malloc_0,globl
|
||||||
OnStackMalloc:
|
|
||||||
pop %rsi
|
|
||||||
.globl __asan_stack_malloc
|
|
||||||
.weak __asan_stack_malloc
|
|
||||||
ezlea __asan_stack_malloc,ax
|
|
||||||
jmp OnAsan
|
|
||||||
.endfn OnStackMalloc
|
|
||||||
__asan_stack_malloc_1:
|
__asan_stack_malloc_1:
|
||||||
push $1
|
push $1
|
||||||
jmp OnStackMalloc
|
jmp OnStackMalloc
|
||||||
|
@ -250,11 +245,54 @@ __asan_stack_malloc_9:
|
||||||
.endfn __asan_stack_malloc_9,globl
|
.endfn __asan_stack_malloc_9,globl
|
||||||
__asan_stack_malloc_10:
|
__asan_stack_malloc_10:
|
||||||
push $10
|
push $10
|
||||||
jmp OnStackMalloc
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn __asan_stack_malloc_10,globl
|
.endfn __asan_stack_malloc_10,globl
|
||||||
|
OnStackMalloc:
|
||||||
|
pop %rsi
|
||||||
|
jmp __asan_stack_malloc
|
||||||
|
.endfn OnStackMalloc
|
||||||
|
|
||||||
|
__asan_handle_no_return:
|
||||||
|
ret
|
||||||
|
.endfn __asan_handle_no_return,globl
|
||||||
|
|
||||||
|
__asan_before_dynamic_init:
|
||||||
|
ret
|
||||||
|
.endfn __asan_before_dynamic_init,globl
|
||||||
|
|
||||||
|
__asan_after_dynamic_init:
|
||||||
|
ret
|
||||||
|
.endfn __asan_after_dynamic_init,globl
|
||||||
|
|
||||||
|
__asan_unregister_globals:
|
||||||
|
ret
|
||||||
|
.endfn __asan_unregister_globals,globl
|
||||||
|
|
||||||
|
__asan_version_mismatch_check_v8:
|
||||||
|
ret
|
||||||
|
.endfn __asan_version_mismatch_check_v8,globl
|
||||||
|
|
||||||
|
/ Initializes Address Sanitizer runtime earlier if linked.
|
||||||
|
.init.start 301,_init_asan
|
||||||
|
push %rdi
|
||||||
|
push %rsi
|
||||||
|
mov %r12,%rdi
|
||||||
|
mov %r13,%rsi
|
||||||
|
mov %r14,%rdx
|
||||||
|
mov %r15,%rcx
|
||||||
|
call __asan_init
|
||||||
|
pop %rsi
|
||||||
|
pop %rdi
|
||||||
|
.init.end 301,_init_asan
|
||||||
|
|
||||||
.rodata.cst4
|
.rodata.cst4
|
||||||
__asan_option_detect_stack_use_after_return:
|
__asan_option_detect_stack_use_after_return:
|
||||||
.long 1
|
.long 1
|
||||||
.endobj __asan_option_detect_stack_use_after_return,globl
|
.endobj __asan_option_detect_stack_use_after_return,globl
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
|
.bss
|
||||||
|
noreentry:
|
||||||
|
.byte 0
|
||||||
|
.endobj noreentry
|
||||||
|
.previous
|
|
@ -6,9 +6,7 @@ PKGS += LIBC_MATH
|
||||||
LIBC_MATH_ARTIFACTS += LIBC_MATH_A
|
LIBC_MATH_ARTIFACTS += LIBC_MATH_A
|
||||||
LIBC_MATH = $(LIBC_MATH_A_DEPS) $(LIBC_MATH_A)
|
LIBC_MATH = $(LIBC_MATH_A_DEPS) $(LIBC_MATH_A)
|
||||||
LIBC_MATH_A = o/$(MODE)/libc/math/math.a
|
LIBC_MATH_A = o/$(MODE)/libc/math/math.a
|
||||||
LIBC_MATH_A_FILES := \
|
LIBC_MATH_A_FILES := $(wildcard libc/math/*)
|
||||||
$(wildcard libc/math/*) \
|
|
||||||
$(wildcard libc/math/delegates/*)
|
|
||||||
LIBC_MATH_A_SRCS_A = $(filter %.s,$(LIBC_MATH_A_FILES))
|
LIBC_MATH_A_SRCS_A = $(filter %.s,$(LIBC_MATH_A_FILES))
|
||||||
LIBC_MATH_A_SRCS_S = $(filter %.S,$(LIBC_MATH_A_FILES))
|
LIBC_MATH_A_SRCS_S = $(filter %.S,$(LIBC_MATH_A_FILES))
|
||||||
LIBC_MATH_A_SRCS_C = $(filter %.c,$(LIBC_MATH_A_FILES))
|
LIBC_MATH_A_SRCS_C = $(filter %.c,$(LIBC_MATH_A_FILES))
|
||||||
|
|
|
@ -26,34 +26,61 @@
|
||||||
/ @param %rsi is ignored
|
/ @param %rsi is ignored
|
||||||
/ @param %rdx is ignored
|
/ @param %rdx is ignored
|
||||||
_ZdlPvSt11align_val_tRKSt9nothrow_t:
|
_ZdlPvSt11align_val_tRKSt9nothrow_t:
|
||||||
|
/ operator delete(void*, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZdaPvSt11align_val_tRKSt9nothrow_t:
|
_ZdaPvSt11align_val_tRKSt9nothrow_t:
|
||||||
|
/ operator delete[](void*, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZdlPvRKSt9nothrow_t:
|
_ZdlPvRKSt9nothrow_t:
|
||||||
|
/ operator delete(void*, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdlPvRKSt9nothrow_t,weak
|
||||||
_ZdaPvRKSt9nothrow_t:
|
_ZdaPvRKSt9nothrow_t:
|
||||||
|
/ operator delete[](void*, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdaPvRKSt9nothrow_t,weak
|
||||||
_ZdlPvmSt11align_val_t:
|
_ZdlPvmSt11align_val_t:
|
||||||
|
/ operator delete(void*, unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdlPvmSt11align_val_t,weak
|
||||||
_ZdaPvmSt11align_val_t:
|
_ZdaPvmSt11align_val_t:
|
||||||
|
/ operator delete[](void*, unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdaPvmSt11align_val_t,weak
|
||||||
_ZdlPvSt11align_val_t:
|
_ZdlPvSt11align_val_t:
|
||||||
|
/ operator delete(void*, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdlPvSt11align_val_t,weak
|
||||||
_ZdaPvSt11align_val_t:
|
_ZdaPvSt11align_val_t:
|
||||||
|
/ operator delete[](void*, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
_ZdaPvm:nop
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
_ZdlPvm:nop
|
.endfn _ZdaPvSt11align_val_t,weak
|
||||||
_ZdaPv: nop
|
_ZdaPvm:
|
||||||
_ZdlPv: jmp *hook$free(%rip)
|
/ operator delete[](void*, unsigned long):
|
||||||
.endfn _ZdlPv,globl,weak
|
nop
|
||||||
.endfn _ZdaPv,globl,weak
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdaPvm,globl,weak
|
.endfn _ZdaPvm,weak
|
||||||
.endfn _ZdlPvm,globl,weak
|
_ZdlPvm:
|
||||||
.endfn _ZdaPvRKSt9nothrow_t,globl,weak
|
/ operator delete(void*, unsigned long)
|
||||||
.endfn _ZdlPvRKSt9nothrow_t,globl,weak
|
nop
|
||||||
.endfn _ZdaPvSt11align_val_t,globl,weak
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
.endfn _ZdlPvSt11align_val_t,globl,weak
|
.endfn _ZdlPvm,weak
|
||||||
.endfn _ZdaPvmSt11align_val_t,globl,weak
|
_ZdaPv:
|
||||||
.endfn _ZdlPvmSt11align_val_t,globl,weak
|
/ operator delete[](void*)
|
||||||
.endfn _ZdlPvSt11align_val_tRKSt9nothrow_t,globl,weak
|
nop
|
||||||
.endfn _ZdaPvSt11align_val_tRKSt9nothrow_t,globl,weak
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZdaPv,weak
|
||||||
|
_ZdlPv:
|
||||||
|
/ operator delete(void*)
|
||||||
|
jmp *hook$free(%rip)
|
||||||
|
.endfn _ZdlPv,weak
|
|
@ -26,15 +26,24 @@
|
||||||
/ @param %rsi is ignored
|
/ @param %rsi is ignored
|
||||||
/ @return new memory or NULL on OOM
|
/ @return new memory or NULL on OOM
|
||||||
_ZnamRKSt9nothrow_t:
|
_ZnamRKSt9nothrow_t:
|
||||||
|
/ operator new[](unsigned long, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZnamRKSt9nothrow_t,weak
|
||||||
_ZnwmRKSt9nothrow_t:
|
_ZnwmRKSt9nothrow_t:
|
||||||
|
/ operator new(unsigned long, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
_Znam: nop
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
_Znwm: test %rdi,%rdi
|
.endfn _ZnwmRKSt9nothrow_t,weak
|
||||||
|
_Znam:
|
||||||
|
/ operator new[](unsigned long)
|
||||||
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _Znam,weak
|
||||||
|
_Znwm:
|
||||||
|
/ operator new(unsigned long)
|
||||||
|
test %rdi,%rdi
|
||||||
jne 1f
|
jne 1f
|
||||||
mov $1,%edi
|
mov $1,%edi
|
||||||
1: jmp *hook$malloc(%rip)
|
1: jmp *hook$malloc(%rip)
|
||||||
.endfn _Znwm,globl,weak
|
.endfn _Znwm,weak
|
||||||
.endfn _Znam,globl,weak
|
|
||||||
.endfn _ZnwmRKSt9nothrow_t,globl,weak
|
|
||||||
.endfn _ZnamRKSt9nothrow_t,globl,weak
|
|
|
@ -27,12 +27,22 @@
|
||||||
/ @param %rdx is ignored
|
/ @param %rdx is ignored
|
||||||
/ @return new memory or NULL on OOM
|
/ @return new memory or NULL on OOM
|
||||||
_ZnamSt11align_val_tRKSt9nothrow_t:
|
_ZnamSt11align_val_tRKSt9nothrow_t:
|
||||||
|
/ operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZnwmSt11align_val_tRKSt9nothrow_t:
|
_ZnwmSt11align_val_tRKSt9nothrow_t:
|
||||||
|
/ operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,weak
|
||||||
_ZnwmSt11align_val_t:
|
_ZnwmSt11align_val_t:
|
||||||
|
/ operator new(unsigned long, std::align_val_t)
|
||||||
nop
|
nop
|
||||||
|
/ 𝑠𝑙𝑖𝑑𝑒
|
||||||
|
.endfn _ZnwmSt11align_val_t,weak
|
||||||
_ZnamSt11align_val_t:
|
_ZnamSt11align_val_t:
|
||||||
|
/ operator new[](unsigned long, std::align_val_t)
|
||||||
test %rdi,%rdi
|
test %rdi,%rdi
|
||||||
jnz 1f
|
jnz 1f
|
||||||
mov $1,%eax
|
mov $1,%eax
|
||||||
|
@ -41,7 +51,4 @@ _ZnamSt11align_val_t:
|
||||||
cmovb %rax,%rsi
|
cmovb %rax,%rsi
|
||||||
xchg %rdi,%rsi
|
xchg %rdi,%rsi
|
||||||
jmp *hook$memalign(%rip)
|
jmp *hook$memalign(%rip)
|
||||||
.endfn _ZnwmSt11align_val_t,globl,weak
|
.endfn _ZnamSt11align_val_t,weak
|
||||||
.endfn _ZnamSt11align_val_t,globl,weak
|
|
||||||
.endfn _ZnamSt11align_val_tRKSt9nothrow_t,globl,weak
|
|
||||||
.endfn _ZnwmSt11align_val_tRKSt9nothrow_t,globl,weak
|
|
|
@ -20,15 +20,15 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 800,_init_calloc
|
.initbss 202,_init_calloc
|
||||||
hook$calloc:
|
hook$calloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$calloc,globl,hidden
|
.endobj hook$calloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 800,_init_calloc
|
.init.start 202,_init_calloc
|
||||||
.hidden dlcalloc
|
.hidden dlcalloc
|
||||||
ezlea dlcalloc,ax
|
ezlea dlcalloc,ax
|
||||||
stosq
|
stosq
|
||||||
yoink free
|
yoink free
|
||||||
.init.end 800,_init_calloc
|
.init.end 202,_init_calloc
|
|
@ -20,16 +20,16 @@
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 800,_init_free
|
.initbss 202,_init_free
|
||||||
hook$free:
|
hook$free:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$free,globl,hidden
|
.endobj hook$free,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 800,_init_free
|
.init.start 202,_init_free
|
||||||
ezlea dlfree,ax
|
ezlea dlfree,ax
|
||||||
stosq
|
stosq
|
||||||
yoink realloc
|
yoink realloc
|
||||||
.init.end 800,_init_free
|
.init.end 202,_init_free
|
||||||
|
|
||||||
.hidden dlfree
|
.hidden dlfree
|
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"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 800,_init_malloc
|
.initbss 202,_init_malloc
|
||||||
hook$malloc:
|
hook$malloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$malloc,globl,hidden
|
.endobj hook$malloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 800,_init_malloc
|
.init.start 202,_init_malloc
|
||||||
|
.hidden dlmalloc
|
||||||
ezlea dlmalloc,ax
|
ezlea dlmalloc,ax
|
||||||
stosq
|
stosq
|
||||||
yoink free
|
yoink free
|
||||||
.init.end 800,_init_malloc
|
.init.end 202,_init_malloc
|
||||||
|
|
||||||
.hidden dlmalloc
|
|
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"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 800,_init_memalign
|
.initbss 202,_init_memalign
|
||||||
hook$memalign:
|
hook$memalign:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$memalign,globl,hidden
|
.endobj hook$memalign,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 800,_init_memalign
|
.init.start 202,_init_memalign
|
||||||
|
.hidden dlmemalign
|
||||||
ezlea dlmemalign,ax
|
ezlea dlmemalign,ax
|
||||||
stosq
|
stosq
|
||||||
yoink free
|
yoink free
|
||||||
.init.end 800,_init_memalign
|
.init.end 202,_init_memalign
|
||||||
|
|
||||||
.hidden dlmemalign
|
|
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"
|
#include "libc/macros.h"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
.initbss 800,_init_realloc
|
.initbss 202,_init_realloc
|
||||||
hook$realloc:
|
hook$realloc:
|
||||||
.quad 0
|
.quad 0
|
||||||
.endobj hook$realloc,globl,hidden
|
.endobj hook$realloc,globl,hidden
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.init.start 800,_init_realloc
|
.init.start 202,_init_realloc
|
||||||
.hidden dlrealloc
|
.hidden dlrealloc
|
||||||
ezlea dlrealloc,ax
|
ezlea dlrealloc,ax
|
||||||
stosq
|
stosq
|
||||||
yoink free
|
yoink free
|
||||||
.init.end 800,_init_realloc
|
.init.end 202,_init_realloc
|
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()
|
/ @see dlmalloc()
|
||||||
malloc: jmp *hook$malloc(%rip)
|
malloc: jmp *hook$malloc(%rip)
|
||||||
.endfn malloc,globl
|
.endfn malloc,globl
|
||||||
|
|
||||||
|
|
|
@ -40,14 +40,3 @@
|
||||||
malloc_usable_size:
|
malloc_usable_size:
|
||||||
jmp *hook$malloc_usable_size(%rip)
|
jmp *hook$malloc_usable_size(%rip)
|
||||||
.endfn malloc_usable_size,globl
|
.endfn malloc_usable_size,globl
|
||||||
|
|
||||||
.initbss 800,_init_malloc_usable_size
|
|
||||||
hook$malloc_usable_size:
|
|
||||||
.quad 0
|
|
||||||
.endobj hook$malloc_usable_size,globl,hidden
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.init.start 800,_init_malloc_usable_size
|
|
||||||
ezlea dlmalloc_usable_size,ax
|
|
||||||
stosq
|
|
||||||
.init.end 800,_init_malloc_usable_size
|
|
||||||
|
|
|
@ -6,11 +6,15 @@ PKGS += LIBC_MEM
|
||||||
LIBC_MEM_ARTIFACTS += LIBC_MEM_A
|
LIBC_MEM_ARTIFACTS += LIBC_MEM_A
|
||||||
LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
|
LIBC_MEM = $(LIBC_MEM_A_DEPS) $(LIBC_MEM_A)
|
||||||
LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
|
LIBC_MEM_A = o/$(MODE)/libc/mem/mem.a
|
||||||
LIBC_MEM_A_FILES := $(wildcard libc/mem/*)
|
|
||||||
LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
|
LIBC_MEM_A_HDRS = $(filter %.h,$(LIBC_MEM_A_FILES))
|
||||||
LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
|
LIBC_MEM_A_SRCS_S = $(filter %.S,$(LIBC_MEM_A_FILES))
|
||||||
LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
|
LIBC_MEM_A_SRCS_C = $(filter %.c,$(LIBC_MEM_A_FILES))
|
||||||
|
|
||||||
|
LIBC_MEM_A_FILES := \
|
||||||
|
$(wildcard libc/mem/*) \
|
||||||
|
$(wildcard libc/mem/cxx/*) \
|
||||||
|
$(wildcard libc/mem/hook/*)
|
||||||
|
|
||||||
LIBC_MEM_A_SRCS = \
|
LIBC_MEM_A_SRCS = \
|
||||||
$(LIBC_MEM_A_SRCS_S) \
|
$(LIBC_MEM_A_SRCS_S) \
|
||||||
$(LIBC_MEM_A_SRCS_C)
|
$(LIBC_MEM_A_SRCS_C)
|
||||||
|
|
|
@ -35,17 +35,3 @@
|
||||||
posix_memalign:
|
posix_memalign:
|
||||||
jmp *hook$posix_memalign(%rip)
|
jmp *hook$posix_memalign(%rip)
|
||||||
.endfn posix_memalign,globl
|
.endfn posix_memalign,globl
|
||||||
|
|
||||||
.initbss 800,_init_posix_memalign
|
|
||||||
hook$posix_memalign:
|
|
||||||
.quad 0
|
|
||||||
.endobj hook$posix_memalign,globl,hidden
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.init.start 800,_init_posix_memalign
|
|
||||||
.hidden dlposix_memalign
|
|
||||||
ezlea dlposix_memalign,ax
|
|
||||||
stosq
|
|
||||||
.init.end 800,_init_posix_memalign
|
|
||||||
|
|
||||||
yoink free
|
|
||||||
|
|
|
@ -22,24 +22,10 @@
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Equivalent to valloc(minimum-page-that-holds(n)), that is,
|
/ Equivalent to valloc(minimum-page-that-holds(n)), that is,
|
||||||
/ round up n to nearest PAGESIZE.
|
/ round up n to nearest pagesize.
|
||||||
/
|
/
|
||||||
/ @param rdi is number of bytes needed
|
/ @param rdi is number of bytes needed
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
/ @return rax is memory address, or NULL w/ errno
|
||||||
/ @see dlpvalloc()
|
/ @see dlpvalloc()
|
||||||
pvalloc:jmp *hook$pvalloc(%rip)
|
pvalloc:jmp *hook$pvalloc(%rip)
|
||||||
.endfn pvalloc,globl
|
.endfn pvalloc,globl
|
||||||
|
|
||||||
.initbss 800,_init_pvalloc
|
|
||||||
hook$pvalloc:
|
|
||||||
.quad 0
|
|
||||||
.endobj hook$pvalloc,globl,hidden
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.init.start 800,_init_pvalloc
|
|
||||||
.hidden dlpvalloc
|
|
||||||
ezlea dlpvalloc,ax
|
|
||||||
stosq
|
|
||||||
.init.end 800,_init_pvalloc
|
|
||||||
|
|
||||||
yoink free
|
|
||||||
|
|
|
@ -55,5 +55,6 @@
|
||||||
/ @note realloc(p=0, n=0) → malloc(32)
|
/ @note realloc(p=0, n=0) → malloc(32)
|
||||||
/ @note realloc(p≠0, n=0) → free(p)
|
/ @note realloc(p≠0, n=0) → free(p)
|
||||||
/ @see dlrealloc()
|
/ @see dlrealloc()
|
||||||
realloc:jmp *hook$realloc(%rip)
|
realloc:
|
||||||
|
jmp *hook$realloc(%rip)
|
||||||
.endfn realloc,globl
|
.endfn realloc,globl
|
||||||
|
|
|
@ -23,12 +23,12 @@
|
||||||
|
|
||||||
/ Resizes the space allocated for p to size n, only if this can be
|
/ Resizes the space allocated for p to size n, only if this can be
|
||||||
/ done without moving p (i.e., only if there is adjacent space
|
/ done without moving p (i.e., only if there is adjacent space
|
||||||
/ available if n is greater than p's current allocated size, or n is
|
/ available if n is greater than p's current allocated size, or n
|
||||||
/ less than or equal to p's size). This may be used instead of plain
|
/ is less than or equal to p's size). This may be used instead of
|
||||||
/ realloc if an alternative allocation strategy is needed upon failure
|
/ plain realloc if an alternative allocation strategy is needed
|
||||||
/ to expand space, for example, reallocation of a buffer that must be
|
/ upon failure to expand space, for example, reallocation of a
|
||||||
/ memory-aligned or cleared. You can use realloc_in_place to trigger
|
/ buffer that must be memory-aligned or cleared. You can use
|
||||||
/ these alternatives only when needed.
|
/ realloc_in_place to trigger these alternatives only when needed.
|
||||||
/
|
/
|
||||||
/ @param rdi (p) is address of current allocation
|
/ @param rdi (p) is address of current allocation
|
||||||
/ @param rsi (newsize) is number of bytes needed
|
/ @param rsi (newsize) is number of bytes needed
|
||||||
|
@ -37,17 +37,3 @@
|
||||||
realloc_in_place:
|
realloc_in_place:
|
||||||
jmp *hook$realloc_in_place(%rip)
|
jmp *hook$realloc_in_place(%rip)
|
||||||
.endfn realloc_in_place,globl
|
.endfn realloc_in_place,globl
|
||||||
|
|
||||||
.initbss 800,_init_realloc_in_place
|
|
||||||
hook$realloc_in_place:
|
|
||||||
.quad 0
|
|
||||||
.endobj hook$realloc_in_place,globl,hidden
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.init.start 800,_init_realloc_in_place
|
|
||||||
.hidden dlrealloc_in_place
|
|
||||||
ezlea dlrealloc_in_place,ax
|
|
||||||
stosq
|
|
||||||
.init.end 800,_init_realloc_in_place
|
|
||||||
|
|
||||||
yoink free
|
|
||||||
|
|
|
@ -21,24 +21,10 @@
|
||||||
#include "libc/notice.inc"
|
#include "libc/notice.inc"
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
||||||
/ Equivalent to memalign(PAGESIZE, n).
|
/ Equivalent to memalign(4096, n).
|
||||||
/
|
/
|
||||||
/ @param rdi is number of bytes needed
|
/ @param rdi is number of bytes needed
|
||||||
/ @return rax is memory address, or NULL w/ errno
|
/ @return rax is memory address, or NULL w/ errno
|
||||||
/ @see dlvalloc()
|
/ @see dlvalloc()
|
||||||
valloc: jmp *hook$valloc(%rip)
|
valloc: jmp *hook$valloc(%rip)
|
||||||
.endfn valloc,globl
|
.endfn valloc,globl
|
||||||
|
|
||||||
.initbss 800,_init_valloc
|
|
||||||
hook$valloc:
|
|
||||||
.quad 0
|
|
||||||
.endobj hook$valloc,globl,hidden
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.init.start 800,_init_valloc
|
|
||||||
.hidden dlvalloc
|
|
||||||
ezlea dlvalloc,ax
|
|
||||||
stosq
|
|
||||||
.init.end 800,_init_valloc
|
|
||||||
|
|
||||||
yoink free
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,9 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
#ifndef COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
||||||
#define COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
#define COSMOPOLITAN_LIBC_NEXGEN32E_GC_H_
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
struct StackFrame;
|
|
||||||
|
|
||||||
struct Garbages {
|
struct Garbages {
|
||||||
size_t i, n;
|
size_t i, n;
|
||||||
struct Garbage {
|
struct Garbage {
|
||||||
|
|
|
@ -25,9 +25,8 @@
|
||||||
world's most popular function──one all programmers love.
|
world's most popular function──one all programmers love.
|
||||||
|
|
||||||
This implementation is the fastest and nearly the tiniest too.
|
This implementation is the fastest and nearly the tiniest too.
|
||||||
It doesn't clobber general registers. It won't break down on old
|
It doesn't break when copying backwards or on misaligned data.
|
||||||
computers or misaligned data. It's so easy that even a child
|
It's so easy that even a child could use it, and they do.
|
||||||
could use it──and they do.
|
|
||||||
*/
|
*/
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
@ -53,11 +52,10 @@ memcpy: mov %rdi,%rax
|
||||||
/ @param rdi is dest
|
/ @param rdi is dest
|
||||||
/ @param rsi is src
|
/ @param rsi is src
|
||||||
/ @param rdx is number of bytes
|
/ @param rdx is number of bytes
|
||||||
/ @clob flags,xmm3,xmm4
|
/ @clob flags,rcx,xmm3,xmm4
|
||||||
/ @mode long
|
/ @mode long
|
||||||
.align 16
|
.align 16
|
||||||
MemCpy: .leafprologue
|
MemCpy: .leafprologue
|
||||||
push %rcx
|
|
||||||
mov $.Lmemcpytab.ro.size,%ecx
|
mov $.Lmemcpytab.ro.size,%ecx
|
||||||
cmp %rcx,%rdx
|
cmp %rcx,%rdx
|
||||||
cmovb %rdx,%rcx
|
cmovb %rdx,%rcx
|
||||||
|
@ -95,8 +93,7 @@ MemCpy: .leafprologue
|
||||||
mov %rcx,(%rdi)
|
mov %rcx,(%rdi)
|
||||||
mov %rbx,-8(%rdi,%rdx)
|
mov %rbx,-8(%rdi,%rdx)
|
||||||
1: pop %rbx
|
1: pop %rbx
|
||||||
.L0: pop %rcx
|
.L0: .leafepilogue
|
||||||
.leafepilogue
|
|
||||||
.L4: push %rbx
|
.L4: push %rbx
|
||||||
mov (%rsi),%ecx
|
mov (%rsi),%ecx
|
||||||
mov -4(%rsi,%rdx),%ebx
|
mov -4(%rsi,%rdx),%ebx
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
/ @param rsi is src
|
/ @param rsi is src
|
||||||
/ @param rdx is number of bytes
|
/ @param rdx is number of bytes
|
||||||
/ @return original rdi copied to rax
|
/ @return original rdi copied to rax
|
||||||
|
/ @clob flags,rcx
|
||||||
/ @asyncsignalsafe
|
/ @asyncsignalsafe
|
||||||
memmove:
|
memmove:
|
||||||
mov %rdi,%rax
|
mov %rdi,%rax
|
||||||
|
@ -36,7 +37,6 @@ memmove:
|
||||||
MemMove:
|
MemMove:
|
||||||
.leafprologue
|
.leafprologue
|
||||||
.profilable
|
.profilable
|
||||||
push %rcx
|
|
||||||
push %rdi
|
push %rdi
|
||||||
push %rsi
|
push %rsi
|
||||||
mov %rdx,%rcx
|
mov %rdx,%rcx
|
||||||
|
@ -49,7 +49,6 @@ MemMove:
|
||||||
cld
|
cld
|
||||||
pop %rsi
|
pop %rsi
|
||||||
pop %rdi
|
pop %rdi
|
||||||
pop %rcx
|
|
||||||
.leafepilogue
|
.leafepilogue
|
||||||
.endfn memmove,globl
|
.endfn memmove,globl
|
||||||
.source __FILE__
|
.source __FILE__
|
||||||
|
|
|
@ -43,12 +43,11 @@ memset: mov %rdi,%rax
|
||||||
/ @param rdi is dest
|
/ @param rdi is dest
|
||||||
/ @param esi is the byte to set
|
/ @param esi is the byte to set
|
||||||
/ @param edx is the number of bytes to set
|
/ @param edx is the number of bytes to set
|
||||||
/ @clob flags,xmm3
|
/ @clob flags,rcx,xmm3
|
||||||
/ @mode long
|
/ @mode long
|
||||||
MemSet: .leafprologue
|
MemSet: .leafprologue
|
||||||
.profilable
|
.profilable
|
||||||
push %rbx
|
push %rbx
|
||||||
push %rcx
|
|
||||||
movd %esi,%xmm3
|
movd %esi,%xmm3
|
||||||
mov $.Lmemsettab.ro.size,%ecx
|
mov $.Lmemsettab.ro.size,%ecx
|
||||||
cmp %rcx,%rdx
|
cmp %rcx,%rdx
|
||||||
|
@ -77,8 +76,7 @@ MemSet: .leafprologue
|
||||||
ja 1b
|
ja 1b
|
||||||
movdqu %xmm3,-16(%rdi,%rdx)
|
movdqu %xmm3,-16(%rdi,%rdx)
|
||||||
pxor %xmm3,%xmm3
|
pxor %xmm3,%xmm3
|
||||||
.L0: pop %rcx
|
.L0: pop %rbx
|
||||||
pop %rbx
|
|
||||||
.leafepilogue
|
.leafepilogue
|
||||||
.L8: movzbq %sil,%rbx
|
.L8: movzbq %sil,%rbx
|
||||||
mov $0x0101010101010101,%rcx
|
mov $0x0101010101010101,%rcx
|
||||||
|
|
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
|
je 2f
|
||||||
push %rax
|
push %rax
|
||||||
push %rcx
|
push %rcx
|
||||||
|
mov %r12,%rdi
|
||||||
|
mov %r13,%rsi
|
||||||
|
mov %r14,%rdx
|
||||||
|
mov %r15,%rcx
|
||||||
call *(%rax)
|
call *(%rax)
|
||||||
pop %rcx
|
pop %rcx
|
||||||
pop %rax
|
pop %rax
|
||||||
|
|
|
@ -17,59 +17,39 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "dsp/mpeg/ycbcrio.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/nt/memory.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/runtime/directmap.h"
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
#include "libc/str/str.h"
|
|
||||||
#include "libc/sysv/consts/ex.h"
|
|
||||||
#include "libc/sysv/consts/exit.h"
|
|
||||||
#include "third_party/getopt/getopt.h"
|
|
||||||
|
|
||||||
#define USAGE \
|
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
|
||||||
" [FLAGS] [PATH...]\n\
|
unsigned prot, unsigned flags,
|
||||||
\n\
|
int fd, int64_t off) {
|
||||||
Flags:\n\
|
struct DirectMap res;
|
||||||
-h shows this information\n\
|
if ((res.maphandle = CreateFileMappingNuma(
|
||||||
\n"
|
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
||||||
|
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
|
||||||
static char *inpath_;
|
kNtNumaNoPreferredNode))) {
|
||||||
|
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
|
||||||
static void PrintUsage(int rc, FILE *f) {
|
off >> 32, off, size, addr,
|
||||||
fputs("Usage: ", f);
|
kNtNumaNoPreferredNode))) {
|
||||||
fputs(program_invocation_name, f);
|
CloseHandle(res.maphandle);
|
||||||
fputs(USAGE, f);
|
res.maphandle = kNtInvalidHandleValue;
|
||||||
exit(rc);
|
res.addr = (void *)(intptr_t)winerr();
|
||||||
}
|
|
||||||
|
|
||||||
static void GetOpts(int *argc, char *argv[]) {
|
|
||||||
int opt;
|
|
||||||
while ((opt = getopt(*argc, argv, "?h")) != -1) {
|
|
||||||
switch (opt) {
|
|
||||||
case '?':
|
|
||||||
case 'h':
|
|
||||||
PrintUsage(EXIT_SUCCESS, stdout);
|
|
||||||
default:
|
|
||||||
PrintUsage(EX_USAGE, stderr);
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
res.maphandle = kNtInvalidHandleValue;
|
||||||
|
res.addr = (void *)(intptr_t)winerr();
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ProcessFile(struct Ycbcrio *m) {
|
struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
|
||||||
/* m->frame-> */
|
unsigned flags, int fd, int64_t off) {
|
||||||
}
|
if (!IsWindows()) {
|
||||||
|
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
|
||||||
int main(int argc, char *argv[]) {
|
kNtInvalidHandleValue};
|
||||||
size_t i;
|
} else {
|
||||||
struct Ycbcrio *m;
|
return DirectMapNt(addr, size, prot, flags, fd, off);
|
||||||
GetOpts(&argc, argv);
|
|
||||||
for (i = optind; i < argc; ++i) {
|
|
||||||
inpath_ = argv[i];
|
|
||||||
m = YcbcrioOpen(inpath_, NULL);
|
|
||||||
ProcessFile(m);
|
|
||||||
YcbcrioClose(&m);
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
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 │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/bits/pushpop.h"
|
|
||||||
#include "libc/bits/safemacros.h"
|
#include "libc/bits/safemacros.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
|
@ -51,8 +50,14 @@ int mapfileread(const char *filename, struct MappedFile *mf) {
|
||||||
int unmapfile(struct MappedFile *mf) {
|
int unmapfile(struct MappedFile *mf) {
|
||||||
int rc;
|
int rc;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
rc |= munmap_s(&mf->addr, mf->size);
|
if (mf->addr != MAP_FAILED) {
|
||||||
rc |= close_s(&mf->fd);
|
rc |= munmap(mf->addr, mf->size);
|
||||||
pushmov(&mf->size, 0);
|
mf->addr = MAP_FAILED;
|
||||||
|
}
|
||||||
|
if (mf->fd != -1) {
|
||||||
|
rc |= close(mf->fd);
|
||||||
|
mf->fd = -1;
|
||||||
|
}
|
||||||
|
mf->size = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "libc/calls/struct/sigset.h"
|
#include "libc/calls/struct/sigset.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#include "libc/nt/files.h"
|
#include "libc/nt/files.h"
|
||||||
#include "libc/nt/runtime.h"
|
#include "libc/nt/runtime.h"
|
||||||
#include "libc/nt/thunk/msabi.h"
|
#include "libc/nt/thunk/msabi.h"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||||
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
#define COSMOPOLITAN_LIBC_RUNTIME_GC_H_
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/nexgen32e/stackframe.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
@ -13,8 +14,6 @@ COSMOPOLITAN_C_START_
|
||||||
* using very few lines of code.
|
* using very few lines of code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct StackFrame;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases resource when function returns.
|
* Releases resource when function returns.
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,10 +19,8 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/bits/safemacros.h"
|
|
||||||
#include "libc/bits/weaken.h"
|
#include "libc/bits/weaken.h"
|
||||||
#include "libc/conv/conv.h"
|
#include "libc/conv/conv.h"
|
||||||
#include "libc/conv/sizemultiply.h"
|
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
@ -70,8 +68,9 @@ bool grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
|
||||||
p1 = isheap(*p) ? *p : NULL;
|
p1 = isheap(*p) ? *p : NULL;
|
||||||
p2 = NULL;
|
p2 = NULL;
|
||||||
n1 = *capacity;
|
n1 = *capacity;
|
||||||
n2 = (*p ? n1 + (n1 >> 1) : max(4, INITIAL_CAPACITY / itemsize)) + extra;
|
n2 = (*p ? n1 + (n1 >> 1) : MAX(4, INITIAL_CAPACITY / itemsize)) + extra;
|
||||||
if (sizemultiply(&t1, n1, itemsize) && sizemultiply(&t2, n2, itemsize)) {
|
if (!__builtin_mul_overflow(n1, itemsize, &t1) &&
|
||||||
|
!__builtin_mul_overflow(n2, itemsize, &t2)) {
|
||||||
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
|
if (weaken(realloc) && (p2 = weaken(realloc)(p1, ROUNDUP(t2, 32)))) {
|
||||||
if (!p1 && *p) memcpy(p2, *p, t1);
|
if (!p1 && *p) memcpy(p2, *p, t1);
|
||||||
memset((char *)p2 + t1, 0, t2 - t1);
|
memset((char *)p2 + t1, 0, t2 - t1);
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
|
hidden extern bool _mmap_asan_mode;
|
||||||
hidden extern char **g_freebsdhint;
|
hidden extern char **g_freebsdhint;
|
||||||
hidden extern unsigned g_runstate;
|
hidden extern unsigned g_runstate;
|
||||||
hidden extern void *g_stacktop;
|
hidden extern void *g_stacktop;
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||||
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
#define COSMOPOLITAN_LIBC_RUNTIME_MEMTRACK_H_
|
||||||
#include "libc/nexgen32e/vendor.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
#define kMappingsSize 0x0000100000000000 /* 16TB */
|
#define kAutomapStart 0x0000100000000000
|
||||||
#define kMappingsStart (IsGenuineCosmo() ? 0x300000000000 : 0x200000000000)
|
#define kAutomapSize 0x0000100000000000
|
||||||
#define kFixedMappingsStart 0x0000100000000000
|
#define kFixedmapStart 0x0000200000000000
|
||||||
#define kFixedMappingsSize kMappingsSize
|
|
||||||
|
|
||||||
struct MemoryIntervals {
|
struct MemoryIntervals {
|
||||||
int i;
|
int i;
|
||||||
|
@ -27,6 +25,7 @@ int TrackMemoryInterval(struct MemoryIntervals *, int, int, long);
|
||||||
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
|
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
|
||||||
void (*)(struct MemoryIntervals *, int, int));
|
void (*)(struct MemoryIntervals *, int, int));
|
||||||
void ReleaseMemoryNt(struct MemoryIntervals *, int, int);
|
void ReleaseMemoryNt(struct MemoryIntervals *, int, int);
|
||||||
|
int UntrackMemoryIntervals(void *, size_t);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -18,13 +18,14 @@
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/assert.h"
|
#include "libc/assert.h"
|
||||||
|
#include "libc/bits/weaken.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/internal.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/log/asan.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/nt/memory.h"
|
|
||||||
#include "libc/nt/runtime.h"
|
|
||||||
#include "libc/rand/rand.h"
|
#include "libc/rand/rand.h"
|
||||||
|
#include "libc/runtime/directmap.h"
|
||||||
#include "libc/runtime/memtrack.h"
|
#include "libc/runtime/memtrack.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -32,79 +33,14 @@
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
#define IP(X) (intptr_t)(X)
|
#define IP(X) (intptr_t)(X)
|
||||||
#define VIP(X) (void *)IP(X)
|
#define VIP(X) (void *)IP(X)
|
||||||
#define COORD(a) (int)(IP(a) >> 16)
|
#define ADDR(c) (void *)(IP(c) << 16)
|
||||||
#define ADDR(c) (void *)(IP(c) << 16)
|
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||||
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
|
||||||
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
|
|
||||||
#define LAST_COORD(a, n) (COORD(a) + (ROUNDUP(n, FRAMESIZE) >> 16) - 1)
|
|
||||||
|
|
||||||
struct DirectMap {
|
|
||||||
void *addr;
|
|
||||||
int64_t maphandle;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MemoryIntervals _mmi;
|
struct MemoryIntervals _mmi;
|
||||||
|
|
||||||
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
|
|
||||||
unsigned prot, unsigned flags,
|
|
||||||
int fd, int64_t off) {
|
|
||||||
struct DirectMap res; /* NT IS TORTURE */
|
|
||||||
if ((res.maphandle = CreateFileMappingNuma(
|
|
||||||
fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue,
|
|
||||||
&kNtIsInheritable, prot2nt(prot, flags), size >> 32, size, NULL,
|
|
||||||
kNtNumaNoPreferredNode))) {
|
|
||||||
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, fprot2nt(prot, flags),
|
|
||||||
off >> 32, off, size, addr,
|
|
||||||
kNtNumaNoPreferredNode))) {
|
|
||||||
CloseHandle(res.maphandle);
|
|
||||||
res.maphandle = kNtInvalidHandleValue;
|
|
||||||
res.addr = VIP(winerr());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
res.maphandle = kNtInvalidHandleValue;
|
|
||||||
res.addr = VIP(winerr());
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
|
|
||||||
unsigned flags, int fd, int64_t off) {
|
|
||||||
if (!IsWindows()) {
|
|
||||||
return (struct DirectMap){mmap$sysv(addr, size, prot, flags, fd, off),
|
|
||||||
kNtInvalidHandleValue};
|
|
||||||
} else {
|
|
||||||
return DirectMapNt(addr, size, prot, flags, fd, off);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int UntrackMemoryIntervals(void *addr, size_t size) {
|
|
||||||
return ReleaseMemoryIntervals(&_mmi, COORD(addr), LAST_COORD(addr, size),
|
|
||||||
ReleaseMemoryNt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases memory pages.
|
|
||||||
*
|
|
||||||
* @param addr is a pointer within any memory mapped region the process
|
|
||||||
* has permission to control, such as address ranges returned by
|
|
||||||
* mmap(), the program image itself, etc.
|
|
||||||
* @param size is the amount of memory to unmap, which needn't be a
|
|
||||||
* multiple of FRAMESIZE, and may be a subset of that which was
|
|
||||||
* mapped previously, and may punch holes in existing mappings,
|
|
||||||
* but your mileage may vary on windows
|
|
||||||
* @return 0 on success, or -1 w/ errno
|
|
||||||
*/
|
|
||||||
int munmap(void *addr, size_t size) {
|
|
||||||
int rc;
|
|
||||||
if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
|
|
||||||
size = ROUNDUP(size, FRAMESIZE);
|
|
||||||
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
|
|
||||||
if (IsWindows()) return 0;
|
|
||||||
return munmap$sysv(addr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Beseeches system for page-table entries.
|
* Beseeches system for page-table entries.
|
||||||
*
|
*
|
||||||
|
@ -120,8 +56,7 @@ int munmap(void *addr, size_t size) {
|
||||||
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
|
* @return virtual base address of new mapping, or MAP_FAILED w/ errno
|
||||||
*/
|
*/
|
||||||
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||||
int i;
|
int i, x, n, a, b;
|
||||||
long gap;
|
|
||||||
struct DirectMap dm;
|
struct DirectMap dm;
|
||||||
if (!size) return VIP(einval());
|
if (!size) return VIP(einval());
|
||||||
if (!ALIGNED(off)) return VIP(einval());
|
if (!ALIGNED(off)) return VIP(einval());
|
||||||
|
@ -134,24 +69,18 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||||
if (UntrackMemoryIntervals(addr, size) == -1) {
|
if (UntrackMemoryIntervals(addr, size) == -1) {
|
||||||
return MAP_FAILED;
|
return MAP_FAILED;
|
||||||
}
|
}
|
||||||
} else if (_mmi.i) {
|
|
||||||
if (0 && IsModeDbg()) {
|
|
||||||
addr = VIP(rand64() & 0x00007ffffffff000);
|
|
||||||
} else {
|
|
||||||
for (i = _mmi.i - 1; i > 0; --i) {
|
|
||||||
gap = _mmi.p[i].x - _mmi.p[i - 1].y - 1;
|
|
||||||
assert(gap > 0);
|
|
||||||
if (gap >= (ROUNDUP(size, FRAMESIZE) >> 16)) {
|
|
||||||
addr = ADDR(_mmi.p[i - 1].y + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!addr) {
|
|
||||||
addr = ADDR(_mmi.p[_mmi.i - 1].y + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
addr = VIP(kMappingsStart);
|
x = kAutomapStart >> 16;
|
||||||
|
n = ROUNDUP(size, FRAMESIZE) >> 16;
|
||||||
|
for (i = 0; i < _mmi.i; ++i) {
|
||||||
|
if (_mmi.p[i].y < x) continue;
|
||||||
|
if (_mmi.p[i].x > x + n - 1) break;
|
||||||
|
x = _mmi.p[i].y + 1;
|
||||||
|
}
|
||||||
|
if (x + n - 1 >= ((kAutomapStart + kAutomapSize) >> 16)) {
|
||||||
|
return (void *)(intptr_t)enomem();
|
||||||
|
}
|
||||||
|
addr = (void *)(intptr_t)((int64_t)x << 16);
|
||||||
}
|
}
|
||||||
assert((flags & MAP_FIXED) ||
|
assert((flags & MAP_FIXED) ||
|
||||||
(!isheap(addr) && !isheap((char *)addr + size - 1)));
|
(!isheap(addr) && !isheap((char *)addr + size - 1)));
|
||||||
|
@ -159,9 +88,13 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
|
||||||
if (dm.addr == MAP_FAILED || dm.addr != addr) {
|
if (dm.addr == MAP_FAILED || dm.addr != addr) {
|
||||||
return MAP_FAILED;
|
return MAP_FAILED;
|
||||||
}
|
}
|
||||||
if (TrackMemoryInterval(&_mmi, COORD(dm.addr), LAST_COORD(dm.addr, size),
|
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||||
dm.maphandle) == -1) {
|
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||||
_Exit(1);
|
if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle) == -1) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (weaken(__asan_map_shadow)) {
|
||||||
|
weaken(__asan_map_shadow)(dm.addr, size);
|
||||||
}
|
}
|
||||||
return dm.addr;
|
return dm.addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,34 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/calls/internal.h"
|
||||||
#include "libc/bits/pushpop.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/macros.h"
|
||||||
|
#include "libc/runtime/memtrack.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
#define IP(X) (intptr_t)(X)
|
||||||
|
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
|
||||||
|
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes memory mapping.
|
* Releases memory pages.
|
||||||
*
|
|
||||||
* The caller's address holder is set to MAP_FAILED (-1) which is a
|
|
||||||
* no-op for subsequent invocations.
|
|
||||||
*
|
*
|
||||||
|
* @param addr is a pointer within any memory mapped region the process
|
||||||
|
* has permission to control, such as address ranges returned by
|
||||||
|
* mmap(), the program image itself, etc.
|
||||||
|
* @param size is the amount of memory to unmap, which needn't be a
|
||||||
|
* multiple of FRAMESIZE, and may be a subset of that which was
|
||||||
|
* mapped previously, and may punch holes in existing mappings,
|
||||||
|
* but your mileage may vary on windows
|
||||||
* @return 0 on success, or -1 w/ errno
|
* @return 0 on success, or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
int munmap_s(void *addrp, uint64_t size) {
|
int munmap(void *addr, size_t size) {
|
||||||
void **addrpp = (void **)addrp;
|
int rc;
|
||||||
void *addr = (void *)pushpop(-1L);
|
if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval();
|
||||||
return munmap(lockxchg(addrpp, &addr), size);
|
size = ROUNDUP(size, FRAMESIZE);
|
||||||
|
if (UntrackMemoryIntervals(addr, size) == -1) return -1;
|
||||||
|
if (IsWindows()) return 0;
|
||||||
|
return munmap$sysv(addr, size);
|
||||||
}
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.h"
|
||||||
#include "libc/runtime/ring.h"
|
#include "libc/runtime/ring.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/map.h"
|
#include "libc/sysv/consts/map.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/runtime/ring.h"
|
#include "libc/runtime/ring.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees ring buffer.
|
* Frees ring buffer.
|
||||||
|
|
|
@ -6,13 +6,6 @@ COSMOPOLITAN_C_START_
|
||||||
│ cosmopolitan § runtime ─╬─│┼
|
│ cosmopolitan § runtime ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
|
|
||||||
struct SymbolTable;
|
|
||||||
|
|
||||||
struct StackFrame {
|
|
||||||
struct StackFrame *next;
|
|
||||||
intptr_t addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef long jmp_buf[8] aligned(CACHELINE);
|
typedef long jmp_buf[8] aligned(CACHELINE);
|
||||||
|
|
||||||
extern int g_argc; /* CRT */
|
extern int g_argc; /* CRT */
|
||||||
|
@ -71,8 +64,12 @@ void loadxmm(void *);
|
||||||
void peekall(void);
|
void peekall(void);
|
||||||
int issetugid(void);
|
int issetugid(void);
|
||||||
void weakfree(void *) libcesque;
|
void weakfree(void *) libcesque;
|
||||||
void __hook(void (*)(void), struct SymbolTable *);
|
|
||||||
bool isheap(void *);
|
bool isheap(void *);
|
||||||
|
void *mmap(void *, uint64_t, int32_t, int32_t, int32_t, int64_t);
|
||||||
|
void *mremap(void *, uint64_t, uint64_t, int32_t, void *);
|
||||||
|
int munmap(void *, uint64_t);
|
||||||
|
int mprotect(void *, uint64_t, int) privileged;
|
||||||
|
int msync(void *, size_t, int);
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § runtime » optimizations ─╬─│┼
|
│ cosmopolitan § runtime » optimizations ─╬─│┼
|
||||||
|
|
|
@ -60,13 +60,8 @@ $(LIBC_RUNTIME_A).pkg: \
|
||||||
$(LIBC_RUNTIME_A_OBJS) \
|
$(LIBC_RUNTIME_A_OBJS) \
|
||||||
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
|
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
o/$(MODE)/libc/runtime/asan.greg.o \
|
$(LIBC_RUNTIME_A_OBJS): \
|
||||||
o/$(MODE)/libc/runtime/shadowargs.o \
|
OVERRIDE_CFLAGS += \
|
||||||
o/$(MODE)/libc/runtime/hook.greg.o \
|
|
||||||
o/$(MODE)/libc/runtime/ftrace.greg.o \
|
|
||||||
o/$(MODE)/libc/runtime/__stack_chk_fail.o \
|
|
||||||
o/$(MODE)/libc/runtime/__stack_chk_guard.o: \
|
|
||||||
OVERRIDE_COPTS += \
|
|
||||||
$(NO_MAGIC)
|
$(NO_MAGIC)
|
||||||
|
|
||||||
# @see ape/ape.s for tuning parameters that make this safe
|
# @see ape/ape.s for tuning parameters that make this safe
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct SymbolTable *opensymboltable(const char *) nodiscard;
|
||||||
int closesymboltable(struct SymbolTable **);
|
int closesymboltable(struct SymbolTable **);
|
||||||
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
|
const struct Symbol *bisectsymbol(struct SymbolTable *, intptr_t, int64_t *);
|
||||||
const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
|
const char *getsymbolname(struct SymbolTable *, const struct Symbol *);
|
||||||
|
void __hook(void (*)(void), struct SymbolTable *);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -17,8 +17,12 @@
|
||||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||||
│ 02110-1301 USA │
|
│ 02110-1301 USA │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/tinymath/tinymath.h"
|
#include "libc/macros.h"
|
||||||
|
#include "libc/runtime/memtrack.h"
|
||||||
|
|
||||||
double(powi)(double a, int b) {
|
int UntrackMemoryIntervals(void *addr, size_t size) {
|
||||||
return tinymath_powl(a, b);
|
int a, b;
|
||||||
|
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
|
||||||
|
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
|
||||||
|
return ReleaseMemoryIntervals(&_mmi, a, b, ReleaseMemoryNt);
|
||||||
}
|
}
|
|
@ -53,9 +53,9 @@ $(LIBC_STDIO_A).pkg: \
|
||||||
$(LIBC_STDIO_A_OBJS) \
|
$(LIBC_STDIO_A_OBJS) \
|
||||||
$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg)
|
$(foreach x,$(LIBC_STDIO_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
#o/$(MODE)/libc/stdio/fputc.o: \
|
o/$(MODE)/libc/stdio/fputc.o: \
|
||||||
OVERRIDE_CFLAGS += \
|
OVERRIDE_CFLAGS += \
|
||||||
$(NO_MAGIC)
|
-O3
|
||||||
|
|
||||||
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
|
LIBC_STDIO_LIBS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)))
|
||||||
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
|
LIBC_STDIO_SRCS = $(foreach x,$(LIBC_STDIO_ARTIFACTS),$($(x)_SRCS))
|
||||||
|
|
|
@ -440,6 +440,12 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||||
|
|
||||||
#define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE))
|
#define memmove(DEST, SRC, SIZE) __memcpy("MemMove", (DEST), (SRC), (SIZE))
|
||||||
|
|
||||||
|
#define mempcpy(DEST, SRC, SIZE) \
|
||||||
|
({ \
|
||||||
|
size_t SIze = (SIZE); \
|
||||||
|
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
||||||
|
})
|
||||||
|
|
||||||
#define __memcpy(FN, DEST, SRC, SIZE) \
|
#define __memcpy(FN, DEST, SRC, SIZE) \
|
||||||
({ \
|
({ \
|
||||||
void *DeSt = (DEST); \
|
void *DeSt = (DEST); \
|
||||||
|
@ -448,16 +454,10 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||||
asm("call\t" FN \
|
asm("call\t" FN \
|
||||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||||
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
|
: "D"(DeSt), "S"(SrC), "d"(SiZe), "m"(*(const char(*)[SiZe])(SrC)) \
|
||||||
: __STR_XMM_CLOBBER "cc"); \
|
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||||
DeSt; \
|
DeSt; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define mempcpy(DEST, SRC, SIZE) \
|
|
||||||
({ \
|
|
||||||
size_t SIze = (SIZE); \
|
|
||||||
(void *)((char *)memcpy((DEST), (SRC), SIze) + SIze); \
|
|
||||||
})
|
|
||||||
|
|
||||||
#define __memset(DEST, BYTE, SIZE) \
|
#define __memset(DEST, BYTE, SIZE) \
|
||||||
({ \
|
({ \
|
||||||
void *DeSt = (DEST); \
|
void *DeSt = (DEST); \
|
||||||
|
@ -465,7 +465,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||||
asm("call\tMemSet" \
|
asm("call\tMemSet" \
|
||||||
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
: "=m"(*(char(*)[SiZe])(DeSt)) \
|
||||||
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
: "D"(DeSt), "S"(BYTE), "d"(SiZe) \
|
||||||
: __STR_XMM_CLOBBER "cc"); \
|
: __STR_XMM_CLOBBER "rcx", "cc"); \
|
||||||
DeSt; \
|
DeSt; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -506,7 +506,7 @@ char *_strncpy(char *, const char *, size_t) asm("strncpy") memcpyesque;
|
||||||
size_t Rcx; \
|
size_t Rcx; \
|
||||||
asm("rep stosb" \
|
asm("rep stosb" \
|
||||||
: "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
: "=D"(Rdi), "=c"(Rcx), "=m"(*(char(*)[SiZe])(Dest)) \
|
||||||
: "0"(Dest), "1"(SiZe), "S"(BYTE) \
|
: "0"(Dest), "1"(SiZe), "a"(BYTE) \
|
||||||
: "cc"); \
|
: "cc"); \
|
||||||
Dest; \
|
Dest; \
|
||||||
})
|
})
|
||||||
|
|
|
@ -42,6 +42,10 @@ $(LIBC_STR_A).pkg: \
|
||||||
$(LIBC_STR_A_OBJS) \
|
$(LIBC_STR_A_OBJS) \
|
||||||
$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg)
|
$(foreach x,$(LIBC_STR_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||||
|
|
||||||
|
o/$(MODE)/libc/str/lz4cpy.o: \
|
||||||
|
OVERRIDE_CFLAGS += \
|
||||||
|
$(NO_MAGIC)
|
||||||
|
|
||||||
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
|
LIBC_STR_LIBS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)))
|
||||||
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
|
LIBC_STR_SRCS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_SRCS))
|
||||||
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
|
LIBC_STR_HDRS = $(foreach x,$(LIBC_STR_ARTIFACTS),$($(x)_HDRS))
|
||||||
|
|
279
libc/stubs/asan.S
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