Get fork() working on Windows

This is done without using Microsoft's internal APIs. MAP_PRIVATE
mappings are copied to the subprocess via a pipe, since Microsoft
doesn't want us to have proper COW pages. MAP_SHARED mappings are
remapped without needing to do any copying. Global variables need
copying along with the stack and the whole heap of anonymous mem.
This actually improves the reliability of the redbean http server
although one shouldn't expect 10k+ connections on a home computer
that isn't running software built to serve like Linux or FreeBSD.
main
Justine Tunney 2020-11-13 01:27:49 -08:00
parent aea89fe832
commit db33973e0a
105 changed files with 1476 additions and 912 deletions

View File

@ -225,9 +225,14 @@ pc: cld
3: call pcread
dec %di
jnz 3b
6: mov %ax,XLM(LOADSTATE)+0
mov %cx,XLM(LOADSTATE)+2
mov %dx,XLM(LOADSTATE)+4
6: mov $XLM(LOADSTATE),%di # ax,cx,dx,es
stosw
xchg %cx,%ax
stosw
xchg %dx,%ax
stosw
mov %es,%ax
stosw
ljmp $0,$REAL(realmodeloader)
.endfn pc,globl,hidden

View File

@ -126,7 +126,7 @@
#define XLM_BADIDT 0x2230
#define XLM_BADIDT_SIZE 6
#define XLM_LOADSTATE 0x2240
#define XLM_LOADSTATE_SIZE 6
#define XLM_LOADSTATE_SIZE 8
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)

View File

@ -280,5 +280,5 @@ if "$@"; then
exit 0
fi
printf "$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
printf "\n$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
exit 1

View File

@ -58,11 +58,11 @@ o/$(MODE)/dsp/core/det3.o: \
OVERRIDE_CFLAGS += \
-ffast-math
ifeq (,$(MODE))
$(DSP_CORE_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(DSP_CORE_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)))
DSP_CORE_SRCS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_SRCS))

View File

@ -59,11 +59,11 @@ o/$(MODE)/dsp/tty/ttyraster.o: \
OVERRIDE_CFLAGS += \
$(MATHEMATICAL)
ifeq (,$(MODE))
$(DSP_TTY_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(DSP_TTY_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)))
DSP_TTY_SRCS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_SRCS))

View File

