mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-01 16:58:30 +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
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue