You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
12 KiB
313 lines
12 KiB
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ |
|
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│ |
|
╞══════════════════════════════════════════════════════════════════════════════╡ |
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │ |
|
│ │ |
|
│ This program is free software; you can redistribute it and/or modify │ |
|
│ it under the terms of the GNU General Public License as published by │ |
|
│ the Free Software Foundation; version 2 of the License. │ |
|
│ │ |
|
│ This program is distributed in the hope that it will be useful, but │ |
|
│ WITHOUT ANY WARRANTY; without even the implied warranty of │ |
|
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │ |
|
│ General Public License for more details. │ |
|
│ │ |
|
│ You should have received a copy of the GNU General Public License │ |
|
│ along with this program; if not, write to the Free Software │ |
|
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │ |
|
│ 02110-1301 USA │ |
|
╚─────────────────────────────────────────────────────────────────────────────*/ |
|
#include "libc/dce.h" |
|
#include "libc/macros.h" |
|
.source __FILE__ |
|
|
|
/* ▄▄▄ |
|
▄▄▄ ▀▓▓▒▄ |
|
▄▓▒▒░ ▀▓▒▒▒▄ |
|
▄▓▓▓▒▀ ▄▄▄▄ ▒▓▒▒░▒▄ |
|
▄▓▓▓▒▓ ▄▄▓██▓▓▓▓▒▒▒▒▓▓▄▄▓▓▒▒▒░░▒ |
|
▓▓▓▓▒▒▒▄▄ ░▒█▓▓▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▓▒░░▒░ |
|
██▓▓▓▒▒░░▒▒▒▒▓▓▓▓▓▓▒▓▒░▒▒░▀▒▒▒▒░▀░▒▒▒░▒ |
|
▓▓▓▓▓▓▓▒▒▒▒▒▒▓▓▒▓▓▒▒▒░▒▒░░ ░▒▒░ ░▒▒▒▒ |
|
▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░▒░░ ░▒▒ ░ ▀▒▒ |
|
▀▓▓█▓▓▓▓▓▓▓▓▓▓▒▒░░▒▒░░ ░░░▓░ ▓░░░▒ |
|
▀▀█▓███▓▓▓▓▓▒▒░░░▒░░ ░█▓░█▓░█▓▓▄▒░ |
|
░▓██▓▓▓▓▓▒▒░░░▒░░ ░████▓▒▓█▓▀░▀▄ |
|
░▓██▓▓▓▓▓▒▒▒░░░▒░░ ▒██▓▒▒▒▒▒▒░░░▒ |
|
████▓▓▓▓▓▒▒▒▒▒▒▒▒▒░░▒▓▓▒░░░░▒░░░▒░ ░░░░░ |
|
░▓███▓▓▓▓▓▒▒░░░░░░░▒▒▒▒▒▒▒▒▒▒▒░░░ ░░░░░ ░ |
|
▓███▓▓▓▓▓▒▓▒▒▒▒░░░░░░░░░▒▓▒▒░▀ ░░░ ░░░░░ |
|
▀▒██▓▓▓▓▒▒▒▓▓▓▓▒▒▒▒▒▒▒▓▀▀░ ░░░░░░░░░ ░ |
|
▓▓▓▓▓▓▓▒▓▒▒▒▒▓▓▓▒▀░ ░░░░░▄░░░ ░░░ ░░░░░░ |
|
▓▓▓▒▒▒▒▒▒▒▒▒▒▒▓ █▓▒░░▒░░░░ ░░░░░░░░ |
|
▄▓▓▓▒▒▒▒▒░░░░░░░▒▄▄▄░▒▓▓▒▒░▀░ |
|
░▓█▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒░░░▒ besiyata |
|
▓▓█▓▓▒▓▓▓▒▒▒░░░░░░▒▓▓▓▓▒▒▒▒▒░ dishmaya |
|
▓▓█▓▓▓▓▓▓▒▒▒░░░░░░░▒▓▓▒▀▀▀ |
|
▓▓██▓▓▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▀ |
|
█▓▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▀ |
|
▒▓▓▓▓▀░░▒▓▓▓▓▓▓▓▓▒▒░░▒ |
|
▄▓▓▀░░░▄▓▓▓▓▒▒▒▒▒░░░░▄░ |
|
▄███▄▄▓▓▓▓▓▓▓▒▒▒▒▒░░▒▒░ |
|
▄▓▓▓█▓█▓▓███▓▓▓▓▓▓▓▓▓▓▓░ |
|
▄░▓▓▓▓▓▓▀▒▓▓▓▒▒▓▒░░░▒▓▒░░░▓ |
|
▄▄▄░▒▓▓▓▓▓▓░▀▀ ▓▓▒░▓▒▒▒▒▒▒▒▒▒▒▄░░▀▀░░ ▄▄▄▄ |
|
▄▄▄▒▒▓▓█▓▓▓▓▓▀▀▀▀▀ ▓▓▓▓▓▒▒▒▒▒▒▒▒▒▒▒▒▒▀░░▀░░▒▒▒░░░ ░░░░░ |
|
▄▓▓▓▒▀▀ ▓▒▓▓▓▓▓▒▒▒▒▒▒▒▒▓░░░ ▒▒▒░░░░░░░░▒ |
|
█▓▓▒ ▄▄▄ ▀▓▒▓▒▒▒▓▓▓▓▓▓▒▒▒░░░░░░░░░▒▒░░░░░░░ |
|
▀▓▓▓▓▒▄▄▒▒▒▒▒▒▄▄ ▀▀▀▀░░▒▒▒▒░░░░░░ |
|
▀▀▀▓▓▓▓▒▒▒▒▒▓▓▄▄ |
|
╔────────────────────────────────────────────────────────────────────────────│─╗ |
|
│ cosmopolitan § bell system five » system call support ─╬─│┼ |
|
╚────────────────────────────────────────────────────────────────────────────│*/ |
|
|
|
/ Performs System Five System Call. |
|
/ |
|
/ Cosmopolitan is designed to delegate all function calls into the |
|
/ Linux, FreeBSD, OpenBSD, and XNU kernels through this function, |
|
/ with few exceptions. This function is intended to be called via |
|
/ generated thunks in the libc/sysv/syscalls/ directory. |
|
/ |
|
/ It's safe to call this function on Windows, where it'll always |
|
/ return -1 w/ errno == ENOSYS. Further note that -1 is the only |
|
/ return value that means error, a common anti-pattern is to check |
|
/ for values less than 0 (which is more problematic on 32-bit). |
|
/ |
|
/ It's important to consider that system calls are an order of a |
|
/ magnitude more expensive than normal function calls. For example |
|
/ getpid() on Linux usually takes 500ns, and cached i/o calls will |
|
/ take 1µs or more. |
|
/ |
|
/ @param %rax function ordinal supplied by jump slot |
|
/ @param %rdi,%rsi,%rdx,%rcx,%r8,%r9 and rest on stack |
|
/ @return %rax:%rdx is result, or -1 w/ errno on error |
|
/ @clob %rcx,%r10,%r11 |
|
/ @see syscalls.sh |
|
.initbss 300,_init_systemfive |
|
hostos: .quad 0 |
|
.endobj hostos,globl,hidden |
|
systemfive: |
|
.quad 0 |
|
.endobj systemfive,globl,hidden |
|
.previous |
|
.Lanchorpoint: |
|
systemfive.linux: |
|
movswl %ax,%eax |
|
test %eax,%eax |
|
js systemfive.enosys |
|
mov %rcx,%r10 |
|
push %rbp |
|
mov %rsp,%rbp |
|
syscall |
|
pop %rbp |
|
cmp $-4095,%rax |
|
jae systemfive.error |
|
ret |
|
.endfn systemfive.linux,globl,hidden |
|
systemfive.error: |
|
neg %eax |
|
/ 𝑠𝑙𝑖𝑑𝑒 |
|
.endfn systemfive.error,globl,hidden |
|
systemfive.errno: |
|
mov %eax,errno(%rip) |
|
push $-1 |
|
pop %rax |
|
stc |
|
ret |
|
.endfn systemfive.errno,globl,hidden |
|
systemfive.enosys: |
|
mov ENOSYS(%rip),%eax |
|
jmp systemfive.errno |
|
.endfn systemfive.enosys,globl,hidden |
|
systemfive.openbsd: |
|
shr $48,%rax |
|
jmp systemfive.bsd |
|
.endfn systemfive.openbsd,globl,hidden |
|
systemfive.freebsd: |
|
shr $32,%rax |
|
movzwl %ax,%eax |
|
/ 𝑠𝑙𝑖𝑑𝑒 |
|
.endfn systemfive.freebsd,globl,hidden |
|
systemfive.bsd: |
|
cmp $0xfff,%ax |
|
jae systemfive.enosys |
|
mov %rcx,%r10 |
|
push %rbp |
|
mov %rsp,%rbp |
|
syscall |
|
pop %rbp |
|
jc systemfive.errno |
|
ret |
|
.endfn systemfive.bsd |
|
systemfive.xnu: |
|
/ do this to rax |
|
/ 0x????????2153???? |
|
/ │└┴┴─┐ |
|
/ └┐ ├┬┐ |
|
/ 0x0000000002000153 |
|
mov %eax,%r11d |
|
shr $4*7,%r11d |
|
shl $4*6,%r11d |
|
shl $4*1,%eax |
|
shr $4*5,%eax |
|
or %r11d,%eax |
|
jmp systemfive.bsd |
|
.endfn systemfive.xnu,globl,hidden |
|
.previous |
|
|
|
/ Initializes System Five system call support. |
|
/ |
|
/ (1) Extracts parameters passed by kernel, |
|
/ (2) Detects O/S without issuing system calls, |
|
/ (3) Unpacks numbers. |
|
/ |
|
/ @param %r15 is auxv |
|
/ @note OpenBSD devs: let us know if you start using auxv |
|
.init.start 300,_init_systemfive |
|
push %rbx |
|
push %rsi |
|
testb $METAL,(%rdi) # @see ape/ape.S |
|
jnz systemfive.init.metal |
|
testb $XNU,(%rdi) # @see libc/crt/crt.S |
|
jnz systemfive.init.xnu |
|
testb $FREEBSD,(%rdi) # @see libc/crt/crt.S |
|
jnz systemfive.init.freebsd |
|
testb $WINDOWS,(%rdi) # @see libc/runtime/winmain.c |
|
jnz systemfive.init.windows |
|
cmpq $0,(%r15) # OpenBSD doesn't have auxv |
|
je systemfive.init.openbsd |
|
/ default state is safe state |
|
/ 𝑠𝑙𝑖𝑑𝑒 |
|
systemfive.init.linux: |
|
pushb systemfive.linux-.Lanchorpoint |
|
push $LINUX |
|
ezlea syscon.linux,si |
|
jmp systemfive.init.os |
|
systemfive.init.metal: |
|
pushb systemfive.linux-.Lanchorpoint |
|
push $METAL |
|
ezlea syscon.linux,si |
|
jmp systemfive.init.os |
|
systemfive.init.windows: |
|
pushb systemfive.enosys-.Lanchorpoint |
|
push $WINDOWS |
|
ezlea syscon.windows,si |
|
jmp systemfive.init.os |
|
systemfive.init.freebsd: |
|
pushb systemfive.freebsd-.Lanchorpoint |
|
push $FREEBSD |
|
ezlea syscon.freebsd,si |
|
jmp systemfive.init.os |
|
systemfive.init.openbsd: |
|
pushb systemfive.openbsd-.Lanchorpoint |
|
push $OPENBSD |
|
ezlea syscon.openbsd,si |
|
jmp systemfive.init.os |
|
systemfive.init.xnu: |
|
pushb systemfive.xnu-.Lanchorpoint |
|
push $XNU |
|
ezlea syscon.xnu,si |
|
/ 𝑠𝑙𝑖𝑑𝑒 |
|
systemfive.init.os: |
|
ezlea .Lanchorpoint,cx |
|
pop %rax |
|
stosq #→ hostos |
|
pop %rax |
|
add %rcx,%rax |
|
stosq #→ systemfive |
|
push %rdi |
|
ezlea syscon.start,di |
|
ezlea syscon.end,bx |
|
call systemfive.sleb128unpacker |
|
pop %rdi |
|
/ 𝑠𝑙𝑖𝑑𝑒 |
|
systemfive.init.done: |
|
pop %rsi |
|
pop %rbx |
|
.init.end 300,_init_systemfive,globl,hidden |
|
|
|
.text.startup |
|
systemfive.sleb128unpacker: |
|
.leafprologue |
|
or $-1,%r9 |
|
2: cmp %rbx,%rdi |
|
jnb 5f |
|
xor %ecx,%ecx |
|
xor %edx,%edx |
|
3: lodsb |
|
mov %rax,%r8 |
|
and $127,%r8d |
|
sal %cl,%r8 |
|
add $7,%ecx |
|
or %r8,%rdx |
|
test %al,%al |
|
js 3b |
|
test $64,%al |
|
je 4f |
|
mov %r9,%rax |
|
sal %cl,%rax |
|
or %rax,%rdx |
|
4: mov %rdx,%rax |
|
cmpq $0,(%rdi) # don't change consts already set |
|
cmovne (%rdi),%rax # @see WinMain() for example |
|
stosq |
|
jmp 2b |
|
5: .leafepilogue |
|
.previous |
|
|
|
/ Sections for varint encoded numbers. |
|
/ |
|
/ These sections are all ordered by (group_name, constant_name). |
|
/ They're populated by modules simply referencing the symbols. |
|
/ |
|
/ @see libc/sysv/consts.sh |
|
/ @see libc/sysv/consts/syscon.h |
|
.section .piro.bss.sort.syscon.1,"aw",@nobits |
|
.align 8 |
|
syscon.start:/* |
|
...decentralized quadwords... |
|
*/.previous |
|
.section .piro.bss.sort.syscon.3,"aw",@nobits |
|
syscon.end: |
|
.previous |
|
.section .sort.rodata.syscon.linux.1,"a",@progbits |
|
.align 1 |
|
syscon.linux:/* |
|
...decentralized leb128... |
|
*/.previous |
|
.section .sort.rodata.syscon.xnu.1,"a",@progbits |
|
.align 1 |
|
syscon.xnu:/* |
|
...decentralized leb128... |
|
*/.previous |
|
.section .sort.rodata.syscon.freebsd.1,"a",@progbits |
|
.align 1 |
|
syscon.freebsd:/* |
|
...decentralized leb128... |
|
*/.previous |
|
.section .sort.rodata.syscon.openbsd.1,"a",@progbits |
|
.align 1 |
|
syscon.openbsd:/* |
|
...decentralized leb128... |
|
*/.previous |
|
.section .sort.rodata.syscon.windows.1,"a",@progbits |
|
.align 1 |
|
syscon.windows:/* |
|
...decentralized leb128... |
|
*/.previous |
|
|
|
.type syscon.start,@object |
|
.type syscon.end,@object |
|
.type syscon.linux,@object |
|
.type syscon.xnu,@object |
|
.type syscon.freebsd,@object |
|
.type syscon.openbsd,@object |
|
.type syscon.windows,@object |
|
|
|
.globl syscon.start |
|
.globl syscon.end |
|
.globl syscon.linux |
|
.globl syscon.xnu |
|
.globl syscon.freebsd |
|
.globl syscon.openbsd |
|
.globl syscon.windows
|
|
|