@ -7,18 +7,20 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/nt/process.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/calls/calls.h"
#include "libc/time/time.h"
noinline void dostuff(void) {
int i, us;
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
for (unsigned i = 0; i < 5; ++i) {
int us = rand() % 500000;
for (i = 0; i < 5; ++i) {
us = rand() % 500000;
usleep(us);
printf("%s%u%s%u [%s=%d]\n", "hello no. ", i, " from ", getpid(), "us", us);
fflush(stdout);
@ -26,9 +28,8 @@ noinline void dostuff(void) {
}
int main(int argc, char *argv[]) {
fprintf(stderr, "%p\n", RtlCloneUserProcess);
int child;
if ((child = fork()) == -1) perror("fork"), exit(1);
int rc, child, wstatus;
CHECK_NE(-1, (child = fork()));
if (!child) {
/* child process */
dostuff();
@ -37,8 +38,7 @@ int main(int argc, char *argv[]) {
/* parent process */
dostuff();
/* note: abandoned children become zombies */
int rc, wstatus;
if ((rc = wait(&wstatus)) == -1) perror("wait"), exit(1);
CHECK_NE(-1, (rc = wait(&wstatus)));
return WEXITSTATUS(wstatus);
}
}

View File

@ -1,51 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/ │
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/x/x.h"
int main(int argc, char *argv[]) {
int pid;
long *addr;
int64_t fh;
if (argc == 1) {
fh = CreateFileMappingNuma(-1, &kNtIsInheritable, kNtPageReadwrite, 0,
FRAMESIZE, NULL, kNtNumaNoPreferredNode);
addr = MapViewOfFileExNuma(fh, kNtFileMapRead | kNtFileMapWrite, 0, 0,
FRAMESIZE, NULL, kNtNumaNoPreferredNode);
*addr = 0x31337;
CHECK_NE(-1, (pid = spawnve(
0, (int[3]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO},
"o/examples/forky.com",
(char *const[]){"o/examples/forky.com",
gc(xasprintf("%#lx", (intptr_t)addr)),
gc(xasprintf("%#lx", fh)), NULL},
environ)));
CHECK_NE(-1, waitpid(pid, NULL, 0));
} else {
addr = (long *)(intptr_t)strtoul(argv[1], NULL, 0);
fh = strtoul(argv[2], NULL, 0);
addr = MapViewOfFileExNuma(fh, kNtFileMapRead | kNtFileMapWrite, 0, 0,
FRAMESIZE, addr, kNtNumaNoPreferredNode);
printf("%#lx\n", *addr);
}
return 0;
}

View File

@ -7,8 +7,6 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/errno.h"
#include "libc/log/log.h"
#include "libc/stdio/stdio.h"
int main() {

View File

@ -24,6 +24,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/ntdll.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
@ -32,7 +33,7 @@
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
const char *ext) {
len = stpcpy(&pathname[len], ext) - &pathname[0];
if (access(pathname, X_OK) != -1) {
if (isexecutable(pathname)) {
return len;
} else {
return -1;
@ -48,7 +49,7 @@ static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
pathlen = strlen(path);
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
p = mempcpy(pathname, path, pathlen);
if (pathlen) *p++ = '/';
if (pathlen && pathname[pathlen - 1] != '/') *p++ = '/';
p = mempcpy(p, name, namelen);
len = p - &pathname[0];
hasdot = !!memchr(basename(name), '.', namelen);

View File

@ -44,7 +44,7 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
(flags & O_CLOEXEC), kNtDuplicateSameAccess)) {
flags & O_CLOEXEC, kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].flags = flags;
return newfd;

View File

@ -134,7 +134,7 @@ DIR *opendir(const char *name) {
DIR *res;
if (!IsWindows() && !IsXnu()) {
res = NULL;
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) {
if (!(res = fdopendir(fd))) close(fd);
}
return res;

View File

@ -0,0 +1,158 @@
/*-*- 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/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/itoa.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/ipc.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
static textwindows int64_t ParseInt(char16_t **p) {
uint64_t x = 0;
while ('0' <= **p && **p <= '9') {
x *= 10;
x += *(*p)++ - '0';
}
return x;
}
static textwindows void WriteAll(int64_t h, void *buf, size_t n) {
char *p;
size_t i;
uint32_t wrote;
for (p = buf, i = 0; i < n; i += wrote) {
WriteFile(h, p + i, n - i, &wrote, NULL);
}
}
static textwindows void ReadAll(int64_t h, void *buf, size_t n) {
char *p;
size_t i;
uint32_t got;
for (p = buf, i = 0; i < n; i += got) {
ReadFile(h, p + i, n - i, &got, NULL);
}
}
textwindows void WinMainForked(void) {
int64_t h;
void *addr;
jmp_buf jb;
char16_t *p;
uint64_t size;
char16_t var[21 + 1 + 21 + 1];
uint32_t i, varlen, protect, access;
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
if (!varlen || varlen >= ARRAYLEN(var)) return;
p = var;
h = ParseInt(&p);
if (*p++ == ' ') CloseHandle(ParseInt(&p));
ReadAll(h, jb, sizeof(jb));
ReadAll(h, &_mmi.i, sizeof(_mmi.i));
for (i = 0; i < _mmi.i; ++i) {
ReadAll(h, &_mmi.p[i], sizeof(_mmi.p[i]));
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
switch (_mmi.p[i].prot) {
case PROT_READ | PROT_WRITE | PROT_EXEC:
protect = kNtPageExecuteReadwrite;
access = kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute;
break;
case PROT_READ | PROT_WRITE:
protect = kNtPageReadwrite;
access = kNtFileMapRead | kNtFileMapWrite;
break;
case PROT_READ:
protect = kNtPageReadonly;
access = kNtFileMapRead;
break;
default:
protect = kNtPageNoaccess;
access = 0;
break;
}
if (_mmi.p[i].flags & MAP_PRIVATE) {
MapViewOfFileExNuma(
(_mmi.p[i].h = CreateFileMappingNuma(-1, NULL, protect, 0, size, NULL,
kNtNumaNoPreferredNode)),
access, 0, 0, size, addr, kNtNumaNoPreferredNode);
ReadAll(h, addr, size);
} else {
MapViewOfFileExNuma(_mmi.p[i].h, access, 0, 0, size, addr,
kNtNumaNoPreferredNode);
}
}
ReadAll(h, _edata, _end - _edata);
CloseHandle(h);
longjmp(jb, 1);
}
textwindows int fork$nt(void) {
jmp_buf jb;
int64_t reader, writer;
int i, rc, pid, fds[3];
char *p, buf[21 + 1 + 21 + 1];
if (!setjmp(jb)) {
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
p = buf;
p += uint64toarray_radix10(reader, p);
*p++ = ' ';
p += uint64toarray_radix10(writer, p);
setenv("_FORK", buf, true);
fds[0] = 0;
fds[1] = 1;
fds[2] = 2;
/* TODO: CloseHandle(g_fds.p[pid].h) if SIGCHLD is SIG_IGN */
if ((pid = spawnve(0, fds, g_argv[0], g_argv, environ)) != -1) {
CloseHandle(reader);
WriteAll(writer, jb, sizeof(jb));
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
for (i = 0; i < _mmi.i; ++i) {
WriteAll(writer, &_mmi.p[i], sizeof(_mmi.p[i]));
if (_mmi.p[i].flags & MAP_PRIVATE) {
WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE);
}
}
WriteAll(writer, _edata, _end - _edata);
CloseHandle(writer);
rc = pid;
} else {
rc = -1;
}
unsetenv("_FORK");
} else {
rc = winerr();
}
} else {
rc = 0;
}
return rc;
}

View File

@ -20,6 +20,7 @@
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Creates new process zygote style.
@ -29,7 +30,13 @@
*/
int fork(void) {
int rc;
rc = fork$sysv();
if (rc == 0) __onfork();
if (!IsWindows()) {
rc = fork$sysv();
} else {
rc = fork$nt();
}
if (rc == 0) {
__onfork();
}
return rc;
}

View File

@ -25,8 +25,10 @@
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"

View File

@ -21,6 +21,7 @@
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/mem/mem.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
/**

View File

@ -67,7 +67,7 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
}
if (handle != -1 &&
ntspawn(program, argv, envp, NULL, NULL,
ntspawn(program, argv, envp, &kNtIsInheritable, NULL,
(flags & SPAWN_TABULARASA) ? false : true,
(flags & SPAWN_DETACH)
? (kNtCreateNewProcessGroup | kNtDetachedProcess |
@ -83,7 +83,7 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
if (handle != -1) {
stdiofds[i] = tubes[i];
g_fds.p[tubes[i]].kind = kFdFile;
g_fds.p[tubes[i]].flags = O_CLOEXEC;
g_fds.p[tubes[i]].flags = 0;
CloseHandle(sti.stdiofds[i]);
} else {
CloseHandle(tubes[i]);

View File

@ -27,7 +27,9 @@
/
/ @return pid of child process or 0 if forked process
/ @returnstwice
vfork: mov __NR_vfork(%rip),%eax
vfork: testb IsWindows()
jnz fork$nt
mov __NR_vfork(%rip),%eax
cmp $-1,%eax
je systemfive.enosys
pop %rsi

View File

@ -56,11 +56,11 @@ struct Fds {
extern const struct Fd kEmptyFd;
extern int g_sighandrvas[NSIG] hidden;
extern struct Fds g_fds hidden;
extern struct NtSystemInfo g_ntsysteminfo hidden;
extern struct NtStartupInfo g_ntstartupinfo hidden;
extern const struct NtSecurityAttributes kNtIsInheritable hidden;
hidden extern int g_sighandrvas[NSIG];
hidden extern struct Fds g_fds;
hidden extern struct NtSystemInfo g_ntsysteminfo;
hidden extern struct NtStartupInfo g_ntstartupinfo;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
ssize_t createfd(void) hidden;
int growfds(void) hidden;
@ -218,6 +218,7 @@ void xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *,
int gettimeofday$nt(struct timeval *, struct timezone *) hidden;
bool32 isatty$nt(int) hidden;
char *getcwd$nt(char *, size_t) hidden;
int fork$nt(void) hidden;
int chdir$nt(const char *) hidden;
int close$nt(int) hidden;
int dup$nt(int, int, int) hidden;
@ -258,6 +259,7 @@ int nanosleep$nt(const struct timespec *, struct timespec *) hidden;
cosmopolitan § syscalls » windows nt » support
*/
void WinMainForked(void) hidden;
int getsetpriority$nt(int, unsigned, int, int (*)(int));
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;

View File

@ -18,9 +18,6 @@
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
/**
* Waits for status to change on any child process.
@ -31,9 +28,5 @@
* @asyncsignalsafe
*/
int wait(int *opt_out_wstatus) {
if (!IsWindows()) {
return wait4$sysv(-1, opt_out_wstatus, 0, NULL);
} else {
return enosys(); /* TODO(jart) */
}
return wait4(-1, opt_out_wstatus, 0, NULL);
}

View File

@ -21,11 +21,14 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/nt/accounting.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/w.h"
@ -33,34 +36,51 @@
textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
struct rusage *opt_out_rusage) {
int pids[64];
int64_t handles[64];
uint32_t dwExitCode;
uint32_t i, count, timeout;
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
if (!isfdkind(pid, kFdProcess)) return esrch();
for (;;) {
dwExitCode = kNtStillActive;
if (!(options & WNOHANG)) {
WaitForSingleObject(g_fds.p[pid].handle, 0xffffffff);
if (pid != -1) {
if (!isfdkind(pid, kFdProcess)) {
return echild();
}
if (GetExitCodeProcess(g_fds.p[pid].handle, &dwExitCode)) {
if (dwExitCode != kNtStillActive) {
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
}
if (opt_out_rusage) {
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
GetProcessTimes(GetCurrentProcess(), &createfiletime, &exitfiletime,
&kernelfiletime, &userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
return pid;
} else if (options & WNOHANG) {
return pid;
} else {
continue;
handles[0] = g_fds.p[pid].handle;
pids[0] = pid;
count = 1;
} else {
for (count = 0, i = g_fds.n; i--;) {
if (g_fds.p[i].kind == kFdProcess) {
pids[count] = i;
handles[count] = g_fds.p[i].handle;
if (++count == ARRAYLEN(handles)) break;
}
} else {
return winerr();
}
if (!count) {
return echild();
}
}
for (;;) {
dwExitCode = kNtStillActive;
if (options & WNOHANG) {
i = WaitForMultipleObjects(count, handles, false, 0);
if (i == kNtWaitTimeout) return 0;
} else {
i = WaitForMultipleObjects(count, handles, false, -1);
}
if (i == kNtWaitFailed) return winerr();
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return winerr();
if (dwExitCode == kNtStillActive) continue;
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
}
if (opt_out_rusage) {
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
GetProcessTimes(GetCurrentProcess(), &createfiletime, &exitfiletime,
&kernelfiletime, &userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
return pids[i];
}
}

View File

@ -17,8 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nt/struct/securityattributes.h"
#include "libc/calls/internal.h"
#include "libc/nt/struct/securityattributes.h"
const struct NtSecurityAttributes kNtIsInheritable = {
sizeof(struct NtSecurityAttributes), NULL, true};
sizeof(struct NtSecurityAttributes),
NULL,
true,
};

View File

@ -69,9 +69,9 @@
#define PINT_PTR intptr_t*
#define UINT_PTR uintptr_t
#define PUINT_PTR uintptr_t*
#define LONG_PTR int32_t*
#define LONG_PTR intptr_t
#define PLONG_PTR int32_t**
#define ULONG_PTR uint32_t*
#define ULONG_PTR uintptr_t
#define PULONG_PTR uint32_t**
#define POINTER_64_INT int64_t*
#define __int3264 int64_t

View File

@ -15,7 +15,6 @@ o/$(MODE)/libc: o/$(MODE)/libc/alg \
o/$(MODE)/libc/crt \
o/$(MODE)/libc/dns \
o/$(MODE)/libc/elf \
o/$(MODE)/libc/escape \
o/$(MODE)/libc/fmt \
o/$(MODE)/libc/intrin \
o/$(MODE)/libc/linux \

View File

@ -401,7 +401,8 @@ void __asan_map_shadow(void *p, size_t n) {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (sm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, a, a, sm.maphandle) == -1) {
TrackMemoryInterval(&_mmi, a, a, sm.maphandle, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED) == -1) {
abort();
}
}

View File

@ -64,9 +64,9 @@ $(LIBC_LOG_A_OBJS): \
$(NO_MAGIC) \
-fwrapv
ifeq (,$(MODE))
LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o
endif
# ifeq (,$(MODE))
# LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o
# endif
LIBC_LOG_ASAN_A = o/$(MODE)/libc/log/log.a
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))

View File

@ -24,53 +24,49 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static size_t g_environcap;
#define MAX_VARS 512
int PutEnvImpl(char *string, bool overwrite) {
if (!environ) {
g_environcap = 0;
if ((environ = calloc(8, sizeof(char *)))) {
g_environcap = 8;
}
}
char *equalp = strchr(string, '=');
if (!equalp) return einval();
unsigned namelen = equalp + 1 - string;
unsigned i;
int PutEnvImpl(char *s, bool overwrite) {
char *p;
unsigned i, namelen;
p = strchr(s, '=');
if (!p) goto fail;
namelen = p + 1 - s;
for (i = 0; environ[i]; ++i) {
if (strncmp(environ[i], string, namelen) == 0) {
if (strncmp(environ[i], s, namelen) == 0) {
if (!overwrite) {
free_s(&string);
free(s);
return 0;
}
goto replace;
}
}
if (i + 1 >= g_environcap) {
if (!g_environcap) g_environcap = i + 1;
if (!grow(&environ, &g_environcap, sizeof(char *), 0)) {
free_s(&string);
return -1;
}
}
if (i + 1 >= MAX_VARS) goto fail;
environ[i + 1] = NULL;
replace:
free_s(&environ[i]);
environ[i] = string;
free(environ[i]);
environ[i] = s;
return 0;
fail:
free(s);
return einval();
}
/**
* Emplaces environment key=value.
* @see setenv(), getenv()
*/
int putenv(char *string) { return PutEnvImpl(string, true); }
textexit static void putenv_fini(void) {
for (char **envp = environ; *envp; ++envp) free_s(envp);
free_s(&environ);
int putenv(char *string) {
return PutEnvImpl(strdup(string), true);
}
textstartup static void putenv_init(void) { atexit(putenv_fini); }
textstartup static void putenv_init(void) {
char **pin, **pout;
pin = environ;
pout = malloc(sizeof(char *) * MAX_VARS);
environ = pout;
while (*pin) *pout++ = strdup(*pin++);
*pout = NULL;
}
const void *const putenv_ctor[] initarray = {putenv_init};

View File

@ -34,8 +34,8 @@ int64_t LoadLibraryEx(const char16_t *lpLibFileName, int64_t hFile,
uint32_t dwFlags);
uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename,
uint32_t nSize);
intptr_t GetModuleHandle(const char *lpModuleName);
intptr_t GetModuleHandleW(const char16_t *lpModuleName);
intptr_t GetModuleHandle(const char *opt_lpModuleName);
intptr_t GetModuleHandleW(const char16_t *opt_lpModuleName);
void *GetProcAddress(int64_t hModule, const char *lpProcName);
int32_t FreeResource(int64_t hResData);
intptr_t LockResource(int64_t hResData);

View File

@ -0,0 +1,35 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_
#define kNtColorScrollbar 0
#define kNtColorBackground 1
#define kNtColorActivecaption 2
#define kNtColorInactivecaption 3
#define kNtColorMenu 4
#define kNtColorWindow 5
#define kNtColorWindowframe 6
#define kNtColorMenutext 7
#define kNtColorWindowtext 8
#define kNtColorCaptiontext 9
#define kNtColorActiveborder 10
#define kNtColorInactiveborder 11
#define kNtColorAppworkspace 12
#define kNtColorHighlight 13
#define kNtColorHighlighttext 14
#define kNtColorBtnface 15
#define kNtColorBtnshadow 16
#define kNtColorGraytext 17
#define kNtColorBtntext 18
#define kNtColorInactivecaptiontext 19
#define kNtColorBtnhighlight 20
#define kNtColor3ddkshadow 21
#define kNtColor3dlight 22
#define kNtColorInfotext 23
#define kNtColorInfobk 24
#define kNtColorHotlight 26
#define kNtColorGradientactivecaption 27
#define kNtColorGradientinactivecaption 28
#define kNtColorMenuhilight 29
#define kNtColorMenubar 30
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_ */

View File

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_CW_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_CW_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define kNtCwUsedefault ((int)0x80000000)
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_CW_H_ */

24
libc/nt/enum/idc.h 100644
View File

@ -0,0 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define kNtIdcArrow ((const char16_t *)32512)
#define kNtIdcIbeam ((const char16_t *)32513)
#define kNtIdcWait ((const char16_t *)32514)
#define kNtIdcCross ((const char16_t *)32515)
#define kNtIdcUparrow ((const char16_t *)32516)
#define kNtIdcSizenwse ((const char16_t *)32642)
#define kNtIdcSizenesw ((const char16_t *)32643)
#define kNtIdcSizewe ((const char16_t *)32644)
#define kNtIdcSizens ((const char16_t *)32645)
#define kNtIdcSizeall ((const char16_t *)32646)
#define kNtIdcNo ((const char16_t *)32648)
#define kNtIdcHand ((const char16_t *)32649)
#define kNtIdcHelp ((const char16_t *)32651)
#define kNtIdcPin ((const char16_t *)32671)
#define kNtIdcPerson ((const char16_t *)32672)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_ */

10
libc/nt/enum/pwr.h 100644
View File

@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_
#define kNtPwrOk 1
#define kNtPwrFail (-1)
#define kNtPwrSuspendrequest 1
#define kNtPwrSuspendresume 2
#define kNtPwrCriticalresume 3
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_ */

19
libc/nt/enum/sw.h 100644
View File

@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_SW_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_SW_H_
#define kNtSwHide 0
#define kNtSwShownormal 1
#define kNtSwNormal 1
#define kNtSwShowminimized 2
#define kNtSwShowmaximized 3
#define kNtSwMaximize 3
#define kNtSwShownoactivate 4
#define kNtSwShow 5
#define kNtSwMinimize 6
#define kNtSwShowminnoactive 7
#define kNtSwShowna 8
#define kNtSwRestore 9
#define kNtSwShowdefault 10
#define kNtSwForceminimize 11
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_SW_H_ */

View File

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WA_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WA_H_
#define kNtWaInactive 0
#define kNtWaActive 1
#define kNtWaClickactive 2
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WA_H_ */

View File

@ -0,0 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_
#define kNtWaitFailed 0xffffffffu
#define kNtWaitTimeout 0x00000102u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_ */

185
libc/nt/enum/wm.h 100644
View File

@ -0,0 +1,185 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WM_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WM_H_
#define kNtWmNull 0x0000
#define kNtWmCreate 0x0001
#define kNtWmDestroy 0x0002
#define kNtWmMove 0x0003
#define kNtWmSize 0x0005
#define kNtWmActivate 0x0006
#define kNtWmSetfocus 0x0007
#define kNtWmKillfocus 0x0008
#define kNtWmEnable 0x000A
#define kNtWmSetredraw 0x000B
#define kNtWmSettext 0x000C
#define kNtWmGettext 0x000D
#define kNtWmGettextlength 0x000E
#define kNtWmPaint 0x000F
#define kNtWmClose 0x0010
#define kNtWmQueryendsession 0x0011
#define kNtWmQueryopen 0x0013
#define kNtWmEndsession 0x0016
#define kNtWmQuit 0x0012
#define kNtWmErasebkgnd 0x0014
#define kNtWmSyscolorchange 0x0015
#define kNtWmShowwindow 0x0018
#define kNtWmWininichange 0x001A
#define kNtWmSettingchange kNtWmWininichange
#define kNtWmDevmodechange 0x001B
#define kNtWmActivateapp 0x001C
#define kNtWmFontchange 0x001D
#define kNtWmTimechange 0x001E
#define kNtWmCancelmode 0x001F
#define kNtWmSetcursor 0x0020
#define kNtWmMouseactivate 0x0021
#define kNtWmChildactivate 0x0022
#define kNtWmQueuesync 0x0023
#define kNtWmGetminmaxinfo 0x0024
#define kNtWmPainticon 0x0026
#define kNtWmIconerasebkgnd 0x0027
#define kNtWmNextdlgctl 0x0028
#define kNtWmSpoolerstatus 0x002A
#define kNtWmDrawitem 0x002B
#define kNtWmMeasureitem 0x002C
#define kNtWmDeleteitem 0x002D
#define kNtWmVkeytoitem 0x002E
#define kNtWmChartoitem 0x002F
#define kNtWmSetfont 0x0030
#define kNtWmGetfont 0x0031
#define kNtWmSethotkey 0x0032
#define kNtWmGethotkey 0x0033
#define kNtWmQuerydragicon 0x0037
#define kNtWmCompareitem 0x0039
#define kNtWmGetobject 0x003D
#define kNtWmCompacting 0x0041
#define kNtWmWindowposchanging 0x0046
#define kNtWmWindowposchanged 0x0047
#define kNtWmPower 0x0048
#define kNtWmCopydata 0x004A
#define kNtWmCanceljournal 0x004B
#define kNtWmNotify 0x004E
#define kNtWmInputlangchangerequest 0x0050
#define kNtWmInputlangchange 0x0051
#define kNtWmTcard 0x0052
#define kNtWmHelp 0x0053
#define kNtWmUserchanged 0x0054
#define kNtWmNotifyformat 0x0055
#define kNtWmContextmenu 0x007B
#define kNtWmStylechanging 0x007C
#define kNtWmStylechanged 0x007D
#define kNtWmDisplaychange 0x007E
#define kNtWmGeticon 0x007F
#define kNtWmSeticon 0x0080
#define kNtWmNccreate 0x0081
#define kNtWmNcdestroy 0x0082
#define kNtWmNccalcsize 0x0083
#define kNtWmNchittest 0x0084
#define kNtWmNcpaint 0x0085
#define kNtWmNcactivate 0x0086
#define kNtWmGetdlgcode 0x0087
#define kNtWmNcmousemove 0x00A0
#define kNtWmNclbuttondown 0x00A1
#define kNtWmNclbuttonup 0x00A2
#define kNtWmNclbuttondblclk 0x00A3
#define kNtWmNcrbuttondown 0x00A4
#define kNtWmNcrbuttonup 0x00A5
#define kNtWmNcrbuttondblclk 0x00A6
#define kNtWmNcmbuttondown 0x00A7
#define kNtWmNcmbuttonup 0x00A8
#define kNtWmNcmbuttondblclk 0x00A9
#define kNtWmNcxbuttondown 0x00AB
#define kNtWmNcxbuttonup 0x00AC
#define kNtWmNcxbuttondblclk 0x00AD
#define kNtWmKeyfirst 0x0100
#define kNtWmKeydown 0x0100
#define kNtWmKeyup 0x0101
#define kNtWmChar 0x0102
#define kNtWmDeadchar 0x0103
#define kNtWmSyskeydown 0x0104
#define kNtWmSyskeyup 0x0105
#define kNtWmSyschar 0x0106
#define kNtWmSysdeadchar 0x0107
#define kNtWmUnichar 0x0109
#define kNtWmKeylast 0x0109
#define kNtWmInitdialog 0x0110
#define kNtWmCommand 0x0111
#define kNtWmSyscommand 0x0112
#define kNtWmTimer 0x0113
#define kNtWmHscroll 0x0114
#define kNtWmVscroll 0x0115
#define kNtWmInitmenu 0x0116
#define kNtWmInitmenupopup 0x0117
#define kNtWmGesture 0x0119
#define kNtWmGesturenotify 0x011A
#define kNtWmMenuselect 0x011F
#define kNtWmMenuchar 0x0120
#define kNtWmEnteridle 0x0121
#define kNtWmMenurbuttonup 0x0122
#define kNtWmMenudrag 0x0123
#define kNtWmMenugetobject 0x0124
#define kNtWmUninitmenupopup 0x0125
#define kNtWmMenucommand 0x0126
#define kNtWmChangeuistate 0x0127
#define kNtWmUpdateuistate 0x0128
#define kNtWmQueryuistate 0x0129
#define kNtWmMousefirst 0x0200
#define kNtWmMousemove 0x0200
#define kNtWmLbuttondown 0x0201
#define kNtWmLbuttonup 0x0202
#define kNtWmLbuttondblclk 0x0203
#define kNtWmRbuttondown 0x0204
#define kNtWmRbuttonup 0x0205
#define kNtWmRbuttondblclk 0x0206
#define kNtWmMbuttondown 0x0207
#define kNtWmMbuttonup 0x0208
#define kNtWmMbuttondblclk 0x0209
#define kNtWmMousewheel 0x020A
#define kNtWmXbuttondown 0x020B
#define kNtWmXbuttonup 0x020C
#define kNtWmXbuttondblclk 0x020D
#define kNtWmMousehwheel 0x020E
#define kNtWmMouselast 0x020E
#define kNtWmParentnotify 0x0210
#define kNtWmEntermenuloop 0x0211
#define kNtWmExitmenuloop 0x0212
#define kNtWmNextmenu 0x0213
#define kNtWmSizing 0x0214
#define kNtWmCapturechanged 0x0215
#define kNtWmMoving 0x0216
#define kNtWmPowerbroadcast 0x0218
#define kNtWmMdicreate 0x0220
#define kNtWmMdidestroy 0x0221
#define kNtWmMdiactivate 0x0222
#define kNtWmMdirestore 0x0223
#define kNtWmMdinext 0x0224
#define kNtWmMdimaximize 0x0225
#define kNtWmMditile 0x0226
#define kNtWmMdicascade 0x0227
#define kNtWmMdiiconarrange 0x0228
#define kNtWmMdigetactive 0x0229
#define kNtWmMdisetmenu 0x0230
#define kNtWmEntersizemove 0x0231
#define kNtWmExitsizemove 0x0232
#define kNtWmDropfiles 0x0233
#define kNtWmMdirefreshmenu 0x0234
#define kNtWmCut 0x0300
#define kNtWmCopy 0x0301
#define kNtWmPaste 0x0302
#define kNtWmClear 0x0303
#define kNtWmUndo 0x0304
#define kNtWmRenderformat 0x0305
#define kNtWmRenderallformats 0x0306
#define kNtWmDestroyclipboard 0x0307
#define kNtWmDrawclipboard 0x0308
#define kNtWmPaintclipboard 0x0309
#define kNtWmVscrollclipboard 0x030A
#define kNtWmSizeclipboard 0x030B
#define kNtWmAskcbformatname 0x030C
#define kNtWmChangecbchain 0x030D
#define kNtWmHscrollclipboard 0x030E
#define kNtWmQuerynewpalette 0x030F
#define kNtWmPaletteischanging 0x0310
#define kNtWmPalettechanged 0x0311
#define kNtWmHotkey 0x0312
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WM_H_ */

62
libc/nt/enum/ws.h 100644
View File

@ -0,0 +1,62 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WS_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WS_H_
#define kNtWsOverlapped 0x00000000
#define kNtWsPopup 0x80000000
#define kNtWsChild 0x40000000
#define kNtWsMinimize 0x20000000
#define kNtWsVisible 0x10000000
#define kNtWsDisabled 0x08000000
#define kNtWsClipsiblings 0x04000000
#define kNtWsClipchildren 0x02000000
#define kNtWsMaximize 0x01000000
#define kNtWsCaption 0x00C00000
#define kNtWsBorder 0x00800000
#define kNtWsDlgframe 0x00400000
#define kNtWsVscroll 0x00200000
#define kNtWsHscroll 0x00100000
#define kNtWsSysmenu 0x00080000
#define kNtWsThickframe 0x00040000
#define kNtWsGroup 0x00020000
#define kNtWsTabstop 0x00010000
#define kNtWsMinimizebox 0x00020000
#define kNtWsMaximizebox 0x00010000
#define kNtWsTiled kNtWsOverlapped
#define kNtWsIconic kNtWsMinimize
#define kNtWsSizebox kNtWsThickframe
#define kNtWsTiledwindow kNtWsOverlappedwindow
#define kNtWsOverlappedwindow \
(kNtWsOverlapped | kNtWsCaption | kNtWsSysmenu | kNtWsThickframe | \
kNtWsMinimizebox | kNtWsMaximizebox)
#define kNtWsPopupwindow (kNtWsPopup | kNtWsBorder | kNtWsSysmenu)
#define kNtWsExDlgmodalframe 0x00000001
#define kNtWsExNoparentnotify 0x00000004
#define kNtWsExTopmost 0x00000008
#define kNtWsExAcceptfiles 0x00000010
#define kNtWsExTransparent 0x00000020
#define kNtWsExMdichild 0x00000040
#define kNtWsExToolwindow 0x00000080
#define kNtWsExWindowedge 0x00000100
#define kNtWsExClientedge 0x00000200
#define kNtWsExContexthelp 0x00000400
#define kNtWsExRight 0x00001000
#define kNtWsExLeft 0x00000000
#define kNtWsExRtlreading 0x00002000
#define kNtWsExLtrreading 0x00000000
#define kNtWsExLeftscrollbar 0x00004000
#define kNtWsExRightscrollbar 0x00000000
#define kNtWsExControlparent 0x00010000
#define kNtWsExStaticedge 0x00020000
#define kNtWsExAppwindow 0x00040000
#define kNtWsExNoinheritlayout 0x00100000
#define kNtWsExNoredirectionbitmap 0x00200000
#define kNtWsExLayoutrtl 0x00400000
#define kNtWsExComposited 0x02000000
#define kNtWsExNoactivate 0x08000000
#define kNtWsExOverlappedwindow (kNtWsExWindowedge | kNtWsExClientedge)
#define kNtWsExPalettewindow \
(kNtWsExWindowedge | kNtWsExToolwindow | kNtWsExTopmost)
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WS_H_ */

View File

@ -1,5 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NT_EVENTS_H_
#define COSMOPOLITAN_LIBC_NT_EVENTS_H_
#include "libc/nt/struct/msg.h"
#include "libc/nt/struct/point.h"
#if 0
/* ░░░░
@ -27,64 +29,61 @@
*/
#endif
#define NT_EVENT_SYSTEM_SOUND 0x0001
#define NT_EVENT_SYSTEM_ALERT 0x0002
#define NT_EVENT_SYSTEM_FOREGROUND 0x0003
#define NT_EVENT_SYSTEM_MENUSTART 0x0004
#define NT_EVENT_SYSTEM_MENUEND 0x0005
#define NT_EVENT_SYSTEM_MENUPOPUPSTART 0x0006
#define NT_EVENT_SYSTEM_MENUPOPUPEND 0x0007
#define NT_EVENT_SYSTEM_CAPTURESTART 0x0008
#define NT_EVENT_SYSTEM_CAPTUREEND 0x0009
#define NT_EVENT_SYSTEM_MOVESIZESTART 0x000A
#define NT_EVENT_SYSTEM_MOVESIZEEND 0x000B
#define NT_EVENT_SYSTEM_SOUND 0x0001
#define NT_EVENT_SYSTEM_ALERT 0x0002
#define NT_EVENT_SYSTEM_FOREGROUND 0x0003
#define NT_EVENT_SYSTEM_MENUSTART 0x0004
#define NT_EVENT_SYSTEM_MENUEND 0x0005
#define NT_EVENT_SYSTEM_MENUPOPUPSTART 0x0006
#define NT_EVENT_SYSTEM_MENUPOPUPEND 0x0007
#define NT_EVENT_SYSTEM_CAPTURESTART 0x0008
#define NT_EVENT_SYSTEM_CAPTUREEND 0x0009
#define NT_EVENT_SYSTEM_MOVESIZESTART 0x000A
#define NT_EVENT_SYSTEM_MOVESIZEEND 0x000B
#define NT_EVENT_SYSTEM_CONTEXTHELPSTART 0x000C
#define NT_EVENT_SYSTEM_CONTEXTHELPEND 0x000D
#define NT_EVENT_SYSTEM_DRAGDROPSTART 0x000E
#define NT_EVENT_SYSTEM_DRAGDROPEND 0x000F
#define NT_EVENT_SYSTEM_DIALOGSTART 0x0010
#define NT_EVENT_SYSTEM_DIALOGEND 0x0011
#define NT_EVENT_SYSTEM_SCROLLINGSTART 0x0012
#define NT_EVENT_SYSTEM_SCROLLINGEND 0x0013
#define NT_EVENT_SYSTEM_SWITCHSTART 0x0014
#define NT_EVENT_SYSTEM_SWITCHEND 0x0015
#define NT_EVENT_SYSTEM_MINIMIZESTART 0x0016
#define NT_EVENT_SYSTEM_MINIMIZEEND 0x0017
#define NT_EVENT_SYSTEM_CONTEXTHELPEND 0x000D
#define NT_EVENT_SYSTEM_DRAGDROPSTART 0x000E
#define NT_EVENT_SYSTEM_DRAGDROPEND 0x000F
#define NT_EVENT_SYSTEM_DIALOGSTART 0x0010
#define NT_EVENT_SYSTEM_DIALOGEND 0x0011
#define NT_EVENT_SYSTEM_SCROLLINGSTART 0x0012
#define NT_EVENT_SYSTEM_SCROLLINGEND 0x0013
#define NT_EVENT_SYSTEM_SWITCHSTART 0x0014
#define NT_EVENT_SYSTEM_SWITCHEND 0x0015
#define NT_EVENT_SYSTEM_MINIMIZESTART 0x0016
#define NT_EVENT_SYSTEM_MINIMIZEEND 0x0017
#define NT_EVENT_CONSOLE_CARET 0x4001
#define NT_EVENT_CONSOLE_UPDATE_REGION 0x4002
#define NT_EVENT_CONSOLE_UPDATE_SIMPLE 0x4003
#define NT_EVENT_CONSOLE_UPDATE_SCROLL 0x4004
#define NT_EVENT_CONSOLE_LAYOUT 0x4005
#define NT_EVENT_CONSOLE_CARET 0x4001
#define NT_EVENT_CONSOLE_UPDATE_REGION 0x4002
#define NT_EVENT_CONSOLE_UPDATE_SIMPLE 0x4003
#define NT_EVENT_CONSOLE_UPDATE_SCROLL 0x4004
#define NT_EVENT_CONSOLE_LAYOUT 0x4005
#define NT_EVENT_CONSOLE_START_APPLICATION 0x4006
#define NT_EVENT_CONSOLE_END_APPLICATION 0x4007
#define NT_EVENT_CONSOLE_END_APPLICATION 0x4007
#define NT_EVENT_OBJECT_CREATE 0x8000
#define NT_EVENT_OBJECT_DESTROY 0x8001
#define NT_EVENT_OBJECT_SHOW 0x8002
#define NT_EVENT_OBJECT_HIDE 0x8003
#define NT_EVENT_OBJECT_REORDER 0x8004
#define NT_EVENT_OBJECT_FOCUS 0x8005
#define NT_EVENT_OBJECT_SELECTION 0x8006
#define NT_EVENT_OBJECT_SELECTIONADD 0x8007
#define NT_EVENT_OBJECT_SELECTIONREMOVE 0x8008
#define NT_EVENT_OBJECT_SELECTIONWITHIN 0x8009
#define NT_EVENT_OBJECT_STATECHANGE 0x800A
#define NT_EVENT_OBJECT_LOCATIONCHANGE 0x800B
#define NT_EVENT_OBJECT_NAMECHANGE 0x800C
#define NT_EVENT_OBJECT_CREATE 0x8000
#define NT_EVENT_OBJECT_DESTROY 0x8001
#define NT_EVENT_OBJECT_SHOW 0x8002
#define NT_EVENT_OBJECT_HIDE 0x8003
#define NT_EVENT_OBJECT_REORDER 0x8004
#define NT_EVENT_OBJECT_FOCUS 0x8005
#define NT_EVENT_OBJECT_SELECTION 0x8006
#define NT_EVENT_OBJECT_SELECTIONADD 0x8007
#define NT_EVENT_OBJECT_SELECTIONREMOVE 0x8008
#define NT_EVENT_OBJECT_SELECTIONWITHIN 0x8009
#define NT_EVENT_OBJECT_STATECHANGE 0x800A
#define NT_EVENT_OBJECT_LOCATIONCHANGE 0x800B
#define NT_EVENT_OBJECT_NAMECHANGE 0x800C
#define NT_EVENT_OBJECT_DESCRIPTIONCHANGE 0x800D
#define NT_EVENT_OBJECT_VALUECHANGE 0x800E
#define NT_EVENT_OBJECT_PARENTCHANGE 0x800F
#define NT_EVENT_OBJECT_HELPCHANGE 0x8010
#define NT_EVENT_OBJECT_DEFACTIONCHANGE 0x8011
#define NT_EVENT_OBJECT_VALUECHANGE 0x800E
#define NT_EVENT_OBJECT_PARENTCHANGE 0x800F
#define NT_EVENT_OBJECT_HELPCHANGE 0x8010
#define NT_EVENT_OBJECT_DEFACTIONCHANGE 0x8011
#define NT_EVENT_OBJECT_ACCELERATORCHANGE 0x8012
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtMsg;
struct NtPoint;
int32_t GetMessage(struct NtMsg *lpMsg, int64_t hWnd, uint32_t wMsgFilterMin,
uint32_t wMsgFilterMax);
int32_t TranslateMessage(const struct NtMsg *lpMsg);

View File

@ -1635,7 +1635,7 @@ imp 'FillConsoleOutputAttribute' FillConsoleOutputAttribute KernelBase 354
imp 'FillConsoleOutputCharacter' FillConsoleOutputCharacterW KernelBase 356 5
imp 'FillConsoleOutputCharacterA' FillConsoleOutputCharacterA KernelBase 355 5
imp 'FillPath' FillPath gdi32 1479
imp 'FillRect' FillRect user32 1780
imp 'FillRect' FillRect user32 1780 3
imp 'FillRgn' FillRgn gdi32 1480
imp 'FindActCtxSectionGuid' FindActCtxSectionGuid KernelBase 357
imp 'FindActCtxSectionGuidWorker' FindActCtxSectionGuidWorker kernel32 372
@ -3191,17 +3191,17 @@ imp 'LoadAlterBitmap' LoadAlterBitmap comdlg32 117
imp 'LoadAppInitDlls' LoadAppInitDlls KernelBase 971
imp 'LoadBitmapA' LoadBitmapA user32 2096
imp 'LoadBitmap' LoadBitmapW user32 2097
imp 'LoadCursorA' LoadCursorA user32 2098
imp 'LoadCursorA' LoadCursorA user32 2098 2
imp 'LoadCursorFromFileA' LoadCursorFromFileA user32 2099
imp 'LoadCursorFromFile' LoadCursorFromFileW user32 2100
imp 'LoadCursor' LoadCursorW user32 2101
imp 'LoadCursor' LoadCursorW user32 2101 2
imp 'LoadEnclaveData' LoadEnclaveData KernelBase 972
imp 'LoadEnclaveImageA' LoadEnclaveImageA KernelBase 973
imp 'LoadEnclaveImage' LoadEnclaveImageW KernelBase 974
imp 'LoadIcon' LoadIconW user32 2103 2
imp 'LoadIconA' LoadIconA user32 2102 2
imp 'LoadImageA' LoadImageA user32 2104
imp 'LoadImage' LoadImageW user32 2105
imp 'LoadImageA' LoadImageA user32 2104 6
imp 'LoadImage' LoadImageW user32 2105 6
imp 'LoadKeyboardLayoutA' LoadKeyboardLayoutA user32 2106
imp 'LoadKeyboardLayoutEx' LoadKeyboardLayoutEx user32 2107
imp 'LoadKeyboardLayout' LoadKeyboardLayoutW user32 2108
@ -3996,6 +3996,8 @@ imp 'NtWriteFileGather' NtWriteFileGather ntdll 656
imp 'NtWriteRequestData' NtWriteRequestData ntdll 657
imp 'NtWriteVirtualMemory' NtWriteVirtualMemory ntdll 658 5
imp 'NtYieldExecution' NtYieldExecution ntdll 659 0
imp 'DefWindowProcA' DefWindowProcA user32 173 4
imp 'DefWindowProc' DefWindowProcW user32 174 4
imp 'NtdllDefWindowProc_A' NtdllDefWindowProc_A ntdll 660
imp 'NtdllDefWindowProc_W' NtdllDefWindowProc_W ntdll 661
imp 'NtdllDialogWndProc_A' NtdllDialogWndProc_A ntdll 662
@ -4644,10 +4646,10 @@ imp 'RegisterApplicationRecoveryCallback' RegisterApplicationRecoveryCallback
imp 'RegisterApplicationRestart' RegisterApplicationRestart kernel32 1185
imp 'RegisterBSDRWindow' RegisterBSDRWindow user32 2247
imp 'RegisterBadMemoryNotification' RegisterBadMemoryNotification KernelBase 1384
imp 'RegisterClassA' RegisterClassA user32 2248
imp 'RegisterClassExA' RegisterClassExA user32 2249
imp 'RegisterClassEx' RegisterClassExW user32 2250
imp 'RegisterClass' RegisterClassW user32 2251
imp 'RegisterClassA' RegisterClassA user32 2248 1
imp 'RegisterClassExA' RegisterClassExA user32 2249 1
imp 'RegisterClassEx' RegisterClassExW user32 2250 1
imp 'RegisterClass' RegisterClassW user32 2251 1
imp 'RegisterClipboardFormatA' RegisterClipboardFormatA user32 2252
imp 'RegisterClipboardFormat' RegisterClipboardFormatW user32 2253
imp 'RegisterConsoleIME' RegisterConsoleIME kernel32 1187
@ -6482,9 +6484,9 @@ imp 'ShipAssert' ShipAssert ntdll 1612
imp 'ShipAssertGetBufferInfo' ShipAssertGetBufferInfo ntdll 1613
imp 'ShipAssertMsgA' ShipAssertMsgA ntdll 1614
imp 'ShipAssertMsg' ShipAssertMsgW ntdll 1615
imp 'ShowCaret' ShowCaret user32 2411
imp 'ShowCaret' ShowCaret user32 2411 1
imp 'ShowConsoleCursor' ShowConsoleCursor kernel32 1409
imp 'ShowCursor' ShowCursor user32 2412
imp 'ShowCursor' ShowCursor user32 2412 1
imp 'ShowOwnedPopups' ShowOwnedPopups user32 2413
imp 'ShowScrollBar' ShowScrollBar user32 2414
imp 'ShowStartGlass' ShowStartGlass user32 2415

View File

@ -1,5 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_PAINT_H_
#define COSMOPOLITAN_LIBC_NT_PAINT_H_
#include "libc/nt/struct/drawtextparams.h"
#include "libc/nt/struct/paintstruct.h"
#include "libc/nt/struct/rect.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#if 0
@ -8,50 +11,22 @@ COSMOPOLITAN_C_START_
*/
#endif
struct NtSize {
int32_t cx;
int32_t cy;
};
struct NtRectangle {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
struct NtDrawTextParams {
uint32_t cbSize;
int32_t iTabLength;
int32_t iLeftMargin;
int32_t iRightMargin;
uint32_t uiLengthDrawn;
};
struct NtPaintStruct {
int64_t hdc;
int32_t fErase;
struct NtRectangle rcPaint;
int32_t fRestore;
int32_t fIncUpdate;
unsigned char rgbReserved[32];
};
int64_t BeginPaint(int64_t hWnd, struct NtPaintStruct *lpPaint);
int32_t EndPaint(int64_t hWnd, const struct NtPaintStruct *lpPaint);
int32_t BitBlt(int64_t hdc, int x, int y, int cx, int cy, int64_t hdcSrc,
int x1, int y1, uint32_t rop);
int32_t GetClientRect(int64_t hWnd, struct NtRectangle *lpRect);
int32_t GetWindowRect(int64_t hWnd, struct NtRectangle *lpRect);
int32_t GetClientRect(int64_t hWnd, struct NtRect *lpRect);
int32_t GetWindowRect(int64_t hWnd, struct NtRect *lpRect);
int32_t SetBkMode(int64_t hdc, int mode);
uint32_t SetTextColor(int64_t hdc, uint32_t color);
uint32_t SetTextAlign(int64_t hdc, uint32_t align);
int32_t SetTextJustification(int64_t hdc, int extra, int count);
int32_t DrawText(int64_t hdc, const char16_t *lpchText, int cchText,
struct NtRectangle *lprc, uint32_t format);
struct NtRect *lprc, uint32_t format);
int32_t DrawTextEx(int64_t hdc, char16_t *lpchText, int cchText,
struct NtRectangle *lprc, uint32_t format,
struct NtRect *lprc, uint32_t format,
struct NtDrawTextParams *lpdtp);
int32_t FillRect(int64_t hDC, const struct NtRect *lpRC, int64_t hBrush);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_DRAWTEXTPARAMS_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_DRAWTEXTPARAMS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtDrawTextParams {
uint32_t cbSize;
int32_t iTabLength;
int32_t iLeftMargin;
int32_t iRightMargin;
uint32_t uiLengthDrawn;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_DRAWTEXTPARAMS_H_ */

View File

@ -6,8 +6,8 @@
struct NtMsg {
int64_t hwnd;
uint32_t message;
uintptr_t wParam;
intptr_t lParam;
uint64_t wParam;
int64_t lParam;
uint32_t time;
struct NtPoint pt;
};

View File

@ -0,0 +1,18 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_PAINTSTRUCT_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_PAINTSTRUCT_H_
#include "libc/nt/struct/rect.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtPaintStruct {
int64_t hdc;
bool32 fErase;
struct NtRect rcPaint;
bool32 fRestore;
bool32 fIncUpdate;
uint8_t rgbReserved[32];
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_PAINTSTRUCT_H_ */

View File

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_RECT_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_RECT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtRect {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_RECT_H_ */

View File

@ -0,0 +1,13 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_SIZE_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_SIZE_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtSize {
int32_t cx;
int32_t cy;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_SIZE_H_ */

View File

@ -0,0 +1,22 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASS_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASS_H_
#include "libc/nt/typedef/wndproc.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtWndClass {
uint32_t style;
NtWndProc lpfnWndProc;
int32_t cbClsExtra;
int32_t cbWndExtra;
int64_t hInstance;
int64_t hIcon;
int64_t hCursor;
int64_t hbrBackground;
const char16_t *lpszMenuName;
const char16_t *lpszClassName;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASS_H_ */

View File

@ -0,0 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASSEX_H_
#define COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASSEX_H_
#include "libc/nt/typedef/wndproc.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtWndClassEx {
uint32_t cbSize;
uint32_t style;
NtWndProc lpfnWndProc;
int32_t cbClsExtra;
int32_t cbWndExtra;
int64_t hInstance;
int64_t hIcon;
int64_t hCursor;
int64_t hbrBackground;
const char16_t *lpszMenuName;
const char16_t *lpszClassName;
int64_t hIconSm;
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_STRUCT_WNDCLASSEX_H_ */

View File

@ -48,11 +48,11 @@ void GetSystemTimeAsFileTime(struct NtFileTime *); // win8+
void GetSystemTimePreciseAsFileTime(struct NtFileTime *); // win8+
uint32_t WaitForSingleObject(int64_t hHandle, uint32_t dwMilliseconds);
uint32_t WaitForMultipleObjects(uint32_t nCount, const void **lpHandles,
uint32_t WaitForMultipleObjects(uint32_t nCount, const int64_t *lpHandles,
bool32 bWaitAll, uint32_t dwMilliseconds);
uint32_t WaitForSingleObjectEx(int64_t hHandle, uint32_t dwMilliseconds,
bool32 bAlertable);
uint32_t WaitForMultipleObjectsEx(unsigned int nCount, const void **lpHandles,
uint32_t WaitForMultipleObjectsEx(unsigned int nCount, const int64_t *lpHandles,
bool32 bWaitAll, uint32_t dwMilliseconds,
bool32 bAlertable);

View File

@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_NT_TYPEDEF_WNDPROC_H_
#define COSMOPOLITAN_LIBC_NT_TYPEDEF_WNDPROC_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
typedef int64_t (*NtWndProc)(int64_t, uint32_t, uint64_t, int64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_TYPEDEF_WNDPROC_H_ */

View File

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_DefWindowProcA,DefWindowProcA,173
.text.windows
DefWindowProcA:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_DefWindowProcA(%rip),%rax
jmp __sysv2nt
.endfn DefWindowProcA,globl
.previous

View File

@ -0,0 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_DefWindowProcW,DefWindowProcW,174
.text.windows
DefWindowProc:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_DefWindowProcW(%rip),%rax
jmp __sysv2nt
.endfn DefWindowProc,globl
.previous

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_FillRect,FillRect,1780
.text.windows
FillRect:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_FillRect(%rip),%rax
jmp __sysv2nt
.endfn FillRect,globl
.previous

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_LoadCursorA,LoadCursorA,2098
.text.windows
LoadCursorA:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_LoadCursorA(%rip),%rax
jmp __sysv2nt
.endfn LoadCursorA,globl
.previous

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_LoadCursorW,LoadCursorW,2101
.text.windows
LoadCursor:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_LoadCursorW(%rip),%rax
jmp __sysv2nt
.endfn LoadCursor,globl
.previous

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_LoadImageA,LoadImageA,2104
.text.windows
LoadImageA:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_LoadImageA(%rip),%rax
jmp __sysv2nt6
.endfn LoadImageA,globl
.previous

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_LoadImageW,LoadImageW,2105
.text.windows
LoadImage:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_LoadImageW(%rip),%rax
jmp __sysv2nt6
.endfn LoadImage,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_RegisterClassA,RegisterClassA,2248
.text.windows
RegisterClassA:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_RegisterClassA(%rip)
leave
ret
.endfn RegisterClassA,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_RegisterClassExA,RegisterClassExA,2249
.text.windows
RegisterClassExA:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_RegisterClassExA(%rip)
leave
ret
.endfn RegisterClassExA,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_RegisterClassExW,RegisterClassExW,2250
.text.windows
RegisterClassEx:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_RegisterClassExW(%rip)
leave
ret
.endfn RegisterClassEx,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_RegisterClassW,RegisterClassW,2251
.text.windows
RegisterClass:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_RegisterClassW(%rip)
leave
ret
.endfn RegisterClass,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_ShowCaret,ShowCaret,2411
.text.windows
ShowCaret:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_ShowCaret(%rip)
leave
ret
.endfn ShowCaret,globl
.previous

View File

@ -1,2 +1,15 @@
.include "o/libc/nt/codegen.inc"
.imp user32,__imp_ShowCursor,ShowCursor,2412
.text.windows
ShowCursor:
push %rbp
mov %rsp,%rbp
.profilable
mov %rdi,%rcx
sub $32,%rsp
call *__imp_ShowCursor(%rip)
leave
ret
.endfn ShowCursor,globl
.previous

View File

@ -1,5 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NT_WINDOWS_H_
#define COSMOPOLITAN_LIBC_NT_WINDOWS_H_
#include "libc/nt/struct/rect.h"
#include "libc/nt/struct/wndclass.h"
#include "libc/nt/typedef/timerproc.h"
#if 0
/* ░░░░
@ -27,322 +29,25 @@
cosmopolitan § new technology » windows
*/
#endif
#define NT_WM_NULL 0x0000
#define NT_WM_CREATE 0x0001
#define NT_WM_DESTROY 0x0002
#define NT_WM_MOVE 0x0003
#define NT_WM_SIZE 0x0005
#define NT_WM_ACTIVATE 0x0006
#define NT_WA_INACTIVE 0
#define NT_WA_ACTIVE 1
#define NT_WA_CLICKACTIVE 2
#define NT_WM_SETFOCUS 0x0007
#define NT_WM_KILLFOCUS 0x0008
#define NT_WM_ENABLE 0x000A
#define NT_WM_SETREDRAW 0x000B
#define NT_WM_SETTEXT 0x000C
#define NT_WM_GETTEXT 0x000D
#define NT_WM_GETTEXTLENGTH 0x000E
#define NT_WM_PAINT 0x000F
#define NT_WM_CLOSE 0x0010
#define NT_WM_QUIT 0x0012
#define NT_WM_ERASEBKGND 0x0014
#define NT_WM_SYSCOLORCHANGE 0x0015
#define NT_WM_SHOWWINDOW 0x0018
#define NT_WM_WININICHANGE 0x001A
#define NT_WM_SETTINGCHANGE WM_WININICHANGE
#define NT_WM_DEVMODECHANGE 0x001B
#define NT_WM_ACTIVATEAPP 0x001C
#define NT_WM_FONTCHANGE 0x001D
#define NT_WM_TIMECHANGE 0x001E
#define NT_WM_CANCELMODE 0x001F
#define NT_WM_SETCURSOR 0x0020
#define NT_WM_MOUSEACTIVATE 0x0021
#define NT_WM_CHILDACTIVATE 0x0022
#define NT_WM_QUEUESYNC 0x0023
#define NT_WM_GETMINMAXINFO 0x0024
#define NT_WS_OVERLAPPED 0x00000000
#define NT_WS_POPUP 0x80000000
#define NT_WS_CHILD 0x40000000
#define NT_WS_MINIMIZE 0x20000000
#define NT_WS_VISIBLE 0x10000000
#define NT_WS_DISABLED 0x08000000
#define NT_WS_CLIPSIBLINGS 0x04000000
#define NT_WS_CLIPCHILDREN 0x02000000
#define NT_WS_MAXIMIZE 0x01000000
#define NT_WS_CAPTION 0x00C00000
#define NT_WS_BORDER 0x00800000
#define NT_WS_DLGFRAME 0x00400000
#define NT_WS_VSCROLL 0x00200000
#define NT_WS_HSCROLL 0x00100000
#define NT_WS_SYSMENU 0x00080000
#define NT_WS_THICKFRAME 0x00040000
#define NT_WS_GROUP 0x00020000
#define NT_WS_TABSTOP 0x00010000
#define NT_WS_MINIMIZEBOX 0x00020000
#define NT_WS_MAXIMIZEBOX 0x00010000
#define NT_WS_TILED WS_OVERLAPPED
#define NT_WS_ICONIC WS_MINIMIZE
#define NT_WS_SIZEBOX WS_THICKFRAME
#define NT_WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
#define NT_WS_OVERLAPPEDWINDOW \
(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | \
WS_MAXIMIZEBOX)
#define NT_WS_POPUPWINDOW (WS_POPUP | WS_BORDER | WS_SYSMENU)
#define NT_WS_CHILDWINDOW (WS_CHILD)
#define NT_WS_EX_DLGMODALFRAME 0x00000001
#define NT_WS_EX_NOPARENTNOTIFY 0x00000004
#define NT_WS_EX_TOPMOST 0x00000008
#define NT_WS_EX_ACCEPTFILES 0x00000010
#define NT_WS_EX_TRANSPARENT 0x00000020
#define NT_WS_EX_MDICHILD 0x00000040
#define NT_WS_EX_TOOLWINDOW 0x00000080
#define NT_WS_EX_WINDOWEDGE 0x00000100
#define NT_WS_EX_CLIENTEDGE 0x00000200
#define NT_WS_EX_CONTEXTHELP 0x00000400
#define NT_WS_EX_RIGHT 0x00001000
#define NT_WS_EX_LEFT 0x00000000
#define NT_WS_EX_RTLREADING 0x00002000
#define NT_WS_EX_LTRREADING 0x00000000
#define NT_WS_EX_LEFTSCROLLBAR 0x00004000
#define NT_WS_EX_RIGHTSCROLLBAR 0x00000000
#define NT_WS_EX_CONTROLPARENT 0x00010000
#define NT_WS_EX_STATICEDGE 0x00020000
#define NT_WS_EX_APPWINDOW 0x00040000
#define NT_WS_EX_OVERLAPPEDWINDOW (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE)
#define NT_WS_EX_PALETTEWINDOW \
(WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST)
#define NT_WS_EX_LAYERED 0x00080000
#define NT_WS_EX_NOINHERITLAYOUT 0x00100000
#define NT_WS_EX_LAYOUTRTL 0x00400000
#define NT_WS_EX_COMPOSITED 0x02000000
#define NT_WS_EX_NOACTIVATE 0x08000000
#define NT_CS_VREDRAW 0x0001
#define NT_CS_HREDRAW 0x0002
#define NT_CS_DBLCLKS 0x0008
#define NT_CS_OWNDC 0x0020
#define NT_CS_CLASSDC 0x0040
#define NT_CS_PARENTDC 0x0080
#define NT_CS_NOCLOSE 0x0200
#define NT_CS_SAVEBITS 0x0800
#define NT_CS_BYTEALIGNCLIENT 0x1000
#define NT_CS_BYTEALIGNWINDOW 0x2000
#define NT_CS_GLOBALCLASS 0x4000
#define NT_CS_IME 0x00010000
#define NT_CS_DROPSHADOW 0x00020000
#define NT_SWP_NOSIZE 0x0001
#define NT_SWP_NOMOVE 0x0002
#define NT_SWP_NOZORDER 0x0004
#define NT_SWP_NOREDRAW 0x0008
#define NT_SWP_NOACTIVATE 0x0010
#define NT_SWP_FRAMECHANGED 0x0020
#define NT_SWP_SHOWWINDOW 0x0040
#define NT_SWP_HIDEWINDOW 0x0080
#define NT_SWP_NOCOPYBITS 0x0100
#define NT_SWP_NOOWNERZORDER 0x0200
#define NT_SWP_NOSENDCHANGING 0x0400
#define NT_SWP_DRAWFRAME SWP_FRAMECHANGED
#define NT_SWP_NOREPOSITION SWP_NOOWNERZORDER
#define NT_SWP_DEFERERASE 0x2000
#define NT_SWP_ASYNCWINDOWPOS 0x4000
#define NT_RI_MOUSE_LEFT_BUTTON_DOWN 0x0001
#define NT_RI_MOUSE_LEFT_BUTTON_UP 0x0002
#define NT_RI_MOUSE_RIGHT_BUTTON_DOWN 0x0004
#define NT_RI_MOUSE_RIGHT_BUTTON_UP 0x0008
#define NT_RI_MOUSE_MIDDLE_BUTTON_DOWN 0x0010
#define NT_RI_MOUSE_MIDDLE_BUTTON_UP 0x0020
#define NT_RI_MOUSE_BUTTON_1_DOWN RI_MOUSE_LEFT_BUTTON_DOWN
#define NT_RI_MOUSE_BUTTON_1_UP RI_MOUSE_LEFT_BUTTON_UP
#define NT_RI_MOUSE_BUTTON_2_DOWN RI_MOUSE_RIGHT_BUTTON_DOWN
#define NT_RI_MOUSE_BUTTON_2_UP RI_MOUSE_RIGHT_BUTTON_UP
#define NT_RI_MOUSE_BUTTON_3_DOWN RI_MOUSE_MIDDLE_BUTTON_DOWN
#define NT_RI_MOUSE_BUTTON_3_UP RI_MOUSE_MIDDLE_BUTTON_UP
#define NT_RI_MOUSE_BUTTON_4_DOWN 0x0040
#define NT_RI_MOUSE_BUTTON_4_UP 0x0080
#define NT_RI_MOUSE_BUTTON_5_DOWN 0x0100
#define NT_RI_MOUSE_BUTTON_5_UP 0x0200
#define NT_RI_MOUSE_WHEEL 0x0400
#define NT_MOUSE_MOVE_RELATIVE 0
#define NT_MOUSE_MOVE_ABSOLUTE 1
#define NT_MOUSE_VIRTUAL_DESKTOP 0x02
#define NT_MOUSE_ATTRIBUTES_CHANGED 0x04
#define NT_STATE_SYSTEM_UNAVAILABLE 0x00000001
#define NT_STATE_SYSTEM_SELECTED 0x00000002
#define NT_STATE_SYSTEM_FOCUSED 0x00000004
#define NT_STATE_SYSTEM_PRESSED 0x00000008
#define NT_STATE_SYSTEM_CHECKED 0x00000010
#define NT_STATE_SYSTEM_MIXED 0x00000020
#define NT_STATE_SYSTEM_INDETERMINATE STATE_SYSTEM_MIXED
#define NT_STATE_SYSTEM_READONLY 0x00000040
#define NT_STATE_SYSTEM_HOTTRACKED 0x00000080
#define NT_STATE_SYSTEM_DEFAULT 0x00000100
#define NT_STATE_SYSTEM_EXPANDED 0x00000200
#define NT_STATE_SYSTEM_COLLAPSED 0x00000400
#define NT_STATE_SYSTEM_BUSY 0x00000800
#define NT_STATE_SYSTEM_FLOATING 0x00001000
#define NT_STATE_SYSTEM_MARQUEED 0x00002000
#define NT_STATE_SYSTEM_ANIMATED 0x00004000
#define NT_STATE_SYSTEM_INVISIBLE 0x00008000
#define NT_STATE_SYSTEM_OFFSCREEN 0x00010000
#define NT_STATE_SYSTEM_SIZEABLE 0x00020000
#define NT_STATE_SYSTEM_MOVEABLE 0x00040000
#define NT_STATE_SYSTEM_SELFVOICING 0x00080000
#define NT_STATE_SYSTEM_FOCUSABLE 0x00100000
#define NT_STATE_SYSTEM_SELECTABLE 0x00200000
#define NT_STATE_SYSTEM_LINKED 0x00400000
#define NT_STATE_SYSTEM_TRAVERSED 0x00800000
#define NT_STATE_SYSTEM_MULTISELECTABLE 0x01000000
#define NT_STATE_SYSTEM_EXTSELECTABLE 0x02000000
#define NT_STATE_SYSTEM_ALERT_LOW 0x04000000
#define NT_STATE_SYSTEM_ALERT_MEDIUM 0x08000000
#define NT_STATE_SYSTEM_ALERT_HIGH 0x10000000
#define NT_STATE_SYSTEM_PROTECTED 0x20000000
#define NT_STATE_SYSTEM_VALID 0x3FFFFFFF
#define NT_IDH_NO_HELP 28440
#define NT_IDH_MISSING_CONTEXT 28441
#define NT_IDH_GENERIC_HELP_BUTTON 28442
#define NT_IDH_OK 28443
#define NT_IDH_CANCEL 28444
#define NT_IDH_HELP 28445
#define NT_SS_LEFT 0x00000000
#define NT_SS_CENTER 0x00000001
#define NT_SS_RIGHT 0x00000002
#define NT_SS_ICON 0x00000003
#define NT_SS_BLACKRECT 0x00000004
#define NT_SS_GRAYRECT 0x00000005
#define NT_SS_WHITERECT 0x00000006
#define NT_SS_BLACKFRAME 0x00000007
#define NT_SS_GRAYFRAME 0x00000008
#define NT_SS_WHITEFRAME 0x00000009
#define NT_SS_USERITEM 0x0000000A
#define NT_SS_SIMPLE 0x0000000B
#define NT_SS_LEFTNOWORDWRAP 0x0000000C
#define NT_SS_OWNERDRAW 0x0000000D
#define NT_SS_BITMAP 0x0000000E
#define NT_SS_ENHMETAFILE 0x0000000F
#define NT_SS_ETCHEDHORZ 0x00000010
#define NT_SS_ETCHEDVERT 0x00000011
#define NT_SS_ETCHEDFRAME 0x00000012
#define NT_SS_TYPEMASK 0x0000001F
#define NT_SS_REALSIZECONTROL 0x00000040
#define NT_SS_NOPREFIX 0x00000080
#define NT_SS_NOTIFY 0x00000100
#define NT_SS_CENTERIMAGE 0x00000200
#define NT_SS_RIGHTJUST 0x00000400
#define NT_SS_REALSIZEIMAGE 0x00000800
#define NT_SS_SUNKEN 0x00001000
#define NT_SS_EDITCONTROL 0x00002000
#define NT_SS_ENDELLIPSIS 0x00004000
#define NT_SS_PATHELLIPSIS 0x00008000
#define NT_SS_WORDELLIPSIS 0x0000C000
#define NT_SS_ELLIPSISMASK 0x0000C000
#define NT_BST_UNCHECKED 0x0000
#define NT_BST_CHECKED 0x0001
#define NT_BST_INDETERMINATE 0x0002
#define NT_BST_PUSHED 0x0004
#define NT_BST_FOCUS 0x0008
#define NT_BS_PUSHBUTTON 0x00000000
#define NT_BS_DEFPUSHBUTTON 0x00000001
#define NT_BS_CHECKBOX 0x00000002
#define NT_BS_AUTOCHECKBOX 0x00000003
#define NT_BS_RADIOBUTTON 0x00000004
#define NT_BS_3STATE 0x00000005
#define NT_BS_AUTO3STATE 0x00000006
#define NT_BS_GROUPBOX 0x00000007
#define NT_BS_USERBUTTON 0x00000008
#define NT_BS_AUTORADIOBUTTON 0x00000009
#define NT_BS_PUSHBOX 0x0000000A
#define NT_BS_OWNERDRAW 0x0000000B
#define NT_BS_TYPEMASK 0x0000000F
#define NT_BS_LEFTTEXT 0x00000020
#define NT_BS_TEXT 0x00000000
#define NT_BS_ICON 0x00000040
#define NT_BS_BITMAP 0x00000080
#define NT_BS_LEFT 0x00000100
#define NT_BS_RIGHT 0x00000200
#define NT_BS_CENTER 0x00000300
#define NT_BS_TOP 0x00000400
#define NT_BS_BOTTOM 0x00000800
#define NT_BS_VCENTER 0x00000C00
#define NT_BS_PUSHLIKE 0x00001000
#define NT_BS_MULTILINE 0x00002000
#define NT_BS_NOTIFY 0x00004000
#define NT_BS_FLAT 0x00008000
#define NT_BS_RIGHTBUTTON BS_LEFTTEXT
#define NT_BN_CLICKED 0
#define NT_BN_PAINT 1
#define NT_BN_HILITE 2
#define NT_BN_UNHILITE 3
#define NT_BN_DISABLE 4
#define NT_BN_DOUBLECLICKED 5
#define NT_BN_PUSHED BN_HILITE
#define NT_BN_UNPUSHED BN_UNHILITE
#define NT_BN_DBLCLK BN_DOUBLECLICKED
#define NT_BN_SETFOCUS 6
#define NT_BN_KILLFOCUS 7
#define NT_BM_GETCHECK 0x00F0
#define NT_BM_SETCHECK 0x00F1
#define NT_BM_GETSTATE 0x00F2
#define NT_BM_SETSTATE 0x00F3
#define NT_BM_SETSTYLE 0x00F4
#define NT_BM_CLICK 0x00F5
#define NT_BM_GETIMAGE 0x00F6
#define NT_BM_SETIMAGE 0x00F7
#define NT_GUI_CARETBLINKING 0x00000001
#define NT_GUI_INMOVESIZE 0x00000002
#define NT_GUI_INMENUMODE 0x00000004
#define NT_GUI_SYSTEMMENUMODE 0x00000008
#define NT_GUI_POPUPMENUMODE 0x00000010
#define NT_GUI_16BITTASK 0x00000020
#define NT_ALERT_SYSTEM_INFORMATIONAL 1
#define NT_ALERT_SYSTEM_WARNING 2
#define NT_ALERT_SYSTEM_ERROR 3
#define NT_ALERT_SYSTEM_QUERY 4
#define NT_ALERT_SYSTEM_CRITICAL 5
#define NT_SOUND_SYSTEM_STARTUP 1
#define NT_SOUND_SYSTEM_SHUTDOWN 2
#define NT_SOUND_SYSTEM_BEEP 3
#define NT_SOUND_SYSTEM_ERROR 4
#define NT_SOUND_SYSTEM_QUESTION 5
#define NT_SOUND_SYSTEM_WARNING 6
#define NT_SOUND_SYSTEM_INFORMATION 7
#define NT_SOUND_SYSTEM_MAXIMIZE 8
#define NT_SOUND_SYSTEM_MINIMIZE 9
#define NT_SOUND_SYSTEM_RESTOREUP 10
#define NT_SOUND_SYSTEM_RESTOREDOWN 11
#define NT_SOUND_SYSTEM_APPSTART 12
#define NT_SOUND_SYSTEM_FAULT 13
#define NT_SOUND_SYSTEM_APPEND 14
#define NT_SOUND_SYSTEM_MENUCOMMAND 15
#define NT_SOUND_SYSTEM_MENUPOPUP 16
#define NT_CSOUND_SYSTEM 16
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int64_t CreateWindowEx(uint32_t dwExStyle, const char16_t *lpClassName,
const char16_t *lpWindowName, uint32_t dwStyle, int X,
int Y, int nWidth, int nHeight, int64_t hWndParent,
int64_t hMenu, int64_t hInstance, void *lpParam);
int64_t hMenu, int64_t hInstance, int64_t lpParam);
uint16_t RegisterClass(const struct NtWndClass *lpWndClass);
int64_t DefWindowProc(int64_t hWnd, uint32_t Msg, uint64_t wParam,
int64_t lParam);
int32_t CloseWindow(int64_t hWnd);
int32_t DestroyWindow(int64_t hWnd);
int32_t ShowWindow(int64_t hWnd, int nCmdShow);
int32_t ShowWindow(int64_t hWnd, int sw);
int32_t ShowCursor(bool32 bShow);
int64_t LoadCursor(int64_t opt_hInstance, const char16_t *lpCursorNameOrIdc);
int32_t ShowCaret(bool32 bShow);
int32_t AnimateWindow(int64_t hWnd, uint32_t dwTime, uint32_t dwFlags);
int64_t LoadIcon(int64_t hInstance, const char16_t *lpIconName);
int32_t IsWindow(int64_t hWnd);
@ -360,7 +65,7 @@ int32_t SetWindowPos(int64_t hWnd, int64_t hWndInsertAfter, int X, int Y,
uintptr_t SetTimer(int64_t opt_hWnd, uintptr_t nIDEvent, uint32_t uElapseMs,
NtTimerProc lpTimerFunc);
int KillTimer(int64_t hWnd, uintptr_t uIDEvent);
int32_t KillTimer(int64_t hWnd, uintptr_t uIDEvent);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -28,10 +28,13 @@
/ @param edi is exit code ∈ [0,256)
/ @note _exit() is same thing
/ @asyncsignalsafe
_Exit: orl $RUNSTATE_TERMINATE,g_runstate(%rip)
_Exit: push %rbp
mov %rsp,%rbp
orl $RUNSTATE_TERMINATE,g_runstate(%rip)
#if SupportsWindows()
testb IsWindows()
jz 1f
sub $32,%rsp
movzbl %dil,%ecx # %ERRORLEVEL% is limitless
4: call *__imp_ExitProcess(%rip)
jmp 4b

View File

@ -25,7 +25,7 @@ bool AreMemoryIntervalsOk(const struct MemoryIntervals *mm) {
for (i = 0; i < mm->i; ++i) {
if (mm->p[i].y < mm->p[i].x) return false;
if (i) {
if (mm->h[i] || mm->h[i - 1]) {
if (mm->p[i].h || mm->p[i - 1].h) {
if (mm->p[i].x <= mm->p[i - 1].y) return false;
} else {
if (mm->p[i].x <= mm->p[i - 1].y + 1) return false;

View File

@ -17,42 +17,10 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/macros.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.h"
static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
unsigned prot, unsigned flags,
int fd, int64_t off) {
int64_t handle;
struct DirectMap res;
uint32_t protect, access;
if (fd != -1) {
handle = g_fds.p[fd].handle;
} else {
handle = kNtInvalidHandleValue;
}
protect = prot2nt(prot, flags);
access = fprot2nt(prot, flags);
if ((res.maphandle =
CreateFileMappingNuma(handle, NULL, protect, size >> 32, size, NULL,
kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, 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;
}
struct DirectMap DirectMap(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
if (!IsWindows()) {

View File

@ -9,6 +9,7 @@ struct DirectMap {
};
struct DirectMap DirectMap(void *, size_t, unsigned, unsigned, int, int64_t);
struct DirectMap DirectMapNt(void *, size_t, unsigned, unsigned, int, int64_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View File

@ -0,0 +1,51 @@
/*-*- 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/calls/internal.h"
#include "libc/nt/memory.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/directmap.h"
textwindows struct DirectMap DirectMapNt(void *addr, size_t size, unsigned prot,
unsigned flags, int fd, int64_t off) {
int64_t handle;
struct DirectMap res;
uint32_t protect, access;
if (fd != -1) {
handle = g_fds.p[fd].handle;
} else {
handle = kNtInvalidHandleValue;
}
protect = prot2nt(prot, flags);
access = fprot2nt(prot, flags);
if ((res.maphandle =
CreateFileMappingNuma(handle, NULL, protect, size >> 32, size, NULL,
kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, 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;
}

View File

@ -27,12 +27,6 @@
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
/* TODO(jart): Make early-stage data structures happen. */
#undef isspace
#undef iswspace
#define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
#define iswspace(c) isspace(c)
struct DosArgv {
const char16_t *s;
char *p;

View File

@ -25,6 +25,7 @@ void *__cxa_finalize(void *) hidden;
void _executive(int, char **, char **, long (*)[2]) hidden noreturn;
void __stack_chk_fail(void) noreturn relegated;
void __stack_chk_fail_local(void) noreturn relegated hidden;
void _jmpstack(void *, void *, ...) hidden noreturn;
long _setstack(void *, void *, ...) hidden;
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;

View File

@ -0,0 +1,38 @@
/*-*- 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"
/ Switches stack.
/
/ @param rdi is new rsp, passed as malloc(size) + size
/ @param rsi is function to call in new stack space
/ @param rdx,rcx,r8,r9 get passed as args to rsi
/ @noreturn
_jmpstack:
mov %rdi,%rsp
mov %rsi,%rax
mov %rdx,%rdi
mov %rcx,%rsi
mov %r8,%rdx
mov %r9,%rcx
xor %rbp,%rbp
call *%rax
ud2
.endfn _jmpstack,globl,hidden

View File

@ -30,8 +30,6 @@ static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
assert(i + n <= mm->i);
memcpy(mm->p + i, mm->p + i + n,
(intptr_t)(mm->p + mm->i) - (intptr_t)(mm->p + i + n));
memcpy(mm->h + i, mm->h + i + n,
(intptr_t)(mm->h + mm->i) - (intptr_t)(mm->h + i + n));
mm->i -= n;
}
@ -41,8 +39,6 @@ static void CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
assert(mm->i < ARRAYLEN(mm->p));
memmove(mm->p + i + 1, mm->p + i,
(intptr_t)(mm->p + mm->i) - (intptr_t)(mm->p + i));
memmove(mm->h + i + 1, mm->h + i,
(intptr_t)(mm->h + mm->i) - (intptr_t)(mm->h + i));
++mm->i;
}
@ -94,25 +90,31 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
return 0;
}
int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h) {
int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
int prot, int flags) {
unsigned i;
assert(y >= x);
assert(AreMemoryIntervalsOk(mm));
i = FindMemoryInterval(mm, x);
if (i && x == mm->p[i - 1].y + 1 && h == mm->h[i - 1]) {
if (i && x == mm->p[i - 1].y + 1 && h == mm->p[i - 1].h &&
prot == mm->p[i - 1].prot && flags == mm->p[i - 1].flags) {
mm->p[i - 1].y = y;
if (i < mm->i && y + 1 == mm->p[i].x && h == mm->h[i]) {
if (i < mm->i && y + 1 == mm->p[i].x && h == mm->p[i].h &&
prot == mm->p[i].prot && flags == mm->p[i].flags) {
mm->p[i - 1].y = mm->p[i].y;
RemoveMemoryIntervals(mm, i, 1);
}
} else if (i < mm->i && y + 1 == mm->p[i].x && h == mm->h[i]) {
} else if (i < mm->i && y + 1 == mm->p[i].x && h == mm->p[i].h &&
prot == mm->p[i].prot && flags == mm->p[i].flags) {
mm->p[i].x = x;
} else {
if (mm->i == ARRAYLEN(mm->p)) return enomem();
CreateMemoryInterval(mm, i);
mm->p[i].x = x;
mm->p[i].y = y;
mm->h[i] = h;
mm->p[i].h = h;
mm->p[i].prot = prot;
mm->p[i].flags = flags;
}
return 0;
}

View File

@ -14,8 +14,10 @@ struct MemoryIntervals {
struct MemoryInterval {
int x;
int y;
long h;
int prot;
int flags;
} p[128];
long h[128];
};
extern struct MemoryIntervals _mmi;
@ -23,7 +25,7 @@ extern struct MemoryIntervals _mmi;
unsigned FindMemoryInterval(const struct MemoryIntervals *, int) nosideeffect;
bool AreMemoryIntervalsOk(const struct MemoryIntervals *) nosideeffect;
void PrintMemoryIntervals(int, const struct MemoryIntervals *);
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long);
int TrackMemoryInterval(struct MemoryIntervals *, int, int, long, int, int);
int ReleaseMemoryIntervals(struct MemoryIntervals *, int, int,
void (*)(struct MemoryIntervals *, int, int));
void ReleaseMemoryNt(struct MemoryIntervals *, int, int);

View File

@ -35,7 +35,7 @@ void ReleaseMemoryNt(struct MemoryIntervals *mm, int l, int r) {
for (i = l; i <= r; ++i) {
ok = UnmapViewOfFile(GetFrameAddr(mm->p[i].x));
assert(ok);
ok = CloseHandle(mm->h[i]);
ok = CloseHandle(mm->p[i].h);
assert(ok);
}
}

View File

@ -39,8 +39,6 @@
#define ALIGNED(p) (!(IP(p) & (FRAMESIZE - 1)))
#define CANONICAL(p) (-0x800000000000 <= IP(p) && IP(p) <= 0x7fffffffffff)
struct MemoryIntervals _mmi;
/**
* Beseeches system for page-table entries.
*
@ -92,7 +90,7 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) {
}
a = ROUNDDOWN((intptr_t)addr, FRAMESIZE) >> 16;
b = ROUNDDOWN((intptr_t)addr + size - 1, FRAMESIZE) >> 16;
if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle) == -1) {
if (TrackMemoryInterval(&_mmi, a, b, dm.maphandle, prot, flags) == -1) {
abort();
}
if (weaken(__asan_map_shadow)) {

22
libc/runtime/mmi.c 100644
View File

@ -0,0 +1,22 @@
/*-*- 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/runtime/memtrack.h"
struct MemoryIntervals _mmi;

View File

@ -30,7 +30,7 @@ textwindows int msync$nt(void *addr, size_t size, int flags) {
for (i = FindMemoryInterval(&_mmi, x); i < _mmi.i; ++i) {
if ((x >= _mmi.p[i].x && x <= _mmi.p[i].y) ||
(y >= _mmi.p[i].x && y <= _mmi.p[i].y)) {
FlushFileBuffers(_mmi.h[i]);
FlushFileBuffers(_mmi.p[i].h);
} else {
break;
}

View File

@ -12,7 +12,6 @@ extern int g_argc; /* CRT */
extern char **g_argv; /* CRT */
extern char **environ; /* CRT */
extern unsigned long *g_auxv; /* CRT */
extern jmp_buf g_winmain; /* CRT */
extern char *program_invocation_name; /* RII */
extern char *program_invocation_short_name; /* RII */
extern uint64_t g_syscount; /* RII */

View File

@ -64,11 +64,6 @@ $(LIBC_RUNTIME_A_OBJS): \
OVERRIDE_CFLAGS += \
$(NO_MAGIC)
# @see ape/ape.s for tuning parameters that make this safe
o/$(MODE)/libc/runtime/winmain.greg.o: \
DEFAULT_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
LIBC_RUNTIME_LIBS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)))
LIBC_RUNTIME_SRCS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_SRCS))
LIBC_RUNTIME_HDRS = $(foreach x,$(LIBC_RUNTIME_ARTIFACTS),$($(x)_HDRS))

View File

@ -20,7 +20,10 @@
#include "libc/bits/bits.h"
#include "libc/bits/pushpop.h"
#include "libc/bits/weaken.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/filetype.h"
@ -34,8 +37,21 @@
#include "libc/nt/struct/teb.h"
#include "libc/runtime/getdosenviron.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/winmain.h"
#include "libc/sock/internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
struct WinArgs {
char *argv[512];
char *envp[512];
long auxv[1][2];
char argblock[ARG_MAX];
char envblock[ENV_MAX];
};
static struct CmdExe {
bool result;
@ -46,13 +62,7 @@ static struct CmdExe {
} oldin, oldout;
} g_cmdexe;
static textwindows void MitigateDriveByDownloads(void) {
unsigned wrote;
if (!SetDefaultDllDirectories(kNtLoadLibrarySearchSearchSystem32)) {
WriteFile(GetStdHandle(kNtStdErrorHandle), "nodll\n", 6, &wrote, NULL);
ExitProcess(1);
}
}
struct WinMain g_winmain;
static textwindows void RestoreCmdExe(void) {
if (g_cmdexe.oldin.handle) {
@ -104,6 +114,53 @@ static textwindows void NormalizeCmdExe(void) {
}
}
static textwindows char *AllocateMemory(void *addr, size_t size, int64_t *h) {
return MapViewOfFileExNuma(
(*h = CreateFileMappingNuma(-1, NULL, pushpop(kNtPageReadwrite), 0, size,
NULL, kNtNumaNoPreferredNode)),
kNtFileMapRead | kNtFileMapWrite, 0, 0, size, addr,
kNtNumaNoPreferredNode);
}
static textwindows noreturn void WinMainNew(int64_t hInstance,
int64_t hPrevInstance,
const char *lpCmdLine,
int nCmdShow) {
int64_t h;
size_t size;
int i, count;
uint64_t data;
struct WinArgs *wa;
const char16_t *env16;
g_winmain.nCmdShow = nCmdShow;
g_winmain.hInstance = hInstance;
g_winmain.hPrevInstance = hPrevInstance;
NormalizeCmdExe();
*(/*unconst*/ int *)&hostos = WINDOWS;
size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE);
data = 0x777000000000;
data = (intptr_t)AllocateMemory((char *)data, size, &_mmi.p[0].h);
_mmi.p[0].x = data >> 16;
_mmi.p[0].y = (data >> 16) + ((size >> 16) - 1);
_mmi.p[0].prot = PROT_READ | PROT_WRITE;
_mmi.p[0].flags = MAP_PRIVATE | MAP_ANONYMOUS;
_mmi.i = pushpop(1L);
wa = (struct WinArgs *)(data + size - sizeof(struct WinArgs));
count = GetDosArgv(GetCommandLine(), wa->argblock, ARG_MAX, wa->argv, 512);
for (i = 0; wa->argv[0][i]; ++i) {
if (wa->argv[0][i] == '\\') {
wa->argv[0][i] = '/';
}
}
env16 = GetEnvironmentStrings();
GetDosEnviron(env16, wa->envblock, ENV_MAX, wa->envp, 512);
FreeEnvironmentStrings(env16);
wa->auxv[0][0] = pushpop(0L);
wa->auxv[0][1] = pushpop(0L);
_jmpstack((char *)data + STACKSIZE, _executive, count, wa->argv, wa->envp,
wa->auxv);
}
/**
* Main function on Windows NT.
*
@ -130,30 +187,15 @@ static textwindows void NormalizeCmdExe(void) {
* the downloads folder. Since we don't even use dynamic linking,
* we've cargo culted some API calls, that may harden against it.
*
* 6. Finally, we need fork. Microsoft designed Windows to prevent us
* from having fork() so we pass pipe handles in an environment
* variable literally copy all the memory.
*
*/
textwindows int WinMain(void *hInstance, void *hPrevInstance,
const char *lpCmdLine, int nCmdShow) {
char *stack;
int i, count;
const char16_t *cmd16, *env16;
char *argv[512], *envp[512];
char argblock[ARG_MAX], envblock[ENV_MAX];
long auxv[][2] = {{pushpop(0L), pushpop(0L)}};
MitigateDriveByDownloads();
NormalizeCmdExe();
*(/*unconst*/ int *)&hostos = WINDOWS;
cmd16 = GetCommandLine();
env16 = GetEnvironmentStrings();
count = GetDosArgv(cmd16, argblock, ARG_MAX, argv, 512);
for (i = 0; argv[0][i]; ++i) {
if (argv[0][i] == '\\') argv[0][i] = '/';
}
GetDosEnviron(env16, envblock, ENV_MAX, envp, 512);
FreeEnvironmentStrings(env16);
stack = MapViewOfFileExNuma(
CreateFileMappingNuma(-1, NULL, pushpop(kNtPageReadwrite), 0, STACKSIZE,
NULL, kNtNumaNoPreferredNode),
kNtFileMapRead | kNtFileMapWrite, 0, 0, STACKSIZE,
(char *)0x777000000000 - STACKSIZE, kNtNumaNoPreferredNode);
return _setstack(stack + STACKSIZE, _executive, count, argv, envp, auxv);
textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int nCmdShow) {
SetDefaultDllDirectories(kNtLoadLibrarySearchSearchSystem32);
if (weaken(winsockinit)) weaken(winsockinit)();
if (weaken(WinMainForked)) weaken(WinMainForked)();
WinMainNew(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

View File

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_RUNTIME_WINMAIN_H_
#define COSMOPOLITAN_LIBC_RUNTIME_WINMAIN_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct WinMain {
int nCmdShow;
int64_t hInstance;
int64_t hPrevInstance;
};
extern struct WinMain g_winmain;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_WINMAIN_H_ */

View File

@ -34,9 +34,6 @@ textwindows int accept$nt(struct Fd *fd, void *addr, uint32_t *addrsize,
if ((client = createfd()) == -1) return -1;
if ((g_fds.p[client].handle = WSAAccept(fd->handle, addr, (int32_t *)addrsize,
NULL, NULL)) != -1) {
if (flags & SOCK_CLOEXEC) {
SetHandleInformation(g_fds.p[client].handle, kNtHandleFlagInherit, 0);
}
if (flags & SOCK_NONBLOCK) {
yes = 1;
if (__ioctlsocket$nt(g_fds.p[client].handle, FIONBIO, &yes) == -1) {

View File

@ -112,6 +112,7 @@ ssize_t sendto$nt(struct Fd *, const struct iovec *, size_t, uint32_t, void *,
ssize_t recvfrom$nt(struct Fd *, const struct iovec *, size_t, uint32_t, void *,
uint32_t *) hidden;
void winsockinit(void) hidden;
int64_t winsockerr(void) nocallback hidden;
int fixupnewsockfd$sysv(int, int) hidden;
ssize_t WinSendRecv(int64_t, void *, size_t, uint32_t, struct sockaddr *,

View File

@ -33,15 +33,15 @@
*/
struct NtWsaData kNtWsaData;
textwindows static void winsockfini(void) { WSACleanup(); }
textstartup static void winsockinit(void) {
if (!IsWindows()) return;
atexit(winsockfini);
textwindows static void winsockfini(void) {
WSACleanup();
}
textwindows void winsockinit(void) {
int rc;
atexit(winsockfini);
if ((rc = WSAStartup(VERSION, &kNtWsaData)) != 0 ||
kNtWsaData.wVersion != VERSION) {
abort();
}
}
const void *const winsockctor[] initarray = {winsockinit};

View File

@ -28,6 +28,7 @@ LIBC_STDIO_A_DIRECTDEPS = \
LIBC_ALG \
LIBC_BITS \
LIBC_CALLS \
LIBC_CALLS_HEFTY \
LIBC_CONV \
LIBC_FMT \
LIBC_MEM \

View File

@ -19,126 +19,12 @@
*/
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/accounting.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processinformation.h"
#include "libc/nt/synchronization.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/dce.h"
#include "libc/paths.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/errfuns.h"
#define SHELL_BIN "/bin/sh"
#define SHELL_ARG "-c"
#define CMD_C "CMD /C "
static int system$sysv(const char *cmdline) {
int rc, n, wstatus;
struct mem {
char shell[sizeof(SHELL_BIN)];
char arg[sizeof(SHELL_ARG)];
char *args[4];
char cmdline[];
} * mem;
if (cmdline != NULL) {
mem = malloc(sizeof(struct mem) + (strlen(cmdline) + 1));
if (!mem) return enomem();
strcpy(mem->shell, SHELL_BIN);
strcpy(mem->arg, SHELL_ARG);
mem->args[0] = mem->shell;
mem->args[1] = mem->arg;
mem->args[2] = mem->cmdline;
mem->args[3] = NULL;
strcpy(mem->cmdline, cmdline);
if ((rc = vfork()) != -1) {
if (rc == 0) {
execve$sysv(mem->shell, mem->args, environ);
abort();
}
if ((rc = wait4$sysv(rc, &wstatus, 0, NULL)) != -1) {
rc = wstatus;
}
}
free(mem);
return rc;
} else {
return fileexists(SHELL_BIN);
}
}
static textwindows noinline int system$nt(const char *cmdline) {
char *mem;
int rc, status;
uint32_t dwExitCode;
struct NtStartupInfo startinfo;
struct NtProcessInformation *info;
uint16_t *cmdline16, *quotedcmdline16;
unsigned len, dosquotemultiplier, cmdline16bytes, quotedcmdline16bytes;
if (cmdline != NULL) {
rc = -1;
dosquotemultiplier = 2;
len = strlen(cmdline);
cmdline16bytes = (len + 1) * sizeof(uint16_t);
quotedcmdline16bytes =
strlen(CMD_C) * sizeof(uint16_t) + cmdline16bytes * dosquotemultiplier;
if (!(mem = malloc(sizeof(struct NtProcessInformation) + cmdline16bytes +
quotedcmdline16bytes))) {
return enomem();
}
info = (struct NtProcessInformation *)mem;
cmdline16 = (uint16_t *)(mem + sizeof(struct NtProcessInformation));
quotedcmdline16 = (uint16_t *)(mem + sizeof(struct NtProcessInformation) +
cmdline16bytes);
strcpyzbw(cmdline16, cmdline);
strcpyzbw(quotedcmdline16, CMD_C);
if (escapedos(quotedcmdline16 + strlen(CMD_C), len * dosquotemultiplier,
cmdline16, len)) {
memset(&startinfo, 0, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = STDIN_FILENO;
startinfo.hStdOutput = STDOUT_FILENO;
startinfo.hStdError = STDERR_FILENO;
if (CreateProcess(
/* lpApplicationName */ NULL,
/* lpCommandLine */ quotedcmdline16,
/* lpProcessAttributes */ NULL,
/* lpThreadAttributes */ NULL,
/* bInheritHandles */ true,
/* dwCreationFlags */ kNtCreateNoWindow,
/* lpEnvironment */ NULL,
/* lpCurrentDirectory */ NULL,
/* lpStartupInfo */ &startinfo,
/* lpProcessInformation */ info)) {
dwExitCode = kNtStillActive;
do {
WaitForSingleObject(info->hProcess, 0xffffffff);
} while ((status = GetExitCodeProcess(info->hProcess, &dwExitCode)) &&
dwExitCode == kNtStillActive);
if (weaken(fflush)) {
weaken(fflush)(*weaken(stderr));
}
rc = (dwExitCode & 0xff) << 8; /* @see WEXITSTATUS() */
CloseHandle(info->hProcess);
CloseHandle(info->hThread);
} else {
rc = winerr();
}
} else {
rc = einval();
}
free(mem);
return rc;
} else {
/* how could cmd.exe not exist? */
return true;
}
}
/**
* Launches program with system command interpreter.
@ -148,12 +34,24 @@ static textwindows noinline int system$nt(const char *cmdline) {
* status that can be accessed using macros like WEXITSTATUS(s)
*/
int system(const char *cmdline) {
int rc;
const char *prog, *arg;
int rc, wstatus, fds[3];
if (weaken(fflush)) weaken(fflush)(NULL);
if (!IsWindows()) {
rc = system$sysv(cmdline);
if (cmdline) {
prog = !IsWindows() ? _PATH_BSHELL : "cmd";
arg = !IsWindows() ? "-c" : "/C";
fds[0] = 0;
fds[1] = 1;
fds[2] = 2;
if ((rc = spawnlp(0, fds, prog, prog, arg, cmdline, NULL)) != -1) {
if ((rc = wait4(rc, &wstatus, 0, NULL)) != -1) {
rc = wstatus;
}
}
return rc;
} else if (IsWindows()) {
return true;
} else {
rc = system$nt(cmdline);
return fileexists(_PATH_BSHELL);
}
return rc;
}

View File

@ -34,7 +34,6 @@ LIBC_SYSV_A_FILES := \
libc/sysv/restorert.S \
libc/sysv/syscall.S \
libc/sysv/systemfive.S \
libc/sysv/vfork.S \
$(wildcard libc/sysv/stubs/*) \
$(wildcard libc/sysv/consts/*) \
$(wildcard libc/sysv/errfuns/*)

View File

@ -59,11 +59,11 @@ o/$(MODE)/net/http/formathttpdatetime.o: \
OVERRIDE_CFLAGS += \
-O3
ifeq (,$(MODE))
$(NET_HTTP_A_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(NET_HTTP_A_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
NET_HTTP_LIBS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)))
NET_HTTP_SRCS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)_SRCS))

View File

@ -50,9 +50,9 @@ o/$(MODE)/test/ape/lib/%.com.dbg: \
$(APE)
@$(APELINK)
$(TEST_APE_LIB_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
# $(TEST_APE_LIB_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
.PHONY: o/$(MODE)/test/ape/lib
o/$(MODE)/test/ape/lib: $(TEST_APE_LIB_BINS) \

View File

@ -47,13 +47,9 @@ o/$(MODE)/test/dsp/core/%.com.dbg: \
$(APE)
@$(APELINK)
$(TEST_DSP_CORE_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
o/$(MODE)/test/dsp/core/getintegercoefficients8_test-gcc.asm: \
OVERRIDE_CFLAGS += \
-fsanitize=address
# $(TEST_DSP_CORE_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
.PHONY: o/$(MODE)/test/dsp/core
o/$(MODE)/test/dsp/core: \

View File

@ -52,9 +52,9 @@ o/$(MODE)/test/libc/intrin/%.com.dbg: \
$(APE)
@$(APELINK)
$(TEST_LIBC_INTRIN_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
# $(TEST_LIBC_INTRIN_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
.PHONY: o/$(MODE)/test/libc/intrin
o/$(MODE)/test/libc/intrin: \

View File

@ -31,7 +31,6 @@ static bool AreMemoryIntervalsEqual(const struct MemoryIntervals *mm1,
const struct MemoryIntervals *mm2) {
if (mm1->i != mm2->i) return false;
if (memcmp(mm1->p, mm2->p, mm1->i * sizeof(*mm2->p)) != 0) return false;
if (memcmp(mm1->h, mm2->h, mm1->i * sizeof(*mm2->h)) != 0) return false;
return true;
}
@ -67,7 +66,7 @@ static void RunTrackMemoryIntervalTest(const struct MemoryIntervals t[2], int x,
struct MemoryIntervals *mm;
mm = memcpy(memalign(alignof(*t), sizeof(*t)), t, sizeof(*t));
CheckMemoryIntervalsAreOk(mm);
CHECK_NE(-1, TrackMemoryInterval(mm, x, y, h));
CHECK_NE(-1, TrackMemoryInterval(mm, x, y, h, 0, 0));
CheckMemoryIntervalsAreOk(mm);
CheckMemoryIntervalsEqual(mm, t + 1);
free(mm);
@ -86,8 +85,8 @@ static void RunReleaseMemoryIntervalsTest(const struct MemoryIntervals t[2],
TEST(TrackMemoryInterval, TestEmpty) {
static const struct MemoryIntervals mm[2] = {
{0, {}, {}},
{1, {{2, 2}}, {0}},
{0, {}},
{1, {{2, 2, 0}}},
};
RunTrackMemoryIntervalTest(mm, 2, 2, 0);
}
@ -98,10 +97,10 @@ TEST(TrackMemoryInterval, TestFull) {
mm = calloc(1, sizeof(struct MemoryIntervals));
for (i = 0; i < ARRAYLEN(mm->p); ++i) {
CheckMemoryIntervalsAreOk(mm);
CHECK_NE(-1, TrackMemoryInterval(mm, i, i, i));
CHECK_NE(-1, TrackMemoryInterval(mm, i, i, i, 0, 0));
CheckMemoryIntervalsAreOk(mm);
}
CHECK_EQ(-1, TrackMemoryInterval(mm, i, i, i));
CHECK_EQ(-1, TrackMemoryInterval(mm, i, i, i, 0, 0));
CHECK_EQ(ENOMEM, errno);
CheckMemoryIntervalsAreOk(mm);
free(mm);
@ -109,62 +108,63 @@ TEST(TrackMemoryInterval, TestFull) {
TEST(TrackMemoryInterval, TestAppend) {
static const struct MemoryIntervals mm[2] = {
{1, {{2, 2}}, {0}},
{1, {{2, 3}}, {0}},
{1, {{2, 2}}},
{1, {{2, 3}}},
};
RunTrackMemoryIntervalTest(mm, 3, 3, 0);
}
TEST(TrackMemoryInterval, TestPrepend) {
static const struct MemoryIntervals mm[2] = {
{1, {{2, 2}}, {0}},
{1, {{1, 2}}, {0}},
{1, {{2, 2}}},
{1, {{1, 2}}},
};
RunTrackMemoryIntervalTest(mm, 1, 1, 0);
}
TEST(TrackMemoryInterval, TestFillHole) {
static const struct MemoryIntervals mm[2] = {
{4, {{1, 1}, {3, 4}, {5, 5}, {6, 8}}, {0, 0, 1, 0}},
{3, {{1, 4}, {5, 5}, {6, 8}}, {0, 1, 0}},
{4, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
{3, {{1, 4}, {5, 5, 1}, {6, 8}}},
};
RunTrackMemoryIntervalTest(mm, 2, 2, 0);
}
TEST(TrackMemoryInterval, TestAppend2) {
static const struct MemoryIntervals mm[2] = {
{1, {{2, 2}}, {0}},
{2, {{2, 2}, {3, 3}}, {0, 1}},
{1, {{2, 2}}},
{2, {{2, 2}, {3, 3, 1}}},
};
RunTrackMemoryIntervalTest(mm, 3, 3, 1);
}
TEST(TrackMemoryInterval, TestPrepend2) {
static const struct MemoryIntervals mm[2] = {
{1, {{2, 2}}, {0}},
{2, {{1, 1}, {2, 2}}, {1, 0}},
{1, {{2, 2}}},
{2, {{1, 1, 1}, {2, 2}}},
};
RunTrackMemoryIntervalTest(mm, 1, 1, 1);
}
TEST(TrackMemoryInterval, TestFillHole2) {
static const struct MemoryIntervals mm[2] = {
{4, {{1, 1}, {3, 4}, {5, 5}, {6, 8}}, {0, 0, 1, 0}},
{5, {{1, 1}, {2, 2}, {3, 4}, {5, 5}, {6, 8}}, {0, 1, 0, 1, 0}},
{4, {{1, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
{5, {{1, 1}, {2, 2, 1}, {3, 4}, {5, 5, 1}, {6, 8}}},
};
RunTrackMemoryIntervalTest(mm, 2, 2, 1);
}
TEST(FindMemoryInterval, Test) {
static const struct MemoryIntervals mm[1] = {
{4,
{
[0] = {1, 1},
[1] = {3, 4},
[2] = {5, 5},
[3] = {6, 8},
},
{0, 0, 1, 0}},
{
4,
{
[0] = {1, 1},
[1] = {3, 4},
[2] = {5, 5, 1},
[3] = {6, 8},
},
},
};
EXPECT_EQ(0, FindMemoryInterval(mm, 0));
EXPECT_EQ(0, FindMemoryInterval(mm, 1));
@ -180,96 +180,96 @@ TEST(FindMemoryInterval, Test) {
TEST(ReleaseMemoryIntervals, TestEmpty) {
static const struct MemoryIntervals mm[2] = {
{0, {}, {}},
{0, {}, {}},
{0, {}},
{0, {}},
};
RunReleaseMemoryIntervalsTest(mm, 2, 2);
}
TEST(ReleaseMemoryIntervals, TestRemoveElement_UsesInclusiveRange) {
static const struct MemoryIntervals mm[2] = {
{3, {{0, 0}, {2, 2}, {4, 4}}, {}},
{2, {{0, 0}, {4, 4}}, {}},
{3, {{0, 0}, {2, 2}, {4, 4}}},
{2, {{0, 0}, {4, 4}}},
};
RunReleaseMemoryIntervalsTest(mm, 2, 2);
}
TEST(ReleaseMemoryIntervals, TestPunchHole) {
static const struct MemoryIntervals mm[2] = {
{1, {{0, 9}}, {}},
{2, {{0, 3}, {6, 9}}, {}},
{1, {{0, 9}}},
{2, {{0, 3}, {6, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, 4, 5);
}
TEST(ReleaseMemoryIntervals, TestShortenLeft) {
static const struct MemoryIntervals mm[2] = {
{1, {{0, 9}}, {}},
{1, {{0, 7}}, {}},
{1, {{0, 9}}},
{1, {{0, 7}}},
};
RunReleaseMemoryIntervalsTest(mm, 8, 9);
}
TEST(ReleaseMemoryIntervals, TestShortenRight) {
static const struct MemoryIntervals mm[2] = {
{1, {{0, 9}}, {}},
{1, {{3, 9}}, {}},
{1, {{0, 9}}},
{1, {{3, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, 0, 2);
}
TEST(ReleaseMemoryIntervals, TestShortenLeft2) {
static const struct MemoryIntervals mm[2] = {
{1, {{0, 9}}, {}},
{1, {{0, 7}}, {}},
{1, {{0, 9}}},
{1, {{0, 7}}},
};
RunReleaseMemoryIntervalsTest(mm, 8, 11);
}
TEST(ReleaseMemoryIntervals, TestShortenRight2) {
static const struct MemoryIntervals mm[2] = {
{1, {{0, 9}}, {}},
{1, {{3, 9}}, {}},
{1, {{0, 9}}},
{1, {{3, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, -3, 2);
}
TEST(ReleaseMemoryIntervals, TestZeroZero) {
static const struct MemoryIntervals mm[2] = {
{1, {{3, 9}}, {}},
{1, {{3, 9}}, {}},
{1, {{3, 9}}},
{1, {{3, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, 0, 0);
}
TEST(ReleaseMemoryIntervals, TestNoopLeft) {
static const struct MemoryIntervals mm[2] = {
{1, {{3, 9}}, {}},
{1, {{3, 9}}, {}},
{1, {{3, 9}}},
{1, {{3, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, 1, 2);
}
TEST(ReleaseMemoryIntervals, TestNoopRight) {
static const struct MemoryIntervals mm[2] = {
{1, {{3, 9}}, {}},
{1, {{3, 9}}, {}},
{1, {{3, 9}}},
{1, {{3, 9}}},
};
RunReleaseMemoryIntervalsTest(mm, 10, 10);
}
TEST(ReleaseMemoryIntervals, TestBigFree) {
static const struct MemoryIntervals mm[2] = {
{2, {{0, 3}, {6, 9}}, {}},
{0, {}, {}},
{2, {{0, 3}, {6, 9}}},
{0, {}},
};
RunReleaseMemoryIntervalsTest(mm, INT_MIN, INT_MAX);
}
TEST(ReleaseMemoryIntervals, TestWeirdGap) {
static const struct MemoryIntervals mm[2] = {
{3, {{10, 10}, {20, 20}, {30, 30}}, {}},
{2, {{10, 10}, {30, 30}}, {}},
{3, {{10, 10}, {20, 20}, {30, 30}}},
{2, {{10, 10}, {30, 30}}},
};
RunReleaseMemoryIntervalsTest(mm, 15, 25);
}
@ -279,7 +279,7 @@ TEST(ReleaseMemoryIntervals, TestOutOfMemory) {
struct MemoryIntervals *mm;
mm = calloc(1, sizeof(struct MemoryIntervals));
for (i = 0; i < ARRAYLEN(mm->p); ++i) {
CHECK_NE(-1, TrackMemoryInterval(mm, i * 10, i * 10 + 8, 0));
CHECK_NE(-1, TrackMemoryInterval(mm, i * 10, i * 10 + 8, 0, 0, 0));
}
CheckMemoryIntervalsAreOk(mm);
CHECK_EQ(-1, ReleaseMemoryIntervals(mm, 4, 4, NULL));

View File

@ -88,11 +88,6 @@ TEST(mmap, testMapFixed_destroysEverythingInItsPath) {
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
ASSERT_GT(_mmi.i, m1);
EXPECT_NE(-1, munmap((void *)kFixedmapStart, FRAMESIZE * 3));
#ifdef __SANITIZE_ADDRESS__
ASSERT_EQ(m1 + 1, _mmi.i);
#else
ASSERT_EQ(m1, _mmi.i);
#endif
}
TEST(isheap, nullPtr) {

View File

@ -63,11 +63,11 @@ $(TEST_LIBC_RUNTIME_OBJS): \
DEFAULT_CCFLAGS += \
-fno-builtin
ifeq (,$(MODE))
$(TEST_LIBC_RUNTIME_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(TEST_LIBC_RUNTIME_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
o/$(MODE)/test/libc/runtime/getenv_test.com.runs: \
o/$(MODE)/test/libc/runtime/getenv_test.com

View File

@ -29,7 +29,11 @@
struct HttpRequest req[1];
static char *slice(const char *m, struct HttpRequestSlice s) {
return memcpy(xmalloc(s.b - s.a), m + s.a, s.b - s.a);
char *p;
p = xmalloc(s.b - s.a + 1);
memcpy(p, m + s.a, s.b - s.a);
p[s.b - s.a] = 0;
return p;
}
TEST(ParseHttpRequest, testEmpty) {

View File

@ -39,9 +39,9 @@ o/$(MODE)/test/net/http/%.com.dbg: \
$(APE)
@$(APELINK)
$(TEST_NET_HTTP_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
# $(TEST_NET_HTTP_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
.PHONY: o/$(MODE)/test/net/http
o/$(MODE)/test/net/http: \

View File

@ -63,11 +63,11 @@ $(THIRD_PARTY_STB_A_OBJS): \
-ffunction-sections \
-fdata-sections
o//third_party/stb/stb_image_write.o \
o//third_party/stb/stb_image.o: \
OVERRIDE_CFLAGS += \
-ftrapv \
-fsanitize=address
# o//third_party/stb/stb_image_write.o \
# o//third_party/stb/stb_image.o: \
# OVERRIDE_CFLAGS += \
# -ftrapv \
# -fsanitize=address
$(THIRD_PARTY_STB_A_OBJS): \
OVERRIDE_CPPFLAGS += \

View File

@ -267,7 +267,7 @@ static struct XmmType xmmtype;
static struct Elf elf[1];
static struct Dis dis[1];
long double last_seconds;
static long double last_seconds;
static long double statusexpires;
static struct termios oldterm;
static char logpath[PATH_MAX];

View File

@ -40,6 +40,8 @@ TOOL_BUILD_DIRECTDEPS = \
LIBC_TINYMATH \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_KERNELBASE \
LIBC_NT_USER32 \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
@ -86,6 +88,12 @@ o/$(MODE)/tool/build/emulator.o: \
OVERRIDE_COPTS += \
-fno-sanitize=pointer-overflow
# ifeq (,$(MODE))
# $(TOOL_BUILD_OBJS): \
# OVERRIDE_COPTS += \
# -fsanitize=address
# endif
.PHONY: o/$(MODE)/tool/build
o/$(MODE)/tool/build: \
o/$(MODE)/tool/build/emucrt \

View File

@ -63,15 +63,11 @@ $(TOOL_BUILD_LIB_A).pkg: \
$(TOOL_BUILD_LIB_A_OBJS) \
$(foreach x,$(TOOL_BUILD_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
ifeq (,$(MODE))
$(TOOL_BUILD_LIB_A_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
o/$(MODE)/tool/build/lib/buffer-gcc.asm: \
OVERRIDE_CFLAGS += \
-fsanitize=address
# ifeq (,$(MODE))
# $(TOOL_BUILD_LIB_A_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
o/$(MODE)/tool/build/lib/ssefloat.o: \
TARGET_ARCH += \

View File

@ -50,7 +50,7 @@ static const char kGreg[2][2][2][8][5] = {
{{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"},
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
{{{"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"},
{"r8w", "re9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"}},
{"r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"}},
{{"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"},
{"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}},
};

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