mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
2d80bbc802
blinkenlights now does a pretty good job emulating what happens when binaries boot from BIOS into long mode. So it's been much easier to debug the bare metal process and wrinkle out many issues.
313 lines
12 KiB
ArmAsm
313 lines
12 KiB
ArmAsm
/*-*- 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
|