Get address sanitizer mostly working

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

370
libc/log/asan.c 100644
View File

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

21
libc/log/asan.h 100644
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,33 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_malloc_usable_size
hook$malloc_usable_size:
.quad 0
.endobj hook$malloc_usable_size,globl,hidden
.previous
.init.start 202,_init_malloc_usable_size
.hidden dlmalloc_usable_size
ezlea dlmalloc_usable_size,ax
stosq
.init.end 202,_init_malloc_usable_size

View File

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

View File

@ -0,0 +1,34 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_posix_memalign
hook$posix_memalign:
.quad 0
.endobj hook$posix_memalign,globl,hidden
.previous
.init.start 202,_init_posix_memalign
.hidden dlposix_memalign
ezlea dlposix_memalign,ax
stosq
yoink free
.init.end 202,_init_posix_memalign

View File

@ -0,0 +1,34 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_pvalloc
hook$pvalloc:
.quad 0
.endobj hook$pvalloc,globl,hidden
.previous
.init.start 202,_init_pvalloc
.hidden dlpvalloc
ezlea dlpvalloc,ax
stosq
yoink free
.init.end 202,_init_pvalloc

View File

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

View File

@ -0,0 +1,34 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_realloc_in_place
hook$realloc_in_place:
.quad 0
.endobj hook$realloc_in_place,globl,hidden
.previous
.init.start 202,_init_realloc_in_place
.hidden dlrealloc_in_place
ezlea dlrealloc_in_place,ax
stosq
yoink free
.init.end 202,_init_realloc_in_place

View File

@ -0,0 +1,34 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
.initbss 202,_init_valloc
hook$valloc:
.quad 0
.endobj hook$valloc,globl,hidden
.previous
.init.start 202,_init_valloc
.hidden dlvalloc
ezlea dlvalloc,ax
stosq
yoink free
.init.end 202,_init_valloc

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

279
libc/stubs/asan.S 100644
View File

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

View File

@ -1,54 +0,0 @@
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/macros.h"
.source __FILE__
__asan_addr_is_in_fake_stack:
__asan_alloca_poison:
__asan_allocas_unpoison:
__asan_get_current_fake_stack:
__asan_handle_no_return:
__asan_init:
__asan_loadN:
__asan_register_globals:
__asan_report_load_n:
__asan_report_store_n:
__asan_stack_free:
__asan_stack_malloc:
__asan_storeN:
__asan_unregister_globals:
__asan_version_mismatch_check_v8:
xor %eax,%eax
ret
.endfn __asan_addr_is_in_fake_stack,globl,weak
.endfn __asan_alloca_poison,globl,weak
.endfn __asan_allocas_unpoison,globl,weak
.endfn __asan_get_current_fake_stack,globl,weak
.endfn __asan_handle_no_return,globl,weak
.endfn __asan_init,globl,weak
.endfn __asan_loadN,globl,weak
.endfn __asan_register_globals,globl,weak
.endfn __asan_report_load_n,globl,weak
.endfn __asan_report_store_n,globl,weak
.endfn __asan_stack_free,globl,weak
.endfn __asan_stack_malloc,globl,weak
.endfn __asan_storeN,globl,weak
.endfn __asan_unregister_globals,globl,weak
.endfn __asan_version_mismatch_check_v8,globl,weak

View File

@ -1,24 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/tinymath/tinymath.h"
float powif(float a, int b) {
return tinymath_powl(a, b);
}

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