mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Implement more security stuff
- Support deterministic stacks on OpenBSD - Support OpenBSD system call origin verification - Fix overrun by one in chibicc string token allocator - Get all chibicc tests passing under Address Sanitizer
This commit is contained in:
parent
cbfd4ccd1e
commit
c843243322
56 changed files with 376 additions and 245 deletions
|
@ -282,6 +282,9 @@ SECTIONS {
|
|||
KEEP(*(.textwindowsepilogue))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||
HIDDEN(__text_syscall_start = .);
|
||||
*(.text.syscall .text.syscall.*)
|
||||
HIDDEN(__text_syscall_end = .);
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot.*))
|
||||
KEEP(*(.keep.text))
|
||||
|
@ -483,6 +486,10 @@ SHSTUB2(.Lape.macho.dd.skip, RVA(ape.macho) / 8);
|
|||
SHSTUB2(.Lape.macho.dd.count, (.Lape.macho.end - ape.macho) / 8);
|
||||
PFSTUB4(.Lape.pe.offset, ape.pe - ape.mz);
|
||||
|
||||
HIDDEN(__text_syscall_addr = ROUNDDOWN(__text_syscall_start, PAGESIZE));
|
||||
HIDDEN(__text_syscall_size = (ROUNDUP(__text_syscall_end, PAGESIZE) -
|
||||
ROUNDDOWN(__text_syscall_start, PAGESIZE)));
|
||||
|
||||
HIDDEN(.Lape.pe.optsz = .Lape.pe.sections - (ape.pe + 24));
|
||||
HIDDEN(.Lape.pe.shnum = (.Lape.pe.sections_end - .Lape.pe.sections) / 40);
|
||||
HIDDEN(.Lidata.idtsize = idata.idtend - idata.idt);
|
||||
|
|
|
@ -94,8 +94,7 @@ CONFIG_CPPFLAGS += \
|
|||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-O1 \
|
||||
-fno-inline
|
||||
-O2
|
||||
|
||||
CONFIG_COPTS += \
|
||||
$(SECURITY_BLANKETS) \
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.syscall
|
||||
|
||||
/ Tiny Raw Linux Binary Tutorial
|
||||
/
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
* @errors ENOENT, ENOTDIR, ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see fchmod()
|
||||
* @syscall
|
||||
*/
|
||||
int chmod(const char *pathname, uint32_t mode) {
|
||||
if (!pathname) return efault();
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
* errno isn't restored to its original value, to detect prec. loss
|
||||
* @see strftime(), gettimeofday()
|
||||
* @asyncsignalsafe
|
||||
* @syscall
|
||||
*/
|
||||
int clock_gettime(int clockid, struct timespec *out_ts) {
|
||||
/* TODO(jart): Just ignore O/S for MONOTONIC and measure RDTSC on start */
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
* @param len 0 means ‘til end of file
|
||||
* @param advice can be MADV_SEQUENTIAL, MADV_RANDOM, etc.
|
||||
* @return -1 on error
|
||||
* @syscall
|
||||
*/
|
||||
int fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
|
||||
if (!IsWindows()) {
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @note limited availability on rhel5 and openbsd
|
||||
* @see ftruncate()
|
||||
* @syscall
|
||||
*/
|
||||
int fallocate(int fd, int32_t mode, int64_t offset, int64_t length) {
|
||||
int rc;
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
* @errors ENOSYS
|
||||
* @asyncsignalsafe
|
||||
* @see chmod()
|
||||
* @syscall
|
||||
*/
|
||||
int fchmod(int fd, uint32_t mode) {
|
||||
/* TODO(jart): Windows */
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see /etc/passwd for user ids
|
||||
* @see /etc/group for group ids
|
||||
* @syscall
|
||||
*/
|
||||
int fchown(int fd, uint32_t uid, uint32_t gid) {
|
||||
/* TODO(jart): Windows? */
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
* @param arg can be FD_CLOEXEC, etc. depending
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
* @syscall
|
||||
*/
|
||||
int fcntl(int fd, int cmd, ...) {
|
||||
va_list va;
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see fsync(), sync_file_range()
|
||||
* @asyncsignalsafe
|
||||
* @syscall
|
||||
*/
|
||||
int fdatasync(int fd) {
|
||||
if (!IsWindows()) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
.text.syscall
|
||||
|
||||
/ Forks process without copying page tables.
|
||||
/
|
||||
|
|
|
@ -34,7 +34,7 @@ extern __msabi typeof(VirtualProtect) *const __imp_VirtualProtect;
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see mmap()
|
||||
*/
|
||||
int mprotect(void *addr, uint64_t len, int prot) {
|
||||
textsyscall int mprotect(void *addr, uint64_t len, int prot) {
|
||||
bool cf;
|
||||
int64_t rc;
|
||||
uint32_t oldprot;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan ELF-Normative Linker Script.
|
||||
|
@ -66,6 +67,9 @@ SECTIONS {
|
|||
.text : {
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
KEEP(*(.keep.text))
|
||||
HIDDEN(__text_syscall_start = .);
|
||||
*(.text.syscall .text.syscall.*)
|
||||
HIDDEN(__text_syscall_end = .);
|
||||
*(.text .text.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.*)))
|
||||
}
|
||||
|
@ -207,3 +211,7 @@ SECTIONS {
|
|||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
HIDDEN(__text_syscall_addr = ROUNDDOWN(__text_syscall_start, PAGESIZE));
|
||||
HIDDEN(__text_syscall_size = (ROUNDUP(__text_syscall_end, PAGESIZE) -
|
||||
ROUNDDOWN(__text_syscall_start, PAGESIZE)));
|
||||
|
|
|
@ -618,6 +618,7 @@ typedef uint64_t uintmax_t;
|
|||
#define textexit _Section(".text.exit") noinstrument
|
||||
#define textreal _Section(".text.real")
|
||||
#define textwindows _Section(".text.windows")
|
||||
#define textsyscall _Section(".text.syscall")
|
||||
#define antiquity _Section(".text.antiquity")
|
||||
#else
|
||||
#define testonly
|
||||
|
|
|
@ -374,7 +374,9 @@ static const char *__asan_dscribe_heap_poison(long c) {
|
|||
}
|
||||
}
|
||||
|
||||
static const char *__asan_describe_access_poison(int c) {
|
||||
static const char *__asan_describe_access_poison(char *p) {
|
||||
int c = p[0];
|
||||
if (1 <= c && c <= 7) c = p[1];
|
||||
switch (c) {
|
||||
case kAsanHeapFree:
|
||||
return "heap use after free";
|
||||
|
@ -407,7 +409,7 @@ static const char *__asan_describe_access_poison(int c) {
|
|||
}
|
||||
}
|
||||
|
||||
static ssize_t __asan_write(const void *data, size_t size) {
|
||||
static textsyscall ssize_t __asan_write(const void *data, size_t size) {
|
||||
ssize_t rc;
|
||||
if (weaken(write)) {
|
||||
if ((rc = weaken(write)(2, data, size)) != -1) {
|
||||
|
@ -421,7 +423,7 @@ static ssize_t __asan_write_string(const char *s) {
|
|||
return __asan_write(s, __asan_strlen(s));
|
||||
}
|
||||
|
||||
static wontreturn void __asan_exit(int rc) {
|
||||
static textsyscall wontreturn void __asan_exit(int rc) {
|
||||
if (weaken(_Exit)) {
|
||||
weaken(_Exit)(rc);
|
||||
} else {
|
||||
|
@ -431,6 +433,7 @@ static wontreturn void __asan_exit(int rc) {
|
|||
}
|
||||
|
||||
static wontreturn void __asan_abort(void) {
|
||||
if (weaken(__die)) weaken(__die)();
|
||||
if (weaken(abort)) weaken(abort)();
|
||||
__asan_exit(134);
|
||||
}
|
||||
|
@ -468,7 +471,7 @@ static wontreturn void __asan_report_memory_fault(uint8_t *addr, int size,
|
|||
const char *kind) {
|
||||
char *p, ibuf[21], buf[256];
|
||||
p = __asan_report_start(buf);
|
||||
p = __asan_stpcpy(p, __asan_describe_access_poison(*SHADOW(addr)));
|
||||
p = __asan_stpcpy(p, __asan_describe_access_poison(SHADOW(addr)));
|
||||
p = __asan_stpcpy(p, " ");
|
||||
p = __asan_mempcpy(p, ibuf, __asan_int2str(size, ibuf));
|
||||
p = __asan_stpcpy(p, "-byte ");
|
||||
|
@ -524,6 +527,7 @@ static void *__asan_allocate(size_t a, size_t n, int underrun, int overrun) {
|
|||
__asan_unpoison((uintptr_t)p, n);
|
||||
__asan_poison((uintptr_t)p - 16, 16, underrun); /* see dlmalloc design */
|
||||
__asan_poison((uintptr_t)p + n, c - n, overrun);
|
||||
__asan_memset(p, 0xF9, n);
|
||||
WRITE64BE(p + c - sizeof(n), n);
|
||||
}
|
||||
return p;
|
||||
|
@ -664,6 +668,14 @@ void __asan_report_store_impl(uint8_t *addr, int size) {
|
|||
__asan_report_memory_fault(addr, size, "store");
|
||||
}
|
||||
|
||||
void __asan_poison_stack_memory(uintptr_t addr, size_t size) {
|
||||
__asan_poison(addr, size, kAsanStackFree);
|
||||
}
|
||||
|
||||
void __asan_unpoison_stack_memory(uintptr_t addr, size_t size) {
|
||||
__asan_unpoison(addr, size);
|
||||
}
|
||||
|
||||
void __asan_alloca_poison(uintptr_t addr, size_t size) {
|
||||
/* TODO(jart): Make sense of this function. */
|
||||
/* __asan_poison(addr - 32, 32, kAsanAllocaUnderrun); */
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/color.internal.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
|
||||
/**
|
||||
|
@ -29,6 +31,18 @@
|
|||
* @see __start_fatal_ndebug()
|
||||
*/
|
||||
relegated void __start_fatal(const char *file, int line) {
|
||||
dprintf(STDERR_FILENO, "%s%s%s%s:%s:%d:%s%s: ", CLS, RED, "error", BLUE1,
|
||||
file, line, program_invocation_short_name, RESET);
|
||||
char s[16 + 16 + 16 + 16 + PATH_MAX + 16 + NAME_MAX + 16], *p;
|
||||
p = stpcpy(s, CLS);
|
||||
p = stpcpy(p, RED);
|
||||
p = stpcpy(p, "error");
|
||||
p = stpcpy(p, BLUE1);
|
||||
p = stpcpy(p, ":");
|
||||
p = stpcpy(p, file);
|
||||
p = stpcpy(p, ":");
|
||||
p += int64toarray_radix10(line, p);
|
||||
p = stpcpy(p, ":");
|
||||
p = stpcpy(p, program_invocation_short_name);
|
||||
p = stpcpy(p, RESET);
|
||||
p = stpcpy(p, ": ");
|
||||
write(2, s, p - s);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
.macro .text.exit
|
||||
.section .text.exit,"ax",@progbits
|
||||
.endm
|
||||
.macro .text.syscall
|
||||
.section .text.syscall,"ax",@progbits
|
||||
.endm
|
||||
.macro .firstclass
|
||||
.section .text.hot,"ax",@progbits
|
||||
.endm
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
/*-*- mode:unix-assembly; 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 │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nexgen32e/macros.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
/ Mutates string to uppercase roman characters.
|
||||
/
|
||||
/ @param RDI points to non-const NUL-terminated string
|
||||
/ @return RAX will be original RDI
|
||||
/ @note 10x faster than C
|
||||
strtoupper:
|
||||
mov $'A-'a,%edx # adding this uppers
|
||||
mov $'a|'z<<8,%ecx # uint8_t range a..z
|
||||
jmp strcaseconv
|
||||
.endfn strtoupper,globl
|
||||
|
||||
/ Mutates string to lowercase roman characters.
|
||||
/
|
||||
/ @param RDI points to non-const NUL-terminated string
|
||||
/ @return RAX will be original RDI
|
||||
/ @note 10x faster than C
|
||||
strtolower:
|
||||
mov $'a-'A,%edx # adding this lowers
|
||||
mov $'A|'Z<<8,%ecx # uint8_t range A..Z
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
.endfn strtolower,globl
|
||||
|
||||
/ Support code for strtolower() and strtoupper().
|
||||
/
|
||||
/ @param RDI points to non-const NUL-terminated string
|
||||
/ @param CL defines start of character range to mutate
|
||||
/ @param CH defines end of character range to mutate
|
||||
/ @param DL is added to each DIL ∈ [CL,CH]
|
||||
/ @return RAX will be original RDI
|
||||
strcaseconv:
|
||||
.leafprologue
|
||||
.profilable
|
||||
mov %rdi,%rsi
|
||||
0: testb $15,%sil # is it aligned?
|
||||
#if X86_NEED(SSE4_2)
|
||||
jz .Lsse4
|
||||
#else
|
||||
jnz 1f
|
||||
testb X86_HAVE(SSE4_2)+kCpuids(%rip)
|
||||
jnz .Lsse4 # is it nehalem?
|
||||
#endif
|
||||
1: lodsb # AL = *RSI++
|
||||
test %al,%al # is it NUL?
|
||||
jz 3f
|
||||
cmp %cl,%al # is it in range?
|
||||
jb 0b
|
||||
cmp %ch,%al
|
||||
ja 0b
|
||||
add %dl,-1(%rsi)
|
||||
jmp 0b
|
||||
.Lsse4: movd %ecx,%xmm1 # XMM1 = ['A,'Z,0,0,...]
|
||||
movd %edx,%xmm2 # XMM2 = ['a-'A,'a-'A,...]
|
||||
pbroadcastb %xmm2
|
||||
xor %ecx,%ecx
|
||||
2: movdqa (%rsi,%rcx),%xmm3
|
||||
/ ┌─0:index of the LEAST significant, set, bit is used
|
||||
/ │ regardless of corresponding input element validity
|
||||
/ │ intres2 is returned in least significant bits of xmm0
|
||||
/ ├─1:index of the MOST significant, set, bit is used
|
||||
/ │ regardless of corresponding input element validity
|
||||
/ │ each bit of intres2 is expanded to byte/word
|
||||
/ │┌─0:negation of intres1 is for all 16 (8) bits
|
||||
/ │├─1:negation of intres1 is masked by reg/mem validity
|
||||
/ ││┌─intres1 is negated (1’s complement)
|
||||
/ │││┌─mode{equalany,ranges,equaleach,equalordered}
|
||||
/ ││││ ┌─issigned
|
||||
/ ││││ │┌─is16bit
|
||||
/ u│││├┐││
|
||||
pcmpistrm $0b01000100,%xmm3,%xmm1 # →XMM0 8-bit byte mask
|
||||
pand %xmm2,%xmm0 # won't mask after NUL
|
||||
paddb %xmm0,%xmm3
|
||||
movdqa %xmm3,(%rsi,%rcx)
|
||||
lea 16(%rcx),%rcx
|
||||
jnz 2b # PCMPISTRM found NUL
|
||||
3: mov %rdi,%rax
|
||||
.leafepilogue
|
||||
.endfn strcaseconv
|
||||
.source __FILE__
|
|
@ -21,7 +21,7 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/consts/nr.h"
|
||||
#include "libc/macros.h"
|
||||
.real
|
||||
.text.syscall
|
||||
.source __FILE__
|
||||
|
||||
/ Terminates program abnormally.
|
||||
|
|
|
@ -95,7 +95,7 @@ static int arch_prctl$freebsd(int code, int64_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$xnu(int code, int64_t addr) {
|
||||
static textsyscall int arch_prctl$xnu(int code, int64_t addr) {
|
||||
int ax;
|
||||
switch (code) {
|
||||
case ARCH_SET_GS:
|
||||
|
@ -113,7 +113,7 @@ static int arch_prctl$xnu(int code, int64_t addr) {
|
|||
}
|
||||
}
|
||||
|
||||
static int arch_prctl$openbsd(int code, int64_t addr) {
|
||||
static textsyscall int arch_prctl$openbsd(int code, int64_t addr) {
|
||||
int64_t rax;
|
||||
switch (code) {
|
||||
case ARCH_GET_FS:
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/macros.h"
|
||||
.privileged
|
||||
.text.syscall
|
||||
.source __FILE__
|
||||
|
||||
/ Terminates process, ignoring destructors and atexit() handlers.
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
#define WasImported(SLOT) \
|
||||
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)
|
||||
|
||||
static privileged void __print$nt(const void *data, size_t len) {
|
||||
static void __print$nt(const void *data, size_t len) {
|
||||
int64_t hand;
|
||||
char xmm[256];
|
||||
uint32_t wrote;
|
||||
|
@ -49,7 +49,7 @@ static privileged void __print$nt(const void *data, size_t len) {
|
|||
* @param len can be computed w/ tinystrlen()
|
||||
* @clob nothing except flags
|
||||
*/
|
||||
privileged void __print(const void *data, size_t len) {
|
||||
textsyscall void __print(const void *data, size_t len) {
|
||||
int64_t ax, ordinal;
|
||||
if (WasImported(__imp_WriteFile)) {
|
||||
__print$nt(data, len);
|
||||
|
@ -68,7 +68,7 @@ privileged void __print(const void *data, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
privileged void __print_string(const char *s) {
|
||||
void __print_string(const char *s) {
|
||||
size_t n = 0;
|
||||
while (s[n]) ++n;
|
||||
__print(s, n);
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
/**
|
||||
* Aborts program under enemy fire to avoid being taken alive.
|
||||
*/
|
||||
void __stack_chk_fail(void) {
|
||||
textsyscall void __stack_chk_fail(void) {
|
||||
size_t len;
|
||||
const char *msg;
|
||||
int64_t ax, cx, si;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "libc/str/oldutf16.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
/**
|
||||
* Encodes character to string as UTF-16.
|
||||
*
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
static inline noasan uint64_t UncheckedAlignedRead64(unsigned char *p) {
|
||||
return (uint64_t)p[7] << 070 | (uint64_t)p[6] << 060 | (uint64_t)p[5] << 050 |
|
||||
(uint64_t)p[4] << 040 | (uint64_t)p[3] << 030 | (uint64_t)p[2] << 020 |
|
||||
(uint64_t)p[1] << 010 | (uint64_t)p[0] << 000;
|
||||
|
|
|
@ -187,7 +187,6 @@ char16_t *tinystrstr16(const char16_t *, const char16_t *) strlenesque;
|
|||
void *tinymemmem(const void *, size_t, const void *, size_t) strlenesque;
|
||||
void *tinymemccpy(void *, const void *, int, size_t) memcpyesque;
|
||||
|
||||
void *memtolower(void *, size_t);
|
||||
char *strntolower(char *, size_t);
|
||||
char *strtolower(char *) paramsnonnull();
|
||||
char *strntoupper(char *, size_t);
|
||||
|
|
|
@ -18,16 +18,18 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates string to ASCII uppercase w/ limit.
|
||||
*
|
||||
* @praam s is string
|
||||
* @praam n is max bytes to consider
|
||||
* @return string
|
||||
*/
|
||||
char *strntoupper(char *s, size_t n) {
|
||||
unsigned char *p = (unsigned char *)s;
|
||||
for (;;) {
|
||||
if (n-- && *p) {
|
||||
if ('a' <= *p && *p <= 'z') {
|
||||
*p -= 'a' - 'A';
|
||||
}
|
||||
++p;
|
||||
} else {
|
||||
break;
|
||||
size_t i;
|
||||
for (i = 0; s[i] && i < n; ++i) {
|
||||
if ('a' <= s[i] && s[i] <= 'z') {
|
||||
s[i] -= 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
|
|
|
@ -16,9 +16,20 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
bool ctz(double x, double y) {
|
||||
return __builtin_islessgreater(x, y);
|
||||
/**
|
||||
* Mutates string to ASCII lowercase.
|
||||
*
|
||||
* @praam s is string
|
||||
* @return string
|
||||
*/
|
||||
char *strtolower(char *s) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if ('A' <= s[i] && s[i] <= 'Z') {
|
||||
s[i] += 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
35
libc/str/strtoupper.c
Normal file
35
libc/str/strtoupper.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Mutates string to ASCII uppercase.
|
||||
*
|
||||
* @praam s is string
|
||||
* @return string
|
||||
*/
|
||||
char *strtoupper(char *s) {
|
||||
size_t i;
|
||||
for (i = 0; s[i]; ++i) {
|
||||
if ('a' <= s[i] && s[i] <= 'z') {
|
||||
s[i] -= 'a' - 'A';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
|
@ -17,15 +17,21 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tinymemmem.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/alg/memmem.c
|
||||
*/
|
||||
void *tinymemmem(const void *haystk, size_t haystksize, const void *needle,
|
||||
void *tinymemmem(const void *haystack, size_t haystacksize, const void *needle,
|
||||
size_t needlesize) {
|
||||
return (/*unconst*/ void *)tinymemmemi(
|
||||
(const unsigned char *)haystk, haystksize, (const unsigned char *)needle,
|
||||
needlesize);
|
||||
size_t i;
|
||||
const char *p, *pe;
|
||||
for (p = haystack, pe = p + haystacksize; p < pe;) {
|
||||
for (++p, i = 0;;) {
|
||||
if (++i > needlesize) return p - 1;
|
||||
if (p == pe) break;
|
||||
if (((const char *)needle)[i - 1] != (p - 1)[i - 1]) break;
|
||||
}
|
||||
}
|
||||
return !haystacksize && !needlesize ? haystack : NULL;
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#ifndef __STRICT_ANSI__
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
forceinline void *tinymemmemi(const void *haystk, size_t haystksize,
|
||||
const void *needle, size_t needlesize) {
|
||||
const char *p = (const char *)haystk;
|
||||
const char *pe = (const char *)haystk + haystksize;
|
||||
while (p < pe) {
|
||||
size_t i = 0;
|
||||
++p;
|
||||
for (;;) {
|
||||
++i;
|
||||
if (i > needlesize) return (/*unconst*/ char *)(p - 1);
|
||||
if (p == pe) break;
|
||||
if (((const char *)needle)[i - 1] != (p - 1)[i - 1]) break;
|
||||
}
|
||||
}
|
||||
return (/*unconst*/ char *)(!haystksize && !needlesize ? haystk : NULL);
|
||||
}
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* !ANSI */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYMEMMEM_H_ */
|
|
@ -17,13 +17,22 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
* @see libc/str/strstr.c
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
char *(tinystrstr)(const char *haystack, const char *needle) {
|
||||
return (/*unconst*/ char *)tinystrstr(haystack, needle);
|
||||
char *tinystrstr(const char *haystack, const char *needle) {
|
||||
size_t i;
|
||||
for (;;) {
|
||||
for (i = 0;;) {
|
||||
if (!needle[i]) return (/*unconst*/ char *)haystack;
|
||||
if (!haystack[i]) break;
|
||||
if (needle[i] != haystack[i]) break;
|
||||
++i;
|
||||
}
|
||||
if (!*haystack++) break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#define COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define tinystrstr(HAYSTACK, NEEDLE) \
|
||||
({ \
|
||||
autotype(HAYSTACK) Haystack = (HAYSTACK); \
|
||||
typeof(Haystack) Needle = (NEEDLE); \
|
||||
for (;;) { \
|
||||
size_t i = 0; \
|
||||
for (;;) { \
|
||||
if (!Needle[i]) goto Found; \
|
||||
if (!Haystack[i]) break; \
|
||||
if (Needle[i] != Haystack[i]) break; \
|
||||
++i; \
|
||||
} \
|
||||
if (!*Haystack++) break; \
|
||||
} \
|
||||
Haystack = NULL; \
|
||||
Found: \
|
||||
Haystack; \
|
||||
})
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_STR_TINYSTRSTR_H_ */
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/internal.h"
|
||||
#include "libc/str/tinystrstr.internal.h"
|
||||
|
||||
/**
|
||||
* Naïve substring search implementation.
|
||||
|
@ -25,5 +24,15 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
char16_t *tinystrstr16(const char16_t *haystack, const char16_t *needle) {
|
||||
return (/*unconst*/ char16_t *)tinystrstr(haystack, needle);
|
||||
size_t i;
|
||||
for (;;) {
|
||||
for (i = 0;;) {
|
||||
if (!needle[i]) return (/*unconst*/ char16_t *)haystack;
|
||||
if (!haystack[i]) break;
|
||||
if (needle[i] != haystack[i]) break;
|
||||
++i;
|
||||
}
|
||||
if (!*haystack++) break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "libc/str/tpdecode.internal.h"
|
||||
#include "libc/str/tpdecodecb.internal.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
forceinline int getbyte(void *arg, uint32_t i) {
|
||||
return ((const unsigned char *)arg)[i];
|
||||
}
|
||||
|
|
|
@ -6,19 +6,14 @@ COSMOPOLITAN_C_START_
|
|||
uint64_t tpenc(int32_t) pureconst;
|
||||
|
||||
#ifndef __STRICT_ANSI__
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Buf; \
|
||||
int32_t Code = (CODE); \
|
||||
if (0 <= Code && Code <= 127) { \
|
||||
Buf = Code; \
|
||||
} else { \
|
||||
asm("call\ttpenc" \
|
||||
: "=a"(Buf), "+D"(Code) \
|
||||
: /* inputs */ \
|
||||
: "rcx", "rdx", "cc"); \
|
||||
} \
|
||||
Buf; \
|
||||
#define tpenc(CODE) \
|
||||
({ \
|
||||
long Edi, Buf; \
|
||||
asm("call\ttpenc" \
|
||||
: "=a"(Buf), "=D"(Edi) \
|
||||
: "1"(CODE) \
|
||||
: "rcx", "rdx", "cc"); \
|
||||
Buf; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,253 +22,367 @@
|
|||
/ @fileoverview Address Sanitizer Linker Poison
|
||||
|
||||
__asan_addr_is_in_fake_stack:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_addr_is_in_fake_stack,weak
|
||||
|
||||
__asan_after_dynamic_init:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_after_dynamic_init,weak
|
||||
|
||||
__asan_alloca_poison:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_alloca_poison,weak
|
||||
|
||||
__asan_allocas_unpoison:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_allocas_unpoison,weak
|
||||
|
||||
__asan_before_dynamic_init:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_before_dynamic_init,weak
|
||||
|
||||
__asan_get_current_fake_stack:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_get_current_fake_stack,weak
|
||||
|
||||
__asan_handle_no_return:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_handle_no_return,weak
|
||||
|
||||
__asan_init:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_init,weak
|
||||
|
||||
__asan_load1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load1,weak
|
||||
|
||||
__asan_load2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load2,weak
|
||||
|
||||
__asan_load4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load4,weak
|
||||
|
||||
__asan_load8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load8,weak
|
||||
|
||||
__asan_load16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load16,weak
|
||||
|
||||
__asan_load32:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_load32,weak
|
||||
|
||||
__asan_option_detect_stack_use_after_return:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_option_detect_stack_use_after_return,weak
|
||||
|
||||
__asan_poison_stack_memory:
|
||||
ud2
|
||||
.endfn __asan_poison_stack_memory,weak
|
||||
|
||||
__asan_register_globals:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_register_globals,weak
|
||||
|
||||
__asan_report_load1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load1,weak
|
||||
|
||||
__asan_report_load2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load2,weak
|
||||
|
||||
__asan_report_load4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load4,weak
|
||||
|
||||
__asan_report_load8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load8,weak
|
||||
|
||||
__asan_report_load16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load16,weak
|
||||
|
||||
__asan_report_load_n:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_load_n,weak
|
||||
|
||||
__asan_report_store1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store1,weak
|
||||
|
||||
__asan_report_store2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store2,weak
|
||||
|
||||
__asan_report_store4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store4,weak
|
||||
|
||||
__asan_report_store8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store8,weak
|
||||
|
||||
__asan_report_store16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store16,weak
|
||||
|
||||
__asan_report_store32:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store32,weak
|
||||
|
||||
__asan_report_store_n:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_report_store_n,weak
|
||||
|
||||
__asan_stack_free:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free,weak
|
||||
|
||||
__asan_stack_free_0:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_0,weak
|
||||
|
||||
__asan_stack_free_1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_1,weak
|
||||
|
||||
__asan_stack_free_10:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_10,weak
|
||||
|
||||
__asan_stack_free_2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_2,weak
|
||||
|
||||
__asan_stack_free_3:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_3,weak
|
||||
|
||||
__asan_stack_free_4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_4,weak
|
||||
|
||||
__asan_stack_free_5:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_5,weak
|
||||
|
||||
__asan_stack_free_6:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_6,weak
|
||||
|
||||
__asan_stack_free_7:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_7,weak
|
||||
|
||||
__asan_stack_free_8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_8,weak
|
||||
|
||||
__asan_stack_free_9:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_free_9,weak
|
||||
|
||||
__asan_stack_malloc:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc,weak
|
||||
|
||||
__asan_stack_malloc_0:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_0,weak
|
||||
|
||||
__asan_stack_malloc_1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_1,weak
|
||||
|
||||
__asan_stack_malloc_2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_2,weak
|
||||
|
||||
__asan_stack_malloc_3:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_3,weak
|
||||
|
||||
__asan_stack_malloc_4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_4,weak
|
||||
|
||||
__asan_stack_malloc_5:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_5,weak
|
||||
|
||||
__asan_stack_malloc_6:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_6,weak
|
||||
|
||||
__asan_stack_malloc_7:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_7,weak
|
||||
|
||||
__asan_stack_malloc_8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_8,weak
|
||||
|
||||
__asan_stack_malloc_9:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_9,weak
|
||||
|
||||
__asan_stack_malloc_10:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_stack_malloc_10,weak
|
||||
|
||||
__asan_store1:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store1,weak
|
||||
|
||||
__asan_store2:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store2,weak
|
||||
|
||||
__asan_store4:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store4,weak
|
||||
|
||||
__asan_store8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store8,weak
|
||||
|
||||
__asan_store16:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store16,weak
|
||||
|
||||
__asan_store32:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_store32,weak
|
||||
|
||||
__asan_unpoison_stack_memory:
|
||||
ud2
|
||||
.endfn __asan_unpoison_stack_memory,weak
|
||||
|
||||
__asan_unregister_globals:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_unregister_globals,weak
|
||||
|
||||
__asan_version_mismatch_check_v8:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
ud2
|
||||
.endfn __asan_version_mismatch_check_v8,weak
|
||||
|
|
2
libc/sysv/calls/msyscall.s
Normal file
2
libc/sysv/calls/msyscall.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall msyscall 0x0025ffffffffffff globl
|
|
@ -237,8 +237,9 @@ syscon mmap MAP_SHARED 1 1 1 1 1 # forced consensus & faked nt
|
|||
syscon mmap MAP_PRIVATE 2 2 2 2 2 # forced consensus & faked nt
|
||||
syscon mmap MAP_FIXED 0x10 0x10 0x10 0x10 0x10 # unix consensus; openbsd appears to forbid; faked nt
|
||||
syscon mmap MAP_ANONYMOUS 0x20 0x1000 0x1000 0x1000 0x20 # bsd consensus; faked nt
|
||||
syscon mmap MAP_GROWSDOWN 0x0100 0 0x0400 0x4000 0x100000 # mandatory for OpenBSD stacks; MAP_STACK on Free/OpenBSD; MEM_TOP_DOWN on NT
|
||||
syscon mmap MAP_CONCEAL 0 0 0x20000 0x8000 0 # omit from core dumps; MAP_NOCORE on FreeBSD
|
||||
syscon mmap MAP_NORESERVE 0x4000 0x40 0 0 0 # Linux calls it "reserve"; NT calls it "commit"? which is default?
|
||||
syscon mmap MAP_GROWSDOWN 0x0100 0 0x0400 0x0400 0x100000 # MAP_STACK on BSD; MEM_TOP_DOWN on NT
|
||||
syscon mmap MAP_HUGETLB 0x040000 0 0 0 0x80000000 # kNtSecLargePages
|
||||
syscon mmap MAP_HUGE_MASK 63 0 0 0 0
|
||||
syscon mmap MAP_HUGE_SHIFT 26 0 0 0 0
|
||||
|
@ -246,6 +247,8 @@ syscon mmap MAP_LOCKED 0x2000 0 0 0 0
|
|||
syscon mmap MAP_NONBLOCK 0x10000 0 0 0 0
|
||||
syscon mmap MAP_POPULATE 0x8000 0 0 0 0 # can avoid madvise(MADV_WILLNEED) on private file mapping
|
||||
syscon mmap MAP_TYPE 15 0 0 0 0 # what is it
|
||||
syscon compat MAP_STACK 0x0100 0 0x0400 0x4000 0x100000 # use MAP_GROWSDOWN
|
||||
syscon compat MAP_NOCORE 0 0 0x20000 0x8000 0 # use MAP_CONCEAL
|
||||
syscon compat MAP_ANON 0x20 0x1000 0x1000 0x1000 0x20 # bsd consensus; faked nt
|
||||
syscon compat MAP_STACK 0x020000 0 0x0400 0x4000 0x100000
|
||||
syscon compat MAP_EXECUTABLE 0x1000 0 0 0 0 # ignored
|
||||
|
@ -3112,6 +3115,7 @@ syscon nr __NR_io_uring_setup 0x01a9 -1 -1 -1 -1
|
|||
syscon nr __NR_io_uring_enter 0x01aa -1 -1 -1 -1
|
||||
syscon nr __NR_io_uring_register 0x01ab -1 -1 -1 -1
|
||||
syscon nr __NR_pledge -1 -1 -1 0x006c -1
|
||||
syscon nr __NR_msyscall -1 -1 -1 0x0025 -1
|
||||
syscon nr __NR_ktrace -1 -1 0x002d 0x002d -1
|
||||
syscon nr __NR_kqueue -1 0x200016a 0x016a 0x010d -1
|
||||
syscon nr __NR_kevent -1 0x2000171 0x0230 0x0048 -1
|
||||
|
|
2
libc/sysv/consts/MAP_CONCEAL.s
Normal file
2
libc/sysv/consts/MAP_CONCEAL.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon mmap MAP_CONCEAL 0 0 0x20000 0x8000 0
|
|
@ -1,2 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon mmap MAP_GROWSDOWN 0x0100 0 0x0400 0x0400 0x100000
|
||||
.syscon mmap MAP_GROWSDOWN 0x0100 0 0x0400 0x4000 0x100000
|
||||
|
|
2
libc/sysv/consts/MAP_NOCORE.s
Normal file
2
libc/sysv/consts/MAP_NOCORE.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon compat MAP_NOCORE 0 0 0x20000 0x8000 0
|
2
libc/sysv/consts/__NR_msyscall.s
Normal file
2
libc/sysv/consts/__NR_msyscall.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "libc/sysv/consts/syscon.inc"
|
||||
.syscon nr __NR_msyscall -1 -1 -1 0x0025 -1
|
|
@ -21,7 +21,6 @@ hidden extern const long MAP_NORESERVE;
|
|||
hidden extern const long MAP_POPULATE;
|
||||
hidden extern const long MAP_PRIVATE;
|
||||
hidden extern const long MAP_SHARED;
|
||||
hidden extern const long MAP_STACK;
|
||||
hidden extern const long MAP_TYPE;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
@ -34,6 +33,7 @@ COSMOPOLITAN_C_END_
|
|||
|
||||
#define MAP_32BIT SYMBOLIC(MAP_32BIT)
|
||||
#define MAP_ANONYMOUS SYMBOLIC(MAP_ANONYMOUS)
|
||||
#define MAP_CONCEAL SYMBOLIC(MAP_CONCEAL)
|
||||
#define MAP_DENYWRITE SYMBOLIC(MAP_DENYWRITE)
|
||||
#define MAP_EXECUTABLE SYMBOLIC(MAP_EXECUTABLE)
|
||||
#define MAP_GROWSDOWN SYMBOLIC(MAP_GROWSDOWN)
|
||||
|
@ -46,7 +46,8 @@ COSMOPOLITAN_C_END_
|
|||
#define MAP_POPULATE SYMBOLIC(MAP_POPULATE)
|
||||
#define MAP_TYPE SYMBOLIC(MAP_TYPE)
|
||||
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_STACK MAP_GROWSDOWN
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
#define MAP_NOCORE MAP_CONCEAL
|
||||
#define MAP_STACK MAP_GROWSDOWN
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_MAP_H_ */
|
||||
|
|
|
@ -332,6 +332,7 @@
|
|||
#define __NR_io_uring_enter SYMBOLIC(__NR_io_uring_enter)
|
||||
#define __NR_io_uring_register SYMBOLIC(__NR_io_uring_register)
|
||||
#define __NR_pledge SYMBOLIC(__NR_pledge)
|
||||
#define __NR_msyscall SYMBOLIC(__NR_msyscall)
|
||||
#define __NR_ktrace SYMBOLIC(__NR_ktrace)
|
||||
#define __NR_kqueue SYMBOLIC(__NR_kqueue)
|
||||
#define __NR_kevent SYMBOLIC(__NR_kevent)
|
||||
|
@ -1105,6 +1106,7 @@ hidden extern const long __NR_io_uring_setup;
|
|||
hidden extern const long __NR_io_uring_enter;
|
||||
hidden extern const long __NR_io_uring_register;
|
||||
hidden extern const long __NR_pledge;
|
||||
hidden extern const long __NR_msyscall;
|
||||
hidden extern const long __NR_ktrace;
|
||||
hidden extern const long __NR_kqueue;
|
||||
hidden extern const long __NR_kevent;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.text.syscall
|
||||
.source __FILE__
|
||||
|
||||
/ Linux Signal Trampoline (HOLY CODE)
|
||||
|
|
|
@ -365,6 +365,7 @@ scall io_uring_enter 0xffffffffffff01aa globl
|
|||
scall io_uring_register 0xffffffffffff01ab globl
|
||||
#────────────────────────RHEL CLOUD────────────────────────── # ←┬─ red hat terminates community release of enterprise linux circa 2020
|
||||
scall pledge 0x006cffffffffffff globl # └─ online linux services ban the president of united states of america
|
||||
scall msyscall 0x0025ffffffffffff globl
|
||||
|
||||
# The Fifth Bell System Interface, Community Edition
|
||||
# » besiyata dishmaya
|
||||
|
|
|
@ -102,6 +102,8 @@ __systemfive:
|
|||
.quad 0
|
||||
.endobj __systemfive,globl,hidden
|
||||
.previous
|
||||
|
||||
.text.syscall
|
||||
.Lanchorpoint:
|
||||
systemfive.linux:
|
||||
movswl %ax,%eax # gnu/systemd ordinal is first word
|
||||
|
@ -256,11 +258,9 @@ systemfive.init.magnums:
|
|||
pop %rbx
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
#ifndef TINY
|
||||
systemfive.init.stack:
|
||||
systemfive.init.stack: # determinism ftw!
|
||||
testb IsWindows() # already did this
|
||||
jnz systemfive.init.done
|
||||
testb IsOpenbsd() # todo fix openbsd
|
||||
jnz systemfive.init.done
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov __NR_mmap,%eax
|
||||
|
@ -269,13 +269,20 @@ systemfive.init.stack:
|
|||
mov $PROT_READ|PROT_WRITE,%edx
|
||||
mov $MAP_PRIVATE|MAP_FIXED,%r10d
|
||||
or MAP_ANONYMOUS,%r10d
|
||||
or MAP_GROWSDOWN,%r10d
|
||||
or $-1,%r8
|
||||
or $-1,%r8d
|
||||
xor %r9d,%r9d
|
||||
push %r9 # openbsd:pad
|
||||
/ clc
|
||||
push %r9 # openbsd:align
|
||||
testb IsOpenbsd()
|
||||
jz 0f
|
||||
syscall # openbsd:dubstack
|
||||
jc 1f
|
||||
mov __NR_mmap,%eax
|
||||
0: or MAP_GROWSDOWN,%r10d # openbsd:mapstack
|
||||
clc
|
||||
syscall
|
||||
pop %r9
|
||||
pop %r9
|
||||
jnc 2f
|
||||
1: mov %eax,%edi
|
||||
mov __NR_exit_group,%eax
|
||||
|
@ -295,12 +302,26 @@ systemfive.init.stack:
|
|||
pop %rdi
|
||||
leave
|
||||
pop %rcx
|
||||
lea STACKSIZE(%rax),%rsp
|
||||
lea STACKSIZE-16(%rax),%rsp # openbsd:stackbound
|
||||
push %rcx
|
||||
xor %ebp,%ebp
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
systemfive.init.syscall:
|
||||
mov __NR_msyscall,%eax # syscall origin protect
|
||||
test %eax,%eax # openbsd is pretty cool
|
||||
js systemfive.init.done
|
||||
push %rdi
|
||||
push %rsi
|
||||
.weak __text_syscall_addr
|
||||
.weak __text_syscall_size
|
||||
mov $__text_syscall_addr,%edi
|
||||
mov $__text_syscall_size,%esi
|
||||
syscall
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
/ 𝑠𝑙𝑖𝑑𝑒
|
||||
#endif /* TINY */
|
||||
systemfive.init.done:
|
||||
nop
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/limits.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
|
@ -45,7 +46,7 @@ TEST(tpenc, testBeyondTheStandard) {
|
|||
}
|
||||
|
||||
uint64_t Tpenc(int x) {
|
||||
return (v = tpenc(VEIL("r", x)));
|
||||
return (v = EXPROPRIATE(tpenc(VEIL("r", x))));
|
||||
}
|
||||
|
||||
BENCH(tpenc, bench) {
|
||||
|
|
2
third_party/chibicc/tokenize.c
vendored
2
third_party/chibicc/tokenize.c
vendored
|
@ -275,7 +275,7 @@ static Token *read_string_literal(char *start, char *quote) {
|
|||
// is called a "surrogate pair".
|
||||
static Token *read_utf16_string_literal(char *start, char *quote) {
|
||||
char *end = string_literal_end(quote + 1);
|
||||
uint16_t *buf = calloc(2, end - start - 1);
|
||||
uint16_t *buf = calloc(2, end - start);
|
||||
int len = 0;
|
||||
for (char *p = quote + 1; p < end;) {
|
||||
if (*p == '\\') {
|
||||
|
|
7
third_party/third_party.mk
vendored
7
third_party/third_party.mk
vendored
|
@ -1,15 +1,10 @@
|
|||
#-*-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───────────────────────┘
|
||||
|
||||
# TODO(jart): make chibicc compiled chibicc work with asan runtime
|
||||
ifneq ($(MODE),dbg)
|
||||
THIRD_PARTY_CHIBICC_XXX = o/$(MODE)/third_party/chibicc
|
||||
endif
|
||||
|
||||
.PHONY: o/$(MODE)/third_party
|
||||
o/$(MODE)/third_party: \
|
||||
o/$(MODE)/third_party/blas \
|
||||
$(THIRD_PARTY_CHIBICC_XXX) \
|
||||
o/$(MODE)/third_party/chibicc \
|
||||
o/$(MODE)/third_party/compiler_rt \
|
||||
o/$(MODE)/third_party/dlmalloc \
|
||||
o/$(MODE)/third_party/gdtoa \
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction-linux.internal.h"
|
||||
|
@ -770,6 +771,30 @@ static ssize_t OpRead(struct Machine *m, int fd, int64_t addr, size_t size) {
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int OpGetdents(struct Machine *m, int dirfd, int64_t addr,
|
||||
uint32_t size) {
|
||||
int rc;
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
if (size < sizeof(struct dirent)) return einval();
|
||||
if (0 <= dirfd && dirfd < m->fds.i) {
|
||||
if ((dir = fdopendir(m->fds.p[dirfd].fd))) {
|
||||
rc = 0;
|
||||
while (rc + sizeof(struct dirent) <= size) {
|
||||
if (!(ent = readdir(dir))) break;
|
||||
VirtualRecvWrite(m, addr + rc, ent, ent->d_reclen);
|
||||
rc += ent->d_reclen;
|
||||
}
|
||||
free(dir);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t OpPread(struct Machine *m, int fd, int64_t addr, size_t size,
|
||||
int64_t offset) {
|
||||
ssize_t rc;
|
||||
|
@ -1395,6 +1420,7 @@ void OpSyscall(struct Machine *m, uint32_t rde) {
|
|||
SYSCALL(0x09E, OpArchPrctl(m, di, si));
|
||||
SYSCALL(0x0BA, OpGetTid(m));
|
||||
SYSCALL(0x0CB, sched_setaffinity(di, si, P(dx)));
|
||||
SYSCALL(0x0D9, OpGetdents(m, di, si, dx));
|
||||
SYSCALL(0x0DD, OpFadvise(m, di, si, dx, r0));
|
||||
SYSCALL(0x0E4, OpClockGettime(m, di, si));
|
||||
SYSCALL(0x101, OpOpenat(m, di, si, dx, r0));
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
"interruptfn"
|
||||
"nocallback"
|
||||
"textstartup"
|
||||
"textsyscall"
|
||||
"warnifused"
|
||||
"attributeallocsize"
|
||||
"attributeallocalign"
|
||||
|
|
|
@ -441,7 +441,7 @@
|
|||
(cond ((not (eq 0 (logand 8 arg)))
|
||||
(cosmo--assembly (setq arg (logand (lognot 8)))
|
||||
"SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'"))
|
||||
(t (cosmo--assembly arg "SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
|
||||
(t (cosmo--assembly arg "SILENT=0 OVERRIDE_COPTS='' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
|
||||
|
||||
(defun cosmo-assembly-native (arg)
|
||||
(interactive "P")
|
||||
|
|
Loading…
Reference in a new issue