Compare commits

..
1 Commits
Author SHA1 Message Date
Justine Tunney face6b61d5 Add APE support for 32-bit programs
This is an experimental proof of concept demo:

    make -j8 o//examples/i386.i386.com
    o//examples/i386.i386.com --32
    echo $?  # <-- prints main32's argc parameter

Please note there's no libc support at the moment. This change is just
for fun and shouldn't be interpreted as intent to support. Having this
project on the whole support i386 would be tough because the calling
conventions are so different. There really isn't much in the way of low
hanging fruit opportunities to do something like NOP out REX prefixes
and call it a day. It'd likely need disjoint builds or possibly better
yet really cleverly crafted code generation in //third_party/chibicc!

Another challenge is is that Linux changed its SYSCALL ordinals when it
migrated from i386 to x86_64. Linux used to use the same magic numbers
as everyone else for functions like exit/write/read/etc. BSDs on the
other hand didn't pointlessly renumber things. So we'd need to find a
way to define the ordinals in libc/sysv/syscalls.sh twice for Linux. The
same goes for other ISAs too. Especially MIPS. For the Linux Kernel
alone, syscall magic numbers and data structure layouts are totally
different, and that's likely the case for other ISAs on other operating
systems too. Probably because ISA code historically got contributed to
open source by the companies that made the chips. Ulrich Drepper wrote
an amusing essay on the subject some years back.
2021-02-20 15:58:48 -08:00
2689 changed files with 118762 additions and 71664 deletions

No files matched your search

