mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-22 10:30:29 +00:00
Make improvements for Actually Portable Emacs
- Get SIGWINCH working again on the New Technology - Correctly handle O_NOFOLLOW in open() on Windows - Implement synthetic umask() functionality on Windows - Do a better job managing file execute access on Windows - Fill in `st_uid` and `st_gid` with username hash on Windows - Munge UNICODE control pictures into control codes on Windows - Do a better job ensuring Windows console settings are restored - Introduce KPRINTF_LOG environment variable to log kprintf to a file
This commit is contained in:
parent
9c7b81ee0f
commit
965516e313
108 changed files with 1126 additions and 807 deletions
|
@ -22,7 +22,7 @@
|
|||
#define ToUpper(c) \
|
||||
(IsWindows() && (c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))
|
||||
|
||||
dontasan struct Env __getenv(char **p, const char *k) {
|
||||
dontasan privileged struct Env __getenv(char **p, const char *k) {
|
||||
char *t;
|
||||
int i, j;
|
||||
for (i = 0; (t = p[i]); ++i) {
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
// __pid_exec is __pid that isn't updated on fork()
|
||||
|
||||
.initbss 301,_init__pid_exec
|
||||
__pid_exec:
|
||||
.quad 0
|
||||
.endobj __pid_exec,globl
|
||||
.previous
|
||||
|
||||
.init.start 301,_init__pid_exec
|
||||
mov __pid(%rip),%rax
|
||||
stosq
|
||||
.init.end 301,_init__pid_exec
|
|
@ -344,7 +344,7 @@ static void __asan_exit(void) {
|
|||
kprintf("your asan runtime needs\n"
|
||||
"\t__static_yoink(\"__die\");\n"
|
||||
"in order to show you backtraces\n");
|
||||
_Exitr(99);
|
||||
_Exit(99);
|
||||
}
|
||||
|
||||
dontdiscard static __asan_die_f *__asan_die(void) {
|
||||
|
@ -1483,7 +1483,7 @@ void __asan_init(int argc, char **argv, char **envp, intptr_t *auxv) {
|
|||
if (!_cmpxchg(&once, false, true)) return;
|
||||
if (IsWindows() && NtGetVersion() < kNtVersionWindows10) {
|
||||
__write_str("error: asan binaries require windows10\r\n");
|
||||
_Exitr(0); /* So `make MODE=dbg test` passes w/ Windows7 */
|
||||
_Exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */
|
||||
}
|
||||
REQUIRE(_mmi);
|
||||
REQUIRE(sys_mmap);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/creationdisposition.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
|
@ -33,30 +35,50 @@ __msabi extern typeof(Sleep) *const __imp_Sleep;
|
|||
/**
|
||||
* Opens file on the New Technology.
|
||||
*
|
||||
* @return handle, or -1 on failure
|
||||
* @return handle, or -1 on failure w/ `errno` set appropriately
|
||||
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
|
||||
*/
|
||||
textwindows int64_t CreateFile(
|
||||
const char16_t *lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode,
|
||||
struct NtSecurityAttributes *opt_lpSecurityAttributes,
|
||||
int dwCreationDisposition, uint32_t dwFlagsAndAttributes,
|
||||
int64_t opt_hTemplateFile) {
|
||||
textwindows int64_t CreateFile(const char16_t *lpFileName, //
|
||||
uint32_t dwDesiredAccess, //
|
||||
uint32_t dwShareMode, //
|
||||
struct NtSecurityAttributes *opt_lpSecurity, //
|
||||
int dwCreationDisposition, //
|
||||
uint32_t dwFlagsAndAttributes, //
|
||||
int64_t opt_hTemplateFile) {
|
||||
int64_t hHandle;
|
||||
uint32_t micros = 1;
|
||||
TryAgain:
|
||||
hHandle = __imp_CreateFileW(lpFileName, dwDesiredAccess, dwShareMode,
|
||||
opt_lpSecurityAttributes, dwCreationDisposition,
|
||||
opt_lpSecurity, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, opt_hTemplateFile);
|
||||
if (hHandle == -1 && __imp_GetLastError() == kNtErrorPipeBusy) {
|
||||
if (micros >= 1024) __imp_Sleep(micros / 1024);
|
||||
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
|
||||
goto TryAgain;
|
||||
if (hHandle == -1) {
|
||||
switch (__imp_GetLastError()) {
|
||||
case kNtErrorPipeBusy:
|
||||
if (micros >= 1024) __imp_Sleep(micros / 1024);
|
||||
if (micros / 1024 < __SIG_POLLING_INTERVAL_MS) micros <<= 1;
|
||||
goto TryAgain;
|
||||
case kNtErrorAccessDenied:
|
||||
// GetNtOpenFlags() always greedily requests execute permissions
|
||||
// because the POSIX flag O_EXEC doesn't mean the same thing. It
|
||||
// seems however this causes the opening of certain files to not
|
||||
// work, possibly due to Windows Defender or some security thing
|
||||
// In that case, we'll cross our fingers the file isn't a binary
|
||||
if ((dwDesiredAccess & kNtGenericExecute) &&
|
||||
(dwCreationDisposition == kNtOpenExisting ||
|
||||
dwCreationDisposition == kNtTruncateExisting)) {
|
||||
dwDesiredAccess &= ~kNtGenericExecute;
|
||||
goto TryAgain;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
__winerr();
|
||||
}
|
||||
if (hHandle == -1) __winerr();
|
||||
NTTRACE("CreateFile(%#hs, %s, %s, %s, %s, %s, %ld) → %ld% m", lpFileName,
|
||||
DescribeNtFileAccessFlags(dwDesiredAccess),
|
||||
DescribeNtFileShareFlags(dwShareMode),
|
||||
DescribeNtSecurityAttributes(opt_lpSecurityAttributes),
|
||||
DescribeNtSecurityAttributes(opt_lpSecurity),
|
||||
DescribeNtCreationDisposition(dwCreationDisposition),
|
||||
DescribeNtFileFlagAttr(dwFlagsAndAttributes), opt_hTemplateFile,
|
||||
hHandle);
|
||||
|
|
|
@ -43,10 +43,12 @@ textwindows int64_t CreateFileMapping(
|
|||
flProtect, dwMaximumSizeHigh,
|
||||
dwMaximumSizeLow, opt_lpName);
|
||||
if (!hHandle) __winerr();
|
||||
#if 1
|
||||
NTTRACE("CreateFileMapping(%ld, %s, %s, %'zu, %#hs) → %ld% m", opt_hFile,
|
||||
DescribeNtSecurityAttributes(opt_lpFileMappingAttributes),
|
||||
DescribeNtPageFlags(flProtect),
|
||||
(uint64_t)dwMaximumSizeHigh << 32 | dwMaximumSizeLow, opt_lpName,
|
||||
hHandle);
|
||||
#endif
|
||||
return hHandle;
|
||||
}
|
||||
|
|
|
@ -120,10 +120,6 @@ const char *(DescribeTermios)(char buf[N], ssize_t rc, struct termios *tio) {
|
|||
append(", .c_lflag=%s",
|
||||
DescribeFlags(b128, 128, kLocal, ARRAYLEN(kLocal), "", tio->c_lflag));
|
||||
|
||||
append(", c_cc[VINTR]=%#o", tio->c_cc[VINTR]);
|
||||
append(", c_cc[VERASE]=%#o", tio->c_cc[VERASE]);
|
||||
append(", c_cc[VWERASE]=%#o", tio->c_cc[VWERASE]);
|
||||
|
||||
append("}");
|
||||
|
||||
return buf;
|
||||
|
|
|
@ -19,31 +19,30 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/directmap.internal.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
#include "libc/nt/enum/pageflags.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/processmemorycounters.h"
|
||||
#include "libc/nt/struct/securityattributes.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
||||
int flags, int fd, int64_t off) {
|
||||
int iscow;
|
||||
int64_t handle;
|
||||
uint32_t oldprot;
|
||||
struct DirectMap dm;
|
||||
struct ProtectNt fl;
|
||||
const struct NtSecurityAttributes *sec;
|
||||
|
||||
int64_t handle;
|
||||
if (flags & MAP_ANONYMOUS) {
|
||||
handle = kNtInvalidHandleValue;
|
||||
} else {
|
||||
handle = g_fds.p[fd].handle;
|
||||
}
|
||||
|
||||
const struct NtSecurityAttributes *sec;
|
||||
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||
sec = 0; // MAP_PRIVATE isn't inherited across fork()
|
||||
} else {
|
||||
|
@ -54,7 +53,8 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
// later using mprotect(). the workaround is to always request execute
|
||||
// and then virtualprotect() it away until we actually need it. please
|
||||
// note that open-nt.c always requests an kNtGenericExecute accessmask
|
||||
iscow = false;
|
||||
int iscow = false;
|
||||
struct ProtectNt fl;
|
||||
if (handle != -1) {
|
||||
if ((flags & MAP_TYPE) != MAP_SHARED) {
|
||||
// windows has cow pages but they can't propagate across fork()
|
||||
|
@ -77,16 +77,43 @@ textwindows struct DirectMap sys_mmap_nt(void *addr, size_t size, int prot,
|
|||
kNtFileMapWrite | kNtFileMapExecute};
|
||||
}
|
||||
|
||||
int e = errno;
|
||||
struct DirectMap dm;
|
||||
TryAgain:
|
||||
if ((dm.maphandle = CreateFileMapping(handle, sec, fl.flags1,
|
||||
(size + off) >> 32, (size + off), 0))) {
|
||||
if ((dm.addr = MapViewOfFileEx(dm.maphandle, fl.flags2, off >> 32, off,
|
||||
size, addr))) {
|
||||
uint32_t oldprot;
|
||||
if (VirtualProtect(addr, size, __prot2nt(prot, iscow), &oldprot)) {
|
||||
return dm;
|
||||
}
|
||||
UnmapViewOfFile(dm.addr);
|
||||
}
|
||||
CloseHandle(dm.maphandle);
|
||||
} else if (!(prot & PROT_EXEC) && //
|
||||
(fl.flags2 & kNtFileMapExecute) && //
|
||||
GetLastError() == kNtErrorAccessDenied) {
|
||||
// your file needs to have been O_CREAT'd with exec `mode` bits in
|
||||
// order to be mapped with executable permission. we always try to
|
||||
// get execute permission if the kernel will give it to us because
|
||||
// win32 would otherwise forbid mprotect() from elevating later on
|
||||
fl.flags2 &= ~kNtFileMapExecute;
|
||||
switch (fl.flags1) {
|
||||
case kNtPageExecuteWritecopy:
|
||||
fl.flags1 = kNtPageWritecopy;
|
||||
break;
|
||||
case kNtPageExecuteReadwrite:
|
||||
fl.flags1 = kNtPageReadwrite;
|
||||
break;
|
||||
case kNtPageExecuteRead:
|
||||
fl.flags1 = kNtPageReadonly;
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
errno = e;
|
||||
goto TryAgain;
|
||||
}
|
||||
|
||||
dm.maphandle = kNtInvalidHandleValue;
|
||||
|
|
|
@ -19,29 +19,30 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/intrin/promises.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nexgen32e/vendor.internal.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
|
||||
/**
|
||||
* Terminates process, ignoring destructors and atexit() handlers.
|
||||
*
|
||||
* When running on bare metal, this function will reboot your computer
|
||||
* by hosing the interrupt descriptors and triple faulting the system.
|
||||
*
|
||||
* Exit codes are narrowed to an unsigned char on most platforms. The
|
||||
* exceptions would be Windows, NetBSD, and OpenBSD, which should let
|
||||
* you have larger exit codes.
|
||||
*
|
||||
* When running on bare metal, this function will reboot your computer
|
||||
* by hosing the interrupt descriptors and triple faulting the system.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @threadsafe
|
||||
* @vforksafe
|
||||
* @noreturn
|
||||
*/
|
||||
wontreturn void _Exit(int exitcode) {
|
||||
int i;
|
||||
STRACE("_Exit(%d)", exitcode);
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
// On Linux _Exit1 (exit) must be called in pledge("") mode. If we
|
||||
|
@ -84,19 +85,24 @@ wontreturn void _Exit(int exitcode) {
|
|||
#endif
|
||||
} else if (IsWindows()) {
|
||||
uint32_t waitstatus;
|
||||
// Restoring the CMD.EXE program to its original state is critical.
|
||||
if (_weaken(__restore_console_win32)) {
|
||||
_weaken(__restore_console_win32)();
|
||||
}
|
||||
// What Microsoft calls an exit code, POSIX calls a status code. See
|
||||
// also the WEXITSTATUS() and WIFEXITED() macros that POSIX defines.
|
||||
waitstatus = exitcode;
|
||||
waitstatus <<= 8;
|
||||
// "The GetExitCodeProcess function returns a valid error code
|
||||
// defined by the application only after the thread terminates.
|
||||
// Therefore, an application should not use kNtStillActive (259) as
|
||||
// an error code (kNtStillActive is a macro for kNtStatusPending).
|
||||
// If a thread returns kNtStillActive (259) as an error code, then
|
||||
// applications that test for that value could interpret it to mean
|
||||
// that the thread is still running, and continue to test for the
|
||||
// completion of the thread after the thread has terminated, which
|
||||
// could put the application into an infinite loop." -Quoth MSDN
|
||||
if (waitstatus == kNtStillActive) {
|
||||
// The GetExitCodeProcess function returns a valid error code
|
||||
// defined by the application only after the thread terminates.
|
||||
// Therefore, an application should not use STILL_ACTIVE (259) as
|
||||
// an error code (STILL_ACTIVE is a macro for STATUS_PENDING
|
||||
// (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as an
|
||||
// error code, then applications that test for that value could
|
||||
// interpret it to mean that the thread is still running, and
|
||||
// continue to test for the completion of the thread after the
|
||||
// thread has terminated, which could put the application into an
|
||||
// infinite loop. -Quoth MSDN (see also libc/calls/wait4-nt.c)
|
||||
waitstatus = 0xc9af3d51u;
|
||||
}
|
||||
ExitProcess(waitstatus);
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
wontreturn void _Exitr(int exitcode) {
|
||||
#if SupportsWindows()
|
||||
_restorewintty();
|
||||
#endif
|
||||
_Exit(exitcode);
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "ape/sections.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
@ -30,20 +29,29 @@
|
|||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/asancodes.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/getenv.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
#include "libc/intrin/nomultics.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/uart.internal.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/filesharemode.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
|
@ -57,8 +65,13 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/str/tab.internal.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "libc/thread/tls2.h"
|
||||
|
@ -107,6 +120,17 @@
|
|||
break; \
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
__msabi extern typeof(CreateFile) *const __imp_CreateFileW;
|
||||
__msabi extern typeof(DuplicateHandle) *const __imp_DuplicateHandle;
|
||||
__msabi extern typeof(GetCurrentProcess) *const __imp_GetCurrentProcess;
|
||||
__msabi extern typeof(GetEnvironmentVariable) *const __imp_GetEnvironmentVariableW;
|
||||
__msabi extern typeof(GetLastError) *const __imp_GetLastError;
|
||||
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
|
||||
__msabi extern typeof(SetLastError) *const __imp_SetLastError;
|
||||
__msabi extern typeof(WriteFile) *const __imp_WriteFile;
|
||||
// clang-format on
|
||||
|
||||
long __klog_handle;
|
||||
extern struct SymbolTable *__symtab;
|
||||
|
||||
|
@ -188,24 +212,180 @@ privileged bool kisdangerous(const void *p) {
|
|||
if (IsStackFrame(frame)) return false;
|
||||
if (kismapped(frame)) return false;
|
||||
}
|
||||
if (GetStackAddr() + 16384 <= (uintptr_t)p &&
|
||||
if (GetStackAddr() + GetGuardSize() <= (uintptr_t)p &&
|
||||
(uintptr_t)p < GetStackAddr() + GetStackSize()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
privileged static long kloghandle(void) {
|
||||
if (__klog_handle) {
|
||||
return __klog_handle;
|
||||
} else if (!IsWindows()) {
|
||||
return 2;
|
||||
} else {
|
||||
return __imp_GetStdHandle(kNtStdErrorHandle);
|
||||
}
|
||||
privileged static void klogclose(long fd) {
|
||||
#ifdef __x86_64__
|
||||
long ax = __NR_close;
|
||||
asm volatile("syscall"
|
||||
: "+a"(ax), "+D"(fd)
|
||||
: /* inputs already specified */
|
||||
: "rsi", "rdx", "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
#elif defined(__aarch64__)
|
||||
register long x0 asm("x0") = fd;
|
||||
register int x8 asm("x8") = __NR_close;
|
||||
register int x16 asm("x16") = __NR_close;
|
||||
asm volatile("svc\t0" : "+r"(x0) : "r"(x8), "r"(x16) : "x9", "memory");
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
}
|
||||
|
||||
privileged void _klog(const char *b, size_t n) {
|
||||
privileged static long klogfcntl(long fd, long cmd, long arg) {
|
||||
#ifdef __x86_64__
|
||||
char cf;
|
||||
long ax = __NR_fcntl;
|
||||
asm volatile("clc\n\tsyscall"
|
||||
: CFLAG_CONSTRAINT(cf), "+a"(ax), "+D"(fd), "+S"(cmd), "+d"(arg)
|
||||
: /* inputs already specified */
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||
if (cf) ax = -ax;
|
||||
return ax;
|
||||
#elif defined(__aarch64__)
|
||||
register long x0 asm("x0") = fd;
|
||||
register long x1 asm("x1") = cmd;
|
||||
register long x2 asm("x2") = arg;
|
||||
register int x8 asm("x8") = __NR_fcntl;
|
||||
register int x16 asm("x16") = __NR_fcntl;
|
||||
asm volatile("mov\tx9,0\n\t" // clear carry flag
|
||||
"adds\tx9,x9,0\n\t" // clear carry flag
|
||||
"svc\t0\n\t"
|
||||
"bcs\t1f\n\t"
|
||||
"b\t2f\n1:\t"
|
||||
"neg\tx0,x0\n2:"
|
||||
: "+r"(x0)
|
||||
: "r"(x1), "r"(x2), "r"(x8), "r"(x16)
|
||||
: "x9", "memory");
|
||||
return x0;
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
}
|
||||
|
||||
privileged static long klogopen(const char *path) {
|
||||
long dirfd = AT_FDCWD;
|
||||
long flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
long mode = 0600;
|
||||
#ifdef __x86_64__
|
||||
char cf;
|
||||
long ax = __NR_openat;
|
||||
register long r10 asm("r10") = mode;
|
||||
asm volatile(CFLAG_ASM("clc\n\tsyscall")
|
||||
: CFLAG_CONSTRAINT(cf), "+a"(ax), "+D"(dirfd), "+S"(path),
|
||||
"+d"(flags), "+r"(r10)
|
||||
: /* inputs already specified */
|
||||
: "rcx", "r8", "r9", "r11", "memory");
|
||||
if (cf) ax = -ax;
|
||||
return ax;
|
||||
#elif defined(__aarch64__)
|
||||
register long x0 asm("x0") = dirfd;
|
||||
register long x1 asm("x1") = (long)path;
|
||||
register long x2 asm("x2") = flags;
|
||||
register long x3 asm("x3") = mode;
|
||||
register int x8 asm("x8") = __NR_openat;
|
||||
register int x16 asm("x16") = __NR_openat;
|
||||
asm volatile("mov\tx9,0\n\t" // clear carry flag
|
||||
"adds\tx9,x9,0\n\t" // clear carry flag
|
||||
"svc\t0\n\t"
|
||||
"bcs\t1f\n\t"
|
||||
"b\t2f\n1:\t"
|
||||
"neg\tx0,x0\n2:"
|
||||
: "+r"(x0)
|
||||
: "r"(x1), "r"(x2), "r"(x3), "r"(x8), "r"(x16)
|
||||
: "x9", "memory");
|
||||
return x0;
|
||||
#else
|
||||
#error "unsupported architecture"
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns log handle or -1 if logging shouldn't happen
|
||||
privileged long kloghandle(void) {
|
||||
// kprintf() needs to own a file descriptor in case apps closes stderr
|
||||
// our close() and dup() implementations will trigger this initializer
|
||||
// to minimize a chance that the user accidentally closes their logger
|
||||
// while at the same time, avoiding a mandatory initialization syscall
|
||||
if (!__klog_handle) {
|
||||
long hand;
|
||||
// setting KPRINTF_LOG="/tmp/foo.log" will override stderr
|
||||
// setting KPRINTF_LOG="INTEGER" logs to a file descriptor
|
||||
// setting KPRINTF_LOG="" shall disable kprintf altogether
|
||||
if (IsMetal()) {
|
||||
hand = STDERR_FILENO;
|
||||
} else if (IsWindows()) {
|
||||
uint32_t e, n;
|
||||
const char16_t path[512];
|
||||
e = __imp_GetLastError();
|
||||
n = __imp_GetEnvironmentVariableW(u"KPRINTF_LOG", path, 512);
|
||||
if (!n && __imp_GetLastError() == kNtErrorEnvvarNotFound) {
|
||||
long proc;
|
||||
proc = __imp_GetCurrentProcess();
|
||||
hand = __imp_GetStdHandle(kNtStdErrorHandle);
|
||||
__imp_DuplicateHandle(proc, hand, proc, &hand, 0, true,
|
||||
kNtDuplicateSameAccess);
|
||||
} else if (n && n < 512) {
|
||||
hand = __imp_CreateFileW(
|
||||
path, kNtGenericWrite | kNtFileAppendData,
|
||||
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete,
|
||||
&kNtIsInheritable, kNtOpenAlways, kNtFileAttributeNormal, 0);
|
||||
} else {
|
||||
hand = -1; // KPRINTF_LOG was empty string or too long
|
||||
}
|
||||
__imp_SetLastError(e);
|
||||
} else {
|
||||
long fd, fd2;
|
||||
bool closefd;
|
||||
const char *path;
|
||||
if (!__NR_write || !__envp) {
|
||||
// it's too early in the initialization process for kprintf
|
||||
return -1;
|
||||
}
|
||||
path = __getenv(__envp, "KPRINTF_LOG").s;
|
||||
closefd = false;
|
||||
if (!path) {
|
||||
fd = STDERR_FILENO;
|
||||
} else if (*path) {
|
||||
const char *p;
|
||||
for (fd = 0, p = path; *p; ++p) {
|
||||
if ('0' <= *p && *p <= '9') {
|
||||
fd *= 10;
|
||||
fd += *p - '0';
|
||||
} else {
|
||||
fd = klogopen(path);
|
||||
closefd = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fd = -1;
|
||||
}
|
||||
if (fd >= 0) {
|
||||
// avoid interfering with hard-coded assumptions about fds
|
||||
if ((fd2 = klogfcntl(fd, F_DUPFD, 100)) >= 0) {
|
||||
klogfcntl(fd2, F_SETFD, FD_CLOEXEC);
|
||||
if (closefd) {
|
||||
klogclose(fd);
|
||||
}
|
||||
} else {
|
||||
// RLIMIT_NOFILE was probably too low for safe duplicate
|
||||
fd2 = fd;
|
||||
}
|
||||
} else {
|
||||
fd2 = -1;
|
||||
}
|
||||
hand = fd2;
|
||||
}
|
||||
__klog_handle = hand;
|
||||
}
|
||||
return __klog_handle;
|
||||
}
|
||||
|
||||
privileged void klog(const char *b, size_t n) {
|
||||
#ifdef __x86_64__
|
||||
int e;
|
||||
long h;
|
||||
|
@ -215,7 +395,9 @@ privileged void _klog(const char *b, size_t n) {
|
|||
uint32_t wrote;
|
||||
unsigned char al;
|
||||
long rax, rdi, rsi, rdx;
|
||||
h = kloghandle();
|
||||
if ((h = kloghandle()) == -1) {
|
||||
return;
|
||||
}
|
||||
if (IsWindows()) {
|
||||
e = __imp_GetLastError();
|
||||
__imp_WriteFile(h, b, n, &wrote, 0);
|
||||
|
@ -243,7 +425,7 @@ privileged void _klog(const char *b, size_t n) {
|
|||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
register long r0 asm("x0") = (long)kloghandle();
|
||||
register long r0 asm("x0") = kloghandle();
|
||||
register long r1 asm("x1") = (long)b;
|
||||
register long r2 asm("x2") = (long)n;
|
||||
register long r8 asm("x8") = (long)__NR_write;
|
||||
|
@ -262,7 +444,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
va_list va) {
|
||||
int si, y;
|
||||
wint_t t, u;
|
||||
char errnum[12];
|
||||
const char *abet;
|
||||
signed char type;
|
||||
const char *s, *f;
|
||||
|
@ -545,11 +726,16 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt,
|
|||
break;
|
||||
} else {
|
||||
type = 0;
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
strerror_r(e, z, sizeof(z));
|
||||
s = z;
|
||||
#else
|
||||
s = _strerrno(e);
|
||||
if (!s) {
|
||||
FormatInt32(errnum, e);
|
||||
s = errnum;
|
||||
FormatInt32(z, e);
|
||||
s = z;
|
||||
}
|
||||
#endif
|
||||
goto FormatString;
|
||||
}
|
||||
}
|
||||
|
@ -851,7 +1037,7 @@ privileged void kvprintf(const char *fmt, va_list v) {
|
|||
size_t n;
|
||||
char b[4000];
|
||||
n = kformat(b, sizeof(b), fmt, v);
|
||||
_klog(b, MIN(n, sizeof(b) - 1));
|
||||
klog(b, MIN(n, sizeof(b) - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -926,9 +1112,9 @@ privileged void kvprintf(const char *fmt, va_list v) {
|
|||
* @vforksafe
|
||||
*/
|
||||
privileged void kprintf(const char *fmt, ...) {
|
||||
/* system call support runtime depends on this function */
|
||||
/* function tracing runtime depends on this function */
|
||||
/* asan runtime depends on this function */
|
||||
// system call support runtime depends on this function
|
||||
// function tracing runtime depends on this function
|
||||
// asan runtime depends on this function
|
||||
va_list v;
|
||||
va_start(v, fmt);
|
||||
kvprintf(fmt, v);
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
#define COSMOPOLITAN_LIBC_INTRIN_KPRINTF_H_
|
||||
#ifdef _COSMO_SOURCE
|
||||
|
||||
#define klog __klog
|
||||
#define kprintf __kprintf
|
||||
#define ksnprintf __ksnprintf
|
||||
#define kvprintf __kvprintf
|
||||
#define kvsnprintf __kvsnprintf
|
||||
#define kloghandle __kloghandle
|
||||
#define kisdangerous __kisdangerous
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
@ -21,8 +23,10 @@ void kprintf(const char *, ...);
|
|||
size_t ksnprintf(char *, size_t, const char *, ...);
|
||||
void kvprintf(const char *, va_list);
|
||||
size_t kvsnprintf(char *, size_t, const char *, va_list);
|
||||
|
||||
bool kisdangerous(const void *);
|
||||
void _klog(const char *, size_t);
|
||||
void klog(const char *, size_t);
|
||||
long kloghandle(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
wontreturn void quick_exit(int exitcode) {
|
||||
const uintptr_t *p;
|
||||
STRACE("quick_exit(%d)", exitcode);
|
||||
_restorewintty();
|
||||
if (_weaken(fflush)) {
|
||||
_weaken(fflush)(0);
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
||||
__msabi extern typeof(GetCurrentProcessId) *const __imp_GetCurrentProcessId;
|
||||
__msabi extern typeof(SetConsoleMode) *const __imp_SetConsoleMode;
|
||||
__msabi extern typeof(GetStdHandle) *const __imp_GetStdHandle;
|
||||
|
||||
extern uint32_t __pid_exec;
|
||||
|
||||
const signed char kNtConsoleHandles[3] = {
|
||||
(signed char)kNtStdInputHandle,
|
||||
(signed char)kNtStdOutputHandle,
|
||||
(signed char)kNtStdErrorHandle,
|
||||
};
|
||||
|
||||
// Puts cmd.exe gui back the way it was.
|
||||
void _restorewintty(void) {
|
||||
int i;
|
||||
if (!IsWindows()) return;
|
||||
if (__imp_GetCurrentProcessId() != __pid_exec) return;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
__imp_SetConsoleMode(__imp_GetStdHandle(kNtConsoleHandles[i]),
|
||||
__ntconsolemode[i]);
|
||||
}
|
||||
}
|
|
@ -16,9 +16,17 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define ShouldUseMsabiAttribute() 1
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/thunk/msabi.h"
|
||||
#include "libc/str/str.h"
|
||||
// clang-format off
|
||||
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
dontasan dontubsan privileged
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts errno value to string.
|
||||
|
@ -27,6 +35,6 @@
|
|||
* @return 0 on success, or error code
|
||||
*/
|
||||
int strerror_r(int err, char *buf, size_t size) {
|
||||
int winerr = IsWindows() ? GetLastError() : 0;
|
||||
int winerr = IsWindows() ? __imp_GetLastError() : 0;
|
||||
return strerror_wr(err, winerr, buf, size);
|
||||
}
|
||||
|
|
|
@ -21,11 +21,17 @@
|
|||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/formatmessageflags.h"
|
||||
#include "libc/nt/enum/lang.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/str/str.h"
|
||||
// clang-format off
|
||||
|
||||
#if defined(SYSDEBUG) && _NTTRACE
|
||||
dontasan dontubsan privileged
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Converts errno value to string with explicit windows errno too.
|
||||
|
@ -53,7 +59,7 @@ int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
|
|||
for (; (c = *sym++); --size)
|
||||
if (size > 1) *buf++ = c;
|
||||
if (size) *buf = 0;
|
||||
} else if (!IsWindows() || ((err == winerr || !winerr) && !wanting)) {
|
||||
} else if (!IsWindows() /* || ((err == winerr || !winerr) && !wanting) */) {
|
||||
ksnprintf(buf, size, "%s/%d/%s", sym, err, msg);
|
||||
} else {
|
||||
if ((n = __imp_FormatMessageW(
|
||||
|
|
|
@ -206,7 +206,7 @@ static void __ubsan_exit(void) {
|
|||
kprintf("your ubsan runtime needs\n"
|
||||
"\t__static_yoink(\"__die\");\n"
|
||||
"in order to show you backtraces\n");
|
||||
_Exitr(99);
|
||||
_Exit(99);
|
||||
}
|
||||
|
||||
static char *__ubsan_stpcpy(char *d, const char *s) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/internal.h"
|
||||
|
||||
uint32_t __ntconsolemode[3];
|
||||
atomic_int __umask;
|
Loading…
Add table
Add a link
Reference in a new issue