mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +00:00
Make improvements
- Fix build flakes - Polyfill SIGWINCH on Windows - Fix an execve issue on Windows - Make strerror show more information - Improve cmd.exe setup/teardown on Windows - Support bracketed paste mode in Blinkenlights - Show keyboard shortcuts in Blinkenlights status bar - Fixed copy_file_range() and copyfile() w/ zip filesystem - Size optimize GetDosArgv() to keep life.com 12kb in size - Improve Blinkenlights ability to load weird ELF executables - Fix program_executable_name and add GetInterpreterExecutableName - Make Python in tiny mode fail better if docstrings are requested - Update Python test exclusions in tiny* modes such as tinylinux - Add bulletproof unbreakable kprintf() troubleshooting function - Remove "oldskool" keyword from ape.S for virus scanners - Fix issue that caused backtraces to not print sometimes - Improve Blinkenlights serial uart character i/o - Make clock_gettime() not clobber errno on xnu - Improve sha256 cpuid check for old computers - Integrate some bestline linenoise fixes - Show runit process names better in htop - Remove SIGPIPE from ShowCrashReports() - Make realpath() not clobber errno - Avoid attaching GDB on non-Linux - Improve img.com example
This commit is contained in:
parent
2a938b3eaa
commit
b45d50b690
194 changed files with 4881 additions and 2966 deletions
|
@ -1,42 +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 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/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Handles failure of assert() macro.
|
||||
*/
|
||||
relegated wontreturn void __assert_fail(const char *expr, const char *file,
|
||||
int line) {
|
||||
static bool noreentry;
|
||||
__printf("%s:%d: assert(%s) failed\r\n", file, line, expr);
|
||||
if (cmpxchg(&noreentry, false, true)) {
|
||||
if (weaken(__die)) {
|
||||
weaken(__die)();
|
||||
} else {
|
||||
__printf("can't backtrace b/c `__die` not linked\r\n");
|
||||
}
|
||||
quick_exit(23);
|
||||
}
|
||||
_Exit(24);
|
||||
}
|
|
@ -16,13 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
|
@ -38,18 +32,8 @@
|
|||
* @noreturn
|
||||
*/
|
||||
wontreturn void exit(int exitcode) {
|
||||
const uintptr_t *p;
|
||||
if (weaken(__cxa_finalize)) {
|
||||
weaken(__cxa_finalize)(NULL);
|
||||
}
|
||||
for (p = __fini_array_end; p > __fini_array_start;) {
|
||||
((void (*)(void))(*--p))();
|
||||
}
|
||||
if (SupportsWindows() && __ntconsolemode) {
|
||||
SetConsoleMode(GetStdHandle(pushpop(kNtStdInputHandle)), __ntconsolemode);
|
||||
SetConsoleMode(GetStdHandle(pushpop(kNtStdOutputHandle)),
|
||||
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
}
|
||||
_Exit(exitcode);
|
||||
quick_exit(exitcode);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,14 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/process.h"
|
||||
|
||||
extern int __pid;
|
||||
|
||||
/**
|
||||
* Creates new process.
|
||||
|
@ -29,7 +34,7 @@
|
|||
*/
|
||||
int fork(void) {
|
||||
axdx_t ad;
|
||||
int ax, dx;
|
||||
int ax, dx, parent;
|
||||
if (!IsWindows()) {
|
||||
ad = sys_fork();
|
||||
ax = ad.ax;
|
||||
|
@ -43,7 +48,19 @@ int fork(void) {
|
|||
ax = sys_fork_nt();
|
||||
}
|
||||
if (!ax) {
|
||||
__onfork();
|
||||
if (!IsWindows()) {
|
||||
dx = sys_getpid().ax;
|
||||
} else {
|
||||
dx = GetCurrentProcessId();
|
||||
}
|
||||
parent = __pid;
|
||||
__pid = dx;
|
||||
SYSDEBUG("fork() → 0 (child of %d)", parent);
|
||||
if (weaken(__onfork)) {
|
||||
weaken(__onfork)();
|
||||
}
|
||||
} else {
|
||||
SYSDEBUG("fork() → %d% m", ax);
|
||||
}
|
||||
return ax;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
|
@ -91,9 +92,9 @@ privileged noinstrument noasan noubsan void ftracer(void) {
|
|||
if ((symbol = __get_symbol(g_symbols, frame->addr)) != -1 &&
|
||||
symbol != g_lastsymbol) {
|
||||
g_lastsymbol = symbol;
|
||||
__printf("+ %*s%s %d\r\n", GetNestingLevel(frame) * 2, "",
|
||||
__get_symbol_name(g_symbols, symbol),
|
||||
(long)(unsignedsubtract(stamp, laststamp) / 3.3));
|
||||
kprintf("+ %*s%s %d\r\n", GetNestingLevel(frame) * 2, "",
|
||||
__get_symbol_name(g_symbols, symbol),
|
||||
(long)(unsignedsubtract(stamp, laststamp) / 3.3));
|
||||
laststamp = X86_HAVE(RDTSCP) ? rdtscp(0) : rdtsc();
|
||||
}
|
||||
}
|
||||
|
@ -110,9 +111,9 @@ textstartup void ftrace_install(void) {
|
|||
ftrace_enabled = 1;
|
||||
__hook(ftrace_hook, g_symbols);
|
||||
} else {
|
||||
__printf("error: --ftrace failed to open symbol table\r\n");
|
||||
kprintf("error: --ftrace failed to open symbol table\r\n");
|
||||
}
|
||||
} else {
|
||||
__printf("error: --ftrace needs concomitant .com.dbg binary\r\n");
|
||||
kprintf("error: --ftrace needs concomitant .com.dbg binary\r\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -32,25 +30,23 @@ struct DosArgv {
|
|||
wint_t wc;
|
||||
};
|
||||
|
||||
static textwindows noasan wint_t DecodeDosArgv(const char16_t **s) {
|
||||
textwindows noasan void DecodeDosArgv(int ignore, struct DosArgv *st) {
|
||||
wint_t x, y;
|
||||
for (;;) {
|
||||
if (!(x = *(*s)++)) break;
|
||||
if (IsUtf16Cont(x)) continue;
|
||||
if (IsUcs2(x)) {
|
||||
return x;
|
||||
} else {
|
||||
if ((y = *(*s)++)) {
|
||||
return MergeUtf16(x, y);
|
||||
if (!(x = *st->s++)) break;
|
||||
if (!IsUcs2(x)) {
|
||||
if ((y = *st->s++)) {
|
||||
x = MergeUtf16(x, y);
|
||||
} else {
|
||||
return 0;
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return x;
|
||||
st->wc = x;
|
||||
}
|
||||
|
||||
static textwindows noasan void AppendDosArgv(struct DosArgv *st, wint_t wc) {
|
||||
static textwindows noasan void AppendDosArgv(wint_t wc, struct DosArgv *st) {
|
||||
uint64_t w;
|
||||
w = tpenc(wc);
|
||||
do {
|
||||
|
@ -59,6 +55,16 @@ static textwindows noasan void AppendDosArgv(struct DosArgv *st, wint_t wc) {
|
|||
} while (w >>= 8);
|
||||
}
|
||||
|
||||
static textwindows noasan int Count(int c, struct DosArgv *st) {
|
||||
int ignore, n = 0;
|
||||
asm("" : "=g"(ignore));
|
||||
while (st->wc == c) {
|
||||
DecodeDosArgv(ignore, st);
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes and transcodes Windows NT CLI args, thus avoiding
|
||||
* CommandLineToArgv() schlepping in forty megs of dependencies.
|
||||
|
@ -81,49 +87,60 @@ static textwindows noasan void AppendDosArgv(struct DosArgv *st, wint_t wc) {
|
|||
textwindows noasan int GetDosArgv(const char16_t *cmdline, char *buf,
|
||||
size_t size, char **argv, size_t max) {
|
||||
bool inquote;
|
||||
size_t i, argc, slashes, quotes;
|
||||
struct DosArgv st;
|
||||
st.s = cmdline;
|
||||
st.p = buf;
|
||||
st.pe = buf + size;
|
||||
int i, argc, slashes, quotes, ignore;
|
||||
static struct DosArgv st_;
|
||||
struct DosArgv *st = &st_;
|
||||
asm("" : "=g"(ignore));
|
||||
asm("" : "+r"(st));
|
||||
st->s = cmdline;
|
||||
st->p = buf;
|
||||
st->pe = buf + size;
|
||||
argc = 0;
|
||||
st.wc = DecodeDosArgv(&st.s);
|
||||
while (st.wc) {
|
||||
while (st.wc && (st.wc == ' ' || st.wc == '\t')) {
|
||||
st.wc = DecodeDosArgv(&st.s);
|
||||
DecodeDosArgv(ignore, st);
|
||||
while (st->wc) {
|
||||
while (st->wc && (st->wc == ' ' || st->wc == '\t')) {
|
||||
DecodeDosArgv(ignore, st);
|
||||
}
|
||||
if (!st.wc) break;
|
||||
if (!st->wc) break;
|
||||
if (++argc < max) {
|
||||
argv[argc - 1] = st.p < st.pe ? st.p : NULL;
|
||||
argv[argc - 1] = st->p < st->pe ? st->p : NULL;
|
||||
}
|
||||
inquote = false;
|
||||
while (st.wc) {
|
||||
if (!inquote && (st.wc == ' ' || st.wc == '\t')) break;
|
||||
if (st.wc == '"' || st.wc == '\\') {
|
||||
slashes = 0;
|
||||
quotes = 0;
|
||||
while (st.wc == '\\') st.wc = DecodeDosArgv(&st.s), slashes++;
|
||||
while (st.wc == '"') st.wc = DecodeDosArgv(&st.s), quotes++;
|
||||
while (st->wc) {
|
||||
if (!inquote && (st->wc == ' ' || st->wc == '\t')) break;
|
||||
if (st->wc == '"' || st->wc == '\\') {
|
||||
slashes = Count('\\', st);
|
||||
quotes = Count('"', st);
|
||||
if (!quotes) {
|
||||
while (slashes--) AppendDosArgv(&st, '\\');
|
||||
while (slashes--) {
|
||||
AppendDosArgv('\\', st);
|
||||
}
|
||||
} else {
|
||||
while (slashes >= 2) AppendDosArgv(&st, '\\'), slashes -= 2;
|
||||
if (slashes) AppendDosArgv(&st, '"'), quotes--;
|
||||
while (slashes >= 2) {
|
||||
AppendDosArgv('\\', st);
|
||||
slashes -= 2;
|
||||
}
|
||||
if (slashes) {
|
||||
AppendDosArgv('"', st);
|
||||
quotes--;
|
||||
}
|
||||
if (quotes > 0) {
|
||||
if (!inquote) quotes--;
|
||||
for (i = 3; i <= quotes + 1; i += 3) AppendDosArgv(&st, '"');
|
||||
for (i = 3; i <= quotes + 1; i += 3) {
|
||||
AppendDosArgv('"', st);
|
||||
}
|
||||
inquote = (quotes % 3 == 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
AppendDosArgv(&st, st.wc);
|
||||
st.wc = DecodeDosArgv(&st.s);
|
||||
AppendDosArgv(st->wc, st);
|
||||
DecodeDosArgv(ignore, st);
|
||||
}
|
||||
}
|
||||
AppendDosArgv(&st, '\0');
|
||||
AppendDosArgv('\0', st);
|
||||
}
|
||||
AppendDosArgv(&st, '\0');
|
||||
if (size) buf[min(st.p - buf, size - 1)] = '\0';
|
||||
AppendDosArgv('\0', st);
|
||||
if (size) buf[min(st->p - buf, size - 1)] = '\0';
|
||||
if (max) argv[min(argc, max - 1)] = NULL;
|
||||
return argc;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ static textwindows noasan noinstrument axdx_t Recode16to8(char *dst,
|
|||
wint_t x, y;
|
||||
for (v = r.ax = 0, r.dx = 0;;) {
|
||||
if (!(x = src[r.dx++])) break;
|
||||
if (IsUtf16Cont(x)) continue;
|
||||
if (!IsUcs2(x)) {
|
||||
y = src[r.dx++];
|
||||
x = MergeUtf16(x, y);
|
||||
|
|
|
@ -16,34 +16,68 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#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/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Exits process faster.
|
||||
* Returns path of executable interperter.
|
||||
*
|
||||
* @param exitcode is masked with 255
|
||||
* @noreturn
|
||||
* Unlike `program_executable_name` which is designed to figure out the
|
||||
* absolute path of the first argument passed to `execve()`, what we do
|
||||
* here is probe things like `/proc` and `sysctl()` to figure out if we
|
||||
* were launched by something like `ape-loader`, and then we return its
|
||||
* path. If we can't determine that path, possibly because we're on XNU
|
||||
* or OpenBSD, then we return -1 with an error code.
|
||||
*
|
||||
* @param p receives utf8 output
|
||||
* @param n is byte size of res buffer
|
||||
* @return p on success or null w/ errno if out of buf or error
|
||||
* @see program_invocation_short_name
|
||||
* @see program_invocation_name
|
||||
* @see program_executable_name
|
||||
*/
|
||||
wontreturn void quick_exit(int exitcode) {
|
||||
const uintptr_t *p;
|
||||
if (weaken(fflush)) {
|
||||
weaken(fflush)(0);
|
||||
char *GetInterpreterExecutableName(char *p, size_t n) {
|
||||
int e;
|
||||
size_t m;
|
||||
int cmd[4];
|
||||
ssize_t rc;
|
||||
char *r, *t;
|
||||
e = errno;
|
||||
if (n < 2) {
|
||||
errno = ENAMETOOLONG;
|
||||
} else if (IsWindows()) {
|
||||
if (strlen(program_executable_name) < n) {
|
||||
strcpy(p, program_executable_name);
|
||||
return p;
|
||||
}
|
||||
errno = ENAMETOOLONG;
|
||||
} else if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, n - 1)) > 0) {
|
||||
p[rc] = 0;
|
||||
return p;
|
||||
} else if ((rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, n - 1)) >
|
||||
0) {
|
||||
errno = e;
|
||||
p[n] = 0;
|
||||
return p;
|
||||
} else if (IsFreebsd() || IsNetbsd()) {
|
||||
cmd[0] = 1 /* CTL_KERN */;
|
||||
cmd[1] = 14 /* KERN_PROC */;
|
||||
if (IsFreebsd()) {
|
||||
cmd[2] = 12 /* KERN_PROC_PATHNAME */;
|
||||
} else {
|
||||
cmd[2] = 5 /* KERN_PROC_PATHNAME */;
|
||||
}
|
||||
cmd[3] = -1; /* current process */
|
||||
if (sysctl(cmd, ARRAYLEN(cmd), p, &n, 0, 0) != -1) {
|
||||
errno = e;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
for (p = __fini_array_end; p > __fini_array_start;) {
|
||||
((void (*)(void))(*--p))();
|
||||
}
|
||||
if (SupportsWindows() && __ntconsolemode) {
|
||||
SetConsoleMode(GetStdHandle(pushpop(kNtStdInputHandle)), __ntconsolemode);
|
||||
SetConsoleMode(GetStdHandle(pushpop(kNtStdOutputHandle)),
|
||||
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
}
|
||||
_Exit(exitcode);
|
||||
return 0;
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern uint32_t __ntconsolemode;
|
||||
extern uint32_t __ntconsolemode[2];
|
||||
extern const char v_ntsubsystem[] __attribute__((__weak__));
|
||||
extern const uintptr_t __fini_array_end[] __attribute__((__weak__));
|
||||
extern const uintptr_t __fini_array_start[] __attribute__((__weak__));
|
||||
|
|
|
@ -21,8 +21,9 @@ COSMOPOLITAN_C_START_
|
|||
#define kFixedmapStart _kMem(0x300000000000, 0x000040000000)
|
||||
#define kFixedmapSize \
|
||||
_kMem(0x400000000000 - 0x300000000000, 0x000070000000 - 0x000040000000)
|
||||
#define _kMmi(VSPACE) \
|
||||
ROUNDUP(VSPACE / FRAMESIZE * sizeof(struct MemoryInterval), FRAMESIZE)
|
||||
#define _kMmi(VSPACE) \
|
||||
ROUNDUP(VSPACE / FRAMESIZE * (intptr_t)sizeof(struct MemoryInterval), \
|
||||
FRAMESIZE)
|
||||
#define _kMem(NORMAL, WIN7) \
|
||||
(!(IsWindows() && NtGetVersion() < kNtVersionWindows10) ? NORMAL : WIN7)
|
||||
|
||||
|
@ -35,7 +36,7 @@ struct MemoryInterval {
|
|||
};
|
||||
|
||||
struct MemoryIntervals {
|
||||
long i, n;
|
||||
size_t i, n;
|
||||
struct MemoryInterval *p;
|
||||
struct MemoryInterval s[OPEN_MAX];
|
||||
};
|
||||
|
@ -57,6 +58,10 @@ int UntrackMemoryIntervals(void *, size_t) hidden;
|
|||
#define IsLegalPointer(p) \
|
||||
(-0x800000000000 <= (intptr_t)(p) && (intptr_t)(p) <= 0x7fffffffffff)
|
||||
|
||||
forceinline pureconst bool IsLegalSize(size_t n) {
|
||||
return n <= 0xffffffffffff;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsAutoFrame(int x) {
|
||||
return (kAutomapStart >> 16) <= x &&
|
||||
x <= ((kAutomapStart + (kAutomapSize - 1)) >> 16);
|
||||
|
@ -75,14 +80,26 @@ forceinline pureconst bool IsShadowFrame(int x) {
|
|||
return 0x7fff <= x && x < 0x10008000;
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsKernelFrame(int x) {
|
||||
return (int)(GetStaticStackAddr(0) >> 16) <= x &&
|
||||
x <= (int)((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >>
|
||||
16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsStaticStackFrame(int x) {
|
||||
return (GetStaticStackAddr(0) >> 16) <= x &&
|
||||
x <= ((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16);
|
||||
return (int)(GetStaticStackAddr(0) >> 16) <= x &&
|
||||
x <= (int)((GetStaticStackAddr(0) + (GetStackSize() - FRAMESIZE)) >>
|
||||
16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsStackFrame(int x) {
|
||||
return (int)(GetStackAddr(0) >> 16) <= x &&
|
||||
x <= (int)((GetStackAddr(0) + (GetStackSize() - FRAMESIZE)) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsSigAltStackFrame(int x) {
|
||||
return (GetStackAddr(0) >> 16) <= x &&
|
||||
x <= ((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16);
|
||||
return (int)(GetStackAddr(0) >> 16) <= x &&
|
||||
x <= (int)((GetStackAddr(0) + (SIGSTKSZ - FRAMESIZE)) >> 16);
|
||||
}
|
||||
|
||||
forceinline pureconst bool IsOldStackFrame(int x) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/memtrack.internal.h"
|
||||
|
||||
|
@ -41,20 +41,20 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
|
|||
for (i = 0; i < mm->i; ++i) {
|
||||
frames = mm->p[i].y + 1 - mm->p[i].x;
|
||||
maptally += frames;
|
||||
__printf("%012x-%012x %s %,*dx%s", ADDR(mm->p[i].x), ADDR(mm->p[i].y + 1),
|
||||
DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames,
|
||||
DescribeFrame(mm->p[i].x));
|
||||
kprintf("%012lx-%012lx %s %'*ldx%s", ADDR(mm->p[i].x), ADDR(mm->p[i].y + 1),
|
||||
DescribeMapping(mm->p[i].prot, mm->p[i].flags, mode), w, frames,
|
||||
DescribeFrame(mm->p[i].x));
|
||||
if (i + 1 < _mmi.i) {
|
||||
frames = mm->p[i + 1].x - mm->p[i].y - 1;
|
||||
if (frames && IsNoteworthyHole(i, mm)) {
|
||||
gaptally += frames;
|
||||
__printf(" w/ %,d frame hole", frames);
|
||||
kprintf(" w/ %'ld frame hole", frames);
|
||||
}
|
||||
}
|
||||
if (mm->p[i].h != -1) {
|
||||
__printf(" h=%d", mm->p[i].h);
|
||||
kprintf(" h=%ld", mm->p[i].h);
|
||||
}
|
||||
__printf("\r\n");
|
||||
kprintf("%n");
|
||||
}
|
||||
__printf("# %d frames mapped w/ %,d frames gapped\r\n", maptally, gaptally);
|
||||
kprintf("# %ld frames mapped w/ %'ld frames gapped%n", maptally, gaptally);
|
||||
}
|
||||
|
|
|
@ -1,135 +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 2021 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/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sysdebug.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define SIZE 1024
|
||||
#define CTL_KERN 1
|
||||
#define KERN_PROC 14
|
||||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
#define KERN_PROC_PATHNAME_NETBSD 5
|
||||
|
||||
/**
|
||||
* Absolute path of executable.
|
||||
*
|
||||
* This variable is initialized automatically at startup. The path is
|
||||
* guaranteed to exist, except on XNU and OpenBSD. It may be a symlink.
|
||||
* It may be spoofed.
|
||||
*/
|
||||
char program_executable_name[SIZE];
|
||||
|
||||
static textwindows bool GetNtExePath(char executable[SIZE]) {
|
||||
uint64_t w;
|
||||
wint_t x, y;
|
||||
uint32_t i, j;
|
||||
char16_t path16[PATH_MAX + 1];
|
||||
if (!GetModuleFileName(0, path16, ARRAYLEN(path16))) return 0;
|
||||
for (i = j = 0; (x = path16[i++] & 0xffff);) {
|
||||
if (!IsUcs2(x)) {
|
||||
y = path16[i++] & 0xffff;
|
||||
x = MergeUtf16(x, y);
|
||||
}
|
||||
if (x == '\\') x = '/';
|
||||
w = tpenc(x);
|
||||
do {
|
||||
executable[j] = w;
|
||||
if (++j == SIZE) {
|
||||
return false;
|
||||
}
|
||||
} while ((w >>= 8));
|
||||
}
|
||||
executable[j] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static textstartup void GetProgramExecutableName(char executable[SIZE],
|
||||
char *p) {
|
||||
char *t;
|
||||
size_t m;
|
||||
int cmd[4];
|
||||
ssize_t n = 0;
|
||||
if (IsWindows() && GetNtExePath(executable)) return;
|
||||
if (fileexists(p)) {
|
||||
if (!_isabspath(p)) {
|
||||
if (getcwd(executable, SIZE - 1)) {
|
||||
n = strlen(executable);
|
||||
executable[n++] = '/';
|
||||
}
|
||||
}
|
||||
} else if ((n = sys_readlinkat(AT_FDCWD, "/proc/self/exe", executable,
|
||||
SIZE - 1)) > 0) {
|
||||
executable[n] = 0;
|
||||
return;
|
||||
} else if ((n = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", executable,
|
||||
SIZE - 1)) > 0) {
|
||||
executable[n] = 0;
|
||||
return;
|
||||
} else if (IsFreebsd() || IsNetbsd()) {
|
||||
cmd[0] = CTL_KERN;
|
||||
cmd[1] = KERN_PROC;
|
||||
if (IsFreebsd()) {
|
||||
cmd[2] = KERN_PROC_PATHNAME_FREEBSD;
|
||||
} else {
|
||||
cmd[2] = KERN_PROC_PATHNAME_NETBSD;
|
||||
}
|
||||
cmd[3] = -1;
|
||||
m = SIZE;
|
||||
if (sysctl(cmd, ARRAYLEN(cmd), executable, &m, 0, 0) != -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (n < 0) n = 0;
|
||||
for (; *p; ++p) {
|
||||
if (n + 1 < SIZE) {
|
||||
executable[n++] = *p;
|
||||
}
|
||||
}
|
||||
executable[n] = 0;
|
||||
}
|
||||
|
||||
textstartup void program_executable_name_init(int argc, char **argv,
|
||||
char **envp, intptr_t *auxv) {
|
||||
static bool once;
|
||||
char executable[SIZE];
|
||||
if (!cmpxchg(&once, 0, 1)) return;
|
||||
__stpcpy(program_executable_name, argv[0]);
|
||||
GetProgramExecutableName(executable, argv[0]);
|
||||
__stpcpy(program_executable_name, executable);
|
||||
SYSDEBUG("GetProgramExecutableName() -> %s", program_executable_name);
|
||||
}
|
||||
|
||||
const void *const program_executable_name_init_ctor[] initarray = {
|
||||
program_executable_name_init,
|
||||
};
|
|
@ -97,6 +97,7 @@ int OpenExecutable(void);
|
|||
void ftrace_install(void);
|
||||
long GetResourceLimit(int);
|
||||
long GetMaxFd(void);
|
||||
char *GetInterpreterExecutableName(char *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define COSMOPOLITAN_LIBC_RUNTIME_STACK_H_
|
||||
#include "ape/config.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/version.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
|
@ -27,7 +28,7 @@
|
|||
/**
|
||||
* Tunes APE stack virtual address.
|
||||
*
|
||||
* This defaults to `0x700000000000 - STACKSIZE`. The value defined by
|
||||
* This defaults to `0x7e0000000000 - STACKSIZE`. The value defined by
|
||||
* this macro will be respected, with two exceptions: (1) in MODE=tiny
|
||||
* the operating system provided stack is used instead and (2) Windows
|
||||
* Seven doesn't support 64-bit addresses so 0x10000000 - GetStackSize
|
||||
|
@ -48,7 +49,7 @@
|
|||
#define _STACK_EXTRA ""
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__ELF__)
|
||||
#if defined(__GNUC__) && defined(__ELF__) && !defined(__STRICT_ANSI__)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern char ape_stack_memsz[] __attribute__((__weak__));
|
||||
|
@ -64,18 +65,18 @@ extern char ape_stack_memsz[] __attribute__((__weak__));
|
|||
/**
|
||||
* Returns preferred bottom address of stack.
|
||||
*/
|
||||
#define GetStaticStackAddr(ADDEND) \
|
||||
({ \
|
||||
intptr_t vAddr; \
|
||||
if (!IsWindows() || NtGetVersion() >= kNtVersionWindows10) { \
|
||||
asm(".weak\tape_stack_vaddr\n\t" \
|
||||
"movabs\t%1+ape_stack_vaddr,%0" \
|
||||
: "=r"(vAddr) \
|
||||
: "i"(ADDEND)); \
|
||||
} else { \
|
||||
vAddr = 0x10000000; \
|
||||
} \
|
||||
vAddr; \
|
||||
#define GetStaticStackAddr(ADDEND) \
|
||||
({ \
|
||||
intptr_t vAddr; \
|
||||
if (!IsWindows() || IsAtLeastWindows10()) { \
|
||||
__asm__(".weak\tape_stack_vaddr\n\t" \
|
||||
"movabs\t%1+ape_stack_vaddr,%0" \
|
||||
: "=r"(vAddr) \
|
||||
: "i"(ADDEND)); \
|
||||
} else { \
|
||||
vAddr = 0x10000000; \
|
||||
} \
|
||||
vAddr; \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -22,9 +22,11 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/bsr.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/enum/filemapflags.h"
|
||||
|
@ -66,9 +68,20 @@ struct WinArgs {
|
|||
char envblock[ARG_MAX];
|
||||
};
|
||||
|
||||
uint32_t __ntconsolemode;
|
||||
extern int __pid;
|
||||
extern bool __nomultics;
|
||||
extern const char kConsoleHandles[2];
|
||||
|
||||
static noasan textwindows noinstrument void MakeLongDoubleLongAgain(void) {
|
||||
static const short kConsoleModes[2] = {
|
||||
kNtEnableProcessedInput | kNtEnableLineInput | kNtEnableEchoInput |
|
||||
kNtEnableMouseInput | kNtEnableQuickEditMode | kNtEnableExtendedFlags |
|
||||
kNtEnableAutoPosition | kNtEnableInsertMode |
|
||||
kNtEnableVirtualTerminalInput,
|
||||
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
|
||||
kNtEnableVirtualTerminalProcessing,
|
||||
};
|
||||
|
||||
forceinline void MakeLongDoubleLongAgain(void) {
|
||||
/* 8087 FPU Control Word
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
|
@ -90,29 +103,22 @@ static noasan textwindows wontreturn noinstrument void WinMainNew(void) {
|
|||
int64_t h;
|
||||
int version;
|
||||
int i, count;
|
||||
int64_t inhand;
|
||||
int64_t hand;
|
||||
struct WinArgs *wa;
|
||||
const char16_t *env16;
|
||||
intptr_t stackaddr, allocaddr;
|
||||
size_t allocsize, argsize, stacksize;
|
||||
extern char os asm("__hostos");
|
||||
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
|
||||
version = NtGetPeb()->OSMajorVersion;
|
||||
__oldstack = (intptr_t)__builtin_frame_address(0);
|
||||
if ((intptr_t)v_ntsubsystem == kNtImageSubsystemWindowsCui && version >= 10) {
|
||||
SetConsoleCP(kNtCpUtf8);
|
||||
SetConsoleOutputCP(kNtCpUtf8);
|
||||
inhand = GetStdHandle(pushpop(kNtStdInputHandle));
|
||||
SetEnvironmentVariable(u"TERM", u"xterm-truecolor");
|
||||
GetConsoleMode(inhand, &__ntconsolemode);
|
||||
SetConsoleMode(inhand, kNtEnableProcessedInput | kNtEnableLineInput |
|
||||
kNtEnableEchoInput | kNtEnableMouseInput |
|
||||
kNtEnableQuickEditMode | kNtEnableExtendedFlags |
|
||||
kNtEnableAutoPosition |
|
||||
kNtEnableVirtualTerminalInput);
|
||||
SetConsoleMode(GetStdHandle(pushpop(kNtStdOutputHandle)),
|
||||
kNtEnableProcessedOutput | kNtEnableWrapAtEolOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
for (i = 0; i < 2; ++i) {
|
||||
hand = GetStdHandle(kConsoleHandles[i]);
|
||||
GetConsoleMode(hand, __ntconsolemode + i);
|
||||
SetConsoleMode(hand, kConsoleModes[i]);
|
||||
}
|
||||
}
|
||||
_mmi.p = _mmi.s;
|
||||
_mmi.n = ARRAYLEN(_mmi.s);
|
||||
|
@ -186,6 +192,12 @@ noasan textwindows noinstrument int64_t WinMain(int64_t hInstance,
|
|||
int64_t hPrevInstance,
|
||||
const char *lpCmdLine,
|
||||
int nCmdShow) {
|
||||
extern char os asm("__hostos");
|
||||
extern uint64_t ts asm("kStartTsc");
|
||||
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
|
||||
ts = rdtsc();
|
||||
__nomultics = true;
|
||||
__pid = GetCurrentProcessId();
|
||||
MakeLongDoubleLongAgain();
|
||||
if (weaken(WinSockInit)) weaken(WinSockInit)();
|
||||
if (weaken(WinMainForked)) weaken(WinMainForked)();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue