Improve synchronization

- Fix bugs in kDos2Errno definition
- malloc() should now be thread safe
- Fix bug in rollup.com header generator
- Fix open(O_APPEND) on the New Technology
- Fix select() on the New Technology and test it
- Work towards refactoring i/o for thread safety
- Socket reads and writes on NT now poll for signals
- Work towards i/o completion ports on the New Technology
- Make read() and write() intermittently check for signals
- Blinkenlights keyboard i/o so much better on NT w/ poll()
- You can now poll() files and sockets at the same time on NT
- Fix bug in appendr() that manifests with dlmalloc footers off
This commit is contained in:
Justine Tunney 2022-04-14 23:39:48 -07:00
parent 233144b19d
commit 933411ba99
266 changed files with 8761 additions and 4344 deletions

View file

@ -97,7 +97,7 @@ privileged int clone(int (*f)(void *), void *stack, int flags, void *arg, ...) {
: "memory");
unreachable;
} else if (IsWindows()) {
if ((tidfd = __reservefd()) == -1) return -1;
if ((tidfd = __reservefd(-1)) == -1) return -1;
if (flags == CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) {
if ((hand = CreateThread(&kNtIsInheritable, 0, NT2SYSV(WinThreadMain),
&(struct WinThread){f, arg, stack}, 0, &tid))) {

View file

@ -24,8 +24,13 @@
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/mem/alloca.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/console.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/enum/creationdisposition.h"
#include "libc/nt/enum/fileflagandattributes.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/enum/processcreationflags.h"
@ -39,6 +44,7 @@
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/ntstdin.internal.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
@ -78,7 +84,7 @@ static inline textwindows ssize_t ForkIo(int64_t h, char *p, size_t n,
static dontinline textwindows bool ForkIo2(int64_t h, void *buf, size_t n,
bool32 (*fn)(), const char *sf) {
ssize_t rc = ForkIo(h, buf, n, fn);
STRACE("%s(%ld, %'zu) → %'zd% m", sf, h, n, rc);
// STRACE("%s(%ld, %'zu) → %'zd% m", sf, h, n, rc);
return rc != -1;
}
@ -90,25 +96,16 @@ static textwindows dontinline bool ReadAll(int64_t h, void *buf, size_t n) {
return ForkIo2(h, buf, n, ReadFile, "ReadFile");
}
static textwindows int OnForkCrash(struct NtExceptionPointers *ep) {
kprintf("error: fork() child crashed!%n"
"\tExceptionCode = %#x%n"
"\tRip = %x%n",
ep->ExceptionRecord->ExceptionCode,
ep->ContextRecord ? ep->ContextRecord->Rip : -1);
ExitProcess(73);
}
textwindows void WinMainForked(void) {
bool ok;
jmp_buf jb;
int64_t reader;
char *addr, *shad;
struct DirectMap dm;
uint64_t size, upsize;
int64_t reader, writer;
int64_t savetsc, savebir;
struct MemoryInterval *maps;
char16_t fvar[21 + 1 + 21 + 1];
int64_t oncrash, savetsc, savebir;
uint32_t i, varlen, oldprot, savepid;
long mapcount, mapcapacity, specialz;
extern uint64_t ts asm("kStartTsc");
@ -119,44 +116,31 @@ textwindows void WinMainForked(void) {
if (!varlen || varlen >= ARRAYLEN(fvar)) return;
STRACE("WinMainForked()");
SetEnvironmentVariable(u"_FORK", NULL);
#ifdef SYSDEBUG
oncrash = AddVectoredExceptionHandler(1, NT2SYSV(OnForkCrash));
#endif
ParseInt(ParseInt(fvar, &reader), &writer);
CloseHandle(writer);
ParseInt(fvar, &reader);
// read the cpu state from the parent process & plus
// read the list of mappings from the parent process
// this is stored in a special secretive memory map!
// read ExtendMemoryIntervals for further details :|
maps = (void *)kMemtrackStart;
if (!ReadAll(reader, jb, sizeof(jb)) ||
!ReadAll(reader, &mapcount, sizeof(_mmi.i)) ||
!ReadAll(reader, &mapcapacity, sizeof(_mmi.n))) {
ExitProcess(40);
}
ReadAll(reader, jb, sizeof(jb));
ReadAll(reader, &mapcount, sizeof(_mmi.i));
ReadAll(reader, &mapcapacity, sizeof(_mmi.n));
specialz = ROUNDUP(mapcapacity * sizeof(_mmi.p[0]), kMemtrackGran);
if (!MapViewOfFileEx(CreateFileMapping(-1, 0, kNtPageReadwrite,
specialz >> 32, specialz, 0),
kNtFileMapWrite, 0, 0, specialz, maps)) {
ExitProcess(41);
}
if (!ReadAll(reader, maps, mapcount * sizeof(_mmi.p[0]))) {
ExitProcess(42);
}
MapViewOfFileEx(
CreateFileMapping(-1, 0, kNtPageReadwrite, specialz >> 32, specialz, 0),
kNtFileMapWrite, 0, 0, specialz, maps);
ReadAll(reader, maps, mapcount * sizeof(_mmi.p[0]));
if (IsAsan()) {
shad = (char *)(((intptr_t)maps >> 3) + 0x7fff8000);
size = ROUNDUP(specialz >> 3, FRAMESIZE);
MapViewOfFileEx(
CreateFileMapping(-1, 0, kNtPageReadwrite, size >> 32, size, 0),
kNtFileMapWrite, 0, 0, size, maps);
if (!ReadAll(reader, shad, (mapcount * sizeof(_mmi.p[0])) >> 3)) {
ExitProcess(43);
}
ReadAll(reader, shad, (mapcount * sizeof(_mmi.p[0])) >> 3);
}
// read the heap mappings from the parent process
// we can avoid copying via pipe for shared maps!
for (i = 0; i < mapcount; ++i) {
addr = (char *)((uint64_t)maps[i].x << 16);
size = maps[i].size;
@ -164,22 +148,18 @@ textwindows void WinMainForked(void) {
upsize = ROUNDUP(size, FRAMESIZE);
// we don't need to close the map handle because sys_mmap_nt
// doesn't mark it inheritable across fork() for MAP_PRIVATE
if (!(maps[i].h = CreateFileMapping(-1, 0, kNtPageExecuteReadwrite,
upsize >> 32, upsize, 0)) ||
!MapViewOfFileEx(maps[i].h, kNtFileMapWrite | kNtFileMapExecute, 0, 0,
upsize, addr) ||
!ReadAll(reader, addr, size)) {
ExitProcess(44);
}
maps[i].h = CreateFileMapping(-1, 0, kNtPageExecuteReadwrite,
upsize >> 32, upsize, 0);
MapViewOfFileEx(maps[i].h, kNtFileMapWrite | kNtFileMapExecute, 0, 0,
upsize, addr);
ReadAll(reader, addr, size);
} else {
// we can however safely inherit MAP_SHARED with zero copy
if (!MapViewOfFileEx(maps[i].h,
maps[i].readonlyfile
? kNtFileMapRead | kNtFileMapExecute
: kNtFileMapWrite | kNtFileMapExecute,
maps[i].offset >> 32, maps[i].offset, size, addr)) {
ExitProcess(45);
}
MapViewOfFileEx(maps[i].h,
maps[i].readonlyfile
? kNtFileMapRead | kNtFileMapExecute
: kNtFileMapWrite | kNtFileMapExecute,
maps[i].offset >> 32, maps[i].offset, size, addr);
}
}
@ -187,10 +167,8 @@ textwindows void WinMainForked(void) {
savepid = __pid;
savebir = __kbirth;
savetsc = ts;
if (!ReadAll(reader, __data_start, __data_end - __data_start) ||
!ReadAll(reader, __bss_start, __bss_end - __bss_start)) {
ExitProcess(46);
}
ReadAll(reader, __data_start, __data_end - __data_start);
ReadAll(reader, __bss_start, __bss_end - __bss_start);
__pid = savepid;
__kbirth = savebir;
ts = savetsc;
@ -203,21 +181,26 @@ textwindows void WinMainForked(void) {
__prot2nt(maps[i].prot, maps[i].iscow), &oldprot);
}
// we're all done reading!
if (!CloseHandle(reader)) {
ExitProcess(47);
}
// mitosis complete
CloseHandle(reader);
// clean up, restore state, and jump back into function below
#ifdef SYSDEBUG
RemoveVectoredExceptionHandler(oncrash);
#endif
// rewrap the stdin named pipe hack
// since the handles closed on fork
if (weaken(ForkNtStdinWorker)) weaken(ForkNtStdinWorker)();
struct Fds *fds = VEIL("r", &g_fds);
fds->__init_p[0].handle = GetStdHandle(kNtStdInputHandle); // just in case
fds->__init_p[1].handle = GetStdHandle(kNtStdOutputHandle); // just in case
fds->__init_p[2].handle = GetStdHandle(kNtStdErrorHandle); // just in case
// restore the crash reporting stuff
if (weaken(__wincrash_nt)) {
AddVectoredExceptionHandler(1, (void *)weaken(__wincrash_nt));
}
if (weaken(__onntconsoleevent_nt)) {
SetConsoleCtrlHandler(weaken(__onntconsoleevent_nt), 1);
}
// jump back into function below
longjmp(jb, 1);
}
@ -225,23 +208,29 @@ textwindows int sys_fork_nt(void) {
bool ok;
jmp_buf jb;
char **args, **args2;
char16_t pipename[64];
int64_t reader, writer;
int i, n, rc, pid, untrackpid;
int i, n, pid, untrackpid, rc = -1;
char *p, forkvar[6 + 21 + 1 + 21 + 1];
struct NtStartupInfo startinfo;
struct NtProcessInformation procinfo;
if ((pid = untrackpid = __reservefd()) == -1) return -1;
if (!setjmp(jb)) {
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
pid = untrackpid = __reservefd(-1);
reader = CreateNamedPipe(CreatePipeName(pipename),
kNtPipeAccessInbound | kNtFileFlagOverlapped,
kNtPipeTypeMessage | kNtPipeReadmodeMessage, 1,
65536, 65536, 0, &kNtIsInheritable);
writer = CreateFile(pipename, kNtGenericWrite, 0, 0, kNtOpenExisting,
kNtFileFlagOverlapped, 0);
if (pid != -1 && reader != -1 && writer != -1) {
p = stpcpy(forkvar, "_FORK=");
p += uint64toarray_radix10(reader, p), *p++ = ' ';
p += uint64toarray_radix10(writer, p);
p += uint64toarray_radix10(reader, p);
bzero(&startinfo, sizeof(startinfo));
startinfo.cb = sizeof(struct NtStartupInfo);
startinfo.dwFlags = kNtStartfUsestdhandles;
startinfo.hStdInput = g_fds.p[0].handle;
startinfo.hStdOutput = g_fds.p[1].handle;
startinfo.hStdError = g_fds.p[2].handle;
startinfo.hStdInput = __getfdhandleactual(0);
startinfo.hStdOutput = __getfdhandleactual(1);
startinfo.hStdError = __getfdhandleactual(2);
args = __argv;
#ifdef SYSDEBUG
// If --strace was passed to this program, then propagate it the
@ -258,7 +247,6 @@ textwindows int sys_fork_nt(void) {
if (ntspawn(GetProgramExecutableName(), args, environ, forkvar,
&kNtIsInheritable, NULL, true, 0, NULL, &startinfo,
&procinfo) != -1) {
CloseHandle(reader);
CloseHandle(procinfo.hThread);
ok = WriteAll(writer, jb, sizeof(jb)) &&
WriteAll(writer, &_mmi.i, sizeof(_mmi.i)) &&
@ -277,12 +265,10 @@ textwindows int sys_fork_nt(void) {
if (ok) ok = WriteAll(writer, __data_start, __data_end - __data_start);
if (ok) ok = WriteAll(writer, __bss_start, __bss_end - __bss_start);
if (ok) {
if (!CloseHandle(writer)) {
ok = false;
}
if (!CloseHandle(writer)) ok = false;
writer = -1;
}
if (ok) {
// XXX: this should be tracked in a separate data structure
g_fds.p[pid].kind = kFdProcess;
g_fds.p[pid].handle = procinfo.hProcess;
g_fds.p[pid].flags = O_CLOEXEC;
@ -290,19 +276,13 @@ textwindows int sys_fork_nt(void) {
untrackpid = -1;
rc = pid;
} else {
rc = __winerr();
TerminateProcess(procinfo.hProcess, 127);
CloseHandle(procinfo.hProcess);
}
} else {
CloseHandle(writer);
rc = -1;
}
} else {
STRACE("CreatePipe() failed %m");
rc = -1;
CloseHandle(writer);
}
if (reader != -1) CloseHandle(reader);
if (writer != -1) CloseHandle(writer);
} else {
rc = 0;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/internal.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"

View file

@ -19,7 +19,6 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/at.h"

View file

@ -20,7 +20,6 @@
#include "libc/bits/bits.h"
#include "libc/bits/weaken.h"
#include "libc/calls/strace.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/symbols.internal.h"

View file

@ -16,7 +16,6 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/kprintf.h"
#include "libc/log/libfatal.internal.h"
#include "libc/runtime/internal.h"
#include "libc/str/str.h"

View file

@ -25,9 +25,9 @@ void __stack_chk_fail(void) wontreturn relegated;
void __stack_chk_fail_local(void) wontreturn relegated hidden;
void _jmpstack(void *, void *, ...) hidden wontreturn;
long _setstack(void *, void *, ...) hidden;
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t);
Elf64_Ehdr *MapElfRead(const char *, struct MappedFile *) hidden;
int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t) hidden;
int GetDosEnviron(const char16_t *, char *, size_t, char **, size_t);
bool __intercept_flag(int *, char *[], const char *);
COSMOPOLITAN_C_END_

View file

@ -59,6 +59,8 @@ noasan void *mapanon(size_t size) {
/* asan runtime depends on this function */
void *m;
m = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (m == MAP_FAILED && weaken(__oom_hook)) weaken(__oom_hook)(size);
if (m == MAP_FAILED && weaken(__oom_hook)) {
weaken(__oom_hook)(size);
}
return m;
}

View file

@ -66,7 +66,7 @@ int UntrackMemoryIntervals(void *, size_t) hidden;
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
forceinline pureconst bool IsLegalSize(size_t n) {
return n <= 0xffffffffffff;
return n <= 0x7fffffffffff;
}
forceinline pureconst bool IsAutoFrame(int x) {

View file

@ -23,7 +23,7 @@
#define PUTC(C) \
do { \
while (!(inb(0x3F8 + UART_LSR) & UART_TTYTXR)) { \
asm("pause"); \
__builtin_ia32_pause(); \
} \
outb(0x3F8, C); \
} while (0)

View file

@ -26,10 +26,14 @@
#include "libc/errno.h"
#include "libc/intrin/asan.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/log/backtrace.internal.h"
#include "libc/log/libfatal.internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/rand/rand.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/internal.h"
@ -49,13 +53,10 @@
#define FRAME(x) ((int)((intptr_t)(x) >> 16))
static wontreturn void OnUnrecoverableMmapError(const char *s) {
if (IsTiny()) {
unreachable;
} else {
STRACE("%s %m", s);
__restorewintty();
_Exit(199);
}
if (weaken(__die)) weaken(__die)();
STRACE("%s %m", s);
__restorewintty();
_Exit(199);
}
noasan static bool IsMapped(char *p, size_t n) {
@ -101,9 +102,12 @@ noasan static bool Automap(int n, int *res) {
if (*res + n <= FRAME(kAutomapStart + (kAutomapStart - 1))) {
return true;
} else {
STRACE("mmap(%.12p, %p) ENOMEM (automap interval exhausted)", ADDR(*res),
ADDR(n + 1));
return false;
}
} else {
STRACE("mmap(%.12p, %p) ENOMEM (automap failed)", ADDR(*res), ADDR(n + 1));
return false;
}
}
@ -149,12 +153,14 @@ static noasan void *MapMemory(void *addr, size_t size, int prot, int flags,
static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
int prot, int flags,
int fd, int64_t off,
int f, int x, size_t n) {
int f, int x, int n) {
size_t i, m;
int64_t oi, sz;
struct DirectMap dm;
bool iscow, readonlyfile;
size_t i, m = (n - 1) * FRAMESIZE;
assert(m < size && m + FRAMESIZE >= size);
m = (size_t)(n - 1) << 16;
assert(m < size);
assert(m + FRAMESIZE >= size);
oi = fd == -1 ? 0 : off + m;
sz = size - m;
dm = sys_mmap(addr + m, sz, prot, f, fd, oi);
@ -214,42 +220,43 @@ static textwindows dontinline noasan void *MapMemories(char *addr, size_t size,
*/
noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
int64_t off) {
STRACE("mmap(%p, %'zu, %s, %s, %d, %'ld) → ...", addr, size,
DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off);
void *res;
char *p = addr;
struct DirectMap dm;
int a, b, i, f, m, n, x;
if (!IsTiny() && UNLIKELY(!size)) {
if (UNLIKELY(!size)) {
STRACE("size=0");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(!IsLegalSize(size))) {
} else if (UNLIKELY(!IsLegalSize(size))) {
STRACE("size isn't 48-bit");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(!IsLegalPointer(p))) {
} else if (UNLIKELY(!IsLegalPointer(p))) {
STRACE("p isn't 48-bit");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(!ALIGNED(p))) {
} else if (UNLIKELY(!ALIGNED(p))) {
STRACE("p isn't 64kb aligned");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(fd < -1)) {
} else if (UNLIKELY(fd < -1)) {
STRACE("mmap(%.12p, %'zu, fd=%d) EBADF", p, size, fd);
res = VIP(ebadf());
} else if (!IsTiny() && UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
} else if (UNLIKELY(!((fd != -1) ^ !!(flags & MAP_ANONYMOUS)))) {
STRACE("fd anonymous mismatch");
res = VIP(einval());
} else if (!IsTiny() &&
UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
} else if (UNLIKELY(!(!!(flags & MAP_PRIVATE) ^ !!(flags & MAP_SHARED)))) {
STRACE("MAP_SHARED ^ MAP_PRIVATE");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(off < 0)) {
} else if (UNLIKELY(off < 0)) {
STRACE("neg off");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(INT64_MAX - size < off)) {
} else if (UNLIKELY(INT64_MAX - size < off)) {
STRACE("too large");
res = VIP(einval());
} else if (!IsTiny() && UNLIKELY(!ALIGNED(off))) {
} else if (UNLIKELY(!ALIGNED(off))) {
STRACE("p isn't 64kb aligned");
res = VIP(einval());
} else if (!IsTiny() && (flags & MAP_FIXED_NOREPLACE) && IsMapped(p, size)) {
} else if ((flags & MAP_FIXED_NOREPLACE) && IsMapped(p, size)) {
#ifdef SYSDEBUG
if (OverlapsImageSpace(p, size)) {
STRACE("overlaps image");
@ -258,7 +265,7 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
}
#endif
res = VIP(efault());
} else if (!IsTiny() && __isfdkind(fd, kFdZip)) {
} else if (__isfdkind(fd, kFdZip)) {
STRACE("fd is zipos handle");
res = VIP(einval());
} else {
@ -268,7 +275,8 @@ noasan void *mmap(void *addr, size_t size, int prot, int flags, int fd,
prot |= PROT_WRITE; /* kludge */
}
}
n = FRAME(size) + !!(size & (FRAMESIZE - 1));
n = (int)(size >> 16) + !!(size & (FRAMESIZE - 1));
assert(n > 0);
f = (flags & ~MAP_FIXED_NOREPLACE) | MAP_FIXED;
if (flags & MAP_FIXED) {
x = FRAME(p);

View file

@ -32,7 +32,7 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
extern typeof(VirtualProtect) *const __imp_VirtualProtect __msabi;
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
#define ADDR(x) ((char *)((int64_t)((uint64_t)(x) << 32) >> 16))

View file

@ -68,6 +68,10 @@ static bool MustMoveMap(intptr_t y, size_t j) {
* @param q is new address
*/
void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
enosys();
return MAP_FAILED;
#if 0
va_list va;
void *res, *q;
if (f & MREMAP_FIXED) {
@ -83,7 +87,6 @@ void *mremap(void *p, size_t n, size_t m, int f, ... /* void *q */) {
DescribeRemapFlags(f), q, res);
return res;
#if 0
// TODO(jart): perhaps some day?
// probably not a big perf gain at this point :|
size_t i, j, k;

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/nt/files.h"
#include "libc/nt/memory.h"

View file

@ -20,8 +20,15 @@
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/nt/enum/startf.h"
#include "libc/nt/runtime.h"
#include "libc/nt/startupinfo.h"
#include "libc/nt/struct/ldrdatatableentry.h"
#include "libc/nt/struct/startupinfo.h"
#include "libc/nt/struct/teb.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/stack.h"
#include "libc/sock/internal.h"
@ -85,7 +92,7 @@ static const struct AuxiliaryValue *DescribeAuxv(unsigned long x) {
return NULL;
}
textstartup void __printargs(void) {
noasan textstartup void __printargs(void) {
#ifdef SYSDEBUG
int st;
long key;
@ -100,16 +107,19 @@ textstartup void __printargs(void) {
st = __strace;
__strace = 0;
PRINT("");
PRINT("ARGUMENTS (%p)", __argv);
for (i = 0; i < __argc; ++i) {
PRINT(" ☼ %s", __argv[i]);
}
PRINT("");
PRINT("ENVIRONMENT (%p)", __envp);
for (env = __envp; *env; ++env) {
PRINT(" ☼ %s", *env);
}
PRINT("");
PRINT("AUXILIARY (%p)", __auxv);
for (auxp = __auxv; *auxp; auxp += 2) {
if ((auxinfo = DescribeAuxv(auxp[0]))) {
@ -120,19 +130,21 @@ textstartup void __printargs(void) {
}
}
PRINT("");
PRINT("SPECIALS");
PRINT(" ☼ %30s = %#s", "kTmpPath", kTmpPath);
PRINT(" ☼ %30s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
PRINT(" ☼ %30s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
PRINT(" ☼ %30s = %#s", "program_executable_name", GetProgramExecutableName());
PRINT(" ☼ %30s = %#s", "GetInterpreterExecutableName()",
PRINT(" ☼ %s = %#s", "kTmpPath", kTmpPath);
PRINT(" ☼ %s = %#s", "kNtSystemDirectory", kNtSystemDirectory);
PRINT(" ☼ %s = %#s", "kNtWindowsDirectory", kNtWindowsDirectory);
PRINT(" ☼ %s = %#s", "program_executable_name", GetProgramExecutableName());
PRINT(" ☼ %s = %#s", "GetInterpreterExecutableName()",
GetInterpreterExecutableName(path, sizeof(path)));
PRINT(" ☼ %30s = %p", "RSP", __builtin_frame_address(0));
PRINT(" ☼ %30s = %p", "GetStackAddr()", GetStackAddr(0));
PRINT(" ☼ %30s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
PRINT(" ☼ %30s = %p", "GetStackSize()", GetStackSize());
PRINT(" ☼ %s = %p", "RSP", __builtin_frame_address(0));
PRINT(" ☼ %s = %p", "GetStackAddr()", GetStackAddr(0));
PRINT(" ☼ %s = %p", "GetStaticStackAddr(0)", GetStaticStackAddr(0));
PRINT(" ☼ %s = %p", "GetStackSize()", GetStackSize());
if (!IsWindows()) {
PRINT("");
PRINT("OPEN FILE DESCRIPTORS");
for (i = 0; i < ARRAYLEN(pfds); ++i) {
pfds[i].fd = i;
@ -148,6 +160,7 @@ textstartup void __printargs(void) {
}
if (!sigprocmask(SIG_BLOCK, 0, &ss) && (ss.__bits[0] || ss.__bits[1])) {
PRINT("");
PRINT("BLOCKED SIGNALS {%#lx, %#lx}", ss.__bits[0], ss.__bits[1]);
for (i = 0; i < 32; ++i) {
if (ss.__bits[0] & (1u << i)) {
@ -156,6 +169,77 @@ textstartup void __printargs(void) {
}
}
if (IsWindows()) {
struct NtStartupInfo startinfo;
GetStartupInfo(&startinfo);
PRINT("");
PRINT("GETSTARTUPINFO");
if (startinfo.lpDesktop)
PRINT(" ☼ %s = %#!hs", "lpDesktop", startinfo.lpDesktop);
if (startinfo.lpTitle) PRINT(" ☼ %s = %#!hs", "lpTitle", startinfo.lpTitle);
if (startinfo.dwX) PRINT(" ☼ %s = %u", "dwX", startinfo.dwX);
if (startinfo.dwY) PRINT(" ☼ %s = %u", "dwY", startinfo.dwY);
if (startinfo.dwXSize) PRINT(" ☼ %s = %u", "dwXSize", startinfo.dwXSize);
if (startinfo.dwYSize) PRINT(" ☼ %s = %u", "dwYSize", startinfo.dwYSize);
if (startinfo.dwXCountChars)
PRINT(" ☼ %s = %u", "dwXCountChars", startinfo.dwXCountChars);
if (startinfo.dwYCountChars)
PRINT(" ☼ %s = %u", "dwYCountChars", startinfo.dwYCountChars);
if (startinfo.dwFillAttribute)
PRINT(" ☼ %s = %u", "dwFillAttribute", startinfo.dwFillAttribute);
if (startinfo.dwFlags)
PRINT(" ☼ %s = %s", "dwFlags", DescribeNtStartFlags(startinfo.dwFlags));
if (startinfo.wShowWindow)
PRINT(" ☼ %s = %hu", "wShowWindow", startinfo.wShowWindow);
if (startinfo.cbReserved2)
PRINT(" ☼ %s = %hu", "cbReserved2", startinfo.cbReserved2);
if (startinfo.hStdInput)
PRINT(" ☼ %s = %ld", "hStdInput", startinfo.hStdInput);
if (startinfo.hStdOutput)
PRINT(" ☼ %s = %ld", "hStdOutput", startinfo.hStdOutput);
if (startinfo.hStdError)
PRINT(" ☼ %s = %ld", "hStdError", startinfo.hStdError);
PRINT("");
PRINT("STANDARD HANDLES");
PRINT(" ☼ %s = %ld", "GetStdHandle(kNtStdInputHandle)",
GetStdHandle(kNtStdInputHandle));
PRINT(" ☼ %s = %ld", "GetStdHandle(kNtStdOutputHandle)",
GetStdHandle(kNtStdOutputHandle));
PRINT(" ☼ %s = %ld", "GetStdHandle(kNtStdErrorHandle)",
GetStdHandle(kNtStdErrorHandle));
PRINT("");
PRINT("TEB");
PRINT(" ☼ gs:0x%02x %s = %p", 0x00, "NtGetSeh()", _NtGetSeh());
PRINT(" ☼ gs:0x%02x %s = %p", 0x08, "NtGetStackHigh()", _NtGetStackHigh());
PRINT(" ☼ gs:0x%02x %s = %p", 0x10, "NtGetStackLow()", _NtGetStackLow());
PRINT(" ☼ gs:0x%02x %s = %p", 0x18, "_NtGetSubsystemTib()",
_NtGetSubsystemTib());
PRINT(" ☼ gs:0x%02x %s = %p", 0x20, "NtGetFib()", _NtGetFib());
PRINT(" ☼ gs:0x%02x %s = %p", 0x30, "NtGetTeb()", NtGetTeb());
PRINT(" ☼ gs:0x%02x %s = %p", 0x38, "NtGetEnv()", _NtGetEnv());
PRINT(" ☼ gs:0x%02x %s = %p", 0x40, "NtGetPid()", NtGetPid());
PRINT(" ☼ gs:0x%02x %s = %p", 0x48, "NtGetTid()", NtGetTid());
PRINT(" ☼ gs:0x%02x %s = %p", 0x50, "NtGetRpc()", _NtGetRpc());
PRINT(" ☼ gs:0x%02x %s = %p", 0x58, "NtGetTls()", _NtGetTls());
PRINT(" ☼ gs:0x%02x %s = %p", 0x60, "NtGetPeb()", NtGetPeb());
PRINT(" ☼ gs:0x%02x %s = %p", 0x68, "NtGetErr()", NtGetErr());
PRINT("");
PRINT("DEPENDENCIES");
struct NtLinkedList *head = &NtGetPeb()->Ldr->InLoadOrderModuleList;
struct NtLinkedList *ldr = head->Next;
do {
const struct NtLdrDataTableEntry *dll =
(const struct NtLdrDataTableEntry *)ldr;
PRINT(" ☼ %.*!hs\t\t%'zu bytes", dll->FullDllName.Length,
dll->FullDllName.Data, dll->SizeOfImage);
} while ((ldr = ldr->Next) && ldr != head);
}
PRINT("");
__strace = st;
#endif
}

View file

@ -57,6 +57,7 @@ $(LIBC_RUNTIME_A).pkg: \
$(LIBC_RUNTIME_A_OBJS) \
$(foreach x,$(LIBC_RUNTIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/runtime/fork-nt.o \
o/$(MODE)/libc/runtime/printf.o \
o/$(MODE)/libc/runtime/abort-nt.o \
o/$(MODE)/libc/runtime/printmemoryintervals.o \
@ -80,6 +81,7 @@ o/$(MODE)/libc/runtime/stackchkfail.o \
o/$(MODE)/libc/runtime/stackchkfaillocal.o \
o/$(MODE)/libc/runtime/winmain.greg.o: \
OVERRIDE_CFLAGS += \
-ffreestanding \
$(NO_MAGIC)
# must use alloca()
@ -87,9 +89,6 @@ o/$(MODE)/libc/runtime/winmain.greg.o: \
o/$(MODE)/libc/runtime/fork-nt.o: \
OVERRIDE_CPPFLAGS += \
-DSTACK_FRAME_UNLIMITED
o/$(MODE)/libc/runtime/fork-nt.o: \
OVERRIDE_CFLAGS += \
$(NO_MAGIC)
o/$(MODE)/libc/runtime/printf.o \
o/$(MODE)/libc/runtime/memtrack.o \

View file

@ -29,6 +29,7 @@
#include "libc/log/libfatal.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
@ -42,7 +43,10 @@
#include "libc/nt/pedef.internal.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/signals.h"
#include "libc/nt/struct/ntexceptionpointers.h"
#include "libc/nt/struct/teb.h"
#include "libc/nt/synchronization.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/runtime/directmap.internal.h"
#include "libc/runtime/internal.h"
@ -53,9 +57,9 @@
#include "libc/str/utf16.h"
#if IsTiny()
extern typeof(CreateFileMapping) *const __imp_CreateFileMappingW __msabi;
extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx __msabi;
extern typeof(VirtualProtect) *const __imp_VirtualProtect __msabi;
__msabi extern typeof(CreateFileMapping) *const __imp_CreateFileMappingW;
__msabi extern typeof(MapViewOfFileEx) *const __imp_MapViewOfFileEx;
__msabi extern typeof(VirtualProtect) *const __imp_VirtualProtect;
#define CreateFileMapping __imp_CreateFileMappingW
#define MapViewOfFileEx __imp_MapViewOfFileEx
#define VirtualProtect __imp_VirtualProtect
@ -84,6 +88,7 @@ struct WinArgs {
extern int __pid;
extern bool __nomultics;
extern uint32_t __winmainpid;
extern int64_t __wincrashearly;
extern const char kConsoleHandles[3];
static const short kConsoleModes[3] = {
@ -115,8 +120,31 @@ forceinline void MakeLongDoubleLongAgain(void) {
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
}
static noasan textwindows wontreturn noinstrument void WinMainNew(
const char16_t *cmdline) {
__msabi static textwindows int WinCrashEarly(struct NtExceptionPointers *ep) {
uint32_t wrote;
char buf[64], *p = buf;
*p++ = 'c';
*p++ = 'r';
*p++ = 'a';
*p++ = 's';
*p++ = 'h';
*p++ = ' ';
*p++ = '0';
*p++ = 'x';
p = __fixcpy(p, ep->ExceptionRecord->ExceptionCode, 32);
*p++ = ' ';
*p++ = 'r';
*p++ = 'i';
*p++ = 'p';
*p++ = ' ';
p = __fixcpy(p, ep->ContextRecord ? ep->ContextRecord->Rip : -1, 32);
*p++ = '\r';
*p++ = '\n';
WriteFile(GetStdHandle(kNtStdErrorHandle), buf, p - buf, &wrote, 0);
ExitProcess(200);
}
__msabi static textwindows wontreturn void WinMainNew(const char16_t *cmdline) {
bool32 rc;
int64_t h, hand;
uint32_t oldprot;
@ -218,10 +246,8 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(
*
* @param hInstance call GetModuleHandle(NULL) from main if you need it
*/
noasan textwindows noinstrument int64_t WinMain(int64_t hInstance,
int64_t hPrevInstance,
const char *lpCmdLine,
int nCmdShow) {
__msabi textwindows int64_t WinMain(int64_t hInstance, int64_t hPrevInstance,
const char *lpCmdLine, int nCmdShow) {
const char16_t *cmdline;
extern char os asm("__hostos");
extern uint64_t ts asm("kStartTsc");
@ -229,6 +255,7 @@ noasan textwindows noinstrument int64_t WinMain(int64_t hInstance,
ts = rdtsc();
__nomultics = true;
__pid = GetCurrentProcessId();
__wincrashearly = AddVectoredExceptionHandler(1, (void *)WinCrashEarly);
cmdline = GetCommandLine();
#ifdef SYSDEBUG
/* sloppy flag-only check for early initialization */