mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
Improve quality of raise(), abort(), and tkill()
This change fixes a nasty bug where SIG_IGN and SIG_DFL weren't working as advertised on BSDs. This change also fixes the tkill() definition on MacOS so it maps to __pthread_kill().
This commit is contained in:
parent
c5659b93f8
commit
c5c4dfcd21
12 changed files with 293 additions and 63 deletions
|
@ -109,7 +109,7 @@ o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/as
|
|||
# May be specified in your ~/.cosmo.mk file. You can also use this to
|
||||
# enable things like function tracing. For example:
|
||||
#
|
||||
# TESTARGS = --ftrace
|
||||
# TESTARGS = ----ftrace
|
||||
# .PLEDGE += prot_exec
|
||||
#
|
||||
# You could then run a command like:
|
||||
|
|
|
@ -17,32 +17,45 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/getconsolectrlevent.internal.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/syscall_support-nt.internal.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/threaded.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/thread/xnu.internal.h"
|
||||
|
||||
static textwindows inline bool HasWorkingConsole(void) {
|
||||
return !!(__ntconsolemode[0] | __ntconsolemode[1] | __ntconsolemode[2]);
|
||||
}
|
||||
|
||||
static noubsan void RaiseSigFpe(void) {
|
||||
volatile int x = 0;
|
||||
x = 1 / x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends signal to this thread.
|
||||
* Sends signal to self.
|
||||
*
|
||||
* This is basically the same as:
|
||||
*
|
||||
* tkill(gettid(), sig);
|
||||
*
|
||||
* Note `SIG_DFL` still results in process death for most signals.
|
||||
*
|
||||
* This function is not entirely equivalent to kill() or tkill(). For
|
||||
* example, we raise `SIGTRAP` and `SIGFPE` the natural way, since that
|
||||
* helps us support Windows. So if the raised signal has a signal
|
||||
* handler, then the reported `si_code` might not be `SI_TKILL`.
|
||||
*
|
||||
* On Windows, if a signal results in the termination of the process
|
||||
* then we use the convention `_Exit(128 + sig)` to notify the parent of
|
||||
* the signal number.
|
||||
*
|
||||
* @param sig can be SIGALRM, SIGINT, SIGTERM, SIGKILL, etc.
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @return 0 if signal was delivered and returned, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int raise(int sig) {
|
||||
|
@ -52,28 +65,12 @@ int raise(int sig) {
|
|||
DebugBreak();
|
||||
rc = 0;
|
||||
} else if (sig == SIGFPE) {
|
||||
volatile int x = 0;
|
||||
x = 1 / x;
|
||||
RaiseSigFpe();
|
||||
rc = 0;
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_tkill(gettid(), sig, 0);
|
||||
} else {
|
||||
if (HasWorkingConsole() && (event = GetConsoleCtrlEvent(sig)) != -1) {
|
||||
// XXX: MSDN says "If this parameter is zero, the signal is
|
||||
// generated in all processes that share the console of the
|
||||
// calling process." which seems to imply multiple process
|
||||
// groups potentially. We just shouldn't use this because it
|
||||
// doesn't make any sense and it's so evil.
|
||||
if (GenerateConsoleCtrlEvent(event, 0)) {
|
||||
SleepEx(100, true);
|
||||
__sig_check(false);
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = __winerr();
|
||||
}
|
||||
} else {
|
||||
rc = __sig_raise(sig, SI_USER);
|
||||
}
|
||||
rc = __sig_raise(sig, SI_TKILL);
|
||||
}
|
||||
STRACE("...raise(%G) → %d% m", sig, rc);
|
||||
return rc;
|
||||
|
|
|
@ -182,8 +182,11 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
ap = ©
|
||||
if (IsXnu()) {
|
||||
ap->sa_restorer = (void *)&__sigenter_xnu;
|
||||
ap->sa_handler = (void *)&__sigenter_xnu;
|
||||
|
||||
if (rva < kSigactionMinRva) {
|
||||
ap->sa_sigaction = (void *)(intptr_t)rva;
|
||||
} else {
|
||||
ap->sa_sigaction = (void *)&__sigenter_xnu;
|
||||
}
|
||||
// mitigate Rosetta signal handling strangeness
|
||||
// https://github.com/jart/cosmopolitan/issues/455
|
||||
ap->sa_flags |= SA_SIGINFO;
|
||||
|
@ -193,11 +196,23 @@ static int __sigaction(int sig, const struct sigaction *act,
|
|||
ap->sa_restorer = &__restore_rt;
|
||||
}
|
||||
} else if (IsNetbsd()) {
|
||||
if (rva < kSigactionMinRva) {
|
||||
ap->sa_sigaction = (void *)(intptr_t)rva;
|
||||
} else {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_netbsd;
|
||||
}
|
||||
} else if (IsFreebsd()) {
|
||||
if (rva < kSigactionMinRva) {
|
||||
ap->sa_sigaction = (void *)(intptr_t)rva;
|
||||
} else {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_freebsd;
|
||||
}
|
||||
} else if (IsOpenbsd()) {
|
||||
if (rva < kSigactionMinRva) {
|
||||
ap->sa_sigaction = (void *)(intptr_t)rva;
|
||||
} else {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_openbsd;
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
|
|
|
@ -17,30 +17,29 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
/**
|
||||
* Terminates program abnormally.
|
||||
*
|
||||
* This function first tries to trigger your SIGABRT handler. If
|
||||
* there isn't one or execution resumes, then abort() terminates
|
||||
* the program using an escalating variety methods of increasing
|
||||
* brutality.
|
||||
* This function first tries to trigger your SIGABRT handler. If the
|
||||
* signal handler returns, then `signal(SIGABRT, SIG_DFL)` is called
|
||||
* before SIGABRT is raised again.
|
||||
*
|
||||
* @asyncsignalsafe
|
||||
* @noreturn
|
||||
*/
|
||||
privileged void abort(void) {
|
||||
sigset_t sm;
|
||||
sigfillset(&sm);
|
||||
sigdelset(&sm, SIGABRT);
|
||||
sigprocmask(SIG_SETMASK, &sm, 0);
|
||||
wontreturn void abort(void) {
|
||||
sigset_t m;
|
||||
sigemptyset(&m);
|
||||
sigaddset(&m, SIGABRT);
|
||||
sigprocmask(SIG_UNBLOCK, &m, 0);
|
||||
raise(SIGABRT);
|
||||
__restorewintty();
|
||||
_Exit(128 + SIGABRT);
|
||||
signal(SIGABRT, SIG_DFL);
|
||||
raise(SIGABRT);
|
||||
asm("hlt");
|
||||
unreachable;
|
||||
}
|
|
@ -65,7 +65,7 @@ void _exit(int) libcesque wontreturn;
|
|||
void _Exit(int) libcesque wontreturn;
|
||||
void _Exit1(int) libcesque wontreturn;
|
||||
void quick_exit(int) wontreturn;
|
||||
void abort(void) wontreturn noinstrument;
|
||||
void abort(void) wontreturn;
|
||||
int __cxa_atexit(void *, void *, void *) libcesque;
|
||||
int atfork(void *, void *) libcesque;
|
||||
int atexit(void (*)(void)) libcesque;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_tkill,0x13e0771b121690c8,globl,hidden
|
||||
.scall sys_tkill,0x13e0771b121480c8,globl,hidden
|
||||
|
|
|
@ -533,7 +533,7 @@ syscon sicode SI_TKILL -6 0x80000000 0x010007 -1 -5 -6 # sent by tk
|
|||
syscon sicode SI_MESGQ -3 0x010005 0x010005 0x80000000 -4 -3 # sent by mq_notify(2); lool
|
||||
syscon sicode SI_ASYNCIO -4 0x010004 0x010004 0x80000000 -3 -4 # aio completion; no thank you
|
||||
syscon sicode SI_ASYNCNL -60 0x80000000 0x80000000 0x80000000 0x80000000 0x80000000 # aio completion for dns; the horror
|
||||
syscon sicode SI_KERNEL 0x80 0x80000000 0x010006 0x80000000 0x80000000 0x80 # wut; openbsd defines as si_code>0
|
||||
syscon sicode SI_KERNEL 128 0x80000000 0x010006 0x80000000 0x80000000 0x80 # wut; openbsd defines as si_code>0
|
||||
syscon sicode SI_NOINFO 32767 0x80000000 0 32767 32767 32767 # no signal specific info available
|
||||
syscon sicode CLD_EXITED 1 1 1 1 1 1 # SIGCHLD; child exited; unix consensus
|
||||
syscon sicode CLD_KILLED 2 2 2 2 2 2 # SIGCHLD; child terminated w/o core; unix consensus
|
||||
|
|
|
@ -98,7 +98,7 @@ scall __sys_wait4 0x1c100b007200703d globl hidden
|
|||
scall sys_kill 0x02507a025202503e globl hidden # kill(pid, sig, 1) b/c xnu
|
||||
scall sys_killpg 0x092fff092fffffff globl hidden
|
||||
scall sys_clone 0x11fffffffffff038 globl hidden
|
||||
scall sys_tkill 0x13e0771b121690c8 globl hidden # thr_kill() on freebsd; _lwp_kill() on netbsd; thrkill() on openbsd where arg3 should be 0; bsdthread_terminate() on XNU which only has 1 arg
|
||||
scall sys_tkill 0x13e0771b121480c8 globl hidden # thr_kill() on freebsd; _lwp_kill() on netbsd; thrkill() on openbsd where arg3 should be 0; __pthread_kill() on XNU
|
||||
scall sys_futex 0x0a6053fffffff0ca globl hidden # raises SIGSYS on NetBSD
|
||||
scall set_robust_list 0x0a7ffffffffff111 globl
|
||||
scall get_robust_list 0x0a8ffffffffff112 globl
|
||||
|
|
|
@ -12,6 +12,7 @@ int bsdthread_create(void *func, void *func_arg, void *stack, void *pthread,
|
|||
uint32_t flags);
|
||||
int bsdthread_terminate(void *stackaddr, size_t freesize, uint32_t port,
|
||||
uint32_t sem);
|
||||
int __pthread_kill(uint32_t port, int sig);
|
||||
int bsdthread_register(
|
||||
void (*threadstart)(void *pthread, int machport, void *(*func)(void *),
|
||||
void *arg, intptr_t *, unsigned),
|
||||
|
|
111
test/libc/calls/raise_test.c
Normal file
111
test/libc/calls/raise_test.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sicode.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SIGTRAP
|
||||
|
||||
TEST(raise, trap_sysv) {
|
||||
if (IsWindows()) return;
|
||||
signal(SIGTRAP, SIG_DFL);
|
||||
SPAWN(fork);
|
||||
raise(SIGTRAP);
|
||||
TERMS(SIGTRAP);
|
||||
}
|
||||
|
||||
TEST(raise, trap_windows) {
|
||||
if (!IsWindows()) return;
|
||||
signal(SIGTRAP, SIG_DFL);
|
||||
SPAWN(fork);
|
||||
raise(SIGTRAP);
|
||||
EXITS(128 + SIGTRAP);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SIGFPE
|
||||
|
||||
TEST(raise, fpe_sysv) {
|
||||
if (IsWindows()) return;
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
SPAWN(fork);
|
||||
raise(SIGFPE);
|
||||
TERMS(SIGFPE);
|
||||
}
|
||||
|
||||
TEST(raise, fpe_windows) {
|
||||
if (!IsWindows()) return;
|
||||
signal(SIGFPE, SIG_DFL);
|
||||
SPAWN(fork);
|
||||
raise(SIGFPE);
|
||||
EXITS(128 + SIGFPE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// SIGUSR1
|
||||
|
||||
TEST(raise, usr1_sysv) {
|
||||
if (IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
raise(SIGUSR1);
|
||||
TERMS(SIGUSR1);
|
||||
}
|
||||
|
||||
TEST(raise, usr1_windows) {
|
||||
if (!IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
raise(SIGUSR1);
|
||||
EXITS(128 + SIGUSR1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// THREADS
|
||||
|
||||
int threadid;
|
||||
|
||||
void WorkerQuit(int sig, siginfo_t *si, void *ctx) {
|
||||
ASSERT_EQ(SIGILL, sig);
|
||||
if (!IsXnu() && !IsOpenbsd()) {
|
||||
ASSERT_EQ(SI_TKILL, si->si_code);
|
||||
}
|
||||
ASSERT_EQ(threadid, gettid());
|
||||
}
|
||||
|
||||
int Worker(void *arg, int tid) {
|
||||
struct sigaction sa = {.sa_sigaction = WorkerQuit, .sa_flags = SA_SIGINFO};
|
||||
ASSERT_EQ(0, sigaction(SIGILL, &sa, 0));
|
||||
threadid = tid;
|
||||
ASSERT_EQ(0, raise(SIGILL));
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(raise, threaded) {
|
||||
signal(SIGILL, SIG_DFL);
|
||||
struct spawn worker;
|
||||
ASSERT_SYS(0, 0, _spawn(Worker, 0, &worker));
|
||||
ASSERT_SYS(0, 0, _join(&worker));
|
||||
}
|
107
test/libc/runtime/abort_test.c
Normal file
107
test/libc/runtime/abort_test.c
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*-*- 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/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
#if 0
|
||||
TEST(abort, sysv) {
|
||||
if (IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
|
||||
abort();
|
||||
TERMS(SIGABRT);
|
||||
}
|
||||
|
||||
TEST(abort, windows) {
|
||||
if (!IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
|
||||
abort();
|
||||
EXITS(128 + SIGABRT);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(abort, blocked_stillTerminates_sysv) {
|
||||
sigset_t ss;
|
||||
if (IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
|
||||
sigfillset(&ss);
|
||||
sigprocmask(SIG_SETMASK, &ss, 0);
|
||||
abort();
|
||||
TERMS(SIGABRT);
|
||||
}
|
||||
|
||||
TEST(abort, blocked_stillTerminates_windows) {
|
||||
sigset_t ss;
|
||||
if (!IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
|
||||
sigfillset(&ss);
|
||||
sigprocmask(SIG_SETMASK, &ss, 0);
|
||||
abort();
|
||||
EXITS(128 + SIGABRT);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(abort, ign_stillTerminates_sysv) {
|
||||
if (IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN));
|
||||
abort();
|
||||
TERMS(SIGABRT);
|
||||
}
|
||||
|
||||
TEST(abort, ign_stillTerminates_windows) {
|
||||
if (!IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN));
|
||||
abort();
|
||||
EXITS(128 + SIGABRT);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#endif
|
||||
|
||||
void Ignore(int sig) {
|
||||
}
|
||||
|
||||
TEST(abort, handled_stillTerminates_sysv) {
|
||||
if (IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore));
|
||||
abort();
|
||||
TERMS(SIGABRT);
|
||||
}
|
||||
|
||||
TEST(abort, handled_stillTerminates_windows) {
|
||||
if (!IsWindows()) return;
|
||||
SPAWN(fork);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore));
|
||||
abort();
|
||||
EXITS(128 + SIGABRT);
|
||||
}
|
|
@ -189,7 +189,7 @@
|
|||
(runs (format "o/$m/%s.com%s V=5 TESTARGS=-b" name runsuffix))
|
||||
(buns (format "o/$m/test/%s_test.com%s V=5 TESTARGS=-b" name runsuffix)))
|
||||
(cond ((not (member ext '("c" "cc" "s" "S" "rl" "f")))
|
||||
(format "m=%s; make -j12 -O MODE=$m o/$m/%s"
|
||||
(format "m=%s; make -j12 MODE=$m o/$m/%s"
|
||||
mode
|
||||
(directory-file-name
|
||||
(or (file-name-directory
|
||||
|
@ -200,7 +200,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
"scp $f $f.dbg win10:; ssh win10 ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((eq kind 'run-xnu)
|
||||
|
@ -208,19 +208,19 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
"scp $f $f.dbg xnu:"
|
||||
"ssh xnu ./%s.com"))
|
||||
mode name (file-name-nondirectory name)))
|
||||
((and (equal suffix "")
|
||||
(cosmo-contains "_test." (buffer-file-name)))
|
||||
(format "m=%s; make -j12 -O MODE=$m %s"
|
||||
(format "m=%s; make -j12 MODE=$m %s"
|
||||
mode runs))
|
||||
((and (equal suffix "")
|
||||
(file-exists-p (format "%s" buddy)))
|
||||
(format (cosmo-join
|
||||
" && "
|
||||
'("m=%s; n=%s; make -j12 -O o/$m/$n%s.o MODE=$m"
|
||||
'("m=%s; n=%s; make -j12 o/$m/$n%s.o MODE=$m"
|
||||
;; "bloat o/$m/%s.o | head"
|
||||
;; "nm -C --size o/$m/%s.o | sort -r"
|
||||
"echo"
|
||||
|
@ -232,11 +232,11 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s.com"
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
"./$f"))
|
||||
mode name))
|
||||
((eq kind 'test)
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && make -j12 -O $f MODE=$m" mode name))
|
||||
(format `"m=%s; f=o/$m/%s.com.ok && make -j12 $f MODE=$m" mode name))
|
||||
((and (file-regular-p this)
|
||||
(file-executable-p this))
|
||||
(format "./%s" file))
|
||||
|
@ -245,7 +245,7 @@
|
|||
(cosmo-join
|
||||
" && "
|
||||
`("m=%s; f=o/$m/%s%s.o"
|
||||
,(concat "make -j12 -O $f MODE=$m")
|
||||
,(concat "make -j12 $f MODE=$m")
|
||||
;; "nm -C --size $f | sort -r"
|
||||
"echo"
|
||||
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
|
||||
|
@ -455,7 +455,7 @@
|
|||
(error "don't know how to show assembly for non c/c++ source file"))
|
||||
(let* ((default-directory root)
|
||||
(compile-command
|
||||
(format "/usr/bin/make %s -j12 -O MODE=%s %s %s"
|
||||
(format "make %s -j12 MODE=%s %s %s"
|
||||
(or extra-make-flags "") mode asm-gcc asm-clang)))
|
||||
(save-buffer)
|
||||
(set-visited-file-modtime (current-time))
|
||||
|
|
Loading…
Reference in a new issue