-6
View File
@@ -1,6 +0,0 @@
virt: lxd
os: linux
language: c
script: make -j4 V=0
notifications:
email: false
+2 -45
View File
@@ -1,12 +1,13 @@
{
"configurations": [
{
"name": "Win32",
"name": "Linux",
"includePath": [
"${workspaceFolder}"
],
"cStandard": "c11",
"cppStandard": "c++11",
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
"forcedInclude": ["${workspaceFolder}/.vscode/vscode.h"],
"defines": [
"libcesque=",
@@ -62,50 +63,6 @@
"attributeallocalign(x)=",
"nullterminated(x)="
]
},
{
"name": "Linux",
"includePath": [
"${workspaceFolder}"
],
"cStandard": "gnu17",
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
"compilerArgs": [
"-Wall",
"-Werror",
"-fdebug-prefix-map=${workspaceFolder}=",
"-frecord-gcc-switches",
"-Wa,-W",
"-Wa,-I.",
"-Wa,--noexecstack",
"-Wa,--nocompress-debug-sections",
"-Og",
"-g",
"-gdescribe-dies",
"-msse3",
"-mno-red-zone",
"-fno-math-errno",
"-fno-trapping-math",
"-fno-fp-int-builtin-inexact",
"-fno-ident",
"-fno-common",
"-fno-gnu-unique",
"-fstrict-aliasing",
"-fstrict-overflow",
"-fno-semantic-interposition",
"-mno-omit-leaf-frame-pointer",
"-fno-jump-tables",
"-nostdinc",
"-iquote."
],
"forcedInclude": [
"libc/integral/normalize.inc"
],
"defines": [
"COSMO",
"MODE=",
"IMAGE_BASE_VIRTUAL=0x400000"
]
}
],
"version": 4
+158
View File
@@ -1,2 +1,160 @@
#define __VSCODE_INTELLISENSE__ 1
#include "libc/integral/normalize.inc"
#if 0
#define __VSCODE_INTELLISENSE__ 1
#define __BIGGEST_ALIGNMENT__ 1
#define __CHAR_MAX__ 0x7F
#define __SCHAR_MAX__ __CHAR_MAX__
#define __SHRT_MAX__ 0x7FFF
#define __INT_MAX__ 0x7FFFFFFF
#define __LONG_MAX__ 0x7FFFFFFFFFFFFFFF
#define __LONG_LONG_MAX__ __LONG_MAX__
#define __CHAR_MIN__ -((__CHAR_MAX__) + 1)
#define __SHRT_MIN__ -((__SHRT_MAX__) + 1)
#define __INT_MIN__ -((__INT_MAX__) + 1)
#define __LONG_MIN__ -((__LONG_MAX__) + 1)
#define __LONG_LONG_MIN__ -((__LONG_LONG_MAX__) + 1)
#define __UCHAR_MAX__ 0xFF
#define __USHRT_MAX__ 0xFFFF
#define __UINT_MAX__ 0xFFFFFFFF
#define __ULONG_MAX__ 0xFFFFFFFFFFFFFFFF
#define __SIZE_MAX__ __ULONG_MAX__
#define __SSIZE_MAX__ __LONG_MAX__
#define __UINTPTR_MAX__ __SIZE_MAX__
#define __INTPTR_MAX__ __SSIZE_MAX__
#define __WCHAR_MAX__ __UINT_MAX__
#define __PTRDIFF_MAX__ __UINTPTR_MAX__
#define __INTMAX_MAX__ __ULONG_MAX__
#define __SIZEOF_POINTER__ 8
#define __SIZEOF_SHORT__ 2
#define __SIZEOF_INT__ 4
#define __SIZEOF_LONG__ 8
#define __SIZEOF_LONG_LONG__ 8
#define __SIZEOF_PTRDIFF_T__ 8
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_WCHAR_T__ 4
#define __SIZEOF_WINT_T__ 4
#define __SIZEOF_FLOAT__ 4
#define __SIZEOF_FLOAT128__ 16
#define __SIZEOF_DOUBLE__ 8
#define __SIZEOF_FLOAT80__ 10
#define __SIZEOF_LONG_DOUBLE__ 16
#define __FLT_MAX__ 1
#define __DBL_MAX__ 1
#define __INT_LEAST8_TYPE__ signed char
#define __INT_LEAST16_TYPE__ signed short
#define __INT_LEAST32_TYPE__ signed int
#define __INT_LEAST64_TYPE__ signed long long
#define __UINT_LEAST8_TYPE__ unsigned char
#define __UINT_LEAST16_TYPE__ unsigned short
#define __UINT_LEAST32_TYPE__ unsigned int
#define __UINT_LEAST64_TYPE__ unsigned long long
#define __UINT8_MAX__ __UCHAR_MAX__
#define __UINT16_MAX__ __USHRT_MAX__
#define __UINT32_MAX__ __UINT_MAX__
#define __UINT64_MAX__ __ULONG_MAX__
#define __INT8_MAX__ __CHAR_MAX__
#define __INT16_MAX__ __SHRT_MAX__
#define __INT32_MAX__ __INT_MAX__
#define __INT64_MAX__ __LONG_MAX__
#define ATEXIT_MAX 1
#define STACKSIZE 0x10000
#define ARG_MAX 255
#define OPEN_MAX 0x7FFF
#define CHAR_BIT 7
#define NSIG 1
#define NULL (0)
#define false 0
#define true (!(false))
#define COSMOPOLITAN_C_START_
#define COSMOPOLITAN_C_END_
#define PAGESIZE 0x1000
#define BIGPAGESIZE 0x10000
#define NAME_MAX 255
#define SWITCHEROO(...) 0
extern unsigned g_loglevel;
typedef void * va_list;
#define va_start(...) 0
#define va_end(...) 0
#define va_arg(x, y) (y)(0)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
#define int64_t long long
#define int128_t int64_t
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef unsigned long long uint128_t;
typedef int errno_t;
typedef uint64_t size_t;
typedef unsigned long long ssize_t;
typedef uint64_t uintptr_t;
typedef long long intptr_t;
typedef unsigned long long uintmax_t;
typedef long long intmax_t;
typedef uint32_t bool32;
#ifndef __cplusplus
typedef uint8_t bool;
typedef uint16_t char16_t;
typedef uint32_t char32_t;
#endif /* __cplusplus */
typedef char32_t wint_t;
typedef char32_t wchar_t;
typedef struct { int ax, dx; } axdx_t;
/* duplicate and replace xmmintrin.internal.h to fix it for IntelliSense
* SEE: <> */
#define _Vector_size(x) __attribute__((__vector_size__(x)))
#define IMAGE_BASE_VIRTUAL 0x400000
#define __SIGACTION(...) (0)
#define VEIL(x, y) (y)
#define STATIC_YOINK(x)
#define BUFSIZ 1
#define FRAMESIZE 0x10000
#define PATH_MAX 252
#define concat(x, y, z) 0
#define CONCAT(a, b, c, d, e) 0
#define shuffle(...) 0
#define reverse(x, y) 0
#define autotype(x) intptr_t
#define _Generic_(...) (void*)(0)
#define _Generic(...) _Generic_
#define _Alignas(...)
#define _Section(...)
#define offsetof(x, y) 0
#define INITIALIZER(...) struct _dummy
#define __far
#define tinystrstr(...) 0
#define BENCHLOOP(...) 0
#ifdef __hook
#undef __hook
#endif /* __hook */
#ifdef UriKeyval
#undef UriKeyval
#endif /* UriKeyval */
#define _Static_assert(...) 0
#endif /* 0 */
+9 -5
View File
@@ -40,7 +40,8 @@
# o/dbg/examples/crashreport.com
# less examples/crashreport.c
#
# # extremely tiny binaries
# # extremely tiny binaries (scout's honor escape hatch)
# # please pay the $1k for commercial license if you can
# make -j8 -O MODE=tiny \
# LDFLAGS+=-s \
# CPPFLAGS+=-DIM_FEELING_NAUGHTY \
@@ -100,6 +101,7 @@ include libc/str/str.mk # │
include third_party/xed/xed.mk # │
include third_party/zlib/zlib.mk # │
include libc/elf/elf.mk # │
include ape/lib/apelib.mk # │
include ape/ape.mk # │
include libc/fmt/fmt.mk #─┘
include libc/calls/calls.mk #─┐
@@ -131,11 +133,11 @@ include dsp/tty/tty.mk # ├──ONLINE RUNTIME
include libc/dns/dns.mk # │ You can communicate with the network
include libc/crypto/crypto.mk # │
include net/http/http.mk #─┘
include third_party/duktape/duktape.mk
include third_party/regex/regex.mk
include third_party/third_party.mk
include libc/testlib/testlib.mk
include tool/viz/lib/vizlib.mk
include third_party/lua/lua.mk
include examples/examples.mk
include third_party/lz4cli/lz4cli.mk
include tool/build/lib/buildlib.mk
@@ -171,13 +173,14 @@ include test/libc/time/test.mk
include test/libc/stdio/test.mk
include test/libc/release/test.mk
include test/libc/test.mk
include test/ape/lib/test.mk
include test/ape/test.mk
include test/net/http/test.mk
include test/net/test.mk
include test/tool/build/lib/test.mk
include test/tool/build/test.mk
include test/tool/viz/lib/test.mk
include test/tool/viz/test.mk
include test/tool/net/test.mk
include test/tool/test.mk
include test/dsp/core/test.mk
include test/dsp/scale/test.mk
@@ -234,15 +237,16 @@ COSMOPOLITAN_OBJECTS = \
LIBC_NT_MSWSOCK \
LIBC_OHMYPLUS \
LIBC_X \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
LIBC_LOG \
LIBC_UNICODE \
LIBC_TIME \
LIBC_ZIPOS \
THIRD_PARTY_ZLIB \
APE_LIB \
THIRD_PARTY_MUSL \
LIBC_STDIO \
THIRD_PARTY_GDTOA \
THIRD_PARTY_REGEX \
LIBC_ALG \
LIBC_MEM \
@@ -265,8 +269,8 @@ COSMOPOLITAN_OBJECTS = \
LIBC_FMT \
THIRD_PARTY_COMPILER_RT \
LIBC_TINYMATH \
LIBC_STR \
LIBC_SYSV \
LIBC_STR \
LIBC_INTRIN \
LIBC_NT_KERNEL32 \
LIBC_NEXGEN32E
-2
View File
@@ -1,5 +1,3 @@
ISC License
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
+7 -32
View File
@@ -19,31 +19,19 @@ libc](https://justine.lol/cosmopolitan/index.html) website. We also have
## Getting Started
If you're doing your development work on Linux or BSD then you need just
five files to get started. Here's what you do on Linux:
five files to get started:
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-0.3.zip
unzip cosmopolitan-amalgamation-0.3.zip
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-0.2.zip
unzip cosmopolitan-amalgamation-0.2.zip
printf 'main() { printf("hello world\\n"); }\n' >hello.c
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
-fno-omit-frame-pointer -pg -mnop-mcount \
gcc -g -O -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds \
-include cosmopolitan.h crt.o ape.o cosmopolitan.a
objcopy -S -O binary hello.com.dbg hello.com
```
You now have a portable program. Please note that your APE binary will
assimilate itself as a conventional resident of your platform after the
first run, so it can be fast and efficient for subsequent executions.
```sh
./hello.com
bash -c './hello.com' # zsh/fish workaround (we upstreamed a patch)
```
So if you intend to copy the binary to Windows or Mac then please do
that before you run it, not after.
If you're developing on Windows or MacOS then you need to download an
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
@@ -53,23 +41,10 @@ universal binaries possible.
Cosmopolitan can also be compiled from source on any Linux distro.
```sh
wget https://justine.lol/cosmopolitan/cosmopolitan-0.3.tar.gz
tar xf cosmopolitan-0.3.tar.gz # see releases page
cd cosmopolitan
wget https://justine.lol/cosmopolitan/cosmopolitan-0.2.tar.gz
tar xf cosmopolitan-0.2.tar.gz # see releases page
cd cosmopolitan-0.2
make -j16
o//examples/hello.com
find o -name \*.com | xargs ls -rShal | less
```
## Support Vector
| Platform | Min Version | Circa |
| :--- | ---: | ---: |
| AMD | K8 Venus | 2005 |
| Intel | Core | 2006 |
| New Technology | Vista | 2006 |
| GNU/Systemd | 2.6.18 | 2007 |
| XNU's Not UNIX! | 15.6 | 2018 |
| FreeBSD | 12 | 2018 |
| OpenBSD | 6.4 | 2018 |
| NetBSD | 9.1 | 2020 |
+356 -238
View File
@@ -32,19 +32,20 @@
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
│ αcτµαlly pδrταblε εxεcµταblε § program header │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/config.h"
#include "ape/lib/pc.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
#include "ape/relocations.h"
#include "libc/dce.h"
#include "libc/elf/def.h"
#include "libc/macho.internal.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/nexgen32e/vidya.internal.h"
#include "libc/nt/pedef.internal.h"
#include "libc/runtime/pc.internal.h"
#include "libc/dce.h"
#include "libc/sysv/consts/prot.h"
#define USE_SYMBOL_HACK 1
#define USE_SYMBOL_HACK 0
.section .text,"ax",@progbits
.align __SIZEOF_POINTER__
@@ -61,6 +62,9 @@ __ro: .endobj __ro,globl,hidden # ←for gdb readibility
.previous
.section .rodata.str1.1,"a",@progbits
cstr: .endobj cstr,globl,hidden # ←for gdb readibility
.previous
.section .sort.rodata.real.str1.1,"a",@progbits
rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility
.previous
.section .head,"ax",@progbits
@@ -101,7 +105,7 @@ cstr: .endobj cstr,globl,hidden # ←for gdb readibility
│ αcτµαlly pδrταblε εxεcµταblε § the old technology │
╚─────────────────────────────────────────────────────────────────────────────*/
#if SupportsWindows() || SupportsMetal() || SupportsXnu()
#if SupportsWindows() || SupportsXnu()
// MZ Literally Executable Header
//
@@ -127,14 +131,14 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
.ascii "JT" # MZ: OEM identifier
.short 0 # MZ: OEM information
.org 0x40-4 # MZ: bytes reserved for you
#if SupportsWindows() || SupportsMetal()
#if SupportsWindows()
.long RVA(ape_pe) # PE: the new technology
#else
.long 0
#endif
.endfn ape_mz,globl,hidden
#else /* !(SupportsWindows() || SupportsMetal() || SupportsXnu()) */
#else /* !(SupportsWindows() || SupportsXnu()) */
// ELF Literally Executable Header
//
@@ -164,7 +168,7 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski
.short ape_elf_shnum # 3c: e_shnum
.short ape_elf_shstrndx # 3e: e_shstrndx
#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */
#endif /* SupportsWindows() || SupportsXnu() */
#if SupportsMetal()
@@ -214,17 +218,17 @@ pc: cld
.byte 0x0f,0x1f,0207 # nop rdi binbase
.short (0x7c00-IMAGE_BASE_VIRTUAL)/512
#endif
mov $0x70000>>4,%di # we need a stack
xor %cx,%cx # 0x7f000-0x80000
mov $REAL_STACK_FRAME>>4,%di # we need a stack
xor %cx,%cx
mov %cx,%es
rlstack %di,%cx
push %cs # determine load address
pop %ds # and relocate this code
call 1f # to a way lower address
1: pop %si # and we'll make cs zero
push %cs # memcpy() [relocate this page]
pop %ds
call 1f
1: pop %si
sub $RVA(1b),%si
mov $IMAGE_BASE_REAL>>4,%ax
push %ax # save IMAGE_BASE_REAL>>4
push %ax # save real base
push %ax
pop %es
xor %di,%di
@@ -234,18 +238,18 @@ pc: cld
.byte 0x0f,0x1f,0207 # nop rdi binbase
.short (IMAGE_BASE_REAL-0x7c00)/512
#endif
ljmp $0,$REAL(1f)
1: mov %cx,%ds
mov $IMAGE_BASE_REAL-0x0500,%cx # clears bss
mov $0x0500>>4,%ax # struct mman
ljmp $0,$REAL(1f) # longjmp()
1: mov %cx,%ds # %ds and %cs are now zero
mov $XLM_SIZE,%cx # memset to clear real bss
mov $XLM_BASE_REAL>>4,%ax
mov %ax,%es
xor %ax,%ax
xor %di,%di
rep stosb
cmp $0x40,%dl
cmp $0x40,%dl # statfs() [disk geometry]
je 6f
call dsknfo
pop %es # restore IMAGE_BASE_REAL>>4
pop %es # restore real base
mov $1,%al # current sector
xor %cx,%cx # current cylinder
xor %dh,%dh # current head
@@ -253,7 +257,15 @@ pc: cld
3: call pcread
dec %di
jnz 3b
6: ljmp $0,$REAL(realmodeloader)
6: mov $XLM(LOADSTATE),%di # ax,cx,dx,es
stosw
xchg %cx,%ax
stosw
xchg %dx,%ax
stosw
mov %es,%ax
stosw
ljmp $0,$REAL(realmodeloader)
.endfn pc
// Determines disk geometry.
@@ -314,7 +326,7 @@ dsknfo: push %bx
movpp %es,%ds
xor %si,%si
mov %si,%es
mov $0x1510,%si # mman::pc_drive_base_table
mov $XLM(DRIVE_BASE_TABLE),%si
xchg %si,%di
movsw #→ headunloadtime, headloadtime
movsw #→ shutofftime, bytespersector
@@ -367,11 +379,11 @@ pcread: push %ax
add $512>>4,%si
mov %si,%es
inc %al # ++sector
cmp 0x151c,%al # mman::pc_drive_last_sector
cmp XLM(DRIVE_LAST_SECTOR),%al
jbe 2f
mov $1,%al
inc %dh # ++head
cmp 0x1520,%dh # mman::pc_drive_last_head
cmp XLM(DRIVE_LAST_HEAD),%dh
jbe 2f
xor %dh,%dh
inc %cx # ++cylinder
@@ -383,82 +395,6 @@ pcread: push %ax
jmp pcread
.endfn pcread
// Video put string.
//
// @param di is the string
// @clob bp,bx
// @mode real
rvputs: mov %di,%si
0: lodsb
test %al,%al
je 1f
mov $7,%bx # normal mda/cga style page zero
mov $0x0e,%ah # teletype output al cp437
int $0x10 # vidya service
jmp 0b
1: ret
.endfn rvputs
// Abnormally halts startup.
//
// @param di message
// @mode real
// @noreturn
rldie: push %di
mov $REAL(str.error),%di
call rvputs
pop %di
call rvputs
mov $REAL(str.crlf),%di
call rvputs
0: rep nop
jmp 0b
.endfn rldie
// Initializes present PC serial lines.
sinit4: mov $4,%cx
mov $0x400,%si # BDA.COM1
0: lodsw
test %ax,%ax
jz 1f
push %cx
push %si
xchg %ax,%di
mov $REAL(sconf),%si
call sinit
pop %si
pop %cx
1: loop 0b
ret
.endfn sinit4,global,hidden
// Initializes Serial Line Communications 8250 UART 16550A
//
// @param word di tty port
// @param char (*{es:,e,r}si)[4] register initial values
// @mode long,legacy,real
// @see www.lammertbies.nl/comm/info/serial-uart.html
sinit: mov %di,%dx
test %dx,%dx
jz 2f
push %dx
push %si
xor %cx,%cx
mov $UART_LCR,%cl
add %cx,%dx
lodsb %ds:(%si),%al
pop %si
or $UART_DLAB,%al
out %al,%dx
pop %dx
1: lodsb %ds:(%si),%al
out %al,%dx
inc %dx
dec %cx
jns 1b
2: ret
.endfn sinit,global,hidden
/*───────────────────────────────────────────────────────────────────────────│─╗
│ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
@@ -533,7 +469,9 @@ ape_disk:
╚────────────────────────────────────────────────────────────────────────────│─╝
the bourne executable & linkable format */
#if SupportsWindows() || SupportsMetal() || SupportsXnu()
#if SupportsSystemv()
#if SupportsWindows() || SupportsXnu()
apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "o=\"$(command -v \"$0\")\"\n"
#if SupportsXnu()
@@ -549,6 +487,36 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "el"
#endif
.ascii "if exec 7<> \"$o\"; then\n"
// Writes 32-bit ELF header if --32 is the first argument
// This should be changed to check $(uname -m) on ENOEXEC
.ascii "if [ x\"$1\" = x--32 ]; then\n"
.ascii "printf '"
.ascii "\\177ELF" # 0x0: ⌂ELF
.ascii "\\1" # 4: legacy mode
.ascii "\\1" # 5: little endian
.ascii "\\1" # 6: elf v1.o
.ascii "\\011" # 7: FreeBSD
.ascii "\\0" # 8: os/abi ver.
.ascii "\\0\\0\\0" # 9: padding 3/7
.ascii "\\0\\0\\0\\0" # padding 4/7
.ascii "\\2\\0" # 10: εxεcµταblε
.ascii "\\3\\0" # 12: i386
.ascii "\\1\\0\\0\\0" # 14: elf v1.o
.shstub ape_elf32_entry,4 # 18: e_entry
.shstub ape_elf32_phoff,4 # 1c: e_phoff
.shstub ape_elf32_shoff,4 # 20: e_shoff
.ascii "\\0\\0\\0\\0" # 24: e_flags
.ascii "\\100\\0" # 28: e_ehsize
.ascii "\\040\\0" # 2a: e_phentsize
.shstub ape_elf32_phnum,2 # 2c: e_phnum
.ascii "\\0\\0" # 2e: e_shentsize
.shstub ape_elf32_shnum,2 # 30: e_shnum
.shstub ape_elf32_shstrndx,2 # 32: e_shstrndx
.ascii "' >&7\n"
.ascii "else\n"
// Standard 64-bit ELF Header
.ascii "printf '"
.ascii "\\177ELF" # 0x0: ⌂ELF
.ascii "\\2" # 4: long mode
@@ -572,9 +540,9 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.shstub ape_elf_shnum,2 # 3c: e_shnum
.shstub ape_elf_shstrndx,2 # 3e: e_shstrndx
.ascii "' >&7\n"
.ascii "fi\n"
.ascii "exec 7<&-\n"
.ascii "else\n"
.ascii "exit 1\n"
.ascii "fi\n"
.ascii "exec \"$0\" \"$@\"\n" # etxtbsy tail recursion
.ascii "R=$?\n" # architecture optimistic
@@ -590,11 +558,10 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.ascii "fi\n"
.ascii "exit $R\n"
.endobj apesh
#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */
#endif /* SupportsWindows() || SupportsXnu() */
#if SupportsSystemv() || SupportsMetal()
.section .elf.phdrs,"a",@progbits
.long PT_LOAD
.long PT_LOAD # text segment
.long PF_R|PF_X
.stub ape_rom_offset,quad
.stub ape_rom_vaddr,quad
@@ -602,7 +569,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.stub ape_rom_filesz,quad
.stub ape_rom_memsz,quad
.stub ape_rom_align,quad
.long PT_LOAD
.long PT_LOAD # data segment
.long PF_R|PF_W
.stub ape_ram_offset,quad
.stub ape_ram_vaddr,quad
@@ -610,16 +577,20 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.stub ape_ram_filesz,quad
.stub ape_ram_memsz,quad
.stub ape_ram_align,quad
.long PT_GNU_STACK
.long PF_R|PF_W
.stub ape_stack_offset,quad
.stub ape_stack_vaddr,quad
.stub ape_stack_paddr,quad
.stub ape_stack_filesz,quad
.stub ape_stack_memsz,quad
.stub ape_stack_align,quad
#if SupportsLinux()
// Linux ignores mprotect() and returns 0 without this lool
// It has nothing to do with the stack, which is still exec
.long PT_GNU_STACK # p_type
.long PF_R|PF_W # p_flags
.quad 0 # p_offset
.quad 0 # p_vaddr
.quad 0 # p_paddr
.quad 0 # p_filesz
.quad 0 # p_memsz
.quad 16 # p_align
#endif
#if SupportsOpenbsd() || SupportsNetbsd()
.long PT_NOTE
.long PT_NOTE # notes
.long PF_R
.stub ape_note_offset,quad
.stub ape_note_vaddr,quad
@@ -629,7 +600,6 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
.stub ape_note_align,quad
#endif
.previous
#endif /* SupportsSystemv() || SupportsMetal() */
#if SupportsOpenbsd()
.section .note.openbsd.ident,"a",@progbits
@@ -659,6 +629,8 @@ netbsd.ident:
.previous
#endif /* SupportsNetbsd() */
#endif /* SupportsSystemv() */
/* ▄▄███▄
▄▄████████▄
▄█████████████▄
@@ -872,7 +844,7 @@ PETEXT = 0b01110000000000000000000001100000
PEDATA = 0b11000000000000000000000011000000
PEIMPS = 0b11000000000000000000000001000000
#if SupportsWindows() || SupportsMetal()
#if SupportsWindows()
.section .pe.header,"a",@progbits
.align __SIZEOF_POINTER__
@@ -890,23 +862,23 @@ ape_pe: .ascin "PE",4
.long 0 # SizeOfCode
.long 0 # SizeOfInitializedData
.long 0 # SizeOfUninitializedData
.long RVA(ape_pe_entry) # EntryPoint
.long RVA(WinMain) # EntryPoint
.long 0 # BaseOfCode
.quad ape_pe_base # ImageBase
.quad IMAGE_BASE_VIRTUAL # ImageBase
.long 4096 # SectionAlignment
.long 4096 # FileAlignment
.short v_ntversion # MajorOperatingSystemVersion
.short 6 # MajorOperatingSystemVersion
.short 0 # MinorOperatingSystemVersion
.short 0 # MajorImageVersion
.short 0 # MinorImageVersion
.short v_ntsubversion # MajorSubsystemVersion
.short 6 # MajorSubsystemVersion
.short 0 # MinorSubsystemVersion
.long 0 # Win32VersionValue
.long RVA(_end) # SizeOfImage
.long RVA(_ehead) # SizeOfHeaders
.long 0 # Checksum
.short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console
.stub v_ntdllchar,short # DllCharacteristics
.short DLLEXE # DllCharacteristics
.quad 0x0000000000100000 # StackReserve
.quad 0x00000000000fc000 # StackCommit
.quad 0 # HeapReserve
@@ -914,7 +886,7 @@ ape_pe: .ascin "PE",4
.long 0 # LoaderFlags
.long 16 # NumberOfDirectoryEntries
.long 0,0 # ExportsDirectory
.stub ape_idata,long # ImportsDirectory
.long RVA(ape_idata_idt) # ImportsDirectory
.stub ape_idata_idtsize,long # ImportsDirectorySize
.long 0,0 # ResourcesDirectory
.long 0,0 # ExceptionsDirectory
@@ -926,7 +898,7 @@ ape_pe: .ascin "PE",4
.long 0,0 # ThreadLocalStorage
.long 0,0 # LoadConfigurationDirectory
.long 0,0 # BoundImportDirectory
.stub ape_idata,long # ImportAddressDirectory
.long RVA(ape_idata_iat) # ImportAddressDirectory
.stub ape_idata_iatsize,long # ImportAddressDirectorySize
.long 0,0 # DelayImportDescriptor
.long 0,0 # ComPlusRuntimeHeader
@@ -944,7 +916,7 @@ ape_pe: .ascin "PE",4
.long 0 # Line Number Table Offset
.short 0 # Relocation Count
.short 0 # Line Number Count
.long PETEXT # Flags
.long PETEXT # Flags
.previous
.section .pe.sections,"a",@progbits
@@ -957,10 +929,10 @@ ape_pe: .ascin "PE",4
.long 0 # Line Number Table Offset
.short 0 # Relocation Count
.short 0 # Line Number Count
.long PEDATA # Flags
.long PEDATA # Flags
.previous
#endif /* SupportsWindows() || SupportsMetal() */
#endif /* SupportsWindows() */
.section .idata.ro.idt.1,"a",@progbits
.type ape_idata_idtend,@object
@@ -998,6 +970,13 @@ ape_idata_iatend:
better code/data separation (.head is rwx[real] rx[long]) */
// NUL-Terminated Strings.
ape.str:
str.ape:
.byte 0xe0,0x63,0xe7,0xe6,0xe0,0x6c,0x6c,0x79 #αcτµαlly
.byte 0x20,0x70,0xeb,0x72,0xe7,0xe0,0x62,0x6c # pδrταbl
.byte 0xee,0x20,0xee,0x78,0xee,0x63,0xe6,0xe7 #ε εxεcµτ
.byte 0xe0,0x62,0x6c,0xee,0x0d,0x0a,0x00 #αblε.
.endobj str.ape
str.error:
.asciz "error: "
.endobj str.error
@@ -1010,12 +989,19 @@ str.cpuid:
str.oldskool:
.asciz "oldskool"
.endobj str.oldskool
str.dsknfo:
.asciz "dsknfo"
.endobj str.dsknfo
str.e820:
.asciz "e820"
.endobj str.e820
str.memory:
.asciz "nomem"
.endobj str.memory
str.long:
.asciz "nolong"
.endobj str.long
.endobj ape.str
// Serial Line Configuration (8250 UART 16550)
// If it's hacked, it'll at least get hacked very slowly.
@@ -1105,8 +1091,8 @@ ape_grub:
.align 4
ape_grub_entry:
.code32
// cmp $GRUB_EAX,%eax
// jne triplf
cmp $GRUB_EAX,%eax
jne triplf
push $0
popf
mov $0x40,%dl
@@ -1122,12 +1108,18 @@ ape_grub_entry:
╚──────────────────────────────────────────────────────────────────────────────╝
the default mode of operation on modern cpus */
nop
nop
nop
nop
realmodeloader:
call rlinit
call sinit4
call16 rlinit
call16 sinit4
mov $REAL(str.ape),%di
call16 rvputs
.optfn _start16
call _start16
call longmodeloader
call16 _start16
call16 longmodeloader
.endfn realmodeloader
.section .sort.text.real.init.1,"ax",@progbits
@@ -1140,6 +1132,86 @@ rlinit: .previous/*
ret
.previous
// Initializes present PC serial lines.
sinit4: mov $4,%cx
mov $kBiosDataAreaXlm+COM1,%si
0: lodsw
test %ax,%ax
jz 1f
push %cx
push %si
xchg %ax,%di
mov $REAL(sconf),%si
call16 sinit
pop %si
pop %cx
1: loop 0b
ret
.endfn sinit4,global,hidden
// Initializes Serial Line Communications 8250 UART 16550A
//
// @param word di tty port
// @param char (*{es:,e,r}si)[4] register initial values
// @mode long,legacy,real
// @see www.lammertbies.nl/comm/info/serial-uart.html
sinit: mov %di,%dx
test %dx,%dx
jz 2f
push %dx
push %si
xorw %cx,%cx
mov $UART_LCR,%cl
add %cx,%dx
lodsb %ds:(%si),%al
pop %si
or $UART_DLAB,%al
out %al,%dx
pop %dx
1: lodsb %ds:(%si),%al
out %al,%dx
add $1,%dx
sub $1,%cx
jns 1b
2: ret
.endfn sinit,global,hidden
// Video put string.
//
// @param di is the string
// @mode real
rvputs: push %bp
push %bx
mov %di,%si
0: lodsb
test %al,%al
je 1f
mov $7,%bx # normal mda/cga style page zero
mov $0x0e,%ah # teletype output al cp437
int $0x10 # vidya service
jmp 0b
1: pop %bx
pop %bp
ret
.endfn rvputs
// Abnormally halts startup.
//
// @param di message
// @mode real
// @noreturn
rldie: push %di
mov $REAL(str.error),%di
call16 rvputs
pop %di
call16 rvputs
mov $REAL(str.crlf),%di
call16 rvputs
xor %ax,%ax # get keystroke
int $0x16 # keyboard service
call16 triplf
.endfn rldie
/* █ █▒
█ █
█▓▄ █ █
@@ -1187,11 +1259,18 @@ rlinit: .previous/*
long mode is long */
longmodeloader:
call lcheck
call a20
call e820
call pinit
call golong
call16 lcheck
call16 a20
mov $XLM(E820),%di
mov $XLM_E820_SIZE,%si
call16 e820
jc 9f
call16 unreal
// call hiload
call16 pinit
call16 golong
9: mov $REAL(str.e820),%ax
call16 rldie
.endfn longmodeloader
// Long Mode Hardware Check
@@ -1227,25 +1306,35 @@ lcheck: pushf # check for i8086 / i8088 / i80186
jne 10f
xor %ax,%ax
1: ret
9: mov $REAL(str.oldskool),%di
9: mov $REAL(str.oldskool),%ax
jmp 20f
10: mov $REAL(str.long),%di
10: mov $REAL(str.long),%ax
jmp 20f
12: mov $REAL(str.cpuid),%di
20: call rldie
12: mov $REAL(str.cpuid),%ax
jmp 20f
20: call16 rldie
.endfn lcheck
// Gets memory map from BIOS.
e820: mov $0x0510>>4,%di # mman::e820
//
// @param di paragraph aligned buffer
// @param si bytes in buffer to fill
// @return number of bytes written or CF on error
// @mode real
e820: push %bp
mov %sp,%bp
pushl $'S'<<24|'M'<<16|'A'<<8|'P' # magic @ -4(%bp)
push %bx
shr $4,%di
mov %di,%es
xor %edi,%edi # es:di is destination buffer
xor %ebx,%ebx # ebx is an api state tracker
1: mov $0xE820,%eax # magic
mov $8+8+4+4,%ecx # sizeof(struct SmapEntry)
mov $0x534d4150,%edx # magic number
mov -4(%bp),%edx # magic
int $0x15 # ax,bx,cx,dx,di → ax,bx,cx
jc 9f # cf = unsupported or abuse
cmp %edx,%eax # more magic means success
cmp -4(%bp),%eax # more magic means success
jne 9f
test %cx,%cx # discard empty results
jz 5f
@@ -1255,14 +1344,78 @@ e820: mov $0x0510>>4,%di # mman::e820
jnz 5f
4: add $8+8+4+4,%di # keep entry
5: test %ebx,%ebx # last entry?
jz 8f
cmp $0x1000,%di
jz 7f
cmp %si,%di # out of buf?
jb 1b
8: ret
9: mov $REAL(str.e820),%di
call rldie
7: mov %di,%ax
8: pop %bx
leave
ret
9: stc
jmp 8b
.endfn e820
// Unreal Mode.
// Makes 4gb of real memory accessible via %fs segment.
unreal: cli
lgdt REAL(gdt)
mov %cr0,%eax
or $CR0_PE,%al
mov %eax,%cr0
jmp 1f
1: mov $GDT_LEGACY_DATA,%cx
mov %cx,%fs
and $~CR0_PE,%al
mov %eax,%cr0
ljmp $0,$REAL(1f)
1: sti
ret
.endfn unreal
// Loads remainder of executable off disk.
hiload: push %bx
mov $IMAGE_BASE_REAL,%esi # relocate, again
mov $IMAGE_BASE_PHYSICAL,%ebx
mov $v_ape_realsectors,%ecx
shl $9,%ecx
or $-4,%edx
0: add $4,%edx
cmp %edx,%ecx
je 1f
mov %fs:(%esi,%edx),%eax
mov %eax,%fs:(%ebx,%edx)
jmp 0b
1: lea (%ebx,%edx),%ebx
mov $v_ape_highsectors,%di # then copy rest off disk
mov $REAL_SCRATCH_AREA>>4,%ax # to real memory buffer
mov %ax,%es
mov XLM(LOADSTATE)+0,%ax
mov XLM(LOADSTATE)+2,%cx
mov XLM(LOADSTATE)+4,%dx
0: test %di,%di
jz 9f
mov %di,%ax
push %bx
xor %bx,%bx
call16 pcread
pop %bx
sub %ax,%di
push %cx
mov %ax,%cx # copy real buffer to high
shl $9,%cx # no way bios loaded >64k
xor %si,%si
1: mov %es:(%si),%eax
mov %eax,%fs:(%ebx)
add $4,%ebx
add $4,%si
sub $4,%cx
jnz 1b
pop %cx
jmp 0b
9: pop %bx
ret
.endfn hiload
// Asks keyboard to grant system 65,519 more bytes of memory.
//
// Yup.
@@ -1293,26 +1446,26 @@ a20: cli
pop %ds
jne 3f
mov $1,%ax
call 1f
call16 1f
mov $0xad,%al
out %al,$0x64
call 1f
call16 1f
mov $0xd0,%al
out %al,$0x64
call 2f
call16 2f
in $0x60,%al
push %ax
call 1f
call16 1f
mov $0xd1,%al
out %al,$0x64
call 1f
call16 1f
pop %ax
or $2,%al
out %al,$0x60
call 1f
call16 1f
mov $0xae,%al
out %al,$0x64
call 1f
call16 1f
jmp a20
1: in $0x64,%al
test $2,%al
@@ -1327,26 +1480,33 @@ a20: cli
.endfn a20
// Initializes long mode paging.
//
// Modern computers access memory via four levels of indirection:
//
// register char (*(*(*(*ram)[512])[512])[512])[4096] asm(cr3)
//
// Your page tables grow down in memory, starting from the real
// stack segment base. This function only defines enough tables
// to get us started.
#define TIP REAL_STACK_FRAME
pinit: push %ds
#define SEG 0x79000
mov $SEG>>4,%ax
mov $(TIP-0x4000)>>4,%ax
mov %ax,%ds
movl $0x7d000+PAGE_V+PAGE_RW,0x7e000-SEG # PDPT←PML4T (+)
movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPT←PML4T (-)
movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDT←PDPT (+)
movl $0x7a000+PAGE_V+PAGE_RW,0x7c000-SEG # PDT←PDPT (-)
movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+)
movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-)
mov $512,%cx # PD±2MB
movl $TIP-0x2000+PAGE_V+PAGE_RW,0x3000 # PML4T→PDPT
movl $TIP-0x3000+PAGE_V+PAGE_RW,0x2000 # PDPT→PDT
movl $TIP-0x4000+PAGE_V+PAGE_RW,0x1000 # PDT→PD
mov $0x100000/0x1000,%cx # PD→512kb
mov $PAGE_V+PAGE_RW,%eax
xor %si,%si
0: mov %eax,(%si)
add $0x1000,%eax
add $8,%si
loop 0b
mov $0x7e000,%eax # PML4T←CR3
mov %eax,%cr3
movb $0,0 # unmap null
pop %ds
movl $TIP-0x4000,XLM(PAGE_TABLE_STACK_POINTER) # STACK→XLM
mov $TIP-0x1000,%eax # PML4T→CR3
mov %eax,%cr3
ret
.endfn pinit
@@ -1354,7 +1514,7 @@ pinit: push %ds
//
// @see Intel Manual V3A §4.1.2
golong: cli
lidt 0x1522 # mman::bad_idt
lidt XLM(BADIDT)
mov %cr4,%eax
or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax
mov %eax,%cr4
@@ -1371,6 +1531,7 @@ golong: cli
.endfn golong
// Long mode is long.
// @noreturn
.code64
long: push $GDT_LONG_DATA
pop %rax
@@ -1379,89 +1540,40 @@ long: push $GDT_LONG_DATA
mov %eax,%es
mov %eax,%fs
mov %eax,%gs
mov $0x80000,%esp
xor %r12d,%r12d
xor %r13d,%r13d
xor %r14d,%r14d
xor %r15d,%r15d
xor %ebx,%ebx
xor %ebp,%ebp
push %rbp
mov $0x0500,%rdi # mman
mov %cr3,%rsi
mov $IMAGE_BASE_REAL,%edx
call __map_phdrs
push $0x037f
fldcw (%rsp)
movabs $kernel,%rax
mov $REAL_STACK_FRAME+FRAMESIZE,%esp
call __map_image
ezlea metal.thunk,ax
jmp *%rax
.endfn long
/* ▄▄▒▀▀▀▀▒▒▄░
█████▓▓▄░░░░ ▒▒▄░
▐█▓▓█▓▄█████▓░ ▀▒▄
▓█▓▓▓▓▓▓▓▓▓█▓ ░▀▒░
░▀▀▓█▓▓▓▓▓▓█▓ ░▀▒▄▄▒▄▄▄▒▒▒▀▀▀▀▀▀▀▀▀▀▀▀▀▀▒▒▄▒
░▀▓▓█▓▓▓▓▓▄ ░ ░▀▒▄▄ ▄
░▀█▓▓▓▓▓▄░ ░▀▒░ ▄▓▌
▀█▓▓▓▓▓█▓░ ░▀▄░ ░▄▓██░
░▀█▓▓▓▓▓█▄ ░▀▒▄▄▄▄▄▄▄▄▒▀▓█▓█▓░
░▀█▓▓▓▓█▓░ ░▄▓█▓▓█▓▄▌
░▀█▓▓▓▓▓▄ ▄▄▄▓▓██▓▓▒▒░ ▒▒▄▓█▓▓▓▓█▓
▀█▓▓▓▓▓▓▄▄░ ░▄▄▓██▓▓▓▓▓██████████████▓▓▓▓▓▓█▀
▐█▓▓▓▓▓▓▓██▓▓▄▄▄▄▄▄▄▄▄▓▓██▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█████████▓▓▀░
▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█░ ░░░░░░
▄░▓█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█▌
█▓▄▀▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██▓▓▀▀▀▀▀▀▀▓█▓▓▓▓▓▓▓▓▓▓▓▓
▐█▓█▓░▓█▓▓▓▓▓▓▓█▀▀▀▀▒░ ▐▓▓▓▓▓▓▄▒▀▓█▓▓▓▓▓▓▓▓█▌
▐█▓▓▓█▒▀█▓▓▓▓▓▓█▌ ▀█▓▓▓▓▓█▄░▀▓▓█▓▓▓▓▓▓█░
█▓▓▓▓▓█░▐█▓▓▓▓▓█▌ ▀▓█▓▓▓▓█▌ ░▀█▓▓▓▓▓█▄
█▓▓▓▓█▌ ░█▓▓▓▓▓█░ ▓█▓▓▓▓▓░ ▒█▓▓▓▓▓█░
█▓▓▓▓█░ █▓▓▓▓▓█░ █▓▓▓▓▓█░ ▐█▓▓▓▓█▌
▐█▓▓▓▓▓▄ █▓▓▓▓▓█ ░▄▄▓█▓▓▓▓▓█░ ▐█▓▓▓▓█░
▓█▓▓▓█▓▐█▓▓▓▓█▌ ▓██▓▓▓▓▓▓█▀ ▓█▓▓▓▓█
▀▓██▒▄█▓▓▓▓▓█░ ░█▓▓▓▓▓██▀░ ░▓█▓▓▓▓█▌
░░█▓▓▓▓▓█▓ ░▀▀▀▀▀▀ ▓█▓▓▓▓▓▓
╔───────────────────────────────────────────────────────────▀▀▀▀▀▀───────────│─╗
│ αcτµαlly pδrταblε εxεcµταblε § cosmopolitan libc runtime runtime ─╬─│┼
╚────────────────────────────────────────────────────────────────────────────│*/
kernel: movabs $ape_stack_vaddr,%rsp
add $ape_stack_memsz,%rsp
movl $0,0x7b000 # unmap null 2mb
// Long mode in virtual address space.
// @noreturn
metal.thunk:
#if USE_SYMBOL_HACK
.byte 0x0f,0x1f,0207 # nop rdi binbase
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
#endif
// 𝑠𝑙𝑖𝑑𝑒
.endfn metal.thunk
metal:
xor %eax,%eax # clear bss
mov $ape_bss_vaddr,%edi
mov $ape_bss_memsz,%ecx
rep stosb
.weak __hostos
ezlea __hostos,ax
test %rax,%rax
jz 1f
movb $METAL,(%rax)
1: xor %eax,%eax
xor %ecx,%ecx
xor %edx,%edx
1: push $0 # auxv
push $0
push $0 # envp
push $0 # auxv
push $0 # argc
xor %edi,%edi
xor %esi,%esi
xor %r8d,%r8d
xor %r9d,%r9d
xor %r10d,%r10d
xor %r11d,%r11d
push $0 # auxv[1][1]
push $0 # auxv[1][0]
push $.Larg0 # auxv[0][1]
push $31 # auxv[0][0] AT_EXECFN
push $0 # envp[1]
push $.Lenv0 # envp[0]
push $0 # argv[1]
push $.Larg0 # argv[0]
push $1 # argc
jmp _start
.endfn kernel
.rodata
.Larg0: .asciz "ape.com"
.Lenv0: .asciz "METAL=1"
.previous
.endfn metal
#endif /* SupportsMetal() */
@@ -1518,6 +1630,12 @@ ape_pad_text:
ape_pad_privileged:
.previous
.section .ape.pad.test,"a",@progbits
.type ape_pad_test,@object
.hidden ape_pad_test
ape_pad_test:
.previous
.section .ape.pad.rodata,"a",@progbits
.type ape_pad_rodata,@object
.hidden ape_pad_rodata
+41 -53
View File
@@ -175,7 +175,7 @@
#ifdef __LINKER__
#include "ape/macros.internal.h"
#include "ape/relocations.h"
#include "ape/config.h"
#include "libc/dce.h"
#include "libc/nt/pedef.internal.h"
#include "libc/zip.h"
@@ -196,18 +196,20 @@ SECTIONS {
/*BEGIN: linux addressability guarantee */
/*BEGIN: bsd addressability guarantee */
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : AT(IMAGE_BASE_REAL) {
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : {
HIDDEN(_base = .);
/* Real Mode */
KEEP(*(.head))
KEEP(*(.text.head))
/* Executable & Linkable Format */
. = ALIGN(__SIZEOF_POINTER__);
HIDDEN(ape_phdrs = .);
KEEP(*(.elf.phdrs))
HIDDEN(ape_phdrs_end = .);
HIDDEN(ape_phdrs32 = .);
KEEP(*(.elf.phdrs32))
HIDDEN(ape_phdrs32_end = .);
/* OpenBSD */
. = ALIGN(__SIZEOF_POINTER__);
@@ -221,14 +223,16 @@ SECTIONS {
HIDDEN(ape_pe_sections = .);
KEEP(*(.pe.sections))
HIDDEN(ape_pe_sections_end = .);
. += 1;
/* Mach-O */
KEEP(*(.macho))
. = ALIGN(__SIZEOF_POINTER__);
HIDDEN(ape_macho_end = .);
. += 1;
KEEP(*(.ape.pad.head))
. = ALIGN(SupportsWindows() || SupportsMetal() ? PAGESIZE : 16);
. = ALIGN(SupportsWindows() ? PAGESIZE : 16);
HIDDEN(_ehead = .);
} :Head
@@ -238,13 +242,14 @@ SECTIONS {
/* Code that needs to be addressable in Real Mode */
*(.text.real)
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
*(.rodata.real)
KEEP(*(SORT_BY_NAME(.sort.rodata.real.*)))
HIDDEN(_ereal = .);
. += 1;
/*END: realmode addressability guarantee */
/* Normal Code */
*(.start)
KEEP(*(.start))
KEEP(*(.initprologue))
KEEP(*(SORT_BY_NAME(.init.*)))
KEEP(*(.init))
@@ -272,17 +277,17 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.sort.text.*)))
KEEP(*(.ape.pad.test));
HIDDEN(__test_start = .);
*(.test.unlikely)
*(.test .test.*)
/* Privileged code invulnerable to magic */
KEEP(*(.ape.pad.privileged));
. += . > 0 ? 1 : 0;
HIDDEN(__privileged_start = .);
. += . > 0 ? 1 : 0;
HIDDEN(__test_end = .);
. += 1;
*(.privileged)
HIDDEN(__privileged_end = .);
. += . > 0 ? 1 : 0;
/*BEGIN: Read Only Data */
@@ -302,10 +307,11 @@ SECTIONS {
KEEP(*(.comment))
KEEP(*(.commentepilogue))
#endif
/* Windows DLL Import Directory */
KEEP(*(.idata.ro));
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
. += 1;
. = ALIGN(__SIZEOF_POINTER__);
PROVIDE_HIDDEN(__init_array_start = .);
@@ -364,23 +370,11 @@ SECTIONS {
PROVIDE_HIDDEN(edata = .);
} :Ram
/*END: file content that's loaded by o/s */
/*BEGIN: bss memory void */
.zip . : {
KEEP(*(SORT_BY_NAME(.zip.*)))
HIDDEN(_ezip = .);
}
/*END: file content */
/*BEGIN: bss memory that's addressable */
.bss ALIGN(__SIZEOF_POINTER__) : {
.bss . : {
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
*(.piro.bss)
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
HIDDEN(__piro_end = .);
. += . > 0 ? 1 : 0;
/*END: Post-Initialization Read-Only */
/* Statically Allocated Empty Space */
@@ -390,10 +384,15 @@ SECTIONS {
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
/* eXtreme Low Memory w/ Userspace Remapping */
. = ALIGN(0x1000);
*(.xlm)
. = ALIGN(0x1000);
. = ALIGN(0x10000); /* for brk()/sbrk() allocation */
HIDDEN(_end = .);
PROVIDE_HIDDEN(end = .);
}
} :Ram
/*END: nt addressability guarantee */
/*END: bsd addressability guarantee */
@@ -449,6 +448,13 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
PFSTUB4(ape_elf_shnum, 0);
PFSTUB4(ape_elf_shstrndx, 0);
PFSTUB4(ape_elf32_entry, _start32);
PFSTUB4(ape_elf32_phoff, RVA(ape_phdrs32));
PFSTUB4(ape_elf32_shoff, 0);
PFSTUB4(ape_elf32_phnum, (ape_phdrs32_end - ape_phdrs32) / 32);
PFSTUB4(ape_elf32_shnum, 0);
PFSTUB4(ape_elf32_shstrndx, 0);
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
ROUNDDOWN(__privileged_start, PAGESIZE)));
@@ -464,18 +470,11 @@ HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
HIDDEN(ape_ram_vaddr = ADDR(.data));
HIDDEN(ape_ram_paddr = LOADADDR(.data));
HIDDEN(ape_ram_filesz = SIZEOF(.data));
HIDDEN(ape_ram_filesz = LOADADDR(.bss) - LOADADDR(.data));
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
HIDDEN(ape_ram_align = PAGESIZE);
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE);
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
HIDDEN(ape_stack_filesz = 0);
HIDDEN(ape_stack_memsz = STACKSIZE);
HIDDEN(ape_stack_align = 16);
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
HIDDEN(ape_note_vaddr = ape_note);
HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset);
@@ -511,30 +510,20 @@ SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
#endif
#if SupportsWindows() || SupportsMetal()
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
#if SupportsWindows()
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL);
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0);
HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0);
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0);
HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0);
HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0);
HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
HIDDEN(v_ntsubsystem = (LINK_WINDOWS
? (DEFINED(GetMessage)
? kNtImageSubsystemWindowsGui
: kNtImageSubsystemWindowsCui)
: kNtImageSubsystemEfiApplication));
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt);
HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat);
HIDDEN(v_ntsubsystem = (DEFINED(GetMessage)
? kNtImageSubsystemWindowsGui
: kNtImageSubsystemWindowsCui));
#endif
#if SupportsMetal()
HIDDEN(v_ape_realsectors =
MIN(0x70000 - IMAGE_BASE_REAL,
MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL,
ROUNDUP(RVA(_edata), 4096)) / 512);
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
HIDDEN(v_ape_highsectors =
@@ -545,9 +534,8 @@ HIDDEN(v_ape_highsectors =
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);
ZIPCONST(v_zip_commentsize, _edata - __zip_end - kZipCdirHdrMinSize);
#if SupportsXnu()
/* Generates deterministic ID. */
@@ -625,7 +613,7 @@ CHURN(v_ape_realsectors);
#if SupportsXnu()
CHURN(ape_macho);
#endif
#if SupportsWindows() || SupportsMetal()
#if SupportsWindows()
CHURN(ape_mz);
CHURN(ape_pe);
CHURN(ape_pe_offset);
+5 -1
View File
@@ -31,10 +31,12 @@ APE_HDRS = $(filter %.h,$(APE_FILES))
APE_INCS = $(filter %.inc,$(APE_FILES))
APE_SRCS = $(filter %.S,$(APE_FILES))
APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
APE_DEPS = $(APE_LIB)
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
o/$(MODE)/ape/ape.lds: \
ape/ape.lds \
ape/config.h \
ape/macros.internal.h \
libc/dce.h \
libc/zip.h
@@ -47,4 +49,6 @@ $(APE_OBJS): $(BUILD_FILES) \
ape/ape.mk
.PHONY: o/$(MODE)/ape
o/$(MODE)/ape: $(APE) $(APE_CHECKS)
o/$(MODE)/ape: $(APE) \
$(APE_CHECKS) \
o/$(MODE)/ape/lib
+118
View File
@@ -0,0 +1,118 @@
#ifndef APE_CONFIG_H_
#define APE_CONFIG_H_
#include "ape/relocations.h"
#include "libc/macros.h"
/*
* Post-Initialization Read-Only Code Size Threshold.
*
* An executable needs to have at least this much code, before the
* linker adds non-mandatory 4kb alignments. The benefit is better
* memory protection. The tradeoff is sparser binaries.
*/
#ifndef APE_PIRO_THRESHOLD
#ifdef CONFIG_DBG
#define APE_PIRO_THRESHOLD 0x1000
#else
#define APE_PIRO_THRESHOLD 0x10000
#endif
#endif
#ifndef METAL_STDIN
#define METAL_STDIN COM1
#endif
#ifndef METAL_STDOUT
#define METAL_STDOUT COM1
#endif
#ifndef METAL_STDERR
#define METAL_STDERR COM1
#endif
#ifndef VIDYA_MODE
#define VIDYA_MODE VIDYA_MODE_CGA
#endif
/* FPU Control Word (x87) Exception Masks
@see Intel Manual V1 §8.1.5
IM: Invalid Operation ───────────────┐
DM: Denormal Operand ───────────────┐│
ZM: Zero Divide ───────────────────┐││
OM: Overflow ─────────────────────┐│││
UM: Underflow ───────────────────┐││││
PM: Precision ──────────────────┐│││││
PC: Precision Control ────────┐ ││││││
{float,∅,double,long double} │ ││││││
RC: Rounding Control ───────┐ │ ││││││
{even, →-∞, →+∞, →0} │┌┤ ││││││
┌┤││ ││││││
d││││rr││││││*/
#define X87_NORMAL 0b000000000001101111111
#define X87_DTOA 0b000000000001000000000
#define X87_DTOA_MASK 0b000000000001100000000
#ifndef X87_DEFAULT
#define X87_DEFAULT X87_NORMAL
#endif
#ifndef UART_BAUD_RATE
#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */
#endif
#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE))
#ifndef UART_CONF_IIR
/* ┌interrupt trigger level {1,4,8,14}
│ ┌enable 64 byte fifo (UART 16750+)
│ │ ┌select dma mode
│ │ │┌clear transmit fifo
│ │ ││┌clear receive fifo
├┐│ │││┌enable fifos*/
#define UART_CONF_IIR 0b00000000
#endif
#ifndef UART_CONF_LCR
/* ┌dlab: flips configuration mode state
│┌enable break signal
││ ┌parity {none,odd,even,high,low}
││ │ ┌extra stop bit
││ │ │┌data word length (bits+5)
││┌┴┐│├┐*/
#define UART_CONF_LCR 0b01000011
#endif
#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR)
#define XLMV(VAR) (__xlm + XLM_##VAR)
#define XLM_BASE_REAL 0x1000
#define XLM_E820 0
#define XLM_E820_SIZE 0x2000
#define XLM_BIOS_DATA_AREA 0x2000
#define XLM_BIOS_DATA_AREA_SIZE 256
#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */
#define XLM_DRIVE_BASE_TABLE_SIZE 11
#define XLM_DRIVE_TYPE 0x220b
#define XLM_DRIVE_TYPE_SIZE 1
#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */
#define XLM_DRIVE_LAST_SECTOR_SIZE 1
#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */
#define XLM_DRIVE_LAST_CYLINDER_SIZE 2
#define XLM_DRIVE_ATTACHED 0x220f
#define XLM_DRIVE_ATTACHED_SIZE 1
#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */
#define XLM_DRIVE_LAST_HEAD_SIZE 1
#define XLM_DRIVE 0x2211
#define XLM_DRIVE_SIZE 1
#define XLM_HAVEEXTMEMKB 0x2212
#define XLM_HAVEEXTMEMKB_SIZE 4
#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */
#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4
#define XLM_PAGE_TABLE_STACK_POINTER 0x2220
#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8
#define XLM_BADIDT 0x2230
#define XLM_BADIDT_SIZE 6
#define XLM_LOADSTATE 0x2240
#define XLM_LOADSTATE_SIZE 8
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)
#if !defined(__LINKER__) && !defined(__ASSEMBLER__)
extern char __xlm[XLM_SIZE];
#endif /* !defined(__LINKER__) && !defined(__ASSEMBLER__) */
#endif /* APE_CONFIG_H_ */
+45
View File
@@ -0,0 +1,45 @@
#-*-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───────────────────────┘
PKGS += APE_LIB
APE_LIB_ARTIFACTS += APE_LIB_A
APE_LIB = $(APE_LIB_A_DEPS) $(APE_LIB_A)
APE_LIB_A = o/$(MODE)/ape/lib/apelib.a
APE_LIB_A_FILES := $(wildcard ape/lib/*)
APE_LIB_A_HDRS = $(filter %.h,$(APE_LIB_A_FILES))
APE_LIB_A_SRCS_S = $(filter %.S,$(APE_LIB_A_FILES))
APE_LIB_A_SRCS_C = $(filter %.c,$(APE_LIB_A_FILES))
APE_LIB_A_SRCS = \
$(APE_LIB_A_SRCS_S) \
$(APE_LIB_A_SRCS_C)
APE_LIB_A_OBJS = \
$(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o)
APE_LIB_A_DIRECTDEPS = \
LIBC_NEXGEN32E \
LIBC_INTRIN \
LIBC_STR \
LIBC_STUBS
APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok)
APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x))))
$(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS)
$(APE_LIB_A).pkg: $(APE_LIB_A_OBJS) $(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)_A).pkg)
APE_LIB_LIBS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)))
APE_LIB_SRCS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_SRCS))
APE_LIB_HDRS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_HDRS))
APE_LIB_BINS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_BINS))
APE_LIB_CHECKS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_CHECKS))
APE_LIB_OBJS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_OBJS))
$(APE_LIB_OBJS): $(BUILD_FILES) libc/str/str.mk
.PHONY: o/$(MODE)/ape/lib
o/$(MODE)/ape/lib: \
$(APE_LIB_CHECKS) \
$(APE_LIB_A)
+19 -121
View File
@@ -1,5 +1,5 @@
/*-*- 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│
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
╞══════════════════════════════════════════════════════════════════════════════╡
│ Copyright 2020 Justine Alexandra Roberts Tunney │
│ │
@@ -30,131 +30,29 @@
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
│ αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management │
│ αcτµαlly pδrταblε εxεcµταblε § green energy │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "ape/relocations.h"
#include "libc/elf/def.h"
#include "libc/elf/struct/phdr.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/uart.internal.h"
#include "libc/runtime/e820.internal.h"
#include "libc/runtime/metalprintf.internal.h"
#include "libc/runtime/pc.internal.h"
#include "libc/runtime/runtime.h"
#ifndef APE_LIB_APM_H_
#define APE_LIB_APM_H_
/**
* Allocates new page of physical memory.
* @fileoverview Advanced Power Management.
*
* <p>APM is useful for exiting programs, without needing to ask the
* human to flip a physical switch or pass QEMU's -no-reboot flag.
*
* <p><b>Implementation Detail:</b> Supporting ACPI would literally
* require implementing a programming language.
*
* @see APM BIOS Interface Specification v1.2
* @since IBM PC/AT
*/
noasan texthead uint64_t __new_page(struct mman *mm) {
uint64_t p;
if (mm->pdpi == mm->e820n) {
/* TODO: reclaim free pages */
return 0;
}
while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) {
if (++mm->pdpi == mm->e820n) return 0;
mm->pdp = mm->e820[mm->pdpi].addr;
}
p = mm->pdp;
mm->pdp += 4096;
return p;
}
/**
* Returns pointer to page table entry for page at virtual address.
* Additional page tables are allocated if needed as a side-effect.
*/
noasan texthead uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
int64_t vaddr, bool maketables) {
uint64_t *e, p;
unsigned char h;
for (h = 39;; h -= 9) {
e = t + ((vaddr >> h) & 511);
if (h == 12) return e;
if (!(*e & PAGE_V)) {
if (!maketables) return NULL;
if (!(p = __new_page(mm))) return NULL;
*e = p | PAGE_V | PAGE_RW;
}
t = (uint64_t *)(BANE + (*e & PAGE_TA));
}
}
#define APM_SERVICE 0x15
/**
* Sorts, rounds, and filters BIOS memory map.
*/
static noasan texthead void __normalize_e820(struct mman *mm) {
uint64_t a, b;
uint64_t x, y;
unsigned i, j, n;
for (n = i = 0; mm->e820[i].size; ++i) {
mm->e820[n] = mm->e820[i];
x = mm->e820[n].addr;
y = mm->e820[n].addr + mm->e820[n].size;
a = ROUNDUP(x, 4096);
b = ROUNDDOWN(y, 4096) - a;
if (b > 0 && mm->e820[i].type == kMemoryUsable) {
mm->e820[n].addr = a;
mm->e820[n].size = b;
++n;
}
}
for (i = 1; i < n; ++i) {
for (j = i; j > 0 && mm->e820[i].addr < mm->e820[j - 1].addr; --j) {
mm->e820[j] = mm->e820[j - 1];
}
mm->e820[j] = mm->e820[i];
}
mm->pdp = MAX(0x80000, mm->e820[0].addr);
mm->pdpi = 0;
mm->e820n = n;
}
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
* Identity maps all usable physical memory to its negative address.
*/
static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) {
uint64_t i, j, *m, p, pe;
for (i = 0; i < mm->e820n; ++i) {
for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size;
p + 0x200000 < pe; p += 4096) {
m = __get_virtual(mm, pml4t, BANE + p, true);
if (m && !(*m & PAGE_V)) {
*m = p | PAGE_V | PAGE_RW;
}
}
}
}
void apmoff(void) wontreturn;
noasan texthead void __setup_mman(struct mman *mm, uint64_t *pml4t) {
__normalize_e820(mm);
__invert_memory(mm, pml4t);
}
/**
* Maps APE-defined ELF program headers into memory and clears BSS.
*/
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) {
struct Elf64_Phdr *p;
uint64_t i, f, v, m, *e;
extern char ape_phdrs[] __attribute__((__weak__));
extern char ape_phdrs_end[] __attribute__((__weak__));
__setup_mman(mm, pml4t);
for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0;
p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) {
if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) {
f = PAGE_V | PAGE_U;
if (p->p_flags & PF_W) f |= PAGE_RW;
for (i = 0; i < p->p_memsz; i += 4096) {
if (i < p->p_filesz) {
v = b + p->p_offset + i;
m = MAX(m, v);
} else {
v = __clear_page(__new_page(mm));
}
*__get_virtual(mm, pml4t, p->p_vaddr + i, true) = (v & PAGE_TA) | f;
}
}
}
mm->pdp = MAX(mm->pdp, m);
}
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* APE_LIB_APM_H_ */
+35
View File
@@ -0,0 +1,35 @@
/*-*- 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 │
│ │
│ 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 "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__
.code16
// Resets personal computer.
//
// @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80
// @mode real
// @noreturn
bootdr: push %bp
mov %sp,%bp
mov %di,%dx
int $0x19
ljmp $0xf000,$0xfff0
.endfn bootdr,globl
+37
View File
@@ -0,0 +1,37 @@
/*-*- 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 "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__
.code16
.globl e820map
.hidden e820map
.type e820map,@object
.size e820map,XLM_E820_SIZE
e820map = ape_xlm + XLM_E820
.globl e820map_xlm
.hidden e820map_xlm
.type e820map_xlm,@object
.size e820map_xlm,XLM_E820_SIZE
e820map_xlm = XLM(E820)
@@ -16,39 +16,40 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/o.h"
#include "ape/config.h"
#include "ape/lib/pc.h"
#include "libc/bits/bits.h"
#include "libc/macros.h"
/**
* Returns current position of stream.
* Virtualizes physical memory.
*
* @param stream is a non-null stream handle
* @returns current byte offset from beginning, or -1 w/ errno
* This function removes memory holes (discovered by e820() earlier) and
* creates the illusion of flat contiguous memory for as much RAM as the
* BIOS reports usable. Memory is safe to use and remap afterwards.
*
* @see ape/ape.S
*/
int64_t ftello(FILE *f) {
ssize_t rc;
int64_t pos;
uint32_t skew;
if (f->fd != -1) {
if (f->beg && !f->end && (f->iomode & O_ACCMODE) != O_RDONLY) {
if ((rc = write(f->fd, f->buf, f->beg)) == -1) {
f->state = errno;
return -1;
textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t,
uint64_t *ptsp) {
uint64_t *entry, paddr, vaddr;
struct SmapEntry *smap, *hole;
for (smap = hole = e820, vaddr = IMAGE_BASE_VIRTUAL; smap->size; ++smap) {
while (smap->size && smap->type != kMemoryUsable) smap++;
paddr = ROUNDUP(MAX(IMAGE_BASE_PHYSICAL, smap->addr), PAGESIZE);
while (paddr < ROUNDDOWN(smap->addr + smap->size, PAGESIZE)) {
while (hole->size &&
(hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) {
hole++;
}
if (paddr >= hole->addr && paddr < hole->addr + hole->size) {
paddr = ROUNDUP(hole->addr + hole->size, PAGESIZE);
} else {
entry = __getpagetableentry(vaddr, 3, pml4t, ptsp);
*entry = paddr | PAGE_V | PAGE_RW;
vaddr += 0x1000;
paddr += 0x1000;
}
if (rc != f->beg) abort();
f->beg = 0;
}
if ((pos = lseek(f->fd, 0, SEEK_CUR)) != -1) {
if (f->beg < f->end) pos -= f->end - f->beg;
return pos;
} else {
f->state = errno == ESPIPE ? EBADF : errno;
return -1;
}
} else {
return f->beg;
}
}
+31
View File
@@ -0,0 +1,31 @@
/*-*- 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 "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__
.code16
.globl g_pml4t
.hidden g_pml4t
.type g_pml4t,@object
.size g_pml4t,0x1000
g_pml4t = REAL_STACK_FRAME - 0x1000
+37
View File
@@ -0,0 +1,37 @@
/*-*- 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 "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__
.code16
.globl g_ptsp
.hidden g_ptsp
.type g_ptsp,@object
.size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE
g_ptsp = ape_xlm + XLM_PAGE_TABLE_STACK_POINTER
.globl g_ptsp_xlm
.hidden g_ptsp_xlm
.type g_ptsp_xlm,@object
.size g_ptsp_xlm,XLM_PAGE_TABLE_STACK_POINTER_SIZE
g_ptsp_xlm = XLM(PAGE_TABLE_STACK_POINTER)
@@ -16,23 +16,27 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/sock/internal.h"
#include "libc/sysv/consts/sock.h"
#include "ape/lib/pc.h"
#include "libc/assert.h"
int sys_socketpair(int family, int type, int protocol, int sv[2]) {
int e = errno;
if (__sys_socketpair(family, type, protocol, sv) != -1) return 0;
if ((type & (SOCK_CLOEXEC | SOCK_NONBLOCK)) &&
(errno == EINVAL || errno == EPROTOTYPE || errno == EPROTONOSUPPORT)) {
errno = e;
if (__sys_socketpair(family, type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK),
protocol, sv) != -1) {
__fixupnewsockfd(sv[0], type);
__fixupnewsockfd(sv[1], type);
return 0;
}
static textreal uint64_t __pushpagetable(uint64_t *ptsp) {
return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW;
}
textreal uint64_t *__getpagetableentry(int64_t vaddr, unsigned depth,
struct PageTable *pml4t,
uint64_t *ptsp) {
uint64_t *entry;
unsigned char shift;
assert(depth <= 3);
assert(!(*ptsp & 0xfff));
assert(!((uintptr_t)pml4t & 0xfff));
shift = 39;
for (;;) {
entry = &pml4t->p[(vaddr >> shift) & 511];
if (!depth--) return entry;
shift -= 9;
if (!*entry) *entry = __pushpagetable(ptsp);
pml4t = (void *)(*entry & PAGE_TA);
}
return -1;
}
+45
View File
@@ -0,0 +1,45 @@
/*-*- 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 "ape/lib/pc.h"
#include "ape/config.h"
#include "ape/macros.internal.h"
#include "ape/notice.inc"
.section .real,"ax",@progbits
.source __FILE__
.code16
.globl kBiosDataArea
.hidden kBiosDataArea
.type kBiosDataArea,@object
.size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE
kBiosDataArea = ape_xlm + XLM_BIOS_DATA_AREA
.globl kBiosDataAreaXlm
.hidden kBiosDataAreaXlm
.type kBiosDataAreaXlm,@object
.size kBiosDataAreaXlm,XLM_BIOS_DATA_AREA_SIZE
kBiosDataAreaXlm = XLM(BIOS_DATA_AREA)
.section .sort.text.real.init.2.kBiosDataArea,"ax",@progbits
movpp %ds,%es # copy bios data to valid page
mov $PC_BIOS_DATA_AREA,%si
mov $XLM(BIOS_DATA_AREA),%di
mov $XLM_BIOS_DATA_AREA_SIZE,%cx
rep movsb
.previous
+36
View File
@@ -0,0 +1,36 @@
/*-*- 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 "ape/lib/pc.h"
#include "ape/relocations.h"
#include "libc/runtime/runtime.h"
textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) {
uint64_t *e;
for (; a < b; a += 0x1000) {
e = __getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm);
*e = (IMAGE_BASE_REAL + a) | k;
}
}
textreal void __map_image(void) {
__map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL);
__map_segment(PAGE_V | PAGE_U | PAGE_RW,
(uintptr_t)_etext - IMAGE_BASE_VIRTUAL,
(uintptr_t)_end - IMAGE_BASE_VIRTUAL);
}
+26
View File
@@ -0,0 +1,26 @@
/*-*- 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 "ape/lib/pc.h"
textreal void pageunmap(int64_t vaddr) {
uint64_t *entry;
entry = __getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm);
*entry &= ~PAGE_V;
asm volatile("invlpg\t(%0)" : /* no outputs */ : "r"(vaddr) : "memory");
}
+61 -36
View File
@@ -32,12 +32,9 @@
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
╚─────────────────────────────────────────────────────────────────────────────*/
#ifndef COSMOPOLITAN_LIBC_RUNTIME_PC_H_
#define COSMOPOLITAN_LIBC_RUNTIME_PC_H_
#include "libc/runtime/e820.internal.h"
#include "libc/runtime/mman.internal.h"
#ifndef APE_LIB_PC_H_
#define APE_LIB_PC_H_
#define BANE -140737488355328
#define BOOTSIG 0xaa55 /* master boot record signature */
#define PC_BIOS_DATA_AREA 0x400
@@ -58,12 +55,8 @@
B: FPU Busy ───────────┐│ │ │ ││││││││
││┌┴┐┌┼┐││││││││
│↓│ │↓↓↓││││││││*/
#define FPU_IE 0b0000000000000000000000001
#define FPU_DE 0b0000000000000000000000010
#define FPU_ZE 0b0000000000000000000000100
#define FPU_OE 0b0000000000000000000001000
#define FPU_UE 0b0000000000000000000010000
#define FPU_PE 0b0000000000000000000100000
#define FPU_IE 0b0000000000100000000000001
#define FPU_ZE 0b0000000000100000000000100
#define FPU_SF 0b0000000000000000001000000
#define FPU_C0 0b0000000000000000100000000
#define FPU_C1 0b0000000000000001000000000
@@ -161,13 +154,35 @@
#define PAGE_4KB /* */ 0b010000000
#define PAGE_2MB /* */ 0b110000000
#define PAGE_1GB /* */ 0b110000000
#define PAGE_TA 0x00007ffffffff000
#define PAGE_PA2 0x00007fffffe00000
#define PAGE_TA 0b11111111111111111111111111111111111111000000000000
#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000
#define PAGE_XD 0x8000000000000000
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#include "ape/config.h"
#define invlpg(p) asm volatile("invlpg\t(%0)" : : "r"(p) : "memory")
struct thatispacked GlobalDescriptorTable {
uint16_t size;
uint64_t *entries;
};
/**
* Memory hole map.
* @see wiki.osdev.org/Detecting_Memory_(x86)
* @since 2002
*/
struct SmapEntry {
uint64_t addr;
uint64_t size;
enum {
kMemoryUsable = 1,
kMemoryUnusable = 2,
kMemoryAcpiReclaimable = 3,
kMemoryAcpiNvs = 4,
kMemoryBad = 5
} type;
uint32_t __acpi3; /* is abstracted */
};
struct IdtDescriptor {
uint16_t offset_1; /* offset bits 0..15 */
@@ -179,10 +194,37 @@ struct IdtDescriptor {
uint32_t zero; /* reserved */
};
uint64_t *__get_virtual(struct mman *, uint64_t *, int64_t, bool);
uint64_t __clear_page(uint64_t);
uint64_t __new_page(struct mman *);
void __map_phdrs(struct mman *, uint64_t *, uint64_t);
struct thatispacked PageTable {
uint64_t p[512];
} forcealign(PAGESIZE);
extern struct PageTable g_pml4t;
extern struct GlobalDescriptorTable gdt;
extern const unsigned char kBiosDataArea[256];
extern const unsigned char kBiosDataAreaXlm[256];
extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)];
extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)];
extern uint64_t g_ptsp;
extern uint64_t g_ptsp_xlm;
void bootdr(char drive) wontreturn;
void smapsort(struct SmapEntry *);
uint64_t *__getpagetableentry(int64_t, unsigned, struct PageTable *,
uint64_t *);
void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *);
void pageunmap(int64_t);
forceinline unsigned long eflags(void) {
unsigned long res;
asm("pushf\n\t"
"pop\t%0"
: "=rm"(res));
return res;
}
forceinline unsigned char inb(unsigned short port) {
unsigned char al;
@@ -196,22 +238,5 @@ forceinline void outb(unsigned short port, unsigned char byte) {
: "a"(byte), "dN"(port));
}
#define __clear_page(page) \
({ \
long di, cx; \
uintptr_t Page = (uintptr_t)(page); \
asm("rep stosb" \
: "=D"(di), "=c"(cx), "=m"(*(char(*)[4096])Page) \
: "0"(Page), "1"(4096), "a"(0)); \
Page; \
})
#define __get_pml4t() \
({ \
intptr_t cr3; \
asm("mov\t%%cr3,%0" : "=r"(cr3)); \
(uint64_t *)(BANE + cr3); \
})
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_RUNTIME_PC_H_ */
#endif /* APE_LIB_PC_H_ */
+46
View File
@@ -0,0 +1,46 @@
/*-*- 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 "ape/lib/pc.h"
textreal static unsigned smapcount(const struct SmapEntry *se) {
unsigned i = 0;
while (se[i].size) ++i;
return i;
}
textreal static void smapsorter(size_t n, struct SmapEntry a[n]) {
struct SmapEntry t;
unsigned i, j;
for (i = 1; i < n; ++i) {
j = i;
t = a[i];
while (j > 0 && (intptr_t)t.addr - (intptr_t)a[j - 1].addr) {
a[j] = a[j - 1];
--j;
}
a[j] = t;
}
}
/**
* Sorts BIOS e820 memory map.
*/
textreal void smapsort(struct SmapEntry *smap) {
smapsorter(smapcount(smap), smap);
}
+8 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#ifndef APE_MACROS_H_
#define APE_MACROS_H_
#include "libc/macros.internal.h"
#include "libc/macros.h"
#ifdef __ASSEMBLER__
/* clang-format off */
@@ -26,6 +26,13 @@
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
*/
// Calls function in real mode.
// It's needed because LLVM 8 LLD doesn't support R_X86_64_PC16.
.macro call16 name:req
mov $REAL(\name),%ax
call *%ax
.endm
// Calls near (i.e. pc+pcrel<64kB) FUNCTION.
// @mode long,legacy,real
// @cost 9 bytes overhead
+20 -2
View File
@@ -11,8 +11,6 @@
In some cases it's necessary to use addend macros that change virtual
addresses into the other two types: physical and real. */
#define IMAGE_BASE_REAL 0x2000
#ifndef IMAGE_BASE_VIRTUAL
#define IMAGE_BASE_VIRTUAL 0x400000
#endif
@@ -21,6 +19,26 @@
#define IMAGE_BASE_PHYSICAL 0x100000
#endif
#ifndef REAL_SCRATCH_AREA
/**
* Location of anything goes memory for real mode.
*
* The MBR won't load program content beyond this address, so we have
* room for buffers, page tables, etc. before we reach the stack frame.
*/
#define REAL_SCRATCH_AREA 0x40000
#endif
#ifndef REAL_STACK_FRAME
/**
* Location of real mode 64kb stack frame.
*
* This address was chosen because memory beyond 0x80000 can't be
* accessed safely without consulting e820.
*/
#define REAL_STACK_FRAME 0x70000
#endif
/**
* Returns Relative Virtual Address.
*/
+29
View File
@@ -0,0 +1,29 @@
#!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
#
# SYNOPSIS
#
# Program Deprioritizer
#
# OVERVIEW
#
# This is a drop-in replacement for the traditional Unix `nice`
# command that also invokes `ionice`, which is important, since
# network and traffic is usually what clobber the system.
if [ -z "$IONICE" ]; then
if IONICE=$(command -v ionice 2>/dev/null); then
IONICE="$IONICE -c3"
fi
fi
if [ -z "$NICE" ]; then
NICE=$(command -v nice 2>/dev/null)
fi
if [ -z "$IONICE$NICE" ]; then
echo "error: can't be nice" >&2
fi
exec $IONICE $NICE "$@"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
# -*- mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8 -*-
# vi: set net ft=sh ts=2 sts=2 sw=2 fenc=utf-8 :vi
echo c |
bochs \
-q \
-f ape/etc/bochsrc.dbg \
floppya:1_44=$1,status=inserted
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
# -*- mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8 -*-
# vi: set net ft=sh ts=2 sts=2 sw=2 fenc=utf-8 :vi
#
# bochs-scriptable executes a disk with serial uart stdio.
#
# USAGE
#
# build/bochs-scriptable IMAGE...
#
# DESCRIPTION
#
# This script is useful for end-to-end testing metal apps in <100ms.
#
# SEE ALSO
#
# build/boot(1)
while getopts h X; do
case $X in
h) exec less "$0" ;;
\?) echo "$0: bad arg" >&2; exit 1 ;;
esac
done
shift $((OPTIND - 1))
trap '' INT
IMG=$1
OUT=/tmp/$USER.$$.bochs.stdout
ERR=/tmp/$USER.$$.bochs.stderr
mkfifo $OUT || exit
cat <$OUT &
CAT=$!
exec 4>$OUT
rm -f $OUT
echo c |
bochs \
-q \
-f ape/etc/bochsrc.ffs \
display_library:nogui \
floppya:1_44=$1,status=inserted \
>>$ERR 2>>$ERR
RC=$?
kill $CAT
exec 4>&-
rm -f $ERR
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+21
View File
@@ -0,0 +1,21 @@
#!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
#
# OVERVIEW
#
# Source File Concatenation Tool
#
# DESCRIPTION
#
# This program is the same as cat, but inserts preprocessor directives
# that allow compiler errors to point back to the original lines.
if [ $# -eq 0 ]; then
cat
else
for x; do
printf '# 1 "%s"\n' "$x"
cat "$x"
done
fi
+9 -4
View File
@@ -130,7 +130,7 @@ endif
# Linux-Only Tiny Mode
#
# - `make MODE=tinylinux`
# - `make MODE=tiny`
# - No checks
# - No asserts
# - No canaries
@@ -158,7 +158,7 @@ endif
# Linux+BSD Tiny Mode
#
# - `make MODE=tinylinuxbsd`
# - `make MODE=tiny`
# - No apple
# - No checks
# - No asserts
@@ -187,7 +187,7 @@ endif
# Unix Tiny Mode
#
# - `make MODE=tinysysv`
# - `make MODE=tiny`
# - No checks
# - No asserts
# - No canaries
@@ -215,7 +215,7 @@ endif
# Tiny Metallic Unix Mode
#
# - `make MODE=tinynowin`
# - `make MODE=tiny`
# - No checks
# - No asserts
# - No canaries
@@ -282,6 +282,11 @@ endif
# such as MSVC or XCode. You can run your binary objects through a tool
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
# rollup one header file that'll enable linkage with minimal issues.
#
# Lastly note that in some cases, such as gc(), there simply isn't any
# ANSI workaround available. It's only in cases like that when we'll use
# the __asm__() header workaround, rather than simply removing it. We do
# however try to do that much less often than mainstream C libraries.
ifeq ($(MODE), ansi)
+8 -3
View File
@@ -50,9 +50,10 @@ TAGS ?= /usr/bin/ctags # emacs source builds or something breaks it
ARFLAGS = rcsD
ZFLAGS ?=
XARGS ?= xargs -P4 -rs8000
NICE ?= build/actuallynice
DOT ?= dot
GZ ?= gzip
CLANG = clang
CLANG = clang-10
FC = gfortran #/opt/cross9f/bin/x86_64-linux-musl-gfortran
# see build/compile, etc. which run third_party/gcc/unbundle.sh
@@ -90,6 +91,7 @@ FTRACE = \
-pg
SANITIZER = \
-fsanitize=leak \
-fsanitize=address
NO_MAGIC = \
@@ -136,8 +138,6 @@ MATHEMATICAL = \
-fwrapv
DEFAULT_CPPFLAGS = \
-DCOSMO \
-DMODE='"$(MODE)"' \
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
-nostdinc \
-iquote.
@@ -299,6 +299,11 @@ OBJECTIFY.greg.c = \
-fno-sanitize=all \
-c
OBJECTIFY.i386.c = \
$(OBJECTIFY.c) \
-m32 \
-wrapper build/i386ify.sh
OBJECTIFY.ansi.c = $(CC) $(OBJECTIFY.c.flags) -ansi -Wextra -Werror -pedantic-errors -c
OBJECTIFY.c99.c = $(CC) $(OBJECTIFY.c.flags) -std=c99 -Wextra -Werror -pedantic-errors -c
OBJECTIFY.c11.c = $(CC) $(OBJECTIFY.c.flags) -std=c11 -Wextra -Werror -pedantic-errors -c
-5
View File
@@ -1,5 +0,0 @@
#!/bin/sh
exec gdb -q -nh -i=mi $1 \
-ex "set confirm off" \
-ex "add-symbol-file $1.dbg 0x401000" \
-ex "run"
+35
View File
@@ -0,0 +1,35 @@
#!/bin/sh
#
# SYNOPSIS
#
# gcc -m32 -wrapper build/i386ify.sh -c -o foo.o foo.c
#
# OVERVIEW
#
# Compiles 32-bit code inside 64-bit ELF objects.
if [ "${1##*/}" = as ]; then
FIRST=0
for x; do
if [ $FIRST -eq 0 ]; then
set --
FIRST=1
fi
if [ "$x" = "--32" ]; then
continue
fi
if [ "${x##*.}" = s ]; then
{
printf "\t.section .yoink\n"
printf "\tnopl\t_start32\n"
printf "\t.previous\n"
printf "\t.code32\n"
cat "$x"
} >"$x".tmp
mv -f "$x".tmp "$x"
fi
set -- "$@" "$x"
done
fi
exec "$@"
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
for x; do
printf '#include "%s"\n' "$x"
done
+2189
View File
File diff suppressed because it is too large. Load diff
Executable
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
for x; do
printf '#include "%s"\n' "$x"
done
+1
View File
@@ -64,6 +64,7 @@ o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds)
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.i386.o: %.i386.c ; @$(COMPILE) -AOBJECTIFY.i386 $(OBJECTIFY.i386.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.ansi.o: %.ansi.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
o/$(MODE)/%.ansi.o: %.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
Executable
+14
View File
@@ -0,0 +1,14 @@
#!/bin/sh
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
#
# OVERVIEW
#
# SSH Command Wrapper
#
# DESCRIPTION
#
# This script, like most of our wrappers, asks the tooling to whine
# less often.
exec ${SSH:-ssh} -o LogLevel=QUIET "$@"
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef COSMOPOLITAN_DSP_CORE_C161_H_
#define COSMOPOLITAN_DSP_CORE_C161_H_
#include "libc/macros.internal.h"
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define EXTRA_SHARP 2
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_DSP_CORE_C161S_H_
#define COSMOPOLITAN_DSP_CORE_C161S_H_
#include "dsp/core/c161.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
forceinline pureconst artificial signed char C161S(signed char al,
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/core.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -20,7 +20,7 @@
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -19,7 +19,7 @@
#include "dsp/core/core.h"
#include "dsp/core/q.h"
#include "libc/dce.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef COSMOPOLITAN_DSP_CORE_HALF_H_
#define COSMOPOLITAN_DSP_CORE_HALF_H_
#include "libc/macros.internal.h"
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
+1 -1
View File
@@ -1,6 +1,6 @@
#ifndef COSMOPOLITAN_DSP_CORE_KS8_H_
#define COSMOPOLITAN_DSP_CORE_KS8_H_
#include "libc/macros.internal.h"
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_DSP_CORE_KSS8_H_
#define COSMOPOLITAN_DSP_CORE_KSS8_H_
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/**
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
#define BIAS 0x84
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef COSMOPOLITAN_DSP_CORE_Q_H_
#define COSMOPOLITAN_DSP_CORE_Q_H_
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
.align 16
// Mixes audio.
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/core/core.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/limits.h"
/**
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
.source __FILE__
clamp4int256$core:
+1 -1
View File
@@ -35,7 +35,7 @@
#include "libc/bits/initializer.internal.h"
#include "libc/fmt/conv.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -28,7 +28,7 @@
│ SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/mpeg/mpeg.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
asm(".ident\t\"\\n\\n\
PL_MPEG (MIT License)\\n\
+2 -2
View File
@@ -24,11 +24,11 @@
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/nexgen32e/bsr.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/gc.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
+1 -1
View File
@@ -20,7 +20,7 @@
#include "dsp/core/ks8.h"
#include "dsp/core/kss8.h"
#include "dsp/scale/cdecimate2xuint8x8.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/str/str.h"
#include "libc/x/x.h"
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/tty.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/bits/weaken.h"
#include "libc/calls/calls.h"
#include "libc/calls/termios.h"
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
// TODO(jart): write me
+1 -1
View File
@@ -22,7 +22,7 @@
#include "libc/bits/initializer.internal.h"
#include "libc/limits.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/quant.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
struct TtyRgb rgb2ttyi2f_(int r, int g, int b) {
return rgb2ttyf((__m128){r, g, b} / 255);
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/quant.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
struct TtyRgb rgb2xterm24_(int r, int g, int b) {
return (struct TtyRgb){MAX(MIN(r, 255), 0), MAX(MIN(g, 255), 0),
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/tty.h"
#include "libc/alg/arraylist2.internal.h"
#include "libc/runtime/gc.internal.h"
#include "libc/runtime/gc.h"
#include "libc/x/x.h"
/* TODO(jart): DELETE */
+1 -1
View File
@@ -18,7 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "dsp/tty/itoa8.h"
#include "dsp/tty/tty.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/limits.h"
#include "libc/log/check.h"
+2 -2
View File
@@ -23,11 +23,11 @@
#include "dsp/tty/windex.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/runtime.h"
+2 -2
View File
@@ -26,8 +26,8 @@
#include "libc/calls/typedef/sigaction_f.h"
#include "libc/calls/ucontext.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/runtime/gc.internal.h"
#include "libc/macros.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
.source __FILE__
// Returns index of minimum uint16 in array.
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/macros.internal.h"
#include "libc/macros.h"
.source __FILE__
// Returns index of minimum positive int16 in array.
+1 -1
View File
@@ -17,7 +17,7 @@
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/nexgen32e/x86feature.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
.source __FILE__
// Dispatches to fastest windex() implementation.
+1 -1
View File
@@ -73,7 +73,7 @@ void GetOpts(int argc, char *argv[]) {
int cp(const char *src, const char *dst) {
if (endswith(dst, "/") || isdirectory(dst)) {
dst = _gc(xasprintf("%s/%s", dst, basename));
dst = gc(xasprintf("%s/%s", dst, basename));
}
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail;
if (copyfile(src, dst, flags) == -1) goto OnFail;
+1 -1
View File
@@ -16,7 +16,7 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
+73 -8
View File
@@ -7,23 +7,88 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/bits/pushpop.h"
#include "libc/calls/calls.h"
#include "libc/calls/ucontext.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/nt/enum/errormodeflags.h"
#include "libc/nt/signals.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/**
* @fileoverview How to print backtraces and cpu state on crash.
* @fileoverview Demonstrates SEGFAULT via NULL pointer dereference.
*
* make -j8 -O o//examples/crashreport.com
* o//examples/crashreport.com
* In MODE=dbg mode, UBSAN should catch this and display a backtrace.
* In most other modes, e.g. MODE=balanced, the oncrash.c sig handler
* will either launch GDB or display a very fancy report.
*
* make -j8 -O MODE=opt o/opt/examples/crashreportdemo.com
* o/opt/examples/crashreportdemo.com
*
* To prevent the GDB GUI from popping up:
*
* export GDB=
* make -j8 -O o//examples/crashreport.com
* o//examples/crashreport.com
* export GDB=""
* make -j8 -O MODE=opt o/opt/examples/crashreportdemo.com
* o/opt/examples/crashreportdemo.com
*/
int boo;
void boop(void);
int main(int argc, char *argv[]) {
volatile int64_t x;
int64_t res;
showcrashreports();
return 1 / (x = 0);
res = 0;
asm volatile("mov\t$0x1111111111111111,%rax\n\t"
"mov\t$0x3333333333333333,%rcx\n\t"
"mov\t$0x4444444444444444,%rdx\n\t"
"mov\t$0x8888888888888888,%r8\n\t"
"mov\t$0x9999999999999999,%r9d\n\t"
"mov\t$0xaaaaaaaaaaaaaaaa,%r10d\n\t"
"mov\t$0xbbbbbbbbbbbbbbbb,%r11d\n\t"
"mov\t$0x0000000000000000,%rax\n\t"
"movd\t%rax,%xmm0\n\t"
"mov\t$0x1111111111111111,%rax\n\t"
"push\t%rax\n\t"
"push\t%rax\n\t"
"movdqu\t(%rsp),%xmm1\n\t"
"pop\t%rax\n\t"
"pop\t%rax\n\t"
"mov\t$0x2222222222220022,%rax\n\t"
"movd\t%rax,%xmm2\n\t"
"mov\t$0x3333333333333333,%rax\n\t"
"movd\t%rax,%xmm3\n\t"
"mov\t$0x4444444444444444,%rax\n\t"
"movd\t%rax,%xmm4\n\t"
"mov\t$0x5555555555555555,%rax\n\t"
"movd\t%rax,%xmm5\n\t"
"mov\t$0x6666666666666666,%rax\n\t"
"movd\t%rax,%xmm6\n\t"
"mov\t$0x7777777777777777,%rax\n\t"
"movd\t%rax,%xmm7\n\t"
"mov\t$0x8888888888888888,%rax\n\t"
"movd\t%rax,%xmm8\n\t"
"mov\t$0x9999999999999999,%rax\n\t"
"movd\t%rax,%xmm9\n\t"
"mov\t$0xaaaaaaaaaaaaaaaa,%rax\n\t"
"movd\t%rax,%xmm10\n\t"
"mov\t$0xbbbbbbbbbbbbbbbb,%rax\n\t"
"movd\t%rax,%xmm11\n\t"
"mov\t$0xcccccccccccccccc,%rax\n\t"
"movd\t%rax,%xmm12\n\t"
"mov\t$0xdddddddddddddddd,%rax\n\t"
"movd\t%rax,%xmm13\n\t"
"mov\t$0xeeeeeeeeeeeeeeee,%rax\n\t"
"movd\t%rax,%xmm14\n\t"
"mov\t$0xffffffffffffffff,%rax\n\t"
"movd\t%rax,%xmm15\n\t"
"fldpi\n\t"
"xor\t%eax,%eax\n\t"
"div\t%eax\n\t");
return res;
}
+3 -2
View File
@@ -14,6 +14,7 @@
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/nt/thread.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@@ -31,9 +32,9 @@ int main(int argc, char *argv[]) {
ssize_t rc;
size_t got, wrote;
unsigned char buf[512];
struct sigaction saint = {.sa_handler = GotCtrlC};
fprintf(stderr, "This echos stdio until Ctrl+C is pressed.\n");
CHECK_NE(-1, sigaction(SIGINT, &saint, NULL));
CHECK_NE(
-1, sigaction(SIGINT, &(struct sigaction){.sa_handler = GotCtrlC}, NULL));
for (;;) {
rc = read(0, buf, BUFSIZ);
if (rc != -1) {
+13 -13
View File
@@ -7,13 +7,13 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/dns/dns.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
@@ -60,17 +60,17 @@ int main(int argc, char *argv[]) {
urislice2cstr(port, sizeof(port), u.port, url, "80");
path = uripath(&u);
pathstr = path.n ? url + path.i : "/";
msg = _gc(xstrcat("GET ", pathstr,
" HTTP/1.1\r\n"
"Host: ",
host,
"\r\n"
"Connection: close\r\n"
"Content-Length: 0\r\n"
"Accept: text/plain; */*\r\n"
"Accept-Encoding: identity\r\n"
"User-Agent: github.com/jart/cosmopolitan\r\n"
"\r\n"));
msg = gc(xstrcat("GET ", pathstr,
" HTTP/1.1\r\n"
"Host: ",
host,
"\r\n"
"Connection: close\r\n"
"Content-Length: 0\r\n"
"Accept: text/plain; */*\r\n"
"Accept-Encoding: identity\r\n"
"User-Agent: github.com/jart/cosmopolitan\r\n"
"\r\n"));
msglen = strlen(msg);
CHECK_EQ(EAI_SUCCESS, getaddrinfo(host, port, &hints, &addrs));
for (addr = addrs; addr; addr = addr->ai_next) {
+1 -1
View File
@@ -16,6 +16,6 @@
*/
int main(int argc, char *argv[]) {
puts(_gc(xiso8601ts(NULL)));
puts(gc(xiso8601ts(NULL)));
return 0;
}
+376
View File
@@ -0,0 +1,376 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "dsp/core/core.h"
#include "dsp/core/twixt8.h"
#include "dsp/scale/scale.h"
#include "dsp/tty/itoa8.h"
#include "dsp/tty/quant.h"
#include "libc/alg/arraylist2.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/winsize.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/consts/termios.h"
#include "libc/x/x.h"
#include "third_party/stb/stb_image.h"
/**
* Hat tips go out to Hornet, CRTC, DESiRE, Hans Petter Jansson, Guihua
* Cui, Ming Ronnier Luoand anyone else Mister Rogers would describe as
* the The Helpers Of This World who've helped us learn more about the
* cool yet exceedingly difficult things possible to do with graphics.
*/
#define DIN99 1
#define GAMMA 4.1
#define GAMMA_A .05
#define GAMMA_B 50.
#define GAMMA_C .055
#define COLORSPACE_SRC kSrgbD65ToXyzD50
#define COLORSPACE_TTY kSrgbD65ToXyzD50
#define SQR(X) ((X) * (X))
#define DEG(X) ((X)*M_PI / 180)
const double kXyzKappa = 24389 / 27.;
const double kXyzEpsilon = 216 / 24389.;
const double kSrgbD65ToXyzD50[3][3] = {
{.4360747, .3850649, .1430804},
{.2225045, .7168786, .0606169},
{.0139322, .0971045, .7141733},
};
const double kCieRgbEToXyz[3][3] = {
{.4887180, .3106803, .2006017},
{.1762044, .8129847, .0108109},
{.0000000, .0102048, .9897952},
};
const unsigned char kShadePct[] = {0300, 0200, 0100};
const unsigned short kShadeRune[] = {u'▓', u'▒', u'░'};
const unsigned char kAnsiTango[16][3] = {
{46, 52, 54}, {204, 0, 0}, {78, 154, 6}, {196, 160, 0},
{52, 101, 164}, {117, 80, 123}, {6, 152, 154}, {211, 215, 207},
{85, 87, 83}, {239, 41, 41}, {138, 226, 52}, {252, 233, 79},
{114, 159, 207}, {173, 127, 168}, {52, 226, 226}, {238, 238, 236},
};
const unsigned char kCga[16][3] = {
{0, 0, 0}, {170, 0, 0}, {0, 170, 0}, {170, 85, 0},
{0, 0, 170}, {170, 0, 170}, {0, 170, 170}, {170, 170, 170},
{85, 85, 85}, {255, 85, 85}, {85, 255, 85}, {255, 255, 85},
{85, 85, 255}, {255, 85, 255}, {85, 255, 255}, {255, 255, 255},
};
struct Blends {
size_t i, n;
struct Blend {
unsigned char color[4];
unsigned char bg, fg;
unsigned short rune;
} * p;
} blends;
static double Gamma(double x) {
if (x < GAMMA_A) return x / GAMMA_B;
return pow(1 / (1 + GAMMA_C) * (x + GAMMA_C), GAMMA);
}
static void *LoadRgb(double rgb[3], const unsigned char pix[3]) {
rgb[0] = Gamma(1. / 255 * pix[0]);
rgb[1] = Gamma(1. / 255 * pix[1]);
rgb[2] = Gamma(1. / 255 * pix[2]);
return rgb;
}
static double Lab(double x) {
return x > kXyzEpsilon ? cbrtf(x) : (kXyzKappa * x + 16) / 116;
}
static void XyzToLab(double lab[3], const double d50xyz[3]) {
double Y, L, a, b;
Y = Lab(d50xyz[1]);
L = 116 * Y - 16;
a = 500 * (Lab(d50xyz[0]) - Y);
b = 200 * (Y - Lab(d50xyz[2]));
lab[0] = L, lab[1] = a, lab[2] = b;
}
static void XyzToDin99d(unsigned char din99d[3], const double d50xyz[3]) {
double e, f, G, C, h, xyz[3], lab[3];
memcpy(xyz, d50xyz, sizeof(xyz));
xyz[0] = 1.12f * xyz[0] - .12f * xyz[2];
XyzToLab(lab, xyz);
e = (+lab[1] * cosf(DEG(50)) + lab[2] * sinf(DEG(50)));
f = (-lab[1] * sinf(DEG(50)) + lab[2] + cosf(DEG(50))) * 1.14;
G = sqrtf(SQR(e) + SQR(f));
C = logf(1 + .06 * G) * 22.5f;
h = atan2f(f, e) + DEG(50);
h = fmodf(h, DEG(360));
if (h < 0) h += DEG(360);
din99d[0] = MIN(255, MAX(0, 325.22f * logf(1 + .0036 * lab[0]) * 2.5f));
din99d[1] = MIN(255, MAX(0, C * cos(h) * 2.5f + 128));
din99d[2] = MIN(255, MAX(0, C * sin(h) * 2.5f + 128));
}
static void AddColor(int bg, int fg, int rune, int r, int g, int b, int x) {
int i;
if (blends.i) {
for (i = blends.i; --i;) {
if (blends.p[i].color[0] == r && blends.p[i].color[1] == g &&
blends.p[i].color[2] == b) {
return;
}
}
}
CHECK_NE(
-1,
APPEND(&blends.p, &blends.i, &blends.n,
(&(struct Blend){
.bg = bg, .fg = fg, .rune = rune, .color = {r, g, b, x}})));
}
static void AddBlend(int bgxterm, int fgxterm, int rune, int shade,
const unsigned char bgrgb[4],
const unsigned char fgrgb[4]) {
AddColor(bgxterm, fgxterm, rune, twixt8(bgrgb[0], fgrgb[0], shade),
twixt8(bgrgb[1], fgrgb[1], shade), twixt8(bgrgb[2], fgrgb[2], shade),
0);
}
static void MakeBlends(const unsigned char palette[16][3]) {
int r, i, j, k;
double rgb[3], xyz[3];
unsigned char tab[256][4];
unsigned char cube[6] = {0, 0137, 0207, 0257, 0327, 0377};
unsigned char seqs[2][2] = {{16, 255}};
for (i = 0; i < 16; ++i) {
tab[i][0] = palette[i][0];
tab[i][1] = palette[i][1];
tab[i][2] = palette[i][2];
tab[i][3] = i;
}
for (i = 16; i < 232; ++i) {
tab[i][0] = cube[((i - 020) / 044) % 6];
tab[i][1] = cube[((i - 020) / 6) % 6];
tab[i][2] = cube[(i - 020) % 6];
tab[i][3] = i;
}
for (i = 232; i < 256; ++i) {
tab[i][0] = 8 + (i - 232) * 10;
tab[i][1] = 8 + (i - 232) * 10;
tab[i][2] = 8 + (i - 232) * 10;
tab[i][3] = i;
}
#if DIN99
for (i = 0; i < 256; ++i) {
LoadRgb(rgb, tab[i]);
vmatmul3(xyz, rgb, COLORSPACE_TTY);
XyzToDin99d(tab[i], xyz);
}
#endif
for (r = 0; r < ARRAYLEN(seqs); ++r) {
for (i = seqs[r][0]; i <= seqs[r][1]; ++i) {
for (j = seqs[r][0]; j <= seqs[r][1]; ++j) {
if (i == j) {
AddColor(i, 0, 0, tab[i][0], tab[i][1], tab[i][2], 0);
} else {
for (k = 0; k < ARRAYLEN(kShadeRune); ++k) {
AddBlend(i, j, kShadeRune[k], kShadePct[k], tab[i], tab[j]);
AddBlend(j, i, kShadeRune[k], kShadePct[k], tab[j], tab[i]);
}
}
}
}
}
}
static int PickColor(unsigned char color[3]) {
int i, best, least, dist;
best = -1;
least = INT_MAX;
for (i = 0; i < blends.i; ++i) {
dist = SQR(blends.p[i].color[0] - color[0]) +
SQR(blends.p[i].color[1] - color[1]) +
SQR(blends.p[i].color[2] - color[2]);
if (dist < least) {
least = dist;
best = i;
}
}
return best;
}
static void SetBg(int x) {
if (0 <= x && x < 16) {
if (x < 8) {
x += 40;
} else {
x -= 8;
x *= 100;
}
printf("\e[%dm", x);
} else {
/* assert(false); */
printf("\e[48;5;%dm", x);
}
}
static void SetFg(int x) {
if (0 <= x && x < 16) {
if (x < 8) {
x += 30;
} else {
x -= 8;
x *= 90;
}
printf("\e[%dm", x);
} else {
/* assert(false); */
printf("\e[38;5;%dm", x);
}
}
static void PrintImage(long yn, long xn, unsigned char src[4][yn][xn]) {
int y, x, c;
double rgb[3], xyz[3];
unsigned char din99d[3];
for (y = 0; y < yn; ++y) {
printf("\n");
for (x = 0; x < xn; ++x) {
din99d[0] = src[0][y][x];
din99d[1] = src[1][y][x];
din99d[2] = src[2][y][x];
#if DIN99
LoadRgb(rgb, din99d);
vmatmul3(xyz, rgb, COLORSPACE_SRC);
XyzToDin99d(din99d, xyz);
#endif
c = PickColor(din99d);
if (blends.p[c].rune) {
SetBg(blends.p[c].bg);
SetFg(blends.p[c].fg);
printf("%hc", blends.p[c].rune);
} else {
SetBg(blends.p[c].bg);
printf(" ");
}
}
printf("\e[0m");
}
printf("\r");
}
static void *Deinterlace(long dcn, long dyn, long dxn,
unsigned char dst[dcn][dyn][dxn], long syw, long sxw,
long scw, const unsigned char src[syw][sxw][scw],
long syn, long sxn, long sy0, long sx0, long sc0) {
long y, x, c;
for (y = 0; y < dyn; ++y) {
for (x = 0; x < dxn; ++x) {
for (c = 0; c < dcn; ++c) {
dst[c][y][x] = src[sy0 + y][sx0 + x][sc0 + c];
}
}
}
return dst;
}
static void GetTermSize(int out_rows[1], int out_cols[1]) {
struct winsize ws;
ws.ws_row = 24;
ws.ws_col = 80;
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) {
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
}
out_rows[0] = ws.ws_row;
out_cols[0] = ws.ws_col;
}
static void ProcessImage(long syn, long sxn, unsigned char img[syn][sxn][4]) {
int dyn, dxn;
double ry, rx;
GetTermSize(&dyn, &dxn);
ry = syn, rx = sxn;
ry /= dyn, rx /= dxn;
PrintImage(
dyn, dxn,
EzGyarados(4, dyn, dxn, gc(xmemalign(32, dyn * dxn * 4)), 4, syn, sxn,
Deinterlace(4, syn, sxn, gc(xmemalign(32, syn * sxn * 4)), syn,
sxn, 4, img, syn, sxn, 0, 0, 0),
0, 4, dyn, dxn, syn, sxn, ry, rx, 0, 0));
}
static void WithImageFile(const char *path,
void fn(long yn, long xn,
unsigned char src[yn][xn][4])) {
struct stat st;
void *map, *data;
int fd, yn, xn, cn;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s",
path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
fn(yn, xn, data);
free(data);
}
static void PrintData(void) {
int i;
for (i = 0; i < blends.i; ++i) {
printf("%3d %3d %3d %3d %3d %d\n", blends.p[i].color[0],
blends.p[i].color[1], blends.p[i].color[2], blends.p[i].bg,
blends.p[i].fg, blends.p[i].rune);
}
}
void *OpenRgbMap(const char *path) {
int fd;
void *map;
size_t size;
size = 256 * 256 * 256 * 3;
CHECK_NE(-1, (fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644)));
CHECK_NE(-1, ftruncate(fd, size));
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)));
CHECK_NE(-1, close(fd));
return map;
}
int main(int argc, char *argv[]) {
int i;
MakeBlends(kCga);
for (i = 1; i < argc; ++i) {
WithImageFile(argv[i], ProcessImage);
}
return 0;
}
+7 -4
View File
@@ -33,6 +33,7 @@ EXAMPLES_BINS = \
$(EXAMPLES_COMS:%=%.dbg)
EXAMPLES_DIRECTDEPS = \
APE_LIB \
DSP_CORE \
DSP_SCALE \
DSP_TTY \
@@ -69,7 +70,6 @@ EXAMPLES_DIRECTDEPS = \
THIRD_PARTY_DLMALLOC \
THIRD_PARTY_GDTOA \
THIRD_PARTY_GETOPT \
THIRD_PARTY_LUA \
THIRD_PARTY_MUSL \
THIRD_PARTY_STB \
THIRD_PARTY_XED \
@@ -81,6 +81,7 @@ EXAMPLES_DEPS := \
o/$(MODE)/examples/examples.pkg: \
$(EXAMPLES_OBJS) \
$(THIRD_PARTY_DUKTAPE_A).pkg \
$(foreach x,$(EXAMPLES_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/examples/unbourne.o: \
@@ -95,10 +96,11 @@ o/$(MODE)/examples/%.com.dbg: \
$(APE)
@$(APELINK)
o/$(MODE)/examples/hellolua.com.dbg: \
o/$(MODE)/examples/hellojs.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/hellolua.o \
o/$(MODE)/examples/hellolua.lua.zip.o \
$(THIRD_PARTY_DUKTAPE) \
o/$(MODE)/examples/hellojs.o \
o/$(MODE)/examples/hello.js.zip.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE)
@@ -115,6 +117,7 @@ o/$(MODE)/examples/ispell.com.dbg: \
o/$(MODE)/examples/nesemu1.com.dbg: \
$(EXAMPLES_DEPS) \
$(THIRD_PARTY_DUKTAPE) \
o/$(MODE)/examples/nesemu1.o \
o/$(MODE)/usr/share/rom/mario.nes.zip.o \
o/$(MODE)/usr/share/rom/zelda.nes.zip.o \
+17
View File
@@ -0,0 +1,17 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
int main(int argc, char *argv[]) {
if (argc < 2) return 1;
execv(argv[1], argv + 1);
abort();
}
+66
View File
@@ -0,0 +1,66 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/color.internal.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/sysv/consts/sig.h"
#include "libc/time/time.h"
static const struct itimerval kTimer = {{0, 10000}, {0, 10000}}; /* 10ms */
static volatile bool32 showprogress_;
static const char *magic_;
void OnInterrupt(int sig) {
showprogress_ = true;
}
void ShowProgress(uintmax_t i, uintmax_t j, uintmax_t n) {
fprintf(stderr, "%s%,40jd%,40jd%,40jd\r\n", magic_, i, j, n);
showprogress_ = false;
}
static bool IsPrime(uintmax_t i) {
uintmax_t j, n;
for (j = 3, n = (unsigned long)floorl(sqrtl(i)); j <= n; j += 2) {
if (showprogress_) ShowProgress(i, j, n);
if (i % j == 0) return false;
}
return true;
}
static void TryNumber(uintmax_t x, uintmax_t i) {
if (IsPrime(i)) {
printf("%s%,jd%s%,jd\n", "the prime nearest ", x, " is ", i);
exit(0);
}
}
int main(int argc, char **argv) {
uintmax_t x, i, j;
CHECK_EQ(2, argc);
signal(SIGALRM, OnInterrupt);
setitimer(ITIMER_REAL, &kTimer, NULL);
magic_ = cancolor() ? "\e[F\e[K" : "";
if ((x = strtoumax(argv[1], NULL, 0)) % 2 == 0) ++x;
TryNumber(x, x);
for (i = x, j = x;;) {
if (i < UINTMAX_MAX) TryNumber(x, i), i += 2;
if (j > 1) TryNumber(x, j), j -= 2;
}
}
+5 -17
View File
@@ -7,24 +7,12 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "third_party/lua/lauxlib.h"
#include "third_party/lua/lualib.h"
int NativeAdd(lua_State *L) {
lua_Number x, y;
x = luaL_checknumber(L, 1);
y = luaL_checknumber(L, 2);
lua_pushnumber(L, x + y);
return 1; /* number of results */
}
#include "libc/calls/calls.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
lua_State *L;
L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, NativeAdd);
lua_setglobal(L, "NativeAdd");
luaL_dofile(L, "zip:examples/hellolua.lua");
lua_close(L);
int pid;
pid = fork();
fprintf(stderr, "fork returned %d\n", pid);
return 0;
}
+1 -65
View File
@@ -7,73 +7,9 @@
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/dce.h"
#include "libc/nexgen32e/nt2sysv.h"
#include "libc/nt/dll.h"
#include "libc/nt/enum/cw.h"
#include "libc/nt/enum/mb.h"
#include "libc/nt/enum/sw.h"
#include "libc/nt/enum/wm.h"
#include "libc/nt/enum/ws.h"
#include "libc/nt/events.h"
#include "libc/nt/messagebox.h"
#include "libc/nt/struct/msg.h"
#include "libc/nt/struct/wndclass.h"
#include "libc/nt/windows.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* @fileoverview GUI Example
*
* Cosmopolitan has had a razor sharp focus on making sockets and stdio
* work well across platforms. When you call a function like read(), it
* will just work on platforms like Windows too. In order to do that we
* need to support the WIN32 API, which you can use, but please note it
* isn't polyfilled on other platforms in the same way as POSIX APIs.
*/
static const char16_t kClassName[] = u"cosmopolitan";
static int64_t WindowProc(int64_t hwnd, uint32_t uMsg, uint64_t wParam,
int64_t lParam) {
switch (uMsg) {
case kNtWmDestroy:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
static void Gui(void) {
int64_t h;
struct NtMsg msg;
struct NtWndClass wc;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = NT2SYSV(WindowProc);
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = kClassName;
RegisterClass(&wc);
h = CreateWindowEx(0, kClassName, u"Hello Cosmopolitan",
kNtWsOverlappedwindow, kNtCwUsedefault, kNtCwUsedefault,
kNtCwUsedefault, kNtCwUsedefault, 0, 0, wc.hInstance, 0);
ShowWindow(h, kNtSwNormal);
/*
* NOTE: Cosmopolitan linker script is hard-coded to change the
* subsystem from CUI to GUI when GetMessage() is linked.
*/
while (GetMessage(&msg, 0, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
int main(int argc, char *argv[]) {
if (!IsWindows()) {
fputs("Sorry! This GUI demo only runs on Windows\n", stderr);
fputs("https://github.com/jart/cosmopolitan/issues/57\n", stderr);
return 1;
}
Gui();
return MessageBox(0, u"hello world", u"cosmopolitan", kNtMbOk) ? 0 : 1;
}
+7
View File
@@ -10,6 +10,13 @@
#include "libc/stdio/stdio.h"
int main() {
/*
* Cosmopolitan's "Hello World" demonstrates a best practice.
*
* Since we conditionally link heavyweight features based on which
* characters are present in the format string, it's a good idea to
* have that string consist solely of directives.
*/
printf("%s\n", "hello world");
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
NativePrint('Hello world!\n');
NativePrint('2+3=' + NativeAdd(2, 3) + '\n');
+5 -2
View File
@@ -8,9 +8,12 @@
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/errno.h"
#include "libc/stdio/stdio.h"
#include "libc/runtime/gc.h"
#include "libc/calls/calls.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/x/x.h"
int main() {
printf("%s \n", "hello world");
dprintf(STDOUT_FILENO, "%s\n", gc(xasprintf("%'s", "(╯°□°)╯︵' ┻━┻")));
return errno;
}
+16
View File
@@ -0,0 +1,16 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/errno.h"
#include "libc/stdio/stdio.h"
int main() {
printf("%s \n", "hello world");
return errno;
}
+60
View File
@@ -0,0 +1,60 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/gc.h"
#include "libc/sysv/consts/o.h"
#include "third_party/duktape/duktape.h"
STATIC_YOINK("zip_uri_support");
static duk_ret_t NativePrint(duk_context *ctx) {
duk_push_string(ctx, " ");
duk_insert(ctx, 0);
duk_join(ctx, duk_get_top(ctx) - 1);
fputs(duk_safe_to_string(ctx, -1), stdout);
return 0;
}
static duk_ret_t NativeAdd(duk_context *ctx) {
int i, n;
double r;
n = duk_get_top(ctx);
for (r = i = 0; i < n; i++) r += duk_to_number(ctx, i);
duk_push_number(ctx, r);
return 1;
}
int main(int argc, char *argv[]) {
int fd;
struct stat st;
const char *code;
duk_context *ctx;
showcrashreports();
ctx = duk_create_heap_default();
duk_push_c_function(ctx, NativePrint, DUK_VARARGS);
duk_put_global_string(ctx, "NativePrint");
duk_push_c_function(ctx, NativeAdd, DUK_VARARGS);
duk_put_global_string(ctx, "NativeAdd");
CHECK_NE(-1, (fd = open("zip:examples/hello.js", O_RDONLY)));
CHECK_NE(-1, fstat(fd, &st));
CHECK_NOTNULL((code = gc(calloc(1, st.st_size + 1))));
CHECK_EQ(st.st_size, read(fd, code, st.st_size));
CHECK_NE(-1, close(fd));
duk_eval_string(ctx, code);
duk_pop(ctx);
duk_destroy_heap(ctx);
return 0;
}
-1
View File
@@ -1 +0,0 @@
print(string.format("2 + 3 = %g", NativeAdd(2, 3)))
+19
View File
@@ -0,0 +1,19 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/str/str.h"
char kTenFour[10] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
int main32(int argc, char *argv[]) {
return argc;
if (memset(argv[0], 4, 10) != argv[0]) return 1;
if (memcmp(argv[0], kTenFour, 10)) return 2;
return 0;
}
+80
View File
@@ -0,0 +1,80 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/bits/bits.h"
#include "libc/dce.h"
#include "libc/log/check.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/sig.h"
#include "libc/time/time.h"
#include "libc/x/x.h"
#include "third_party/gdtoa/gdtoa.h"
/**
* @fileoverview Measure CPU clock mystery constants.
* @note CPUID EAX=15h/16h is a joke
*/
const long double kInterval = 0.001L;
long double start_;
char dtoabuf_[3][32];
volatile bool isdone_;
void OnCtrlC(int sig) {
isdone_ = true;
}
long double now(void) {
return dtime(CLOCK_MONOTONIC);
}
long double GetSample(void) {
uint64_t tick1, tick2;
long double time1, time2;
time1 = now();
tick1 = rdtsc();
nanosleep(&(struct timespec){0, 100000}, NULL);
time2 = now();
tick2 = rdtsc();
return ((time2 - time1) * 1e9L) / (long double)(tick2 - tick1);
}
void MeasureNanosecondsPerAlwaysRunningTimerCycle(void) {
int i;
long double avg, samp, elapsed;
start_ = now();
for (i = 1, avg = 1.0L; !isdone_; ++i) {
samp = GetSample();
avg += (samp - avg) / i;
dsleep(kInterval);
elapsed = now() - start_;
g_xfmt_p(dtoabuf_[0], &avg, 15, 32, 0);
g_xfmt_p(dtoabuf_[1], &samp, 15, 32, 0);
g_xfmt_p(dtoabuf_[2], &elapsed, 15, 32, 0);
printf("1c = %sns (last=%sns spent=%ss)\n", dtoabuf_[0], dtoabuf_[1],
dtoabuf_[2]);
}
}
int main(int argc, char *argv[]) {
if (!X86_HAVE(INVTSC)) {
fprintf(stderr, "warning: html can reprogram your microcode\n");
}
if (X86_HAVE(HYPERVISOR)) {
fprintf(stderr, "warning: virtual machine rdtsc isn't great\n");
}
CHECK_NE(-1, xsigaction(SIGINT, OnCtrlC, 0, 0, NULL));
MeasureNanosecondsPerAlwaysRunningTimerCycle();
return 0;
}
+1 -1
View File
@@ -15,7 +15,7 @@
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
+1 -1
View File
@@ -49,7 +49,7 @@ void List(const char *path) {
if (strcmp(path, ".") == 0) {
vpath = "";
} else if (!endswith(path, "/")) {
vpath = _gc(xasprintf("%s/", path));
vpath = gc(xasprintf("%s/", path));
} else {
vpath = path;
}
+2 -2
View File
@@ -9,7 +9,7 @@
#endif
#include "libc/alg/alg.h"
#include "libc/alg/arraylist2.internal.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
@@ -51,7 +51,7 @@ void WalkPaths(const char *dirpath) {
if (strcmp(e->d_name, "o") == 0) continue;
if (strcmp(e->d_name, ".git") == 0) continue;
if (e->d_type == DT_DIR) {
WalkPaths(_gc(path));
WalkPaths(gc(path));
} else {
CHECK_NE(-1, lstat(path, &st), "%s", path);
f.mt = st.st_mtim;
+50
View File
@@ -0,0 +1,50 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
/*
OpenBSD
00025ff61000 000000000000 65536
00026cf1d000 00000cfbc000 65536
000254d83000 ffffe7e66000 65536
0002c7bde000 000072e5b000 65536
000253ff9000 ffff8c41b000 65536
0002e96f3000 0000956fa000 65536
000236346000 ffff4cc53000 65536
0002ce744000 0000983fe000 65536
0002fe0b8000 00002f974000 65536
000225cd7000 ffff27c1f000 65536
*/
struct Mapping {
uint8_t *map;
size_t mapsize;
};
int main(int argc, char *argv[]) {
size_t i;
struct Mapping m[10];
for (i = 0; i < ARRAYLEN(m); ++i) {
m[i].mapsize = FRAMESIZE;
m[i].map = mmap(NULL, m[i].mapsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
}
for (i = 0; i < ARRAYLEN(m); ++i) {
printf("%p %p %zu\n", m[i].map, i ? m[i].map - m[i - 1].map : 0,
m[i].mapsize);
}
return 0;
}
+3 -2
View File
@@ -13,7 +13,7 @@
#include "libc/alg/arraylist2.internal.h"
#include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.internal.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/winsize.h"
@@ -23,10 +23,11 @@
#include "libc/inttypes.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/ohmyplus/vector.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
+1 -1
View File
@@ -1,4 +1,4 @@
#include "libc/macros.internal.h"
#include "libc/macros.h"
// Example assembly function.
//
+39
View File
@@ -0,0 +1,39 @@
/*-*- 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/fmt/conv.h"
#include "libc/runtime/interruptiblecall.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
struct InterruptibleCall icall;
static intptr_t peek(intptr_t *addr) {
return *addr;
}
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
intptr_t addr = strtoul(argv[i], NULL, 0);
icall.sig = SIGSEGV;
printf("%#p → %#lx\n", addr,
interruptiblecall(&icall, (void *)peek, addr, 0, 0, 0));
}
return 0;
}
Loaded 100 of 2689 files, more files were not shown because too many files have changed in this diff. Show more