mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-03 19:22:27 +00:00
Initial import
This commit is contained in:
commit
c91b3c5006
14915 changed files with 590219 additions and 0 deletions
95
libc/log/attachdebugger.c
Normal file
95
libc/log/attachdebugger.c
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
|
||||
/**
|
||||
* Launches GDB debugger GUI for current process.
|
||||
*
|
||||
* This function abstracts the toilsome details of configuring the best
|
||||
* possible UX for debugging your app, for varying levels of available
|
||||
* information, on most of the various platforms.
|
||||
*
|
||||
* Before calling this function, consider placing showcrashreports() in
|
||||
* your main function and calling DebugBreak() wherever you want; it's
|
||||
* safer. Also note the "GDB" environment variable can be set to empty
|
||||
* string, as a fail-safe for disabling this behavior.
|
||||
*
|
||||
* @param continuetoaddr can be a code address, 0, or -1 for auto
|
||||
* @return gdb pid if continuing, 0 if detached, or -1 w/ errno
|
||||
* @note this is called via eponymous spinlock macro wrapper
|
||||
*/
|
||||
relegated int(attachdebugger)(intptr_t continuetoaddr) {
|
||||
int ttyin, ttyout;
|
||||
struct StackFrame *bp;
|
||||
char pidstr[11], breakcmd[40];
|
||||
const char *se, *elf, *gdb, *rewind, *layout;
|
||||
if (!((gdb = commandv(firstnonnull(getenv("GDB"), "gdb"))) &&
|
||||
(ttyin = ttyout = open(_PATH_TTY, O_RDWR, 0)) != -1)) {
|
||||
return -1;
|
||||
}
|
||||
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
|
||||
layout = "layout asm";
|
||||
if ((elf = finddebugbinary())) {
|
||||
se = "-se";
|
||||
if (fileexists(__FILE__)) layout = "layout src";
|
||||
} else {
|
||||
se = "-q";
|
||||
elf = "-q";
|
||||
}
|
||||
if (continuetoaddr) {
|
||||
if (continuetoaddr == -1) {
|
||||
bp = __builtin_frame_address(0);
|
||||
continuetoaddr = bp->addr;
|
||||
}
|
||||
rewind = "-ex";
|
||||
snprintf(breakcmd, sizeof(breakcmd), "%s *%#p", "break", continuetoaddr);
|
||||
} else {
|
||||
rewind = NULL;
|
||||
breakcmd[0] = '\0';
|
||||
}
|
||||
return spawnve(0, (int[3]){ttyin, ttyout, STDERR_FILENO}, gdb,
|
||||
(char *const[]){
|
||||
"gdb", "--tui",
|
||||
"-p", pidstr,
|
||||
se, elf,
|
||||
"-ex", "set osabi GNU/Linux",
|
||||
"-ex", "set complaints 0",
|
||||
"-ex", "set confirm off",
|
||||
"-ex", layout,
|
||||
"-ex", "layout reg",
|
||||
"-ex", "set var g_gdbsync = 1",
|
||||
"-q", rewind,
|
||||
breakcmd, "-ex",
|
||||
"c", NULL,
|
||||
},
|
||||
environ);
|
||||
}
|
25
libc/log/backtrace.c
Normal file
25
libc/log/backtrace.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
relegated void backtrace(FILE *f) {
|
||||
showbacktrace(f, __builtin_frame_address(0));
|
||||
}
|
170
libc/log/backtrace2.c
Normal file
170
libc/log/backtrace2.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/alg/bisectcarleft.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/nexgen32e/gc.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
#define kBacktraceMaxFrames 128
|
||||
#define kBacktraceBufSize ((kBacktraceMaxFrames - 1) * (16 + 1))
|
||||
|
||||
static char *formataddress(FILE *f, const struct SymbolTable *st, intptr_t addr,
|
||||
char *out, unsigned size, bool symbolic) {
|
||||
int64_t addend;
|
||||
const char *name;
|
||||
const struct Symbol *symbol;
|
||||
if (st->count && ((intptr_t)addr >= (intptr_t)&_base &&
|
||||
(intptr_t)addr <= (intptr_t)&_end && symbolic)) {
|
||||
symbol = &st->symbols[bisectcarleft((const int32_t(*)[2])st->symbols,
|
||||
st->count, addr - st->addr_base - 1)];
|
||||
addend = addr - st->addr_base - symbol->addr_rva;
|
||||
name = &st->name_base[symbol->name_rva];
|
||||
snprintf(out, size, "%s%c%#x", name, addend >= 0 ? '+' : '-', abs(addend));
|
||||
} else {
|
||||
snprintf(out, size, "%p", addr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static int printbacktraceusingsymbols(FILE *f, const struct StackFrame *bp,
|
||||
char buf[hasatleast kBacktraceBufSize]) {
|
||||
size_t gi;
|
||||
intptr_t addr;
|
||||
struct Garbages *garbage;
|
||||
struct SymbolTable *symbols;
|
||||
const struct StackFrame *frame;
|
||||
if ((symbols = getsymboltable())) {
|
||||
garbage = weaken(__garbage);
|
||||
gi = garbage ? garbage->i : 0;
|
||||
for (frame = bp; frame; frame = frame->next) {
|
||||
addr = frame->addr;
|
||||
if (addr == weakaddr("__gc")) {
|
||||
do {
|
||||
--gi;
|
||||
} while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
||||
}
|
||||
fprintf(f, "%p %p %s\n", frame, addr,
|
||||
formataddress(f, symbols, addr, buf, kBacktraceBufSize, true));
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int printbacktraceusingaddr2line(
|
||||
FILE *f, const struct StackFrame *bp,
|
||||
char buf[hasatleast kBacktraceBufSize],
|
||||
char *argv[hasatleast kBacktraceMaxFrames]) {
|
||||
ssize_t got;
|
||||
intptr_t addr;
|
||||
size_t i, j, gi;
|
||||
int rc, pid, tubes[3];
|
||||
struct Garbages *garbage;
|
||||
const struct StackFrame *frame;
|
||||
const char *addr2line, *debugbin, *p1, *p2, *p3;
|
||||
if (!(debugbin = finddebugbinary()) ||
|
||||
!(addr2line = emptytonull(firstnonnull(
|
||||
getenv("ADDR2LINE"), firstnonnull(commandv("addr2line"), ""))))) {
|
||||
return -1;
|
||||
}
|
||||
i = 0;
|
||||
j = 0;
|
||||
argv[i++] = "addr2line";
|
||||
argv[i++] = "-a"; /* filter out w/ shell script wrapper for old versions */
|
||||
argv[i++] = "-pCife";
|
||||
argv[i++] = debugbin;
|
||||
garbage = weaken(__garbage);
|
||||
gi = garbage ? garbage->i : 0;
|
||||
for (frame = bp; frame && i < kBacktraceMaxFrames - 1; frame = frame->next) {
|
||||
addr = frame->addr;
|
||||
if (addr == weakaddr("__gc")) {
|
||||
do {
|
||||
--gi;
|
||||
} while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
|
||||
}
|
||||
argv[i++] = &buf[j];
|
||||
j += snprintf(&buf[j], 17, "%#x", addr - 1) + 1;
|
||||
}
|
||||
argv[i++] = NULL;
|
||||
tubes[0] = STDIN_FILENO;
|
||||
tubes[1] = -1;
|
||||
tubes[2] = STDERR_FILENO;
|
||||
if ((pid = spawnve(0, tubes, addr2line, argv, environ)) == -1) return -1;
|
||||
while ((got = read(tubes[1], buf, kBacktraceBufSize)) > 0) {
|
||||
for (p1 = buf; got;) {
|
||||
/*
|
||||
* remove racist output from gnu tooling, that can't be disabled
|
||||
* otherwise, since it breaks other tools like emacs that aren't
|
||||
* equipped to ignore it, and what's most problematic is that
|
||||
* addr2line somehow manages to put the racism onto the one line
|
||||
* in the backtrace we actually care about.
|
||||
*/
|
||||
if ((p2 = memmem(p1, got, " (discriminator ",
|
||||
strlen(" (discriminator ") - 1)) &&
|
||||
(p3 = memchr(p2, '\n', got - (p2 - p1)))) {
|
||||
if (p3 > p2 && p3[-1] == '\r') --p3;
|
||||
fwrite(p1, 1, p2 - p1, f);
|
||||
got -= p3 - p1;
|
||||
p1 += p3 - p1;
|
||||
} else {
|
||||
fwrite(p1, 1, got, f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(tubes[1]);
|
||||
if (waitpid(pid, &rc, 0) == -1) return -1;
|
||||
if (WEXITSTATUS(rc) != 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static noinline int printbacktrace(FILE *f, const struct StackFrame *bp,
|
||||
char *argv[hasatleast kBacktraceMaxFrames],
|
||||
char buf[hasatleast kBacktraceBufSize]) {
|
||||
if (!IsTiny()) {
|
||||
if (printbacktraceusingaddr2line(f, bp, buf, argv) != -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return printbacktraceusingsymbols(f, bp, buf);
|
||||
}
|
||||
|
||||
void showbacktrace(FILE *f, const struct StackFrame *bp) {
|
||||
static bool noreentry;
|
||||
char *argv[kBacktraceMaxFrames];
|
||||
char buf[kBacktraceBufSize];
|
||||
if (!noreentry) {
|
||||
noreentry = true;
|
||||
printbacktrace(f, bp, argv, buf);
|
||||
noreentry = 0;
|
||||
}
|
||||
}
|
43
libc/log/bisectsymbol.c
Normal file
43
libc/log/bisectsymbol.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/bisectcarleft.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
/**
|
||||
* Finds symbol associated with address.
|
||||
* @param symbol table pointer (null propagating)
|
||||
* @return symbol address or NULL if not found
|
||||
*/
|
||||
const struct Symbol *bisectsymbol(struct SymbolTable *t,
|
||||
intptr_t virtual_address,
|
||||
int64_t *opt_out_addend) {
|
||||
const struct Symbol *symbol = NULL;
|
||||
int64_t addend = (intptr_t)virtual_address;
|
||||
if (t && t->count) {
|
||||
unsigned key = (unsigned)((intptr_t)virtual_address - t->addr_base - 1);
|
||||
unsigned i = bisectcarleft((const int32_t(*)[2])t->symbols, t->count, key);
|
||||
assert(0 <= i && i < t->count);
|
||||
symbol = &t->symbols[i];
|
||||
addend = (int64_t)key - (int64_t)symbol->addr_rva;
|
||||
}
|
||||
if (opt_out_addend) *opt_out_addend = addend;
|
||||
return symbol;
|
||||
}
|
31
libc/log/bsd.h
Normal file
31
libc/log/bsd.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_BSD_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_BSD_H_
|
||||
#include "libc/fmt/pflink.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § logging » berkeley logger ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void err(int, const char *, ...) printfesque(2) noreturn;
|
||||
void errx(int, const char *, ...) printfesque(2) noreturn;
|
||||
void verr(int, const char *, va_list) paramsnonnull((3)) noreturn;
|
||||
void verrx(int, const char *, va_list) paramsnonnull((3)) noreturn;
|
||||
void vwarn(const char *, va_list) paramsnonnull((2));
|
||||
void vwarnx(const char *, va_list) paramsnonnull((2));
|
||||
void warn(const char *, ...) printfesque(1);
|
||||
void warnx(const char *, ...) printfesque(1);
|
||||
|
||||
#define err(EVAL, FMT, ...) (err)(EVAL, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define errx(EVAL, FMT, ...) (errx)(EVAL, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define verr(EVAL, FMT, VA) (verr)(EVAL, PFLINK(FMT), VA)
|
||||
#define verrx(EVAL, FMT, VA) (verrx)(EVAL, PFLINK(FMT), VA)
|
||||
#define vwarn(FMT, VA) (vwarn)(PFLINK(FMT), VA)
|
||||
#define vwarnx(FMT, VA) (vwarnx)(PFLINK(FMT), VA)
|
||||
#define warn(FMT, ...) (warn)(PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define warnx(FMT, ...) (warn)(PFLINK(FMT), ##__VA_ARGS__)
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_BSD_H_ */
|
120
libc/log/cancolor.c
Normal file
120
libc/log/cancolor.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/nt/enum/filetype.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/pedef.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
static struct CanColor {
|
||||
bool once;
|
||||
bool result;
|
||||
struct OldNtConsole {
|
||||
unsigned codepage;
|
||||
unsigned mode;
|
||||
int64_t handle;
|
||||
} oldin, oldout;
|
||||
} g_cancolor;
|
||||
|
||||
static textwindows void restorecmdexe(void) {
|
||||
if (g_cancolor.oldin.handle) {
|
||||
SetConsoleCP(g_cancolor.oldin.codepage);
|
||||
SetConsoleMode(g_cancolor.oldin.handle, g_cancolor.oldin.mode);
|
||||
}
|
||||
if (g_cancolor.oldout.handle) {
|
||||
SetConsoleOutputCP(g_cancolor.oldout.codepage);
|
||||
SetConsoleMode(g_cancolor.oldout.handle, g_cancolor.oldout.mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if ANSI terminal colors are appropriate.
|
||||
*
|
||||
* We take an optimistic approach here. We use colors, unless we see the
|
||||
* environment variable TERM=dumb, which is set by software like Emacs.
|
||||
* It's a common antipattern to check isatty(STDERR_FILENO), since that
|
||||
* usually makes colors harder to get than they are to remove:
|
||||
*
|
||||
* sed 's/\x1b\[[;[:digit:]]*m//g' <color.txt >uncolor.txt
|
||||
*
|
||||
* Ideally, all software should be updated to understand color, since
|
||||
* it's been formally standardized nearly as long as ASCII. Even old
|
||||
* MS-DOS supports it (but Windows didn't until Windows 10) yet even
|
||||
* tools like less may need wrapper scripts, e.g.:
|
||||
*
|
||||
* #!/bin/sh
|
||||
* LESSCHARSET=UTF-8 exec /usr/bin/less -RS "$@"
|
||||
*
|
||||
* It's that easy fam.
|
||||
*/
|
||||
bool cancolor(void) {
|
||||
int64_t handle;
|
||||
const char *term;
|
||||
if (g_cancolor.once) return g_cancolor.result;
|
||||
g_cancolor.once = true;
|
||||
if (IsWindows()) {
|
||||
if ((int)weakaddr("v_ntsubsystem") == kNtImageSubsystemWindowsCui &&
|
||||
NtGetVersion() >= kNtVersionWindows10) {
|
||||
atexit(restorecmdexe);
|
||||
if (GetFileType((handle = g_fds.p[STDIN_FILENO].handle)) ==
|
||||
kNtFileTypeChar) {
|
||||
g_cancolor.result = true;
|
||||
g_cancolor.oldin.handle = handle;
|
||||
g_cancolor.oldin.codepage = GetConsoleCP();
|
||||
SetConsoleCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cancolor.oldin.mode);
|
||||
SetConsoleMode(handle, g_cancolor.oldin.mode | kNtEnableProcessedInput |
|
||||
kNtEnableVirtualTerminalInput);
|
||||
}
|
||||
if (GetFileType((handle = g_fds.p[STDOUT_FILENO].handle)) ==
|
||||
kNtFileTypeChar ||
|
||||
GetFileType((handle = g_fds.p[STDERR_FILENO].handle)) ==
|
||||
kNtFileTypeChar) {
|
||||
g_cancolor.result = true;
|
||||
g_cancolor.oldout.handle = handle;
|
||||
g_cancolor.oldout.codepage = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(kNtCpUtf8);
|
||||
GetConsoleMode(handle, &g_cancolor.oldout.mode);
|
||||
SetConsoleMode(handle, g_cancolor.oldout.mode |
|
||||
kNtEnableProcessedOutput |
|
||||
kNtEnableVirtualTerminalProcessing);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!g_cancolor.result) {
|
||||
if ((term = getenv("TERM"))) {
|
||||
/* anything but emacs basically */
|
||||
g_cancolor.result = strcmp(term, "dumb") != 0;
|
||||
} else {
|
||||
/* TODO(jart): Why does Mac bash login shell exec nuke TERM? */
|
||||
g_cancolor.result = IsXnu();
|
||||
}
|
||||
}
|
||||
return g_cancolor.result;
|
||||
}
|
96
libc/log/check.h
Normal file
96
libc/log/check.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_CHECK_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_CHECK_H_
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Modern assertions, courtesy of Elgoog.
|
||||
*/
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define CHECK(X, ...) __CHK(eq, ==, true, "true", !!(X), #X, "" __VA_ARGS__)
|
||||
#define CHECK_EQ(Y, X, ...) __CHK(eq, ==, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_NE(Y, X, ...) __CHK(ne, !=, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_LE(Y, X, ...) __CHK(le, <=, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_LT(Y, X, ...) __CHK(lt, <, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_GE(Y, X, ...) __CHK(ge, >=, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_GT(Y, X, ...) __CHK(gt, >, Y, #Y, X, #X, "" __VA_ARGS__)
|
||||
#define CHECK_NOTNULL(X, ...) __CHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
|
||||
|
||||
#define DCHECK(X, ...) __DCHK(eq, ==, true, "true", !!(X), #X, "" __VA_ARGS__)
|
||||
#define DCHECK_EQ(Y, X, ...) __DCHK(eq, ==, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_NE(Y, X, ...) __DCHK(ne, !=, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_LE(Y, X, ...) __DCHK(le, <=, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_LT(Y, X, ...) __DCHK(lt, <, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_GE(Y, X, ...) __DCHK(ge, >=, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_GT(Y, X, ...) __DCHK(gt, >, Y, #X, X, #Y, "" __VA_ARGS__)
|
||||
#define DCHECK_NOTNULL(X, ...) \
|
||||
__DCHK(ne, !=, NULL, "NULL", X, #X, "" __VA_ARGS__)
|
||||
|
||||
#define CHECK_ALIGNED(BYTES, VAR) \
|
||||
do { \
|
||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||
__check_fail_aligned(BYTES, (uintptr_t)VAR); \
|
||||
unreachable; \
|
||||
} \
|
||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||
} while (0)
|
||||
|
||||
#define DCHECK_ALIGNED(BYTES, VAR) \
|
||||
do { \
|
||||
if (((uintptr_t)VAR & ((BYTES)-1u))) { \
|
||||
__DCHK_ALIGNED(BYTES, (uintptr_t)VAR); \
|
||||
unreachable; \
|
||||
} \
|
||||
VAR = (typeof(VAR))__builtin_assume_aligned(VAR, BYTES); \
|
||||
} while (0)
|
||||
|
||||
#define __CHK(SUFFIX, OP, WANT, WANTSTR, GOT, GOTSTR, ...) \
|
||||
do { \
|
||||
autotype(WANT) Want = (WANT); \
|
||||
autotype(GOT) Got = (GOT); \
|
||||
if (!(Want OP Got)) { \
|
||||
if (!NoDebug()) { \
|
||||
__check_fail(#SUFFIX, #OP, (uint64_t)Want, (WANTSTR), (uint64_t)Got, \
|
||||
(GOTSTR), __FILE__, __LINE__, __VA_ARGS__); \
|
||||
} else { \
|
||||
__check_fail_##SUFFIX((uint64_t)Want, (uint64_t)Got); \
|
||||
} \
|
||||
unreachable; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define __DCHK(SUFFIX, OP, WANT, WANTSTR, GOT, ...) \
|
||||
do { \
|
||||
autotype(WANT) Want = (WANT); \
|
||||
autotype(GOT) Got = (GOT); \
|
||||
if (!(Want OP Got)) unreachable; \
|
||||
} while (0)
|
||||
#else
|
||||
#define __DCHK(SUFFIX, OP, WANT, WANTSTR, GOT, GOTSTR, ...) \
|
||||
__CHK(SUFFIX, OP, WANT, WANTSTR, GOT, GOTSTR, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define __DCHK_ALIGNED(BYTES, VAR)
|
||||
#else
|
||||
#define __DCHK_ALIGNED(BYTES, VAR) __check_fail_aligned(BYTES, VAR)
|
||||
#endif
|
||||
|
||||
void __check_fail(const char *, const char *, uint64_t, const char *, uint64_t,
|
||||
const char *, const char *, int, const char *,
|
||||
...) relegated noreturn;
|
||||
|
||||
void __check_fail_eq(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_ne(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_le(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_lt(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_ge(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_gt(uint64_t, uint64_t) relegated noreturn;
|
||||
void __check_fail_aligned(unsigned, uint64_t) relegated noreturn;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_CHECK_H_ */
|
30
libc/log/checkaligned.c
Normal file
30
libc/log/checkaligned.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void __check_fail_aligned(unsigned bytes, uint64_t ptr) {
|
||||
if (!IsTiny()) memsummary(stderr);
|
||||
fprintf(stderr, "%s%d%s%#p\n", "error: pointer not ", bytes,
|
||||
"-byte aligned: ", ptr);
|
||||
die();
|
||||
}
|
79
libc/log/checkfail.c
Normal file
79
libc/log/checkfail.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
/**
|
||||
* Handles failure of CHECK_xx() macros.
|
||||
*/
|
||||
relegated void __check_fail(const char *suffix, const char *opstr,
|
||||
uint64_t want, const char *wantstr, uint64_t got,
|
||||
const char *gotstr, const char *file, int line,
|
||||
const char *fmt, ...) {
|
||||
size_t i;
|
||||
va_list va;
|
||||
char sufbuf[8];
|
||||
int lasterr = errno;
|
||||
startfatal(file, line);
|
||||
|
||||
if (!memccpy(sufbuf, suffix, '\0', sizeof(sufbuf))) strcpy(sufbuf, "?");
|
||||
strtoupper(sufbuf);
|
||||
|
||||
fprintf(stderr,
|
||||
"check failed\n"
|
||||
"\tCHECK_%s(%s, %s);\n"
|
||||
"\t\t → %#lx (%s)\n"
|
||||
"\t\t%s %#lx (%s)\n",
|
||||
sufbuf, wantstr, gotstr, got, gotstr, opstr, want, wantstr);
|
||||
|
||||
if (!isempty(fmt)) {
|
||||
fputc('\t', stderr);
|
||||
va_start(va, fmt);
|
||||
vfprintf(stderr, fmt, va);
|
||||
va_end(va);
|
||||
fputc('\n', stderr);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\t%s\n\t%s%s%s%s\n", strerror(lasterr), SUBTLE,
|
||||
getauxval(AT_EXECFN), g_argc > 1 ? " \\" : "", RESET);
|
||||
|
||||
for (i = 1; i < g_argc; ++i) {
|
||||
fprintf(stderr, "\t\t%s%s\n", g_argv[i], i < g_argc - 1 ? " \\" : "");
|
||||
}
|
||||
|
||||
if (!IsTiny() && lasterr == ENOMEM) {
|
||||
fprintf(stderr, "\n");
|
||||
showmappings(stderr);
|
||||
}
|
||||
|
||||
fflush(stderr);
|
||||
die();
|
||||
unreachable;
|
||||
}
|
42
libc/log/checkfail_ndebug.c
Normal file
42
libc/log/checkfail_ndebug.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Handles failure of CHECK_xx() macros in -DNDEBUG mode.
|
||||
*
|
||||
* This handler (1) makes binaries smaller by not embedding source code;
|
||||
* and therefore (2) less likely to leak sensitive information. This can
|
||||
* still print backtraces with function names if the .com.dbg file is in
|
||||
* the same folder.
|
||||
*
|
||||
* @see libc/log/thunks/__check_fail_ndebug.S
|
||||
*/
|
||||
relegated void ___check_fail_ndebug(uint64_t want, uint64_t got,
|
||||
const char *opchar) {
|
||||
int lasterr = errno;
|
||||
startfatal_ndebug();
|
||||
fprintf(stderr, "%s: %#lx %s %#lx (%s)\n", "check failed", want, opchar, got,
|
||||
strerror(lasterr));
|
||||
}
|
42
libc/log/commandvenv.c
Normal file
42
libc/log/commandvenv.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
|
||||
/**
|
||||
* Finds full executable path in overridable way.
|
||||
*/
|
||||
nodiscard char *commandvenv(const char *var, const char *cmd) {
|
||||
const char *exepath;
|
||||
if ((exepath = getenv(var))) {
|
||||
if (!isempty(exepath) && access(exepath, X_OK) != -1) {
|
||||
return exepath;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else if ((exepath = commandv(cmd))) {
|
||||
return exepath;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
43
libc/log/die.c
Normal file
43
libc/log/die.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
|
||||
/**
|
||||
* Aborts process after printing details on its current state.
|
||||
*/
|
||||
relegated noreturn void die(void) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
once = true;
|
||||
if (!IsTiny()) {
|
||||
g_runstate |= RUNSTATE_BROKEN;
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
backtrace(stderr);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
unreachable;
|
||||
}
|
||||
abort();
|
||||
unreachable;
|
||||
}
|
27
libc/log/err.c
Normal file
27
libc/log/err.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
|
||||
noreturn void(err)(int eval, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
(verr)(eval, fmt, va);
|
||||
va_end(va);
|
||||
}
|
27
libc/log/errx.c
Normal file
27
libc/log/errx.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
|
||||
noreturn void(errx)(int eval, const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
(verrx)(eval, fmt, va);
|
||||
va_end(va);
|
||||
}
|
32
libc/log/flogf.c
Normal file
32
libc/log/flogf.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
|
||||
/**
|
||||
* Writes formatted message w/ timestamp to log.
|
||||
* @see vflogf()
|
||||
*/
|
||||
void(flogf)(unsigned level, const char *file, int line, FILE *f,
|
||||
const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
(vflogf)(level, file, line, f, fmt, va);
|
||||
va_end(va);
|
||||
}
|
37
libc/log/gdb.h
Normal file
37
libc/log/gdb.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_GDB_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_GDB_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern volatile int g_gdbsync;
|
||||
|
||||
int gdbexec(const char *);
|
||||
int attachdebugger(intptr_t);
|
||||
|
||||
#define attachdebugger(CONTINUE_TO_ADDR) /* shorten backtraces */ \
|
||||
SYNCHRONIZE_DEBUGGER((attachdebugger)(CONTINUE_TO_ADDR))
|
||||
|
||||
#define SYNCHRONIZE_DEBUGGER(PID) \
|
||||
({ \
|
||||
int Rc, Pid = (PID); \
|
||||
if (Pid != -1) { \
|
||||
while ((Rc = WAIT4(Pid, NULL, WNOHANG, NULL)) == 0) { \
|
||||
if (g_gdbsync) { \
|
||||
g_gdbsync = 0; \
|
||||
if (Rc > 0) Pid = 0; \
|
||||
break; \
|
||||
} else { \
|
||||
SCHED_YIELD(); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
Pid; \
|
||||
})
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_GDB_H_ */
|
78
libc/log/gdbexec.c
Normal file
78
libc/log/gdbexec.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
/**
|
||||
* Attachs GDB temporarilly, to do something like print a variable.
|
||||
*/
|
||||
int(gdbexec)(const char *cmd) {
|
||||
int ttyin, ttyout;
|
||||
struct StackFrame *bp;
|
||||
intptr_t continuetoaddr;
|
||||
const char *se, *elf, *gdb;
|
||||
char pidstr[11], breakcmd[40];
|
||||
if (!(gdb = commandv(firstnonnull(getenv("GDB"), "gdb")))) {
|
||||
return -1;
|
||||
}
|
||||
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
|
||||
if ((elf = finddebugbinary())) {
|
||||
se = "-se";
|
||||
} else {
|
||||
se = "-q";
|
||||
elf = "-q";
|
||||
}
|
||||
bp = __builtin_frame_address(0);
|
||||
continuetoaddr = bp->addr;
|
||||
snprintf(breakcmd, sizeof(breakcmd), "%s *%#p", "break", bp->addr);
|
||||
|
||||
char *const args[] = {
|
||||
"gdb",
|
||||
"--nx",
|
||||
"--nh",
|
||||
"-p",
|
||||
pidstr,
|
||||
se,
|
||||
elf,
|
||||
"-ex",
|
||||
"set osabi GNU/Linux",
|
||||
"-ex",
|
||||
"set complaints 0",
|
||||
"-ex",
|
||||
"set confirm off",
|
||||
"-ex",
|
||||
"set var g_gdbsync = 1",
|
||||
"-q",
|
||||
"-ex",
|
||||
breakcmd,
|
||||
"-ex",
|
||||
cmd,
|
||||
"-ex",
|
||||
"quit",
|
||||
NULL,
|
||||
};
|
||||
|
||||
return SYNCHRONIZE_DEBUGGER(spawnve(0, NULL, gdb, args, environ));
|
||||
}
|
22
libc/log/gdbsync.c
Normal file
22
libc/log/gdbsync.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/gdb.h"
|
||||
|
||||
volatile int g_gdbsync;
|
32
libc/log/getsymbolname.c
Normal file
32
libc/log/getsymbolname.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/elf.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
/**
|
||||
* Finds starting address of symbol.
|
||||
* @param symbol table pointer (null propagating)
|
||||
* @return name string or null if not found
|
||||
*/
|
||||
const char *getsymbolname(struct SymbolTable *t, const struct Symbol *symbol) {
|
||||
return (t && symbol)
|
||||
? getelfstring(t->elf, t->elfsize, t->name_base, symbol->name_rva)
|
||||
: NULL;
|
||||
}
|
39
libc/log/getsymboltable.c
Normal file
39
libc/log/getsymboltable.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
/**
|
||||
* Returns debug binary symbol table, as global singleton.
|
||||
* @return symbol table, or NULL w/ errno on first call
|
||||
*/
|
||||
struct SymbolTable *getsymboltable(void) {
|
||||
static bool once;
|
||||
static struct SymbolTable *singleton;
|
||||
const char *debugbin;
|
||||
if (!once) {
|
||||
once = true;
|
||||
if ((debugbin = finddebugbinary()) &&
|
||||
(singleton = opensymboltable(debugbin))) {
|
||||
__cxa_atexit(closesymboltable, &singleton, NULL);
|
||||
}
|
||||
}
|
||||
return singleton;
|
||||
}
|
40
libc/log/getttycols.c
Normal file
40
libc/log/getttycols.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
/**
|
||||
* Shorthand for getting ws_col from getttysize().
|
||||
*
|
||||
* It is recommended that programs err on the side of showing more
|
||||
* information, if this value can't be obtained with certainty.
|
||||
*
|
||||
* @return terminal width or defaultcols on error
|
||||
*/
|
||||
uint16_t getttycols(uint16_t defaultcols) {
|
||||
struct winsize wsize;
|
||||
if (getttysize(STDIN_FILENO, &wsize) != -1) {
|
||||
return wsize.ws_col;
|
||||
} else {
|
||||
return defaultcols;
|
||||
}
|
||||
}
|
47
libc/log/getttysize.c
Normal file
47
libc/log/getttysize.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
/**
|
||||
* Returns dimensions of controlling terminal.
|
||||
*
|
||||
* It is recommended that programs err on the side of showing more
|
||||
* information, if this value can't be obtained with certainty.
|
||||
*
|
||||
* @param out stores determined dimensions, only on success
|
||||
* @returns -1 on error or something else on success
|
||||
*/
|
||||
int getttysize(int fd, struct winsize *out) {
|
||||
if (isterminalinarticulate()) {
|
||||
out->ws_col = strtoimax(firstnonnull(getenv("COLUMNS"), "80"), NULL, 0);
|
||||
out->ws_row = strtoimax(firstnonnull(getenv("ROWS"), "40"), NULL, 0);
|
||||
out->ws_xpixel = 0;
|
||||
out->ws_ypixel = 0;
|
||||
return 0;
|
||||
} else {
|
||||
return ioctl(fd, TIOCGWINSZ, out);
|
||||
}
|
||||
}
|
35
libc/log/internal.h
Normal file
35
libc/log/internal.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
#define RED (cancolor() ? "\x1b[30;101m" : "")
|
||||
#define UNBOLD (cancolor() ? "\x1b[22m" : "")
|
||||
#define RED2 (cancolor() ? "\x1b[91;1m" : "")
|
||||
#define BLUE1 (cancolor() ? "\x1b[94;49m" : "")
|
||||
#define BLUE2 (cancolor() ? "\x1b[34m" : "")
|
||||
#define RESET (cancolor() ? "\x1b[0m" : "")
|
||||
#define SUBTLE (cancolor() ? "\x1b[35m" : "")
|
||||
|
||||
enum NtExceptionHandlerActions;
|
||||
struct NtExceptionPointers;
|
||||
|
||||
extern int kCrashSigs[8];
|
||||
extern struct sigaction g_oldcrashacts[8];
|
||||
extern const char kCrashSigNames[8][5] aligned(1);
|
||||
extern const char kGodHatesFlags[12][2] aligned(1);
|
||||
extern const char kGregNames[17][4] aligned(1);
|
||||
extern const char kGregOrder[17] aligned(1);
|
||||
|
||||
void startfatal(const char *, int) hidden;
|
||||
void startfatal_ndebug(void) hidden;
|
||||
void oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
||||
enum NtExceptionHandlerActions wincrash$nt(
|
||||
const struct NtExceptionPointers *) relegated;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_INTERNAL_H_ */
|
26
libc/log/isrunningundermake.c
Normal file
26
libc/log/isrunningundermake.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Returns true if current process was spawned by GNU Make.
|
||||
*/
|
||||
bool isrunningundermake(void) { return !!getenv("MAKEFLAGS"); }
|
30
libc/log/isterminalinarticulate.c
Normal file
30
libc/log/isterminalinarticulate.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Checks if we're probably running inside Emacs.
|
||||
*/
|
||||
bool isterminalinarticulate(void) {
|
||||
return strcmp(nulltoempty(getenv("TERM")), "dumb") == 0;
|
||||
}
|
215
libc/log/log.h
Normal file
215
libc/log/log.h
Normal file
|
@ -0,0 +1,215 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
|
||||
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
|
||||
#include "libc/dce.h"
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § liblog ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define kLogFatal 0u
|
||||
#define kLogError 1u
|
||||
#define kLogWarn 2u
|
||||
#define kLogInfo 3u
|
||||
#define kLogDebug 4u
|
||||
|
||||
/**
|
||||
* Log level for compile-time DCE.
|
||||
*/
|
||||
#ifndef LOGGABLELEVEL
|
||||
#ifndef NDEBUG
|
||||
#define LOGGABLELEVEL kLogDebug
|
||||
#elif IsTiny()
|
||||
#define LOGGABLELEVEL kLogFatal
|
||||
#else
|
||||
#define LOGGABLELEVEL kLogInfo
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct sigset;
|
||||
struct winsize;
|
||||
struct StackFrame;
|
||||
typedef struct FILE FILE;
|
||||
|
||||
extern FILE *g_logfile;
|
||||
|
||||
void backtrace(FILE *) relegated; /* shows fn backtrace and args */
|
||||
void perror(const char *) relegated; /* print the last system error */
|
||||
void die(void) relegated noreturn; /* print backtrace and abort() */
|
||||
void meminfo(FILE *); /* shows malloc statistics &c. */
|
||||
void memsummary(FILE *); /* light version of same thing */
|
||||
uint16_t getttycols(uint16_t);
|
||||
int getttysize(int, struct winsize *) paramsnonnull();
|
||||
bool cancolor(void) nothrow nocallback;
|
||||
bool isterminalinarticulate(void) nosideeffect;
|
||||
char *commandvenv(const char *, const char *) nodiscard;
|
||||
|
||||
void showmappings(FILE *);
|
||||
void showcrashreports(void);
|
||||
void callexitontermination(struct sigset *);
|
||||
bool32 IsDebuggerPresent(bool);
|
||||
bool isrunningundermake(void);
|
||||
void showbacktrace(FILE *, const struct StackFrame *);
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § liblog » logging ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
extern unsigned g_loglevel; /* log level for runtime check */
|
||||
|
||||
#define LOGGABLE(LEVEL) \
|
||||
((!isconstant(LEVEL) || (LEVEL) <= LOGGABLELEVEL) && (LEVEL) <= g_loglevel)
|
||||
|
||||
#define LOGF(FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogInfo)) { \
|
||||
flogf(kLogInfo, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFLOG(FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogInfo)) { \
|
||||
vflogf(kLogInfo, __FILE__, __LINE__, NULL, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FLOGF(F, FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogInfo)) { \
|
||||
flogf(kLogInfo, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFLOGF(F, FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogInfo)) { \
|
||||
vflogf(kLogInfo, __FILE__, __LINE__, F, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define WARNF(FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogWarn)) { \
|
||||
flogf(kLogWarn, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VWARNF(FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogWarn)) { \
|
||||
vflogf(kLogWarn, __FILE__, __LINE__, NULL, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FWARNF(F, FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogWarn)) { \
|
||||
flogf(kLogWarn, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFWARNF(F, FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogWarn)) { \
|
||||
vflogf(kLogWarn, __FILE__, __LINE__, F, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FATALF(FMT, ...) \
|
||||
do { \
|
||||
ffatalf(kLogFatal, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
#define VFATALF(FMT, VA) \
|
||||
do { \
|
||||
vffatalf(kLogFatal, __FILE__, __LINE__, NULL, FMT, VA); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
#define FFATALF(F, FMT, ...) \
|
||||
do { \
|
||||
ffatalf(kLogFatal, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
#define VFFATALF(F, FMT, VA) \
|
||||
do { \
|
||||
vffatalf(kLogFatal, __FILE__, __LINE__, F, FMT, VA); \
|
||||
unreachable; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGF(FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogDebug)) { \
|
||||
fdebugf(kLogDebug, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VDEBUGF(FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogDebug)) { \
|
||||
vfdebugf(kLogDebug, __FILE__, __LINE__, NULL, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FDEBUGF(F, FMT, ...) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogDebug)) { \
|
||||
fdebugf(kLogDebug, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VFDEBUGF(F, FMT, VA) \
|
||||
do { \
|
||||
if (LOGGABLE(kLogDebug)) { \
|
||||
vfdebugf(kLogDebug, __FILE__, __LINE__, F, FMT, VA); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § liblog » on error resume next ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define LOGIFNEG1(FORM) \
|
||||
({ \
|
||||
autotype(FORM) Ax = (FORM); \
|
||||
if (Ax == (typeof(Ax))(-1) && LOGGABLE(kLogWarn)) { \
|
||||
__logerrno(__FILE__, __LINE__, #FORM); \
|
||||
} \
|
||||
Ax; \
|
||||
})
|
||||
|
||||
#define LOGIFNULL(FORM) \
|
||||
({ \
|
||||
autotype(FORM) Ax = (FORM); \
|
||||
if (Ax == NULL && LOGGABLE(kLogWarn)) { \
|
||||
__logerrno(__FILE__, __LINE__, #FORM); \
|
||||
} \
|
||||
Ax; \
|
||||
})
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § liblog » implementation details ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void __logerrno(const char *, int, const char *) relegated;
|
||||
|
||||
#define ARGS unsigned, const char *, int, FILE *, const char *
|
||||
#define ATTR paramsnonnull((5)) printfesque(5)
|
||||
#define ATTRV paramsnonnull((5, 6))
|
||||
void flogf(ARGS, ...) ATTR libcesque;
|
||||
void vflogf(ARGS, va_list) ATTRV libcesque;
|
||||
void fdebugf(ARGS, ...) asm("flogf") ATTR relegated libcesque;
|
||||
void vfdebugf(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
|
||||
void ffatalf(ARGS, ...) asm("flogf") ATTR relegated noreturn libcesque;
|
||||
void vffatalf(ARGS, va_list) asm("vflogf") ATTRV relegated noreturn libcesque;
|
||||
#undef ARGS
|
||||
#undef ATTR
|
||||
#undef ATTRV
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_LOG_LOG_H_ */
|
86
libc/log/log.mk
Normal file
86
libc/log/log.mk
Normal file
|
@ -0,0 +1,86 @@
|
|||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
|
||||
PKGS += LIBC_LOG
|
||||
|
||||
LIBC_LOG_ARTIFACTS += LIBC_LOG_A
|
||||
LIBC_LOG = $(LIBC_LOG_A_DEPS) $(LIBC_LOG_A)
|
||||
LIBC_LOG_A = o/$(MODE)/libc/log/log.a
|
||||
LIBC_LOG_A_FILES := \
|
||||
$(wildcard libc/log/thunks/*) \
|
||||
$(wildcard libc/log/elf/*) \
|
||||
$(wildcard libc/log/*)
|
||||
LIBC_LOG_A_HDRS = $(filter %.h,$(LIBC_LOG_A_FILES))
|
||||
LIBC_LOG_A_SRCS_C = $(filter %.c,$(LIBC_LOG_A_FILES))
|
||||
LIBC_LOG_A_SRCS_S = $(filter %.S,$(LIBC_LOG_A_FILES))
|
||||
|
||||
LIBC_LOG_A_SRCS = \
|
||||
$(LIBC_LOG_A_SRCS_C) \
|
||||
$(LIBC_LOG_A_SRCS_S)
|
||||
|
||||
LIBC_LOG_A_OBJS = \
|
||||
$(LIBC_LOG_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_LOG_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(LIBC_LOG_A_SRCS_S:%.S=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_LOG_A_CHECKS = \
|
||||
$(LIBC_LOG_A).pkg \
|
||||
$(LIBC_LOG_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_LOG_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_CALLS_HEFTY \
|
||||
LIBC_CONV \
|
||||
LIBC_ELF \
|
||||
LIBC_ESCAPE \
|
||||
LIBC_FMT \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_UNICODE \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
THIRD_PARTY_DLMALLOC
|
||||
|
||||
LIBC_LOG_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_LOG_A): libc/log/ \
|
||||
$(LIBC_LOG_A).pkg \
|
||||
$(LIBC_LOG_A_OBJS)
|
||||
|
||||
$(LIBC_LOG_A).pkg: \
|
||||
$(LIBC_LOG_A_OBJS) \
|
||||
$(foreach x,$(LIBC_LOG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/log/die.o \
|
||||
o/$(MODE)/libc/log/perror.o \
|
||||
o/$(MODE)/libc/log/ftrace.o \
|
||||
o/$(MODE)/libc/log/ubsan.o \
|
||||
o/$(MODE)/libc/log/symbols.o \
|
||||
o/$(MODE)/libc/log/backtrace.o \
|
||||
o/$(MODE)/libc/log/oncrash.o \
|
||||
o/$(MODE)/libc/log/shadowargs.o \
|
||||
o/$(MODE)/libc/log/thunks/__check_fail_ndebug.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
$(NO_MAGIC)
|
||||
|
||||
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))
|
||||
LIBC_LOG_SRCS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_LOG_HDRS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_LOG_BINS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_LOG_CHECKS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_LOG_OBJS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_OBJS))
|
||||
LIBC_LOG_TESTS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)_TESTS))
|
||||
|
||||
$(LIBC_LOG_OBJS): $(BUILD_FILES) libc/log/log.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/log
|
||||
o/$(MODE)/libc/log: $(LIBC_LOG_CHECKS)
|
27
libc/log/logerrno.c
Normal file
27
libc/log/logerrno.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void __logerrno(const char *file, int line, const char *form) {
|
||||
flogf(kLogWarn, file, line, NULL, PFLINK("%s → %s"), form, strerror(errno));
|
||||
}
|
26
libc/log/logfile.c
Normal file
26
libc/log/logfile.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
FILE *g_logfile;
|
||||
|
||||
INITIALIZER(401, _init_g_logfile, (g_logfile = stderr));
|
33
libc/log/loglevel.S
Normal file
33
libc/log/loglevel.S
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
.bss
|
||||
.align 4
|
||||
g_loglevel:
|
||||
.long 0
|
||||
.endobj g_loglevel,globl
|
||||
.previous
|
||||
|
||||
.init.start 200,_init_g_loglevel
|
||||
movb $kLogInfo,g_loglevel(%rip)
|
||||
.init.end 200,_init_g_loglevel
|
31
libc/log/malloc_stats.c
Normal file
31
libc/log/malloc_stats.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "third_party/dlmalloc/dlmalloc.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
|
||||
void malloc_stats(void) {
|
||||
struct MallocStats res = dlmalloc_stats(gm);
|
||||
(fprintf)(stderr, "max system bytes = %'10zu\n", res.maxfp);
|
||||
(fprintf)(stderr, "system bytes = %'10zu\n", res.fp);
|
||||
(fprintf)(stderr, "in use bytes = %'10zu\n", res.used);
|
||||
}
|
39
libc/log/meminfo.c
Normal file
39
libc/log/meminfo.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
||||
static void onmemchunk(void *start, void *end, size_t used_bytes, void *arg) {
|
||||
FILE *f = arg;
|
||||
(fprintf)(f, "%p - %p : %08zx / %08lx\n", start, end, used_bytes,
|
||||
(intptr_t)end - (intptr_t)start);
|
||||
}
|
||||
|
||||
void meminfo(FILE *f) {
|
||||
memsummary(f);
|
||||
(fprintf)(f, "%*s %*s %*s %*s\n", POINTER_XDIGITS, "start",
|
||||
POINTER_XDIGITS, "end", 8, "used", 8, "size");
|
||||
malloc_inspect_all(onmemchunk, f);
|
||||
}
|
38
libc/log/memsummary.c
Normal file
38
libc/log/memsummary.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
|
||||
void memsummary(FILE *f) {
|
||||
struct mallinfo mi = mallinfo();
|
||||
(fprintf)(f,
|
||||
"arena\t\t%,-12zu\t# space allocated from system\n"
|
||||
"ordblks\t\t%,-12zu\t# number of free chunks\n"
|
||||
"hblkhd\t\t%,-12zu\t# space in mmapped regions\n"
|
||||
"usmblks\t\t%,-12zu\t# maximum total allocated space\n"
|
||||
"uordblks\t%,-12zu\t# total allocated space\n"
|
||||
"fordblks\t%,-12zu\t# total free space\n"
|
||||
"keepcost\t%,-12zu\t# releasable (via malloc_trim) space\n\n",
|
||||
mi.arena, mi.ordblks, mi.hblkhd, mi.usmblks, mi.uordblks,
|
||||
mi.fordblks, mi.keepcost);
|
||||
}
|
214
libc/log/oncrash.c
Normal file
214
libc/log/oncrash.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("ftoa");
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
||||
/**
|
||||
* @fileoverview Abnormal termination handling & GUI debugging.
|
||||
* @see libc/onkill.c
|
||||
*/
|
||||
|
||||
struct siginfo;
|
||||
|
||||
aligned(1) const char kGregOrder[17] = {13, 11, 8, 14, 12, 9, 10, 15, 16,
|
||||
0, 1, 2, 3, 4, 5, 6, 7};
|
||||
aligned(1) const char kGregNames[17][4] = {
|
||||
"R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "RDI",
|
||||
"RSI", "RBP", "RBX", "RDX", "RAX", "RCX", "RSP", "RIP"};
|
||||
aligned(1) const char kGodHatesFlags[12][2] = {
|
||||
"CF", "VF", "PF", "RF", "AF", "KF", "ZF", "SF", "TF", "IF", "DF", "OF"};
|
||||
aligned(1) const char kCrashSigNames[8][5] = {"QUIT", "FPE", "ILL", "SEGV",
|
||||
"TRAP", "ABRT", "BUS"};
|
||||
|
||||
int kCrashSigs[8];
|
||||
struct sigaction g_oldcrashacts[8];
|
||||
|
||||
relegated static const char *tinystrsignal(int sig) {
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
if (kCrashSigs[i] && sig == kCrashSigs[i]) {
|
||||
return kCrashSigNames[i];
|
||||
}
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
relegated static void showfunctioncalls(FILE *f, ucontext_t *ctx) {
|
||||
fputc('\n', f);
|
||||
struct StackFrame *bp;
|
||||
struct StackFrame goodframe;
|
||||
if (ctx && ctx->uc_mcontext.rip && ctx->uc_mcontext.rbp) {
|
||||
goodframe.next = (struct StackFrame *)ctx->uc_mcontext.rbp;
|
||||
goodframe.addr = ctx->uc_mcontext.rip;
|
||||
bp = &goodframe;
|
||||
showbacktrace(f, bp);
|
||||
}
|
||||
}
|
||||
|
||||
relegated static void describecpuflags(FILE *f, unsigned efl) {
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAYLEN(kGodHatesFlags); ++i) {
|
||||
if (efl & 1) {
|
||||
fputc(' ', f);
|
||||
fputc(kGodHatesFlags[i][0], f);
|
||||
fputc(kGodHatesFlags[i][1], f);
|
||||
}
|
||||
efl >>= 1;
|
||||
}
|
||||
(fprintf)(f, " %s%d\n", "IOPL", efl & 3);
|
||||
}
|
||||
|
||||
relegated static void showgeneralregisters(FILE *f, ucontext_t *ctx) {
|
||||
size_t i, j, k;
|
||||
long double st;
|
||||
fputc('\n', f);
|
||||
for (i = 0, j = 0, k = 0; i < ARRAYLEN(kGregNames); ++i) {
|
||||
if (j > 0) {
|
||||
fputc(' ', f);
|
||||
}
|
||||
(fprintf)(f, "%-3s %016lx", kGregNames[(unsigned)kGregOrder[i]],
|
||||
ctx->uc_mcontext.gregs[(unsigned)kGregOrder[i]]);
|
||||
if (++j == 3) {
|
||||
j = 0;
|
||||
memcpy(&st, (char *)&ctx->fpustate.st[k], sizeof(st));
|
||||
(fprintf)(f, " %s(%zu) %Lf", "ST", k, st);
|
||||
++k;
|
||||
fputc('\r', f);
|
||||
fputc('\n', f);
|
||||
}
|
||||
}
|
||||
fflush(stderr);
|
||||
describecpuflags(f, ctx->uc_mcontext.gregs[REG_EFL]);
|
||||
}
|
||||
|
||||
relegated static void showsseregisters(FILE *f, ucontext_t *ctx) {
|
||||
size_t i;
|
||||
fputc('\n', f);
|
||||
for (i = 0; i < 8; ++i) {
|
||||
(fprintf)(f, VEIL("r", "%s%-2zu %016lx%016lx %s%-2d %016lx%016lx\n"), "XMM",
|
||||
i + 0, ctx->fpustate.xmm[i + 0].u64[0],
|
||||
ctx->fpustate.xmm[i + 0].u64[1], "XMM", i + 8,
|
||||
ctx->fpustate.xmm[i + 8].u64[0], ctx->fpustate.xmm[i + 8].u64[1]);
|
||||
}
|
||||
}
|
||||
|
||||
relegated static void showmemorymappings(FILE *f) {
|
||||
int c;
|
||||
FILE *f2;
|
||||
if (!IsTiny()) {
|
||||
showmappings(f);
|
||||
if (IsLinux()) {
|
||||
if ((f2 = fopen("/proc/self/maps", "r"))) {
|
||||
while ((c = fgetc(f2)) != -1) {
|
||||
if (fputc(c, f) == -1) break;
|
||||
}
|
||||
}
|
||||
fclose(f2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
relegated static void showcrashreport(int err, FILE *f, int sig,
|
||||
ucontext_t *ctx) {
|
||||
struct utsname names;
|
||||
(fprintf)(f, VEIL("r", "\n%serror%s: Uncaught SIG%s\n %s\n %s\n"), RED2,
|
||||
RESET, tinystrsignal(sig), getauxval(AT_EXECFN), strerror(err));
|
||||
if (uname(&names) != -1) {
|
||||
(fprintf)(f, VEIL("r", " %s %s %s %s\n"), names.sysname, names.nodename,
|
||||
names.release, names.version);
|
||||
}
|
||||
showfunctioncalls(f, ctx);
|
||||
if (ctx) {
|
||||
showgeneralregisters(f, ctx);
|
||||
showsseregisters(f, ctx);
|
||||
}
|
||||
fputc('\n', f);
|
||||
memsummary(f);
|
||||
showmemorymappings(f);
|
||||
}
|
||||
|
||||
relegated static void restoredefaultcrashsignalhandlers(void) {
|
||||
size_t i;
|
||||
sigset_t ss;
|
||||
sigemptyset(&ss);
|
||||
sigprocmask(SIG_SETMASK, &ss, NULL);
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
if (kCrashSigs[i]) sigaction(kCrashSigs[i], &g_oldcrashacts[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crashes in a developer-friendly human-centric way.
|
||||
*
|
||||
* We first try to launch GDB if it's an interactive development
|
||||
* session. Otherwise we show a really good crash report, sort of like
|
||||
* Python, that includes filenames and line numbers. Many editors, e.g.
|
||||
* Emacs, will even recognize its syntax for quick hopping to the
|
||||
* failing line. That's only possible if the the .com.dbg file is in the
|
||||
* same folder. If the concomitant debug binary can't be found, we
|
||||
* simply print addresses which may be cross-referenced using objdump.
|
||||
*
|
||||
* This function never returns, except for traps w/ human supervision.
|
||||
*/
|
||||
relegated void oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
||||
intptr_t rip;
|
||||
int gdbpid, err;
|
||||
static bool once;
|
||||
err = errno;
|
||||
g_runstate |= RUNSTATE_BROKEN;
|
||||
if (once) abort();
|
||||
once = true;
|
||||
/* TODO(jart): Needs translation for ucontext_t and possibly siginfo_t. */
|
||||
if (IsFreebsd() || IsOpenbsd()) ctx = NULL;
|
||||
rip = ctx ? ctx->uc_mcontext.rip : 0;
|
||||
if ((gdbpid = IsDebuggerPresent(true))) {
|
||||
DebugBreak();
|
||||
} else if (isterminalinarticulate() || isrunningundermake()) {
|
||||
gdbpid = -1;
|
||||
} else {
|
||||
restoredefaultcrashsignalhandlers();
|
||||
gdbpid =
|
||||
attachdebugger(((sig == SIGTRAP || sig == SIGQUIT) &&
|
||||
(rip >= (intptr_t)&_base && rip < (intptr_t)&_etext))
|
||||
? rip
|
||||
: 0);
|
||||
}
|
||||
if (gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT)) return;
|
||||
showcrashreport(err, stderr, sig, ctx);
|
||||
quick_exit(128 + sig);
|
||||
unreachable;
|
||||
}
|
92
libc/log/oncrashthunks.S
Normal file
92
libc/log/oncrashthunks.S
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
/ These function names make it a bit more obvious which signal
|
||||
/ caused the crash, particularly in the GDB GUI. They're coded
|
||||
/ into an array to pinch pennies on code size registering them.
|
||||
|
||||
kOncrashThunks:
|
||||
|
||||
.org 11*0
|
||||
oncrash_sigquit:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigquit,globl
|
||||
|
||||
.org 11*1
|
||||
oncrash_sigfpe:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigfpe,globl
|
||||
|
||||
.org 11*2
|
||||
oncrash_sigill:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigill,globl
|
||||
|
||||
.org 11*3
|
||||
oncrash_sigsegv:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigsegv,globl
|
||||
|
||||
.org 11*4
|
||||
oncrash_sigtrap:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigtrap,globl
|
||||
|
||||
.org 11*5
|
||||
oncrash_sigabrt:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigabrt,globl
|
||||
|
||||
.org 11*6
|
||||
oncrash_sigbus:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call oncrash
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn oncrash_sigbus,globl
|
||||
|
||||
.endobj kOncrashThunks,globl
|
69
libc/log/onkill.c
Normal file
69
libc/log/onkill.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Default handlers for normal termination signals.
|
||||
* @note This gets linked when __cxa_atexit() is linked.
|
||||
* @see also libc/oncrash.c
|
||||
*/
|
||||
|
||||
struct ucontext;
|
||||
struct siginfo;
|
||||
|
||||
static const int sigs[] = {
|
||||
SIGHUP, /* hangup aka ctrl_close_event */
|
||||
SIGINT, /* ctrl+c aka ^C aka ETX aka \003 aka ♥ */
|
||||
SIGTERM /* kill (default signal) */
|
||||
};
|
||||
|
||||
textexit static void __onkill(int sig, struct siginfo *si,
|
||||
struct ucontext *context) {
|
||||
/* https://www.tldp.org/LDP/abs/html/exitcodes.html */
|
||||
exit(128 + sig);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs default handlers for friendly kill signals.
|
||||
* @see showcrashreports()
|
||||
*/
|
||||
void callexitontermination(sigset_t *opt_out_exitsigs) {
|
||||
struct sigaction sa;
|
||||
if (opt_out_exitsigs) sigemptyset(opt_out_exitsigs);
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_sigaction = __onkill;
|
||||
sa.sa_flags = SA_RESETHAND;
|
||||
for (unsigned i = 0; i < ARRAYLEN(sigs); ++i) {
|
||||
if (!sigs[i]) continue;
|
||||
if (opt_out_exitsigs) sigaddset(opt_out_exitsigs, sigs[i]);
|
||||
sigaction(sigs[i], &sa, NULL);
|
||||
}
|
||||
}
|
28
libc/log/perror.c
Normal file
28
libc/log/perror.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void perror(const char *message) {
|
||||
fprintf(stderr, "%s%s%s: %s: %m: %s\n", RED2, "error", RESET,
|
||||
program_invocation_name, message);
|
||||
}
|
58
libc/log/shadowargs.greg.c
Normal file
58
libc/log/shadowargs.greg.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/log/shadowargs.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/symbols.h"
|
||||
|
||||
alignas(1) const
|
||||
char __shadowargs_slotnames[SHADOWARGS_SLOTS][SHADOWARGS_MAXNAME] = {
|
||||
"func", "%rsp", "%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9",
|
||||
};
|
||||
alignas(64) struct ShadowArgs __shadowargs[SHADOWARGS_COUNT];
|
||||
unsigned __shadowargs_index;
|
||||
|
||||
nocallersavedregisters void __fentry__(uint64_t rdi, uint64_t rsi, uint64_t rdx,
|
||||
uint64_t rcx, uint64_t r8, uint64_t r9) {
|
||||
void *addr = __builtin_return_address(0);
|
||||
intptr_t frame = (intptr_t)__builtin_frame_address(0);
|
||||
unsigned i = __shadowargs_index;
|
||||
intptr_t lastframe = (intptr_t)__shadowargs[i].frame;
|
||||
if (frame < lastframe) {
|
||||
i--;
|
||||
i &= SHADOWARGS_COUNT - 1;
|
||||
} else if (frame > lastframe) {
|
||||
unsigned j = i;
|
||||
do {
|
||||
j++;
|
||||
j &= SHADOWARGS_COUNT - 1;
|
||||
} while (frame > (intptr_t)__shadowargs[j].frame && j != i);
|
||||
i = j;
|
||||
}
|
||||
__shadowargs[i].addr = addr;
|
||||
__shadowargs[i].frame = (void *)frame;
|
||||
__shadowargs[i].arg1 = rdi;
|
||||
__shadowargs[i].arg2 = rsi;
|
||||
__shadowargs[i].arg3 = rdx;
|
||||
__shadowargs[i].arg4 = rcx;
|
||||
__shadowargs[i].arg5 = r8;
|
||||
__shadowargs[i].arg6 = r9;
|
||||
__shadowargs_index = i;
|
||||
}
|
53
libc/log/shadowargs.h
Normal file
53
libc/log/shadowargs.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef COSMOPOLITAN_LIBC_SHADOWARGS_H_
|
||||
#define COSMOPOLITAN_LIBC_SHADOWARGS_H_
|
||||
|
||||
#define SHADOWARGS_COUNT 32
|
||||
#define SHADOWARGS_SLOTS 8
|
||||
#define SHADOWARGS_MAXNAME 5
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct ShadowArgs {
|
||||
union {
|
||||
unsigned long slots[SHADOWARGS_SLOTS];
|
||||
struct {
|
||||
void *addr;
|
||||
void *frame;
|
||||
unsigned long arg1;
|
||||
unsigned long arg2;
|
||||
unsigned long arg3;
|
||||
unsigned long arg4;
|
||||
unsigned long arg5;
|
||||
unsigned long arg6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hidden extern unsigned __shadowargs_index;
|
||||
hidden extern struct ShadowArgs __shadowargs[SHADOWARGS_COUNT];
|
||||
hidden extern const char __shadowargs_slotnames[SHADOWARGS_SLOTS]
|
||||
[SHADOWARGS_MAXNAME];
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SHADOWARGS_H_ */
|
78
libc/log/showcrashreports.c
Normal file
78
libc/log/showcrashreports.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/nt/signals.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
extern const unsigned char kOncrashThunks[7][11];
|
||||
|
||||
/**
|
||||
* Installs crash signal handlers.
|
||||
*
|
||||
* Normally, only functions calling die() will print backtraces. This
|
||||
* function may be called at program startup to install handlers that
|
||||
* will display similar information, for most types of crashes.
|
||||
*
|
||||
* - Backtraces
|
||||
* - CPU state printout
|
||||
* - Automatic debugger attachment
|
||||
*
|
||||
* Another trick this function enables, is you can press CTRL+\ to open
|
||||
* the debugger GUI at any point while the program is running. It can be
|
||||
* useful, for example, if a program is caught in an infinite loop.
|
||||
*
|
||||
* @see callexitontermination()
|
||||
*/
|
||||
optimizesize void showcrashreports(void) {
|
||||
size_t i;
|
||||
struct sigaction sa;
|
||||
if (IsModeDbg()) STATIC_YOINK("__ubsan_abort");
|
||||
if (!NoDebug()) STATIC_YOINK("die");
|
||||
/* <SYNC-LIST>: oncrashthunks.S */
|
||||
kCrashSigs[0] = SIGQUIT; /* ctrl+\ aka ctrl+break */
|
||||
kCrashSigs[1] = SIGFPE; /* 1 / 0 */
|
||||
kCrashSigs[2] = SIGILL; /* illegal instruction */
|
||||
kCrashSigs[3] = SIGSEGV; /* bad memory access */
|
||||
kCrashSigs[4] = SIGTRAP; /* bad system call */
|
||||
kCrashSigs[5] = SIGABRT; /* abort() called */
|
||||
kCrashSigs[6] = SIGBUS; /* misaligned, noncanonical ptr, etc. */
|
||||
/* </SYNC-LIST>: oncrashthunks.S */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_flags = SA_RESETHAND;
|
||||
sigfillset(&sa.sa_mask);
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
sigdelset(&sa.sa_mask, kCrashSigs[i]);
|
||||
}
|
||||
for (i = 0; i < ARRAYLEN(kCrashSigs); ++i) {
|
||||
if (kCrashSigs[i]) {
|
||||
sa.sa_sigaction = (sigaction_f)kOncrashThunks[i];
|
||||
sigaction(kCrashSigs[i], &sa, &g_oldcrashacts[i]);
|
||||
}
|
||||
}
|
||||
}
|
58
libc/log/showmappings.c
Normal file
58
libc/log/showmappings.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/mappings.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
||||
/**
|
||||
* Displays memory mappings in a way that's readable.
|
||||
*
|
||||
* It's readable because (1) map sizes are in bytes bytes with thousand
|
||||
* separators; (2) output is valid code; (3) memory addresses aren't
|
||||
* obfuscated; (4) we only need 8 hex digits to display each 64kb
|
||||
* granular 48-bit NexGen32e pointer; (5) ranges are inclusive; and (6)
|
||||
* gaps are made apparent.
|
||||
*/
|
||||
void showmappings(FILE *f) {
|
||||
size_t i, bytes, maptally, gaptally;
|
||||
maptally = 0;
|
||||
gaptally = 0;
|
||||
(fprintf)(f, "%s%zu%s\n", "_mm.i == ", _mm.i, ";");
|
||||
for (i = 0; i < _mm.i; ++i) {
|
||||
if (i && _mm.p[i].x != _mm.p[i - 1].y + 1) {
|
||||
bytes = _mm.p[i].x - _mm.p[i - 1].y - 1;
|
||||
bytes *= FRAMESIZE;
|
||||
gaptally += bytes;
|
||||
(fprintf)(f, "%s%,9zu%s\n", "/* ", bytes, " */");
|
||||
}
|
||||
bytes = _mm.p[i].y - _mm.p[i].x + 1;
|
||||
bytes *= FRAMESIZE;
|
||||
maptally += bytes;
|
||||
(fprintf)(f, "%s%3u%s0x%08x,0x%08x};%s%,9zu%s\n", "_mm.p[", i, "]=={",
|
||||
_mm.p[i].x, _mm.p[i].y, " /* ", bytes, " */");
|
||||
}
|
||||
(fprintf)(f, "%s%,zu%s%,zu%s\n", "/* ", maptally, " bytes mapped w/ ",
|
||||
gaptally, " bytes gapped */");
|
||||
fprintf(f, "\n");
|
||||
}
|
34
libc/log/startfatal.c
Normal file
34
libc/log/startfatal.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* Prints initial part of fatal message.
|
||||
*
|
||||
* @note this is support code for __check_fail(), __assert_fail(), etc.
|
||||
* @see startfatal_ndebug()
|
||||
*/
|
||||
relegated void startfatal(const char *file, int line) {
|
||||
fflush(stdout);
|
||||
fprintf(stderr, "%s%s%s:%s:%d:%s%s: ", RED, "error", BLUE1, file, line,
|
||||
program_invocation_short_name, RESET);
|
||||
}
|
37
libc/log/startfatal_ndebug.c
Normal file
37
libc/log/startfatal_ndebug.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Prints initial part of fatal message.
|
||||
*
|
||||
* @note this is support code for __check_fail(), __assert_fail(), etc.
|
||||
* @see startfatal()
|
||||
*/
|
||||
relegated void startfatal_ndebug(void) {
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
stderr->bufmode = _IOFBF;
|
||||
fprintf(stderr, "%s%s%s:%s%s: ", RED, "error", BLUE1, program_invocation_name,
|
||||
RESET);
|
||||
}
|
28
libc/log/thunks/__check_fail_eq.S
Normal file
28
libc/log/thunks/__check_fail_eq.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_EQ() in NDEBUG mode.
|
||||
__check_fail_eq:
|
||||
loadstr "==",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_eq,globl
|
28
libc/log/thunks/__check_fail_ge.S
Normal file
28
libc/log/thunks/__check_fail_ge.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_GE() in NDEBUG mode.
|
||||
__check_fail_ge:
|
||||
loadstr ">=",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_ge,globl
|
28
libc/log/thunks/__check_fail_gt.S
Normal file
28
libc/log/thunks/__check_fail_gt.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_GT() in NDEBUG mode.
|
||||
__check_fail_gt:
|
||||
loadstr ">",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_gt,globl
|
28
libc/log/thunks/__check_fail_le.S
Normal file
28
libc/log/thunks/__check_fail_le.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_LE() in NDEBUG mode.
|
||||
__check_fail_le:
|
||||
loadstr "<=",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_le,globl
|
28
libc/log/thunks/__check_fail_lt.S
Normal file
28
libc/log/thunks/__check_fail_lt.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_LT() in NDEBUG mode.
|
||||
__check_fail_lt:
|
||||
loadstr "<",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_lt,globl
|
29
libc/log/thunks/__check_fail_ndebug.S
Normal file
29
libc/log/thunks/__check_fail_ndebug.S
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.yoink __FILE__
|
||||
|
||||
__check_fail_ndebug:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
call ___check_fail_ndebug
|
||||
pop %rbp
|
||||
jmp die # fewer elements in backtrace
|
||||
.endfn __check_fail_ndebug,globl
|
28
libc/log/thunks/__check_fail_ne.S
Normal file
28
libc/log/thunks/__check_fail_ne.S
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
/ Code-size saving thunk for CHECK_NE() in NDEBUG mode.
|
||||
__check_fail_ne:
|
||||
loadstr "!=",dx
|
||||
jmp __check_fail_ndebug
|
||||
.endfn __check_fail_ne,globl
|
122
libc/log/ubsan.c
Normal file
122
libc/log/ubsan.c
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/log/ubsan.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/missioncritical.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
static char __ubsan_buf[256];
|
||||
|
||||
static const char kUbsanTypeCheckKinds[] = "load of\0"
|
||||
"store to\0"
|
||||
"reference binding to\0"
|
||||
"member access within\0"
|
||||
"member call on\0"
|
||||
"constructor call on\0"
|
||||
"downcast of\0"
|
||||
"downcast of\0"
|
||||
"upcast of\0"
|
||||
"cast to virtual base of\0"
|
||||
"\0";
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *loc,
|
||||
const char *description) {
|
||||
static bool once;
|
||||
if (!once) {
|
||||
once = true;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
g_runstate |= RUNSTATE_BROKEN;
|
||||
if (IsDebuggerPresent(false)) DebugBreak();
|
||||
startfatal(loc->file, loc->line);
|
||||
fprintf(stderr, "%s\n", description);
|
||||
die();
|
||||
unreachable;
|
||||
}
|
||||
|
||||
void __ubsan_handle_out_of_bounds(struct UbsanOutOfBoundsInfo *info,
|
||||
uintptr_t index) {
|
||||
snprintf(__ubsan_buf, sizeof(__ubsan_buf),
|
||||
"%s index %,lu into %s out of bounds", info->index_type->name, index,
|
||||
info->array_type->name);
|
||||
__ubsan_abort(&info->location, __ubsan_buf);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *type_mismatch,
|
||||
uintptr_t pointer) {
|
||||
struct UbsanSourceLocation *loc = &type_mismatch->location;
|
||||
const char *description;
|
||||
const char *kind = indexdoublenulstring(kUbsanTypeCheckKinds,
|
||||
type_mismatch->type_check_kind);
|
||||
if (pointer == 0) {
|
||||
description = "null pointer access";
|
||||
} else if (type_mismatch->alignment != 0 &&
|
||||
(pointer & (type_mismatch->alignment - 1))) {
|
||||
description = __ubsan_buf;
|
||||
snprintf(__ubsan_buf, sizeof(__ubsan_buf), "%s %s %s @%p %s %d",
|
||||
"unaligned", kind, type_mismatch->type->name, pointer, "align",
|
||||
type_mismatch->alignment);
|
||||
} else {
|
||||
description = __ubsan_buf;
|
||||
snprintf(__ubsan_buf, sizeof(__ubsan_buf), "%s\n\t%s %s %p %s %s",
|
||||
"insufficient size", kind, "address", pointer,
|
||||
"with insufficient space for object of type",
|
||||
type_mismatch->type->name);
|
||||
}
|
||||
__ubsan_abort(loc, description);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
void ___ubsan_handle_type_mismatch_v1(
|
||||
struct UbsanTypeMismatchInfoClang *type_mismatch, uintptr_t pointer) {
|
||||
struct UbsanTypeMismatchInfo mm;
|
||||
mm.location = type_mismatch->location;
|
||||
mm.type = type_mismatch->type;
|
||||
mm.alignment = 1u << type_mismatch->log_alignment;
|
||||
mm.type_check_kind = type_mismatch->type_check_kind;
|
||||
__ubsan_handle_type_mismatch(&mm, pointer);
|
||||
unreachable;
|
||||
}
|
||||
|
||||
void __ubsan_handle_float_cast_overflow(void *data_raw, void *from_raw) {
|
||||
struct UbsanFloatCastOverflowData *data =
|
||||
(struct UbsanFloatCastOverflowData *)data_raw;
|
||||
#if __GNUC__ + 0 >= 6
|
||||
__ubsan_abort(&data->location, "float cast overflow");
|
||||
#else
|
||||
const struct UbsanSourceLocation kUnknownLocation = {
|
||||
"<unknown file>",
|
||||
pushpop(0),
|
||||
pushpop(0),
|
||||
};
|
||||
__ubsan_abort(((void)data, &kUnknownLocation), "float cast overflow");
|
||||
#endif
|
||||
unreachable;
|
||||
}
|
110
libc/log/ubsan.h
Normal file
110
libc/log/ubsan.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_UBSAN_H_
|
||||
#define COSMOPOLITAN_LIBC_UBSAN_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § runtime » behavior enforcement ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
struct UbsanSourceLocation {
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct UbsanTypeDescriptor {
|
||||
uint16_t kind;
|
||||
uint16_t info;
|
||||
char name[];
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
uintptr_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanTypeMismatchInfoClang {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
unsigned char log_alignment; /* https://reviews.llvm.org/D28244 */
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsInfo {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *array_type;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanUnreachableData {
|
||||
struct UbsanSourceLocation location;
|
||||
};
|
||||
|
||||
struct UbsanVlaBoundData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullArgData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanCfiBadIcallData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanNonnullReturnData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanSourceLocation attr_location;
|
||||
};
|
||||
|
||||
struct UbsanFunctionTypeMismatchData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanInvalidValueData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanOverflowData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *type;
|
||||
};
|
||||
|
||||
struct UbsanFloatCastOverflowData {
|
||||
#if __GNUC__ + 0 >= 6
|
||||
struct UbsanSourceLocation location;
|
||||
#endif
|
||||
struct UbsanTypeDescriptor *from_type;
|
||||
struct UbsanTypeDescriptor *to_type;
|
||||
};
|
||||
|
||||
struct UbsanOutOfBoundsData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *arraytype;
|
||||
struct UbsanTypeDescriptor *index_type;
|
||||
};
|
||||
|
||||
struct UbsanShiftOutOfBoundsData {
|
||||
struct UbsanSourceLocation location;
|
||||
struct UbsanTypeDescriptor *lhs_type;
|
||||
struct UbsanTypeDescriptor *rhs_type;
|
||||
};
|
||||
|
||||
void __ubsan_abort(const struct UbsanSourceLocation *,
|
||||
const char *) relegated hidden noreturn;
|
||||
void __ubsan_handle_type_mismatch(struct UbsanTypeMismatchInfo *,
|
||||
uintptr_t) relegated hidden noreturn;
|
||||
void ___ubsan_handle_type_mismatch_v1(struct UbsanTypeMismatchInfoClang *,
|
||||
uintptr_t) relegated hidden noreturn;
|
||||
void __ubsan_handle_float_cast_overflow(void *,
|
||||
void *) relegated hidden noreturn;
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_UBSAN_H_ */
|
266
libc/log/ubsanjmp.S
Normal file
266
libc/log/ubsanjmp.S
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.unlikely
|
||||
.yoink __FILE__
|
||||
|
||||
__ubsan_default_options:
|
||||
ret
|
||||
.endfn __ubsan_default_options
|
||||
|
||||
__ubsan_on_report:
|
||||
ret
|
||||
.endfn __ubsan_on_report,globl
|
||||
|
||||
__ubsan_get_current_report_data:
|
||||
xor %eax,%eax
|
||||
ret
|
||||
.endfn __ubsan_get_current_report_data,globl
|
||||
|
||||
__ubsan_handle_type_mismatch_abort:
|
||||
jmp __ubsan_handle_type_mismatch
|
||||
.endfn __ubsan_handle_type_mismatch_abort,globl
|
||||
|
||||
__ubsan_handle_float_cast_overflow_abort:
|
||||
jmp __ubsan_handle_float_cast_overflow
|
||||
.endfn __ubsan_handle_float_cast_overflow_abort,globl
|
||||
|
||||
__ubsan_handle_type_mismatch_v1:
|
||||
__ubsan_handle_type_mismatch_v1_abort:
|
||||
jmp ___ubsan_handle_type_mismatch_v1
|
||||
.endfn __ubsan_handle_type_mismatch_v1,globl
|
||||
.endfn __ubsan_handle_type_mismatch_v1_abort,globl
|
||||
|
||||
__ubsan_handle_add_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_add_overflow_abort,globl
|
||||
__ubsan_handle_add_overflow:
|
||||
loadstr "add_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_add_overflow,globl
|
||||
|
||||
__ubsan_handle_alignment_assumption_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_alignment_assumption_abort,globl
|
||||
__ubsan_handle_alignment_assumption:
|
||||
loadstr "alignment_assumption",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_alignment_assumption,globl
|
||||
|
||||
__ubsan_handle_builtin_unreachable_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_builtin_unreachable_abort,globl
|
||||
__ubsan_handle_builtin_unreachable:
|
||||
loadstr "builtin_unreachable",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_builtin_unreachable,globl
|
||||
|
||||
__ubsan_handle_cfi_bad_type_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_cfi_bad_type_abort,globl
|
||||
__ubsan_handle_cfi_bad_type:
|
||||
loadstr "cfi_bad_type",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_cfi_bad_type,globl
|
||||
|
||||
__ubsan_handle_cfi_check_fail_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_cfi_check_fail_abort,globl
|
||||
__ubsan_handle_cfi_check_fail:
|
||||
loadstr "cfi_check_fail",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_cfi_check_fail,globl
|
||||
|
||||
__ubsan_handle_divrem_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_divrem_overflow_abort,globl
|
||||
__ubsan_handle_divrem_overflow:
|
||||
loadstr "divrem_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_divrem_overflow,globl
|
||||
|
||||
__ubsan_handle_dynamic_type_cache_miss_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss_abort,globl
|
||||
__ubsan_handle_dynamic_type_cache_miss:
|
||||
loadstr "dynamic_type_cache_miss",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_dynamic_type_cache_miss,globl
|
||||
|
||||
__ubsan_handle_function_type_mismatch_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_function_type_mismatch_abort,globl
|
||||
__ubsan_handle_function_type_mismatch:
|
||||
loadstr "function_type_mismatch",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_function_type_mismatch,globl
|
||||
|
||||
__ubsan_handle_implicit_conversion_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_implicit_conversion_abort,globl
|
||||
__ubsan_handle_implicit_conversion:
|
||||
loadstr "implicit_conversion",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_implicit_conversion,globl
|
||||
|
||||
__ubsan_handle_invalid_builtin_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_invalid_builtin_abort,globl
|
||||
__ubsan_handle_invalid_builtin:
|
||||
loadstr "invalid_builtin",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_invalid_builtin,globl
|
||||
|
||||
__ubsan_handle_load_invalid_value_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_load_invalid_value_abort,globl
|
||||
__ubsan_handle_load_invalid_value:
|
||||
loadstr "load_invalid_value (try checking for uninitialized variables)",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_load_invalid_value,globl
|
||||
|
||||
__ubsan_handle_missing_return_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_missing_return_abort,globl
|
||||
__ubsan_handle_missing_return:
|
||||
loadstr "missing_return",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_missing_return,globl
|
||||
|
||||
__ubsan_handle_mul_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_mul_overflow_abort,globl
|
||||
__ubsan_handle_mul_overflow:
|
||||
loadstr "mul_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_mul_overflow,globl
|
||||
|
||||
__ubsan_handle_negate_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_negate_overflow_abort,globl
|
||||
__ubsan_handle_negate_overflow:
|
||||
loadstr "negate_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_negate_overflow,globl
|
||||
|
||||
__ubsan_handle_nonnull_arg_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_nonnull_arg_abort,globl
|
||||
__ubsan_handle_nonnull_arg:
|
||||
loadstr "nonnull_arg",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_nonnull_arg,globl
|
||||
|
||||
__ubsan_handle_nonnull_return_v1_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return_v1_abort,globl
|
||||
__ubsan_handle_nonnull_return_v1:
|
||||
loadstr "nonnull_return_v1",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_nonnull_return_v1,globl
|
||||
|
||||
__ubsan_hop:
|
||||
jmp __ubsan_abort
|
||||
.endfn __ubsan_hop
|
||||
|
||||
__ubsan_handle_nullability_arg_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_nullability_arg_abort,globl
|
||||
__ubsan_handle_nullability_arg:
|
||||
loadstr "nullability_arg",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_nullability_arg,globl
|
||||
|
||||
__ubsan_handle_nullability_return_v1_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_nullability_return_v1_abort,globl
|
||||
__ubsan_handle_nullability_return_v1:
|
||||
loadstr "nullability_return_v1",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_nullability_return_v1,globl
|
||||
|
||||
__ubsan_handle_pointer_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_pointer_overflow_abort,globl
|
||||
__ubsan_handle_pointer_overflow:
|
||||
loadstr "pointer_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_pointer_overflow,globl
|
||||
|
||||
__ubsan_handle_shift_out_of_bounds_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_shift_out_of_bounds_abort,globl
|
||||
__ubsan_handle_shift_out_of_bounds:
|
||||
loadstr "shift_out_of_bounds",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_shift_out_of_bounds,globl
|
||||
|
||||
__ubsan_handle_sub_overflow_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_sub_overflow_abort,globl
|
||||
__ubsan_handle_sub_overflow:
|
||||
loadstr "sub_overflow",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_sub_overflow,globl
|
||||
|
||||
__ubsan_handle_vla_bound_not_positive_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_vla_bound_not_positive_abort,globl
|
||||
__ubsan_handle_vla_bound_not_positive:
|
||||
loadstr "vla_bound_not_positive",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_vla_bound_not_positive,globl
|
||||
|
||||
__ubsan_handle_nonnull_return_abort:
|
||||
nop
|
||||
/ fallthrough
|
||||
.endfn __ubsan_handle_nonnull_return_abort,globl
|
||||
__ubsan_handle_nonnull_return:
|
||||
loadstr "nonnull_return",si
|
||||
jmp __ubsan_hop
|
||||
.endfn __ubsan_handle_nonnull_return,globl
|
||||
|
||||
__ubsan_handle_out_of_bounds_abort:
|
||||
jmp __ubsan_handle_out_of_bounds
|
||||
.endfn __ubsan_handle_out_of_bounds_abort,globl
|
||||
|
||||
.previous
|
31
libc/log/verr.c
Normal file
31
libc/log/verr.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
noreturn void(verr)(int eval, const char *fmt, va_list va) {
|
||||
fprintf(stderr, "%s: %s%s%s[%m]: ", program_invocation_name, RED2, "ERROR",
|
||||
RESET);
|
||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
exit(eval);
|
||||
}
|
31
libc/log/verrx.c
Normal file
31
libc/log/verrx.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
noreturn void(verrx)(int eval, const char *fmt, va_list va) {
|
||||
fprintf(stderr, "%s: %s%s%s: ", program_invocation_name, RED2, "ERROR",
|
||||
RESET);
|
||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
exit(eval);
|
||||
}
|
116
libc/log/vflogf.c
Normal file
116
libc/log/vflogf.c
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
#define kNontrivialSize (8 * 1000 * 1000)
|
||||
|
||||
static int loglevel2char(unsigned level) {
|
||||
switch (level) {
|
||||
case kLogInfo:
|
||||
return 'I';
|
||||
case kLogDebug:
|
||||
return 'D';
|
||||
case kLogWarn:
|
||||
return 'W';
|
||||
case kLogFatal:
|
||||
return 'F';
|
||||
default:
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes corrective action if logging is on the fritz.
|
||||
*/
|
||||
void vflogf_onfail(FILE *f) {
|
||||
errno_t err;
|
||||
struct stat st;
|
||||
if (IsTiny()) return;
|
||||
err = ferror(f);
|
||||
if ((err == ENOSPC || err == EDQUOT || err == EFBIG) &&
|
||||
(fstat(fileno(f), &st) == -1 || st.st_size > kNontrivialSize)) {
|
||||
ftruncate(fileno(f), 0);
|
||||
fseek(f, SEEK_SET, 0);
|
||||
f->beg = f->end = 0;
|
||||
clearerr(f);
|
||||
(fprintf)(f, "performed emergency log truncation: %s\n", strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes formatted message w/ timestamp to log.
|
||||
*/
|
||||
void(vflogf)(unsigned level, const char *file, int line, FILE *f,
|
||||
const char *fmt, va_list va) {
|
||||
static struct timespec ts;
|
||||
struct tm tm;
|
||||
long double t2;
|
||||
const char *prog;
|
||||
int64_t secs, nsec, dots;
|
||||
char zonebuf[8], *zonebufp;
|
||||
char timebuf[24], *timebufp;
|
||||
if (!f) f = g_logfile;
|
||||
if (fileno(f) == -1) return;
|
||||
t2 = nowl();
|
||||
secs = t2;
|
||||
nsec = mod1000000000int64(t2 * 1e9L);
|
||||
if (secs > ts.tv_sec) {
|
||||
localtime_r(&secs, &tm);
|
||||
strftime(timebuf, sizeof(timebuf), "%Y%m%dT%H%M%S", &tm);
|
||||
strftime(zonebuf, sizeof(zonebuf), "%Z", &tm);
|
||||
timebufp = timebuf;
|
||||
zonebufp = zonebuf;
|
||||
dots = nsec;
|
||||
} else {
|
||||
timebufp = "---------------";
|
||||
zonebufp = "---";
|
||||
dots = nsec - ts.tv_nsec;
|
||||
}
|
||||
ts.tv_sec = secs;
|
||||
ts.tv_nsec = nsec;
|
||||
prog = basename(program_invocation_name);
|
||||
if (fprintf(f, "%c%s%s%06ld:%s:%d:%.*s:%d] ", loglevel2char(level), timebufp,
|
||||
zonebufp, mod1000000int64(div1000int64(dots)), file, line,
|
||||
strchrnul(prog, '.') - prog, prog, getpid()) <= 0) {
|
||||
vflogf_onfail(f);
|
||||
}
|
||||
(vfprintf)(f, fmt, va);
|
||||
va_end(va);
|
||||
fputc('\n', f);
|
||||
if (level == kLogFatal) {
|
||||
die();
|
||||
unreachable;
|
||||
}
|
||||
}
|
30
libc/log/vwarn.c
Normal file
30
libc/log/vwarn.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void(vwarn)(const char *fmt, va_list va) {
|
||||
fprintf(stderr, "%s: %s%s%s[%m]: ", program_invocation_name, SUBTLE,
|
||||
"WARNING", RESET);
|
||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
30
libc/log/vwarnx.c
Normal file
30
libc/log/vwarnx.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
void(vwarnx)(const char *fmt, va_list va) {
|
||||
fprintf(stderr, "%s: %s%s%s: ", program_invocation_name, SUBTLE, "WARNING",
|
||||
RESET);
|
||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
27
libc/log/warn.c
Normal file
27
libc/log/warn.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
|
||||
void(warn)(const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
(vwarn)(fmt, va);
|
||||
va_end(va);
|
||||
}
|
27
libc/log/warnx.c
Normal file
27
libc/log/warnx.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/bsd.h"
|
||||
|
||||
void(warnx)(const char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
(vwarnx)(fmt, va);
|
||||
va_end(va);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue