mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-03 09:48:29 +00:00
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:
parent
233144b19d
commit
933411ba99
266 changed files with 8761 additions and 4344 deletions
|
@ -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))) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue