Get codebase completely working with LLVM

You can now build Cosmopolitan with Clang:

    make -j8 MODE=llvm
    o/llvm/examples/hello.com

The assembler and linker code is now friendly to LLVM too.
So it's not needed to configure Clang to use binutils under
the hood. If you love LLVM then you can now use pure LLVM.
This commit is contained in:
Justine Tunney 2021-02-08 09:19:00 -08:00
parent 0e36cb3ac4
commit e75ffde09e
4528 changed files with 7776 additions and 11640 deletions

View file

@ -23,16 +23,16 @@
#include "libc/macros.h"
.privileged
/ Terminates program abnormally.
/
/ This function first tries to trigger your SIGABRT handler. If
/ there isn't one or execution resumes, then abort() terminates
/ the program using an escalating variety methods of increasing
/ brutality.
/
/ @forcealignargpointer
/ @asyncsignalsafe
/ @noreturn
// Terminates program abnormally.
//
// This function first tries to trigger your SIGABRT handler. If
// there isn't one or execution resumes, then abort() terminates
// the program using an escalating variety methods of increasing
// brutality.
//
// @forcealignargpointer
// @asyncsignalsafe
// @noreturn
abort: push %rbp
mov %rsp,%rbp
and $-16,%rsp

View file

@ -21,12 +21,12 @@
.text.startup
.source __FILE__
/ Calls global initialization functions.
/
/ @param r12 is argc
/ @param r13 is argv
/ @param r14 is environ
/ @param r15 is auxv
// Calls global initialization functions.
//
// @param r12 is argc
// @param r13 is argv
// @param r14 is environ
// @param r15 is auxv
_construct:
push %rbp
mov %rsp,%rbp

View file

@ -24,13 +24,13 @@
#include "libc/dce.h"
.text.startup
/ Cosmopolitan runtime.
/
/ @param edi is argc
/ @param rsi is argv
/ @param rdx is environ
/ @param rcx is auxv
/ @noreturn
// Cosmopolitan runtime.
//
// @param edi is argc
// @param rsi is argv
// @param rdx is environ
// @param rcx is auxv
// @noreturn
cosmo: push %rbp
mov %rsp,%rbp
mov %edi,%r12d
@ -60,10 +60,6 @@ cosmo: push %rbp
add $8,%rax
jmp 1b
2: nop
#if !IsTrustworthy()
mov $PROT_READ,%edi
call _piro
#endif
call .Largs
.weak main
call main

View file

@ -1,62 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/alg/arraylist.internal.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/gc.internal.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
forceinline bool PointerNotOwnedByParentStackFrame(struct StackFrame *frame,
struct StackFrame *parent,
void *ptr) {
return !(((intptr_t)ptr > (intptr_t)frame) &&
((intptr_t)ptr < (intptr_t)parent));
}
/**
* Adds destructor to garbage shadow stack.
*
* @param frame is passed automatically by wrapper macro
* @param fn takes one argument
* @param arg is passed to fn(arg)
* @return arg
*/
void __defer(struct StackFrame *frame, void *fn, void *arg) {
struct StackFrame *frame2;
/*
* To avoid an API requiring dlmalloc dependency, say:
* defer(free_s, &ptr_not_owned_by_current_frame)
* Rather than:
* defer(weak(free), ptr)
*/
if (!arg) return;
frame2 = __builtin_frame_address(0);
assert(frame2->next == frame);
assert(PointerNotOwnedByParentStackFrame(frame2, frame, arg));
if (append(&__garbage,
(&(const struct Garbage){frame->next, (intptr_t)fn, (intptr_t)arg,
frame->addr})) != -1) {
atomic_store(&frame->addr, (intptr_t)&__gc);
} else {
abort();
}
}

View file

@ -20,8 +20,8 @@
.text.exit
.source __FILE__
/ Calls linker registered finalization functions.
/ @note functions are called in reverse order
// Calls linker registered finalization functions.
// @note functions are called in reverse order
_destruct:
push %rbp
mov %rsp,%rbp

View file

@ -20,7 +20,7 @@
#include "libc/notice.inc"
.source __FILE__
/ Uniquely identifies each artifact linked in an address space.
// Uniquely identifies each artifact linked in an address space.
__dso_handle:
.quad __dso_handle
.endobj __dso_handle,globl,hidden

View file

@ -20,10 +20,10 @@
.text.exit
.source __FILE__
/ Exits program with grace.
/
/ @param %dil has exit code
/ @noreturn
// Exits program with grace.
//
// @param %dil has exit code
// @noreturn
exit: push %rbp
mov %rsp,%rbp
push %rdi

View file

@ -20,11 +20,11 @@
.privileged
.source __FILE__
/ Terminates process, ignoring destructors and atexit() handlers.
/
/ @param edi is exit code ∈ [0,256)
/ @asyncsignalsafe
/ @vforksafe
/ @noreturn
// Terminates process, ignoring destructors and atexit() handlers.
//
// @param edi is exit code ∈ [0,256)
// @asyncsignalsafe
// @vforksafe
// @noreturn
_exit: jmp _Exit
.endfn _exit,globl,protected

View file

@ -22,12 +22,12 @@
.privileged
.source __FILE__
/ Terminates process, ignoring destructors and atexit() handlers.
/
/ @param edi is exit code ∈ [0,256)
/ @asyncsignalsafe
/ @vforksafe
/ @noreturn
// Terminates process, ignoring destructors and atexit() handlers.
//
// @param edi is exit code ∈ [0,256)
// @asyncsignalsafe
// @vforksafe
// @noreturn
_Exit: push %rbp
mov %rsp,%rbp
#if SupportsWindows()

View file

@ -19,7 +19,7 @@
#include "libc/macros.h"
.source __FILE__
/ Re-initializes FPU.
// Re-initializes FPU.
fpreset:
_fpreset:
.leafprologue

View file

@ -20,12 +20,8 @@
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
/**
* Frees memory, the Cosmopolitan way.
*
* The caller's pointer is zeroed. Stack and static memory is ignored.
* This doesn't require a dependency on malloc().
*/
/* TODO(jart): DELETE */
void free_s(void *v) {
void **pp = (void **)v;
void *p = NULL;

View file

@ -0,0 +1,66 @@
/*-*- 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 2021 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.privileged
ftrace_hook:
push %rbp
mov %rsp,%rbp
and $-16,%rsp
sub $0x80,%rsp
movaps %xmm0,0x00(%rsp)
movaps %xmm1,0x10(%rsp)
movaps %xmm2,0x20(%rsp)
movaps %xmm3,0x30(%rsp)
movaps %xmm4,0x40(%rsp)
movaps %xmm5,0x50(%rsp)
movaps %xmm6,0x60(%rsp)
movaps %xmm7,0x70(%rsp)
push %rax
push %rax
push %rdi
push %rsi
push %rdx
push %rcx
push %r8
push %r9
push %r10
push %r11
call ftrace
pop %r11
pop %r10
pop %r9
pop %r8
pop %rcx
pop %rdx
pop %rsi
pop %rdi
pop %rax
pop %rax
movaps 0x00(%rsp),%xmm0
movaps 0x10(%rsp),%xmm1
movaps 0x20(%rsp),%xmm2
movaps 0x30(%rsp),%xmm3
movaps 0x40(%rsp),%xmm4
movaps 0x50(%rsp),%xmm5
movaps 0x60(%rsp),%xmm6
movaps 0x70(%rsp),%xmm7
leave
ret
.endfn ftrace_hook,globl

View file

@ -46,6 +46,9 @@
* into gzip.
*/
void ftrace_hook(void);
static int noreentry;
static char g_buf[512];
static const char *g_lastsymbol;
static struct SymbolTable *g_symbols;
@ -66,12 +69,14 @@ forceinline int GetNestingLevel(struct StackFrame *frame) {
* prologues of other functions. We assume those functions behave
* according to the System Five NexGen32e ABI.
*/
privileged interruptfn void ftrace_hook(void) {
privileged void ftrace(void) {
size_t i, j, nesting;
const char *symbol;
struct StackFrame *frame;
if (!cmpxchg(&noreentry, 0, 1)) return;
if (g_symbols) {
frame = __builtin_frame_address(0);
frame = frame->next;
symbol =
&g_symbols->name_base[g_symbols
->symbols[bisectcarleft(
@ -84,18 +89,21 @@ privileged interruptfn void ftrace_hook(void) {
i = 2;
j = 0;
while (nesting--) {
asm volatile("" : : : "memory");
g_buf[i++] = ' ';
g_buf[i++] = ' ';
}
while (i < ARRAYLEN(g_buf) - 2 && symbol[j]) {
asm volatile("" : : : "memory");
g_buf[i++] = symbol[j++];
}
g_buf[i++] = '\r';
g_buf[i++] = '\n';
__print(g_buf, i);
write(2, g_buf, i);
}
g_lastsymbol = symbol;
}
noreentry = 0;
}
/**

View file

@ -19,7 +19,7 @@
#include "libc/macros.h"
.source __FILE__
/ Returns granularity of memory manager.
// Returns granularity of memory manager.
getpagesize:
.leafprologue
.profilable

View file

@ -42,7 +42,7 @@
*
* @see ape/ape.lds
*/
privileged void __hook(void ifunc(void), struct SymbolTable *symbols) {
privileged void __hook(void *ifunc, struct SymbolTable *symbols) {
size_t i;
intptr_t addr;
sigset_t oldmask;

View file

@ -22,30 +22,30 @@
#include "libc/dce.h"
.source __FILE__
/ Decentralized function for process initialization.
/
/ Modules may inject cheap data structure initialization code into
/ this function using the .init.start and .init.end macros. That
/ code can use the LODS and STOS instructions to initialize memory
/ that's restricted to read-only after initialization by PIRO.
/
/ This is fast, since the linker is able to roll-up initialization
/ for large codebases comprised of many modules, into a perfectly
/ linear order. It also enables a common pattern we use, which we
/ call Referencing Is Initialization (RII).
/
/ C/C++ code should favor using ordinary constructors, since under
/ normal circumstances the compiler will clobber RDI and RSI which
/ are granted special meanings within this function.
/
/ @param r12 is argc (still callee saved)
/ @param r13 is argv (still callee saved)
/ @param r14 is envp (still callee saved)
/ @param r15 is envp (still callee saved)
/ @note rdi is __init_bss_start (callee monotonic lockstep)
/ @note rsi is __init_rodata_start (callee monotonic lockstep)
/ @see .init.start & .init.end (libc/macros.internal.inc)
/ @see ape/ape.lds
// Decentralized function for process initialization.
//
// Modules may inject cheap data structure initialization code into
// this function using the .init.start and .init.end macros. That
// code can use the LODS and STOS instructions to initialize memory
// that's restricted to read-only after initialization by PIRO.
//
// This is fast, since the linker is able to roll-up initialization
// for large codebases comprised of many modules, into a perfectly
// linear order. It also enables a common pattern we use, which we
// call Referencing Is Initialization (RII).
//
// C/C++ code should favor using ordinary constructors, since under
// normal circumstances the compiler will clobber RDI and RSI which
// are granted special meanings within this function.
//
// @param r12 is argc (still callee saved)
// @param r13 is argv (still callee saved)
// @param r14 is envp (still callee saved)
// @param r15 is envp (still callee saved)
// @note rdi is __init_bss_start (callee monotonic lockstep)
// @note rsi is __init_rodata_start (callee monotonic lockstep)
// @see .init.start & .init.end (libc/macros.internal.inc)
// @see ape/ape.lds
.section .initprologue,"ax",@progbits
.type _init,@function
.globl _init
@ -75,10 +75,10 @@ _woot: leave
ret
.previous
/ Decentralized section for packed data structures & initializers.
/
/ @see .initro (libc/macros.internal.inc)
/ @see ape/ape.lds
// Decentralized section for packed data structures & initializers.
//
// @see .initro (libc/macros.internal.inc)
// @see ape/ape.lds
.section .initroprologue,"a",@progbits
.type __init_rodata_start,@object
.type __init_rodata_end,@object
@ -95,13 +95,13 @@ __init_rodata_end:
.byte 0x90
.previous
/ Decentralized section for unpacked data structures.
/
/ Data in this section becomes read-only after initialization.
/
/ @see .piro.bss.init (libc/macros.internal.inc)
/ @see libc/runtime/piro.c
/ @see ape/ape.lds
// Decentralized section for unpacked data structures.
//
// Data in this section becomes read-only after initialization.
//
// @see .piro.bss.init (libc/macros.internal.inc)
// @see libc/runtime/piro.c
// @see ape/ape.lds
.section .piro.bss.init.1,"aw",@nobits
.type __init_bss_start,@object
.type __init_bss_end,@object
@ -118,14 +118,14 @@ __init_bss_end:
.byte 0
.previous
/ Special area for Windows NT support code.
/
/ Isolating this code adds value for Windows users by minimizing
/ page faults through improved locality. On System Five the PIRO
/ runtime can unmap these pages.
/
/ @see libc/runtime/piro.c
/ @see ape/ape.lds
// Special area for Windows NT support code.
//
// Isolating this code adds value for Windows users by minimizing
// page faults through improved locality. On System Five the PIRO
// runtime can unmap these pages.
//
// @see libc/runtime/piro.c
// @see ape/ape.lds
.section .textwindowsprologue,"ax",@progbits
.type __text_windows_start,@object
.type __text_windows_end,@object

View file

@ -17,7 +17,6 @@ extern hidden char **g_freebsdhint;
extern hidden void *g_stacktop;
void _init(void) hidden;
void _piro(int) hidden;
void *__cxa_finalize(void *) hidden;
void cosmo(int, char **, char **, long (*)[2]) hidden wontreturn;
void __stack_chk_fail(void) wontreturn relegated;

View file

@ -18,12 +18,12 @@
*/
#include "libc/macros.h"
/ Switches stack.
/
/ @param rdi is new rsp, passed as malloc(size) + size
/ @param rsi is function to call in new stack space
/ @param rdx,rcx,r8,r9 get passed as args to rsi
/ @noreturn
// Switches stack.
//
// @param rdi is new rsp, passed as malloc(size) + size
// @param rsi is function to call in new stack space
// @param rdx,rcx,r8,r9 get passed as args to rsi
// @noreturn
_jmpstack:
mov %rdi,%rsp
mov %rsi,%rax

View file

@ -20,7 +20,7 @@
#include "libc/macros.h"
.source __FILE__
/ Loads all pages from program image into memory.
// Loads all pages from program image into memory.
peekall:.leafprologue
ezlea _base,si
ezlea _end,cx

View file

@ -1,69 +0,0 @@
/*-*- 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
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.
αcτµαlly pδrταblε εxεcµταblε § post-initialization read-only
*/
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/runtime/internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/prot.h"
#define getaddr(section) ((intptr_t)weakaddr(section))
static textstartup void _piro_protect(intptr_t start, intptr_t end, int prot) {
ssize_t len = end - start;
if (len > 0 && start && start % PAGESIZE == 0 && len % PAGESIZE == 0) {
if (mprotect((void *)(unsigned long)start, len, prot) == -1) abort();
}
}
/**
* Protects memory initialized at startup.
* e.g. function hooks, unpacked data structures, etc.
*
* This is only performed for executables of nontrivial size. It won't
* break the build if the α linker script wasn't used. Test code is
* protected too, so we don't end up like Knight Capital.
*
* @param prot can have PROT_{NONE,READ,WRITE,EXEC}
* @see ape/ape.lds
* @see libc/_start.S
*/
textstartup void _piro(int prot) {
if (getaddr("main") < getaddr("__test_start")) {
_piro_protect(getaddr("__test_start"), getaddr("__test_end"), PROT_NONE);
}
_piro_protect(getaddr("__ro"), getaddr("_etext"), PROT_READ);
_piro_protect(getaddr("__piro_start"), getaddr("__piro_end"), prot);
}

View file

@ -25,6 +25,8 @@
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/nr.h"
/* TODO(jart): DELETE */
#define WasImported(SLOT) \
((void *)*SLOT && *SLOT != (void *)&missingno /* see libc/crt/crt.S */)

View file

@ -19,7 +19,7 @@
#include "libc/macros.h"
.source __FILE__
/ Provides argv[0] The BSD Way.
// Provides argv[0] The BSD Way.
.initbss 300,_init___progname
__progname:
.quad 0

View file

@ -19,7 +19,7 @@
#include "libc/macros.h"
.source __FILE__
/ Supplies basename(argv[0]) The GNU Way.
// Supplies basename(argv[0]) The GNU Way.
.initbss 400,_init_program_invocation_short_name
program_invocation_short_name:
.quad 0
@ -34,9 +34,9 @@ program_invocation_short_name:
mov (%r13),%rsi # argv[0]
mov %rsi,%rcx
1: lodsb
cmp $'/,%al
cmp $'/',%al
cmoveq %rsi,%rcx
cmp $'\\,%al
cmp $'\\',%al
cmoveq %rsi,%rcx
test %al,%al
jnz 1b

View file

@ -18,12 +18,12 @@
*/
#include "libc/macros.h"
/ Switches stack.
/
/ @param rdi is new rsp, passed as malloc(size) + size
/ @param rsi is function to call in new stack space
/ @param rdx,rcx,r8,r9 get passed as args to rsi
/ @return rax and happens on original stack
// Switches stack.
//
// @param rdi is new rsp, passed as malloc(size) + size
// @param rsi is function to call in new stack space
// @param rdx,rcx,r8,r9 get passed as args to rsi
// @return rax and happens on original stack
_setstack:
push %rbp
mov %rsp,%rbp

View file

@ -32,7 +32,7 @@ const char *FindComBinary(void);
const char *FindDebugBinary(void);
struct SymbolTable *OpenSymbolTable(const char *) nodiscard;
int CloseSymbolTable(struct SymbolTable **);
void __hook(void (*)(void), struct SymbolTable *);
void __hook(void *, struct SymbolTable *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -20,20 +20,20 @@
#include "libc/macros.h"
.privileged
/ Forks process without copying page tables.
/
/ This is the same as fork() except it's optimized for the case
/ where the caller invokes execve() immediately afterwards. You
/ can also call functions like close(), dup2(), etc. You cannot
/ call read() safely but you can call pread(). Call _exit() but
/ don't call exit(). Look for the vforksafe function annotation
/
/ Do not make the assumption that the parent is suspended until
/ the child terminates since this impl calls fork() on Windows.
/
/ @return pid of child process or 0 if forked process
/ @returnstwice
/ @vforksafe
// Forks process without copying page tables.
//
// This is the same as fork() except it's optimized for the case
// where the caller invokes execve() immediately afterwards. You
// can also call functions like close(), dup2(), etc. You cannot
// call read() safely but you can call pread(). Call _exit() but
// don't call exit(). Look for the vforksafe function annotation
//
// Do not make the assumption that the parent is suspended until
// the child terminates since this impl calls fork() on Windows.
//
// @return pid of child process or 0 if forked process
// @returnstwice
// @vforksafe
vfork:
#if SupportsWindows()
testb IsWindows()
@ -48,7 +48,7 @@ vfork:
syscall
push %rsi # note it happens twice in same page
cmp $-4095,%eax
jae systemfive.error
jae systemfive_error
0: ezlea __vforked,di
test %eax,%eax
jz 1f
@ -62,7 +62,7 @@ vfork:
vfork.bsd:
syscall
push %rsi
jc systemfive.errno
jc systemfive_errno
#if SupportsXnu()
testb IsXnu()
jz 0b

View file

@ -19,9 +19,9 @@
#include "libc/macros.h"
.source __FILE__
/ Thunks free() if it's linked, otherwise do nothing.
/
/ @see free_s() which can ignore static/stack and clear refs
// Thunks free() if it's linked, otherwise do nothing.
//
// @see free_s() which can ignore static/stack and clear refs
weakfree:
push %rbp
mov %rsp,%rbp

View file

@ -103,8 +103,9 @@ static noasan textwindows wontreturn void WinMainNew(void) {
long auxv[1][2];
struct WinArgs *wa;
const char16_t *env16;
extern char os asm("__hostos");
os = WINDOWS; /* madness https://news.ycombinator.com/item?id=21019722 */
NormalizeCmdExe();
*(/*unconst*/ int *)&__hostos = WINDOWS;
addr = NtGetVersion() < kNtVersionWindows10 ? 0xff00000 : 0x777000000000;
size = ROUNDUP(STACKSIZE + sizeof(struct WinArgs), FRAMESIZE);
_mmi.p[0].h =