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:
Justine Tunney 2021-02-02 20:21:06 -08:00
parent cbfd4ccd1e
commit c843243322
56 changed files with 376 additions and 245 deletions

View file

@ -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);

View file

@ -94,8 +94,7 @@ CONFIG_CPPFLAGS += \
CONFIG_CCFLAGS += \
$(BACKTRACES) \
$(FTRACE) \
-O1 \
-fno-inline
-O2
CONFIG_COPTS += \
$(SECURITY_BLANKETS) \

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.text.syscall
/ Tiny Raw Linux Binary Tutorial
/

View file

@ -42,7 +42,6 @@
* @errors ENOENT, ENOTDIR, ENOSYS
* @asyncsignalsafe
* @see fchmod()
* @syscall
*/
int chmod(const char *pathname, uint32_t mode) {
if (!pathname) return efault();

View file

@ -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 */

View file

@ -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()) {

View file

@ -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;

View file

@ -40,7 +40,6 @@
* @errors ENOSYS
* @asyncsignalsafe
* @see chmod()
* @syscall
*/
int fchmod(int fd, uint32_t mode) {
/* TODO(jart): Windows */

View file

@ -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? */

View file

@ -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;

View file

@ -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()) {

View file

@ -18,6 +18,7 @@
*/
#include "libc/dce.h"
#include "libc/macros.h"
.text.syscall
/ Forks process without copying page tables.
/

View file

@ -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;

View file

@ -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)));

View file

@ -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

View file

@ -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); */

View file

@ -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);
}

View file

@ -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

View file

@ -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 (1s 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__

View 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.

View file

@ -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:

View file

@ -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.

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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.
*

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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
View 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;
}

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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];
}

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.internal.inc"
.scall msyscall 0x0025ffffffffffff globl

View file

@ -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

View file

@ -0,0 +1,2 @@
.include "libc/sysv/consts/syscon.inc"
.syscon mmap MAP_CONCEAL 0 0 0x20000 0x8000 0

View file

@ -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

View file

@ -0,0 +1,2 @@
.include "libc/sysv/consts/syscon.inc"
.syscon compat MAP_NOCORE 0 0 0x20000 0x8000 0

View file

@ -0,0 +1,2 @@
.include "libc/sysv/consts/syscon.inc"
.syscon nr __NR_msyscall -1 -1 -1 0x0025 -1

View file

@ -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_ */

View file

@ -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;

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.text.syscall
.source __FILE__
/ Linux Signal Trampoline (HOLY CODE)

View file

@ -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

View file

@ -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

View file

@ -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) {

View file

@ -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 == '\\') {

View file

@ -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 \

View file

@ -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));

View file

@ -176,6 +176,7 @@
"interruptfn"
"nocallback"
"textstartup"
"textsyscall"
"warnifused"
"attributeallocsize"
"attributeallocalign"

View file

@ -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")